@salesforce/sfdx-agent-sdk 0.1.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/LICENSE.txt +21 -0
- package/README.md +508 -0
- package/dist/agent-connectivity-resolver.d.ts +62 -0
- package/dist/agent-connectivity-resolver.js +47 -0
- package/dist/agent-connectivity-resolver.js.map +1 -0
- package/dist/agent-manager.d.ts +134 -0
- package/dist/agent-manager.js +266 -0
- package/dist/agent-manager.js.map +1 -0
- package/dist/agent.d.ts +218 -0
- package/dist/agent.js +313 -0
- package/dist/agent.js.map +1 -0
- package/dist/chat-session.d.ts +298 -0
- package/dist/chat-session.js +407 -0
- package/dist/chat-session.js.map +1 -0
- package/dist/errors.d.ts +12 -0
- package/dist/errors.js +20 -0
- package/dist/errors.js.map +1 -0
- package/dist/harness/agent-harness.d.ts +200 -0
- package/dist/harness/agent-harness.js +6 -0
- package/dist/harness/agent-harness.js.map +1 -0
- package/dist/harness/harness-bus-owner.d.ts +34 -0
- package/dist/harness/harness-bus-owner.js +78 -0
- package/dist/harness/harness-bus-owner.js.map +1 -0
- package/dist/harness/harness-config.d.ts +89 -0
- package/dist/harness/harness-config.js +26 -0
- package/dist/harness/harness-config.js.map +1 -0
- package/dist/harness/harness-factory.d.ts +21 -0
- package/dist/harness/harness-factory.js +6 -0
- package/dist/harness/harness-factory.js.map +1 -0
- package/dist/harness/index.d.ts +4 -0
- package/dist/harness/index.js +6 -0
- package/dist/harness/index.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/telemetry-router.d.ts +41 -0
- package/dist/internal/telemetry-router.js +128 -0
- package/dist/internal/telemetry-router.js.map +1 -0
- package/dist/mcp-auth.d.ts +20 -0
- package/dist/mcp-auth.js +40 -0
- package/dist/mcp-auth.js.map +1 -0
- package/dist/mcp-config.d.ts +52 -0
- package/dist/mcp-config.js +13 -0
- package/dist/mcp-config.js.map +1 -0
- package/dist/test/tsconfig.tsbuildinfo +1 -0
- package/dist/types/events.d.ts +151 -0
- package/dist/types/events.js +6 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/messages.d.ts +60 -0
- package/dist/types/messages.js +6 -0
- package/dist/types/messages.js.map +1 -0
- package/dist/types/telemetry-events.d.ts +93 -0
- package/dist/types/telemetry-events.js +6 -0
- package/dist/types/telemetry-events.js.map +1 -0
- package/dist/types/tools.d.ts +57 -0
- package/dist/types/tools.js +6 -0
- package/dist/types/tools.js.map +1 -0
- package/dist/types/usage.d.ts +31 -0
- package/dist/types/usage.js +6 -0
- package/dist/types/usage.js.map +1 -0
- package/dist/workspace.d.ts +15 -0
- package/dist/workspace.js +48 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +64 -0
package/dist/agent.js
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026, Salesforce, Inc. All rights reserved.
|
|
3
|
+
* See LICENSE.txt for license terms.
|
|
4
|
+
*/
|
|
5
|
+
import { EventBus, LogBus, RealClock, UUIDGenerator, } from '@salesforce/agentic-common';
|
|
6
|
+
import { toHarnessConfig } from './harness/harness-config.js';
|
|
7
|
+
import { DefaultChatSession } from './chat-session.js';
|
|
8
|
+
import { Models } from '@salesforce/llm-gateway-sdk';
|
|
9
|
+
import { AgentSDKError, AgentSDKErrorType } from './errors.js';
|
|
10
|
+
/**
|
|
11
|
+
* Default implementation of {@link Agent} that delegates
|
|
12
|
+
* agent and thread operations to an {@link AgentHarness}.
|
|
13
|
+
*/
|
|
14
|
+
export class DefaultAgent {
|
|
15
|
+
harness;
|
|
16
|
+
agentId;
|
|
17
|
+
projectRoot;
|
|
18
|
+
config;
|
|
19
|
+
llmGatewayClient;
|
|
20
|
+
orgConnection;
|
|
21
|
+
orgJwt;
|
|
22
|
+
agentConnectivityResolver;
|
|
23
|
+
sessions = new Map();
|
|
24
|
+
sessionSliceUnregisters = new Map();
|
|
25
|
+
router;
|
|
26
|
+
telemetryBus = new EventBus();
|
|
27
|
+
logBus = new LogBus();
|
|
28
|
+
inboundUnsubs;
|
|
29
|
+
parentUnsubs;
|
|
30
|
+
clock;
|
|
31
|
+
idGenerator;
|
|
32
|
+
disposed = false;
|
|
33
|
+
/**
|
|
34
|
+
* @param harness - The agent harness managing agent and thread lifecycle.
|
|
35
|
+
* @param agentId - Unique identifier for this agent.
|
|
36
|
+
* @param projectRoot - Project folder this agent is allowed to operate within.
|
|
37
|
+
* @param config - Initial agent configuration (instructions, model, tools, etc.).
|
|
38
|
+
* @param llmGatewayClient - Authenticated LLM gateway client for the resolved org.
|
|
39
|
+
* @param orgConnection - Authenticated org connection carrying identity and env inference.
|
|
40
|
+
* @param orgJwt - Self-refreshing JWT for the resolved org (used for MCP auth injection).
|
|
41
|
+
* @param agentConnectivityResolver - Used to re-resolve org connectivity when the org or model changes.
|
|
42
|
+
* @param router - Telemetry router used to obtain session slices when sessions are created.
|
|
43
|
+
* @param inbound - Router slice delivering harness events routed to this agent (non-session-scoped).
|
|
44
|
+
* @param parent - Manager's bus pair; this agent forwards its events upward into them.
|
|
45
|
+
*/
|
|
46
|
+
constructor(harness, agentId, projectRoot, config, llmGatewayClient, orgConnection, orgJwt, agentConnectivityResolver, router, inbound, parent, clock = new RealClock(), idGenerator = new UUIDGenerator()) {
|
|
47
|
+
this.harness = harness;
|
|
48
|
+
this.agentId = agentId;
|
|
49
|
+
this.projectRoot = projectRoot;
|
|
50
|
+
this.config = config;
|
|
51
|
+
this.llmGatewayClient = llmGatewayClient;
|
|
52
|
+
this.orgConnection = orgConnection;
|
|
53
|
+
this.orgJwt = orgJwt;
|
|
54
|
+
this.agentConnectivityResolver = agentConnectivityResolver;
|
|
55
|
+
this.router = router;
|
|
56
|
+
this.clock = clock;
|
|
57
|
+
this.idGenerator = idGenerator;
|
|
58
|
+
this.inboundUnsubs = [inbound.telemetry.forwardTo(this.telemetryBus), inbound.log.forwardTo(this.logBus)];
|
|
59
|
+
this.parentUnsubs = [this.telemetryBus.forwardTo(parent.telemetry), this.logBus.forwardTo(parent.log)];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* @requirements
|
|
63
|
+
* - MUST return the agent's ID.
|
|
64
|
+
*/
|
|
65
|
+
getId() {
|
|
66
|
+
this.assertNotDisposed();
|
|
67
|
+
return this.agentId;
|
|
68
|
+
}
|
|
69
|
+
/** Returns the project root folder this agent operates within. */
|
|
70
|
+
getProjectRoot() {
|
|
71
|
+
this.assertNotDisposed();
|
|
72
|
+
return this.projectRoot;
|
|
73
|
+
}
|
|
74
|
+
getOrgConnection() {
|
|
75
|
+
this.assertNotDisposed();
|
|
76
|
+
return this.orgConnection;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* @requirements
|
|
80
|
+
* - MUST return a shallow copy of the internal `config` object to prevent external mutation of the agent's state.
|
|
81
|
+
*/
|
|
82
|
+
getAgentConfig() {
|
|
83
|
+
this.assertNotDisposed();
|
|
84
|
+
return { ...this.config };
|
|
85
|
+
}
|
|
86
|
+
getMcpServerInfo() {
|
|
87
|
+
this.assertNotDisposed();
|
|
88
|
+
return this.harness.getMcpServerInfo(this.agentId);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* @requirements
|
|
92
|
+
* - MUST merge the provided `config` with the internal `config` object.
|
|
93
|
+
* - MUST guarantee that the `agentId` remains unchanged during the merge.
|
|
94
|
+
* - MUST destroy the existing agent in the harness by delegating to `this.harness.destroyAgent(this.getId())`.
|
|
95
|
+
* - MUST recreate the agent in the harness with the newly merged configuration by delegating to `this.harness.createAgent(...)`.
|
|
96
|
+
* - MUST preserve the previous in-memory config state if recreation fails.
|
|
97
|
+
*/
|
|
98
|
+
async updateAgentConfig(config = {}, options) {
|
|
99
|
+
this.assertNotDisposed();
|
|
100
|
+
const previousConfig = { ...this.config };
|
|
101
|
+
const previousClient = this.llmGatewayClient;
|
|
102
|
+
const previousOrgJwt = this.orgJwt;
|
|
103
|
+
const nextConfig = { ...this.config, ...config };
|
|
104
|
+
const orgAliasRequested = Object.prototype.hasOwnProperty.call(config, 'orgAlias');
|
|
105
|
+
const previousModelName = previousClient.getModel().name;
|
|
106
|
+
const nextModelName = nextConfig.modelId ?? Models.getDefault().name;
|
|
107
|
+
let nextClient = previousClient;
|
|
108
|
+
let nextConnection = this.orgConnection;
|
|
109
|
+
let nextOrgJwt = this.orgJwt;
|
|
110
|
+
if (orgAliasRequested) {
|
|
111
|
+
const runtime = await this.agentConnectivityResolver.resolve(this.projectRoot, nextConfig);
|
|
112
|
+
nextClient = runtime.llmGatewayClient;
|
|
113
|
+
nextConnection = runtime.orgConnection;
|
|
114
|
+
nextOrgJwt = runtime.orgJwt;
|
|
115
|
+
}
|
|
116
|
+
else if (nextModelName !== previousModelName) {
|
|
117
|
+
// Keep the same authenticated client, but pin the updated model.
|
|
118
|
+
// (If modelId is omitted, the resolver pinned the default at creation time.)
|
|
119
|
+
nextClient.setModel(Models.getByName(nextModelName));
|
|
120
|
+
}
|
|
121
|
+
await this.harness.destroyAgent(this.agentId);
|
|
122
|
+
try {
|
|
123
|
+
await this.harness.createAgent(this.agentId, this.projectRoot, nextClient, toHarnessConfig(nextConfig, nextOrgJwt), options);
|
|
124
|
+
this.config = nextConfig;
|
|
125
|
+
this.llmGatewayClient = nextClient;
|
|
126
|
+
this.orgConnection = nextConnection;
|
|
127
|
+
this.orgJwt = nextOrgJwt;
|
|
128
|
+
// Release the old client only once the swap has succeeded. When the orgAlias is unchanged,
|
|
129
|
+
// nextClient === previousClient and we must NOT dispose.
|
|
130
|
+
if (nextClient !== previousClient) {
|
|
131
|
+
previousClient.dispose();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
// Best-effort restoration to keep wrapper and harness state aligned.
|
|
136
|
+
try {
|
|
137
|
+
// Restore client model if we mutated it in-place.
|
|
138
|
+
if (nextClient === previousClient) {
|
|
139
|
+
previousClient.setModel(Models.getByName(previousModelName));
|
|
140
|
+
}
|
|
141
|
+
await this.harness.createAgent(this.agentId, this.projectRoot, previousClient, toHarnessConfig(previousConfig, previousOrgJwt));
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
// Ignore restoration errors; rethrow the original failure.
|
|
145
|
+
}
|
|
146
|
+
// A freshly-resolved client we never installed must be released so its auth resources don't leak.
|
|
147
|
+
if (nextClient !== previousClient) {
|
|
148
|
+
try {
|
|
149
|
+
nextClient.dispose();
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// Ignore; the original error is the one the caller cares about.
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* @requirements
|
|
160
|
+
* - MUST delegate to `this.harness.createThread(this.config.agentId)` to generate a new thread ID.
|
|
161
|
+
* - MUST instantiate a new `DefaultChatSession` initialized with the harness, agent ID, and the new thread ID.
|
|
162
|
+
* - MUST store the newly created session in the internal `sessions` map, keyed by the thread ID.
|
|
163
|
+
* - MUST return the newly created session.
|
|
164
|
+
*/
|
|
165
|
+
async createChatSession() {
|
|
166
|
+
this.assertNotDisposed();
|
|
167
|
+
const threadId = await this.harness.createThread(this.agentId);
|
|
168
|
+
return this.attachSession(threadId);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* @requirements
|
|
172
|
+
* - MUST throw an Error if the provided `sessionId` is not found in the internal `sessions` map.
|
|
173
|
+
* - MUST delegate to `this.harness.destroyThread(this.config.agentId, sessionId)`.
|
|
174
|
+
* - MUST remove the session from the internal `sessions` map.
|
|
175
|
+
*/
|
|
176
|
+
async destroyChatSession(sessionId) {
|
|
177
|
+
this.assertNotDisposed();
|
|
178
|
+
const session = this.sessions.get(sessionId);
|
|
179
|
+
if (!session) {
|
|
180
|
+
throw new AgentSDKError(`No ChatSession found with id: "${sessionId}"`, AgentSDKErrorType.CHAT_SESSION_NOT_FOUND);
|
|
181
|
+
}
|
|
182
|
+
await this.harness.destroyThread(this.agentId, sessionId);
|
|
183
|
+
this.detachSession(sessionId, session);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* @requirements
|
|
187
|
+
* - MUST throw an Error if the provided `sessionId` is not found in the internal `sessions` map.
|
|
188
|
+
* - MUST return the session object associated with the given `sessionId`.
|
|
189
|
+
*/
|
|
190
|
+
getChatSession(sessionId) {
|
|
191
|
+
this.assertNotDisposed();
|
|
192
|
+
const session = this.sessions.get(sessionId);
|
|
193
|
+
if (!session) {
|
|
194
|
+
throw new AgentSDKError(`No ChatSession found with id: "${sessionId}"`, AgentSDKErrorType.CHAT_SESSION_NOT_FOUND);
|
|
195
|
+
}
|
|
196
|
+
return session;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* @requirements
|
|
200
|
+
* - MUST return an array of all string keys (session IDs) currently tracked in the internal `sessions` map.
|
|
201
|
+
*/
|
|
202
|
+
getChatSessionIds() {
|
|
203
|
+
this.assertNotDisposed();
|
|
204
|
+
return Array.from(this.sessions.keys());
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* @requirements
|
|
208
|
+
* - MUST throw an Error if the provided `sourceSessionId` is not found in the internal `sessions` map.
|
|
209
|
+
* - MUST delegate to `this.harness.cloneThread(this.config.agentId, sourceSessionId)` to create a new thread with cloned history.
|
|
210
|
+
* - MUST instantiate a new `DefaultChatSession` initialized with the harness, agent ID, and the new thread ID.
|
|
211
|
+
* - MUST store the newly created session in the internal `sessions` map, keyed by the new thread ID.
|
|
212
|
+
* - MUST return the newly created session.
|
|
213
|
+
*/
|
|
214
|
+
async cloneChatSession(sourceSessionId) {
|
|
215
|
+
this.assertNotDisposed();
|
|
216
|
+
if (!this.sessions.has(sourceSessionId)) {
|
|
217
|
+
throw new AgentSDKError(`No ChatSession found with id: "${sourceSessionId}"`, AgentSDKErrorType.CHAT_SESSION_NOT_FOUND);
|
|
218
|
+
}
|
|
219
|
+
const newThreadId = await this.harness.cloneThread(this.agentId, sourceSessionId);
|
|
220
|
+
return this.attachSession(newThreadId);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* @requirements
|
|
224
|
+
* - MUST throw an Error if the provided `sessionId` is not found in the internal `sessions` map.
|
|
225
|
+
* - MUST delegate to `this.harness.compactThread(this.agentId, sessionId)` to create a new thread with a summary.
|
|
226
|
+
* - MUST detach the source session from this agent on success — the
|
|
227
|
+
* harness destroys the source thread, so leaving the wrapper attached
|
|
228
|
+
* would leak a router slice and a `DefaultChatSession` whose thread
|
|
229
|
+
* no longer exists.
|
|
230
|
+
* - MUST instantiate a new `DefaultChatSession` initialized with the harness, agent ID, and the new thread ID.
|
|
231
|
+
* - MUST store the newly created session in the internal `sessions` map, keyed by the new thread ID.
|
|
232
|
+
* - MUST return the newly created session.
|
|
233
|
+
*/
|
|
234
|
+
async compactChatSession(sessionId) {
|
|
235
|
+
this.assertNotDisposed();
|
|
236
|
+
const sourceSession = this.sessions.get(sessionId);
|
|
237
|
+
if (!sourceSession) {
|
|
238
|
+
throw new AgentSDKError(`No ChatSession found with id: "${sessionId}"`, AgentSDKErrorType.CHAT_SESSION_NOT_FOUND);
|
|
239
|
+
}
|
|
240
|
+
const newThreadId = await this.harness.compactThread(this.agentId, sessionId);
|
|
241
|
+
this.detachSession(sessionId, sourceSession);
|
|
242
|
+
return this.attachSession(newThreadId);
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* @requirements
|
|
246
|
+
* - MUST iterate over all active session IDs and sequentially delegate to `this.harness.destroyThread()` for each.
|
|
247
|
+
* - MUST clear the internal `sessions` map.
|
|
248
|
+
* - MUST delegate to `this.harness.destroyAgent(this.config.agentId)` to clean up the agent's harness resources.
|
|
249
|
+
*/
|
|
250
|
+
async destroy() {
|
|
251
|
+
if (this.disposed) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
for (const [sessionId, session] of this.sessions) {
|
|
255
|
+
await this.harness.destroyThread(this.agentId, sessionId);
|
|
256
|
+
this.detachSession(sessionId, session);
|
|
257
|
+
}
|
|
258
|
+
this.sessions.clear();
|
|
259
|
+
await this.harness.destroyAgent(this.agentId);
|
|
260
|
+
this.llmGatewayClient.dispose();
|
|
261
|
+
this.telemetryBus.emit({
|
|
262
|
+
type: 'agent-destroyed',
|
|
263
|
+
timestamp: this.clock.now(),
|
|
264
|
+
agentId: this.agentId,
|
|
265
|
+
});
|
|
266
|
+
for (const unsub of this.inboundUnsubs)
|
|
267
|
+
unsub();
|
|
268
|
+
for (const unsub of this.parentUnsubs)
|
|
269
|
+
unsub();
|
|
270
|
+
this.telemetryBus.dispose();
|
|
271
|
+
this.logBus.dispose();
|
|
272
|
+
this.disposed = true;
|
|
273
|
+
}
|
|
274
|
+
onTelemetry(callback) {
|
|
275
|
+
this.assertNotDisposed();
|
|
276
|
+
return this.telemetryBus.on(callback);
|
|
277
|
+
}
|
|
278
|
+
onLog(callback) {
|
|
279
|
+
this.assertNotDisposed();
|
|
280
|
+
return this.logBus.on(callback);
|
|
281
|
+
}
|
|
282
|
+
attachSession(threadId) {
|
|
283
|
+
const slice = this.router.registerSession(threadId);
|
|
284
|
+
const session = new DefaultChatSession(this.harness, this.agentId, threadId, slice, {
|
|
285
|
+
telemetry: this.telemetryBus,
|
|
286
|
+
log: this.logBus,
|
|
287
|
+
}, this.clock, this.idGenerator);
|
|
288
|
+
this.sessions.set(threadId, session);
|
|
289
|
+
this.sessionSliceUnregisters.set(threadId, () => this.router.unregisterSession(threadId));
|
|
290
|
+
this.telemetryBus.emit({
|
|
291
|
+
type: 'session-created',
|
|
292
|
+
timestamp: this.clock.now(),
|
|
293
|
+
agentId: this.agentId,
|
|
294
|
+
threadId,
|
|
295
|
+
});
|
|
296
|
+
return session;
|
|
297
|
+
}
|
|
298
|
+
detachSession(threadId, session) {
|
|
299
|
+
session.dispose();
|
|
300
|
+
const unregister = this.sessionSliceUnregisters.get(threadId);
|
|
301
|
+
if (unregister) {
|
|
302
|
+
unregister();
|
|
303
|
+
this.sessionSliceUnregisters.delete(threadId);
|
|
304
|
+
}
|
|
305
|
+
this.sessions.delete(threadId);
|
|
306
|
+
}
|
|
307
|
+
assertNotDisposed() {
|
|
308
|
+
if (this.disposed) {
|
|
309
|
+
throw new AgentSDKError('Agent has been disposed.', AgentSDKErrorType.DISPOSED);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAEH,QAAQ,EACR,MAAM,EAGN,SAAS,EAGT,aAAa,GAChB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAoB,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAoB,MAAM,mBAAmB,CAAC;AAEzE,OAAO,EAAE,MAAM,EAA4C,MAAM,6BAA6B,CAAC;AAE/F,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAwG/D;;;GAGG;AACH,MAAM,OAAO,YAAY;IACJ,OAAO,CAAe;IACtB,OAAO,CAAS;IAChB,WAAW,CAAS;IAC7B,MAAM,CAAc;IACpB,gBAAgB,CAAmB;IACnC,aAAa,CAAgB;IAC7B,MAAM,CAAe;IACZ,yBAAyB,CAA4B;IACrD,QAAQ,GAAoC,IAAI,GAAG,EAAE,CAAC;IACtD,uBAAuB,GAA4B,IAAI,GAAG,EAAE,CAAC;IAC7D,MAAM,CAAkB;IACxB,YAAY,GAAiB,IAAI,QAAQ,EAAkB,CAAC;IAC5D,MAAM,GAAW,IAAI,MAAM,EAAE,CAAC;IAC9B,aAAa,CAAgB;IAC7B,YAAY,CAAgB;IAC5B,KAAK,CAAQ;IACb,WAAW,CAAoB;IACxC,QAAQ,GAAY,KAAK,CAAC;IAElC;;;;;;;;;;;;OAYG;IACH,YACI,OAAqB,EACrB,OAAe,EACf,WAAmB,EACnB,MAAmB,EACnB,gBAAkC,EAClC,aAA4B,EAC5B,MAAoB,EACpB,yBAAoD,EACpD,MAAuB,EACvB,OAAuB,EACvB,MAAwB,EACxB,QAAe,IAAI,SAAS,EAAE,EAC9B,cAAiC,IAAI,aAAa,EAAE;QAEpD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;QACzC,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,yBAAyB,GAAG,yBAAyB,CAAC;QAC3D,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,aAAa,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QAC1G,IAAI,CAAC,YAAY,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3G,CAAC;IAED;;;OAGG;IACH,KAAK;QACD,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;IAED,kEAAkE;IAClE,cAAc;QACV,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,WAAW,CAAC;IAC5B,CAAC;IAED,gBAAgB;QACZ,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,aAAa,CAAC;IAC9B,CAAC;IAED;;;OAGG;IACH,cAAc;QACV,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,OAAO,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAC9B,CAAC;IAED,gBAAgB;QACZ,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvD,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,iBAAiB,CAAC,SAAsB,EAAE,EAAE,OAAuC;QACrF,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,MAAM,cAAc,GAAgB,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACvD,MAAM,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAC;QAC7C,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC;QACnC,MAAM,UAAU,GAAgB,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;QAE9D,MAAM,iBAAiB,GAAG,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACnF,MAAM,iBAAiB,GAAG,cAAc,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC;QACzD,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC;QAErE,IAAI,UAAU,GAAqB,cAAc,CAAC;QAClD,IAAI,cAAc,GAAkB,IAAI,CAAC,aAAa,CAAC;QACvD,IAAI,UAAU,GAAiB,IAAI,CAAC,MAAM,CAAC;QAE3C,IAAI,iBAAiB,EAAE,CAAC;YACpB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,yBAAyB,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;YAC3F,UAAU,GAAG,OAAO,CAAC,gBAAgB,CAAC;YACtC,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;YACvC,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;QAChC,CAAC;aAAM,IAAI,aAAa,KAAK,iBAAiB,EAAE,CAAC;YAC7C,iEAAiE;YACjE,6EAA6E;YAC7E,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC;QACzD,CAAC;QAED,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,CAAC;YACD,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAC1B,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,WAAW,EAChB,UAAU,EACV,eAAe,CAAC,UAAU,EAAE,UAAU,CAAC,EACvC,OAAO,CACV,CAAC;YACF,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC;YACzB,IAAI,CAAC,gBAAgB,GAAG,UAAU,CAAC;YACnC,IAAI,CAAC,aAAa,GAAG,cAAc,CAAC;YACpC,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC;YACzB,2FAA2F;YAC3F,yDAAyD;YACzD,IAAI,UAAU,KAAK,cAAc,EAAE,CAAC;gBAChC,cAAc,CAAC,OAAO,EAAE,CAAC;YAC7B,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,qEAAqE;YACrE,IAAI,CAAC;gBACD,kDAAkD;gBAClD,IAAI,UAAU,KAAK,cAAc,EAAE,CAAC;oBAChC,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC;gBACjE,CAAC;gBAED,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAC1B,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,WAAW,EAChB,cAAc,EACd,eAAe,CAAC,cAAc,EAAE,cAAc,CAAC,CAClD,CAAC;YACN,CAAC;YAAC,MAAM,CAAC;gBACL,2DAA2D;YAC/D,CAAC;YACD,kGAAkG;YAClG,IAAI,UAAU,KAAK,cAAc,EAAE,CAAC;gBAChC,IAAI,CAAC;oBACD,UAAU,CAAC,OAAO,EAAE,CAAC;gBACzB,CAAC;gBAAC,MAAM,CAAC;oBACL,gEAAgE;gBACpE,CAAC;YACL,CAAC;YACD,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,iBAAiB;QACnB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,kBAAkB,CAAC,SAAiB;QACtC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC7C,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,MAAM,IAAI,aAAa,CACnB,kCAAkC,SAAS,GAAG,EAC9C,iBAAiB,CAAC,sBAAsB,CAC3C,CAAC;QACN,CAAC;QACD,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC1D,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED;;;;OAIG;IACH,cAAc,CAAC,SAAiB;QAC5B,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC7C,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,MAAM,IAAI,aAAa,CACnB,kCAAkC,SAAS,GAAG,EAC9C,iBAAiB,CAAC,sBAAsB,CAC3C,CAAC;QACN,CAAC;QACD,OAAO,OAAO,CAAC;IACnB,CAAC;IAED;;;OAGG;IACH,iBAAiB;QACb,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,gBAAgB,CAAC,eAAuB;QAC1C,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,aAAa,CACnB,kCAAkC,eAAe,GAAG,EACpD,iBAAiB,CAAC,sBAAsB,CAC3C,CAAC;QACN,CAAC;QACD,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QAClF,OAAO,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,kBAAkB,CAAC,SAAiB;QACtC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,CAAC,aAAa,EAAE,CAAC;YACjB,MAAM,IAAI,aAAa,CACnB,kCAAkC,SAAS,GAAG,EAC9C,iBAAiB,CAAC,sBAAsB,CAC3C,CAAC;QACN,CAAC;QACD,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC9E,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,OAAO;QACT,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,OAAO;QACX,CAAC;QACD,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC/C,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAC1D,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC3C,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC;QAEhC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;YACnB,IAAI,EAAE,iBAAiB;YACvB,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;YAC3B,OAAO,EAAE,IAAI,CAAC,OAAO;SACxB,CAAC,CAAC;QAEH,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa;YAAE,KAAK,EAAE,CAAC;QAChD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,YAAY;YAAE,KAAK,EAAE,CAAC;QAC/C,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACtB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;IACzB,CAAC;IAED,WAAW,CAAC,QAAgC;QACxC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,QAAqC;QACvC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAEO,aAAa,CAAC,QAAgB;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,IAAI,kBAAkB,CAClC,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,OAAO,EACZ,QAAQ,EACR,KAAK,EACL;YACI,SAAS,EAAE,IAAI,CAAC,YAAY;YAC5B,GAAG,EAAE,IAAI,CAAC,MAAM;SACnB,EACD,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,WAAW,CACnB,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACrC,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC1F,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;YACnB,IAAI,EAAE,iBAAiB;YACvB,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;YAC3B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,QAAQ;SACX,CAAC,CAAC;QACH,OAAO,OAAO,CAAC;IACnB,CAAC;IAEO,aAAa,CAAC,QAAgB,EAAE,OAA2B;QAC/D,OAAO,CAAC,OAAO,EAAE,CAAC;QAClB,MAAM,UAAU,GAAG,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9D,IAAI,UAAU,EAAE,CAAC;YACb,UAAU,EAAE,CAAC;YACb,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAClD,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;IAEO,iBAAiB;QACrB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,MAAM,IAAI,aAAa,CAAC,0BAA0B,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACpF,CAAC;IACL,CAAC;CACJ"}
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { type Clock, LogBus, type LogRecord, type UniqueIDGenerator, type Unsubscribe } from '@salesforce/agentic-common';
|
|
2
|
+
import type { AgentHarness } from './harness/agent-harness.js';
|
|
3
|
+
import type { StreamOptions } from './harness/harness-config.js';
|
|
4
|
+
import type { TelemetrySlice } from './internal/telemetry-router.js';
|
|
5
|
+
import type { ChatEvent, ChatStreamResult } from './types/events.js';
|
|
6
|
+
import type { Message } from './types/messages.js';
|
|
7
|
+
import type { TelemetryBus, TelemetryEventCallback } from './types/telemetry-events.js';
|
|
8
|
+
import type { ToolResultInfo } from './types/tools.js';
|
|
9
|
+
/**
|
|
10
|
+
* Options for a single chat interaction.
|
|
11
|
+
*/
|
|
12
|
+
export type ChatOptions = StreamOptions;
|
|
13
|
+
/**
|
|
14
|
+
* Parent bus pair used to wire upward forwarding at construction time.
|
|
15
|
+
*/
|
|
16
|
+
export type ChatSessionParentBuses = {
|
|
17
|
+
telemetry: TelemetryBus;
|
|
18
|
+
log: LogBus;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* An isolated conversation thread with an agent.
|
|
22
|
+
*
|
|
23
|
+
* Each `ChatSession` maps to a single thread in the underlying harness. Sessions maintain their own message
|
|
24
|
+
* history but share the parent agent's tools, workspace, and model configuration.
|
|
25
|
+
*
|
|
26
|
+
* ### Failure handling for streaming methods
|
|
27
|
+
*
|
|
28
|
+
* `chat()`, `submitToolResult()`, `approveToolCall()`, and `declineToolCall()` share a single failure
|
|
29
|
+
* contract. Subscribers registered via {@link ChatSession.subscribe} are guaranteed to observe a
|
|
30
|
+
* terminal event for every turn:
|
|
31
|
+
*
|
|
32
|
+
* - **Pre-stream failure** (the harness rejects before producing a stream): subscribers receive an
|
|
33
|
+
* `ErrorEvent` followed by a `FinishEvent` with `finishReason: 'error'`, then the returned promise
|
|
34
|
+
* rejects with the original error.
|
|
35
|
+
* - **In-stream failure** (the stream yields an `error` event or the underlying generator throws):
|
|
36
|
+
* the event stream itself yields the `ErrorEvent` (synthesizing one from a thrown exception if
|
|
37
|
+
* needed) and, if no `FinishEvent` was already emitted, appends a synthetic
|
|
38
|
+
* `FinishEvent(finishReason: 'error')` at the end. Subscribers see the same sequence.
|
|
39
|
+
* - **Calling a disposed session** throws `AgentSDKError('DISPOSED')` synchronously without
|
|
40
|
+
* notifying subscribers — this is a programmer error, not an operational one.
|
|
41
|
+
*/
|
|
42
|
+
export interface ChatSession {
|
|
43
|
+
/** Returns the unique session/thread identifier. */
|
|
44
|
+
getId(): string;
|
|
45
|
+
/**
|
|
46
|
+
* Send a message and stream the agent's response.
|
|
47
|
+
* Returns a {@link ChatStreamResult} which provides multiple ways to consume
|
|
48
|
+
* the stream (text-only or full events).
|
|
49
|
+
*
|
|
50
|
+
* On pre-stream failure, subscribers are notified with `ErrorEvent` + `FinishEvent` before
|
|
51
|
+
* the returned promise rejects. See the interface-level "Failure handling" notes for details.
|
|
52
|
+
*
|
|
53
|
+
* @param message - User message as a plain string.
|
|
54
|
+
* @param options - Per-call options controlling mode, tools, model, etc.
|
|
55
|
+
*/
|
|
56
|
+
chat(message: string, options?: ChatOptions): Promise<ChatStreamResult>;
|
|
57
|
+
/**
|
|
58
|
+
* Feed the result of a client-side tool execution back into the conversation
|
|
59
|
+
* and resume stream generation.
|
|
60
|
+
*
|
|
61
|
+
* Resumes the suspended agentic loop from the most recent `chat()` call.
|
|
62
|
+
*
|
|
63
|
+
* On pre-stream failure, subscribers are notified with `ErrorEvent` + `FinishEvent` before
|
|
64
|
+
* the returned promise rejects. See the interface-level "Failure handling" notes for details.
|
|
65
|
+
*
|
|
66
|
+
* @param toolResult - The completed tool execution result.
|
|
67
|
+
*/
|
|
68
|
+
submitToolResult(toolResult: ToolResultInfo): Promise<ChatStreamResult>;
|
|
69
|
+
/**
|
|
70
|
+
* Approve a pending tool call, allowing the harness to execute it.
|
|
71
|
+
* Called after receiving a `tool-approval-request` event from the stream.
|
|
72
|
+
*
|
|
73
|
+
* Returns a `ChatStreamResult` containing the continuation stream — the harness
|
|
74
|
+
* executes the approved tool, generates the model's follow-up response, and
|
|
75
|
+
* streams both the text and events back to the caller.
|
|
76
|
+
*
|
|
77
|
+
* On pre-stream failure, subscribers are notified with `ErrorEvent` + `FinishEvent` before
|
|
78
|
+
* the returned promise rejects. See the interface-level "Failure handling" notes for details.
|
|
79
|
+
*
|
|
80
|
+
* @param toolCallId - ID of the pending tool call to approve.
|
|
81
|
+
* @param options - Optional approval metadata.
|
|
82
|
+
* @param options.remember - When `true`, signals that the consumer wants to
|
|
83
|
+
* persist this approval decision (e.g., "always allow this tool").
|
|
84
|
+
* The harness does not implement the persistence — the consumer manages
|
|
85
|
+
* its own permission cache. Borrowed from OpenCode's `once/always/reject` model.
|
|
86
|
+
*/
|
|
87
|
+
approveToolCall(toolCallId: string, options?: {
|
|
88
|
+
remember?: boolean;
|
|
89
|
+
}): Promise<ChatStreamResult>;
|
|
90
|
+
/**
|
|
91
|
+
* Decline a pending tool call. The stream resumes with the model
|
|
92
|
+
* acknowledging the decline and potentially suggesting alternatives.
|
|
93
|
+
*
|
|
94
|
+
* Returns a `ChatStreamResult` containing the continuation stream — the harness
|
|
95
|
+
* cancels the pending tool call, generates the model's acknowledgement response,
|
|
96
|
+
* and streams both the text and events back to the caller.
|
|
97
|
+
*
|
|
98
|
+
* On pre-stream failure, subscribers are notified with `ErrorEvent` + `FinishEvent` before
|
|
99
|
+
* the returned promise rejects. See the interface-level "Failure handling" notes for details.
|
|
100
|
+
*
|
|
101
|
+
* @param toolCallId - ID of the pending tool call to decline.
|
|
102
|
+
*/
|
|
103
|
+
declineToolCall(toolCallId: string): Promise<ChatStreamResult>;
|
|
104
|
+
/**
|
|
105
|
+
* Retrieve message history for this session.
|
|
106
|
+
*
|
|
107
|
+
* @returns All messages in chronological order (ascending by creation time).
|
|
108
|
+
*/
|
|
109
|
+
getMessageHistory(): Promise<Message[]>;
|
|
110
|
+
/** Delete all messages in this session's history. */
|
|
111
|
+
clearHistory(): Promise<void>;
|
|
112
|
+
/**
|
|
113
|
+
* Inject context messages into the thread without triggering an LLM response.
|
|
114
|
+
* Useful for seeding file contents, system instructions, or prior conversation
|
|
115
|
+
* state before the user's first prompt.
|
|
116
|
+
*
|
|
117
|
+
* Borrowed from OpenCode's `session.prompt({ noReply: true })` pattern.
|
|
118
|
+
*
|
|
119
|
+
* @param message - Context to inject (string shorthand or structured messages).
|
|
120
|
+
*/
|
|
121
|
+
addContext(message: string | Message[]): Promise<void>;
|
|
122
|
+
/**
|
|
123
|
+
* Register a callback to receive chat events in real-time. Returns an `Unsubscribe` function
|
|
124
|
+
* that removes the listener. The returned function is safe to call after `dispose()` (no-op).
|
|
125
|
+
* Multiple listeners can be registered concurrently.
|
|
126
|
+
*/
|
|
127
|
+
subscribe(callback: (event: ChatEvent) => void): Unsubscribe;
|
|
128
|
+
/** Subscribe to telemetry events scoped to this session. Returns an unsubscribe function. */
|
|
129
|
+
onTelemetry(callback: TelemetryEventCallback): Unsubscribe;
|
|
130
|
+
/** Subscribe to structured log records scoped to this session. Returns an unsubscribe function. */
|
|
131
|
+
onLog(callback: (record: LogRecord) => void): Unsubscribe;
|
|
132
|
+
/**
|
|
133
|
+
* Release session-level event resources. Idempotent. After `dispose()`, public methods throw
|
|
134
|
+
* `AgentSDKError('DISPOSED')`.
|
|
135
|
+
*/
|
|
136
|
+
dispose(): void;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Default implementation of {@link ChatSession} that delegates all operations
|
|
140
|
+
* to an {@link AgentHarness}. The session holds its agent ID and thread ID
|
|
141
|
+
* and forwards calls with appropriate scoping.
|
|
142
|
+
*/
|
|
143
|
+
export declare class DefaultChatSession implements ChatSession {
|
|
144
|
+
private readonly harness;
|
|
145
|
+
private readonly agentId;
|
|
146
|
+
private readonly threadId;
|
|
147
|
+
private readonly chatEventBus;
|
|
148
|
+
private readonly telemetryBus;
|
|
149
|
+
private readonly logBus;
|
|
150
|
+
private readonly inboundUnsubs;
|
|
151
|
+
private readonly parentUnsubs;
|
|
152
|
+
private readonly clock;
|
|
153
|
+
private readonly idGenerator;
|
|
154
|
+
private disposed;
|
|
155
|
+
/**
|
|
156
|
+
* @param harness - The agent harness managing thread and message lifecycle.
|
|
157
|
+
* @param agentId - ID of the agent this session belongs to.
|
|
158
|
+
* @param threadId - ID of the conversation thread backing this session.
|
|
159
|
+
* @param inbound - Router slice delivering harness events routed to this session.
|
|
160
|
+
* @param parent - Parent agent's buses; this session forwards its events upward into them.
|
|
161
|
+
* @param clock - Source of monotonic timestamps for telemetry events. Defaults to `RealClock`.
|
|
162
|
+
* @param idGenerator - Source of message ids for `addContext()`. Defaults to `UUIDGenerator`.
|
|
163
|
+
*/
|
|
164
|
+
constructor(harness: AgentHarness, agentId: string, threadId: string, inbound: TelemetrySlice, parent: ChatSessionParentBuses, clock?: Clock, idGenerator?: UniqueIDGenerator);
|
|
165
|
+
getId(): string;
|
|
166
|
+
/**
|
|
167
|
+
* @requirements
|
|
168
|
+
* - MUST delegate to `this.harness.stream()`, passing `this.agentId` and `this.threadId`.
|
|
169
|
+
* - MUST pass the `message` string and `options` arguments directly to the harness.
|
|
170
|
+
* - MUST wrap the returned `eventStream` using `this.wrapEventStream()` so that listeners are notified.
|
|
171
|
+
* - MUST return an object containing the original `textStream` and the wrapped `eventStream`.
|
|
172
|
+
* - MUST notify listeners with `ErrorEvent` + `FinishEvent` and re-throw if the harness throws
|
|
173
|
+
* before returning a stream result.
|
|
174
|
+
*/
|
|
175
|
+
chat(message: string, options?: ChatOptions): Promise<ChatStreamResult>;
|
|
176
|
+
/**
|
|
177
|
+
* @requirements
|
|
178
|
+
* - MUST delegate to `this.harness.submitToolResult()`, passing `this.agentId` and `this.threadId`.
|
|
179
|
+
* - MUST pass the `toolResult` argument directly to the harness.
|
|
180
|
+
* - MUST wrap the returned `eventStream` using `this.wrapEventStream()` so that listeners are notified.
|
|
181
|
+
* - MUST return an object containing the original `textStream` and the wrapped `eventStream`.
|
|
182
|
+
* - MUST notify listeners with `ErrorEvent` + `FinishEvent` and re-throw if the harness throws
|
|
183
|
+
* before returning a stream result.
|
|
184
|
+
*/
|
|
185
|
+
submitToolResult(toolResult: ToolResultInfo): Promise<ChatStreamResult>;
|
|
186
|
+
/**
|
|
187
|
+
* @requirements
|
|
188
|
+
* - MUST yield each event from the provided `stream`.
|
|
189
|
+
* - MUST emit the event to the internal `chatEventBus`.
|
|
190
|
+
* - MUST always yield a `FinishEvent` with `finishReason: 'error'` after any error path
|
|
191
|
+
* (in-stream `ErrorEvent` or thrown exception) if no `FinishEvent` was already emitted.
|
|
192
|
+
* - MUST emit `chat-stream-completed` telemetry on natural completion (no error path).
|
|
193
|
+
* - MUST emit `chat-stream-error` telemetry exactly once when an error occurred (in-stream
|
|
194
|
+
* `ErrorEvent` or thrown exception). Mutually exclusive with `chat-stream-completed`.
|
|
195
|
+
* - MUST derive `tool-execution-started`, `tool-execution-completed`, and
|
|
196
|
+
* `tool-approval-requested` telemetry from the corresponding `ChatEvent` types so harness
|
|
197
|
+
* implementations don't reimplement this. `tool-execution-completed.durationMs` is measured
|
|
198
|
+
* between the matching `tool-call` and `tool-result`; an unmatched `tool-result` (e.g. from
|
|
199
|
+
* a resume flow that crosses a stream boundary) is skipped.
|
|
200
|
+
*
|
|
201
|
+
* `chat-stream-started` is emitted by the entry-point method (chat / submitToolResult /
|
|
202
|
+
* approveToolCall / declineToolCall) before the harness call so that pre-stream rejections
|
|
203
|
+
* still produce a started+error pair. `startedAt` is captured there and threaded down so
|
|
204
|
+
* `durationMs` measures real elapsed time on both terminal events.
|
|
205
|
+
*/
|
|
206
|
+
private wrapEventStream;
|
|
207
|
+
/**
|
|
208
|
+
* @requirements
|
|
209
|
+
* - MUST delegate to `this.harness.approveToolCall()`, passing `this.agentId`, `this.threadId`, and `toolCallId`.
|
|
210
|
+
* - MUST wrap the returned `eventStream` using `this.wrapEventStream()` so that listeners are notified.
|
|
211
|
+
* - MUST return an object containing the original `textStream` and the wrapped `eventStream`.
|
|
212
|
+
* - MUST emit `tool-approval-resolved` telemetry with `approved: true` only after the harness
|
|
213
|
+
* call resolves. Pre-stream rejections produce `chat-stream-error` via `notifyPreStreamError`
|
|
214
|
+
* and intentionally skip approval-resolved emission — consumers correlate the prior
|
|
215
|
+
* `tool-approval-requested` by `toolCallId` and observe the failure on the chat-stream contract.
|
|
216
|
+
* - MUST notify listeners with `ErrorEvent` + `FinishEvent` and re-throw if the harness throws
|
|
217
|
+
* before returning a stream result.
|
|
218
|
+
* - The `options.remember` flag is consumer-only metadata — the harness does not use it.
|
|
219
|
+
*/
|
|
220
|
+
approveToolCall(toolCallId: string, _options?: {
|
|
221
|
+
remember?: boolean;
|
|
222
|
+
}): Promise<ChatStreamResult>;
|
|
223
|
+
/**
|
|
224
|
+
* @requirements
|
|
225
|
+
* - MUST delegate to `this.harness.declineToolCall()`, passing `this.agentId`, `this.threadId`, and `toolCallId`.
|
|
226
|
+
* - MUST wrap the returned `eventStream` using `this.wrapEventStream()` so that listeners are notified.
|
|
227
|
+
* - MUST return an object containing the original `textStream` and the wrapped `eventStream`.
|
|
228
|
+
* - MUST emit `tool-approval-resolved` telemetry with `approved: false` only after the harness
|
|
229
|
+
* call resolves. Pre-stream rejections produce `chat-stream-error` via `notifyPreStreamError`
|
|
230
|
+
* and intentionally skip approval-resolved emission.
|
|
231
|
+
* - MUST notify listeners with `ErrorEvent` + `FinishEvent` and re-throw if the harness throws
|
|
232
|
+
* before returning a stream result.
|
|
233
|
+
*/
|
|
234
|
+
declineToolCall(toolCallId: string): Promise<ChatStreamResult>;
|
|
235
|
+
/**
|
|
236
|
+
* @requirements
|
|
237
|
+
* - MUST delegate to `this.harness.getMessages()`, passing `this.agentId` and `this.threadId`.
|
|
238
|
+
* - MUST return the result directly.
|
|
239
|
+
*/
|
|
240
|
+
getMessageHistory(): Promise<Message[]>;
|
|
241
|
+
/**
|
|
242
|
+
* @requirements
|
|
243
|
+
* - MUST delegate to `this.harness.clearMessages()`, passing `this.agentId` and `this.threadId`.
|
|
244
|
+
*/
|
|
245
|
+
clearHistory(): Promise<void>;
|
|
246
|
+
/**
|
|
247
|
+
* @requirements
|
|
248
|
+
* - IF `message` is a `string`, it MUST be formatted into a standard `Message` object array containing exactly one message.
|
|
249
|
+
* - The formatted message MUST have `role: 'user'`.
|
|
250
|
+
* - The formatted message MUST have a newly generated `id` from the injected `idGenerator`.
|
|
251
|
+
* - The formatted message MUST have a `createdAt` timestamp from the injected `clock`.
|
|
252
|
+
* - IF `message` is already an array of `Message` objects, it MUST be used directly.
|
|
253
|
+
* - MUST delegate the final array of messages to `this.harness.addContext()`, passing `this.agentId` and `this.threadId`.
|
|
254
|
+
*/
|
|
255
|
+
addContext(message: string | Message[]): Promise<void>;
|
|
256
|
+
/**
|
|
257
|
+
* @requirements
|
|
258
|
+
* - MUST register the provided `callback` on the internal `chatEventBus`.
|
|
259
|
+
* - MUST return an `Unsubscribe` closure that removes the callback when called.
|
|
260
|
+
*/
|
|
261
|
+
subscribe(callback: (event: ChatEvent) => void): Unsubscribe;
|
|
262
|
+
onTelemetry(callback: TelemetryEventCallback): Unsubscribe;
|
|
263
|
+
onLog(callback: (record: LogRecord) => void): Unsubscribe;
|
|
264
|
+
dispose(): void;
|
|
265
|
+
private emitToolApprovalResolved;
|
|
266
|
+
/**
|
|
267
|
+
* Derives `tool-execution-*` and `tool-approval-requested` telemetry from `ChatEvent`s as
|
|
268
|
+
* they pass through the stream wrapper. Centralizing the derivation here keeps every harness
|
|
269
|
+
* implementation free of telemetry plumbing — they just yield the right `ChatEvent` shapes.
|
|
270
|
+
*
|
|
271
|
+
* `tool-execution-completed.durationMs` is measured between the matching `tool-call` and
|
|
272
|
+
* `tool-result` using `this.clock`. An unmatched `tool-result` (e.g. a resume flow that
|
|
273
|
+
* crosses a stream boundary so the original `tool-call` was on a previous stream) is skipped
|
|
274
|
+
* — the consumer correlates by `toolCallId` against the earlier `tool-execution-started`.
|
|
275
|
+
*/
|
|
276
|
+
private deriveToolTelemetry;
|
|
277
|
+
/**
|
|
278
|
+
* Emits a `chat-stream-started` telemetry event and returns the `startedAt` timestamp the
|
|
279
|
+
* caller threads through to the stream wrapper / pre-stream error notifier so terminal
|
|
280
|
+
* events report real elapsed time.
|
|
281
|
+
*
|
|
282
|
+
* Hoisting this above the harness call keeps the `chat-stream-*` contract honest under
|
|
283
|
+
* pre-stream failures: every `chat-stream-error` follows a `chat-stream-started` for the
|
|
284
|
+
* same `(agentId, threadId)` pair.
|
|
285
|
+
*/
|
|
286
|
+
private emitChatStreamStarted;
|
|
287
|
+
/**
|
|
288
|
+
* Emits an `ErrorEvent` + `FinishEvent` to all `subscribe()` listeners and a `chat-stream-error`
|
|
289
|
+
* telemetry event for a failure that occurred before a stream was established. The caller is
|
|
290
|
+
* responsible for re-throwing the original error after calling this — the method itself does
|
|
291
|
+
* not throw.
|
|
292
|
+
*
|
|
293
|
+
* `startedAt` is the timestamp captured by {@link emitChatStreamStarted} so `durationMs`
|
|
294
|
+
* measures real elapsed time even for pre-stream rejections.
|
|
295
|
+
*/
|
|
296
|
+
private notifyPreStreamError;
|
|
297
|
+
private assertNotDisposed;
|
|
298
|
+
}
|