@odla-ai/cli 0.46.8 → 0.46.10

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.cjs CHANGED
@@ -8236,7 +8236,7 @@ var init_code2 = __esm({
8236
8236
  }
8237
8237
  });
8238
8238
 
8239
- // ../harness/dist/chunk-IWVGSWY6.js
8239
+ // ../harness/dist/chunk-NG7AYYH3.js
8240
8240
  async function digestStagedWorkspace(root, limits) {
8241
8241
  const files = [];
8242
8242
  const walk = async (directory) => {
@@ -8263,45 +8263,6 @@ async function digestStagedWorkspace(root, limits) {
8263
8263
  }
8264
8264
  return `sha256:${hash.digest("hex")}`;
8265
8265
  }
8266
- async function runCodeRuntimeHeartbeatLoop(options) {
8267
- const heartbeatMs = options.heartbeatMs ?? 15e3;
8268
- if (!Number.isSafeInteger(heartbeatMs) || heartbeatMs < 1e3 || heartbeatMs > 3e5) {
8269
- throw new TypeError("heartbeatMs must be an integer from 1000 to 300000");
8270
- }
8271
- let retryMs = 1e3;
8272
- do {
8273
- if (options.signal?.aborted) return;
8274
- try {
8275
- const snapshot = await options.control.heartbeat(options.runtimeVersion, options.capabilities);
8276
- await options.onSnapshot?.(snapshot);
8277
- retryMs = 1e3;
8278
- if (options.once) return;
8279
- await wait(heartbeatMs, options.signal);
8280
- } catch (error) {
8281
- if (options.signal?.aborted) return;
8282
- if (options.once || !retryableControlFailure(error)) throw error;
8283
- await options.onRetry?.(error, retryMs);
8284
- await wait(retryMs, options.signal);
8285
- retryMs = Math.min(retryMs * 2, 3e4);
8286
- }
8287
- } while (!options.signal?.aborted);
8288
- }
8289
- function retryableControlFailure(value2) {
8290
- if (!value2 || typeof value2 !== "object") return false;
8291
- const failure = value2;
8292
- if (failure.code === "invalid_response" || typeof failure.status !== "number") return false;
8293
- return failure.status === 408 || failure.status === 425 || failure.status === 429 || failure.status >= 500;
8294
- }
8295
- function wait(ms, signal) {
8296
- return new Promise((resolve52) => {
8297
- if (signal?.aborted) return resolve52();
8298
- const timer = setTimeout(resolve52, ms);
8299
- signal?.addEventListener("abort", () => {
8300
- clearTimeout(timer);
8301
- resolve52();
8302
- }, { once: true });
8303
- });
8304
- }
8305
8266
  function createCodeRuntimeControlClient(options) {
8306
8267
  const endpoint = validatedEndpoint(options.endpoint);
8307
8268
  if (!/^odla_code_host_[0-9a-f]{64}$/.test(options.token)) throw new TypeError("invalid Code host credential");
@@ -8314,9 +8275,10 @@ function createCodeRuntimeControlClient(options) {
8314
8275
  throw new TypeError("modelRequestTimeoutMs must be an integer from 30000 to 1800000");
8315
8276
  }
8316
8277
  const request3 = options.fetch ?? fetch;
8317
- const call4 = async (path, body, timeoutMs = requestTimeoutMs) => {
8278
+ const call4 = async (path, body, timeoutMs = requestTimeoutMs, operationSignal) => {
8318
8279
  const timeout = AbortSignal.timeout(timeoutMs);
8319
- const signal = options.signal ? AbortSignal.any([options.signal, timeout]) : timeout;
8280
+ const signals = [options.signal, operationSignal, timeout].filter((item) => Boolean(item));
8281
+ const signal = signals.length === 1 ? signals[0] : AbortSignal.any(signals);
8320
8282
  let response2;
8321
8283
  try {
8322
8284
  response2 = await request3(`${endpoint}${path}`, {
@@ -8327,7 +8289,7 @@ function createCodeRuntimeControlClient(options) {
8327
8289
  signal
8328
8290
  });
8329
8291
  } catch (cause) {
8330
- if (options.signal?.aborted) throw cause;
8292
+ if (options.signal?.aborted || operationSignal?.aborted) throw cause;
8331
8293
  throw new CodeRuntimeControlError("Code runtime control plane is unavailable", 503, "transport_unavailable");
8332
8294
  }
8333
8295
  const value2 = await response2.json().catch(() => null);
@@ -8347,8 +8309,7 @@ function createCodeRuntimeControlClient(options) {
8347
8309
  return parseSnapshot(await call4("/registry/code/runtime/heartbeat", { runtimeVersion: version, capabilities }));
8348
8310
  },
8349
8311
  acknowledge: async (commandId, result) => {
8350
- if (!/^ccmd_[0-9a-f]{32}$/.test(commandId)) throw new TypeError("invalid Code runtime command id");
8351
- await call4(`/registry/code/runtime/commands/${commandId}/ack`, result);
8312
+ await call4(`/registry/code/runtime/commands/${validCommandId(commandId)}/ack`, result);
8352
8313
  },
8353
8314
  source: async (sessionId) => parseSource(
8354
8315
  await call4(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/source`, {})
@@ -8391,12 +8352,71 @@ function createCodeRuntimeControlClient(options) {
8391
8352
  rememberMemory: async (sessionId, memory) => {
8392
8353
  await call4(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/remember`, memory);
8393
8354
  },
8355
+ collaborationSkills: async (sessionId, commandId) => {
8356
+ try {
8357
+ return parseCollaborationSkills(await call4(
8358
+ `/registry/code/runtime/sessions/${validSessionId(sessionId)}/collaboration/skills`,
8359
+ { commandId: validCommandId(commandId) }
8360
+ ));
8361
+ } catch (cause) {
8362
+ if (cause instanceof CodeRuntimeControlError && cause.status === 404 && cause.code === "not_found") return [];
8363
+ throw cause;
8364
+ }
8365
+ },
8366
+ executeCollaborationTool: async (sessionId, collaboration, signal) => {
8367
+ validateCollaborationToolRequest(collaboration);
8368
+ return parseCollaborationToolOutput(await call4(
8369
+ `/registry/code/runtime/sessions/${validSessionId(sessionId)}/collaboration/tools`,
8370
+ collaboration,
8371
+ requestTimeoutMs,
8372
+ signal
8373
+ ));
8374
+ },
8394
8375
  reportSessionFailure: async (sessionId, message2) => {
8395
8376
  if (!message2.trim() || message2.length > 2e3) throw new TypeError("invalid Code session failure");
8396
8377
  await call4(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/failure`, { message: message2 });
8397
8378
  }
8398
8379
  };
8399
8380
  }
8381
+ async function runCodeRuntimeHeartbeatLoop(options) {
8382
+ const heartbeatMs = options.heartbeatMs ?? 15e3;
8383
+ if (!Number.isSafeInteger(heartbeatMs) || heartbeatMs < 1e3 || heartbeatMs > 3e5) {
8384
+ throw new TypeError("heartbeatMs must be an integer from 1000 to 300000");
8385
+ }
8386
+ let retryMs = 1e3;
8387
+ do {
8388
+ if (options.signal?.aborted) return;
8389
+ try {
8390
+ const snapshot = await options.control.heartbeat(options.runtimeVersion, options.capabilities);
8391
+ await options.onSnapshot?.(snapshot);
8392
+ retryMs = 1e3;
8393
+ if (options.once) return;
8394
+ await wait(heartbeatMs, options.signal);
8395
+ } catch (error) {
8396
+ if (options.signal?.aborted) return;
8397
+ if (options.once || !retryableControlFailure(error)) throw error;
8398
+ await options.onRetry?.(error, retryMs);
8399
+ await wait(retryMs, options.signal);
8400
+ retryMs = Math.min(retryMs * 2, 3e4);
8401
+ }
8402
+ } while (!options.signal?.aborted);
8403
+ }
8404
+ function retryableControlFailure(value2) {
8405
+ if (!value2 || typeof value2 !== "object") return false;
8406
+ const failure = value2;
8407
+ if (failure.code === "invalid_response" || typeof failure.status !== "number") return false;
8408
+ return failure.status === 408 || failure.status === 425 || failure.status === 429 || failure.status >= 500;
8409
+ }
8410
+ function wait(ms, signal) {
8411
+ return new Promise((resolve52) => {
8412
+ if (signal?.aborted) return resolve52();
8413
+ const timer = setTimeout(resolve52, ms);
8414
+ signal?.addEventListener("abort", () => {
8415
+ clearTimeout(timer);
8416
+ resolve52();
8417
+ }, { once: true });
8418
+ });
8419
+ }
8400
8420
  function validatedEndpoint(value2) {
8401
8421
  const endpoint = value2.replace(/\/+$/, "");
8402
8422
  let url;
@@ -8415,6 +8435,10 @@ function validSessionId(value2) {
8415
8435
  if (!/^csess_[0-9a-f]{32}$/.test(value2)) throw new TypeError("invalid Code session id");
8416
8436
  return value2;
8417
8437
  }
8438
+ function validCommandId(value2) {
8439
+ if (!/^ccmd_[0-9a-f]{32}$/.test(value2)) throw new TypeError("invalid Code runtime command id");
8440
+ return value2;
8441
+ }
8418
8442
  function validateHeartbeat(version, capabilities) {
8419
8443
  if (!version.trim() || version.length > 80) throw new TypeError("runtimeVersion is required and at most 80 characters");
8420
8444
  if (capabilities.protocolVersion !== CODE_RUNTIME_PROTOCOL_VERSION) throw new TypeError("unsupported Code runtime protocol version");
@@ -8496,6 +8520,91 @@ function parseCandidate(value2) {
8496
8520
  }
8497
8521
  return { candidateId: candidate.candidateId, status: candidate.status };
8498
8522
  }
8523
+ function parseCollaborationSkills(value2) {
8524
+ const items = record5(value2)?.skills;
8525
+ if (!Array.isArray(items) || items.length > 16) throw invalid("collaboration skills");
8526
+ const skillNames2 = /* @__PURE__ */ new Set();
8527
+ const toolNames = /* @__PURE__ */ new Set();
8528
+ return items.map((item) => {
8529
+ const skill = record5(item);
8530
+ if (!skill || !validManifestName(skill.name) || skillNames2.has(skill.name) || skill.instructions !== void 0 && (typeof skill.instructions !== "string" || utf8Bytes(skill.instructions) > 32e3) || !Array.isArray(skill.tools) || !skill.tools.length || skill.tools.length > 128) {
8531
+ throw invalid("collaboration skill");
8532
+ }
8533
+ skillNames2.add(skill.name);
8534
+ const tools = skill.tools.map((candidate) => {
8535
+ const tool = record5(candidate);
8536
+ const inputSchema = record5(tool?.inputSchema);
8537
+ if (!tool || !validManifestName(tool.name) || toolNames.has(tool.name) || typeof tool.description !== "string" || utf8Bytes(tool.description) > 8e3 || !inputSchema || jsonBytes(inputSchema) > 64e3 || tool.concurrency !== void 0 && tool.concurrency !== "parallel") {
8538
+ throw invalid("collaboration tool");
8539
+ }
8540
+ const outputTaint = parseTaintLabels(tool.outputTaint);
8541
+ const acceptsTaint = parseTaintLabels(tool.acceptsTaint);
8542
+ toolNames.add(tool.name);
8543
+ return {
8544
+ name: tool.name,
8545
+ description: tool.description,
8546
+ inputSchema,
8547
+ ...tool.concurrency === "parallel" ? { concurrency: "parallel" } : {},
8548
+ ...outputTaint ? { outputTaint } : {},
8549
+ ...acceptsTaint ? { acceptsTaint } : {}
8550
+ };
8551
+ });
8552
+ return {
8553
+ name: skill.name,
8554
+ ...typeof skill.instructions === "string" ? { instructions: skill.instructions } : {},
8555
+ tools
8556
+ };
8557
+ });
8558
+ }
8559
+ function validateCollaborationToolRequest(value2) {
8560
+ validCommandId(value2.commandId);
8561
+ if (typeof value2.toolCallId !== "string" || value2.toolCallId.length > 256 || !/^[^\s\u0000-\u001f\u007f]+$/.test(value2.toolCallId) || !validManifestName(value2.skill) || !validManifestName(value2.tool) || !record5(value2.input) || jsonBytes(value2.input) > 128e3) {
8562
+ throw new TypeError("invalid Code collaboration tool request");
8563
+ }
8564
+ }
8565
+ function parseCollaborationToolOutput(value2) {
8566
+ const output = record5(record5(value2)?.output);
8567
+ if (!output || output.isError !== void 0 && typeof output.isError !== "boolean") {
8568
+ throw invalid("collaboration tool");
8569
+ }
8570
+ if (typeof output.content === "string") {
8571
+ if (utf8Bytes(output.content) > 1e6) throw invalid("collaboration tool");
8572
+ return { content: output.content, ...output.isError === true ? { isError: true } : {} };
8573
+ }
8574
+ if (!Array.isArray(output.content) || output.content.length > 64 || jsonBytes(output.content) > 1e6 || !output.content.every((block2) => {
8575
+ const item = record5(block2);
8576
+ return item && ["text", "image", "audio", "document", "tool_use", "tool_result", "thinking"].includes(String(item.type));
8577
+ })) throw invalid("collaboration tool");
8578
+ return {
8579
+ content: output.content,
8580
+ ...output.isError === true ? { isError: true } : {}
8581
+ };
8582
+ }
8583
+ function parseTaintLabels(value2) {
8584
+ if (value2 === void 0) return void 0;
8585
+ if (!Array.isArray(value2) || value2.length > 16) throw invalid("collaboration tool taint");
8586
+ const labels = value2.map((item) => {
8587
+ if (item === "web_untrusted" || item === "operator_pasted_untrusted" || item === "llm_inherited") return item;
8588
+ if (typeof item === "string" && /^tool_untrusted:[^\s\u0000-\u001f\u007f]{1,100}$/.test(item)) {
8589
+ return item;
8590
+ }
8591
+ throw invalid("collaboration tool taint");
8592
+ });
8593
+ return [...new Set(labels)];
8594
+ }
8595
+ function validManifestName(value2) {
8596
+ return typeof value2 === "string" && /^[A-Za-z][A-Za-z0-9._:-]{0,127}$/.test(value2);
8597
+ }
8598
+ function utf8Bytes(value2) {
8599
+ return new TextEncoder().encode(value2).byteLength;
8600
+ }
8601
+ function jsonBytes(value2) {
8602
+ try {
8603
+ return utf8Bytes(JSON.stringify(value2));
8604
+ } catch {
8605
+ return Number.POSITIVE_INFINITY;
8606
+ }
8607
+ }
8499
8608
  function stripPatchEnvelope(patch2) {
8500
8609
  if (!/^\*\*\* (?:Begin|End) Patch\s*$/m.test(patch2)) return patch2;
8501
8610
  const kept = patch2.split("\n").filter((line2) => !/^\*\*\* (?:Begin|End) Patch\s*$/.test(line2));
@@ -9401,6 +9510,46 @@ Finish with a concise, non-empty answer to the owner. Do not call tools or promi
9401
9510
  return { status: "failed", finalText: "", error };
9402
9511
  }
9403
9512
  }
9513
+ function createCodeRuntimeSessionSkillLoader(control) {
9514
+ const load = control.collaborationSkills?.bind(control);
9515
+ const execute2 = control.executeCollaborationTool?.bind(control);
9516
+ if (!load || !execute2) return async () => [];
9517
+ return async (command) => {
9518
+ const manifests = await load(command.sessionId, command.commandId);
9519
+ return manifests.map((manifest) => ({
9520
+ name: manifest.name,
9521
+ ...manifest.instructions === void 0 ? {} : { instructions: manifest.instructions },
9522
+ tools: manifest.tools.map((tool) => ({
9523
+ name: tool.name,
9524
+ description: tool.description,
9525
+ inputSchema: tool.inputSchema,
9526
+ ...tool.concurrency === void 0 ? {} : { concurrency: tool.concurrency },
9527
+ ...tool.outputTaint === void 0 ? {} : { outputTaint: tool.outputTaint },
9528
+ ...tool.acceptsTaint === void 0 ? {} : { acceptsTaint: tool.acceptsTaint },
9529
+ handler: async (input, context) => {
9530
+ if (!context.toolCallId) throw new TypeError("collaboration tool call identity is required");
9531
+ return execute2(command.sessionId, {
9532
+ commandId: command.commandId,
9533
+ toolCallId: context.toolCallId,
9534
+ skill: manifest.name,
9535
+ tool: tool.name,
9536
+ input
9537
+ }, context.signal);
9538
+ }
9539
+ }))
9540
+ }));
9541
+ };
9542
+ }
9543
+ async function sessionSkillsFor(options, command) {
9544
+ try {
9545
+ return await options.sessionSkills?.(command) ?? [];
9546
+ } catch (cause) {
9547
+ options.onDiagnostic?.(
9548
+ `session skills unavailable, continuing with code tools only: ${cause instanceof Error ? cause.message : String(cause)}`
9549
+ );
9550
+ return [];
9551
+ }
9552
+ }
9404
9553
  async function handleCodeRuntimeInference(input) {
9405
9554
  const { command, request: request3, state: state2 } = input;
9406
9555
  const startedAt = Date.now();
@@ -10211,16 +10360,6 @@ function assertBudget(budget) {
10211
10360
  throw new TypeError("goal budget deadline must be epoch milliseconds");
10212
10361
  }
10213
10362
  }
10214
- async function sessionSkillsFor(options, command) {
10215
- try {
10216
- return await options.sessionSkills?.(command) ?? [];
10217
- } catch (cause) {
10218
- options.onDiagnostic?.(
10219
- `session skills unavailable, continuing with code tools only: ${cause instanceof Error ? cause.message : String(cause)}`
10220
- );
10221
- return [];
10222
- }
10223
- }
10224
10363
  function createCodeRuntimeToolBroker(input, lease, role) {
10225
10364
  const broker = createCodeToolBroker({
10226
10365
  recipes: input.recipes,
@@ -10484,9 +10623,26 @@ function codeToolResultPresentation(request3, response2) {
10484
10623
  ...excerpt(output, true) ? { excerpt: excerpt(output, true) } : {}
10485
10624
  };
10486
10625
  }
10626
+ function codeRuntimeAcknowledgementGate(signal) {
10627
+ let settle;
10628
+ let settled = false;
10629
+ const ready = new Promise((resolve52) => {
10630
+ settle = resolve52;
10631
+ });
10632
+ const release = (run) => {
10633
+ if (settled) return;
10634
+ settled = true;
10635
+ signal.removeEventListener("abort", onAbort);
10636
+ settle(run);
10637
+ };
10638
+ const onAbort = () => release(false);
10639
+ if (signal.aborted) release(false);
10640
+ else signal.addEventListener("abort", onAbort, { once: true });
10641
+ return { ready, release };
10642
+ }
10487
10643
  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_child_process6, 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, MAX_NATIVE_ARG_BYTES, DESTINATIONS, READ, LIST, SEARCH, GRAPH, PATCH, RECIPE, cache, shortId, GRAPH_TOOLS, MAX_MEMORY_BODY, POSITIVE, digestRuntimeValue, runtimeErrorMessage, text3, integer2, record32, excerpt, paths, TheseusRuntimeEngine;
10488
- var init_chunk_IWVGSWY6 = __esm({
10489
- "../harness/dist/chunk-IWVGSWY6.js"() {
10644
+ var init_chunk_NG7AYYH3 = __esm({
10645
+ "../harness/dist/chunk-NG7AYYH3.js"() {
10490
10646
  "use strict";
10491
10647
  init_cjs_shims();
10492
10648
  init_chunk_CR6RE3A2();
@@ -10782,6 +10938,8 @@ Never claim a build or test passed unless odla_run_recipe returned that result.`
10782
10938
  const active = this.#active.get(command.sessionId);
10783
10939
  if (!active || result.status !== "running") return;
10784
10940
  active.acknowledged = true;
10941
+ active.startGate?.release(true);
10942
+ active.startGate = void 0;
10785
10943
  if (active.failure) await this.options.control.reportSessionFailure(command.sessionId, active.failure).catch(() => void 0);
10786
10944
  }
10787
10945
  async close() {
@@ -10801,13 +10959,14 @@ Never claim a build or test passed unless odla_run_recipe returned that result.`
10801
10959
  control: this.options.control,
10802
10960
  ...this.options.localSource ? { localSource: this.options.localSource } : {}
10803
10961
  });
10804
- const abort = new AbortController();
10962
+ const abort = new AbortController(), startGate = codeRuntimeAcknowledgementGate(abort.signal);
10805
10963
  const conversationRefs = [];
10806
10964
  const active = {
10807
10965
  workspace,
10808
10966
  abort,
10809
10967
  conversationRefs,
10810
10968
  acknowledged: false,
10969
+ startGate,
10811
10970
  role: metadata2.role,
10812
10971
  title: metadata2.title,
10813
10972
  maxTokensPerInteraction: metadata2.maxTokensPerInteraction,
@@ -10831,7 +10990,7 @@ Never claim a build or test passed unless odla_run_recipe returned that result.`
10831
10990
  body: `Source snapshot: local checkout ${requestedLocal.snapshotDigest} \xB7 ${requestedLocal.modified ? "modified" : "clean"} \xB7 Git ${requestedLocal.headCommitSha}`
10832
10991
  }, conversationRefs);
10833
10992
  }
10834
- active.done = this.#runAttempt(command, metadata2, active).catch(async (cause) => {
10993
+ active.done = startGate.ready.then((run) => run ? this.#runAttempt(command, metadata2, active) : null).catch(async (cause) => {
10835
10994
  const detail = runtimeErrorMessage(cause);
10836
10995
  await this.#event(command, { type: "message", actor: "system", body: detail }, conversationRefs).catch(() => void 0);
10837
10996
  await this.#diagnostic(command, active, detail);
@@ -11051,7 +11210,7 @@ var init_node = __esm({
11051
11210
  "../harness/dist/node.js"() {
11052
11211
  "use strict";
11053
11212
  init_cjs_shims();
11054
- init_chunk_IWVGSWY6();
11213
+ init_chunk_NG7AYYH3();
11055
11214
  init_chunk_CR6RE3A2();
11056
11215
  MEASURED_PREMIUM = Object.freeze({
11057
11216
  /** 3 racers vs pure depth at equal budget: 21,044 / 7,936. */
@@ -11438,6 +11597,7 @@ async function runCodeRuntime(input) {
11438
11597
  engine: input.engine,
11439
11598
  recipes: CODE_BUILD_RECIPES,
11440
11599
  recipeAuthorization: "registered_recipe",
11600
+ sessionSkills: createCodeRuntimeSessionSkillLoader(control),
11441
11601
  localSource: input.localSource,
11442
11602
  onDiagnostic: (message2) => input.stdout.error(`Theseus runtime failed \xB7 ${message2}`)
11443
11603
  });