@odla-ai/harness 0.5.1 → 0.5.2

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.
@@ -1316,8 +1316,10 @@ async function runCodeAgent(options) {
1316
1316
  }
1317
1317
 
1318
1318
  // src/code-runtime-attempt.ts
1319
+ import { extractText } from "@odla-ai/ai";
1319
1320
  async function runCodeAgentAttempt(options) {
1320
1321
  try {
1322
+ const surface = options.surface ?? "v2";
1321
1323
  const { run } = await runCodeAgent({
1322
1324
  inference: options.inference,
1323
1325
  broker: options.broker,
@@ -1327,17 +1329,31 @@ async function runCodeAgentAttempt(options) {
1327
1329
  // The brokered route resolves the real model from platform policy; this
1328
1330
  // id only labels the request the control plane is about to rewrite.
1329
1331
  model: "brokered",
1330
- surface: options.surface ?? "v2",
1332
+ surface,
1331
1333
  ...options.maxSteps === void 0 ? {} : { maxSteps: options.maxSteps },
1332
1334
  ...options.budget ? { budget: options.budget } : {},
1333
1335
  ...options.signal ? { signal: options.signal } : {},
1334
1336
  ...options.onToolCall ? { onToolCall: options.onToolCall } : {}
1335
1337
  });
1338
+ let finalText = run.finalText.trim();
1339
+ if (!finalText && run.stoppedReason !== "refusal") {
1340
+ const closing = await options.inference.chat({
1341
+ model: "brokered",
1342
+ system: `${SYSTEM_PROMPT_FOR[surface]}
1343
+
1344
+ Finish with a concise, non-empty answer to the owner. Do not call tools or promise future work.`,
1345
+ messages: [...run.messages, { role: "user", content: "Give the owner the closing answer now, grounded in the repository evidence and tool results above." }],
1346
+ maxTokens: 16384,
1347
+ ...options.signal ? { signal: options.signal } : {}
1348
+ });
1349
+ finalText = extractText(closing.content).trim();
1350
+ }
1351
+ const missingClosing = !finalText && run.stoppedReason !== "refusal";
1336
1352
  return {
1337
- status: run.stoppedReason === "refusal" ? "failed" : "completed",
1338
- finalText: run.finalText,
1353
+ status: run.stoppedReason === "refusal" || missingClosing ? "failed" : "completed",
1354
+ finalText,
1339
1355
  stoppedReason: run.stoppedReason,
1340
- ...run.stoppedReason === "refusal" ? { error: run.finalText || "the agent refused the task" } : {}
1356
+ ...run.stoppedReason === "refusal" ? { error: finalText || "the agent refused the task" } : missingClosing ? { error: "the Code agent did not produce a closing answer" } : {}
1341
1357
  };
1342
1358
  } catch (cause) {
1343
1359
  const error = (cause instanceof Error ? cause.message : String(cause)).slice(0, 2e3);
@@ -1347,31 +1363,7 @@ async function runCodeAgentAttempt(options) {
1347
1363
 
1348
1364
  // src/code-runtime-inference.ts
1349
1365
  async function handleCodeRuntimeInference(input) {
1350
- const { command, metadata, request, state } = input;
1351
- if (state.tokens >= metadata.maxTokensPerInteraction) {
1352
- if (!state.noticeEmitted) {
1353
- state.noticeEmitted = true;
1354
- await input.event({
1355
- type: "message",
1356
- actor: "system",
1357
- body: `The agent paused at the ${metadata.maxTokensPerInteraction.toLocaleString("en-US")}-token per-interaction limit. Send a new instruction to continue.`
1358
- }).catch(() => void 0);
1359
- }
1360
- return {
1361
- protocolVersion: HARNESS_PROTOCOL_VERSION,
1362
- type: "inference.response",
1363
- requestId: request.requestId,
1364
- response: {
1365
- id: `budget:${command.commandId}`,
1366
- provider: "openai",
1367
- model: "interaction-budget",
1368
- role: "assistant",
1369
- content: [{ type: "text", text: "Pause now. The owner-set token limit for this interaction has been reached." }],
1370
- stopReason: "end_turn",
1371
- usage: { inputTokens: 0, outputTokens: 0 }
1372
- }
1373
- };
1374
- }
1366
+ const { command, request, state } = input;
1375
1367
  const startedAt = Date.now();
1376
1368
  const response2 = await input.control.infer(command.sessionId, {
1377
1369
  requestId: request.requestId,
@@ -1391,7 +1383,6 @@ async function handleCodeRuntimeInference(input) {
1391
1383
  durationMs: Date.now() - startedAt,
1392
1384
  interactionId: command.commandId,
1393
1385
  interactionTokens: state.tokens,
1394
- interactionMaxTokens: metadata.maxTokensPerInteraction,
1395
1386
  ...costUsd === void 0 ? {} : { costUsd },
1396
1387
  ...state.costKnown ? { interactionCostUsd: state.costUsd } : {}
1397
1388
  }).catch(() => void 0);
@@ -2537,7 +2528,7 @@ var CodePiRuntimeEngine = class {
2537
2528
  recipeAuthorization: this.options.recipeAuthorization
2538
2529
  }, lease, metadata.role));
2539
2530
  const startedAt = Date.now();
2540
- const interaction = { tokens: 0, noticeEmitted: false, costUsd: 0, costKnown: true };
2531
+ const interaction = { tokens: 0, costUsd: 0, costKnown: true };
2541
2532
  const inference = createCodeRuntimeInference({
2542
2533
  command,
2543
2534
  metadata,
@@ -2552,31 +2543,30 @@ var CodePiRuntimeEngine = class {
2552
2543
  lease,
2553
2544
  workspaceDir: active.workspace.workspaceDir,
2554
2545
  prompt: metadata.prompt,
2555
- signal: active.abort.signal,
2556
- // The owner's per-interaction allowance, enforced by runAgent against
2557
- // INCREMENTAL usage. The control plane still reserves against the same
2558
- // ceiling, but this is what stops the loop cleanly at the boundary rather
2559
- // than letting it discover the limit through a synthesized pause reply.
2560
- budget: { maxTotalTokens: metadata.maxTokensPerInteraction }
2546
+ signal: active.abort.signal
2561
2547
  });
2562
- const body = result.finalText.trim() || (result.status === "completed" ? "The agent finished without a closing message." : result.error ?? "The agent failed.");
2548
+ const closing = result.finalText.trim();
2549
+ const completed = result.status === "completed" && Boolean(closing);
2550
+ const detail = result.error?.trim() || (closing ? "the Code agent failed" : "the Code agent did not produce a closing answer");
2551
+ const body = closing || detail;
2563
2552
  await this.#event(command, {
2564
2553
  type: "message",
2565
- actor: result.status === "completed" ? "agent" : "system",
2554
+ actor: completed ? "agent" : "system",
2566
2555
  body
2567
2556
  }, active.conversationRefs).catch(() => void 0);
2568
2557
  await this.#event(command, {
2569
2558
  type: "status",
2570
- status: result.status === "completed" ? "idle" : "failed",
2559
+ status: completed ? "idle" : "failed",
2571
2560
  durationMs: Date.now() - startedAt
2572
2561
  }, active.conversationRefs).catch(() => void 0);
2573
- if (result.status === "failed") {
2574
- const detail = (result.error ?? "").trim() || "the Code agent failed";
2562
+ if (!completed) {
2575
2563
  await this.#diagnostic(command, active, detail);
2576
2564
  await this.#failure(command, active, detail);
2577
2565
  }
2578
2566
  return {
2579
2567
  ...result,
2568
+ status: completed ? "completed" : "failed",
2569
+ ...!completed ? { error: detail } : {},
2580
2570
  tokens: interaction.tokens,
2581
2571
  ...interaction.costKnown ? { costUsd: interaction.costUsd } : {}
2582
2572
  };
@@ -2673,4 +2663,4 @@ export {
2673
2663
  runGoal,
2674
2664
  CodePiRuntimeEngine
2675
2665
  };
2676
- //# sourceMappingURL=chunk-L2T3LPEF.js.map
2666
+ //# sourceMappingURL=chunk-5HX5LWTG.js.map