@salesforce/sfdx-agent-sdk 0.14.0 → 0.16.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/README.md +255 -100
- package/dist/agent-connectivity-resolver.d.ts +16 -1
- package/dist/agent-connectivity-resolver.js +54 -3
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +30 -14
- package/dist/chat-session.d.ts +109 -27
- package/dist/chat-session.js +120 -26
- package/dist/harness/agent-harness.d.ts +59 -22
- package/dist/harness/gen-sink.d.ts +41 -0
- package/dist/harness/gen-sink.js +88 -0
- package/dist/harness/harness-config.d.ts +10 -3
- package/dist/harness/index.d.ts +1 -0
- package/dist/harness/index.js +1 -0
- package/dist/harness/public.d.ts +49 -0
- package/dist/harness/public.js +10 -0
- package/dist/index.d.ts +3 -5
- package/dist/index.js +1 -4
- package/dist/mcp-config.d.ts +26 -0
- package/dist/types/events.d.ts +1 -14
- package/dist/types/messages.d.ts +12 -1
- package/dist/types/usage.d.ts +65 -0
- package/package.json +9 -5
|
@@ -112,7 +112,14 @@ export interface AgentHarness {
|
|
|
112
112
|
}): Promise<void>;
|
|
113
113
|
/**
|
|
114
114
|
* Destroy an agent and release its resources (MCP connections, workspace, memory).
|
|
115
|
+
*
|
|
116
|
+
* MUST throw if `agentId` is not registered. Symmetric with `createThread`,
|
|
117
|
+
* `destroyThread`, and `clearMessages`, which all reject unknown ids the
|
|
118
|
+
* same way; gives SDK rollback paths in `Agent.updateAgentConfig` and
|
|
119
|
+
* `AgentManager.installAgent` an explicit failure mode they can catch.
|
|
120
|
+
*
|
|
115
121
|
* @param agentId - ID of the agent to destroy.
|
|
122
|
+
* @returns `true` after a real removal.
|
|
116
123
|
*/
|
|
117
124
|
destroyAgent(agentId: string): Promise<boolean>;
|
|
118
125
|
/**
|
|
@@ -124,8 +131,11 @@ export interface AgentHarness {
|
|
|
124
131
|
* including connection status and discovered tool names. This is a synchronous
|
|
125
132
|
* snapshot — status is updated asynchronously by background discovery promises.
|
|
126
133
|
*
|
|
134
|
+
* MUST throw if `agentId` is not registered.
|
|
135
|
+
*
|
|
127
136
|
* @param agentId - ID of the agent whose MCP servers to inspect.
|
|
128
|
-
* @returns Info for each configured MCP server (empty array if
|
|
137
|
+
* @returns Info for each configured MCP server (empty array if the agent
|
|
138
|
+
* exists but has no MCP servers configured).
|
|
129
139
|
*/
|
|
130
140
|
getMcpServerInfo(agentId: string): McpServerInfo[];
|
|
131
141
|
/**
|
|
@@ -175,14 +185,31 @@ export interface AgentHarness {
|
|
|
175
185
|
*/
|
|
176
186
|
getThreadIds(agentId: string): Promise<string[]>;
|
|
177
187
|
/**
|
|
178
|
-
* Clone an existing thread, creating a new thread
|
|
179
|
-
* Used to implement conversation
|
|
188
|
+
* Clone an existing thread, creating a new thread that mirrors the source
|
|
189
|
+
* thread's state at the moment of the call. Used to implement conversation
|
|
190
|
+
* forking.
|
|
191
|
+
*
|
|
192
|
+
* The harness chooses the new thread's id; consumers read it from the
|
|
193
|
+
* returned value. The id is unique within the agent.
|
|
194
|
+
*
|
|
195
|
+
* Two source-state shapes are observable to consumers:
|
|
196
|
+
*
|
|
197
|
+
* - **Source thread has been streamed at least once** — the new thread
|
|
198
|
+
* inherits the source's persisted message history; subsequent
|
|
199
|
+
* `getMessages()` returns it. Implementations may copy the underlying
|
|
200
|
+
* transcript (Mastra's libsql `cloneThread`, Claude's `forkSession`)
|
|
201
|
+
* or any harness-specific equivalent.
|
|
202
|
+
* - **Source thread has never been streamed** (`addContext`-only or
|
|
203
|
+
* freshly-created) — the new thread is allocated empty by design;
|
|
204
|
+
* `addContext`-injected messages on the source are copied forward by
|
|
205
|
+
* harnesses that mirror them in-process, but no persisted transcript
|
|
206
|
+
* exists to fork.
|
|
207
|
+
*
|
|
180
208
|
* @param agentId - ID of the owning agent.
|
|
181
209
|
* @param sourceThreadId - ID of the thread to clone.
|
|
182
|
-
* @param targetThreadId - Optional ID for the new thread.
|
|
183
210
|
* @returns The ID of the cloned thread.
|
|
184
211
|
*/
|
|
185
|
-
cloneThread(agentId: string, sourceThreadId: string
|
|
212
|
+
cloneThread(agentId: string, sourceThreadId: string): Promise<string>;
|
|
186
213
|
/**
|
|
187
214
|
* Compacts a thread's message history to reduce context window usage.
|
|
188
215
|
* Starts a new conversation thread seeded with an LLM-generated summary of the current session.
|
|
@@ -211,55 +238,65 @@ export interface AgentHarness {
|
|
|
211
238
|
stream(agentId: string, threadId: string, message: string | MessagePart[], options?: StreamOptions): Promise<ChatStreamResult>;
|
|
212
239
|
/**
|
|
213
240
|
* Feed the result of a **consumer-executed (client-side) tool** back into the
|
|
214
|
-
* conversation
|
|
241
|
+
* conversation. Implements the consumer-facing
|
|
215
242
|
* {@link ChatSession.submitToolResult} contract: see that JSDoc for the
|
|
216
243
|
* full consumer-level semantics.
|
|
217
244
|
*
|
|
218
245
|
* Called only for tools declared in {@link HarnessAgentConfig.tools} (no
|
|
219
246
|
* `execute` function). Tools provided via `mcpServers` are executed by the
|
|
220
|
-
* harness directly and never reach this method.
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
*
|
|
247
|
+
* harness directly and never reach this method.
|
|
248
|
+
*
|
|
249
|
+
* Returns `Promise<void>` once the harness has accepted the tool result
|
|
250
|
+
* (the parked bridge handler resolved). Post-resume events
|
|
251
|
+
* (`tool-result`, model follow-up text, terminal `finish`) flow through
|
|
252
|
+
* the SAME `ChatStreamResult.eventStream` returned by the most recent
|
|
253
|
+
* {@link stream} call on the thread — the consumer is still iterating
|
|
254
|
+
* that stream and sees the events arrive.
|
|
224
255
|
*
|
|
225
256
|
* @param agentId - ID of the agent.
|
|
226
257
|
* @param threadId - ID of the conversation thread.
|
|
227
258
|
* @param toolResult - The completed tool execution result; `toolCallId`
|
|
228
259
|
* matches the id from the originating `tool-call` event.
|
|
229
260
|
*/
|
|
230
|
-
submitToolResult(agentId: string, threadId: string, toolResult: ToolResultInfo): Promise<
|
|
261
|
+
submitToolResult(agentId: string, threadId: string, toolResult: ToolResultInfo): Promise<void>;
|
|
231
262
|
/**
|
|
232
263
|
* Approve a pending tool call, allowing the harness to execute it.
|
|
233
264
|
* Called after receiving a `tool-approval-request` event.
|
|
234
265
|
*
|
|
235
|
-
* Returns
|
|
236
|
-
*
|
|
237
|
-
*
|
|
266
|
+
* Returns `Promise<void>` once the harness has accepted the approval
|
|
267
|
+
* (the parked PreToolUse hook resolved on Claude; the resume call was
|
|
268
|
+
* dispatched on Mastra). Post-resume events flow through the SAME
|
|
269
|
+
* `ChatStreamResult.eventStream` returned by the most recent
|
|
270
|
+
* {@link stream} call on the thread.
|
|
238
271
|
*
|
|
239
272
|
* @param agentId - ID of the agent.
|
|
240
273
|
* @param threadId - ID of the conversation thread (needed for harness-internal state lookup).
|
|
241
274
|
* @param toolCallId - ID of the tool call to approve.
|
|
242
275
|
*/
|
|
243
|
-
approveToolCall(agentId: string, threadId: string, toolCallId: string): Promise<
|
|
276
|
+
approveToolCall(agentId: string, threadId: string, toolCallId: string): Promise<void>;
|
|
244
277
|
/**
|
|
245
|
-
* Decline a pending tool call. The harness resumes the
|
|
246
|
-
* model acknowledging the decline and potentially suggesting
|
|
278
|
+
* Decline a pending tool call. The harness resumes the agentic loop with
|
|
279
|
+
* the model acknowledging the decline and potentially suggesting
|
|
280
|
+
* alternatives.
|
|
247
281
|
*
|
|
248
|
-
* Returns
|
|
249
|
-
*
|
|
250
|
-
*
|
|
282
|
+
* Returns `Promise<void>` once the harness has accepted the decline.
|
|
283
|
+
* Post-resume events flow through the SAME `ChatStreamResult.eventStream`
|
|
284
|
+
* returned by the most recent {@link stream} call on the thread.
|
|
251
285
|
*
|
|
252
286
|
* @param agentId - ID of the agent.
|
|
253
287
|
* @param threadId - ID of the conversation thread.
|
|
254
288
|
* @param toolCallId - ID of the tool call to decline.
|
|
255
289
|
*/
|
|
256
|
-
declineToolCall(agentId: string, threadId: string, toolCallId: string): Promise<
|
|
290
|
+
declineToolCall(agentId: string, threadId: string, toolCallId: string): Promise<void>;
|
|
257
291
|
/**
|
|
258
292
|
* Retrieve message history for a thread.
|
|
259
293
|
*
|
|
294
|
+
* MUST populate `Message.createdAt` on every returned message. MUST return
|
|
295
|
+
* messages sorted ascending by `createdAt`.
|
|
296
|
+
*
|
|
260
297
|
* @param agentId - ID of the agent.
|
|
261
298
|
* @param threadId - ID of the conversation thread.
|
|
262
|
-
* @returns All messages in chronological order (ascending by
|
|
299
|
+
* @returns All messages in chronological order (ascending by `createdAt`).
|
|
263
300
|
*/
|
|
264
301
|
getMessages(agentId: string, threadId: string): Promise<Message[]>;
|
|
265
302
|
/**
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Buffered async-generator wrapper used by `AgentHarness` implementations to
|
|
3
|
+
* deliver `ChatEvent`s to a consumer's `ChatStreamResult.eventStream`.
|
|
4
|
+
*
|
|
5
|
+
* The buffer holds events pushed before the consumer starts iterating, so the
|
|
6
|
+
* harness can begin populating the sink eagerly without coordinating with the
|
|
7
|
+
* consumer's `for await` loop. Events pushed after iteration starts unblock
|
|
8
|
+
* the awaiting consumer via an internal Promise waiter.
|
|
9
|
+
*
|
|
10
|
+
* # Single-iteration invariant
|
|
11
|
+
*
|
|
12
|
+
* `generator()` may be called **at most once** per sink. Sinks are stateful
|
|
13
|
+
* (single waiter slot, single buffer); two iterators on the same sink race on
|
|
14
|
+
* both, so two iterators is always a bug. Calling `generator()` a second time
|
|
15
|
+
* throws — the alternative (silently allowing the second call to share the
|
|
16
|
+
* buffer / waiter with the first) produced the deadlock-class bug catalogued
|
|
17
|
+
* in [issue #529](https://github.com/forcedotcom/agentic-dx/issues/529)
|
|
18
|
+
* Finding 4. Surface failures at construction-time, not at deadlock-time.
|
|
19
|
+
*
|
|
20
|
+
* # `isEnded()`
|
|
21
|
+
*
|
|
22
|
+
* Exposes the closed state for routing logic that needs to skip pushes onto
|
|
23
|
+
* a sink that's already been retired. Routing for a closed sink should
|
|
24
|
+
* silently no-op with a debug log rather than throw — the late event is
|
|
25
|
+
* upstream noise, not a programmer error.
|
|
26
|
+
*
|
|
27
|
+
* Exported from the public `index.ts` so third-party `AgentHarness`
|
|
28
|
+
* implementations in sibling packages can reuse it.
|
|
29
|
+
*/
|
|
30
|
+
export declare class GenSink<T> {
|
|
31
|
+
private readonly buffered;
|
|
32
|
+
private ended;
|
|
33
|
+
private waiter;
|
|
34
|
+
private generated;
|
|
35
|
+
push(event: T): void;
|
|
36
|
+
end(): void;
|
|
37
|
+
isEnded(): boolean;
|
|
38
|
+
generator(): AsyncGenerator<T, void>;
|
|
39
|
+
private iterate;
|
|
40
|
+
private wake;
|
|
41
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026, Salesforce, Inc. All rights reserved.
|
|
3
|
+
* See LICENSE.txt for license terms.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Buffered async-generator wrapper used by `AgentHarness` implementations to
|
|
7
|
+
* deliver `ChatEvent`s to a consumer's `ChatStreamResult.eventStream`.
|
|
8
|
+
*
|
|
9
|
+
* The buffer holds events pushed before the consumer starts iterating, so the
|
|
10
|
+
* harness can begin populating the sink eagerly without coordinating with the
|
|
11
|
+
* consumer's `for await` loop. Events pushed after iteration starts unblock
|
|
12
|
+
* the awaiting consumer via an internal Promise waiter.
|
|
13
|
+
*
|
|
14
|
+
* # Single-iteration invariant
|
|
15
|
+
*
|
|
16
|
+
* `generator()` may be called **at most once** per sink. Sinks are stateful
|
|
17
|
+
* (single waiter slot, single buffer); two iterators on the same sink race on
|
|
18
|
+
* both, so two iterators is always a bug. Calling `generator()` a second time
|
|
19
|
+
* throws — the alternative (silently allowing the second call to share the
|
|
20
|
+
* buffer / waiter with the first) produced the deadlock-class bug catalogued
|
|
21
|
+
* in [issue #529](https://github.com/forcedotcom/agentic-dx/issues/529)
|
|
22
|
+
* Finding 4. Surface failures at construction-time, not at deadlock-time.
|
|
23
|
+
*
|
|
24
|
+
* # `isEnded()`
|
|
25
|
+
*
|
|
26
|
+
* Exposes the closed state for routing logic that needs to skip pushes onto
|
|
27
|
+
* a sink that's already been retired. Routing for a closed sink should
|
|
28
|
+
* silently no-op with a debug log rather than throw — the late event is
|
|
29
|
+
* upstream noise, not a programmer error.
|
|
30
|
+
*
|
|
31
|
+
* Exported from the public `index.ts` so third-party `AgentHarness`
|
|
32
|
+
* implementations in sibling packages can reuse it.
|
|
33
|
+
*/
|
|
34
|
+
export class GenSink {
|
|
35
|
+
buffered = [];
|
|
36
|
+
ended = false;
|
|
37
|
+
waiter = null;
|
|
38
|
+
generated = false;
|
|
39
|
+
push(event) {
|
|
40
|
+
if (this.ended)
|
|
41
|
+
return;
|
|
42
|
+
this.buffered.push(event);
|
|
43
|
+
this.wake();
|
|
44
|
+
}
|
|
45
|
+
end() {
|
|
46
|
+
if (this.ended)
|
|
47
|
+
return;
|
|
48
|
+
this.ended = true;
|
|
49
|
+
this.wake();
|
|
50
|
+
}
|
|
51
|
+
isEnded() {
|
|
52
|
+
return this.ended;
|
|
53
|
+
}
|
|
54
|
+
generator() {
|
|
55
|
+
// Synchronous guard. Must live outside the async generator body —
|
|
56
|
+
// async generators are lazy (the body does not execute until the
|
|
57
|
+
// first `next()`), so a `throw` inside the body would not surface
|
|
58
|
+
// at the second `generator()` call site as expected.
|
|
59
|
+
if (this.generated) {
|
|
60
|
+
throw new Error('GenSink.generator(): sinks are single-iteration. ' +
|
|
61
|
+
'Two iterators on one sink race on the buffer and waiter slot. ' +
|
|
62
|
+
'See https://github.com/forcedotcom/agentic-dx/issues/529 (Finding 4).');
|
|
63
|
+
}
|
|
64
|
+
this.generated = true;
|
|
65
|
+
return this.iterate();
|
|
66
|
+
}
|
|
67
|
+
async *iterate() {
|
|
68
|
+
while (true) {
|
|
69
|
+
if (this.buffered.length > 0) {
|
|
70
|
+
yield this.buffered.shift();
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (this.ended)
|
|
74
|
+
return;
|
|
75
|
+
await new Promise((resolve) => {
|
|
76
|
+
this.waiter = { resolve };
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
wake() {
|
|
81
|
+
const w = this.waiter;
|
|
82
|
+
if (w) {
|
|
83
|
+
this.waiter = null;
|
|
84
|
+
w.resolve();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=gen-sink.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ToolDefinition } from '../types/tools.js';
|
|
2
2
|
import type { MCPConfiguration } from '../mcp-config.js';
|
|
3
|
-
import type { JSONWebToken, ModelName } from '@salesforce/llm-gateway-sdk';
|
|
3
|
+
import type { JSONWebToken, Model, ModelName } from '@salesforce/llm-gateway-sdk';
|
|
4
4
|
/**
|
|
5
5
|
* Configuration for an agent's behavior and capabilities.
|
|
6
6
|
* This excludes identity; `agentId` is handled separately.
|
|
@@ -14,8 +14,15 @@ export type AgentConfig = {
|
|
|
14
14
|
* - Otherwise, use the default org configured on the machine.
|
|
15
15
|
*/
|
|
16
16
|
orgAlias?: string;
|
|
17
|
-
/**
|
|
18
|
-
|
|
17
|
+
/**
|
|
18
|
+
* The model to use for this agent.
|
|
19
|
+
*
|
|
20
|
+
* Accepts either a {@link ModelName} enum value (the typical case for in-tree models) or a
|
|
21
|
+
* pre-built {@link Model} instance. The instance form lets consumers opt into a Claude
|
|
22
|
+
* variant published on the gateway before the SDK has been updated — see
|
|
23
|
+
* `createClaudeModel(gatewayId, overrides)` from `@salesforce/llm-gateway-sdk`.
|
|
24
|
+
*/
|
|
25
|
+
modelId?: ModelName | Model;
|
|
19
26
|
/** Human-readable name for the agent. */
|
|
20
27
|
name?: string;
|
|
21
28
|
/** Description of the agent's purpose. ACP/OASF-ready metadata. */
|
package/dist/harness/index.d.ts
CHANGED
|
@@ -2,3 +2,4 @@ export type { AgentHarness, WithAgentConfig, ConfigOf } from './agent-harness.js
|
|
|
2
2
|
export type { HarnessFactory } from './harness-factory.js';
|
|
3
3
|
export type { AgentConfig, StreamOptions } from './harness-config.js';
|
|
4
4
|
export { toHarnessConfig, DEFAULT_MAX_STEPS } from './harness-config.js';
|
|
5
|
+
export { GenSink } from './gen-sink.js';
|
package/dist/harness/index.js
CHANGED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness-implementation public surface.
|
|
3
|
+
*
|
|
4
|
+
* This module is reachable as `@salesforce/sfdx-agent-sdk/harness` —
|
|
5
|
+
* **never** import directly from `dist/` or via deep relative paths.
|
|
6
|
+
*
|
|
7
|
+
* # When to import from here
|
|
8
|
+
*
|
|
9
|
+
* Use this surface when implementing an `AgentHarness` (e.g.
|
|
10
|
+
* `@salesforce/sfdx-agent-harness-claude`,
|
|
11
|
+
* `@salesforce/sfdx-agent-harness-mastra`). It re-exports both the
|
|
12
|
+
* harness contract types (`AgentHarness`, `HarnessFactory`) and the
|
|
13
|
+
* harness-implementation helpers consumer applications must not touch
|
|
14
|
+
* (`HarnessBusOwner`, `GenSink`, `lowerStreamInput`,
|
|
15
|
+
* `SUPPORTED_PROTOCOL_VERSIONS`).
|
|
16
|
+
*
|
|
17
|
+
* # Why this is a separate subpath
|
|
18
|
+
*
|
|
19
|
+
* Consumer applications (anything that calls `createAgentManager` and
|
|
20
|
+
* iterates `ChatStreamResult`) import from the bare specifier:
|
|
21
|
+
*
|
|
22
|
+
* import { createAgentManager, Agent } from '@salesforce/sfdx-agent-sdk';
|
|
23
|
+
*
|
|
24
|
+
* Harness implementations import from the subpath:
|
|
25
|
+
*
|
|
26
|
+
* import { HarnessBusOwner, GenSink } from '@salesforce/sfdx-agent-sdk/harness';
|
|
27
|
+
*
|
|
28
|
+
* The split makes the boundary mechanical: a consumer who tries to import
|
|
29
|
+
* `HarnessBusOwner` from the bare specifier gets an immediate
|
|
30
|
+
* "not exported" error from the bundler / TS resolver, instead of
|
|
31
|
+
* accidentally reaching for a primitive they shouldn't be using.
|
|
32
|
+
*
|
|
33
|
+
* Type-only references to the contract interface (`AgentHarness`,
|
|
34
|
+
* `HarnessFactory`) ALSO appear on the bare specifier so consumer code
|
|
35
|
+
* that needs `AgentManager<H extends AgentHarness>` typing still works
|
|
36
|
+
* without a subpath import — but their runtime / constructible
|
|
37
|
+
* counterparts live only here.
|
|
38
|
+
*
|
|
39
|
+
* Symbols that consumers and harnesses both need (`AgentConfig`,
|
|
40
|
+
* `StreamOptions`, `DEFAULT_MAX_STEPS`, `resolveToolApprovalMode`,
|
|
41
|
+
* `ChatEvent` types, `Message` types, `MCPConfiguration`, etc.) stay on
|
|
42
|
+
* the bare specifier. The split is "harness-only" vs. "consumer-AND-harness",
|
|
43
|
+
* not "harness vs. consumer."
|
|
44
|
+
*/
|
|
45
|
+
export type { AgentHarness, HarnessFactory, WithAgentConfig, ConfigOf } from './index.js';
|
|
46
|
+
export { SUPPORTED_PROTOCOL_VERSIONS } from './agent-harness.js';
|
|
47
|
+
export { HarnessBusOwner } from './harness-bus-owner.js';
|
|
48
|
+
export { lowerStreamInput, type InputMessagePart } from './stream-input.js';
|
|
49
|
+
export { GenSink } from './gen-sink.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026, Salesforce, Inc. All rights reserved.
|
|
3
|
+
* See LICENSE.txt for license terms.
|
|
4
|
+
*/
|
|
5
|
+
export { SUPPORTED_PROTOCOL_VERSIONS } from './agent-harness.js';
|
|
6
|
+
// ── Harness-implementation helpers ──────────────────────────────────
|
|
7
|
+
export { HarnessBusOwner } from './harness-bus-owner.js';
|
|
8
|
+
export { lowerStreamInput } from './stream-input.js';
|
|
9
|
+
export { GenSink } from './gen-sink.js';
|
|
10
|
+
//# sourceMappingURL=public.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
export type { Message, MessagePart, ImagePart, FilePart } from './types/messages.js';
|
|
2
2
|
export type { ChatEvent, StartEvent, TextDeltaEvent, ReasoningDeltaEvent, ToolCallEvent, ToolApprovalRequestEvent, ToolResultEvent, StepStartEvent, StepFinishEvent, ErrorEvent, FinishEvent, ChatStreamResult, } from './types/events.js';
|
|
3
3
|
export type { ToolDefinition, ToolCallInfo, ToolResultInfo } from './types/tools.js';
|
|
4
|
-
export type { FinishReason, UsageMetadata } from './types/usage.js';
|
|
4
|
+
export type { ContextUsage, FinishReason, UsageMetadata } from './types/usage.js';
|
|
5
5
|
export type { AgentConfig, HarnessAgentConfig, StreamOptions, ToolApprovalMode } from './harness/harness-config.js';
|
|
6
6
|
export { DEFAULT_MAX_STEPS, resolveToolApprovalMode } from './harness/harness-config.js';
|
|
7
7
|
export type { MCPConfiguration, MCPServerConfig, MCPStdioServerConfig, MCPRemoteServerConfig, McpServerInfo, McpServerErrorCategory, McpServerErrorDetail, McpToolInfo, McpToolAnnotations, } from './mcp-config.js';
|
|
8
8
|
export { McpServerStatus } from './mcp-config.js';
|
|
9
|
-
export { ModelName } from '@salesforce/llm-gateway-sdk';
|
|
9
|
+
export { Model, ModelName, createClaudeModel } from '@salesforce/llm-gateway-sdk';
|
|
10
|
+
export type { ClaudeModelOverrides } from '@salesforce/llm-gateway-sdk';
|
|
10
11
|
export { inferSfApiEnv, SfApiEnv } from '@salesforce/agentic-common';
|
|
11
12
|
export { type AgentManager, type RestoreFailure, createAgentManager } from './agent-manager.js';
|
|
12
13
|
export { type Agent } from './agent.js';
|
|
13
14
|
export { type ChatSession, type ChatOptions } from './chat-session.js';
|
|
14
15
|
export type { AgentConnectivityResolver, ResolvedConnectivity } from './agent-connectivity-resolver.js';
|
|
15
16
|
export type { AgentHarness, HarnessFactory, WithAgentConfig, ConfigOf } from './harness/index.js';
|
|
16
|
-
export { SUPPORTED_PROTOCOL_VERSIONS } from './harness/agent-harness.js';
|
|
17
|
-
export { HarnessBusOwner } from './harness/harness-bus-owner.js';
|
|
18
|
-
export { lowerStreamInput, type InputMessagePart } from './harness/stream-input.js';
|
|
19
17
|
export { AgentSDKError, AgentSDKErrorType } from './errors.js';
|
|
20
18
|
export type { AgentCreatedEvent, AgentDestroyedEvent, ChatStreamCompletedEvent, ChatStreamErrorEvent, ChatStreamStartedEvent, ChatStreamTrigger, McpServerDiscoveryCompletedEvent, McpServerDiscoveryFailedEvent, McpServerDiscoveryStartedEvent, McpServerStatusChangedEvent, SessionCreatedEvent, SessionDestroyedEvent, TelemetryEvent, TelemetryEventCallback, ToolApprovalRequestedEvent, ToolApprovalResolvedEvent, ToolExecutionCompletedEvent, ToolExecutionStartedEvent, } from './types/telemetry-events.js';
|
|
21
19
|
export type { LogLevel, LogRecord, Unsubscribe } from '@salesforce/agentic-common';
|
package/dist/index.js
CHANGED
|
@@ -4,15 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { DEFAULT_MAX_STEPS, resolveToolApprovalMode } from './harness/harness-config.js';
|
|
6
6
|
export { McpServerStatus } from './mcp-config.js';
|
|
7
|
-
export { ModelName } from '@salesforce/llm-gateway-sdk';
|
|
7
|
+
export { Model, ModelName, createClaudeModel } from '@salesforce/llm-gateway-sdk';
|
|
8
8
|
export { inferSfApiEnv, SfApiEnv } from '@salesforce/agentic-common';
|
|
9
9
|
// ── Agent Layer ─────────────────────────────────────────────────────
|
|
10
10
|
export { createAgentManager } from './agent-manager.js';
|
|
11
11
|
export {} from './agent.js';
|
|
12
12
|
export {} from './chat-session.js';
|
|
13
|
-
export { SUPPORTED_PROTOCOL_VERSIONS } from './harness/agent-harness.js';
|
|
14
|
-
export { HarnessBusOwner } from './harness/harness-bus-owner.js';
|
|
15
|
-
export { lowerStreamInput } from './harness/stream-input.js';
|
|
16
13
|
// ── Errors ───────────────────────────────────────────────────────────
|
|
17
14
|
export { AgentSDKError, AgentSDKErrorType } from './errors.js';
|
|
18
15
|
// ── MCP Auth ────────────────────────────────────────────────────────
|
package/dist/mcp-config.d.ts
CHANGED
|
@@ -65,6 +65,32 @@ export type MCPRemoteServerConfig = {
|
|
|
65
65
|
enabled?: boolean;
|
|
66
66
|
/** Timeout in milliseconds for individual requests to the server. */
|
|
67
67
|
timeout?: number;
|
|
68
|
+
/**
|
|
69
|
+
* Transport-level reconnection tuning for HTTP MCP servers. Forwarded to
|
|
70
|
+
* the underlying SDK transport (`@modelcontextprotocol/sdk`'s
|
|
71
|
+
* `StreamableHTTPClientTransport` on the Claude harness, and the
|
|
72
|
+
* equivalent plumb-through on `@mastra/mcp`'s `HttpServerDefinition`).
|
|
73
|
+
*
|
|
74
|
+
* Each field is optional. The harness mappers merge unspecified fields
|
|
75
|
+
* with the MCP SDK's built-in defaults (`maxRetries: 2`,
|
|
76
|
+
* `initialReconnectionDelay: 1000`, `maxReconnectionDelay: 30000`,
|
|
77
|
+
* `reconnectionDelayGrowFactor: 1.5`) so a partial override leaves the
|
|
78
|
+
* other fields at their defaults rather than zeroing them out — the
|
|
79
|
+
* underlying transport replaces the entire defaults object when
|
|
80
|
+
* `reconnectionOptions` is set.
|
|
81
|
+
*
|
|
82
|
+
* No-op for stdio servers — only `MCPRemoteServerConfig` carries it.
|
|
83
|
+
*/
|
|
84
|
+
reconnectionOptions?: {
|
|
85
|
+
/** Maximum number of reconnection attempts before giving up. Default `2`. */
|
|
86
|
+
maxRetries?: number;
|
|
87
|
+
/** Initial backoff between reconnection attempts in milliseconds. Default `1000`. */
|
|
88
|
+
initialReconnectionDelay?: number;
|
|
89
|
+
/** Maximum backoff between reconnection attempts in milliseconds. Default `30000`. */
|
|
90
|
+
maxReconnectionDelay?: number;
|
|
91
|
+
/** Factor by which the reconnection delay grows after each attempt. Default `1.5`. */
|
|
92
|
+
reconnectionDelayGrowFactor?: number;
|
|
93
|
+
};
|
|
68
94
|
/**
|
|
69
95
|
* Opt the server's tool surface out of the active runtime's tool-search
|
|
70
96
|
* deferral. See {@link MCPStdioServerConfig.alwaysLoad}.
|
package/dist/types/events.d.ts
CHANGED
|
@@ -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 | ToolApprovalRequestEvent | ToolResultEvent | StepStartEvent | StepFinishEvent | ErrorEvent | FinishEvent;
|
|
12
12
|
/**
|
|
13
13
|
* The stream has begun. Symmetric counterpart to {@link FinishEvent}.
|
|
14
14
|
*
|
|
@@ -155,19 +155,6 @@ export type ErrorEvent = {
|
|
|
155
155
|
/** Machine-readable error code (e.g., `'insufficient-tokens'`). */
|
|
156
156
|
code?: string;
|
|
157
157
|
};
|
|
158
|
-
/**
|
|
159
|
-
* A stream chunk from the underlying harness that has no `ChatEvent` counterpart.
|
|
160
|
-
*
|
|
161
|
-
* Returned instead of silently discarding the chunk, so consumers can log or
|
|
162
|
-
* monitor unhandled harness events for observability.
|
|
163
|
-
*/
|
|
164
|
-
export type UnmappedChunkEvent = {
|
|
165
|
-
type: 'unmapped-chunk';
|
|
166
|
-
/** The original harness chunk type string (e.g., `'tool-call-suspended'`, `'raw'`). */
|
|
167
|
-
chunkType: string;
|
|
168
|
-
/** The raw chunk object, preserved for diagnostic logging. */
|
|
169
|
-
rawChunk: unknown;
|
|
170
|
-
};
|
|
171
158
|
/** The entire stream has completed. */
|
|
172
159
|
export type FinishEvent = {
|
|
173
160
|
type: 'finish';
|
package/dist/types/messages.d.ts
CHANGED
|
@@ -24,7 +24,18 @@ export type Message = {
|
|
|
24
24
|
role: MessageRole;
|
|
25
25
|
/** Message content — plain text or structured parts. */
|
|
26
26
|
content: string | MessagePart[];
|
|
27
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Timestamp of when the message was created. **Always populated** on
|
|
29
|
+
* messages returned from `ChatSession.getMessageHistory()`. **Optional on
|
|
30
|
+
* write** — consumers constructing `Message` for `ChatSession.addContext()`
|
|
31
|
+
* may omit it; the SDK backfills the current time before forwarding to
|
|
32
|
+
* the harness, so the on-read contract still holds.
|
|
33
|
+
*
|
|
34
|
+
* The read-side guarantee lives on `AgentHarness.getMessages` — see its
|
|
35
|
+
* JSDoc for the contract every harness implementation upholds (populated
|
|
36
|
+
* `createdAt` on every returned message; array sorted ascending by
|
|
37
|
+
* `createdAt`). The SDK passes the harness's output through unchanged.
|
|
38
|
+
*/
|
|
28
39
|
createdAt?: Date;
|
|
29
40
|
};
|
|
30
41
|
/**
|
package/dist/types/usage.d.ts
CHANGED
|
@@ -16,6 +16,71 @@ export type UsageMetadata = {
|
|
|
16
16
|
/** Input tokens written to the provider cache during this interaction. */
|
|
17
17
|
cacheWriteInputTokens?: number;
|
|
18
18
|
};
|
|
19
|
+
/**
|
|
20
|
+
* Snapshot of how much of the model's context window the most recent
|
|
21
|
+
* turn used. Returned by {@link ChatSession.getContextUsage}.
|
|
22
|
+
*
|
|
23
|
+
* Consumers use this to decide when to call `compactThread()`, switch to a
|
|
24
|
+
* smaller model, or warn the user as the conversation approaches the
|
|
25
|
+
* model's context limit.
|
|
26
|
+
*
|
|
27
|
+
* `usage` carries the **last per-step** reading from the model —
|
|
28
|
+
* specifically the `usage` from the latest `step-finish` event whose `usage`
|
|
29
|
+
* was defined. This is the size of the prompt the model saw on its last
|
|
30
|
+
* invocation, which is the right "how full is my context" reading. This is
|
|
31
|
+
* **not** the per-turn billing aggregate (which sums steps and double-counts
|
|
32
|
+
* persistent context). For per-turn billing totals, subscribe to
|
|
33
|
+
* `chat-stream-completed` telemetry instead.
|
|
34
|
+
*
|
|
35
|
+
* Field shapes:
|
|
36
|
+
*
|
|
37
|
+
* - `usage` is always populated. Pre-first-turn (or post-`clearHistory()`)
|
|
38
|
+
* it is the empty object `{}` — i.e., a `UsageMetadata` whose token fields
|
|
39
|
+
* are all `undefined` — making "no reading yet" indistinguishable from
|
|
40
|
+
* "harness reported every field as undefined."
|
|
41
|
+
* - `contextWindow` is always populated, contractually. Every `Model`
|
|
42
|
+
* reachable via `Agent.llmGatewayClient.getModel()` must publish a
|
|
43
|
+
* `contextWindow`; see the `sfdx-agent-sdk` ARCHITECTURE.md Critical
|
|
44
|
+
* Invariant on this and issue #507.
|
|
45
|
+
* - `usedFraction` is `undefined` iff every input-bearing field on the
|
|
46
|
+
* latest reading (`inputTokens`, `cachedInputTokens`, `cacheWriteInputTokens`)
|
|
47
|
+
* is `undefined` — the only honest answer when we have no input-side
|
|
48
|
+
* reading to divide. The denominator-numerator sums all three because
|
|
49
|
+
* cached prompt tokens occupy real space in the context window (see the
|
|
50
|
+
* field-level doc on `usedFraction` for the Bedrock-Claude rationale).
|
|
51
|
+
* Consumers who want zero-on-empty UX can collapse with `usedFraction ?? 0`.
|
|
52
|
+
*/
|
|
53
|
+
export type ContextUsage = {
|
|
54
|
+
/**
|
|
55
|
+
* Last per-step usage reading observed on this session. Pre-first-turn
|
|
56
|
+
* and immediately after `clearHistory()` this is `{}` (every token field
|
|
57
|
+
* undefined).
|
|
58
|
+
*/
|
|
59
|
+
usage: UsageMetadata;
|
|
60
|
+
/**
|
|
61
|
+
* The model's total context-window size in tokens. Read live at call
|
|
62
|
+
* time from the agent's currently-bound `LLMGatewayClient`, so it stays
|
|
63
|
+
* correct across `Agent.updateAgentConfig()` model swaps.
|
|
64
|
+
*/
|
|
65
|
+
contextWindow: number;
|
|
66
|
+
/**
|
|
67
|
+
* `(usage.inputTokens + usage.cachedInputTokens + usage.cacheWriteInputTokens) /
|
|
68
|
+
* contextWindow`, clamped to `[0, 1]`. The denominator-numerator includes
|
|
69
|
+
* cached prompt tokens because they are real tokens occupying the model's
|
|
70
|
+
* context window — Bedrock-Claude's `message_delta.usage` reports only the
|
|
71
|
+
* incremental `inputTokens` per delta, with the bulk of the prompt riding
|
|
72
|
+
* on `cachedInputTokens` / `cacheWriteInputTokens`. Counting only
|
|
73
|
+
* `inputTokens` would underreport "how full" by orders of magnitude on
|
|
74
|
+
* cache-hit paths. Mastra is unaffected because it does not populate the
|
|
75
|
+
* cache fields, so the sum collapses to `inputTokens` alone.
|
|
76
|
+
*
|
|
77
|
+
* `undefined` when ALL three input-bearing fields are missing on the
|
|
78
|
+
* latest reading (pre-first-turn, post-`clearHistory()`, or when a
|
|
79
|
+
* harness emits a reading without any input-side counts). Consumers
|
|
80
|
+
* wanting zero-on-empty: `usedFraction ?? 0`.
|
|
81
|
+
*/
|
|
82
|
+
usedFraction: number | undefined;
|
|
83
|
+
};
|
|
19
84
|
/**
|
|
20
85
|
* Reason the model stopped generating.
|
|
21
86
|
* Aligned with AI SDK V3's unified finish-reason set; harnesses normalize provider-specific
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/sfdx-agent-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Harness-agnostic agentic infrastructure for Salesforce developer experience tooling",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"default": "./dist/index.js"
|
|
12
12
|
},
|
|
13
|
+
"./harness": {
|
|
14
|
+
"types": "./dist/harness/public.d.ts",
|
|
15
|
+
"default": "./dist/harness/public.js"
|
|
16
|
+
},
|
|
13
17
|
"./package.json": "./package.json"
|
|
14
18
|
},
|
|
15
19
|
"scripts": {
|
|
@@ -35,13 +39,13 @@
|
|
|
35
39
|
"LICENSE.txt"
|
|
36
40
|
],
|
|
37
41
|
"dependencies": {
|
|
38
|
-
"@salesforce/agentic-common": "0.
|
|
39
|
-
"@salesforce/llm-gateway-sdk": "0.
|
|
42
|
+
"@salesforce/agentic-common": "0.8.0",
|
|
43
|
+
"@salesforce/llm-gateway-sdk": "0.12.0"
|
|
40
44
|
},
|
|
41
45
|
"devDependencies": {
|
|
42
46
|
"@eslint/js": "^10.0.1",
|
|
43
|
-
"@salesforce/sfdx-agent-harness-claude": "0.
|
|
44
|
-
"@salesforce/sfdx-agent-harness-mastra": "0.
|
|
47
|
+
"@salesforce/sfdx-agent-harness-claude": "0.12.0",
|
|
48
|
+
"@salesforce/sfdx-agent-harness-mastra": "0.15.0",
|
|
45
49
|
"@types/node": "^22.19.17",
|
|
46
50
|
"@vitest/coverage-istanbul": "^4.1.7",
|
|
47
51
|
"@vitest/eslint-plugin": "^1.6.17",
|