@salesforce/sfdx-agent-sdk 0.63.0 → 0.65.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 +9 -0
- package/README.md +24 -15
- package/dist/chat-session.d.ts +40 -0
- package/dist/chat-session.js +54 -0
- package/dist/errors.d.ts +1 -0
- package/dist/errors.js +1 -0
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,15 @@
|
|
|
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.65.0] - 2026-09-02
|
|
7
|
+
|
|
8
|
+
_No changes — released alongside dependent packages._
|
|
9
|
+
|
|
10
|
+
## [0.64.0] - 2026-09-02
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
- **agent-sdk,harness-mastra,harness-claude,harness-openai**: reject concurrent turns with a typed SESSION_BUSY error @W-24044572@ ([#783](https://github.com/forcedotcom/agentic-dx/pull/783))
|
|
14
|
+
|
|
6
15
|
## [0.63.0] - 2026-09-02
|
|
7
16
|
|
|
8
17
|
_No changes — released alongside dependent packages._
|
package/README.md
CHANGED
|
@@ -774,21 +774,22 @@ totals, subscribe to `chat-stream-completed` telemetry instead.
|
|
|
774
774
|
The SDK throws `AgentSDKError` for predictable not-found and compatibility conditions. Each error has a `type` property
|
|
775
775
|
from `AgentSDKErrorType`:
|
|
776
776
|
|
|
777
|
-
| Type | Thrown By
|
|
778
|
-
| -------------------------------- |
|
|
779
|
-
| `AGENT_NOT_FOUND` | `AgentManager.getAgent()`, `AgentManager.destroyAgent()`, `AgentManager.recoverAgent()` (id neither live nor a restore-failure)
|
|
780
|
-
| `CHAT_SESSION_NOT_FOUND` | `Agent.getChatSession()`, `Agent.destroyChatSession()`, `Agent.cloneChatSession()`, `Agent.compactChatSession()`
|
|
781
|
-
| `COMPACTION_FAILED` | `Agent.compactChatSession()` when the harness's underlying summarization call rejects. The original error is attached as `cause`; the source session is left intact.
|
|
782
|
-
| `DISPOSED` | `Agent` and `ChatSession` methods called after the owner has been destroyed
|
|
783
|
-
| `INCOMPATIBLE_HARNESS` | `createAgentManager()` when the factory advertises an unsupported `protocolVersion`, or the constructed harness reports a `protocolVersion` that differs from the factory's
|
|
784
|
-
| `INVALID_MESSAGE_CONTENT` | `ChatSession.chat()` / harness `stream()` when a message part is not valid as input (a `tool-call`/`tool-result` part, or non-base64-string file data); also `ChatSession.setSessionContext()` / harness `setSessionContext()` when the object exceeds a harness's size / nesting bounds (Mastra: 256 KiB serialized, depth 200). `getSessionContext()` never throws on a corrupt stored slot — it soft-skips to `{}` and logs.
|
|
785
|
-
| `MCP_SERVER_DISABLED` | `Agent.reconnectMcpServer()` when the named server is configured with `enabled: false`
|
|
786
|
-
| `MCP_SERVER_NOT_FOUND` | `Agent.reconnectMcpServer()` when the server name is not in the agent's `mcpServers` config
|
|
787
|
-
| `MODEL_NOT_SUPPORTED_BY_HARNESS` | `AgentManager.createAgent()` / `Agent.updateAgentConfig()` (G8 pre-flight) when the resolved `ModelConnectivityInfo.providerHint` isn't in the harness's `supportedProviderHints`. Surfaces before any harness work runs (no MCP discovery, no subprocess spawn, no language-model construction) so the consumer can branch cleanly on `err.type` and recover without resource cleanup.
|
|
788
|
-
| `MULTIMODAL_NOT_SUPPORTED` | `ChatSession.chat()` / harness `stream()` when a file fails pre-stream capability validation (unsupported format, too large, or too many files)
|
|
789
|
-
| `NOT_SUPPORTED` | `ApiKeyConnectivityResolver.resolve()` when the consumer-supplied `getApiKey` returns an empty / nullish value. Surfaces locally so the consumer sees "the resolver returned an empty key" rather than chasing a 401 through provider logs after `Authorization: Bearer ` (no key) lands on the wire.
|
|
790
|
-
| `
|
|
791
|
-
| `
|
|
777
|
+
| Type | Thrown By |
|
|
778
|
+
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
779
|
+
| `AGENT_NOT_FOUND` | `AgentManager.getAgent()`, `AgentManager.destroyAgent()`, `AgentManager.recoverAgent()` (id neither live nor a restore-failure) |
|
|
780
|
+
| `CHAT_SESSION_NOT_FOUND` | `Agent.getChatSession()`, `Agent.destroyChatSession()`, `Agent.cloneChatSession()`, `Agent.compactChatSession()` |
|
|
781
|
+
| `COMPACTION_FAILED` | `Agent.compactChatSession()` when the harness's underlying summarization call rejects. The original error is attached as `cause`; the source session is left intact. |
|
|
782
|
+
| `DISPOSED` | `Agent` and `ChatSession` methods called after the owner has been destroyed |
|
|
783
|
+
| `INCOMPATIBLE_HARNESS` | `createAgentManager()` when the factory advertises an unsupported `protocolVersion`, or the constructed harness reports a `protocolVersion` that differs from the factory's |
|
|
784
|
+
| `INVALID_MESSAGE_CONTENT` | `ChatSession.chat()` / harness `stream()` when a message part is not valid as input (a `tool-call`/`tool-result` part, or non-base64-string file data); also `ChatSession.setSessionContext()` / harness `setSessionContext()` when the object exceeds a harness's size / nesting bounds (Mastra: 256 KiB serialized, depth 200). `getSessionContext()` never throws on a corrupt stored slot — it soft-skips to `{}` and logs. |
|
|
785
|
+
| `MCP_SERVER_DISABLED` | `Agent.reconnectMcpServer()` when the named server is configured with `enabled: false` |
|
|
786
|
+
| `MCP_SERVER_NOT_FOUND` | `Agent.reconnectMcpServer()` when the server name is not in the agent's `mcpServers` config |
|
|
787
|
+
| `MODEL_NOT_SUPPORTED_BY_HARNESS` | `AgentManager.createAgent()` / `Agent.updateAgentConfig()` (G8 pre-flight) when the resolved `ModelConnectivityInfo.providerHint` isn't in the harness's `supportedProviderHints`. Surfaces before any harness work runs (no MCP discovery, no subprocess spawn, no language-model construction) so the consumer can branch cleanly on `err.type` and recover without resource cleanup. |
|
|
788
|
+
| `MULTIMODAL_NOT_SUPPORTED` | `ChatSession.chat()` / harness `stream()` when a file fails pre-stream capability validation (unsupported format, too large, or too many files) |
|
|
789
|
+
| `NOT_SUPPORTED` | `ApiKeyConnectivityResolver.resolve()` when the consumer-supplied `getApiKey` returns an empty / nullish value. Surfaces locally so the consumer sees "the resolver returned an empty key" rather than chasing a 401 through provider logs after `Authorization: Bearer ` (no key) lands on the wire. |
|
|
790
|
+
| `SESSION_BUSY` | `ChatSession.chat()` (and, at the harness layer, `stream()`) when a turn is already in flight on that session / `(agentId, threadId)`. A session runs **one turn at a time**. `submitToolResult()` / `approveToolCall()` / `declineToolCall()` are control messages on the in-flight turn — never rejected as busy. Two origins with different observable side effects: **SDK-detected** (the session's own in-flight flag is set) is thrown synchronously without notifying subscribers, same posture as `DISPOSED`; **harness-detected** (a `stream()` reaches the harness while its per-turn coordinator is still active) travels the pre-stream-failure path below — subscribers see `ErrorEvent` + `FinishEvent(error)` and a `chat-stream-error` telemetry event before the promise rejects. This replaces the previous silent-dispose-and-replace, so racing two turns against one `(agentId, threadId)` rejects rather than losing the first turn. Abandoning a turn's stream clears the SDK flag but does **not** settle the underlying harness turn, so an immediate re-`chat()` may still surface a harness-origin `SESSION_BUSY` until that turn settles — **abort** (via the turn's `abortSignal`) to release deterministically. |
|
|
791
|
+
| `THREAD_NOT_FOUND` | `ChatSession.setSessionContext()` / harness `setSessionContext()` when seeding context on a thread that was never created (create-first contract). A `ChatSession` is only reachable via `createChatSession()` → `createThread`, so this indicates a seed-before-create misuse; the harness maps its runtime "thread not found" to this typed error. |
|
|
792
|
+
| `TOOL_CALL_NOT_FOUND` | `ChatSession.approveToolCall()` / `declineToolCall()` / `submitToolResult()` when the supplied `toolCallId` doesn't match any pending tool-call request on the current session. Typically indicates a wrong-id, wrong-session, or already-settled call. Both production harnesses (Mastra, Claude) throw this from their per-turn approval coordinator. |
|
|
792
793
|
|
|
793
794
|
```typescript
|
|
794
795
|
import { AgentSDKError, AgentSDKErrorType } from '@salesforce/sfdx-agent-sdk';
|
|
@@ -816,6 +817,14 @@ receive a terminal event for every turn:
|
|
|
816
817
|
already emitted, appends a synthetic `FinishEvent(finishReason: 'error')` at the end. The originating `chat()` promise
|
|
817
818
|
resolves normally; iterate the stream to observe the failure.
|
|
818
819
|
- **Calling a disposed session** throws `AgentSDKError('DISPOSED')` synchronously without notifying subscribers.
|
|
820
|
+
- **Calling `chat()` while a turn is in flight** throws `AgentSDKError('SESSION_BUSY')`. One turn runs at a time per
|
|
821
|
+
session; settle calls (`submitToolResult()` / `approveToolCall()` / `declineToolCall()`) act on the in-flight turn and
|
|
822
|
+
are never rejected as busy. When the session detects the concurrent call itself it throws synchronously without
|
|
823
|
+
notifying subscribers (like `DISPOSED`); when the rejection originates in the harness (a `stream()` racing an active
|
|
824
|
+
coordinator) it follows the pre-stream-failure path above (subscribers see `ErrorEvent` + `FinishEvent`,
|
|
825
|
+
`chat-stream-error` fires). Abandoning a turn's `eventStream` clears the SDK-level busy state but leaves the
|
|
826
|
+
underlying harness turn running until it settles, so **abort** (rather than merely abandon) to admit the next `chat()`
|
|
827
|
+
deterministically.
|
|
819
828
|
|
|
820
829
|
### MCP Server Configuration
|
|
821
830
|
|
package/dist/chat-session.d.ts
CHANGED
|
@@ -70,6 +70,24 @@ export type ChatSessionParentBuses = {
|
|
|
70
70
|
* `FinishEvent(finishReason: 'error')` at the end. Subscribers see the same sequence.
|
|
71
71
|
* - **Calling a disposed session** throws `AgentSDKError('DISPOSED')` synchronously without
|
|
72
72
|
* notifying subscribers — this is a programmer error, not an operational one.
|
|
73
|
+
* - **Calling `chat()` while a turn is already in flight** throws `AgentSDKError('SESSION_BUSY')`. A
|
|
74
|
+
* session runs one turn at a time. `submitToolResult()` / `approveToolCall()` / `declineToolCall()`
|
|
75
|
+
* are control messages on the in-flight turn — NOT new turns — so they are never rejected as busy.
|
|
76
|
+
* `SESSION_BUSY` has **two origins with different observable side effects**:
|
|
77
|
+
* - **SDK-detected** (the session's own in-flight flag is still set): thrown synchronously by
|
|
78
|
+
* `chat()` before `chat-stream-started` or any subscriber notification — a programmer error, same
|
|
79
|
+
* posture as `DISPOSED`. The session's flag clears when the turn's `chat()`-returned `eventStream`
|
|
80
|
+
* reaches its terminal `finish`, **or** when the consumer abandons that stream (early `break` /
|
|
81
|
+
* `.return()`).
|
|
82
|
+
* - **Harness-detected** (a `stream()` reaches the harness while its per-turn coordinator for the
|
|
83
|
+
* `(agentId, threadId)` is still active): travels the normal **pre-stream-failure** path above —
|
|
84
|
+
* subscribers receive `ErrorEvent` + `FinishEvent(finishReason: 'error')` and a `chat-stream-error`
|
|
85
|
+
* telemetry event fires before the promise rejects. This is what a consumer sees if it *abandons*
|
|
86
|
+
* a turn's stream without aborting it and then immediately calls `chat()` again: the SDK flag has
|
|
87
|
+
* cleared, but the underlying harness turn keeps running until it settles, so the harness rejects
|
|
88
|
+
* the new turn until then. **To release a turn deterministically, abort it (via the turn's
|
|
89
|
+
* `abortSignal`) rather than merely abandoning its stream** — abort settles the coordinator, so the
|
|
90
|
+
* next `chat()` is admitted cleanly.
|
|
73
91
|
*/
|
|
74
92
|
export interface ChatSession {
|
|
75
93
|
/** Returns the unique session/thread identifier. */
|
|
@@ -322,6 +340,18 @@ export declare class DefaultChatSession implements ChatSession {
|
|
|
322
340
|
*/
|
|
323
341
|
private latestUsage;
|
|
324
342
|
private disposed;
|
|
343
|
+
/**
|
|
344
|
+
* True while a turn started by {@link chat} is in flight — from the `chat()`
|
|
345
|
+
* call until its returned `eventStream` reaches its terminal `finish` (or is
|
|
346
|
+
* abandoned). A second `chat()` while this is set throws
|
|
347
|
+
* `AgentSDKError('SESSION_BUSY')` synchronously (see {@link assertNotBusy}),
|
|
348
|
+
* giving the SDK its own "one turn at a time per session" enforcement rather
|
|
349
|
+
* than relying solely on a caller / service to serialize turns. Settle calls
|
|
350
|
+
* (`submitToolResult` / `approveToolCall` / `declineToolCall`) are control
|
|
351
|
+
* messages on the in-flight turn, not new turns, so they do NOT consult or
|
|
352
|
+
* mutate this flag. See the interface-level "Failure handling" notes.
|
|
353
|
+
*/
|
|
354
|
+
private turnActive;
|
|
325
355
|
/**
|
|
326
356
|
* @param harness - The agent harness managing thread and message lifecycle.
|
|
327
357
|
* @param agentId - ID of the agent this session belongs to.
|
|
@@ -564,4 +594,14 @@ export declare class DefaultChatSession implements ChatSession {
|
|
|
564
594
|
*/
|
|
565
595
|
private notifySettleRejection;
|
|
566
596
|
private assertNotDisposed;
|
|
597
|
+
/**
|
|
598
|
+
* Rejects a second `chat()` while a turn started by an earlier `chat()` is
|
|
599
|
+
* still in flight. This gives the SDK its own enforcement of the "one turn at
|
|
600
|
+
* a time per session" invariant, rather than relying solely on a caller (or
|
|
601
|
+
* the service's process-local status registry) to serialize turns — closing
|
|
602
|
+
* the "second chat() silently disposes the first" class of lost-turn bug at
|
|
603
|
+
* the harness layer. Like {@link assertNotDisposed}, it throws synchronously
|
|
604
|
+
* without notifying subscribers (a programmer error, not an operational one).
|
|
605
|
+
*/
|
|
606
|
+
private assertNotBusy;
|
|
567
607
|
}
|
package/dist/chat-session.js
CHANGED
|
@@ -73,6 +73,18 @@ export class DefaultChatSession {
|
|
|
73
73
|
*/
|
|
74
74
|
latestUsage = {};
|
|
75
75
|
disposed = false;
|
|
76
|
+
/**
|
|
77
|
+
* True while a turn started by {@link chat} is in flight — from the `chat()`
|
|
78
|
+
* call until its returned `eventStream` reaches its terminal `finish` (or is
|
|
79
|
+
* abandoned). A second `chat()` while this is set throws
|
|
80
|
+
* `AgentSDKError('SESSION_BUSY')` synchronously (see {@link assertNotBusy}),
|
|
81
|
+
* giving the SDK its own "one turn at a time per session" enforcement rather
|
|
82
|
+
* than relying solely on a caller / service to serialize turns. Settle calls
|
|
83
|
+
* (`submitToolResult` / `approveToolCall` / `declineToolCall`) are control
|
|
84
|
+
* messages on the in-flight turn, not new turns, so they do NOT consult or
|
|
85
|
+
* mutate this flag. See the interface-level "Failure handling" notes.
|
|
86
|
+
*/
|
|
87
|
+
turnActive = false;
|
|
76
88
|
/**
|
|
77
89
|
* @param harness - The agent harness managing thread and message lifecycle.
|
|
78
90
|
* @param agentId - ID of the agent this session belongs to.
|
|
@@ -112,6 +124,13 @@ export class DefaultChatSession {
|
|
|
112
124
|
*/
|
|
113
125
|
async chat(message, options) {
|
|
114
126
|
this.assertNotDisposed();
|
|
127
|
+
// Reject a concurrent turn before any observable side effect (no
|
|
128
|
+
// chat-stream-started, no subscriber notification) — SESSION_BUSY is a
|
|
129
|
+
// programmer error, same posture as DISPOSED. Set the in-flight flag
|
|
130
|
+
// synchronously (before the `await`) so a second `chat()` racing this one
|
|
131
|
+
// cannot slip past the guard.
|
|
132
|
+
this.assertNotBusy();
|
|
133
|
+
this.turnActive = true;
|
|
115
134
|
const startedAt = this.emitChatStreamStarted('chat');
|
|
116
135
|
try {
|
|
117
136
|
const result = await this.harness.stream(this.agentId, this.threadId, message, options);
|
|
@@ -121,6 +140,9 @@ export class DefaultChatSession {
|
|
|
121
140
|
};
|
|
122
141
|
}
|
|
123
142
|
catch (err) {
|
|
143
|
+
// Pre-stream failure ends the turn before a stream exists — clear the
|
|
144
|
+
// flag here since `wrapEventStream` (which normally clears it) never runs.
|
|
145
|
+
this.turnActive = false;
|
|
124
146
|
this.notifyPreStreamError(err, startedAt);
|
|
125
147
|
throw err;
|
|
126
148
|
}
|
|
@@ -226,6 +248,23 @@ export class DefaultChatSession {
|
|
|
226
248
|
yield errorEvent;
|
|
227
249
|
lastError = error;
|
|
228
250
|
}
|
|
251
|
+
finally {
|
|
252
|
+
// The SDK-level turn is no longer in flight: the stream drained to its
|
|
253
|
+
// terminal event, threw (caught above), or the consumer abandoned it via
|
|
254
|
+
// `.return()` / an early `break` (the generator suspends on the
|
|
255
|
+
// `yield event` inside this `try`, so `finally` runs on that path too).
|
|
256
|
+
// Clearing here — not only at the `finish` event — is what lets the SDK
|
|
257
|
+
// busy-guard (see `assertNotBusy`) admit the next `chat()` after ANY of
|
|
258
|
+
// those exits, so the SDK flag never wedges the session.
|
|
259
|
+
//
|
|
260
|
+
// NOTE: on an ABANDON-without-abort this clears the SDK flag while the
|
|
261
|
+
// underlying harness turn keeps running (the harness coordinator settles
|
|
262
|
+
// on its own terminal / a teardown, not on consumer abandonment), so the
|
|
263
|
+
// next `chat()` can still surface a harness-origin `SESSION_BUSY` until
|
|
264
|
+
// that turn settles. Aborting (not merely abandoning) releases both
|
|
265
|
+
// layers deterministically. See the interface-level "Failure handling".
|
|
266
|
+
this.turnActive = false;
|
|
267
|
+
}
|
|
229
268
|
if (!sawFinish && lastError !== undefined) {
|
|
230
269
|
const finishEvent = { type: 'finish', finishReason: 'error' };
|
|
231
270
|
this.chatEventBus.emit(finishEvent);
|
|
@@ -721,5 +760,20 @@ export class DefaultChatSession {
|
|
|
721
760
|
throw new AgentSDKError('ChatSession has been disposed.', AgentSDKErrorType.DISPOSED);
|
|
722
761
|
}
|
|
723
762
|
}
|
|
763
|
+
/**
|
|
764
|
+
* Rejects a second `chat()` while a turn started by an earlier `chat()` is
|
|
765
|
+
* still in flight. This gives the SDK its own enforcement of the "one turn at
|
|
766
|
+
* a time per session" invariant, rather than relying solely on a caller (or
|
|
767
|
+
* the service's process-local status registry) to serialize turns — closing
|
|
768
|
+
* the "second chat() silently disposes the first" class of lost-turn bug at
|
|
769
|
+
* the harness layer. Like {@link assertNotDisposed}, it throws synchronously
|
|
770
|
+
* without notifying subscribers (a programmer error, not an operational one).
|
|
771
|
+
*/
|
|
772
|
+
assertNotBusy() {
|
|
773
|
+
if (this.turnActive) {
|
|
774
|
+
throw new AgentSDKError('A chat turn is already in progress for this session. Await (or abandon) the current ' +
|
|
775
|
+
"turn's event stream before starting another.", AgentSDKErrorType.SESSION_BUSY);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
724
778
|
}
|
|
725
779
|
//# sourceMappingURL=chat-session.js.map
|
package/dist/errors.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export declare const AgentSDKErrorType: {
|
|
|
11
11
|
readonly MODEL_NOT_SUPPORTED_BY_HARNESS: 'MODEL_NOT_SUPPORTED_BY_HARNESS';
|
|
12
12
|
readonly MULTIMODAL_NOT_SUPPORTED: 'MULTIMODAL_NOT_SUPPORTED';
|
|
13
13
|
readonly NOT_SUPPORTED: 'NOT_SUPPORTED';
|
|
14
|
+
readonly SESSION_BUSY: 'SESSION_BUSY';
|
|
14
15
|
readonly THREAD_NOT_FOUND: 'THREAD_NOT_FOUND';
|
|
15
16
|
readonly TOOL_CALL_NOT_FOUND: 'TOOL_CALL_NOT_FOUND';
|
|
16
17
|
};
|
package/dist/errors.js
CHANGED
|
@@ -15,6 +15,7 @@ export const AgentSDKErrorType = {
|
|
|
15
15
|
MODEL_NOT_SUPPORTED_BY_HARNESS: 'MODEL_NOT_SUPPORTED_BY_HARNESS',
|
|
16
16
|
MULTIMODAL_NOT_SUPPORTED: 'MULTIMODAL_NOT_SUPPORTED',
|
|
17
17
|
NOT_SUPPORTED: 'NOT_SUPPORTED',
|
|
18
|
+
SESSION_BUSY: 'SESSION_BUSY',
|
|
18
19
|
THREAD_NOT_FOUND: 'THREAD_NOT_FOUND',
|
|
19
20
|
TOOL_CALL_NOT_FOUND: 'TOOL_CALL_NOT_FOUND',
|
|
20
21
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/sfdx-agent-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.65.0",
|
|
4
4
|
"description": "Harness-agnostic agentic infrastructure for Salesforce developer experience tooling",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -47,9 +47,9 @@
|
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@eslint/js": "^10.0.1",
|
|
50
|
-
"@salesforce/sfdx-agent-harness-claude": "0.
|
|
51
|
-
"@salesforce/sfdx-agent-harness-mastra": "0.
|
|
52
|
-
"@salesforce/sfdx-agent-harness-openai": "0.
|
|
50
|
+
"@salesforce/sfdx-agent-harness-claude": "0.61.0",
|
|
51
|
+
"@salesforce/sfdx-agent-harness-mastra": "0.64.0",
|
|
52
|
+
"@salesforce/sfdx-agent-harness-openai": "0.30.0",
|
|
53
53
|
"@types/node": "^22.20.1",
|
|
54
54
|
"@vitest/coverage-istanbul": "^4.1.10",
|
|
55
55
|
"@vitest/eslint-plugin": "^1.6.27",
|