@odla-ai/cli 0.46.12 → 0.48.0
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 +33 -0
- package/dist/bin.cjs +556 -344
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-Q4BGAUEH.js → chunk-BD5KIG63.js} +519 -324
- package/dist/chunk-BD5KIG63.js.map +1 -0
- package/dist/{cli-5CDFI4AY.js → cli-MXYYOFBR.js} +2 -2
- package/dist/index.cjs +521 -326
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +1 -1
- package/package.json +3 -3
- package/skills/odla/references/sdks.md +5 -0
- package/dist/chunk-Q4BGAUEH.js.map +0 -1
- /package/dist/{cli-5CDFI4AY.js.map → cli-MXYYOFBR.js.map} +0 -0
package/dist/bin.cjs
CHANGED
|
@@ -1783,6 +1783,7 @@ var init_surface = __esm({
|
|
|
1783
1783
|
watch: {}
|
|
1784
1784
|
},
|
|
1785
1785
|
provision: {},
|
|
1786
|
+
promotion: { plan: {}, inspect: {}, status: {}, apply: {}, rollback: {}, next: {}, record: {}, cancel: {} },
|
|
1786
1787
|
runbook: {
|
|
1787
1788
|
ask: {},
|
|
1788
1789
|
search: {},
|
|
@@ -4270,9 +4271,9 @@ function canonicalValue(value2) {
|
|
|
4270
4271
|
}
|
|
4271
4272
|
if (Array.isArray(value2)) return value2.map(canonicalValue);
|
|
4272
4273
|
if (value2 && typeof value2 === "object") {
|
|
4273
|
-
const
|
|
4274
|
+
const record12 = value2;
|
|
4274
4275
|
return Object.fromEntries(
|
|
4275
|
-
Object.keys(
|
|
4276
|
+
Object.keys(record12).filter((key) => record12[key] !== void 0).sort().map((key) => [key, canonicalValue(record12[key])])
|
|
4276
4277
|
);
|
|
4277
4278
|
}
|
|
4278
4279
|
throw new TypeError("canonical JSON rejects unsupported values");
|
|
@@ -6878,17 +6879,17 @@ var init_cli_project = __esm({
|
|
|
6878
6879
|
}
|
|
6879
6880
|
});
|
|
6880
6881
|
|
|
6881
|
-
// ../harness/dist/chunk-
|
|
6882
|
+
// ../harness/dist/chunk-U324RQ4N.js
|
|
6882
6883
|
var HARNESS_PROTOCOL_VERSION;
|
|
6883
|
-
var
|
|
6884
|
-
"../harness/dist/chunk-
|
|
6884
|
+
var init_chunk_U324RQ4N = __esm({
|
|
6885
|
+
"../harness/dist/chunk-U324RQ4N.js"() {
|
|
6885
6886
|
"use strict";
|
|
6886
6887
|
init_cjs_shims();
|
|
6887
6888
|
HARNESS_PROTOCOL_VERSION = 1;
|
|
6888
6889
|
}
|
|
6889
6890
|
});
|
|
6890
6891
|
|
|
6891
|
-
// ../harness/dist/chunk-
|
|
6892
|
+
// ../harness/dist/chunk-5LRYJKUI.js
|
|
6892
6893
|
function assertPinnedImage(image) {
|
|
6893
6894
|
if (!DIGEST_IMAGE.test(image)) throw new TypeError("container image must be pinned by sha256 digest");
|
|
6894
6895
|
}
|
|
@@ -7032,8 +7033,8 @@ async function materializeGitTree(source, commitSha, options = {}) {
|
|
|
7032
7033
|
const maxFiles = options.maxFiles ?? 2e4;
|
|
7033
7034
|
const maxBytes = options.maxBytes ?? 512 * 1024 * 1024;
|
|
7034
7035
|
const inventory = (await gitOutput(sourceDir, ["ls-tree", "-rz", commitSha], 16 * 1024 * 1024)).toString("utf8").split("\0").filter(Boolean);
|
|
7035
|
-
const entries = inventory.flatMap((
|
|
7036
|
-
const match = /^(100644|100755) blob ([0-9a-f]{40,64})\t([\s\S]+)$/.exec(
|
|
7036
|
+
const entries = inventory.flatMap((record12) => {
|
|
7037
|
+
const match = /^(100644|100755) blob ([0-9a-f]{40,64})\t([\s\S]+)$/.exec(record12);
|
|
7037
7038
|
return match && allowedWorkspacePath(match[3]) ? [{ mode: match[1], hash: match[2], path: match[3] }] : [];
|
|
7038
7039
|
});
|
|
7039
7040
|
if (entries.length > maxFiles) throw new Error(`workspace exceeds ${maxFiles} files`);
|
|
@@ -7237,8 +7238,8 @@ async function stageWorkspacePair(baselineSource, workspaceSource, options = {})
|
|
|
7237
7238
|
}
|
|
7238
7239
|
}
|
|
7239
7240
|
var import_child_process, import_fs, import_promises2, import_path, import_process, import_promises3, import_os, import_path2, import_child_process2, import_path3, import_promises4, import_os2, import_path4, import_child_process3, DIGEST_IMAGE, SKIP_WORKSPACE_DIRS, SECRET_WORKSPACE_FILE;
|
|
7240
|
-
var
|
|
7241
|
-
"../harness/dist/chunk-
|
|
7241
|
+
var init_chunk_5LRYJKUI = __esm({
|
|
7242
|
+
"../harness/dist/chunk-5LRYJKUI.js"() {
|
|
7242
7243
|
"use strict";
|
|
7243
7244
|
init_cjs_shims();
|
|
7244
7245
|
import_child_process = require("child_process");
|
|
@@ -7268,6 +7269,171 @@ var init_chunk_HDIR4MM5 = __esm({
|
|
|
7268
7269
|
}
|
|
7269
7270
|
});
|
|
7270
7271
|
|
|
7272
|
+
// ../harness/dist/chunk-FAN2R3GW.js
|
|
7273
|
+
function patchStats(value2) {
|
|
7274
|
+
if (typeof value2 !== "string") return {};
|
|
7275
|
+
let additions = 0;
|
|
7276
|
+
let deletions = 0;
|
|
7277
|
+
for (const line2 of value2.slice(0, 262144).split("\n")) {
|
|
7278
|
+
if (line2.startsWith("+++") || line2.startsWith("---")) continue;
|
|
7279
|
+
if (line2.startsWith("+")) additions += 1;
|
|
7280
|
+
else if (line2.startsWith("-")) deletions += 1;
|
|
7281
|
+
}
|
|
7282
|
+
return { ...additions ? { additions } : {}, ...deletions ? { deletions } : {} };
|
|
7283
|
+
}
|
|
7284
|
+
function searchResults(value2) {
|
|
7285
|
+
if (typeof value2 !== "string") return void 0;
|
|
7286
|
+
const results = value2.split("\n").flatMap((line2) => {
|
|
7287
|
+
const match = /^([^:\n]{1,1024}):(\d+):\s?(.*)$/.exec(line2);
|
|
7288
|
+
if (!match) return [];
|
|
7289
|
+
const lineNumber = Number(match[2]);
|
|
7290
|
+
const itemText = text3(match[3], 240);
|
|
7291
|
+
if (!Number.isSafeInteger(lineNumber) || lineNumber < 1) return [];
|
|
7292
|
+
return [{ path: match[1], line: lineNumber, ...itemText ? { text: itemText } : {} }];
|
|
7293
|
+
}).slice(0, 5);
|
|
7294
|
+
return results.length ? results : void 0;
|
|
7295
|
+
}
|
|
7296
|
+
function codeToolRequestPresentation(request3) {
|
|
7297
|
+
const input = request3.input;
|
|
7298
|
+
if (request3.tool === "sandbox.read") {
|
|
7299
|
+
const path = text3(input.path, 1024);
|
|
7300
|
+
if (!path) return void 0;
|
|
7301
|
+
const startLine = integer(input.startLine);
|
|
7302
|
+
const endLine = integer(input.endLine);
|
|
7303
|
+
return { kind: "read", path, ...startLine ? { startLine } : {}, ...endLine ? { endLine } : {} };
|
|
7304
|
+
}
|
|
7305
|
+
if (request3.tool === "sandbox.list") {
|
|
7306
|
+
const scope = text3(input.prefix, 1024);
|
|
7307
|
+
return { kind: "list", ...scope ? { scope } : {} };
|
|
7308
|
+
}
|
|
7309
|
+
if (request3.tool === "sandbox.search" || request3.tool === "sandbox.overview" || request3.tool === "sandbox.where_is" || request3.tool === "sandbox.who_imports" || request3.tool === "sandbox.who_touches") {
|
|
7310
|
+
const query = text3(input.query, 512);
|
|
7311
|
+
const scope = request3.tool === "sandbox.search" ? text3(input.prefix, 1024) : void 0;
|
|
7312
|
+
if (request3.tool === "sandbox.search" && !query) return void 0;
|
|
7313
|
+
return { kind: "query", ...query ? { query } : {}, ...scope ? { scope } : {} };
|
|
7314
|
+
}
|
|
7315
|
+
if (request3.tool === "sandbox.apply_patch") {
|
|
7316
|
+
return { kind: "patch", ...patchStats(input.patch) };
|
|
7317
|
+
}
|
|
7318
|
+
const recipeId = text3(input.recipeId, 120);
|
|
7319
|
+
return recipeId ? { kind: "recipe", recipeId } : void 0;
|
|
7320
|
+
}
|
|
7321
|
+
function codeToolResultPresentation(request3, response2) {
|
|
7322
|
+
const started = codeToolRequestPresentation(request3);
|
|
7323
|
+
if (!started || !response2.ok) return started;
|
|
7324
|
+
const details = record5(response2.details);
|
|
7325
|
+
if (started.kind === "read") {
|
|
7326
|
+
return {
|
|
7327
|
+
...started,
|
|
7328
|
+
...integer(details?.startLine) ? { startLine: integer(details?.startLine) } : {},
|
|
7329
|
+
...integer(details?.endLine) ? { endLine: integer(details?.endLine) } : {},
|
|
7330
|
+
...excerpt(response2.content) ? { excerpt: excerpt(response2.content) } : {}
|
|
7331
|
+
};
|
|
7332
|
+
}
|
|
7333
|
+
if (started.kind === "list") {
|
|
7334
|
+
const listed = response2.content.split("\n").filter((line2) => line2 && !line2.startsWith("\u2026") && !line2.startsWith("Workspace ")).map((line2) => text3(line2, 1024)).filter((line2) => Boolean(line2)).slice(0, 8);
|
|
7335
|
+
return {
|
|
7336
|
+
...started,
|
|
7337
|
+
...integer(details?.count) !== void 0 ? { count: integer(details?.count) } : {},
|
|
7338
|
+
...listed.length ? { paths: listed } : {}
|
|
7339
|
+
};
|
|
7340
|
+
}
|
|
7341
|
+
if (started.kind === "query") {
|
|
7342
|
+
const results = request3.tool === "sandbox.search" ? searchResults(response2.content) : void 0;
|
|
7343
|
+
const resultExcerpt = request3.tool === "sandbox.search" ? void 0 : excerpt(response2.content);
|
|
7344
|
+
return {
|
|
7345
|
+
...started,
|
|
7346
|
+
...integer(details?.count) !== void 0 ? { count: integer(details?.count) } : {},
|
|
7347
|
+
...results ? { results } : {},
|
|
7348
|
+
...resultExcerpt ? { excerpt: resultExcerpt } : {}
|
|
7349
|
+
};
|
|
7350
|
+
}
|
|
7351
|
+
if (started.kind === "patch") {
|
|
7352
|
+
return { ...started, ...paths(details?.paths) ? { paths: paths(details?.paths) } : {} };
|
|
7353
|
+
}
|
|
7354
|
+
const output = response2.content.replace(/^Recipe [^\n]*\.?\s*/u, "");
|
|
7355
|
+
return {
|
|
7356
|
+
...started,
|
|
7357
|
+
...integer(details?.exitCode) !== void 0 ? { exitCode: integer(details?.exitCode) } : {},
|
|
7358
|
+
...typeof details?.timedOut === "boolean" ? { timedOut: details.timedOut } : {},
|
|
7359
|
+
...typeof details?.outputLimitExceeded === "boolean" ? { outputLimitExceeded: details.outputLimitExceeded } : {},
|
|
7360
|
+
...excerpt(output, true) ? { excerpt: excerpt(output, true) } : {}
|
|
7361
|
+
};
|
|
7362
|
+
}
|
|
7363
|
+
function toolFailureReason(response2) {
|
|
7364
|
+
if (response2.ok) return void 0;
|
|
7365
|
+
const supplied = response2.details?.failureReason;
|
|
7366
|
+
const reason = typeof supplied === "string" && supplied || DEFAULT_FAILURE_REASON[response2.content] || response2.content || "tool request failed; inspect the tool input and workspace state";
|
|
7367
|
+
return reason.slice(0, MAX_FAILURE_REASON);
|
|
7368
|
+
}
|
|
7369
|
+
function observedBroker(input) {
|
|
7370
|
+
const now = input.now ?? Date.now;
|
|
7371
|
+
return {
|
|
7372
|
+
execute: async (context, request3) => {
|
|
7373
|
+
const startedAt = now();
|
|
7374
|
+
const operationId = input.operationIdFor(request3.requestId);
|
|
7375
|
+
const startedPresentation = codeToolRequestPresentation(request3);
|
|
7376
|
+
await input.emit({
|
|
7377
|
+
type: "tool",
|
|
7378
|
+
phase: "started",
|
|
7379
|
+
tool: request3.tool,
|
|
7380
|
+
operationId,
|
|
7381
|
+
...startedPresentation ? { presentation: startedPresentation } : {}
|
|
7382
|
+
});
|
|
7383
|
+
const response2 = await input.broker.execute(context, request3);
|
|
7384
|
+
const completedPresentation = codeToolResultPresentation(request3, response2);
|
|
7385
|
+
const failureReason = toolFailureReason(response2);
|
|
7386
|
+
await input.emit({
|
|
7387
|
+
type: "tool",
|
|
7388
|
+
phase: "completed",
|
|
7389
|
+
tool: request3.tool,
|
|
7390
|
+
ok: response2.ok,
|
|
7391
|
+
durationMs: now() - startedAt,
|
|
7392
|
+
operationId,
|
|
7393
|
+
...failureReason ? { failureReason } : {},
|
|
7394
|
+
...completedPresentation ? { presentation: completedPresentation } : {}
|
|
7395
|
+
});
|
|
7396
|
+
return response2;
|
|
7397
|
+
}
|
|
7398
|
+
};
|
|
7399
|
+
}
|
|
7400
|
+
var text3, integer, record5, excerpt, paths, MAX_FAILURE_REASON, DEFAULT_FAILURE_REASON;
|
|
7401
|
+
var init_chunk_FAN2R3GW = __esm({
|
|
7402
|
+
"../harness/dist/chunk-FAN2R3GW.js"() {
|
|
7403
|
+
"use strict";
|
|
7404
|
+
init_cjs_shims();
|
|
7405
|
+
text3 = (value2, maximum) => {
|
|
7406
|
+
if (typeof value2 !== "string") return void 0;
|
|
7407
|
+
const bounded = value2.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, " ").trim();
|
|
7408
|
+
return bounded ? bounded.slice(0, maximum) : void 0;
|
|
7409
|
+
};
|
|
7410
|
+
integer = (value2) => Number.isSafeInteger(value2) && Number(value2) >= 0 ? Number(value2) : void 0;
|
|
7411
|
+
record5 = (value2) => value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : void 0;
|
|
7412
|
+
excerpt = (value2, tail = false) => {
|
|
7413
|
+
if (typeof value2 !== "string") return void 0;
|
|
7414
|
+
const safe = value2.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, " ");
|
|
7415
|
+
const source = (tail ? safe.slice(-1e4) : safe.slice(0, 1e4)).trim();
|
|
7416
|
+
if (!source) return void 0;
|
|
7417
|
+
const lines = source.split("\n").filter((line2) => line2.trim()).map((line2) => line2.slice(0, 240));
|
|
7418
|
+
const selected = tail ? lines.slice(-10) : lines.slice(0, 10);
|
|
7419
|
+
return text3(selected.join("\n"), 2400);
|
|
7420
|
+
};
|
|
7421
|
+
paths = (value2) => {
|
|
7422
|
+
if (!Array.isArray(value2)) return void 0;
|
|
7423
|
+
const items = value2.flatMap((item) => {
|
|
7424
|
+
const path = text3(item, 1024);
|
|
7425
|
+
return path ? [path] : [];
|
|
7426
|
+
}).slice(0, 12);
|
|
7427
|
+
return items.length ? items : void 0;
|
|
7428
|
+
};
|
|
7429
|
+
MAX_FAILURE_REASON = 240;
|
|
7430
|
+
DEFAULT_FAILURE_REASON = {
|
|
7431
|
+
"tool denied by CaMeL policy": "tool denied by CaMeL policy",
|
|
7432
|
+
"review sessions are read-only": "review session is read-only; workspace changes are not permitted"
|
|
7433
|
+
};
|
|
7434
|
+
}
|
|
7435
|
+
});
|
|
7436
|
+
|
|
7271
7437
|
// ../camel/dist/chunk-7FHPOQVP.js
|
|
7272
7438
|
var CamelError;
|
|
7273
7439
|
var init_chunk_7FHPOQVP = __esm({
|
|
@@ -7314,8 +7480,8 @@ function normalize(value2) {
|
|
|
7314
7480
|
if (Array.isArray(value2)) return value2.map(normalize);
|
|
7315
7481
|
if (value2 instanceof Uint8Array) return { $bytes: [...value2] };
|
|
7316
7482
|
if (typeof value2 === "object") {
|
|
7317
|
-
const
|
|
7318
|
-
return Object.fromEntries(Object.keys(
|
|
7483
|
+
const record12 = value2;
|
|
7484
|
+
return Object.fromEntries(Object.keys(record12).filter((key) => record12[key] !== void 0).sort().map((key) => [key, normalize(record12[key])]));
|
|
7319
7485
|
}
|
|
7320
7486
|
throw new CamelError("state_conflict", "Canonical JSON rejects unsupported values.");
|
|
7321
7487
|
}
|
|
@@ -8236,7 +8402,7 @@ var init_code2 = __esm({
|
|
|
8236
8402
|
}
|
|
8237
8403
|
});
|
|
8238
8404
|
|
|
8239
|
-
// ../harness/dist/chunk-
|
|
8405
|
+
// ../harness/dist/chunk-Q4NL5XO3.js
|
|
8240
8406
|
async function digestStagedWorkspace(root, limits) {
|
|
8241
8407
|
const files = [];
|
|
8242
8408
|
const walk = async (directory) => {
|
|
@@ -8294,7 +8460,7 @@ function createCodeRuntimeControlClient(options) {
|
|
|
8294
8460
|
}
|
|
8295
8461
|
const value2 = await response2.json().catch(() => null);
|
|
8296
8462
|
if (!response2.ok) {
|
|
8297
|
-
const problem =
|
|
8463
|
+
const problem = record6(record6(value2)?.error);
|
|
8298
8464
|
throw new CodeRuntimeControlError(
|
|
8299
8465
|
typeof problem?.message === "string" ? problem.message : `Code runtime request failed (${response2.status})`,
|
|
8300
8466
|
response2.status,
|
|
@@ -8315,12 +8481,12 @@ function createCodeRuntimeControlClient(options) {
|
|
|
8315
8481
|
await call4(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/source`, {})
|
|
8316
8482
|
),
|
|
8317
8483
|
infer: async (sessionId, inference) => {
|
|
8318
|
-
const value2 =
|
|
8484
|
+
const value2 = record6(await call4(
|
|
8319
8485
|
`/registry/code/runtime/sessions/${validSessionId(sessionId)}/inference`,
|
|
8320
8486
|
inference,
|
|
8321
8487
|
modelRequestTimeoutMs
|
|
8322
8488
|
));
|
|
8323
|
-
if (!value2 || value2.requestId !== inference.requestId || !
|
|
8489
|
+
if (!value2 || value2.requestId !== inference.requestId || !record6(value2.response) || !record6(value2.receipt)) {
|
|
8324
8490
|
throw new CodeRuntimeControlError("invalid Code inference response", 502, "invalid_response");
|
|
8325
8491
|
}
|
|
8326
8492
|
return value2;
|
|
@@ -8451,12 +8617,12 @@ function validateHeartbeat(version, capabilities) {
|
|
|
8451
8617
|
}
|
|
8452
8618
|
}
|
|
8453
8619
|
function parseSnapshot(value2) {
|
|
8454
|
-
const root =
|
|
8455
|
-
const host =
|
|
8620
|
+
const root = record6(value2);
|
|
8621
|
+
const host = record6(root?.host);
|
|
8456
8622
|
if (!host || typeof host.hostId !== "string" || typeof host.runtimeVersion !== "string" || !Number.isSafeInteger(host.lastSeenAt) || host.revokedAt !== null || !Array.isArray(root?.bindings) || root.bindings.length > 1024 || !Array.isArray(root?.commands) || root.commands.length > 64) throw invalid("heartbeat");
|
|
8457
8623
|
const bindingIds = /* @__PURE__ */ new Set();
|
|
8458
8624
|
const bindings = root.bindings.map((item) => {
|
|
8459
|
-
const binding =
|
|
8625
|
+
const binding = record6(item);
|
|
8460
8626
|
if (!binding || typeof binding.bindingId !== "string" || typeof binding.appId !== "string" || binding.env !== "dev" && binding.env !== "prod" || typeof binding.offerId !== "string" || binding.hostId !== host.hostId || !Number.isSafeInteger(binding.generation) || Number(binding.generation) < 1 || binding.revokedAt !== null || bindingIds.has(binding.bindingId)) {
|
|
8461
8627
|
throw invalid("binding");
|
|
8462
8628
|
}
|
|
@@ -8466,10 +8632,10 @@ function parseSnapshot(value2) {
|
|
|
8466
8632
|
const commandIds = /* @__PURE__ */ new Set();
|
|
8467
8633
|
const commandSequences = /* @__PURE__ */ new Set();
|
|
8468
8634
|
const commands = root.commands.map((item) => {
|
|
8469
|
-
const command =
|
|
8635
|
+
const command = record6(item);
|
|
8470
8636
|
const binding = bindings.find((candidate) => candidate.bindingId === command?.bindingId);
|
|
8471
8637
|
const sequenceKey = `${String(command?.instanceId)}:${String(command?.sequence)}`;
|
|
8472
|
-
if (!command || typeof command.commandId !== "string" || !/^ccmd_[0-9a-f]{32}$/.test(command.commandId) || typeof command.instanceId !== "string" || typeof command.sessionId !== "string" || !/^csess_[0-9a-f]{32}$/.test(command.sessionId) || typeof command.appId !== "string" || command.env !== "dev" && command.env !== "prod" || command.hostId !== host.hostId || !binding || binding.appId !== command.appId || binding.generation !== command.bindingGeneration || !Number.isSafeInteger(command.sequence) || Number(command.sequence) < 1 || commandIds.has(command.commandId) || commandSequences.has(sequenceKey) || !["start", "prompt", "checkpoint_stop", "resume"].includes(String(command.kind)) || !
|
|
8638
|
+
if (!command || typeof command.commandId !== "string" || !/^ccmd_[0-9a-f]{32}$/.test(command.commandId) || typeof command.instanceId !== "string" || typeof command.sessionId !== "string" || !/^csess_[0-9a-f]{32}$/.test(command.sessionId) || typeof command.appId !== "string" || command.env !== "dev" && command.env !== "prod" || command.hostId !== host.hostId || !binding || binding.appId !== command.appId || binding.generation !== command.bindingGeneration || !Number.isSafeInteger(command.sequence) || Number(command.sequence) < 1 || commandIds.has(command.commandId) || commandSequences.has(sequenceKey) || !["start", "prompt", "checkpoint_stop", "resume"].includes(String(command.kind)) || !record6(command.payload) || !Number.isSafeInteger(command.createdAt)) throw invalid("command");
|
|
8473
8639
|
commandIds.add(command.commandId);
|
|
8474
8640
|
commandSequences.add(sequenceKey);
|
|
8475
8641
|
return command;
|
|
@@ -8478,10 +8644,10 @@ function parseSnapshot(value2) {
|
|
|
8478
8644
|
}
|
|
8479
8645
|
async function parseSource(value2) {
|
|
8480
8646
|
const repositoryLimits = { maximumFiles: 1e5, maximumBytes: 80 * 1024 * 1024 };
|
|
8481
|
-
const snapshot =
|
|
8647
|
+
const snapshot = record6(record6(value2)?.snapshot);
|
|
8482
8648
|
if (!snapshot || typeof snapshot.repository !== "string" || typeof snapshot.commitSha !== "string" || typeof snapshot.treeDigest !== "string" || !Array.isArray(snapshot.files)) throw invalid("source");
|
|
8483
8649
|
const files = snapshot.files.map((value22) => {
|
|
8484
|
-
const file =
|
|
8650
|
+
const file = record6(value22);
|
|
8485
8651
|
if (!file || typeof file.path !== "string" || typeof file.content !== "string") throw invalid("source file");
|
|
8486
8652
|
return { path: file.path, content: file.content };
|
|
8487
8653
|
});
|
|
@@ -8490,11 +8656,11 @@ async function parseSource(value2) {
|
|
|
8490
8656
|
const aliases = /* @__PURE__ */ new Set();
|
|
8491
8657
|
const references = [];
|
|
8492
8658
|
for (const item of referencesValue) {
|
|
8493
|
-
const reference =
|
|
8659
|
+
const reference = record6(item);
|
|
8494
8660
|
if (!reference || typeof reference.alias !== "string" || !/^[a-z][a-z0-9-]{0,39}$/.test(reference.alias) || aliases.has(reference.alias) || reference.alias === "primary" || typeof reference.repository !== "string" || typeof reference.commitSha !== "string" || typeof reference.treeDigest !== "string" || !Array.isArray(reference.files)) throw invalid("reference source");
|
|
8495
8661
|
aliases.add(reference.alias);
|
|
8496
8662
|
const referenceFiles = reference.files.map((entry) => {
|
|
8497
|
-
const file =
|
|
8663
|
+
const file = record6(entry);
|
|
8498
8664
|
if (!file || typeof file.path !== "string" || typeof file.content !== "string") throw invalid("reference source file");
|
|
8499
8665
|
return { path: file.path, content: file.content };
|
|
8500
8666
|
});
|
|
@@ -8509,31 +8675,31 @@ async function parseSource(value2) {
|
|
|
8509
8675
|
return { ...source, treeDigest: digest, ...references.length ? { references } : {} };
|
|
8510
8676
|
}
|
|
8511
8677
|
function parseReview(value2) {
|
|
8512
|
-
const review =
|
|
8513
|
-
if (!review || !["approved", "rejected"].includes(String(review.verdict)) || typeof review.reviewDigest !== "string" || !/^sha256:[0-9a-f]{64}$/.test(review.reviewDigest) || typeof review.provider !== "string" || !review.provider || typeof review.model !== "string" || !review.model || !Number.isSafeInteger(review.policyVersion) || Number(review.policyVersion) < 1) throw invalid("review");
|
|
8678
|
+
const review = record6(record6(value2)?.review);
|
|
8679
|
+
if (!review || !["approved", "rejected"].includes(String(review.verdict)) || typeof review.reviewDigest !== "string" || !/^sha256:[0-9a-f]{64}$/.test(review.reviewDigest) || typeof review.provider !== "string" || !review.provider || typeof review.model !== "string" || !review.model || !Number.isSafeInteger(review.policyVersion) || Number(review.policyVersion) < 1 || !Number.isSafeInteger(review.score) || Number(review.score) < 0 || Number(review.score) > 100 || typeof review.summary !== "string" || !Array.isArray(review.findings) || review.findings.length > 12) throw invalid("review");
|
|
8514
8680
|
return review;
|
|
8515
8681
|
}
|
|
8516
8682
|
function parseCandidate(value2) {
|
|
8517
|
-
const candidate =
|
|
8683
|
+
const candidate = record6(record6(value2)?.candidate);
|
|
8518
8684
|
if (!candidate || typeof candidate.candidateId !== "string" || !/^ccand_[0-9a-f]{32}$/.test(candidate.candidateId) || !["submitted", "approved", "published", "failed"].includes(String(candidate.status))) {
|
|
8519
8685
|
throw invalid("candidate");
|
|
8520
8686
|
}
|
|
8521
8687
|
return { candidateId: candidate.candidateId, status: candidate.status };
|
|
8522
8688
|
}
|
|
8523
8689
|
function parseCollaborationSkills(value2) {
|
|
8524
|
-
const items =
|
|
8690
|
+
const items = record6(value2)?.skills;
|
|
8525
8691
|
if (!Array.isArray(items) || items.length > 16) throw invalid("collaboration skills");
|
|
8526
8692
|
const skillNames2 = /* @__PURE__ */ new Set();
|
|
8527
8693
|
const toolNames = /* @__PURE__ */ new Set();
|
|
8528
8694
|
return items.map((item) => {
|
|
8529
|
-
const skill =
|
|
8695
|
+
const skill = record6(item);
|
|
8530
8696
|
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
8697
|
throw invalid("collaboration skill");
|
|
8532
8698
|
}
|
|
8533
8699
|
skillNames2.add(skill.name);
|
|
8534
8700
|
const tools = skill.tools.map((candidate) => {
|
|
8535
|
-
const tool =
|
|
8536
|
-
const inputSchema =
|
|
8701
|
+
const tool = record6(candidate);
|
|
8702
|
+
const inputSchema = record6(tool?.inputSchema);
|
|
8537
8703
|
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
8704
|
throw invalid("collaboration tool");
|
|
8539
8705
|
}
|
|
@@ -8558,12 +8724,12 @@ function parseCollaborationSkills(value2) {
|
|
|
8558
8724
|
}
|
|
8559
8725
|
function validateCollaborationToolRequest(value2) {
|
|
8560
8726
|
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) || !
|
|
8727
|
+
if (typeof value2.toolCallId !== "string" || value2.toolCallId.length > 256 || !/^[^\s\u0000-\u001f\u007f]+$/.test(value2.toolCallId) || !validManifestName(value2.skill) || !validManifestName(value2.tool) || !record6(value2.input) || jsonBytes(value2.input) > 128e3) {
|
|
8562
8728
|
throw new TypeError("invalid Code collaboration tool request");
|
|
8563
8729
|
}
|
|
8564
8730
|
}
|
|
8565
8731
|
function parseCollaborationToolOutput(value2) {
|
|
8566
|
-
const output =
|
|
8732
|
+
const output = record6(record6(value2)?.output);
|
|
8567
8733
|
if (!output || output.isError !== void 0 && typeof output.isError !== "boolean") {
|
|
8568
8734
|
throw invalid("collaboration tool");
|
|
8569
8735
|
}
|
|
@@ -8572,7 +8738,7 @@ function parseCollaborationToolOutput(value2) {
|
|
|
8572
8738
|
return { content: output.content, ...output.isError === true ? { isError: true } : {} };
|
|
8573
8739
|
}
|
|
8574
8740
|
if (!Array.isArray(output.content) || output.content.length > 64 || jsonBytes(output.content) > 1e6 || !output.content.every((block2) => {
|
|
8575
|
-
const item =
|
|
8741
|
+
const item = record6(block2);
|
|
8576
8742
|
return item && ["text", "image", "audio", "document", "tool_use", "tool_result", "thinking"].includes(String(item.type));
|
|
8577
8743
|
})) throw invalid("collaboration tool");
|
|
8578
8744
|
return {
|
|
@@ -8606,10 +8772,41 @@ function jsonBytes(value2) {
|
|
|
8606
8772
|
}
|
|
8607
8773
|
}
|
|
8608
8774
|
function stripPatchEnvelope(patch2) {
|
|
8609
|
-
if (!/^\*\*\* (?:Begin|End) Patch\s*$/m.test(patch2)) return patch2;
|
|
8775
|
+
if (!/^\*\*\* (?:Begin|End) Patch\s*$/m.test(patch2)) return applyPatchDialectToDiff(patch2);
|
|
8610
8776
|
const kept = patch2.split("\n").filter((line2) => !/^\*\*\* (?:Begin|End) Patch\s*$/.test(line2));
|
|
8611
8777
|
const stripped = kept.join("\n");
|
|
8612
|
-
|
|
8778
|
+
if (/^diff --git /m.test(stripped)) return stripped;
|
|
8779
|
+
const translated = applyPatchDialectToDiff(stripped);
|
|
8780
|
+
return translated === stripped ? patch2 : translated;
|
|
8781
|
+
}
|
|
8782
|
+
function applyPatchDialectToDiff(patch2) {
|
|
8783
|
+
if (!/^\*\*\* (?:Update|Add|Delete) File: /m.test(patch2)) return patch2;
|
|
8784
|
+
const out = [];
|
|
8785
|
+
let open = false;
|
|
8786
|
+
for (const line2 of patch2.split("\n")) {
|
|
8787
|
+
const file = /^\*\*\* (Update|Add|Delete) File: (.+?)\s*$/.exec(line2);
|
|
8788
|
+
if (file) {
|
|
8789
|
+
const [, verb, raw] = file;
|
|
8790
|
+
const path = raw.trim();
|
|
8791
|
+
if (!PATH.test(path)) return patch2;
|
|
8792
|
+
out.push(`diff --git a/${path} b/${path}`);
|
|
8793
|
+
if (verb === "Add") out.push("new file mode 100644", "--- /dev/null", `+++ b/${path}`);
|
|
8794
|
+
else if (verb === "Delete") out.push(`--- a/${path}`, "+++ /dev/null");
|
|
8795
|
+
else out.push(`--- a/${path}`, `+++ b/${path}`);
|
|
8796
|
+
open = true;
|
|
8797
|
+
continue;
|
|
8798
|
+
}
|
|
8799
|
+
if (/^\*\*\* /.test(line2)) continue;
|
|
8800
|
+
if (!open) continue;
|
|
8801
|
+
if (/^@@/.test(line2)) {
|
|
8802
|
+
out.push("@@ -1 +1 @@");
|
|
8803
|
+
continue;
|
|
8804
|
+
}
|
|
8805
|
+
out.push(line2);
|
|
8806
|
+
}
|
|
8807
|
+
if (!open) return patch2;
|
|
8808
|
+
return `${out.join("\n").replace(/\n+$/, "")}
|
|
8809
|
+
`;
|
|
8613
8810
|
}
|
|
8614
8811
|
function validateCodePatch(rawPatch, maxBytes) {
|
|
8615
8812
|
const patch2 = stripPatchEnvelope(rawPatch);
|
|
@@ -8662,17 +8859,20 @@ function resolveCodePath(workspaceDir, path) {
|
|
|
8662
8859
|
if (target !== root && !target.startsWith(`${root}${import_path6.sep}`)) throw new TypeError("path escapes the staged workspace");
|
|
8663
8860
|
return target;
|
|
8664
8861
|
}
|
|
8862
|
+
function hasContextFreeHunk(patch2) {
|
|
8863
|
+
const bodies = patch2.split(/^@@.*$/m).slice(1);
|
|
8864
|
+
return bodies.some((body) => !body.split("\n").some((line2) => line2.startsWith(" ") && line2.trim().length > 0));
|
|
8865
|
+
}
|
|
8665
8866
|
function describePatchFailure(patch2, detail) {
|
|
8666
8867
|
const hunks = patch2.split("\n").filter((line2) => line2.startsWith("@@"));
|
|
8667
|
-
const
|
|
8668
|
-
const contextless = bodies.some((body) => !body.split("\n").some((line2) => line2.startsWith(" ") && line2.trim().length > 0));
|
|
8669
|
-
const hint = hunks.length > 0 && contextless ? " A hunk has no context lines; include at least one unchanged line above or below each change." : "";
|
|
8868
|
+
const hint = hunks.length > 0 && hasContextFreeHunk(patch2) ? " A hunk has no context lines; include at least one unchanged line above or below each change." : "";
|
|
8670
8869
|
return `patch did not apply: ${detail}${hint}`;
|
|
8671
8870
|
}
|
|
8672
8871
|
async function applyCodePatch(workspaceDir, rawPatch, paths2) {
|
|
8673
8872
|
const patch2 = stripPatchEnvelope(rawPatch);
|
|
8674
|
-
|
|
8675
|
-
await gitApply(workspaceDir, patch2,
|
|
8873
|
+
const zero = hasContextFreeHunk(patch2);
|
|
8874
|
+
await gitApply(workspaceDir, patch2, true, zero);
|
|
8875
|
+
await gitApply(workspaceDir, patch2, false, zero);
|
|
8676
8876
|
for (const path of paths2) {
|
|
8677
8877
|
try {
|
|
8678
8878
|
const info = await (0, import_promises6.lstat)(resolveCodePath(workspaceDir, path));
|
|
@@ -8684,9 +8884,16 @@ async function applyCodePatch(workspaceDir, rawPatch, paths2) {
|
|
|
8684
8884
|
}
|
|
8685
8885
|
}
|
|
8686
8886
|
}
|
|
8687
|
-
function gitApply(cwd, patch2, check) {
|
|
8887
|
+
function gitApply(cwd, patch2, check, unidiffZero = false) {
|
|
8688
8888
|
return new Promise((accept, reject) => {
|
|
8689
|
-
const args = [
|
|
8889
|
+
const args = [
|
|
8890
|
+
"apply",
|
|
8891
|
+
"--recount",
|
|
8892
|
+
...unidiffZero ? ["--unidiff-zero"] : [],
|
|
8893
|
+
"--whitespace=nowarn",
|
|
8894
|
+
...check ? ["--check"] : [],
|
|
8895
|
+
"-"
|
|
8896
|
+
];
|
|
8690
8897
|
const child = (0, import_child_process4.spawn)("git", args, {
|
|
8691
8898
|
cwd,
|
|
8692
8899
|
shell: false,
|
|
@@ -8695,8 +8902,8 @@ function gitApply(cwd, patch2, check) {
|
|
|
8695
8902
|
});
|
|
8696
8903
|
let stderr2 = "";
|
|
8697
8904
|
child.stderr.setEncoding("utf8");
|
|
8698
|
-
child.stderr.on("data", (
|
|
8699
|
-
if (stderr2.length < 4e3) stderr2 +=
|
|
8905
|
+
child.stderr.on("data", (text4) => {
|
|
8906
|
+
if (stderr2.length < 4e3) stderr2 += text4.slice(0, 4e3);
|
|
8700
8907
|
});
|
|
8701
8908
|
child.once("error", reject);
|
|
8702
8909
|
child.once("exit", (code) => code === 0 ? accept() : reject(new TypeError(describePatchFailure(patch2, stderr2.trim().slice(0, 500)))));
|
|
@@ -8934,7 +9141,7 @@ function validate2(input) {
|
|
|
8934
9141
|
maximumFiles: policy.maximumFiles ?? 2e4,
|
|
8935
9142
|
maximumBytes: policy.maximumBytes ?? 512 * 1024 * 1024
|
|
8936
9143
|
};
|
|
8937
|
-
if ([...result.testPathPrefixes, ...result.testPathSuffixes].some((rule) => !RULE.test(rule)) || !
|
|
9144
|
+
if ([...result.testPathPrefixes, ...result.testPathSuffixes].some((rule) => !RULE.test(rule)) || !integer2(result.maximumChangedTests, 0, 1e4) || !integer2(result.maximumPatchBytes, 1, 4 * 1024 * 1024) || !integer2(result.maximumFiles, 1, 1e5) || !integer2(result.maximumBytes, 1, 2 * 1024 * 1024 * 1024)) {
|
|
8938
9145
|
throw new TypeError("clean verification policy exceeds its bounds");
|
|
8939
9146
|
}
|
|
8940
9147
|
return result;
|
|
@@ -8985,7 +9192,7 @@ function hashFile(path) {
|
|
|
8985
9192
|
});
|
|
8986
9193
|
}
|
|
8987
9194
|
function checkedResult(result, maximumOutputBytes) {
|
|
8988
|
-
if (!
|
|
9195
|
+
if (!integer2(result.exitCode, 0, 255) || !integer2(result.durationMs, 0, 30 * 6e4) || typeof result.stdout !== "string" || typeof result.stderr !== "string" || typeof result.outputLimitExceeded !== "boolean" || typeof result.timedOut !== "boolean") {
|
|
8989
9196
|
throw new TypeError("recipe executor returned an invalid result");
|
|
8990
9197
|
}
|
|
8991
9198
|
const bytes = Buffer.byteLength(result.stdout) + Buffer.byteLength(result.stderr);
|
|
@@ -9035,7 +9242,7 @@ function digestJson(value2) {
|
|
|
9035
9242
|
function digestBytes(value2) {
|
|
9036
9243
|
return `sha256:${(0, import_crypto3.createHash)("sha256").update(value2).digest("hex")}`;
|
|
9037
9244
|
}
|
|
9038
|
-
function
|
|
9245
|
+
function integer2(value2, minimum, maximum) {
|
|
9039
9246
|
return Number.isSafeInteger(value2) && value2 >= minimum && value2 <= maximum;
|
|
9040
9247
|
}
|
|
9041
9248
|
async function prepareRuntimeCheckpoint(input) {
|
|
@@ -9062,9 +9269,9 @@ async function prepareRuntimeCheckpoint(input) {
|
|
|
9062
9269
|
if (evidence.receipt.outcome === "passed") {
|
|
9063
9270
|
verification = evidence.receipt;
|
|
9064
9271
|
review = await input.review(patch2, verification);
|
|
9065
|
-
note = review
|
|
9272
|
+
note = describeReview(review);
|
|
9066
9273
|
} else {
|
|
9067
|
-
note =
|
|
9274
|
+
note = describeGateFailure(evidence);
|
|
9068
9275
|
}
|
|
9069
9276
|
} catch (cause) {
|
|
9070
9277
|
note = `Candidate verification or review failed closed: ${message(cause)}`;
|
|
@@ -9089,6 +9296,23 @@ async function prepareRuntimeCheckpoint(input) {
|
|
|
9089
9296
|
});
|
|
9090
9297
|
return { checkpoint, verification, review, note };
|
|
9091
9298
|
}
|
|
9299
|
+
function describeReview(review) {
|
|
9300
|
+
const findings = review.findings.map((finding) => ` - [${finding.severity}] ${finding.detail}`).join("\n");
|
|
9301
|
+
const head = review.verdict === "approved" ? `Clean verification and independent review passed (score ${review.score}/100).` : `Clean verification passed; independent review REJECTED this candidate (score ${review.score}/100). Address the findings and checkpoint again.`;
|
|
9302
|
+
return [head, review.summary, findings].filter(Boolean).join("\n").slice(0, 4e3);
|
|
9303
|
+
}
|
|
9304
|
+
function describeGateFailure(evidence) {
|
|
9305
|
+
const failed = evidence.receipt.recipes.filter((recipe2) => recipe2.status !== "passed");
|
|
9306
|
+
const detail = failed.map((recipe2) => {
|
|
9307
|
+
const log = evidence.logs.find((entry) => entry.recipeId === recipe2.recipeId);
|
|
9308
|
+
const output = `${log?.stdout ?? ""}
|
|
9309
|
+
${log?.stderr ?? ""}`.trim();
|
|
9310
|
+
return `${recipe2.recipeId}=${recipe2.status}${output ? `
|
|
9311
|
+
${output.slice(0, 1500)}` : ""}`;
|
|
9312
|
+
}).join("\n\n");
|
|
9313
|
+
return `Clean verification failed. Fix this and checkpoint again:
|
|
9314
|
+
${detail}`.slice(0, 4e3);
|
|
9315
|
+
}
|
|
9092
9316
|
function codeCommandMetadata(payload, resume) {
|
|
9093
9317
|
const trusted = record22(payload.trustedBase);
|
|
9094
9318
|
const role = payload.role;
|
|
@@ -9969,7 +10193,9 @@ function optionalInteger(value2) {
|
|
|
9969
10193
|
return value2;
|
|
9970
10194
|
}
|
|
9971
10195
|
function response(request3, ok, content2, details) {
|
|
9972
|
-
return { requestId: request3.requestId, ok, content: content2, ...details ? { details } : {} };
|
|
10196
|
+
if (ok) return { requestId: request3.requestId, ok, content: content2, ...details ? { details } : {} };
|
|
10197
|
+
const failureReason = typeof details?.failureReason === "string" && details.failureReason || DEFAULT_FAILURE_REASON2[content2] || content2 || "tool request failed; inspect the tool input and workspace state";
|
|
10198
|
+
return { requestId: request3.requestId, ok, content: content2, details: { ...details, failureReason } };
|
|
9973
10199
|
}
|
|
9974
10200
|
function workspaceGraphs(workspaceDir, paths2) {
|
|
9975
10201
|
const existing = cache.get(workspaceDir);
|
|
@@ -10533,96 +10759,6 @@ async function appendCodeRuntimeEvent(control, command, event, refs) {
|
|
|
10533
10759
|
const bounded = attributed.type === "message" ? { ...attributed, body: attributed.body.trim().slice(0, 2e4) || `${attributed.actor} event` } : attributed;
|
|
10534
10760
|
await control.appendSessionEvent(command.sessionId, eventId, bounded);
|
|
10535
10761
|
}
|
|
10536
|
-
function patchStats(value2) {
|
|
10537
|
-
if (typeof value2 !== "string") return {};
|
|
10538
|
-
let additions = 0;
|
|
10539
|
-
let deletions = 0;
|
|
10540
|
-
for (const line2 of value2.slice(0, 262144).split("\n")) {
|
|
10541
|
-
if (line2.startsWith("+++") || line2.startsWith("---")) continue;
|
|
10542
|
-
if (line2.startsWith("+")) additions += 1;
|
|
10543
|
-
else if (line2.startsWith("-")) deletions += 1;
|
|
10544
|
-
}
|
|
10545
|
-
return { ...additions ? { additions } : {}, ...deletions ? { deletions } : {} };
|
|
10546
|
-
}
|
|
10547
|
-
function searchResults(value2) {
|
|
10548
|
-
if (typeof value2 !== "string") return void 0;
|
|
10549
|
-
const results = value2.split("\n").flatMap((line2) => {
|
|
10550
|
-
const match = /^([^:\n]{1,1024}):(\d+):\s?(.*)$/.exec(line2);
|
|
10551
|
-
if (!match) return [];
|
|
10552
|
-
const lineNumber = Number(match[2]);
|
|
10553
|
-
const itemText = text3(match[3], 240);
|
|
10554
|
-
if (!Number.isSafeInteger(lineNumber) || lineNumber < 1) return [];
|
|
10555
|
-
return [{ path: match[1], line: lineNumber, ...itemText ? { text: itemText } : {} }];
|
|
10556
|
-
}).slice(0, 5);
|
|
10557
|
-
return results.length ? results : void 0;
|
|
10558
|
-
}
|
|
10559
|
-
function codeToolRequestPresentation(request3) {
|
|
10560
|
-
const input = request3.input;
|
|
10561
|
-
if (request3.tool === "sandbox.read") {
|
|
10562
|
-
const path = text3(input.path, 1024);
|
|
10563
|
-
if (!path) return void 0;
|
|
10564
|
-
const startLine = integer2(input.startLine);
|
|
10565
|
-
const endLine = integer2(input.endLine);
|
|
10566
|
-
return { kind: "read", path, ...startLine ? { startLine } : {}, ...endLine ? { endLine } : {} };
|
|
10567
|
-
}
|
|
10568
|
-
if (request3.tool === "sandbox.list") {
|
|
10569
|
-
const scope = text3(input.prefix, 1024);
|
|
10570
|
-
return { kind: "list", ...scope ? { scope } : {} };
|
|
10571
|
-
}
|
|
10572
|
-
if (request3.tool === "sandbox.search" || request3.tool === "sandbox.overview" || request3.tool === "sandbox.where_is" || request3.tool === "sandbox.who_imports" || request3.tool === "sandbox.who_touches") {
|
|
10573
|
-
const query = text3(input.query, 512);
|
|
10574
|
-
const scope = request3.tool === "sandbox.search" ? text3(input.prefix, 1024) : void 0;
|
|
10575
|
-
if (request3.tool === "sandbox.search" && !query) return void 0;
|
|
10576
|
-
return { kind: "query", ...query ? { query } : {}, ...scope ? { scope } : {} };
|
|
10577
|
-
}
|
|
10578
|
-
if (request3.tool === "sandbox.apply_patch") {
|
|
10579
|
-
return { kind: "patch", ...patchStats(input.patch) };
|
|
10580
|
-
}
|
|
10581
|
-
const recipeId = text3(input.recipeId, 120);
|
|
10582
|
-
return recipeId ? { kind: "recipe", recipeId } : void 0;
|
|
10583
|
-
}
|
|
10584
|
-
function codeToolResultPresentation(request3, response2) {
|
|
10585
|
-
const started = codeToolRequestPresentation(request3);
|
|
10586
|
-
if (!started || !response2.ok) return started;
|
|
10587
|
-
const details = record32(response2.details);
|
|
10588
|
-
if (started.kind === "read") {
|
|
10589
|
-
return {
|
|
10590
|
-
...started,
|
|
10591
|
-
...integer2(details?.startLine) ? { startLine: integer2(details?.startLine) } : {},
|
|
10592
|
-
...integer2(details?.endLine) ? { endLine: integer2(details?.endLine) } : {},
|
|
10593
|
-
...excerpt(response2.content) ? { excerpt: excerpt(response2.content) } : {}
|
|
10594
|
-
};
|
|
10595
|
-
}
|
|
10596
|
-
if (started.kind === "list") {
|
|
10597
|
-
const listed = response2.content.split("\n").filter((line2) => line2 && !line2.startsWith("\u2026") && !line2.startsWith("Workspace ")).map((line2) => text3(line2, 1024)).filter((line2) => Boolean(line2)).slice(0, 8);
|
|
10598
|
-
return {
|
|
10599
|
-
...started,
|
|
10600
|
-
...integer2(details?.count) !== void 0 ? { count: integer2(details?.count) } : {},
|
|
10601
|
-
...listed.length ? { paths: listed } : {}
|
|
10602
|
-
};
|
|
10603
|
-
}
|
|
10604
|
-
if (started.kind === "query") {
|
|
10605
|
-
const results = request3.tool === "sandbox.search" ? searchResults(response2.content) : void 0;
|
|
10606
|
-
const resultExcerpt = request3.tool === "sandbox.search" ? void 0 : excerpt(response2.content);
|
|
10607
|
-
return {
|
|
10608
|
-
...started,
|
|
10609
|
-
...integer2(details?.count) !== void 0 ? { count: integer2(details?.count) } : {},
|
|
10610
|
-
...results ? { results } : {},
|
|
10611
|
-
...resultExcerpt ? { excerpt: resultExcerpt } : {}
|
|
10612
|
-
};
|
|
10613
|
-
}
|
|
10614
|
-
if (started.kind === "patch") {
|
|
10615
|
-
return { ...started, ...paths(details?.paths) ? { paths: paths(details?.paths) } : {} };
|
|
10616
|
-
}
|
|
10617
|
-
const output = response2.content.replace(/^Recipe [^\n]*\.?\s*/u, "");
|
|
10618
|
-
return {
|
|
10619
|
-
...started,
|
|
10620
|
-
...integer2(details?.exitCode) !== void 0 ? { exitCode: integer2(details?.exitCode) } : {},
|
|
10621
|
-
...typeof details?.timedOut === "boolean" ? { timedOut: details.timedOut } : {},
|
|
10622
|
-
...typeof details?.outputLimitExceeded === "boolean" ? { outputLimitExceeded: details.outputLimitExceeded } : {},
|
|
10623
|
-
...excerpt(output, true) ? { excerpt: excerpt(output, true) } : {}
|
|
10624
|
-
};
|
|
10625
|
-
}
|
|
10626
10762
|
function codeRuntimeAcknowledgementGate(signal) {
|
|
10627
10763
|
let settle;
|
|
10628
10764
|
let settled = false;
|
|
@@ -10689,13 +10825,14 @@ function observeCodeRuntimeSessionSkills(command, skills, emit4) {
|
|
|
10689
10825
|
})
|
|
10690
10826
|
}));
|
|
10691
10827
|
}
|
|
10692
|
-
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,
|
|
10693
|
-
var
|
|
10694
|
-
"../harness/dist/chunk-
|
|
10828
|
+
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, record6, 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, DEFAULT_FAILURE_REASON2, cache, shortId, GRAPH_TOOLS, MAX_MEMORY_BODY, POSITIVE, digestRuntimeValue, runtimeErrorMessage, TheseusRuntimeEngine;
|
|
10829
|
+
var init_chunk_Q4NL5XO3 = __esm({
|
|
10830
|
+
"../harness/dist/chunk-Q4NL5XO3.js"() {
|
|
10695
10831
|
"use strict";
|
|
10696
10832
|
init_cjs_shims();
|
|
10697
|
-
|
|
10698
|
-
|
|
10833
|
+
init_chunk_FAN2R3GW();
|
|
10834
|
+
init_chunk_5LRYJKUI();
|
|
10835
|
+
init_chunk_U324RQ4N();
|
|
10699
10836
|
import_crypto = require("crypto");
|
|
10700
10837
|
import_promises5 = require("fs/promises");
|
|
10701
10838
|
import_path5 = require("path");
|
|
@@ -10777,7 +10914,7 @@ var init_chunk_4EPJJMFG = __esm({
|
|
|
10777
10914
|
code;
|
|
10778
10915
|
name = "CodeRuntimeControlError";
|
|
10779
10916
|
};
|
|
10780
|
-
|
|
10917
|
+
record6 = (value2) => value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
|
|
10781
10918
|
invalid = (part) => new CodeRuntimeControlError(`invalid Code runtime ${part} response`, 502, "invalid_response");
|
|
10782
10919
|
RESERVED = /* @__PURE__ */ new Set([".git", ".odla", ".wrangler", "node_modules", "dist", "coverage"]);
|
|
10783
10920
|
SECRET = /^(?:\.env(?:\..+)?|\.dev\.vars|credentials(?:\..+)?\.json|dev-token(?:\..+)?\.json)$/i;
|
|
@@ -10930,6 +11067,10 @@ Never claim a build or test passed unless odla_run_recipe returned that result.`
|
|
|
10930
11067
|
recipeId: "selector",
|
|
10931
11068
|
sourceDigest: "payload"
|
|
10932
11069
|
});
|
|
11070
|
+
DEFAULT_FAILURE_REASON2 = {
|
|
11071
|
+
"tool denied by CaMeL policy": "tool denied by CaMeL policy",
|
|
11072
|
+
"review sessions are read-only": "review session is read-only; workspace changes are not permitted"
|
|
11073
|
+
};
|
|
10933
11074
|
cache = /* @__PURE__ */ new Map();
|
|
10934
11075
|
shortId = (id2) => id2.slice(id2.indexOf(":") + 1);
|
|
10935
11076
|
GRAPH_TOOLS = /* @__PURE__ */ new Set([
|
|
@@ -10942,30 +11083,6 @@ Never claim a build or test passed unless odla_run_recipe returned that result.`
|
|
|
10942
11083
|
POSITIVE = (value2) => Number.isFinite(value2) && Number(value2) > 0 ? Number(value2) : void 0;
|
|
10943
11084
|
digestRuntimeValue = (value2) => `sha256:${(0, import_crypto4.createHash)("sha256").update(value2).digest("hex")}`;
|
|
10944
11085
|
runtimeErrorMessage = (value2) => value2 instanceof Error ? value2.message : String(value2);
|
|
10945
|
-
text3 = (value2, maximum) => {
|
|
10946
|
-
if (typeof value2 !== "string") return void 0;
|
|
10947
|
-
const bounded = value2.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, " ").trim();
|
|
10948
|
-
return bounded ? bounded.slice(0, maximum) : void 0;
|
|
10949
|
-
};
|
|
10950
|
-
integer2 = (value2) => Number.isSafeInteger(value2) && Number(value2) >= 0 ? Number(value2) : void 0;
|
|
10951
|
-
record32 = (value2) => value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : void 0;
|
|
10952
|
-
excerpt = (value2, tail = false) => {
|
|
10953
|
-
if (typeof value2 !== "string") return void 0;
|
|
10954
|
-
const safe = value2.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, " ");
|
|
10955
|
-
const source = (tail ? safe.slice(-1e4) : safe.slice(0, 1e4)).trim();
|
|
10956
|
-
if (!source) return void 0;
|
|
10957
|
-
const lines = source.split("\n").filter((line2) => line2.trim()).map((line2) => line2.slice(0, 240));
|
|
10958
|
-
const selected = tail ? lines.slice(-10) : lines.slice(0, 10);
|
|
10959
|
-
return text3(selected.join("\n"), 2400);
|
|
10960
|
-
};
|
|
10961
|
-
paths = (value2) => {
|
|
10962
|
-
if (!Array.isArray(value2)) return void 0;
|
|
10963
|
-
const items = value2.flatMap((item) => {
|
|
10964
|
-
const path = text3(item, 1024);
|
|
10965
|
-
return path ? [path] : [];
|
|
10966
|
-
}).slice(0, 12);
|
|
10967
|
-
return items.length ? items : void 0;
|
|
10968
|
-
};
|
|
10969
11086
|
TheseusRuntimeEngine = class {
|
|
10970
11087
|
constructor(options) {
|
|
10971
11088
|
this.options = options;
|
|
@@ -11201,36 +11318,11 @@ Never claim a build or test passed unless odla_run_recipe returned that result.`
|
|
|
11201
11318
|
}
|
|
11202
11319
|
/** Report every brokered effect as it starts and finishes. */
|
|
11203
11320
|
#observed(command, active, broker) {
|
|
11204
|
-
return {
|
|
11205
|
-
|
|
11206
|
-
|
|
11207
|
-
|
|
11208
|
-
|
|
11209
|
-
await this.#event(
|
|
11210
|
-
command,
|
|
11211
|
-
{
|
|
11212
|
-
type: "tool",
|
|
11213
|
-
phase: "started",
|
|
11214
|
-
tool: request3.tool,
|
|
11215
|
-
operationId,
|
|
11216
|
-
...startedPresentation ? { presentation: startedPresentation } : {}
|
|
11217
|
-
},
|
|
11218
|
-
active.conversationRefs
|
|
11219
|
-
).catch(() => void 0);
|
|
11220
|
-
const response2 = await broker.execute(context, request3);
|
|
11221
|
-
const completedPresentation = codeToolResultPresentation(request3, response2);
|
|
11222
|
-
await this.#event(command, {
|
|
11223
|
-
type: "tool",
|
|
11224
|
-
phase: "completed",
|
|
11225
|
-
tool: request3.tool,
|
|
11226
|
-
ok: response2.ok,
|
|
11227
|
-
durationMs: Date.now() - startedAt,
|
|
11228
|
-
operationId,
|
|
11229
|
-
...completedPresentation ? { presentation: completedPresentation } : {}
|
|
11230
|
-
}, active.conversationRefs).catch(() => void 0);
|
|
11231
|
-
return response2;
|
|
11232
|
-
}
|
|
11233
|
-
};
|
|
11321
|
+
return observedBroker({
|
|
11322
|
+
broker,
|
|
11323
|
+
operationIdFor: (requestId) => digestRuntimeValue(`${command.commandId}:${requestId}`),
|
|
11324
|
+
emit: (event) => this.#event(command, event, active.conversationRefs).catch(() => void 0)
|
|
11325
|
+
});
|
|
11234
11326
|
}
|
|
11235
11327
|
async #checkpoint(command) {
|
|
11236
11328
|
const active = this.#active.get(command.sessionId);
|
|
@@ -11267,8 +11359,8 @@ var init_node = __esm({
|
|
|
11267
11359
|
"../harness/dist/node.js"() {
|
|
11268
11360
|
"use strict";
|
|
11269
11361
|
init_cjs_shims();
|
|
11270
|
-
|
|
11271
|
-
|
|
11362
|
+
init_chunk_Q4NL5XO3();
|
|
11363
|
+
init_chunk_5LRYJKUI();
|
|
11272
11364
|
MEASURED_PREMIUM = Object.freeze({
|
|
11273
11365
|
/** 3 racers vs pure depth at equal budget: 21,044 / 7,936. */
|
|
11274
11366
|
racePerRacer: 0.55,
|
|
@@ -11510,6 +11602,19 @@ var init_code_runtime_config = __esm({
|
|
|
11510
11602
|
init_cjs_shims();
|
|
11511
11603
|
CODE_NODE_IMAGE = "node:24-alpine@sha256:a0b9bf06e4e6193cf7a0f58816cc935ff8c2a908f81e6f1a95432d679c54fbfd";
|
|
11512
11604
|
CODE_BUILD_RECIPES = Object.freeze([{
|
|
11605
|
+
id: "odla-code-gates",
|
|
11606
|
+
image: CODE_NODE_IMAGE,
|
|
11607
|
+
// Selects the repository's fast, no-capability gates from the same manifest
|
|
11608
|
+
// CI and `npm run preflight` read, so a new gate is picked up without a
|
|
11609
|
+
// second list to keep in sync. The container has no shell: this is argv.
|
|
11610
|
+
command: ["node", "scripts/recipe-gates.mjs"],
|
|
11611
|
+
timeoutMs: 18e4,
|
|
11612
|
+
maxOutputBytes: 1024 * 1024,
|
|
11613
|
+
cpus: 1,
|
|
11614
|
+
// check:secrets holds ~2,500 source files in memory at once.
|
|
11615
|
+
memory: "1g",
|
|
11616
|
+
pids: 128
|
|
11617
|
+
}, {
|
|
11513
11618
|
id: "odla-code-contracts",
|
|
11514
11619
|
image: CODE_NODE_IMAGE,
|
|
11515
11620
|
command: [
|
|
@@ -11691,20 +11796,20 @@ async function runCodeRuntime(input) {
|
|
|
11691
11796
|
}
|
|
11692
11797
|
}
|
|
11693
11798
|
function parseConnection(value2, appId, appEnv) {
|
|
11694
|
-
const root =
|
|
11695
|
-
const host =
|
|
11696
|
-
const offer =
|
|
11697
|
-
const binding =
|
|
11799
|
+
const root = record7(value2);
|
|
11800
|
+
const host = record7(root?.host);
|
|
11801
|
+
const offer = record7(root?.offer);
|
|
11802
|
+
const binding = record7(root?.binding);
|
|
11698
11803
|
if (!root || typeof root.token !== "string" || !/^odla_code_host_[0-9a-f]{64}$/.test(root.token) || typeof root.resumed !== "boolean" || !host || !/^chost_[0-9a-f]{32}$/.test(String(host.hostId)) || typeof host.name !== "string" || !offer || !Number.isSafeInteger(offer.slots) || !binding || typeof binding.appId !== "string" || !binding.appId || appId && binding.appId !== appId || binding.env !== appEnv || !Number.isSafeInteger(binding.generation)) {
|
|
11699
11804
|
throw new Error("connect Code host returned an invalid response");
|
|
11700
11805
|
}
|
|
11701
11806
|
return root;
|
|
11702
11807
|
}
|
|
11703
11808
|
function apiFailure(action2, status, value2) {
|
|
11704
|
-
const message2 =
|
|
11809
|
+
const message2 = record7(record7(value2)?.error)?.message;
|
|
11705
11810
|
return `${action2} failed (${status})${typeof message2 === "string" ? `: ${message2}` : ""}`;
|
|
11706
11811
|
}
|
|
11707
|
-
function
|
|
11812
|
+
function record7(value2) {
|
|
11708
11813
|
return value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
|
|
11709
11814
|
}
|
|
11710
11815
|
var import_node_fs18, import_node_os5, import_node_path18;
|
|
@@ -12299,6 +12404,14 @@ Usage:
|
|
|
12299
12404
|
odla-ai ai models [--config odla.config.mjs] [--env dev] [--provider <id>] [--json]
|
|
12300
12405
|
odla-ai config <diff|plan> [--config odla.config.mjs] [--email <odla-account>] [--json]
|
|
12301
12406
|
odla-ai config apply --plan <plan.json> [--idempotency-key <key>] [--email <odla-account>] [--json]
|
|
12407
|
+
odla-ai promotion plan --file <promotion-plan.json> [--env dev] [--json]
|
|
12408
|
+
odla-ai promotion inspect <plan-id> [--env dev] [--json]
|
|
12409
|
+
odla-ai promotion status <plan-id> [--env dev] [--json]
|
|
12410
|
+
odla-ai promotion apply <plan-id> --approval <approval-id> [--idempotency-key <key>] [--env dev] [--json]
|
|
12411
|
+
odla-ai promotion rollback <plan-id> --approval <approval-id> [--idempotency-key <key>] [--env dev] [--json]
|
|
12412
|
+
odla-ai promotion next <plan-id> <operation-id> [--env dev] [--json]
|
|
12413
|
+
odla-ai promotion record <plan-id> <operation-id> <step-id> --file <step-receipt.json> [--env dev] [--json]
|
|
12414
|
+
odla-ai promotion cancel <plan-id> <operation-id> [--env dev] [--json]
|
|
12302
12415
|
odla-ai operations get <operation-id> [--json]
|
|
12303
12416
|
odla-ai operations wait <operation-id> [--interval <seconds>] [--timeout <seconds>] [--json]
|
|
12304
12417
|
odla-ai calendar status [--env dev] [--email <odla-account>] [--json]
|
|
@@ -12467,6 +12580,11 @@ Commands:
|
|
|
12467
12580
|
init Create a generic odla.config.mjs plus starter schema/rules files.
|
|
12468
12581
|
doctor Validate and summarize the project config without network calls.
|
|
12469
12582
|
config Diff Registry intent, freeze a CAS-bound plan, and conditionally apply its safe actions.
|
|
12583
|
+
promotion Plan and inspect exact selective-release bundles without target
|
|
12584
|
+
mutation, then queue and resume a human-approved apply or rollback
|
|
12585
|
+
from an enrolled device. Each target step is leased and receipt-
|
|
12586
|
+
journaled; approval remains bound to the immutable plan digest,
|
|
12587
|
+
target set, action, and expiry, so every mismatch fails closed.
|
|
12470
12588
|
operations Inspect or wait on one exact, durable config-operation receipt.
|
|
12471
12589
|
calendar Inspect, connect, or disconnect the live Google booking connection.
|
|
12472
12590
|
app Archive (suspend, data retained), restore, export, import, or
|
|
@@ -13376,17 +13494,17 @@ function collectEntityFields(entity, parsed, allowClear) {
|
|
|
13376
13494
|
if (entity === "task" && fields.column === "ready") fields.column = "todo";
|
|
13377
13495
|
return fields;
|
|
13378
13496
|
}
|
|
13379
|
-
function statusCol(entity,
|
|
13380
|
-
if (entity === "bug") return `${
|
|
13497
|
+
function statusCol(entity, record12) {
|
|
13498
|
+
if (entity === "bug") return `${record12.status ?? ""}/${record12.severity ?? ""}`;
|
|
13381
13499
|
if (entity === "task") {
|
|
13382
|
-
const state2 =
|
|
13383
|
-
return
|
|
13500
|
+
const state2 = record12.column === "todo" ? "ready" : String(record12.column ?? "");
|
|
13501
|
+
return record12.revision ? `${state2}; r${record12.revision}` : state2;
|
|
13384
13502
|
}
|
|
13385
|
-
return String(
|
|
13503
|
+
return String(record12.status ?? "");
|
|
13386
13504
|
}
|
|
13387
|
-
function referenceMarkup(entity,
|
|
13388
|
-
const label = (
|
|
13389
|
-
return `@[${label}](pm:${entity}/${
|
|
13505
|
+
function referenceMarkup(entity, record12) {
|
|
13506
|
+
const label = (record12.title?.trim() || `${entity} ${record12.id}`).replaceAll("]", ")");
|
|
13507
|
+
return `@[${label}](pm:${entity}/${record12.id})`;
|
|
13390
13508
|
}
|
|
13391
13509
|
function studioRecordUrl(ctx, entity, id2) {
|
|
13392
13510
|
return new URL(
|
|
@@ -13394,13 +13512,13 @@ function studioRecordUrl(ctx, entity, id2) {
|
|
|
13394
13512
|
ctx.platformUrl
|
|
13395
13513
|
).href;
|
|
13396
13514
|
}
|
|
13397
|
-
function studioRecordLink(ctx, entity,
|
|
13398
|
-
const label = (
|
|
13399
|
-
return `[${label}](${studioRecordUrl(ctx, entity,
|
|
13515
|
+
function studioRecordLink(ctx, entity, record12) {
|
|
13516
|
+
const label = (record12.title?.trim() || `${entity} ${record12.id}`).replaceAll("]", ")");
|
|
13517
|
+
return `[${label}](${studioRecordUrl(ctx, entity, record12.id)})`;
|
|
13400
13518
|
}
|
|
13401
|
-
function printRecord(ctx, entity,
|
|
13519
|
+
function printRecord(ctx, entity, record12) {
|
|
13402
13520
|
ctx.out.log(
|
|
13403
|
-
`${
|
|
13521
|
+
`${record12.id} [${statusCol(entity, record12)}] ${record12.appId} ${studioRecordLink(ctx, entity, record12)}`
|
|
13404
13522
|
);
|
|
13405
13523
|
}
|
|
13406
13524
|
function emit2(ctx, value2, human) {
|
|
@@ -13504,8 +13622,8 @@ async function pmAdd(ctx, entity, parsed) {
|
|
|
13504
13622
|
input,
|
|
13505
13623
|
mutationId: writeMutationId2(parsed)
|
|
13506
13624
|
});
|
|
13507
|
-
const
|
|
13508
|
-
emit2(ctx, res, () => ctx.out.log(`created ${entity}: ${studioRecordLink(ctx, entity,
|
|
13625
|
+
const record12 = { id: res.id, appId, title: String(input.title) };
|
|
13626
|
+
emit2(ctx, res, () => ctx.out.log(`created ${entity}: ${studioRecordLink(ctx, entity, record12)}`));
|
|
13509
13627
|
}
|
|
13510
13628
|
function looksLikeUuidPrefix(value2) {
|
|
13511
13629
|
if (!UUID_PREFIX.test(value2) || !/[0-9a-f]/i.test(value2)) return false;
|
|
@@ -13523,7 +13641,7 @@ async function resolvePmId(ctx, entity, supplied) {
|
|
|
13523
13641
|
"GET",
|
|
13524
13642
|
`/${entity}?limit=${limit}&offset=${offset}`
|
|
13525
13643
|
);
|
|
13526
|
-
matches.push(...page2.records.map((
|
|
13644
|
+
matches.push(...page2.records.map((record12) => record12.id).filter((id2) => id2.toLowerCase().startsWith(prefix)));
|
|
13527
13645
|
offset += page2.records.length;
|
|
13528
13646
|
if (matches.length > 1 || page2.records.length === 0 || offset >= page2.total) break;
|
|
13529
13647
|
}
|
|
@@ -13537,17 +13655,17 @@ async function resolvePmId(ctx, entity, supplied) {
|
|
|
13537
13655
|
}
|
|
13538
13656
|
async function pmGet(ctx, entity, id2) {
|
|
13539
13657
|
const resolved = await resolvePmId(ctx, entity, id2);
|
|
13540
|
-
const { record:
|
|
13541
|
-
emit2(ctx,
|
|
13658
|
+
const { record: record12 } = await pmRequest(ctx, "GET", `/${entity}/${encodeURIComponent(resolved)}`);
|
|
13659
|
+
emit2(ctx, record12, () => printRecord(ctx, entity, record12));
|
|
13542
13660
|
}
|
|
13543
13661
|
async function pmReference(ctx, entity, id2) {
|
|
13544
|
-
const { record:
|
|
13662
|
+
const { record: record12 } = await pmRequest(
|
|
13545
13663
|
ctx,
|
|
13546
13664
|
"GET",
|
|
13547
13665
|
`/${entity}/${encodeURIComponent(id2)}`
|
|
13548
13666
|
);
|
|
13549
|
-
const markup = referenceMarkup(entity,
|
|
13550
|
-
emit2(ctx, { kind: `pm:${entity}`, id:
|
|
13667
|
+
const markup = referenceMarkup(entity, record12);
|
|
13668
|
+
emit2(ctx, { kind: `pm:${entity}`, id: record12.id, label: record12.title ?? "", markup }, () => {
|
|
13551
13669
|
ctx.out.log(markup);
|
|
13552
13670
|
});
|
|
13553
13671
|
}
|
|
@@ -13626,16 +13744,16 @@ var init_pm_actions = __esm({
|
|
|
13626
13744
|
});
|
|
13627
13745
|
|
|
13628
13746
|
// src/pm-lean.ts
|
|
13629
|
-
function leanRecord(entity,
|
|
13747
|
+
function leanRecord(entity, record12) {
|
|
13630
13748
|
const out = {};
|
|
13631
13749
|
for (const key of [...COMMON, ...PER_ENTITY[entity]]) {
|
|
13632
|
-
const value2 =
|
|
13750
|
+
const value2 = record12[key];
|
|
13633
13751
|
if (value2 !== void 0 && value2 !== null) out[key] = value2;
|
|
13634
13752
|
}
|
|
13635
13753
|
return out;
|
|
13636
13754
|
}
|
|
13637
13755
|
function leanRecords(entity, records, verbose) {
|
|
13638
|
-
return verbose ? records : records.map((
|
|
13756
|
+
return verbose ? records : records.map((record12) => leanRecord(entity, record12));
|
|
13639
13757
|
}
|
|
13640
13758
|
var COMMON, PER_ENTITY;
|
|
13641
13759
|
var init_pm_lean = __esm({
|
|
@@ -13687,8 +13805,8 @@ async function pmNext(ctx, parsed) {
|
|
|
13687
13805
|
// One request for both live columns; the split below is over open work only.
|
|
13688
13806
|
listFiltered(ctx, "task", appId, projectId, { column: `${READY_COLUMN},doing` })
|
|
13689
13807
|
]);
|
|
13690
|
-
const ready = tasks.filter((
|
|
13691
|
-
const doing = tasks.filter((
|
|
13808
|
+
const ready = tasks.filter((record12) => record12.column === READY_COLUMN);
|
|
13809
|
+
const doing = tasks.filter((record12) => record12.column === "doing");
|
|
13692
13810
|
const guidance = !goals.length ? "discuss alignment with the user before creating or claiming project work" : !ready.length ? 'refine a linked Backlog task and mark it Ready with "pm task ready <id>"' : `claim the top Ready task in one call: odla-ai pm start --app ${appId}`;
|
|
13693
13811
|
const monitor = `odla-ai pm watch --app ${appId} --jsonl`;
|
|
13694
13812
|
const result = {
|
|
@@ -13709,7 +13827,7 @@ async function pmNext(ctx, parsed) {
|
|
|
13709
13827
|
]) {
|
|
13710
13828
|
ctx.out.log(`${label}:`);
|
|
13711
13829
|
if (!records.length) ctx.out.log("- (none)");
|
|
13712
|
-
else for (const
|
|
13830
|
+
else for (const record12 of records) printRecord(ctx, entity, record12);
|
|
13713
13831
|
}
|
|
13714
13832
|
ctx.out.log(`next: ${guidance}`);
|
|
13715
13833
|
ctx.out.log(`monitor: ${monitor}`);
|
|
@@ -13748,7 +13866,7 @@ async function pmHandoff(ctx, parsed) {
|
|
|
13748
13866
|
]) {
|
|
13749
13867
|
ctx.out.log(`${label}:`);
|
|
13750
13868
|
if (!records.length) ctx.out.log("- (none)");
|
|
13751
|
-
else for (const
|
|
13869
|
+
else for (const record12 of records) printRecord(ctx, entity, record12);
|
|
13752
13870
|
}
|
|
13753
13871
|
ctx.out.log(`monitor: ${monitor}`);
|
|
13754
13872
|
});
|
|
@@ -13849,14 +13967,14 @@ var init_pm_start = __esm({
|
|
|
13849
13967
|
|
|
13850
13968
|
// src/pm-links.ts
|
|
13851
13969
|
async function pmLink(ctx, entity, id2) {
|
|
13852
|
-
const { record:
|
|
13970
|
+
const { record: record12 } = await pmRequest(
|
|
13853
13971
|
ctx,
|
|
13854
13972
|
"GET",
|
|
13855
13973
|
`/${entity}/${encodeURIComponent(id2)}`
|
|
13856
13974
|
);
|
|
13857
|
-
const url = studioRecordUrl(ctx, entity,
|
|
13858
|
-
const markdown = studioRecordLink(ctx, entity,
|
|
13859
|
-
emit2(ctx, { kind: entity, id:
|
|
13975
|
+
const url = studioRecordUrl(ctx, entity, record12.id);
|
|
13976
|
+
const markdown = studioRecordLink(ctx, entity, record12);
|
|
13977
|
+
emit2(ctx, { kind: entity, id: record12.id, label: record12.title ?? "", url, markdown }, () => {
|
|
13860
13978
|
ctx.out.log(markdown);
|
|
13861
13979
|
});
|
|
13862
13980
|
}
|
|
@@ -14011,16 +14129,16 @@ async function page(ctx, appId, cursor) {
|
|
|
14011
14129
|
}
|
|
14012
14130
|
return data;
|
|
14013
14131
|
}
|
|
14014
|
-
function recordState(
|
|
14015
|
-
if (
|
|
14016
|
-
return String(
|
|
14132
|
+
function recordState(record12) {
|
|
14133
|
+
if (record12.column) return record12.column === "todo" ? "ready" : record12.column;
|
|
14134
|
+
return String(record12.status ?? "");
|
|
14017
14135
|
}
|
|
14018
14136
|
function eventRecord(event) {
|
|
14019
14137
|
return event.payload.payload;
|
|
14020
14138
|
}
|
|
14021
14139
|
function eventLabel(event) {
|
|
14022
|
-
const
|
|
14023
|
-
if (
|
|
14140
|
+
const record12 = eventRecord(event);
|
|
14141
|
+
if (record12) return String(record12.title ?? event.payload.entityId);
|
|
14024
14142
|
const body = event.payload.message?.body?.replace(/\s+/g, " ").trim();
|
|
14025
14143
|
return body || event.payload.entityId;
|
|
14026
14144
|
}
|
|
@@ -14028,10 +14146,10 @@ function report3(ctx, parsed, result) {
|
|
|
14028
14146
|
if (ctx.json) ctx.out.log(JSON.stringify(result, null, 2));
|
|
14029
14147
|
else if (parsed.options.jsonl !== true && result.found) {
|
|
14030
14148
|
for (const event of result.events ?? []) {
|
|
14031
|
-
const
|
|
14032
|
-
const state2 =
|
|
14149
|
+
const record12 = eventRecord(event);
|
|
14150
|
+
const state2 = record12 ? recordState(record12) : "comment";
|
|
14033
14151
|
ctx.out.log(
|
|
14034
|
-
`${event.id} ${event.type} ${state2}${
|
|
14152
|
+
`${event.id} ${event.type} ${state2}${record12?.revision ? `; r${record12.revision}` : ""} ${eventLabel(event)}`
|
|
14035
14153
|
);
|
|
14036
14154
|
}
|
|
14037
14155
|
}
|
|
@@ -14105,8 +14223,8 @@ async function pmWatch(ctx, parsed) {
|
|
|
14105
14223
|
}
|
|
14106
14224
|
firstSuccess = false;
|
|
14107
14225
|
const matching = current.events.filter((event) => {
|
|
14108
|
-
const
|
|
14109
|
-
const state2 =
|
|
14226
|
+
const record12 = eventRecord(event);
|
|
14227
|
+
const state2 = record12 ? recordState(record12).toLowerCase() : "";
|
|
14110
14228
|
return (!entity || event.payload.entityKind === entity) && (!action2 || event.payload.action === action2) && (!wantedState || state2 === wantedState || wantedState === "todo" && state2 === "ready") && (!by || event.actor.id === by) && (!self || event.actor.id !== self);
|
|
14111
14229
|
});
|
|
14112
14230
|
for (const event of matching) {
|
|
@@ -14594,17 +14712,17 @@ async function platformStatus(parsed, deps) {
|
|
|
14594
14712
|
}
|
|
14595
14713
|
}
|
|
14596
14714
|
function isPlatformStatus(value2) {
|
|
14597
|
-
if (!
|
|
14598
|
-
if (!
|
|
14599
|
-
if (!
|
|
14715
|
+
if (!record8(value2) || value2.schemaVersion !== "odla.platform-status/v1") return false;
|
|
14716
|
+
if (!record8(value2.verdict) || !Array.isArray(value2.verdict.reasons)) return false;
|
|
14717
|
+
if (!record8(value2.catalog) || !record8(value2.summary)) return false;
|
|
14600
14718
|
return Array.isArray(value2.services) && Array.isArray(value2.nextActions);
|
|
14601
14719
|
}
|
|
14602
14720
|
function apiMessage(value2) {
|
|
14603
|
-
if (!
|
|
14604
|
-
const error =
|
|
14721
|
+
if (!record8(value2)) return "request failed";
|
|
14722
|
+
const error = record8(value2.error) ? value2.error : value2;
|
|
14605
14723
|
return typeof error.message === "string" ? error.message : typeof error.code === "string" ? error.code : "request failed";
|
|
14606
14724
|
}
|
|
14607
|
-
function
|
|
14725
|
+
function record8(value2) {
|
|
14608
14726
|
return !!value2 && typeof value2 === "object" && !Array.isArray(value2);
|
|
14609
14727
|
}
|
|
14610
14728
|
var init_platform_command = __esm({
|
|
@@ -14656,7 +14774,7 @@ function statusVerdict(reads) {
|
|
|
14656
14774
|
severity: "degraded"
|
|
14657
14775
|
});
|
|
14658
14776
|
}
|
|
14659
|
-
const performance =
|
|
14777
|
+
const performance = record9(reads.liveSync.body.performance) ? reads.liveSync.body.performance : null;
|
|
14660
14778
|
if (performance?.status === "unavailable") {
|
|
14661
14779
|
reasons.push({
|
|
14662
14780
|
source: "liveSync",
|
|
@@ -14737,7 +14855,7 @@ function statusVerdict(reads) {
|
|
|
14737
14855
|
reasons
|
|
14738
14856
|
};
|
|
14739
14857
|
}
|
|
14740
|
-
function
|
|
14858
|
+
function record9(value2) {
|
|
14741
14859
|
return Boolean(value2) && typeof value2 === "object" && !Array.isArray(value2);
|
|
14742
14860
|
}
|
|
14743
14861
|
function numeric2(value2) {
|
|
@@ -14771,7 +14889,7 @@ function printO11yStatus(status, out) {
|
|
|
14771
14889
|
out.log(
|
|
14772
14890
|
`o11y status ${status.scope.appId}/${status.scope.env} (${status.scope.minutes}m)`
|
|
14773
14891
|
);
|
|
14774
|
-
const routes = Array.isArray(status.application.body.routes) ? status.application.body.routes.filter(
|
|
14892
|
+
const routes = Array.isArray(status.application.body.routes) ? status.application.body.routes.filter(record10) : [];
|
|
14775
14893
|
const requests = routes.reduce(
|
|
14776
14894
|
(total, row) => total + numeric3(row.requests),
|
|
14777
14895
|
0
|
|
@@ -14783,39 +14901,39 @@ function printO11yStatus(status, out) {
|
|
|
14783
14901
|
out.log(
|
|
14784
14902
|
`application ${status.application.httpStatus} ${requests} requests ${errors} errors`
|
|
14785
14903
|
);
|
|
14786
|
-
const versions = Array.isArray(status.applicationVersions.body.rows) ? status.applicationVersions.body.rows.filter(
|
|
14904
|
+
const versions = Array.isArray(status.applicationVersions.body.rows) ? status.applicationVersions.body.rows.filter(record10) : [];
|
|
14787
14905
|
out.log(
|
|
14788
14906
|
`application-versions ${status.applicationVersions.httpStatus} ${versions.length ? versions.slice(0, 5).map(
|
|
14789
14907
|
(row) => `${String(row.value || "(unattributed)")}:${numeric3(row.requests)}`
|
|
14790
14908
|
).join(", ") : "none observed"}`
|
|
14791
14909
|
);
|
|
14792
14910
|
out.log(liveSyncLine(status.liveSync));
|
|
14793
|
-
const canaryDurations =
|
|
14911
|
+
const canaryDurations = record10(status.canary.body.durationsMs) ? status.canary.body.durationsMs : {};
|
|
14794
14912
|
out.log(
|
|
14795
14913
|
`canary ${status.canary.httpStatus} ${String(status.canary.body.status ?? status.canary.body.error ?? "unavailable")} ${optionalNumeric(canaryDurations.publishToVisibleMs)} publish-to-visible`
|
|
14796
14914
|
);
|
|
14797
|
-
const collectorIngest =
|
|
14798
|
-
const collectorStorage =
|
|
14915
|
+
const collectorIngest = record10(status.collector.body.ingest) ? status.collector.body.ingest : {};
|
|
14916
|
+
const collectorStorage = record10(collectorIngest.storage) ? collectorIngest.storage : {};
|
|
14799
14917
|
out.log(
|
|
14800
14918
|
`collector ${status.collector.httpStatus} ${String(status.collector.body.status ?? status.collector.body.error ?? "unavailable")} ${numeric3(collectorStorage.affectedPoints)} affected points`
|
|
14801
14919
|
);
|
|
14802
|
-
const providerMetrics =
|
|
14803
|
-
const providerCapacity =
|
|
14804
|
-
const workerMemory =
|
|
14920
|
+
const providerMetrics = record10(status.provider.body.metrics) ? status.provider.body.metrics : {};
|
|
14921
|
+
const providerCapacity = record10(status.provider.body.capacity) ? status.provider.body.capacity : {};
|
|
14922
|
+
const workerMemory = record10(providerCapacity.memory) ? providerCapacity.memory : {};
|
|
14805
14923
|
out.log(
|
|
14806
14924
|
`cloudflare ${status.provider.httpStatus} ${String(status.provider.body.status ?? status.provider.body.error ?? "unavailable")} ${numeric3(providerMetrics.requests)} invocations ${numeric3(providerMetrics.errors)} runtime errors ${optionalBytes(workerMemory.headroomBytes)} isolate memory headroom`
|
|
14807
14925
|
);
|
|
14808
14926
|
for (const line2 of providerCapacityLines(status.providerCapacity)) {
|
|
14809
14927
|
out.log(line2);
|
|
14810
14928
|
}
|
|
14811
|
-
const coverage =
|
|
14812
|
-
const coverageCounts =
|
|
14813
|
-
const coverageBudget =
|
|
14929
|
+
const coverage = record10(status.providerReconciliation.body.comparison) ? status.providerReconciliation.body.comparison : {};
|
|
14930
|
+
const coverageCounts = record10(status.providerReconciliation.body.counts) ? status.providerReconciliation.body.counts : {};
|
|
14931
|
+
const coverageBudget = record10(status.providerReconciliation.body.budget) ? status.providerReconciliation.body.budget : {};
|
|
14814
14932
|
out.log(
|
|
14815
14933
|
`request-coverage ${status.providerReconciliation.httpStatus} ${String(status.providerReconciliation.body.status ?? status.providerReconciliation.body.error ?? "unavailable")} ${optionalPercent(coverage.applicationCoverage)} application/provider ${numeric3(coverageCounts.applicationRequests)}/${numeric3(coverageCounts.providerRequests)} requests \xB1${optionalPercent(coverageBudget.maxRelativeError)} budget`
|
|
14816
14934
|
);
|
|
14817
14935
|
const providerPoints = Array.isArray(status.providerHistory.body.points) ? status.providerHistory.body.points.length : 0;
|
|
14818
|
-
const providerFreshness =
|
|
14936
|
+
const providerFreshness = record10(status.providerHistory.body.freshness) ? status.providerHistory.body.freshness : {};
|
|
14819
14937
|
out.log(
|
|
14820
14938
|
`cloudflare-history ${status.providerHistory.httpStatus} ${String(status.providerHistory.body.status ?? status.providerHistory.body.error ?? "unavailable")} ${providerPoints} snapshots ${optionalAge(providerFreshness.ageMs)} old`
|
|
14821
14939
|
);
|
|
@@ -14824,17 +14942,17 @@ function printO11yStatus(status, out) {
|
|
|
14824
14942
|
);
|
|
14825
14943
|
}
|
|
14826
14944
|
function providerCapacityLines(read3) {
|
|
14827
|
-
const resources =
|
|
14828
|
-
const durableObjects =
|
|
14829
|
-
const periodic =
|
|
14830
|
-
const storage =
|
|
14831
|
-
const d1 =
|
|
14832
|
-
const d1Activity =
|
|
14833
|
-
const d1Storage =
|
|
14834
|
-
const d1Latency =
|
|
14835
|
-
const r2 =
|
|
14836
|
-
const r2Operations =
|
|
14837
|
-
const r2Storage =
|
|
14945
|
+
const resources = record10(read3.body.resources) ? read3.body.resources : {};
|
|
14946
|
+
const durableObjects = record10(resources.durableObjects) ? resources.durableObjects : {};
|
|
14947
|
+
const periodic = record10(durableObjects.periodic) ? durableObjects.periodic : {};
|
|
14948
|
+
const storage = record10(durableObjects.sqliteStorage) ? durableObjects.sqliteStorage : {};
|
|
14949
|
+
const d1 = record10(resources.d1) ? resources.d1 : {};
|
|
14950
|
+
const d1Activity = record10(d1.activity) ? d1.activity : {};
|
|
14951
|
+
const d1Storage = record10(d1.storage) ? d1.storage : {};
|
|
14952
|
+
const d1Latency = record10(d1Activity.latency) ? d1Activity.latency : {};
|
|
14953
|
+
const r2 = record10(resources.r2) ? resources.r2 : {};
|
|
14954
|
+
const r2Operations = record10(r2.operations) ? r2.operations : {};
|
|
14955
|
+
const r2Storage = record10(r2.storage) ? r2.storage : {};
|
|
14838
14956
|
const status = String(
|
|
14839
14957
|
read3.body.status ?? read3.body.error ?? "unavailable"
|
|
14840
14958
|
);
|
|
@@ -14845,11 +14963,11 @@ function providerCapacityLines(read3) {
|
|
|
14845
14963
|
];
|
|
14846
14964
|
}
|
|
14847
14965
|
function liveSyncLine(read3) {
|
|
14848
|
-
const performance =
|
|
14849
|
-
const commitToSend =
|
|
14966
|
+
const performance = record10(read3.body.performance) ? read3.body.performance : {};
|
|
14967
|
+
const commitToSend = record10(performance.commitToSend) ? performance.commitToSend : {};
|
|
14850
14968
|
return `live-sync ${read3.httpStatus} ${String(read3.body.status ?? read3.body.error ?? "unavailable")} ${numeric3(read3.body.activeConnections)} active ${optionalNumeric(commitToSend.p95)} commit-to-send p95 ${numeric3(performance.sendFailures)} send failures`;
|
|
14851
14969
|
}
|
|
14852
|
-
function
|
|
14970
|
+
function record10(value2) {
|
|
14853
14971
|
return Boolean(value2) && typeof value2 === "object" && !Array.isArray(value2);
|
|
14854
14972
|
}
|
|
14855
14973
|
function numeric3(value2) {
|
|
@@ -15197,7 +15315,7 @@ async function monitorCommand(parsed, deps = {}) {
|
|
|
15197
15315
|
if (action2 === "plan" || action2 === "apply") {
|
|
15198
15316
|
const desired = monitoringWireConfig(context.cfg, env);
|
|
15199
15317
|
const live = await request2(`${base}?env=${encodeURIComponent(env)}`, { headers }, doFetch);
|
|
15200
|
-
const currentRevision =
|
|
15318
|
+
const currentRevision = record11(live.config) ? string(live.config.revision) : null;
|
|
15201
15319
|
const changed = currentRevision !== desired.revision;
|
|
15202
15320
|
const plan = {
|
|
15203
15321
|
schemaVersion: 1,
|
|
@@ -15242,7 +15360,7 @@ async function monitorCommand(parsed, deps = {}) {
|
|
|
15242
15360
|
headers
|
|
15243
15361
|
}, doFetch);
|
|
15244
15362
|
emit3(result2, jsonOutput, out, () => {
|
|
15245
|
-
const run =
|
|
15363
|
+
const run = record11(result2.run) ? result2.run : {};
|
|
15246
15364
|
out.log(`monitor run ${appId}/${env}/${probeId}: ${string(run.outcome) ?? "unknown"}${run.failure_code ? ` (${String(run.failure_code)})` : ""}`);
|
|
15247
15365
|
});
|
|
15248
15366
|
return;
|
|
@@ -15267,12 +15385,12 @@ async function request2(url, init, doFetch) {
|
|
|
15267
15385
|
let body = {};
|
|
15268
15386
|
try {
|
|
15269
15387
|
const parsed = text4 ? JSON.parse(text4) : {};
|
|
15270
|
-
body =
|
|
15388
|
+
body = record11(parsed) ? parsed : { value: parsed };
|
|
15271
15389
|
} catch {
|
|
15272
15390
|
body = { message: text4.slice(0, 500) };
|
|
15273
15391
|
}
|
|
15274
15392
|
if (!response2.ok) {
|
|
15275
|
-
const error =
|
|
15393
|
+
const error = record11(body.error) ? body.error : body;
|
|
15276
15394
|
throw new Error(string(error.message) ?? string(error.code) ?? `monitor request failed (${response2.status})`);
|
|
15277
15395
|
}
|
|
15278
15396
|
return body;
|
|
@@ -15280,7 +15398,7 @@ async function request2(url, init, doFetch) {
|
|
|
15280
15398
|
function printRead(action2, appId, env, result, out) {
|
|
15281
15399
|
if (action2 === "status") {
|
|
15282
15400
|
out.log(`monitor status ${appId}/${env}: ${String(result.overall ?? (result.configured === false ? "not configured" : "unknown"))}`);
|
|
15283
|
-
const slos = Array.isArray(result.slos) ? result.slos.filter(
|
|
15401
|
+
const slos = Array.isArray(result.slos) ? result.slos.filter(record11) : [];
|
|
15284
15402
|
for (const slo of slos) out.log(`slo ${String(slo.id)} ${String(slo.state)} ${percent(slo.observed)} observed ${percent(slo.budgetRemaining)} budget remaining`);
|
|
15285
15403
|
const incidents = Array.isArray(result.openIncidents) ? result.openIncidents.length : 0;
|
|
15286
15404
|
const gaps = Array.isArray(result.monitoringGaps) ? result.monitoringGaps.length : 0;
|
|
@@ -15289,20 +15407,20 @@ function printRead(action2, appId, env, result, out) {
|
|
|
15289
15407
|
return;
|
|
15290
15408
|
}
|
|
15291
15409
|
if (action2 === "incidents") {
|
|
15292
|
-
const incidents = Array.isArray(result.incidents) ? result.incidents.filter(
|
|
15410
|
+
const incidents = Array.isArray(result.incidents) ? result.incidents.filter(record11) : [];
|
|
15293
15411
|
out.log(`monitor incidents ${appId}/${env}: ${incidents.length}`);
|
|
15294
15412
|
for (const incident2 of incidents) out.log(`${String(incident2.state)} ${String(incident2.kind)} ${String(incident2.slo_id)} ${new Date(Number(incident2.opened_at)).toISOString()}`);
|
|
15295
15413
|
return;
|
|
15296
15414
|
}
|
|
15297
15415
|
out.log(`monitor report ${appId}/${env}: ${String(result.period)} ${String(result.overall)}`);
|
|
15298
|
-
const probes = Array.isArray(result.probes) ? result.probes.filter(
|
|
15416
|
+
const probes = Array.isArray(result.probes) ? result.probes.filter(record11) : [];
|
|
15299
15417
|
for (const probe of probes) out.log(`probe ${String(probe.id)} ${Number(probe.good)} good ${Number(probe.bad)} bad ${Number(probe.unknown)} unknown`);
|
|
15300
15418
|
}
|
|
15301
15419
|
function emit3(value2, json, out, human) {
|
|
15302
15420
|
if (json) out.log(JSON.stringify(value2, null, 2));
|
|
15303
15421
|
else human();
|
|
15304
15422
|
}
|
|
15305
|
-
function
|
|
15423
|
+
function record11(value2) {
|
|
15306
15424
|
return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
|
|
15307
15425
|
}
|
|
15308
15426
|
function string(value2) {
|
|
@@ -15870,6 +15988,139 @@ var init_provision = __esm({
|
|
|
15870
15988
|
}
|
|
15871
15989
|
});
|
|
15872
15990
|
|
|
15991
|
+
// src/security-command-context.ts
|
|
15992
|
+
async function hostedSecurityContext(parsed, dependencies) {
|
|
15993
|
+
const configPath = stringOpt(parsed.options.config) ?? "odla.config.mjs";
|
|
15994
|
+
const cfg = await loadProjectConfig(configPath);
|
|
15995
|
+
const env = stringOpt(parsed.options.env) ?? (cfg.envs.includes("dev") ? "dev" : cfg.envs[0]);
|
|
15996
|
+
if (!env || !cfg.envs.includes(env)) {
|
|
15997
|
+
throw new Error(`env "${env ?? ""}" is not declared in ${configPath}`);
|
|
15998
|
+
}
|
|
15999
|
+
const platform = platformAudience(stringOpt(parsed.options.platform) ?? cfg.platformUrl);
|
|
16000
|
+
if (platformAudience(cfg.platformUrl) !== platform) {
|
|
16001
|
+
throw new Error("--platform cannot reuse a project developer token from another platform; update odla.config.mjs and authenticate there");
|
|
16002
|
+
}
|
|
16003
|
+
const doFetch = dependencies.fetch ?? fetch;
|
|
16004
|
+
const stdout = dependencies.stdout ?? console;
|
|
16005
|
+
const open = parsed.options.open === false ? false : parsed.options.open === true ? true : void 0;
|
|
16006
|
+
const token = await getDeveloperToken(
|
|
16007
|
+
cfg,
|
|
16008
|
+
{ configPath, email: stringOpt(parsed.options.email), open, openApprovalUrl: dependencies.openUrl },
|
|
16009
|
+
doFetch,
|
|
16010
|
+
stdout,
|
|
16011
|
+
{ optionalProjectCapabilities: ["app.manage"] }
|
|
16012
|
+
);
|
|
16013
|
+
return { platform, token, appId: cfg.app.id, env, fetch: doFetch, stdout };
|
|
16014
|
+
}
|
|
16015
|
+
function requiredSecurityPositional(parsed, index, label) {
|
|
16016
|
+
const value2 = parsed.positionals[index];
|
|
16017
|
+
if (!value2) throw new Error(`${label} is required`);
|
|
16018
|
+
return value2;
|
|
16019
|
+
}
|
|
16020
|
+
function securityProfile(value2) {
|
|
16021
|
+
if (value2 === void 0) return void 0;
|
|
16022
|
+
if (value2 === "odla" || value2 === "cloudflare-app" || value2 === "generic") return value2;
|
|
16023
|
+
throw new Error("--profile must be odla, cloudflare-app, or generic");
|
|
16024
|
+
}
|
|
16025
|
+
var init_security_command_context = __esm({
|
|
16026
|
+
"src/security-command-context.ts"() {
|
|
16027
|
+
"use strict";
|
|
16028
|
+
init_cjs_shims();
|
|
16029
|
+
init_argv();
|
|
16030
|
+
init_config();
|
|
16031
|
+
init_token();
|
|
16032
|
+
}
|
|
16033
|
+
});
|
|
16034
|
+
|
|
16035
|
+
// src/promotion-command.ts
|
|
16036
|
+
async function promotionCommand(parsed, dependencies) {
|
|
16037
|
+
const action2 = parsed.positionals[1];
|
|
16038
|
+
if (!action2 || !["plan", "inspect", "status", "apply", "rollback", "next", "record", "cancel"].includes(action2)) rejectWord(["promotion"], action2);
|
|
16039
|
+
assertArgs(parsed, ["config", "env", "platform", "email", "open", "json", "file", "approval", "idempotency-key"], 5);
|
|
16040
|
+
const context = await hostedSecurityContext(parsed, dependencies);
|
|
16041
|
+
const client = (0, import_apps14.createAppsClient)({
|
|
16042
|
+
token: context.token,
|
|
16043
|
+
fetcher: { fetch: (request3, init) => {
|
|
16044
|
+
const internal = new URL(typeof request3 === "string" ? request3 : request3.url);
|
|
16045
|
+
return context.fetch(`${context.platform}${internal.pathname}${internal.search}`, init);
|
|
16046
|
+
} }
|
|
16047
|
+
});
|
|
16048
|
+
const json = parsed.options.json === true;
|
|
16049
|
+
if (action2 === "plan") {
|
|
16050
|
+
if (parsed.positionals[2]) throw new Error("promotion plan takes --file, not a positional plan id");
|
|
16051
|
+
const file = stringOpt(parsed.options.file);
|
|
16052
|
+
if (!file) throw new Error("--file <promotion-plan.json> is required");
|
|
16053
|
+
const source = JSON.parse(await (0, import_promises12.readFile)(file, "utf8"));
|
|
16054
|
+
const plan2 = await client.createPromotionReleasePlan(context.appId, source);
|
|
16055
|
+
render(plan2, json, context.stdout);
|
|
16056
|
+
return;
|
|
16057
|
+
}
|
|
16058
|
+
const planId = requiredSecurityPositional(parsed, 2, "plan id");
|
|
16059
|
+
if (action2 === "inspect") {
|
|
16060
|
+
if (parsed.positionals[3]) throw new Error("promotion inspect takes only a plan id");
|
|
16061
|
+
const plan2 = await client.getPromotionReleasePlan(context.appId, planId);
|
|
16062
|
+
if (!plan2) throw new Error(`promotion release ${planId} was not found`);
|
|
16063
|
+
render(plan2, json, context.stdout);
|
|
16064
|
+
return;
|
|
16065
|
+
}
|
|
16066
|
+
if (action2 === "status") {
|
|
16067
|
+
if (parsed.positionals[3]) throw new Error("promotion status takes only a plan id");
|
|
16068
|
+
const status = await client.getPromotionReleaseStatus(context.appId, planId);
|
|
16069
|
+
if (!status) throw new Error(`promotion release ${planId} was not found`);
|
|
16070
|
+
render(status, json, context.stdout);
|
|
16071
|
+
return;
|
|
16072
|
+
}
|
|
16073
|
+
if (action2 === "next" || action2 === "cancel" || action2 === "record") {
|
|
16074
|
+
const operationId = requiredSecurityPositional(parsed, 3, "operation id");
|
|
16075
|
+
if (action2 === "next") {
|
|
16076
|
+
if (parsed.positionals[4]) throw new Error("promotion next takes only plan and operation ids");
|
|
16077
|
+
render(await client.claimPromotionReleaseWork(context.appId, planId, operationId), json, context.stdout);
|
|
16078
|
+
return;
|
|
16079
|
+
}
|
|
16080
|
+
if (action2 === "cancel") {
|
|
16081
|
+
if (parsed.positionals[4]) throw new Error("promotion cancel takes only plan and operation ids");
|
|
16082
|
+
render(await client.cancelPromotionReleaseOperation(context.appId, planId, operationId), json, context.stdout);
|
|
16083
|
+
return;
|
|
16084
|
+
}
|
|
16085
|
+
const stepId = requiredSecurityPositional(parsed, 4, "step id");
|
|
16086
|
+
const file = stringOpt(parsed.options.file);
|
|
16087
|
+
if (!file) throw new Error("--file <step-receipt.json> is required");
|
|
16088
|
+
const receipt = JSON.parse(await (0, import_promises12.readFile)(file, "utf8"));
|
|
16089
|
+
render(await client.recordPromotionReleaseWork(context.appId, planId, operationId, stepId, receipt), json, context.stdout);
|
|
16090
|
+
return;
|
|
16091
|
+
}
|
|
16092
|
+
const approvalId = stringOpt(parsed.options.approval);
|
|
16093
|
+
if (parsed.positionals[3]) throw new Error(`promotion ${action2} takes only a plan id`);
|
|
16094
|
+
if (!approvalId) throw new Error(`--approval <approval-id> is required for promotion ${action2}`);
|
|
16095
|
+
const plan = await client.getPromotionReleasePlan(context.appId, planId);
|
|
16096
|
+
if (!plan) throw new Error(`promotion release ${planId} was not found`);
|
|
16097
|
+
if (plan.state !== "reviewable") throw new Error(`promotion release is ${plan.state}: ${plan.blockers.join("; ")}`);
|
|
16098
|
+
const operationAction = action2;
|
|
16099
|
+
const operation = await client.requestPromotionReleaseOperation(context.appId, planId, operationAction, {
|
|
16100
|
+
approvalId,
|
|
16101
|
+
planDigest: plan.planDigest,
|
|
16102
|
+
targetSetDigest: plan.targetSetDigest,
|
|
16103
|
+
idempotencyKey: stringOpt(parsed.options["idempotency-key"]) ?? `${operationAction}:${planId}`
|
|
16104
|
+
});
|
|
16105
|
+
render(operation, json, context.stdout);
|
|
16106
|
+
}
|
|
16107
|
+
var import_promises12, import_apps14, render;
|
|
16108
|
+
var init_promotion_command = __esm({
|
|
16109
|
+
"src/promotion-command.ts"() {
|
|
16110
|
+
"use strict";
|
|
16111
|
+
init_cjs_shims();
|
|
16112
|
+
import_promises12 = require("fs/promises");
|
|
16113
|
+
import_apps14 = require("@odla-ai/apps");
|
|
16114
|
+
init_argv();
|
|
16115
|
+
init_security_command_context();
|
|
16116
|
+
init_surface();
|
|
16117
|
+
render = (value2, json, out) => {
|
|
16118
|
+
if (json) out.log(JSON.stringify(value2));
|
|
16119
|
+
else out.log(JSON.stringify(value2, null, 2));
|
|
16120
|
+
};
|
|
16121
|
+
}
|
|
16122
|
+
});
|
|
16123
|
+
|
|
15873
16124
|
// src/record.ts
|
|
15874
16125
|
function recordInvocation(parsed) {
|
|
15875
16126
|
const file = import_node_process19.default.env.ODLA_CLI_RECORD;
|
|
@@ -15901,7 +16152,7 @@ function advisoryCollectingFetch(inner, sink) {
|
|
|
15901
16152
|
return (async (input, init) => {
|
|
15902
16153
|
const response2 = await inner(input, init);
|
|
15903
16154
|
try {
|
|
15904
|
-
sink.push(...(0,
|
|
16155
|
+
sink.push(...(0, import_apps15.parseAdvisories)(response2));
|
|
15905
16156
|
} catch {
|
|
15906
16157
|
}
|
|
15907
16158
|
return response2;
|
|
@@ -15920,15 +16171,15 @@ function renderAdvisories(out, advisories, env = process.env) {
|
|
|
15920
16171
|
const key = `${advisory.code}:${advisory.message}`;
|
|
15921
16172
|
if (seen.has(key)) continue;
|
|
15922
16173
|
seen.add(key);
|
|
15923
|
-
out.error((0,
|
|
16174
|
+
out.error((0, import_apps15.formatAdvisory)(advisory));
|
|
15924
16175
|
}
|
|
15925
16176
|
}
|
|
15926
|
-
var
|
|
16177
|
+
var import_apps15, superseded;
|
|
15927
16178
|
var init_advisory_output = __esm({
|
|
15928
16179
|
"src/advisory-output.ts"() {
|
|
15929
16180
|
"use strict";
|
|
15930
16181
|
init_cjs_shims();
|
|
15931
|
-
|
|
16182
|
+
import_apps15 = require("@odla-ai/apps");
|
|
15932
16183
|
superseded = /* @__PURE__ */ new Set();
|
|
15933
16184
|
}
|
|
15934
16185
|
});
|
|
@@ -16187,7 +16438,7 @@ async function bySlug(ctx, slug) {
|
|
|
16187
16438
|
"GET",
|
|
16188
16439
|
`/runbook?app=${encodeURIComponent(ctx.appId)}&slug=${encodeURIComponent(slug)}&limit=1`
|
|
16189
16440
|
);
|
|
16190
|
-
const filtered = page2.records.find((
|
|
16441
|
+
const filtered = page2.records.find((record12) => record12.slug === slug);
|
|
16191
16442
|
if (filtered) return filtered;
|
|
16192
16443
|
const limit = 100;
|
|
16193
16444
|
for (let offset = 0; ; offset += limit) {
|
|
@@ -16196,7 +16447,7 @@ async function bySlug(ctx, slug) {
|
|
|
16196
16447
|
"GET",
|
|
16197
16448
|
`/runbook?app=${encodeURIComponent(ctx.appId)}&limit=${limit}&offset=${offset}`
|
|
16198
16449
|
);
|
|
16199
|
-
const found = fallback.records.find((
|
|
16450
|
+
const found = fallback.records.find((record12) => record12.slug === slug);
|
|
16200
16451
|
if (found) return found;
|
|
16201
16452
|
if (!fallback.records.length || offset + fallback.records.length >= fallback.total) break;
|
|
16202
16453
|
}
|
|
@@ -17081,50 +17332,6 @@ var init_runbook_command = __esm({
|
|
|
17081
17332
|
}
|
|
17082
17333
|
});
|
|
17083
17334
|
|
|
17084
|
-
// src/security-command-context.ts
|
|
17085
|
-
async function hostedSecurityContext(parsed, dependencies) {
|
|
17086
|
-
const configPath = stringOpt(parsed.options.config) ?? "odla.config.mjs";
|
|
17087
|
-
const cfg = await loadProjectConfig(configPath);
|
|
17088
|
-
const env = stringOpt(parsed.options.env) ?? (cfg.envs.includes("dev") ? "dev" : cfg.envs[0]);
|
|
17089
|
-
if (!env || !cfg.envs.includes(env)) {
|
|
17090
|
-
throw new Error(`env "${env ?? ""}" is not declared in ${configPath}`);
|
|
17091
|
-
}
|
|
17092
|
-
const platform = platformAudience(stringOpt(parsed.options.platform) ?? cfg.platformUrl);
|
|
17093
|
-
if (platformAudience(cfg.platformUrl) !== platform) {
|
|
17094
|
-
throw new Error("--platform cannot reuse a project developer token from another platform; update odla.config.mjs and authenticate there");
|
|
17095
|
-
}
|
|
17096
|
-
const doFetch = dependencies.fetch ?? fetch;
|
|
17097
|
-
const stdout = dependencies.stdout ?? console;
|
|
17098
|
-
const open = parsed.options.open === false ? false : parsed.options.open === true ? true : void 0;
|
|
17099
|
-
const token = await getDeveloperToken(
|
|
17100
|
-
cfg,
|
|
17101
|
-
{ configPath, email: stringOpt(parsed.options.email), open, openApprovalUrl: dependencies.openUrl },
|
|
17102
|
-
doFetch,
|
|
17103
|
-
stdout,
|
|
17104
|
-
{ optionalProjectCapabilities: ["app.manage"] }
|
|
17105
|
-
);
|
|
17106
|
-
return { platform, token, appId: cfg.app.id, env, fetch: doFetch, stdout };
|
|
17107
|
-
}
|
|
17108
|
-
function requiredSecurityPositional(parsed, index, label) {
|
|
17109
|
-
const value2 = parsed.positionals[index];
|
|
17110
|
-
if (!value2) throw new Error(`${label} is required`);
|
|
17111
|
-
return value2;
|
|
17112
|
-
}
|
|
17113
|
-
function securityProfile(value2) {
|
|
17114
|
-
if (value2 === void 0) return void 0;
|
|
17115
|
-
if (value2 === "odla" || value2 === "cloudflare-app" || value2 === "generic") return value2;
|
|
17116
|
-
throw new Error("--profile must be odla, cloudflare-app, or generic");
|
|
17117
|
-
}
|
|
17118
|
-
var init_security_command_context = __esm({
|
|
17119
|
-
"src/security-command-context.ts"() {
|
|
17120
|
-
"use strict";
|
|
17121
|
-
init_cjs_shims();
|
|
17122
|
-
init_argv();
|
|
17123
|
-
init_config();
|
|
17124
|
-
init_token();
|
|
17125
|
-
}
|
|
17126
|
-
});
|
|
17127
|
-
|
|
17128
17335
|
// src/security-command-output.ts
|
|
17129
17336
|
function printHostedSecurityPlan(out, plan, appId) {
|
|
17130
17337
|
out.log(`Hosted security plan for ${appId}/${plan.env}: ${plan.ready ? "ready" : "not ready"}`);
|
|
@@ -17916,6 +18123,10 @@ async function dispatchCli(argv2, dependencies) {
|
|
|
17916
18123
|
await securityCommand(parsed, runtime);
|
|
17917
18124
|
return;
|
|
17918
18125
|
}
|
|
18126
|
+
if (command === "promotion") {
|
|
18127
|
+
await promotionCommand(parsed, runtime);
|
|
18128
|
+
return;
|
|
18129
|
+
}
|
|
17919
18130
|
if (command === "brand") {
|
|
17920
18131
|
await brandCommand(parsed, runtime);
|
|
17921
18132
|
return;
|
|
@@ -18045,6 +18256,7 @@ var init_cli = __esm({
|
|
|
18045
18256
|
init_o11y_command();
|
|
18046
18257
|
init_monitor_command();
|
|
18047
18258
|
init_provision();
|
|
18259
|
+
init_promotion_command();
|
|
18048
18260
|
init_record();
|
|
18049
18261
|
init_advisory_output();
|
|
18050
18262
|
init_cached_credential();
|