@odla-ai/cli 0.40.2 → 0.41.1

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/bin.js CHANGED
@@ -174,7 +174,7 @@ function absoluteEntryPath(entryPath) {
174
174
 
175
175
  // src/bin.ts
176
176
  var argv = process.argv.slice(2);
177
- requireCurrentCliForProvision(argv).then(() => requireCoherentProvisionRuntime(argv)).then(async () => (await import("./cli-WJSQEBDO.js")).runCli()).catch((err) => {
177
+ requireCurrentCliForProvision(argv).then(() => requireCoherentProvisionRuntime(argv)).then(async () => (await import("./cli-N5PASRYU.js")).runCli()).catch((err) => {
178
178
  console.error(redactSecrets(`odla-ai: ${err instanceof Error ? err.message : String(err)}`));
179
179
  process.exitCode = exitCodeFor(err);
180
180
  });
@@ -6145,7 +6145,7 @@ async function stageWorkspacePair(baselineSource, workspaceSource, options = {})
6145
6145
  }
6146
6146
  }
6147
6147
 
6148
- // ../harness/dist/chunk-L2T3LPEF.js
6148
+ // ../harness/dist/chunk-5HX5LWTG.js
6149
6149
  import { createHash as createHash3 } from "crypto";
6150
6150
  import { readFile as readFile2, readdir as readdir2 } from "fs/promises";
6151
6151
  import { relative as relative4, resolve as resolve10 } from "path";
@@ -6482,7 +6482,7 @@ function validateSnapshot(snapshot, limits) {
6482
6482
  }
6483
6483
  }
6484
6484
 
6485
- // ../harness/dist/chunk-L2T3LPEF.js
6485
+ // ../harness/dist/chunk-5HX5LWTG.js
6486
6486
  import { spawn as spawn4 } from "child_process";
6487
6487
  import { lstat as lstat2 } from "fs/promises";
6488
6488
  import { resolve as resolve23, sep as sep3 } from "path";
@@ -6500,6 +6500,7 @@ import {
6500
6500
  keepRecentExchanges,
6501
6501
  runAgent
6502
6502
  } from "@odla-ai/ai";
6503
+ import { extractText } from "@odla-ai/ai";
6503
6504
  import { readFile as readFile22, readdir as readdir22 } from "fs/promises";
6504
6505
  import { relative as relative22, resolve as resolve42 } from "path";
6505
6506
 
@@ -6787,7 +6788,7 @@ function looksLikeDestination(value2) {
6787
6788
  return /^(?:[a-z][a-z0-9+.-]*:\/\/|\/|\\\\)/i.test(text3) || /^[\w.-]+\.[a-z]{2,}(?:[/:]|$)/i.test(text3);
6788
6789
  }
6789
6790
 
6790
- // ../harness/dist/chunk-L2T3LPEF.js
6791
+ // ../harness/dist/chunk-5HX5LWTG.js
6791
6792
  import { readFile as readFile4, stat as stat2 } from "fs/promises";
6792
6793
  import { readFile as readFile3 } from "fs/promises";
6793
6794
  import { join as join33 } from "path";
@@ -7055,7 +7056,7 @@ async function buildCodeGraph(input) {
7055
7056
  return builder.build();
7056
7057
  }
7057
7058
 
7058
- // ../harness/dist/chunk-L2T3LPEF.js
7059
+ // ../harness/dist/chunk-5HX5LWTG.js
7059
7060
  import { createHash as createHash32 } from "crypto";
