@salesforce/sfdx-agent-sdk 0.76.0 → 0.77.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 +5 -0
- package/README.md +4 -3
- package/dist/agent-manager.d.ts +5 -1
- package/dist/agent-manager.js +7 -1
- package/dist/agent.d.ts +25 -0
- package/dist/agent.js +47 -2
- package/dist/chat-session.d.ts +13 -0
- package/dist/chat-session.js +20 -0
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,11 @@
|
|
|
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.77.0] - 2026-09-08
|
|
7
|
+
|
|
8
|
+
### Fixes
|
|
9
|
+
- **agent-sdk**: AgentManager.shutdown disposes agents instead of destroying them @W-23632695@ ([#794](https://github.com/forcedotcom/agentic-dx/pull/794))
|
|
10
|
+
|
|
6
11
|
## [0.76.0] - 2026-09-08
|
|
7
12
|
|
|
8
13
|
### Features
|
package/README.md
CHANGED
|
@@ -52,8 +52,9 @@ for await (const event of eventStream) {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
// 4. Shut down.
|
|
56
|
-
//
|
|
55
|
+
// 4. Shut down. Agents are disposed (in-memory release) and the harness is torn down;
|
|
56
|
+
// persisted identity, threads, message history, and session context are NOT removed,
|
|
57
|
+
// so a subsequent `createAgentManager` restores the agents and their chat sessions.
|
|
57
58
|
await manager.shutdown();
|
|
58
59
|
```
|
|
59
60
|
|
|
@@ -110,7 +111,7 @@ explicitly. The `createAgent` config parameter narrows automatically when the ha
|
|
|
110
111
|
| `getAgent` | `(agentId: string) => Agent<H>` | Retrieve a live agent by ID. Throws `AgentSDKError` (`AGENT_NOT_FOUND`) for unknown ids and for ids that are only present in `getRestoreFailures()`. |
|
|
111
112
|
| `getAgentIds` | `() => string[]` | List all live agent IDs (successful + successfully restored). Failed-restore agents are not included — query `getRestoreFailures()` separately. |
|
|
112
113
|
| `destroyAgent` | `(agentId: string) => Promise<void>` | Destroy an agent, remove its identity record from disk, and clear any matching `getRestoreFailures()` entry. Failed-restore-only ids are accepted (no harness call made). |
|
|
113
|
-
| `shutdown` | `() => Promise<void>` |
|
|
114
|
+
| `shutdown` | `() => Promise<void>` | Dispose all live agents (release in-memory resources) and shut down the harness. Persisted threads, message history, and session context are NOT deleted; restart `createAgentManager` over the same root to restore the agents and their chat sessions. |
|
|
114
115
|
| `onTelemetry` | `(callback: TelemetryEventCallback) => Unsubscribe` | Subscribe to telemetry across all managed agents. |
|
|
115
116
|
| `onLog` | `(callback: (record: LogRecord) => void) => Unsubscribe` | Subscribe to structured logs across all managed agents. Bridge this into your host logger to observe restore-failure events + soft-skip warnings. |
|
|
116
117
|
| `onWireCommunication` | `(callback: WireCommunicationEventCallback) => Unsubscribe` | Subscribe to wire-level communication events from the harness. Opt-in diagnostic channel that surfaces outbound LLM requests, responses, and harness-specific monitoring metadata. Subscriber-gated end-to-end — harnesses pay no cost when nobody listens. See "Wire-Communication Events" below for the event-shape catalog and the harness-asymmetric coverage (Mastra emits per-call request/response pairs; Claude emits a per-stream pointer to a debug log file). |
|
package/dist/agent-manager.d.ts
CHANGED
|
@@ -136,7 +136,11 @@ export interface AgentManager<H extends AgentHarness = AgentHarness> {
|
|
|
136
136
|
* restore-failure entry.
|
|
137
137
|
*/
|
|
138
138
|
destroyAgent(agentId: string): Promise<void>;
|
|
139
|
-
/**
|
|
139
|
+
/**
|
|
140
|
+
* Disposes every live agent (in-memory release) and shuts down the harness. Persisted
|
|
141
|
+
* threads, message history, and per-thread session context are NOT deleted, so a subsequent
|
|
142
|
+
* `createAgentManager` over the same storage root restores the agents and their chat sessions.
|
|
143
|
+
*/
|
|
140
144
|
shutdown(): Promise<void>;
|
|
141
145
|
/**
|
|
142
146
|
* Harness-specific extensions namespace, typed off the harness subtype `H`.
|
package/dist/agent-manager.js
CHANGED
|
@@ -128,7 +128,13 @@ export class DefaultAgentManager {
|
|
|
128
128
|
return;
|
|
129
129
|
}
|
|
130
130
|
for (const [agentId, agent] of this.agents) {
|
|
131
|
-
|
|
131
|
+
// Graceful shutdown releases in-memory resources but MUST NOT delete persisted
|
|
132
|
+
// threads / message history / session context — `dispose()`, not `destroy()`. A
|
|
133
|
+
// subsequent createAgentManager over the same storageRootFolder then restores every
|
|
134
|
+
// agent's chat sessions and seeded context. `harness.shutdown()` below releases the
|
|
135
|
+
// harness-side per-agent runtime (coordinators, MCP clients, storage handle). Using
|
|
136
|
+
// `destroy()` here deleted the very state boot-restore exists to bring back (W-23632695).
|
|
137
|
+
agent.dispose();
|
|
132
138
|
this.router.unregisterAgent(agentId);
|
|
133
139
|
}
|
|
134
140
|
this.agents.clear();
|
package/dist/agent.d.ts
CHANGED
|
@@ -345,6 +345,31 @@ export declare class DefaultAgent implements Agent {
|
|
|
345
345
|
* - MUST delegate to `this.harness.destroyAgent(this.config.agentId)` to clean up the agent's harness resources.
|
|
346
346
|
*/
|
|
347
347
|
destroy(): Promise<void>;
|
|
348
|
+
/**
|
|
349
|
+
* Release this agent's in-memory resources WITHOUT deleting any persisted state.
|
|
350
|
+
* Used by {@link DefaultAgentManager.shutdown} on a graceful process stop.
|
|
351
|
+
*
|
|
352
|
+
* Unlike {@link destroy} (the `DELETE /agents` verb), `dispose` does NOT call
|
|
353
|
+
* `harness.destroyThread` / `harness.destroyAgent`, so the agent's threads, message
|
|
354
|
+
* history, and per-thread session context stay on the storage root and a subsequent
|
|
355
|
+
* `createAgentManager` over that root restores them. The harness's own per-agent
|
|
356
|
+
* runtime (coordinators, MCP clients, storage handle) is released by
|
|
357
|
+
* `harness.shutdown()`, which the manager calls after disposing every agent.
|
|
358
|
+
*
|
|
359
|
+
* Emits NO `agent-destroyed` telemetry — the agent is being released for restart,
|
|
360
|
+
* not destroyed. Idempotent via the shared `disposed` guard.
|
|
361
|
+
*
|
|
362
|
+
* Not on the public {@link Agent} interface — only {@link DefaultAgentManager} calls
|
|
363
|
+
* it, and it holds the concrete `DefaultAgent` (same reason {@link restoreSessions}
|
|
364
|
+
* is DefaultAgent-only). See W-23632695.
|
|
365
|
+
*/
|
|
366
|
+
dispose(): void;
|
|
367
|
+
/**
|
|
368
|
+
* Tear down inbound + parent telemetry/log forwarding and dispose this agent's own
|
|
369
|
+
* buses, then flip `disposed`. Shared by {@link destroy} and {@link dispose} so the
|
|
370
|
+
* two teardown verbs can't drift on forwarding / bus cleanup.
|
|
371
|
+
*/
|
|
372
|
+
private teardownForwardingAndBuses;
|
|
348
373
|
onTelemetry(callback: TelemetryEventCallback): Unsubscribe;
|
|
349
374
|
onLog(callback: (record: LogRecord) => void): Unsubscribe;
|
|
350
375
|
/**
|
package/dist/agent.js
CHANGED
|
@@ -387,6 +387,42 @@ export class DefaultAgent {
|
|
|
387
387
|
message: 'Agent destroyed',
|
|
388
388
|
context: { event_type: 'agent-destroyed', agentId: this.agentId },
|
|
389
389
|
}, agentDestroyedAt);
|
|
390
|
+
this.teardownForwardingAndBuses();
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Release this agent's in-memory resources WITHOUT deleting any persisted state.
|
|
394
|
+
* Used by {@link DefaultAgentManager.shutdown} on a graceful process stop.
|
|
395
|
+
*
|
|
396
|
+
* Unlike {@link destroy} (the `DELETE /agents` verb), `dispose` does NOT call
|
|
397
|
+
* `harness.destroyThread` / `harness.destroyAgent`, so the agent's threads, message
|
|
398
|
+
* history, and per-thread session context stay on the storage root and a subsequent
|
|
399
|
+
* `createAgentManager` over that root restores them. The harness's own per-agent
|
|
400
|
+
* runtime (coordinators, MCP clients, storage handle) is released by
|
|
401
|
+
* `harness.shutdown()`, which the manager calls after disposing every agent.
|
|
402
|
+
*
|
|
403
|
+
* Emits NO `agent-destroyed` telemetry — the agent is being released for restart,
|
|
404
|
+
* not destroyed. Idempotent via the shared `disposed` guard.
|
|
405
|
+
*
|
|
406
|
+
* Not on the public {@link Agent} interface — only {@link DefaultAgentManager} calls
|
|
407
|
+
* it, and it holds the concrete `DefaultAgent` (same reason {@link restoreSessions}
|
|
408
|
+
* is DefaultAgent-only). See W-23632695.
|
|
409
|
+
*/
|
|
410
|
+
dispose() {
|
|
411
|
+
if (this.disposed) {
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
for (const [sessionId, session] of this.sessions) {
|
|
415
|
+
this.detachSession(sessionId, session, false);
|
|
416
|
+
}
|
|
417
|
+
this.sessions.clear();
|
|
418
|
+
this.teardownForwardingAndBuses();
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Tear down inbound + parent telemetry/log forwarding and dispose this agent's own
|
|
422
|
+
* buses, then flip `disposed`. Shared by {@link destroy} and {@link dispose} so the
|
|
423
|
+
* two teardown verbs can't drift on forwarding / bus cleanup.
|
|
424
|
+
*/
|
|
425
|
+
teardownForwardingAndBuses() {
|
|
390
426
|
for (const unsub of this.inboundUnsubs)
|
|
391
427
|
unsub();
|
|
392
428
|
for (const unsub of this.parentUnsubs)
|
|
@@ -456,8 +492,17 @@ export class DefaultAgent {
|
|
|
456
492
|
}, sessionCreatedAt);
|
|
457
493
|
return session;
|
|
458
494
|
}
|
|
459
|
-
detachSession(threadId, session) {
|
|
460
|
-
|
|
495
|
+
detachSession(threadId, session, emitDestroyed = true) {
|
|
496
|
+
// `emitDestroyed` is false only on the graceful-shutdown release path (`dispose()`): the
|
|
497
|
+
// session is preserved on disk for restore, so it must not emit `session-destroyed` — the
|
|
498
|
+
// session-level analog of `dispose()` suppressing `agent-destroyed` (W-23632695). Every real
|
|
499
|
+
// teardown (destroy / destroyChatSession / compact / clone source) keeps the default `true`.
|
|
500
|
+
if (emitDestroyed) {
|
|
501
|
+
session.dispose();
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
session.releaseWithoutEvent();
|
|
505
|
+
}
|
|
461
506
|
const unregister = this.sessionSliceUnregisters.get(threadId);
|
|
462
507
|
if (unregister) {
|
|
463
508
|
unregister();
|
package/dist/chat-session.d.ts
CHANGED
|
@@ -566,6 +566,19 @@ export declare class DefaultChatSession implements ChatSession {
|
|
|
566
566
|
onTelemetry(callback: TelemetryEventCallback): Unsubscribe;
|
|
567
567
|
onLog(callback: (record: LogRecord) => void): Unsubscribe;
|
|
568
568
|
dispose(): void;
|
|
569
|
+
/**
|
|
570
|
+
* Release this session's in-memory resources WITHOUT emitting `session-destroyed`.
|
|
571
|
+
* Used on the graceful-shutdown release path (`DefaultAgent.dispose()`), where the thread
|
|
572
|
+
* and its session context are preserved on disk for restore, so a "destroyed" signal would
|
|
573
|
+
* misinform telemetry observers. Teardown is otherwise identical to `dispose()`. Not on the
|
|
574
|
+
* public `ChatSession` interface — only `DefaultAgent.detachSession` calls it (W-23632695).
|
|
575
|
+
*/
|
|
576
|
+
releaseWithoutEvent(): void;
|
|
577
|
+
/**
|
|
578
|
+
* Shared in-memory teardown for `dispose()` (which first emits `session-destroyed`) and
|
|
579
|
+
* `releaseWithoutEvent()` (silent), so the two paths can't drift on cleanup.
|
|
580
|
+
*/
|
|
581
|
+
private teardown;
|
|
569
582
|
private emitToolApprovalResolved;
|
|
570
583
|
/**
|
|
571
584
|
* Clears the per-turn tracking maps at a terminal `finish`. Both maps are
|
package/dist/chat-session.js
CHANGED
|
@@ -663,6 +663,26 @@ export class DefaultChatSession {
|
|
|
663
663
|
threadId: this.threadId,
|
|
664
664
|
},
|
|
665
665
|
}, sessionDestroyedAt);
|
|
666
|
+
this.teardown();
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Release this session's in-memory resources WITHOUT emitting `session-destroyed`.
|
|
670
|
+
* Used on the graceful-shutdown release path (`DefaultAgent.dispose()`), where the thread
|
|
671
|
+
* and its session context are preserved on disk for restore, so a "destroyed" signal would
|
|
672
|
+
* misinform telemetry observers. Teardown is otherwise identical to `dispose()`. Not on the
|
|
673
|
+
* public `ChatSession` interface — only `DefaultAgent.detachSession` calls it (W-23632695).
|
|
674
|
+
*/
|
|
675
|
+
releaseWithoutEvent() {
|
|
676
|
+
if (this.disposed) {
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
this.teardown();
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Shared in-memory teardown for `dispose()` (which first emits `session-destroyed`) and
|
|
683
|
+
* `releaseWithoutEvent()` (silent), so the two paths can't drift on cleanup.
|
|
684
|
+
*/
|
|
685
|
+
teardown() {
|
|
666
686
|
for (const unsub of this.inboundUnsubs)
|
|
667
687
|
unsub();
|
|
668
688
|
for (const unsub of this.parentUnsubs)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/sfdx-agent-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.77.0",
|
|
4
4
|
"description": "Harness-agnostic agentic infrastructure for Salesforce developer experience tooling",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@eslint/js": "^10.0.1",
|
|
51
|
-
"@salesforce/sfdx-agent-harness-claude": "0.
|
|
52
|
-
"@salesforce/sfdx-agent-harness-mastra": "0.
|
|
53
|
-
"@salesforce/sfdx-agent-harness-openai": "0.
|
|
51
|
+
"@salesforce/sfdx-agent-harness-claude": "0.73.0",
|
|
52
|
+
"@salesforce/sfdx-agent-harness-mastra": "0.76.0",
|
|
53
|
+
"@salesforce/sfdx-agent-harness-openai": "0.42.0",
|
|
54
54
|
"@types/node": "^22.20.1",
|
|
55
55
|
"@vitest/coverage-istanbul": "^4.1.11",
|
|
56
56
|
"@vitest/eslint-plugin": "^1.6.27",
|