@ai-sdk/harness 1.0.123 → 1.0.126
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 +29 -0
- package/README.md +9 -8
- package/agent/index.ts +2 -0
- package/dist/agent/index.d.ts +31 -19
- package/dist/agent/index.js +484 -262
- package/dist/agent/index.js.map +1 -1
- package/dist/index.d.ts +39 -17
- package/dist/index.js.map +1 -1
- package/dist/utils/index.d.ts +7 -14
- package/dist/utils/index.js +63 -97
- package/dist/utils/index.js.map +1 -1
- package/package.json +4 -4
- package/src/agent/create-harness-sandbox-template.ts +80 -0
- package/src/agent/harness-agent-settings.ts +1 -0
- package/src/agent/harness-agent-types.ts +2 -0
- package/src/agent/harness-agent.ts +23 -0
- package/src/agent/internal/on-bootstrap-marker.ts +70 -0
- package/src/agent/internal/prepared-sandbox-identity.ts +42 -0
- package/src/agent/internal/run-prompt.ts +134 -19
- package/src/agent/internal/sandbox-bootstrap.ts +19 -0
- package/src/agent/internal/strip-work-dir.ts +57 -0
- package/src/agent/prepare-harness-sandbox-template.ts +5 -2
- package/src/agent/prepare-sandbox-for-harness.ts +7 -51
- package/src/v1/harness-v1-network-sandbox-session.ts +7 -14
- package/src/v1/harness-v1-sandbox-provider.ts +3 -2
- package/src/v1/harness-v1-sandbox-session-create-options.ts +14 -0
- package/src/v1/harness-v1-sandbox-session-resume-options.ts +10 -0
- package/src/v1/harness-v1-sandbox-template.ts +9 -0
- package/src/v1/index.ts +3 -0
package/dist/agent/index.js
CHANGED
|
@@ -521,7 +521,7 @@ var HarnessStreamTextResult = class {
|
|
|
521
521
|
]) {
|
|
522
522
|
try {
|
|
523
523
|
dp.reject(error);
|
|
524
|
-
} catch
|
|
524
|
+
} catch {
|
|
525
525
|
}
|
|
526
526
|
}
|
|
527
527
|
}
|
|
@@ -644,11 +644,10 @@ var HarnessStreamTextResult = class {
|
|
|
644
644
|
);
|
|
645
645
|
}
|
|
646
646
|
get elementStream() {
|
|
647
|
-
|
|
648
|
-
const transform = (_a4 = this.outputSpecification) == null ? void 0 : _a4.createElementStreamTransform();
|
|
647
|
+
const transform = this.outputSpecification?.createElementStreamTransform();
|
|
649
648
|
if (transform == null) {
|
|
650
649
|
throw notSupportedYet(
|
|
651
|
-
`element streams in ${
|
|
650
|
+
`element streams in ${this.outputSpecification?.name ?? "text"} mode`
|
|
652
651
|
);
|
|
653
652
|
}
|
|
654
653
|
return createAsyncIterableStream(
|
|
@@ -807,7 +806,6 @@ function createOutputTransformStream(output) {
|
|
|
807
806
|
};
|
|
808
807
|
return new TransformStream({
|
|
809
808
|
async transform(chunk, controller) {
|
|
810
|
-
var _a4;
|
|
811
809
|
if (chunk.type === "finish-step" && textChunk.length > 0) {
|
|
812
810
|
publishTextChunk({ controller });
|
|
813
811
|
}
|
|
@@ -834,7 +832,7 @@ function createOutputTransformStream(output) {
|
|
|
834
832
|
}
|
|
835
833
|
text += chunk.text;
|
|
836
834
|
textChunk += chunk.text;
|
|
837
|
-
textProviderMetadata =
|
|
835
|
+
textProviderMetadata = chunk.providerMetadata ?? textProviderMetadata;
|
|
838
836
|
if (chunk.text.length === 0 && chunk.providerMetadata != null) {
|
|
839
837
|
controller.enqueue({ part: chunk, partialOutput: void 0 });
|
|
840
838
|
return;
|
|
@@ -880,7 +878,6 @@ function getOwn(obj, key) {
|
|
|
880
878
|
// src/agent/internal/translate-stream-part.ts
|
|
881
879
|
import { generateId } from "@ai-sdk/provider-utils";
|
|
882
880
|
function translateStreamPart(event, options = {}) {
|
|
883
|
-
var _a4, _b4;
|
|
884
881
|
switch (event.type) {
|
|
885
882
|
case "stream-start":
|
|
886
883
|
return [];
|
|
@@ -943,7 +940,7 @@ function translateStreamPart(event, options = {}) {
|
|
|
943
940
|
case "tool-approval-request":
|
|
944
941
|
return [];
|
|
945
942
|
case "tool-result":
|
|
946
|
-
if (event.isError === true && (
|
|
943
|
+
if (event.isError === true && (options.isProviderExecuted?.(event.toolCallId) ?? true)) {
|
|
947
944
|
return [
|
|
948
945
|
{
|
|
949
946
|
type: "tool-error",
|
|
@@ -1042,7 +1039,6 @@ function createToolInputWorkDirStripper({
|
|
|
1042
1039
|
}) {
|
|
1043
1040
|
const stateByToolCallId = /* @__PURE__ */ new Map();
|
|
1044
1041
|
return (part) => {
|
|
1045
|
-
var _a4;
|
|
1046
1042
|
if (sessionWorkDir.length === 0) return [part];
|
|
1047
1043
|
if (part.type === "tool-input-start") {
|
|
1048
1044
|
stateByToolCallId.set(part.id, {
|
|
@@ -1052,7 +1048,7 @@ function createToolInputWorkDirStripper({
|
|
|
1052
1048
|
return [part];
|
|
1053
1049
|
}
|
|
1054
1050
|
if (part.type === "tool-input-delta") {
|
|
1055
|
-
const state2 =
|
|
1051
|
+
const state2 = stateByToolCallId.get(part.id) ?? {
|
|
1056
1052
|
pending: "",
|
|
1057
1053
|
precedingCharacter: void 0
|
|
1058
1054
|
};
|
|
@@ -1103,6 +1099,45 @@ function stripWorkDir(part, sessionWorkDir) {
|
|
|
1103
1099
|
return part;
|
|
1104
1100
|
}
|
|
1105
1101
|
}
|
|
1102
|
+
function stripParsedToolInputWorkDir({
|
|
1103
|
+
value,
|
|
1104
|
+
sessionWorkDir
|
|
1105
|
+
}) {
|
|
1106
|
+
if (sessionWorkDir.length === 0) return value;
|
|
1107
|
+
const projected = /* @__PURE__ */ new WeakMap();
|
|
1108
|
+
const pending = [];
|
|
1109
|
+
const project = (item) => {
|
|
1110
|
+
if (typeof item === "string") return stripString(item, sessionWorkDir);
|
|
1111
|
+
if (item === null || typeof item !== "object") return item;
|
|
1112
|
+
if (!Array.isArray(item) && Object.getPrototypeOf(item) !== Object.prototype && Object.getPrototypeOf(item) !== null) {
|
|
1113
|
+
return item;
|
|
1114
|
+
}
|
|
1115
|
+
if (projected.has(item)) return projected.get(item);
|
|
1116
|
+
const target = Array.isArray(item) ? new Array(item.length) : {};
|
|
1117
|
+
projected.set(item, target);
|
|
1118
|
+
pending.push({ source: item, target });
|
|
1119
|
+
return target;
|
|
1120
|
+
};
|
|
1121
|
+
const result = project(value);
|
|
1122
|
+
while (pending.length > 0) {
|
|
1123
|
+
const { source, target } = pending.pop();
|
|
1124
|
+
if (Array.isArray(source) && Array.isArray(target)) {
|
|
1125
|
+
for (let index = 0; index < source.length; index++) {
|
|
1126
|
+
if (index in source) target[index] = project(source[index]);
|
|
1127
|
+
}
|
|
1128
|
+
} else {
|
|
1129
|
+
for (const [key, item] of Object.entries(source)) {
|
|
1130
|
+
Object.defineProperty(target, key, {
|
|
1131
|
+
value: project(item),
|
|
1132
|
+
enumerable: true,
|
|
1133
|
+
writable: true,
|
|
1134
|
+
configurable: true
|
|
1135
|
+
});
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
return result;
|
|
1140
|
+
}
|
|
1106
1141
|
function stripString(value, workDir) {
|
|
1107
1142
|
return stripStreamingString({
|
|
1108
1143
|
value,
|
|
@@ -1192,15 +1227,14 @@ import { createTelemetryDispatcher } from "ai/internal";
|
|
|
1192
1227
|
async function notify(event, ...callbacks) {
|
|
1193
1228
|
await Promise.allSettled(
|
|
1194
1229
|
callbacks.map(async (callback) => {
|
|
1195
|
-
await
|
|
1230
|
+
await callback?.(event);
|
|
1196
1231
|
})
|
|
1197
1232
|
);
|
|
1198
1233
|
}
|
|
1199
1234
|
function createTurnLifecycle(options) {
|
|
1200
|
-
var _a4;
|
|
1201
1235
|
const telemetry = options.telemetry == null ? {} : createTelemetryDispatcher({ telemetry: options.telemetry });
|
|
1202
1236
|
const provider = `harness:${options.harnessId}`;
|
|
1203
|
-
let modelId =
|
|
1237
|
+
let modelId = options.modelId ?? "";
|
|
1204
1238
|
let started = false;
|
|
1205
1239
|
let stepOpen = false;
|
|
1206
1240
|
let stepNumber = 0;
|
|
@@ -1342,7 +1376,6 @@ function createTurnLifecycle(options) {
|
|
|
1342
1376
|
);
|
|
1343
1377
|
},
|
|
1344
1378
|
async stepEnd(step) {
|
|
1345
|
-
var _a5, _b4, _c;
|
|
1346
1379
|
if (!stepOpen) return;
|
|
1347
1380
|
completedSteps.push(step);
|
|
1348
1381
|
const telemetryStepEndEvent = Object.assign(/* @__PURE__ */ Object.create(null), {
|
|
@@ -1373,8 +1406,8 @@ function createTurnLifecycle(options) {
|
|
|
1373
1406
|
dynamicToolResults: step.dynamicToolResults
|
|
1374
1407
|
});
|
|
1375
1408
|
await Promise.allSettled([
|
|
1376
|
-
|
|
1377
|
-
|
|
1409
|
+
options.callbacks.onStepEnd?.(step),
|
|
1410
|
+
telemetry.onStepEnd?.(telemetryStepEndEvent)
|
|
1378
1411
|
]);
|
|
1379
1412
|
stepOpen = false;
|
|
1380
1413
|
stepNumber += 1;
|
|
@@ -1406,10 +1439,7 @@ function createTurnLifecycle(options) {
|
|
|
1406
1439
|
rawFinishReason: finalStep.rawFinishReason,
|
|
1407
1440
|
usage,
|
|
1408
1441
|
totalUsage: usage,
|
|
1409
|
-
warnings: steps.flatMap((step) =>
|
|
1410
|
-
var _a5;
|
|
1411
|
-
return (_a5 = step.warnings) != null ? _a5 : [];
|
|
1412
|
-
}),
|
|
1442
|
+
warnings: steps.flatMap((step) => step.warnings ?? []),
|
|
1413
1443
|
request: finalStep.request,
|
|
1414
1444
|
response: finalStep.response,
|
|
1415
1445
|
providerMetadata: finalStep.providerMetadata,
|
|
@@ -1432,11 +1462,10 @@ function createTurnLifecycle(options) {
|
|
|
1432
1462
|
});
|
|
1433
1463
|
},
|
|
1434
1464
|
async error(error) {
|
|
1435
|
-
var _a5;
|
|
1436
1465
|
if (ended) return;
|
|
1437
1466
|
if (!started) await start();
|
|
1438
1467
|
ended = true;
|
|
1439
|
-
await
|
|
1468
|
+
await telemetry.onError?.(error);
|
|
1440
1469
|
}
|
|
1441
1470
|
};
|
|
1442
1471
|
}
|
|
@@ -1444,16 +1473,14 @@ function createTurnLifecycle(options) {
|
|
|
1444
1473
|
// src/agent/internal/permission-mode.ts
|
|
1445
1474
|
var DEFAULT_PERMISSION_MODE = "allow-all";
|
|
1446
1475
|
function resolvePermissionMode(input) {
|
|
1447
|
-
|
|
1448
|
-
return (_a4 = input.permissionMode) != null ? _a4 : DEFAULT_PERMISSION_MODE;
|
|
1476
|
+
return input.permissionMode ?? DEFAULT_PERMISSION_MODE;
|
|
1449
1477
|
}
|
|
1450
1478
|
function permissionModeNeedsBuiltinSupport(input) {
|
|
1451
1479
|
return input.permissionMode !== "allow-all";
|
|
1452
1480
|
}
|
|
1453
1481
|
function resolveCustomToolApproval(input) {
|
|
1454
|
-
var _a4;
|
|
1455
1482
|
const status = normalizeToolApprovalStatus({
|
|
1456
|
-
status:
|
|
1483
|
+
status: input.toolApproval?.[input.toolName]
|
|
1457
1484
|
});
|
|
1458
1485
|
switch (status.type) {
|
|
1459
1486
|
case "not-applicable":
|
|
@@ -1479,24 +1506,23 @@ function stringifyUnknown(value) {
|
|
|
1479
1506
|
if (typeof value === "string") return value;
|
|
1480
1507
|
try {
|
|
1481
1508
|
return JSON.stringify(value);
|
|
1482
|
-
} catch
|
|
1509
|
+
} catch {
|
|
1483
1510
|
return String(value);
|
|
1484
1511
|
}
|
|
1485
1512
|
}
|
|
1486
1513
|
function formatBridgeError(error) {
|
|
1487
|
-
var _a4, _b4;
|
|
1488
1514
|
if (error instanceof Error) {
|
|
1489
|
-
return
|
|
1515
|
+
return error.stack ?? `${error.name}: ${error.message}`;
|
|
1490
1516
|
}
|
|
1491
1517
|
if (isSerializedError(error)) {
|
|
1492
|
-
return
|
|
1518
|
+
return error.stack ?? `${error.name ? `${error.name}: ` : ""}${error.message}`;
|
|
1493
1519
|
}
|
|
1494
1520
|
return stringifyUnknown(error);
|
|
1495
1521
|
}
|
|
1496
1522
|
function writeToStderr(line) {
|
|
1497
1523
|
try {
|
|
1498
1524
|
process.stderr.write(line);
|
|
1499
|
-
} catch
|
|
1525
|
+
} catch {
|
|
1500
1526
|
}
|
|
1501
1527
|
}
|
|
1502
1528
|
function logBridgeError({
|
|
@@ -1525,12 +1551,12 @@ var sandboxChannelEventCheckpointSymbol = /* @__PURE__ */ Symbol.for(
|
|
|
1525
1551
|
"vercel.ai.harness.sandboxChannelEventCheckpoint"
|
|
1526
1552
|
);
|
|
1527
1553
|
function pinSandboxChannelEventCheckpoint(event) {
|
|
1528
|
-
var _a4;
|
|
1529
1554
|
if (event == null || typeof event !== "object") return void 0;
|
|
1530
|
-
return
|
|
1555
|
+
return event[sandboxChannelEventCheckpointSymbol]?.pin();
|
|
1531
1556
|
}
|
|
1532
1557
|
|
|
1533
1558
|
// src/agent/internal/run-prompt.ts
|
|
1559
|
+
var invalidToolInputMessage = "Tool input validation failed.";
|
|
1534
1560
|
function unwrapToolResultOutput(toolResult) {
|
|
1535
1561
|
switch (toolResult.output.type) {
|
|
1536
1562
|
case "text":
|
|
@@ -1551,29 +1577,28 @@ function unwrapToolResultOutput(toolResult) {
|
|
|
1551
1577
|
}
|
|
1552
1578
|
}
|
|
1553
1579
|
function runPrompt(input) {
|
|
1554
|
-
var _a4, _b4, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
1555
1580
|
const callId = generateId2();
|
|
1556
|
-
const toolsContext =
|
|
1581
|
+
const toolsContext = input.toolsContext ?? {};
|
|
1557
1582
|
const result = new HarnessStreamTextResult({
|
|
1558
1583
|
tools: input.tools,
|
|
1559
1584
|
runtimeContext: input.runtimeContext,
|
|
1560
1585
|
toolsContext,
|
|
1561
1586
|
harnessId: input.harness.harnessId,
|
|
1562
1587
|
callId,
|
|
1563
|
-
modelId:
|
|
1588
|
+
modelId: input.model ?? "",
|
|
1564
1589
|
output: input.output
|
|
1565
1590
|
});
|
|
1566
|
-
const pendingToolApprovals =
|
|
1567
|
-
const pendingToolResults =
|
|
1568
|
-
const onPendingToolApproval =
|
|
1591
|
+
const pendingToolApprovals = input.pendingToolApprovals ?? [];
|
|
1592
|
+
const pendingToolResults = input.pendingToolResults ?? [];
|
|
1593
|
+
const onPendingToolApproval = input.onPendingToolApproval ?? (() => {
|
|
1569
1594
|
});
|
|
1570
|
-
const onToolApprovalSettled =
|
|
1595
|
+
const onToolApprovalSettled = input.onToolApprovalSettled ?? (() => {
|
|
1571
1596
|
});
|
|
1572
|
-
const onPendingToolResult =
|
|
1597
|
+
const onPendingToolResult = input.onPendingToolResult ?? (() => {
|
|
1573
1598
|
});
|
|
1574
|
-
const onToolResultSettled =
|
|
1599
|
+
const onToolResultSettled = input.onToolResultSettled ?? (() => {
|
|
1575
1600
|
});
|
|
1576
|
-
const activeTools =
|
|
1601
|
+
const activeTools = input.activeTools ?? input.tools;
|
|
1577
1602
|
const activeToolNames = Object.keys(input.tools).filter(
|
|
1578
1603
|
(toolName) => Object.prototype.hasOwnProperty.call(activeTools, toolName) || Object.prototype.hasOwnProperty.call(
|
|
1579
1604
|
input.harness.builtinTools,
|
|
@@ -1586,7 +1611,7 @@ function runPrompt(input) {
|
|
|
1586
1611
|
const lifecycle = createTurnLifecycle({
|
|
1587
1612
|
callId,
|
|
1588
1613
|
telemetry: input.telemetry,
|
|
1589
|
-
callbacks:
|
|
1614
|
+
callbacks: input.callbacks ?? {},
|
|
1590
1615
|
harnessId: input.harness.harnessId,
|
|
1591
1616
|
modelId: input.model,
|
|
1592
1617
|
instructions: input.instructions,
|
|
@@ -1599,11 +1624,10 @@ function runPrompt(input) {
|
|
|
1599
1624
|
output: input.output
|
|
1600
1625
|
});
|
|
1601
1626
|
const settleFailure = (err) => {
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
(_b5 = input.onTurnFailed) == null ? void 0 : _b5.call(input);
|
|
1627
|
+
if (!input.isTurnSuspending?.()) {
|
|
1628
|
+
input.onTurnFailed?.();
|
|
1605
1629
|
}
|
|
1606
|
-
if (
|
|
1630
|
+
if (input.abortSignal?.aborted) {
|
|
1607
1631
|
result.abort({
|
|
1608
1632
|
error: err,
|
|
1609
1633
|
...input.abortSignal.reason !== void 0 ? { reason: getErrorMessage(input.abortSignal.reason) } : {}
|
|
@@ -1613,23 +1637,18 @@ function runPrompt(input) {
|
|
|
1613
1637
|
result.fail(err);
|
|
1614
1638
|
};
|
|
1615
1639
|
const done = (async () => {
|
|
1616
|
-
var _a5, _b5, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k, _l, _m, _n, _o;
|
|
1617
1640
|
let bridge;
|
|
1618
1641
|
try {
|
|
1619
1642
|
bridge = await toHarnessStream({
|
|
1620
|
-
invoke: input.mode === "continue" ? (emit) => {
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
emit
|
|
1630
|
-
});
|
|
1631
|
-
} : (emit) => {
|
|
1632
|
-
var _a6;
|
|
1643
|
+
invoke: input.mode === "continue" ? (emit) => input.session.doContinueTurn({
|
|
1644
|
+
model: input.model,
|
|
1645
|
+
skills: input.skills ?? [],
|
|
1646
|
+
responseFormat: input.responseFormat,
|
|
1647
|
+
tools: input.toolSpecs,
|
|
1648
|
+
instructions: input.instructions,
|
|
1649
|
+
abortSignal: input.abortSignal,
|
|
1650
|
+
emit
|
|
1651
|
+
}) : (emit) => {
|
|
1633
1652
|
if (input.prompt == null) {
|
|
1634
1653
|
throw new Error(
|
|
1635
1654
|
'runPrompt: `prompt` is required for mode "prompt".'
|
|
@@ -1638,7 +1657,7 @@ function runPrompt(input) {
|
|
|
1638
1657
|
return input.session.doPromptTurn({
|
|
1639
1658
|
prompt: input.prompt,
|
|
1640
1659
|
model: input.model,
|
|
1641
|
-
skills:
|
|
1660
|
+
skills: input.skills ?? [],
|
|
1642
1661
|
responseFormat: input.responseFormat,
|
|
1643
1662
|
tools: input.toolSpecs,
|
|
1644
1663
|
instructions: input.instructions,
|
|
@@ -1659,7 +1678,7 @@ function runPrompt(input) {
|
|
|
1659
1678
|
return;
|
|
1660
1679
|
}
|
|
1661
1680
|
const { stream, control } = bridge;
|
|
1662
|
-
|
|
1681
|
+
input.onPromptControlAvailable?.(control);
|
|
1663
1682
|
const reader = stream.getReader();
|
|
1664
1683
|
const stripToolInputWorkDir = createToolInputWorkDirStripper({
|
|
1665
1684
|
sessionWorkDir: input.sessionWorkDir
|
|
@@ -1679,7 +1698,7 @@ function runPrompt(input) {
|
|
|
1679
1698
|
pendingToolApprovals.map((approval) => [approval.toolCallId, approval])
|
|
1680
1699
|
);
|
|
1681
1700
|
const continuationsByApprovalId = new Map(
|
|
1682
|
-
(
|
|
1701
|
+
(input.toolApprovalContinuations ?? []).map((continuation) => [
|
|
1683
1702
|
continuation.approvalId,
|
|
1684
1703
|
continuation
|
|
1685
1704
|
])
|
|
@@ -1691,7 +1710,7 @@ function runPrompt(input) {
|
|
|
1691
1710
|
])
|
|
1692
1711
|
);
|
|
1693
1712
|
const continuationsByToolCallId = new Map(
|
|
1694
|
-
(
|
|
1713
|
+
(input.toolResultContinuations ?? []).map((continuation) => [
|
|
1695
1714
|
continuation.toolCallId,
|
|
1696
1715
|
continuation
|
|
1697
1716
|
])
|
|
@@ -1720,8 +1739,7 @@ function runPrompt(input) {
|
|
|
1720
1739
|
}
|
|
1721
1740
|
};
|
|
1722
1741
|
const releasePendingStopBoundary = () => {
|
|
1723
|
-
|
|
1724
|
-
(_a6 = pendingStopBoundary == null ? void 0 : pendingStopBoundary.releaseCheckpoint) == null ? void 0 : _a6.call(pendingStopBoundary);
|
|
1742
|
+
pendingStopBoundary?.releaseCheckpoint?.();
|
|
1725
1743
|
pendingStopBoundary = void 0;
|
|
1726
1744
|
};
|
|
1727
1745
|
let stepText = "";
|
|
@@ -1732,7 +1750,6 @@ function runPrompt(input) {
|
|
|
1732
1750
|
let bufferedToolOutcomes = [];
|
|
1733
1751
|
const toolExecutions = /* @__PURE__ */ new Map();
|
|
1734
1752
|
const publishToolExecutions = async () => {
|
|
1735
|
-
var _a6;
|
|
1736
1753
|
for (const execution of toolExecutions.values()) {
|
|
1737
1754
|
if (execution.toolOutput == null) continue;
|
|
1738
1755
|
await lifecycle.toolExecutionStart({
|
|
@@ -1741,7 +1758,7 @@ function runPrompt(input) {
|
|
|
1741
1758
|
await lifecycle.toolExecutionEnd({
|
|
1742
1759
|
toolCall: execution.toolCall,
|
|
1743
1760
|
toolOutput: execution.toolOutput,
|
|
1744
|
-
toolExecutionMs:
|
|
1761
|
+
toolExecutionMs: execution.toolExecutionMs ?? 0
|
|
1745
1762
|
});
|
|
1746
1763
|
}
|
|
1747
1764
|
for (const publish of bufferedToolOutcomes) publish();
|
|
@@ -1856,8 +1873,7 @@ function runPrompt(input) {
|
|
|
1856
1873
|
});
|
|
1857
1874
|
};
|
|
1858
1875
|
const recordPendingToolResult = (options) => {
|
|
1859
|
-
|
|
1860
|
-
const pendingResult = (_a6 = pendingResultsByToolCallId.get(options.toolCall.toolCallId)) != null ? _a6 : {
|
|
1876
|
+
const pendingResult = pendingResultsByToolCallId.get(options.toolCall.toolCallId) ?? {
|
|
1861
1877
|
toolCallId: options.toolCall.toolCallId,
|
|
1862
1878
|
toolName: options.toolCall.toolName,
|
|
1863
1879
|
input: options.toolCall.input,
|
|
@@ -1896,11 +1912,10 @@ function runPrompt(input) {
|
|
|
1896
1912
|
});
|
|
1897
1913
|
};
|
|
1898
1914
|
const submitToolResult = async (submission) => {
|
|
1899
|
-
|
|
1900
|
-
if (!((_a6 = input.isTurnSuspending) == null ? void 0 : _a6.call(input))) {
|
|
1915
|
+
if (!input.isTurnSuspending?.()) {
|
|
1901
1916
|
return control.submitToolResult(submission);
|
|
1902
1917
|
}
|
|
1903
|
-
const toolCall =
|
|
1918
|
+
const toolCall = rawToolCallsByToolCallId.get(submission.toolCallId) ?? pendingResultsByToolCallId.get(submission.toolCallId) ?? pendingToolApprovals.find(
|
|
1904
1919
|
(approval) => approval.toolCallId === submission.toolCallId
|
|
1905
1920
|
);
|
|
1906
1921
|
if (toolCall == null) {
|
|
@@ -1944,8 +1959,7 @@ function runPrompt(input) {
|
|
|
1944
1959
|
pendingResultsByToolCallId.delete(pendingResult.toolCallId);
|
|
1945
1960
|
};
|
|
1946
1961
|
const processPendingApprovalContinuation = async (approval, continuation) => {
|
|
1947
|
-
|
|
1948
|
-
const rawToolCall = (_a6 = rawToolCallsByToolCallId.get(approval.toolCallId)) != null ? _a6 : {
|
|
1962
|
+
const rawToolCall = (approval.kind === "builtin" ? rawToolCallsByToolCallId.get(approval.toolCallId) : void 0) ?? {
|
|
1949
1963
|
type: "tool-call",
|
|
1950
1964
|
toolCallId: approval.toolCallId,
|
|
1951
1965
|
toolName: approval.toolName,
|
|
@@ -1953,14 +1967,29 @@ function runPrompt(input) {
|
|
|
1953
1967
|
providerExecuted: approval.providerExecuted,
|
|
1954
1968
|
nativeName: approval.nativeName
|
|
1955
1969
|
};
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1970
|
+
let validatedToolCall;
|
|
1971
|
+
let toolCall;
|
|
1972
|
+
if (approval.kind === "custom" && continuation.approved) {
|
|
1973
|
+
validatedToolCall = asToolCallTextStreamPart({
|
|
1974
|
+
part: await validateToolCall({
|
|
1975
|
+
event: rawToolCall,
|
|
1976
|
+
tools: input.tools
|
|
1977
|
+
})
|
|
1978
|
+
});
|
|
1979
|
+
toolCall = displayHostToolCall({
|
|
1980
|
+
toolCall: validatedToolCall,
|
|
1981
|
+
sessionWorkDir: input.sessionWorkDir
|
|
1982
|
+
});
|
|
1983
|
+
} else {
|
|
1984
|
+
const parsedInput = await safeParseJSON2({ text: rawToolCall.input });
|
|
1985
|
+
toolCall = {
|
|
1986
|
+
type: "tool-call",
|
|
1987
|
+
toolCallId: rawToolCall.toolCallId,
|
|
1988
|
+
toolName: rawToolCall.toolName,
|
|
1989
|
+
input: parsedInput.success ? parsedInput.value : rawToolCall.input,
|
|
1990
|
+
...rawToolCall.providerExecuted !== void 0 ? { providerExecuted: rawToolCall.providerExecuted } : {}
|
|
1991
|
+
};
|
|
1992
|
+
}
|
|
1964
1993
|
enqueueApprovalResponse(approval, continuation, toolCall);
|
|
1965
1994
|
onToolApprovalSettled(approval.approvalId);
|
|
1966
1995
|
pendingApprovalsByApprovalId.delete(approval.approvalId);
|
|
@@ -1990,6 +2019,27 @@ function runPrompt(input) {
|
|
|
1990
2019
|
});
|
|
1991
2020
|
return "continued";
|
|
1992
2021
|
}
|
|
2022
|
+
if (validatedToolCall == null) {
|
|
2023
|
+
throw new Error(
|
|
2024
|
+
`Harness '${input.harness.harnessId}' could not validate approved host tool '${approval.toolName}'.`
|
|
2025
|
+
);
|
|
2026
|
+
}
|
|
2027
|
+
if (validatedToolCall.invalid) {
|
|
2028
|
+
const error = new Error(invalidToolInputMessage);
|
|
2029
|
+
await submitToolResult({
|
|
2030
|
+
toolCallId: approval.toolCallId,
|
|
2031
|
+
output: { error: invalidToolInputMessage },
|
|
2032
|
+
isError: true
|
|
2033
|
+
});
|
|
2034
|
+
bufferedToolOutcomes.push(() => {
|
|
2035
|
+
enqueueHostToolOutcome({
|
|
2036
|
+
toolCall,
|
|
2037
|
+
outcome: { ok: false, error }
|
|
2038
|
+
});
|
|
2039
|
+
});
|
|
2040
|
+
await publishToolExecutions();
|
|
2041
|
+
return "continued";
|
|
2042
|
+
}
|
|
1993
2043
|
await lifecycle.start(input.model);
|
|
1994
2044
|
toolExecutions.set(rawToolCall.toolCallId, {
|
|
1995
2045
|
toolCall
|
|
@@ -1997,6 +2047,7 @@ function runPrompt(input) {
|
|
|
1997
2047
|
const executionStartedAt = Date.now();
|
|
1998
2048
|
const execution = await maybeExecuteHostTool({
|
|
1999
2049
|
event: rawToolCall,
|
|
2050
|
+
parsedToolCall: validatedToolCall,
|
|
2000
2051
|
tools: activeTools,
|
|
2001
2052
|
toolsContext,
|
|
2002
2053
|
wrappedExecuteTool: lifecycle.executeTool,
|
|
@@ -2088,7 +2139,7 @@ function runPrompt(input) {
|
|
|
2088
2139
|
(condition) => condition({ steps: completedSteps })
|
|
2089
2140
|
)
|
|
2090
2141
|
)).some(Boolean)) {
|
|
2091
|
-
await
|
|
2142
|
+
await input.onStopConditionMet?.();
|
|
2092
2143
|
const { usage } = pendingStopBoundary;
|
|
2093
2144
|
releasePendingStopBoundary();
|
|
2094
2145
|
await lifecycle.end({
|
|
@@ -2102,7 +2153,7 @@ function runPrompt(input) {
|
|
|
2102
2153
|
}
|
|
2103
2154
|
}
|
|
2104
2155
|
if (value.type === "stream-start") {
|
|
2105
|
-
const modelId =
|
|
2156
|
+
const modelId = value.modelId ?? input.model;
|
|
2106
2157
|
if (modelId != null) result.setModelId(modelId);
|
|
2107
2158
|
await lifecycle.start(modelId);
|
|
2108
2159
|
}
|
|
@@ -2146,7 +2197,7 @@ function runPrompt(input) {
|
|
|
2146
2197
|
const rawToolCall = rawToolCallsByToolCallId.get(
|
|
2147
2198
|
displayValue.toolCallId
|
|
2148
2199
|
);
|
|
2149
|
-
const toolName =
|
|
2200
|
+
const toolName = rawToolCall?.toolName ?? toolCall.toolName;
|
|
2150
2201
|
if (!isHarnessV1BuiltinToolIncluded({
|
|
2151
2202
|
toolName,
|
|
2152
2203
|
toolFiltering: input.builtinToolFiltering
|
|
@@ -2169,7 +2220,7 @@ function runPrompt(input) {
|
|
|
2169
2220
|
if (value.type === "error" && displayValue.type === "error") {
|
|
2170
2221
|
await waitForOutstandingHostToolExecutions();
|
|
2171
2222
|
await lifecycle.error(value.error);
|
|
2172
|
-
if (!
|
|
2223
|
+
if (!input.abortSignal?.aborted) {
|
|
2173
2224
|
logBridgeError({
|
|
2174
2225
|
harnessId: input.harness.harnessId,
|
|
2175
2226
|
sessionId: input.session.sessionId,
|
|
@@ -2191,15 +2242,25 @@ function runPrompt(input) {
|
|
|
2191
2242
|
} else {
|
|
2192
2243
|
for (const part of translatedParts) result.enqueue(part);
|
|
2193
2244
|
}
|
|
2245
|
+
let validatedHostToolCall;
|
|
2194
2246
|
if (displayValue.type === "tool-call") {
|
|
2247
|
+
const isHostTool = value.type === "tool-call" && !value.providerExecuted && hasTool({ tools: activeTools, toolName: value.toolName }) && !(value.toolName === "askUserQuestions" && hasTool({
|
|
2248
|
+
tools: input.harness.builtinTools,
|
|
2249
|
+
toolName: value.toolName
|
|
2250
|
+
}));
|
|
2195
2251
|
const parsed = await validateToolCall({
|
|
2196
|
-
event: displayValue,
|
|
2252
|
+
event: isHostTool ? value : displayValue,
|
|
2197
2253
|
tools: input.tools
|
|
2198
2254
|
});
|
|
2199
2255
|
const parsedToolCall = asToolCallTextStreamPart({ part: parsed });
|
|
2256
|
+
validatedHostToolCall = isHostTool ? parsedToolCall : void 0;
|
|
2257
|
+
const displayToolCall = isHostTool ? displayHostToolCall({
|
|
2258
|
+
toolCall: parsedToolCall,
|
|
2259
|
+
sessionWorkDir: input.sessionWorkDir
|
|
2260
|
+
}) : parsedToolCall;
|
|
2200
2261
|
rawToolCallsByToolCallId.set(displayValue.toolCallId, displayValue);
|
|
2201
|
-
toolCallsByToolCallId.set(displayValue.toolCallId,
|
|
2202
|
-
result.enqueue(
|
|
2262
|
+
toolCallsByToolCallId.set(displayValue.toolCallId, displayToolCall);
|
|
2263
|
+
result.enqueue(displayToolCall);
|
|
2203
2264
|
}
|
|
2204
2265
|
if (value.type === "text-delta") {
|
|
2205
2266
|
stepText += value.delta;
|
|
@@ -2208,7 +2269,7 @@ function runPrompt(input) {
|
|
|
2208
2269
|
}
|
|
2209
2270
|
if (value.type === "tool-call") {
|
|
2210
2271
|
observedStepToolCallCount += 1;
|
|
2211
|
-
expectedStepToolCallCount
|
|
2272
|
+
expectedStepToolCallCount ??= value.stepToolCallCount;
|
|
2212
2273
|
const toolCall = toolCallsByToolCallId.get(value.toolCallId);
|
|
2213
2274
|
if (toolCall != null) {
|
|
2214
2275
|
stepToolCalls.push(toolCall);
|
|
@@ -2230,7 +2291,7 @@ function runPrompt(input) {
|
|
|
2230
2291
|
output: value.result
|
|
2231
2292
|
};
|
|
2232
2293
|
}
|
|
2233
|
-
if (
|
|
2294
|
+
if (rawToolCallsByToolCallId.get(value.toolCallId)?.providerExecuted === true && execution?.toolOutput != null) {
|
|
2234
2295
|
stepProviderToolResults.push(
|
|
2235
2296
|
execution.toolOutput
|
|
2236
2297
|
);
|
|
@@ -2244,14 +2305,14 @@ function runPrompt(input) {
|
|
|
2244
2305
|
);
|
|
2245
2306
|
}
|
|
2246
2307
|
const rawToolCall = rawToolCallsByToolCallId.get(value.toolCallId);
|
|
2247
|
-
const pendingApproval =
|
|
2308
|
+
const pendingApproval = pendingApprovalsByApprovalId.get(value.approvalId) ?? {
|
|
2248
2309
|
approvalId: value.approvalId,
|
|
2249
2310
|
toolCallId: value.toolCallId,
|
|
2250
2311
|
toolName: toolCall.toolName,
|
|
2251
|
-
input:
|
|
2312
|
+
input: rawToolCall?.input ?? JSON.stringify(toolCall.input),
|
|
2252
2313
|
kind: "builtin",
|
|
2253
|
-
providerExecuted:
|
|
2254
|
-
...
|
|
2314
|
+
providerExecuted: rawToolCall?.providerExecuted ?? true,
|
|
2315
|
+
...rawToolCall?.nativeName !== void 0 ? { nativeName: rawToolCall.nativeName } : {}
|
|
2255
2316
|
};
|
|
2256
2317
|
pendingApprovalsByApprovalId.set(
|
|
2257
2318
|
pendingApproval.approvalId,
|
|
@@ -2345,6 +2406,31 @@ function runPrompt(input) {
|
|
|
2345
2406
|
await finishForHostInputPause({ completeCurrentStep: true });
|
|
2346
2407
|
return;
|
|
2347
2408
|
}
|
|
2409
|
+
if (validatedHostToolCall == null) {
|
|
2410
|
+
throw new Error(
|
|
2411
|
+
`Harness '${input.harness.harnessId}' could not validate host tool '${toolCall.toolName}'.`
|
|
2412
|
+
);
|
|
2413
|
+
}
|
|
2414
|
+
if (validatedHostToolCall.invalid) {
|
|
2415
|
+
settledHostToolCallIds.add(toolCall.toolCallId);
|
|
2416
|
+
toolExecutions.delete(toolCall.toolCallId);
|
|
2417
|
+
bufferedToolOutcomes.push(() => {
|
|
2418
|
+
result.enqueue({
|
|
2419
|
+
type: "tool-error",
|
|
2420
|
+
toolCallId: toolCall.toolCallId,
|
|
2421
|
+
toolName: toolCall.toolName,
|
|
2422
|
+
input: parsedToolCall.input,
|
|
2423
|
+
error: new Error(invalidToolInputMessage),
|
|
2424
|
+
dynamic: true
|
|
2425
|
+
});
|
|
2426
|
+
});
|
|
2427
|
+
await submitToolResult({
|
|
2428
|
+
toolCallId: toolCall.toolCallId,
|
|
2429
|
+
output: { error: invalidToolInputMessage },
|
|
2430
|
+
isError: true
|
|
2431
|
+
});
|
|
2432
|
+
continue;
|
|
2433
|
+
}
|
|
2348
2434
|
const customToolApprovalDecision = resolveCustomToolApproval({
|
|
2349
2435
|
toolName: toolCall.toolName,
|
|
2350
2436
|
toolApproval: input.toolApproval
|
|
@@ -2380,7 +2466,7 @@ function runPrompt(input) {
|
|
|
2380
2466
|
}
|
|
2381
2467
|
continue;
|
|
2382
2468
|
}
|
|
2383
|
-
const pendingApproval =
|
|
2469
|
+
const pendingApproval = pendingApprovalsByToolCallId.get(toolCall.toolCallId) ?? (customToolApprovalDecision.type === "request" ? {
|
|
2384
2470
|
approvalId: generateId2(),
|
|
2385
2471
|
toolCallId: toolCall.toolCallId,
|
|
2386
2472
|
toolName: toolCall.toolName,
|
|
@@ -2388,7 +2474,7 @@ function runPrompt(input) {
|
|
|
2388
2474
|
kind: "custom",
|
|
2389
2475
|
providerExecuted: false,
|
|
2390
2476
|
...toolCall.nativeName !== void 0 ? { nativeName: toolCall.nativeName } : {}
|
|
2391
|
-
} : void 0;
|
|
2477
|
+
} : void 0);
|
|
2392
2478
|
if (pendingApproval != null) {
|
|
2393
2479
|
pendingApprovalsByApprovalId.set(
|
|
2394
2480
|
pendingApproval.approvalId,
|
|
@@ -2444,6 +2530,7 @@ function runPrompt(input) {
|
|
|
2444
2530
|
const executionStartedAt = Date.now();
|
|
2445
2531
|
const execution = await maybeExecuteHostTool({
|
|
2446
2532
|
event: toolCall,
|
|
2533
|
+
parsedToolCall: validatedHostToolCall,
|
|
2447
2534
|
tools: activeTools,
|
|
2448
2535
|
toolsContext,
|
|
2449
2536
|
wrappedExecuteTool: lifecycle.executeTool,
|
|
@@ -2490,16 +2577,16 @@ function runPrompt(input) {
|
|
|
2490
2577
|
}
|
|
2491
2578
|
}
|
|
2492
2579
|
await waitForOutstandingHostToolExecutions();
|
|
2493
|
-
const isTurnSuspending =
|
|
2580
|
+
const isTurnSuspending = input.isTurnSuspending?.() === true;
|
|
2494
2581
|
if (isTurnSuspending) {
|
|
2495
2582
|
await publishToolExecutions();
|
|
2496
2583
|
if (finalFinish == null) {
|
|
2497
2584
|
result.discardCurrentStepContent();
|
|
2498
2585
|
}
|
|
2499
2586
|
} else if (finalFinish != null) {
|
|
2500
|
-
|
|
2587
|
+
input.onTurnFinished?.();
|
|
2501
2588
|
} else {
|
|
2502
|
-
|
|
2589
|
+
input.onTurnFailed?.();
|
|
2503
2590
|
}
|
|
2504
2591
|
await result.finish(
|
|
2505
2592
|
finalFinish ? {
|
|
@@ -2511,7 +2598,7 @@ function runPrompt(input) {
|
|
|
2511
2598
|
} catch (err) {
|
|
2512
2599
|
try {
|
|
2513
2600
|
await waitForOutstandingHostToolExecutions();
|
|
2514
|
-
} catch
|
|
2601
|
+
} catch {
|
|
2515
2602
|
}
|
|
2516
2603
|
await lifecycle.error(err);
|
|
2517
2604
|
logBridgeError({
|
|
@@ -2549,14 +2636,31 @@ function asToolCallTextStreamPart(input) {
|
|
|
2549
2636
|
}
|
|
2550
2637
|
return input.part;
|
|
2551
2638
|
}
|
|
2639
|
+
function displayHostToolCall(input) {
|
|
2640
|
+
return {
|
|
2641
|
+
...input.toolCall,
|
|
2642
|
+
input: stripParsedToolInputWorkDir({
|
|
2643
|
+
value: input.toolCall.input,
|
|
2644
|
+
sessionWorkDir: input.sessionWorkDir
|
|
2645
|
+
}),
|
|
2646
|
+
...input.toolCall.invalid ? { error: new Error(invalidToolInputMessage) } : {}
|
|
2647
|
+
};
|
|
2648
|
+
}
|
|
2552
2649
|
function hasTool(input) {
|
|
2553
2650
|
return Object.prototype.hasOwnProperty.call(input.tools, input.toolName);
|
|
2554
2651
|
}
|
|
2555
2652
|
async function maybeExecuteHostTool(input) {
|
|
2556
2653
|
const tool = input.tools[input.event.toolName];
|
|
2557
2654
|
if (!isExecutableTool(tool)) return { executed: false };
|
|
2558
|
-
|
|
2559
|
-
|
|
2655
|
+
if (input.parsedToolCall.invalid) {
|
|
2656
|
+
const error = new Error(invalidToolInputMessage);
|
|
2657
|
+
await input.submitToolResult({
|
|
2658
|
+
toolCallId: input.event.toolCallId,
|
|
2659
|
+
output: { error: invalidToolInputMessage },
|
|
2660
|
+
isError: true
|
|
2661
|
+
});
|
|
2662
|
+
return { executed: true, outcome: { ok: false, error } };
|
|
2663
|
+
}
|
|
2560
2664
|
let context;
|
|
2561
2665
|
try {
|
|
2562
2666
|
context = await validateToolContext({
|
|
@@ -2579,7 +2683,7 @@ async function maybeExecuteHostTool(input) {
|
|
|
2579
2683
|
let output2;
|
|
2580
2684
|
const stream = executeTool({
|
|
2581
2685
|
tool,
|
|
2582
|
-
input:
|
|
2686
|
+
input: input.parsedToolCall.input,
|
|
2583
2687
|
options: {
|
|
2584
2688
|
toolCallId: input.event.toolCallId,
|
|
2585
2689
|
messages: [],
|
|
@@ -2658,23 +2762,22 @@ var HarnessAgentSession = class {
|
|
|
2658
2762
|
this.sessionState = "active";
|
|
2659
2763
|
this.turnSequence = 0;
|
|
2660
2764
|
this.activeTurnSequence = 0;
|
|
2661
|
-
var _a4, _b4, _c, _d;
|
|
2662
2765
|
this.sessionId = options.sessionId;
|
|
2663
2766
|
this.harness = options.harness;
|
|
2664
2767
|
this.underlyingSession = options.underlyingSession;
|
|
2665
2768
|
this.sandboxSession = options.sandboxSession;
|
|
2666
|
-
this.ownsSandboxLifecycle =
|
|
2769
|
+
this.ownsSandboxLifecycle = options.ownsSandboxLifecycle ?? true;
|
|
2667
2770
|
this.sessionWorkDir = options.sessionWorkDir;
|
|
2668
2771
|
this.toolApproval = options.toolApproval;
|
|
2669
|
-
for (const approval of
|
|
2772
|
+
for (const approval of options.pendingToolApprovals ?? []) {
|
|
2670
2773
|
this.pendingToolApprovals.set(approval.approvalId, approval);
|
|
2671
2774
|
}
|
|
2672
|
-
for (const pendingResult of
|
|
2775
|
+
for (const pendingResult of options.pendingToolResults ?? []) {
|
|
2673
2776
|
this.pendingToolResults.set(pendingResult.toolCallId, pendingResult);
|
|
2674
2777
|
}
|
|
2675
2778
|
this.persistedTurnSettings = options.turnSettings;
|
|
2676
2779
|
this.resumedToolsContext = options.resumedToolsContext;
|
|
2677
|
-
this.turnState =
|
|
2780
|
+
this.turnState = options.turnState ?? (this.pendingToolApprovals.size > 0 ? "awaiting-approval" : this.pendingToolResults.size > 0 ? "awaiting-tool-result" : "idle");
|
|
2678
2781
|
this.isResume = options.underlyingSession.isResume;
|
|
2679
2782
|
}
|
|
2680
2783
|
/**
|
|
@@ -3041,9 +3144,8 @@ var HarnessAgentSession = class {
|
|
|
3041
3144
|
};
|
|
3042
3145
|
}
|
|
3043
3146
|
async suspendCurrentTurn(options) {
|
|
3044
|
-
var _a4;
|
|
3045
3147
|
this.clearActivePromptControl();
|
|
3046
|
-
|
|
3148
|
+
this.suspendedTurnState ??= (async () => {
|
|
3047
3149
|
const raw = await options.session.doSuspendTurn();
|
|
3048
3150
|
const validated = await validateLifecycleStateData({
|
|
3049
3151
|
harness: this.harness,
|
|
@@ -3135,14 +3237,14 @@ var HarnessAgentSession = class {
|
|
|
3135
3237
|
}
|
|
3136
3238
|
setPromptControl(options) {
|
|
3137
3239
|
const activePromptControl = this.activePromptControl;
|
|
3138
|
-
if (this.sessionState !== "active" || this.turnState !== "running" || this.activeTurnSequence !== options.turnId ||
|
|
3240
|
+
if (this.sessionState !== "active" || this.turnState !== "running" || this.activeTurnSequence !== options.turnId || activePromptControl?.turnId !== options.turnId) {
|
|
3139
3241
|
return;
|
|
3140
3242
|
}
|
|
3141
3243
|
this.settleActivePromptControl(options.control);
|
|
3142
3244
|
}
|
|
3143
3245
|
async waitForPromptControl(options) {
|
|
3144
3246
|
const activePromptControl = this.activePromptControl;
|
|
3145
|
-
if (
|
|
3247
|
+
if (activePromptControl?.turnId !== options.turnId) return;
|
|
3146
3248
|
await activePromptControl.promise;
|
|
3147
3249
|
}
|
|
3148
3250
|
settleActivePromptControl(control) {
|
|
@@ -3170,11 +3272,10 @@ var HarnessAgentSession = class {
|
|
|
3170
3272
|
this.turnState = "idle";
|
|
3171
3273
|
}
|
|
3172
3274
|
resolveActiveTurnSettings(options) {
|
|
3173
|
-
var _a4, _b4;
|
|
3174
3275
|
if (this.activeTurnSettings != null) {
|
|
3175
3276
|
return this.activeTurnSettings;
|
|
3176
3277
|
}
|
|
3177
|
-
const persisted =
|
|
3278
|
+
const persisted = this.persistedTurnSettings ?? {
|
|
3178
3279
|
...options.model == null ? {} : { model: options.model },
|
|
3179
3280
|
skills: options.skills,
|
|
3180
3281
|
...options.instructions == null ? {} : { instructions: options.instructions },
|
|
@@ -3194,7 +3295,7 @@ var HarnessAgentSession = class {
|
|
|
3194
3295
|
this.activeTurnSettings = {
|
|
3195
3296
|
persisted,
|
|
3196
3297
|
tools: options.tools,
|
|
3197
|
-
toolsContext:
|
|
3298
|
+
toolsContext: this.resumedToolsContext ?? options.toolsContext,
|
|
3198
3299
|
activeTools,
|
|
3199
3300
|
builtinToolFiltering: options.builtinToolFiltering
|
|
3200
3301
|
};
|
|
@@ -3219,7 +3320,7 @@ var HarnessAgentSession = class {
|
|
|
3219
3320
|
// src/agent/harness-agent-tool-approval-continuation.ts
|
|
3220
3321
|
function collectHarnessAgentToolApprovalContinuations(input) {
|
|
3221
3322
|
const lastMessage = input.messages.at(-1);
|
|
3222
|
-
if (
|
|
3323
|
+
if (lastMessage?.role !== "tool") return [];
|
|
3223
3324
|
const toolCallIds = /* @__PURE__ */ new Set();
|
|
3224
3325
|
const approvalRequestsByApprovalId = /* @__PURE__ */ new Map();
|
|
3225
3326
|
for (const message of input.messages) {
|
|
@@ -3263,7 +3364,7 @@ function collectHarnessAgentToolApprovalContinuations(input) {
|
|
|
3263
3364
|
// src/agent/harness-agent-tool-result-continuation.ts
|
|
3264
3365
|
function collectHarnessAgentToolResultContinuations(input) {
|
|
3265
3366
|
const lastMessage = input.messages.at(-1);
|
|
3266
|
-
if (
|
|
3367
|
+
if (lastMessage?.role !== "tool") return [];
|
|
3267
3368
|
return lastMessage.content.filter((part) => part.type === "tool-result");
|
|
3268
3369
|
}
|
|
3269
3370
|
|
|
@@ -3388,7 +3489,7 @@ function resolveBootstrapPath({
|
|
|
3388
3489
|
}
|
|
3389
3490
|
|
|
3390
3491
|
// src/agent/internal/sandbox-bootstrap.ts
|
|
3391
|
-
import { posix as
|
|
3492
|
+
import { posix as posix6 } from "path";
|
|
3392
3493
|
|
|
3393
3494
|
// src/utils/resolve-sandbox-default-working-directory.ts
|
|
3394
3495
|
import { posix as posix4 } from "path";
|
|
@@ -3436,6 +3537,59 @@ async function resolveSandboxHomeDir({
|
|
|
3436
3537
|
return homeDir;
|
|
3437
3538
|
}
|
|
3438
3539
|
|
|
3540
|
+
// src/agent/internal/on-bootstrap-marker.ts
|
|
3541
|
+
import { posix as posix5 } from "path";
|
|
3542
|
+
async function onBootstrapMarkerPath({
|
|
3543
|
+
session,
|
|
3544
|
+
bootstrapHash,
|
|
3545
|
+
abortSignal
|
|
3546
|
+
}) {
|
|
3547
|
+
const digest = new Uint8Array(
|
|
3548
|
+
await crypto.subtle.digest(
|
|
3549
|
+
"SHA-256",
|
|
3550
|
+
new TextEncoder().encode(bootstrapHash)
|
|
3551
|
+
)
|
|
3552
|
+
);
|
|
3553
|
+
const filename = Array.from(
|
|
3554
|
+
digest,
|
|
3555
|
+
(byte) => byte.toString(16).padStart(2, "0")
|
|
3556
|
+
).join("");
|
|
3557
|
+
return posix5.join(
|
|
3558
|
+
harnessStateDirectoryPath({
|
|
3559
|
+
sandboxHomeDir: await resolveSandboxHomeDir({
|
|
3560
|
+
sandbox: session,
|
|
3561
|
+
abortSignal
|
|
3562
|
+
})
|
|
3563
|
+
}),
|
|
3564
|
+
".on-bootstrap",
|
|
3565
|
+
`${filename}.ok`
|
|
3566
|
+
);
|
|
3567
|
+
}
|
|
3568
|
+
async function hasOnBootstrapMarker(options) {
|
|
3569
|
+
return await options.session.readTextFile({
|
|
3570
|
+
path: await onBootstrapMarkerPath(options),
|
|
3571
|
+
abortSignal: options.abortSignal
|
|
3572
|
+
}) !== null;
|
|
3573
|
+
}
|
|
3574
|
+
async function writeOnBootstrapMarker(options) {
|
|
3575
|
+
const path2 = await onBootstrapMarkerPath(options);
|
|
3576
|
+
const result = await options.session.run({
|
|
3577
|
+
command: 'mkdir -p "$MARKER_DIR"',
|
|
3578
|
+
env: { MARKER_DIR: posix5.dirname(path2) },
|
|
3579
|
+
abortSignal: options.abortSignal
|
|
3580
|
+
});
|
|
3581
|
+
if (result.exitCode !== 0) {
|
|
3582
|
+
throw new Error(
|
|
3583
|
+
`Failed to create onBootstrap marker directory: ${result.stderr || result.stdout}`
|
|
3584
|
+
);
|
|
3585
|
+
}
|
|
3586
|
+
await options.session.writeTextFile({
|
|
3587
|
+
path: path2,
|
|
3588
|
+
content: "",
|
|
3589
|
+
abortSignal: options.abortSignal
|
|
3590
|
+
});
|
|
3591
|
+
}
|
|
3592
|
+
|
|
3439
3593
|
// src/agent/internal/sandbox-bootstrap.ts
|
|
3440
3594
|
var SANDBOX_BOOTSTRAP_IDENTITY_VERSION = 1;
|
|
3441
3595
|
function validateSandboxBootstrapSettings(settings) {
|
|
@@ -3462,10 +3616,10 @@ function normalizeSandboxWorkDir(workDir) {
|
|
|
3462
3616
|
"HarnessAgent: `sandboxConfig.workDir` must use POSIX path separators."
|
|
3463
3617
|
);
|
|
3464
3618
|
}
|
|
3465
|
-
if (
|
|
3619
|
+
if (posix6.isAbsolute(workDir)) {
|
|
3466
3620
|
throw new Error("HarnessAgent: `sandboxConfig.workDir` must be relative.");
|
|
3467
3621
|
}
|
|
3468
|
-
const normalized =
|
|
3622
|
+
const normalized = posix6.normalize(workDir);
|
|
3469
3623
|
if (normalized === "." || normalized === ".." || normalized.startsWith("../")) {
|
|
3470
3624
|
throw new Error(
|
|
3471
3625
|
"HarnessAgent: `sandboxConfig.workDir` must stay inside the sandbox default working directory."
|
|
@@ -3481,7 +3635,7 @@ function resolveSessionWorkDir({
|
|
|
3481
3635
|
}) {
|
|
3482
3636
|
return joinSandboxPath({
|
|
3483
3637
|
base: defaultWorkingDirectory,
|
|
3484
|
-
path: workDir
|
|
3638
|
+
path: workDir ?? `${encodeHarnessPathSegment(harnessId)}-${encodeHarnessPathSegment(sessionId)}`
|
|
3485
3639
|
});
|
|
3486
3640
|
}
|
|
3487
3641
|
async function createSandboxBootstrapPlan({
|
|
@@ -3509,6 +3663,7 @@ async function createSandboxBootstrapPlan({
|
|
|
3509
3663
|
recipeIdentity,
|
|
3510
3664
|
workDir,
|
|
3511
3665
|
onBootstrap: settings.onBootstrap,
|
|
3666
|
+
bootstrapHash: settings.bootstrapHash,
|
|
3512
3667
|
abortSignal: opts.abortSignal
|
|
3513
3668
|
})
|
|
3514
3669
|
} : {}
|
|
@@ -3520,6 +3675,8 @@ async function runSandboxBootstrap({
|
|
|
3520
3675
|
recipeIdentity,
|
|
3521
3676
|
workDir,
|
|
3522
3677
|
onBootstrap,
|
|
3678
|
+
bootstrapHash,
|
|
3679
|
+
skipOnBootstrapIfMarked = false,
|
|
3523
3680
|
defaultWorkingDirectory,
|
|
3524
3681
|
abortSignal
|
|
3525
3682
|
}) {
|
|
@@ -3544,7 +3701,9 @@ async function runSandboxBootstrap({
|
|
|
3544
3701
|
});
|
|
3545
3702
|
}
|
|
3546
3703
|
if (onBootstrap == null) return;
|
|
3547
|
-
|
|
3704
|
+
if (skipOnBootstrapIfMarked && bootstrapHash != null && await hasOnBootstrapMarker({ session, bootstrapHash, abortSignal }))
|
|
3705
|
+
return;
|
|
3706
|
+
const resolvedDefaultWorkingDirectory = defaultWorkingDirectory ?? await resolveSandboxDefaultWorkingDirectory({
|
|
3548
3707
|
sandboxSession: session,
|
|
3549
3708
|
abortSignal
|
|
3550
3709
|
});
|
|
@@ -3558,6 +3717,9 @@ async function runSandboxBootstrap({
|
|
|
3558
3717
|
abortSignal
|
|
3559
3718
|
});
|
|
3560
3719
|
await onBootstrap({ session, workDir: bootstrapWorkDir, abortSignal });
|
|
3720
|
+
if (bootstrapHash != null) {
|
|
3721
|
+
await writeOnBootstrapMarker({ session, bootstrapHash, abortSignal });
|
|
3722
|
+
}
|
|
3561
3723
|
}
|
|
3562
3724
|
async function ensureSandboxDirectory({
|
|
3563
3725
|
session,
|
|
@@ -3587,9 +3749,9 @@ async function hashSandboxBootstrapIdentity({
|
|
|
3587
3749
|
chunks.push(encoder.encode("\0"));
|
|
3588
3750
|
};
|
|
3589
3751
|
pushString(String(SANDBOX_BOOTSTRAP_IDENTITY_VERSION));
|
|
3590
|
-
pushString(recipeIdentity
|
|
3591
|
-
pushString(bootstrapHash
|
|
3592
|
-
pushString(workDir
|
|
3752
|
+
pushString(recipeIdentity ?? "");
|
|
3753
|
+
pushString(bootstrapHash ?? "");
|
|
3754
|
+
pushString(workDir ?? "");
|
|
3593
3755
|
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
3594
3756
|
const buffer = new Uint8Array(totalLength);
|
|
3595
3757
|
let offset = 0;
|
|
@@ -3609,7 +3771,7 @@ function joinSandboxPath({
|
|
|
3609
3771
|
base,
|
|
3610
3772
|
path: path2
|
|
3611
3773
|
}) {
|
|
3612
|
-
return
|
|
3774
|
+
return posix6.join(base, path2);
|
|
3613
3775
|
}
|
|
3614
3776
|
|
|
3615
3777
|
// src/agent/internal/resolve-observability.ts
|
|
@@ -3621,10 +3783,9 @@ function parseList(value) {
|
|
|
3621
3783
|
return items.length > 0 ? items : void 0;
|
|
3622
3784
|
}
|
|
3623
3785
|
function resolveDebugConfig(debug, env = process.env) {
|
|
3624
|
-
|
|
3625
|
-
const
|
|
3626
|
-
const
|
|
3627
|
-
const subsystems = (debug == null ? void 0 : debug.subsystems) ? [...debug.subsystems] : parseList(env.HARNESS_DEBUG_SUBSYSTEMS);
|
|
3786
|
+
const enabled = debug?.enabled ?? ENV_TRUTHY.has((env.HARNESS_DEBUG ?? "").toLowerCase());
|
|
3787
|
+
const level = debug?.level ?? env.HARNESS_DEBUG_LEVEL ?? "debug";
|
|
3788
|
+
const subsystems = debug?.subsystems ? [...debug.subsystems] : parseList(env.HARNESS_DEBUG_SUBSYSTEMS);
|
|
3628
3789
|
return { enabled, level, subsystems };
|
|
3629
3790
|
}
|
|
3630
3791
|
function toHarnessDiagnostic(d) {
|
|
@@ -3642,36 +3803,33 @@ function toHarnessDiagnostic(d) {
|
|
|
3642
3803
|
};
|
|
3643
3804
|
}
|
|
3644
3805
|
function formatForStderr(d) {
|
|
3645
|
-
var _a4;
|
|
3646
3806
|
const parts = [`[harness:${d.level}]`, d.subsystem, d.message].filter(
|
|
3647
3807
|
Boolean
|
|
3648
3808
|
);
|
|
3649
3809
|
let line = parts.join(" ");
|
|
3650
3810
|
if (d.error) {
|
|
3651
|
-
line += ` (${
|
|
3811
|
+
line += ` (${d.error.name ?? "Error"}: ${d.error.message})`;
|
|
3652
3812
|
}
|
|
3653
3813
|
return `${line}
|
|
3654
3814
|
`;
|
|
3655
3815
|
}
|
|
3656
3816
|
function buildObservability(options) {
|
|
3657
|
-
var _a4;
|
|
3658
3817
|
const resolved = resolveDebugConfig(options.settings.debug);
|
|
3659
3818
|
if (!resolved.enabled) return void 0;
|
|
3660
3819
|
const onLog = options.settings.onLog;
|
|
3661
|
-
const integrations =
|
|
3820
|
+
const integrations = options.settings.telemetry?.integrations ? asArray(options.settings.telemetry.integrations) : [];
|
|
3662
3821
|
const diagnosticConsumers = integrations.filter(
|
|
3663
3822
|
(integration) => typeof integration.ingestDiagnostic === "function"
|
|
3664
3823
|
);
|
|
3665
3824
|
const report = (emitted) => {
|
|
3666
|
-
var _a5;
|
|
3667
3825
|
const diagnostic = toHarnessDiagnostic(emitted);
|
|
3668
3826
|
try {
|
|
3669
3827
|
process.stderr.write(formatForStderr(diagnostic));
|
|
3670
|
-
} catch
|
|
3828
|
+
} catch {
|
|
3671
3829
|
}
|
|
3672
|
-
onLog
|
|
3830
|
+
onLog?.(diagnostic);
|
|
3673
3831
|
for (const consumer of diagnosticConsumers) {
|
|
3674
|
-
|
|
3832
|
+
consumer.ingestDiagnostic?.(diagnostic);
|
|
3675
3833
|
}
|
|
3676
3834
|
};
|
|
3677
3835
|
return {
|
|
@@ -3696,7 +3854,7 @@ function resolveHarnessAgentToolFiltering(input) {
|
|
|
3696
3854
|
const activeTools = dedupeToolNames({ toolNames: input.activeTools });
|
|
3697
3855
|
const inactiveTools = dedupeToolNames({ toolNames: input.inactiveTools });
|
|
3698
3856
|
validateToolNames({
|
|
3699
|
-
requestedToolNames: activeTools
|
|
3857
|
+
requestedToolNames: activeTools ?? inactiveTools,
|
|
3700
3858
|
availableToolNames: allToolNames
|
|
3701
3859
|
});
|
|
3702
3860
|
const userToolNames = Object.keys(input.userTools);
|
|
@@ -3744,11 +3902,115 @@ function filterToolSet(input) {
|
|
|
3744
3902
|
);
|
|
3745
3903
|
}
|
|
3746
3904
|
|
|
3905
|
+
// src/agent/internal/prepared-sandbox-identity.ts
|
|
3906
|
+
var PREPARED_SANDBOX_IDENTITY_VERSION = 1;
|
|
3907
|
+
async function resolvePreparedSandboxIdentity({
|
|
3908
|
+
recipeIdentities,
|
|
3909
|
+
bootstrapHash,
|
|
3910
|
+
workDir
|
|
3911
|
+
}) {
|
|
3912
|
+
const entries = Object.entries(recipeIdentities).sort(
|
|
3913
|
+
([a], [b]) => a.localeCompare(b)
|
|
3914
|
+
);
|
|
3915
|
+
if (entries.length === 0 && bootstrapHash == null) return void 0;
|
|
3916
|
+
const encoder = new TextEncoder();
|
|
3917
|
+
const chunks = [];
|
|
3918
|
+
const pushString = (value) => {
|
|
3919
|
+
chunks.push(encoder.encode(value));
|
|
3920
|
+
chunks.push(encoder.encode("\0"));
|
|
3921
|
+
};
|
|
3922
|
+
pushString(String(PREPARED_SANDBOX_IDENTITY_VERSION));
|
|
3923
|
+
pushString(workDir ?? "");
|
|
3924
|
+
pushString(bootstrapHash ?? "");
|
|
3925
|
+
for (const [harnessId, identity] of entries) {
|
|
3926
|
+
pushString(harnessId);
|
|
3927
|
+
pushString(identity);
|
|
3928
|
+
}
|
|
3929
|
+
const buffer = new Uint8Array(
|
|
3930
|
+
chunks.reduce((sum, chunk) => sum + chunk.length, 0)
|
|
3931
|
+
);
|
|
3932
|
+
let offset = 0;
|
|
3933
|
+
for (const chunk of chunks) {
|
|
3934
|
+
buffer.set(chunk, offset);
|
|
3935
|
+
offset += chunk.length;
|
|
3936
|
+
}
|
|
3937
|
+
const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", buffer));
|
|
3938
|
+
return Array.from(
|
|
3939
|
+
digest.slice(0, 8),
|
|
3940
|
+
(byte) => byte.toString(16).padStart(2, "0")
|
|
3941
|
+
).join("");
|
|
3942
|
+
}
|
|
3943
|
+
|
|
3944
|
+
// src/agent/create-harness-sandbox-template.ts
|
|
3945
|
+
async function createHarnessSandboxTemplate(options) {
|
|
3946
|
+
if (options.harnesses.length === 0) {
|
|
3947
|
+
throw new Error(
|
|
3948
|
+
"createHarnessSandboxTemplate: at least one harness must be provided."
|
|
3949
|
+
);
|
|
3950
|
+
}
|
|
3951
|
+
const settings = options.sandboxConfig ?? {};
|
|
3952
|
+
validateSandboxBootstrapSettings(settings);
|
|
3953
|
+
const workDir = settings.workDir == null ? void 0 : normalizeSandboxWorkDir(settings.workDir);
|
|
3954
|
+
const harnesses = [
|
|
3955
|
+
...new Map(
|
|
3956
|
+
options.harnesses.map((harness) => [harness.harnessId, harness])
|
|
3957
|
+
).values()
|
|
3958
|
+
].sort((a, b) => a.harnessId.localeCompare(b.harnessId));
|
|
3959
|
+
const recipes = await Promise.all(
|
|
3960
|
+
harnesses.map(async (harness) => {
|
|
3961
|
+
const recipe = await harness.getBootstrap?.({});
|
|
3962
|
+
return recipe == null ? void 0 : {
|
|
3963
|
+
recipe,
|
|
3964
|
+
identity: await hashHarnessBootstrap(recipe)
|
|
3965
|
+
};
|
|
3966
|
+
})
|
|
3967
|
+
);
|
|
3968
|
+
const recipeIdentities = {};
|
|
3969
|
+
for (let index = 0; index < harnesses.length; index++) {
|
|
3970
|
+
const entry = recipes[index];
|
|
3971
|
+
if (entry != null)
|
|
3972
|
+
recipeIdentities[harnesses[index].harnessId] = entry.identity;
|
|
3973
|
+
}
|
|
3974
|
+
const identity = await resolvePreparedSandboxIdentity({
|
|
3975
|
+
recipeIdentities,
|
|
3976
|
+
bootstrapHash: settings.bootstrapHash,
|
|
3977
|
+
workDir
|
|
3978
|
+
});
|
|
3979
|
+
if (identity == null) return void 0;
|
|
3980
|
+
return {
|
|
3981
|
+
identity,
|
|
3982
|
+
prepare: async ({ session, abortSignal }) => {
|
|
3983
|
+
for (const entry of recipes) {
|
|
3984
|
+
if (entry != null) {
|
|
3985
|
+
await runSandboxBootstrap({
|
|
3986
|
+
session,
|
|
3987
|
+
recipe: entry.recipe,
|
|
3988
|
+
recipeIdentity: entry.identity,
|
|
3989
|
+
abortSignal
|
|
3990
|
+
});
|
|
3991
|
+
}
|
|
3992
|
+
}
|
|
3993
|
+
await runSandboxBootstrap({
|
|
3994
|
+
session,
|
|
3995
|
+
workDir,
|
|
3996
|
+
onBootstrap: settings.onBootstrap,
|
|
3997
|
+
bootstrapHash: settings.bootstrapHash,
|
|
3998
|
+
skipOnBootstrapIfMarked: true,
|
|
3999
|
+
abortSignal
|
|
4000
|
+
});
|
|
4001
|
+
}
|
|
4002
|
+
};
|
|
4003
|
+
}
|
|
4004
|
+
|
|
3747
4005
|
// src/agent/harness-agent.ts
|
|
3748
4006
|
var HarnessAgent = class {
|
|
3749
4007
|
constructor(settings) {
|
|
3750
4008
|
this.version = "agent-v1";
|
|
3751
|
-
|
|
4009
|
+
if (settings.sandbox != null) {
|
|
4010
|
+
console.warn(
|
|
4011
|
+
"HarnessAgent: `sandbox` is deprecated. Supply `sandboxSession` to createSession() instead."
|
|
4012
|
+
);
|
|
4013
|
+
}
|
|
3752
4014
|
const sandboxConfig = resolveSandboxConfig(settings);
|
|
3753
4015
|
validateSandboxBootstrapSettings(sandboxConfig);
|
|
3754
4016
|
this.settings = settings;
|
|
@@ -3760,7 +4022,7 @@ var HarnessAgent = class {
|
|
|
3760
4022
|
"user-agent",
|
|
3761
4023
|
"x-client-app"
|
|
3762
4024
|
]);
|
|
3763
|
-
const forbiddenHeader = Object.keys(
|
|
4025
|
+
const forbiddenHeader = Object.keys(settings.headers ?? {}).map((name4) => name4.toLowerCase()).find((name4) => forbiddenHeaders.has(name4));
|
|
3764
4026
|
if (forbiddenHeader != null) {
|
|
3765
4027
|
throw new Error(
|
|
3766
4028
|
`HarnessAgent: \`headers\` must not include the managed header \`${forbiddenHeader}\`.`
|
|
@@ -3769,7 +4031,7 @@ var HarnessAgent = class {
|
|
|
3769
4031
|
const headers = normalizeHeaders(settings.headers);
|
|
3770
4032
|
this.headers = Object.keys(headers).length === 0 ? void 0 : headers;
|
|
3771
4033
|
this.id = settings.id;
|
|
3772
|
-
const userTools =
|
|
4034
|
+
const userTools = settings.tools ?? {};
|
|
3773
4035
|
assertNoReservedQuestionTool({
|
|
3774
4036
|
harness: settings.harness,
|
|
3775
4037
|
userTools
|
|
@@ -3807,6 +4069,12 @@ var HarnessAgent = class {
|
|
|
3807
4069
|
get hasOutput() {
|
|
3808
4070
|
return this.settings.output != null;
|
|
3809
4071
|
}
|
|
4072
|
+
getSandboxTemplate() {
|
|
4073
|
+
return createHarnessSandboxTemplate({
|
|
4074
|
+
harnesses: [this.settings.harness],
|
|
4075
|
+
sandboxConfig: this.sandboxConfig
|
|
4076
|
+
});
|
|
4077
|
+
}
|
|
3810
4078
|
/**
|
|
3811
4079
|
* Start a fresh session, or resume from state previously returned by
|
|
3812
4080
|
* `session.detach()` or `session.stop()`. The returned
|
|
@@ -3815,12 +4083,11 @@ var HarnessAgent = class {
|
|
|
3815
4083
|
* `session.destroy()`.
|
|
3816
4084
|
*/
|
|
3817
4085
|
async createSession(options) {
|
|
3818
|
-
|
|
3819
|
-
const
|
|
3820
|
-
const
|
|
3821
|
-
const
|
|
3822
|
-
const
|
|
3823
|
-
const abortSignal = options == null ? void 0 : options.abortSignal;
|
|
4086
|
+
const sessionId = options?.sessionId ?? generateId3();
|
|
4087
|
+
const resumeFrom = options?.resumeFrom;
|
|
4088
|
+
const continueFrom = options?.continueFrom;
|
|
4089
|
+
const providedSandboxSession = options?.sandboxSession;
|
|
4090
|
+
const abortSignal = options?.abortSignal;
|
|
3824
4091
|
const harness = this.settings.harness;
|
|
3825
4092
|
const sandboxProvider = this.settings.sandbox;
|
|
3826
4093
|
const ownsSandboxLifecycle = providedSandboxSession == null;
|
|
@@ -3845,8 +4112,8 @@ var HarnessAgent = class {
|
|
|
3845
4112
|
expectedType: "continue-turn"
|
|
3846
4113
|
});
|
|
3847
4114
|
}
|
|
3848
|
-
const effectiveContinueFrom = validatedContinueFrom
|
|
3849
|
-
if (
|
|
4115
|
+
const effectiveContinueFrom = validatedContinueFrom ?? validatedResumeFrom?.continueFrom;
|
|
4116
|
+
if (options?.toolsContext != null && effectiveContinueFrom == null) {
|
|
3850
4117
|
throw new Error(
|
|
3851
4118
|
"HarnessAgent.createSession: `toolsContext` can only rebind an unfinished turn from `continueFrom` or `resumeFrom`."
|
|
3852
4119
|
);
|
|
@@ -3867,7 +4134,7 @@ var HarnessAgent = class {
|
|
|
3867
4134
|
sessionId,
|
|
3868
4135
|
workDir: this.sandboxConfig.workDir
|
|
3869
4136
|
});
|
|
3870
|
-
const recipe = await
|
|
4137
|
+
const recipe = await harness.getBootstrap?.({ abortSignal });
|
|
3871
4138
|
if (recipe != null) {
|
|
3872
4139
|
const recipeIdentity = await hashHarnessBootstrap(recipe);
|
|
3873
4140
|
try {
|
|
@@ -3899,7 +4166,7 @@ var HarnessAgent = class {
|
|
|
3899
4166
|
"HarnessAgent.createSession: configure `sandbox` on HarnessAgent or pass `sandboxSession` to createSession()."
|
|
3900
4167
|
);
|
|
3901
4168
|
}
|
|
3902
|
-
const recipe = await
|
|
4169
|
+
const recipe = await harness.getBootstrap?.({ abortSignal });
|
|
3903
4170
|
if (isResumedSession) {
|
|
3904
4171
|
if (sandboxProvider.resumeSession == null) {
|
|
3905
4172
|
throw new HarnessCapabilityUnsupportedError({
|
|
@@ -3988,6 +4255,14 @@ var HarnessAgent = class {
|
|
|
3988
4255
|
}
|
|
3989
4256
|
}
|
|
3990
4257
|
try {
|
|
4258
|
+
await runSandboxBootstrap({
|
|
4259
|
+
session: getRestrictedSandboxSession(sandboxSession),
|
|
4260
|
+
workDir: this.sandboxConfig.workDir,
|
|
4261
|
+
onBootstrap: this.sandboxConfig.onBootstrap,
|
|
4262
|
+
bootstrapHash: this.sandboxConfig.bootstrapHash,
|
|
4263
|
+
skipOnBootstrapIfMarked: true,
|
|
4264
|
+
abortSignal
|
|
4265
|
+
});
|
|
3991
4266
|
await ensureSandboxDirectory({
|
|
3992
4267
|
session: sandboxSession,
|
|
3993
4268
|
workDir: sessionWorkDir,
|
|
@@ -4031,10 +4306,10 @@ var HarnessAgent = class {
|
|
|
4031
4306
|
ownsSandboxLifecycle,
|
|
4032
4307
|
sessionWorkDir,
|
|
4033
4308
|
toolApproval: this.settings.toolApproval,
|
|
4034
|
-
pendingToolApprovals: effectiveContinueFrom
|
|
4035
|
-
pendingToolResults: effectiveContinueFrom
|
|
4036
|
-
turnSettings: effectiveContinueFrom
|
|
4037
|
-
resumedToolsContext: options
|
|
4309
|
+
pendingToolApprovals: effectiveContinueFrom?.pendingToolApprovals,
|
|
4310
|
+
pendingToolResults: effectiveContinueFrom?.pendingToolResults,
|
|
4311
|
+
turnSettings: effectiveContinueFrom?.turnSettings,
|
|
4312
|
+
resumedToolsContext: options?.toolsContext,
|
|
4038
4313
|
turnState: effectiveContinueFrom == null ? "idle" : effectiveContinueFrom.pendingToolApprovals != null && effectiveContinueFrom.pendingToolApprovals.length > 0 ? "awaiting-approval" : effectiveContinueFrom.pendingToolResults != null && effectiveContinueFrom.pendingToolResults.length > 0 ? "awaiting-tool-result" : "suspended"
|
|
4039
4314
|
});
|
|
4040
4315
|
} catch (error) {
|
|
@@ -4075,13 +4350,12 @@ var HarnessAgent = class {
|
|
|
4075
4350
|
* consuming a turn that crossed a process boundary.
|
|
4076
4351
|
*/
|
|
4077
4352
|
async continueGenerate(options) {
|
|
4078
|
-
var _a4, _b4;
|
|
4079
4353
|
const runtimeContext = {};
|
|
4080
4354
|
const { result, done } = await this._startContinueTurn({
|
|
4081
4355
|
session: options.session,
|
|
4082
4356
|
turnInput: {
|
|
4083
|
-
toolApprovalContinuations:
|
|
4084
|
-
toolResultContinuations:
|
|
4357
|
+
toolApprovalContinuations: options.toolApprovalContinuations ?? [],
|
|
4358
|
+
toolResultContinuations: options.toolResultContinuations ?? []
|
|
4085
4359
|
},
|
|
4086
4360
|
runtimeContext,
|
|
4087
4361
|
abortSignal: options.abortSignal
|
|
@@ -4098,13 +4372,12 @@ var HarnessAgent = class {
|
|
|
4098
4372
|
* follows from how the adapter resumed the session.
|
|
4099
4373
|
*/
|
|
4100
4374
|
async continueStream(options) {
|
|
4101
|
-
var _a4, _b4;
|
|
4102
4375
|
const runtimeContext = {};
|
|
4103
4376
|
const { result, ready } = await this._startContinueTurn({
|
|
4104
4377
|
session: options.session,
|
|
4105
4378
|
turnInput: {
|
|
4106
|
-
toolApprovalContinuations:
|
|
4107
|
-
toolResultContinuations:
|
|
4379
|
+
toolApprovalContinuations: options.toolApprovalContinuations ?? [],
|
|
4380
|
+
toolResultContinuations: options.toolResultContinuations ?? []
|
|
4108
4381
|
},
|
|
4109
4382
|
runtimeContext,
|
|
4110
4383
|
abortSignal: options.abortSignal
|
|
@@ -4172,31 +4445,30 @@ var HarnessAgent = class {
|
|
|
4172
4445
|
};
|
|
4173
4446
|
}
|
|
4174
4447
|
_resolveLifecycleCallbacks(call) {
|
|
4175
|
-
var _a4, _b4, _c, _d, _e, _f;
|
|
4176
4448
|
return {
|
|
4177
4449
|
onStart: mergeCallbacks(
|
|
4178
4450
|
this.settings.onStart,
|
|
4179
|
-
|
|
4451
|
+
call?.onStart ?? call?.experimental_onStart
|
|
4180
4452
|
),
|
|
4181
4453
|
onStepStart: mergeCallbacks(
|
|
4182
4454
|
this.settings.onStepStart,
|
|
4183
|
-
|
|
4455
|
+
call?.onStepStart ?? call?.experimental_onStepStart
|
|
4184
4456
|
),
|
|
4185
4457
|
onLanguageModelCallStart: this.settings.onLanguageModelCallStart,
|
|
4186
4458
|
onLanguageModelCallEnd: this.settings.onLanguageModelCallEnd,
|
|
4187
4459
|
onToolExecutionStart: mergeCallbacks(
|
|
4188
4460
|
this.settings.onToolExecutionStart,
|
|
4189
|
-
|
|
4461
|
+
call?.onToolExecutionStart ?? call?.experimental_onToolCallStart
|
|
4190
4462
|
),
|
|
4191
4463
|
onToolExecutionEnd: mergeCallbacks(
|
|
4192
4464
|
this.settings.onToolExecutionEnd,
|
|
4193
|
-
|
|
4465
|
+
call?.onToolExecutionEnd ?? call?.experimental_onToolCallFinish
|
|
4194
4466
|
),
|
|
4195
4467
|
onStepEnd: mergeCallbacks(
|
|
4196
4468
|
this.settings.onStepEnd,
|
|
4197
|
-
|
|
4469
|
+
call?.onStepEnd ?? call?.onStepFinish
|
|
4198
4470
|
),
|
|
4199
|
-
onEnd: mergeCallbacks(this.settings.onEnd,
|
|
4471
|
+
onEnd: mergeCallbacks(this.settings.onEnd, call?.onEnd ?? call?.onFinish)
|
|
4200
4472
|
};
|
|
4201
4473
|
}
|
|
4202
4474
|
_resolveContinueTurnInput(options) {
|
|
@@ -4231,7 +4503,7 @@ var HarnessAgent = class {
|
|
|
4231
4503
|
if (Array.isArray(messages)) {
|
|
4232
4504
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
4233
4505
|
const message = messages[i];
|
|
4234
|
-
if (
|
|
4506
|
+
if (message?.role === "user") return message;
|
|
4235
4507
|
}
|
|
4236
4508
|
throw new Error(
|
|
4237
4509
|
'HarnessAgent: messages must contain at least one `role: "user"` entry.'
|
|
@@ -4240,7 +4512,6 @@ var HarnessAgent = class {
|
|
|
4240
4512
|
throw new Error("HarnessAgent: either `prompt` or `messages` is required.");
|
|
4241
4513
|
}
|
|
4242
4514
|
async _preparePromptTurnInput(options) {
|
|
4243
|
-
var _a4, _b4, _c, _d;
|
|
4244
4515
|
let callOptions = options;
|
|
4245
4516
|
if (this.settings.callOptionsSchema != null && options.options !== void 0) {
|
|
4246
4517
|
const validatedOptions = await validateTypes({
|
|
@@ -4277,13 +4548,12 @@ var HarnessAgent = class {
|
|
|
4277
4548
|
skills: this.settings.skills,
|
|
4278
4549
|
instructions: this.settings.instructions,
|
|
4279
4550
|
tools: this.settings.tools,
|
|
4280
|
-
toolsContext:
|
|
4551
|
+
toolsContext: this.settings.toolsContext ?? {},
|
|
4281
4552
|
...promptOptions
|
|
4282
4553
|
};
|
|
4283
|
-
const preparedCallArgs =
|
|
4284
|
-
_b4,
|
|
4554
|
+
const preparedCallArgs = await this.settings.prepareCall?.(
|
|
4285
4555
|
baseCallArgs
|
|
4286
|
-
)
|
|
4556
|
+
) ?? baseCallArgs;
|
|
4287
4557
|
if (this._resolveContinueTurnInput(preparedCallArgs) != null) {
|
|
4288
4558
|
throw new Error(
|
|
4289
4559
|
"HarnessAgent.prepareCall must return a fresh user prompt, not a tool continuation."
|
|
@@ -4301,7 +4571,6 @@ var HarnessAgent = class {
|
|
|
4301
4571
|
};
|
|
4302
4572
|
}
|
|
4303
4573
|
_prepareContinueTurnInput(options) {
|
|
4304
|
-
var _a4, _b4;
|
|
4305
4574
|
return {
|
|
4306
4575
|
...this._prepareTurnSettings({
|
|
4307
4576
|
model: this.settings.model,
|
|
@@ -4310,13 +4579,12 @@ var HarnessAgent = class {
|
|
|
4310
4579
|
tools: this.settings.tools,
|
|
4311
4580
|
toolsContext: this.settings.toolsContext
|
|
4312
4581
|
}),
|
|
4313
|
-
toolApprovalContinuations:
|
|
4314
|
-
toolResultContinuations:
|
|
4582
|
+
toolApprovalContinuations: options.toolApprovalContinuations ?? [],
|
|
4583
|
+
toolResultContinuations: options.toolResultContinuations ?? []
|
|
4315
4584
|
};
|
|
4316
4585
|
}
|
|
4317
4586
|
_prepareTurnSettings(options) {
|
|
4318
|
-
|
|
4319
|
-
const userTools = (_a4 = options.tools) != null ? _a4 : {};
|
|
4587
|
+
const userTools = options.tools ?? {};
|
|
4320
4588
|
assertNoReservedQuestionTool({
|
|
4321
4589
|
harness: this.settings.harness,
|
|
4322
4590
|
userTools
|
|
@@ -4334,10 +4602,10 @@ var HarnessAgent = class {
|
|
|
4334
4602
|
});
|
|
4335
4603
|
return {
|
|
4336
4604
|
model: options.model,
|
|
4337
|
-
skills:
|
|
4338
|
-
instructions: typeof options.instructions === "string" ? options.instructions :
|
|
4605
|
+
skills: options.skills ?? [],
|
|
4606
|
+
instructions: typeof options.instructions === "string" ? options.instructions : options.instructions?.content,
|
|
4339
4607
|
tools,
|
|
4340
|
-
toolsContext:
|
|
4608
|
+
toolsContext: options.toolsContext ?? {},
|
|
4341
4609
|
activeTools: toolFiltering.activeUserTools,
|
|
4342
4610
|
toolSpecs: this._toToolSpecs(toolFiltering.activeUserTools),
|
|
4343
4611
|
builtinToolFiltering: toolFiltering.builtinToolFiltering
|
|
@@ -4360,7 +4628,7 @@ var HarnessAgent = class {
|
|
|
4360
4628
|
inputSchema = asSchema(
|
|
4361
4629
|
t.inputSchema
|
|
4362
4630
|
).jsonSchema;
|
|
4363
|
-
} catch
|
|
4631
|
+
} catch {
|
|
4364
4632
|
}
|
|
4365
4633
|
}
|
|
4366
4634
|
specs.push({ name: name4, description: t.description, inputSchema });
|
|
@@ -4377,8 +4645,7 @@ var HarnessAgent = class {
|
|
|
4377
4645
|
return new HarnessGenerateTextResult({ steps, usage, responseMessages, output });
|
|
4378
4646
|
}
|
|
4379
4647
|
async _resolveResponseFormat() {
|
|
4380
|
-
|
|
4381
|
-
const responseFormat = await ((_a4 = this.settings.output) == null ? void 0 : _a4.responseFormat);
|
|
4648
|
+
const responseFormat = await this.settings.output?.responseFormat;
|
|
4382
4649
|
if (responseFormat == null || responseFormat.type === "text") {
|
|
4383
4650
|
return responseFormat == null ? void 0 : { type: "text" };
|
|
4384
4651
|
}
|
|
@@ -4447,10 +4714,7 @@ var HarnessGenerateTextResult = class {
|
|
|
4447
4714
|
return this.finalStep.rawFinishReason;
|
|
4448
4715
|
}
|
|
4449
4716
|
get warnings() {
|
|
4450
|
-
return this.steps.flatMap((step) =>
|
|
4451
|
-
var _a4;
|
|
4452
|
-
return (_a4 = step.warnings) != null ? _a4 : [];
|
|
4453
|
-
});
|
|
4717
|
+
return this.steps.flatMap((step) => step.warnings ?? []);
|
|
4454
4718
|
}
|
|
4455
4719
|
get reasoning() {
|
|
4456
4720
|
return this.finalStep.content.filter(
|
|
@@ -4474,7 +4738,6 @@ var HarnessGenerateTextResult = class {
|
|
|
4474
4738
|
}
|
|
4475
4739
|
};
|
|
4476
4740
|
function resolveSandboxConfig(settings) {
|
|
4477
|
-
var _a4;
|
|
4478
4741
|
if (settings.onSandboxSession != null) {
|
|
4479
4742
|
console.warn(
|
|
4480
4743
|
"HarnessAgent: `onSandboxSession` is deprecated. Use `sandboxConfig.onSession` instead."
|
|
@@ -4482,7 +4745,7 @@ function resolveSandboxConfig(settings) {
|
|
|
4482
4745
|
}
|
|
4483
4746
|
return {
|
|
4484
4747
|
...settings.sandboxConfig,
|
|
4485
|
-
...
|
|
4748
|
+
...settings.sandboxConfig?.onSession == null && settings.onSandboxSession != null ? { onSession: settings.onSandboxSession } : {}
|
|
4486
4749
|
};
|
|
4487
4750
|
}
|
|
4488
4751
|
async function cleanupAfterStartFailure(input) {
|
|
@@ -4495,8 +4758,10 @@ async function cleanupAfterStartFailure(input) {
|
|
|
4495
4758
|
|
|
4496
4759
|
// src/agent/prepare-harness-sandbox-template.ts
|
|
4497
4760
|
async function prepareHarnessSandboxTemplate(options) {
|
|
4498
|
-
|
|
4499
|
-
|
|
4761
|
+
console.warn(
|
|
4762
|
+
"prepareHarnessSandboxTemplate (prewarmHarness) is deprecated. Use createHarnessSandboxTemplate and a sandbox session creator instead."
|
|
4763
|
+
);
|
|
4764
|
+
const sandboxConfig = options.sandboxConfig ?? {};
|
|
4500
4765
|
validateSandboxBootstrapSettings(sandboxConfig);
|
|
4501
4766
|
const { harness, sandboxProvider, abortSignal } = options;
|
|
4502
4767
|
let recipe;
|
|
@@ -4541,10 +4806,11 @@ async function prepareHarnessSandboxTemplate(options) {
|
|
|
4541
4806
|
var prewarmHarness = prepareHarnessSandboxTemplate;
|
|
4542
4807
|
|
|
4543
4808
|
// src/agent/prepare-sandbox-for-harness.ts
|
|
4544
|
-
var PREPARED_SANDBOX_IDENTITY_VERSION = 1;
|
|
4545
4809
|
async function prepareSandboxForHarness(options) {
|
|
4546
|
-
|
|
4547
|
-
|
|
4810
|
+
console.warn(
|
|
4811
|
+
"prepareSandboxForHarness is deprecated. Use createHarnessSandboxTemplate and template.prepare instead."
|
|
4812
|
+
);
|
|
4813
|
+
const sandboxConfig = options.sandboxConfig ?? {};
|
|
4548
4814
|
validateSandboxBootstrapSettings(sandboxConfig);
|
|
4549
4815
|
if (options.harnesses.length === 0) {
|
|
4550
4816
|
throw new Error(
|
|
@@ -4561,16 +4827,16 @@ async function prepareSandboxForHarness(options) {
|
|
|
4561
4827
|
const skippedHarnessIds = [];
|
|
4562
4828
|
let stateDirectory;
|
|
4563
4829
|
for (const harness of harnesses) {
|
|
4564
|
-
const recipe = await
|
|
4830
|
+
const recipe = await harness.getBootstrap?.({
|
|
4565
4831
|
abortSignal: options.abortSignal
|
|
4566
|
-
})
|
|
4832
|
+
});
|
|
4567
4833
|
if (recipe == null) {
|
|
4568
4834
|
skippedHarnessIds.push(harness.harnessId);
|
|
4569
4835
|
continue;
|
|
4570
4836
|
}
|
|
4571
4837
|
const recipeIdentity = await hashHarnessBootstrap(recipe);
|
|
4572
4838
|
recipeIdentities[harness.harnessId] = recipeIdentity;
|
|
4573
|
-
stateDirectory
|
|
4839
|
+
stateDirectory ??= harnessStateDirectoryPath({
|
|
4574
4840
|
sandboxHomeDir: await resolveSandboxHomeDir({
|
|
4575
4841
|
sandbox: options.session,
|
|
4576
4842
|
abortSignal: options.abortSignal
|
|
@@ -4592,6 +4858,7 @@ async function prepareSandboxForHarness(options) {
|
|
|
4592
4858
|
session: options.session,
|
|
4593
4859
|
workDir,
|
|
4594
4860
|
onBootstrap: sandboxConfig.onBootstrap,
|
|
4861
|
+
bootstrapHash: sandboxConfig.bootstrapHash,
|
|
4595
4862
|
defaultWorkingDirectory,
|
|
4596
4863
|
abortSignal: options.abortSignal
|
|
4597
4864
|
});
|
|
@@ -4607,45 +4874,6 @@ async function prepareSandboxForHarness(options) {
|
|
|
4607
4874
|
skippedHarnessIds
|
|
4608
4875
|
};
|
|
4609
4876
|
}
|
|
4610
|
-
async function resolvePreparedSandboxIdentity({
|
|
4611
|
-
recipeIdentities,
|
|
4612
|
-
bootstrapHash,
|
|
4613
|
-
workDir
|
|
4614
|
-
}) {
|
|
4615
|
-
const entries = Object.entries(recipeIdentities).sort(
|
|
4616
|
-
([a], [b]) => a.localeCompare(b)
|
|
4617
|
-
);
|
|
4618
|
-
if (entries.length === 0 && bootstrapHash == null) {
|
|
4619
|
-
return void 0;
|
|
4620
|
-
}
|
|
4621
|
-
const encoder = new TextEncoder();
|
|
4622
|
-
const chunks = [];
|
|
4623
|
-
const pushString = (value) => {
|
|
4624
|
-
chunks.push(encoder.encode(value));
|
|
4625
|
-
chunks.push(encoder.encode("\0"));
|
|
4626
|
-
};
|
|
4627
|
-
pushString(String(PREPARED_SANDBOX_IDENTITY_VERSION));
|
|
4628
|
-
pushString(workDir != null ? workDir : "");
|
|
4629
|
-
pushString(bootstrapHash != null ? bootstrapHash : "");
|
|
4630
|
-
for (const [harnessId, identity] of entries) {
|
|
4631
|
-
pushString(harnessId);
|
|
4632
|
-
pushString(identity);
|
|
4633
|
-
}
|
|
4634
|
-
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
4635
|
-
const buffer = new Uint8Array(totalLength);
|
|
4636
|
-
let offset = 0;
|
|
4637
|
-
for (const chunk of chunks) {
|
|
4638
|
-
buffer.set(chunk, offset);
|
|
4639
|
-
offset += chunk.length;
|
|
4640
|
-
}
|
|
4641
|
-
const digest = await crypto.subtle.digest("SHA-256", buffer);
|
|
4642
|
-
const bytes = new Uint8Array(digest);
|
|
4643
|
-
let hex = "";
|
|
4644
|
-
for (let i = 0; i < 8; i++) {
|
|
4645
|
-
hex += bytes[i].toString(16).padStart(2, "0");
|
|
4646
|
-
}
|
|
4647
|
-
return hex;
|
|
4648
|
-
}
|
|
4649
4877
|
|
|
4650
4878
|
// src/errors/harness-sandbox-authentication-error.ts
|
|
4651
4879
|
import { AISDKError as AISDKError3 } from "@ai-sdk/provider";
|
|
@@ -4681,10 +4909,9 @@ function getHarnessErrorMessage(error) {
|
|
|
4681
4909
|
// src/agent/observability/file-reporter.ts
|
|
4682
4910
|
import { appendFileSync, mkdirSync } from "fs";
|
|
4683
4911
|
function createFileReporter(options) {
|
|
4684
|
-
|
|
4685
|
-
const fileName = (_a4 = options.fileName) != null ? _a4 : "events.jsonl";
|
|
4912
|
+
const fileName = options.fileName ?? "events.jsonl";
|
|
4686
4913
|
const path2 = `${options.dir}/${fileName}`;
|
|
4687
|
-
const failOnly =
|
|
4914
|
+
const failOnly = options.failOnly ?? false;
|
|
4688
4915
|
const turns = /* @__PURE__ */ new Map();
|
|
4689
4916
|
let lastOpenCallId;
|
|
4690
4917
|
let dirReady = false;
|
|
@@ -4697,7 +4924,7 @@ function createFileReporter(options) {
|
|
|
4697
4924
|
return bucket;
|
|
4698
4925
|
};
|
|
4699
4926
|
const record = (callId, rec) => {
|
|
4700
|
-
const id = callId
|
|
4927
|
+
const id = callId ?? lastOpenCallId;
|
|
4701
4928
|
if (id == null) {
|
|
4702
4929
|
flushLines([rec]);
|
|
4703
4930
|
return;
|
|
@@ -4712,7 +4939,7 @@ function createFileReporter(options) {
|
|
|
4712
4939
|
dirReady = true;
|
|
4713
4940
|
}
|
|
4714
4941
|
appendFileSync(path2, lines.map((l) => JSON.stringify(l)).join("\n") + "\n");
|
|
4715
|
-
} catch
|
|
4942
|
+
} catch {
|
|
4716
4943
|
}
|
|
4717
4944
|
};
|
|
4718
4945
|
const finishTurn = (callId) => {
|
|
@@ -4783,14 +5010,13 @@ function createFileReporter(options) {
|
|
|
4783
5010
|
});
|
|
4784
5011
|
},
|
|
4785
5012
|
onEnd(event) {
|
|
4786
|
-
var _a5;
|
|
4787
5013
|
const e = event;
|
|
4788
5014
|
record(e.callId, {
|
|
4789
5015
|
ts: Date.now(),
|
|
4790
5016
|
kind: "turn-finish",
|
|
4791
5017
|
callId: e.callId,
|
|
4792
5018
|
finishReason: e.finishReason,
|
|
4793
|
-
usage:
|
|
5019
|
+
usage: e.totalUsage ?? e.usage
|
|
4794
5020
|
});
|
|
4795
5021
|
finishTurn(e.callId);
|
|
4796
5022
|
},
|
|
@@ -4817,8 +5043,7 @@ function createFileReporter(options) {
|
|
|
4817
5043
|
|
|
4818
5044
|
// src/agent/observability/trace-tree-reporter.ts
|
|
4819
5045
|
function createTraceTreeReporter(options = {}) {
|
|
4820
|
-
|
|
4821
|
-
const write = (_a4 = options.write) != null ? _a4 : ((chunk) => void process.stderr.write(chunk));
|
|
5046
|
+
const write = options.write ?? ((chunk) => void process.stderr.write(chunk));
|
|
4822
5047
|
const turns = /* @__PURE__ */ new Map();
|
|
4823
5048
|
const render = (node, depth) => {
|
|
4824
5049
|
const indent = " ".repeat(depth);
|
|
@@ -4830,11 +5055,10 @@ function createTraceTreeReporter(options = {}) {
|
|
|
4830
5055
|
};
|
|
4831
5056
|
return {
|
|
4832
5057
|
onStart(event) {
|
|
4833
|
-
var _a5;
|
|
4834
5058
|
const e = event;
|
|
4835
5059
|
turns.set(e.callId, {
|
|
4836
5060
|
root: {
|
|
4837
|
-
label: `${
|
|
5061
|
+
label: `${e.operationId ?? "turn"}${e.modelId ? ` ${e.modelId}` : ""}`,
|
|
4838
5062
|
startMs: Date.now(),
|
|
4839
5063
|
children: []
|
|
4840
5064
|
},
|
|
@@ -4842,12 +5066,11 @@ function createTraceTreeReporter(options = {}) {
|
|
|
4842
5066
|
});
|
|
4843
5067
|
},
|
|
4844
5068
|
onStepStart(event) {
|
|
4845
|
-
var _a5;
|
|
4846
5069
|
const e = event;
|
|
4847
5070
|
const turn = turns.get(e.callId);
|
|
4848
5071
|
if (!turn) return;
|
|
4849
5072
|
const step = {
|
|
4850
|
-
label: `step ${(
|
|
5073
|
+
label: `step ${(e.stepNumber ?? turn.root.children.length) + 1}`,
|
|
4851
5074
|
startMs: Date.now(),
|
|
4852
5075
|
children: []
|
|
4853
5076
|
};
|
|
@@ -4855,10 +5078,9 @@ function createTraceTreeReporter(options = {}) {
|
|
|
4855
5078
|
turn.root.children.push(step);
|
|
4856
5079
|
},
|
|
4857
5080
|
onToolExecutionStart(event) {
|
|
4858
|
-
var _a5;
|
|
4859
5081
|
const e = event;
|
|
4860
5082
|
const turn = turns.get(e.callId);
|
|
4861
|
-
const parent =
|
|
5083
|
+
const parent = turn?.step ?? turn?.root;
|
|
4862
5084
|
if (!turn || !parent) return;
|
|
4863
5085
|
const node = {
|
|
4864
5086
|
label: `tool ${e.toolCall.toolName}`,
|
|
@@ -4869,9 +5091,8 @@ function createTraceTreeReporter(options = {}) {
|
|
|
4869
5091
|
parent.children.push(node);
|
|
4870
5092
|
},
|
|
4871
5093
|
onToolExecutionEnd(event) {
|
|
4872
|
-
var _a5;
|
|
4873
5094
|
const e = event;
|
|
4874
|
-
const node =
|
|
5095
|
+
const node = turns.get(e.callId)?.tools.get(e.toolCall.toolCallId);
|
|
4875
5096
|
if (!node) return;
|
|
4876
5097
|
node.endMs = Date.now();
|
|
4877
5098
|
if (e.toolOutput.type === "error") node.label += " [error]";
|
|
@@ -4879,7 +5100,7 @@ function createTraceTreeReporter(options = {}) {
|
|
|
4879
5100
|
onStepFinish(event) {
|
|
4880
5101
|
const e = event;
|
|
4881
5102
|
const turn = turns.get(e.callId);
|
|
4882
|
-
if (turn
|
|
5103
|
+
if (turn?.step) {
|
|
4883
5104
|
turn.step.endMs = Date.now();
|
|
4884
5105
|
turn.step = void 0;
|
|
4885
5106
|
}
|
|
@@ -4893,7 +5114,7 @@ function createTraceTreeReporter(options = {}) {
|
|
|
4893
5114
|
try {
|
|
4894
5115
|
write(`
|
|
4895
5116
|
${render(turn.root, 0)}`);
|
|
4896
|
-
} catch
|
|
5117
|
+
} catch {
|
|
4897
5118
|
}
|
|
4898
5119
|
}
|
|
4899
5120
|
};
|
|
@@ -4907,6 +5128,7 @@ export {
|
|
|
4907
5128
|
collectHarnessAgentToolApprovalContinuations,
|
|
4908
5129
|
collectHarnessAgentToolResultContinuations,
|
|
4909
5130
|
createFileReporter,
|
|
5131
|
+
createHarnessSandboxTemplate,
|
|
4910
5132
|
createTraceTreeReporter,
|
|
4911
5133
|
getHarnessErrorMessage,
|
|
4912
5134
|
prepareHarnessSandboxTemplate,
|