7060
7061
  async function digestStagedWorkspace(root, limits) {
7061
7062
  const files = [];
@@ -8301,6 +8302,7 @@ async function runCodeAgent(options) {
8301
8302
  }
8302
8303
  async function runCodeAgentAttempt(options) {
8303
8304
  try {
8305
+ const surface = options.surface ?? "v2";
8304
8306
  const { run } = await runCodeAgent({
8305
8307
  inference: options.inference,
8306
8308
  broker: options.broker,
@@ -8310,17 +8312,31 @@ async function runCodeAgentAttempt(options) {
8310
8312
  // The brokered route resolves the real model from platform policy; this
8311
8313
  // id only labels the request the control plane is about to rewrite.
8312
8314
  model: "brokered",
8313
- surface: options.surface ?? "v2",
8315
+ surface,
8314
8316
  ...options.maxSteps === void 0 ? {} : { maxSteps: options.maxSteps },
8315
8317
  ...options.budget ? { budget: options.budget } : {},
8316
8318
  ...options.signal ? { signal: options.signal } : {},
8317
8319
  ...options.onToolCall ? { onToolCall: options.onToolCall } : {}
8318
8320
  });
8321
+ let finalText = run.finalText.trim();
8322
+ if (!finalText && run.stoppedReason !== "refusal") {
8323
+ const closing = await options.inference.chat({
8324
+ model: "brokered",
8325
+ system: `${SYSTEM_PROMPT_FOR[surface]}
8326
+
8327
+ Finish with a concise, non-empty answer to the owner. Do not call tools or promise future work.`,
8328
+ messages: [...run.messages, { role: "user", content: "Give the owner the closing answer now, grounded in the repository evidence and tool results above." }],
8329
+ maxTokens: 16384,
8330
+ ...options.signal ? { signal: options.signal } : {}
8331
+ });
8332
+ finalText = extractText(closing.content).trim();
8333
+ }
8334
+ const missingClosing = !finalText && run.stoppedReason !== "refusal";
8319
8335
  return {
8320
- status: run.stoppedReason === "refusal" ? "failed" : "completed",
8321
- finalText: run.finalText,
8336
+ status: run.stoppedReason === "refusal" || missingClosing ? "failed" : "completed",
8337
+ finalText,
8322
8338
  stoppedReason: run.stoppedReason,
8323
- ...run.stoppedReason === "refusal" ? { error: run.finalText || "the agent refused the task" } : {}
8339
+ ...run.stoppedReason === "refusal" ? { error: finalText || "the agent refused the task" } : missingClosing ? { error: "the Code agent did not produce a closing answer" } : {}
8324
8340
  };
8325
8341
  } catch (cause) {
8326
8342
  const error = (cause instanceof Error ? cause.message : String(cause)).slice(0, 2e3);
@@ -8328,31 +8344,7 @@ async function runCodeAgentAttempt(options) {
8328
8344
  }
8329
8345
  }
8330
8346
  async function handleCodeRuntimeInference(input) {
8331
- const { command, metadata: metadata2, request: request3, state: state2 } = input;
8332
- if (state2.tokens >= metadata2.maxTokensPerInteraction) {
8333
- if (!state2.noticeEmitted) {
8334
- state2.noticeEmitted = true;
8335
- await input.event({
8336
- type: "message",
8337
- actor: "system",
8338
- body: `The agent paused at the ${metadata2.maxTokensPerInteraction.toLocaleString("en-US")}-token per-interaction limit. Send a new instruction to continue.`
8339
- }).catch(() => void 0);
8340
- }
8341
- return {
8342
- protocolVersion: HARNESS_PROTOCOL_VERSION,
8343
- type: "inference.response",
8344
- requestId: request3.requestId,
8345
- response: {
8346
- id: `budget:${command.commandId}`,
8347
- provider: "openai",
8348
- model: "interaction-budget",
8349
- role: "assistant",
8350
- content: [{ type: "text", text: "Pause now. The owner-set token limit for this interaction has been reached." }],
8351
- stopReason: "end_turn",
8352
- usage: { inputTokens: 0, outputTokens: 0 }
8353
- }
8354
- };
8355
- }
8347
+ const { command, request: request3, state: state2 } = input;
8356
8348
  const startedAt = Date.now();
8357
8349
  const response2 = await input.control.infer(command.sessionId, {
8358
8350
  requestId: request3.requestId,
@@ -8372,7 +8364,6 @@ async function handleCodeRuntimeInference(input) {
8372
8364
  durationMs: Date.now() - startedAt,
8373
8365
  interactionId: command.commandId,
8374
8366
  interactionTokens: state2.tokens,
8375
- interactionMaxTokens: metadata2.maxTokensPerInteraction,
8376
8367
  ...costUsd === void 0 ? {} : { costUsd },
8377
8368
  ...state2.costKnown ? { interactionCostUsd: state2.costUsd } : {}
8378
8369
  }).catch(() => void 0);
@@ -9441,7 +9432,7 @@ var CodePiRuntimeEngine = class {
9441
9432
  recipeAuthorization: this.options.recipeAuthorization
9442
9433
  }, lease, metadata2.role));
9443
9434
  const startedAt = Date.now();
9444
- const interaction = { tokens: 0, noticeEmitted: false, costUsd: 0, costKnown: true };
9435
+ const interaction = { tokens: 0, costUsd: 0, costKnown: true };
9445
9436
  const inference = createCodeRuntimeInference({
9446
9437
  command,
9447
9438
  metadata: metadata2,
@@ -9456,31 +9447,30 @@ var CodePiRuntimeEngine = class {
9456
9447
  lease,
9457
9448
  workspaceDir: active.workspace.workspaceDir,
9458
9449
  prompt: metadata2.prompt,
9459
- signal: active.abort.signal,
9460
- // The owner's per-interaction allowance, enforced by runAgent against
9461
- // INCREMENTAL usage. The control plane still reserves against the same
9462
- // ceiling, but this is what stops the loop cleanly at the boundary rather
9463
- // than letting it discover the limit through a synthesized pause reply.
9464
- budget: { maxTotalTokens: metadata2.maxTokensPerInteraction }
9450
+ signal: active.abort.signal
9465
9451
  });
9466
- const body = result.finalText.trim() || (result.status === "completed" ? "The agent finished without a closing message." : result.error ?? "The agent failed.");
9452
+ const closing = result.finalText.trim();
9453
+ const completed = result.status === "completed" && Boolean(closing);
9454
+ const detail = result.error?.trim() || (closing ? "the Code agent failed" : "the Code agent did not produce a closing answer");
9455
+ const body = closing || detail;
9467
9456
  await this.#event(command, {
9468
9457
  type: "message",
9469
- actor: result.status === "completed" ? "agent" : "system",
9458
+ actor: completed ? "agent" : "system",
9470
9459
  body
9471
9460
  }, active.conversationRefs).catch(() => void 0);
9472
9461
  await this.#event(command, {
9473
9462
  type: "status",
9474
- status: result.status === "completed" ? "idle" : "failed",
9463
+ status: completed ? "idle" : "failed",
9475
9464
  durationMs: Date.now() - startedAt
9476
9465
  }, active.conversationRefs).catch(() => void 0);
9477
- if (result.status === "failed") {
9478
- const detail = (result.error ?? "").trim() || "the Code agent failed";
9466
+ if (!completed) {
9479
9467
  await this.#diagnostic(command, active, detail);
9480
9468
  await this.#failure(command, active, detail);
9481
9469
  }
9482
9470
  return {
9483
9471
  ...result,
9472
+ status: completed ? "completed" : "failed",
9473
+ ...!completed ? { error: detail } : {},
9484
9474
  tokens: interaction.tokens,
9485
9475
  ...interaction.costKnown ? { costUsd: interaction.costUsd } : {}
9486
9476
  };
@@ -10567,12 +10557,12 @@ Usage:
10567
10557
  odla-ai pm <goal|task|decision|bug> rm <id>
10568
10558
  odla-ai pm handoff --app <id> [--project <id>] [--json]
10569
10559
  odla-ai discuss groups [--json]
10570
- odla-ai discuss list [--app <id>] [--q <text>] [--state open|resolved|all] [--json]
10560
+ odla-ai discuss list [--app <id>] [--q <text>] [--state open|resolved|all] [--mentions] [--json]
10571
10561
  odla-ai discuss read <topic> [--limit <n> --offset <n>] [--json]
10572
10562
  odla-ai discuss post --app <id> --subject "..." --body "..." [--markup "... @[Label](kind/id)"] [--mutation-id <id>]
10573
10563
  odla-ai discuss reply <topic> --body "..." [--markup "..."] [--mutation-id <id>]
10574
10564
  odla-ai discuss resolve <topic> [--reopen] [--mutation-id <id>]
10575
- odla-ai discuss who --q <text> [--app <id>] [--kinds user,pm:task] [--json]
10565
+ odla-ai discuss who --q <text> [--app <id>] [--topic <id>] [--kinds user,pm:task] [--json]
10576
10566
  odla-ai discuss watch [<topic>] [--cursor <cursor>] [--by <authorId>] [--self <authorId>] [--interval <s>] [--timeout <s>] [--json|--jsonl]
10577
10567
  odla-ai agent jobs [--env dev] [--state pending|running|succeeded|dead_letter] [--limit 50] [--token <ODLA_API_KEY>] [--json]
10578
10568
  odla-ai agent retry <job-id> [--env dev] [--token <ODLA_API_KEY>] [--json]
@@ -11011,6 +11001,7 @@ async function discussList(ctx, parsed) {
11011
11001
  const value2 = stringOpt(parsed.options[flag]);
11012
11002
  if (value2) query.set(param, value2);
11013
11003
  }
11004
+ if (parsed.options.mentions === true) query.set("mentions", "1");
11014
11005
  const qs = query.toString();
11015
11006
  const page2 = await request(ctx, "GET", `/topics${qs ? `?${qs}` : ""}`);
11016
11007
  emit(ctx, page2, () => {
@@ -11117,11 +11108,16 @@ async function discussWho(ctx, parsed) {
11117
11108
  if (app) query.set("app", app);
11118
11109
  const kinds = stringOpt(parsed.options.kinds);
11119
11110
  if (kinds) query.set("kinds", kinds);
11111
+ const topic = stringOpt(parsed.options.topic);
11112
+ if (topic) query.set("topic", topic);
11120
11113
  const found = await request(ctx, "GET", `/mentionables?${query.toString()}`);
11121
11114
  emit(ctx, found, () => {
11122
- ctx.out.log("mention kind hint");
11115
+ ctx.out.log("mention kind use hint");
11123
11116
  for (const item of found.items) {
11124
- ctx.out.log(`@[${item.label}](${item.kind}/${item.id}) ${item.kind} ${item.hint ?? ""}`);
11117
+ const use = item.kind === "agent" ? item.meta?.executionAvailability === "runnable" ? "runnable" : "reference" : "";
11118
+ ctx.out.log(
11119
+ `@[${item.label}](${item.kind}/${item.id}) ${item.kind} ${use} ${item.hint ?? ""}`
11120
+ );
11125
11121
  }
11126
11122
  if (found.failed.length > 0) ctx.out.error(`(no results from: ${found.failed.join(", ")})`);
11127
11123
  });
@@ -11371,6 +11367,8 @@ var ALLOWED = [
11371
11367
  "reopen",
11372
11368
  "by",
11373
11369
  "self",
11370
+ "topic",
11371
+ "mentions",
11374
11372
  "interval",
11375
11373
  "timeout",
11376
11374
  "cursor",
@@ -15799,4 +15797,4 @@ export {
15799
15797
  isTerminalHostedSecurityStatus,
15800
15798
  runCli
15801
15799
  };
15802
- //# sourceMappingURL=chunk-XUTMQMXZ.js.map
15800
+ //# sourceMappingURL=chunk-6RGM4W73.js.map