@salesforce/sfdx-agent-sdk 0.72.0 → 0.73.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 +21 -15
- package/dist/agent-manager.js +6 -0
- package/dist/agent.js +9 -0
- package/dist/errors.d.ts +7 -0
- package/dist/errors.js +7 -0
- package/dist/harness/public.d.ts +1 -0
- package/dist/harness/public.js +1 -0
- package/dist/harness/tool-args-validation.d.ts +121 -0
- package/dist/harness/tool-args-validation.js +180 -0
- package/dist/internal/tool-schema-registration.d.ts +17 -0
- package/dist/internal/tool-schema-registration.js +30 -0
- package/package.json +6 -5
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.73.0] - 2026-09-04
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
- **agent-sdk,harness-claude,harness-mastra,harness-openai**: validate frontend tool-call args @W-24023028@ ([#789](https://github.com/forcedotcom/agentic-dx/pull/789))
|
|
10
|
+
|
|
6
11
|
## [0.72.0] - 2026-09-02
|
|
7
12
|
|
|
8
13
|
### Features
|
package/README.md
CHANGED
|
@@ -174,7 +174,7 @@ A single conversation thread.
|
|
|
174
174
|
| `getContextUsage` | `() => ContextUsage` | Snapshot of how much of the model's context window the most recent turn used. |
|
|
175
175
|
| `addMessages` | `(message: string \| Message[]) => Promise<void>` | Append real transcript messages (`user` / `assistant` / `tool`) to the thread **without requesting an agent response** — the write-only half of a turn. The messages persist, appear in `getMessageHistory()`, and replay to the model as prior conversation on the next `chat()`. Use it to seed earlier turns (e.g. file contents as a user message) before the first live prompt; the SDK equivalent of the service's `POST /messages` with `noReply=true`. **Not** `setSessionContext`: this writes _transcript history_ (visible in `getMessageHistory`, additive); `setSessionContext` writes an _out-of-history overlay object_ (never in history, whole-object replace). `'system'` is not a valid role here — system-level state rides `setSessionContext` / `AgentConfig.instructions`. |
|
|
176
176
|
| `addContext` | `(message: string \| Message[]) => Promise<void>` | **Deprecated** — renamed to `addMessages` (identical signature/behavior); delegates to it. The old name read as a sibling of `setSessionContext`, but the two are distinct channels. Will be removed in a future release; migrate to `addMessages`. |
|
|
177
|
-
| `setSessionContext` | `(content: SessionContext) => Promise<void>` | Replace this session's session-context object in full (whole-object set, not a merge). Persisted per-thread and durable across restart; kept out of message history, so it never appears in `getMessageHistory()`. Rendered into the model's system-level context on every subsequent turn (deterministic, key-ordered) on all three harnesses (**Mastra** W-23632686, **Claude** W-23632691, and **OpenAI** W-23632694). Delegates to `AgentHarness.setSessionContext` — see that method's JSDoc for the full delivery/durability/isolation contract.
|
|
177
|
+
| `setSessionContext` | `(content: SessionContext) => Promise<void>` | Replace this session's session-context object in full (whole-object set, not a merge). Persisted per-thread and durable across restart; kept out of message history, so it never appears in `getMessageHistory()`. Rendered into the model's system-level context on every subsequent turn (deterministic, key-ordered) on all three harnesses (**Mastra** W-23632686, **Claude** W-23632691, and **OpenAI** W-23632694). Delegates to `AgentHarness.setSessionContext` — see that method's JSDoc for the full delivery/durability/isolation contract. |
|
|
178
178
|
| `getSessionContext` | `() => Promise<SessionContext>` | Read this session's current session-context object. Returns `{}` (an empty object) — never `null` or `undefined` — when nothing has been set on this thread yet, so callers never need a null-check. Unrelated to `getContextUsage()`, which reports context-window token occupancy, not the seeded context object. |
|
|
179
179
|
| `subscribe` | `(callback: (event: ChatEvent) => void) => void` | Register a real-time event listener. |
|
|
180
180
|
| `unsubscribe` | `(callback: (event: ChatEvent) => void) => void` | Remove a listener. |
|
|
@@ -783,6 +783,7 @@ from `AgentSDKErrorType`:
|
|
|
783
783
|
| `DISPOSED` | `Agent` and `ChatSession` methods called after the owner has been destroyed |
|
|
784
784
|
| `INCOMPATIBLE_HARNESS` | `createAgentManager()` when the factory advertises an unsupported `protocolVersion`, or the constructed harness reports a `protocolVersion` that differs from the factory's |
|
|
785
785
|
| `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. |
|
|
786
|
+
| `INVALID_TOOL_SCHEMA` | `AgentManager.createAgent()` / `Agent.updateAgentConfig()` when a consumer-declared `AgentConfig.tools[i].inputSchema` is not a compilable JSON Schema. Fails loud at registration (before any harness work) so a schema typo doesn't surface lazily on the model's first call to that tool. |
|
|
786
787
|
| `MCP_SERVER_DISABLED` | `Agent.reconnectMcpServer()` when the named server is configured with `enabled: false` |
|
|
787
788
|
| `MCP_SERVER_NOT_FOUND` | `Agent.reconnectMcpServer()` when the server name is not in the agent's `mcpServers` config |
|
|
788
789
|
| `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. |
|
|
@@ -1559,20 +1560,25 @@ This package publishes two ESM entry points:
|
|
|
1559
1560
|
> see the subpath. Modern bundlers (Vite, esbuild, Webpack 5+, tsup, Rollup with `@rollup/plugin-node-resolve` v15+)
|
|
1560
1561
|
> resolve it natively. This is a harness-author concern only; consumer applications never touch the subpath.
|
|
1561
1562
|
|
|
1562
|
-
| Export | Surface | Role
|
|
1563
|
-
| ---------------------------------- | ------------------------------------------- |
|
|
1564
|
-
| `HarnessFactory<H>` | Type only on bare; value+type on `/harness` | Construct a harness of type `H` bound to a storage root. Declares `harnessId` and `protocolVersion`. Default `H = AgentHarness`.
|
|
1565
|
-
| `AgentHarness` | Type only on bare; type on `/harness` | Runtime contract: agent / thread / stream / tool / message lifecycle. Declares its own `harnessId` and `protocolVersion`.
|
|
1566
|
-
| `SUPPORTED_PROTOCOL_VERSIONS` | `/harness` only | Readonly list of harness protocol versions this SDK accepts. `createAgentManager` checks both the factory and the constructed harness.
|
|
1567
|
-
| `HarnessBusOwner` | `/harness` only | Composition helper owning telemetry + log buses with `dispose()` semantics. Reuse it instead of reimplementing bus plumbing.
|
|
1568
|
-
| `lowerStreamInput` | `/harness` only | Validates a `MessagePart[]` and lowers each input part to your runtime's content-block shape. Use it in `stream()` so multimodal caps and `MULTIMODAL_NOT_SUPPORTED` / `INVALID_MESSAGE_CONTENT` semantics match every other harness.
|
|
1569
|
-
| `GenSink<T>` | `/harness` only | Buffered async-generator wrapper for routing `ChatEvent`s to a consumer's `ChatStreamResult.eventStream`. Single-iteration: calling `generator()` twice throws — sinks have one waiter slot and one buffer, two iterators race on both.
|
|
1570
|
-
| `mcpServerConfigEqual` | Bare specifier and `/harness` | Structural deep-equality predicate over `MCPServerConfig`. Use inside `updateAgent` to decide which servers to preserve vs. cycle. Treats `enabled: undefined` and `enabled: true` as equal; compares URLs via `String(url)` (so `URL` instances and strings round-trip); `headers` and `env` are key-order-insensitive; `reconnectionOptions` compares field-wise.
|
|
1571
|
-
| `AlwaysActiveEntry` | `/harness` only | Entry shape consumed by per-harness `toolSearch.alwaysActive` extension fields. Three matching patterns: `{ serverName }` (server-wide), `{ serverName, toolName }` (precise), `{ toolName }` (cross-source). At least one of `serverName` / `toolName` must be present.
|
|
1572
|
-
| `matchesAlwaysActive` | `/harness` only | Predicate `(entries, serverName, toolName) → boolean` consulted per-tool when stamping always-load metadata or partitioning a tool-search pool. Use this instead of pattern-matching entries by hand so harness behavior stays uniform.
|
|
1573
|
-
| `validateAlwaysActiveEntry` | `/harness` only | Throws on a malformed entry (`{}`, both fields empty). Call once per entry at the harness boundary so a typo fails loud at config time rather than silently dropping the entry on every `stream()`.
|
|
1574
|
-
| `splitToolResultsIntoToolMessages` | `/harness` only | Read-side normalizer `(Message[]) → Message[]`. Hoists every completed tool call's `tool-result` part onto its own `role: 'tool'` message (leaving the `tool-call` on the assistant message), so `getMessages()` returns the canonical cross-harness layout. Idempotent; backfills a blank result `toolName` from the matching call; preserves `isError` and (in-memory) `error`. Call it at the end of `getMessages()`. (Whether `error` survives to the returned history is a harness-persistence concern — see `AgentHarness.getMessages`; `isError` always survives.)
|
|
1575
|
-
| `mergeToolResultsIntoAssistant` | `/harness` only | Write-side inverse `(Message[]) → Message[]`. Folds each `role: 'tool'` message's result back adjacent to its `tool-call` in the preceding assistant message, so a runtime that stores a completed call as one merged object round-trips losslessly. Call it at the start of `addMessages()` before persisting.
|
|
1563
|
+
| Export | Surface | Role |
|
|
1564
|
+
| ---------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
1565
|
+
| `HarnessFactory<H>` | Type only on bare; value+type on `/harness` | Construct a harness of type `H` bound to a storage root. Declares `harnessId` and `protocolVersion`. Default `H = AgentHarness`. |
|
|
1566
|
+
| `AgentHarness` | Type only on bare; type on `/harness` | Runtime contract: agent / thread / stream / tool / message lifecycle. Declares its own `harnessId` and `protocolVersion`. |
|
|
1567
|
+
| `SUPPORTED_PROTOCOL_VERSIONS` | `/harness` only | Readonly list of harness protocol versions this SDK accepts. `createAgentManager` checks both the factory and the constructed harness. |
|
|
1568
|
+
| `HarnessBusOwner` | `/harness` only | Composition helper owning telemetry + log buses with `dispose()` semantics. Reuse it instead of reimplementing bus plumbing. |
|
|
1569
|
+
| `lowerStreamInput` | `/harness` only | Validates a `MessagePart[]` and lowers each input part to your runtime's content-block shape. Use it in `stream()` so multimodal caps and `MULTIMODAL_NOT_SUPPORTED` / `INVALID_MESSAGE_CONTENT` semantics match every other harness. |
|
|
1570
|
+
| `GenSink<T>` | `/harness` only | Buffered async-generator wrapper for routing `ChatEvent`s to a consumer's `ChatStreamResult.eventStream`. Single-iteration: calling `generator()` twice throws — sinks have one waiter slot and one buffer, two iterators race on both. |
|
|
1571
|
+
| `mcpServerConfigEqual` | Bare specifier and `/harness` | Structural deep-equality predicate over `MCPServerConfig`. Use inside `updateAgent` to decide which servers to preserve vs. cycle. Treats `enabled: undefined` and `enabled: true` as equal; compares URLs via `String(url)` (so `URL` instances and strings round-trip); `headers` and `env` are key-order-insensitive; `reconnectionOptions` compares field-wise. |
|
|
1572
|
+
| `AlwaysActiveEntry` | `/harness` only | Entry shape consumed by per-harness `toolSearch.alwaysActive` extension fields. Three matching patterns: `{ serverName }` (server-wide), `{ serverName, toolName }` (precise), `{ toolName }` (cross-source). At least one of `serverName` / `toolName` must be present. |
|
|
1573
|
+
| `matchesAlwaysActive` | `/harness` only | Predicate `(entries, serverName, toolName) → boolean` consulted per-tool when stamping always-load metadata or partitioning a tool-search pool. Use this instead of pattern-matching entries by hand so harness behavior stays uniform. |
|
|
1574
|
+
| `validateAlwaysActiveEntry` | `/harness` only | Throws on a malformed entry (`{}`, both fields empty). Call once per entry at the harness boundary so a typo fails loud at config time rather than silently dropping the entry on every `stream()`. |
|
|
1575
|
+
| `splitToolResultsIntoToolMessages` | `/harness` only | Read-side normalizer `(Message[]) → Message[]`. Hoists every completed tool call's `tool-result` part onto its own `role: 'tool'` message (leaving the `tool-call` on the assistant message), so `getMessages()` returns the canonical cross-harness layout. Idempotent; backfills a blank result `toolName` from the matching call; preserves `isError` and (in-memory) `error`. Call it at the end of `getMessages()`. (Whether `error` survives to the returned history is a harness-persistence concern — see `AgentHarness.getMessages`; `isError` always survives.) |
|
|
1576
|
+
| `mergeToolResultsIntoAssistant` | `/harness` only | Write-side inverse `(Message[]) → Message[]`. Folds each `role: 'tool'` message's result back adjacent to its `tool-call` in the preceding assistant message, so a runtime that stores a completed call as one merged object round-trips losslessly. Call it at the start of `addMessages()` before persisting. |
|
|
1577
|
+
| `validateToolArgs` | `/harness` only | Validates a raw tool-call argument buffer for a consumer/frontend tool (an `AgentConfig.tools` entry with no `execute`) against its declared `inputSchema`, returning a discriminated `'ok' \| 'unparseable'{reason:'not-json'\|'not-object'} \| 'schema' \| 'invalid-schema'` result. `'invalid-schema'` is a consumer misconfiguration (a schema that won't compile) the gate fails **open** on — the parsed args pass through with a loggable `schemaError`, never fed to the model. Call it before forwarding parsed args to the consumer so every harness rejects malformed/schema-violating buffers identically instead of silently collapsing them to `{}`. |
|
|
1578
|
+
| `validateToolSchemaCompiles` | `/harness` only | Registration-time guard: reports whether a consumer tool's declared `inputSchema` compiles, so a typo fails loud at `createAgent` / `updateAgentConfig` (via `INVALID_TOOL_SCHEMA`) rather than lazily at first call. Shares the same compile cache as `validateToolArgs`. |
|
|
1579
|
+
| `TOOL_ARGS_MAX_ATTEMPTS` | `/harness` only | The single shared retry cap (`3`) every harness bounds its per-tool-call consumer-args retries against, so the "will not be retried further" exhaustion wording can't drift between harnesses. |
|
|
1580
|
+
| `describeToolArgsFailure` | `/harness` only | Builds the one canonical model-visible message for a `validateToolArgs` failure outcome, so wording can't drift between harnesses. Pass `{ exhausted: true, maxAttempts }` on the final retry to append a "will not be retried further" clause. Throws on the non-failure outcomes (`'ok'` / `'invalid-schema'`), which are never fed to the model. |
|
|
1581
|
+
| `recordToolArgsFailure` | `/harness` only | Records one consumer-args failure against a caller-owned, tool-NAME-keyed attempt counter (`Map<string, number>`) and returns `{ attempt, exhausted }` (against `TOOL_ARGS_MAX_ATTEMPTS`, or a supplied override). The one shared increment-then-compare computation every harness's gate uses; storage stays caller-owned (harnesses scope the map per-turn/per-thread or per-`stream()`). Reset a name's streak with a plain `counts.delete(name)` on a non-failure outcome. |
|
|
1576
1582
|
|
|
1577
1583
|
Minimal skeleton:
|
|
1578
1584
|
|
package/dist/agent-manager.js
CHANGED
|
@@ -13,6 +13,7 @@ import { AgentSDKError, AgentSDKErrorType } from './errors.js';
|
|
|
13
13
|
import { TelemetryRouter } from './internal/telemetry-router.js';
|
|
14
14
|
import { WireCommunicationRouter } from './internal/wire-communication-router.js';
|
|
15
15
|
import { AgentIdentityStore } from './internal/agent-identity-store.js';
|
|
16
|
+
import { assertToolSchemasCompile } from './internal/tool-schema-registration.js';
|
|
16
17
|
import { createTelemetryBus } from './types/telemetry-events.js';
|
|
17
18
|
import { DefaultAgentConnectivityResolver } from './agent-connectivity-resolver.js';
|
|
18
19
|
/**
|
|
@@ -150,6 +151,11 @@ export class DefaultAgentManager {
|
|
|
150
151
|
if (this.agents.has(agentId)) {
|
|
151
152
|
throw new Error(`Agent with id "${agentId}" already exists`);
|
|
152
153
|
}
|
|
154
|
+
// Fail loud at registration on a non-compilable consumer tool inputSchema
|
|
155
|
+
// (W-24023028 B1) — before any harness resources are allocated. NOT run on
|
|
156
|
+
// the boot-restore path (see the helper's doc): a bad persisted schema
|
|
157
|
+
// degrades to the runtime gate's fail-open instead of bricking reboot.
|
|
158
|
+
assertToolSchemasCompile(agentConfig);
|
|
153
159
|
// installAgent validates projectRoot existence — same path as the restore loop.
|
|
154
160
|
const agent = await this.installAgent(agentId, resolvedProjectRoot, agentConfig, {
|
|
155
161
|
abortSignal: options?.abortSignal,
|
package/dist/agent.js
CHANGED
|
@@ -7,6 +7,7 @@ import { toHarnessConfig, } from './harness/harness-config.js';
|
|
|
7
7
|
import { normalizeMcpAuthProviders } from './mcp-auth.js';
|
|
8
8
|
import { DefaultChatSession } from './chat-session.js';
|
|
9
9
|
import { AgentSDKError, AgentSDKErrorType } from './errors.js';
|
|
10
|
+
import { assertToolSchemasCompile } from './internal/tool-schema-registration.js';
|
|
10
11
|
import { createTelemetryBus } from './types/telemetry-events.js';
|
|
11
12
|
/**
|
|
12
13
|
* Resolves the next consumer-metadata value from the current value and an optional mutation. `replace` deep-clones the
|
|
@@ -187,6 +188,14 @@ export class DefaultAgent {
|
|
|
187
188
|
}
|
|
188
189
|
return;
|
|
189
190
|
}
|
|
191
|
+
// Fail loud on a non-compilable consumer tool inputSchema in THIS update's
|
|
192
|
+
// `tools` delta (W-24023028 B1), before any harness work. Validate only the
|
|
193
|
+
// incoming delta — not the merged `nextConfig` — so a policy-only update
|
|
194
|
+
// (notably the load-bearing `approveToolCall({ remember: true })` path,
|
|
195
|
+
// which passes `toolPolicies` and no `tools`) never re-validates inherited
|
|
196
|
+
// schemas and so can never regress on a pre-guard agent whose persisted
|
|
197
|
+
// schema is bad (that degrades to the runtime gate's fail-open instead).
|
|
198
|
+
assertToolSchemasCompile(config);
|
|
190
199
|
const orgAliasRequested = Object.prototype.hasOwnProperty.call(config, 'orgAlias');
|
|
191
200
|
const modelIdRequested = Object.prototype.hasOwnProperty.call(config, 'modelId');
|
|
192
201
|
let nextModelConnectivityInfo = previousModelConnectivityInfo;
|
package/dist/errors.d.ts
CHANGED
|
@@ -7,6 +7,13 @@ export declare const AgentSDKErrorType: {
|
|
|
7
7
|
readonly INCOMPATIBLE_HARNESS: 'INCOMPATIBLE_HARNESS';
|
|
8
8
|
readonly INVALID_MCP_AUTH_CONFIG: 'INVALID_MCP_AUTH_CONFIG';
|
|
9
9
|
readonly INVALID_MESSAGE_CONTENT: 'INVALID_MESSAGE_CONTENT';
|
|
10
|
+
/**
|
|
11
|
+
* A consumer-declared `AgentConfig.tools[i].inputSchema` is not a compilable
|
|
12
|
+
* JSON Schema. Thrown at `createAgent` / `updateAgentConfig` so a schema typo
|
|
13
|
+
* fails loud at registration rather than surfacing lazily (and fail-open) on
|
|
14
|
+
* the model's first call to that tool (W-24023028 B1).
|
|
15
|
+
*/
|
|
16
|
+
readonly INVALID_TOOL_SCHEMA: 'INVALID_TOOL_SCHEMA';
|
|
10
17
|
readonly MCP_SERVER_DISABLED: 'MCP_SERVER_DISABLED';
|
|
11
18
|
readonly MCP_SERVER_NOT_FOUND: 'MCP_SERVER_NOT_FOUND';
|
|
12
19
|
readonly MODEL_NOT_SUPPORTED_BY_HARNESS: 'MODEL_NOT_SUPPORTED_BY_HARNESS';
|
package/dist/errors.js
CHANGED
|
@@ -11,6 +11,13 @@ export const AgentSDKErrorType = {
|
|
|
11
11
|
INCOMPATIBLE_HARNESS: 'INCOMPATIBLE_HARNESS',
|
|
12
12
|
INVALID_MCP_AUTH_CONFIG: 'INVALID_MCP_AUTH_CONFIG',
|
|
13
13
|
INVALID_MESSAGE_CONTENT: 'INVALID_MESSAGE_CONTENT',
|
|
14
|
+
/**
|
|
15
|
+
* A consumer-declared `AgentConfig.tools[i].inputSchema` is not a compilable
|
|
16
|
+
* JSON Schema. Thrown at `createAgent` / `updateAgentConfig` so a schema typo
|
|
17
|
+
* fails loud at registration rather than surfacing lazily (and fail-open) on
|
|
18
|
+
* the model's first call to that tool (W-24023028 B1).
|
|
19
|
+
*/
|
|
20
|
+
INVALID_TOOL_SCHEMA: 'INVALID_TOOL_SCHEMA',
|
|
14
21
|
MCP_SERVER_DISABLED: 'MCP_SERVER_DISABLED',
|
|
15
22
|
MCP_SERVER_NOT_FOUND: 'MCP_SERVER_NOT_FOUND',
|
|
16
23
|
MODEL_NOT_SUPPORTED_BY_HARNESS: 'MODEL_NOT_SUPPORTED_BY_HARNESS',
|
package/dist/harness/public.d.ts
CHANGED
|
@@ -51,4 +51,5 @@ export { lowerStreamInput, type InputMessagePart } from './stream-input.js';
|
|
|
51
51
|
export { GenSink } from './gen-sink.js';
|
|
52
52
|
export { matchesAlwaysActive, validateAlwaysActiveEntry, type AlwaysActiveEntry } from './always-active.js';
|
|
53
53
|
export { splitToolResultsIntoToolMessages, mergeToolResultsIntoAssistant } from './tool-message-normalizer.js';
|
|
54
|
+
export { validateToolArgs, validateToolSchemaCompiles, describeToolArgsFailure, recordToolArgsFailure, TOOL_ARGS_MAX_ATTEMPTS, type ValidateToolArgsResult, type ToolArgsSchemaViolation, } from './tool-args-validation.js';
|
|
54
55
|
export { resolveToolDeclineModelMessage } from './tool-decline.js';
|
package/dist/harness/public.js
CHANGED
|
@@ -10,5 +10,6 @@ export { lowerStreamInput } from './stream-input.js';
|
|
|
10
10
|
export { GenSink } from './gen-sink.js';
|
|
11
11
|
export { matchesAlwaysActive, validateAlwaysActiveEntry } from './always-active.js';
|
|
12
12
|
export { splitToolResultsIntoToolMessages, mergeToolResultsIntoAssistant } from './tool-message-normalizer.js';
|
|
13
|
+
export { validateToolArgs, validateToolSchemaCompiles, describeToolArgsFailure, recordToolArgsFailure, TOOL_ARGS_MAX_ATTEMPTS, } from './tool-args-validation.js';
|
|
13
14
|
export { resolveToolDeclineModelMessage } from './tool-decline.js';
|
|
14
15
|
//# sourceMappingURL=public.js.map
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single, shared retry cap for the consumer/frontend tool-args gate. Every
|
|
3
|
+
* harness bounds its per-tool-call retries against THIS constant so the
|
|
4
|
+
* exhaustion behavior — and the "will not be retried further after N failed
|
|
5
|
+
* attempts" wording {@link describeToolArgsFailure} builds — cannot drift
|
|
6
|
+
* between harnesses. Owning the cap here, next to the message that names it,
|
|
7
|
+
* keeps the two in lockstep (W-24023028 S2 — replaces the three per-harness
|
|
8
|
+
* literals that a future tune of one could have silently diverged).
|
|
9
|
+
*/
|
|
10
|
+
export declare const TOOL_ARGS_MAX_ATTEMPTS = 3;
|
|
11
|
+
/**
|
|
12
|
+
* Records one model-facing tool-args failure against a caller-owned,
|
|
13
|
+
* tool-NAME-keyed attempt counter and reports whether the retry cap is now
|
|
14
|
+
* reached. Every harness gates its consumer/frontend tool-args retries with an
|
|
15
|
+
* identical increment-then-compare against {@link TOOL_ARGS_MAX_ATTEMPTS}; this
|
|
16
|
+
* factors out that one shared computation so the three can't drift on it, while
|
|
17
|
+
* the storage stays caller-owned (the Mastra harness scopes its counter
|
|
18
|
+
* per-`(agentId, threadId)`; Claude/OpenAI scope theirs per-`stream()` adapter
|
|
19
|
+
* instance — the map's lifetime is the harness's concern, not this helper's).
|
|
20
|
+
* Keying by tool NAME (not `toolCallId`) is deliberate: each retry mints a fresh
|
|
21
|
+
* id, so a stable name is the only thing a streak can accumulate against.
|
|
22
|
+
* Callers reset a name's streak on a non-failure outcome via a plain
|
|
23
|
+
* `counts.delete(name)` — a one-liner not worth wrapping.
|
|
24
|
+
*/
|
|
25
|
+
export declare function recordToolArgsFailure(counts: Map<string, number>, toolName: string, maxAttempts?: number): {
|
|
26
|
+
attempt: number;
|
|
27
|
+
exhausted: boolean;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* One AJV validation failure, reduced to just the fields a model-visible
|
|
31
|
+
* message needs. AJV's own `ErrorObject` never leaks past this module.
|
|
32
|
+
*/
|
|
33
|
+
export type ToolArgsSchemaViolation = {
|
|
34
|
+
/** JSON-pointer-ish path to the offending field, e.g. `/city` or `/` (root). */
|
|
35
|
+
path: string;
|
|
36
|
+
/** AJV's human-readable message for this violation, e.g. "must be string". */
|
|
37
|
+
message: string;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Outcome of validating a raw tool-call argument buffer against a consumer
|
|
41
|
+
* tool's declared `inputSchema`.
|
|
42
|
+
*
|
|
43
|
+
* Two of these are model-facing failures the harness feeds back so the model
|
|
44
|
+
* can retry (`unparseable`, `schema`); the other two are not the model's fault
|
|
45
|
+
* and are never fed back (`ok` is success; `invalid-schema` is a consumer
|
|
46
|
+
* misconfiguration the gate fails *open* on — see {@link validateToolArgs}).
|
|
47
|
+
*/
|
|
48
|
+
export type ValidateToolArgsResult = {
|
|
49
|
+
outcome: 'ok';
|
|
50
|
+
args: Record<string, unknown>;
|
|
51
|
+
} | {
|
|
52
|
+
outcome: 'unparseable';
|
|
53
|
+
rawBuffer: string;
|
|
54
|
+
reason: 'not-json' | 'not-object';
|
|
55
|
+
} | {
|
|
56
|
+
outcome: 'schema';
|
|
57
|
+
args: Record<string, unknown>;
|
|
58
|
+
violations: ToolArgsSchemaViolation[];
|
|
59
|
+
} | {
|
|
60
|
+
outcome: 'invalid-schema';
|
|
61
|
+
args: Record<string, unknown>;
|
|
62
|
+
schemaError: string;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Validates a raw tool-call argument buffer (the string a model emitted for a
|
|
66
|
+
* consumer/frontend tool call) against that tool's declared `inputSchema`.
|
|
67
|
+
*
|
|
68
|
+
* One code path handles every shape a harness can hand it:
|
|
69
|
+
*
|
|
70
|
+
* 1. `null` / `undefined` / whitespace-only buffer coerces to `'{}'` before
|
|
71
|
+
* parsing — the ONLY special case, and it folds into the normal path rather
|
|
72
|
+
* than short-circuiting, so an empty buffer against a schema with no
|
|
73
|
+
* required fields still validates as `ok:{}`.
|
|
74
|
+
* 2. `JSON.parse` failure ⇒ `unparseable` / `not-json`; a successfully-parsed
|
|
75
|
+
* non-object (array, string, number, `null`) ⇒ `unparseable` / `not-object`.
|
|
76
|
+
* Both echo the *original*, uncoerced buffer so the caller's error message
|
|
77
|
+
* reflects what the model actually sent, and the `reason` lets the message
|
|
78
|
+
* distinguish "fix your JSON syntax" from "send a JSON object".
|
|
79
|
+
* 3. No `schema` declared ⇒ `ok`, the parsed object unvalidated.
|
|
80
|
+
* 4. Schema that will not compile (a consumer typo) ⇒ `invalid-schema`, failing
|
|
81
|
+
* OPEN: the parsed `args` are returned so the caller can let the call
|
|
82
|
+
* through, and `schemaError` lets the caller log the misconfiguration. The
|
|
83
|
+
* model is never told to fix a schema it did not author. (Registration-time
|
|
84
|
+
* validation via {@link validateToolSchemaCompiles} is the loud early
|
|
85
|
+
* signal; this is the safe runtime fallback so a bad schema degrades one
|
|
86
|
+
* tool to no-validation instead of throwing mid-turn — W-24023028 B1.)
|
|
87
|
+
* 5. Otherwise validated against the cached compiled schema ⇒ `ok` or `schema`.
|
|
88
|
+
*/
|
|
89
|
+
export declare function validateToolArgs(rawBuffer: string | null | undefined, schema: Record<string, unknown> | undefined): ValidateToolArgsResult;
|
|
90
|
+
/**
|
|
91
|
+
* Registration-time guard: reports whether a consumer tool's declared
|
|
92
|
+
* `inputSchema` compiles. Harnesses call this when an agent is created / updated
|
|
93
|
+
* so a schema typo fails loud at registration rather than lazily on the model's
|
|
94
|
+
* first call to that tool. Shares — and warms — the same compile cache
|
|
95
|
+
* {@link validateToolArgs} uses (W-24023028 B1).
|
|
96
|
+
*/
|
|
97
|
+
export declare function validateToolSchemaCompiles(schema: Record<string, unknown>): {
|
|
98
|
+
compilable: true;
|
|
99
|
+
} | {
|
|
100
|
+
compilable: false;
|
|
101
|
+
error: string;
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Builds the one canonical model-visible message per model-facing
|
|
105
|
+
* {@link ValidateToolArgsResult} failure kind, reused verbatim by every harness
|
|
106
|
+
* so the wording cannot drift between them.
|
|
107
|
+
*
|
|
108
|
+
* Only the two model-facing failures (`unparseable`, `schema`) have a message;
|
|
109
|
+
* `ok` and `invalid-schema` are never fed to the model, so calling this with
|
|
110
|
+
* either is a programmer error.
|
|
111
|
+
*
|
|
112
|
+
* `opts` pairs `exhausted` with `maxAttempts` as one optional unit (N1): the
|
|
113
|
+
* exhaustion clause interpolates the cap, so a caller cannot ask for the clause
|
|
114
|
+
* without supplying the number — the type makes an `…after undefined failed
|
|
115
|
+
* attempts.` message unconstructible rather than relying on every call site to
|
|
116
|
+
* remember to pass both.
|
|
117
|
+
*/
|
|
118
|
+
export declare function describeToolArgsFailure(toolName: string, result: ValidateToolArgsResult, opts?: {
|
|
119
|
+
exhausted: true;
|
|
120
|
+
maxAttempts: number;
|
|
121
|
+
}): string;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026, Salesforce, Inc. All rights reserved.
|
|
3
|
+
* See LICENSE.txt for license terms.
|
|
4
|
+
*/
|
|
5
|
+
import { getErrorMessage } from '@salesforce/agentic-common';
|
|
6
|
+
import { Ajv } from 'ajv';
|
|
7
|
+
/**
|
|
8
|
+
* The single, shared retry cap for the consumer/frontend tool-args gate. Every
|
|
9
|
+
* harness bounds its per-tool-call retries against THIS constant so the
|
|
10
|
+
* exhaustion behavior — and the "will not be retried further after N failed
|
|
11
|
+
* attempts" wording {@link describeToolArgsFailure} builds — cannot drift
|
|
12
|
+
* between harnesses. Owning the cap here, next to the message that names it,
|
|
13
|
+
* keeps the two in lockstep (W-24023028 S2 — replaces the three per-harness
|
|
14
|
+
* literals that a future tune of one could have silently diverged).
|
|
15
|
+
*/
|
|
16
|
+
export const TOOL_ARGS_MAX_ATTEMPTS = 3;
|
|
17
|
+
/**
|
|
18
|
+
* Records one model-facing tool-args failure against a caller-owned,
|
|
19
|
+
* tool-NAME-keyed attempt counter and reports whether the retry cap is now
|
|
20
|
+
* reached. Every harness gates its consumer/frontend tool-args retries with an
|
|
21
|
+
* identical increment-then-compare against {@link TOOL_ARGS_MAX_ATTEMPTS}; this
|
|
22
|
+
* factors out that one shared computation so the three can't drift on it, while
|
|
23
|
+
* the storage stays caller-owned (the Mastra harness scopes its counter
|
|
24
|
+
* per-`(agentId, threadId)`; Claude/OpenAI scope theirs per-`stream()` adapter
|
|
25
|
+
* instance — the map's lifetime is the harness's concern, not this helper's).
|
|
26
|
+
* Keying by tool NAME (not `toolCallId`) is deliberate: each retry mints a fresh
|
|
27
|
+
* id, so a stable name is the only thing a streak can accumulate against.
|
|
28
|
+
* Callers reset a name's streak on a non-failure outcome via a plain
|
|
29
|
+
* `counts.delete(name)` — a one-liner not worth wrapping.
|
|
30
|
+
*/
|
|
31
|
+
export function recordToolArgsFailure(counts, toolName, maxAttempts = TOOL_ARGS_MAX_ATTEMPTS) {
|
|
32
|
+
const attempt = (counts.get(toolName) ?? 0) + 1;
|
|
33
|
+
counts.set(toolName, attempt);
|
|
34
|
+
return { attempt, exhausted: attempt >= maxAttempts };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Compiled-validator cache keyed by schema object identity. Schema objects are
|
|
38
|
+
* stable for the lifetime of an `AgentConfig` until a consumer supplies a new
|
|
39
|
+
* one via `updateAgentConfig`, so a `WeakMap` gives free invalidation with no
|
|
40
|
+
* explicit clear path. A *failed* compile is cached too, so a malformed schema
|
|
41
|
+
* is compiled (and reported) exactly once rather than re-throwing on every
|
|
42
|
+
* retry (W-24023028 B1).
|
|
43
|
+
*/
|
|
44
|
+
const compiledCache = new WeakMap();
|
|
45
|
+
function compile(schema) {
|
|
46
|
+
const cached = compiledCache.get(schema);
|
|
47
|
+
if (cached) {
|
|
48
|
+
return cached;
|
|
49
|
+
}
|
|
50
|
+
let result;
|
|
51
|
+
try {
|
|
52
|
+
// `strict: false` — `inputSchema` is arbitrary consumer-declared JSON
|
|
53
|
+
// Schema, not a dialect this SDK controls. `allErrors: true` so a
|
|
54
|
+
// schema failure can name every offending field, not just the first.
|
|
55
|
+
const validate = new Ajv({ strict: false, allErrors: true }).compile(schema);
|
|
56
|
+
// AJV compiles an `$async: true` schema into a PROMISE-returning validator,
|
|
57
|
+
// not a boolean one — and `.compile()` does NOT throw for it. Our gate calls
|
|
58
|
+
// `validate(args)` synchronously: a returned Promise is always truthy, so a
|
|
59
|
+
// `$async` schema would silently pass EVERY payload as `'ok'` (validation
|
|
60
|
+
// bypass), and the promise it returns rejects unawaited — crashing the host
|
|
61
|
+
// with an unhandled rejection on the first invalid call. Treat an async
|
|
62
|
+
// schema as non-compilable so it degrades through the same fail-open
|
|
63
|
+
// (`'invalid-schema'`) runtime path and is rejected loud at registration by
|
|
64
|
+
// `validateToolSchemaCompiles`, exactly like a schema that won't compile.
|
|
65
|
+
result = validate.$async
|
|
66
|
+
? { error: 'async JSON Schema ($async: true) is not supported for tool inputSchema validation' }
|
|
67
|
+
: { validate };
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
// AJV throws synchronously on a malformed schema even with `strict:
|
|
71
|
+
// false` (a bad `type`, a non-object `properties`, an unresolvable
|
|
72
|
+
// `$ref`, a bad `pattern`, …). Capture the reason and cache it so the
|
|
73
|
+
// throw happens once, not on every model retry of that tool.
|
|
74
|
+
result = { error: getErrorMessage(error) };
|
|
75
|
+
}
|
|
76
|
+
compiledCache.set(schema, result);
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Validates a raw tool-call argument buffer (the string a model emitted for a
|
|
81
|
+
* consumer/frontend tool call) against that tool's declared `inputSchema`.
|
|
82
|
+
*
|
|
83
|
+
* One code path handles every shape a harness can hand it:
|
|
84
|
+
*
|
|
85
|
+
* 1. `null` / `undefined` / whitespace-only buffer coerces to `'{}'` before
|
|
86
|
+
* parsing — the ONLY special case, and it folds into the normal path rather
|
|
87
|
+
* than short-circuiting, so an empty buffer against a schema with no
|
|
88
|
+
* required fields still validates as `ok:{}`.
|
|
89
|
+
* 2. `JSON.parse` failure ⇒ `unparseable` / `not-json`; a successfully-parsed
|
|
90
|
+
* non-object (array, string, number, `null`) ⇒ `unparseable` / `not-object`.
|
|
91
|
+
* Both echo the *original*, uncoerced buffer so the caller's error message
|
|
92
|
+
* reflects what the model actually sent, and the `reason` lets the message
|
|
93
|
+
* distinguish "fix your JSON syntax" from "send a JSON object".
|
|
94
|
+
* 3. No `schema` declared ⇒ `ok`, the parsed object unvalidated.
|
|
95
|
+
* 4. Schema that will not compile (a consumer typo) ⇒ `invalid-schema`, failing
|
|
96
|
+
* OPEN: the parsed `args` are returned so the caller can let the call
|
|
97
|
+
* through, and `schemaError` lets the caller log the misconfiguration. The
|
|
98
|
+
* model is never told to fix a schema it did not author. (Registration-time
|
|
99
|
+
* validation via {@link validateToolSchemaCompiles} is the loud early
|
|
100
|
+
* signal; this is the safe runtime fallback so a bad schema degrades one
|
|
101
|
+
* tool to no-validation instead of throwing mid-turn — W-24023028 B1.)
|
|
102
|
+
* 5. Otherwise validated against the cached compiled schema ⇒ `ok` or `schema`.
|
|
103
|
+
*/
|
|
104
|
+
export function validateToolArgs(rawBuffer, schema) {
|
|
105
|
+
const original = rawBuffer ?? '';
|
|
106
|
+
const buffer = original.trim() === '' ? '{}' : original;
|
|
107
|
+
let parsed;
|
|
108
|
+
try {
|
|
109
|
+
parsed = JSON.parse(buffer);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return { outcome: 'unparseable', rawBuffer: original, reason: 'not-json' };
|
|
113
|
+
}
|
|
114
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
115
|
+
return { outcome: 'unparseable', rawBuffer: original, reason: 'not-object' };
|
|
116
|
+
}
|
|
117
|
+
const args = parsed;
|
|
118
|
+
if (!schema) {
|
|
119
|
+
return { outcome: 'ok', args };
|
|
120
|
+
}
|
|
121
|
+
const compiled = compile(schema);
|
|
122
|
+
if ('error' in compiled) {
|
|
123
|
+
return { outcome: 'invalid-schema', args, schemaError: compiled.error };
|
|
124
|
+
}
|
|
125
|
+
if (compiled.validate(args)) {
|
|
126
|
+
return { outcome: 'ok', args };
|
|
127
|
+
}
|
|
128
|
+
const violations = (compiled.validate.errors ?? []).map((error) => ({
|
|
129
|
+
path: error.instancePath || '/',
|
|
130
|
+
message: error.message ?? 'does not match schema',
|
|
131
|
+
}));
|
|
132
|
+
return { outcome: 'schema', args, violations };
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Registration-time guard: reports whether a consumer tool's declared
|
|
136
|
+
* `inputSchema` compiles. Harnesses call this when an agent is created / updated
|
|
137
|
+
* so a schema typo fails loud at registration rather than lazily on the model's
|
|
138
|
+
* first call to that tool. Shares — and warms — the same compile cache
|
|
139
|
+
* {@link validateToolArgs} uses (W-24023028 B1).
|
|
140
|
+
*/
|
|
141
|
+
export function validateToolSchemaCompiles(schema) {
|
|
142
|
+
const compiled = compile(schema);
|
|
143
|
+
return 'error' in compiled ? { compilable: false, error: compiled.error } : { compilable: true };
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Builds the one canonical model-visible message per model-facing
|
|
147
|
+
* {@link ValidateToolArgsResult} failure kind, reused verbatim by every harness
|
|
148
|
+
* so the wording cannot drift between them.
|
|
149
|
+
*
|
|
150
|
+
* Only the two model-facing failures (`unparseable`, `schema`) have a message;
|
|
151
|
+
* `ok` and `invalid-schema` are never fed to the model, so calling this with
|
|
152
|
+
* either is a programmer error.
|
|
153
|
+
*
|
|
154
|
+
* `opts` pairs `exhausted` with `maxAttempts` as one optional unit (N1): the
|
|
155
|
+
* exhaustion clause interpolates the cap, so a caller cannot ask for the clause
|
|
156
|
+
* without supplying the number — the type makes an `…after undefined failed
|
|
157
|
+
* attempts.` message unconstructible rather than relying on every call site to
|
|
158
|
+
* remember to pass both.
|
|
159
|
+
*/
|
|
160
|
+
export function describeToolArgsFailure(toolName, result, opts) {
|
|
161
|
+
let message;
|
|
162
|
+
if (result.outcome === 'unparseable') {
|
|
163
|
+
message =
|
|
164
|
+
result.reason === 'not-object'
|
|
165
|
+
? `Invalid arguments for tool "${toolName}": arguments must be a JSON object.`
|
|
166
|
+
: `Invalid JSON in arguments for tool "${toolName}": the arguments were not valid JSON.`;
|
|
167
|
+
}
|
|
168
|
+
else if (result.outcome === 'schema') {
|
|
169
|
+
const clauses = result.violations.map((v) => `at "${v.path}", ${v.message}`).join('; ');
|
|
170
|
+
message = `Arguments for tool "${toolName}" do not match its schema: ${clauses}`;
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
throw new Error(`describeToolArgsFailure called with a non-failure outcome: "${result.outcome}"`);
|
|
174
|
+
}
|
|
175
|
+
if (opts?.exhausted) {
|
|
176
|
+
message += ` This tool call will not be retried further after ${opts.maxAttempts} failed attempts.`;
|
|
177
|
+
}
|
|
178
|
+
return message;
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=tool-args-validation.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AgentConfig } from '../harness/harness-config.js';
|
|
2
|
+
/**
|
|
3
|
+
* Registration-time guard (W-24023028 B1): asserts that every consumer-declared
|
|
4
|
+
* `AgentConfig.tools[i].inputSchema` compiles, throwing
|
|
5
|
+
* `AgentSDKError(INVALID_TOOL_SCHEMA)` on the first that does not. Called at
|
|
6
|
+
* `createAgent` / `updateAgentConfig` so a schema typo fails loud at
|
|
7
|
+
* registration rather than surfacing lazily — and fail-open — on the model's
|
|
8
|
+
* first call to that tool. This is the cross-harness, single-site complement to
|
|
9
|
+
* the runtime gate's fail-open `'invalid-schema'` outcome: normally a bad schema
|
|
10
|
+
* is caught here; if one ever slips to runtime the gate degrades that one tool
|
|
11
|
+
* to no-validation instead of terminating the turn.
|
|
12
|
+
*
|
|
13
|
+
* It is deliberately NOT called on the boot-restore path — a bad schema
|
|
14
|
+
* persisted before this guard shipped should degrade to fail-open at runtime,
|
|
15
|
+
* not brick the agent on every reboot.
|
|
16
|
+
*/
|
|
17
|
+
export declare function assertToolSchemasCompile(config: Pick<AgentConfig, 'tools'>): void;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026, Salesforce, Inc. All rights reserved.
|
|
3
|
+
* See LICENSE.txt for license terms.
|
|
4
|
+
*/
|
|
5
|
+
import { AgentSDKError, AgentSDKErrorType } from '../errors.js';
|
|
6
|
+
import { validateToolSchemaCompiles } from '../harness/tool-args-validation.js';
|
|
7
|
+
/**
|
|
8
|
+
* Registration-time guard (W-24023028 B1): asserts that every consumer-declared
|
|
9
|
+
* `AgentConfig.tools[i].inputSchema` compiles, throwing
|
|
10
|
+
* `AgentSDKError(INVALID_TOOL_SCHEMA)` on the first that does not. Called at
|
|
11
|
+
* `createAgent` / `updateAgentConfig` so a schema typo fails loud at
|
|
12
|
+
* registration rather than surfacing lazily — and fail-open — on the model's
|
|
13
|
+
* first call to that tool. This is the cross-harness, single-site complement to
|
|
14
|
+
* the runtime gate's fail-open `'invalid-schema'` outcome: normally a bad schema
|
|
15
|
+
* is caught here; if one ever slips to runtime the gate degrades that one tool
|
|
16
|
+
* to no-validation instead of terminating the turn.
|
|
17
|
+
*
|
|
18
|
+
* It is deliberately NOT called on the boot-restore path — a bad schema
|
|
19
|
+
* persisted before this guard shipped should degrade to fail-open at runtime,
|
|
20
|
+
* not brick the agent on every reboot.
|
|
21
|
+
*/
|
|
22
|
+
export function assertToolSchemasCompile(config) {
|
|
23
|
+
for (const tool of config.tools ?? []) {
|
|
24
|
+
const result = validateToolSchemaCompiles(tool.inputSchema);
|
|
25
|
+
if (!result.compilable) {
|
|
26
|
+
throw new AgentSDKError(`Tool "${tool.name}" declares an inputSchema that does not compile: ${result.error}`, AgentSDKErrorType.INVALID_TOOL_SCHEMA);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=tool-schema-registration.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/sfdx-agent-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.73.0",
|
|
4
4
|
"description": "Harness-agnostic agentic infrastructure for Salesforce developer experience tooling",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -43,13 +43,14 @@
|
|
|
43
43
|
"LICENSE.txt"
|
|
44
44
|
],
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@salesforce/agentic-common": "0.19.0"
|
|
46
|
+
"@salesforce/agentic-common": "0.19.0",
|
|
47
|
+
"ajv": "^8.20.0"
|
|
47
48
|
},
|
|
48
49
|
"devDependencies": {
|
|
49
50
|
"@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.
|
|
51
|
+
"@salesforce/sfdx-agent-harness-claude": "0.69.0",
|
|
52
|
+
"@salesforce/sfdx-agent-harness-mastra": "0.72.0",
|
|
53
|
+
"@salesforce/sfdx-agent-harness-openai": "0.38.0",
|
|
53
54
|
"@types/node": "^22.20.1",
|
|
54
55
|
"@vitest/coverage-istanbul": "^4.1.11",
|
|
55
56
|
"@vitest/eslint-plugin": "^1.6.27",
|