@ai-sdk/harness 1.0.100 → 1.0.102

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.
@@ -42,9 +42,11 @@ var HarnessCapabilityUnsupportedError = class extends (_b2 = HarnessError, _a2 =
42
42
  import {
43
43
  asArray as asArray2,
44
44
  asSchema,
45
- generateId as generateId5,
45
+ generateId as generateId3,
46
+ normalizeHeaders,
46
47
  validateTypes
47
48
  } from "@ai-sdk/provider-utils";
49
+ import { mergeCallbacks } from "ai/internal";
48
50
 
49
51
  // src/agent/internal/lifecycle-state-validation.ts
50
52
  import { safeValidateTypes } from "@ai-sdk/provider-utils";
@@ -155,19 +157,18 @@ async function toHarnessStream(options) {
155
157
  // src/agent/internal/run-prompt.ts
156
158
  import {
157
159
  executeTool,
158
- generateId as generateId4,
160
+ generateId as generateId2,
159
161
  isExecutableTool,
160
162
  safeParseJSON as safeParseJSON2
161
163
  } from "@ai-sdk/provider-utils";
162
164
  import {
163
165
  getErrorMessage
164
166
  } from "@ai-sdk/provider";
165
- import { parseToolCall } from "ai/internal";
167
+ import { asLanguageModelUsage as asLanguageModelUsage2, parseToolCall } from "ai/internal";
166
168
 
167
169
  // src/agent/internal/harness-stream-text-result.ts
168
170
  import {
169
- DelayedPromise,
170
- generateId
171
+ DelayedPromise
171
172
  } from "@ai-sdk/provider-utils";
172
173
  import {
173
174
  addLanguageModelUsage,
@@ -224,7 +225,8 @@ var HarnessStreamTextResult = class {
224
225
  this.runtimeContext = options.runtimeContext;
225
226
  this.toolsContext = options.toolsContext;
226
227
  this.providerName = `harness:${options.harnessId}`;
227
- this.modelId = options.sessionId;
228
+ this.callId = options.callId;
229
+ this.modelId = options.modelId;
228
230
  this.outputSpecification = options.output;
229
231
  let controllerRef;
230
232
  const baseStream = new ReadableStream({
@@ -252,6 +254,11 @@ var HarnessStreamTextResult = class {
252
254
  this.fullStreamController.enqueue(part);
253
255
  this.appendToCurrentStepContent(part);
254
256
  }
257
+ setModelId(modelId) {
258
+ if (this.stepsBuffer.length === 0) {
259
+ this.modelId = modelId;
260
+ }
261
+ }
255
262
  /**
256
263
  * Push a continuation input into the consumer stream without attributing it
257
264
  * to the next model step. Approval responses and client tool results arrive
@@ -281,7 +288,7 @@ var HarnessStreamTextResult = class {
281
288
  const finishReason = input.finishReason.unified;
282
289
  const rawFinishReason = input.finishReason.raw;
283
290
  const step = new DefaultStepResult({
284
- callId: generateId(),
291
+ callId: this.callId,
285
292
  stepNumber: this.stepNumber,
286
293
  provider: this.providerName,
287
294
  modelId: this.modelId,
@@ -295,7 +302,7 @@ var HarnessStreamTextResult = class {
295
302
  warnings: input.warnings.length > 0 ? input.warnings : void 0,
296
303
  request: {},
297
304
  response: {
298
- id: generateId(),
305
+ id: `${this.callId}-${this.stepNumber}`,
299
306
  timestamp: /* @__PURE__ */ new Date(),
300
307
  modelId: this.modelId,
301
308
  messages: []
@@ -357,7 +364,7 @@ var HarnessStreamTextResult = class {
357
364
  }
358
365
  this.settled = true;
359
366
  const finalStep = this.stepsBuffer.length > 0 ? this.stepsBuffer[this.stepsBuffer.length - 1] : new DefaultStepResult({
360
- callId: generateId(),
367
+ callId: this.callId,
361
368
  stepNumber: 0,
362
369
  provider: this.providerName,
363
370
  modelId: this.modelId,
@@ -371,7 +378,7 @@ var HarnessStreamTextResult = class {
371
378
  warnings: void 0,
372
379
  request: {},
373
380
  response: {
374
- id: generateId(),
381
+ id: `${this.callId}-0`,
375
382
  timestamp: /* @__PURE__ */ new Date(),
376
383
  modelId: this.modelId,
377
384
  messages: []
@@ -733,6 +740,18 @@ var HarnessStreamTextResult = class {
733
740
  }
734
741
  return;
735
742
  }
743
+ case "reasoning-delta": {
744
+ const last = this.currentStepContent[this.currentStepContent.length - 1];
745
+ if (last && last.type === "reasoning") {
746
+ last.text += part.text;
747
+ } else {
748
+ this.currentStepContent.push({
749
+ type: "reasoning",
750
+ text: part.text
751
+ });
752
+ }
753
+ return;
754
+ }
736
755
  case "tool-call":
737
756
  case "tool-approval-request":
738
757
  case "tool-approval-response":
@@ -833,7 +852,7 @@ function notSupportedYet(feature) {
833
852
  }
834
853
 
835
854
  // src/agent/internal/translate-stream-part.ts
836
- import { generateId as generateId2 } from "@ai-sdk/provider-utils";
855
+ import { generateId } from "@ai-sdk/provider-utils";
837
856
  function translateStreamPart(event, options = {}) {
838
857
  var _a4, _b4;
839
858
  switch (event.type) {
@@ -925,7 +944,7 @@ function translateStreamPart(event, options = {}) {
925
944
  }
926
945
  ];
927
946
  case "file-change": {
928
- const toolCallId = `harness-file-change-${generateId2()}`;
947
+ const toolCallId = `harness-file-change-${generateId()}`;
929
948
  const payload = { event: event.event, path: event.path };
930
949
  return [
931
950
  {
@@ -950,7 +969,7 @@ function translateStreamPart(event, options = {}) {
950
969
  ];
951
970
  }
952
971
  case "compaction": {
953
- const toolCallId = `harness-compaction-${generateId2()}`;
972
+ const toolCallId = `harness-compaction-${generateId()}`;
954
973
  const output = {
955
974
  trigger: event.trigger,
956
975
  summary: event.summary,
@@ -1097,371 +1116,255 @@ function stripDeep(value, workDir) {
1097
1116
  }
1098
1117
 
1099
1118
  // src/agent/internal/turn-telemetry.ts
1100
- import {
1101
- generateId as generateId3
1102
- } from "@ai-sdk/provider-utils";
1103
1119
  import { createTelemetryDispatcher } from "ai/internal";
1104
- var NOOP = {
1105
- async start() {
1106
- },
1107
- async ensureStepOpen() {
1108
- },
1109
- async stepFinish() {
1110
- },
1111
- async toolStart() {
1112
- },
1113
- async executeTool({ execute }) {
1114
- return await execute();
1115
- },
1116
- async toolEnd() {
1117
- },
1118
- async end() {
1119
- },
1120
- async error() {
1121
- }
1122
- };
1123
- function normalizeFinishReason(finishReason) {
1124
- if (finishReason != null && typeof finishReason === "object" && "unified" in finishReason) {
1125
- return finishReason.unified;
1126
- }
1127
- return finishReason;
1128
- }
1129
- function addTokenCounts(tokenCount1, tokenCount2) {
1130
- return tokenCount1 == null && tokenCount2 == null ? void 0 : (tokenCount1 != null ? tokenCount1 : 0) + (tokenCount2 != null ? tokenCount2 : 0);
1131
- }
1132
- function normalizeUsage(usage) {
1133
- if (usage == null || typeof usage !== "object" || !("inputTokens" in usage) || !("outputTokens" in usage)) {
1134
- return usage;
1135
- }
1136
- const inputTokens = usage.inputTokens;
1137
- const outputTokens = usage.outputTokens;
1138
- if (inputTokens == null || typeof inputTokens !== "object" || outputTokens == null || typeof outputTokens !== "object") {
1139
- return usage;
1140
- }
1141
- const input = inputTokens;
1142
- const output = outputTokens;
1143
- return {
1144
- inputTokens: input.total,
1145
- inputTokenDetails: {
1146
- noCacheTokens: input.noCache,
1147
- cacheReadTokens: input.cacheRead,
1148
- cacheWriteTokens: input.cacheWrite
1149
- },
1150
- outputTokens: output.total,
1151
- outputTokenDetails: {
1152
- textTokens: output.text,
1153
- reasoningTokens: output.reasoning
1154
- },
1155
- totalTokens: addTokenCounts(input.total, output.total),
1156
- raw: usage.raw
1157
- };
1120
+ async function notify(event, ...callbacks) {
1121
+ await Promise.allSettled(
1122
+ callbacks.map(async (callback) => {
1123
+ await (callback == null ? void 0 : callback(event));
1124
+ })
1125
+ );
1158
1126
  }
1159
- function createTurnTelemetry(opts) {
1127
+ function createTurnLifecycle(options) {
1160
1128
  var _a4;
1161
- if (opts.telemetry == null) return NOOP;
1162
- const dispatcher = createTelemetryDispatcher({ telemetry: opts.telemetry });
1163
- const callId = generateId3();
1164
- const provider = opts.harnessId;
1165
- let modelId = (_a4 = opts.modelId) != null ? _a4 : "";
1166
- const runtimeContext = opts.runtimeContext;
1167
- const inputMessages = [
1168
- { role: "user", content: opts.promptText }
1169
- ];
1170
- const languageModelTools = opts.toolSpecs.length === 0 ? void 0 : opts.toolSpecs.map((tool) => ({
1171
- type: "function",
1172
- name: tool.name,
1173
- ...tool.description != null ? { description: tool.description } : {},
1174
- ...tool.inputSchema != null ? { inputSchema: tool.inputSchema } : {}
1175
- }));
1129
+ const telemetry = options.telemetry == null ? {} : createTelemetryDispatcher({ telemetry: options.telemetry });
1130
+ const provider = `harness:${options.harnessId}`;
1131
+ let modelId = (_a4 = options.modelId) != null ? _a4 : "";
1176
1132
  let started = false;
1177
1133
  let stepOpen = false;
1178
1134
  let stepNumber = 0;
1179
1135
  let ended = false;
1180
- let finalStepText = "";
1181
- let finalStepReasoning = [];
1182
- let finalStepProviderMetadata;
1183
- let outputToolCalls = [];
1184
- const openTools = /* @__PURE__ */ new Map();
1185
- const cast = (event) => event;
1186
- const fireStart = async () => {
1187
- var _a5;
1188
- if (started) return;
1189
- started = true;
1190
- await ((_a5 = dispatcher.onStart) == null ? void 0 : _a5.call(
1191
- dispatcher,
1192
- cast({
1193
- callId,
1194
- operationId: "ai.harness",
1195
- provider,
1196
- modelId,
1197
- tools: opts.tools,
1198
- toolChoice: void 0,
1199
- activeTools: opts.activeToolNames,
1200
- maxRetries: 0,
1201
- timeout: void 0,
1202
- headers: void 0,
1203
- providerOptions: void 0,
1204
- output: void 0,
1205
- toolsContext: void 0,
1206
- runtimeContext,
1207
- instructions: opts.instructions,
1208
- messages: inputMessages
1209
- })
1210
- ));
1211
- };
1136
+ let modelCallStartedAt = 0;
1137
+ const completedSteps = [];
1138
+ const languageModelTools = options.toolSpecs.length === 0 ? void 0 : options.toolSpecs.map((tool) => ({
1139
+ type: "function",
1140
+ name: tool.name,
1141
+ ...tool.description == null ? {} : { description: tool.description },
1142
+ ...tool.inputSchema == null ? {} : { inputSchema: tool.inputSchema }
1143
+ }));
1212
1144
  const start = async (overrideModelId) => {
1213
1145
  if (started) return;
1214
- if (overrideModelId) modelId = overrideModelId;
1215
- await fireStart();
1146
+ if (overrideModelId != null) modelId = overrideModelId;
1147
+ started = true;
1148
+ const event = {
1149
+ callId: options.callId,
1150
+ operationId: "ai.harness",
1151
+ provider,
1152
+ modelId,
1153
+ tools: options.tools,
1154
+ toolChoice: void 0,
1155
+ activeTools: options.activeToolNames,
1156
+ toolOrder: [],
1157
+ maxRetries: 0,
1158
+ timeout: void 0,
1159
+ headers: void 0,
1160
+ providerOptions: void 0,
1161
+ output: options.output,
1162
+ toolsContext: options.toolsContext,
1163
+ runtimeContext: options.runtimeContext,
1164
+ instructions: options.instructions,
1165
+ messages: options.messages
1166
+ };
1167
+ await notify(
1168
+ event,
1169
+ options.callbacks.onStart,
1170
+ telemetry.onStart
1171
+ );
1216
1172
  };
1217
1173
  const ensureStepOpen = async () => {
1218
- var _a5, _b4;
1219
- if (!started) await fireStart();
1174
+ if (!started) await start();
1220
1175
  if (stepOpen || ended) return;
1221
1176
  stepOpen = true;
1222
- await ((_a5 = dispatcher.onStepStart) == null ? void 0 : _a5.call(
1223
- dispatcher,
1224
- cast({
1225
- callId,
1226
- provider,
1227
- modelId,
1228
- stepNumber,
1229
- tools: opts.tools,
1230
- toolChoice: void 0,
1231
- activeTools: opts.activeToolNames,
1232
- steps: new Array(stepNumber),
1233
- providerOptions: void 0,
1234
- output: void 0,
1235
- runtimeContext,
1236
- instructions: opts.instructions,
1237
- messages: inputMessages
1238
- })
1239
- ));
1240
- await ((_b4 = dispatcher.onLanguageModelCallStart) == null ? void 0 : _b4.call(
1241
- dispatcher,
1242
- cast({
1243
- callId,
1244
- provider,
1245
- modelId,
1246
- instructions: opts.instructions,
1247
- messages: inputMessages,
1248
- tools: languageModelTools
1249
- })
1250
- ));
1177
+ const stepStartEvent = {
1178
+ callId: options.callId,
1179
+ provider,
1180
+ modelId,
1181
+ stepNumber,
1182
+ tools: options.tools,
1183
+ toolChoice: void 0,
1184
+ activeTools: options.activeToolNames,
1185
+ toolOrder: [],
1186
+ steps: [...completedSteps],
1187
+ providerOptions: void 0,
1188
+ output: options.output,
1189
+ runtimeContext: options.runtimeContext,
1190
+ toolsContext: options.toolsContext,
1191
+ instructions: options.instructions,
1192
+ messages: options.messages
1193
+ };
1194
+ await notify(
1195
+ stepStartEvent,
1196
+ options.callbacks.onStepStart,
1197
+ telemetry.onStepStart
1198
+ );
1199
+ const modelStartEvent = {
1200
+ callId: options.callId,
1201
+ provider,
1202
+ modelId,
1203
+ instructions: options.instructions,
1204
+ messages: options.messages,
1205
+ tools: languageModelTools
1206
+ };
1207
+ modelCallStartedAt = Date.now();
1208
+ await notify(
1209
+ modelStartEvent,
1210
+ options.callbacks.onLanguageModelCallStart,
1211
+ telemetry.onLanguageModelCallStart
1212
+ );
1251
1213
  };
1252
- const inferenceEnd = async (info) => {
1253
- var _a5;
1254
- const finishReason = normalizeFinishReason(info.finishReason);
1255
- const usage = normalizeUsage(info.usage);
1256
- await ((_a5 = dispatcher.onLanguageModelCallEnd) == null ? void 0 : _a5.call(
1257
- dispatcher,
1258
- cast({
1259
- callId,
1214
+ return {
1215
+ start,
1216
+ ensureStepOpen,
1217
+ async languageModelCallEnd(input) {
1218
+ await ensureStepOpen();
1219
+ const event = {
1220
+ callId: options.callId,
1260
1221
  provider,
1261
1222
  modelId,
1262
- finishReason,
1263
- responseId: callId,
1264
- usage,
1265
- content: info.content,
1266
- ...info.providerMetadata != null ? { providerMetadata: info.providerMetadata } : {},
1223
+ finishReason: input.finishReason,
1224
+ usage: input.usage,
1225
+ content: input.content,
1226
+ responseId: `${options.callId}-${stepNumber}`,
1227
+ providerMetadata: input.providerMetadata,
1267
1228
  performance: {
1268
- responseTimeMs: void 0,
1229
+ responseTimeMs: Math.max(0, Date.now() - modelCallStartedAt),
1230
+ effectiveOutputTokensPerSecond: 0,
1231
+ outputTokensPerSecond: void 0,
1232
+ inputTokensPerSecond: void 0,
1233
+ effectiveTotalTokensPerSecond: 0,
1269
1234
  timeToFirstOutputMs: void 0,
1270
1235
  timeBetweenOutputChunksMs: void 0
1271
1236
  }
1272
- })
1273
- ));
1274
- };
1275
- const recordOutputContent = (content) => {
1276
- finalStepText = "";
1277
- finalStepReasoning = [];
1278
- for (const part of content) {
1279
- if (part.type === "text") {
1280
- finalStepText += part.text;
1281
- } else if (part.type === "reasoning") {
1282
- finalStepReasoning.push({ text: part.text });
1283
- } else if (part.type === "tool-call") {
1284
- outputToolCalls.push(part);
1285
- }
1286
- }
1287
- };
1288
- const closeOpenTools = async () => {
1289
- var _a5;
1290
- for (const call of openTools.values()) {
1291
- await ((_a5 = dispatcher.onToolExecutionEnd) == null ? void 0 : _a5.call(
1292
- dispatcher,
1293
- cast({
1294
- callId,
1295
- toolExecutionMs: 0,
1296
- messages: [],
1297
- toolCall: {
1298
- type: "tool-call",
1299
- toolCallId: call.toolCallId,
1300
- toolName: call.toolName,
1301
- input: call.input,
1302
- dynamic: true
1303
- },
1304
- toolContext: void 0,
1305
- toolOutput: { type: "error", error: new Error("tool span unclosed") }
1306
- })
1307
- ));
1308
- }
1309
- openTools.clear();
1310
- };
1311
- return {
1312
- start,
1313
- ensureStepOpen,
1314
- async stepFinish(info) {
1315
- var _a5, _b4;
1237
+ };
1238
+ await notify(
1239
+ event,
1240
+ options.callbacks.onLanguageModelCallEnd,
1241
+ telemetry.onLanguageModelCallEnd
1242
+ );
1243
+ },
1244
+ async toolExecutionStart({ toolCall }) {
1245
+ const event = {
1246
+ callId: options.callId,
1247
+ messages: options.messages,
1248
+ toolCall,
1249
+ toolContext: void 0
1250
+ };
1251
+ await notify(
1252
+ event,
1253
+ options.callbacks.onToolExecutionStart,
1254
+ telemetry.onToolExecutionStart
1255
+ );
1256
+ },
1257
+ async toolExecutionEnd({ toolCall, toolOutput, toolExecutionMs }) {
1258
+ const event = {
1259
+ callId: options.callId,
1260
+ messages: options.messages,
1261
+ toolCall,
1262
+ toolContext: void 0,
1263
+ toolOutput,
1264
+ toolExecutionMs
1265
+ };
1266
+ await notify(
1267
+ event,
1268
+ options.callbacks.onToolExecutionEnd,
1269
+ telemetry.onToolExecutionEnd
1270
+ );
1271
+ },
1272
+ async stepEnd(step) {
1273
+ var _a5, _b4, _c;
1316
1274
  if (!stepOpen) return;
1317
- const content = (_a5 = info.content) != null ? _a5 : [];
1318
- const finishReason = normalizeFinishReason(info.finishReason);
1319
- const usage = normalizeUsage(info.usage);
1320
- recordOutputContent(content);
1321
- finalStepProviderMetadata = info.providerMetadata;
1322
- await closeOpenTools();
1323
- await inferenceEnd({
1324
- finishReason,
1325
- usage,
1326
- content,
1327
- providerMetadata: info.providerMetadata
1275
+ completedSteps.push(step);
1276
+ const telemetryStepEndEvent = Object.assign(/* @__PURE__ */ Object.create(null), {
1277
+ callId: step.callId,
1278
+ stepNumber: step.stepNumber,
1279
+ model: step.model,
1280
+ toolsContext: step.toolsContext,
1281
+ runtimeContext: step.runtimeContext,
1282
+ content: step.content,
1283
+ finishReason: step.finishReason,
1284
+ rawFinishReason: step.rawFinishReason,
1285
+ usage: step.usage,
1286
+ performance: step.performance,
1287
+ warnings: step.warnings,
1288
+ request: step.request,
1289
+ response: step.response,
1290
+ providerMetadata: step.providerMetadata,
1291
+ text: step.text,
1292
+ reasoning: step.reasoning,
1293
+ reasoningText: step.reasoningText,
1294
+ files: step.files,
1295
+ sources: step.sources,
1296
+ toolCalls: step.toolCalls,
1297
+ staticToolCalls: step.staticToolCalls,
1298
+ dynamicToolCalls: step.dynamicToolCalls,
1299
+ toolResults: step.toolResults,
1300
+ staticToolResults: step.staticToolResults,
1301
+ dynamicToolResults: step.dynamicToolResults
1328
1302
  });
1329
- await ((_b4 = dispatcher.onStepEnd) == null ? void 0 : _b4.call(
1330
- dispatcher,
1331
- cast({
1332
- callId,
1333
- stepNumber,
1334
- finishReason,
1335
- usage,
1336
- providerMetadata: info.providerMetadata,
1337
- content,
1338
- response: {
1339
- id: callId,
1340
- modelId,
1341
- timestamp: /* @__PURE__ */ new Date(0),
1342
- messages: []
1343
- }
1344
- })
1345
- ));
1303
+ await Promise.allSettled([
1304
+ (_b4 = (_a5 = options.callbacks).onStepEnd) == null ? void 0 : _b4.call(_a5, step),
1305
+ (_c = telemetry.onStepEnd) == null ? void 0 : _c.call(telemetry, telemetryStepEndEvent)
1306
+ ]);
1346
1307
  stepOpen = false;
1347
1308
  stepNumber += 1;
1348
1309
  },
1349
- async toolStart(call) {
1350
- var _a5;
1351
- await ensureStepOpen();
1352
- if (openTools.has(call.toolCallId)) return;
1353
- openTools.set(call.toolCallId, call);
1354
- await ((_a5 = dispatcher.onToolExecutionStart) == null ? void 0 : _a5.call(
1355
- dispatcher,
1356
- cast({
1357
- callId,
1358
- messages: [],
1359
- toolCall: {
1360
- type: "tool-call",
1361
- toolCallId: call.toolCallId,
1362
- toolName: call.toolName,
1363
- input: call.input,
1364
- dynamic: true
1365
- },
1366
- toolContext: void 0
1367
- })
1368
- ));
1310
+ async end({ steps, usage }) {
1311
+ if (!started) await start();
1312
+ if (ended || steps.length === 0) return;
1313
+ ended = true;
1314
+ const finalStep = steps[steps.length - 1];
1315
+ const event = {
1316
+ callId: options.callId,
1317
+ stepNumber: finalStep.stepNumber,
1318
+ model: finalStep.model,
1319
+ toolsContext: finalStep.toolsContext,
1320
+ runtimeContext: finalStep.runtimeContext,
1321
+ content: steps.flatMap((step) => step.content),
1322
+ text: finalStep.text,
1323
+ reasoning: finalStep.reasoning,
1324
+ reasoningText: finalStep.reasoningText,
1325
+ files: steps.flatMap((step) => step.files),
1326
+ sources: steps.flatMap((step) => step.sources),
1327
+ toolCalls: steps.flatMap((step) => step.toolCalls),
1328
+ staticToolCalls: steps.flatMap((step) => step.staticToolCalls),
1329
+ dynamicToolCalls: steps.flatMap((step) => step.dynamicToolCalls),
1330
+ toolResults: steps.flatMap((step) => step.toolResults),
1331
+ staticToolResults: steps.flatMap((step) => step.staticToolResults),
1332
+ dynamicToolResults: steps.flatMap((step) => step.dynamicToolResults),
1333
+ finishReason: finalStep.finishReason,
1334
+ rawFinishReason: finalStep.rawFinishReason,
1335
+ usage,
1336
+ totalUsage: usage,
1337
+ warnings: steps.flatMap((step) => {
1338
+ var _a5;
1339
+ return (_a5 = step.warnings) != null ? _a5 : [];
1340
+ }),
1341
+ request: finalStep.request,
1342
+ response: finalStep.response,
1343
+ providerMetadata: finalStep.providerMetadata,
1344
+ responseMessages: steps.flatMap((step) => step.response.messages),
1345
+ steps,
1346
+ finalStep
1347
+ };
1348
+ await notify(
1349
+ event,
1350
+ options.callbacks.onEnd,
1351
+ telemetry.onEnd
1352
+ );
1369
1353
  },
1370
1354
  async executeTool({ toolCallId, execute }) {
1371
- if (dispatcher.executeTool == null) return await execute();
1372
- return await dispatcher.executeTool({ callId, toolCallId, execute });
1373
- },
1374
- async toolEnd(toolCallId, output) {
1375
- var _a5;
1376
- const call = openTools.get(toolCallId);
1377
- const normalizedOutput = output.ok ? { type: "tool-result", output: output.output } : { type: "error", error: output.error };
1378
- if (call == null) return;
1379
- openTools.delete(toolCallId);
1380
- await ((_a5 = dispatcher.onToolExecutionEnd) == null ? void 0 : _a5.call(
1381
- dispatcher,
1382
- cast({
1383
- callId,
1384
- toolExecutionMs: 0,
1385
- messages: [],
1386
- toolCall: {
1387
- type: "tool-call",
1388
- toolCallId: call.toolCallId,
1389
- toolName: call.toolName,
1390
- input: call.input,
1391
- dynamic: true
1392
- },
1393
- toolContext: void 0,
1394
- toolOutput: normalizedOutput
1395
- })
1396
- ));
1397
- },
1398
- async end(info) {
1399
- var _a5, _b4;
1400
- if (ended) return;
1401
- const finishReason = normalizeFinishReason(info.finishReason);
1402
- const usage = normalizeUsage(info.usage);
1403
- if (!started) await fireStart();
1404
- if (stepOpen) {
1405
- await closeOpenTools();
1406
- await inferenceEnd({
1407
- finishReason,
1408
- usage,
1409
- content: []
1410
- });
1411
- await ((_a5 = dispatcher.onStepEnd) == null ? void 0 : _a5.call(
1412
- dispatcher,
1413
- cast({
1414
- callId,
1415
- stepNumber,
1416
- finishReason,
1417
- usage,
1418
- providerMetadata: void 0,
1419
- content: [],
1420
- response: {
1421
- id: callId,
1422
- modelId,
1423
- timestamp: /* @__PURE__ */ new Date(0),
1424
- messages: []
1425
- }
1426
- })
1427
- ));
1428
- stepOpen = false;
1429
- }
1430
- ended = true;
1431
- await ((_b4 = dispatcher.onEnd) == null ? void 0 : _b4.call(
1432
- dispatcher,
1433
- cast({
1434
- callId,
1435
- operationId: "ai.harness",
1436
- finishReason,
1437
- usage,
1438
- totalUsage: usage,
1439
- content: [],
1440
- text: finalStepText,
1441
- finalStep: {
1442
- reasoning: finalStepReasoning,
1443
- providerMetadata: finalStepProviderMetadata
1444
- },
1445
- toolCalls: outputToolCalls,
1446
- files: [],
1447
- steps: new Array(stepNumber),
1448
- response: {
1449
- id: callId,
1450
- modelId,
1451
- timestamp: /* @__PURE__ */ new Date(0),
1452
- messages: []
1453
- },
1454
- runtimeContext
1455
- })
1456
- ));
1355
+ if (telemetry.executeTool == null) return await execute();
1356
+ return await telemetry.executeTool({
1357
+ callId: options.callId,
1358
+ toolCallId,
1359
+ execute
1360
+ });
1457
1361
  },
1458
- async error(err) {
1362
+ async error(error) {
1459
1363
  var _a5;
1460
1364
  if (ended) return;
1461
- if (!started) await fireStart();
1462
- await closeOpenTools();
1365
+ if (!started) await start();
1463
1366
  ended = true;
1464
- await ((_a5 = dispatcher.onError) == null ? void 0 : _a5.call(dispatcher, err));
1367
+ await ((_a5 = telemetry.onError) == null ? void 0 : _a5.call(telemetry, error));
1465
1368
  }
1466
1369
  };
1467
1370
  }
@@ -1556,28 +1459,49 @@ function pinSandboxChannelEventCheckpoint(event) {
1556
1459
  }
1557
1460
 
1558
1461
  // src/agent/internal/run-prompt.ts
1462
+ function unwrapToolResultOutput(toolResult) {
1463
+ switch (toolResult.output.type) {
1464
+ case "text":
1465
+ case "json":
1466
+ return { output: toolResult.output.value };
1467
+ case "error-text":
1468
+ case "error-json":
1469
+ return { output: toolResult.output.value, isError: true };
1470
+ case "execution-denied":
1471
+ return {
1472
+ output: {
1473
+ type: toolResult.output.type,
1474
+ reason: toolResult.output.reason
1475
+ }
1476
+ };
1477
+ case "content":
1478
+ return { output: toolResult.output };
1479
+ }
1480
+ }
1559
1481
  function runPrompt(input) {
1560
- var _a4, _b4, _c, _d, _e, _f, _g;
1482
+ var _a4, _b4, _c, _d, _e, _f, _g, _h, _i;
1483
+ const callId = generateId2();
1484
+ const toolsContext = {};
1561
1485
  const result = new HarnessStreamTextResult({
1562
1486
  tools: input.tools,
1563
1487
  runtimeContext: input.runtimeContext,
1564
- // toolsContext is not configurable for harnesses; pass undefined cast.
1565
- toolsContext: void 0,
1488
+ toolsContext,
1566
1489
  harnessId: input.harness.harnessId,
1567
- sessionId: input.session.sessionId,
1490
+ callId,
1491
+ modelId: (_a4 = input.model) != null ? _a4 : "",
1568
1492
  output: input.output
1569
1493
  });
1570
- const pendingToolApprovals = (_a4 = input.pendingToolApprovals) != null ? _a4 : [];
1571
- const pendingToolResults = (_b4 = input.pendingToolResults) != null ? _b4 : [];
1572
- const onPendingToolApproval = (_c = input.onPendingToolApproval) != null ? _c : (() => {
1494
+ const pendingToolApprovals = (_b4 = input.pendingToolApprovals) != null ? _b4 : [];
1495
+ const pendingToolResults = (_c = input.pendingToolResults) != null ? _c : [];
1496
+ const onPendingToolApproval = (_d = input.onPendingToolApproval) != null ? _d : (() => {
1573
1497
  });
1574
- const onToolApprovalSettled = (_d = input.onToolApprovalSettled) != null ? _d : (() => {
1498
+ const onToolApprovalSettled = (_e = input.onToolApprovalSettled) != null ? _e : (() => {
1575
1499
  });
1576
- const onPendingToolResult = (_e = input.onPendingToolResult) != null ? _e : (() => {
1500
+ const onPendingToolResult = (_f = input.onPendingToolResult) != null ? _f : (() => {
1577
1501
  });
1578
- const onToolResultSettled = (_f = input.onToolResultSettled) != null ? _f : (() => {
1502
+ const onToolResultSettled = (_g = input.onToolResultSettled) != null ? _g : (() => {
1579
1503
  });
1580
- const activeTools = (_g = input.activeTools) != null ? _g : input.tools;
1504
+ const activeTools = (_h = input.activeTools) != null ? _h : input.tools;
1581
1505
  const activeToolNames = Object.keys(input.tools).filter(
1582
1506
  (toolName) => Object.prototype.hasOwnProperty.call(activeTools, toolName) || Object.prototype.hasOwnProperty.call(
1583
1507
  input.harness.builtinTools,
@@ -1587,16 +1511,20 @@ function runPrompt(input) {
1587
1511
  toolFiltering: input.builtinToolFiltering
1588
1512
  })
1589
1513
  );
1590
- const telemetry = createTurnTelemetry({
1514
+ const lifecycle = createTurnLifecycle({
1515
+ callId,
1591
1516
  telemetry: input.telemetry,
1517
+ callbacks: (_i = input.callbacks) != null ? _i : {},
1592
1518
  harnessId: input.harness.harnessId,
1593
1519
  modelId: input.model,
1594
1520
  instructions: input.instructions,
1595
1521
  tools: input.tools,
1596
1522
  activeToolNames,
1597
1523
  toolSpecs: input.toolSpecs,
1598
- promptText: input.prompt != null ? promptToText(input.prompt) : "",
1599
- runtimeContext: input.runtimeContext
1524
+ messages: input.prompt == null ? [] : [{ role: "user", content: promptToText(input.prompt) }],
1525
+ runtimeContext: input.runtimeContext,
1526
+ toolsContext,
1527
+ output: input.output
1600
1528
  });
1601
1529
  const settleFailure = (err) => {
1602
1530
  var _a5, _b5, _c2;
@@ -1613,7 +1541,7 @@ function runPrompt(input) {
1613
1541
  result.fail(err);
1614
1542
  };
1615
1543
  const done = (async () => {
1616
- var _a5, _b5, _c2, _d2, _e2, _f2, _g2, _h, _i, _j, _k, _l, _m, _n;
1544
+ var _a5, _b5, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j, _k, _l, _m, _n, _o;
1617
1545
  let bridge;
1618
1546
  try {
1619
1547
  bridge = await toHarnessStream({
@@ -1648,7 +1576,7 @@ function runPrompt(input) {
1648
1576
  }
1649
1577
  });
1650
1578
  } catch (err) {
1651
- await telemetry.error(err);
1579
+ await lifecycle.error(err);
1652
1580
  logBridgeError({
1653
1581
  harnessId: input.harness.harnessId,
1654
1582
  sessionId: input.session.sessionId,
@@ -1680,7 +1608,7 @@ function runPrompt(input) {
1680
1608
  );
1681
1609
  const continuationsByApprovalId = new Map(
1682
1610
  ((_b5 = input.toolApprovalContinuations) != null ? _b5 : []).map((continuation) => [
1683
- continuation.approvalResponse.approvalId,
1611
+ continuation.approvalId,
1684
1612
  continuation
1685
1613
  ])
1686
1614
  );
@@ -1727,20 +1655,47 @@ function runPrompt(input) {
1727
1655
  let stepText = "";
1728
1656
  let stepReasoning = "";
1729
1657
  let stepToolCalls = [];
1658
+ let stepProviderToolResults = [];
1659
+ let stepApprovalRequests = [];
1660
+ let bufferedToolOutcomes = [];
1661
+ const toolExecutions = /* @__PURE__ */ new Map();
1662
+ const publishToolExecutions = async () => {
1663
+ var _a6;
1664
+ for (const execution of toolExecutions.values()) {
1665
+ if (execution.toolOutput == null) continue;
1666
+ await lifecycle.toolExecutionStart({
1667
+ toolCall: execution.toolCall
1668
+ });
1669
+ await lifecycle.toolExecutionEnd({
1670
+ toolCall: execution.toolCall,
1671
+ toolOutput: execution.toolOutput,
1672
+ toolExecutionMs: (_a6 = execution.toolExecutionMs) != null ? _a6 : 0
1673
+ });
1674
+ }
1675
+ for (const publish of bufferedToolOutcomes) publish();
1676
+ toolExecutions.clear();
1677
+ bufferedToolOutcomes = [];
1678
+ };
1730
1679
  let expectedStepToolCallCount;
1731
1680
  let observedStepToolCallCount = 0;
1732
1681
  let pauseAfterStepToolCalls = false;
1733
- const buildStepContent = () => {
1682
+ const buildModelCallContent = () => {
1734
1683
  const parts = [];
1735
1684
  if (stepText) parts.push({ type: "text", text: stepText });
1736
1685
  if (stepReasoning) parts.push({ type: "reasoning", text: stepReasoning });
1737
1686
  parts.push(...stepToolCalls);
1687
+ parts.push(...stepApprovalRequests);
1688
+ parts.push(...stepProviderToolResults);
1738
1689
  return parts;
1739
1690
  };
1740
1691
  const resetStepContent = () => {
1741
1692
  stepText = "";
1742
1693
  stepReasoning = "";
1743
1694
  stepToolCalls = [];
1695
+ stepProviderToolResults = [];
1696
+ stepApprovalRequests = [];
1697
+ bufferedToolOutcomes = [];
1698
+ toolExecutions.clear();
1744
1699
  expectedStepToolCallCount = void 0;
1745
1700
  observedStepToolCallCount = 0;
1746
1701
  pauseAfterStepToolCalls = false;
@@ -1763,13 +1718,13 @@ function runPrompt(input) {
1763
1718
  raw: void 0
1764
1719
  };
1765
1720
  const completeStep = async (input2) => {
1766
- await telemetry.stepFinish({
1767
- finishReason: input2.finishReason,
1768
- usage: input2.usage,
1721
+ await lifecycle.languageModelCallEnd({
1722
+ finishReason: input2.finishReason.unified,
1723
+ usage: asLanguageModelUsage2(input2.usage),
1769
1724
  providerMetadata: input2.providerMetadata,
1770
- content: buildStepContent()
1725
+ content: buildModelCallContent()
1771
1726
  });
1772
- resetStepContent();
1727
+ await publishToolExecutions();
1773
1728
  const step = result.finishStep({
1774
1729
  finishReason: input2.finishReason,
1775
1730
  usage: input2.usage,
@@ -1777,6 +1732,8 @@ function runPrompt(input) {
1777
1732
  warnings: []
1778
1733
  });
1779
1734
  completedSteps.push(step);
1735
+ await lifecycle.stepEnd(step);
1736
+ resetStepContent();
1780
1737
  return step;
1781
1738
  };
1782
1739
  const finishForHostInputPause = async (options) => {
@@ -1787,20 +1744,24 @@ function runPrompt(input) {
1787
1744
  usage: zeroUsage,
1788
1745
  providerMetadata: void 0
1789
1746
  });
1747
+ } else {
1748
+ await publishToolExecutions();
1790
1749
  }
1791
- await telemetry.end({
1792
- finishReason: toolCallsFinishReason,
1793
- usage: zeroUsage
1750
+ await lifecycle.end({
1751
+ steps: completedSteps,
1752
+ usage: asLanguageModelUsage2(zeroUsage)
1794
1753
  });
1795
1754
  await result.finish();
1796
1755
  };
1797
1756
  const enqueueApprovalRequest = (approval) => {
1798
- result.enqueue({
1757
+ const part = {
1799
1758
  type: "tool-approval-request",
1800
1759
  approvalId: approval.approvalId,
1801
1760
  toolCall: approval.toolCall,
1802
1761
  ...approval.isAutomatic !== void 0 ? { isAutomatic: approval.isAutomatic } : {}
1803
- });
1762
+ };
1763
+ result.enqueue(part);
1764
+ stepApprovalRequests.push(part);
1804
1765
  };
1805
1766
  const enqueueAutomaticApprovalResponse = (input2) => {
1806
1767
  result.enqueue({
@@ -1812,13 +1773,13 @@ function runPrompt(input) {
1812
1773
  ...input2.providerExecuted !== void 0 ? { providerExecuted: input2.providerExecuted } : {}
1813
1774
  });
1814
1775
  };
1815
- const enqueueApprovalResponse = (approval, continuation) => {
1776
+ const enqueueApprovalResponse = (approval, continuation, toolCall) => {
1816
1777
  result.enqueueContinuation({
1817
1778
  type: "tool-approval-response",
1818
1779
  approvalId: approval.approvalId,
1819
- toolCall: continuation.toolCall,
1820
- approved: continuation.approvalResponse.approved,
1821
- ...continuation.approvalResponse.reason !== void 0 ? { reason: continuation.approvalResponse.reason } : {},
1780
+ toolCall,
1781
+ approved: continuation.approved,
1782
+ ...continuation.reason !== void 0 ? { reason: continuation.reason } : {},
1822
1783
  ...approval.providerExecuted !== void 0 ? { providerExecuted: approval.providerExecuted } : {}
1823
1784
  });
1824
1785
  };
@@ -1827,20 +1788,27 @@ function runPrompt(input) {
1827
1788
  const pendingResult = (_a6 = pendingResultsByToolCallId.get(options.toolCall.toolCallId)) != null ? _a6 : {
1828
1789
  toolCallId: options.toolCall.toolCallId,
1829
1790
  toolName: options.toolCall.toolName,
1830
- input: options.toolCall.input
1791
+ input: options.toolCall.input,
1792
+ ...options.toolCall.providerMetadata !== void 0 ? { providerOptions: options.toolCall.providerMetadata } : {}
1831
1793
  };
1832
1794
  pendingResultsByToolCallId.set(pendingResult.toolCallId, pendingResult);
1833
1795
  onPendingToolResult(pendingResult);
1834
1796
  return pendingResult;
1835
1797
  };
1836
1798
  const processPendingToolResultContinuation = async (pendingResult, continuation) => {
1799
+ const result2 = unwrapToolResultOutput(continuation);
1837
1800
  onToolResultSettled(pendingResult.toolCallId);
1838
1801
  pendingResultsByToolCallId.delete(pendingResult.toolCallId);
1839
1802
  settledHostToolCallIds.add(pendingResult.toolCallId);
1840
1803
  await control.submitToolResult({
1841
1804
  toolCallId: pendingResult.toolCallId,
1842
- output: continuation.output,
1843
- isError: continuation.isError
1805
+ output: result2.output,
1806
+ isError: result2.isError,
1807
+ toolResult: {
1808
+ ...continuation,
1809
+ toolName: pendingResult.toolName,
1810
+ ...continuation.providerOptions == null && pendingResult.providerOptions != null ? { providerOptions: pendingResult.providerOptions } : {}
1811
+ }
1844
1812
  });
1845
1813
  };
1846
1814
  const enqueueHostToolOutcome = (options) => {
@@ -1873,7 +1841,23 @@ function runPrompt(input) {
1873
1841
  };
1874
1842
  const processPendingApprovalContinuation = async (approval, continuation) => {
1875
1843
  var _a6;
1876
- enqueueApprovalResponse(approval, continuation);
1844
+ const rawToolCall = (_a6 = rawToolCallsByToolCallId.get(approval.toolCallId)) != null ? _a6 : {
1845
+ type: "tool-call",
1846
+ toolCallId: approval.toolCallId,
1847
+ toolName: approval.toolName,
1848
+ input: approval.input,
1849
+ providerExecuted: approval.providerExecuted,
1850
+ nativeName: approval.nativeName
1851
+ };
1852
+ const parsedInput = await safeParseJSON2({ text: rawToolCall.input });
1853
+ const toolCall = {
1854
+ type: "tool-call",
1855
+ toolCallId: rawToolCall.toolCallId,
1856
+ toolName: rawToolCall.toolName,
1857
+ input: parsedInput.success ? parsedInput.value : rawToolCall.input,
1858
+ ...rawToolCall.providerExecuted !== void 0 ? { providerExecuted: rawToolCall.providerExecuted } : {}
1859
+ };
1860
+ enqueueApprovalResponse(approval, continuation, toolCall);
1877
1861
  onToolApprovalSettled(approval.approvalId);
1878
1862
  pendingApprovalsByApprovalId.delete(approval.approvalId);
1879
1863
  pendingApprovalsByToolCallId.delete(approval.toolCallId);
@@ -1886,38 +1870,31 @@ function runPrompt(input) {
1886
1870
  }
1887
1871
  await control.submitToolApproval({
1888
1872
  approvalId: approval.approvalId,
1889
- approved: continuation.approvalResponse.approved,
1890
- reason: continuation.approvalResponse.reason
1873
+ approved: continuation.approved,
1874
+ reason: continuation.reason
1891
1875
  });
1892
1876
  return "continued";
1893
1877
  }
1894
1878
  settledHostToolCallIds.add(approval.toolCallId);
1895
- if (!continuation.approvalResponse.approved) {
1879
+ if (!continuation.approved) {
1896
1880
  await control.submitToolResult({
1897
1881
  toolCallId: approval.toolCallId,
1898
1882
  output: {
1899
1883
  type: "execution-denied",
1900
- reason: continuation.approvalResponse.reason
1884
+ reason: continuation.reason
1901
1885
  }
1902
1886
  });
1903
1887
  return "continued";
1904
1888
  }
1905
- const rawToolCall = (_a6 = rawToolCallsByToolCallId.get(approval.toolCallId)) != null ? _a6 : {
1906
- type: "tool-call",
1907
- toolCallId: approval.toolCallId,
1908
- toolName: approval.toolName,
1909
- input: approval.input
1910
- };
1911
- await telemetry.start(input.model);
1912
- await telemetry.toolStart({
1913
- toolCallId: rawToolCall.toolCallId,
1914
- toolName: rawToolCall.toolName,
1915
- input: rawToolCall.input
1889
+ await lifecycle.start(input.model);
1890
+ toolExecutions.set(rawToolCall.toolCallId, {
1891
+ toolCall
1916
1892
  });
1893
+ const executionStartedAt = Date.now();
1917
1894
  const execution = await maybeExecuteHostTool({
1918
1895
  event: rawToolCall,
1919
1896
  tools: activeTools,
1920
- wrappedExecuteTool: telemetry.executeTool,
1897
+ wrappedExecuteTool: lifecycle.executeTool,
1921
1898
  sandboxSession: input.sandboxSession,
1922
1899
  abortSignal: input.abortSignal,
1923
1900
  control,
@@ -1931,13 +1908,15 @@ function runPrompt(input) {
1931
1908
  },
1932
1909
  input.sessionWorkDir
1933
1910
  );
1934
- result.enqueue({
1935
- type: "tool-result",
1936
- toolCallId: rawToolCall.toolCallId,
1937
- toolName: rawToolCall.toolName,
1938
- input: void 0,
1939
- output: stripped.result,
1940
- preliminary: true
1911
+ bufferedToolOutcomes.push(() => {
1912
+ result.enqueue({
1913
+ type: "tool-result",
1914
+ toolCallId: rawToolCall.toolCallId,
1915
+ toolName: rawToolCall.toolName,
1916
+ input: void 0,
1917
+ output: stripped.result,
1918
+ preliminary: true
1919
+ });
1941
1920
  });
1942
1921
  }
1943
1922
  });
@@ -1946,11 +1925,19 @@ function runPrompt(input) {
1946
1925
  await finishForHostInputPause({ completeCurrentStep: false });
1947
1926
  return "awaiting-tool-result";
1948
1927
  }
1949
- enqueueHostToolOutcome({
1950
- toolCall: continuation.toolCall,
1928
+ const toolExecution = toolExecutions.get(rawToolCall.toolCallId);
1929
+ toolExecution.toolOutput = toToolOutput({
1930
+ toolCall,
1951
1931
  outcome: execution.outcome
1952
1932
  });
1953
- await telemetry.toolEnd(rawToolCall.toolCallId, execution.outcome);
1933
+ toolExecution.toolExecutionMs = Date.now() - executionStartedAt;
1934
+ bufferedToolOutcomes.push(() => {
1935
+ enqueueHostToolOutcome({
1936
+ toolCall,
1937
+ outcome: execution.outcome
1938
+ });
1939
+ });
1940
+ await publishToolExecutions();
1954
1941
  return "continued";
1955
1942
  };
1956
1943
  try {
@@ -1997,9 +1984,12 @@ function runPrompt(input) {
1997
1984
  )
1998
1985
  )).some(Boolean)) {
1999
1986
  await ((_d2 = input.onStopConditionMet) == null ? void 0 : _d2.call(input));
2000
- const { finishReason, usage } = pendingStopBoundary;
1987
+ const { usage } = pendingStopBoundary;
2001
1988
  releasePendingStopBoundary();
2002
- await telemetry.end({ finishReason, usage });
1989
+ await lifecycle.end({
1990
+ steps: completedSteps,
1991
+ usage: asLanguageModelUsage2(usage)
1992
+ });
2003
1993
  await result.finish();
2004
1994
  return;
2005
1995
  } else {
@@ -2007,10 +1997,12 @@ function runPrompt(input) {
2007
1997
  }
2008
1998
  }
2009
1999
  if (value.type === "stream-start") {
2010
- await telemetry.start((_e2 = value.modelId) != null ? _e2 : input.model);
2000
+ const modelId = (_e2 = value.modelId) != null ? _e2 : input.model;
2001
+ if (modelId != null) result.setModelId(modelId);
2002
+ await lifecycle.start(modelId);
2011
2003
  }
2012
2004
  if (value.type !== "stream-start" && value.type !== "finish-step" && value.type !== "finish" && value.type !== "error") {
2013
- await telemetry.ensureStepOpen();
2005
+ await lifecycle.ensureStepOpen();
2014
2006
  }
2015
2007
  if (value.type === "tool-input-start" || value.type === "tool-input-delta" || value.type === "tool-input-end") {
2016
2008
  if (settledHostToolCallIds.has(value.id) || settledBuiltinApprovalToolCallIds.has(value.id)) {
@@ -2034,6 +2026,7 @@ function runPrompt(input) {
2034
2026
  }
2035
2027
  if (displayValue.type === "finish-step" && closingResumedStep) {
2036
2028
  closingResumedStep = false;
2029
+ await publishToolExecutions();
2037
2030
  resetStepContent();
2038
2031
  result.discardCurrentStepContent();
2039
2032
  continue;
@@ -2070,7 +2063,7 @@ function runPrompt(input) {
2070
2063
  }
2071
2064
  if (value.type === "error" && displayValue.type === "error") {
2072
2065
  await waitForOutstandingHostToolExecutions();
2073
- await telemetry.error(value.error);
2066
+ await lifecycle.error(value.error);
2074
2067
  if (!((_g2 = input.abortSignal) == null ? void 0 : _g2.aborted)) {
2075
2068
  logBridgeError({
2076
2069
  harnessId: input.harness.harnessId,
@@ -2082,11 +2075,16 @@ function runPrompt(input) {
2082
2075
  settleFailure(displayValue.error);
2083
2076
  return;
2084
2077
  }
2085
- for (const part of translateStreamPart(
2078
+ const translatedParts = translateStreamPart(
2086
2079
  displayValue,
2087
2080
  translateOptions
2088
- )) {
2089
- result.enqueue(part);
2081
+ );
2082
+ if (value.type === "tool-result") {
2083
+ bufferedToolOutcomes.push(() => {
2084
+ for (const part of translatedParts) result.enqueue(part);
2085
+ });
2086
+ } else {
2087
+ for (const part of translatedParts) result.enqueue(part);
2090
2088
  }
2091
2089
  if (displayValue.type === "tool-call") {
2092
2090
  const parsed = await validateToolCall({
@@ -2106,23 +2104,32 @@ function runPrompt(input) {
2106
2104
  if (value.type === "tool-call") {
2107
2105
  observedStepToolCallCount += 1;
2108
2106
  expectedStepToolCallCount != null ? expectedStepToolCallCount : expectedStepToolCallCount = value.stepToolCallCount;
2109
- stepToolCalls.push({
2110
- type: "tool-call",
2111
- toolCallId: value.toolCallId,
2112
- toolName: value.toolName,
2113
- input: value.input
2114
- });
2115
- await telemetry.toolStart({
2116
- toolCallId: value.toolCallId,
2117
- toolName: value.toolName,
2118
- input: value.input
2119
- });
2107
+ const toolCall = toolCallsByToolCallId.get(value.toolCallId);
2108
+ if (toolCall != null) {
2109
+ stepToolCalls.push(toolCall);
2110
+ toolExecutions.set(value.toolCallId, {
2111
+ toolCall
2112
+ });
2113
+ }
2120
2114
  }
2121
2115
  if (value.type === "tool-result") {
2122
- await telemetry.toolEnd(
2123
- value.toolCallId,
2124
- value.isError ? { ok: false, error: value.result } : { ok: true, output: value.result }
2125
- );
2116
+ const execution = toolExecutions.get(value.toolCallId);
2117
+ if (execution != null && execution.toolOutput == null) {
2118
+ execution.toolOutput = value.isError ? {
2119
+ ...execution.toolCall,
2120
+ type: "tool-error",
2121
+ error: value.result
2122
+ } : {
2123
+ ...execution.toolCall,
2124
+ type: "tool-result",
2125
+ output: value.result
2126
+ };
2127
+ }
2128
+ if (((_h2 = rawToolCallsByToolCallId.get(value.toolCallId)) == null ? void 0 : _h2.providerExecuted) === true && (execution == null ? void 0 : execution.toolOutput) != null) {
2129
+ stepProviderToolResults.push(
2130
+ execution.toolOutput
2131
+ );
2132
+ }
2126
2133
  }
2127
2134
  if (value.type === "tool-approval-request") {
2128
2135
  const toolCall = toolCallsByToolCallId.get(value.toolCallId);
@@ -2132,13 +2139,13 @@ function runPrompt(input) {
2132
2139
  );
2133
2140
  }
2134
2141
  const rawToolCall = rawToolCallsByToolCallId.get(value.toolCallId);
2135
- const pendingApproval = (_j = pendingApprovalsByApprovalId.get(value.approvalId)) != null ? _j : {
2142
+ const pendingApproval = (_k = pendingApprovalsByApprovalId.get(value.approvalId)) != null ? _k : {
2136
2143
  approvalId: value.approvalId,
2137
2144
  toolCallId: value.toolCallId,
2138
2145
  toolName: toolCall.toolName,
2139
- input: (_h = rawToolCall == null ? void 0 : rawToolCall.input) != null ? _h : JSON.stringify(toolCall.input),
2146
+ input: (_i2 = rawToolCall == null ? void 0 : rawToolCall.input) != null ? _i2 : JSON.stringify(toolCall.input),
2140
2147
  kind: "builtin",
2141
- providerExecuted: (_i = rawToolCall == null ? void 0 : rawToolCall.providerExecuted) != null ? _i : true,
2148
+ providerExecuted: (_j = rawToolCall == null ? void 0 : rawToolCall.providerExecuted) != null ? _j : true,
2142
2149
  ...(rawToolCall == null ? void 0 : rawToolCall.nativeName) !== void 0 ? { nativeName: rawToolCall.nativeName } : {}
2143
2150
  };
2144
2151
  pendingApprovalsByApprovalId.set(
@@ -2187,9 +2194,9 @@ function runPrompt(input) {
2187
2194
  if (value.type === "finish") {
2188
2195
  await waitForOutstandingHostToolExecutions();
2189
2196
  finalFinish = value;
2190
- await telemetry.end({
2191
- finishReason: value.finishReason,
2192
- usage: value.totalUsage
2197
+ await lifecycle.end({
2198
+ steps: completedSteps,
2199
+ usage: asLanguageModelUsage2(value.totalUsage)
2193
2200
  });
2194
2201
  }
2195
2202
  if (value.type === "tool-call" && !value.providerExecuted) {
@@ -2200,7 +2207,11 @@ function runPrompt(input) {
2200
2207
  `Harness '${input.harness.harnessId}' could not find parsed tool call '${toolCall.toolCallId}' for custom tool approval.`
2201
2208
  );
2202
2209
  }
2203
- if (!hasTool({ tools: activeTools, toolName: toolCall.toolName })) {
2210
+ const isClientExecutedBuiltin = toolCall.toolName === "askUserQuestions" && Object.prototype.hasOwnProperty.call(
2211
+ input.harness.builtinTools,
2212
+ toolCall.toolName
2213
+ );
2214
+ if (!isClientExecutedBuiltin && !hasTool({ tools: activeTools, toolName: toolCall.toolName })) {
2204
2215
  const output = {
2205
2216
  type: "execution-denied",
2206
2217
  reason: getHarnessV1BuiltinToolFilteringDenialReason({
@@ -2211,15 +2222,30 @@ function runPrompt(input) {
2211
2222
  toolCallId: toolCall.toolCallId,
2212
2223
  output
2213
2224
  });
2214
- await telemetry.toolEnd(toolCall.toolCallId, { ok: true, output });
2225
+ const execution = toolExecutions.get(toolCall.toolCallId);
2226
+ if (execution != null) {
2227
+ execution.toolOutput = toToolOutput({
2228
+ toolCall: parsedToolCall,
2229
+ outcome: { ok: true, output }
2230
+ });
2231
+ }
2215
2232
  continue;
2216
2233
  }
2234
+ if (isClientExecutedBuiltin) {
2235
+ recordPendingToolResult({ toolCall });
2236
+ if (expectedStepToolCallCount != null && observedStepToolCallCount < expectedStepToolCallCount) {
2237
+ pauseAfterStepToolCalls = true;
2238
+ continue;
2239
+ }
2240
+ await finishForHostInputPause({ completeCurrentStep: true });
2241
+ return;
2242
+ }
2217
2243
  const customToolApprovalDecision = resolveCustomToolApproval({
2218
2244
  toolName: toolCall.toolName,
2219
2245
  toolApproval: input.toolApproval
2220
2246
  });
2221
2247
  if (customToolApprovalDecision.type === "deny") {
2222
- const approvalId = generateId4();
2248
+ const approvalId = generateId2();
2223
2249
  enqueueApprovalRequest({
2224
2250
  approvalId,
2225
2251
  toolCall: parsedToolCall,
@@ -2240,11 +2266,17 @@ function runPrompt(input) {
2240
2266
  toolCallId: toolCall.toolCallId,
2241
2267
  output
2242
2268
  });
2243
- await telemetry.toolEnd(toolCall.toolCallId, { ok: true, output });
2269
+ const execution = toolExecutions.get(toolCall.toolCallId);
2270
+ if (execution != null) {
2271
+ execution.toolOutput = toToolOutput({
2272
+ toolCall: parsedToolCall,
2273
+ outcome: { ok: true, output }
2274
+ });
2275
+ }
2244
2276
  continue;
2245
2277
  }
2246
- const pendingApproval = (_k = pendingApprovalsByToolCallId.get(toolCall.toolCallId)) != null ? _k : customToolApprovalDecision.type === "request" ? {
2247
- approvalId: generateId4(),
2278
+ const pendingApproval = (_l = pendingApprovalsByToolCallId.get(toolCall.toolCallId)) != null ? _l : customToolApprovalDecision.type === "request" ? {
2279
+ approvalId: generateId2(),
2248
2280
  toolCallId: toolCall.toolCallId,
2249
2281
  toolName: toolCall.toolName,
2250
2282
  input: toolCall.input,
@@ -2304,10 +2336,11 @@ function runPrompt(input) {
2304
2336
  }
2305
2337
  startHostToolExecution(
2306
2338
  (async () => {
2339
+ const executionStartedAt = Date.now();
2307
2340
  const execution = await maybeExecuteHostTool({
2308
2341
  event: toolCall,
2309
2342
  tools: activeTools,
2310
- wrappedExecuteTool: telemetry.executeTool,
2343
+ wrappedExecuteTool: lifecycle.executeTool,
2311
2344
  sandboxSession: input.sandboxSession,
2312
2345
  abortSignal: input.abortSignal,
2313
2346
  control,
@@ -2321,13 +2354,15 @@ function runPrompt(input) {
2321
2354
  },
2322
2355
  input.sessionWorkDir
2323
2356
  );
2324
- result.enqueue({
2325
- type: "tool-result",
2326
- toolCallId: toolCall.toolCallId,
2327
- toolName: toolCall.toolName,
2328
- input: void 0,
2329
- output: stripped.result,
2330
- preliminary: true
2357
+ bufferedToolOutcomes.push(() => {
2358
+ result.enqueue({
2359
+ type: "tool-result",
2360
+ toolCallId: toolCall.toolCallId,
2361
+ toolName: toolCall.toolName,
2362
+ input: void 0,
2363
+ output: stripped.result,
2364
+ preliminary: true
2365
+ });
2331
2366
  });
2332
2367
  }
2333
2368
  });
@@ -2336,21 +2371,28 @@ function runPrompt(input) {
2336
2371
  `Harness '${input.harness.harnessId}' could not execute host tool '${toolCall.toolName}'.`
2337
2372
  );
2338
2373
  }
2339
- await telemetry.toolEnd(toolCall.toolCallId, execution.outcome);
2374
+ const toolExecution = toolExecutions.get(toolCall.toolCallId);
2375
+ if (toolExecution != null) {
2376
+ toolExecution.toolOutput = toToolOutput({
2377
+ toolCall: parsedToolCall,
2378
+ outcome: execution.outcome
2379
+ });
2380
+ toolExecution.toolExecutionMs = Date.now() - executionStartedAt;
2381
+ }
2340
2382
  })()
2341
2383
  );
2342
2384
  }
2343
2385
  }
2344
2386
  await waitForOutstandingHostToolExecutions();
2345
- const isTurnSuspending = ((_l = input.isTurnSuspending) == null ? void 0 : _l.call(input)) === true;
2387
+ const isTurnSuspending = ((_m = input.isTurnSuspending) == null ? void 0 : _m.call(input)) === true;
2346
2388
  if (isTurnSuspending) {
2347
2389
  if (finalFinish == null) {
2348
2390
  result.discardCurrentStepContent();
2349
2391
  }
2350
2392
  } else if (finalFinish != null) {
2351
- (_m = input.onTurnFinished) == null ? void 0 : _m.call(input);
2393
+ (_n = input.onTurnFinished) == null ? void 0 : _n.call(input);
2352
2394
  } else {
2353
- (_n = input.onTurnFailed) == null ? void 0 : _n.call(input);
2395
+ (_o = input.onTurnFailed) == null ? void 0 : _o.call(input);
2354
2396
  }
2355
2397
  await result.finish(
2356
2398
  finalFinish ? {
@@ -2364,7 +2406,7 @@ function runPrompt(input) {
2364
2406
  await waitForOutstandingHostToolExecutions();
2365
2407
  } catch (e) {
2366
2408
  }
2367
- await telemetry.error(err);
2409
+ await lifecycle.error(err);
2368
2410
  logBridgeError({
2369
2411
  harnessId: input.harness.harnessId,
2370
2412
  sessionId: input.session.sessionId,
@@ -2381,6 +2423,17 @@ function runPrompt(input) {
2381
2423
  });
2382
2424
  return { result, done };
2383
2425
  }
2426
+ function toToolOutput(input) {
2427
+ return input.outcome.ok ? {
2428
+ ...input.toolCall,
2429
+ type: "tool-result",
2430
+ output: input.outcome.output
2431
+ } : {
2432
+ ...input.toolCall,
2433
+ type: "tool-error",
2434
+ error: input.outcome.error
2435
+ };
2436
+ }
2384
2437
  function asToolCallTextStreamPart(input) {
2385
2438
  if (input.part.type !== "tool-call") {
2386
2439
  throw new Error(
@@ -2562,6 +2615,7 @@ var HarnessAgentSession = class {
2562
2615
  responseFormat: options.responseFormat,
2563
2616
  output: options.output,
2564
2617
  telemetry: options.telemetry,
2618
+ callbacks: options.callbacks,
2565
2619
  stopConditions: options.stopConditions,
2566
2620
  toolApproval: this.toolApproval,
2567
2621
  pendingToolApprovals: this.getPendingToolApprovals(),
@@ -2634,6 +2688,7 @@ var HarnessAgentSession = class {
2634
2688
  responseFormat: options.responseFormat,
2635
2689
  output: options.output,
2636
2690
  telemetry: options.telemetry,
2691
+ callbacks: options.callbacks,
2637
2692
  stopConditions: options.stopConditions,
2638
2693
  toolApproval: this.toolApproval,
2639
2694
  pendingToolApprovals: this.getPendingToolApprovals(),
@@ -3030,7 +3085,7 @@ var HarnessAgentSession = class {
3030
3085
  function collectHarnessAgentToolApprovalContinuations(input) {
3031
3086
  const lastMessage = input.messages.at(-1);
3032
3087
  if ((lastMessage == null ? void 0 : lastMessage.role) !== "tool") return [];
3033
- const toolCallsByToolCallId = /* @__PURE__ */ new Map();
3088
+ const toolCallIds = /* @__PURE__ */ new Set();
3034
3089
  const approvalRequestsByApprovalId = /* @__PURE__ */ new Map();
3035
3090
  for (const message of input.messages) {
3036
3091
  if (message.role !== "assistant" || typeof message.content === "string") {
@@ -3038,13 +3093,7 @@ function collectHarnessAgentToolApprovalContinuations(input) {
3038
3093
  }
3039
3094
  for (const part of message.content) {
3040
3095
  if (part.type === "tool-call") {
3041
- toolCallsByToolCallId.set(part.toolCallId, {
3042
- type: "tool-call",
3043
- toolCallId: part.toolCallId,
3044
- toolName: part.toolName,
3045
- input: part.input,
3046
- ...part.providerExecuted !== void 0 ? { providerExecuted: part.providerExecuted } : {}
3047
- });
3096
+ toolCallIds.add(part.toolCallId);
3048
3097
  } else if (part.type === "tool-approval-request") {
3049
3098
  approvalRequestsByApprovalId.set(part.approvalId, part);
3050
3099
  }
@@ -3066,16 +3115,12 @@ function collectHarnessAgentToolApprovalContinuations(input) {
3066
3115
  });
3067
3116
  }
3068
3117
  if (toolResultIds.has(approvalRequest.toolCallId)) continue;
3069
- const toolCall = toolCallsByToolCallId.get(approvalRequest.toolCallId);
3070
- if (toolCall == null) {
3118
+ if (!toolCallIds.has(approvalRequest.toolCallId)) {
3071
3119
  throw new HarnessError({
3072
3120
  message: `Tool approval request '${approvalRequest.approvalId}' references unknown tool call '${approvalRequest.toolCallId}'.`
3073
3121
  });
3074
3122
  }
3075
- continuations.push({
3076
- approvalResponse: part,
3077
- toolCall
3078
- });
3123
+ continuations.push(part);
3079
3124
  }
3080
3125
  return continuations;
3081
3126
  }
@@ -3084,42 +3129,7 @@ function collectHarnessAgentToolApprovalContinuations(input) {
3084
3129
  function collectHarnessAgentToolResultContinuations(input) {
3085
3130
  const lastMessage = input.messages.at(-1);
3086
3131
  if ((lastMessage == null ? void 0 : lastMessage.role) !== "tool") return [];
3087
- return lastMessage.content.filter((part) => part.type === "tool-result").map(
3088
- (part) => toToolResultContinuation({
3089
- toolCallId: part.toolCallId,
3090
- output: part.output
3091
- })
3092
- );
3093
- }
3094
- function toToolResultContinuation(input) {
3095
- switch (input.output.type) {
3096
- case "text":
3097
- case "json":
3098
- return {
3099
- toolCallId: input.toolCallId,
3100
- output: input.output.value
3101
- };
3102
- case "error-text":
3103
- case "error-json":
3104
- return {
3105
- toolCallId: input.toolCallId,
3106
- output: input.output.value,
3107
- isError: true
3108
- };
3109
- case "execution-denied":
3110
- return {
3111
- toolCallId: input.toolCallId,
3112
- output: {
3113
- type: input.output.type,
3114
- reason: input.output.reason
3115
- }
3116
- };
3117
- case "content":
3118
- return {
3119
- toolCallId: input.toolCallId,
3120
- output: input.output
3121
- };
3122
- }
3132
+ return lastMessage.content.filter((part) => part.type === "tool-result");
3123
3133
  }
3124
3134
 
3125
3135
  // src/agent/internal/bootstrap-recipe.ts
@@ -3574,14 +3584,32 @@ function filterToolSet(input) {
3574
3584
  var HarnessAgent = class {
3575
3585
  constructor(settings) {
3576
3586
  this.version = "agent-v1";
3577
- var _a4;
3587
+ var _a4, _b4;
3578
3588
  const sandboxConfig = resolveSandboxConfig(settings);
3579
3589
  validateSandboxBootstrapSettings(sandboxConfig);
3580
3590
  this.settings = settings;
3581
3591
  this.stopConditions = settings.stopWhen == null ? [] : asArray2(settings.stopWhen);
3582
3592
  this.sandboxConfig = sandboxConfig;
3593
+ const forbiddenHeaders = /* @__PURE__ */ new Set([
3594
+ "authorization",
3595
+ "x-api-key",
3596
+ "user-agent",
3597
+ "x-client-app"
3598
+ ]);
3599
+ const forbiddenHeader = Object.keys((_a4 = settings.headers) != null ? _a4 : {}).map((name4) => name4.toLowerCase()).find((name4) => forbiddenHeaders.has(name4));
3600
+ if (forbiddenHeader != null) {
3601
+ throw new Error(
3602
+ `HarnessAgent: \`headers\` must not include the managed header \`${forbiddenHeader}\`.`
3603
+ );
3604
+ }
3605
+ const headers = normalizeHeaders(settings.headers);
3606
+ this.headers = Object.keys(headers).length === 0 ? void 0 : headers;
3583
3607
  this.id = settings.id;
3584
- const userTools = (_a4 = settings.tools) != null ? _a4 : {};
3608
+ const userTools = (_b4 = settings.tools) != null ? _b4 : {};
3609
+ assertNoReservedQuestionTool({
3610
+ harness: settings.harness,
3611
+ userTools
3612
+ });
3585
3613
  this.permissionMode = resolvePermissionMode({
3586
3614
  permissionMode: settings.permissionMode
3587
3615
  });
@@ -3620,7 +3648,7 @@ var HarnessAgent = class {
3620
3648
  */
3621
3649
  async createSession(options) {
3622
3650
  var _a4, _b4, _c;
3623
- const sessionId = (_a4 = options == null ? void 0 : options.sessionId) != null ? _a4 : generateId5();
3651
+ const sessionId = (_a4 = options == null ? void 0 : options.sessionId) != null ? _a4 : generateId3();
3624
3652
  const resumeFrom = options == null ? void 0 : options.resumeFrom;
3625
3653
  const continueFrom = options == null ? void 0 : options.continueFrom;
3626
3654
  const providedSandboxSession = options == null ? void 0 : options.sandboxSession;
@@ -3788,6 +3816,7 @@ var HarnessAgent = class {
3788
3816
  try {
3789
3817
  const baseStartOptions = {
3790
3818
  sessionId,
3819
+ ...this.headers == null ? {} : { headers: this.headers },
3791
3820
  resumeFrom: validatedResumeFrom,
3792
3821
  continueFrom: effectiveContinueFrom,
3793
3822
  permissionMode: this.permissionMode,
@@ -3907,7 +3936,8 @@ var HarnessAgent = class {
3907
3936
  turnSettings: turnInput,
3908
3937
  runtimeContext: input.runtimeContext,
3909
3938
  abortSignal: input.options.abortSignal,
3910
- responseFormat
3939
+ responseFormat,
3940
+ callbacks: this._resolveLifecycleCallbacks(input.options)
3911
3941
  }),
3912
3942
  prompt: turnInput.prompt
3913
3943
  });
@@ -3920,7 +3950,8 @@ var HarnessAgent = class {
3920
3950
  turnSettings: turnInput,
3921
3951
  runtimeContext: input.runtimeContext,
3922
3952
  abortSignal: input.abortSignal,
3923
- responseFormat
3953
+ responseFormat,
3954
+ callbacks: this._resolveLifecycleCallbacks()
3924
3955
  }),
3925
3956
  toolApprovalContinuations: turnInput.toolApprovalContinuations,
3926
3957
  toolResultContinuations: turnInput.toolResultContinuations
@@ -3940,9 +3971,38 @@ var HarnessAgent = class {
3940
3971
  responseFormat: input.responseFormat,
3941
3972
  output: this.settings.output,
3942
3973
  telemetry: this.settings.telemetry,
3974
+ callbacks: input.callbacks,
3943
3975
  stopConditions: this.stopConditions
3944
3976
  };
3945
3977
  }
3978
+ _resolveLifecycleCallbacks(call) {
3979
+ var _a4, _b4, _c, _d, _e, _f;
3980
+ return {
3981
+ onStart: mergeCallbacks(
3982
+ this.settings.onStart,
3983
+ (_a4 = call == null ? void 0 : call.onStart) != null ? _a4 : call == null ? void 0 : call.experimental_onStart
3984
+ ),
3985
+ onStepStart: mergeCallbacks(
3986
+ this.settings.onStepStart,
3987
+ (_b4 = call == null ? void 0 : call.onStepStart) != null ? _b4 : call == null ? void 0 : call.experimental_onStepStart
3988
+ ),
3989
+ onLanguageModelCallStart: this.settings.onLanguageModelCallStart,
3990
+ onLanguageModelCallEnd: this.settings.onLanguageModelCallEnd,
3991
+ onToolExecutionStart: mergeCallbacks(
3992
+ this.settings.onToolExecutionStart,
3993
+ (_c = call == null ? void 0 : call.onToolExecutionStart) != null ? _c : call == null ? void 0 : call.experimental_onToolCallStart
3994
+ ),
3995
+ onToolExecutionEnd: mergeCallbacks(
3996
+ this.settings.onToolExecutionEnd,
3997
+ (_d = call == null ? void 0 : call.onToolExecutionEnd) != null ? _d : call == null ? void 0 : call.experimental_onToolCallFinish
3998
+ ),
3999
+ onStepEnd: mergeCallbacks(
4000
+ this.settings.onStepEnd,
4001
+ (_e = call == null ? void 0 : call.onStepEnd) != null ? _e : call == null ? void 0 : call.onStepFinish
4002
+ ),
4003
+ onEnd: mergeCallbacks(this.settings.onEnd, (_f = call == null ? void 0 : call.onEnd) != null ? _f : call == null ? void 0 : call.onFinish)
4004
+ };
4005
+ }
3946
4006
  _resolveContinueTurnInput(options) {
3947
4007
  if (typeof options.prompt === "string") {
3948
4008
  return void 0;
@@ -4059,6 +4119,10 @@ var HarnessAgent = class {
4059
4119
  _prepareTurnSettings(options) {
4060
4120
  var _a4, _b4;
4061
4121
  const userTools = (_a4 = options.tools) != null ? _a4 : {};
4122
+ assertNoReservedQuestionTool({
4123
+ harness: this.settings.harness,
4124
+ userTools
4125
+ });
4062
4126
  const tools = {
4063
4127
  ...this.settings.harness.builtinTools,
4064
4128
  ...userTools
@@ -4127,6 +4191,16 @@ var HarnessAgent = class {
4127
4191
  };
4128
4192
  }
4129
4193
  };
4194
+ function assertNoReservedQuestionTool(input) {
4195
+ if (Object.prototype.hasOwnProperty.call(
4196
+ input.harness.builtinTools,
4197
+ "askUserQuestions"
4198
+ ) && Object.prototype.hasOwnProperty.call(input.userTools, "askUserQuestions")) {
4199
+ throw new Error(
4200
+ "HarnessAgent tool name 'askUserQuestions' is reserved for harness question requests."
4201
+ );
4202
+ }
4203
+ }
4130
4204
  var HarnessGenerateTextResult = class {
4131
4205
  constructor(options) {
4132
4206
  this.steps = options.steps;