@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.
@@ -6,7 +6,7 @@ import {
6
6
  assertCodeBuildRecipe,
7
7
  createCodeRuntimeControlClient,
8
8
  runCodeRuntimeHeartbeatLoop
9
- } from "./chunk-L2T3LPEF.js";
9
+ } from "./chunk-5HX5LWTG.js";
10
10
  import {
11
11
  assertPinnedImage,
12
12
  selectContainerEngine
package/dist/node.cjs CHANGED
@@ -1966,6 +1966,9 @@ async function materializeCommandWorkspace(input) {
1966
1966
  }
1967
1967
  }
1968
1968
 
1969
+ // src/code-runtime-attempt.ts
1970
+ var import_ai2 = require("@odla-ai/ai");
1971
+
1969
1972
  // src/code-agent.ts
1970
1973
  var import_ai = require("@odla-ai/ai");
1971
1974
 
@@ -2166,6 +2169,7 @@ async function runCodeAgent(options) {
2166
2169
  // src/code-runtime-attempt.ts
2167
2170
  async function runCodeAgentAttempt(options) {
2168
2171
  try {
2172
+ const surface = options.surface ?? "v2";
2169
2173
  const { run } = await runCodeAgent({
2170
2174
  inference: options.inference,
2171
2175
  broker: options.broker,
@@ -2175,17 +2179,31 @@ async function runCodeAgentAttempt(options) {
2175
2179
  // The brokered route resolves the real model from platform policy; this
2176
2180
  // id only labels the request the control plane is about to rewrite.
2177
2181
  model: "brokered",
2178
- surface: options.surface ?? "v2",
2182
+ surface,
2179
2183
  ...options.maxSteps === void 0 ? {} : { maxSteps: options.maxSteps },
2180
2184
  ...options.budget ? { budget: options.budget } : {},
2181
2185
  ...options.signal ? { signal: options.signal } : {},
2182
2186
  ...options.onToolCall ? { onToolCall: options.onToolCall } : {}
2183
2187
  });
2188
+ let finalText = run.finalText.trim();
2189
+ if (!finalText && run.stoppedReason !== "refusal") {
2190
+ const closing = await options.inference.chat({
2191
+ model: "brokered",
2192
+ system: `${SYSTEM_PROMPT_FOR[surface]}
2193
+
2194
+ Finish with a concise, non-empty answer to the owner. Do not call tools or promise future work.`,
2195
+ messages: [...run.messages, { role: "user", content: "Give the owner the closing answer now, grounded in the repository evidence and tool results above." }],
2196
+ maxTokens: 16384,
2197
+ ...options.signal ? { signal: options.signal } : {}
2198
+ });
2199
+ finalText = (0, import_ai2.extractText)(closing.content).trim();
2200
+ }
2201
+ const missingClosing = !finalText && run.stoppedReason !== "refusal";
2184
2202
  return {
2185
- status: run.stoppedReason === "refusal" ? "failed" : "completed",
2186
- finalText: run.finalText,
2203
+ status: run.stoppedReason === "refusal" || missingClosing ? "failed" : "completed",
2204
+ finalText,
2187
2205
  stoppedReason: run.stoppedReason,
2188
- ...run.stoppedReason === "refusal" ? { error: run.finalText || "the agent refused the task" } : {}
2206
+ ...run.stoppedReason === "refusal" ? { error: finalText || "the agent refused the task" } : missingClosing ? { error: "the Code agent did not produce a closing answer" } : {}
2189
2207
  };
2190
2208
  } catch (cause) {
2191
2209
  const error = (cause instanceof Error ? cause.message : String(cause)).slice(0, 2e3);
@@ -2195,31 +2213,7 @@ async function runCodeAgentAttempt(options) {
2195
2213
 
2196
2214
  // src/code-runtime-inference.ts
2197
2215
  async function handleCodeRuntimeInference(input) {
2198
- const { command, metadata, request, state } = input;
2199
- if (state.tokens >= metadata.maxTokensPerInteraction) {
2200
- if (!state.noticeEmitted) {
2201
- state.noticeEmitted = true;
2202
- await input.event({
2203
- type: "message",
2204
- actor: "system",
2205
- body: `The agent paused at the ${metadata.maxTokensPerInteraction.toLocaleString("en-US")}-token per-interaction limit. Send a new instruction to continue.`
2206
- }).catch(() => void 0);
2207
- }
2208
- return {
2209
- protocolVersion: HARNESS_PROTOCOL_VERSION,
2210
- type: "inference.response",
2211
- requestId: request.requestId,
2212
- response: {
2213
- id: `budget:${command.commandId}`,
2214
- provider: "openai",
2215
- model: "interaction-budget",
2216
- role: "assistant",
2217
- content: [{ type: "text", text: "Pause now. The owner-set token limit for this interaction has been reached." }],
2218
- stopReason: "end_turn",
2219
- usage: { inputTokens: 0, outputTokens: 0 }
2220
- }
2221
- };
2222
- }
2216
+ const { command, request, state } = input;
2223
2217
  const startedAt = Date.now();
2224
2218
  const response2 = await input.control.infer(command.sessionId, {
2225
2219
  requestId: request.requestId,
@@ -2239,7 +2233,6 @@ async function handleCodeRuntimeInference(input) {
2239
2233
  durationMs: Date.now() - startedAt,
2240
2234
  interactionId: command.commandId,
2241
2235
  interactionTokens: state.tokens,
2242
- interactionMaxTokens: metadata.maxTokensPerInteraction,
2243
2236
  ...costUsd === void 0 ? {} : { costUsd },
2244
2237
  ...state.costKnown ? { interactionCostUsd: state.costUsd } : {}
2245
2238
  }).catch(() => void 0);
@@ -3370,7 +3363,7 @@ var CodePiRuntimeEngine = class {
3370
3363
  recipeAuthorization: this.options.recipeAuthorization
3371
3364
  }, lease, metadata.role));
3372
3365
  const startedAt = Date.now();
3373
- const interaction = { tokens: 0, noticeEmitted: false, costUsd: 0, costKnown: true };
3366
+ const interaction = { tokens: 0, costUsd: 0, costKnown: true };
3374
3367
  const inference = createCodeRuntimeInference({
3375
3368
  command,
3376
3369
  metadata,
@@ -3385,31 +3378,30 @@ var CodePiRuntimeEngine = class {
3385
3378
  lease,
3386
3379
  workspaceDir: active.workspace.workspaceDir,
3387
3380
  prompt: metadata.prompt,
3388
- signal: active.abort.signal,
3389
- // The owner's per-interaction allowance, enforced by runAgent against
3390
- // INCREMENTAL usage. The control plane still reserves against the same
3391
- // ceiling, but this is what stops the loop cleanly at the boundary rather
3392
- // than letting it discover the limit through a synthesized pause reply.
3393
- budget: { maxTotalTokens: metadata.maxTokensPerInteraction }
3381
+ signal: active.abort.signal
3394
3382
  });
3395
- const body = result.finalText.trim() || (result.status === "completed" ? "The agent finished without a closing message." : result.error ?? "The agent failed.");
3383
+ const closing = result.finalText.trim();
3384
+ const completed = result.status === "completed" && Boolean(closing);
3385
+ const detail = result.error?.trim() || (closing ? "the Code agent failed" : "the Code agent did not produce a closing answer");
3386
+ const body = closing || detail;
3396
3387
  await this.#event(command, {
3397
3388
  type: "message",
3398
- actor: result.status === "completed" ? "agent" : "system",
3389
+ actor: completed ? "agent" : "system",
3399
3390
  body
3400
3391
  }, active.conversationRefs).catch(() => void 0);
3401
3392
  await this.#event(command, {
3402
3393
  type: "status",
3403
- status: result.status === "completed" ? "idle" : "failed",
3394
+ status: completed ? "idle" : "failed",
3404
3395
  durationMs: Date.now() - startedAt
3405
3396
  }, active.conversationRefs).catch(() => void 0);
3406
- if (result.status === "failed") {
3407
- const detail = (result.error ?? "").trim() || "the Code agent failed";
3397
+ if (!completed) {
3408
3398
  await this.#diagnostic(command, active, detail);
3409
3399
  await this.#failure(command, active, detail);
3410
3400
  }
3411
3401
  return {
3412
3402
  ...result,
3403
+ status: completed ? "completed" : "failed",
3404
+ ...!completed ? { error: detail } : {},
3413
3405
  tokens: interaction.tokens,
3414
3406
  ...interaction.costKnown ? { costUsd: interaction.costUsd } : {}
3415
3407
  };