@salesforce/sfdx-agent-sdk 0.18.0 → 0.20.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
@@ -3,6 +3,20 @@
3
3
  All notable changes to `@salesforce/sfdx-agent-sdk` are documented in this file.
4
4
  Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
+ ## [0.20.0] - 2026-06-12
7
+
8
+ ### Features
9
+ - **agent-sdk,harness-mastra,harness-claude**: add tool-call-delta ChatEvent for streaming tool-call args @W-22965697@ ([#597](https://github.com/forcedotcom/agentic-dx/pull/597))
10
+ - **agent-sdk,harness-mastra,harness-claude**: add tool-progress ChatEvent variant @W-22951127@ ([#594](https://github.com/forcedotcom/agentic-dx/pull/594))
11
+ - **harness-claude**: map SDKThinkingTokensMessage to UsageMetadata.reasoningTokens ([#595](https://github.com/forcedotcom/agentic-dx/pull/595))
12
+
13
+ ### Fixes
14
+ - **harness-claude**: map SDKResultSuccess.is_error to ChatEvent.error ([#593](https://github.com/forcedotcom/agentic-dx/pull/593))
15
+
16
+ ## [0.19.0] - 2026-06-11
17
+
18
+ _No changes — released alongside dependent packages._
19
+
6
20
  ## [0.18.0] - 2026-06-09
7
21
 
8
22
  ### Tests
package/README.md CHANGED
@@ -190,18 +190,20 @@ iterating the same `eventStream` until it sees a terminal `finish` event.
190
190
 
191
191
  Discriminated union (`event.type`) of streaming events:
192
192
 
193
- | Type | Key Fields | Description |
194
- | ----------------------- | --------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
195
- | `start` | — | Stream has begun. |
196
- | `text-delta` | `text` | Incremental response text. |
197
- | `reasoning-delta` | `text` | Chain-of-thought fragment. |
198
- | `tool-call` | `toolCallId`, `toolName`, `args`, `annotations?`, `serverName?` | Tool invocation. `annotations` is the MCP-spec hints (`readOnlyHint`, `destructiveHint`, …) when the source declared them; `serverName` is set when the tool came from an MCP server. |
199
- | `tool-approval-request` | `toolCall: ToolCallInfo`, `annotations?`, `serverName?` | Engine requests approval before executing a tool. Same `annotations` / `serverName` semantics as `tool-call`. |
200
- | `tool-result` | `toolCallId`, `toolName`, `result`, `isError?`, `error?`, `annotations?`, `serverName?` | Tool execution completed. `error` is present when `isError` is true (best-effort: harnesses may synthesize an `Error` from a string payload, so `error.stack` is not guaranteed to point at the tool's throw site; the field may be absent on empty error payloads). Same `annotations` / `serverName` semantics as `tool-call`. |
201
- | `step-start` | `stepIndex` | New LLM invocation step began. |
202
- | `step-finish` | `stepIndex`, `finishReason`, `usage?` | Step completed with per-step token usage. |
203
- | `error` | `error`, `code?` | Mid-stream error (yielded, not thrown). |
204
- | `finish` | `finishReason`, `usage?` | Stream completed with aggregate token usage. |
193
+ | Type | Key Fields | Description |
194
+ | ----------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
195
+ | `start` | — | Stream has begun. |
196
+ | `text-delta` | `text` | Incremental response text. |
197
+ | `reasoning-delta` | `text` | Chain-of-thought fragment. |
198
+ | `tool-call` | `toolCallId`, `toolName`, `args`, `annotations?`, `serverName?` | Tool invocation. `annotations` is the MCP-spec hints (`readOnlyHint`, `destructiveHint`, …) when the source declared them; `serverName` is set when the tool came from an MCP server. |
199
+ | `tool-call-delta` | `toolCallId`, `toolName?`, `argsTextDelta` | Incremental fragment of a tool call's args JSON, emitted while the model composes the call. Concatenate successive deltas for the same `toolCallId` to build the args text; the parsed result matches the terminal `tool-call.args`. Useful for live-typing tool inputs UI; consumers that don't need streaming-args can ignore this event and continue reading the parsed `args` on the terminal `tool-call`. `toolName` is optional (Claude's signal does not carry it on the wire). |
200
+ | `tool-approval-request` | `toolCall: ToolCallInfo`, `annotations?`, `serverName?` | Engine requests approval before executing a tool. Same `annotations` / `serverName` semantics as `tool-call`. |
201
+ | `tool-result` | `toolCallId`, `toolName`, `result`, `isError?`, `error?`, `annotations?`, `serverName?` | Tool execution completed. `error` is present when `isError` is true (best-effort: harnesses may synthesize an `Error` from a string payload, so `error.stack` is not guaranteed to point at the tool's throw site; the field may be absent on empty error payloads). Same `annotations` / `serverName` semantics as `tool-call`. |
202
+ | `tool-progress` | `toolCallId`, `toolName`, `output?`, `parentToolCallId?` | Incremental progress signal from a long-running tool call. Distinct from `tool-result`: zero or more `tool-progress` events may be emitted before exactly one terminal `tool-result`. `output` and `parentToolCallId` are best-effort enrichment that depends on the tool — the event itself is the load-bearing "tool is still working" signal; consumers SHOULD NOT branch on which optional fields are present. Useful for "tool is working" UI on long-running tools (build, test, deploy, large search, sub-agent tasks). |
203
+ | `step-start` | `stepIndex` | New LLM invocation step began. |
204
+ | `step-finish` | `stepIndex`, `finishReason`, `usage?` | Step completed with per-step token usage. |
205
+ | `error` | `error`, `code?` | Mid-stream error (yielded, not thrown). |
206
+ | `finish` | `finishReason`, `usage?` | Stream completed with aggregate token usage. |
205
207
 
206
208
  > **Diagnostic logging.** The `ChatEvent` union is the harness-agnostic public stream — it never carries
207
209
  > harness-internal chunk shapes. When a harness encounters a chunk type its adapter does not recognize (typically after
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export type { Message, MessagePart, ImagePart, FilePart } from './types/messages.js';
2
- export type { ChatEvent, StartEvent, TextDeltaEvent, ReasoningDeltaEvent, ToolCallEvent, ToolApprovalRequestEvent, ToolResultEvent, StepStartEvent, StepFinishEvent, ErrorEvent, FinishEvent, ChatStreamResult, } from './types/events.js';
2
+ export type { ChatEvent, StartEvent, TextDeltaEvent, ReasoningDeltaEvent, ToolCallEvent, ToolCallDeltaEvent, ToolApprovalRequestEvent, ToolResultEvent, ToolProgressEvent, StepStartEvent, StepFinishEvent, ErrorEvent, FinishEvent, ChatStreamResult, } from './types/events.js';
3
3
  export type { ToolDefinition, ToolCallInfo, ToolResultInfo } from './types/tools.js';
4
4
  export type { ContextUsage, FinishReason, UsageMetadata } from './types/usage.js';
5
5
  export type { AgentHooks, HooksForAgent, ToolResultRedactor, ToolResultRedactionInput, ToolResultRedactionResult, } from './types/redaction.js';
@@ -8,7 +8,7 @@ import type { FinishReason, UsageMetadata } from './usage.js';
8
8
  * convention, with the addition of `tool-approval-request` for human-in-the-loop
9
9
  * tool approval flows.
10
10
  */
11
- export type ChatEvent = StartEvent | TextDeltaEvent | ReasoningDeltaEvent | ToolCallEvent | ToolApprovalRequestEvent | ToolResultEvent | StepStartEvent | StepFinishEvent | ErrorEvent | FinishEvent;
11
+ export type ChatEvent = StartEvent | TextDeltaEvent | ReasoningDeltaEvent | ToolCallEvent | ToolCallDeltaEvent | ToolApprovalRequestEvent | ToolResultEvent | ToolProgressEvent | StepStartEvent | StepFinishEvent | ErrorEvent | FinishEvent;
12
12
  /**
13
13
  * The stream has begun. Symmetric counterpart to {@link FinishEvent}.
14
14
  *
@@ -68,6 +68,39 @@ export type ToolCallEvent = ToolCallInfo & {
68
68
  */
69
69
  serverName?: string;
70
70
  };
71
+ /**
72
+ * An incremental fragment of a tool call's args JSON, emitted while the
73
+ * model is still composing the call. Concatenate successive
74
+ * `tool-call-delta` events for the same `toolCallId` to build the complete
75
+ * args JSON that lands on the terminal {@link ToolCallEvent}.
76
+ *
77
+ * Useful for UIs that want to render "live-typing" tool args as the model
78
+ * generates them, mirroring `text-delta` for chat responses. Consumers that
79
+ * don't need streaming-args UX can ignore this event and continue to read
80
+ * the parsed `args` object on the terminal {@link ToolCallEvent}, which is
81
+ * unchanged.
82
+ *
83
+ * Both harnesses produce the underlying signal natively (Claude:
84
+ * `input_json_delta`; Mastra: `tool-call-delta` chunk). The terminal
85
+ * {@link ToolCallEvent} still fires once the full args object has been
86
+ * parsed — `tool-call-delta` is purely additive UX enrichment.
87
+ */
88
+ export type ToolCallDeltaEvent = {
89
+ type: 'tool-call-delta';
90
+ /** The id of the in-progress tool call. Matches the eventual {@link ToolCallEvent.toolCallId}. */
91
+ toolCallId: string;
92
+ /**
93
+ * The name of the tool. Optional because Mastra's `tool-call-delta`
94
+ * chunk types `toolName` as optional and may omit it; Claude always
95
+ * populates it from the per-`toolCallId` state captured on the prior
96
+ * `content_block_start`. Consumers SHOULD NOT branch on `toolName`
97
+ * presence — when absent, resolve it from the prior
98
+ * {@link ToolCallEvent} on the same `toolCallId`.
99
+ */
100
+ toolName?: string;
101
+ /** The args-JSON text fragment. */
102
+ argsTextDelta: string;
103
+ };
71
104
  /**
72
105
  * The harness is requesting approval before executing a tool call.
73
106
  * The stream suspends until the consumer calls `approveToolCall()` or
@@ -119,6 +152,39 @@ export type ToolResultEvent = ToolResultInfo & {
119
152
  */
120
153
  serverName?: string;
121
154
  };
155
+ /**
156
+ * An incremental tool-progress signal emitted while a long-running tool call is
157
+ * still in flight. Distinct from {@link ToolResultEvent} which marks terminal
158
+ * completion: a single tool call may emit zero or more `tool-progress` events,
159
+ * followed by exactly one `tool-result`.
160
+ *
161
+ * Useful for UIs that want to render a "tool is working" indicator for
162
+ * long-running tools (build, test, deploy, large search, sub-agent tasks)
163
+ * where the user benefits from seeing intermediate activity before the terminal
164
+ * `tool-result` lands.
165
+ *
166
+ * The event itself is the load-bearing "tool is still working" signal —
167
+ * `output` and `parentToolCallId` are best-effort enrichment that depends on
168
+ * the tool. Consumer code SHOULD NOT branch on which optional fields are
169
+ * present.
170
+ */
171
+ export type ToolProgressEvent = {
172
+ type: 'tool-progress';
173
+ /** The id of the in-progress tool call. Matches a prior {@link ToolCallEvent.toolCallId}. */
174
+ toolCallId: string;
175
+ /** The name of the tool. Matches a prior {@link ToolCallEvent.toolName}. */
176
+ toolName: string;
177
+ /**
178
+ * The tool's incremental output, if the tool produces one. Shape is
179
+ * tool-defined.
180
+ */
181
+ output?: unknown;
182
+ /**
183
+ * The parent tool-call id when this progress is for a nested tool call
184
+ * (e.g. a sub-agent invoking another tool), if applicable.
185
+ */
186
+ parentToolCallId?: string;
187
+ };
122
188
  /**
123
189
  * Marks the beginning of a new LLM invocation within a multi-step agentic loop.
124
190
  *
@@ -9,7 +9,25 @@ export type UsageMetadata = {
9
9
  outputTokens?: number;
10
10
  /** Sum of input and output tokens. */
11
11
  totalTokens?: number;
12
- /** Tokens consumed by the model's reasoning/thinking phase. */
12
+ /**
13
+ * Tokens consumed by the model's reasoning/thinking phase.
14
+ *
15
+ * Provider-reported and possibly approximate: Mastra surfaces an
16
+ * actual billed count from the gateway, while Claude surfaces a live
17
+ * estimate digested from `SDKThinkingTokensMessage.estimated_tokens`
18
+ * (the SDK's own JSDoc flags this as "approximate progress for
19
+ * spinners/pills, not the authoritative billed output_tokens").
20
+ * Consumers reading this field see the best-available reasoning-token
21
+ * count regardless of harness — both surfaces populate the same slot
22
+ * with the same shape and semantics on `step-finish.usage` and
23
+ * `finish.usage`.
24
+ *
25
+ * Intentionally excluded from {@link ContextUsage.usedFraction} —
26
+ * reasoning tokens don't survive into the next turn's prompt, so they
27
+ * don't belong in a "should I compact?" denominator. See
28
+ * `packages/sfdx-agent-sdk/ARCHITECTURE.md` →
29
+ * "Context-window usage tracking" for the rationale.
30
+ */
13
31
  reasoningTokens?: number;
14
32
  /** Input tokens served from provider cache (reduces cost). */
15
33
  cachedInputTokens?: number;
@@ -74,6 +92,13 @@ export type ContextUsage = {
74
92
  * cache-hit paths. Mastra is unaffected because it does not populate the
75
93
  * cache fields, so the sum collapses to `inputTokens` alone.
76
94
  *
95
+ * `reasoningTokens` is intentionally NOT in the sum: this fraction
96
+ * answers "should I compact for the next turn?" and reasoning blocks
97
+ * are stripped from the transcript before the next turn's prompt is
98
+ * sent, so they don't occupy next-turn context. See
99
+ * `packages/sfdx-agent-sdk/ARCHITECTURE.md` →
100
+ * "Context-window usage tracking" for the rationale.
101
+ *
77
102
  * `undefined` when ALL three input-bearing fields are missing on the
78
103
  * latest reading (pre-first-turn, post-`clearHistory()`, or when a
79
104
  * harness emits a reading without any input-side counts). Consumers
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/sfdx-agent-sdk",
3
- "version": "0.18.0",
3
+ "version": "0.20.0",
4
4
  "description": "Harness-agnostic agentic infrastructure for Salesforce developer experience tooling",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -45,8 +45,8 @@
45
45
  },
46
46
  "devDependencies": {
47
47
  "@eslint/js": "^10.0.1",
48
- "@salesforce/sfdx-agent-harness-claude": "0.14.0",
49
- "@salesforce/sfdx-agent-harness-mastra": "0.17.0",
48
+ "@salesforce/sfdx-agent-harness-claude": "0.16.0",
49
+ "@salesforce/sfdx-agent-harness-mastra": "0.19.0",
50
50
  "@types/node": "^22.19.20",
51
51
  "@vitest/coverage-istanbul": "^4.1.8",
52
52
  "@vitest/eslint-plugin": "^1.6.19",