Skip to content

Preserve Tinfoil reasoning passthrough semantics#153

Merged
AnthonyRonning merged 4 commits intomasterfrom
fix/tinfoil-reasoning-pcr-updates
Mar 27, 2026
Merged

Preserve Tinfoil reasoning passthrough semantics#153
AnthonyRonning merged 4 commits intomasterfrom
fix/tinfoil-reasoning-pcr-updates

Conversation

@AnthonyRonning
Copy link
Copy Markdown
Contributor

@AnthonyRonning AnthonyRonning commented Mar 27, 2026

Summary

  • ignore local .factory workspace files
  • preserve reasoning and reasoning_content as distinct chat-completions fields in the Tinfoil proxy while still rebuilding the shipped binary
  • let the Responses API bridge accept either reasoning field name without changing the agnostic chat-completions passthrough in src/web/openai.rs
  • refresh the signed dev/prod PCR files with just update-pcr-all

Validation

  • cargo fmt --manifest-path Cargo.toml
  • cargo test --manifest-path Cargo.toml
  • go test ./... (in tinfoil-proxy)
  • just build-tinfoil-proxy
  • just update-pcr-all
  • manually verified Kimi reasoning deltas locally

Summary by CodeRabbit

  • Bug Fixes

    • Improved handling of assistant "reasoning" data so streaming and non-streaming AI responses support both new and legacy payload shapes for more reliable, complete outputs.
  • Chores

    • Updated version control ignore rules to exclude new AI prompt artifact files.
    • Appended new entries to development and production PCR history data files.

Keep Factory session metadata out of the repository.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 27, 2026

Walkthrough

Adds propagation of reasoning-related extra fields through the proxy and web handlers: a new Reasoning field on chat messages, helpers to extract/populate reasoning/reasoning_content from upstream extra fields, and updates to streaming and non-streaming flows (including legacy fallback handling).

Changes

Cohort / File(s) Summary
Config / Ignore
\.gitignore
Added .factory/ to ignore list under AI Prompts.
Go Proxy Implementation
tinfoil-proxy/main.go
Added ChatMessage.Reasoning; implemented extractExtraFieldString, populateReasoningFields, and buildAssistantMessage; updated message conversion, streaming delta handling, and non-streaming post-processing to carry reasoning and reasoning_content, and to restore missing message fields before populating reasoning.
Rust Web Handlers
src/web/responses/handlers.rs
Updated completion processor to prefer delta.reasoning with fallback to delta.reasoning_content for streaming deltas; adjusted trace/log messages to reference reasoning fields.
PCR History Data
pcrDevHistory.json, pcrProdHistory.json
Appended one new PCR history entry to each JSON file (new PCR values, timestamp, and signature).

Sequence Diagram(s)

sequenceDiagram
    participant Upstream as Upstream API
    participant Proxy as tinfoil-proxy
    participant Web as Rust Handler
    participant Client as OpenAI Client

    rect rgba(120,180,240,0.5)
    Note over Upstream,Client: Reasoning propagation (streaming & non-streaming)
    Upstream->>Proxy: Response with extra_fields (`reasoning`, `reasoning_content`)
    activate Proxy
    Proxy->>Proxy: extractExtraFieldString(extra_fields)
    Proxy->>Proxy: populateReasoningFields(message, extra_fields)
    Proxy->>Web: stream/emit delta with reasoning fields
    deactivate Proxy

    activate Web
    Web->>Web: prefer delta.reasoning, fallback to delta.reasoning_content
    Web->>Client: SSE/forwarded message with reasoning metadata
    deactivate Web
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰
I nibble at fields both subtle and bright,
Carrying reasoning through stream and byte,
New hops and old now travel in line,
Extra fields snug in every sign,
Hooray — the rabbit dots the logic right!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main objective: preserving both reasoning and reasoning_content field passthrough in the Tinfoil proxy while maintaining existing semantics.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/tinfoil-reasoning-pcr-updates

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 3 additional findings.

Open in Devin Review

coderabbitai[bot]

This comment was marked as resolved.

Keep chat completions lossless by forwarding `reasoning` and `reasoning_content` exactly as received, while letting the Responses API bridge consume either field name. Includes the rebuilt proxy binary.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@AnthonyRonning AnthonyRonning force-pushed the fix/tinfoil-reasoning-pcr-updates branch from 6db4c3b to a71b077 Compare March 27, 2026 22:16
@AnthonyRonning AnthonyRonning changed the title Fix Tinfoil reasoning passthrough and refresh PCR values Preserve Tinfoil reasoning passthrough semantics Mar 27, 2026
coderabbitai[bot]

