@ai-sdk/harness 1.0.118 → 1.0.120
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 +16 -0
- package/README.md +4 -108
- package/dist/agent/index.d.ts +25 -3
- package/dist/agent/index.js +66 -23
- package/dist/agent/index.js.map +1 -1
- package/package.json +3 -3
- package/src/agent/harness-agent-session.ts +15 -0
- package/src/agent/harness-agent-settings.ts +17 -4
- package/src/agent/harness-agent.ts +25 -1
- package/src/agent/internal/get-own.ts +8 -0
- package/src/agent/internal/run-prompt.ts +31 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @ai-sdk/harness
|
|
2
2
|
|
|
3
|
+
## 1.0.120
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- ai@7.0.110
|
|
8
|
+
|
|
9
|
+
## 1.0.119
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 125f493: fix(harness): forward validated `toolsContext` to host-executed tools in alignment with `ToolLoopAgent`
|
|
14
|
+
- Updated dependencies [0343bb1]
|
|
15
|
+
- Updated dependencies [2b105fa]
|
|
16
|
+
- Updated dependencies [125f493]
|
|
17
|
+
- ai@7.0.109
|
|
18
|
+
|
|
3
19
|
## 1.0.118
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -99,112 +99,8 @@ const agent = new HarnessAgent({
|
|
|
99
99
|
});
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
## Documentation
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
`sandbox` is an optional `HarnessV1SandboxProvider`. When omitted, pass a `HarnessV1NetworkSandboxSession` to every `agent.createSession({ sandboxSession })` call. Use `sandboxConfig` for agent specific sandbox configuration that works independently from the sandbox provider that is used:
|
|
108
|
-
|
|
109
|
-
- Use `sandboxConfig.onSession` to prepare the acquired sandbox before the harness adapter starts. The hook runs for fresh and resumed sessions, so keep it idempotent.
|
|
110
|
-
- Use `sandboxConfig.onBootstrap` for expensive sandbox setup that should be baked into a reusable snapshot, such as installing tools or cloning a large repository. Provide `sandboxConfig.bootstrapHash` with it and change that value whenever the bootstrap output should invalidate the cached snapshot.
|
|
111
|
-
- Use `sandboxConfig.workDir` to set a stable working directory for the agent, relative to the sandbox's default working directory; otherwise regular sessions use the existing `<harnessId>-<sessionId>` directory. In that case, the `onBootstrap` callback receives the sandbox's default working directory.
|
|
112
|
-
|
|
113
|
-
Use `prepareHarnessSandboxTemplate()` to create or refresh the sandbox provider's
|
|
114
|
-
own reusable template for one harness before serving traffic. This is the
|
|
115
|
-
replacement for `prewarmHarness()`, which remains as a deprecated alias.
|
|
116
|
-
|
|
117
|
-
Use `prepareSandboxForHarness()` when you own an existing sandbox and want to
|
|
118
|
-
prepare it before creating your own snapshot. It applies the selected harness
|
|
119
|
-
bootstrap recipes and `sandboxConfig.onBootstrap`, returns the computed
|
|
120
|
-
preparation identity and per-harness recipe identities, and leaves snapshotting
|
|
121
|
-
or stopping the sandbox to your code. Later, create a sandbox from that snapshot
|
|
122
|
-
and pass the native sandbox object to `createVercelSandbox({ sandbox })` for the
|
|
123
|
-
`HarnessAgent`. When several bridge-backed harnesses share a caller-provided
|
|
124
|
-
sandbox, create that sandbox with one exposed port for each harness. Then pass
|
|
125
|
-
each harness's assigned port to that harness's `create*` function.
|
|
126
|
-
|
|
127
|
-
### Available harnesses
|
|
128
|
-
|
|
129
|
-
See the [harness adapters documentation](https://ai-sdk.dev/v7/docs/ai-sdk-harnesses/harness-adapters).
|
|
130
|
-
|
|
131
|
-
## Implementing a harness
|
|
132
|
-
|
|
133
|
-
Implement the `HarnessV1` factory and a `HarnessV1Session` whose `doPromptTurn` emits events; the agent surface, streaming, tool execution, and multi-turn state are handled for you. Read `startOpts.model` for the consumer-selected model and `startOpts.sandboxSession` for the selected network sandbox session. The harness layer stops or destroys sessions it acquires from the provider, while a session passed to `agent.createSession({ sandboxSession })` remains caller-owned. Call `sandboxSession.restricted()` for the tool-safe file-IO/exec/spawn surface.
|
|
134
|
-
|
|
135
|
-
Each prompt and continuation receives an optional `responseFormat`. JSON
|
|
136
|
-
formats carry a caller-provided JSON Schema plus optional name and description;
|
|
137
|
-
the adapter must enforce the schema and emit the resulting JSON through normal
|
|
138
|
-
text parts. If the runtime cannot honor the format, throw
|
|
139
|
-
`HarnessCapabilityUnsupportedError` before starting the turn.
|
|
140
|
-
|
|
141
|
-
Bootstrap recipe paths may be absolute or relative. Relative `bootstrapDir` and
|
|
142
|
-
file paths are resolved against `sandboxSession.defaultWorkingDirectory`.
|
|
143
|
-
The framework creates `bootstrapDir` before writing files, and bootstrap
|
|
144
|
-
commands always run from that directory. Prefer a relative directory such as
|
|
145
|
-
`.harness-bootstrap/my-harness` so bootstrap assets are kept with the sandbox's
|
|
146
|
-
snapshot-persistent working tree.
|
|
147
|
-
|
|
148
|
-
```ts
|
|
149
|
-
import type { HarnessV1, HarnessV1Session } from '@ai-sdk/harness';
|
|
150
|
-
|
|
151
|
-
export function myHarness(): HarnessV1 {
|
|
152
|
-
return {
|
|
153
|
-
specificationVersion: 'harness-v1',
|
|
154
|
-
harnessId: 'my-harness',
|
|
155
|
-
builtinTools: {},
|
|
156
|
-
doStart: async startOpts => {
|
|
157
|
-
const usage = {
|
|
158
|
-
inputTokens: { total: 0, noCache: 0 },
|
|
159
|
-
outputTokens: { total: 0, text: 0 },
|
|
160
|
-
};
|
|
161
|
-
const resumeState = {
|
|
162
|
-
type: 'resume-session' as const,
|
|
163
|
-
harnessId: 'my-harness',
|
|
164
|
-
specificationVersion: 'harness-v1' as const,
|
|
165
|
-
data: {},
|
|
166
|
-
};
|
|
167
|
-
const continueState = {
|
|
168
|
-
type: 'continue-turn' as const,
|
|
169
|
-
harnessId: 'my-harness',
|
|
170
|
-
specificationVersion: 'harness-v1' as const,
|
|
171
|
-
data: {},
|
|
172
|
-
};
|
|
173
|
-
const session: HarnessV1Session = {
|
|
174
|
-
sessionId: startOpts.sessionId,
|
|
175
|
-
isResume:
|
|
176
|
-
startOpts.resumeFrom != null || startOpts.continueFrom != null,
|
|
177
|
-
doPromptTurn: async promptOpts => {
|
|
178
|
-
const done = Promise.resolve().then(() => {
|
|
179
|
-
promptOpts.emit({ type: 'text-start', id: 't' });
|
|
180
|
-
promptOpts.emit({ type: 'text-delta', id: 't', delta: 'Hello.' });
|
|
181
|
-
promptOpts.emit({ type: 'text-end', id: 't' });
|
|
182
|
-
promptOpts.emit({
|
|
183
|
-
type: 'finish',
|
|
184
|
-
finishReason: { unified: 'stop', raw: 'stop' },
|
|
185
|
-
totalUsage: usage,
|
|
186
|
-
});
|
|
187
|
-
});
|
|
188
|
-
return { submitToolResult: async () => {}, done };
|
|
189
|
-
},
|
|
190
|
-
doContinueTurn: async continueOpts => {
|
|
191
|
-
const done = Promise.resolve().then(() => {
|
|
192
|
-
continueOpts.emit({
|
|
193
|
-
type: 'finish',
|
|
194
|
-
finishReason: { unified: 'stop', raw: 'stop' },
|
|
195
|
-
totalUsage: usage,
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
return { submitToolResult: async () => {}, done };
|
|
199
|
-
},
|
|
200
|
-
doCompact: async () => {},
|
|
201
|
-
doDetach: async () => resumeState,
|
|
202
|
-
doStop: async () => resumeState,
|
|
203
|
-
doDestroy: async () => {},
|
|
204
|
-
doSuspendTurn: async () => continueState,
|
|
205
|
-
};
|
|
206
|
-
return session;
|
|
207
|
-
},
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
```
|
|
104
|
+
- [Detailed usage documentation](https://ai-sdk.dev/docs/ai-sdk-harnesses)
|
|
105
|
+
- [Harness abstraction architecture](https://github.com/vercel/ai/blob/main/architecture/harness-abstraction.md)
|
|
106
|
+
- [Sandbox abstraction architecture](https://github.com/vercel/ai/blob/main/architecture/sandbox-abstraction.md)
|
package/dist/agent/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';
|
|
2
|
-
import { Experimental_SandboxSession, UserModelMessage, ToolResultPart, ProviderOptions, ToolSet, FlexibleSchema, Tool, Context, SystemModelMessage, MaybePromiseLike, Arrayable, ToolApprovalResponse, ModelMessage } from '@ai-sdk/provider-utils';
|
|
2
|
+
import { Experimental_SandboxSession, UserModelMessage, ToolResultPart, ProviderOptions, ToolSet, FlexibleSchema, Tool, Context, InferToolSetContext, SystemModelMessage, MaybePromiseLike, Arrayable, ToolApprovalResponse, ModelMessage } from '@ai-sdk/provider-utils';
|
|
3
|
+
import { ToolsContextSettings } from 'ai/internal';
|
|
3
4
|
import { OutputInterface, AgentCallParameters, Prompt, StopCondition, GenerateTextOnStartCallback, GenerateTextOnStepStartCallback, OnLanguageModelCallStartCallback, OnLanguageModelCallEndCallback, OnToolExecutionStartCallback, OnToolExecutionEndCallback, GenerateTextOnStepEndCallback, GenerateTextOnEndCallback, ToolApprovalStatus, TelemetryOptions, ActiveTools, StreamTextResult, Agent, GenerateTextResult, AgentStreamParameters, Telemetry } from 'ai';
|
|
4
5
|
import { z } from 'zod/v4';
|
|
5
6
|
import { JSONSchema7, JSONValue, LanguageModelV4StreamPart, LanguageModelV4ToolCall, LanguageModelV4ToolApprovalRequest, LanguageModelV4ToolResult, LanguageModelV4FinishReason, LanguageModelV4Usage, AISDKError } from '@ai-sdk/provider';
|
|
@@ -1344,6 +1345,12 @@ type HarnessAgentSettings<THarness extends HarnessAgentAdapter<any> = HarnessAge
|
|
|
1344
1345
|
* declare a tool with the same name as a builtin to override.
|
|
1345
1346
|
*/
|
|
1346
1347
|
readonly tools?: TUserTools;
|
|
1348
|
+
/**
|
|
1349
|
+
* Per-tool context passed to host-executed tools. Each entry is validated
|
|
1350
|
+
* against the matching tool's `contextSchema` before execution.
|
|
1351
|
+
* `prepareCall` can replace it for each new turn.
|
|
1352
|
+
*/
|
|
1353
|
+
readonly toolsContext?: InferToolSetContext<TUserTools>;
|
|
1347
1354
|
/**
|
|
1348
1355
|
* Skills made available to the underlying runtime. Each adapter decides how
|
|
1349
1356
|
* to surface skills. `prepareCall` can replace them between completed turns.
|
|
@@ -1383,7 +1390,11 @@ type HarnessAgentSettings<THarness extends HarnessAgentAdapter<any> = HarnessAge
|
|
|
1383
1390
|
* })
|
|
1384
1391
|
* ```
|
|
1385
1392
|
*/
|
|
1386
|
-
readonly prepareCall?: (options: Omit<AgentCallParameters<CALL_OPTIONS, HarnessAllTools<THarness, TUserTools>, RUNTIME_CONTEXT>, 'abortSignal' | 'timeout' | 'onStart' | 'experimental_onStart' | 'onStepStart' | 'experimental_onStepStart' | 'onToolExecutionStart' | 'experimental_onToolCallStart' | 'onToolExecutionEnd' | 'experimental_onToolCallFinish' | 'onStepEnd' | 'onStepFinish' | 'onEnd' | 'onFinish' | 'experimental_sandbox'> & Pick<HarnessAgentSettings<THarness, TUserTools, RUNTIME_CONTEXT, NoInfer<OUTPUT>, CALL_OPTIONS>, 'model' | 'skills' | 'instructions' | 'tools'>
|
|
1393
|
+
readonly prepareCall?: (options: Omit<AgentCallParameters<CALL_OPTIONS, HarnessAllTools<THarness, TUserTools>, RUNTIME_CONTEXT>, 'abortSignal' | 'timeout' | 'onStart' | 'experimental_onStart' | 'onStepStart' | 'experimental_onStepStart' | 'onToolExecutionStart' | 'experimental_onToolCallStart' | 'onToolExecutionEnd' | 'experimental_onToolCallFinish' | 'onStepEnd' | 'onStepFinish' | 'onEnd' | 'onFinish' | 'experimental_sandbox'> & Pick<HarnessAgentSettings<THarness, TUserTools, RUNTIME_CONTEXT, NoInfer<OUTPUT>, CALL_OPTIONS>, 'model' | 'skills' | 'instructions' | 'tools'> & {
|
|
1394
|
+
toolsContext: InferToolSetContext<TUserTools>;
|
|
1395
|
+
}) => MaybePromiseLike<Pick<HarnessAgentSettings<THarness, TUserTools, RUNTIME_CONTEXT, NoInfer<OUTPUT>, CALL_OPTIONS>, 'model' | 'skills' | 'instructions' | 'tools'> & {
|
|
1396
|
+
toolsContext: InferToolSetContext<TUserTools>;
|
|
1397
|
+
} & Omit<Prompt, 'system' | 'instructions' | 'allowSystemInMessages'>>;
|
|
1387
1398
|
/**
|
|
1388
1399
|
* Optional specification for generating typed output. The same output
|
|
1389
1400
|
* requirement is active for every turn run by this agent.
|
|
@@ -1478,7 +1489,7 @@ type HarnessAgentSettings<THarness extends HarnessAgentAdapter<any> = HarnessAge
|
|
|
1478
1489
|
* stderr default — wire this to capture diagnostics in code.
|
|
1479
1490
|
*/
|
|
1480
1491
|
readonly onLog?: (event: HarnessDiagnostic) => void;
|
|
1481
|
-
} & HarnessAgentToolFilteringSettings<HarnessAllTools<THarness, TUserTools>>;
|
|
1492
|
+
} & ToolsContextSettings<TUserTools> & HarnessAgentToolFilteringSettings<HarnessAllTools<THarness, TUserTools>>;
|
|
1482
1493
|
|
|
1483
1494
|
type HarnessAgentLifecycleCallbacks<TOOLS extends ToolSet, RUNTIME_CONTEXT extends Context, OUTPUT extends OutputInterface> = {
|
|
1484
1495
|
onStart?: GenerateTextOnStartCallback<TOOLS, RUNTIME_CONTEXT, OUTPUT>;
|
|
@@ -1533,6 +1544,7 @@ declare class HarnessAgentSession {
|
|
|
1533
1544
|
private suspendedTurnState;
|
|
1534
1545
|
private activeTurnSettings;
|
|
1535
1546
|
private persistedTurnSettings;
|
|
1547
|
+
private readonly resumedToolsContext;
|
|
1536
1548
|
/**
|
|
1537
1549
|
* Whether this session was created from `resumeFrom` or `continueFrom`.
|
|
1538
1550
|
* Captured at construction so it survives lifecycle cleanup.
|
|
@@ -1549,6 +1561,7 @@ declare class HarnessAgentSession {
|
|
|
1549
1561
|
pendingToolApprovals?: readonly HarnessAgentPendingToolApproval[];
|
|
1550
1562
|
pendingToolResults?: readonly HarnessAgentPendingToolResult[];
|
|
1551
1563
|
turnSettings?: HarnessV1TurnSettings;
|
|
1564
|
+
resumedToolsContext?: Record<string, Context | undefined>;
|
|
1552
1565
|
turnState?: HarnessAgentTurnState;
|
|
1553
1566
|
});
|
|
1554
1567
|
hasUnfinishedTurn(): boolean;
|
|
@@ -1558,6 +1571,7 @@ declare class HarnessAgentSession {
|
|
|
1558
1571
|
skills: ReadonlyArray<HarnessV1Skill>;
|
|
1559
1572
|
instructions: string | undefined;
|
|
1560
1573
|
tools: TOOLS;
|
|
1574
|
+
toolsContext: InferToolSetContext<TOOLS>;
|
|
1561
1575
|
activeTools: ToolSet;
|
|
1562
1576
|
toolSpecs: HarnessAgentToolSpec[];
|
|
1563
1577
|
builtinToolFiltering: HarnessV1BuiltinToolFiltering | undefined;
|
|
@@ -1574,6 +1588,7 @@ declare class HarnessAgentSession {
|
|
|
1574
1588
|
skills: ReadonlyArray<HarnessV1Skill>;
|
|
1575
1589
|
instructions: string | undefined;
|
|
1576
1590
|
tools: TOOLS;
|
|
1591
|
+
toolsContext: InferToolSetContext<TOOLS>;
|
|
1577
1592
|
activeTools: ToolSet;
|
|
1578
1593
|
toolSpecs: HarnessAgentToolSpec[];
|
|
1579
1594
|
builtinToolFiltering: HarnessV1BuiltinToolFiltering | undefined;
|
|
@@ -1756,6 +1771,13 @@ declare class HarnessAgent<THarness extends HarnessAgentAdapter<any> = HarnessAg
|
|
|
1756
1771
|
* handing it to the adapter.
|
|
1757
1772
|
*/
|
|
1758
1773
|
continueFrom?: HarnessAgentContinueTurnState;
|
|
1774
|
+
/**
|
|
1775
|
+
* Rebinds host-only tool context for an unfinished turn resumed with
|
|
1776
|
+
* `continueFrom` (directly or through `resumeFrom`). Tool context is not
|
|
1777
|
+
* serialized into lifecycle state because it may contain credentials or
|
|
1778
|
+
* non-serializable host objects.
|
|
1779
|
+
*/
|
|
1780
|
+
toolsContext?: ToolsContextSettings<TUserTools>['toolsContext'];
|
|
1759
1781
|
/**
|
|
1760
1782
|
* Existing sandbox session to run the harness in. When provided, the
|
|
1761
1783
|
* caller retains ownership of the sandbox lifecycle.
|
package/dist/agent/index.js
CHANGED
|
@@ -164,7 +164,11 @@ import {
|
|
|
164
164
|
import {
|
|
165
165
|
getErrorMessage
|
|
166
166
|
} from "@ai-sdk/provider";
|
|
167
|
-
import {
|
|
167
|
+
import {
|
|
168
|
+
asLanguageModelUsage as asLanguageModelUsage2,
|
|
169
|
+
parseToolCall,
|
|
170
|
+
validateToolContext
|
|
171
|
+
} from "ai/internal";
|
|
168
172
|
|
|
169
173
|
// src/agent/internal/harness-stream-text-result.ts
|
|
170
174
|
import {
|
|
@@ -851,6 +855,11 @@ function notSupportedYet(feature) {
|
|
|
851
855
|
);
|
|
852
856
|
}
|
|
853
857
|
|
|
858
|
+
// src/agent/internal/get-own.ts
|
|
859
|
+
function getOwn(obj, key) {
|
|
860
|
+
return obj != null && Object.prototype.hasOwnProperty.call(obj, key) ? obj[key] : void 0;
|
|
861
|
+
}
|
|
862
|
+
|
|
854
863
|
// src/agent/internal/translate-stream-part.ts
|
|
855
864
|
import { generateId } from "@ai-sdk/provider-utils";
|
|
856
865
|
function translateStreamPart(event, options = {}) {
|
|
@@ -1525,29 +1534,29 @@ function unwrapToolResultOutput(toolResult) {
|
|
|
1525
1534
|
}
|
|
1526
1535
|
}
|
|
1527
1536
|
function runPrompt(input) {
|
|
1528
|
-
var _a4, _b4, _c, _d, _e, _f, _g, _h, _i;
|
|
1537
|
+
var _a4, _b4, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1529
1538
|
const callId = generateId2();
|
|
1530
|
-
const toolsContext = {};
|
|
1539
|
+
const toolsContext = (_a4 = input.toolsContext) != null ? _a4 : {};
|
|
1531
1540
|
const result = new HarnessStreamTextResult({
|
|
1532
1541
|
tools: input.tools,
|
|
1533
1542
|
runtimeContext: input.runtimeContext,
|
|
1534
1543
|
toolsContext,
|
|
1535
1544
|
harnessId: input.harness.harnessId,
|
|
1536
1545
|
callId,
|
|
1537
|
-
modelId: (
|
|
1546
|
+
modelId: (_b4 = input.model) != null ? _b4 : "",
|
|
1538
1547
|
output: input.output
|
|
1539
1548
|
});
|
|
1540
|
-
const pendingToolApprovals = (
|
|
1541
|
-
const pendingToolResults = (
|
|
1542
|
-
const onPendingToolApproval = (
|
|
1549
|
+
const pendingToolApprovals = (_c = input.pendingToolApprovals) != null ? _c : [];
|
|
1550
|
+
const pendingToolResults = (_d = input.pendingToolResults) != null ? _d : [];
|
|
1551
|
+
const onPendingToolApproval = (_e = input.onPendingToolApproval) != null ? _e : (() => {
|
|
1543
1552
|
});
|
|
1544
|
-
const onToolApprovalSettled = (
|
|
1553
|
+
const onToolApprovalSettled = (_f = input.onToolApprovalSettled) != null ? _f : (() => {
|
|
1545
1554
|
});
|
|
1546
|
-
const onPendingToolResult = (
|
|
1555
|
+
const onPendingToolResult = (_g = input.onPendingToolResult) != null ? _g : (() => {
|
|
1547
1556
|
});
|
|
1548
|
-
const onToolResultSettled = (
|
|
1557
|
+
const onToolResultSettled = (_h = input.onToolResultSettled) != null ? _h : (() => {
|
|
1549
1558
|
});
|
|
1550
|
-
const activeTools = (
|
|
1559
|
+
const activeTools = (_i = input.activeTools) != null ? _i : input.tools;
|
|
1551
1560
|
const activeToolNames = Object.keys(input.tools).filter(
|
|
1552
1561
|
(toolName) => Object.prototype.hasOwnProperty.call(activeTools, toolName) || Object.prototype.hasOwnProperty.call(
|
|
1553
1562
|
input.harness.builtinTools,
|
|
@@ -1560,7 +1569,7 @@ function runPrompt(input) {
|
|
|
1560
1569
|
const lifecycle = createTurnLifecycle({
|
|
1561
1570
|
callId,
|
|
1562
1571
|
telemetry: input.telemetry,
|
|
1563
|
-
callbacks: (
|
|
1572
|
+
callbacks: (_j = input.callbacks) != null ? _j : {},
|
|
1564
1573
|
harnessId: input.harness.harnessId,
|
|
1565
1574
|
modelId: input.model,
|
|
1566
1575
|
instructions: input.instructions,
|
|
@@ -1587,7 +1596,7 @@ function runPrompt(input) {
|
|
|
1587
1596
|
result.fail(err);
|
|
1588
1597
|
};
|
|
1589
1598
|
const done = (async () => {
|
|
1590
|
-
var _a5, _b5, _c2, _d2, _e2, _f2, _g2, _h2, _i2,
|
|
1599
|
+
var _a5, _b5, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k, _l, _m, _n, _o;
|
|
1591
1600
|
let bridge;
|
|
1592
1601
|
try {
|
|
1593
1602
|
bridge = await toHarnessStream({
|
|
@@ -1972,6 +1981,7 @@ function runPrompt(input) {
|
|
|
1972
1981
|
const execution = await maybeExecuteHostTool({
|
|
1973
1982
|
event: rawToolCall,
|
|
1974
1983
|
tools: activeTools,
|
|
1984
|
+
toolsContext,
|
|
1975
1985
|
wrappedExecuteTool: lifecycle.executeTool,
|
|
1976
1986
|
sandboxSession: input.sandboxSession,
|
|
1977
1987
|
abortSignal: input.abortSignal,
|
|
@@ -2223,7 +2233,7 @@ function runPrompt(input) {
|
|
|
2223
2233
|
toolName: toolCall.toolName,
|
|
2224
2234
|
input: (_i2 = rawToolCall == null ? void 0 : rawToolCall.input) != null ? _i2 : JSON.stringify(toolCall.input),
|
|
2225
2235
|
kind: "builtin",
|
|
2226
|
-
providerExecuted: (
|
|
2236
|
+
providerExecuted: (_j2 = rawToolCall == null ? void 0 : rawToolCall.providerExecuted) != null ? _j2 : true,
|
|
2227
2237
|
...(rawToolCall == null ? void 0 : rawToolCall.nativeName) !== void 0 ? { nativeName: rawToolCall.nativeName } : {}
|
|
2228
2238
|
};
|
|
2229
2239
|
pendingApprovalsByApprovalId.set(
|
|
@@ -2418,6 +2428,7 @@ function runPrompt(input) {
|
|
|
2418
2428
|
const execution = await maybeExecuteHostTool({
|
|
2419
2429
|
event: toolCall,
|
|
2420
2430
|
tools: activeTools,
|
|
2431
|
+
toolsContext,
|
|
2421
2432
|
wrappedExecuteTool: lifecycle.executeTool,
|
|
2422
2433
|
sandboxSession: input.sandboxSession,
|
|
2423
2434
|
abortSignal: input.abortSignal,
|
|
@@ -2529,6 +2540,21 @@ async function maybeExecuteHostTool(input) {
|
|
|
2529
2540
|
if (!isExecutableTool(tool)) return { executed: false };
|
|
2530
2541
|
const parsed = await safeParseJSON2({ text: input.event.input });
|
|
2531
2542
|
const args = parsed.success ? parsed.value : input.event.input;
|
|
2543
|
+
let context;
|
|
2544
|
+
try {
|
|
2545
|
+
context = await validateToolContext({
|
|
2546
|
+
toolName: input.event.toolName,
|
|
2547
|
+
context: getOwn(input.toolsContext, input.event.toolName),
|
|
2548
|
+
contextSchema: tool.contextSchema
|
|
2549
|
+
});
|
|
2550
|
+
} catch (err) {
|
|
2551
|
+
await input.submitToolResult({
|
|
2552
|
+
toolCallId: input.event.toolCallId,
|
|
2553
|
+
output: { error: "Tool context validation failed." },
|
|
2554
|
+
isError: true
|
|
2555
|
+
});
|
|
2556
|
+
return { executed: true, outcome: { ok: false, error: err } };
|
|
2557
|
+
}
|
|
2532
2558
|
try {
|
|
2533
2559
|
const output = await input.wrappedExecuteTool({
|
|
2534
2560
|
toolCallId: input.event.toolCallId,
|
|
@@ -2541,7 +2567,7 @@ async function maybeExecuteHostTool(input) {
|
|
|
2541
2567
|
toolCallId: input.event.toolCallId,
|
|
2542
2568
|
messages: [],
|
|
2543
2569
|
abortSignal: input.abortSignal,
|
|
2544
|
-
context
|
|
2570
|
+
context,
|
|
2545
2571
|
experimental_sandbox: input.sandboxSession
|
|
2546
2572
|
}
|
|
2547
2573
|
});
|
|
@@ -2630,6 +2656,7 @@ var HarnessAgentSession = class {
|
|
|
2630
2656
|
this.pendingToolResults.set(pendingResult.toolCallId, pendingResult);
|
|
2631
2657
|
}
|
|
2632
2658
|
this.persistedTurnSettings = options.turnSettings;
|
|
2659
|
+
this.resumedToolsContext = options.resumedToolsContext;
|
|
2633
2660
|
this.turnState = (_d = options.turnState) != null ? _d : this.pendingToolApprovals.size > 0 ? "awaiting-approval" : this.pendingToolResults.size > 0 ? "awaiting-tool-result" : "idle";
|
|
2634
2661
|
this.isResume = options.underlyingSession.isResume;
|
|
2635
2662
|
}
|
|
@@ -2670,6 +2697,7 @@ var HarnessAgentSession = class {
|
|
|
2670
2697
|
this.activeTurnSettings = {
|
|
2671
2698
|
persisted: this.persistedTurnSettings,
|
|
2672
2699
|
tools: options.tools,
|
|
2700
|
+
toolsContext: options.toolsContext,
|
|
2673
2701
|
activeTools: options.activeTools,
|
|
2674
2702
|
builtinToolFiltering: options.builtinToolFiltering
|
|
2675
2703
|
};
|
|
@@ -2684,6 +2712,7 @@ var HarnessAgentSession = class {
|
|
|
2684
2712
|
skills: options.skills,
|
|
2685
2713
|
instructions: options.instructions,
|
|
2686
2714
|
tools: options.tools,
|
|
2715
|
+
toolsContext: options.toolsContext,
|
|
2687
2716
|
activeTools: options.activeTools,
|
|
2688
2717
|
toolSpecs: options.toolSpecs,
|
|
2689
2718
|
builtinToolFiltering: options.builtinToolFiltering,
|
|
@@ -2743,6 +2772,7 @@ var HarnessAgentSession = class {
|
|
|
2743
2772
|
skills: options.skills,
|
|
2744
2773
|
instructions: options.instructions,
|
|
2745
2774
|
tools: options.tools,
|
|
2775
|
+
toolsContext: options.toolsContext,
|
|
2746
2776
|
activeTools: options.activeTools,
|
|
2747
2777
|
toolSpecs: options.toolSpecs,
|
|
2748
2778
|
builtinToolFiltering: options.builtinToolFiltering
|
|
@@ -2758,6 +2788,7 @@ var HarnessAgentSession = class {
|
|
|
2758
2788
|
skills: turnSettings.persisted.skills,
|
|
2759
2789
|
instructions: turnSettings.persisted.instructions,
|
|
2760
2790
|
tools: turnSettings.tools,
|
|
2791
|
+
toolsContext: turnSettings.toolsContext,
|
|
2761
2792
|
activeTools: turnSettings.activeTools,
|
|
2762
2793
|
toolSpecs: [...turnSettings.persisted.tools],
|
|
2763
2794
|
builtinToolFiltering: turnSettings.builtinToolFiltering,
|
|
@@ -3122,7 +3153,7 @@ var HarnessAgentSession = class {
|
|
|
3122
3153
|
this.turnState = "idle";
|
|
3123
3154
|
}
|
|
3124
3155
|
resolveActiveTurnSettings(options) {
|
|
3125
|
-
var _a4;
|
|
3156
|
+
var _a4, _b4;
|
|
3126
3157
|
if (this.activeTurnSettings != null) {
|
|
3127
3158
|
return this.activeTurnSettings;
|
|
3128
3159
|
}
|
|
@@ -3146,6 +3177,7 @@ var HarnessAgentSession = class {
|
|
|
3146
3177
|
this.activeTurnSettings = {
|
|
3147
3178
|
persisted,
|
|
3148
3179
|
tools: options.tools,
|
|
3180
|
+
toolsContext: (_b4 = this.resumedToolsContext) != null ? _b4 : options.toolsContext,
|
|
3149
3181
|
activeTools,
|
|
3150
3182
|
builtinToolFiltering: options.builtinToolFiltering
|
|
3151
3183
|
};
|
|
@@ -3768,6 +3800,11 @@ var HarnessAgent = class {
|
|
|
3768
3800
|
});
|
|
3769
3801
|
}
|
|
3770
3802
|
const effectiveContinueFrom = validatedContinueFrom != null ? validatedContinueFrom : validatedResumeFrom == null ? void 0 : validatedResumeFrom.continueFrom;
|
|
3803
|
+
if ((options == null ? void 0 : options.toolsContext) != null && effectiveContinueFrom == null) {
|
|
3804
|
+
throw new Error(
|
|
3805
|
+
"HarnessAgent.createSession: `toolsContext` can only rebind an unfinished turn from `continueFrom` or `resumeFrom`."
|
|
3806
|
+
);
|
|
3807
|
+
}
|
|
3771
3808
|
const isResumedSession = validatedResumeFrom != null || effectiveContinueFrom != null;
|
|
3772
3809
|
let sandboxSession;
|
|
3773
3810
|
let sessionWorkDir;
|
|
@@ -3930,6 +3967,7 @@ var HarnessAgent = class {
|
|
|
3930
3967
|
pendingToolApprovals: effectiveContinueFrom == null ? void 0 : effectiveContinueFrom.pendingToolApprovals,
|
|
3931
3968
|
pendingToolResults: effectiveContinueFrom == null ? void 0 : effectiveContinueFrom.pendingToolResults,
|
|
3932
3969
|
turnSettings: effectiveContinueFrom == null ? void 0 : effectiveContinueFrom.turnSettings,
|
|
3970
|
+
resumedToolsContext: options == null ? void 0 : options.toolsContext,
|
|
3933
3971
|
turnState: effectiveContinueFrom == null ? "idle" : effectiveContinueFrom.pendingToolApprovals != null && effectiveContinueFrom.pendingToolApprovals.length > 0 ? "awaiting-approval" : effectiveContinueFrom.pendingToolResults != null && effectiveContinueFrom.pendingToolResults.length > 0 ? "awaiting-tool-result" : "suspended"
|
|
3934
3972
|
});
|
|
3935
3973
|
} catch (error) {
|
|
@@ -4053,6 +4091,7 @@ var HarnessAgent = class {
|
|
|
4053
4091
|
skills: input.turnSettings.skills,
|
|
4054
4092
|
instructions: input.turnSettings.instructions,
|
|
4055
4093
|
tools: input.turnSettings.tools,
|
|
4094
|
+
toolsContext: input.turnSettings.toolsContext,
|
|
4056
4095
|
activeTools: input.turnSettings.activeTools,
|
|
4057
4096
|
toolSpecs: input.turnSettings.toolSpecs,
|
|
4058
4097
|
builtinToolFiltering: input.turnSettings.builtinToolFiltering,
|
|
@@ -4135,7 +4174,7 @@ var HarnessAgent = class {
|
|
|
4135
4174
|
throw new Error("HarnessAgent: either `prompt` or `messages` is required.");
|
|
4136
4175
|
}
|
|
4137
4176
|
async _preparePromptTurnInput(options) {
|
|
4138
|
-
var _a4, _b4, _c;
|
|
4177
|
+
var _a4, _b4, _c, _d;
|
|
4139
4178
|
let callOptions = options;
|
|
4140
4179
|
if (this.settings.callOptionsSchema != null && options.options !== void 0) {
|
|
4141
4180
|
const validatedOptions = await validateTypes({
|
|
@@ -4172,12 +4211,13 @@ var HarnessAgent = class {
|
|
|
4172
4211
|
skills: this.settings.skills,
|
|
4173
4212
|
instructions: this.settings.instructions,
|
|
4174
4213
|
tools: this.settings.tools,
|
|
4214
|
+
toolsContext: (_a4 = this.settings.toolsContext) != null ? _a4 : {},
|
|
4175
4215
|
...promptOptions
|
|
4176
4216
|
};
|
|
4177
|
-
const preparedCallArgs = (
|
|
4178
|
-
|
|
4217
|
+
const preparedCallArgs = (_d = await ((_c = (_b4 = this.settings).prepareCall) == null ? void 0 : _c.call(
|
|
4218
|
+
_b4,
|
|
4179
4219
|
baseCallArgs
|
|
4180
|
-
))) != null ?
|
|
4220
|
+
))) != null ? _d : baseCallArgs;
|
|
4181
4221
|
if (this._resolveContinueTurnInput(preparedCallArgs) != null) {
|
|
4182
4222
|
throw new Error(
|
|
4183
4223
|
"HarnessAgent.prepareCall must return a fresh user prompt, not a tool continuation."
|
|
@@ -4189,7 +4229,8 @@ var HarnessAgent = class {
|
|
|
4189
4229
|
model: preparedCallArgs.model,
|
|
4190
4230
|
skills: preparedCallArgs.skills,
|
|
4191
4231
|
instructions: preparedCallArgs.instructions,
|
|
4192
|
-
tools: preparedCallArgs.tools
|
|
4232
|
+
tools: preparedCallArgs.tools,
|
|
4233
|
+
toolsContext: preparedCallArgs.toolsContext
|
|
4193
4234
|
})
|
|
4194
4235
|
};
|
|
4195
4236
|
}
|
|
@@ -4200,14 +4241,15 @@ var HarnessAgent = class {
|
|
|
4200
4241
|
model: this.settings.model,
|
|
4201
4242
|
skills: this.settings.skills,
|
|
4202
4243
|
instructions: this.settings.instructions,
|
|
4203
|
-
tools: this.settings.tools
|
|
4244
|
+
tools: this.settings.tools,
|
|
4245
|
+
toolsContext: this.settings.toolsContext
|
|
4204
4246
|
}),
|
|
4205
4247
|
toolApprovalContinuations: (_a4 = options.toolApprovalContinuations) != null ? _a4 : [],
|
|
4206
4248
|
toolResultContinuations: (_b4 = options.toolResultContinuations) != null ? _b4 : []
|
|
4207
4249
|
};
|
|
4208
4250
|
}
|
|
4209
4251
|
_prepareTurnSettings(options) {
|
|
4210
|
-
var _a4, _b4, _c;
|
|
4252
|
+
var _a4, _b4, _c, _d;
|
|
4211
4253
|
const userTools = (_a4 = options.tools) != null ? _a4 : {};
|
|
4212
4254
|
assertNoReservedQuestionTool({
|
|
4213
4255
|
harness: this.settings.harness,
|
|
@@ -4229,6 +4271,7 @@ var HarnessAgent = class {
|
|
|
4229
4271
|
skills: (_b4 = options.skills) != null ? _b4 : [],
|
|
4230
4272
|
instructions: typeof options.instructions === "string" ? options.instructions : (_c = options.instructions) == null ? void 0 : _c.content,
|
|
4231
4273
|
tools,
|
|
4274
|
+
toolsContext: (_d = options.toolsContext) != null ? _d : {},
|
|
4232
4275
|
activeTools: toolFiltering.activeUserTools,
|
|
4233
4276
|
toolSpecs: this._toToolSpecs(toolFiltering.activeUserTools),
|
|
4234
4277
|
builtinToolFiltering: toolFiltering.builtinToolFiltering
|