@combycode/llm-sdk 1.5.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,13 +6,106 @@ All notable changes to `@combycode/llm-sdk` are documented here. The format foll
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
- ## [1.5.1] - 2026-07-06
9
+ ## [1.6.0] - 2026-07-11
10
+
11
+ ### Added
12
+ - **Typed structured-output failure + opt-in repair.** Structured output that can't be parsed now throws
13
+ a typed `InvalidFinalOutputError` (extends `AgentRunError`, carries `reason: 'invalid_final_output'` and
14
+ the model's `rawText`) instead of a bare `SyntaxError`, so callers can `instanceof`/inspect/retry.
15
+ `structuredComplete` gains an opt-in `structured.repairAttempts` (default 0): on a parse failure it
16
+ re-prompts with the error up to N times before throwing. Exports `AgentRunError`,
17
+ `InvalidFinalOutputError`. (`max_steps` / `model_refusal` stay returned results, differentiated by
18
+ `finishReason` / `AgentRunReport.reason`; run-error handler hooks can layer on later.)
19
+ - **`user_profile_id` + Interactions `cached_content`.** Anthropic forwards `providerOptions.userProfileId`
20
+ to the `anthropic-user-profile-id` header; Google Interactions maps `providerOptions.cachedContent` to
21
+ its `cached_content` resource.
22
+ - **Sampling penalties.** `presencePenalty` / `frequencyPenalty` ([-2, 2]) on `complete()` / `stream()`
23
+ (and `NormalizedRequest`), mapped to the providers that accept them — OpenAI/xAI **chat-completions**
24
+ (`presence_penalty` / `frequency_penalty`), OpenRouter (inherited), Google **generateContent**
25
+ (`generationConfig.presencePenalty` / `frequencyPenalty`) and **Interactions** (snake_case). Ignored by
26
+ OpenAI/xAI **Responses** and Anthropic, which don't accept them (verified against the SDK sources — the
27
+ Responses API has no penalty fields). Verified live on OpenAI, Google, and xAI.
28
+ - **Unified `web_fetch` hosted tool.** New `{ type: 'web_fetch' }` builtin that reads a
29
+ user-provided URL, mapped to Anthropic's `web_fetch_20260318` (GA; `params` like `allowed_domains`
30
+ / `blocked_domains` / `citations` / `max_content_tokens` / `max_uses` forwarded verbatim, with
31
+ `allowed_callers: ['direct']` defaulted so it works on chat models) and Google's `urlContext` tool.
32
+ The fetched URL surfaces on `response.builtinToolCalls` (`{ tool: 'web_fetch', url }`) and the
33
+ streamed `builtin_tool_start` / `builtin_tool_end` events, normalized across both providers.
34
+ `capabilities.builtinTools` / `catalog.supportsBuiltinTool()` / `select('web_fetch')` report it on
35
+ Anthropic + Google (OpenAI's `web_search` already opens pages; xAI / OpenRouter expose no fetch
36
+ tool). Verified live on Anthropic and Google.
37
+ - **Builtin-tool call payloads.** `BuiltinToolCall` (and the `builtin_tool_end` stream event) now
38
+ carry what the tool ran: `code` + `output` (stdout) for `code_interpreter`, and `query` (search
39
+ step) or `url` (page-open step) for `web_search` — normalized across every provider (OpenAI/xAI
40
+ `code_interpreter_call.code` + `web_search_call.action` `query`/`queries[]`/`url`, Anthropic
41
+ `server_tool_use.input` streamed via `input_json_delta` and correlated to its `*_tool_result`
42
+ stdout, Google `executableCode`/`codeExecutionResult` + grounding `webSearchQueries`). A single
43
+ OpenAI web search is a multi-step agent: `search` actions carry a query, `open_page`/`find`
44
+ actions carry the URL they read. Available on both `complete()` and streamed responses; verified
45
+ live on all four providers.
46
+
47
+ ### Changed
48
+ - **Anthropic web-search bumped to `web_search_20260318`** (from `web_search_20250305`) and now forwards
49
+ the unified `BuiltinTool.params` verbatim — `allowed_domains`, `blocked_domains`, `user_location`,
50
+ `response_inclusion`, `max_uses` (previously all silently dropped). The new version defaults to
51
+ *programmatic* tool calling (via code execution), which chat models like haiku reject, so the adapter
52
+ sends `allowed_callers: ['direct']` by default to preserve the classic direct-call behaviour; callers
53
+ override any default through `params`. Live-verified across all providers (scenario 27, 5/5).
10
54
 
11
55
  ### Fixed
