@ai-sdk/harness 1.0.10 → 1.0.12
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 +13 -0
- package/agent/index.ts +1 -0
- package/dist/agent/index.d.ts +57 -11
- package/dist/agent/index.js +151 -15
- package/dist/agent/index.js.map +1 -1
- package/dist/index.d.ts +46 -1
- package/dist/index.js +28 -2
- package/dist/index.js.map +1 -1
- package/dist/utils/index.d.ts +60 -2
- package/dist/utils/index.js +144 -2
- package/dist/utils/index.js.map +1 -1
- package/package.json +2 -2
- package/src/agent/harness-agent-session.ts +9 -0
- package/src/agent/harness-agent-settings.ts +23 -2
- package/src/agent/harness-agent-tool-types.ts +15 -0
- package/src/agent/harness-agent.ts +29 -18
- package/src/agent/internal/run-prompt.ts +67 -10
- package/src/agent/internal/tool-filtering.ts +114 -0
- package/src/utils/index.ts +7 -0
- package/src/utils/sandbox-home-dir.ts +22 -0
- package/src/utils/shell-quote.ts +3 -0
- package/src/utils/write-skills.ts +141 -0
- package/src/v1/harness-v1-bridge-protocol.ts +15 -0
- package/src/v1/harness-v1-session.ts +8 -0
- package/src/v1/harness-v1-tool-filtering.ts +25 -0
- package/src/v1/harness-v1.ts +11 -0
- package/src/v1/index.ts +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @ai-sdk/harness
|
|
2
2
|
|
|
3
|
+
## 1.0.12
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7859cea: feat(harness): add tool filtering via `activeTools` and `inactiveTools`
|
|
8
|
+
- c857346: feat(harness): add utility functions for certain duplicated layers in harnesses
|
|
9
|
+
|
|
10
|
+
## 1.0.11
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- ai@7.0.9
|
|
15
|
+
|
|
3
16
|
## 1.0.10
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/agent/index.ts
CHANGED
package/dist/agent/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';
|
|
2
2
|
import { Experimental_SandboxSession, UserModelMessage, ToolSet, FlexibleSchema, Tool, ToolApprovalResponse, ModelMessage, Context } from '@ai-sdk/provider-utils';
|
|
3
|
-
import { ToolApprovalStatus, TelemetryOptions, StreamTextResult, Agent, AgentCallParameters, GenerateTextResult, AgentStreamParameters, Telemetry } from 'ai';
|
|
3
|
+
import { ToolApprovalStatus, TelemetryOptions, ActiveTools, StreamTextResult, Agent, AgentCallParameters, GenerateTextResult, AgentStreamParameters, Telemetry } from 'ai';
|
|
4
4
|
import { z } from 'zod/v4';
|
|
5
5
|
import { JSONValue, LanguageModelV4ToolCall, LanguageModelV4ToolApprovalRequest, LanguageModelV4ToolResult, LanguageModelV4FinishReason, LanguageModelV4Usage, JSONSchema7, AISDKError } from '@ai-sdk/provider';
|
|
6
6
|
|
|
@@ -585,6 +585,14 @@ type HarnessV1ToolSpec = {
|
|
|
585
585
|
readonly inputSchema?: JSONSchema7;
|
|
586
586
|
};
|
|
587
587
|
|
|
588
|
+
type HarnessV1BuiltinToolFiltering = {
|
|
589
|
+
mode: 'allow';
|
|
590
|
+
toolNames: string[];
|
|
591
|
+
} | {
|
|
592
|
+
mode: 'deny';
|
|
593
|
+
toolNames: string[];
|
|
594
|
+
};
|
|
595
|
+
|
|
588
596
|
/**
|
|
589
597
|
* Options passed to `HarnessV1.doStart`.
|
|
590
598
|
*
|
|
@@ -622,6 +630,12 @@ type HarnessV1StartOptions = {
|
|
|
622
630
|
* the adapter.
|
|
623
631
|
*/
|
|
624
632
|
readonly permissionMode?: HarnessV1PermissionMode;
|
|
633
|
+
/**
|
|
634
|
+
* Adapter-native built-in tools that should be available for this session.
|
|
635
|
+
* Custom host-executed tools are filtered by the framework before they reach
|
|
636
|
+
* the adapter.
|
|
637
|
+
*/
|
|
638
|
+
readonly builtinToolFiltering?: HarnessV1BuiltinToolFiltering;
|
|
625
639
|
/**
|
|
626
640
|
* Signal that aborts startup. The adapter must propagate cancellation to
|
|
627
641
|
* any spawned processes or network calls.
|
|
@@ -858,6 +872,16 @@ type HarnessV1<TBuiltinTools extends ToolSet = ToolSet> = {
|
|
|
858
872
|
* only describes adapter-native tool approval support.
|
|
859
873
|
*/
|
|
860
874
|
readonly supportsBuiltinToolApprovals?: boolean;
|
|
875
|
+
/**
|
|
876
|
+
* Whether the adapter can prevent its underlying runtime from seeing or
|
|
877
|
+
* calling inactive built-in tools for every tool in `builtinTools`.
|
|
878
|
+
*
|
|
879
|
+
* Adapters without native filtering can still support `activeTools` and
|
|
880
|
+
* `inactiveTools` for built-ins when `supportsBuiltinToolApprovals` is
|
|
881
|
+
* `true`: the framework routes inactive built-in tool calls through the
|
|
882
|
+
* approval path and auto-denies them before they execute.
|
|
883
|
+
*/
|
|
884
|
+
readonly supportsBuiltinToolFiltering?: boolean;
|
|
861
885
|
/**
|
|
862
886
|
* Optional schema for the adapter-defined `data` payload returned by session
|
|
863
887
|
* lifecycle methods. When present, the adapter promises that exported state
|
|
@@ -1038,6 +1062,14 @@ type HarnessAgentPendingToolApproval = HarnessV1PendingToolApproval;
|
|
|
1038
1062
|
type HarnessAgentSkill = HarnessV1Skill;
|
|
1039
1063
|
type HarnessAgentPermissionMode = HarnessV1PermissionMode;
|
|
1040
1064
|
|
|
1065
|
+
/** Extract the builtin tool set type from a harness adapter parameter. */
|
|
1066
|
+
type HarnessBuiltinToolsOf<H> = H extends HarnessAgentAdapter<infer T> ? T : never;
|
|
1067
|
+
/**
|
|
1068
|
+
* Type-level merge of a harness's builtin tools with user-defined tools.
|
|
1069
|
+
* User tools override builtins on key collision.
|
|
1070
|
+
*/
|
|
1071
|
+
type HarnessAllTools<THarness extends HarnessAgentAdapter<any>, TUserTools extends ToolSet> = Omit<HarnessBuiltinToolsOf<THarness>, keyof TUserTools> & TUserTools;
|
|
1072
|
+
|
|
1041
1073
|
type HarnessAgentToolApprovalConfiguration = Readonly<Record<string, ToolApprovalStatus>>;
|
|
1042
1074
|
type HarnessAgentSandboxConfig = {
|
|
1043
1075
|
/**
|
|
@@ -1077,6 +1109,7 @@ type HarnessAgentSandboxConfig = {
|
|
|
1077
1109
|
readonly abortSignal?: AbortSignal;
|
|
1078
1110
|
}) => Promise<void>;
|
|
1079
1111
|
};
|
|
1112
|
+
type HarnessTools<TOOLS extends ToolSet> = ActiveTools<NoInfer<TOOLS>>;
|
|
1080
1113
|
/**
|
|
1081
1114
|
* Construction-time settings for a `HarnessAgent`.
|
|
1082
1115
|
*
|
|
@@ -1084,6 +1117,21 @@ type HarnessAgentSandboxConfig = {
|
|
|
1084
1117
|
* `AgentCallParameters` / `AgentStreamParameters` passed to `generate` /
|
|
1085
1118
|
* `stream` and are not duplicated here.
|
|
1086
1119
|
*/
|
|
1120
|
+
type HarnessAgentToolFilteringSettings<TOOLS extends ToolSet> = {
|
|
1121
|
+
/**
|
|
1122
|
+
* Limits the tools that are available for the harness to call without
|
|
1123
|
+
* changing the tool call and result types in the result.
|
|
1124
|
+
*/
|
|
1125
|
+
readonly activeTools?: HarnessTools<TOOLS>;
|
|
1126
|
+
readonly inactiveTools?: never;
|
|
1127
|
+
} | {
|
|
1128
|
+
readonly activeTools?: never;
|
|
1129
|
+
/**
|
|
1130
|
+
* Excludes tools from the set that is available for the harness to call
|
|
1131
|
+
* without changing the tool call and result types in the result.
|
|
1132
|
+
*/
|
|
1133
|
+
readonly inactiveTools?: HarnessTools<TOOLS>;
|
|
1134
|
+
};
|
|
1087
1135
|
type HarnessAgentSettings<THarness extends HarnessAgentAdapter<any> = HarnessAgentAdapter, TUserTools extends ToolSet = {}> = {
|
|
1088
1136
|
/**
|
|
1089
1137
|
* The harness adapter driving the underlying agent runtime. Its
|
|
@@ -1165,7 +1213,7 @@ type HarnessAgentSettings<THarness extends HarnessAgentAdapter<any> = HarnessAge
|
|
|
1165
1213
|
* stderr default — wire this to capture diagnostics in code.
|
|
1166
1214
|
*/
|
|
1167
1215
|
readonly onLog?: (event: HarnessDiagnostic) => void;
|
|
1168
|
-
}
|
|
1216
|
+
} & HarnessAgentToolFilteringSettings<HarnessAllTools<THarness, TUserTools>>;
|
|
1169
1217
|
|
|
1170
1218
|
type HarnessAgentToolApprovalContinuation = {
|
|
1171
1219
|
readonly approvalResponse: ToolApprovalResponse;
|
|
@@ -1250,7 +1298,9 @@ declare class HarnessAgentSession {
|
|
|
1250
1298
|
prompt: HarnessAgentPrompt;
|
|
1251
1299
|
instructions: string | undefined;
|
|
1252
1300
|
tools: TOOLS;
|
|
1301
|
+
activeTools: ToolSet;
|
|
1253
1302
|
toolSpecs: HarnessAgentToolSpec[];
|
|
1303
|
+
builtinToolFiltering: HarnessV1BuiltinToolFiltering | undefined;
|
|
1254
1304
|
runtimeContext: RUNTIME_CONTEXT;
|
|
1255
1305
|
abortSignal: AbortSignal | undefined;
|
|
1256
1306
|
telemetry: TelemetryOptions | undefined;
|
|
@@ -1258,7 +1308,9 @@ declare class HarnessAgentSession {
|
|
|
1258
1308
|
continueTurn<TOOLS extends ToolSet, RUNTIME_CONTEXT extends Context>(options: {
|
|
1259
1309
|
instructions: string | undefined;
|
|
1260
1310
|
tools: TOOLS;
|
|
1311
|
+
activeTools: ToolSet;
|
|
1261
1312
|
toolSpecs: HarnessAgentToolSpec[];
|
|
1313
|
+
builtinToolFiltering: HarnessV1BuiltinToolFiltering | undefined;
|
|
1262
1314
|
runtimeContext: RUNTIME_CONTEXT;
|
|
1263
1315
|
abortSignal: AbortSignal | undefined;
|
|
1264
1316
|
telemetry: TelemetryOptions | undefined;
|
|
@@ -1322,13 +1374,6 @@ declare class HarnessAgentSession {
|
|
|
1322
1374
|
private requireReusableSession;
|
|
1323
1375
|
}
|
|
1324
1376
|
|
|
1325
|
-
/** Extract the builtin tool set type from a harness adapter parameter. */
|
|
1326
|
-
type BuiltinToolsOf<H> = H extends HarnessAgentAdapter<infer T> ? T : never;
|
|
1327
|
-
/**
|
|
1328
|
-
* Type-level merge of a harness's builtin tools with user-defined tools.
|
|
1329
|
-
* User tools override builtins on key collision.
|
|
1330
|
-
*/
|
|
1331
|
-
type HarnessAllTools<THarness extends HarnessAgentAdapter<any>, TUserTools extends ToolSet> = Omit<BuiltinToolsOf<THarness>, keyof TUserTools> & TUserTools;
|
|
1332
1377
|
/**
|
|
1333
1378
|
* Required `session` extension on every `HarnessAgent.generate` /
|
|
1334
1379
|
* `HarnessAgent.stream` call. The agent operates exclusively on the
|
|
@@ -1387,7 +1432,8 @@ declare class HarnessAgent<THarness extends HarnessAgentAdapter<any> = HarnessAg
|
|
|
1387
1432
|
readonly tools: HarnessAllTools<THarness, TUserTools>;
|
|
1388
1433
|
private readonly settings;
|
|
1389
1434
|
private readonly sandboxConfig;
|
|
1390
|
-
private readonly
|
|
1435
|
+
private readonly activeUserTools;
|
|
1436
|
+
private readonly builtinToolFiltering;
|
|
1391
1437
|
private readonly permissionMode;
|
|
1392
1438
|
constructor(settings: HarnessAgentSettings<THarness, TUserTools>);
|
|
1393
1439
|
/** Identifier of the harness backing this agent. */
|
|
@@ -1565,4 +1611,4 @@ interface TraceTreeReporterOptions {
|
|
|
1565
1611
|
}
|
|
1566
1612
|
declare function createTraceTreeReporter(options?: TraceTreeReporterOptions): Telemetry;
|
|
1567
1613
|
|
|
1568
|
-
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 HarnessAgentPermissionMode, type HarnessAgentPrompt, type HarnessAgentPromptControl, type HarnessAgentPromptTurnOptions, type HarnessAgentResumeSessionState, type HarnessAgentSandboxConfig, HarnessAgentSession, type HarnessAgentSettings, type HarnessAgentSkill, type HarnessAgentStartOptions, type HarnessAgentStreamPart, type HarnessAgentToolApprovalConfiguration, type HarnessAgentToolApprovalContinuation, type HarnessAgentToolSpec, HarnessCapabilityUnsupportedError, type HarnessDebugConfig, type HarnessDebugLevel, type HarnessDiagnostic, type HarnessDiagnosticConsumer, HarnessError, type PrepareSandboxForHarnessResult, type TraceTreeReporterOptions, collectHarnessAgentToolApprovalContinuations, createFileReporter, createTraceTreeReporter, prepareHarnessSandboxTemplate, prepareSandboxForHarness, prewarmHarness };
|
|
1614
|
+
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 HarnessAgentPermissionMode, type HarnessAgentPrompt, type HarnessAgentPromptControl, type HarnessAgentPromptTurnOptions, type HarnessAgentResumeSessionState, type HarnessAgentSandboxConfig, HarnessAgentSession, type HarnessAgentSettings, type HarnessAgentSkill, type HarnessAgentStartOptions, type HarnessAgentStreamPart, type HarnessAgentToolApprovalConfiguration, type HarnessAgentToolApprovalContinuation, type HarnessAgentToolSpec, type HarnessAllTools, HarnessCapabilityUnsupportedError, type HarnessDebugConfig, type HarnessDebugLevel, type HarnessDiagnostic, type HarnessDiagnosticConsumer, HarnessError, type PrepareSandboxForHarnessResult, type TraceTreeReporterOptions, collectHarnessAgentToolApprovalContinuations, createFileReporter, createTraceTreeReporter, prepareHarnessSandboxTemplate, prepareSandboxForHarness, prewarmHarness };
|
package/dist/agent/index.js
CHANGED
|
@@ -131,6 +131,15 @@ async function validateLifecycleStateData(input) {
|
|
|
131
131
|
};
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
// src/v1/harness-v1-tool-filtering.ts
|
|
135
|
+
function isHarnessV1BuiltinToolIncluded(input) {
|
|
136
|
+
if (input.toolFiltering == null) return true;
|
|
137
|
+
return input.toolFiltering.mode === "allow" ? input.toolFiltering.toolNames.includes(input.toolName) : !input.toolFiltering.toolNames.includes(input.toolName);
|
|
138
|
+
}
|
|
139
|
+
function getHarnessV1BuiltinToolFilteringDenialReason(input) {
|
|
140
|
+
return `Tool '${input.toolName}' is inactive due to the HarnessAgent tool filtering policy.`;
|
|
141
|
+
}
|
|
142
|
+
|
|
134
143
|
// src/agent/internal/to-harness-stream.ts
|
|
135
144
|
async function toHarnessStream(options) {
|
|
136
145
|
let controller;
|
|
@@ -1162,7 +1171,7 @@ function normalizeToolApprovalStatus(input) {
|
|
|
1162
1171
|
|
|
1163
1172
|
// src/agent/internal/run-prompt.ts
|
|
1164
1173
|
function runPrompt(input) {
|
|
1165
|
-
var _a3, _b3, _c;
|
|
1174
|
+
var _a3, _b3, _c, _d;
|
|
1166
1175
|
const result = new HarnessStreamTextResult({
|
|
1167
1176
|
tools: input.tools,
|
|
1168
1177
|
runtimeContext: input.runtimeContext,
|
|
@@ -1176,6 +1185,7 @@ function runPrompt(input) {
|
|
|
1176
1185
|
});
|
|
1177
1186
|
const onToolApprovalSettled = (_c = input.onToolApprovalSettled) != null ? _c : (() => {
|
|
1178
1187
|
});
|
|
1188
|
+
const activeTools = (_d = input.activeTools) != null ? _d : input.tools;
|
|
1179
1189
|
const telemetry = createTurnTelemetry({
|
|
1180
1190
|
telemetry: input.telemetry,
|
|
1181
1191
|
harnessId: input.harness.harnessId,
|
|
@@ -1185,7 +1195,7 @@ function runPrompt(input) {
|
|
|
1185
1195
|
runtimeContext: input.runtimeContext
|
|
1186
1196
|
});
|
|
1187
1197
|
const done = (async () => {
|
|
1188
|
-
var _a4, _b4, _c2,
|
|
1198
|
+
var _a4, _b4, _c2, _d2, _e, _f, _g, _h;
|
|
1189
1199
|
let bridge;
|
|
1190
1200
|
try {
|
|
1191
1201
|
bridge = await toHarnessStream({
|
|
@@ -1348,7 +1358,7 @@ function runPrompt(input) {
|
|
|
1348
1358
|
};
|
|
1349
1359
|
const outcome = await maybeExecuteHostTool({
|
|
1350
1360
|
event: rawToolCall,
|
|
1351
|
-
tools:
|
|
1361
|
+
tools: activeTools,
|
|
1352
1362
|
sandboxSession: input.sandboxSession,
|
|
1353
1363
|
abortSignal: input.abortSignal,
|
|
1354
1364
|
control,
|
|
@@ -1396,6 +1406,36 @@ function runPrompt(input) {
|
|
|
1396
1406
|
if (settledApprovalToolCallReplay) {
|
|
1397
1407
|
continue;
|
|
1398
1408
|
}
|
|
1409
|
+
if (displayValue.type === "tool-approval-request") {
|
|
1410
|
+
const toolCall = toolCallsByToolCallId.get(displayValue.toolCallId);
|
|
1411
|
+
if (toolCall == null) {
|
|
1412
|
+
throw new Error(
|
|
1413
|
+
`Harness '${input.harness.harnessId}' emitted approval request '${displayValue.approvalId}' for unknown tool call '${displayValue.toolCallId}'.`
|
|
1414
|
+
);
|
|
1415
|
+
}
|
|
1416
|
+
const rawToolCall = rawToolCallsByToolCallId.get(
|
|
1417
|
+
displayValue.toolCallId
|
|
1418
|
+
);
|
|
1419
|
+
const toolName = (_c2 = rawToolCall == null ? void 0 : rawToolCall.toolName) != null ? _c2 : toolCall.toolName;
|
|
1420
|
+
if (!isHarnessV1BuiltinToolIncluded({
|
|
1421
|
+
toolName,
|
|
1422
|
+
toolFiltering: input.builtinToolFiltering
|
|
1423
|
+
})) {
|
|
1424
|
+
if (control.submitToolApproval == null) {
|
|
1425
|
+
throw new Error(
|
|
1426
|
+
`Harness '${input.harness.harnessId}' emitted a built-in tool approval request but does not support approval responses.`
|
|
1427
|
+
);
|
|
1428
|
+
}
|
|
1429
|
+
await control.submitToolApproval({
|
|
1430
|
+
approvalId: displayValue.approvalId,
|
|
1431
|
+
approved: false,
|
|
1432
|
+
reason: getHarnessV1BuiltinToolFilteringDenialReason({
|
|
1433
|
+
toolName
|
|
1434
|
+
})
|
|
1435
|
+
});
|
|
1436
|
+
continue;
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1399
1439
|
for (const part of translateStreamPart(displayValue)) {
|
|
1400
1440
|
result.enqueue(part);
|
|
1401
1441
|
}
|
|
@@ -1441,13 +1481,13 @@ function runPrompt(input) {
|
|
|
1441
1481
|
);
|
|
1442
1482
|
}
|
|
1443
1483
|
const rawToolCall = rawToolCallsByToolCallId.get(value.toolCallId);
|
|
1444
|
-
const pendingApproval = (
|
|
1484
|
+
const pendingApproval = (_f = pendingApprovalsByApprovalId.get(value.approvalId)) != null ? _f : {
|
|
1445
1485
|
approvalId: value.approvalId,
|
|
1446
1486
|
toolCallId: value.toolCallId,
|
|
1447
1487
|
toolName: toolCall.toolName,
|
|
1448
|
-
input: (
|
|
1488
|
+
input: (_d2 = rawToolCall == null ? void 0 : rawToolCall.input) != null ? _d2 : JSON.stringify(toolCall.input),
|
|
1449
1489
|
kind: "builtin",
|
|
1450
|
-
providerExecuted: (
|
|
1490
|
+
providerExecuted: (_e = rawToolCall == null ? void 0 : rawToolCall.providerExecuted) != null ? _e : true,
|
|
1451
1491
|
...(rawToolCall == null ? void 0 : rawToolCall.nativeName) !== void 0 ? { nativeName: rawToolCall.nativeName } : {}
|
|
1452
1492
|
};
|
|
1453
1493
|
pendingApprovalsByApprovalId.set(
|
|
@@ -1506,6 +1546,20 @@ function runPrompt(input) {
|
|
|
1506
1546
|
`Harness '${input.harness.harnessId}' could not find parsed tool call '${toolCall.toolCallId}' for custom tool approval.`
|
|
1507
1547
|
);
|
|
1508
1548
|
}
|
|
1549
|
+
if (!hasTool({ tools: activeTools, toolName: toolCall.toolName })) {
|
|
1550
|
+
const output = {
|
|
1551
|
+
type: "execution-denied",
|
|
1552
|
+
reason: getHarnessV1BuiltinToolFilteringDenialReason({
|
|
1553
|
+
toolName: toolCall.toolName
|
|
1554
|
+
})
|
|
1555
|
+
};
|
|
1556
|
+
await control.submitToolResult({
|
|
1557
|
+
toolCallId: toolCall.toolCallId,
|
|
1558
|
+
output
|
|
1559
|
+
});
|
|
1560
|
+
telemetry.toolEnd(toolCall.toolCallId, { ok: true, output });
|
|
1561
|
+
continue;
|
|
1562
|
+
}
|
|
1509
1563
|
const customToolApprovalDecision = resolveCustomToolApproval({
|
|
1510
1564
|
toolName: toolCall.toolName,
|
|
1511
1565
|
toolApproval: input.toolApproval
|
|
@@ -1535,7 +1589,7 @@ function runPrompt(input) {
|
|
|
1535
1589
|
telemetry.toolEnd(toolCall.toolCallId, { ok: true, output });
|
|
1536
1590
|
continue;
|
|
1537
1591
|
}
|
|
1538
|
-
const pendingApproval = (
|
|
1592
|
+
const pendingApproval = (_g = pendingApprovalsByToolCallId.get(toolCall.toolCallId)) != null ? _g : customToolApprovalDecision.type === "request" ? {
|
|
1539
1593
|
approvalId: generateId4(),
|
|
1540
1594
|
toolCallId: toolCall.toolCallId,
|
|
1541
1595
|
toolName: toolCall.toolName,
|
|
@@ -1581,7 +1635,7 @@ function runPrompt(input) {
|
|
|
1581
1635
|
}
|
|
1582
1636
|
const outcome = await maybeExecuteHostTool({
|
|
1583
1637
|
event: toolCall,
|
|
1584
|
-
tools:
|
|
1638
|
+
tools: activeTools,
|
|
1585
1639
|
sandboxSession: input.sandboxSession,
|
|
1586
1640
|
abortSignal: input.abortSignal,
|
|
1587
1641
|
control,
|
|
@@ -1613,7 +1667,7 @@ function runPrompt(input) {
|
|
|
1613
1667
|
return;
|
|
1614
1668
|
}
|
|
1615
1669
|
}
|
|
1616
|
-
(
|
|
1670
|
+
(_h = input.onTurnFinished) == null ? void 0 : _h.call(input);
|
|
1617
1671
|
await result.finish(
|
|
1618
1672
|
finalFinish ? {
|
|
1619
1673
|
finishReason: finalFinish.finishReason,
|
|
@@ -1640,6 +1694,9 @@ function asToolCallTextStreamPart(input) {
|
|
|
1640
1694
|
}
|
|
1641
1695
|
return input.part;
|
|
1642
1696
|
}
|
|
1697
|
+
function hasTool(input) {
|
|
1698
|
+
return Object.prototype.hasOwnProperty.call(input.tools, input.toolName);
|
|
1699
|
+
}
|
|
1643
1700
|
async function maybeExecuteHostTool(input) {
|
|
1644
1701
|
const tool = input.tools[input.event.toolName];
|
|
1645
1702
|
if (!isExecutableTool(tool)) return { ok: true, output: void 0 };
|
|
@@ -1767,7 +1824,9 @@ var HarnessAgentSession = class {
|
|
|
1767
1824
|
prompt: options.prompt,
|
|
1768
1825
|
instructions: options.instructions,
|
|
1769
1826
|
tools: options.tools,
|
|
1827
|
+
activeTools: options.activeTools,
|
|
1770
1828
|
toolSpecs: options.toolSpecs,
|
|
1829
|
+
builtinToolFiltering: options.builtinToolFiltering,
|
|
1771
1830
|
sandboxSession: sandboxSession.restricted(),
|
|
1772
1831
|
sessionWorkDir: this.sessionWorkDir,
|
|
1773
1832
|
runtimeContext: options.runtimeContext,
|
|
@@ -1805,7 +1864,9 @@ var HarnessAgentSession = class {
|
|
|
1805
1864
|
mode: "continue",
|
|
1806
1865
|
instructions: options.instructions,
|
|
1807
1866
|
tools: options.tools,
|
|
1867
|
+
activeTools: options.activeTools,
|
|
1808
1868
|
toolSpecs: options.toolSpecs,
|
|
1869
|
+
builtinToolFiltering: options.builtinToolFiltering,
|
|
1809
1870
|
sandboxSession: sandboxSession.restricted(),
|
|
1810
1871
|
sessionWorkDir: this.sessionWorkDir,
|
|
1811
1872
|
runtimeContext: options.runtimeContext,
|
|
@@ -2458,6 +2519,66 @@ function buildObservability(options) {
|
|
|
2458
2519
|
};
|
|
2459
2520
|
}
|
|
2460
2521
|
|
|
2522
|
+
// src/agent/internal/tool-filtering.ts
|
|
2523
|
+
import { NoSuchToolError } from "ai";
|
|
2524
|
+
function resolveHarnessAgentToolFiltering(input) {
|
|
2525
|
+
if (input.activeTools !== void 0 && input.inactiveTools !== void 0) {
|
|
2526
|
+
throw new Error(
|
|
2527
|
+
"HarnessAgent: pass either `activeTools` or `inactiveTools`, not both."
|
|
2528
|
+
);
|
|
2529
|
+
}
|
|
2530
|
+
const allToolNames = Object.keys(input.allTools);
|
|
2531
|
+
const activeTools = dedupeToolNames({ toolNames: input.activeTools });
|
|
2532
|
+
const inactiveTools = dedupeToolNames({ toolNames: input.inactiveTools });
|
|
2533
|
+
validateToolNames({
|
|
2534
|
+
requestedToolNames: activeTools != null ? activeTools : inactiveTools,
|
|
2535
|
+
availableToolNames: allToolNames
|
|
2536
|
+
});
|
|
2537
|
+
const userToolNames = Object.keys(input.userTools);
|
|
2538
|
+
const activeUserToolNames = activeTools != null ? userToolNames.filter((name3) => activeTools.includes(name3)) : inactiveTools != null ? userToolNames.filter((name3) => !inactiveTools.includes(name3)) : userToolNames;
|
|
2539
|
+
const builtinToolNames = Object.keys(input.harness.builtinTools);
|
|
2540
|
+
const disabledBuiltinToolNames = activeTools != null ? builtinToolNames.filter((name3) => !activeTools.includes(name3)) : inactiveTools != null ? builtinToolNames.filter((name3) => inactiveTools.includes(name3)) : [];
|
|
2541
|
+
const builtinToolFiltering = disabledBuiltinToolNames.length > 0 ? activeTools != null ? {
|
|
2542
|
+
mode: "allow",
|
|
2543
|
+
toolNames: builtinToolNames.filter(
|
|
2544
|
+
(name3) => activeTools.includes(name3)
|
|
2545
|
+
)
|
|
2546
|
+
} : { mode: "deny", toolNames: disabledBuiltinToolNames } : void 0;
|
|
2547
|
+
if (builtinToolFiltering != null && input.harness.supportsBuiltinToolFiltering !== true && input.harness.supportsBuiltinToolApprovals !== true) {
|
|
2548
|
+
throw new HarnessCapabilityUnsupportedError({
|
|
2549
|
+
message: `Harness '${input.harness.harnessId}' does not support built-in tool filtering controls.`,
|
|
2550
|
+
harnessId: input.harness.harnessId
|
|
2551
|
+
});
|
|
2552
|
+
}
|
|
2553
|
+
return {
|
|
2554
|
+
activeUserTools: filterToolSet({
|
|
2555
|
+
tools: input.userTools,
|
|
2556
|
+
toolNames: activeUserToolNames
|
|
2557
|
+
}),
|
|
2558
|
+
...builtinToolFiltering != null ? { builtinToolFiltering } : {}
|
|
2559
|
+
};
|
|
2560
|
+
}
|
|
2561
|
+
function dedupeToolNames(input) {
|
|
2562
|
+
return input.toolNames == null ? void 0 : Array.from(new Set(input.toolNames));
|
|
2563
|
+
}
|
|
2564
|
+
function validateToolNames(input) {
|
|
2565
|
+
if (input.requestedToolNames == null) return;
|
|
2566
|
+
for (const toolName of input.requestedToolNames) {
|
|
2567
|
+
if (!input.availableToolNames.includes(toolName)) {
|
|
2568
|
+
throw new NoSuchToolError({
|
|
2569
|
+
toolName,
|
|
2570
|
+
availableTools: [...input.availableToolNames]
|
|
2571
|
+
});
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
function filterToolSet(input) {
|
|
2576
|
+
const allowed = new Set(input.toolNames);
|
|
2577
|
+
return Object.fromEntries(
|
|
2578
|
+
Object.entries(input.tools).filter(([name3]) => allowed.has(name3))
|
|
2579
|
+
);
|
|
2580
|
+
}
|
|
2581
|
+
|
|
2461
2582
|
// src/agent/harness-agent.ts
|
|
2462
2583
|
var HarnessAgent = class {
|
|
2463
2584
|
constructor(settings) {
|
|
@@ -2468,10 +2589,23 @@ var HarnessAgent = class {
|
|
|
2468
2589
|
this.settings = settings;
|
|
2469
2590
|
this.sandboxConfig = sandboxConfig;
|
|
2470
2591
|
this.id = settings.id;
|
|
2471
|
-
|
|
2592
|
+
const userTools = (_a3 = settings.tools) != null ? _a3 : {};
|
|
2472
2593
|
this.permissionMode = resolvePermissionMode({
|
|
2473
2594
|
permissionMode: settings.permissionMode
|
|
2474
2595
|
});
|
|
2596
|
+
const tools = {
|
|
2597
|
+
...settings.harness.builtinTools,
|
|
2598
|
+
...userTools
|
|
2599
|
+
};
|
|
2600
|
+
const toolFiltering = resolveHarnessAgentToolFiltering({
|
|
2601
|
+
harness: settings.harness,
|
|
2602
|
+
userTools,
|
|
2603
|
+
allTools: tools,
|
|
2604
|
+
activeTools: settings.activeTools,
|
|
2605
|
+
inactiveTools: settings.inactiveTools
|
|
2606
|
+
});
|
|
2607
|
+
this.activeUserTools = toolFiltering.activeUserTools;
|
|
2608
|
+
this.builtinToolFiltering = toolFiltering.builtinToolFiltering;
|
|
2475
2609
|
if (Object.keys(settings.harness.builtinTools).length > 0 && permissionModeNeedsBuiltinSupport({
|
|
2476
2610
|
permissionMode: this.permissionMode
|
|
2477
2611
|
}) && settings.harness.supportsBuiltinToolApprovals !== true) {
|
|
@@ -2480,10 +2614,7 @@ var HarnessAgent = class {
|
|
|
2480
2614
|
harnessId: settings.harness.harnessId
|
|
2481
2615
|
});
|
|
2482
2616
|
}
|
|
2483
|
-
this.tools =
|
|
2484
|
-
...settings.harness.builtinTools,
|
|
2485
|
-
...this.userTools
|
|
2486
|
-
};
|
|
2617
|
+
this.tools = tools;
|
|
2487
2618
|
}
|
|
2488
2619
|
/** Identifier of the harness backing this agent. */
|
|
2489
2620
|
get harnessId() {
|
|
@@ -2592,6 +2723,7 @@ var HarnessAgent = class {
|
|
|
2592
2723
|
resumeFrom: validatedResumeFrom,
|
|
2593
2724
|
continueFrom: effectiveContinueFrom,
|
|
2594
2725
|
permissionMode: this.permissionMode,
|
|
2726
|
+
builtinToolFiltering: this.builtinToolFiltering,
|
|
2595
2727
|
abortSignal,
|
|
2596
2728
|
observability: buildObservability({ settings: this.settings })
|
|
2597
2729
|
};
|
|
@@ -2693,7 +2825,9 @@ var HarnessAgent = class {
|
|
|
2693
2825
|
return input.session.continueTurn({
|
|
2694
2826
|
instructions: this.settings.instructions,
|
|
2695
2827
|
tools: this.tools,
|
|
2828
|
+
activeTools: this.activeUserTools,
|
|
2696
2829
|
toolSpecs: this._toToolSpecs(),
|
|
2830
|
+
builtinToolFiltering: this.builtinToolFiltering,
|
|
2697
2831
|
runtimeContext: input.runtimeContext,
|
|
2698
2832
|
abortSignal: input.abortSignal,
|
|
2699
2833
|
telemetry: this.settings.telemetry,
|
|
@@ -2704,7 +2838,9 @@ var HarnessAgent = class {
|
|
|
2704
2838
|
prompt: input.turnInput.prompt,
|
|
2705
2839
|
instructions: this.settings.instructions,
|
|
2706
2840
|
tools: this.tools,
|
|
2841
|
+
activeTools: this.activeUserTools,
|
|
2707
2842
|
toolSpecs: this._toToolSpecs(),
|
|
2843
|
+
builtinToolFiltering: this.builtinToolFiltering,
|
|
2708
2844
|
runtimeContext: input.runtimeContext,
|
|
2709
2845
|
abortSignal: input.abortSignal,
|
|
2710
2846
|
telemetry: this.settings.telemetry
|
|
@@ -2771,7 +2907,7 @@ var HarnessAgent = class {
|
|
|
2771
2907
|
_toToolSpecs() {
|
|
2772
2908
|
const specs = [];
|
|
2773
2909
|
for (const [name3, tool] of Object.entries(
|
|
2774
|
-
this.
|
|
2910
|
+
this.activeUserTools
|
|
2775
2911
|
)) {
|
|
2776
2912
|
const t = tool;
|
|
2777
2913
|
let inputSchema;
|