@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/README.md +2 -2
- package/dist/bin.cjs +114 -32
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-FRDIQURT.js → chunk-YWC7F5T3.js} +115 -33
- package/dist/chunk-YWC7F5T3.js.map +1 -0
- package/dist/index.cjs +114 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/skills/odla-migrate/references/phase-2-db.md +2 -2
- package/dist/chunk-FRDIQURT.js.map +0 -1
package/README.md
CHANGED
|
@@ -29,8 +29,8 @@ For a project you keep working in, install it as a dev dependency so the
|
|
|
29
29
|
shorter `npx odla-ai` form works and the version is pinned by your lockfile:
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
npm view @odla-ai/cli@0.16.
|
|
33
|
-
npm i -D --save-exact @odla-ai/cli@0.16.
|
|
32
|
+
npm view @odla-ai/cli@0.16.3 version
|
|
33
|
+
npm i -D --save-exact @odla-ai/cli@0.16.3
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
## Prerequisites
|
package/dist/bin.cjs
CHANGED
|
@@ -1942,10 +1942,10 @@ var import_node_fs7 = require("fs");
|
|
|
1942
1942
|
var import_node_os = require("os");
|
|
1943
1943
|
var import_node_path4 = require("path");
|
|
1944
1944
|
|
|
1945
|
-
// ../harness/dist/chunk-
|
|
1945
|
+
// ../harness/dist/chunk-QTUEF2HZ.js
|
|
1946
1946
|
var HARNESS_PROTOCOL_VERSION = 1;
|
|
1947
1947
|
|
|
1948
|
-
// ../harness/dist/chunk-
|
|
1948
|
+
// ../harness/dist/chunk-GE6CCN7W.js
|
|
1949
1949
|
var CONTROL = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/;
|
|
1950
1950
|
var HarnessProtocolError = class extends Error {
|
|
1951
1951
|
name = "HarnessProtocolError";
|
|
@@ -2023,7 +2023,7 @@ function encodeAgentInput(message2) {
|
|
|
2023
2023
|
`;
|
|
2024
2024
|
}
|
|
2025
2025
|
|
|
2026
|
-
// ../harness/dist/chunk-
|
|
2026
|
+
// ../harness/dist/chunk-IRFCMVKU.js
|
|
2027
2027
|
var import_child_process = require("child_process");
|
|
2028
2028
|
var import_fs = require("fs");
|
|
2029
2029
|
var import_promises2 = require("fs/promises");
|
|
@@ -2540,7 +2540,7 @@ async function stageWorkspacePair(baselineSource, workspaceSource, options = {})
|
|
|
2540
2540
|
}
|
|
2541
2541
|
}
|
|
2542
2542
|
|
|
2543
|
-
// ../harness/dist/chunk-
|
|
2543
|
+
// ../harness/dist/chunk-4MOSEKB6.js
|
|
2544
2544
|
var import_crypto = require("crypto");
|
|
2545
2545
|
var import_promises5 = require("fs/promises");
|
|
2546
2546
|
var import_path5 = require("path");
|
|
@@ -2877,7 +2877,7 @@ function validateSnapshot(snapshot, limits) {
|
|
|
2877
2877
|
}
|
|
2878
2878
|
}
|
|
2879
2879
|
|
|
2880
|
-
// ../harness/dist/chunk-
|
|
2880
|
+
// ../harness/dist/chunk-4MOSEKB6.js
|
|
2881
2881
|
var import_child_process4 = require("child_process");
|
|
2882
2882
|
var import_promises6 = require("fs/promises");
|
|
2883
2883
|
var import_path6 = require("path");
|
|
@@ -3170,7 +3170,7 @@ function looksLikeDestination(value) {
|
|
|
3170
3170
|
return /^(?:[a-z][a-z0-9+.-]*:\/\/|\/|\\\\)/i.test(text) || /^[\w.-]+\.[a-z]{2,}(?:[/:]|$)/i.test(text);
|
|
3171
3171
|
}
|
|
3172
3172
|
|
|
3173
|
-
// ../harness/dist/chunk-
|
|
3173
|
+
// ../harness/dist/chunk-4MOSEKB6.js
|
|
3174
3174
|
var import_crypto4 = require("crypto");
|
|
3175
3175
|
async function digestStagedWorkspace(root, limits) {
|
|
3176
3176
|
const files = [];
|
|
@@ -4361,6 +4361,7 @@ function codeCommandMetadata(payload, resume) {
|
|
|
4361
4361
|
const role = payload.role;
|
|
4362
4362
|
const title = payload.title;
|
|
4363
4363
|
const prompt = payload.prompt;
|
|
4364
|
+
const maxTokensPerInteraction = payload.maxTokensPerInteraction ?? 32e3;
|
|
4364
4365
|
if (role !== "coding" && role !== "review" || typeof title !== "string" || typeof prompt !== "string") {
|
|
4365
4366
|
throw new TypeError(`invalid Code ${resume ? "resume" : "start"} metadata`);
|
|
4366
4367
|
}
|
|
@@ -4372,10 +4373,14 @@ function codeCommandMetadata(payload, resume) {
|
|
|
4372
4373
|
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)) {
|
|
4373
4374
|
throw new TypeError(`invalid Code ${resume ? "resume" : "start"} trusted base`);
|
|
4374
4375
|
}
|
|
4376
|
+
if (!Number.isSafeInteger(maxTokensPerInteraction) || Number(maxTokensPerInteraction) < 4e3 || Number(maxTokensPerInteraction) > 2e5) {
|
|
4377
|
+
throw new TypeError(`invalid Code ${resume ? "resume" : "start"} interaction token limit`);
|
|
4378
|
+
}
|
|
4375
4379
|
return {
|
|
4376
4380
|
role,
|
|
4377
4381
|
title,
|
|
4378
4382
|
prompt,
|
|
4383
|
+
maxTokensPerInteraction: Number(maxTokensPerInteraction),
|
|
4379
4384
|
planningInputDigest: typeof planning === "string" && /^sha256:[0-9a-f]{64}$/.test(planning) ? planning : null,
|
|
4380
4385
|
attestationDigest: typeof attestation === "string" ? attestation : "resume",
|
|
4381
4386
|
repository,
|
|
@@ -4451,6 +4456,57 @@ function createCodeRuntimeToolBroker(input, lease, role) {
|
|
|
4451
4456
|
});
|
|
4452
4457
|
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" }) };
|
|
4453
4458
|
}
|
|
4459
|
+
async function handleCodeRuntimeInference(input) {
|
|
4460
|
+
const { command, metadata: metadata2, request, state } = input;
|
|
4461
|
+
if (state.tokens >= metadata2.maxTokensPerInteraction) {
|
|
4462
|
+
if (!state.noticeEmitted) {
|
|
4463
|
+
state.noticeEmitted = true;
|
|
4464
|
+
await input.event({
|
|
4465
|
+
type: "message",
|
|
4466
|
+
actor: "system",
|
|
4467
|
+
body: `Pi paused at the ${metadata2.maxTokensPerInteraction.toLocaleString("en-US")}-token per-interaction limit. Send a new instruction to continue.`
|
|
4468
|
+
}).catch(() => void 0);
|
|
4469
|
+
}
|
|
4470
|
+
return {
|
|
4471
|
+
protocolVersion: HARNESS_PROTOCOL_VERSION,
|
|
4472
|
+
type: "inference.response",
|
|
4473
|
+
requestId: request.requestId,
|
|
4474
|
+
response: {
|
|
4475
|
+
id: `budget:${command.commandId}`,
|
|
4476
|
+
provider: "openai",
|
|
4477
|
+
model: "interaction-budget",
|
|
4478
|
+
role: "assistant",
|
|
4479
|
+
content: [{ type: "text", text: "Pause now. The owner-set token limit for this interaction has been reached." }],
|
|
4480
|
+
stopReason: "end_turn",
|
|
4481
|
+
usage: { inputTokens: 0, outputTokens: 0 }
|
|
4482
|
+
}
|
|
4483
|
+
};
|
|
4484
|
+
}
|
|
4485
|
+
const startedAt = Date.now();
|
|
4486
|
+
const response2 = await input.control.infer(command.sessionId, {
|
|
4487
|
+
requestId: request.requestId,
|
|
4488
|
+
interactionId: command.commandId,
|
|
4489
|
+
call: request.call
|
|
4490
|
+
});
|
|
4491
|
+
state.tokens += response2.receipt.inputTokens + response2.receipt.outputTokens;
|
|
4492
|
+
await input.event({
|
|
4493
|
+
type: "usage",
|
|
4494
|
+
provider: response2.receipt.provider,
|
|
4495
|
+
model: response2.receipt.model,
|
|
4496
|
+
inputTokens: response2.receipt.inputTokens,
|
|
4497
|
+
outputTokens: response2.receipt.outputTokens,
|
|
4498
|
+
durationMs: Date.now() - startedAt,
|
|
4499
|
+
interactionId: command.commandId,
|
|
4500
|
+
interactionTokens: state.tokens,
|
|
4501
|
+
interactionMaxTokens: metadata2.maxTokensPerInteraction
|
|
4502
|
+
}).catch(() => void 0);
|
|
4503
|
+
return {
|
|
4504
|
+
protocolVersion: HARNESS_PROTOCOL_VERSION,
|
|
4505
|
+
type: "inference.response",
|
|
4506
|
+
requestId: request.requestId,
|
|
4507
|
+
response: response2.response
|
|
4508
|
+
};
|
|
4509
|
+
}
|
|
4454
4510
|
async function appendCodeRuntimeEvent(control, command, event, refs) {
|
|
4455
4511
|
const eventId = `${command.commandId.slice(0, 45)}:${refs.length + 1}`;
|
|
4456
4512
|
refs.push(eventId);
|
|
@@ -4469,7 +4525,13 @@ var safeRuntimeJson = (value) => {
|
|
|
4469
4525
|
};
|
|
4470
4526
|
function runtimeResultText(value) {
|
|
4471
4527
|
const record32 = runtimeRecord(value);
|
|
4472
|
-
|
|
4528
|
+
if (record32 && typeof record32.text === "string") return record32.text.slice(0, 2e4);
|
|
4529
|
+
if (record32 && typeof record32.error === "string") return `Pi failed: ${record32.error.slice(0, 19989)}`;
|
|
4530
|
+
return null;
|
|
4531
|
+
}
|
|
4532
|
+
function runtimeResultError(value) {
|
|
4533
|
+
const record32 = runtimeRecord(value);
|
|
4534
|
+
return record32 && typeof record32.error === "string" && record32.error.trim() ? record32.error.trim().slice(0, 2e3) : null;
|
|
4473
4535
|
}
|
|
4474
4536
|
var CodePiRuntimeEngine = class {
|
|
4475
4537
|
constructor(options) {
|
|
@@ -4556,6 +4618,7 @@ var CodePiRuntimeEngine = class {
|
|
|
4556
4618
|
acknowledged: false,
|
|
4557
4619
|
role: metadata2.role,
|
|
4558
4620
|
title: metadata2.title,
|
|
4621
|
+
maxTokensPerInteraction: metadata2.maxTokensPerInteraction,
|
|
4559
4622
|
baseCommitSha: metadata2.baseCommitSha,
|
|
4560
4623
|
repository: metadata2.repository,
|
|
4561
4624
|
sourceTreeDigest: metadata2.sourceTreeDigest,
|
|
@@ -4577,9 +4640,11 @@ var CodePiRuntimeEngine = class {
|
|
|
4577
4640
|
}, conversationRefs);
|
|
4578
4641
|
}
|
|
4579
4642
|
active.done = this.#runAttempt(command, metadata2, active).catch(async (cause) => {
|
|
4580
|
-
|
|
4643
|
+
const detail = runtimeErrorMessage(cause);
|
|
4644
|
+
await this.#event(command, { type: "message", actor: "system", body: `Pi failed: ${detail}` }, conversationRefs).catch(() => void 0);
|
|
4645
|
+
await this.#diagnostic(command, active, detail);
|
|
4581
4646
|
await this.#event(command, { type: "status", status: "failed" }, conversationRefs).catch(() => void 0);
|
|
4582
|
-
await this.#failure(command, active,
|
|
4647
|
+
await this.#failure(command, active, detail);
|
|
4583
4648
|
return null;
|
|
4584
4649
|
});
|
|
4585
4650
|
return { status: "running", message: resume ? "Pi resumed from a portable checkpoint" : "Pi started" };
|
|
@@ -4590,6 +4655,11 @@ var CodePiRuntimeEngine = class {
|
|
|
4590
4655
|
if (!active || typeof prompt !== "string" || !prompt.trim() || prompt.length > 2e4) {
|
|
4591
4656
|
throw new TypeError("prompt requires an active Code session and bounded text");
|
|
4592
4657
|
}
|
|
4658
|
+
const requestedLimit = command.payload.maxTokensPerInteraction ?? active.maxTokensPerInteraction;
|
|
4659
|
+
if (!Number.isSafeInteger(requestedLimit) || Number(requestedLimit) < 4e3 || Number(requestedLimit) > 2e5) {
|
|
4660
|
+
throw new TypeError("prompt requires a valid interaction token limit");
|
|
4661
|
+
}
|
|
4662
|
+
active.maxTokensPerInteraction = Number(requestedLimit);
|
|
4593
4663
|
await active.done;
|
|
4594
4664
|
active.abort = new AbortController();
|
|
4595
4665
|
active.acknowledged = false;
|
|
@@ -4598,19 +4668,22 @@ var CodePiRuntimeEngine = class {
|
|
|
4598
4668
|
role: active.role,
|
|
4599
4669
|
title: active.title,
|
|
4600
4670
|
prompt,
|
|
4671
|
+
maxTokensPerInteraction: active.maxTokensPerInteraction,
|
|
4601
4672
|
planningInputDigest: active.planningInputDigest,
|
|
4602
4673
|
attestationDigest: "follow-up",
|
|
4603
4674
|
repository: active.repository,
|
|
4604
4675
|
baseCommitSha: active.baseCommitSha,
|
|
4605
4676
|
sourceTreeDigest: active.sourceTreeDigest
|
|
4606
4677
|
}, active).catch(async (cause) => {
|
|
4678
|
+
const detail = runtimeErrorMessage(cause);
|
|
4607
4679
|
await this.#event(
|
|
4608
4680
|
command,
|
|
4609
|
-
{ type: "message", actor: "system", body: `Pi failed: ${
|
|
4681
|
+
{ type: "message", actor: "system", body: `Pi failed: ${detail}` },
|
|
4610
4682
|
active.conversationRefs
|
|
4611
4683
|
).catch(() => void 0);
|
|
4684
|
+
await this.#diagnostic(command, active, detail);
|
|
4612
4685
|
await this.#event(command, { type: "status", status: "failed" }, active.conversationRefs).catch(() => void 0);
|
|
4613
|
-
await this.#failure(command, active,
|
|
4686
|
+
await this.#failure(command, active, detail);
|
|
4614
4687
|
return null;
|
|
4615
4688
|
});
|
|
4616
4689
|
return { status: "running", message: "Pi accepted the owner prompt" };
|
|
@@ -4624,6 +4697,7 @@ var CodePiRuntimeEngine = class {
|
|
|
4624
4697
|
}, lease, metadata2.role);
|
|
4625
4698
|
const startedAt = Date.now();
|
|
4626
4699
|
let completionSeen = false;
|
|
4700
|
+
const interaction = { tokens: 0, noticeEmitted: false };
|
|
4627
4701
|
const result = await this.#run({
|
|
4628
4702
|
engine: this.options.engine,
|
|
4629
4703
|
image: this.options.image,
|
|
@@ -4639,25 +4713,18 @@ var CodePiRuntimeEngine = class {
|
|
|
4639
4713
|
}, active.conversationRefs),
|
|
4640
4714
|
onMessage: async (output) => {
|
|
4641
4715
|
if (output.type === "inference.request") {
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4716
|
+
return handleCodeRuntimeInference({
|
|
4717
|
+
command,
|
|
4718
|
+
metadata: metadata2,
|
|
4719
|
+
request: output,
|
|
4720
|
+
state: interaction,
|
|
4721
|
+
control: this.options.control,
|
|
4722
|
+
event: (event) => this.#event(
|
|
4723
|
+
command,
|
|
4724
|
+
event,
|
|
4725
|
+
active.conversationRefs
|
|
4726
|
+
)
|
|
4646
4727
|
});
|
|
4647
|
-
await this.#event(command, {
|
|
4648
|
-
type: "usage",
|
|
4649
|
-
provider: response2.receipt.provider,
|
|
4650
|
-
model: response2.receipt.model,
|
|
4651
|
-
inputTokens: response2.receipt.inputTokens,
|
|
4652
|
-
outputTokens: response2.receipt.outputTokens,
|
|
4653
|
-
durationMs: Date.now() - inferenceStarted
|
|
4654
|
-
}, active.conversationRefs).catch(() => void 0);
|
|
4655
|
-
return {
|
|
4656
|
-
protocolVersion: HARNESS_PROTOCOL_VERSION,
|
|
4657
|
-
type: "inference.response",
|
|
4658
|
-
requestId: output.requestId,
|
|
4659
|
-
response: response2.response
|
|
4660
|
-
};
|
|
4661
4728
|
}
|
|
4662
4729
|
if (output.type === "tool.request") {
|
|
4663
4730
|
const toolStarted = Date.now();
|
|
@@ -4722,7 +4789,9 @@ var CodePiRuntimeEngine = class {
|
|
|
4722
4789
|
durationMs: Date.now() - startedAt
|
|
4723
4790
|
}, active.conversationRefs).catch(() => void 0);
|
|
4724
4791
|
if (result.status === "failed") {
|
|
4725
|
-
|
|
4792
|
+
const detail = (runtimeResultError(result.result) ?? result.stderr.trim()) || "Pi container failed";
|
|
4793
|
+
await this.#diagnostic(command, active, detail);
|
|
4794
|
+
await this.#failure(command, active, detail);
|
|
4726
4795
|
}
|
|
4727
4796
|
return result;
|
|
4728
4797
|
}
|
|
@@ -4739,6 +4808,15 @@ var CodePiRuntimeEngine = class {
|
|
|
4739
4808
|
await this.options.control.reportSessionFailure(command.sessionId, active.failure).catch(() => void 0);
|
|
4740
4809
|
}
|
|
4741
4810
|
}
|
|
4811
|
+
async #diagnostic(command, active, value) {
|
|
4812
|
+
const detail = value.trim().slice(0, 2e3) || "Pi runtime failed";
|
|
4813
|
+
this.options.onDiagnostic?.(detail);
|
|
4814
|
+
await this.#event(
|
|
4815
|
+
command,
|
|
4816
|
+
{ type: "diagnostic", level: "error", message: detail },
|
|
4817
|
+
active.conversationRefs
|
|
4818
|
+
).catch(() => void 0);
|
|
4819
|
+
}
|
|
4742
4820
|
async #event(command, event, refs) {
|
|
4743
4821
|
await appendCodeRuntimeEvent(this.options.control, command, event, refs);
|
|
4744
4822
|
}
|
|
@@ -5145,12 +5223,15 @@ async function prepareCodeImages(engine, images) {
|
|
|
5145
5223
|
}
|
|
5146
5224
|
|
|
5147
5225
|
// src/code-runtime-config.ts
|
|
5148
|
-
var CODE_PI_IMAGE = "ghcr.io/cory/odla-pi-agent@sha256:
|
|
5226
|
+
var CODE_PI_IMAGE = "ghcr.io/cory/odla-pi-agent@sha256:2a52a1c8eed66ad167e7bccab4d603ed8fcd75c42dddfb320083436ed89b7c9c";
|
|
5149
5227
|
var CODE_BUILD_RECIPES = Object.freeze([{
|
|
5150
5228
|
id: "odla-code-contracts",
|
|
5151
5229
|
image: "node:24-alpine@sha256:a0b9bf06e4e6193cf7a0f58816cc935ff8c2a908f81e6f1a95432d679c54fbfd",
|
|
5152
5230
|
command: [
|
|
5153
5231
|
"node",
|
|
5232
|
+
// The clean source mount deliberately has no node_modules. Reuse the
|
|
5233
|
+
// semver copy inside this digest-pinned npm image without network access.
|
|
5234
|
+
"--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",
|
|
5154
5235
|
"--test",
|
|
5155
5236
|
"scripts/lib/directories.test.mjs",
|
|
5156
5237
|
"scripts/lib/internal-deps.test.mjs",
|
|
@@ -5291,7 +5372,8 @@ async function runCodeRuntime(input) {
|
|
|
5291
5372
|
image: CODE_PI_IMAGE,
|
|
5292
5373
|
recipes: CODE_BUILD_RECIPES,
|
|
5293
5374
|
recipeAuthorization: "registered_recipe",
|
|
5294
|
-
localSource: input.localSource
|
|
5375
|
+
localSource: input.localSource,
|
|
5376
|
+
onDiagnostic: (message2) => input.stdout.error(`Pi runtime failed \xB7 ${message2}`)
|
|
5295
5377
|
});
|
|
5296
5378
|
const reconciler = new CodeRuntimeReconciler(control, commandEngine);
|
|
5297
5379
|
try {
|