@combycode/llm-sdk 2.0.0 → 2.0.1

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
@@ -4,6 +4,37 @@ All notable changes to `@combycode/llm-sdk` are documented here. The format foll
4
4
  [Keep a Changelog](https://keepachangelog.com/) and the project adheres to
5
5
  [Semantic Versioning](https://semver.org/).
6
6
 
7
+ ## [2.0.1] - 2026-08-10
8
+
9
+ Three defects reported by a consumer within a day of 2.0.0 — all reachable by reading the shipped
10
+ `.d.ts`, none caught by our gate. See the note at the end.
11
+
12
+ ### Fixed
13
+
14
+ - **`agent.stream()` now carries `phase` on text events.** The raw stream event had it, and the
15
+ agent mapper *used* it internally to keep commentary out of the answer — then yielded both deltas
16
+ through one `{ type: 'text', text }` with the phase stripped. A UI streaming those straight
17
+ through put the model's thinking-aloud into the transcript **as if it were the reply**, with no
18
+ way to tell them apart. `finalAnswerText()` could not help: it takes a finished message's
19
+ `content`, not deltas.
20
+ - Additive: `phase` is **absent** (not `undefined`) when the provider reports none, so every
21
+ non-codex provider is byte-identical to before.
22
+ - **Docs: `agent.run()` does not exist.** The agent-loop guide recommended it for a non-throwing
23
+ report. The class exposes `stop` / `complete` / `structuredComplete` / `stream`; the report is
24
+ reached with `try/catch` + `agent.lastReport`. The guide now shows that.
25
+ - **Docs: the 2.0.0 changelog overstated live commentary.** It said commentary "is still yielded to
26
+ the consumer (a UI may well want to render it live)" — true only in the sense that the bytes
27
+ arrived; they were unlabelled, so a UI could not act on them. The 2.0.0 entry now says so and
28
+ points here.
29
+
30
+ ### Why this got out
31
+
32
+ The feature was verified end-to-end on the **buffered** path (`finalAnswerText`, `response.text`,
33
+ live-tested against real models) and never once from the **layer most consumers actually call**.
34
+ 1778 tests, four MCP transports and two live corpora, and no check that a shipped type was usable
35
+ from `agent.stream()`. The gate was deep where it was pointed and blind where it was not — so the
36
+ release checklist now includes a consumer-surface pass over the published `.d.ts`.
37
+
7
38
  ## [2.0.0] - 2026-08-09
8
39
 
9
40
  **Upgrading:** three things can require action, and none of them is a provider change — that is the
@@ -250,8 +281,9 @@ with `inputRequiredMaxRounds`.
250
281
  silently drop the answer.
251
282
  - Streaming carries it too. `phase` is announced once on `response.output_item.added` and belongs
252
283
  on every delta of that item, so the parser keeps per-stream item→phase state; concurrent streams
253
- cannot leak phases into each other. Commentary is still yielded to the consumer (a UI may well
254
- want to render it live) and is preserved in the assembled content as its own phase-tagged part.
284
+ cannot leak phases into each other. Commentary is yielded to the consumer and preserved in the
285
+ assembled content as its own phase-tagged part. (In 2.0.0 the agent-layer event dropped the
286
+ phase, so a UI could not act on it — corrected in 2.0.1.)
255
287
  - Nothing is inferred: a model that reports no phase produces parts with no phase, exactly as
256
288
  before.
257
289
  - **`name` + `namespace` on `function_call_output`.** The tool name is taken from the matching
@@ -1,7 +1,7 @@
1
1
  /** Agent-layer shared types — TokenCounter contract used by ContextRegistry,
2
2
  * ConversationHistory, and the ContextMeasurer plugin.
3
3
  * Also defines AgentTool (executable tool) and run-report types. */
4
- import type { ContentPart, Message } from '../llm/types/messages';
4
+ import type { AssistantPhase, ContentPart, Message } from '../llm/types/messages';
5
5
  import type { Tool } from '../llm/types/tools';
6
6
  import type { Usage } from '../llm/types/response';
7
7
  import type { HistorySnapshot } from './history-types';
@@ -103,9 +103,15 @@ export interface AgentRunReport {
103
103
  export type AgentStreamEvent = {
104
104
  type: 'step_start';
105
105
  step: number;
106
- } | {
106
+ }
107
+ /** `phase` mirrors the raw stream event: `'commentary'` is the model narrating, anything
108
+ * else (usually absent) is the answer. Passed through so a consumer can tell them apart
109
+ * LIVE — `finalAnswerText()` only cleans a finished message and cannot touch deltas.
110
+ * Absent on every provider that reports no phase, exactly as before. */
111
+ | {
107
112
  type: 'text';
108
113
  text: string;
114
+ phase?: AssistantPhase;
109
115
  } | {
110
116
  type: 'thinking';
111
117
  text: string;
@@ -31110,7 +31110,7 @@ function accumulateStreamEvent(event, state) {
31110
31110
  case "text":
31111
31111
  if (event.phase === "commentary") state.stepCommentary += event.text;
31112
31112
  else state.stepText += event.text;
31113
- return { type: "text", text: event.text };
31113
+ return { type: "text", text: event.text, ...event.phase ? { phase: event.phase } : {} };
31114
31114
  case "thinking":
31115
31115
  state.stepThinking += event.text;
31116
31116
  return { type: "thinking", text: event.text };
package/dist/index.js CHANGED
@@ -31037,7 +31037,7 @@ function accumulateStreamEvent(event, state) {
31037
31037
  case "text":
31038
31038
  if (event.phase === "commentary") state.stepCommentary += event.text;
31039
31039
  else state.stepText += event.text;
31040
- return { type: "text", text: event.text };
31040
+ return { type: "text", text: event.text, ...event.phase ? { phase: event.phase } : {} };
31041
31041
  case "thinking":
31042
31042
  state.stepThinking += event.text;
31043
31043
  return { type: "thinking", text: event.text };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@combycode/llm-sdk",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "Unified, pluggable AI SDK for accessing the LLMs of every major provider (Anthropic, OpenAI, Google, xAI, OpenRouter) through one API. Cross-environment: Node, Bun, and the browser.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",