@odla-ai/harness 0.5.1 → 0.6.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.
@@ -1165,7 +1165,12 @@ function codeSkill(opts) {
1165
1165
  { lease: opts.lease, workspaceDir: opts.workspaceDir, signal },
1166
1166
  { requestId: `bench-${tool}-${++seq}`, tool, input }
1167
1167
  );
1168
- opts.onToolCall?.({ tool, ok: response2.ok, durationMs: Date.now() - startedAt });
1168
+ opts.onToolCall?.({
1169
+ tool,
1170
+ ok: response2.ok,
1171
+ durationMs: Date.now() - startedAt,
1172
+ ...response2.ok ? {} : { error: String(response2.content).slice(0, 300) }
1173
+ });
1169
1174
  return { content: response2.content, isError: !response2.ok };
1170
1175
  };
1171
1176
  const read2 = {
@@ -1316,8 +1321,10 @@ async function runCodeAgent(options) {
1316
1321
  }
1317
1322
 
1318
1323
  // src/code-runtime-attempt.ts
1324
+ import { extractText } from "@odla-ai/ai";
1319
1325
  async function runCodeAgentAttempt(options) {
1320
1326
  try {
1327
+ const surface = options.surface ?? "v2";
1321
1328
  const { run } = await runCodeAgent({
1322
1329
  inference: options.inference,
1323
1330
  broker: options.broker,
@@ -1327,17 +1334,31 @@ async function runCodeAgentAttempt(options) {
1327
1334
  // The brokered route resolves the real model from platform policy; this
1328
1335
  // id only labels the request the control plane is about to rewrite.
1329
1336
  model: "brokered",
1330
- surface: options.surface ?? "v2",
1337
+ surface,
1331
1338
  ...options.maxSteps === void 0 ? {} : { maxSteps: options.maxSteps },
1332
1339
  ...options.budget ? { budget: options.budget } : {},
1333
1340
  ...options.signal ? { signal: options.signal } : {},
1334
1341
  ...options.onToolCall ? { onToolCall: options.onToolCall } : {}
1335
1342
  });
1343
+ let finalText = run.finalText.trim();
1344
+ if (!finalText && run.stoppedReason !== "refusal") {
1345
+ const closing = await options.inference.chat({
1346
+ model: "brokered",
1347
+ system: `${SYSTEM_PROMPT_FOR[surface]}
1348
+
1349
+ Finish with a concise, non-empty answer to the owner. Do not call tools or promise future work.`,
1350
+ messages: [...run.messages, { role: "user", content: "Give the owner the closing answer now, grounded in the repository evidence and tool results above." }],
1351
+ maxTokens: 16384,
1352
+ ...options.signal ? { signal: options.signal } : {}
1353
+ });
1354
+ finalText = extractText(closing.content).trim();
1355
+ }
1356
+ const missingClosing = !finalText && run.stoppedReason !== "refusal";
1336
1357
  return {
1337
- status: run.stoppedReason === "refusal" ? "failed" : "completed",
1338
- finalText: run.finalText,
1358
+ status: run.stoppedReason === "refusal" || missingClosing ? "failed" : "completed",
1359
+ finalText,
1339
1360
  stoppedReason: run.stoppedReason,
1340
- ...run.stoppedReason === "refusal" ? { error: run.finalText || "the agent refused the task" } : {}
1361
+ ...run.stoppedReason === "refusal" ? { error: finalText || "the agent refused the task" } : missingClosing ? { error: "the Code agent did not produce a closing answer" } : {}
1341
1362
  };
1342
1363
  } catch (cause) {
1343
1364
  const error = (cause instanceof Error ? cause.message : String(cause)).slice(0, 2e3);
@@ -1347,31 +1368,7 @@ async function runCodeAgentAttempt(options) {
1347
1368
 
1348
1369
  // src/code-runtime-inference.ts
1349
1370
  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
- }
1371
+ const { command, request, state } = input;
1375
1372
  const startedAt = Date.now();
1376
1373
  const response2 = await input.control.infer(command.sessionId, {
1377
1374
  requestId: request.requestId,
@@ -1391,7 +1388,6 @@ async function handleCodeRuntimeInference(input) {
1391
1388
  durationMs: Date.now() - startedAt,
1392
1389
  interactionId: command.commandId,
1393
1390
  interactionTokens: state.tokens,
1394
- interactionMaxTokens: metadata.maxTokensPerInteraction,
1395
1391
  ...costUsd === void 0 ? {} : { costUsd },
1396
1392
  ...state.costKnown ? { interactionCostUsd: state.costUsd } : {}
1397
1393
  }).catch(() => void 0);
@@ -2537,7 +2533,7 @@ var CodePiRuntimeEngine = class {
2537
2533
  recipeAuthorization: this.options.recipeAuthorization
2538
2534
  }, lease, metadata.role));
2539
2535
  const startedAt = Date.now();
2540
- const interaction = { tokens: 0, noticeEmitted: false, costUsd: 0, costKnown: true };
2536
+ const interaction = { tokens: 0, costUsd: 0, costKnown: true };
2541
2537
  const inference = createCodeRuntimeInference({
2542
2538
  command,
2543
2539
  metadata,
@@ -2552,31 +2548,30 @@ var CodePiRuntimeEngine = class {
2552
2548
  lease,
2553
2549
  workspaceDir: active.workspace.workspaceDir,
2554
2550
  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 }
2551
+ signal: active.abort.signal
2561
2552
  });
2562
- const body = result.finalText.trim() || (result.status === "completed" ? "The agent finished without a closing message." : result.error ?? "The agent failed.");
2553
+ const closing = result.finalText.trim();
2554
+ const completed = result.status === "completed" && Boolean(closing);
2555
+ const detail = result.error?.trim() || (closing ? "the Code agent failed" : "the Code agent did not produce a closing answer");
2556
+ const body = closing || detail;
2563
2557
  await this.#event(command, {
2564
2558
  type: "message",
2565
- actor: result.status === "completed" ? "agent" : "system",
2559
+ actor: completed ? "agent" : "system",
2566
2560
  body
2567
2561
  }, active.conversationRefs).catch(() => void 0);
2568
2562
  await this.#event(command, {
2569
2563
  type: "status",
2570
- status: result.status === "completed" ? "idle" : "failed",
2564
+ status: completed ? "idle" : "failed",
2571
2565
  durationMs: Date.now() - startedAt
2572
2566
  }, active.conversationRefs).catch(() => void 0);
2573
- if (result.status === "failed") {
2574
- const detail = (result.error ?? "").trim() || "the Code agent failed";
2567
+ if (!completed) {
2575
2568
  await this.#diagnostic(command, active, detail);
2576
2569
  await this.#failure(command, active, detail);
2577
2570
  }
2578
2571
  return {
2579
2572
  ...result,
2573
+ status: completed ? "completed" : "failed",
2574
+ ...!completed ? { error: detail } : {},
2580
2575
  tokens: interaction.tokens,
2581
2576
  ...interaction.costKnown ? { costUsd: interaction.costUsd } : {}
2582
2577
  };
@@ -2673,4 +2668,4 @@ export {
2673
2668
  runGoal,
2674
2669
  CodePiRuntimeEngine
2675
2670
  };
2676
- //# sourceMappingURL=chunk-L2T3LPEF.js.map
2671
+ //# sourceMappingURL=chunk-ZYNGL5SC.js.map