@odla-ai/cli 0.41.1 → 0.42.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/bin/odla-ai.js CHANGED
@@ -3,7 +3,7 @@ import { existsSync, readFileSync, statSync } from "node:fs";
3
3
  import { spawnSync } from "node:child_process";
4
4
  import { dirname, join } from "node:path";
5
5
  import { fileURLToPath, pathToFileURL } from "node:url";
6
- import { workspaceBuildOrder } from "./workspace-build.js";
6
+ import { workspaceBuildOrder, workspaceInitialBuildArguments } from "./workspace-build.js";
7
7
  import { firstStaleWorkspace, staleBuildNotice } from "./stale-build.js";
8
8
 
9
9
  const packageRoot = join(dirname(fileURLToPath(import.meta.url)), "..");
@@ -22,10 +22,9 @@ if (!existsSync(builtEntry)) {
22
22
 
23
23
  console.error("odla-ai: workspace CLI is not built; building the local monorepo first");
24
24
  const npm = process.platform === "win32" ? "npm.cmd" : "npm";
25
- const workspaces = workspaceBuildOrder(workspaceRoot);
26
25
  const child = spawnSync(
27
26
  npm,
28
- ["run", "build", ...workspaces.map((name) => `--workspace=${name}`)],
27
+ workspaceInitialBuildArguments(),
29
28
  { cwd: workspaceRoot, stdio: "inherit" },
30
29
  );
31
30
  if (child.error) throw child.error;
@@ -1,5 +1,6 @@
1
1
  /** Return buildable internal dependencies in dependency-first order. */
2
2
  export declare function workspaceBuildOrder(root: string): string[];
3
+ export declare function workspaceInitialBuildArguments(): string[];
3
4
 
4
5
  /** Every workspace in the checkout, by package name, with its directory. */
5
6
  export declare function workspacePackages(
@@ -46,3 +46,11 @@ export function workspaceBuildOrder(root) {
46
46
  visit("@odla-ai/cli");
47
47
  return order;
48
48
  }
49
+
50
+ /** The missing-build recovery path must use the repository's canonical build.
51
+ * Its project-reference steps include internal packages that intentionally do
52
+ * not expose workspace build scripts, so a workspace-only closure is unsafe in
53
+ * a fresh checkout. */
54
+ export function workspaceInitialBuildArguments() {
55
+ return ["run", "build"];
56
+ }
package/dist/bin.cjs CHANGED
@@ -7915,7 +7915,7 @@ var init_code2 = __esm({
7915
7915
  }
7916
7916
  });
7917
7917
 
7918
- // ../harness/dist/chunk-5HX5LWTG.js
7918
+ // ../harness/dist/chunk-QZXCQSPZ.js
7919
7919
  async function digestStagedWorkspace(root, limits) {
7920
7920
  const files = [];
7921
7921
  const walk = async (directory) => {
@@ -8868,7 +8868,12 @@ function codeSkill(opts) {
8868
8868
  { lease: opts.lease, workspaceDir: opts.workspaceDir, signal },
8869
8869
  { requestId: `bench-${tool}-${++seq}`, tool, input }
8870
8870
  );
8871
- opts.onToolCall?.({ tool, ok: response2.ok, durationMs: Date.now() - startedAt });
8871
+ opts.onToolCall?.({
8872
+ tool,
8873
+ ok: response2.ok,
8874
+ durationMs: Date.now() - startedAt,
8875
+ ...response2.ok ? {} : { error: String(response2.content).slice(0, 300) }
8876
+ });
8872
8877
  return { content: response2.content, isError: !response2.ok };
8873
8878
  };
8874
8879
  const read22 = {
@@ -8899,11 +8904,17 @@ function codeSkill(opts) {
8899
8904
  };
8900
8905
  const runRecipe = {
8901
8906
  name: "odla_run_recipe",
8902
- description: "Run one app-registered build or test recipe through CaMeL policy.",
8907
+ description: `Run one app-registered build or test recipe through CaMeL policy.${opts.recipeIds?.length ? ` Available recipes: ${opts.recipeIds.join(", ")}.` : ""}`,
8903
8908
  inputSchema: {
8904
8909
  type: "object",
8905
8910
  required: ["recipeId"],
8906
- properties: { recipeId: { type: "string", minLength: 1, maxLength: 120, pattern: "^[a-zA-Z0-9._:-]+$" } },
8911
+ properties: { recipeId: {
8912
+ type: "string",
8913
+ minLength: 1,
8914
+ maxLength: 120,
8915
+ pattern: "^[a-zA-Z0-9._:-]+$",
8916
+ ...opts.recipeIds?.length ? { enum: [...opts.recipeIds] } : {}
8917
+ } },
8907
8918
  additionalProperties: false
8908
8919
  },
8909
8920
  handler: (input, ctx) => call4("sandbox.run_recipe", input, ctx.signal)
@@ -8985,6 +8996,7 @@ async function runCodeAgent(options) {
8985
8996
  lease: options.lease,
8986
8997
  workspaceDir: options.workspaceDir,
8987
8998
  surface,
8999
+ ...options.recipeIds ? { recipeIds: options.recipeIds } : {},
8988
9000
  onToolCall: (call4) => {
8989
9001
  toolCalls.push(call4);
8990
9002
  options.onToolCall?.(call4);
@@ -9013,7 +9025,7 @@ async function runCodeAgent(options) {
9013
9025
  }
9014
9026
  async function runCodeAgentAttempt(options) {
9015
9027
  try {
9016
- const surface = options.surface ?? "v2";
9028
+ const surface = options.surface ?? "v3";
9017
9029
  const { run } = await runCodeAgent({
9018
9030
  inference: options.inference,
9019
9031
  broker: options.broker,
@@ -9024,6 +9036,7 @@ async function runCodeAgentAttempt(options) {
9024
9036
  // id only labels the request the control plane is about to rewrite.
9025
9037
  model: "brokered",
9026
9038
  surface,
9039
+ ...options.recipeIds ? { recipeIds: options.recipeIds } : {},
9027
9040
  ...options.maxSteps === void 0 ? {} : { maxSteps: options.maxSteps },
9028
9041
  ...options.budget ? { budget: options.budget } : {},
9029
9042
  ...options.signal ? { signal: options.signal } : {},
@@ -9904,9 +9917,9 @@ async function appendCodeRuntimeEvent(control, command, event, refs) {
9904
9917
  const bounded = event.type === "message" ? { ...event, body: event.body.trim().slice(0, 2e4) || `${event.actor} event` } : event;
9905
9918
  await control.appendSessionEvent(command.sessionId, eventId, bounded);
9906
9919
  }
9907
- var import_crypto, import_promises5, import_path5, import_child_process4, import_promises6, import_path6, import_child_process5, import_process2, import_crypto2, import_crypto3, import_fs2, import_promises7, import_path7, import_promises8, import_os3, import_path8, import_ai4, import_ai5, import_promises9, import_path9, import_promises10, import_promises11, import_path10, import_crypto4, CODE_RUNTIME_PROTOCOL_VERSION, CodeRuntimeReconciler, CodeRuntimeControlError, record5, invalid, RESERVED, SECRET, PATH, FORBIDDEN, ARTIFACT_PATH, PRIVATE_ARTIFACT_PART, SHA3, DIGEST3, ID3, RULE, DEFAULT_PREFIXES, DEFAULT_SUFFIXES, message, CodeRuntimeCheckpointManager, record22, SOURCE_LIMITS, RESERVED2, SECRET2, SOURCE_MAX_FILES, SOURCE_MAX_BYTES, SOURCE_SET_MAX_BYTES, V1_SYSTEM_PROMPT, V2_SYSTEM_PROMPT, V3_SYSTEM_PROMPT, SYSTEM_PROMPT_FOR, DEFAULT_MAX_FILES, DEFAULT_MAX_RESULTS, DEFAULT_MAX_FILE_BYTES, DESTINATIONS, READ, LIST, SEARCH, GRAPH, PATCH, RECIPE, cache, shortId, GRAPH_TOOLS, MAX_MEMORY_BODY, POSITIVE, digestRuntimeValue, runtimeErrorMessage, CodePiRuntimeEngine;
9908
- var init_chunk_5HX5LWTG = __esm({
9909
- "../harness/dist/chunk-5HX5LWTG.js"() {
9920
+ var import_crypto, import_promises5, import_path5, import_child_process4, import_promises6, import_path6, import_child_process5, import_process2, import_crypto2, import_crypto3, import_fs2, import_promises7, import_path7, import_promises8, import_os3, import_path8, import_ai4, import_ai5, import_promises9, import_path9, import_promises10, import_promises11, import_path10, import_crypto4, CODE_RUNTIME_PROTOCOL_VERSION, CodeRuntimeReconciler, CodeRuntimeControlError, record5, invalid, RESERVED, SECRET, PATH, FORBIDDEN, ARTIFACT_PATH, PRIVATE_ARTIFACT_PART, SHA3, DIGEST3, ID3, RULE, DEFAULT_PREFIXES, DEFAULT_SUFFIXES, message, CodeRuntimeCheckpointManager, record22, SOURCE_LIMITS, RESERVED2, SECRET2, SOURCE_MAX_FILES, SOURCE_MAX_BYTES, SOURCE_SET_MAX_BYTES, V1_SYSTEM_PROMPT, V2_SYSTEM_PROMPT, V3_SYSTEM_PROMPT, SYSTEM_PROMPT_FOR, DEFAULT_MAX_FILES, DEFAULT_MAX_RESULTS, DEFAULT_MAX_FILE_BYTES, DESTINATIONS, READ, LIST, SEARCH, GRAPH, PATCH, RECIPE, cache, shortId, GRAPH_TOOLS, MAX_MEMORY_BODY, POSITIVE, digestRuntimeValue, runtimeErrorMessage, TheseusRuntimeEngine;
9921
+ var init_chunk_QZXCQSPZ = __esm({
9922
+ "../harness/dist/chunk-QZXCQSPZ.js"() {
9910
9923
  "use strict";
9911
9924
  init_cjs_shims();
9912
9925
  init_chunk_K76I2TCQ();
@@ -10026,7 +10039,7 @@ var init_chunk_5HX5LWTG = __esm({
10026
10039
  await this.options.event(command, { type: "message", actor: "system", body: prepared.note }, active.conversationRefs).catch(() => void 0);
10027
10040
  await active.workspace.cleanup();
10028
10041
  await this.options.event(command, { type: "status", status: "checkpointed" }, active.conversationRefs).catch(() => void 0);
10029
- return { status: "checkpointed", checkpoint: prepared.checkpoint, message: "Pi stopped at a portable checkpoint" };
10042
+ return { status: "checkpointed", checkpoint: prepared.checkpoint, message: "Theseus stopped at a portable checkpoint" };
10030
10043
  }
10031
10044
  async acknowledged(command, result) {
10032
10045
  if (command.kind !== "checkpoint_stop" || result.status !== "checkpointed") return false;
@@ -10050,7 +10063,7 @@ var init_chunk_5HX5LWTG = __esm({
10050
10063
  SOURCE_MAX_FILES = 1e5;
10051
10064
  SOURCE_MAX_BYTES = 80 * 1024 * 1024;
10052
10065
  SOURCE_SET_MAX_BYTES = 480 * 1024 * 1024;
10053
- V1_SYSTEM_PROMPT = `You are Pi, the coding agent inside an odla Code harness.
10066
+ V1_SYSTEM_PROMPT = `You are Theseus, the coding agent inside an odla Code harness.
10054
10067
  Use only the odla_read, odla_apply_git_diff, and odla_run_recipe tools.
10055
10068
  For mutations, call odla_apply_git_diff with raw git diff text. It must start
10056
10069
  with "diff --git a/<path> b/<path>", include matching "---" and "+++" file
@@ -10144,7 +10157,7 @@ Never claim a build or test passed unless odla_run_recipe returned that result.`
10144
10157
  POSITIVE = (value2) => Number.isFinite(value2) && Number(value2) > 0 ? Number(value2) : void 0;
10145
10158
  digestRuntimeValue = (value2) => `sha256:${(0, import_crypto4.createHash)("sha256").update(value2).digest("hex")}`;
10146
10159
  runtimeErrorMessage = (value2) => value2 instanceof Error ? value2.message : String(value2);
10147
- CodePiRuntimeEngine = class {
10160
+ TheseusRuntimeEngine = class {
10148
10161
  constructor(options) {
10149
10162
  this.options = options;
10150
10163
  this.#attempt = options.runAgentAttempt ?? runCodeAgentAttempt;
@@ -10230,7 +10243,7 @@ Never claim a build or test passed unless odla_run_recipe returned that result.`
10230
10243
  await this.#failure(command, active, detail);
10231
10244
  return null;
10232
10245
  });
10233
- return { status: "running", message: resume ? "Pi resumed from a portable checkpoint" : "Pi started" };
10246
+ return { status: "running", message: resume ? "Theseus resumed from a portable checkpoint" : "Theseus started" };
10234
10247
  }
10235
10248
  /**
10236
10249
  * Pursue a goal: attempt, judge with the clean verifier, re-prompt from what
@@ -10318,7 +10331,7 @@ Never claim a build or test passed unless odla_run_recipe returned that result.`
10318
10331
  await this.#failure(command, active, detail);
10319
10332
  return null;
10320
10333
  });
10321
- return { status: "running", message: "Pi accepted the owner prompt" };
10334
+ return { status: "running", message: "Theseus accepted the owner prompt" };
10322
10335
  }
10323
10336
  async #runAttempt(command, metadata2, active) {
10324
10337
  const lease = fakeCodeLease(command, metadata2);
@@ -10343,7 +10356,8 @@ Never claim a build or test passed unless odla_run_recipe returned that result.`
10343
10356
  lease,
10344
10357
  workspaceDir: active.workspace.workspaceDir,
10345
10358
  prompt: metadata2.prompt,
10346
- signal: active.abort.signal
10359
+ signal: active.abort.signal,
10360
+ recipeIds: this.options.recipes.map((recipe2) => recipe2.id)
10347
10361
  });
10348
10362
  const closing = result.finalText.trim();
10349
10363
  const completed = result.status === "completed" && Boolean(closing);
@@ -10407,7 +10421,7 @@ Never claim a build or test passed unless odla_run_recipe returned that result.`
10407
10421
  }
10408
10422
  }
10409
10423
  async #diagnostic(command, active, value2) {
10410
- const detail = value2.trim().slice(0, 2e3) || "Pi runtime failed";
10424
+ const detail = value2.trim().slice(0, 2e3) || "Theseus runtime failed";
10411
10425
  this.options.onDiagnostic?.(detail);
10412
10426
  await this.#event(
10413
10427
  command,
@@ -10428,7 +10442,7 @@ var init_node = __esm({
10428
10442
  "../harness/dist/node.js"() {
10429
10443
  "use strict";
10430
10444
  init_cjs_shims();
10431
- init_chunk_5HX5LWTG();
10445
+ init_chunk_QZXCQSPZ();
10432
10446
  init_chunk_K76I2TCQ();
10433
10447
  MEASURED_PREMIUM = Object.freeze({
10434
10448
  /** 3 racers vs pure depth at equal budget: 21,044 / 7,936. */
@@ -10709,8 +10723,9 @@ async function codeConnect(options) {
10709
10723
  const appId = requestedAppId ?? cfg?.app.id;
10710
10724
  const platform = (options.platform ?? cfg?.platformUrl ?? process.env.ODLA_PLATFORM_URL ?? "https://odla.ai").replace(/\/+$/, "");
10711
10725
  const appEnv = options.env ?? (cfg ? cfg.envs.includes("dev") ? "dev" : cfg.envs[0] : void 0);
10712
- if (appEnv !== "dev" && appEnv !== "prod" || cfg && !cfg.envs.includes(appEnv)) {
10713
- throw new Error(cfg ? `Code env "${appEnv ?? ""}" must be dev or prod and declared in ${options.configPath}` : `Code env "${appEnv ?? ""}" must be dev or prod; pass --env explicitly when there is no ${options.configPath}`);
10726
+ const explicitEnv = options.env !== void 0;
10727
+ if (appEnv !== "dev" && appEnv !== "prod" || !explicitEnv && cfg && !cfg.envs.includes(appEnv)) {
10728
+ throw new Error(cfg ? `Code env "${appEnv ?? ""}" must be dev or prod and declared in ${options.configPath}, unless dev or prod is passed explicitly` : `Code env "${appEnv ?? ""}" must be dev or prod; pass --env explicitly when there is no ${options.configPath}`);
10714
10729
  }
10715
10730
  if (process.platform !== "darwin" && process.platform !== "linux") {
10716
10731
  throw new Error("odla Code hosts require macOS or Linux");
@@ -10807,16 +10822,15 @@ async function runCodeRuntime(input) {
10807
10822
  const control = createCodeRuntimeControlClient({
10808
10823
  endpoint: input.endpoint,
10809
10824
  token: input.token,
10810
- signal,
10811
10825
  fetch: input.fetch
10812
10826
  });
10813
- const commandEngine = new CodePiRuntimeEngine({
10827
+ const commandEngine = new TheseusRuntimeEngine({
10814
10828
  control,
10815
10829
  engine: input.engine,
10816
10830
  recipes: CODE_BUILD_RECIPES,
10817
10831
  recipeAuthorization: "registered_recipe",
10818
10832
  localSource: input.localSource,
10819
- onDiagnostic: (message2) => input.stdout.error(`Pi runtime failed \xB7 ${message2}`)
10833
+ onDiagnostic: (message2) => input.stdout.error(`Theseus runtime failed \xB7 ${message2}`)
10820
10834
  });
10821
10835
  const reconciler = new CodeRuntimeReconciler(control, commandEngine);
10822
10836
  try {
@@ -11654,7 +11668,7 @@ Commands:
11654
11668
  their own credentials for the shared db (the live one included)
11655
11669
  \u2014 no secret is ever copied between people.
11656
11670
  capabilities Show what the CLI automates vs agent edits and human checkpoints.
11657
- code Enroll this Mac/Linux host for the current Studio-connected repository and run Pi.
11671
+ code Enroll this Mac/Linux host for the current Studio-connected repository and run Theseus.
11658
11672
  "code repository show" reports the repository an app works on (Studio or a
11659
11673
  human session connects one); "code grant request|list|approve|revoke" then
11660
11674
  governs unattended access: an agent may request, only a human may approve.
@@ -11670,12 +11684,10 @@ Commands:
11670
11684
  explicitly. Same device-grant auth as "app".
11671
11685
  Status changes and comments post to each item's @odla-ai/chat
11672
11686
  discussion thread.
11673
- NOTE: "--column ready" is OWNER-ONLY. Creating a task in Ready
11674
- approves its complete execution contract, so it needs pm.plan,
11675
- which no device enrollment or handshake approval can grant. An
11676
- agent proposes in Backlog (the default); a human owner or a
11677
- pm.plan agent promotes. This is deliberate, not a permission
11678
- gap \u2014 it was reported as one.
11687
+ Creating or promoting a task in Ready requires a complete
11688
+ execution contract and a reviewed revision. Any caller with PM
11689
+ mutation access to that app/project may do it; claims coordinate
11690
+ execution but never own or lock the PM record.
11679
11691
  bug Intent-first alias for PM bugs. "bug report" writes to
11680
11692
  odla PM; odla product defects do not belong in GitHub Issues.
11681
11693
  discuss Group discussions (via @odla-ai/chat) for the apps you co-own: