@harness-kernel/core 0.2.1 → 0.3.0
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/dist/agent/context.d.ts +2 -3
- package/dist/agent/context.js +1 -1
- package/dist/agent/event.d.ts +3 -2
- package/dist/agent/event.js +6 -2
- package/dist/agent/hook.d.ts +3 -4
- package/dist/agent/hook.js +1 -1
- package/dist/agent/mode.d.ts +2 -3
- package/dist/agent/mode.js +1 -1
- package/dist/agent/role.js +1 -1
- package/dist/agent/session.d.ts +3 -4
- package/dist/agent/session.js +8 -2
- package/dist/agent/tool.d.ts +39 -3
- package/dist/agent/tool.js +8 -2
- package/dist/agent.d.ts +6 -6
- package/dist/{approval-D_G2w-fW.d.ts → approval-Ch0LwJFM.d.ts} +18 -13
- package/dist/chunk-2NQ3JL7K.js +502 -0
- package/dist/chunk-2NQ3JL7K.js.map +1 -0
- package/dist/{chunk-JIJHGB6H.js → chunk-3QOAFCCZ.js} +24 -2
- package/dist/chunk-3QOAFCCZ.js.map +1 -0
- package/dist/chunk-NCSQEUQC.js +37 -0
- package/dist/chunk-NCSQEUQC.js.map +1 -0
- package/dist/{chunk-B4Q6CPYO.js → chunk-TCHZYK5Y.js} +3 -1
- package/dist/{chunk-B4Q6CPYO.js.map → chunk-TCHZYK5Y.js.map} +1 -1
- package/dist/{chunk-QEVKKJ7N.js → chunk-UKXJIKED.js} +354 -132
- package/dist/chunk-UKXJIKED.js.map +1 -0
- package/dist/{context-BfpLqV11.d.ts → context-Bz9C_rL9.d.ts} +88 -3
- package/dist/errors-DHHy8V3O.d.ts +6 -0
- package/dist/errors-hpkW3tfR.d.ts +112 -0
- package/dist/{event-CKV4EeZ3.d.ts → event-DMBY-R6h.d.ts} +33 -4
- package/dist/{hook-CfBbhUQf.d.ts → hook-DD7uuzE3.d.ts} +2 -2
- package/dist/index.d.ts +21 -15
- package/dist/index.js +19 -6
- package/dist/metrics-DMN8bfY6.d.ts +23 -0
- package/dist/{model-provider-Ch7tzk1x.d.ts → model-provider-DGkLQJWP.d.ts} +6 -4
- package/dist/runner/approval.d.ts +7 -7
- package/dist/runner/event.d.ts +3 -2
- package/dist/runner/event.js +6 -2
- package/dist/runner/logging.d.ts +7 -3
- package/dist/runner/logging.js +11 -1
- package/dist/runner/model-provider.d.ts +6 -6
- package/dist/runner/storage.d.ts +181 -4
- package/dist/{runner-B41JEovO.d.ts → runner-CZHeMHKV.d.ts} +7 -5
- package/dist/runner.d.ts +9 -8
- package/dist/runner.js +11 -5
- package/package.json +2 -2
- package/dist/chunk-JIJHGB6H.js.map +0 -1
- package/dist/chunk-Q44U2CMM.js +0 -239
- package/dist/chunk-Q44U2CMM.js.map +0 -1
- package/dist/chunk-QEVKKJ7N.js.map +0 -1
- package/dist/events-D4xcDi53.d.ts +0 -69
- package/dist/storage-DCZE_hES.d.ts +0 -200
- package/dist/tool-errors-CygY1Nba.d.ts +0 -27
- package/dist/types-BPmsw-mF.d.ts +0 -80
|
@@ -9,11 +9,14 @@ import {
|
|
|
9
9
|
AgentWarnLog,
|
|
10
10
|
ConsoleLogSink,
|
|
11
11
|
HarnessLog,
|
|
12
|
+
annotateHarnessError,
|
|
13
|
+
normalizeHarnessError,
|
|
12
14
|
normalizeHarnessLog,
|
|
13
15
|
randomId,
|
|
16
|
+
sanitizeHarnessError,
|
|
14
17
|
shouldWriteLog,
|
|
15
18
|
summarizeValue
|
|
16
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-2NQ3JL7K.js";
|
|
17
20
|
import {
|
|
18
21
|
HarnessSandboxSession,
|
|
19
22
|
NoopSandbox
|
|
@@ -22,6 +25,10 @@ import {
|
|
|
22
25
|
HarnessSessionStorage,
|
|
23
26
|
MemorySessionStorage
|
|
24
27
|
} from "./chunk-ONYDIU4X.js";
|
|
28
|
+
import {
|
|
29
|
+
createToolErrorPayload,
|
|
30
|
+
createToolErrorResult
|
|
31
|
+
} from "./chunk-NCSQEUQC.js";
|
|
25
32
|
import {
|
|
26
33
|
ContextReadyEvent,
|
|
27
34
|
ErrorEvent,
|
|
@@ -31,7 +38,9 @@ import {
|
|
|
31
38
|
ModeChangedEvent,
|
|
32
39
|
ModelAfterEvent,
|
|
33
40
|
ModelBeforeEvent,
|
|
41
|
+
RunAbortedEvent,
|
|
34
42
|
RunEndEvent,
|
|
43
|
+
RunFailedEvent,
|
|
35
44
|
RunStartEvent,
|
|
36
45
|
SnapshotCreatedEvent,
|
|
37
46
|
SnapshotDeletedEvent,
|
|
@@ -44,7 +53,7 @@ import {
|
|
|
44
53
|
TurnEndEvent,
|
|
45
54
|
TurnStartEvent,
|
|
46
55
|
runtimeEventClasses
|
|
47
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-3QOAFCCZ.js";
|
|
48
57
|
import {
|
|
49
58
|
normalizeSchema
|
|
50
59
|
} from "./chunk-OBKS4AJR.js";
|
|
@@ -59,21 +68,7 @@ import {
|
|
|
59
68
|
systemRole,
|
|
60
69
|
toolRole,
|
|
61
70
|
userRole
|
|
62
|
-
} from "./chunk-
|
|
63
|
-
|
|
64
|
-
// src/logging/tool-errors.ts
|
|
65
|
-
function createToolErrorPayload(input) {
|
|
66
|
-
return {
|
|
67
|
-
ok: false,
|
|
68
|
-
error: {
|
|
69
|
-
code: input.code,
|
|
70
|
-
message: input.message,
|
|
71
|
-
toolName: input.toolName,
|
|
72
|
-
invalidFields: input.invalidFields,
|
|
73
|
-
metadata: input.metadata
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
}
|
|
71
|
+
} from "./chunk-TCHZYK5Y.js";
|
|
77
72
|
|
|
78
73
|
// src/logging/runtime-logs.ts
|
|
79
74
|
var SessionCreatedLog = class extends HarnessLog {
|
|
@@ -100,8 +95,11 @@ var RunCompletedLog = class extends HarnessLog {
|
|
|
100
95
|
var RunFailedLog = class extends HarnessLog {
|
|
101
96
|
level = "error";
|
|
102
97
|
category = "run";
|
|
103
|
-
|
|
104
|
-
return
|
|
98
|
+
levelFor(fields) {
|
|
99
|
+
return fields.error.severity === "warn" ? "warn" : "error";
|
|
100
|
+
}
|
|
101
|
+
message(fields) {
|
|
102
|
+
return `run.failed code=${fields.error.code}`;
|
|
105
103
|
}
|
|
106
104
|
};
|
|
107
105
|
var TurnStartedLog = class extends HarnessLog {
|
|
@@ -135,8 +133,11 @@ var ContextBuildCompletedLog = class extends HarnessLog {
|
|
|
135
133
|
var ContextProviderFailedLog = class extends HarnessLog {
|
|
136
134
|
level = "error";
|
|
137
135
|
category = "context";
|
|
136
|
+
levelFor(fields) {
|
|
137
|
+
return fields.error.severity === "warn" ? "warn" : "error";
|
|
138
|
+
}
|
|
138
139
|
message(fields) {
|
|
139
|
-
return `context.provider.failed ${fields.providerType}`;
|
|
140
|
+
return `context.provider.failed ${fields.providerType} code=${fields.error.code}`;
|
|
140
141
|
}
|
|
141
142
|
};
|
|
142
143
|
var ModelCallStartedLog = class extends HarnessLog {
|
|
@@ -156,8 +157,11 @@ var ModelCallCompletedLog = class extends HarnessLog {
|
|
|
156
157
|
var ModelCallFailedLog = class extends HarnessLog {
|
|
157
158
|
level = "error";
|
|
158
159
|
category = "model";
|
|
160
|
+
levelFor(fields) {
|
|
161
|
+
return fields.error.severity === "warn" ? "warn" : "error";
|
|
162
|
+
}
|
|
159
163
|
message(fields) {
|
|
160
|
-
return `model.failed model=${fields.model}`;
|
|
164
|
+
return `model.failed model=${fields.model} code=${fields.error.code}`;
|
|
161
165
|
}
|
|
162
166
|
};
|
|
163
167
|
var ModelDeltaLog = class extends HarnessLog {
|
|
@@ -198,8 +202,11 @@ var ToolCompletedLog = class extends HarnessLog {
|
|
|
198
202
|
var ToolFailedLog = class extends HarnessLog {
|
|
199
203
|
level = "error";
|
|
200
204
|
category = "tool";
|
|
205
|
+
levelFor(fields) {
|
|
206
|
+
return fields.error?.severity === "warn" ? "warn" : "error";
|
|
207
|
+
}
|
|
201
208
|
message(fields) {
|
|
202
|
-
return `tool.failed ${fields.toolName}`;
|
|
209
|
+
return `tool.failed ${fields.toolName}${fields.error ? ` code=${fields.error.code}` : ""}`;
|
|
203
210
|
}
|
|
204
211
|
};
|
|
205
212
|
var ToolApprovalRequestedLog = class extends HarnessLog {
|
|
@@ -244,7 +251,7 @@ var SandboxExecFailedLog = class extends HarnessLog {
|
|
|
244
251
|
level = "error";
|
|
245
252
|
category = "tool";
|
|
246
253
|
message(fields) {
|
|
247
|
-
return `sandbox.exec.failed ${fields.sandboxId}`;
|
|
254
|
+
return `sandbox.exec.failed ${fields.sandboxId}${fields.error ? ` code=${fields.error.code}` : ""}`;
|
|
248
255
|
}
|
|
249
256
|
};
|
|
250
257
|
var SandboxClosedLog = class extends HarnessLog {
|
|
@@ -300,7 +307,7 @@ var StorageWriteFailedLog = class extends HarnessLog {
|
|
|
300
307
|
level = "error";
|
|
301
308
|
category = "storage";
|
|
302
309
|
message(fields) {
|
|
303
|
-
return `storage.write_failed ${fields.operation}`;
|
|
310
|
+
return `storage.write_failed ${fields.operation} code=${fields.error.code}`;
|
|
304
311
|
}
|
|
305
312
|
};
|
|
306
313
|
|
|
@@ -666,7 +673,6 @@ var RunStorageCoordinator = class {
|
|
|
666
673
|
await this.write("save_transcript", (store) => store.saveTranscript(messages));
|
|
667
674
|
}
|
|
668
675
|
async saveMetrics(metrics) {
|
|
669
|
-
if (this.input.storage instanceof HarnessSessionStorage) return;
|
|
670
676
|
await this.write("save_metrics", (store) => store.saveMetrics(metrics));
|
|
671
677
|
}
|
|
672
678
|
async saveSnapshot(snapshot) {
|
|
@@ -1175,6 +1181,9 @@ function ensureToolMetric(metrics, name) {
|
|
|
1175
1181
|
metrics.tools[name] = metric;
|
|
1176
1182
|
return metric;
|
|
1177
1183
|
}
|
|
1184
|
+
function toolResultErrorCode(value) {
|
|
1185
|
+
return value === "tool.args.invalid_schema" || value === "tool.approval.denied" || value === "sandbox.exec.failed" || value === "tool.failed" ? value : "tool.failed";
|
|
1186
|
+
}
|
|
1178
1187
|
var ToolExecutor = class {
|
|
1179
1188
|
constructor(input) {
|
|
1180
1189
|
this.input = input;
|
|
@@ -1219,6 +1228,13 @@ var ToolExecutor = class {
|
|
|
1219
1228
|
};
|
|
1220
1229
|
const parsedArgs = safeParseWithSchema(input.tool.inputSchema, input.args);
|
|
1221
1230
|
if (!parsedArgs.ok) {
|
|
1231
|
+
const error = this.toolError({
|
|
1232
|
+
error: parsedArgs.error,
|
|
1233
|
+
code: "tool.args.invalid_schema",
|
|
1234
|
+
message: "Tool arguments did not match schema.",
|
|
1235
|
+
source: toolSource,
|
|
1236
|
+
details: { invalidFields: parsedArgs.invalidFields }
|
|
1237
|
+
});
|
|
1222
1238
|
const result = this.structuredToolError({
|
|
1223
1239
|
toolName: input.tool.name,
|
|
1224
1240
|
code: "tool.args.invalid_schema",
|
|
@@ -1228,7 +1244,7 @@ var ToolExecutor = class {
|
|
|
1228
1244
|
const durationMs = Math.round(performance.now() - start);
|
|
1229
1245
|
metric.errorCount++;
|
|
1230
1246
|
metric.totalDurationMs += durationMs;
|
|
1231
|
-
metrics.errors.push(
|
|
1247
|
+
metrics.errors.push(sanitizeHarnessError(error, this.input.errorPolicy));
|
|
1232
1248
|
this.input.log(
|
|
1233
1249
|
ToolInvalidSchemaLog,
|
|
1234
1250
|
{ toolName: input.tool.name, issues: parsedArgs.issues },
|
|
@@ -1238,6 +1254,7 @@ var ToolExecutor = class {
|
|
|
1238
1254
|
{ durationMs }
|
|
1239
1255
|
);
|
|
1240
1256
|
await this.input.addToolResultMessage(input.tool, result, id);
|
|
1257
|
+
await this.emitToolError(error, toolEventOptions);
|
|
1241
1258
|
await this.input.emitInternal(ToolEndEvent, { id, name: input.tool.name, durationMs, result }, callerEventOptions);
|
|
1242
1259
|
this.input.throwIfTurnHandoffRequested();
|
|
1243
1260
|
return result;
|
|
@@ -1257,6 +1274,13 @@ var ToolExecutor = class {
|
|
|
1257
1274
|
callerEventOptions
|
|
1258
1275
|
);
|
|
1259
1276
|
if (!approved) {
|
|
1277
|
+
const error = this.toolError({
|
|
1278
|
+
error: new Error(`Tool '${input.tool.name}' was denied by runner policy.`),
|
|
1279
|
+
code: "tool.approval.denied",
|
|
1280
|
+
message: `Tool '${input.tool.name}' was denied by runner policy.`,
|
|
1281
|
+
source: toolSource,
|
|
1282
|
+
severity: "warn"
|
|
1283
|
+
});
|
|
1260
1284
|
const denied = this.structuredToolError({
|
|
1261
1285
|
toolName: input.tool.name,
|
|
1262
1286
|
code: "tool.approval.denied",
|
|
@@ -1266,12 +1290,15 @@ var ToolExecutor = class {
|
|
|
1266
1290
|
metric.errorCount++;
|
|
1267
1291
|
const durationMs = Math.round(performance.now() - start);
|
|
1268
1292
|
metric.totalDurationMs += durationMs;
|
|
1293
|
+
metrics.errors.push(sanitizeHarnessError(error, this.input.errorPolicy));
|
|
1269
1294
|
this.input.log(ToolFailedLog, {
|
|
1270
1295
|
toolName: input.tool.name,
|
|
1271
1296
|
durationMs,
|
|
1297
|
+
error,
|
|
1272
1298
|
result: summarizeValue(denied)
|
|
1273
1299
|
}, toolSource, id, startEvent.id, { durationMs });
|
|
1274
1300
|
await this.input.addToolResultMessage(input.tool, denied, id);
|
|
1301
|
+
await this.emitToolError(error, toolEventOptions);
|
|
1275
1302
|
await this.input.emitInternal(ToolEndEvent, { id, name: input.tool.name, durationMs, result: denied }, callerEventOptions);
|
|
1276
1303
|
this.input.throwIfTurnHandoffRequested();
|
|
1277
1304
|
return denied;
|
|
@@ -1285,9 +1312,19 @@ var ToolExecutor = class {
|
|
|
1285
1312
|
metric.totalDurationMs += durationMs;
|
|
1286
1313
|
if (result.isError) metric.errorCount++;
|
|
1287
1314
|
if (result.isError) {
|
|
1315
|
+
const errorCode = toolResultErrorCode(result.metadata?.errorCode);
|
|
1316
|
+
const error = this.toolError({
|
|
1317
|
+
error: new Error(result.content || "Tool execution failed."),
|
|
1318
|
+
code: errorCode,
|
|
1319
|
+
message: result.content || "Tool execution failed.",
|
|
1320
|
+
source: toolSource,
|
|
1321
|
+
details: result.data
|
|
1322
|
+
});
|
|
1323
|
+
metrics.errors.push(sanitizeHarnessError(error, this.input.errorPolicy));
|
|
1288
1324
|
this.input.log(ToolFailedLog, {
|
|
1289
1325
|
toolName: input.tool.name,
|
|
1290
1326
|
durationMs,
|
|
1327
|
+
error,
|
|
1291
1328
|
result: summarizeValue(result)
|
|
1292
1329
|
}, toolSource, id, startEvent.id, { durationMs });
|
|
1293
1330
|
} else {
|
|
@@ -1303,7 +1340,13 @@ var ToolExecutor = class {
|
|
|
1303
1340
|
this.input.throwIfTurnHandoffRequested();
|
|
1304
1341
|
return result;
|
|
1305
1342
|
} catch (error) {
|
|
1306
|
-
const
|
|
1343
|
+
const normalized = this.toolError({
|
|
1344
|
+
error,
|
|
1345
|
+
code: "tool.failed",
|
|
1346
|
+
message: "Tool execution failed.",
|
|
1347
|
+
source: toolSource,
|
|
1348
|
+
details: { toolName: input.tool.name }
|
|
1349
|
+
});
|
|
1307
1350
|
const result = this.structuredToolError({
|
|
1308
1351
|
toolName: input.tool.name,
|
|
1309
1352
|
code: "tool.failed",
|
|
@@ -1313,14 +1356,15 @@ var ToolExecutor = class {
|
|
|
1313
1356
|
const durationMs = Math.round(performance.now() - start);
|
|
1314
1357
|
metric.errorCount++;
|
|
1315
1358
|
metric.totalDurationMs += durationMs;
|
|
1316
|
-
metrics.errors.push(
|
|
1359
|
+
metrics.errors.push(sanitizeHarnessError(normalized, this.input.errorPolicy));
|
|
1317
1360
|
this.input.log(ToolFailedLog, {
|
|
1318
1361
|
toolName: input.tool.name,
|
|
1319
1362
|
durationMs,
|
|
1320
|
-
error
|
|
1363
|
+
error: normalized,
|
|
1364
|
+
internalError: error
|
|
1321
1365
|
}, toolSource, id, startEvent.id, { durationMs });
|
|
1322
1366
|
await this.input.addToolResultMessage(input.tool, result, id);
|
|
1323
|
-
await this.
|
|
1367
|
+
await this.emitToolError(normalized, toolEventOptions);
|
|
1324
1368
|
await this.input.emitInternal(ToolEndEvent, { id, name: input.tool.name, durationMs, result }, callerEventOptions);
|
|
1325
1369
|
this.input.throwIfTurnHandoffRequested();
|
|
1326
1370
|
return result;
|
|
@@ -1329,21 +1373,7 @@ var ToolExecutor = class {
|
|
|
1329
1373
|
}
|
|
1330
1374
|
}
|
|
1331
1375
|
structuredToolError(input) {
|
|
1332
|
-
return
|
|
1333
|
-
content: input.message,
|
|
1334
|
-
data: createToolErrorPayload({
|
|
1335
|
-
code: input.code,
|
|
1336
|
-
message: input.message,
|
|
1337
|
-
toolName: input.toolName,
|
|
1338
|
-
invalidFields: input.invalidFields
|
|
1339
|
-
}),
|
|
1340
|
-
isError: true,
|
|
1341
|
-
metadata: {
|
|
1342
|
-
errorCode: input.code,
|
|
1343
|
-
...input.invalidFields ? { invalidFields: input.invalidFields } : {},
|
|
1344
|
-
...input.metadata ?? {}
|
|
1345
|
-
}
|
|
1346
|
-
};
|
|
1376
|
+
return createToolErrorResult(input);
|
|
1347
1377
|
}
|
|
1348
1378
|
ensureStructuredToolErrorResult(tool, result) {
|
|
1349
1379
|
if (!result.isError || result.data !== void 0) return result;
|
|
@@ -1360,6 +1390,29 @@ var ToolExecutor = class {
|
|
|
1360
1390
|
}
|
|
1361
1391
|
};
|
|
1362
1392
|
}
|
|
1393
|
+
toolError(input) {
|
|
1394
|
+
const normalized = normalizeHarnessError(input.error, {
|
|
1395
|
+
code: input.code,
|
|
1396
|
+
category: input.code === "tool.approval.denied" ? "approval" : input.code === "sandbox.exec.failed" ? "sandbox" : "tool",
|
|
1397
|
+
severity: input.severity ?? (input.code === "tool.approval.denied" ? "warn" : "error"),
|
|
1398
|
+
recoverable: true,
|
|
1399
|
+
source: input.source,
|
|
1400
|
+
message: input.message,
|
|
1401
|
+
details: input.details
|
|
1402
|
+
}, this.input.errorPolicy);
|
|
1403
|
+
annotateHarnessError(input.error, normalized);
|
|
1404
|
+
return normalized;
|
|
1405
|
+
}
|
|
1406
|
+
async emitToolError(error, options) {
|
|
1407
|
+
const sanitized = sanitizeHarnessError(error, this.input.errorPolicy);
|
|
1408
|
+
await this.input.emitInternal(ErrorEvent, {
|
|
1409
|
+
error: sanitized,
|
|
1410
|
+
message: sanitized.message,
|
|
1411
|
+
code: sanitized.code,
|
|
1412
|
+
recoverable: sanitized.recoverable,
|
|
1413
|
+
details: sanitized.details
|
|
1414
|
+
}, options);
|
|
1415
|
+
}
|
|
1363
1416
|
async approveTool(request, tool, args, eventOptions) {
|
|
1364
1417
|
const policy = this.input.getToolApprovalMode() ?? "tool-default";
|
|
1365
1418
|
if (policy === "auto") return this.recordApprovalResolution(request, "approved", eventOptions);
|
|
@@ -1520,6 +1573,20 @@ var SnapshotManager = class {
|
|
|
1520
1573
|
};
|
|
1521
1574
|
|
|
1522
1575
|
// src/runtime/model-pipeline.ts
|
|
1576
|
+
function retryDelayMs(attempt, backoffMs, maxBackoffMs) {
|
|
1577
|
+
return Math.min(maxBackoffMs, backoffMs * 2 ** Math.max(0, attempt - 1));
|
|
1578
|
+
}
|
|
1579
|
+
function delay(ms, signal) {
|
|
1580
|
+
if (ms <= 0) return Promise.resolve();
|
|
1581
|
+
if (signal?.aborted) return Promise.reject(new Error("Run aborted."));
|
|
1582
|
+
return new Promise((resolve, reject) => {
|
|
1583
|
+
const timeout = setTimeout(resolve, ms);
|
|
1584
|
+
signal?.addEventListener("abort", () => {
|
|
1585
|
+
clearTimeout(timeout);
|
|
1586
|
+
reject(new Error("Run aborted."));
|
|
1587
|
+
}, { once: true });
|
|
1588
|
+
});
|
|
1589
|
+
}
|
|
1523
1590
|
var ModelPipeline = class {
|
|
1524
1591
|
constructor(input) {
|
|
1525
1592
|
this.input = input;
|
|
@@ -1532,62 +1599,83 @@ var ModelPipeline = class {
|
|
|
1532
1599
|
const model = this.input.getModel();
|
|
1533
1600
|
const resolved = this.input.resolveModelProvider(model);
|
|
1534
1601
|
const source = this.modelProviderSource(resolved);
|
|
1535
|
-
|
|
1536
|
-
|
|
1602
|
+
const modelStart = performance.now();
|
|
1603
|
+
const retry = this.input.errorPolicy?.retry?.model;
|
|
1604
|
+
const maxAttempts = Math.max(1, retry?.attempts ?? 1);
|
|
1605
|
+
const backoffMs = Math.max(0, retry?.backoffMs ?? 250);
|
|
1606
|
+
const maxBackoffMs = Math.max(backoffMs, retry?.maxBackoffMs ?? 5e3);
|
|
1607
|
+
let result;
|
|
1608
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
1609
|
+
let toolExecuted = false;
|
|
1610
|
+
let providerEventEmitted = false;
|
|
1537
1611
|
this.input.log(ModelCallStartedLog, { model, messageCount: messages.length }, source);
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
} catch (error) {
|
|
1584
|
-
if (this.input.isTurnHandoffSignal(error)) return;
|
|
1585
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1586
|
-
this.input.getMetrics().errors.push(message);
|
|
1587
|
-
this.input.log(ModelCallFailedLog, { model, error }, source);
|
|
1588
|
-
await this.input.emitInternal(ErrorEvent, { message, details: error });
|
|
1589
|
-
throw error;
|
|
1612
|
+
try {
|
|
1613
|
+
result = await resolved.provider.run({
|
|
1614
|
+
runId: this.input.getRunId(),
|
|
1615
|
+
turnId: this.input.getTurnId(),
|
|
1616
|
+
modeId: this.input.getModeId(),
|
|
1617
|
+
modelRef: resolved.modelRef,
|
|
1618
|
+
provider: resolved.namespace,
|
|
1619
|
+
model: resolved.modelId,
|
|
1620
|
+
systemPrompt,
|
|
1621
|
+
messages,
|
|
1622
|
+
roles: this.input.roles,
|
|
1623
|
+
tools: input.tools,
|
|
1624
|
+
maxTurns: input.mode.maxTurns ?? 20,
|
|
1625
|
+
signal: input.options.signal,
|
|
1626
|
+
prepareContext: () => this.prepareContext(input.mode, input.userMessage),
|
|
1627
|
+
emit: async (eventClass, payload2, options) => {
|
|
1628
|
+
providerEventEmitted = true;
|
|
1629
|
+
const event = await this.input.emit(
|
|
1630
|
+
eventClass,
|
|
1631
|
+
payload2,
|
|
1632
|
+
this.input.withEmitDefaults(source, void 0, void 0, options)
|
|
1633
|
+
);
|
|
1634
|
+
this.input.throwIfTurnHandoffRequested();
|
|
1635
|
+
return event;
|
|
1636
|
+
},
|
|
1637
|
+
executeTool: async (tool, args, callId) => {
|
|
1638
|
+
toolExecuted = true;
|
|
1639
|
+
return this.input.executeTool(tool, args, callId, source);
|
|
1640
|
+
}
|
|
1641
|
+
});
|
|
1642
|
+
break;
|
|
1643
|
+
} catch (error) {
|
|
1644
|
+
if (this.input.isTurnHandoffSignal(error)) return;
|
|
1645
|
+
const normalized = normalizeHarnessError(error, {
|
|
1646
|
+
category: "model",
|
|
1647
|
+
severity: "error",
|
|
1648
|
+
recoverable: false,
|
|
1649
|
+
source
|
|
1650
|
+
}, this.input.errorPolicy);
|
|
1651
|
+
annotateHarnessError(error, normalized);
|
|
1652
|
+
this.input.log(ModelCallFailedLog, { model, error: normalized, internalError: error, attempt }, source);
|
|
1653
|
+
const canRetry = attempt < maxAttempts && normalized.category === "model" && !toolExecuted && !providerEventEmitted && input.options.signal?.aborted !== true;
|
|
1654
|
+
if (!canRetry) throw error;
|
|
1655
|
+
await delay(retryDelayMs(attempt, backoffMs, maxBackoffMs), input.options.signal);
|
|
1656
|
+
}
|
|
1590
1657
|
}
|
|
1658
|
+
if (!result) throw new Error("Model provider did not return a result.");
|
|
1659
|
+
const assistantMessage = await this.input.addAssistantMessage(result.content, {
|
|
1660
|
+
usage: result.usage,
|
|
1661
|
+
finishReason: result.finishReason
|
|
1662
|
+
});
|
|
1663
|
+
this.input.setFinalAnswer(result.content);
|
|
1664
|
+
this.input.getMetrics().usage = result.usage;
|
|
1665
|
+
await this.input.emitInternal(MessageEndEvent, { message: assistantMessage });
|
|
1666
|
+
await this.input.markMessageEventCursor(assistantMessage.id);
|
|
1667
|
+
this.input.log(ModelCallCompletedLog, {
|
|
1668
|
+
model,
|
|
1669
|
+
durationMs: Math.round(performance.now() - modelStart),
|
|
1670
|
+
finishReason: result.finishReason
|
|
1671
|
+
}, source);
|
|
1672
|
+
await this.input.emitInternal(ModelAfterEvent, {
|
|
1673
|
+
model,
|
|
1674
|
+
content: result.content,
|
|
1675
|
+
usage: result.usage,
|
|
1676
|
+
finishReason: result.finishReason
|
|
1677
|
+
});
|
|
1678
|
+
this.input.throwIfTurnHandoffRequested();
|
|
1591
1679
|
}
|
|
1592
1680
|
modelProviderSource(resolved) {
|
|
1593
1681
|
const id = modelProviderId(resolved.provider);
|
|
@@ -1776,7 +1864,16 @@ var AgentSessionRunner = class {
|
|
|
1776
1864
|
mode: () => this.currentMode,
|
|
1777
1865
|
openExistingRun: Boolean(options.initialRunId),
|
|
1778
1866
|
logOpened: (fields) => this.log(RunStorageOpenedLog, fields),
|
|
1779
|
-
logFailed: (fields) =>
|
|
1867
|
+
logFailed: (fields) => {
|
|
1868
|
+
const error = this.normalizeError(fields.error, {
|
|
1869
|
+
code: "storage.write_failed",
|
|
1870
|
+
category: "storage",
|
|
1871
|
+
severity: "error",
|
|
1872
|
+
recoverable: true,
|
|
1873
|
+
details: { operation: fields.operation }
|
|
1874
|
+
});
|
|
1875
|
+
this.log(StorageWriteFailedLog, { operation: fields.operation, error, internalError: fields.error });
|
|
1876
|
+
}
|
|
1780
1877
|
});
|
|
1781
1878
|
this.snapshotManager = new SnapshotManager({
|
|
1782
1879
|
now: () => nowIso4(),
|
|
@@ -1870,13 +1967,28 @@ var AgentSessionRunner = class {
|
|
|
1870
1967
|
logClosed: (fields) => this.log(SandboxClosedLog, fields),
|
|
1871
1968
|
logExecStarted: (fields) => this.log(SandboxExecStartedLog, fields),
|
|
1872
1969
|
logExecCompleted: (fields) => this.log(SandboxExecCompletedLog, fields),
|
|
1873
|
-
logExecFailed: (fields) =>
|
|
1970
|
+
logExecFailed: (fields) => {
|
|
1971
|
+
const error = this.normalizeError(fields.error, {
|
|
1972
|
+
code: "sandbox.exec.failed",
|
|
1973
|
+
category: "sandbox",
|
|
1974
|
+
severity: "error",
|
|
1975
|
+
recoverable: true,
|
|
1976
|
+
details: { sandboxId: fields.sandboxId, durationMs: fields.durationMs }
|
|
1977
|
+
});
|
|
1978
|
+
this.log(SandboxExecFailedLog, {
|
|
1979
|
+
sandboxId: fields.sandboxId,
|
|
1980
|
+
durationMs: fields.durationMs,
|
|
1981
|
+
error,
|
|
1982
|
+
internalError: fields.error
|
|
1983
|
+
});
|
|
1984
|
+
}
|
|
1874
1985
|
});
|
|
1875
1986
|
this.toolExecutor = new ToolExecutor({
|
|
1876
1987
|
getMetrics: () => this.metrics,
|
|
1877
1988
|
getCurrentMode: () => this.currentMode,
|
|
1878
1989
|
getToolApprovalMode: () => this.getModeDefinition(this.currentMode).toolApproval,
|
|
1879
1990
|
approveTool: this.options.approveTool,
|
|
1991
|
+
errorPolicy: this.options.errorPolicy,
|
|
1880
1992
|
ensureSandboxOpen: () => this.ensureSandboxOpen(),
|
|
1881
1993
|
buildActionSession: (tool, source, correlationId, causationId) => this.buildActionSession(tool, source, correlationId, causationId),
|
|
1882
1994
|
addToolCallMessage: (tool, args, toolCallId, source) => this.addToolCallMessage(tool, args, toolCallId, source),
|
|
@@ -1907,7 +2019,8 @@ var AgentSessionRunner = class {
|
|
|
1907
2019
|
withEmitDefaults: (source, correlationId, causationId, eventOptions) => this.withEmitDefaults(source, correlationId, causationId, eventOptions),
|
|
1908
2020
|
log: (logClass, fields, source, correlationId, causationId, overrides) => this.log(logClass, fields, source, correlationId, causationId, overrides),
|
|
1909
2021
|
throwIfTurnHandoffRequested: () => this.throwIfTurnHandoffRequested(),
|
|
1910
|
-
isTurnHandoffSignal: (error) => error instanceof TurnHandoffSignal
|
|
2022
|
+
isTurnHandoffSignal: (error) => error instanceof TurnHandoffSignal,
|
|
2023
|
+
errorPolicy: this.options.errorPolicy
|
|
1911
2024
|
});
|
|
1912
2025
|
this.state = this.createInitialState(this.agent);
|
|
1913
2026
|
for (const eventClass of runtimeEventClasses) eventType(eventClass);
|
|
@@ -1945,6 +2058,14 @@ var AgentSessionRunner = class {
|
|
|
1945
2058
|
hookDepth = 0;
|
|
1946
2059
|
turnHandoffRequested = false;
|
|
1947
2060
|
restoredFromRun = false;
|
|
2061
|
+
normalizeError(error, context = {}) {
|
|
2062
|
+
const normalized = normalizeHarnessError(error, context, this.options.errorPolicy);
|
|
2063
|
+
annotateHarnessError(error, normalized);
|
|
2064
|
+
return normalized;
|
|
2065
|
+
}
|
|
2066
|
+
publicError(error) {
|
|
2067
|
+
return sanitizeHarnessError(error, this.options.errorPolicy);
|
|
2068
|
+
}
|
|
1948
2069
|
logSource(source) {
|
|
1949
2070
|
if (!source) return { kind: "runtime" };
|
|
1950
2071
|
return {
|
|
@@ -2053,12 +2174,12 @@ var AgentSessionRunner = class {
|
|
|
2053
2174
|
this.turnHandoffRequested = false;
|
|
2054
2175
|
}
|
|
2055
2176
|
async run(message, options = {}) {
|
|
2056
|
-
if (options.signal?.aborted) throw new Error("Run aborted.");
|
|
2057
2177
|
await this.beginNewRun();
|
|
2058
2178
|
this.runModelOverride = void 0;
|
|
2059
2179
|
this.runModelOverride = this.normalizeModelOverride(options.model);
|
|
2060
2180
|
let runStarted = false;
|
|
2061
2181
|
try {
|
|
2182
|
+
if (options.signal?.aborted) throw new Error("Run aborted.");
|
|
2062
2183
|
await this.start();
|
|
2063
2184
|
runStarted = true;
|
|
2064
2185
|
this.pendingInputs.push({
|
|
@@ -2102,7 +2223,34 @@ var AgentSessionRunner = class {
|
|
|
2102
2223
|
outputDir: this.storeRunDir()
|
|
2103
2224
|
};
|
|
2104
2225
|
} catch (error) {
|
|
2105
|
-
this.
|
|
2226
|
+
const normalized = this.normalizeError(error, {
|
|
2227
|
+
code: "run.failed",
|
|
2228
|
+
category: "run",
|
|
2229
|
+
severity: "fatal",
|
|
2230
|
+
recoverable: false,
|
|
2231
|
+
source: { kind: "runtime" }
|
|
2232
|
+
});
|
|
2233
|
+
const publicError = this.publicError(normalized);
|
|
2234
|
+
this.finalizeMetrics();
|
|
2235
|
+
this.metrics.errors.push(publicError);
|
|
2236
|
+
await this.tryFailureWrite(() => this.storageCoordinator.saveTranscript(this.transcriptManager.allMessages));
|
|
2237
|
+
await this.tryFailureWrite(() => this.emitInternal(ErrorEvent, {
|
|
2238
|
+
error: publicError,
|
|
2239
|
+
message: publicError.message,
|
|
2240
|
+
code: publicError.code,
|
|
2241
|
+
recoverable: publicError.recoverable,
|
|
2242
|
+
details: publicError.details
|
|
2243
|
+
}, { skipHooks: true }));
|
|
2244
|
+
const terminalEvent = publicError.code === "run.aborted" ? RunAbortedEvent : RunFailedEvent;
|
|
2245
|
+
await this.tryFailureWrite(() => this.emitInternal(terminalEvent, {
|
|
2246
|
+
error: publicError,
|
|
2247
|
+
metrics: cloneJSON4({ ...this.metrics, eventCount: this.eventRecorder.count + 1 }),
|
|
2248
|
+
finalAnswer: this.finalAnswer || void 0
|
|
2249
|
+
}, { skipHooks: true }));
|
|
2250
|
+
this.contextRegistry.expireScope("run" /* Run */);
|
|
2251
|
+
this.finalizeMetrics();
|
|
2252
|
+
await this.tryFailureWrite(() => this.storageCoordinator.saveMetrics(this.metrics));
|
|
2253
|
+
this.log(RunFailedLog, { error: normalized, internalError: error });
|
|
2106
2254
|
throw error;
|
|
2107
2255
|
} finally {
|
|
2108
2256
|
if (runStarted) await this.closeSandbox();
|
|
@@ -2112,6 +2260,18 @@ var AgentSessionRunner = class {
|
|
|
2112
2260
|
async prompt(message, options = {}) {
|
|
2113
2261
|
return this.run(message, options);
|
|
2114
2262
|
}
|
|
2263
|
+
finalizeMetrics() {
|
|
2264
|
+
this.metrics.completedAt = this.metrics.completedAt ?? nowIso4();
|
|
2265
|
+
this.metrics.durationMs = this.startedAtPerf > 0 ? Math.round(performance.now() - this.startedAtPerf) : 0;
|
|
2266
|
+
this.metrics.finalMode = this.currentMode;
|
|
2267
|
+
this.metrics.eventCount = this.eventRecorder.count;
|
|
2268
|
+
}
|
|
2269
|
+
async tryFailureWrite(write) {
|
|
2270
|
+
try {
|
|
2271
|
+
await write();
|
|
2272
|
+
} catch {
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2115
2275
|
async hydrate() {
|
|
2116
2276
|
if (!this.restoredFromRun) return;
|
|
2117
2277
|
await this.ensureStoreInitialized();
|
|
@@ -2602,7 +2762,11 @@ var AgentSessionRunner = class {
|
|
|
2602
2762
|
this.log(ContextBuildStartedLog, { providerCount: activeBindings.length }, { kind: "runtime" });
|
|
2603
2763
|
const providers = [];
|
|
2604
2764
|
for (const binding of activeBindings) {
|
|
2605
|
-
|
|
2765
|
+
try {
|
|
2766
|
+
providers.push(await this.loadContextProvider(binding));
|
|
2767
|
+
} catch (error) {
|
|
2768
|
+
if (!this.handleContextProviderFailure(binding, error)) throw error;
|
|
2769
|
+
}
|
|
2606
2770
|
}
|
|
2607
2771
|
const dynamicEntries = this.dynamicContextEntriesFor(trigger);
|
|
2608
2772
|
const contributions = [
|
|
@@ -2654,18 +2818,40 @@ var AgentSessionRunner = class {
|
|
|
2654
2818
|
binding: summary,
|
|
2655
2819
|
contributions: this.normalizeContextOutput(provider, output)
|
|
2656
2820
|
};
|
|
2657
|
-
} catch (error) {
|
|
2658
|
-
this.log(
|
|
2659
|
-
ContextProviderFailedLog,
|
|
2660
|
-
{ providerType: summary.type, error },
|
|
2661
|
-
{ kind: "context_provider", id: summary.type, name: summary.label },
|
|
2662
|
-
this.currentTurnId
|
|
2663
|
-
);
|
|
2664
|
-
throw error;
|
|
2665
2821
|
} finally {
|
|
2666
2822
|
this.providerStack.pop();
|
|
2667
2823
|
}
|
|
2668
2824
|
}
|
|
2825
|
+
handleContextProviderFailure(binding, error) {
|
|
2826
|
+
let summary = { type: "unknown" };
|
|
2827
|
+
let required = true;
|
|
2828
|
+
try {
|
|
2829
|
+
const { provider, options } = this.providerFromReference(binding, true);
|
|
2830
|
+
summary = contextProviderSummary(provider, options);
|
|
2831
|
+
required = isContextProviderBinding(binding) && typeof binding.required === "boolean" ? binding.required : provider.required ?? true;
|
|
2832
|
+
} catch {
|
|
2833
|
+
}
|
|
2834
|
+
const modeFailure = this.getModeDefinition(this.currentMode).contextFailure;
|
|
2835
|
+
const policyAllowsSkip = this.options.errorPolicy?.contextFailure === "warn-and-skip";
|
|
2836
|
+
const skip = policyAllowsSkip && (required === false || modeFailure === "warn-and-skip");
|
|
2837
|
+
const source = { kind: "context_provider", id: summary.type, name: summary.label };
|
|
2838
|
+
const normalized = this.normalizeError(error, {
|
|
2839
|
+
code: "context.provider.failed",
|
|
2840
|
+
category: "context",
|
|
2841
|
+
severity: skip ? "warn" : "error",
|
|
2842
|
+
recoverable: skip,
|
|
2843
|
+
source,
|
|
2844
|
+
details: { providerType: summary.type }
|
|
2845
|
+
});
|
|
2846
|
+
this.log(
|
|
2847
|
+
ContextProviderFailedLog,
|
|
2848
|
+
{ providerType: summary.type, error: normalized, internalError: error },
|
|
2849
|
+
source,
|
|
2850
|
+
this.currentTurnId
|
|
2851
|
+
);
|
|
2852
|
+
if (skip) this.metrics.errors.push(this.publicError(normalized));
|
|
2853
|
+
return skip;
|
|
2854
|
+
}
|
|
2669
2855
|
normalizeContextContribution(input, context = {}) {
|
|
2670
2856
|
if (typeof input === "string") {
|
|
2671
2857
|
const role2 = this.resolveRole(context.defaultRole ?? systemRole);
|
|
@@ -3078,6 +3264,20 @@ var SessionEventHub = class {
|
|
|
3078
3264
|
runId: record.runId,
|
|
3079
3265
|
mode: String(payload2.modeId ?? record.modeId ?? "")
|
|
3080
3266
|
});
|
|
3267
|
+
} else if (record.type === RunFailedEvent.type) {
|
|
3268
|
+
events.push({
|
|
3269
|
+
type: "run.failed",
|
|
3270
|
+
runId: record.runId,
|
|
3271
|
+
error: payload2.error,
|
|
3272
|
+
metrics: payload2.metrics
|
|
3273
|
+
});
|
|
3274
|
+
} else if (record.type === RunAbortedEvent.type) {
|
|
3275
|
+
events.push({
|
|
3276
|
+
type: "run.aborted",
|
|
3277
|
+
runId: record.runId,
|
|
3278
|
+
error: payload2.error,
|
|
3279
|
+
metrics: payload2.metrics
|
|
3280
|
+
});
|
|
3081
3281
|
} else if (record.type === MessageDeltaEvent.type) {
|
|
3082
3282
|
events.push({
|
|
3083
3283
|
type: "assistant.delta",
|
|
@@ -3224,14 +3424,17 @@ var SessionQueue = class {
|
|
|
3224
3424
|
if (!targetType) return "none";
|
|
3225
3425
|
if (record.type === targetType) {
|
|
3226
3426
|
this.pendingSendTriggers.shift();
|
|
3227
|
-
return record.type
|
|
3427
|
+
return this.isTerminalRunEvent(record.type) ? "cleared" : "handoff";
|
|
3228
3428
|
}
|
|
3229
|
-
if (record.type
|
|
3429
|
+
if (this.isTerminalRunEvent(record.type)) {
|
|
3230
3430
|
this.pendingSendTriggers.shift();
|
|
3231
3431
|
return "cleared";
|
|
3232
3432
|
}
|
|
3233
3433
|
return "none";
|
|
3234
3434
|
}
|
|
3435
|
+
isTerminalRunEvent(type) {
|
|
3436
|
+
return type === RunEndEvent.type || type === RunFailedEvent.type || type === RunAbortedEvent.type;
|
|
3437
|
+
}
|
|
3235
3438
|
};
|
|
3236
3439
|
|
|
3237
3440
|
// src/session/stream.ts
|
|
@@ -3358,9 +3561,19 @@ var SessionStatusTracker = class {
|
|
|
3358
3561
|
this.currentTurnIdValue = void 0;
|
|
3359
3562
|
} else if (record.type === RunEndEvent.type) {
|
|
3360
3563
|
this.phaseValue = "completed" /* Completed */;
|
|
3361
|
-
} else if (record.type ===
|
|
3564
|
+
} else if (record.type === RunFailedEvent.type || record.type === RunAbortedEvent.type) {
|
|
3362
3565
|
this.phaseValue = "error" /* Error */;
|
|
3363
|
-
this.lastErrorValue =
|
|
3566
|
+
this.lastErrorValue = payload2.error;
|
|
3567
|
+
} else if (record.type === ErrorEvent.type) {
|
|
3568
|
+
const error = payload2.error;
|
|
3569
|
+
this.lastErrorValue = error ?? {
|
|
3570
|
+
code: "runtime.failed",
|
|
3571
|
+
category: "runtime",
|
|
3572
|
+
severity: "fatal",
|
|
3573
|
+
recoverable: false,
|
|
3574
|
+
message: String(payload2.message ?? "Unknown error")
|
|
3575
|
+
};
|
|
3576
|
+
if (!this.lastErrorValue.recoverable) this.phaseValue = "error" /* Error */;
|
|
3364
3577
|
}
|
|
3365
3578
|
if (record.turnId) this.currentTurnIdValue = record.turnId;
|
|
3366
3579
|
}
|
|
@@ -3385,17 +3598,6 @@ function nowIso6() {
|
|
|
3385
3598
|
function normalizeInput(input) {
|
|
3386
3599
|
return typeof input === "string" ? { content: input } : input;
|
|
3387
3600
|
}
|
|
3388
|
-
function toErrorShape(error) {
|
|
3389
|
-
if (error instanceof Error) {
|
|
3390
|
-
return {
|
|
3391
|
-
name: error.name,
|
|
3392
|
-
message: error.message,
|
|
3393
|
-
stack: error.stack,
|
|
3394
|
-
cause: error.cause
|
|
3395
|
-
};
|
|
3396
|
-
}
|
|
3397
|
-
return { message: String(error) };
|
|
3398
|
-
}
|
|
3399
3601
|
var HarnessSessionImpl = class {
|
|
3400
3602
|
constructor(config, input) {
|
|
3401
3603
|
this.config = config;
|
|
@@ -3424,7 +3626,8 @@ var HarnessSessionImpl = class {
|
|
|
3424
3626
|
initialRunId: input.restoredSession?.latestRunId,
|
|
3425
3627
|
resources: config.resources,
|
|
3426
3628
|
approveTool: (request) => this.requestToolApproval(request),
|
|
3427
|
-
logger: this.logger
|
|
3629
|
+
logger: this.logger,
|
|
3630
|
+
errorPolicy: config.errorPolicy
|
|
3428
3631
|
});
|
|
3429
3632
|
this.logger.emit(SessionCreatedLog, { sessionId: this.id }, { sessionId: this.id, source: { kind: "runtime" } });
|
|
3430
3633
|
this.unsubscribeRunner = this.runner.subscribe((record) => {
|
|
@@ -3517,11 +3720,18 @@ var HarnessSessionImpl = class {
|
|
|
3517
3720
|
await this.logger.flush();
|
|
3518
3721
|
return sendResult;
|
|
3519
3722
|
} catch (error) {
|
|
3520
|
-
const shaped =
|
|
3723
|
+
const shaped = sanitizeHarnessError(normalizeHarnessError(error, {
|
|
3724
|
+
code: "run.failed",
|
|
3725
|
+
category: "run",
|
|
3726
|
+
severity: "fatal",
|
|
3727
|
+
recoverable: false,
|
|
3728
|
+
source: { kind: "runtime" }
|
|
3729
|
+
}, this.config.errorPolicy), this.config.errorPolicy);
|
|
3521
3730
|
this.status.failRun(shaped);
|
|
3522
3731
|
this.notify({ type: "error", error: shaped });
|
|
3523
3732
|
this.notifyStatus();
|
|
3524
3733
|
await this.logger.flush();
|
|
3734
|
+
if (this.config.errorPolicy?.closeSessionOnFatal) await this.closeAfterFatal();
|
|
3525
3735
|
throw error;
|
|
3526
3736
|
} finally {
|
|
3527
3737
|
unsubscribe();
|
|
@@ -3676,6 +3886,17 @@ var HarnessSessionImpl = class {
|
|
|
3676
3886
|
this.activeAbort?.abort(reason);
|
|
3677
3887
|
this.approvals.denyAll();
|
|
3678
3888
|
}
|
|
3889
|
+
async closeAfterFatal() {
|
|
3890
|
+
if (this.closed) return;
|
|
3891
|
+
this.closed = true;
|
|
3892
|
+
this.status.close();
|
|
3893
|
+
this.approvals.denyAll();
|
|
3894
|
+
this.unsubscribeRunner();
|
|
3895
|
+
await this.runner.close();
|
|
3896
|
+
this.notifyStatus();
|
|
3897
|
+
this.events.clear();
|
|
3898
|
+
await this.logger.close();
|
|
3899
|
+
}
|
|
3679
3900
|
};
|
|
3680
3901
|
async function createHarnessSession(config, options = {}) {
|
|
3681
3902
|
const agent = await resolveAgent(config.agent);
|
|
@@ -3709,6 +3930,7 @@ function mergeConfig(base, overrides) {
|
|
|
3709
3930
|
providers: overrides?.providers ?? base.providers,
|
|
3710
3931
|
resources: overrides?.resources ?? base.resources,
|
|
3711
3932
|
logging: overrides?.logging ?? base.logging,
|
|
3933
|
+
errorPolicy: overrides?.errorPolicy ?? base.errorPolicy,
|
|
3712
3934
|
storage: overrides?.storage ?? base.storage
|
|
3713
3935
|
};
|
|
3714
3936
|
}
|
|
@@ -3794,6 +4016,7 @@ var HarnessSessionStoreImpl = class {
|
|
|
3794
4016
|
this.unsubscriptions.set(id, session.on((event) => {
|
|
3795
4017
|
if (event.type === "run.started") this.latestRunIds.set(id, event.runId);
|
|
3796
4018
|
if (event.type === "run.completed") this.latestRunIds.set(id, event.result.runId);
|
|
4019
|
+
if (event.type === "run.failed" || event.type === "run.aborted") this.latestRunIds.set(id, event.runId);
|
|
3797
4020
|
if (event.type === "session.status") {
|
|
3798
4021
|
void this.storage.touchSession({
|
|
3799
4022
|
sessionId: id,
|
|
@@ -3891,7 +4114,6 @@ async function createHarnessSessionStore(config) {
|
|
|
3891
4114
|
}
|
|
3892
4115
|
|
|
3893
4116
|
export {
|
|
3894
|
-
createToolErrorPayload,
|
|
3895
4117
|
AgentSessionRunner,
|
|
3896
4118
|
HarnessSessionPhase,
|
|
3897
4119
|
HarnessSessionImpl,
|
|
@@ -3899,4 +4121,4 @@ export {
|
|
|
3899
4121
|
HarnessSessionStoreImpl,
|
|
3900
4122
|
createHarnessSessionStore
|
|
3901
4123
|
};
|
|
3902
|
-
//# sourceMappingURL=chunk-
|
|
4124
|
+
//# sourceMappingURL=chunk-UKXJIKED.js.map
|