Skip to content

feat(studio): add structured-output prefill generation - #393

Merged
danvitv merged 7 commits into
hydall:nightlyfrom
danvitv:feat/studio-structured-prefill
Sep 6, 2026
Merged

feat(studio): add structured-output prefill generation#393
danvitv merged 7 commits into
hydall:nightlyfrom
danvitv:feat/studio-structured-prefill

Conversation

@danvitv

@danvitv danvitv commented Sep 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • add Gemini 3.8 structured-output prefill support and preserve it through Studio preset encoding
  • execute functionPrefill blocks with a two-pass generator while carrying reasoning into the final request
  • handle reasoning-channel and inline reasoning output consistently across streaming and non-streaming replies
  • split the database migration suite across four test entrypoints and isolate expensive setup, reducing the full-suite runtime from 8m10s to 4m52s locally

Verification

  • flutter analyze --no-fatal-infos --no-fatal-warnings (no errors; 9 pre-existing warnings/info)
  • migration suite: 67 passed in 30s
  • flutter test --reporter expanded: 3840 passed, 3 failed in 4m52s
  • the remaining failures are the existing clipboard-image assertions in test/chat_input_bar_test.dart introduced by upstream feat(chat): attach pasted images, up to four per message #389 (find.byType(Image) finds no thumbnail)

Add a prefillStyle toggle to functionPrefill blocks. When set to
'structured', the block emits a strict JSON schema (response_format on
the OpenAI wire, responseMimeType/responseSchema on native Gemini)
instead of a synthetic tool_call. Gemini 3.8 rejects the legacy
tool-call prefill with a missing thought_signature; structured output
carries no such requirement, so the prefill keeps working.

Default stays 'tool' — nothing changes unless a preset opts in.
Add a 'two-pass' prefill style. Instead of a synthetic tool call or a
JSON response schema, the final generator runs twice: a quiet first pass
produces the internal <thinking> block, then a second pass writes the
visible reply seeded by that block. The reasoning is surfaced via
AgentRunResult.reasoning. Survives Gemini 3.8's thought_signature
requirement without tool_calls or a fragile schema.
The quiet thinking pass ran with isFinalResponse:false, which resolves
the pre-gen controller model and its reasoning settings instead of the
final model. Run it with isFinalResponse:true so both passes hit the
final model + final reasoning config.
…plies

The two-pass generator runs its final pass with stream=false, so the
incoming <audit> reasoning block was never parsed out of the reply text
and the model's second reasoning block leaked into content. Route the
full non-streaming response through StreamAccumulator and preserve both
reasoning blocks on the result.
@danvitv
danvitv merged commit 2406dd5 into hydall:nightly Sep 6, 2026
3 checks passed
@danvitv
danvitv deleted the feat/studio-structured-prefill branch September 6, 2026 21:10
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