12
- - **Anthropic file retrieval from the browser** was blocked by CORS. `retrieveFile` /
13
- `streamFile` now send Anthropic's `anthropic-dangerous-direct-browser-access: true` header
14
- when running in a browser (matching the completion adapter), so hosted code-execution files
15
- download directly. No effect on Node/Bun.
56
+ - **xAI `service_tier` maps to xAI's own enum.** The xAI adapter inherited OpenAI's tier map and could
57
+ emit `auto` / `flex` / `scale`, which xAI's API rejects (its `ServiceTier` is `default` | `priority`
58
+ only). It now remaps from the unified tier `standard` `default`, `priority` → `priority`, and any
59
+ value xAI can't honor is omitted (the server picks its default) rather than 400'ing. Live-verified:
60
+ `priority` sent and billed back (`usage.serviceTier`/`pricingTier`), `flex` no longer errors.
61
+ - **Agent loop no longer swallows failed runs into empty text.** `AgentLoop.complete()` and
62
+ `.stream()` caught any mid-run LLM error, set `finishReason:'error'`, and returned an empty
63
+ `CompletionResponse` (or ended the stream) with the error message dropped — so a tool-using
64
+ `complete()` / `delegate()` / `handoff()` returned `""` on an auth failure, rate limit, context
65
+ overflow, etc., while the same call *without* tools threw. Both now **re-throw** the original error
66
+ (preserving `LLMError` kind/status) after finalizing metrics/hooks, matching the no-tools path and
67
+ the raw client stream. `AgentLoop.run()` is unchanged — it still returns an `AgentRunReport` with
68
+ `reason:'error'` + `error` for callers that want partial results. Live-verified (bad key → thrown
69
+ `auth` error, not empty text).
70
+ - **Agent loop now continues stateful turns server-side.** After a tool call the loop stamped its
71
+ assistant turn without provenance, so multi-turn runs on a stateful API always resent the full
72
+ transcript. On Google Interactions that transcript replay is *rejected* (the API requires resuming
73
+ by `previous_interaction_id`), which surfaced as an **empty final answer** on agentic tool use. The
74
+ loop now stamps `id` / `createdAt` / `origin.serverStateId` (via the shared `buildAssistantMessage`),
75
+ so the server-state brain continues by id and sends only the new turn — gated, as before, by catalog
76
+ support, the retention TTL (openai/xai 30d, google 72h), and model binding. Live-verified: Interactions
77
+ agentic round-trip now answers; OpenAI Responses / Anthropic tool loops unchanged.
78
+ - **Google Interactions streaming (opt-in `api: 'interactions'`) brought current with the 2.10 wire.**
79
+ The regenerated Interactions client replaced the old `content.delta` / `interaction.complete` events
80
+ with a step machine — `step.start` / `step.delta` / `step.stop`, `interaction.created` /
81
+ `interaction.completed` / `interaction.status_update` — so the previous parser produced no output.
82
+ The parser now reads `step.delta` payloads (`text`, `thought_summary` → thinking, `arguments_delta`),
83
+ opens/attaches/closes a function call across `step.start` → `arguments_delta` → `step.stop` (the
84
+ `arguments_delta` carries no id, so a per-stream parser correlates it), and finishes on
85
+ `interaction.completed` / `interaction.failed` with usage from `interaction.usage`. Live-verified
86
+ against the 2.10 API (streamed text, tool calls, usage). The default Google path (`generateContent`)
87
+ is unaffected.
88
+ - **OpenAI web-search query precedence.** OpenAI deprecated the singular `web_search_call.action.query`
89
+ in favour of `action.queries[]`; the Responses adapter now prefers the array and falls back to the
90
+ scalar, so `BuiltinToolCall.query` stays populated on the new wire.
91
+ - **Duplicate OpenAI code-execution files.** When code calls `plt.show()` *and* saves the figure,
92
+ OpenAI emits an extra auto-display container file alongside the saved one — surfacing the same
93
+ chart twice on `response.files`. The Responses adapter now drops the auto-display artifact (an
94
+ image citation named after its own file id, with a zero-width span) when the same image was also
95
+ saved, matching ChatGPT's own UI. A display-only run keeps its sole figure; distinct saved files
96
+ are never collapsed. Investigated across providers: only OpenAI has this pattern (Anthropic/xAI
97
+ return only saved files; Google returns one artifact per output) — so the fix is scoped to the
98
+ OpenAI Responses adapter.
99
+
100
+ ## [1.5.1] - 2026-07-06
101
+
102
+ ### Changed
103
+ - `retrieveFile` / `streamFile` now send Anthropic's `anthropic-dangerous-direct-browser-access:
104
+ true` header in the browser, for consistency with the completion adapter. **Note:** this does
105
+ NOT make Anthropic hosted-tool files downloadable from a browser — Anthropic's Files API
106
+ (`GET /v1/files/{id}/content`) does not return CORS headers (unlike `/v1/messages`), so file
107
+ retrieval for Anthropic is **server-side only** (verified against the API + the official docs).
108
+ OpenAI works in-browser; Google and xAI return files inline (no fetch), so they work too.
16
109
 
17
110
  ## [1.5.0] - 2026-07-06
18
111
 
@@ -145,6 +238,7 @@ First public release.
145
238
  - Service tiers end to end (request → bill → cost).
146
239
  - Cross-environment: runs on Node, Bun, and the browser. ESM, zero runtime deps.
147
240
 
241
+ [1.6.0]: https://github.com/combycode/llm-sdk-ts/releases/tag/v1.6.0
148
242
  [1.2.0]: https://github.com/combycode/llm-sdk-ts/releases/tag/v1.2.0
149
243
  [1.1.0]: https://github.com/combycode/llm-sdk-ts/releases/tag/v1.1.0
150
244
  [1.0.0]: https://github.com/combycode/llm-sdk-ts/releases/tag/v1.0.0