@salesforce/sfdx-agent-sdk 0.38.0 → 0.40.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,16 @@
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.40.0] - 2026-08-03
7
+
8
+ ### Features
9
+ - **agent-sdk,harness-mastra,harness-claude,harness-openai**: observability gaps — mcp-tool-call-completed, llm-retry, responseText/TTFT @W-23528008@ ([#717](https://github.com/forcedotcom/agentic-dx/pull/717))
10
+
11
+ ## [0.39.0] - 2026-07-30
12
+
13
+ ### Features
14
+ - **harness-openai**: MCP tool-progress @W-23558557@ ([#715](https://github.com/forcedotcom/agentic-dx/pull/715))
15
+
6
16
  ## [0.38.0] - 2026-07-28
7
17
 
8
18
  ### Fixes
package/README.md CHANGED
@@ -1192,6 +1192,9 @@ const unsubscribe = manager.onWireCommunication((event) => {
1192
1192
  case 'llm-response':
1193
1193
  // matching response (or terminal failure)
1194
1194
  break;
1195
+ case 'mcp-tool-call-completed':
1196
+ // completed MCP tool call; redact args/result before persisting
1197
+ break;
1195
1198
  case 'wire-monitoring-not-supported':
1196
1199
  // harness can't emit per-call events for this stream;
1197
1200
  // event.message points at the workaround (typically a debug log file path)
@@ -1200,17 +1203,28 @@ const unsubscribe = manager.onWireCommunication((event) => {
1200
1203
  });
1201
1204
  ```
1202
1205
 
1203
- **Discriminated union — three variants keyed on `type`:**
1206
+ **Discriminated union — four variants keyed on `type`:**
1207
+
1208
+ | `type` | Fields |
1209
+ | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1210
+ | `llm-request` | `timestamp`, `url`, `method`, `model`, `correlationId?`, `xClientTraceId?`, `body?` |
1211
+ | `llm-response` | `timestamp`, `model`, `correlationId?`, `status`, `xClientTraceId?`, `totalDurationMs?`, `timeToFirstTokenMs?`, `usage?` (`inputTokens?`, `outputTokens?`, `totalTokens?`, `reasoningTokens?`), `responseText?`, `error?` ({ `message` }) |
1212
+ | `mcp-tool-call-completed` | `timestamp`, `serverName`, `toolName`, `bareToolName`, `args`, `result`, `durationMs?` |
1213
+ | `wire-monitoring-not-supported` | `timestamp`, `harnessId`, `message` (free-form text — typically explains why direct wire monitoring isn't available and points at a fallback log file the harness wrote) |
1214
+
1215
+ `correlationId` is the harness-guaranteed pairing key stamped identically on a matching `llm-request` / `llm-response`
1216
+ pair. Pair requests and responses on it, **not** on their positions in the event stream. `xClientTraceId` is an optional
1217
+ header value for cross-checking, not the pairing contract.
1204
1218
 
1205
- | `type` | Fields |
1206
- | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1207
- | `llm-request` | `timestamp`, `url`, `method`, `model`, `body?` |
1208
- | `llm-response` | `timestamp`, `model`, `status`, `xClientTraceId?`, `totalDurationMs?`, `timeToFirstTokenMs?`, `usage?` (`inputTokens?`, `outputTokens?`, `totalTokens?`, `reasoningTokens?`), `responseText?`, `error?` ({ `message` }) |
1209
- | `wire-monitoring-not-supported` | `timestamp`, `harnessId`, `message` (free-form text — typically explains why direct wire monitoring isn't available and points at a fallback log file the harness wrote) |
1219
+ `mcp-tool-call-completed` is a **DEBUG-ONLY** diagnostic event: it is opt-in and subscriber-gated like the rest of this
1220
+ channel, is never a `TelemetryEvent`, and is never shipped through telemetry or other externally-shipped event surfaces.
1221
+ Its `args` and `result` are captured verbatim and MAY contain PII. Apply your own redaction / scrubbing before
1222
+ persisting or sharing. `durationMs` is harness-specific: Claude reports RPC latency, while Mastra and OpenAI report an
1223
+ adapter-observed window. Do not compare `durationMs` across harnesses.
1210
1224
 
1211
- **Privacy contract.** Events MAY contain user prompts, tool arguments, and model output in the `body` field. They are
1212
- **not** flowed to the structured-log channel by default — consumers opt in to wire-level visibility explicitly via
1213
- `onWireCommunication`. Apply your own redaction / scrubbing before persisting or sharing. Note that request HTTP headers
1225
+ **Privacy contract.** LLM events MAY contain user prompts and model output in `body` / `responseText`; MCP completion
1226
+ events MAY contain PII in verbatim `args` / `result`. These events are **not** flowed to the structured-log channel by
1227
+ default consumers opt in to wire-level visibility explicitly via `onWireCommunication`. Note that request HTTP headers
1214
1228
  (e.g. `Authorization`) are **not** captured on the events; the harness's fetch wrapper sees them but doesn't forward
1215
1229
  them onto the channel.
1216
1230
 
@@ -1221,17 +1235,26 @@ harness in particular skips writing the subprocess's debug log when nobody is li
1221
1235
  `chat()` you want to inspect: subscriptions added mid-stream miss the in-flight subprocess on Claude (the listener count
1222
1236
  is captured at stream-start).
1223
1237
 
1224
- **Cross-harness coverage.**
1238
+ #### Cross-harness coverage
1239
+
1240
+ This table is the canonical compatibility reference for the SDK's public observability and wire-diagnostic surfaces.
1241
+ Feature availability is intentionally asymmetric where a runtime does not expose a faithful observation seam.
1242
+
1243
+ | Feature | Claude | Mastra | OpenAI |
1244
+ | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1245
+ | Structured `llm-request` / `llm-response` wire events | **Not implemented.** The opaque native subprocess provides no capturable, parseable per-call format. When subscribed, emits `wire-monitoring-not-supported` and writes a subprocess debug-log file. | **Delivered.** Emits one request/response pair per outbound LLM HTTP call. | **Delivered.** Emits one request/response pair per outbound LLM HTTP call. |
1246
+ | Pairing structured LLM events | N/A — no structured LLM wire events. | **Delivered.** Matching request/response events share a harness-generated `correlationId`; pair on it, never event position or `xClientTraceId` alone. | **Delivered.** Matching request/response events share a harness-generated `correlationId`; pair on it, never event position or `xClientTraceId` alone. |
1247
+ | `responseText` and `timeToFirstTokenMs` on `llm-response` | N/A — no structured LLM wire events. | **Delivered.** A streaming-body tee produces one HTTP-body-terminal response event with best-effort response text and first-token latency. | **Delivered.** A streaming-body tee produces one HTTP-body-terminal response event with best-effort response text and first-token latency. |
1248
+ | `mcp-tool-call-completed` debug event | **Delivered.** External-MCP bridge observation with true RPC latency in `durationMs`. | **Delivered.** Adapter/coordinator-observed `durationMs`, which can include a model round-trip. | **Delivered.** Adapter/coordinator-observed `durationMs`, which can include a model round-trip. |
1249
+ | `llm-retry` telemetry | **Delivered.** Emits numeric-only, PII-free data when the Claude Agent SDK reports an actual `api_retry`. | **Documented limitation:** does not emit; the stateless fetch layer has no retry loop or attempt counter. A `429` / `retry-after` response is a failed attempt, not a retry. | **Documented limitation:** does not emit; the stateless fetch layer has no retry loop or attempt counter. A `429` / `retry-after` response is a failed attempt, not a retry. |
1250
+
1251
+ Claude's debug log is written to `${storageRoot}/claude-debug-logs/${agentId}__${threadId}.log` when at least one
1252
+ consumer is subscribed at stream-start (one file per thread; turns of the same conversation accumulate, separated by
1253
+ greppable `# Turn started: <ISO>` banners). It is left in place; the consumer is responsible for retention and cleanup.
1225
1254
 
1226
- - **Mastra harness**: emits one `llm-request` + one `llm-response` per outbound HTTP call to the LLM provider (every
1227
- provider — Bedrock-Anthropic, direct Anthropic, OpenAI Responses, OpenAI Chat Completions). The body is captured from
1228
- the in-process fetch wrapper.
1229
- - **Claude harness**: cannot emit per-call events because the Claude Agent SDK runs the model client in a subprocess
1230
- with no programmatic HTTP-interception seam. Instead, when at least one consumer is subscribed at stream-start, the
1231
- harness writes the subprocess's debug log to `${storageRoot}/claude-debug-logs/${agentId}__${threadId}.log` (one file
1232
- per thread; turns of the same conversation accumulate, separated by greppable `# Turn started: <ISO>` banners) and
1233
- emits a single `wire-monitoring-not-supported` event whose `message` field embeds the file path. The file is left in
1234
- place; the consumer is responsible for retention and cleanup.
1255
+ Mastra and OpenAI callers can identify any upstream-retried requests only as distinct `llm-request` / `llm-response`
1256
+ pairs, using `correlationId`, `xClientTraceId`, and timestamps. Neither harness synthesizes a partial `llm-retry` event
1257
+ from an HTTP response header.
1235
1258
 
1236
1259
  #### `WireCommunicationFileWriter`
1237
1260
 
@@ -1253,11 +1276,11 @@ const writer = new WireCommunicationFileWriter(manager, {
1253
1276
  writer.detach();
1254
1277
  ```
1255
1278
 
1256
- The output file is plain Markdown with one `### <iso-timestamp> [llm-request]`, `[llm-response]`, or
1257
- `[wire-monitoring-not-supported]` header per event followed by the populated fields. Optional fields are emitted only
1258
- when set — sparse responses do not pad the file with empty `**Field**: N/A` lines. On the Claude harness, the
1259
- `wire-monitoring-not-supported` block links to the per-thread debug log file where raw wire detail can be inspected
1260
- directly.
1279
+ The output file is plain Markdown with one `### <iso-timestamp> [llm-request]`, `[llm-response]`,
1280
+ `[mcp-tool-call-completed]`, or `[wire-monitoring-not-supported]` header per event followed by the populated fields.
1281
+ Optional fields are emitted only when set — sparse responses do not pad the file with empty `**Field**: N/A` lines. On
1282
+ the Claude harness, the `wire-monitoring-not-supported` block links to the per-thread debug log file where raw wire
1283
+ detail can be inspected directly.
1261
1284
 
1262
1285
  The same privacy contract applies: the resulting file may contain prompts, tool arguments, and model output. Treat it as
1263
1286
  sensitive and apply your own retention / scrubbing rules before sharing.
@@ -1491,6 +1514,7 @@ All variants share `{ type: <discriminant>, timestamp: Date }` plus the fields b
1491
1514
  | `mcp-server-discovery-completed` | `agentId`, `serverName`, `toolCount`, `durationMs` |
1492
1515
  | `mcp-server-discovery-failed` | `agentId`, `serverName`, `durationMs`, `error`, `errorDetail?` ([`McpServerErrorDetail`](#mcpservererrordetail)) |
1493
1516
  | `mcp-server-status-changed` | `agentId`, `serverName`, `previousStatus`, `nextStatus`, `error?` |
1517
+ | `llm-retry` | `attempt`, `maxRetries`, `retryDelayMs`, `errorStatus?` — Claude-only; numeric-only and PII-free |
1494
1518
 
1495
1519
  Each variant is also exported as a named type so consumers can write narrowed handlers: `AgentCreatedEvent`,
1496
1520
  `AgentDestroyedEvent`, `SessionCreatedEvent`, `SessionDestroyedEvent`, `ChatStreamStartedEvent`,
@@ -100,11 +100,14 @@ export interface AgentHarness {
100
100
  *
101
101
  * Fidelity may differ between harnesses: the Mastra (in-process) path
102
102
  * emits one `request` + one `response` event per outbound HTTP call,
103
- * with the full body and status visible. The Claude (subprocess) path
104
- * has the seam wired but does not emit yet — emission would parse
105
- * `ANTHROPIC_LOG=debug` stderr from the CLI. Consumers subscribe once
106
- * at the `AgentManager` layer; the SDK forwards events upward through
107
- * the bus hierarchy the same way it does for telemetry and log records.
103
+ * with the full body and status visible. The Claude path runs the model
104
+ * client in an opaque native subprocess with no capturable, parseable
105
+ * per-call debug format, so it emits `wire-monitoring-not-supported`
106
+ * pointing at the subprocess debug-log file rather than structured
107
+ * `llm-request` / `llm-response` events. Structured parsing is deferred
108
+ * pending a stable, capturable debug format. Consumers subscribe once at
109
+ * the `AgentManager` layer; the SDK forwards events upward through the
110
+ * bus hierarchy the same way it does for telemetry and log records.
108
111
  */
109
112
  onWireCommunication(callback: WireCommunicationEventCallback): Unsubscribe;
110
113
  /**
package/dist/index.d.ts CHANGED
@@ -19,11 +19,11 @@ export { type ChatSession, type ChatOptions } from './chat-session.js';
19
19
  export type { AgentConnectivityResolver, ResolvedConnectivity } from './agent-connectivity-resolver.js';
20
20
  export { ApiKeyConnectivityResolver, type ApiKeyConnectivityResolverConfig } from './api-key-connectivity-resolver.js';
21
21
  export type { ModelConnectivityInfo, ProviderHint } from './types/model-connectivity-info.js';
22
- export type { LlmRequestEvent, LlmResponseEvent, WireCommunicationEvent, WireCommunicationEventCallback, WireMonitoringNotSupportedEvent, } from './types/wire-communication-event.js';
22
+ export type { LlmRequestEvent, LlmResponseEvent, McpToolCallCompletedEvent, WireCommunicationEvent, WireCommunicationEventCallback, WireMonitoringNotSupportedEvent, } from './types/wire-communication-event.js';
23
23
  export { WireCommunicationFileWriter, type WireCommunicationEmitter, type WireCommunicationFileWriterOptions, } from './wire-communication-file-writer.js';
24
24
  export type { AgentHarness, HarnessFactory, WithAgentConfig, ConfigOf } from './harness/index.js';
25
25
  export { AgentSDKError, AgentSDKErrorType } from './errors.js';
26
- export type { AgentCreatedEvent, AgentDestroyedEvent, ChatStreamCompletedEvent, ChatStreamErrorEvent, ChatStreamStartedEvent, ChatStreamTrigger, McpServerDiscoveryCompletedEvent, McpServerDiscoveryFailedEvent, McpServerDiscoveryStartedEvent, McpServerStatusChangedEvent, SessionCreatedEvent, SessionDestroyedEvent, TelemetryEvent, TelemetryEventCallback, ToolApprovalPolicyResolvedEvent, ToolApprovalRequestedEvent, ToolApprovalResolvedEvent, ToolExecutionCompletedEvent, ToolExecutionStartedEvent, } from './types/telemetry-events.js';
26
+ export type { AgentCreatedEvent, AgentDestroyedEvent, ChatStreamCompletedEvent, ChatStreamErrorEvent, ChatStreamStartedEvent, ChatStreamTrigger, LlmRetryEvent, McpServerDiscoveryCompletedEvent, McpServerDiscoveryFailedEvent, McpServerDiscoveryStartedEvent, McpServerStatusChangedEvent, SessionCreatedEvent, SessionDestroyedEvent, TelemetryEvent, TelemetryEventCallback, ToolApprovalPolicyResolvedEvent, ToolApprovalRequestedEvent, ToolApprovalResolvedEvent, ToolExecutionCompletedEvent, ToolExecutionStartedEvent, } from './types/telemetry-events.js';
27
27
  export type { LogLevel, LogRecord, Unsubscribe } from '@salesforce/agentic-common';
28
28
  export { resolveMcpServerHeaders } from './mcp-auth.js';
29
29
  export type { OrgConnection, OrgConnectionFactory } from '@salesforce/agentic-common';
@@ -91,10 +91,12 @@ export class TelemetryRouter {
91
91
  return;
92
92
  }
93
93
  }
94
- const agentSlice = this.agentSlices.get(event.agentId);
95
- if (agentSlice) {
96
- agentSlice.telemetry.emit(event);
97
- return;
94
+ if ('agentId' in event) {
95
+ const agentSlice = this.agentSlices.get(event.agentId);
96
+ if (agentSlice) {
97
+ agentSlice.telemetry.emit(event);
98
+ return;
99
+ }
98
100
  }
99
101
  this.unroutedSlice.telemetry.emit(event);
100
102
  }
@@ -178,7 +178,21 @@ export type McpServerStatusChangedEvent = Base<'mcp-server-status-changed'> & {
178
178
  /** Populated when `nextStatus === 'error'`. */
179
179
  error?: string;
180
180
  };
181
- export type TelemetryEvent = AgentCreatedEvent | AgentDestroyedEvent | SessionCreatedEvent | SessionDestroyedEvent | ChatStreamStartedEvent | ChatStreamCompletedEvent | ChatStreamErrorEvent | ToolExecutionStartedEvent | ToolExecutionCompletedEvent | ToolApprovalRequestedEvent | ToolApprovalResolvedEvent | ToolApprovalPolicyResolvedEvent | McpServerDiscoveryStartedEvent | McpServerDiscoveryCompletedEvent | McpServerDiscoveryFailedEvent | McpServerStatusChangedEvent;
181
+ /**
182
+ * Emitted for each retry attempt initiated by the Claude harness.
183
+ *
184
+ * This event is Claude-only by contract: Mastra and OpenAI expose no observable
185
+ * attempt counter. The type has no harness discriminant, but only the Claude
186
+ * harness emits it. Its required retry fields intentionally remain complete so
187
+ * consumers never receive a partial retry record.
188
+ */
189
+ export type LlmRetryEvent = Base<'llm-retry'> & {
190
+ attempt: number;
191
+ maxRetries: number;
192
+ retryDelayMs: number;
193
+ errorStatus?: number;
194
+ };
195
+ export type TelemetryEvent = AgentCreatedEvent | AgentDestroyedEvent | SessionCreatedEvent | SessionDestroyedEvent | ChatStreamStartedEvent | ChatStreamCompletedEvent | ChatStreamErrorEvent | ToolExecutionStartedEvent | ToolExecutionCompletedEvent | ToolApprovalRequestedEvent | ToolApprovalResolvedEvent | ToolApprovalPolicyResolvedEvent | McpServerDiscoveryStartedEvent | McpServerDiscoveryCompletedEvent | McpServerDiscoveryFailedEvent | McpServerStatusChangedEvent | LlmRetryEvent;
182
196
  export type TelemetryEventCallback = (event: TelemetryEvent) => void;
183
197
  export type TelemetryBus = EventBus<TelemetryEvent>;
184
198
  export {};
@@ -1,7 +1,7 @@
1
1
  import type { UsageMetadata } from './usage.js';
2
2
  /**
3
3
  * Wire-level communication events, emitted by the harness layer so consumers
4
- * see the same shape regardless of harness. The union has three members today:
4
+ * see the same shape regardless of harness. The union has four members today:
5
5
  * - `LlmRequestEvent` (`type: 'llm-request'`) — one outbound HTTP request to
6
6
  * the LLM provider.
7
7
  * - `LlmResponseEvent` (`type: 'llm-response'`) — the matching inbound
@@ -12,6 +12,8 @@ import type { UsageMetadata } from './usage.js';
12
12
  * subprocess owns the HTTP traffic). The event carries a free-form
13
13
  * `message` explaining the situation and (when applicable) where the
14
14
  * underlying data was written instead.
15
+ * - `McpToolCallCompletedEvent` (`type: 'mcp-tool-call-completed'`) — an
16
+ * opt-in debug record of an MCP tool call's completed input and output.
15
17
  *
16
18
  * **Privacy contract.** Wire-communication events may contain user prompts,
17
19
  * tool arguments, model output, and other PII. They are opt-in (subscribed
@@ -55,6 +57,18 @@ export type LlmRequestEvent = {
55
57
  method: string;
56
58
  /** Native model id sent on the wire (per `ModelConnectivityInfo.nativeModelId`). */
57
59
  model: string;
60
+ /**
61
+ * Harness-generated per-fetch pairing key. Stamped identically on the matching
62
+ * `LlmResponseEvent`; consumers MUST use it as the reliable pairing key rather
63
+ * than positional event ordering. Producers obtain it from the injected
64
+ * `UniqueIDGenerator` in `@salesforce/agentic-common`, never `randomUUID()`.
65
+ */
66
+ correlationId?: string;
67
+ /**
68
+ * `x-client-trace-id` header value attached to this request. Consumers pair on
69
+ * `correlationId` (the harness-guaranteed key) and may cross-check this value.
70
+ */
71
+ xClientTraceId?: string;
58
72
  /** Request body. Best-effort: partial / absent on harnesses that can't observe it. */
59
73
  body?: Record<string, unknown>;
60
74
  };
@@ -65,6 +79,13 @@ export type LlmResponseEvent = {
65
79
  timestamp: Date;
66
80
  /** Native model id from the matching request. */
67
81
  model: string;
82
+ /**
83
+ * Harness-generated per-fetch pairing key. Stamped identically on the matching
84
+ * `LlmRequestEvent`; consumers MUST use it as the reliable pairing key rather
85
+ * than positional event ordering. Producers obtain it from the injected
86
+ * `UniqueIDGenerator` in `@salesforce/agentic-common`, never `randomUUID()`.
87
+ */
88
+ correlationId?: string;
68
89
  /** HTTP status code; `0` for harness-internal terminal failures with no transport response. */
69
90
  status: number;
70
91
  /** Error captured from a transport / parse failure, if any. */
@@ -85,9 +106,42 @@ export type LlmResponseEvent = {
85
106
  totalDurationMs?: number;
86
107
  /** Best-effort extracted response text (may be omitted by the harness). */
87
108
  responseText?: string;
88
- /** `x-client-trace-id` header value the SDK / harness attached to the request. */
109
+ /**
110
+ * `x-client-trace-id` header value attached to the matching request. Consumers
111
+ * pair on `correlationId` (the harness-guaranteed key) and may cross-check this value.
112
+ */
89
113
  xClientTraceId?: string;
90
114
  };
115
+ /**
116
+ * Debug-only, opt-in, subscriber-gated record of a completed MCP tool call.
117
+ * `args` and `result` are captured verbatim and MAY contain PII, so consumers
118
+ * must redact before persisting or sharing. This is not a telemetry event and
119
+ * MUST NOT be added to `TelemetryEvent` or any externally-shipped surface.
120
+ *
121
+ * `toolName` is the harness-namespaced display name and `bareToolName` is the
122
+ * un-namespaced leaf. `durationMs` semantics differ by harness: the Claude
123
+ * bridge reports true RPC latency, while Mastra and OpenAI report an
124
+ * adapter/coordinator-observed window that may include a model round-trip.
125
+ * Consumers MUST NOT compare durations across harnesses.
126
+ */
127
+ export type McpToolCallCompletedEvent = {
128
+ /** Direction discriminator. */
129
+ type: 'mcp-tool-call-completed';
130
+ /** Wall-clock timestamp when the tool call completed. */
131
+ timestamp: Date;
132
+ /** Logical MCP server name from the configured server catalog. */
133
+ serverName: string;
134
+ /** Harness-namespaced display name presented to the model. */
135
+ toolName: string;
136
+ /** Un-namespaced tool-name leaf. */
137
+ bareToolName: string;
138
+ /** Verbatim arguments passed to the tool. May contain PII. */
139
+ args: Record<string, unknown>;
140
+ /** Verbatim result returned by the tool. May contain PII. */
141
+ result: unknown;
142
+ /** Harness-dependent observed duration; do not compare across harnesses. */
143
+ durationMs?: number;
144
+ };
91
145
  /**
92
146
  * Emitted by harnesses whose runtime doesn't expose a programmatic seam for
93
147
  * per-call wire monitoring. The event signals to consumers that
@@ -120,5 +174,5 @@ export type WireMonitoringNotSupportedEvent = {
120
174
  * Union over every wire-communication event the harness layer can emit.
121
175
  * Discriminate on the `type` field.
122
176
  */
123
- export type WireCommunicationEvent = LlmRequestEvent | LlmResponseEvent | WireMonitoringNotSupportedEvent;
177
+ export type WireCommunicationEvent = LlmRequestEvent | LlmResponseEvent | McpToolCallCompletedEvent | WireMonitoringNotSupportedEvent;
124
178
  export type WireCommunicationEventCallback = (event: WireCommunicationEvent) => void;
@@ -68,6 +68,8 @@ function formatAsMarkdown(event) {
68
68
  return formatRequestMarkdown(event);
69
69
  case 'llm-response':
70
70
  return formatResponseMarkdown(event);
71
+ case 'mcp-tool-call-completed':
72
+ return formatMcpToolCallCompletedMarkdown(event);
71
73
  case 'wire-monitoring-not-supported':
72
74
  return formatWireMonitoringNotSupportedMarkdown(event);
73
75
  }
@@ -135,6 +137,32 @@ function formatResponseMarkdown(event) {
135
137
  }
136
138
  return lines.join('\n');
137
139
  }
140
+ function formatMcpToolCallCompletedMarkdown(event) {
141
+ const lines = [
142
+ `### ${event.timestamp.toISOString()} [${event.type}]`,
143
+ ``,
144
+ `**Server**: ${event.serverName}`,
145
+ ``,
146
+ `**Tool**: ${event.toolName}`,
147
+ ``,
148
+ `**Bare tool**: ${event.bareToolName}`,
149
+ ``,
150
+ `**Args**:`,
151
+ '```json',
152
+ JSON.stringify(event.args, null, 2),
153
+ '```',
154
+ ``,
155
+ `**Result**:`,
156
+ '```json',
157
+ JSON.stringify(event.result, null, 2),
158
+ '```',
159
+ ``,
160
+ ];
161
+ if (event.durationMs !== undefined) {
162
+ lines.push(`**Duration**: ${event.durationMs}`, ``);
163
+ }
164
+ return lines.join('\n');
165
+ }
138
166
  function formatWireMonitoringNotSupportedMarkdown(event) {
139
167
  const dateTime = event.timestamp.toISOString();
140
168
  return [`### ${dateTime} [${event.type}]`, ``, `**Harness**: ${event.harnessId}`, ``, event.message, ``, ``].join('\n');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/sfdx-agent-sdk",
3
- "version": "0.38.0",
3
+ "version": "0.40.0",
4
4
  "description": "Harness-agnostic agentic infrastructure for Salesforce developer experience tooling",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -47,9 +47,9 @@
47
47
  },
48
48
  "devDependencies": {
49
49
  "@eslint/js": "^10.0.1",
50
- "@salesforce/sfdx-agent-harness-claude": "0.34.0",
51
- "@salesforce/sfdx-agent-harness-mastra": "0.37.0",
52
- "@salesforce/sfdx-agent-harness-openai": "0.3.0",
50
+ "@salesforce/sfdx-agent-harness-claude": "0.36.0",
51
+ "@salesforce/sfdx-agent-harness-mastra": "0.39.0",
52
+ "@salesforce/sfdx-agent-harness-openai": "0.5.0",
53
53
  "@types/node": "^22.20.0",
54
54
  "@vitest/coverage-istanbul": "^4.1.10",
55
55
  "@vitest/eslint-plugin": "^1.6.22",