@salesforce/sfdx-agent-harness-claude 0.17.0 → 0.19.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 +15 -0
- package/README.md +54 -80
- package/dist/claude-harness-factory.d.ts +9 -3
- package/dist/claude-harness-factory.js +17 -2
- package/dist/claude-harness-factory.js.map +1 -1
- package/dist/claude-harness.d.ts +57 -5
- package/dist/claude-harness.js +135 -21
- package/dist/claude-harness.js.map +1 -1
- package/dist/claude-query-env-builder.d.ts +22 -7
- package/dist/claude-query-env-builder.js +116 -9
- package/dist/claude-query-env-builder.js.map +1 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp-client-factory.d.ts +9 -2
- package/dist/mcp-client-factory.js +13 -6
- package/dist/mcp-client-factory.js.map +1 -1
- package/dist/test/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -9
- package/dist/claude-transport-resolver.d.ts +0 -21
- package/dist/claude-transport-resolver.js +0 -6
- package/dist/claude-transport-resolver.js.map +0 -1
- package/dist/direct-claude-transport-resolver.d.ts +0 -13
- package/dist/direct-claude-transport-resolver.js +0 -23
- package/dist/direct-claude-transport-resolver.js.map +0 -1
- package/dist/salesforce-bedrock-transport-resolver.d.ts +0 -104
- package/dist/salesforce-bedrock-transport-resolver.js +0 -74
- package/dist/salesforce-bedrock-transport-resolver.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,21 @@
|
|
|
3
3
|
All notable changes to `@salesforce/sfdx-agent-harness-claude` are documented in this file.
|
|
4
4
|
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
5
5
|
|
|
6
|
+
## [0.19.0] - 2026-06-22
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
- **agentic-common,harnesses**: route HTTPS_PROXY via injectable undici Dispatcher @W-23121596 ([#610](https://github.com/forcedotcom/agentic-dx/pull/610))
|
|
10
|
+
|
|
11
|
+
## [0.18.0] - 2026-06-19
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
- **BREAKING** Major refactor to Unify Connectivity via ModelConnectivityInfo @W-22782317 ([#607](https://github.com/forcedotcom/agentic-dx/pull/607))
|
|
15
|
+
|
|
16
|
+
### Chores
|
|
17
|
+
- **deps-dev**: bump @vitest/eslint-plugin from 1.6.19 to 1.6.20 in the vitest group across 1 directory ([#601](https://github.com/forcedotcom/agentic-dx/pull/601))
|
|
18
|
+
- **deps-dev**: bump eslint from 10.4.1 to 10.5.0 in the eslint group across 1 directory ([#600](https://github.com/forcedotcom/agentic-dx/pull/600))
|
|
19
|
+
- **deps-dev**: bump @types/node from 22.19.20 to 22.19.21 in the dev-dependencies group ([#599](https://github.com/forcedotcom/agentic-dx/pull/599))
|
|
20
|
+
|
|
6
21
|
## [0.17.0] - 2026-06-15
|
|
7
22
|
|
|
8
23
|
### Fixes
|
package/README.md
CHANGED
|
@@ -15,37 +15,39 @@ npm install @salesforce/sfdx-agent-sdk @salesforce/sfdx-agent-harness-claude
|
|
|
15
15
|
## Quick start
|
|
16
16
|
|
|
17
17
|
```ts
|
|
18
|
-
import { createAgentManager } from '@salesforce/sfdx-agent-sdk';
|
|
19
|
-
import { ClaudeHarnessFactory
|
|
18
|
+
import { createAgentManager, DefaultAgentConnectivityResolver } from '@salesforce/sfdx-agent-sdk';
|
|
19
|
+
import { ClaudeHarnessFactory } from '@salesforce/sfdx-agent-harness-claude';
|
|
20
20
|
|
|
21
21
|
const harnessFactory = new ClaudeHarnessFactory({
|
|
22
|
-
resolver: new DirectClaudeTransportResolver(() => process.env.ANTHROPIC_API_KEY!),
|
|
23
22
|
permissionMode: 'bypassPermissions',
|
|
24
23
|
});
|
|
25
24
|
|
|
26
|
-
const manager = await createAgentManager('/path/to/storage', harnessFactory
|
|
25
|
+
const manager = await createAgentManager('/path/to/storage', harnessFactory, {
|
|
26
|
+
connectivityResolver: new DefaultAgentConnectivityResolver(),
|
|
27
|
+
});
|
|
27
28
|
```
|
|
28
29
|
|
|
30
|
+
Connectivity (gateway URL, JWT, headers, native model id) is resolved by an `AgentConnectivityResolver` on the SDK and
|
|
31
|
+
handed to the harness as a `ModelConnectivityInfo` bag. The harness factory itself owns harness-only concerns
|
|
32
|
+
(permission mode, tool-approval timeout, bypass list, query defaults). For BYOK / direct-Anthropic / LLMG-Express
|
|
33
|
+
deployments use `ApiKeyConnectivityResolver`; for non-Salesforce hosts implement your own resolver. See the
|
|
34
|
+
[`@salesforce/sfdx-agent-sdk` README](../sfdx-agent-sdk/README.md) for the full resolver surface.
|
|
35
|
+
|
|
29
36
|
See the [`@salesforce/sfdx-agent-sdk` README](../sfdx-agent-sdk/README.md) for the full consumer-facing API. For
|
|
30
37
|
internal architecture, see [ARCHITECTURE.md](ARCHITECTURE.md).
|
|
31
38
|
|
|
32
39
|
## Public API
|
|
33
40
|
|
|
34
|
-
| Export
|
|
35
|
-
|
|
|
36
|
-
| `ClaudeHarnessFactory`
|
|
37
|
-
| `ClaudeHarnessFactoryConfig`
|
|
38
|
-
| `ClaudeHarnessPermissionMode`
|
|
39
|
-
| `ClaudeAgentHarness`
|
|
40
|
-
| `ClaudeAgentConfig`
|
|
41
|
-
| `ClaudeSkillSearchConfig`
|
|
42
|
-
| `ClaudeToolSearchConfig`
|
|
43
|
-
| `
|
|
44
|
-
| `ClaudeTransportResolverResult` | type | Return type of `ClaudeTransportResolver.resolve()` (`env` + `nativeModelId`). |
|
|
45
|
-
| `ClaudeQueryDefaults` | type | Consumer-overridable defaults for the Claude `query()` call (excludes `model`). |
|
|
46
|
-
| `DirectClaudeTransportResolver` | class | Resolver for direct Anthropic API access (sets `ANTHROPIC_API_KEY`). Suitable for local dev with a personal API key; not the production path. |
|
|
47
|
-
| `SalesforceBedrockClaudeTransportResolver` | class | Resolver that routes the Claude subprocess through the Salesforce LLM Gateway's Bedrock proxy. Canonical production path for Salesforce developer-tooling consumers. |
|
|
48
|
-
| `SalesforceBedrockClaudeTransportResolverConfig` | interface | Configuration for `SalesforceBedrockClaudeTransportResolver` (`gatewayBaseUrl`, optional `modelIdMap`, `appContext`, `featureId`, `ideContext`). |
|
|
41
|
+
| Export | Kind | Description |
|
|
42
|
+
| ----------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
43
|
+
| `ClaudeHarnessFactory` | class | `HarnessFactory` that produces a Claude-backed `AgentHarness` bound to a storage root. |
|
|
44
|
+
| `ClaudeHarnessFactoryConfig` | interface | Configuration for `ClaudeHarnessFactory` (`permissionMode`, optional `queryDefaults`, `toolApprovalTimeoutMs`, `bypassApprovalTools`, `dispatcher`). |
|
|
45
|
+
| `ClaudeHarnessPermissionMode` | type | Narrowed permission mode: `'bypassPermissions' \| 'acceptEdits' \| 'plan'`. |
|
|
46
|
+
| `ClaudeAgentHarness` | type | Branded `AgentHarness` subtype carrying the Claude-specific config inference. Inferred at `manager.createAgent` automatically — annotation rarely needed. |
|
|
47
|
+
| `ClaudeAgentConfig` | type | `AgentConfig` extended with Claude-only fields (`skillSearch`, `toolSearch`). |
|
|
48
|
+
| `ClaudeSkillSearchConfig` | type | Shape of `ClaudeAgentConfig.skillSearch` (`topK`). Opts the in-process `skill_bridge` MCP server into search-on-demand mode. |
|
|
49
|
+
| `ClaudeToolSearchConfig` | type | Shape of `ClaudeAgentConfig.toolSearch` (`alwaysActive`). Stamps `_meta['anthropic/alwaysLoad']` on matching tools so they bypass Claude tool-search deferral. |
|
|
50
|
+
| `ClaudeQueryDefaults` | type | Consumer-overridable defaults for the Claude `query()` call (excludes `model`). |
|
|
49
51
|
|
|
50
52
|
### Permission modes
|
|
51
53
|
|
|
@@ -61,6 +63,19 @@ provide. For human-in-the-loop gating, set `StreamOptions.requireToolApproval: t
|
|
|
61
63
|
installs a `PreToolUse` SDK hook for that turn that gates every tool call through the SDK's `tool-approval-request` flow
|
|
62
64
|
regardless of the factory-pinned permission mode.
|
|
63
65
|
|
|
66
|
+
### HTTPS proxy routing
|
|
67
|
+
|
|
68
|
+
The harness honors `HTTPS_PROXY` / `HTTP_PROXY` / `NO_PROXY` (either casing) for the host-side MCP HTTP transport via
|
|
69
|
+
`@salesforce/agentic-common`'s `resolveProxyDispatcher()`. When either proxy var is set at factory `create()` time, the
|
|
70
|
+
harness wraps the transport `fetch` with an undici-backed routing function — no `globalThis` mutation. When no proxy
|
|
71
|
+
env is set, `fetch` runs unwrapped (zero overhead).
|
|
72
|
+
|
|
73
|
+
The Claude subprocess inherits `HTTPS_PROXY` from the host env separately and is unaffected by the host-side wrapping.
|
|
74
|
+
Subprocess-side proxy routing follows whatever env was set when the subprocess spawned.
|
|
75
|
+
|
|
76
|
+
**Snapshot timing.** `HTTPS_PROXY` / `HTTP_PROXY` are captured at `create()` time and pinned for the harness's lifetime;
|
|
77
|
+
`NO_PROXY` is re-evaluated per request. Set the proxy env vars before constructing the factory's first harness.
|
|
78
|
+
|
|
64
79
|
### Skill search
|
|
65
80
|
|
|
66
81
|
`AgentConfig.skills` is a cross-harness field; both Mastra and Claude surface configured skills to the model. By default
|
|
@@ -201,65 +216,25 @@ afterwards.
|
|
|
201
216
|
> (which `break` does inside `for await`) finalizes the harness's source generator before the terminal event can reach
|
|
202
217
|
> you. Settle in-line and keep iterating; the loop exits naturally when the terminal `finish` arrives.
|
|
203
218
|
|
|
204
|
-
###
|
|
219
|
+
### Connectivity (gateway URL, auth, native model id)
|
|
205
220
|
|
|
206
|
-
The
|
|
207
|
-
|
|
221
|
+
The Claude harness reads connectivity per-spawn from a `ModelConnectivityInfo` bag the SDK hands it. The bag carries the
|
|
222
|
+
gateway base URL, the native model id (e.g. `anthropic.claude-sonnet-4-6`), the provider hint (`bedrock-anthropic` or
|
|
223
|
+
`anthropic`), and a `getHeaders()` callback the harness invokes once per subprocess spawn. JWT rotation rides on that
|
|
224
|
+
callback — the next `stream()` call reads the rotated JWT through the same closure without rebuilding anything.
|
|
208
225
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
import { ClaudeHarnessFactory, SalesforceBedrockClaudeTransportResolver } from '@salesforce/sfdx-agent-harness-claude';
|
|
226
|
+
The SDK ships two bundled resolvers and a documented extension point — see the
|
|
227
|
+
[`@salesforce/sfdx-agent-sdk` README](../sfdx-agent-sdk/README.md):
|
|
212
228
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
// every Anthropic Claude model, and the SDK's `Model.name` is already that
|
|
220
|
-
// canonical id, so the resolver's default passthrough is correct. Set the
|
|
221
|
-
// map only if your consumer needs to translate to a different shape (e.g.
|
|
222
|
-
// a self-hosted Bedrock proxy that expects the bare-native ids).
|
|
223
|
-
// Optional: override the `x-client-feature-id` header. Defaults to `orgJwt.getFeatureId()`.
|
|
224
|
-
featureId: 'EinsteinGptForDevelopers',
|
|
225
|
-
// Optional: getter for the `x-aip-user-ctx-tag` header. Invoked on every `resolve()`;
|
|
226
|
-
// returning `undefined` (or omitting the option) drops the header. Use when the tag is
|
|
227
|
-
// derived from post-JWT-mint state that changes between turns.
|
|
228
|
-
ideContext: () => orgEntitlement.ideUserContext,
|
|
229
|
-
}),
|
|
230
|
-
permissionMode: 'bypassPermissions',
|
|
231
|
-
});
|
|
229
|
+
- **`DefaultAgentConnectivityResolver`** — Salesforce-org gateway path. Targets the LLM Gateway's pass-through Bedrock
|
|
230
|
+
endpoint (`/invoke-with-response-stream`) using an org JWT.
|
|
231
|
+
- **`ApiKeyConnectivityResolver`** — direct-Anthropic / OpenAI-direct / LLMG-Express. Constructor takes
|
|
232
|
+
`{ getApiKey, baseUrl, providerHint, ... }`.
|
|
233
|
+
- **Custom `AgentConnectivityResolver`** — for deployments neither bundled resolver covers, implement the SDK's
|
|
234
|
+
`AgentConnectivityResolver` interface and pass it to `createAgentManager({ ..., connectivityResolver })`.
|
|
232
235
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
JWT refresh works the same as elsewhere in the harness: each `resolve()` call eagerly reads `orgJwt.getValue()` /
|
|
237
|
-
`orgJwt.getTenantKey()` and freezes the result into the static subprocess headers. `Agent.updateAgentConfig({})` runs
|
|
238
|
-
`harness.updateAgent`, the resolver re-reads the fresh JWT on the next `stream()`, and the next subprocess spawns with
|
|
239
|
-
the new headers — connected MCP clients are preserved through the rotation.
|
|
240
|
-
|
|
241
|
-
### Using a custom resolver
|
|
242
|
-
|
|
243
|
-
For deployment topologies neither built-in resolver covers (alternative gateways, custom auth flows, etc.), implement
|
|
244
|
-
the `ClaudeTransportResolver` interface directly.
|
|
245
|
-
|
|
246
|
-
```ts
|
|
247
|
-
import { createAgentManager } from '@salesforce/sfdx-agent-sdk';
|
|
248
|
-
import { ClaudeHarnessFactory } from '@salesforce/sfdx-agent-harness-claude';
|
|
249
|
-
import type { ClaudeTransportResolver } from '@salesforce/sfdx-agent-harness-claude';
|
|
250
|
-
|
|
251
|
-
const resolver: ClaudeTransportResolver = {
|
|
252
|
-
async resolve(orgJwt, modelId) {
|
|
253
|
-
return {
|
|
254
|
-
env: { ANTHROPIC_API_KEY: '...' },
|
|
255
|
-
nativeModelId: 'anthropic.claude-sonnet-4-6',
|
|
256
|
-
};
|
|
257
|
-
},
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
const harnessFactory = new ClaudeHarnessFactory({ resolver, permissionMode: 'bypassPermissions' });
|
|
261
|
-
const manager = await createAgentManager('/path/to/storage', harnessFactory);
|
|
262
|
-
```
|
|
236
|
+
The harness factory itself takes no resolver, gateway URL, or auth field — those concerns live entirely on the
|
|
237
|
+
connectivity resolver.
|
|
263
238
|
|
|
264
239
|
### Per-server MCP reconnect (eager semantics)
|
|
265
240
|
|
|
@@ -287,7 +262,6 @@ reject.
|
|
|
287
262
|
|
|
288
263
|
```ts
|
|
289
264
|
const harnessFactory = new ClaudeHarnessFactory({
|
|
290
|
-
resolver: new DirectClaudeTransportResolver(() => process.env.ANTHROPIC_API_KEY!),
|
|
291
265
|
permissionMode: 'bypassPermissions',
|
|
292
266
|
queryDefaults: {
|
|
293
267
|
maxTurns: 5,
|
|
@@ -307,11 +281,10 @@ across harnesses.
|
|
|
307
281
|
`ClaudeQueryDefaults` does not strip). It blocks the model from emitting `tool_use` for the named built-ins entirely.
|
|
308
282
|
|
|
309
283
|
```ts
|
|
310
|
-
import { createAgentManager } from '@salesforce/sfdx-agent-sdk';
|
|
311
|
-
import { ClaudeHarnessFactory
|
|
284
|
+
import { createAgentManager, DefaultAgentConnectivityResolver } from '@salesforce/sfdx-agent-sdk';
|
|
285
|
+
import { ClaudeHarnessFactory } from '@salesforce/sfdx-agent-harness-claude';
|
|
312
286
|
|
|
313
287
|
const harnessFactory = new ClaudeHarnessFactory({
|
|
314
|
-
resolver: new SalesforceBedrockClaudeTransportResolver({ gatewayBaseUrl: '...' }),
|
|
315
288
|
permissionMode: 'bypassPermissions',
|
|
316
289
|
// Suppress the built-in `AskUserQuestion` so the cross-harness consumer
|
|
317
290
|
// tool below is the only ask-the-user surface the model sees on Claude
|
|
@@ -321,7 +294,9 @@ const harnessFactory = new ClaudeHarnessFactory({
|
|
|
321
294
|
},
|
|
322
295
|
});
|
|
323
296
|
|
|
324
|
-
const manager = await createAgentManager('/path/to/storage', harnessFactory
|
|
297
|
+
const manager = await createAgentManager('/path/to/storage', harnessFactory, {
|
|
298
|
+
connectivityResolver: new DefaultAgentConnectivityResolver(),
|
|
299
|
+
});
|
|
325
300
|
const agent = await manager.createAgent(projectRoot, {
|
|
326
301
|
instructions: '...',
|
|
327
302
|
tools: [
|
|
@@ -360,7 +335,6 @@ additional tool names out of the gate.
|
|
|
360
335
|
|
|
361
336
|
```ts
|
|
362
337
|
const harnessFactory = new ClaudeHarnessFactory({
|
|
363
|
-
resolver: new SalesforceBedrockClaudeTransportResolver({ gatewayBaseUrl: '...' }),
|
|
364
338
|
permissionMode: 'bypassPermissions',
|
|
365
339
|
// Even when `requireToolApproval: true`, calls to these tools bypass the
|
|
366
340
|
// PreToolUse hook. They still emit `tool-call` / `tool-result` ChatEvents,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { HarnessFactory } from '@salesforce/sfdx-agent-sdk';
|
|
2
|
-
import type { ClaudeTransportResolver } from './claude-transport-resolver.js';
|
|
1
|
+
import type { HarnessFactory, ProviderHint } from '@salesforce/sfdx-agent-sdk';
|
|
3
2
|
import type { ClaudeQueryDefaults } from './claude-query-options-builder.js';
|
|
4
3
|
import { type ClaudeAgentHarness } from './claude-harness.js';
|
|
5
4
|
/**
|
|
@@ -13,7 +12,6 @@ import { type ClaudeAgentHarness } from './claude-harness.js';
|
|
|
13
12
|
*/
|
|
14
13
|
export type ClaudeHarnessPermissionMode = 'bypassPermissions' | 'acceptEdits' | 'plan';
|
|
15
14
|
export interface ClaudeHarnessFactoryConfig {
|
|
16
|
-
resolver: ClaudeTransportResolver;
|
|
17
15
|
permissionMode: ClaudeHarnessPermissionMode;
|
|
18
16
|
queryDefaults?: ClaudeQueryDefaults;
|
|
19
17
|
/**
|
|
@@ -42,6 +40,14 @@ export declare class ClaudeHarnessFactory implements HarnessFactory<ClaudeAgentH
|
|
|
42
40
|
private readonly config;
|
|
43
41
|
readonly harnessId = "claude";
|
|
44
42
|
readonly protocolVersion = 1;
|
|
43
|
+
/**
|
|
44
|
+
* The Claude CLI binary speaks Anthropic-shaped protocols only — both the
|
|
45
|
+
* Bedrock pass-through (`'bedrock-anthropic'`) and direct Anthropic API
|
|
46
|
+
* (`'anthropic'`). Routing it at a non-Anthropic model is a programming
|
|
47
|
+
* error caught at `createAgent` / `updateAgentConfig` by the manager's
|
|
48
|
+
* G8 validation.
|
|
49
|
+
*/
|
|
50
|
+
readonly supportedProviderHints: readonly ProviderHint[];
|
|
45
51
|
constructor(config: ClaudeHarnessFactoryConfig);
|
|
46
52
|
create(storageRootFolder: string): Promise<ClaudeAgentHarness>;
|
|
47
53
|
}
|
|
@@ -2,19 +2,30 @@
|
|
|
2
2
|
* Copyright 2026, Salesforce, Inc. All rights reserved.
|
|
3
3
|
* See LICENSE.txt for license terms.
|
|
4
4
|
*/
|
|
5
|
+
import { createProxyAwareFetch, resolveProxyDispatcher } from '@salesforce/agentic-common';
|
|
5
6
|
import { ClaudeQueryEnvBuilder } from './claude-query-env-builder.js';
|
|
6
7
|
import { ClaudeQueryOptionsBuilder } from './claude-query-options-builder.js';
|
|
7
8
|
import { ClaudeHarness } from './claude-harness.js';
|
|
9
|
+
import { buildMcpClients } from './mcp-client-factory.js';
|
|
8
10
|
const DEFAULT_TOOL_APPROVAL_TIMEOUT_MS = 600_000;
|
|
9
11
|
export class ClaudeHarnessFactory {
|
|
10
12
|
config;
|
|
11
13
|
harnessId = 'claude';
|
|
12
14
|
protocolVersion = 1;
|
|
15
|
+
/**
|
|
16
|
+
* The Claude CLI binary speaks Anthropic-shaped protocols only — both the
|
|
17
|
+
* Bedrock pass-through (`'bedrock-anthropic'`) and direct Anthropic API
|
|
18
|
+
* (`'anthropic'`). Routing it at a non-Anthropic model is a programming
|
|
19
|
+
* error caught at `createAgent` / `updateAgentConfig` by the manager's
|
|
20
|
+
* G8 validation.
|
|
21
|
+
*/
|
|
22
|
+
supportedProviderHints = ['anthropic', 'bedrock-anthropic'];
|
|
13
23
|
constructor(config) {
|
|
14
24
|
this.config = config;
|
|
15
25
|
}
|
|
16
26
|
async create(storageRootFolder) {
|
|
17
|
-
const
|
|
27
|
+
const innerFetch = createProxyAwareFetch(resolveProxyDispatcher());
|
|
28
|
+
const envBuilder = new ClaudeQueryEnvBuilder(storageRootFolder);
|
|
18
29
|
const permissionDefaults = {
|
|
19
30
|
permissionMode: this.config.permissionMode,
|
|
20
31
|
...(this.config.permissionMode === 'bypassPermissions'
|
|
@@ -27,7 +38,11 @@ export class ClaudeHarnessFactory {
|
|
|
27
38
|
// under issue #529 — every event flows through the single
|
|
28
39
|
// `initial` sink.
|
|
29
40
|
const optionsBuilder = new ClaudeQueryOptionsBuilder({ ...permissionDefaults, ...this.config.queryDefaults }, new Set(this.config.bypassApprovalTools ?? []));
|
|
30
|
-
|
|
41
|
+
// Bind `innerFetch` into the mcp-client factory closure so every
|
|
42
|
+
// call site inside `ClaudeHarness` (createAgent, reconnect, updateAgent)
|
|
43
|
+
// routes MCP HTTP transports through the same proxy-aware fetch.
|
|
44
|
+
const mcpClientFactory = (config, orgJwt) => buildMcpClients(config, orgJwt, innerFetch);
|
|
45
|
+
return new ClaudeHarness(envBuilder, optionsBuilder, this.config.toolApprovalTimeoutMs ?? DEFAULT_TOOL_APPROVAL_TIMEOUT_MS, storageRootFolder, { mcpClientFactory });
|
|
31
46
|
}
|
|
32
47
|
}
|
|
33
48
|
//# sourceMappingURL=claude-harness-factory.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-harness-factory.js","sourceRoot":"","sources":["../src/claude-harness-factory.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"claude-harness-factory.js","sourceRoot":"","sources":["../src/claude-harness-factory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAG3F,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,aAAa,EAA2B,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAa1D,MAAM,gCAAgC,GAAG,OAAO,CAAC;AA4BjD,MAAM,OAAO,oBAAoB;IAYA;IAXpB,SAAS,GAAG,QAAQ,CAAC;IACrB,eAAe,GAAG,CAAC,CAAC;IAC7B;;;;;;OAMG;IACM,sBAAsB,GAA4B,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;IAE9F,YAA6B,MAAkC;QAAlC,WAAM,GAAN,MAAM,CAA4B;IAAG,CAAC;IAEnE,KAAK,CAAC,MAAM,CAAC,iBAAyB;QAClC,MAAM,UAAU,GAAG,qBAAqB,CAAC,sBAAsB,EAAE,CAAC,CAAC;QACnE,MAAM,UAAU,GAAG,IAAI,qBAAqB,CAAC,iBAAiB,CAAC,CAAC;QAChE,MAAM,kBAAkB,GAAG;YACvB,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,cAAc;YAC1C,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,KAAK,mBAAmB;gBAClD,CAAC,CAAC,EAAE,+BAA+B,EAAE,IAAa,EAAE;gBACpD,CAAC,CAAC,EAAE,CAAC;SACZ,CAAC;QACF,iEAAiE;QACjE,iEAAiE;QACjE,iEAAiE;QACjE,0DAA0D;QAC1D,kBAAkB;QAClB,MAAM,cAAc,GAAG,IAAI,yBAAyB,CAChD,EAAE,GAAG,kBAAkB,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,EACvD,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,mBAAmB,IAAI,EAAE,CAAC,CACjD,CAAC;QACF,iEAAiE;QACjE,yEAAyE;QACzE,iEAAiE;QACjE,MAAM,gBAAgB,GAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAChE,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;QAChD,OAAO,IAAI,aAAa,CACpB,UAAU,EACV,cAAc,EACd,IAAI,CAAC,MAAM,CAAC,qBAAqB,IAAI,gCAAgC,EACrE,iBAAiB,EACjB,EAAE,gBAAgB,EAAE,CACvB,CAAC;IACN,CAAC;CACJ"}
|
package/dist/claude-harness.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { type Clock, type LogRecord, type UniqueIDGenerator, type Unsubscribe } from '@salesforce/agentic-common';
|
|
2
|
-
import { type AgentHarness, type ChatStreamResult, type HarnessAgentConfig, type McpServerInfo, type Message, type MessagePart, type StreamOptions, type TelemetryEventCallback, type ToolResultInfo } from '@salesforce/sfdx-agent-sdk';
|
|
2
|
+
import { type AgentHarness, type ChatStreamResult, type HarnessAgentConfig, type McpServerInfo, type Message, type MessagePart, type ModelConnectivityInfo, type StreamOptions, type TelemetryEventCallback, type ToolResultInfo, type WireCommunicationEventCallback } from '@salesforce/sfdx-agent-sdk';
|
|
3
3
|
import { type AgentHooks, type WithAgentConfig } from '@salesforce/sfdx-agent-sdk/harness';
|
|
4
4
|
import type { ClaudeAgentConfig } from './claude-config.js';
|
|
5
|
-
import { type LLMGatewayClient } from '@salesforce/llm-gateway-sdk';
|
|
6
5
|
import type { ClaudeQueryEnvBuilder } from './claude-query-env-builder.js';
|
|
7
6
|
import type { ClaudeQueryOptionsBuilder } from './claude-query-options-builder.js';
|
|
8
7
|
import { buildMcpClients } from './mcp-client-factory.js';
|
|
@@ -35,6 +34,20 @@ import { ThreadContextStore } from './thread-context-store.js';
|
|
|
35
34
|
export type ClaudeAgentHarness = WithAgentConfig<AgentHarness & {
|
|
36
35
|
readonly harnessId: 'claude';
|
|
37
36
|
}, ClaudeAgentConfig>;
|
|
37
|
+
/**
|
|
38
|
+
* Construction options for {@link ClaudeHarness}. Internal — consumers
|
|
39
|
+
* configure the harness via {@link ClaudeHarnessFactory}. The factory threads
|
|
40
|
+
* `mcpClientFactory` (bound with the proxy-aware `innerFetch`); tests pass
|
|
41
|
+
* stubs (`clock`, `idGenerator`, `sessionStore`, `mcpClientFactory`,
|
|
42
|
+
* `threadContextStore`) directly.
|
|
43
|
+
*/
|
|
44
|
+
export interface ClaudeHarnessOptions {
|
|
45
|
+
clock?: Clock;
|
|
46
|
+
idGenerator?: UniqueIDGenerator;
|
|
47
|
+
sessionStore?: DiskBackedSessionStore;
|
|
48
|
+
mcpClientFactory?: typeof buildMcpClients;
|
|
49
|
+
threadContextStore?: ThreadContextStore;
|
|
50
|
+
}
|
|
38
51
|
export declare class ClaudeHarness implements ClaudeAgentHarness {
|
|
39
52
|
private readonly envBuilder;
|
|
40
53
|
private readonly optionsBuilder;
|
|
@@ -71,13 +84,52 @@ export declare class ClaudeHarness implements ClaudeAgentHarness {
|
|
|
71
84
|
* collaborators on this constructor.
|
|
72
85
|
*/
|
|
73
86
|
private readonly mcpClientFactory;
|
|
87
|
+
private readonly storageRootFolder;
|
|
74
88
|
private shuttingDown;
|
|
75
|
-
constructor(envBuilder: ClaudeQueryEnvBuilder, optionsBuilder: ClaudeQueryOptionsBuilder, toolApprovalTimeoutMs: number, storageRootFolder: string,
|
|
89
|
+
constructor(envBuilder: ClaudeQueryEnvBuilder, optionsBuilder: ClaudeQueryOptionsBuilder, toolApprovalTimeoutMs: number, storageRootFolder: string, opts?: ClaudeHarnessOptions);
|
|
76
90
|
private coordinatorKey;
|
|
91
|
+
/**
|
|
92
|
+
* Returns a per-thread debug-log file path under the SDK storage root when a
|
|
93
|
+
* wire-communication consumer is subscribed; otherwise `undefined`. Callers pass the
|
|
94
|
+
* returned path as `query({ options: { debugFile } })` so the Claude subprocess writes
|
|
95
|
+
* its debug log to a file we own — and emit a `WireMonitoringNotSupportedEvent`
|
|
96
|
+
* pointing at the path immediately, before the subprocess starts.
|
|
97
|
+
*
|
|
98
|
+
* The path is **per-thread** (not per-turn): turns within the same conversation share
|
|
99
|
+
* a single file, accumulating wire data via the SDK's append-on-write behavior. A
|
|
100
|
+
* banner line written by {@link writeTurnBanner} delimits each turn within the file.
|
|
101
|
+
*
|
|
102
|
+
* Listener-count gating: relies on the wire-communication chain
|
|
103
|
+
* (`harness.wireBus → router slice → manager.wireBus`) being wired with
|
|
104
|
+
* `forwardWhileSubscribed`, so a consumer-less manager leaves
|
|
105
|
+
* `wireBus.listenerCount === 0` and this method returns `undefined` (no file written,
|
|
106
|
+
* no debug overhead in the subprocess).
|
|
107
|
+
*/
|
|
108
|
+
private maybeAllocateWireDebugLogPath;
|
|
109
|
+
/**
|
|
110
|
+
* Append a turn-start banner to the per-thread wire-debug log file so consumers
|
|
111
|
+
* grepping the accumulated content can find each turn's boundary. The Claude SDK
|
|
112
|
+
* appends to `debugFile` across `query()` calls with no separator of its own; this
|
|
113
|
+
* banner makes turn boundaries explicit and version-stable.
|
|
114
|
+
*/
|
|
115
|
+
private writeTurnBanner;
|
|
77
116
|
shutdown(): Promise<void>;
|
|
78
117
|
onTelemetry(callback: TelemetryEventCallback): Unsubscribe;
|
|
79
118
|
onLog(callback: (record: LogRecord) => void): Unsubscribe;
|
|
80
|
-
|
|
119
|
+
/**
|
|
120
|
+
* The Claude harness emits `WireMonitoringNotSupportedEvent` (one per stream) when at
|
|
121
|
+
* least one consumer is subscribed at stream-start. The Claude Agent SDK runs the model
|
|
122
|
+
* client in a subprocess with no programmatic seam for HTTP-level monitoring, so per-call
|
|
123
|
+
* `LlmRequestEvent` / `LlmResponseEvent` (Mastra's contract) are not produced here;
|
|
124
|
+
* instead, the harness writes the subprocess's debug log to a file under the SDK storage
|
|
125
|
+
* root and points at it from the event's `message` field.
|
|
126
|
+
*
|
|
127
|
+
* **Subscribe-before-stream**: subscriptions added mid-stream miss the in-flight
|
|
128
|
+
* subprocess on Claude — the listener-count check happens once at `stream()` start. The
|
|
129
|
+
* next subprocess spawn (next `chat()` call) will pick up the subscriber.
|
|
130
|
+
*/
|
|
131
|
+
onWireCommunication(callback: WireCommunicationEventCallback): Unsubscribe;
|
|
132
|
+
createAgent(agentId: string, projectRoot: string, modelConnectivityInfo: ModelConnectivityInfo, config?: HarnessAgentConfig, options?: {
|
|
81
133
|
abortSignal?: AbortSignal;
|
|
82
134
|
hooks?: AgentHooks;
|
|
83
135
|
}): Promise<void>;
|
|
@@ -146,7 +198,7 @@ export declare class ClaudeHarness implements ClaudeAgentHarness {
|
|
|
146
198
|
* `state.threads` is intentionally untouched — sessions are config-
|
|
147
199
|
* independent, so an `updateAgent` cannot invalidate them.
|
|
148
200
|
*/
|
|
149
|
-
updateAgent(agentId: string,
|
|
201
|
+
updateAgent(agentId: string, modelConnectivityInfo: ModelConnectivityInfo, config?: HarnessAgentConfig, options?: {
|
|
150
202
|
abortSignal?: AbortSignal;
|
|
151
203
|
hooks?: AgentHooks;
|
|
152
204
|
}): Promise<void>;
|