@odla-ai/cli 0.26.2 → 0.27.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.cjs +291 -135
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-MBZXWPZP.js → chunk-4JWDJN3P.js} +175 -14
- package/dist/chunk-4JWDJN3P.js.map +1 -0
- package/dist/index.cjs +291 -135
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -1
- package/dist/chunk-MBZXWPZP.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -314,7 +314,7 @@ var import_node_process2 = __toESM(require("process"), 1);
|
|
|
314
314
|
async function openUrl(url, options = {}) {
|
|
315
315
|
const command = openerFor(options.platform ?? import_node_process2.default.platform);
|
|
316
316
|
const doSpawn = options.spawnImpl ?? import_node_child_process.spawn;
|
|
317
|
-
await new Promise((
|
|
317
|
+
await new Promise((resolve13, reject) => {
|
|
318
318
|
const child = doSpawn(command.cmd, [...command.args, url], {
|
|
319
319
|
stdio: "ignore",
|
|
320
320
|
detached: true
|
|
@@ -322,7 +322,7 @@ async function openUrl(url, options = {}) {
|
|
|
322
322
|
child.once("error", reject);
|
|
323
323
|
child.once("spawn", () => {
|
|
324
324
|
child.unref();
|
|
325
|
-
|
|
325
|
+
resolve13();
|
|
326
326
|
});
|
|
327
327
|
});
|
|
328
328
|
}
|
|
@@ -406,6 +406,7 @@ async function freshHandshake(ctx, waitMs) {
|
|
|
406
406
|
endpoint: ctx.cfg.platformUrl,
|
|
407
407
|
email: ctx.email,
|
|
408
408
|
label: `${ctx.cfg.app.id} provisioner`,
|
|
409
|
+
projectIds: [ctx.cfg.app.id],
|
|
409
410
|
fetch: ctx.doFetch,
|
|
410
411
|
waitMs,
|
|
411
412
|
onCode: async ({ userCode, deviceCode, expiresIn, interval, verificationUriComplete }) => {
|
|
@@ -2243,6 +2244,153 @@ async function appCommand(parsed, dependencies = {}) {
|
|
|
2243
2244
|
else await appRestore(options);
|
|
2244
2245
|
}
|
|
2245
2246
|
|
|
2247
|
+
// src/brand-command.ts
|
|
2248
|
+
var import_promises2 = require("fs/promises");
|
|
2249
|
+
var import_node_path7 = require("path");
|
|
2250
|
+
|
|
2251
|
+
// src/brand-design-unpack.ts
|
|
2252
|
+
var import_node_zlib = require("zlib");
|
|
2253
|
+
var import_brand = require("@odla-ai/brand");
|
|
2254
|
+
var EXTENSIONS = {
|
|
2255
|
+
"image/png": "png",
|
|
2256
|
+
"image/jpeg": "jpg",
|
|
2257
|
+
"image/gif": "gif",
|
|
2258
|
+
"image/webp": "webp",
|
|
2259
|
+
"image/svg+xml": "svg",
|
|
2260
|
+
"image/avif": "avif",
|
|
2261
|
+
"font/woff2": "woff2",
|
|
2262
|
+
"font/woff": "woff",
|
|
2263
|
+
"font/ttf": "ttf",
|
|
2264
|
+
"font/otf": "otf",
|
|
2265
|
+
"text/javascript": "js",
|
|
2266
|
+
"application/javascript": "js",
|
|
2267
|
+
"text/css": "css",
|
|
2268
|
+
"text/html": "html",
|
|
2269
|
+
"application/json": "json"
|
|
2270
|
+
};
|
|
2271
|
+
var encode = (text2) => new TextEncoder().encode(text2);
|
|
2272
|
+
function assetFileName(uuid, mime) {
|
|
2273
|
+
const ext = EXTENSIONS[mime.split(";")[0].trim().toLowerCase()] ?? "bin";
|
|
2274
|
+
return `${uuid.replace(/[^a-zA-Z0-9._-]/g, "_")}.${ext}`;
|
|
2275
|
+
}
|
|
2276
|
+
function decodePayload(data, compressed) {
|
|
2277
|
+
const raw = Buffer.from(data, "base64");
|
|
2278
|
+
return new Uint8Array(compressed ? (0, import_node_zlib.gunzipSync)(raw) : raw);
|
|
2279
|
+
}
|
|
2280
|
+
function rewriteReferences(template, assetPaths, pagePaths) {
|
|
2281
|
+
let out = template;
|
|
2282
|
+
for (const [uuid, path] of pagePaths) {
|
|
2283
|
+
out = out.split(`about:blank#${uuid}`).join(path);
|
|
2284
|
+
}
|
|
2285
|
+
for (const [uuid, path] of assetPaths) {
|
|
2286
|
+
out = out.split(uuid).join(path);
|
|
2287
|
+
}
|
|
2288
|
+
return out;
|
|
2289
|
+
}
|
|
2290
|
+
function tokensCss(digest) {
|
|
2291
|
+
if (Object.keys(digest.tokens.light).length === 0) return null;
|
|
2292
|
+
return (0, import_brand.renderTokensCss)(digest.tokens.light, { dark: digest.tokens.dark });
|
|
2293
|
+
}
|
|
2294
|
+
function unpackDesign(html) {
|
|
2295
|
+
const bundle = (0, import_brand.parseDesignBundle)(html);
|
|
2296
|
+
const manifest = (0, import_brand.readDesignManifest)(html);
|
|
2297
|
+
const digest = (0, import_brand.digestDesignBundle)(bundle);
|
|
2298
|
+
const pageUuids = new Set(bundle.pageOrder);
|
|
2299
|
+
const files = [];
|
|
2300
|
+
const failed = [];
|
|
2301
|
+
const assetPaths = /* @__PURE__ */ new Map();
|
|
2302
|
+
const pagePaths = /* @__PURE__ */ new Map();
|
|
2303
|
+
for (const [uuid, entry] of Object.entries(manifest)) {
|
|
2304
|
+
let bytes;
|
|
2305
|
+
try {
|
|
2306
|
+
bytes = decodePayload(entry.data, entry.compressed);
|
|
2307
|
+
} catch {
|
|
2308
|
+
failed.push(uuid);
|
|
2309
|
+
continue;
|
|
2310
|
+
}
|
|
2311
|
+
if (pageUuids.has(uuid)) {
|
|
2312
|
+
const path2 = `pages/${assetFileName(uuid, "text/html")}`;
|
|
2313
|
+
pagePaths.set(uuid, `./${path2}`);
|
|
2314
|
+
files.push({ path: path2, bytes });
|
|
2315
|
+
continue;
|
|
2316
|
+
}
|
|
2317
|
+
const path = `assets/${assetFileName(uuid, entry.mime)}`;
|
|
2318
|
+
assetPaths.set(uuid, `./${path}`);
|
|
2319
|
+
files.push({ path, bytes });
|
|
2320
|
+
}
|
|
2321
|
+
files.push({
|
|
2322
|
+
path: "index.html",
|
|
2323
|
+
bytes: encode(rewriteReferences(bundle.template, assetPaths, pagePaths))
|
|
2324
|
+
});
|
|
2325
|
+
files.push({ path: "digest.json", bytes: encode(`${JSON.stringify(digest, null, 2)}
|
|
2326
|
+
`) });
|
|
2327
|
+
const css = tokensCss(digest);
|
|
2328
|
+
if (css !== null) files.push({ path: "tokens.css", bytes: encode(css) });
|
|
2329
|
+
if (bundle.thumbnailSvg) files.push({ path: "thumbnail.svg", bytes: encode(bundle.thumbnailSvg) });
|
|
2330
|
+
return { files, digest, failed };
|
|
2331
|
+
}
|
|
2332
|
+
function describeUnpack(result, outDir) {
|
|
2333
|
+
const { digest } = result;
|
|
2334
|
+
const lines = [
|
|
2335
|
+
`Unpacked ${digest.title ? `"${digest.title}"` : "design"} into ${outDir}`,
|
|
2336
|
+
` index.html the design, offline-runnable (${digest.templateBytes} bytes)`,
|
|
2337
|
+
` assets/ ${digest.assetCount} embedded files (${digest.assetBytes} bytes)`,
|
|
2338
|
+
` digest.json ${Object.keys(digest.tokens.light).length} --ui-* tokens, ${digest.props.length} props, ${digest.outline.length} headings`
|
|
2339
|
+
];
|
|
2340
|
+
if (result.files.some((f) => f.path === "tokens.css"))
|
|
2341
|
+
lines.push(" tokens.css the design's tokens as an @odla-ai/ui theme sheet");
|
|
2342
|
+
if (digest.fonts.length > 0) lines.push(`Typefaces: ${digest.fonts.join(", ")}`);
|
|
2343
|
+
if (result.failed.length > 0)
|
|
2344
|
+
lines.push(`WARNING: ${result.failed.length} embedded asset(s) could not be decoded.`);
|
|
2345
|
+
return lines;
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2348
|
+
// src/brand-command.ts
|
|
2349
|
+
var USAGE = "usage: odla-ai brand design unpack <bundle.html|-> [--out <dir>] [--json]";
|
|
2350
|
+
async function readBundle(source, deps) {
|
|
2351
|
+
if (source !== "-") return (0, import_promises2.readFile)((0, import_node_path7.resolve)(source), "utf8");
|
|
2352
|
+
const readStdin = deps.readStdin;
|
|
2353
|
+
if (!readStdin) throw new Error("reading a bundle from stdin is not supported here");
|
|
2354
|
+
return readStdin();
|
|
2355
|
+
}
|
|
2356
|
+
async function writeAll(result, outDir) {
|
|
2357
|
+
for (const file of result.files) {
|
|
2358
|
+
const target = (0, import_node_path7.resolve)(outDir, file.path);
|
|
2359
|
+
await (0, import_promises2.mkdir)((0, import_node_path7.dirname)(target), { recursive: true });
|
|
2360
|
+
await (0, import_promises2.writeFile)(target, file.bytes);
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
async function designUnpack(parsed, deps) {
|
|
2364
|
+
assertArgs(parsed, ["out", "json"], 4);
|
|
2365
|
+
const source = parsed.positionals[3];
|
|
2366
|
+
if (!source) throw new Error(USAGE);
|
|
2367
|
+
const outDir = (0, import_node_path7.resolve)(stringOpt(parsed.options.out) ?? "design");
|
|
2368
|
+
const result = unpackDesign(await readBundle(source, deps));
|
|
2369
|
+
await writeAll(result, outDir);
|
|
2370
|
+
const out = deps.stdout ?? console;
|
|
2371
|
+
if (parsed.options.json === true) {
|
|
2372
|
+
out.log(
|
|
2373
|
+
JSON.stringify({
|
|
2374
|
+
outDir,
|
|
2375
|
+
files: result.files.map((f) => f.path),
|
|
2376
|
+
failed: result.failed,
|
|
2377
|
+
digest: result.digest
|
|
2378
|
+
})
|
|
2379
|
+
);
|
|
2380
|
+
return;
|
|
2381
|
+
}
|
|
2382
|
+
for (const line of describeUnpack(result, outDir)) out.log(line);
|
|
2383
|
+
}
|
|
2384
|
+
async function brandCommand(parsed, deps) {
|
|
2385
|
+
const subject = parsed.positionals[1];
|
|
2386
|
+
const action2 = parsed.positionals[2];
|
|
2387
|
+
if (subject === "design" && action2 === "unpack") {
|
|
2388
|
+
await designUnpack(parsed, deps);
|
|
2389
|
+
return;
|
|
2390
|
+
}
|
|
2391
|
+
throw new Error(USAGE);
|
|
2392
|
+
}
|
|
2393
|
+
|
|
2246
2394
|
// src/calendar-errors.ts
|
|
2247
2395
|
var PLATFORM_NOT_READY_CODES = /* @__PURE__ */ new Set([
|
|
2248
2396
|
"calendar_google_oauth_not_configured",
|
|
@@ -2516,8 +2664,8 @@ function credential(value2) {
|
|
|
2516
2664
|
// src/calendar-poll.ts
|
|
2517
2665
|
async function waitForCalendarPoll(milliseconds, signal) {
|
|
2518
2666
|
if (signal?.aborted) throw signal.reason ?? new Error("calendar connection aborted");
|
|
2519
|
-
await new Promise((
|
|
2520
|
-
const timer = setTimeout(
|
|
2667
|
+
await new Promise((resolve13, reject) => {
|
|
2668
|
+
const timer = setTimeout(resolve13, milliseconds);
|
|
2521
2669
|
signal?.addEventListener("abort", () => {
|
|
2522
2670
|
clearTimeout(timer);
|
|
2523
2671
|
reject(signal.reason ?? new Error("calendar connection aborted"));
|
|
@@ -2771,7 +2919,7 @@ function printGroup(out, heading, items) {
|
|
|
2771
2919
|
|
|
2772
2920
|
// src/config-operation-command.ts
|
|
2773
2921
|
var import_apps6 = require("@odla-ai/apps");
|
|
2774
|
-
var
|
|
2922
|
+
var import_node_path8 = require("path");
|
|
2775
2923
|
|
|
2776
2924
|
// src/version.ts
|
|
2777
2925
|
var import_node_fs9 = require("fs");
|
|
@@ -3150,7 +3298,7 @@ async function configOperationWait(options) {
|
|
|
3150
3298
|
assertOperationId(options.operationId);
|
|
3151
3299
|
const cfg = await loadProjectConfig(options.configPath);
|
|
3152
3300
|
const client = await operationClient(cfg, options, "wait");
|
|
3153
|
-
const wait2 = options.pollWait ?? ((ms) => new Promise((
|
|
3301
|
+
const wait2 = options.pollWait ?? ((ms) => new Promise((resolve13) => setTimeout(resolve13, ms)));
|
|
3154
3302
|
const now = () => (options.now?.() ?? /* @__PURE__ */ new Date()).getTime();
|
|
3155
3303
|
const deadline = now() + (options.timeoutSeconds ?? DEFAULT_WAIT_SECONDS) * 1e3;
|
|
3156
3304
|
const interval = (options.intervalSeconds ?? DEFAULT_INTERVAL_SECONDS) * 1e3;
|
|
@@ -3181,7 +3329,7 @@ async function operationClient(cfg, options, purpose) {
|
|
|
3181
3329
|
platform: cfg.platformUrl,
|
|
3182
3330
|
scope: "app:config:write",
|
|
3183
3331
|
token: options.token,
|
|
3184
|
-
tokenFile: (0,
|
|
3332
|
+
tokenFile: (0, import_node_path8.join)(cfg.rootDir, ".odla", "admin-token.local.json"),
|
|
3185
3333
|
rootDir: cfg.rootDir,
|
|
3186
3334
|
email: options.email,
|
|
3187
3335
|
open: options.open,
|
|
@@ -3236,7 +3384,7 @@ function record3(value2) {
|
|
|
3236
3384
|
|
|
3237
3385
|
// src/config-reconcile-command.ts
|
|
3238
3386
|
var import_apps8 = require("@odla-ai/apps");
|
|
3239
|
-
var
|
|
3387
|
+
var import_node_path9 = require("path");
|
|
3240
3388
|
|
|
3241
3389
|
// src/config-reconcile.ts
|
|
3242
3390
|
var import_apps7 = require("@odla-ai/apps");
|
|
@@ -3532,7 +3680,7 @@ async function inspectConfig(options) {
|
|
|
3532
3680
|
platform: cfg.platformUrl,
|
|
3533
3681
|
scope: "app:config:read",
|
|
3534
3682
|
token: options.token,
|
|
3535
|
-
tokenFile: (0,
|
|
3683
|
+
tokenFile: (0, import_node_path9.join)(cfg.rootDir, ".odla", "admin-token.local.json"),
|
|
3536
3684
|
rootDir: cfg.rootDir,
|
|
3537
3685
|
email: options.email,
|
|
3538
3686
|
open: options.open,
|
|
@@ -3665,12 +3813,12 @@ function quoteArg2(value2) {
|
|
|
3665
3813
|
// src/doctor-checks.ts
|
|
3666
3814
|
var import_node_child_process3 = require("child_process");
|
|
3667
3815
|
var import_node_fs12 = require("fs");
|
|
3668
|
-
var
|
|
3816
|
+
var import_node_path11 = require("path");
|
|
3669
3817
|
|
|
3670
3818
|
// src/wrangler.ts
|
|
3671
3819
|
var import_node_child_process2 = require("child_process");
|
|
3672
3820
|
var import_node_fs11 = require("fs");
|
|
3673
|
-
var
|
|
3821
|
+
var import_node_path10 = require("path");
|
|
3674
3822
|
var defaultRunner = (cmd, args, opts) => new Promise((resolvePromise, reject) => {
|
|
3675
3823
|
const child = (0, import_node_child_process2.spawn)(cmd, args, { cwd: opts?.cwd, stdio: ["pipe", "pipe", "pipe"] });
|
|
3676
3824
|
let stdout = "";
|
|
@@ -3684,7 +3832,7 @@ var defaultRunner = (cmd, args, opts) => new Promise((resolvePromise, reject) =>
|
|
|
3684
3832
|
var WRANGLER_CONFIG_FILES = ["wrangler.jsonc", "wrangler.json", "wrangler.toml"];
|
|
3685
3833
|
function findWranglerConfig(rootDir) {
|
|
3686
3834
|
for (const name of WRANGLER_CONFIG_FILES) {
|
|
3687
|
-
const path = (0,
|
|
3835
|
+
const path = (0, import_node_path10.join)(rootDir, name);
|
|
3688
3836
|
if ((0, import_node_fs11.existsSync)(path)) return path;
|
|
3689
3837
|
}
|
|
3690
3838
|
return null;
|
|
@@ -3797,10 +3945,10 @@ function wranglerWarnings(rootDir) {
|
|
|
3797
3945
|
for (const { label, block } of blocks) {
|
|
3798
3946
|
const assets = block.assets;
|
|
3799
3947
|
if (assets?.directory) {
|
|
3800
|
-
const dir = (0,
|
|
3801
|
-
if (dir === (0,
|
|
3948
|
+
const dir = (0, import_node_path11.resolve)(rootDir, assets.directory);
|
|
3949
|
+
if (dir === (0, import_node_path11.resolve)(rootDir)) {
|
|
3802
3950
|
warnings.push(`${label}assets.directory is the project root \u2014 point it at a dedicated build dir (wrangler dev fails with "spawn EBADF")`);
|
|
3803
|
-
} else if ((0, import_node_fs12.existsSync)((0,
|
|
3951
|
+
} else if ((0, import_node_fs12.existsSync)((0, import_node_path11.join)(dir, "node_modules"))) {
|
|
3804
3952
|
warnings.push(`${label}assets.directory contains node_modules \u2014 wrangler dev's watcher will exhaust file descriptors`);
|
|
3805
3953
|
}
|
|
3806
3954
|
}
|
|
@@ -3835,7 +3983,7 @@ function o11yProjectWarnings(rootDir) {
|
|
|
3835
3983
|
warnings.push("cannot verify o11y Worker instrumentation \u2014 add a parseable wrangler.jsonc/json config");
|
|
3836
3984
|
return warnings;
|
|
3837
3985
|
}
|
|
3838
|
-
const main = typeof config.main === "string" ? (0,
|
|
3986
|
+
const main = typeof config.main === "string" ? (0, import_node_path11.resolve)(rootDir, config.main) : null;
|
|
3839
3987
|
if (!main || !(0, import_node_fs12.existsSync)(main)) {
|
|
3840
3988
|
warnings.push("cannot verify o11y Worker instrumentation \u2014 wrangler main is missing or unreadable");
|
|
3841
3989
|
} else {
|
|
@@ -3865,7 +4013,7 @@ function calendarProjectWarnings(rootDir) {
|
|
|
3865
4013
|
}
|
|
3866
4014
|
function readPackageJson(rootDir) {
|
|
3867
4015
|
try {
|
|
3868
|
-
return JSON.parse((0, import_node_fs12.readFileSync)((0,
|
|
4016
|
+
return JSON.parse((0, import_node_fs12.readFileSync)((0, import_node_path11.join)(rootDir, "package.json"), "utf8"));
|
|
3869
4017
|
} catch {
|
|
3870
4018
|
return null;
|
|
3871
4019
|
}
|
|
@@ -4093,12 +4241,12 @@ function harnessOption(value2, flag) {
|
|
|
4093
4241
|
|
|
4094
4242
|
// src/init.ts
|
|
4095
4243
|
var import_node_fs13 = require("fs");
|
|
4096
|
-
var
|
|
4244
|
+
var import_node_path12 = require("path");
|
|
4097
4245
|
var import_apps9 = require("@odla-ai/apps");
|
|
4098
4246
|
function initProject(options) {
|
|
4099
4247
|
const out = options.stdout ?? console;
|
|
4100
|
-
const rootDir = (0,
|
|
4101
|
-
const configPath = (0,
|
|
4248
|
+
const rootDir = (0, import_node_path12.resolve)(options.rootDir ?? process.cwd());
|
|
4249
|
+
const configPath = (0, import_node_path12.resolve)(rootDir, options.configPath ?? "odla.config.mjs");
|
|
4102
4250
|
if ((0, import_node_fs13.existsSync)(configPath) && !options.force) {
|
|
4103
4251
|
throw new Error(`${configPath} already exists. Pass --force to overwrite.`);
|
|
4104
4252
|
}
|
|
@@ -4115,12 +4263,12 @@ function initProject(options) {
|
|
|
4115
4263
|
}
|
|
4116
4264
|
}
|
|
4117
4265
|
const aiProvider = options.aiProvider ?? "anthropic";
|
|
4118
|
-
(0, import_node_fs13.mkdirSync)((0,
|
|
4119
|
-
(0, import_node_fs13.mkdirSync)((0,
|
|
4120
|
-
(0, import_node_fs13.mkdirSync)((0,
|
|
4266
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path12.dirname)(configPath), { recursive: true });
|
|
4267
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path12.resolve)(rootDir, "src/odla"), { recursive: true });
|
|
4268
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path12.resolve)(rootDir, ".odla"), { recursive: true });
|
|
4121
4269
|
(0, import_node_fs13.writeFileSync)(configPath, configTemplate({ appId: options.appId, name: options.name, envs, services, aiProvider }));
|
|
4122
|
-
writeIfMissing((0,
|
|
4123
|
-
writeIfMissing((0,
|
|
4270
|
+
writeIfMissing((0, import_node_path12.resolve)(rootDir, "src/odla/schema.mjs"), schemaTemplate());
|
|
4271
|
+
writeIfMissing((0, import_node_path12.resolve)(rootDir, "src/odla/rules.mjs"), rulesTemplate());
|
|
4124
4272
|
ensureGitignore(rootDir);
|
|
4125
4273
|
out.log(`created ${relativeDisplay(configPath, rootDir)}`);
|
|
4126
4274
|
out.log("created src/odla/schema.mjs and src/odla/rules.mjs");
|
|
@@ -4361,7 +4509,7 @@ async function resolveVaultWrite(options) {
|
|
|
4361
4509
|
// src/skill.ts
|
|
4362
4510
|
var import_node_fs14 = require("fs");
|
|
4363
4511
|
var import_node_os2 = require("os");
|
|
4364
|
-
var
|
|
4512
|
+
var import_node_path13 = require("path");
|
|
4365
4513
|
var import_node_url2 = require("url");
|
|
4366
4514
|
|
|
4367
4515
|
// src/skill-adapters.ts
|
|
@@ -4440,8 +4588,8 @@ function installSkill(options = {}) {
|
|
|
4440
4588
|
const files = listFiles(sourceDir);
|
|
4441
4589
|
if (files.length === 0) throw new Error(`no bundled skills found at ${sourceDir}`);
|
|
4442
4590
|
const harnesses = normalizeHarnesses(options.harnesses, options.global === true);
|
|
4443
|
-
const root = (0,
|
|
4444
|
-
const home = (0,
|
|
4591
|
+
const root = (0, import_node_path13.resolve)(options.dir ?? process.cwd());
|
|
4592
|
+
const home = (0, import_node_path13.resolve)(options.homeDir ?? (0, import_node_os2.homedir)());
|
|
4445
4593
|
const plans = /* @__PURE__ */ new Map();
|
|
4446
4594
|
const targets = /* @__PURE__ */ new Map();
|
|
4447
4595
|
const rememberTarget = (harness, target) => {
|
|
@@ -4455,48 +4603,48 @@ function installSkill(options = {}) {
|
|
|
4455
4603
|
plans.set(target, { target, content: content2, boundary, managedMerge });
|
|
4456
4604
|
};
|
|
4457
4605
|
const planSkillTree = (targetDir2, boundary = root) => {
|
|
4458
|
-
for (const rel of files) plan((0,
|
|
4606
|
+
for (const rel of files) plan((0, import_node_path13.join)(targetDir2, rel), (0, import_node_fs14.readFileSync)((0, import_node_path13.join)(sourceDir, rel), "utf8"), false, boundary);
|
|
4459
4607
|
};
|
|
4460
4608
|
let targetDir;
|
|
4461
4609
|
if (options.global) {
|
|
4462
|
-
const claudeRoot = (0,
|
|
4463
|
-
const codexRoot = (0,
|
|
4610
|
+
const claudeRoot = (0, import_node_path13.join)(home, ".claude", "skills");
|
|
4611
|
+
const codexRoot = (0, import_node_path13.resolve)(options.codexHomeDir ?? process.env.CODEX_HOME ?? (0, import_node_path13.join)(home, ".codex"), "skills");
|
|
4464
4612
|
targetDir = harnesses[0] === "codex" ? codexRoot : claudeRoot;
|
|
4465
4613
|
for (const harness of harnesses) {
|
|
4466
4614
|
const skillRoot = harness === "claude" ? claudeRoot : codexRoot;
|
|
4467
|
-
planSkillTree(skillRoot, harness === "claude" ? home : (0,
|
|
4615
|
+
planSkillTree(skillRoot, harness === "claude" ? home : (0, import_node_path13.dirname)((0, import_node_path13.dirname)(codexRoot)));
|
|
4468
4616
|
rememberTarget(harness, skillRoot);
|
|
4469
4617
|
}
|
|
4470
4618
|
} else {
|
|
4471
|
-
const sharedRoot = (0,
|
|
4619
|
+
const sharedRoot = (0, import_node_path13.join)(root, ".agents", "skills");
|
|
4472
4620
|
planSkillTree(sharedRoot);
|
|
4473
|
-
const claudeRoot = (0,
|
|
4621
|
+
const claudeRoot = (0, import_node_path13.join)(root, ".claude", "skills");
|
|
4474
4622
|
targetDir = harnesses.includes("claude") ? claudeRoot : sharedRoot;
|
|
4475
4623
|
for (const harness of harnesses) rememberTarget(harness, sharedRoot);
|
|
4476
4624
|
if (harnesses.includes("claude")) {
|
|
4477
4625
|
for (const skill of skillNames(files)) {
|
|
4478
|
-
const canonical = (0, import_node_fs14.readFileSync)((0,
|
|
4479
|
-
plan((0,
|
|
4626
|
+
const canonical = (0, import_node_fs14.readFileSync)((0, import_node_path13.join)(sourceDir, skill, "SKILL.md"), "utf8");
|
|
4627
|
+
plan((0, import_node_path13.join)(claudeRoot, skill, "SKILL.md"), claudeAdapter(skill, canonical));
|
|
4480
4628
|
}
|
|
4481
4629
|
rememberTarget("claude", claudeRoot);
|
|
4482
4630
|
}
|
|
4483
4631
|
if (harnesses.includes("cursor")) {
|
|
4484
|
-
const cursorRule = (0,
|
|
4632
|
+
const cursorRule = (0, import_node_path13.join)(root, ".cursor", "rules", "odla.mdc");
|
|
4485
4633
|
plan(cursorRule, CURSOR_RULE);
|
|
4486
4634
|
rememberTarget("cursor", cursorRule);
|
|
4487
4635
|
}
|
|
4488
4636
|
if (harnesses.includes("agents")) {
|
|
4489
|
-
const agentsFile = (0,
|
|
4637
|
+
const agentsFile = (0, import_node_path13.join)(root, "AGENTS.md");
|
|
4490
4638
|
plan(agentsFile, managedFileContent(agentsFile, PROJECT_INSTRUCTIONS, options.force === true, root), true);
|
|
4491
4639
|
rememberTarget("agents", agentsFile);
|
|
4492
4640
|
}
|
|
4493
4641
|
if (harnesses.includes("copilot")) {
|
|
4494
|
-
const copilotFile = (0,
|
|
4642
|
+
const copilotFile = (0, import_node_path13.join)(root, ".github", "copilot-instructions.md");
|
|
4495
4643
|
plan(copilotFile, managedFileContent(copilotFile, PROJECT_INSTRUCTIONS, options.force === true, root), true);
|
|
4496
4644
|
rememberTarget("copilot", copilotFile);
|
|
4497
4645
|
}
|
|
4498
4646
|
if (harnesses.includes("gemini")) {
|
|
4499
|
-
const geminiFile = (0,
|
|
4647
|
+
const geminiFile = (0, import_node_path13.join)(root, "GEMINI.md");
|
|
4500
4648
|
plan(geminiFile, managedFileContent(geminiFile, PROJECT_INSTRUCTIONS, options.force === true, root), true);
|
|
4501
4649
|
rememberTarget("gemini", geminiFile);
|
|
4502
4650
|
}
|
|
@@ -4532,7 +4680,7 @@ ${conflicts.map((f) => ` - ${f}`).join("\n")}`
|
|
|
4532
4680
|
}
|
|
4533
4681
|
for (const file of plans.values()) {
|
|
4534
4682
|
if (!(0, import_node_fs14.existsSync)(file.target) || (0, import_node_fs14.readFileSync)(file.target, "utf8") !== file.content) {
|
|
4535
|
-
(0, import_node_fs14.mkdirSync)((0,
|
|
4683
|
+
(0, import_node_fs14.mkdirSync)((0, import_node_path13.dirname)(file.target), { recursive: true });
|
|
4536
4684
|
(0, import_node_fs14.writeFileSync)(file.target, file.content);
|
|
4537
4685
|
}
|
|
4538
4686
|
}
|
|
@@ -4552,7 +4700,7 @@ ${conflicts.map((f) => ` - ${f}`).join("\n")}`
|
|
|
4552
4700
|
};
|
|
4553
4701
|
}
|
|
4554
4702
|
function pathsUnder(root, paths) {
|
|
4555
|
-
return [...paths].map((path) => (0,
|
|
4703
|
+
return [...paths].map((path) => (0, import_node_path13.relative)(root, path)).filter((path) => path !== ".." && !path.startsWith(`..${import_node_path13.sep}`) && !(0, import_node_path13.isAbsolute)(path)).sort();
|
|
4556
4704
|
}
|
|
4557
4705
|
function normalizeHarnesses(values, global) {
|
|
4558
4706
|
const requested = values?.length ? values : ["claude"];
|
|
@@ -4597,13 +4745,13 @@ function managedFileContent(path, block, force, boundary) {
|
|
|
4597
4745
|
return `${current.slice(0, startAt)}${block}${current.slice(afterEnd)}`;
|
|
4598
4746
|
}
|
|
4599
4747
|
function symlinkedComponent(boundary, target) {
|
|
4600
|
-
const rel = (0,
|
|
4601
|
-
if (rel === ".." || rel.startsWith(`..${
|
|
4748
|
+
const rel = (0, import_node_path13.relative)(boundary, target);
|
|
4749
|
+
if (rel === ".." || rel.startsWith(`..${import_node_path13.sep}`) || (0, import_node_path13.isAbsolute)(rel)) {
|
|
4602
4750
|
throw new Error(`agent setup target escapes its install root: ${target}`);
|
|
4603
4751
|
}
|
|
4604
4752
|
let current = boundary;
|
|
4605
|
-
for (const part of rel.split(
|
|
4606
|
-
current = (0,
|
|
4753
|
+
for (const part of rel.split(import_node_path13.sep).filter(Boolean)) {
|
|
4754
|
+
current = (0, import_node_path13.join)(current, part);
|
|
4607
4755
|
try {
|
|
4608
4756
|
if ((0, import_node_fs14.lstatSync)(current).isSymbolicLink()) return current;
|
|
4609
4757
|
} catch (error) {
|
|
@@ -4620,9 +4768,9 @@ function listFiles(dir) {
|
|
|
4620
4768
|
const results = [];
|
|
4621
4769
|
const walk = (current) => {
|
|
4622
4770
|
for (const entry of (0, import_node_fs14.readdirSync)(current, { withFileTypes: true })) {
|
|
4623
|
-
const path = (0,
|
|
4771
|
+
const path = (0, import_node_path13.join)(current, entry.name);
|
|
4624
4772
|
if (entry.isDirectory()) walk(path);
|
|
4625
|
-
else results.push((0,
|
|
4773
|
+
else results.push((0, import_node_path13.relative)(dir, path));
|
|
4626
4774
|
}
|
|
4627
4775
|
};
|
|
4628
4776
|
walk(dir);
|
|
@@ -4934,7 +5082,7 @@ async function projectCommand(command, parsed, deps) {
|
|
|
4934
5082
|
// src/code-connect.ts
|
|
4935
5083
|
var import_node_fs15 = require("fs");
|
|
4936
5084
|
var import_node_os4 = require("os");
|
|
4937
|
-
var
|
|
5085
|
+
var import_node_path15 = require("path");
|
|
4938
5086
|
|
|
4939
5087
|
// ../harness/dist/chunk-QTUEF2HZ.js
|
|
4940
5088
|
var HARNESS_PROTOCOL_VERSION = 1;
|
|
@@ -5020,15 +5168,15 @@ function encodeAgentInput(message2) {
|
|
|
5020
5168
|
// ../harness/dist/chunk-PHXQH4YM.js
|
|
5021
5169
|
var import_child_process = require("child_process");
|
|
5022
5170
|
var import_fs = require("fs");
|
|
5023
|
-
var
|
|
5171
|
+
var import_promises3 = require("fs/promises");
|
|
5024
5172
|
var import_path = require("path");
|
|
5025
5173
|
var import_process = require("process");
|
|
5026
|
-
var
|
|
5174
|
+
var import_promises4 = require("fs/promises");
|
|
5027
5175
|
var import_os = require("os");
|
|
5028
5176
|
var import_path2 = require("path");
|
|
5029
5177
|
var import_child_process2 = require("child_process");
|
|
5030
5178
|
var import_path3 = require("path");
|
|
5031
|
-
var
|
|
5179
|
+
var import_promises5 = require("fs/promises");
|
|
5032
5180
|
var import_os2 = require("os");
|
|
5033
5181
|
var import_path4 = require("path");
|
|
5034
5182
|
var import_child_process3 = require("child_process");
|
|
@@ -5039,7 +5187,7 @@ function assertPinnedImage(image) {
|
|
|
5039
5187
|
async function commandAvailable(engine) {
|
|
5040
5188
|
for (const directory of (process.env.PATH ?? "").split(import_path.delimiter).filter(Boolean)) {
|
|
5041
5189
|
try {
|
|
5042
|
-
await (0,
|
|
5190
|
+
await (0, import_promises3.access)((0, import_path.join)(directory, engine), import_fs.constants.X_OK);
|
|
5043
5191
|
return true;
|
|
5044
5192
|
} catch {
|
|
5045
5193
|
}
|
|
@@ -5325,7 +5473,7 @@ async function gitBlobs(cwd, entries, maxBytes) {
|
|
|
5325
5473
|
}
|
|
5326
5474
|
async function materializeGitTree(source, commitSha, options = {}) {
|
|
5327
5475
|
if (!/^[0-9a-f]{40}$/.test(commitSha)) throw new TypeError("Git tree requires an exact commit SHA");
|
|
5328
|
-
const sourceDir = await (0,
|
|
5476
|
+
const sourceDir = await (0, import_promises4.realpath)((0, import_path2.resolve)(source));
|
|
5329
5477
|
const maxFiles = options.maxFiles ?? 2e4;
|
|
5330
5478
|
const maxBytes = options.maxBytes ?? 512 * 1024 * 1024;
|
|
5331
5479
|
const inventory = (await gitOutput(sourceDir, ["ls-tree", "-rz", commitSha], 16 * 1024 * 1024)).toString("utf8").split("\0").filter(Boolean);
|
|
@@ -5334,9 +5482,9 @@ async function materializeGitTree(source, commitSha, options = {}) {
|
|
|
5334
5482
|
return match && allowedWorkspacePath(match[3]) ? [{ mode: match[1], hash: match[2], path: match[3] }] : [];
|
|
5335
5483
|
});
|
|
5336
5484
|
if (entries.length > maxFiles) throw new Error(`workspace exceeds ${maxFiles} files`);
|
|
5337
|
-
const root = await (0,
|
|
5485
|
+
const root = await (0, import_promises4.mkdtemp)((0, import_path2.join)(options.tempRoot ?? (0, import_os.tmpdir)(), "odla-git-tree-"));
|
|
5338
5486
|
const targetRoot = (0, import_path2.join)(root, "source");
|
|
5339
|
-
await (0,
|
|
5487
|
+
await (0, import_promises4.mkdir)(targetRoot);
|
|
5340
5488
|
let byteCount = 0;
|
|
5341
5489
|
try {
|
|
5342
5490
|
const blobs = await gitBlobs(sourceDir, entries, maxBytes);
|
|
@@ -5346,18 +5494,18 @@ async function materializeGitTree(source, commitSha, options = {}) {
|
|
|
5346
5494
|
if (byteCount > maxBytes) throw new Error(`workspace exceeds ${maxBytes} bytes`);
|
|
5347
5495
|
const target = (0, import_path2.resolve)(targetRoot, entry.path);
|
|
5348
5496
|
if (!target.startsWith(`${(0, import_path2.resolve)(targetRoot)}${import_path2.sep}`)) throw new TypeError("Git tree path escapes workspace");
|
|
5349
|
-
await (0,
|
|
5350
|
-
await (0,
|
|
5497
|
+
await (0, import_promises4.mkdir)((0, import_path2.resolve)(target, ".."), { recursive: true });
|
|
5498
|
+
await (0, import_promises4.writeFile)(target, content2, { flag: "wx", mode: entry.mode === "100755" ? 493 : 420 });
|
|
5351
5499
|
}
|
|
5352
5500
|
return {
|
|
5353
5501
|
root,
|
|
5354
5502
|
sourceDir: targetRoot,
|
|
5355
5503
|
fileCount: entries.length,
|
|
5356
5504
|
byteCount,
|
|
5357
|
-
cleanup: () => (0,
|
|
5505
|
+
cleanup: () => (0, import_promises4.rm)(root, { recursive: true, force: true })
|
|
5358
5506
|
};
|
|
5359
5507
|
} catch (error) {
|
|
5360
|
-
await (0,
|
|
5508
|
+
await (0, import_promises4.rm)(root, { recursive: true, force: true });
|
|
5361
5509
|
throw error;
|
|
5362
5510
|
}
|
|
5363
5511
|
}
|
|
@@ -5365,7 +5513,7 @@ async function sourceFiles(sourceDir, maxFiles, maxBytes) {
|
|
|
5365
5513
|
const files = [];
|
|
5366
5514
|
let bytes = 0;
|
|
5367
5515
|
const walk = async (dir) => {
|
|
5368
|
-
for (const entry of await (0,
|
|
5516
|
+
for (const entry of await (0, import_promises5.readdir)(dir, { withFileTypes: true })) {
|
|
5369
5517
|
if (entry.isDirectory() && SKIP_WORKSPACE_DIRS.has(entry.name)) continue;
|
|
5370
5518
|
if (!entry.isDirectory() && SECRET_WORKSPACE_FILE.test(entry.name)) continue;
|
|
5371
5519
|
const path = (0, import_path4.join)(dir, entry.name);
|
|
@@ -5375,7 +5523,7 @@ async function sourceFiles(sourceDir, maxFiles, maxBytes) {
|
|
|
5375
5523
|
continue;
|
|
5376
5524
|
}
|
|
5377
5525
|
if (!entry.isFile()) continue;
|
|
5378
|
-
const metadata2 = await (0,
|
|
5526
|
+
const metadata2 = await (0, import_promises5.stat)(path);
|
|
5379
5527
|
bytes += metadata2.size;
|
|
5380
5528
|
if (files.length + 1 > maxFiles) throw new Error(`workspace exceeds ${maxFiles} files`);
|
|
5381
5529
|
if (bytes > maxBytes) throw new Error(`workspace exceeds ${maxBytes} bytes`);
|
|
@@ -5424,7 +5572,7 @@ async function gitSourceFiles(sourceDir, maxFiles, maxBytes) {
|
|
|
5424
5572
|
if (!source.startsWith(`${root}${import_path4.sep}`)) throw new TypeError("git file path escapes workspace");
|
|
5425
5573
|
let metadata2;
|
|
5426
5574
|
try {
|
|
5427
|
-
metadata2 = await (0,
|
|
5575
|
+
metadata2 = await (0, import_promises5.lstat)(source);
|
|
5428
5576
|
} catch (error) {
|
|
5429
5577
|
if (error.code === "ENOENT") continue;
|
|
5430
5578
|
throw error;
|
|
@@ -5439,9 +5587,9 @@ async function gitSourceFiles(sourceDir, maxFiles, maxBytes) {
|
|
|
5439
5587
|
async function copyTree(files, destination) {
|
|
5440
5588
|
for (const file of files) {
|
|
5441
5589
|
const target = (0, import_path4.join)(destination, file.relativePath);
|
|
5442
|
-
await (0,
|
|
5443
|
-
await (0,
|
|
5444
|
-
await (0,
|
|
5590
|
+
await (0, import_promises5.mkdir)((0, import_path4.resolve)(target, ".."), { recursive: true });
|
|
5591
|
+
await (0, import_promises5.copyFile)(file.source, target);
|
|
5592
|
+
await (0, import_promises5.chmod)(target, file.mode);
|
|
5445
5593
|
}
|
|
5446
5594
|
}
|
|
5447
5595
|
async function captureGitDiff(root, maxBytes) {
|
|
@@ -5478,13 +5626,13 @@ async function captureGitDiff(root, maxBytes) {
|
|
|
5478
5626
|
return Buffer.concat(stdout).toString("utf8").replaceAll("a/baseline/", "a/").replaceAll("a/workspace/", "a/").replaceAll("b/baseline/", "b/").replaceAll("b/workspace/", "b/").replaceAll("--- a/baseline", "--- a").replaceAll("+++ b/workspace", "+++ b");
|
|
5479
5627
|
}
|
|
5480
5628
|
async function stageWorkspace(source, options = {}) {
|
|
5481
|
-
const sourceDir = await (0,
|
|
5482
|
-
const sourceStat = await (0,
|
|
5629
|
+
const sourceDir = await (0, import_promises5.realpath)((0, import_path4.resolve)(source));
|
|
5630
|
+
const sourceStat = await (0, import_promises5.stat)(sourceDir);
|
|
5483
5631
|
if (!sourceStat.isDirectory()) throw new TypeError("workspace source must be a directory");
|
|
5484
|
-
const root = await (0,
|
|
5632
|
+
const root = await (0, import_promises5.mkdtemp)((0, import_path4.join)(options.tempRoot ?? (0, import_os2.tmpdir)(), "odla-harness-"));
|
|
5485
5633
|
const baselineDir = (0, import_path4.join)(root, "baseline");
|
|
5486
5634
|
const workspaceDir = (0, import_path4.join)(root, "workspace");
|
|
5487
|
-
await Promise.all([(0,
|
|
5635
|
+
await Promise.all([(0, import_promises5.mkdir)(baselineDir), (0, import_promises5.mkdir)(workspaceDir)]);
|
|
5488
5636
|
try {
|
|
5489
5637
|
const maxFiles = options.maxFiles ?? 2e4;
|
|
5490
5638
|
const maxBytes = options.maxBytes ?? 512 * 1024 * 1024;
|
|
@@ -5497,26 +5645,26 @@ async function stageWorkspace(source, options = {}) {
|
|
|
5497
5645
|
fileCount: files.length,
|
|
5498
5646
|
byteCount: files.reduce((sum, file) => sum + file.bytes, 0),
|
|
5499
5647
|
patch: (maxBytes2) => captureGitDiff(root, maxBytes2),
|
|
5500
|
-
cleanup: () => (0,
|
|
5648
|
+
cleanup: () => (0, import_promises5.rm)(root, { recursive: true, force: true })
|
|
5501
5649
|
};
|
|
5502
5650
|
} catch (error) {
|
|
5503
|
-
await (0,
|
|
5651
|
+
await (0, import_promises5.rm)(root, { recursive: true, force: true });
|
|
5504
5652
|
throw error;
|
|
5505
5653
|
}
|
|
5506
5654
|
}
|
|
5507
5655
|
async function stageWorkspacePair(baselineSource, workspaceSource, options = {}) {
|
|
5508
|
-
const baselineDirSource = await (0,
|
|
5509
|
-
const workspaceDirSource = await (0,
|
|
5656
|
+
const baselineDirSource = await (0, import_promises5.realpath)((0, import_path4.resolve)(baselineSource));
|
|
5657
|
+
const workspaceDirSource = await (0, import_promises5.realpath)((0, import_path4.resolve)(workspaceSource));
|
|
5510
5658
|
const maxFiles = options.maxFiles ?? 2e4;
|
|
5511
5659
|
const maxBytes = options.maxBytes ?? 512 * 1024 * 1024;
|
|
5512
5660
|
const [baselineFiles, workspaceFiles] = await Promise.all([
|
|
5513
5661
|
sourceFiles(baselineDirSource, maxFiles, maxBytes),
|
|
5514
5662
|
sourceFiles(workspaceDirSource, maxFiles, maxBytes)
|
|
5515
5663
|
]);
|
|
5516
|
-
const root = await (0,
|
|
5664
|
+
const root = await (0, import_promises5.mkdtemp)((0, import_path4.join)(options.tempRoot ?? (0, import_os2.tmpdir)(), "odla-harness-"));
|
|
5517
5665
|
const baselineDir = (0, import_path4.join)(root, "baseline");
|
|
5518
5666
|
const workspaceDir = (0, import_path4.join)(root, "workspace");
|
|
5519
|
-
await Promise.all([(0,
|
|
5667
|
+
await Promise.all([(0, import_promises5.mkdir)(baselineDir), (0, import_promises5.mkdir)(workspaceDir)]);
|
|
5520
5668
|
try {
|
|
5521
5669
|
await Promise.all([copyTree(baselineFiles, baselineDir), copyTree(workspaceFiles, workspaceDir)]);
|
|
5522
5670
|
return {
|
|
@@ -5526,17 +5674,17 @@ async function stageWorkspacePair(baselineSource, workspaceSource, options = {})
|
|
|
5526
5674
|
fileCount: workspaceFiles.length,
|
|
5527
5675
|
byteCount: workspaceFiles.reduce((sum, file) => sum + file.bytes, 0),
|
|
5528
5676
|
patch: (maxPatchBytes) => captureGitDiff(root, maxPatchBytes),
|
|
5529
|
-
cleanup: () => (0,
|
|
5677
|
+
cleanup: () => (0, import_promises5.rm)(root, { recursive: true, force: true })
|
|
5530
5678
|
};
|
|
5531
5679
|
} catch (error) {
|
|
5532
|
-
await (0,
|
|
5680
|
+
await (0, import_promises5.rm)(root, { recursive: true, force: true });
|
|
5533
5681
|
throw error;
|
|
5534
5682
|
}
|
|
5535
5683
|
}
|
|
5536
5684
|
|
|
5537
5685
|
// ../harness/dist/chunk-GMVZ4LZH.js
|
|
5538
5686
|
var import_crypto = require("crypto");
|
|
5539
|
-
var
|
|
5687
|
+
var import_promises6 = require("fs/promises");
|
|
5540
5688
|
var import_path5 = require("path");
|
|
5541
5689
|
|
|
5542
5690
|
// ../camel/dist/chunk-7FHPOQVP.js
|
|
@@ -5873,19 +6021,19 @@ function validateSnapshot(snapshot, limits) {
|
|
|
5873
6021
|
|
|
5874
6022
|
// ../harness/dist/chunk-GMVZ4LZH.js
|
|
5875
6023
|
var import_child_process4 = require("child_process");
|
|
5876
|
-
var
|
|
6024
|
+
var import_promises7 = require("fs/promises");
|
|
5877
6025
|
var import_path6 = require("path");
|
|
5878
6026
|
var import_child_process5 = require("child_process");
|
|
5879
6027
|
var import_process2 = require("process");
|
|
5880
6028
|
var import_crypto2 = require("crypto");
|
|
5881
6029
|
var import_crypto3 = require("crypto");
|
|
5882
6030
|
var import_fs2 = require("fs");
|
|
5883
|
-
var import_promises7 = require("fs/promises");
|
|
5884
|
-
var import_path7 = require("path");
|
|
5885
6031
|
var import_promises8 = require("fs/promises");
|
|
6032
|
+
var import_path7 = require("path");
|
|
6033
|
+
var import_promises9 = require("fs/promises");
|
|
5886
6034
|
var import_os3 = require("os");
|
|
5887
6035
|
var import_path8 = require("path");
|
|
5888
|
-
var
|
|
6036
|
+
var import_promises10 = require("fs/promises");
|
|
5889
6037
|
var import_path9 = require("path");
|
|
5890
6038
|
|
|
5891
6039
|
// ../camel/dist/chunk-LAXU2AVK.js
|
|
@@ -6169,7 +6317,7 @@ var import_crypto4 = require("crypto");
|
|
|
6169
6317
|
async function digestStagedWorkspace(root, limits) {
|
|
6170
6318
|
const files = [];
|
|
6171
6319
|
const walk = async (directory) => {
|
|
6172
|
-
const entries = await (0,
|
|
6320
|
+
const entries = await (0, import_promises6.readdir)(directory, { withFileTypes: true });
|
|
6173
6321
|
for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
|
|
6174
6322
|
if (entry.isSymbolicLink()) throw new TypeError("workspace digest refuses symbolic links");
|
|
6175
6323
|
const target = (0, import_path5.resolve)(directory, entry.name);
|
|
@@ -6184,7 +6332,7 @@ async function digestStagedWorkspace(root, limits) {
|
|
|
6184
6332
|
const hash = (0, import_crypto.createHash)("sha256");
|
|
6185
6333
|
let bytes = 0;
|
|
6186
6334
|
for (const file of files.sort((left, right) => left.path.localeCompare(right.path))) {
|
|
6187
|
-
const content2 = await (0,
|
|
6335
|
+
const content2 = await (0, import_promises6.readFile)(file.target);
|
|
6188
6336
|
bytes += Buffer.byteLength(file.path) + content2.byteLength;
|
|
6189
6337
|
if (bytes > limits.maxBytes) throw new TypeError("workspace digest exceeds its byte bound");
|
|
6190
6338
|
hash.update(`${Buffer.byteLength(file.path)}:${file.path}:${content2.byteLength}:`);
|
|
@@ -6510,7 +6658,7 @@ async function applyCodePatch(workspaceDir, patch2, paths) {
|
|
|
6510
6658
|
await gitApply(workspaceDir, patch2, false);
|
|
6511
6659
|
for (const path of paths) {
|
|
6512
6660
|
try {
|
|
6513
|
-
const info = await (0,
|
|
6661
|
+
const info = await (0, import_promises7.lstat)(resolveCodePath(workspaceDir, path));
|
|
6514
6662
|
if (info.isSymbolicLink() || !info.isFile() && !info.isDirectory()) {
|
|
6515
6663
|
throw new TypeError("patch created a non-regular workspace entry");
|
|
6516
6664
|
}
|
|
@@ -6801,7 +6949,7 @@ async function inspectArtifacts(workspaceDir, recipe2) {
|
|
|
6801
6949
|
for (const artifact of recipe2.expectedArtifacts ?? []) {
|
|
6802
6950
|
try {
|
|
6803
6951
|
const path = (0, import_path7.join)(workspaceDir, artifact.path);
|
|
6804
|
-
const info = await (0,
|
|
6952
|
+
const info = await (0, import_promises8.lstat)(path);
|
|
6805
6953
|
if (!info.isFile() || info.isSymbolicLink()) {
|
|
6806
6954
|
receipts.push({ artifactId: artifact.id, status: "invalid", bytes: null, digest: null });
|
|
6807
6955
|
} else if (info.size > artifact.maximumBytes) {
|
|
@@ -6982,9 +7130,9 @@ var RESERVED2 = /* @__PURE__ */ new Set([".git", ".odla", ".wrangler", "node_mod
|
|
|
6982
7130
|
var SECRET2 = /^(?:\.env(?:\..+)?|\.dev\.vars|credentials(?:\..+)?\.json|dev-token(?:\..+)?\.json)$/i;
|
|
6983
7131
|
async function materializeCodeRuntimeSource(snapshot, tempRoot = (0, import_os3.tmpdir)()) {
|
|
6984
7132
|
if (!snapshot.files.length || snapshot.files.length > 1e4) throw new TypeError("Code source file count is invalid");
|
|
6985
|
-
const root = await (0,
|
|
7133
|
+
const root = await (0, import_promises9.mkdtemp)((0, import_path8.join)(tempRoot, "odla-code-source-"));
|
|
6986
7134
|
const sourceDir = (0, import_path8.join)(root, "source");
|
|
6987
|
-
await (0,
|
|
7135
|
+
await (0, import_promises9.mkdir)(sourceDir);
|
|
6988
7136
|
const seen = /* @__PURE__ */ new Set();
|
|
6989
7137
|
let bytes = 0;
|
|
6990
7138
|
try {
|
|
@@ -6996,8 +7144,8 @@ async function materializeCodeRuntimeSource(snapshot, tempRoot = (0, import_os3.
|
|
|
6996
7144
|
if (bytes > 16 * 1024 * 1024) throw new TypeError("Code source exceeds its byte bound");
|
|
6997
7145
|
const target = (0, import_path8.resolve)(sourceDir, file.path);
|
|
6998
7146
|
if (!target.startsWith(`${(0, import_path8.resolve)(sourceDir)}${import_path8.sep}`)) throw new TypeError("Code source path escapes its root");
|
|
6999
|
-
await (0,
|
|
7000
|
-
await (0,
|
|
7147
|
+
await (0, import_promises9.mkdir)((0, import_path8.dirname)(target), { recursive: true });
|
|
7148
|
+
await (0, import_promises9.writeFile)(target, file.content, { flag: "wx", mode: 420 });
|
|
7001
7149
|
}
|
|
7002
7150
|
for (const reference of snapshot.references ?? []) {
|
|
7003
7151
|
validateAlias(reference.alias);
|
|
@@ -7011,13 +7159,13 @@ async function materializeCodeRuntimeSource(snapshot, tempRoot = (0, import_os3.
|
|
|
7011
7159
|
if (bytes > 80 * 1024 * 1024) throw new TypeError("Code source set exceeds its byte bound");
|
|
7012
7160
|
const target = (0, import_path8.resolve)(sourceDir, path);
|
|
7013
7161
|
if (!target.startsWith(`${(0, import_path8.resolve)(sourceDir)}${import_path8.sep}`)) throw new TypeError("Code reference path escapes its root");
|
|
7014
|
-
await (0,
|
|
7015
|
-
await (0,
|
|
7162
|
+
await (0, import_promises9.mkdir)((0, import_path8.dirname)(target), { recursive: true });
|
|
7163
|
+
await (0, import_promises9.writeFile)(target, file.content, { flag: "wx", mode: 292 });
|
|
7016
7164
|
}
|
|
7017
7165
|
}
|
|
7018
|
-
return { sourceDir, cleanup: () => (0,
|
|
7166
|
+
return { sourceDir, cleanup: () => (0, import_promises9.rm)(root, { recursive: true, force: true }) };
|
|
7019
7167
|
} catch (cause) {
|
|
7020
|
-
await (0,
|
|
7168
|
+
await (0, import_promises9.rm)(root, { recursive: true, force: true });
|
|
7021
7169
|
throw cause;
|
|
7022
7170
|
}
|
|
7023
7171
|
}
|
|
@@ -7038,8 +7186,8 @@ async function attachCodeRuntimeReferences(workspace, references) {
|
|
|
7038
7186
|
for (const root of [workspace.baselineDir, workspace.workspaceDir]) {
|
|
7039
7187
|
const target = (0, import_path8.resolve)(root, path);
|
|
7040
7188
|
if (!target.startsWith(`${(0, import_path8.resolve)(root)}${import_path8.sep}`)) throw new TypeError("Code reference path escapes its root");
|
|
7041
|
-
await (0,
|
|
7042
|
-
await (0,
|
|
7189
|
+
await (0, import_promises9.mkdir)((0, import_path8.dirname)(target), { recursive: true });
|
|
7190
|
+
await (0, import_promises9.writeFile)(target, file.content, { flag: "wx", mode: 292 });
|
|
7043
7191
|
}
|
|
7044
7192
|
}
|
|
7045
7193
|
}
|
|
@@ -7225,11 +7373,11 @@ async function read(context, request2, options, policy) {
|
|
|
7225
7373
|
const allowed = await policy.read(policyContext(context, request2, options, { paths, path, startLine, endLine }));
|
|
7226
7374
|
if (!allowed) return response(request2, false, "tool denied by CaMeL policy");
|
|
7227
7375
|
const target = resolveCodePath(context.workspaceDir, path);
|
|
7228
|
-
const info = await (0,
|
|
7376
|
+
const info = await (0, import_promises10.stat)(target);
|
|
7229
7377
|
if (!info.isFile() || info.size > Math.max(options.maxReadBytes ?? 128 * 1024, 2 * 1024 * 1024)) {
|
|
7230
7378
|
throw new TypeError("file is not a bounded regular source file");
|
|
7231
7379
|
}
|
|
7232
|
-
const source = await (0,
|
|
7380
|
+
const source = await (0, import_promises10.readFile)(target);
|
|
7233
7381
|
if (source.includes(0)) throw new TypeError("binary files are not readable through this tool");
|
|
7234
7382
|
const lines = source.toString("utf8").split("\n");
|
|
7235
7383
|
const content2 = lines.slice(startLine - 1, endLine).join("\n");
|
|
@@ -7306,7 +7454,7 @@ function policyContext(context, request2, options, extra) {
|
|
|
7306
7454
|
async function registeredFiles(root, limit) {
|
|
7307
7455
|
const paths = [];
|
|
7308
7456
|
const walk = async (directory) => {
|
|
7309
|
-
for (const entry of await (0,
|
|
7457
|
+
for (const entry of await (0, import_promises10.readdir)(directory, { withFileTypes: true })) {
|
|
7310
7458
|
if (entry.isSymbolicLink()) throw new TypeError("workspace contains a symbolic link");
|
|
7311
7459
|
const target = (0, import_path9.resolve)(directory, entry.name);
|
|
7312
7460
|
if (entry.isDirectory()) await walk(target);
|
|
@@ -7905,8 +8053,8 @@ function hostedPollTimeout(value2 = 10 * 6e4) {
|
|
|
7905
8053
|
}
|
|
7906
8054
|
async function waitForHostedPoll(milliseconds, signal) {
|
|
7907
8055
|
if (signal?.aborted) throw signal.reason ?? new DOMException("aborted", "AbortError");
|
|
7908
|
-
await new Promise((
|
|
7909
|
-
const timer = setTimeout(
|
|
8056
|
+
await new Promise((resolve13, reject) => {
|
|
8057
|
+
const timer = setTimeout(resolve13, milliseconds);
|
|
7910
8058
|
signal?.addEventListener("abort", () => {
|
|
7911
8059
|
clearTimeout(timer);
|
|
7912
8060
|
reject(signal.reason ?? new DOMException("aborted", "AbortError"));
|
|
@@ -8091,9 +8239,9 @@ function digestText(value2) {
|
|
|
8091
8239
|
// src/code-images.ts
|
|
8092
8240
|
var import_node_child_process6 = require("child_process");
|
|
8093
8241
|
var import_node_crypto3 = require("crypto");
|
|
8094
|
-
var
|
|
8242
|
+
var import_promises11 = require("fs/promises");
|
|
8095
8243
|
var import_node_os3 = require("os");
|
|
8096
|
-
var
|
|
8244
|
+
var import_node_path14 = require("path");
|
|
8097
8245
|
var import_node_url3 = require("url");
|
|
8098
8246
|
|
|
8099
8247
|
// src/code-runtime-config.ts
|
|
@@ -8173,16 +8321,16 @@ function embeddedPiAssetPath() {
|
|
|
8173
8321
|
return (0, import_node_url3.fileURLToPath)(new URL("./runtime/pi-agent.js", importMetaUrl));
|
|
8174
8322
|
}
|
|
8175
8323
|
async function embeddedPiImageName() {
|
|
8176
|
-
const bundle = await (0,
|
|
8324
|
+
const bundle = await (0, import_promises11.readFile)(embeddedPiAssetPath()).catch(() => {
|
|
8177
8325
|
throw new Error("CLI-embedded Pi runtime is missing; reinstall this exact @odla-ai/cli version");
|
|
8178
8326
|
});
|
|
8179
8327
|
return `odla-ai/pi-agent:embedded-sha256-${(0, import_node_crypto3.createHash)("sha256").update(bundle).digest("hex")}`;
|
|
8180
8328
|
}
|
|
8181
8329
|
async function buildEmbeddedPiImage(engine, image, run) {
|
|
8182
|
-
const context = await (0,
|
|
8330
|
+
const context = await (0, import_promises11.mkdtemp)((0, import_node_path14.join)((0, import_node_os3.tmpdir)(), "odla-code-pi-"));
|
|
8183
8331
|
try {
|
|
8184
|
-
await (0,
|
|
8185
|
-
await (0,
|
|
8332
|
+
await (0, import_promises11.copyFile)(embeddedPiAssetPath(), (0, import_node_path14.join)(context, "pi-agent.js"));
|
|
8333
|
+
await (0, import_promises11.writeFile)((0, import_node_path14.join)(context, "Dockerfile"), [
|
|
8186
8334
|
`FROM ${CODE_NODE_IMAGE}`,
|
|
8187
8335
|
"COPY pi-agent.js /opt/odla/pi-agent.js",
|
|
8188
8336
|
"WORKDIR /workspace",
|
|
@@ -8191,14 +8339,14 @@ async function buildEmbeddedPiImage(engine, image, run) {
|
|
|
8191
8339
|
].join("\n"), { mode: 384 });
|
|
8192
8340
|
await run(engine, ["build", "--tag", image, context], "inherit");
|
|
8193
8341
|
} finally {
|
|
8194
|
-
await (0,
|
|
8342
|
+
await (0, import_promises11.rm)(context, { recursive: true, force: true });
|
|
8195
8343
|
}
|
|
8196
8344
|
}
|
|
8197
8345
|
|
|
8198
8346
|
// src/code-connect.ts
|
|
8199
8347
|
async function codeConnect(options) {
|
|
8200
8348
|
const cwd = options.cwd ?? process.cwd();
|
|
8201
|
-
const configPath = (0,
|
|
8349
|
+
const configPath = (0, import_node_path15.resolve)(cwd, options.configPath);
|
|
8202
8350
|
const cfg = (0, import_node_fs15.existsSync)(configPath) ? await loadProjectConfig(configPath) : null;
|
|
8203
8351
|
const requestedAppId = options.appId?.trim();
|
|
8204
8352
|
if (requestedAppId && !/^[a-z0-9][a-z0-9-]{1,62}$/.test(requestedAppId)) {
|
|
@@ -8567,10 +8715,8 @@ function requireName(parsed) {
|
|
|
8567
8715
|
return name;
|
|
8568
8716
|
}
|
|
8569
8717
|
|
|
8570
|
-
// src/help.ts
|
|
8571
|
-
|
|
8572
|
-
output.log(`odla-ai
|
|
8573
|
-
|
|
8718
|
+
// src/help-usage.ts
|
|
8719
|
+
var USAGE_SECTION = `
|
|
8574
8720
|
Start here:
|
|
8575
8721
|
odla-ai runbook ask "<question>" The current procedure, from odla's own
|
|
8576
8722
|
runbooks. Ask BEFORE searching the web or
|
|
@@ -8604,6 +8750,7 @@ Usage:
|
|
|
8604
8750
|
odla-ai app owners list [--config odla.config.mjs] [--email <odla-account>] [--json]
|
|
8605
8751
|
odla-ai app owners add <email> [--email <odla-account>] [--json]
|
|
8606
8752
|
odla-ai app owners remove <email> [--email <odla-account>] [--json]
|
|
8753
|
+
odla-ai brand design unpack <bundle.html|-> [--out <dir>] [--json]
|
|
8607
8754
|
odla-ai pm goal list [--app <id>] [--status <s>] [--q <text>] [--limit <n>] [--offset <n>] [--json]
|
|
8608
8755
|
odla-ai pm task list [--app <id>] [--column <c>] [--goal <id>] [--assignee <id>] [--q <text>] [--limit <n>] [--offset <n>] [--json]
|
|
8609
8756
|
odla-ai pm decision list [--app <id>] [--status <s>] [--q <text>] [--limit <n>] [--offset <n>] [--json]
|
|
@@ -8683,8 +8830,12 @@ Usage:
|
|
|
8683
8830
|
odla-ai secrets push --env <env> [--config odla.config.mjs] [--dry-run] [--yes]
|
|
8684
8831
|
odla-ai secrets set <name> --env <env> (--from-env <NAME>|--stdin) [--email <odla-account>] [--config odla.config.mjs] [--yes]
|
|
8685
8832
|
odla-ai secrets set-clerk-key --env <env> (--from-env <NAME>|--stdin) [--email <odla-account>] [--config odla.config.mjs] [--yes]
|
|
8686
|
-
odla-ai version
|
|
8833
|
+
odla-ai version`;
|
|
8687
8834
|
|
|
8835
|
+
// src/help.ts
|
|
8836
|
+
function printHelp(output = console) {
|
|
8837
|
+
output.log(`odla-ai
|
|
8838
|
+
${USAGE_SECTION}
|
|
8688
8839
|
Commands:
|
|
8689
8840
|
agent Inspect durable agent wakeups and explicitly requeue a
|
|
8690
8841
|
dead-lettered job; JSON output is stable for remote operators.
|
|
@@ -9133,7 +9284,7 @@ function jsonl(ctx, parsed, value2) {
|
|
|
9133
9284
|
}
|
|
9134
9285
|
async function discussWatch(ctx, topicId, parsed) {
|
|
9135
9286
|
if (ctx.json && parsed.options.jsonl === true) throw new Error("--json and --jsonl cannot be combined");
|
|
9136
|
-
const sleep = ctx.sleep ?? ((ms) => new Promise((
|
|
9287
|
+
const sleep = ctx.sleep ?? ((ms) => new Promise((resolve13) => setTimeout(resolve13, ms)));
|
|
9137
9288
|
const now = ctx.now ?? Date.now;
|
|
9138
9289
|
const intervalMs = (numberOpt2(parsed, "interval", DEFAULT_INTERVAL_MS / 1e3) ?? DEFAULT_INTERVAL_MS / 1e3) * 1e3;
|
|
9139
9290
|
const timeoutSeconds = numberOpt2(parsed, "timeout");
|
|
@@ -10605,6 +10756,7 @@ var COMMAND_SURFACE = {
|
|
|
10605
10756
|
promote: {},
|
|
10606
10757
|
owners: { list: {}, add: {}, remove: {} }
|
|
10607
10758
|
},
|
|
10759
|
+
brand: { design: { unpack: {} } },
|
|
10608
10760
|
calendar: { status: {}, calendars: {}, connect: {}, disconnect: {} },
|
|
10609
10761
|
capabilities: {},
|
|
10610
10762
|
code: { connect: {} },
|
|
@@ -10910,7 +11062,7 @@ async function runbookRemove(ctx, slug) {
|
|
|
10910
11062
|
|
|
10911
11063
|
// src/runbook-import.ts
|
|
10912
11064
|
var import_node_fs18 = require("fs");
|
|
10913
|
-
var
|
|
11065
|
+
var import_node_path16 = require("path");
|
|
10914
11066
|
function parseRunbook(text2, slug) {
|
|
10915
11067
|
let rest = text2;
|
|
10916
11068
|
const meta = {};
|
|
@@ -10939,8 +11091,8 @@ function readRunbookDir(dir) {
|
|
|
10939
11091
|
const files = (0, import_node_fs18.readdirSync)(dir).filter((f) => f.endsWith(".md")).sort();
|
|
10940
11092
|
if (!files.length) throw new Error(`no .md files in ${dir}`);
|
|
10941
11093
|
return files.map((file) => {
|
|
10942
|
-
const slug = (0,
|
|
10943
|
-
const parsed = parseRunbook((0, import_node_fs18.readFileSync)((0,
|
|
11094
|
+
const slug = (0, import_node_path16.basename)(file, ".md");
|
|
11095
|
+
const parsed = parseRunbook((0, import_node_fs18.readFileSync)((0, import_node_path16.join)(dir, file), "utf8"), slug);
|
|
10944
11096
|
return { file, slug, ...parsed, words: parsed.body.split(/\s+/).filter(Boolean).length };
|
|
10945
11097
|
});
|
|
10946
11098
|
}
|
|
@@ -11014,7 +11166,7 @@ async function upsert(ctx, r, visibility) {
|
|
|
11014
11166
|
// src/runbook-impact.ts
|
|
11015
11167
|
var import_node_child_process7 = require("child_process");
|
|
11016
11168
|
var import_node_fs19 = require("fs");
|
|
11017
|
-
var
|
|
11169
|
+
var import_node_path17 = require("path");
|
|
11018
11170
|
|
|
11019
11171
|
// src/runbook-impact-scan.ts
|
|
11020
11172
|
var DECL = /^[+-]\s*export\s+(?:declare\s+)?(?:default\s+)?(?:abstract\s+)?(?:async\s+)?(?:const|let|var|function|class|interface|type|enum)\s+([A-Za-z_$][\w$]*)/;
|
|
@@ -11183,7 +11335,7 @@ ${body.split("\n").map((line) => `+${line}`).join("\n")}
|
|
|
11183
11335
|
}
|
|
11184
11336
|
function manifestLabeller(root) {
|
|
11185
11337
|
return (workspace) => {
|
|
11186
|
-
const manifest = (0,
|
|
11338
|
+
const manifest = (0, import_node_path17.join)(root, workspace, "package.json");
|
|
11187
11339
|
if (!(0, import_node_fs19.existsSync)(manifest)) return void 0;
|
|
11188
11340
|
try {
|
|
11189
11341
|
const name = JSON.parse((0, import_node_fs19.readFileSync)(manifest, "utf8")).name;
|
|
@@ -11253,7 +11405,7 @@ function report3(ctx, impacts) {
|
|
|
11253
11405
|
async function runbookImpact(ctx, options, deps = {}) {
|
|
11254
11406
|
const cwd = deps.cwd ?? process.cwd();
|
|
11255
11407
|
const runGit = deps.runGit ?? gitRunner(cwd);
|
|
11256
|
-
const read3 = deps.readRepoFile ?? ((path) => (0, import_node_fs19.readFileSync)((0,
|
|
11408
|
+
const read3 = deps.readRepoFile ?? ((path) => (0, import_node_fs19.readFileSync)((0, import_node_path17.join)(cwd, path), "utf8"));
|
|
11257
11409
|
const surfaces = changedSurfaces(collectDiff(runGit, options.base, read3), manifestLabeller(cwd));
|
|
11258
11410
|
if (!surfaces.length) {
|
|
11259
11411
|
return ctx.out.log(
|
|
@@ -11388,7 +11540,7 @@ async function runbookComment(ctx, slug, body) {
|
|
|
11388
11540
|
var import_node_child_process8 = require("child_process");
|
|
11389
11541
|
var import_node_fs20 = require("fs");
|
|
11390
11542
|
var import_node_os5 = require("os");
|
|
11391
|
-
var
|
|
11543
|
+
var import_node_path18 = require("path");
|
|
11392
11544
|
var import_node_process12 = __toESM(require("process"), 1);
|
|
11393
11545
|
var EDITOR_ENV = ["ODLA_EDITOR", "VISUAL", "EDITOR"];
|
|
11394
11546
|
function resolveEditor(env = import_node_process12.default.env) {
|
|
@@ -11414,8 +11566,8 @@ function editText(initial, slug, deps = {}) {
|
|
|
11414
11566
|
);
|
|
11415
11567
|
if (!interactive())
|
|
11416
11568
|
throw new Error(`cannot open an editor without a terminal \u2014 pass --file <path> or --body "\u2026" instead`);
|
|
11417
|
-
const dir = (0, import_node_fs20.mkdtempSync)((0,
|
|
11418
|
-
const file = (0,
|
|
11569
|
+
const dir = (0, import_node_fs20.mkdtempSync)((0, import_node_path18.join)((0, import_node_os5.tmpdir)(), "odla-runbook-"));
|
|
11570
|
+
const file = (0, import_node_path18.join)(dir, `${slug}.md`);
|
|
11419
11571
|
try {
|
|
11420
11572
|
(0, import_node_fs20.writeFileSync)(file, initial, { mode: 384 });
|
|
11421
11573
|
const code = defaultRunOrInjected(deps)(editor, file);
|
|
@@ -11757,7 +11909,7 @@ async function runbookCommand(parsed, deps = {}) {
|
|
|
11757
11909
|
}
|
|
11758
11910
|
|
|
11759
11911
|
// src/security-command-context.ts
|
|
11760
|
-
var
|
|
11912
|
+
var import_promises12 = require("readline/promises");
|
|
11761
11913
|
async function hostedSecurityContext(parsed, dependencies) {
|
|
11762
11914
|
const configPath = stringOpt(parsed.options.config) ?? "odla.config.mjs";
|
|
11763
11915
|
const cfg = await loadProjectConfig(configPath);
|
|
@@ -11783,7 +11935,7 @@ async function hostedSecurityContext(parsed, dependencies) {
|
|
|
11783
11935
|
async function interactiveConfirmation(message2, dependencies) {
|
|
11784
11936
|
if (dependencies.confirm) return dependencies.confirm(message2);
|
|
11785
11937
|
if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
|
|
11786
|
-
const prompt = (0,
|
|
11938
|
+
const prompt = (0, import_promises12.createInterface)({ input: process.stdin, output: process.stdout });
|
|
11787
11939
|
try {
|
|
11788
11940
|
const answer = await prompt.question(`${message2} [y/N] `);
|
|
11789
11941
|
return /^y(?:es)?$/i.test(answer.trim());
|
|
@@ -11910,7 +12062,7 @@ function hostedSeverity(value2, flag) {
|
|
|
11910
12062
|
var import_security2 = require("@odla-ai/security");
|
|
11911
12063
|
|
|
11912
12064
|
// src/security.ts
|
|
11913
|
-
var
|
|
12065
|
+
var import_node_path19 = require("path");
|
|
11914
12066
|
var import_security = require("@odla-ai/security");
|
|
11915
12067
|
var import_node3 = require("@odla-ai/security/node");
|
|
11916
12068
|
async function runHostedSecurity(options) {
|
|
@@ -11922,9 +12074,9 @@ async function runHostedSecurity(options) {
|
|
|
11922
12074
|
const appId = selfAudit ? "odla-ai" : cfg.app.id;
|
|
11923
12075
|
const env = selfAudit ? "prod" : selectEnv(options.env, cfg.envs, cfg.configPath, cfg.rootDir);
|
|
11924
12076
|
const platform = options.platform ?? cfg?.platformUrl ?? "https://odla.ai";
|
|
11925
|
-
const target = (0,
|
|
11926
|
-
const output = (0,
|
|
11927
|
-
const outputRelative = (0,
|
|
12077
|
+
const target = (0, import_node_path19.resolve)(options.target ?? cfg?.rootDir ?? ".");
|
|
12078
|
+
const output = (0, import_node_path19.resolve)(options.out ?? (0, import_node_path19.resolve)(target, ".odla/security/hosted"));
|
|
12079
|
+
const outputRelative = (0, import_node_path19.relative)(target, output).split(import_node_path19.sep).join("/");
|
|
11928
12080
|
if (!outputRelative) throw new Error("Hosted security output cannot be the repository root");
|
|
11929
12081
|
const profile = profileFor(options.profile ?? "odla", options.maxHuntTasks ?? 12);
|
|
11930
12082
|
const tokenRequest = {
|
|
@@ -11936,7 +12088,7 @@ async function runHostedSecurity(options) {
|
|
|
11936
12088
|
};
|
|
11937
12089
|
const token = await injectedToken(options, tokenRequest);
|
|
11938
12090
|
const snapshot = await (0, import_node3.snapshotDirectory)(target, {
|
|
11939
|
-
exclude: !outputRelative.startsWith("../") && !(0,
|
|
12091
|
+
exclude: !outputRelative.startsWith("../") && !(0, import_node_path19.isAbsolute)(outputRelative) ? [outputRelative] : []
|
|
11940
12092
|
});
|
|
11941
12093
|
const hosted = await (0, import_security.createPlatformSecurityReasoners)({
|
|
11942
12094
|
platform,
|
|
@@ -11954,7 +12106,7 @@ async function runHostedSecurity(options) {
|
|
|
11954
12106
|
});
|
|
11955
12107
|
const harness = (0, import_security.createSecurityHarness)({
|
|
11956
12108
|
profile,
|
|
11957
|
-
store: new import_node3.FileRunStore((0,
|
|
12109
|
+
store: new import_node3.FileRunStore((0, import_node_path19.resolve)(output, "state")),
|
|
11958
12110
|
discoveryReasoner: hosted.discoveryReasoner,
|
|
11959
12111
|
validationReasoner: hosted.validationReasoner,
|
|
11960
12112
|
policy: {
|
|
@@ -11978,7 +12130,7 @@ async function runHostedSecurity(options) {
|
|
|
11978
12130
|
function selectEnv(requested, declared, configPath, rootDir) {
|
|
11979
12131
|
const env = requested ?? (declared.includes("dev") ? "dev" : declared[0]);
|
|
11980
12132
|
if (!env || !declared.includes(env)) {
|
|
11981
|
-
const shown = (0,
|
|
12133
|
+
const shown = (0, import_node_path19.relative)(rootDir, configPath) || configPath;
|
|
11982
12134
|
throw new Error(`env "${env ?? ""}" is not declared in ${shown}`);
|
|
11983
12135
|
}
|
|
11984
12136
|
return env;
|
|
@@ -12007,7 +12159,7 @@ function printSummary(out, appId, env, run, report4, output) {
|
|
|
12007
12159
|
out.log(` coverage: ${report4.coverageStatus} ${complete}/${report4.coverage.length} blocked=${report4.metrics.blockedCells} shallow=${report4.metrics.shallowCells} unscheduled=${report4.metrics.unscheduledCells} budget_exhausted=${report4.metrics.budgetExhaustedCells}`);
|
|
12008
12160
|
if (report4.callBudget) out.log(` calls: discovery=${formatBudget(report4.callBudget.discovery)} validation=${formatBudget(report4.callBudget.validation)}`);
|
|
12009
12161
|
out.log(` findings: confirmed=${report4.metrics.confirmed} needs_reproduction=${report4.metrics.needsReproduction} candidates=${report4.metrics.candidates}`);
|
|
12010
|
-
out.log(` report: ${(0,
|
|
12162
|
+
out.log(` report: ${(0, import_node_path19.resolve)(output, "REPORT.md")}`);
|
|
12011
12163
|
}
|
|
12012
12164
|
function formatBudget(usage) {
|
|
12013
12165
|
return usage ? `${usage.usedCalls}/${usage.maxCalls} skipped=${usage.skippedCalls}` : "caller-managed";
|
|
@@ -12519,6 +12671,10 @@ async function runCli(argv = process.argv.slice(2), dependencies = {}) {
|
|
|
12519
12671
|
await securityCommand(parsed, runtime);
|
|
12520
12672
|
return;
|
|
12521
12673
|
}
|
|
12674
|
+
if (command === "brand") {
|
|
12675
|
+
await brandCommand(parsed, runtime);
|
|
12676
|
+
return;
|
|
12677
|
+
}
|
|
12522
12678
|
if (command === "pm") {
|
|
12523
12679
|
await pmCommand(parsed, runtime);
|
|
12524
12680
|
return;
|