@ai-sdk/harness 1.0.99 → 1.0.101
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 +19 -0
- package/agent/index.ts +2 -8
- package/dist/agent/index.d.ts +65 -46
- package/dist/agent/index.js +93 -71
- package/dist/agent/index.js.map +1 -1
- package/dist/bridge/index.d.ts +11 -1
- package/dist/bridge/index.js +37 -7
- package/dist/bridge/index.js.map +1 -1
- package/dist/index.d.ts +80 -2
- package/dist/index.js +286 -229
- package/dist/index.js.map +1 -1
- package/dist/utils/index.d.ts +9 -1
- package/dist/utils/index.js +17 -2
- package/dist/utils/index.js.map +1 -1
- package/package.json +3 -3
- package/src/agent/harness-agent-session.ts +4 -8
- package/src/agent/harness-agent-tool-approval-continuation.ts +6 -32
- package/src/agent/harness-agent-tool-result-continuation.ts +4 -53
- package/src/agent/harness-agent.ts +40 -18
- package/src/agent/internal/run-prompt.ts +100 -35
- package/src/bridge/index.ts +82 -11
- package/src/utils/sandbox-credential-brokering.ts +32 -1
- package/src/v1/harness-v1-bridge-protocol.ts +1 -0
- package/src/v1/harness-v1-builtin-tool.ts +2 -0
- package/src/v1/harness-v1-lifecycle-state.ts +2 -0
- package/src/v1/harness-v1-prompt-control.ts +3 -0
- package/src/v1/harness-v1-questions-tool.ts +72 -0
- package/src/v1/index.ts +9 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @ai-sdk/harness
|
|
2
2
|
|
|
3
|
+
## 1.0.101
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 951c54d: feat(harness): support `askUserQuestions` tool including support for normalization across harness adapters
|
|
8
|
+
- Updated dependencies [a51cc94]
|
|
9
|
+
- Updated dependencies [d1904d3]
|
|
10
|
+
- Updated dependencies [84e5a79]
|
|
11
|
+
- Updated dependencies [a8e8ad0]
|
|
12
|
+
- ai@7.0.92
|
|
13
|
+
|
|
14
|
+
## 1.0.100
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- 0c37bf0: fix(harness): avoid warning about lack of credential brokering support when `credentialForwarding` callback is used to replace all credentials with ephemeral fake secrets
|
|
19
|
+
- Updated dependencies [802af1e]
|
|
20
|
+
- ai@7.0.91
|
|
21
|
+
|
|
3
22
|
## 1.0.99
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/agent/index.ts
CHANGED
|
@@ -28,14 +28,8 @@ export type {
|
|
|
28
28
|
HarnessAgentToolSpec,
|
|
29
29
|
} from '../src/agent/harness-agent-types';
|
|
30
30
|
export { HarnessAgentSession } from '../src/agent/harness-agent-session';
|
|
31
|
-
export {
|
|
32
|
-
|
|
33
|
-
type HarnessAgentToolApprovalContinuation,
|
|
34
|
-
} from '../src/agent/harness-agent-tool-approval-continuation';
|
|
35
|
-
export {
|
|
36
|
-
collectHarnessAgentToolResultContinuations,
|
|
37
|
-
type HarnessAgentToolResultContinuation,
|
|
38
|
-
} from '../src/agent/harness-agent-tool-result-continuation';
|
|
31
|
+
export { collectHarnessAgentToolApprovalContinuations } from '../src/agent/harness-agent-tool-approval-continuation';
|
|
32
|
+
export { collectHarnessAgentToolResultContinuations } from '../src/agent/harness-agent-tool-result-continuation';
|
|
39
33
|
export {
|
|
40
34
|
prepareHarnessSandboxTemplate,
|
|
41
35
|
prewarmHarness,
|
package/dist/agent/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';
|
|
2
|
-
import { Experimental_SandboxSession, UserModelMessage, ToolSet, FlexibleSchema, Tool, Context, MaybePromiseLike, Arrayable, ToolApprovalResponse, ModelMessage } from '@ai-sdk/provider-utils';
|
|
2
|
+
import { Experimental_SandboxSession, UserModelMessage, ToolResultPart, ProviderOptions, ToolSet, FlexibleSchema, Tool, Context, MaybePromiseLike, Arrayable, ToolApprovalResponse, ModelMessage } from '@ai-sdk/provider-utils';
|
|
3
3
|
import { OutputInterface, AgentCallParameters, Prompt, StopCondition, ToolApprovalStatus, TelemetryOptions, ActiveTools, StreamTextResult, Agent, GenerateTextResult, AgentStreamParameters, Telemetry } from 'ai';
|
|
4
4
|
import { z } from 'zod/v4';
|
|
5
5
|
import { JSONSchema7, JSONValue, LanguageModelV4StreamPart, LanguageModelV4ToolCall, LanguageModelV4ToolApprovalRequest, LanguageModelV4ToolResult, LanguageModelV4FinishReason, LanguageModelV4Usage, AISDKError } from '@ai-sdk/provider';
|
|
@@ -347,6 +347,7 @@ type HarnessV1PromptControl = {
|
|
|
347
347
|
toolCallId: string;
|
|
348
348
|
output: unknown;
|
|
349
349
|
isError?: boolean;
|
|
350
|
+
toolResult?: ToolResultPart;
|
|
350
351
|
}): PromiseLike<void>;
|
|
351
352
|
/**
|
|
352
353
|
* Respond to a `tool-approval-request` the adapter emitted.
|
|
@@ -465,6 +466,7 @@ type HarnessV1PendingToolResult = {
|
|
|
465
466
|
readonly toolCallId: string;
|
|
466
467
|
readonly toolName: string;
|
|
467
468
|
readonly input: string;
|
|
469
|
+
readonly providerOptions?: ProviderOptions;
|
|
468
470
|
};
|
|
469
471
|
/**
|
|
470
472
|
* Framework-owned settings captured when a turn begins. The same settings are
|
|
@@ -1015,6 +1017,40 @@ declare const HARNESS_V1_BUILTIN_TOOLS: {
|
|
|
1015
1017
|
readonly webSearch: Tool<{
|
|
1016
1018
|
query: string;
|
|
1017
1019
|
}, unknown, _ai_sdk_provider_utils.Context>;
|
|
1020
|
+
readonly askUserQuestions: _ai_sdk_provider_utils.FunctionTool<{
|
|
1021
|
+
allowPartialAnswers: boolean;
|
|
1022
|
+
questions: {
|
|
1023
|
+
id: string;
|
|
1024
|
+
question: string;
|
|
1025
|
+
header?: string | undefined;
|
|
1026
|
+
options?: {
|
|
1027
|
+
id: string;
|
|
1028
|
+
label: string;
|
|
1029
|
+
description?: string | undefined;
|
|
1030
|
+
preview?: string | undefined;
|
|
1031
|
+
}[] | undefined;
|
|
1032
|
+
allowMultiple?: boolean | undefined;
|
|
1033
|
+
allowFreeForm?: boolean | {
|
|
1034
|
+
secret: boolean;
|
|
1035
|
+
} | undefined;
|
|
1036
|
+
}[];
|
|
1037
|
+
}, {
|
|
1038
|
+
action: "answered";
|
|
1039
|
+
answers: Record<string, {
|
|
1040
|
+
optionIds: string[];
|
|
1041
|
+
freeform?: string | undefined;
|
|
1042
|
+
}>;
|
|
1043
|
+
} | {
|
|
1044
|
+
action: "partially-answered";
|
|
1045
|
+
answers: Record<string, {
|
|
1046
|
+
optionIds: string[];
|
|
1047
|
+
freeform?: string | undefined;
|
|
1048
|
+
}>;
|
|
1049
|
+
} | {
|
|
1050
|
+
action: "declined";
|
|
1051
|
+
} | {
|
|
1052
|
+
action: "cancelled";
|
|
1053
|
+
}>;
|
|
1018
1054
|
};
|
|
1019
1055
|
type HarnessV1BuiltinToolName = keyof typeof HARNESS_V1_BUILTIN_TOOLS;
|
|
1020
1056
|
type HarnessV1BuiltinToolUseKind = 'readonly' | 'edit' | 'bash';
|
|
@@ -1391,44 +1427,6 @@ type HarnessAgentSettings<THarness extends HarnessAgentAdapter<any> = HarnessAge
|
|
|
1391
1427
|
readonly onLog?: (event: HarnessDiagnostic) => void;
|
|
1392
1428
|
} & HarnessAgentToolFilteringSettings<HarnessAllTools<THarness, TUserTools>>;
|
|
1393
1429
|
|
|
1394
|
-
type HarnessAgentToolApprovalContinuation = {
|
|
1395
|
-
readonly approvalResponse: ToolApprovalResponse;
|
|
1396
|
-
readonly toolCall: {
|
|
1397
|
-
readonly type: 'tool-call';
|
|
1398
|
-
readonly toolCallId: string;
|
|
1399
|
-
readonly toolName: string;
|
|
1400
|
-
readonly input: unknown;
|
|
1401
|
-
readonly providerExecuted?: boolean;
|
|
1402
|
-
};
|
|
1403
|
-
};
|
|
1404
|
-
/**
|
|
1405
|
-
* Extract approval decisions that should continue a suspended harness turn.
|
|
1406
|
-
*
|
|
1407
|
-
* AI SDK clients send approval decisions as a trailing `role: "tool"` message
|
|
1408
|
-
* containing `tool-approval-response` parts. The response only carries the
|
|
1409
|
-
* approval id, so the harness has to recover the matching approval request
|
|
1410
|
-
* locally to find the original tool call before it can resume the paused turn.
|
|
1411
|
-
* Responses that already have a tool result are ignored, because those
|
|
1412
|
-
* approvals were already consumed by a prior continuation.
|
|
1413
|
-
*/
|
|
1414
|
-
declare function collectHarnessAgentToolApprovalContinuations(input: {
|
|
1415
|
-
messages: readonly ModelMessage[];
|
|
1416
|
-
}): readonly HarnessAgentToolApprovalContinuation[];
|
|
1417
|
-
|
|
1418
|
-
type HarnessAgentToolResultContinuation = {
|
|
1419
|
-
readonly toolCallId: string;
|
|
1420
|
-
readonly output: unknown;
|
|
1421
|
-
readonly isError?: boolean;
|
|
1422
|
-
};
|
|
1423
|
-
/**
|
|
1424
|
-
* Extract client-provided tool results from the trailing tool message and
|
|
1425
|
-
* convert AI SDK model-output wrappers back into values a harness runtime can
|
|
1426
|
-
* return from its pending host-tool invocation.
|
|
1427
|
-
*/
|
|
1428
|
-
declare function collectHarnessAgentToolResultContinuations(input: {
|
|
1429
|
-
messages: readonly ModelMessage[];
|
|
1430
|
-
}): readonly HarnessAgentToolResultContinuation[];
|
|
1431
|
-
|
|
1432
1430
|
type HarnessAgentTurnResult<TOOLS extends ToolSet, RUNTIME_CONTEXT extends Context, OUTPUT extends OutputInterface> = {
|
|
1433
1431
|
result: StreamTextResult<TOOLS, RUNTIME_CONTEXT, OUTPUT>;
|
|
1434
1432
|
done: Promise<void>;
|
|
@@ -1519,8 +1517,8 @@ declare class HarnessAgentSession {
|
|
|
1519
1517
|
output: OUTPUT | undefined;
|
|
1520
1518
|
telemetry: TelemetryOptions | undefined;
|
|
1521
1519
|
stopConditions: ReadonlyArray<StopCondition<TOOLS, RUNTIME_CONTEXT>>;
|
|
1522
|
-
toolApprovalContinuations?: readonly
|
|
1523
|
-
toolResultContinuations?: readonly
|
|
1520
|
+
toolApprovalContinuations?: readonly ToolApprovalResponse[] | undefined;
|
|
1521
|
+
toolResultContinuations?: readonly ToolResultPart[] | undefined;
|
|
1524
1522
|
}): HarnessAgentTurnResult<TOOLS, RUNTIME_CONTEXT, OUTPUT>;
|
|
1525
1523
|
/**
|
|
1526
1524
|
* Ask the underlying runtime to compact its context. The runtime performs
|
|
@@ -1703,8 +1701,8 @@ declare class HarnessAgent<THarness extends HarnessAgentAdapter<any> = HarnessAg
|
|
|
1703
1701
|
*/
|
|
1704
1702
|
continueGenerate(options: {
|
|
1705
1703
|
session: HarnessAgentSession;
|
|
1706
|
-
toolApprovalContinuations?: readonly
|
|
1707
|
-
toolResultContinuations?: readonly
|
|
1704
|
+
toolApprovalContinuations?: readonly ToolApprovalResponse[];
|
|
1705
|
+
toolResultContinuations?: readonly ToolResultPart[];
|
|
1708
1706
|
abortSignal?: AbortSignal;
|
|
1709
1707
|
}): Promise<GenerateTextResult<HarnessAllTools<THarness, TUserTools>, RUNTIME_CONTEXT, OUTPUT>>;
|
|
1710
1708
|
/**
|
|
@@ -1717,8 +1715,8 @@ declare class HarnessAgent<THarness extends HarnessAgentAdapter<any> = HarnessAg
|
|
|
1717
1715
|
*/
|
|
1718
1716
|
continueStream(options: {
|
|
1719
1717
|
session: HarnessAgentSession;
|
|
1720
|
-
toolApprovalContinuations?: readonly
|
|
1721
|
-
toolResultContinuations?: readonly
|
|
1718
|
+
toolApprovalContinuations?: readonly ToolApprovalResponse[];
|
|
1719
|
+
toolResultContinuations?: readonly ToolResultPart[];
|
|
1722
1720
|
abortSignal?: AbortSignal;
|
|
1723
1721
|
}): Promise<StreamTextResult<HarnessAllTools<THarness, TUserTools>, RUNTIME_CONTEXT, OUTPUT>>;
|
|
1724
1722
|
/**
|
|
@@ -1745,6 +1743,27 @@ declare class HarnessAgent<THarness extends HarnessAgentAdapter<any> = HarnessAg
|
|
|
1745
1743
|
private _resolveResponseFormat;
|
|
1746
1744
|
}
|
|
1747
1745
|
|
|
1746
|
+
/**
|
|
1747
|
+
* Extract approval decisions that should continue a suspended harness turn.
|
|
1748
|
+
*
|
|
1749
|
+
* AI SDK clients send approval decisions as a trailing `role: "tool"` message
|
|
1750
|
+
* containing `tool-approval-response` parts. The response only carries the
|
|
1751
|
+
* approval id, so the harness has to recover the matching approval request
|
|
1752
|
+
* locally to find the original tool call before it can resume the paused turn.
|
|
1753
|
+
* Responses that already have a tool result are ignored, because those
|
|
1754
|
+
* approvals were already consumed by a prior continuation.
|
|
1755
|
+
*/
|
|
1756
|
+
declare function collectHarnessAgentToolApprovalContinuations(input: {
|
|
1757
|
+
messages: readonly ModelMessage[];
|
|
1758
|
+
}): readonly ToolApprovalResponse[];
|
|
1759
|
+
|
|
1760
|
+
/**
|
|
1761
|
+
* Extract client-provided tool results from the trailing tool message.
|
|
1762
|
+
*/
|
|
1763
|
+
declare function collectHarnessAgentToolResultContinuations(input: {
|
|
1764
|
+
messages: readonly ModelMessage[];
|
|
1765
|
+
}): readonly ToolResultPart[];
|
|
1766
|
+
|
|
1748
1767
|
type SandboxBootstrapSettings = Omit<HarnessAgentSandboxConfig, 'onSession'>;
|
|
1749
1768
|
/**
|
|
1750
1769
|
* Prepare a harness's sandbox template without running an agent. Idempotent: if
|
|
@@ -1902,4 +1921,4 @@ interface TraceTreeReporterOptions {
|
|
|
1902
1921
|
}
|
|
1903
1922
|
declare function createTraceTreeReporter(options?: TraceTreeReporterOptions): Telemetry;
|
|
1904
1923
|
|
|
1905
|
-
export { type FileReporter, type FileReporterOptions, HarnessAgent, type HarnessAgentAdapter, type HarnessAgentAdapterSession, type HarnessAgentBuiltinTool, type HarnessAgentBuiltinToolName, type HarnessAgentBuiltinToolUseKind, type HarnessAgentBuiltinTools, type HarnessAgentContinueTurnOptions, type HarnessAgentContinueTurnState, type HarnessAgentLifecycleState, type HarnessAgentPendingToolApproval, type HarnessAgentPendingToolResult, type HarnessAgentPermissionMode, type HarnessAgentPrompt, type HarnessAgentPromptControl, type HarnessAgentPromptTurnOptions, type HarnessAgentResumeSessionState, type HarnessAgentSandboxConfig, HarnessAgentSession, type HarnessAgentSettings, type HarnessAgentSkill, type HarnessAgentStartOptions, type HarnessAgentStreamPart, type HarnessAgentToolApprovalConfiguration, type
|
|
1924
|
+
export { type FileReporter, type FileReporterOptions, HarnessAgent, type HarnessAgentAdapter, type HarnessAgentAdapterSession, type HarnessAgentBuiltinTool, type HarnessAgentBuiltinToolName, type HarnessAgentBuiltinToolUseKind, type HarnessAgentBuiltinTools, type HarnessAgentContinueTurnOptions, type HarnessAgentContinueTurnState, type HarnessAgentLifecycleState, type HarnessAgentPendingToolApproval, type HarnessAgentPendingToolResult, type HarnessAgentPermissionMode, type HarnessAgentPrompt, type HarnessAgentPromptControl, type HarnessAgentPromptTurnOptions, type HarnessAgentResumeSessionState, type HarnessAgentSandboxConfig, HarnessAgentSession, type HarnessAgentSettings, type HarnessAgentSkill, type HarnessAgentStartOptions, type HarnessAgentStreamPart, type HarnessAgentToolApprovalConfiguration, type HarnessAgentToolSpec, type HarnessAllTools, HarnessCapabilityUnsupportedError, type HarnessDebugConfig, type HarnessDebugLevel, type HarnessDiagnostic, type HarnessDiagnosticConsumer, HarnessError, HarnessSandboxAuthenticationError, type PrepareSandboxForHarnessResult, type TraceTreeReporterOptions, collectHarnessAgentToolApprovalContinuations, collectHarnessAgentToolResultContinuations, createFileReporter, createTraceTreeReporter, getHarnessErrorMessage, prepareHarnessSandboxTemplate, prepareSandboxForHarness, prewarmHarness };
|
package/dist/agent/index.js
CHANGED
|
@@ -1556,6 +1556,25 @@ function pinSandboxChannelEventCheckpoint(event) {
|
|
|
1556
1556
|
}
|
|
1557
1557
|
|
|
1558
1558
|
// src/agent/internal/run-prompt.ts
|
|
1559
|
+
function unwrapToolResultOutput(toolResult) {
|
|
1560
|
+
switch (toolResult.output.type) {
|
|
1561
|
+
case "text":
|
|
1562
|
+
case "json":
|
|
1563
|
+
return { output: toolResult.output.value };
|
|
1564
|
+
case "error-text":
|
|
1565
|
+
case "error-json":
|
|
1566
|
+
return { output: toolResult.output.value, isError: true };
|
|
1567
|
+
case "execution-denied":
|
|
1568
|
+
return {
|
|
1569
|
+
output: {
|
|
1570
|
+
type: toolResult.output.type,
|
|
1571
|
+
reason: toolResult.output.reason
|
|
1572
|
+
}
|
|
1573
|
+
};
|
|
1574
|
+
case "content":
|
|
1575
|
+
return { output: toolResult.output };
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1559
1578
|
function runPrompt(input) {
|
|
1560
1579
|
var _a4, _b4, _c, _d, _e, _f, _g;
|
|
1561
1580
|
const result = new HarnessStreamTextResult({
|
|
@@ -1680,7 +1699,7 @@ function runPrompt(input) {
|
|
|
1680
1699
|
);
|
|
1681
1700
|
const continuationsByApprovalId = new Map(
|
|
1682
1701
|
((_b5 = input.toolApprovalContinuations) != null ? _b5 : []).map((continuation) => [
|
|
1683
|
-
continuation.
|
|
1702
|
+
continuation.approvalId,
|
|
1684
1703
|
continuation
|
|
1685
1704
|
])
|
|
1686
1705
|
);
|
|
@@ -1812,13 +1831,13 @@ function runPrompt(input) {
|
|
|
1812
1831
|
...input2.providerExecuted !== void 0 ? { providerExecuted: input2.providerExecuted } : {}
|
|
1813
1832
|
});
|
|
1814
1833
|
};
|
|
1815
|
-
const enqueueApprovalResponse = (approval, continuation) => {
|
|
1834
|
+
const enqueueApprovalResponse = (approval, continuation, toolCall) => {
|
|
1816
1835
|
result.enqueueContinuation({
|
|
1817
1836
|
type: "tool-approval-response",
|
|
1818
1837
|
approvalId: approval.approvalId,
|
|
1819
|
-
toolCall
|
|
1820
|
-
approved: continuation.
|
|
1821
|
-
...continuation.
|
|
1838
|
+
toolCall,
|
|
1839
|
+
approved: continuation.approved,
|
|
1840
|
+
...continuation.reason !== void 0 ? { reason: continuation.reason } : {},
|
|
1822
1841
|
...approval.providerExecuted !== void 0 ? { providerExecuted: approval.providerExecuted } : {}
|
|
1823
1842
|
});
|
|
1824
1843
|
};
|
|
@@ -1827,20 +1846,27 @@ function runPrompt(input) {
|
|
|
1827
1846
|
const pendingResult = (_a6 = pendingResultsByToolCallId.get(options.toolCall.toolCallId)) != null ? _a6 : {
|
|
1828
1847
|
toolCallId: options.toolCall.toolCallId,
|
|
1829
1848
|
toolName: options.toolCall.toolName,
|
|
1830
|
-
input: options.toolCall.input
|
|
1849
|
+
input: options.toolCall.input,
|
|
1850
|
+
...options.toolCall.providerMetadata !== void 0 ? { providerOptions: options.toolCall.providerMetadata } : {}
|
|
1831
1851
|
};
|
|
1832
1852
|
pendingResultsByToolCallId.set(pendingResult.toolCallId, pendingResult);
|
|
1833
1853
|
onPendingToolResult(pendingResult);
|
|
1834
1854
|
return pendingResult;
|
|
1835
1855
|
};
|
|
1836
1856
|
const processPendingToolResultContinuation = async (pendingResult, continuation) => {
|
|
1857
|
+
const result2 = unwrapToolResultOutput(continuation);
|
|
1837
1858
|
onToolResultSettled(pendingResult.toolCallId);
|
|
1838
1859
|
pendingResultsByToolCallId.delete(pendingResult.toolCallId);
|
|
1839
1860
|
settledHostToolCallIds.add(pendingResult.toolCallId);
|
|
1840
1861
|
await control.submitToolResult({
|
|
1841
1862
|
toolCallId: pendingResult.toolCallId,
|
|
1842
|
-
output:
|
|
1843
|
-
isError:
|
|
1863
|
+
output: result2.output,
|
|
1864
|
+
isError: result2.isError,
|
|
1865
|
+
toolResult: {
|
|
1866
|
+
...continuation,
|
|
1867
|
+
toolName: pendingResult.toolName,
|
|
1868
|
+
...continuation.providerOptions == null && pendingResult.providerOptions != null ? { providerOptions: pendingResult.providerOptions } : {}
|
|
1869
|
+
}
|
|
1844
1870
|
});
|
|
1845
1871
|
};
|
|
1846
1872
|
const enqueueHostToolOutcome = (options) => {
|
|
@@ -1873,7 +1899,23 @@ function runPrompt(input) {
|
|
|
1873
1899
|
};
|
|
1874
1900
|
const processPendingApprovalContinuation = async (approval, continuation) => {
|
|
1875
1901
|
var _a6;
|
|
1876
|
-
|
|
1902
|
+
const rawToolCall = (_a6 = rawToolCallsByToolCallId.get(approval.toolCallId)) != null ? _a6 : {
|
|
1903
|
+
type: "tool-call",
|
|
1904
|
+
toolCallId: approval.toolCallId,
|
|
1905
|
+
toolName: approval.toolName,
|
|
1906
|
+
input: approval.input,
|
|
1907
|
+
providerExecuted: approval.providerExecuted,
|
|
1908
|
+
nativeName: approval.nativeName
|
|
1909
|
+
};
|
|
1910
|
+
const parsedInput = await safeParseJSON2({ text: rawToolCall.input });
|
|
1911
|
+
const toolCall = {
|
|
1912
|
+
type: "tool-call",
|
|
1913
|
+
toolCallId: rawToolCall.toolCallId,
|
|
1914
|
+
toolName: rawToolCall.toolName,
|
|
1915
|
+
input: parsedInput.success ? parsedInput.value : rawToolCall.input,
|
|
1916
|
+
...rawToolCall.providerExecuted !== void 0 ? { providerExecuted: rawToolCall.providerExecuted } : {}
|
|
1917
|
+
};
|
|
1918
|
+
enqueueApprovalResponse(approval, continuation, toolCall);
|
|
1877
1919
|
onToolApprovalSettled(approval.approvalId);
|
|
1878
1920
|
pendingApprovalsByApprovalId.delete(approval.approvalId);
|
|
1879
1921
|
pendingApprovalsByToolCallId.delete(approval.toolCallId);
|
|
@@ -1886,28 +1928,22 @@ function runPrompt(input) {
|
|
|
1886
1928
|
}
|
|
1887
1929
|
await control.submitToolApproval({
|
|
1888
1930
|
approvalId: approval.approvalId,
|
|
1889
|
-
approved: continuation.
|
|
1890
|
-
reason: continuation.
|
|
1931
|
+
approved: continuation.approved,
|
|
1932
|
+
reason: continuation.reason
|
|
1891
1933
|
});
|
|
1892
1934
|
return "continued";
|
|
1893
1935
|
}
|
|
1894
1936
|
settledHostToolCallIds.add(approval.toolCallId);
|
|
1895
|
-
if (!continuation.
|
|
1937
|
+
if (!continuation.approved) {
|
|
1896
1938
|
await control.submitToolResult({
|
|
1897
1939
|
toolCallId: approval.toolCallId,
|
|
1898
1940
|
output: {
|
|
1899
1941
|
type: "execution-denied",
|
|
1900
|
-
reason: continuation.
|
|
1942
|
+
reason: continuation.reason
|
|
1901
1943
|
}
|
|
1902
1944
|
});
|
|
1903
1945
|
return "continued";
|
|
1904
1946
|
}
|
|
1905
|
-
const rawToolCall = (_a6 = rawToolCallsByToolCallId.get(approval.toolCallId)) != null ? _a6 : {
|
|
1906
|
-
type: "tool-call",
|
|
1907
|
-
toolCallId: approval.toolCallId,
|
|
1908
|
-
toolName: approval.toolName,
|
|
1909
|
-
input: approval.input
|
|
1910
|
-
};
|
|
1911
1947
|
await telemetry.start(input.model);
|
|
1912
1948
|
await telemetry.toolStart({
|
|
1913
1949
|
toolCallId: rawToolCall.toolCallId,
|
|
@@ -1947,7 +1983,7 @@ function runPrompt(input) {
|
|
|
1947
1983
|
return "awaiting-tool-result";
|
|
1948
1984
|
}
|
|
1949
1985
|
enqueueHostToolOutcome({
|
|
1950
|
-
toolCall
|
|
1986
|
+
toolCall,
|
|
1951
1987
|
outcome: execution.outcome
|
|
1952
1988
|
});
|
|
1953
1989
|
await telemetry.toolEnd(rawToolCall.toolCallId, execution.outcome);
|
|
@@ -2200,7 +2236,11 @@ function runPrompt(input) {
|
|
|
2200
2236
|
`Harness '${input.harness.harnessId}' could not find parsed tool call '${toolCall.toolCallId}' for custom tool approval.`
|
|
2201
2237
|
);
|
|
2202
2238
|
}
|
|
2203
|
-
|
|
2239
|
+
const isClientExecutedBuiltin = toolCall.toolName === "askUserQuestions" && Object.prototype.hasOwnProperty.call(
|
|
2240
|
+
input.harness.builtinTools,
|
|
2241
|
+
toolCall.toolName
|
|
2242
|
+
);
|
|
2243
|
+
if (!isClientExecutedBuiltin && !hasTool({ tools: activeTools, toolName: toolCall.toolName })) {
|
|
2204
2244
|
const output = {
|
|
2205
2245
|
type: "execution-denied",
|
|
2206
2246
|
reason: getHarnessV1BuiltinToolFilteringDenialReason({
|
|
@@ -2214,6 +2254,15 @@ function runPrompt(input) {
|
|
|
2214
2254
|
await telemetry.toolEnd(toolCall.toolCallId, { ok: true, output });
|
|
2215
2255
|
continue;
|
|
2216
2256
|
}
|
|
2257
|
+
if (isClientExecutedBuiltin) {
|
|
2258
|
+
recordPendingToolResult({ toolCall });
|
|
2259
|
+
if (expectedStepToolCallCount != null && observedStepToolCallCount < expectedStepToolCallCount) {
|
|
2260
|
+
pauseAfterStepToolCalls = true;
|
|
2261
|
+
continue;
|
|
2262
|
+
}
|
|
2263
|
+
await finishForHostInputPause({ completeCurrentStep: true });
|
|
2264
|
+
return;
|
|
2265
|
+
}
|
|
2217
2266
|
const customToolApprovalDecision = resolveCustomToolApproval({
|
|
2218
2267
|
toolName: toolCall.toolName,
|
|
2219
2268
|
toolApproval: input.toolApproval
|
|
@@ -3030,7 +3079,7 @@ var HarnessAgentSession = class {
|
|
|
3030
3079
|
function collectHarnessAgentToolApprovalContinuations(input) {
|
|
3031
3080
|
const lastMessage = input.messages.at(-1);
|
|
3032
3081
|
if ((lastMessage == null ? void 0 : lastMessage.role) !== "tool") return [];
|
|
3033
|
-
const
|
|
3082
|
+
const toolCallIds = /* @__PURE__ */ new Set();
|
|
3034
3083
|
const approvalRequestsByApprovalId = /* @__PURE__ */ new Map();
|
|
3035
3084
|
for (const message of input.messages) {
|
|
3036
3085
|
if (message.role !== "assistant" || typeof message.content === "string") {
|
|
@@ -3038,13 +3087,7 @@ function collectHarnessAgentToolApprovalContinuations(input) {
|
|
|
3038
3087
|
}
|
|
3039
3088
|
for (const part of message.content) {
|
|
3040
3089
|
if (part.type === "tool-call") {
|
|
3041
|
-
|
|
3042
|
-
type: "tool-call",
|
|
3043
|
-
toolCallId: part.toolCallId,
|
|
3044
|
-
toolName: part.toolName,
|
|
3045
|
-
input: part.input,
|
|
3046
|
-
...part.providerExecuted !== void 0 ? { providerExecuted: part.providerExecuted } : {}
|
|
3047
|
-
});
|
|
3090
|
+
toolCallIds.add(part.toolCallId);
|
|
3048
3091
|
} else if (part.type === "tool-approval-request") {
|
|
3049
3092
|
approvalRequestsByApprovalId.set(part.approvalId, part);
|
|
3050
3093
|
}
|
|
@@ -3066,16 +3109,12 @@ function collectHarnessAgentToolApprovalContinuations(input) {
|
|
|
3066
3109
|
});
|
|
3067
3110
|
}
|
|
3068
3111
|
if (toolResultIds.has(approvalRequest.toolCallId)) continue;
|
|
3069
|
-
|
|
3070
|
-
if (toolCall == null) {
|
|
3112
|
+
if (!toolCallIds.has(approvalRequest.toolCallId)) {
|
|
3071
3113
|
throw new HarnessError({
|
|
3072
3114
|
message: `Tool approval request '${approvalRequest.approvalId}' references unknown tool call '${approvalRequest.toolCallId}'.`
|
|
3073
3115
|
});
|
|
3074
3116
|
}
|
|
3075
|
-
continuations.push(
|
|
3076
|
-
approvalResponse: part,
|
|
3077
|
-
toolCall
|
|
3078
|
-
});
|
|
3117
|
+
continuations.push(part);
|
|
3079
3118
|
}
|
|
3080
3119
|
return continuations;
|
|
3081
3120
|
}
|
|
@@ -3084,42 +3123,7 @@ function collectHarnessAgentToolApprovalContinuations(input) {
|
|
|
3084
3123
|
function collectHarnessAgentToolResultContinuations(input) {
|
|
3085
3124
|
const lastMessage = input.messages.at(-1);
|
|
3086
3125
|
if ((lastMessage == null ? void 0 : lastMessage.role) !== "tool") return [];
|
|
3087
|
-
return lastMessage.content.filter((part) => part.type === "tool-result")
|
|
3088
|
-
(part) => toToolResultContinuation({
|
|
3089
|
-
toolCallId: part.toolCallId,
|
|
3090
|
-
output: part.output
|
|
3091
|
-
})
|
|
3092
|
-
);
|
|
3093
|
-
}
|
|
3094
|
-
function toToolResultContinuation(input) {
|
|
3095
|
-
switch (input.output.type) {
|
|
3096
|
-
case "text":
|
|
3097
|
-
case "json":
|
|
3098
|
-
return {
|
|
3099
|
-
toolCallId: input.toolCallId,
|
|
3100
|
-
output: input.output.value
|
|
3101
|
-
};
|
|
3102
|
-
case "error-text":
|
|
3103
|
-
case "error-json":
|
|
3104
|
-
return {
|
|
3105
|
-
toolCallId: input.toolCallId,
|
|
3106
|
-
output: input.output.value,
|
|
3107
|
-
isError: true
|
|
3108
|
-
};
|
|
3109
|
-
case "execution-denied":
|
|
3110
|
-
return {
|
|
3111
|
-
toolCallId: input.toolCallId,
|
|
3112
|
-
output: {
|
|
3113
|
-
type: input.output.type,
|
|
3114
|
-
reason: input.output.reason
|
|
3115
|
-
}
|
|
3116
|
-
};
|
|
3117
|
-
case "content":
|
|
3118
|
-
return {
|
|
3119
|
-
toolCallId: input.toolCallId,
|
|
3120
|
-
output: input.output
|
|
3121
|
-
};
|
|
3122
|
-
}
|
|
3126
|
+
return lastMessage.content.filter((part) => part.type === "tool-result");
|
|
3123
3127
|
}
|
|
3124
3128
|
|
|
3125
3129
|
// src/agent/internal/bootstrap-recipe.ts
|
|
@@ -3582,6 +3586,10 @@ var HarnessAgent = class {
|
|
|
3582
3586
|
this.sandboxConfig = sandboxConfig;
|
|
3583
3587
|
this.id = settings.id;
|
|
3584
3588
|
const userTools = (_a4 = settings.tools) != null ? _a4 : {};
|
|
3589
|
+
assertNoReservedQuestionTool({
|
|
3590
|
+
harness: settings.harness,
|
|
3591
|
+
userTools
|
|
3592
|
+
});
|
|
3585
3593
|
this.permissionMode = resolvePermissionMode({
|
|
3586
3594
|
permissionMode: settings.permissionMode
|
|
3587
3595
|
});
|
|
@@ -4059,6 +4067,10 @@ var HarnessAgent = class {
|
|
|
4059
4067
|
_prepareTurnSettings(options) {
|
|
4060
4068
|
var _a4, _b4;
|
|
4061
4069
|
const userTools = (_a4 = options.tools) != null ? _a4 : {};
|
|
4070
|
+
assertNoReservedQuestionTool({
|
|
4071
|
+
harness: this.settings.harness,
|
|
4072
|
+
userTools
|
|
4073
|
+
});
|
|
4062
4074
|
const tools = {
|
|
4063
4075
|
...this.settings.harness.builtinTools,
|
|
4064
4076
|
...userTools
|
|
@@ -4127,6 +4139,16 @@ var HarnessAgent = class {
|
|
|
4127
4139
|
};
|
|
4128
4140
|
}
|
|
4129
4141
|
};
|
|
4142
|
+
function assertNoReservedQuestionTool(input) {
|
|
4143
|
+
if (Object.prototype.hasOwnProperty.call(
|
|
4144
|
+
input.harness.builtinTools,
|
|
4145
|
+
"askUserQuestions"
|
|
4146
|
+
) && Object.prototype.hasOwnProperty.call(input.userTools, "askUserQuestions")) {
|
|
4147
|
+
throw new Error(
|
|
4148
|
+
"HarnessAgent tool name 'askUserQuestions' is reserved for harness question requests."
|
|
4149
|
+
);
|
|
4150
|
+
}
|
|
4151
|
+
}
|
|
4130
4152
|
var HarnessGenerateTextResult = class {
|
|
4131
4153
|
constructor(options) {
|
|
4132
4154
|
this.steps = options.steps;
|