@ai-sdk/harness 1.0.167 → 1.0.169
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 +27 -0
- package/dist/agent/index.js +79 -14
- package/dist/agent/index.js.map +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +10 -4
- package/dist/utils/index.js.map +1 -1
- package/package.json +5 -5
- package/src/agent/internal/run-prompt.ts +98 -15
- package/src/utils/sandbox-channel.ts +15 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# @ai-sdk/harness
|
|
2
2
|
|
|
3
|
+
## 1.0.169
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [7716e18]
|
|
8
|
+
- Updated dependencies [8ba3a5c]
|
|
9
|
+
- Updated dependencies [5c247e9]
|
|
10
|
+
- Updated dependencies [dcd2f8d]
|
|
11
|
+
- @ai-sdk/provider-utils@5.0.72
|
|
12
|
+
- ai@7.0.158
|
|
13
|
+
- @ai-sdk/provider@4.0.35
|
|
14
|
+
|
|
15
|
+
## 1.0.168
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- 033f8d9: fix(harness): preserve execution-denied outputs for denied host tool calls without invoking the tool's `toModelOutput` converter
|
|
20
|
+
- e7a8988: fix(harness): preserve differing runtime-native tool names in `providerMetadata[harnessId].nativeToolName` on tool calls and their approval requests
|
|
21
|
+
- 2c12e25: fix(harness): fix completed host tool results being silently lost when a WebSocket enters CLOSING before the channel detects the disconnect
|
|
22
|
+
- 6eab0f7: Fix turns hanging when a built-in tool approval and a host tool call share an assistant message. Pause for the approval without waiting for runtime echoes of completed host tools, preserving their results and original call metadata across consecutive approval pauses and session resumes until the runtime echo arrives, without executing them again or emitting duplicate results.
|
|
23
|
+
- Updated dependencies [0cc4921]
|
|
24
|
+
- Updated dependencies [61a315e]
|
|
25
|
+
- Updated dependencies [077cfb3]
|
|
26
|
+
- Updated dependencies [eb768e2]
|
|
27
|
+
- ai@7.0.157
|
|
28
|
+
- @ai-sdk/provider-utils@5.0.71
|
|
29
|
+
|
|
3
30
|
## 1.0.167
|
|
4
31
|
|
|
5
32
|
### Patch Changes
|
package/dist/agent/index.js
CHANGED
|
@@ -1744,6 +1744,7 @@ function runPrompt(input) {
|
|
|
1744
1744
|
let deferredPauseFinishStep;
|
|
1745
1745
|
let ignoredFinishStep;
|
|
1746
1746
|
const hostToolCallIdsAwaitingEcho = /* @__PURE__ */ new Set();
|
|
1747
|
+
const submittedHostToolResults = /* @__PURE__ */ new Map();
|
|
1747
1748
|
const buildModelCallContent = () => {
|
|
1748
1749
|
const parts = [];
|
|
1749
1750
|
if (stepText) parts.push({
|
|
@@ -1815,6 +1816,34 @@ function runPrompt(input) {
|
|
|
1815
1816
|
};
|
|
1816
1817
|
const pauseForHostInput = async (finishStep) => {
|
|
1817
1818
|
await waitForOutstandingHostToolExecutions();
|
|
1819
|
+
for (const submission of submittedHostToolResults.values()) {
|
|
1820
|
+
const { toolCallId, ...completedResult } = submission;
|
|
1821
|
+
const rawToolCall = rawToolCallsByToolCallId.get(toolCallId);
|
|
1822
|
+
const toolCall = toolCallsByToolCallId.get(toolCallId);
|
|
1823
|
+
const pendingResult = pendingResultsByToolCallId.get(toolCallId) ?? (rawToolCall == null ? void 0 : {
|
|
1824
|
+
toolCallId,
|
|
1825
|
+
toolName: rawToolCall.toolName,
|
|
1826
|
+
input: rawToolCall.input,
|
|
1827
|
+
...rawToolCall.providerMetadata !== void 0 ? { providerOptions: rawToolCall.providerMetadata } : {}
|
|
1828
|
+
});
|
|
1829
|
+
if (pendingResult == null) continue;
|
|
1830
|
+
onPendingToolResult({
|
|
1831
|
+
...pendingResult,
|
|
1832
|
+
completedResult
|
|
1833
|
+
});
|
|
1834
|
+
const toolOutput = toolExecutions.get(toolCallId)?.toolOutput;
|
|
1835
|
+
if (toolCall != null && toolOutput != null && !settledHostToolCallIds.has(toolCallId)) enqueueHostToolOutcome({
|
|
1836
|
+
toolCall,
|
|
1837
|
+
outcome: toolOutput.type === "tool-error" ? {
|
|
1838
|
+
ok: false,
|
|
1839
|
+
error: toolOutput.error
|
|
1840
|
+
} : {
|
|
1841
|
+
ok: true,
|
|
1842
|
+
output: toolOutput.output
|
|
1843
|
+
},
|
|
1844
|
+
isContinuation: false
|
|
1845
|
+
});
|
|
1846
|
+
}
|
|
1818
1847
|
closingResumedStep = false;
|
|
1819
1848
|
await completeStep({
|
|
1820
1849
|
finishReason: toolCallsFinishReason,
|
|
@@ -1865,6 +1894,10 @@ function runPrompt(input) {
|
|
|
1865
1894
|
return pendingResult;
|
|
1866
1895
|
};
|
|
1867
1896
|
const enqueueHostToolOutcome = (options) => {
|
|
1897
|
+
const enqueue = (part) => {
|
|
1898
|
+
if (options.isContinuation === false) result.enqueue(part);
|
|
1899
|
+
else result.enqueueContinuation(part);
|
|
1900
|
+
};
|
|
1868
1901
|
if (options.outcome.ok) {
|
|
1869
1902
|
const stripped = stripWorkDir({
|
|
1870
1903
|
type: "tool-result",
|
|
@@ -1872,7 +1905,7 @@ function runPrompt(input) {
|
|
|
1872
1905
|
toolName: options.toolCall.toolName,
|
|
1873
1906
|
result: options.outcome.output
|
|
1874
1907
|
}, input.sessionWorkDir);
|
|
1875
|
-
|
|
1908
|
+
enqueue({
|
|
1876
1909
|
type: "tool-result",
|
|
1877
1910
|
toolCallId: options.toolCall.toolCallId,
|
|
1878
1911
|
toolName: options.toolCall.toolName,
|
|
@@ -1881,7 +1914,7 @@ function runPrompt(input) {
|
|
|
1881
1914
|
});
|
|
1882
1915
|
return;
|
|
1883
1916
|
}
|
|
1884
|
-
|
|
1917
|
+
enqueue({
|
|
1885
1918
|
type: "tool-error",
|
|
1886
1919
|
toolCallId: options.toolCall.toolCallId,
|
|
1887
1920
|
toolName: options.toolCall.toolName,
|
|
@@ -1915,6 +1948,7 @@ function runPrompt(input) {
|
|
|
1915
1948
|
}
|
|
1916
1949
|
if (!input.isTurnSuspending?.()) {
|
|
1917
1950
|
if (!settledHostToolCallIds.has(submission.toolCallId)) hostToolCallIdsAwaitingEcho.add(submission.toolCallId);
|
|
1951
|
+
submittedHostToolResults.set(submission.toolCallId, submission);
|
|
1918
1952
|
return control.submitToolResult(submission);
|
|
1919
1953
|
}
|
|
1920
1954
|
const toolCall = rawToolCallsByToolCallId.get(submission.toolCallId) ?? pendingResultsByToolCallId.get(submission.toolCallId) ?? pendingToolApprovals.find((approval) => approval.toolCallId === submission.toolCallId);
|
|
@@ -1954,7 +1988,6 @@ function runPrompt(input) {
|
|
|
1954
1988
|
toolCallId: pendingResult.toolCallId,
|
|
1955
1989
|
...submission
|
|
1956
1990
|
});
|
|
1957
|
-
pendingResultsByToolCallId.delete(pendingResult.toolCallId);
|
|
1958
1991
|
};
|
|
1959
1992
|
const processPendingApprovalContinuation = async (approval, continuation) => {
|
|
1960
1993
|
const rawToolCall = (approval.kind === "builtin" ? rawToolCallsByToolCallId.get(approval.toolCallId) : void 0) ?? {
|
|
@@ -1970,7 +2003,8 @@ function runPrompt(input) {
|
|
|
1970
2003
|
if (approval.kind === "custom" && continuation.approved) {
|
|
1971
2004
|
validatedToolCall = asToolCallTextStreamPart({ part: await validateToolCall({
|
|
1972
2005
|
event: rawToolCall,
|
|
1973
|
-
tools: input.tools
|
|
2006
|
+
tools: input.tools,
|
|
2007
|
+
harnessId: input.harness.harnessId
|
|
1974
2008
|
}) });
|
|
1975
2009
|
toolCall = displayHostToolCall({
|
|
1976
2010
|
toolCall: validatedToolCall,
|
|
@@ -2002,11 +2036,18 @@ function runPrompt(input) {
|
|
|
2002
2036
|
}
|
|
2003
2037
|
settledHostToolCallIds.add(approval.toolCallId);
|
|
2004
2038
|
if (!continuation.approved) {
|
|
2039
|
+
const output = {
|
|
2040
|
+
type: "execution-denied",
|
|
2041
|
+
reason: continuation.reason
|
|
2042
|
+
};
|
|
2005
2043
|
await submitToolResult({
|
|
2006
2044
|
toolCallId: approval.toolCallId,
|
|
2007
|
-
output
|
|
2008
|
-
|
|
2009
|
-
|
|
2045
|
+
output,
|
|
2046
|
+
toolResult: {
|
|
2047
|
+
type: "tool-result",
|
|
2048
|
+
toolCallId: approval.toolCallId,
|
|
2049
|
+
toolName: approval.toolName,
|
|
2050
|
+
output
|
|
2010
2051
|
}
|
|
2011
2052
|
});
|
|
2012
2053
|
return "continued";
|
|
@@ -2109,7 +2150,11 @@ function runPrompt(input) {
|
|
|
2109
2150
|
result.enqueueRaw(value.rawValue);
|
|
2110
2151
|
continue;
|
|
2111
2152
|
}
|
|
2112
|
-
if (value.type === "tool-result")
|
|
2153
|
+
if (value.type === "tool-result") {
|
|
2154
|
+
hostToolCallIdsAwaitingEcho.delete(value.toolCallId);
|
|
2155
|
+
submittedHostToolResults.delete(value.toolCallId);
|
|
2156
|
+
pendingResultsByToolCallId.delete(value.toolCallId);
|
|
2157
|
+
}
|
|
2113
2158
|
if (pendingStopBoundary != null) {
|
|
2114
2159
|
if (value.type === "finish") releasePendingStopBoundary();
|
|
2115
2160
|
else if ((await Promise.all(input.stopConditions.map((condition) => condition({ steps: completedSteps })))).some(Boolean)) {
|
|
@@ -2142,7 +2187,7 @@ function runPrompt(input) {
|
|
|
2142
2187
|
if (value.type === "finish-step") {
|
|
2143
2188
|
if (hostInputPauseRequested) {
|
|
2144
2189
|
await waitForOutstandingHostToolExecutions();
|
|
2145
|
-
if (hostToolCallIdsAwaitingEcho.size === 0) {
|
|
2190
|
+
if (hostToolCallIdsAwaitingEcho.size === 0 || [...pendingApprovalsByApprovalId.values()].some((approval) => approval.kind === "builtin")) {
|
|
2146
2191
|
await pauseForHostInput(value);
|
|
2147
2192
|
return;
|
|
2148
2193
|
}
|
|
@@ -2236,7 +2281,8 @@ function runPrompt(input) {
|
|
|
2236
2281
|
});
|
|
2237
2282
|
const parsedToolCall = asToolCallTextStreamPart({ part: await validateToolCall({
|
|
2238
2283
|
event: isHostTool ? value : displayValue,
|
|
2239
|
-
tools: isFilteredBuiltinDynamicCall ? void 0 : input.tools
|
|
2284
|
+
tools: isFilteredBuiltinDynamicCall ? void 0 : input.tools,
|
|
2285
|
+
harnessId: input.harness.harnessId
|
|
2240
2286
|
}) });
|
|
2241
2287
|
validatedHostToolCall = isHostTool ? parsedToolCall : void 0;
|
|
2242
2288
|
const displayToolCall = isHostTool ? displayHostToolCall({
|
|
@@ -2338,7 +2384,13 @@ function runPrompt(input) {
|
|
|
2338
2384
|
};
|
|
2339
2385
|
await submitToolResult({
|
|
2340
2386
|
toolCallId: toolCall.toolCallId,
|
|
2341
|
-
output
|
|
2387
|
+
output,
|
|
2388
|
+
toolResult: {
|
|
2389
|
+
type: "tool-result",
|
|
2390
|
+
toolCallId: toolCall.toolCallId,
|
|
2391
|
+
toolName: toolCall.toolName,
|
|
2392
|
+
output
|
|
2393
|
+
}
|
|
2342
2394
|
});
|
|
2343
2395
|
const execution = toolExecutions.get(toolCall.toolCallId);
|
|
2344
2396
|
if (execution != null) execution.toolOutput = toToolOutput({
|
|
@@ -2402,7 +2454,13 @@ function runPrompt(input) {
|
|
|
2402
2454
|
if (execution != null) await publishToolExecutionStart(execution);
|
|
2403
2455
|
await submitToolResult({
|
|
2404
2456
|
toolCallId: toolCall.toolCallId,
|
|
2405
|
-
output
|
|
2457
|
+
output,
|
|
2458
|
+
toolResult: {
|
|
2459
|
+
type: "tool-result",
|
|
2460
|
+
toolCallId: toolCall.toolCallId,
|
|
2461
|
+
toolName: toolCall.toolName,
|
|
2462
|
+
output
|
|
2463
|
+
}
|
|
2406
2464
|
});
|
|
2407
2465
|
if (execution != null) {
|
|
2408
2466
|
execution.toolOutput = toToolOutput({
|
|
@@ -2657,7 +2715,14 @@ async function maybeExecuteHostTool(input) {
|
|
|
2657
2715
|
}
|
|
2658
2716
|
}
|
|
2659
2717
|
async function validateToolCall(args) {
|
|
2660
|
-
const { event, tools } = args;
|
|
2718
|
+
const { event, tools, harnessId } = args;
|
|
2719
|
+
const providerMetadata = event.nativeName !== void 0 && event.nativeName !== event.toolName ? {
|
|
2720
|
+
...event.providerMetadata,
|
|
2721
|
+
[harnessId]: {
|
|
2722
|
+
...event.providerMetadata?.[harnessId],
|
|
2723
|
+
nativeToolName: event.nativeName
|
|
2724
|
+
}
|
|
2725
|
+
} : event.providerMetadata;
|
|
2661
2726
|
const toolCall = {
|
|
2662
2727
|
type: "tool-call",
|
|
2663
2728
|
toolCallId: event.toolCallId,
|
|
@@ -2665,7 +2730,7 @@ async function validateToolCall(args) {
|
|
|
2665
2730
|
input: event.input,
|
|
2666
2731
|
...event.providerExecuted !== void 0 ? { providerExecuted: event.providerExecuted } : {},
|
|
2667
2732
|
...event.dynamic !== void 0 ? { dynamic: event.dynamic } : {},
|
|
2668
|
-
...
|
|
2733
|
+
...providerMetadata !== void 0 ? { providerMetadata } : {}
|
|
2669
2734
|
};
|
|
2670
2735
|
return await parseToolCall({
|
|
2671
2736
|
toolCall,
|