* fix: repair YAML bullet lists in malformed tool-call JSON (#2660)
When LLMs copy YAML template formatting into tool-call arguments, they
produce `"key": - item` instead of `"key": ["item"]`, causing JSON parse
errors that block milestone completion. Add a repairToolJson() utility
that detects and converts YAML-style bullet lists into JSON arrays before
parsing. Integrated into both the PartialMessageBuilder (claude-code-cli)
and the anthropic-shared streaming provider, with fallback in
parseStreamingJson for all other providers.
Closes#2660
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use .js import extension in repair-tool-json test
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The claude-code provider in gsd-pi was effectively stateless: it sent
only the last user message, disabled session persistence, and filtered
out all sidechain/subagent events. This made multi-turn conversations
feel isolated and caused incomplete responses.
- Replace extractLastUserPrompt with buildPromptFromContext that
serialises the full conversation history (system prompt + all turns)
- Change persistSession from false to true for session continuity
- Remove parent_tool_use_id filtering so delegated/sidechain outputs
are included in the final response
- Extract buildSdkOptions for testability
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Treat Claude SDK generator exhaustion without a terminal result as a
stream interruption instead of a successful completion.
This prevents phantom-success auto-mode advances, keeps the failure
classifiable as transient provider recovery, and adds regression tests
for the fallback message plus provider classification.
Closes#2575
When the API stream is truncated mid-tool-call, PartialMessageBuilder
emits a toolcall_end event with { _raw: "<broken json>" } in the
arguments — but the event looks identical to a healthy tool completion.
Downstream consumers (error classifiers, tool handlers, activity log)
have no way to distinguish a truncated call from a completed one.
Add a malformedArguments: boolean flag to the toolcall_end event variant
in AssistantMessageEvent. The flag is set to true only in the JSON parse
catch path, so existing consumers (which do not check for it) are
unaffected. New consumers like classifyProviderError can use it to
handle truncated tool calls appropriately.
Closes#2574
- Filter toolcall_start/delta/end events from streaming to prevent
out-of-order rendering in the TUI's accumulated message content
- Collect tool calls from intermediate SDK turns and include them
BEFORE text content in the final AssistantMessage
- The agent loop's externalToolExecution path emits proper
tool_execution_start/end events for each intermediate tool call
- Result: tool activity renders above the text response, not below
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds `externalToolExecution` flag to AgentLoopConfig. When true, the
agent loop emits tool_execution_start/end events for TUI rendering but
skips local tool dispatch. Used by providers that handle tool execution
internally (e.g., Claude Code CLI via Agent SDK).
The flag is dynamically evaluated per-loop via a callback on
AgentOptions, so model switches mid-session are handled correctly.
Providers with authMode "externalCli" automatically use this mode.
Also updates the Claude Code CLI stream adapter to preserve tool call
blocks in the final message instead of stripping them.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add pathToClaudeCodeExecutable to SDK query options, resolving the
system `claude` binary via `which claude`. Without this, the SDK
looks for a bundled cli.js that doesn't exist when installed as a
library dependency.
- Remove env option that was replacing the subprocess environment and
stripping auth credentials, causing "Not logged in" errors.
- Update model IDs to current versions: claude-opus-4-6 (1M ctx),
claude-sonnet-4-6 (1M ctx), claude-haiku-4-5 (200K ctx).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements Phase 1 of the Claude Code subscription-as-provider integration
(issue #2509). Users with a Claude Code subscription (Pro/Max/Team) can
use subsidized inference through GSD's UI via the official Agent SDK.
The extension registers a provider with authMode: "externalCli" that
delegates to the user's locally-installed claude CLI. The SDK runs the
full agentic loop (multi-turn, tool execution) in one streamSimple call.
Tool calls stream in real-time for TUI visibility but are stripped from
the final AssistantMessage so the agent loop ends cleanly without local
tool dispatch.
Zero core changes — pure extension-based implementation.
Closes#2509
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>