This comment was marked as resolved.

AnthonyRonning and others added 2 commits March 27, 2026 17:39
Keep replayed assistant turns lossless by forwarding explicit empty content and include the rebuilt proxy binary.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Refresh the dev and prod PCR manifests after rebuilding the EIFs and appending their signed history entries.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@AnthonyRonning AnthonyRonning force-pushed the fix/tinfoil-reasoning-pcr-updates branch from fe7591f to dcbb9ac Compare March 27, 2026 22:42
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tinfoil-proxy/main.go (1)

910-921: Consider restoring ToolCalls in the nil-message fallback path.

When response.Choices[i].Message is nil, the fallback only restores Role, Content, and Refusal. If the SDK's completion contains ToolCalls or FunctionCall, they would be lost. While this is an edge case (the marshal/unmarshal path at lines 892-904 should normally preserve these), adding them to the fallback would make the recovery more robust.

💡 Proposed fix to include tool calls in fallback
 			if response.Choices[i].Message == nil {
 				response.Choices[i].Message = &ChatMessage{
 					Role:    string(completion.Choices[i].Message.Role),
 					Content: completion.Choices[i].Message.Content,
 					Refusal: completion.Choices[i].Message.Refusal,
 				}
+				// Restore tool calls if present
+				if len(completion.Choices[i].Message.ToolCalls) > 0 {
+					toolCallsJSON, _ := json.Marshal(completion.Choices[i].Message.ToolCalls)
+					json.Unmarshal(toolCallsJSON, &response.Choices[i].Message.ToolCalls)
+				}
 			}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tinfoil-proxy/main.go` around lines 910 - 921, The nil-message fallback
currently creates a ChatMessage with only Role, Content and Refusal, losing
completion-side ToolCalls and FunctionCall; when building the fallback
ChatMessage in the loop over response.Choices (comparing to completion.Choices)
include any ToolCalls and FunctionCall from completion.Choices[i].Message into
the new ChatMessage before calling populateReasoningFields so those fields are
preserved (update the fallback construction where response.Choices[i].Message is
set to &ChatMessage{...} to copy ToolCalls and FunctionCall from
completion.Choices[i].Message).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tinfoil-proxy/main.go`:
- Line 19: The import for the OpenAI respjson package is incorrect; update the
import of the respjson package used by main.go from the wrong path that includes
"packages/" to the correct module path by replacing the imported path for the
respjson package so the code imports the package named respjson from
"github.com/openai/openai-go/v2/respjson" (i.e., remove the "packages/" segment)
so references to respjson in main.go compile.

---

Nitpick comments:
In `@tinfoil-proxy/main.go`:
- Around line 910-921: The nil-message fallback currently creates a ChatMessage
with only Role, Content and Refusal, losing completion-side ToolCalls and
FunctionCall; when building the fallback ChatMessage in the loop over
response.Choices (comparing to completion.Choices) include any ToolCalls and
FunctionCall from completion.Choices[i].Message into the new ChatMessage before
calling populateReasoningFields so those fields are preserved (update the
fallback construction where response.Choices[i].Message is set to
&ChatMessage{...} to copy ToolCalls and FunctionCall from
completion.Choices[i].Message).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2ddf7044-0eb2-40e8-88a1-61f749fdcc07

📥 Commits

Reviewing files that changed from the base of the PR and between fe7591f and dcbb9ac.

⛔ Files ignored due to path filters (3)
  • pcrDev.json is excluded by !pcrDev.json
  • pcrProd.json is excluded by !pcrProd.json
  • tinfoil-proxy/dist/tinfoil-proxy is excluded by !**/dist/**
📒 Files selected for processing (3)
  • pcrDevHistory.json
  • pcrProdHistory.json
  • tinfoil-proxy/main.go
✅ Files skipped from review due to trivial changes (2)
  • pcrProdHistory.json
  • pcrDevHistory.json

Comment thread tinfoil-proxy/main.go
@AnthonyRonning AnthonyRonning merged commit 8ab45f8 into master Mar 27, 2026
9 checks passed
@AnthonyRonning AnthonyRonning deleted the fix/tinfoil-reasoning-pcr-updates branch March 27, 2026 22:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant