@odla-ai/cli 0.16.1 → 0.16.3

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
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  exitCodeFor,
4
4
  runCli
5
- } from "./chunk-FRDIQURT.js";
5
+ } from "./chunk-YWC7F5T3.js";
6
6
 
7
7
  // src/bin.ts
8
8
  runCli().catch((err) => {
@@ -1775,12 +1775,15 @@ async function defaultReadOrigin(cwd) {
1775
1775
  }
1776
1776
 
1777
1777
  // src/code-runtime-config.ts
1778
- var CODE_PI_IMAGE = "ghcr.io/cory/odla-pi-agent@sha256:e7858b4f0291543171b2659b47c5d00f97acc4767cafd9b74ae5228899e0cde4";
1778
+ var CODE_PI_IMAGE = "ghcr.io/cory/odla-pi-agent@sha256:2a52a1c8eed66ad167e7bccab4d603ed8fcd75c42dddfb320083436ed89b7c9c";
1779
1779
  var CODE_BUILD_RECIPES = Object.freeze([{
1780
1780
  id: "odla-code-contracts",
1781
1781
  image: "node:24-alpine@sha256:a0b9bf06e4e6193cf7a0f58816cc935ff8c2a908f81e6f1a95432d679c54fbfd",
1782
1782
  command: [
1783
1783
  "node",
1784
+ // The clean source mount deliberately has no node_modules. Reuse the
1785
+ // semver copy inside this digest-pinned npm image without network access.
1786
+ "--import=data:text/javascript,import%20Module%20from%20%22node%3Amodule%22%3Bprocess.env.NODE_PATH%3D%22%2Fusr%2Flocal%2Flib%2Fnode_modules%2Fnpm%2Fnode_modules%22%3BModule._initPaths%28%29",
1784
1787
  "--test",
1785
1788
  "scripts/lib/directories.test.mjs",
1786
1789
  "scripts/lib/internal-deps.test.mjs",
@@ -1800,10 +1803,10 @@ import { existsSync as existsSync4 } from "fs";
1800
1803
  import { cpus, hostname, totalmem } from "os";
1801
1804
  import { resolve as resolve5 } from "path";
1802
1805
 
1803
- // ../harness/dist/chunk-UG5XHNFB.js
1806
+ // ../harness/dist/chunk-QTUEF2HZ.js
1804
1807
  var HARNESS_PROTOCOL_VERSION = 1;
1805
1808
 
1806
- // ../harness/dist/chunk-QALIIZRJ.js
1809
+ // ../harness/dist/chunk-GE6CCN7W.js
1807
1810
  var CONTROL = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/;
1808
1811
  var HarnessProtocolError = class extends Error {
1809
1812
  name = "HarnessProtocolError";
@@ -1881,7 +1884,7 @@ function encodeAgentInput(message2) {
1881
1884
  `;
1882
1885
  }
1883
1886
 
1884
- // ../harness/dist/chunk-TA2FKK27.js
1887
+ // ../harness/dist/chunk-IRFCMVKU.js
1885
1888
  import { execFile as execFile2, spawn as spawn2 } from "child_process";
1886
1889
  import { constants } from "fs";
1887
1890
  import { access } from "fs/promises";
@@ -2398,7 +2401,7 @@ async function stageWorkspacePair(baselineSource, workspaceSource, options = {})
2398
2401
  }
2399
2402
  }
2400
2403
 
2401
- // ../harness/dist/chunk-5E2R3LHE.js
2404
+ // ../harness/dist/chunk-4MOSEKB6.js
2402
2405
  import { createHash } from "crypto";
2403
2406
  import { readFile, readdir as readdir2 } from "fs/promises";
2404
2407
  import { relative as relative3, resolve as resolve4 } from "path";
@@ -2735,7 +2738,7 @@ function validateSnapshot(snapshot, limits) {
2735
2738
  }
2736
2739
  }
2737
2740
 
2738
- // ../harness/dist/chunk-5E2R3LHE.js
2741
+ // ../harness/dist/chunk-4MOSEKB6.js
2739
2742
  import { spawn as spawn4 } from "child_process";
2740
2743
  import { lstat as lstat2 } from "fs/promises";
2741
2744
  import { resolve as resolve23, sep as sep3 } from "path";
@@ -3028,7 +3031,7 @@ function looksLikeDestination(value) {
3028
3031
  return /^(?:[a-z][a-z0-9+.-]*:\/\/|\/|\\\\)/i.test(text) || /^[\w.-]+\.[a-z]{2,}(?:[/:]|$)/i.test(text);
3029
3032
  }
3030
3033
 
3031
- // ../harness/dist/chunk-5E2R3LHE.js
3034
+ // ../harness/dist/chunk-4MOSEKB6.js
3032
3035
  import { createHash as createHash3 } from "crypto";
3033
3036
  async function digestStagedWorkspace(root, limits) {
3034
3037
  const files = [];
@@ -4219,6 +4222,7 @@ function codeCommandMetadata(payload, resume) {
4219
4222
  const role = payload.role;
4220
4223
  const title = payload.title;
4221
4224
  const prompt = payload.prompt;
4225
+ const maxTokensPerInteraction = payload.maxTokensPerInteraction ?? 32e3;
4222
4226
  if (role !== "coding" && role !== "review" || typeof title !== "string" || typeof prompt !== "string") {
4223
4227
  throw new TypeError(`invalid Code ${resume ? "resume" : "start"} metadata`);
4224
4228
  }
@@ -4230,10 +4234,14 @@ function codeCommandMetadata(payload, resume) {
4230
4234
  if (typeof repository !== "string" || !repository.includes("/") || typeof baseCommitSha !== "string" || !/^[0-9a-f]{40}$/.test(baseCommitSha) || typeof sourceTreeDigest !== "string" || !/^sha256:[0-9a-f]{64}$/.test(sourceTreeDigest)) {
4231
4235
  throw new TypeError(`invalid Code ${resume ? "resume" : "start"} trusted base`);
4232
4236
  }
4237
+ if (!Number.isSafeInteger(maxTokensPerInteraction) || Number(maxTokensPerInteraction) < 4e3 || Number(maxTokensPerInteraction) > 2e5) {
4238
+ throw new TypeError(`invalid Code ${resume ? "resume" : "start"} interaction token limit`);
4239
+ }
4233
4240
  return {
4234
4241
  role,
4235
4242
  title,
4236
4243
  prompt,
4244
+ maxTokensPerInteraction: Number(maxTokensPerInteraction),
4237
4245
  planningInputDigest: typeof planning === "string" && /^sha256:[0-9a-f]{64}$/.test(planning) ? planning : null,
4238
4246
  attestationDigest: typeof attestation === "string" ? attestation : "resume",
4239
4247
  repository,
@@ -4309,6 +4317,57 @@ function createCodeRuntimeToolBroker(input, lease, role) {
4309
4317
  });
4310
4318
  return role === "coding" ? broker : { execute: (context, request) => request.tool === "sandbox.read" ? broker.execute(context, request) : Promise.resolve({ requestId: request.requestId, ok: false, content: "review sessions are read-only" }) };
4311
4319
  }
4320
+ async function handleCodeRuntimeInference(input) {
4321
+ const { command, metadata: metadata2, request, state } = input;
4322
+ if (state.tokens >= metadata2.maxTokensPerInteraction) {
4323
+ if (!state.noticeEmitted) {
4324
+ state.noticeEmitted = true;
4325
+ await input.event({
4326
+ type: "message",
4327
+ actor: "system",
4328
+ body: `Pi paused at the ${metadata2.maxTokensPerInteraction.toLocaleString("en-US")}-token per-interaction limit. Send a new instruction to continue.`
4329
+ }).catch(() => void 0);
4330
+ }
4331
+ return {
4332
+ protocolVersion: HARNESS_PROTOCOL_VERSION,
4333
+ type: "inference.response",
4334
+ requestId: request.requestId,
4335
+ response: {
4336
+ id: `budget:${command.commandId}`,
4337
+ provider: "openai",
4338
+ model: "interaction-budget",
4339
+ role: "assistant",
4340
+ content: [{ type: "text", text: "Pause now. The owner-set token limit for this interaction has been reached." }],
4341
+ stopReason: "end_turn",
4342
+ usage: { inputTokens: 0, outputTokens: 0 }
4343
+ }
4344
+ };
4345
+ }
4346
+ const startedAt = Date.now();
4347
+ const response2 = await input.control.infer(command.sessionId, {
4348
+ requestId: request.requestId,
4349
+ interactionId: command.commandId,
4350
+ call: request.call
4351
+ });
4352
+ state.tokens += response2.receipt.inputTokens + response2.receipt.outputTokens;
4353
+ await input.event({
4354
+ type: "usage",
4355
+ provider: response2.receipt.provider,
4356
+ model: response2.receipt.model,
4357
+ inputTokens: response2.receipt.inputTokens,
4358
+ outputTokens: response2.receipt.outputTokens,
4359
+ durationMs: Date.now() - startedAt,
4360
+ interactionId: command.commandId,
4361
+ interactionTokens: state.tokens,
4362
+ interactionMaxTokens: metadata2.maxTokensPerInteraction
4363
+ }).catch(() => void 0);
4364
+ return {
4365
+ protocolVersion: HARNESS_PROTOCOL_VERSION,
4366
+ type: "inference.response",
4367
+ requestId: request.requestId,
4368
+ response: response2.response
4369
+ };
4370
+ }
4312
4371
  async function appendCodeRuntimeEvent(control, command, event, refs) {
4313
4372
  const eventId = `${command.commandId.slice(0, 45)}:${refs.length + 1}`;
4314
4373
  refs.push(eventId);
@@ -4327,7 +4386,13 @@ var safeRuntimeJson = (value) => {
4327
4386
  };
4328
4387
  function runtimeResultText(value) {
4329
4388
  const record32 = runtimeRecord(value);
4330
- return record32 && typeof record32.text === "string" ? record32.text.slice(0, 2e4) : null;
4389
+ if (record32 && typeof record32.text === "string") return record32.text.slice(0, 2e4);
4390
+ if (record32 && typeof record32.error === "string") return `Pi failed: ${record32.error.slice(0, 19989)}`;
4391
+ return null;
4392
+ }
4393
+ function runtimeResultError(value) {
4394
+ const record32 = runtimeRecord(value);
4395
+ return record32 && typeof record32.error === "string" && record32.error.trim() ? record32.error.trim().slice(0, 2e3) : null;
4331
4396
  }
4332
4397
  var CodePiRuntimeEngine = class {
4333
4398
  constructor(options) {
@@ -4414,6 +4479,7 @@ var CodePiRuntimeEngine = class {
4414
4479
  acknowledged: false,
4415
4480
  role: metadata2.role,
4416
4481
  title: metadata2.title,
4482
+ maxTokensPerInteraction: metadata2.maxTokensPerInteraction,
4417
4483
  baseCommitSha: metadata2.baseCommitSha,
4418
4484
  repository: metadata2.repository,
4419
4485
  sourceTreeDigest: metadata2.sourceTreeDigest,
@@ -4435,9 +4501,11 @@ var CodePiRuntimeEngine = class {
4435
4501
  }, conversationRefs);
4436
4502
  }
4437
4503
  active.done = this.#runAttempt(command, metadata2, active).catch(async (cause) => {
4438
- await this.#event(command, { type: "message", actor: "system", body: `Pi failed: ${runtimeErrorMessage(cause)}` }, conversationRefs).catch(() => void 0);
4504
+ const detail = runtimeErrorMessage(cause);
4505
+ await this.#event(command, { type: "message", actor: "system", body: `Pi failed: ${detail}` }, conversationRefs).catch(() => void 0);
4506
+ await this.#diagnostic(command, active, detail);
4439
4507
  await this.#event(command, { type: "status", status: "failed" }, conversationRefs).catch(() => void 0);
4440
- await this.#failure(command, active, runtimeErrorMessage(cause));
4508
+ await this.#failure(command, active, detail);
4441
4509
  return null;
4442
4510
  });
4443
4511
  return { status: "running", message: resume ? "Pi resumed from a portable checkpoint" : "Pi started" };
@@ -4448,6 +4516,11 @@ var CodePiRuntimeEngine = class {
4448
4516
  if (!active || typeof prompt !== "string" || !prompt.trim() || prompt.length > 2e4) {
4449
4517
  throw new TypeError("prompt requires an active Code session and bounded text");
4450
4518
  }
4519
+ const requestedLimit = command.payload.maxTokensPerInteraction ?? active.maxTokensPerInteraction;
4520
+ if (!Number.isSafeInteger(requestedLimit) || Number(requestedLimit) < 4e3 || Number(requestedLimit) > 2e5) {
4521
+ throw new TypeError("prompt requires a valid interaction token limit");
4522
+ }
4523
+ active.maxTokensPerInteraction = Number(requestedLimit);
4451
4524
  await active.done;
4452
4525
  active.abort = new AbortController();
4453
4526
  active.acknowledged = false;
@@ -4456,19 +4529,22 @@ var CodePiRuntimeEngine = class {
4456
4529
  role: active.role,
4457
4530
  title: active.title,
4458
4531
  prompt,
4532
+ maxTokensPerInteraction: active.maxTokensPerInteraction,
4459
4533
  planningInputDigest: active.planningInputDigest,
4460
4534
  attestationDigest: "follow-up",
4461
4535
  repository: active.repository,
4462
4536
  baseCommitSha: active.baseCommitSha,
4463
4537
  sourceTreeDigest: active.sourceTreeDigest
4464
4538
  }, active).catch(async (cause) => {
4539
+ const detail = runtimeErrorMessage(cause);
4465
4540
  await this.#event(
4466
4541
  command,
4467
- { type: "message", actor: "system", body: `Pi failed: ${runtimeErrorMessage(cause)}` },
4542
+ { type: "message", actor: "system", body: `Pi failed: ${detail}` },
4468
4543
  active.conversationRefs
4469
4544
  ).catch(() => void 0);
4545
+ await this.#diagnostic(command, active, detail);
4470
4546
  await this.#event(command, { type: "status", status: "failed" }, active.conversationRefs).catch(() => void 0);
4471
- await this.#failure(command, active, runtimeErrorMessage(cause));
4547
+ await this.#failure(command, active, detail);
4472
4548
  return null;
4473
4549
  });
4474
4550
  return { status: "running", message: "Pi accepted the owner prompt" };
@@ -4482,6 +4558,7 @@ var CodePiRuntimeEngine = class {
4482
4558
  }, lease, metadata2.role);
4483
4559
  const startedAt = Date.now();
4484
4560
  let completionSeen = false;
4561
+ const interaction = { tokens: 0, noticeEmitted: false };
4485
4562
  const result = await this.#run({
4486
4563
  engine: this.options.engine,
4487
4564
  image: this.options.image,
@@ -4497,25 +4574,18 @@ var CodePiRuntimeEngine = class {
4497
4574
  }, active.conversationRefs),
4498
4575
  onMessage: async (output) => {
4499
4576
  if (output.type === "inference.request") {
4500
- const inferenceStarted = Date.now();
4501
- const response2 = await this.options.control.infer(command.sessionId, {
4502
- requestId: output.requestId,
4503
- call: output.call
4577
+ return handleCodeRuntimeInference({
4578
+ command,
4579
+ metadata: metadata2,
4580
+ request: output,
4581
+ state: interaction,
4582
+ control: this.options.control,
4583
+ event: (event) => this.#event(
4584
+ command,
4585
+ event,
4586
+ active.conversationRefs
4587
+ )
4504
4588
  });
4505
- await this.#event(command, {
4506
- type: "usage",
4507
- provider: response2.receipt.provider,
4508
- model: response2.receipt.model,
4509
- inputTokens: response2.receipt.inputTokens,
4510
- outputTokens: response2.receipt.outputTokens,
4511
- durationMs: Date.now() - inferenceStarted
4512
- }, active.conversationRefs).catch(() => void 0);
4513
- return {
4514
- protocolVersion: HARNESS_PROTOCOL_VERSION,
4515
- type: "inference.response",
4516
- requestId: output.requestId,
4517
- response: response2.response
4518
- };
4519
4589
  }
4520
4590
  if (output.type === "tool.request") {
4521
4591
  const toolStarted = Date.now();
@@ -4580,7 +4650,9 @@ var CodePiRuntimeEngine = class {
4580
4650
  durationMs: Date.now() - startedAt
4581
4651
  }, active.conversationRefs).catch(() => void 0);
4582
4652
  if (result.status === "failed") {
4583
- await this.#failure(command, active, result.stderr || "Pi container failed");
4653
+ const detail = (runtimeResultError(result.result) ?? result.stderr.trim()) || "Pi container failed";
4654
+ await this.#diagnostic(command, active, detail);
4655
+ await this.#failure(command, active, detail);
4584
4656
  }
4585
4657
  return result;
4586
4658
  }
@@ -4597,6 +4669,15 @@ var CodePiRuntimeEngine = class {
4597
4669
  await this.options.control.reportSessionFailure(command.sessionId, active.failure).catch(() => void 0);
4598
4670
  }
4599
4671
  }
4672
+ async #diagnostic(command, active, value) {
4673
+ const detail = value.trim().slice(0, 2e3) || "Pi runtime failed";
4674
+ this.options.onDiagnostic?.(detail);
4675
+ await this.#event(
4676
+ command,
4677
+ { type: "diagnostic", level: "error", message: detail },
4678
+ active.conversationRefs
4679
+ ).catch(() => void 0);
4680
+ }
4600
4681
  async #event(command, event, refs) {
4601
4682
  await appendCodeRuntimeEvent(this.options.control, command, event, refs);
4602
4683
  }
@@ -4914,7 +4995,8 @@ async function runCodeRuntime(input) {
4914
4995
  image: CODE_PI_IMAGE,
4915
4996
  recipes: CODE_BUILD_RECIPES,
4916
4997
  recipeAuthorization: "registered_recipe",
4917
- localSource: input.localSource
4998
+ localSource: input.localSource,
4999
+ onDiagnostic: (message2) => input.stdout.error(`Pi runtime failed \xB7 ${message2}`)
4918
5000
  });
4919
5001
  const reconciler = new CodeRuntimeReconciler(control, commandEngine);
4920
5002
  try {
@@ -7754,4 +7836,4 @@ export {
7754
7836
  exitCodeFor,
7755
7837
  runCli
7756
7838
  };
7757
- //# sourceMappingURL=chunk-FRDIQURT.js.map
7839
+ //# sourceMappingURL=chunk-YWC7F5T3.js.map