• v1.13.1-C: port ask_user_input correlation to parts + wire reasoning_parts end-to-end

    indifferentketchup released this 2026-05-22 06:34:10 +00:00 | 108 commits to main since this release

    Pass 1 — ask_user_input correlation port (messages.ts:478, :549):

    • The two correlation queries that backed the elicitation flow used to scan
      messages.tool_calls and messages.tool_results JSON columns directly. They
      now JOIN message_parts on payload->>'id' (for the caller assistant) and
      payload->>'tool_call_id' (for the pending tool row). Semantics preserved:
      ORDER BY m.created_at DESC LIMIT 1 still picks the latest issuance, the
      already-answered 409 guard now reads payload.output, and the UPDATE +
      parts replace inside sql.begin is unchanged from v1.13.0.
    • Pre-v1.13.0 history has no parts rows and is unreachable to this lookup
      path (404). Acceptable per dispatch decision — no pending elicitation
      from before v1.13.0 will still be open. JSON-column fallback can land as
      a hotfix if it ever surfaces.

    Pass 2 — reasoning_parts wired end-to-end:

    • types.ts/StreamResult gains reasoning: string. stream-phase.ts accumulates
      reasoning-delta text per stream (replacing the v1.13.1-A counter-only
      diagnostic) and returns it on the result.
    • parts.ts/partsFromAssistantMessage gains an optional reasoning param.
      When present it emits a kind='reasoning' part at sequence 0, ahead of
      the text and tool_call parts.
    • error-handler.ts/finalizeCompletion and tool-phase.ts/executeToolPhase
      both thread result.reasoning into the dual-write call so reasoning-channel
      models (qwen3.6) get persistent reasoning rows.
    • payload.ts: loadContext SELECT pulls reasoning_parts from the v1.13.1-B
      view; OpenAiMessage gains an optional reasoning field; buildMessagesPayload
      collapses reasoning_parts into a single string per assistant message.
    • stream-phase.ts/toModelMessages converts assistant messages with reasoning
      into an AI SDK ModelMessage content array starting with a ReasoningPart,
      matching the @ai-sdk/provider-utils AssistantContent union. Reasoning
      models can now replay prior reasoning context across tool-call boundaries.
    • types/api.ts and apps/web/src/api/types.ts Message interface gain
      reasoning_parts (optional, nullable). Frontend doesn't render this yet —
      field reserved for a v1.14 UI surface.

    Tests: 2 new in parts.test.ts cover reasoning-at-sequence-0 with and
    without text content. 172 tests pass (170 prior + 2 new).

    Smoke verified against the live container:

    • A reasoning-prompt ("walk through 17 × 23 step by step") produced one
      message with kind='reasoning' (361 chars) at sequence 0 and kind='text'
      (429 chars) at sequence 1. Adapter log confirmed reasoning capture.
    • The new correlation SQL was validated against existing tool_call /
      tool_result parts: returns the expected message_id + payload shape with
      pending state correctly identified via payload.output IS NULL.
    • ask_user_input end-to-end through the UI is Sam's smoke — the Prompt
      Builder agent does not always trigger ask_user_input for these prompts,
      so synthetic verification via SQL substituted for traffic-driven cover.

    Annotation: the v1.13.1-A abort-throw site in stream-phase.ts got a
    one-liner comment ("AI SDK v6 fullStream returns normally on abort; check
    signal explicitly.") to prevent a future refactor removing it.

    v1.13.2 drops the dual-write + the JSON columns + collapses the view.

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    Downloads