1 Commits
Author SHA1 Message Date
james.maes 2323a6b929 feat(04-02): NDJSONDecoder with tool_calls-on-sight invariant + OllamaRequestBody drop-tools-array on .none (AGENT-04, AGENT-07)
- NDJSONDecoder emits .toolUseRequested whenever tool_calls is present on
  any chunk; never gates on done:true (AGENT-04 transport gotcha).
- Each tool_use gets a fresh UUID id (Ollama emits no ids on /api/chat).
- done_reason mapping: stop→endTurn (or toolUse if calls seen), length→
  maxTokens, tool_calls→toolUse, missing→toolUse-if-calls-else-endTurn.
- Mid-stream EOF emits .stopReason(.streamTruncated) — no
  partialToolUseAtDisconnect (NDJSON is atomic per line).
- OllamaRequestBody.encodeNative drops the tools array entirely when
  ToolChoice == .none (AGENT-07 cap-recovery invariant).
- ToolChoice.tool(name:) appends a best-effort system hint message
  (Ollama has no first-class tool-choice.force).
- OpenAI-compat path: tool_choice serializes as "auto"/"none"/"required"
  string or {type:function,function:{name}} object.
- Replaces Plan 04-01 placeholder files; tests: 19 passing.
2026-04-24 17:38:35 -05:00