@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/bin.cjs
CHANGED
|
@@ -246,7 +246,7 @@ var import_node_process2 = __toESM(require("process"), 1);
|
|
|
246
246
|
async function openUrl(url, options = {}) {
|
|
247
247
|
const command = openerFor(options.platform ?? import_node_process2.default.platform);
|
|
248
248
|
const doSpawn = options.spawnImpl ?? import_node_child_process.spawn;
|
|
249
|
-
await new Promise((
|
|
249
|
+
await new Promise((resolve13, reject) => {
|
|
250
250
|
const child = doSpawn(command.cmd, [...command.args, url], {
|
|
251
251
|
stdio: "ignore",
|
|
252
252
|
detached: true
|
|
@@ -254,7 +254,7 @@ async function openUrl(url, options = {}) {
|
|
|
254
254
|
child.once("error", reject);
|
|
255
255
|
child.once("spawn", () => {
|
|
256
256
|
child.unref();
|
|
257
|
-
|
|
257
|
+
resolve13();
|
|
258
258
|
});
|
|
259
259
|
});
|
|
260
260
|
}
|
|
@@ -338,6 +338,7 @@ async function freshHandshake(ctx, waitMs) {
|
|
|
338
338
|
endpoint: ctx.cfg.platformUrl,
|
|
339
339
|
email: ctx.email,
|
|
340
340
|
label: `${ctx.cfg.app.id} provisioner`,
|
|
341
|
+
projectIds: [ctx.cfg.app.id],
|
|
341
342
|
fetch: ctx.doFetch,
|
|
342
343
|
waitMs,
|
|
343
344
|
onCode: async ({ userCode, deviceCode, expiresIn, interval, verificationUriComplete }) => {
|
|
@@ -2175,6 +2176,153 @@ async function appCommand(parsed, dependencies = {}) {
|
|
|
2175
2176
|
else await appRestore(options);
|
|
2176
2177
|
}
|
|
2177
2178
|
|
|
2179
|
+
// src/brand-command.ts
|
|
2180
|
+
var import_promises2 = require("fs/promises");
|
|
2181
|
+
var import_node_path7 = require("path");
|
|
2182
|
+
|
|
2183
|
+
// src/brand-design-unpack.ts
|
|
2184
|
+
var import_node_zlib = require("zlib");
|
|
2185
|
+
var import_brand = require("@odla-ai/brand");
|
|
2186
|
+
var EXTENSIONS = {
|
|
2187
|
+
"image/png": "png",
|
|
2188
|
+
"image/jpeg": "jpg",
|
|
2189
|
+
"image/gif": "gif",
|
|
2190
|
+
"image/webp": "webp",
|
|
2191
|
+
"image/svg+xml": "svg",
|
|
2192
|
+
"image/avif": "avif",
|
|
2193
|
+
"font/woff2": "woff2",
|
|
2194
|
+
"font/woff": "woff",
|
|
2195
|
+
"font/ttf": "ttf",
|
|
2196
|
+
"font/otf": "otf",
|
|
2197
|
+
"text/javascript": "js",
|
|
2198
|
+
"application/javascript": "js",
|
|
2199
|
+
"text/css": "css",
|
|
2200
|
+
"text/html": "html",
|
|
2201
|
+
"application/json": "json"
|
|
2202
|
+
};
|
|
2203
|
+
var encode = (text2) => new TextEncoder().encode(text2);
|
|
2204
|
+
function assetFileName(uuid, mime) {
|
|
2205
|
+
const ext = EXTENSIONS[mime.split(";")[0].trim().toLowerCase()] ?? "bin";
|
|
2206
|
+
return `${uuid.replace(/[^a-zA-Z0-9._-]/g, "_")}.${ext}`;
|
|
2207
|
+
}
|
|
2208
|
+
function decodePayload(data, compressed) {
|
|
2209
|
+
const raw = Buffer.from(data, "base64");
|
|
2210
|
+
return new Uint8Array(compressed ? (0, import_node_zlib.gunzipSync)(raw) : raw);
|
|
2211
|
+
}
|
|
2212
|
+
function rewriteReferences(template, assetPaths, pagePaths) {
|
|
2213
|
+
let out = template;
|
|
2214
|
+
for (const [uuid, path] of pagePaths) {
|
|
2215
|
+
out = out.split(`about:blank#${uuid}`).join(path);
|
|
2216
|
+
}
|
|
2217
|
+
for (const [uuid, path] of assetPaths) {
|
|
2218
|
+
out = out.split(uuid).join(path);
|
|
2219
|
+
}
|
|
2220
|
+
return out;
|
|
2221
|
+
}
|
|
2222
|
+
function tokensCss(digest) {
|
|
2223
|
+
if (Object.keys(digest.tokens.light).length === 0) return null;
|
|
2224
|
+
return (0, import_brand.renderTokensCss)(digest.tokens.light, { dark: digest.tokens.dark });
|
|
2225
|
+
}
|
|
2226
|
+
function unpackDesign(html) {
|
|
2227
|
+
const bundle = (0, import_brand.parseDesignBundle)(html);
|
|
2228
|
+
const manifest = (0, import_brand.readDesignManifest)(html);
|
|
2229
|
+
const digest = (0, import_brand.digestDesignBundle)(bundle);
|
|
2230
|
+
const pageUuids = new Set(bundle.pageOrder);
|
|
2231
|
+
const files = [];
|
|
2232
|
+
const failed = [];
|
|
2233
|
+
const assetPaths = /* @__PURE__ */ new Map();
|
|
2234
|
+
const pagePaths = /* @__PURE__ */ new Map();
|
|
2235
|
+
for (const [uuid, entry] of Object.entries(manifest)) {
|
|
2236
|
+
let bytes;
|
|
2237
|
+
try {
|
|
2238
|
+
bytes = decodePayload(entry.data, entry.compressed);
|
|
2239
|
+
} catch {
|
|
2240
|
+
failed.push(uuid);
|
|
2241
|
+
continue;
|
|
2242
|
+
}
|
|
2243
|
+
if (pageUuids.has(uuid)) {
|
|
2244
|
+
const path2 = `pages/${assetFileName(uuid, "text/html")}`;
|
|
2245
|
+
pagePaths.set(uuid, `./${path2}`);
|
|
2246
|
+
files.push({ path: path2, bytes });
|
|
2247
|
+
continue;
|
|
2248
|
+
}
|
|
2249
|
+
const path = `assets/${assetFileName(uuid, entry.mime)}`;
|
|
2250
|
+
assetPaths.set(uuid, `./${path}`);
|
|
2251
|
+
files.push({ path, bytes });
|
|
2252
|
+
}
|
|
2253
|
+
files.push({
|
|
2254
|
+
path: "index.html",
|
|
2255
|
+
bytes: encode(rewriteReferences(bundle.template, assetPaths, pagePaths))
|
|
2256
|
+
});
|
|
2257
|
+
files.push({ path: "digest.json", bytes: encode(`${JSON.stringify(digest, null, 2)}
|
|
2258
|
+
`) });
|
|
2259
|
+
const css = tokensCss(digest);
|
|
2260
|
+
if (css !== null) files.push({ path: "tokens.css", bytes: encode(css) });
|
|
2261
|
+
if (bundle.thumbnailSvg) files.push({ path: "thumbnail.svg", bytes: encode(bundle.thumbnailSvg) });
|
|
2262
|
+
return { files, digest, failed };
|
|
2263
|
+
}
|
|
2264
|
+
function describeUnpack(result, outDir) {
|
|
2265
|
+
const { digest } = result;
|
|
2266
|
+
const lines = [
|
|
2267
|
+
`Unpacked ${digest.title ? `"${digest.title}"` : "design"} into ${outDir}`,
|
|
2268
|
+
` index.html the design, offline-runnable (${digest.templateBytes} bytes)`,
|
|
2269
|
+
` assets/ ${digest.assetCount} embedded files (${digest.assetBytes} bytes)`,
|
|
2270
|
+
` digest.json ${Object.keys(digest.tokens.light).length} --ui-* tokens, ${digest.props.length} props, ${digest.outline.length} headings`
|
|
2271
|
+
];
|
|
2272
|
+
if (result.files.some((f) => f.path === "tokens.css"))
|
|
2273
|
+
lines.push(" tokens.css the design's tokens as an @odla-ai/ui theme sheet");
|
|
2274
|
+
if (digest.fonts.length > 0) lines.push(`Typefaces: ${digest.fonts.join(", ")}`);
|
|
2275
|
+
if (result.failed.length > 0)
|
|
2276
|
+
lines.push(`WARNING: ${result.failed.length} embedded asset(s) could not be decoded.`);
|
|
2277
|
+
return lines;
|
|
2278
|
+
}
|
|
2279
|
+
|
|
2280
|
+
// src/brand-command.ts
|
|
2281
|
+
var USAGE = "usage: odla-ai brand design unpack <bundle.html|-> [--out <dir>] [--json]";
|
|
2282
|
+
async function readBundle(source, deps) {
|
|
2283
|
+
if (source !== "-") return (0, import_promises2.readFile)((0, import_node_path7.resolve)(source), "utf8");
|
|
2284
|
+
const readStdin = deps.readStdin;
|
|
2285
|
+
if (!readStdin) throw new Error("reading a bundle from stdin is not supported here");
|
|
2286
|
+
return readStdin();
|
|
2287
|
+
}
|
|
2288
|
+
async function writeAll(result, outDir) {
|
|
2289
|
+
for (const file of result.files) {
|
|
2290
|
+
const target = (0, import_node_path7.resolve)(outDir, file.path);
|
|
2291
|
+
await (0, import_promises2.mkdir)((0, import_node_path7.dirname)(target), { recursive: true });
|
|
2292
|
+
await (0, import_promises2.writeFile)(target, file.bytes);
|
|
2293
|
+
}
|
|
2294
|
+
}
|
|
2295
|
+
async function designUnpack(parsed, deps) {
|
|
2296
|
+
assertArgs(parsed, ["out", "json"], 4);
|
|
2297
|
+
const source = parsed.positionals[3];
|
|
2298
|
+
if (!source) throw new Error(USAGE);
|
|
2299
|
+
const outDir = (0, import_node_path7.resolve)(stringOpt(parsed.options.out) ?? "design");
|
|
2300
|
+
const result = unpackDesign(await readBundle(source, deps));
|
|
2301
|
+
await writeAll(result, outDir);
|
|
2302
|
+
const out = deps.stdout ?? console;
|
|
2303
|
+
if (parsed.options.json === true) {
|
|
2304
|
+
out.log(
|
|
2305
|
+
JSON.stringify({
|
|
2306
|
+
outDir,
|
|
2307
|
+
files: result.files.map((f) => f.path),
|
|
2308
|
+
failed: result.failed,
|
|
2309
|
+
digest: result.digest
|
|
2310
|
+
})
|
|
2311
|
+
);
|
|
2312
|
+
return;
|
|
2313
|
+
}
|
|
2314
|
+
for (const line of describeUnpack(result, outDir)) out.log(line);
|
|
2315
|
+
}
|
|
2316
|
+
async function brandCommand(parsed, deps) {
|
|
2317
|
+
const subject = parsed.positionals[1];
|
|
2318
|
+
const action2 = parsed.positionals[2];
|
|
2319
|
+
if (subject === "design" && action2 === "unpack") {
|
|
2320
|
+
await designUnpack(parsed, deps);
|
|
2321
|
+
return;
|
|
2322
|
+
}
|
|
2323
|
+
throw new Error(USAGE);
|
|
2324
|
+
}
|
|
2325
|
+
|
|
2178
2326
|
// src/calendar-errors.ts
|
|
2179
2327
|
var PLATFORM_NOT_READY_CODES = /* @__PURE__ */ new Set([
|
|
2180
2328
|
"calendar_google_oauth_not_configured",
|
|
@@ -2448,8 +2596,8 @@ function credential(value2) {
|
|
|
2448
2596
|
// src/calendar-poll.ts
|
|
2449
2597
|
async function waitForCalendarPoll(milliseconds, signal) {
|
|
2450
2598
|
if (signal?.aborted) throw signal.reason ?? new Error("calendar connection aborted");
|
|
2451
|
-
await new Promise((
|
|
2452
|
-
const timer = setTimeout(
|
|
2599
|
+
await new Promise((resolve13, reject) => {
|
|
2600
|
+
const timer = setTimeout(resolve13, milliseconds);
|
|
2453
2601
|
signal?.addEventListener("abort", () => {
|
|
2454
2602
|
clearTimeout(timer);
|
|
2455
2603
|
reject(signal.reason ?? new Error("calendar connection aborted"));
|
|
@@ -2703,7 +2851,7 @@ function printGroup(out, heading, items) {
|
|
|
2703
2851
|
|
|
2704
2852
|
// src/config-operation-command.ts
|
|
2705
2853
|
var import_apps6 = require("@odla-ai/apps");
|
|
2706
|
-
var
|
|
2854
|
+
var import_node_path8 = require("path");
|
|
2707
2855
|
|
|
2708
2856
|
// src/version.ts
|
|
2709
2857
|
var import_node_fs9 = require("fs");
|
|
@@ -3082,7 +3230,7 @@ async function configOperationWait(options) {
|
|
|
3082
3230
|
assertOperationId(options.operationId);
|
|
3083
3231
|
const cfg = await loadProjectConfig(options.configPath);
|
|
3084
3232
|
const client = await operationClient(cfg, options, "wait");
|
|
3085
|
-
const wait2 = options.pollWait ?? ((ms) => new Promise((
|
|
3233
|
+
const wait2 = options.pollWait ?? ((ms) => new Promise((resolve13) => setTimeout(resolve13, ms)));
|
|
3086
3234
|
const now = () => (options.now?.() ?? /* @__PURE__ */ new Date()).getTime();
|
|
3087
3235
|
const deadline = now() + (options.timeoutSeconds ?? DEFAULT_WAIT_SECONDS) * 1e3;
|
|
3088
3236
|
const interval = (options.intervalSeconds ?? DEFAULT_INTERVAL_SECONDS) * 1e3;
|
|
@@ -3113,7 +3261,7 @@ async function operationClient(cfg, options, purpose) {
|
|
|
3113
3261
|
platform: cfg.platformUrl,
|
|
3114
3262
|
scope: "app:config:write",
|
|
3115
3263
|
token: options.token,
|
|
3116
|
-
tokenFile: (0,
|
|
3264
|
+
tokenFile: (0, import_node_path8.join)(cfg.rootDir, ".odla", "admin-token.local.json"),
|
|
3117
3265
|
rootDir: cfg.rootDir,
|
|
3118
3266
|
email: options.email,
|
|
3119
3267
|
open: options.open,
|
|
@@ -3168,7 +3316,7 @@ function record3(value2) {
|
|
|
3168
3316
|
|
|
3169
3317
|
// src/config-reconcile-command.ts
|
|
3170
3318
|
var import_apps8 = require("@odla-ai/apps");
|
|
3171
|
-
var
|
|
3319
|
+
var import_node_path9 = require("path");
|
|
3172
3320
|
|
|
3173
3321
|
// src/config-reconcile.ts
|
|
3174
3322
|
var import_apps7 = require("@odla-ai/apps");
|
|
@@ -3464,7 +3612,7 @@ async function inspectConfig(options) {
|
|
|
3464
3612
|
platform: cfg.platformUrl,
|
|
3465
3613
|
scope: "app:config:read",
|
|
3466
3614
|
token: options.token,
|
|
3467
|
-
tokenFile: (0,
|
|
3615
|
+
tokenFile: (0, import_node_path9.join)(cfg.rootDir, ".odla", "admin-token.local.json"),
|
|
3468
3616
|
rootDir: cfg.rootDir,
|
|
3469
3617
|
email: options.email,
|
|
3470
3618
|
open: options.open,
|
|
@@ -3597,12 +3745,12 @@ function quoteArg2(value2) {
|
|
|
3597
3745
|
// src/doctor-checks.ts
|
|
3598
3746
|
var import_node_child_process3 = require("child_process");
|
|
3599
3747
|
var import_node_fs12 = require("fs");
|
|
3600
|
-
var
|
|
3748
|
+
var import_node_path11 = require("path");
|
|
3601
3749
|
|
|
3602
3750
|
// src/wrangler.ts
|
|
3603
3751
|
var import_node_child_process2 = require("child_process");
|
|
3604
3752
|
var import_node_fs11 = require("fs");
|
|
3605
|
-
var
|
|
3753
|
+
var import_node_path10 = require("path");
|
|
3606
3754
|
var defaultRunner = (cmd, args, opts) => new Promise((resolvePromise, reject) => {
|
|
3607
3755
|
const child = (0, import_node_child_process2.spawn)(cmd, args, { cwd: opts?.cwd, stdio: ["pipe", "pipe", "pipe"] });
|
|
3608
3756
|
let stdout = "";
|
|
@@ -3616,7 +3764,7 @@ var defaultRunner = (cmd, args, opts) => new Promise((resolvePromise, reject) =>
|
|
|
3616
3764
|
var WRANGLER_CONFIG_FILES = ["wrangler.jsonc", "wrangler.json", "wrangler.toml"];
|
|
3617
3765
|
function findWranglerConfig(rootDir) {
|
|
3618
3766
|
for (const name of WRANGLER_CONFIG_FILES) {
|
|
3619
|
-
const path = (0,
|
|
3767
|
+
const path = (0, import_node_path10.join)(rootDir, name);
|
|
3620
3768
|
if ((0, import_node_fs11.existsSync)(path)) return path;
|
|
3621
3769
|
}
|
|
3622
3770
|
return null;
|
|
@@ -3729,10 +3877,10 @@ function wranglerWarnings(rootDir) {
|
|
|
3729
3877
|
for (const { label, block } of blocks) {
|
|
3730
3878
|
const assets = block.assets;
|
|
3731
3879
|
if (assets?.directory) {
|
|
3732
|
-
const dir = (0,
|
|
3733
|
-
if (dir === (0,
|
|
3880
|
+
const dir = (0, import_node_path11.resolve)(rootDir, assets.directory);
|
|
3881
|
+
if (dir === (0, import_node_path11.resolve)(rootDir)) {
|
|
3734
3882
|
warnings.push(`${label}assets.directory is the project root \u2014 point it at a dedicated build dir (wrangler dev fails with "spawn EBADF")`);
|
|
3735
|
-
} else if ((0, import_node_fs12.existsSync)((0,
|
|
3883
|
+
} else if ((0, import_node_fs12.existsSync)((0, import_node_path11.join)(dir, "node_modules"))) {
|
|
3736
3884
|
warnings.push(`${label}assets.directory contains node_modules \u2014 wrangler dev's watcher will exhaust file descriptors`);
|
|
3737
3885
|
}
|
|
3738
3886
|
}
|
|
@@ -3767,7 +3915,7 @@ function o11yProjectWarnings(rootDir) {
|
|
|
3767
3915
|
warnings.push("cannot verify o11y Worker instrumentation \u2014 add a parseable wrangler.jsonc/json config");
|
|
3768
3916
|
return warnings;
|
|
3769
3917
|
}
|
|
3770
|
-
const main = typeof config.main === "string" ? (0,
|
|
3918
|
+
const main = typeof config.main === "string" ? (0, import_node_path11.resolve)(rootDir, config.main) : null;
|
|
3771
3919
|
if (!main || !(0, import_node_fs12.existsSync)(main)) {
|
|
3772
3920
|
warnings.push("cannot verify o11y Worker instrumentation \u2014 wrangler main is missing or unreadable");
|
|
3773
3921
|
} else {
|
|
@@ -3797,7 +3945,7 @@ function calendarProjectWarnings(rootDir) {
|
|
|
3797
3945
|
}
|
|
3798
3946
|
function readPackageJson(rootDir) {
|
|
3799
3947
|
try {
|
|
3800
|
-
return JSON.parse((0, import_node_fs12.readFileSync)((0,
|
|
3948
|
+
return JSON.parse((0, import_node_fs12.readFileSync)((0, import_node_path11.join)(rootDir, "package.json"), "utf8"));
|
|
3801
3949
|
} catch {
|
|
3802
3950
|
return null;
|
|
3803
3951
|
}
|
|
@@ -4025,12 +4173,12 @@ function harnessOption(value2, flag) {
|
|
|
4025
4173
|
|
|
4026
4174
|
// src/init.ts
|
|
4027
4175
|
var import_node_fs13 = require("fs");
|
|
4028
|
-
var
|
|
4176
|
+
var import_node_path12 = require("path");
|
|
4029
4177
|
var import_apps9 = require("@odla-ai/apps");
|
|
4030
4178
|
function initProject(options) {
|
|
4031
4179
|
const out = options.stdout ?? console;
|
|
4032
|
-
const rootDir = (0,
|
|
4033
|
-
const configPath = (0,
|
|
4180
|
+
const rootDir = (0, import_node_path12.resolve)(options.rootDir ?? process.cwd());
|
|
4181
|
+
const configPath = (0, import_node_path12.resolve)(rootDir, options.configPath ?? "odla.config.mjs");
|
|
4034
4182
|
if ((0, import_node_fs13.existsSync)(configPath) && !options.force) {
|
|
4035
4183
|
throw new Error(`${configPath} already exists. Pass --force to overwrite.`);
|
|
4036
4184
|
}
|
|
@@ -4047,12 +4195,12 @@ function initProject(options) {
|
|
|
4047
4195
|
}
|
|
4048
4196
|
}
|
|
4049
4197
|
const aiProvider = options.aiProvider ?? "anthropic";
|
|
4050
|
-
(0, import_node_fs13.mkdirSync)((0,
|
|
4051
|
-
(0, import_node_fs13.mkdirSync)((0,
|
|
4052
|
-
(0, import_node_fs13.mkdirSync)((0,
|
|
4198
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path12.dirname)(configPath), { recursive: true });
|
|
4199
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path12.resolve)(rootDir, "src/odla"), { recursive: true });
|
|
4200
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path12.resolve)(rootDir, ".odla"), { recursive: true });
|
|
4053
4201
|
(0, import_node_fs13.writeFileSync)(configPath, configTemplate({ appId: options.appId, name: options.name, envs, services, aiProvider }));
|
|
4054
|
-
writeIfMissing((0,
|
|
4055
|
-
writeIfMissing((0,
|
|
4202
|
+
writeIfMissing((0, import_node_path12.resolve)(rootDir, "src/odla/schema.mjs"), schemaTemplate());
|
|
4203
|
+
writeIfMissing((0, import_node_path12.resolve)(rootDir, "src/odla/rules.mjs"), rulesTemplate());
|
|
4056
4204
|
ensureGitignore(rootDir);
|
|
4057
4205
|
out.log(`created ${relativeDisplay(configPath, rootDir)}`);
|
|
4058
4206
|
out.log("created src/odla/schema.mjs and src/odla/rules.mjs");
|
|
@@ -4293,7 +4441,7 @@ async function resolveVaultWrite(options) {
|
|
|
4293
4441
|
// src/skill.ts
|
|
4294
4442
|
var import_node_fs14 = require("fs");
|
|
4295
4443
|
var import_node_os2 = require("os");
|
|
4296
|
-
var
|
|
4444
|
+
var import_node_path13 = require("path");
|
|
4297
4445
|
var import_node_url2 = require("url");
|
|
4298
4446
|
|
|
4299
4447
|
// src/skill-adapters.ts
|
|
@@ -4372,8 +4520,8 @@ function installSkill(options = {}) {
|
|
|
4372
4520
|
const files = listFiles(sourceDir);
|
|
4373
4521
|
if (files.length === 0) throw new Error(`no bundled skills found at ${sourceDir}`);
|
|
4374
4522
|
const harnesses = normalizeHarnesses(options.harnesses, options.global === true);
|
|
4375
|
-
const root = (0,
|
|
4376
|
-
const home = (0,
|
|
4523
|
+
const root = (0, import_node_path13.resolve)(options.dir ?? process.cwd());
|
|
4524
|
+
const home = (0, import_node_path13.resolve)(options.homeDir ?? (0, import_node_os2.homedir)());
|
|
4377
4525
|
const plans = /* @__PURE__ */ new Map();
|
|
4378
4526
|
const targets = /* @__PURE__ */ new Map();
|
|
4379
4527
|
const rememberTarget = (harness, target) => {
|
|
@@ -4387,48 +4535,48 @@ function installSkill(options = {}) {
|
|
|
4387
4535
|
plans.set(target, { target, content: content2, boundary, managedMerge });
|
|
4388
4536
|
};
|
|
4389
4537
|
const planSkillTree = (targetDir2, boundary = root) => {
|
|
4390
|
-
for (const rel of files) plan((0,
|
|
4538
|
+
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);
|
|
4391
4539
|
};
|
|
4392
4540
|
let targetDir;
|
|
4393
4541
|
if (options.global) {
|
|
4394
|
-
const claudeRoot = (0,
|
|
4395
|
-
const codexRoot = (0,
|
|
4542
|
+
const claudeRoot = (0, import_node_path13.join)(home, ".claude", "skills");
|
|
4543
|
+
const codexRoot = (0, import_node_path13.resolve)(options.codexHomeDir ?? process.env.CODEX_HOME ?? (0, import_node_path13.join)(home, ".codex"), "skills");
|
|
4396
4544
|
targetDir = harnesses[0] === "codex" ? codexRoot : claudeRoot;
|
|
4397
4545
|
for (const harness of harnesses) {
|
|
4398
4546
|
const skillRoot = harness === "claude" ? claudeRoot : codexRoot;
|
|
4399
|
-
planSkillTree(skillRoot, harness === "claude" ? home : (0,
|
|
4547
|
+
planSkillTree(skillRoot, harness === "claude" ? home : (0, import_node_path13.dirname)((0, import_node_path13.dirname)(codexRoot)));
|
|
4400
4548
|
rememberTarget(harness, skillRoot);
|
|
4401
4549
|
}
|
|
4402
4550
|
} else {
|
|
4403
|
-
const sharedRoot = (0,
|
|
4551
|
+
const sharedRoot = (0, import_node_path13.join)(root, ".agents", "skills");
|
|
4404
4552
|
planSkillTree(sharedRoot);
|
|
4405
|
-
const claudeRoot = (0,
|
|
4553
|
+
const claudeRoot = (0, import_node_path13.join)(root, ".claude", "skills");
|
|
4406
4554
|
targetDir = harnesses.includes("claude") ? claudeRoot : sharedRoot;
|
|
4407
4555
|
for (const harness of harnesses) rememberTarget(harness, sharedRoot);
|
|
4408
4556
|
if (harnesses.includes("claude")) {
|
|
4409
4557
|
for (const skill of skillNames(files)) {
|
|
4410
|
-
const canonical = (0, import_node_fs14.readFileSync)((0,
|
|
4411
|
-
plan((0,
|
|
4558
|
+
const canonical = (0, import_node_fs14.readFileSync)((0, import_node_path13.join)(sourceDir, skill, "SKILL.md"), "utf8");
|
|
4559
|
+
plan((0, import_node_path13.join)(claudeRoot, skill, "SKILL.md"), claudeAdapter(skill, canonical));
|
|
4412
4560
|
}
|
|
4413
4561
|
rememberTarget("claude", claudeRoot);
|
|
4414
4562
|
}
|
|
4415
4563
|
if (harnesses.includes("cursor")) {
|
|
4416
|
-
const cursorRule = (0,
|
|
4564
|
+
const cursorRule = (0, import_node_path13.join)(root, ".cursor", "rules", "odla.mdc");
|
|
4417
4565
|
plan(cursorRule, CURSOR_RULE);
|
|
4418
4566
|
rememberTarget("cursor", cursorRule);
|
|
4419
4567
|
}
|
|
4420
4568
|
if (harnesses.includes("agents")) {
|
|
4421
|
-
const agentsFile = (0,
|
|
4569
|
+
const agentsFile = (0, import_node_path13.join)(root, "AGENTS.md");
|
|
4422
4570
|
plan(agentsFile, managedFileContent(agentsFile, PROJECT_INSTRUCTIONS, options.force === true, root), true);
|
|
4423
4571
|
rememberTarget("agents", agentsFile);
|
|
4424
4572
|
}
|
|
4425
4573
|
if (harnesses.includes("copilot")) {
|
|
4426
|
-
const copilotFile = (0,
|
|
4574
|
+
const copilotFile = (0, import_node_path13.join)(root, ".github", "copilot-instructions.md");
|
|
4427
4575
|
plan(copilotFile, managedFileContent(copilotFile, PROJECT_INSTRUCTIONS, options.force === true, root), true);
|
|
4428
4576
|
rememberTarget("copilot", copilotFile);
|
|
4429
4577
|
}
|
|
4430
4578
|
if (harnesses.includes("gemini")) {
|
|
4431
|
-
const geminiFile = (0,
|
|
4579
|
+
const geminiFile = (0, import_node_path13.join)(root, "GEMINI.md");
|
|
4432
4580
|
plan(geminiFile, managedFileContent(geminiFile, PROJECT_INSTRUCTIONS, options.force === true, root), true);
|
|
4433
4581
|
rememberTarget("gemini", geminiFile);
|
|
4434
4582
|
}
|
|
@@ -4464,7 +4612,7 @@ ${conflicts.map((f) => ` - ${f}`).join("\n")}`
|
|
|
4464
4612
|
}
|
|
4465
4613
|
for (const file of plans.values()) {
|
|
4466
4614
|
if (!(0, import_node_fs14.existsSync)(file.target) || (0, import_node_fs14.readFileSync)(file.target, "utf8") !== file.content) {
|
|
4467
|
-
(0, import_node_fs14.mkdirSync)((0,
|
|
4615
|
+
(0, import_node_fs14.mkdirSync)((0, import_node_path13.dirname)(file.target), { recursive: true });
|
|
4468
4616
|
(0, import_node_fs14.writeFileSync)(file.target, file.content);
|
|
4469
4617
|
}
|
|
4470
4618
|
}
|
|
@@ -4484,7 +4632,7 @@ ${conflicts.map((f) => ` - ${f}`).join("\n")}`
|
|
|
4484
4632
|
};
|
|
4485
4633
|
}
|
|
4486
4634
|
function pathsUnder(root, paths) {
|
|
4487
|
-
return [...paths].map((path) => (0,
|
|
4635
|
+
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();
|
|
4488
4636
|
}
|
|
4489
4637
|
function normalizeHarnesses(values, global) {
|
|
4490
4638
|
const requested = values?.length ? values : ["claude"];
|
|
@@ -4529,13 +4677,13 @@ function managedFileContent(path, block, force, boundary) {
|
|
|
4529
4677
|
return `${current.slice(0, startAt)}${block}${current.slice(afterEnd)}`;
|
|
4530
4678
|
}
|
|
4531
4679
|
function symlinkedComponent(boundary, target) {
|
|
4532
|
-
const rel = (0,
|
|
4533
|
-
if (rel === ".." || rel.startsWith(`..${
|
|
4680
|
+
const rel = (0, import_node_path13.relative)(boundary, target);
|
|
4681
|
+
if (rel === ".." || rel.startsWith(`..${import_node_path13.sep}`) || (0, import_node_path13.isAbsolute)(rel)) {
|
|
4534
4682
|
throw new Error(`agent setup target escapes its install root: ${target}`);
|
|
4535
4683
|
}
|
|
4536
4684
|
let current = boundary;
|
|
4537
|
-
for (const part of rel.split(
|
|
4538
|
-
current = (0,
|
|
4685
|
+
for (const part of rel.split(import_node_path13.sep).filter(Boolean)) {
|
|
4686
|
+
current = (0, import_node_path13.join)(current, part);
|
|
4539
4687
|
try {
|
|
4540
4688
|
if ((0, import_node_fs14.lstatSync)(current).isSymbolicLink()) return current;
|
|
4541
4689
|
} catch (error) {
|
|
@@ -4552,9 +4700,9 @@ function listFiles(dir) {
|
|
|
4552
4700
|
const results = [];
|
|
4553
4701
|
const walk = (current) => {
|
|
4554
4702
|
for (const entry of (0, import_node_fs14.readdirSync)(current, { withFileTypes: true })) {
|
|
4555
|
-
const path = (0,
|
|
4703
|
+
const path = (0, import_node_path13.join)(current, entry.name);
|
|
4556
4704
|
if (entry.isDirectory()) walk(path);
|
|
4557
|
-
else results.push((0,
|
|
4705
|
+
else results.push((0, import_node_path13.relative)(dir, path));
|
|
4558
4706
|
}
|
|
4559
4707
|
};
|
|
4560
4708
|
walk(dir);
|
|
@@ -4866,7 +5014,7 @@ async function projectCommand(command, parsed, deps) {
|
|
|
4866
5014
|
// src/code-connect.ts
|
|
4867
5015
|
var import_node_fs15 = require("fs");
|
|
4868
5016
|
var import_node_os4 = require("os");
|
|
4869
|
-
var
|
|
5017
|
+
var import_node_path15 = require("path");
|
|
4870
5018
|
|
|
4871
5019
|
// ../harness/dist/chunk-QTUEF2HZ.js
|
|
4872
5020
|
var HARNESS_PROTOCOL_VERSION = 1;
|
|
@@ -4952,15 +5100,15 @@ function encodeAgentInput(message2) {
|
|
|
4952
5100
|
// ../harness/dist/chunk-PHXQH4YM.js
|
|
4953
5101
|
var import_child_process = require("child_process");
|
|
4954
5102
|
var import_fs = require("fs");
|
|
4955
|
-
var
|
|
5103
|
+
var import_promises3 = require("fs/promises");
|
|
4956
5104
|
var import_path = require("path");
|
|
4957
5105
|
var import_process = require("process");
|
|
4958
|
-
var
|
|
5106
|
+
var import_promises4 = require("fs/promises");
|
|
4959
5107
|
var import_os = require("os");
|
|
4960
5108
|
var import_path2 = require("path");
|
|
4961
5109
|
var import_child_process2 = require("child_process");
|
|
4962
5110
|
var import_path3 = require("path");
|
|
4963
|
-
var
|
|
5111
|
+
var import_promises5 = require("fs/promises");
|
|
4964
5112
|
var import_os2 = require("os");
|
|
4965
5113
|
var import_path4 = require("path");
|
|
4966
5114
|
var import_child_process3 = require("child_process");
|
|
@@ -4971,7 +5119,7 @@ function assertPinnedImage(image) {
|
|
|
4971
5119
|
async function commandAvailable(engine) {
|
|
4972
5120
|
for (const directory of (process.env.PATH ?? "").split(import_path.delimiter).filter(Boolean)) {
|
|
4973
5121
|
try {
|
|
4974
|
-
await (0,
|
|
5122
|
+
await (0, import_promises3.access)((0, import_path.join)(directory, engine), import_fs.constants.X_OK);
|
|
4975
5123
|
return true;
|
|
4976
5124
|
} catch {
|
|
4977
5125
|
}
|
|
@@ -5257,7 +5405,7 @@ async function gitBlobs(cwd, entries, maxBytes) {
|
|
|
5257
5405
|
}
|
|
5258
5406
|
async function materializeGitTree(source, commitSha, options = {}) {
|
|
5259
5407
|
if (!/^[0-9a-f]{40}$/.test(commitSha)) throw new TypeError("Git tree requires an exact commit SHA");
|
|
5260
|
-
const sourceDir = await (0,
|
|
5408
|
+
const sourceDir = await (0, import_promises4.realpath)((0, import_path2.resolve)(source));
|
|
5261
5409
|
const maxFiles = options.maxFiles ?? 2e4;
|
|
5262
5410
|
const maxBytes = options.maxBytes ?? 512 * 1024 * 1024;
|
|
5263
5411
|
const inventory = (await gitOutput(sourceDir, ["ls-tree", "-rz", commitSha], 16 * 1024 * 1024)).toString("utf8").split("\0").filter(Boolean);
|
|
@@ -5266,9 +5414,9 @@ async function materializeGitTree(source, commitSha, options = {}) {
|
|
|
5266
5414
|
return match && allowedWorkspacePath(match[3]) ? [{ mode: match[1], hash: match[2], path: match[3] }] : [];
|
|
5267
5415
|
});
|
|
5268
5416
|
if (entries.length > maxFiles) throw new Error(`workspace exceeds ${maxFiles} files`);
|
|
5269
|
-
const root = await (0,
|
|
5417
|
+
const root = await (0, import_promises4.mkdtemp)((0, import_path2.join)(options.tempRoot ?? (0, import_os.tmpdir)(), "odla-git-tree-"));
|
|
5270
5418
|
const targetRoot = (0, import_path2.join)(root, "source");
|
|
5271
|
-
await (0,
|
|
5419
|
+
await (0, import_promises4.mkdir)(targetRoot);
|
|
5272
5420
|
let byteCount = 0;
|
|
5273
5421
|
try {
|
|
5274
5422
|
const blobs = await gitBlobs(sourceDir, entries, maxBytes);
|
|
@@ -5278,18 +5426,18 @@ async function materializeGitTree(source, commitSha, options = {}) {
|
|
|
5278
5426
|
if (byteCount > maxBytes) throw new Error(`workspace exceeds ${maxBytes} bytes`);
|
|
5279
5427
|
const target = (0, import_path2.resolve)(targetRoot, entry.path);
|
|
5280
5428
|
if (!target.startsWith(`${(0, import_path2.resolve)(targetRoot)}${import_path2.sep}`)) throw new TypeError("Git tree path escapes workspace");
|
|
5281
|
-
await (0,
|
|
5282
|
-
await (0,
|
|
5429
|
+
await (0, import_promises4.mkdir)((0, import_path2.resolve)(target, ".."), { recursive: true });
|
|
5430
|
+
await (0, import_promises4.writeFile)(target, content2, { flag: "wx", mode: entry.mode === "100755" ? 493 : 420 });
|
|
5283
5431
|
}
|
|
5284
5432
|
return {
|
|
5285
5433
|
root,
|
|
5286
5434
|
sourceDir: targetRoot,
|
|
5287
5435
|
fileCount: entries.length,
|
|
5288
5436
|
byteCount,
|
|
5289
|
-
cleanup: () => (0,
|
|
5437
|
+
cleanup: () => (0, import_promises4.rm)(root, { recursive: true, force: true })
|
|
5290
5438
|
};
|
|
5291
5439
|
} catch (error) {
|
|
5292
|
-
await (0,
|
|
5440
|
+
await (0, import_promises4.rm)(root, { recursive: true, force: true });
|
|
5293
5441
|
throw error;
|
|
5294
5442
|
}
|
|
5295
5443
|
}
|
|
@@ -5297,7 +5445,7 @@ async function sourceFiles(sourceDir, maxFiles, maxBytes) {
|
|
|
5297
5445
|
const files = [];
|
|
5298
5446
|
let bytes = 0;
|
|
5299
5447
|
const walk = async (dir) => {
|
|
5300
|
-
for (const entry of await (0,
|
|
5448
|
+
for (const entry of await (0, import_promises5.readdir)(dir, { withFileTypes: true })) {
|
|
5301
5449
|
if (entry.isDirectory() && SKIP_WORKSPACE_DIRS.has(entry.name)) continue;
|
|
5302
5450
|
if (!entry.isDirectory() && SECRET_WORKSPACE_FILE.test(entry.name)) continue;
|
|
5303
5451
|
const path = (0, import_path4.join)(dir, entry.name);
|
|
@@ -5307,7 +5455,7 @@ async function sourceFiles(sourceDir, maxFiles, maxBytes) {
|
|
|
5307
5455
|
continue;
|
|
5308
5456
|
}
|
|
5309
5457
|
if (!entry.isFile()) continue;
|
|
5310
|
-
const metadata2 = await (0,
|
|
5458
|
+
const metadata2 = await (0, import_promises5.stat)(path);
|
|
5311
5459
|
bytes += metadata2.size;
|
|
5312
5460
|
if (files.length + 1 > maxFiles) throw new Error(`workspace exceeds ${maxFiles} files`);
|
|
5313
5461
|
if (bytes > maxBytes) throw new Error(`workspace exceeds ${maxBytes} bytes`);
|
|
@@ -5356,7 +5504,7 @@ async function gitSourceFiles(sourceDir, maxFiles, maxBytes) {
|
|
|
5356
5504
|
if (!source.startsWith(`${root}${import_path4.sep}`)) throw new TypeError("git file path escapes workspace");
|
|
5357
5505
|
let metadata2;
|
|
5358
5506
|
try {
|
|
5359
|
-
metadata2 = await (0,
|
|
5507
|
+
metadata2 = await (0, import_promises5.lstat)(source);
|
|
5360
5508
|
} catch (error) {
|
|
5361
5509
|
if (error.code === "ENOENT") continue;
|
|
5362
5510
|
throw error;
|
|
@@ -5371,9 +5519,9 @@ async function gitSourceFiles(sourceDir, maxFiles, maxBytes) {
|
|
|
5371
5519
|
async function copyTree(files, destination) {
|
|
5372
5520
|
for (const file of files) {
|
|
5373
5521
|
const target = (0, import_path4.join)(destination, file.relativePath);
|
|
5374
|
-
await (0,
|
|
5375
|
-
await (0,
|
|
5376
|
-
await (0,
|
|
5522
|
+
await (0, import_promises5.mkdir)((0, import_path4.resolve)(target, ".."), { recursive: true });
|
|
5523
|
+
await (0, import_promises5.copyFile)(file.source, target);
|
|
5524
|
+
await (0, import_promises5.chmod)(target, file.mode);
|
|
5377
5525
|
}
|
|
5378
5526
|
}
|
|
5379
5527
|
async function captureGitDiff(root, maxBytes) {
|
|
@@ -5410,13 +5558,13 @@ async function captureGitDiff(root, maxBytes) {
|
|
|
5410
5558
|
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");
|
|
5411
5559
|
}
|
|
5412
5560
|
async function stageWorkspace(source, options = {}) {
|
|
5413
|
-
const sourceDir = await (0,
|
|
5414
|
-
const sourceStat = await (0,
|
|
5561
|
+
const sourceDir = await (0, import_promises5.realpath)((0, import_path4.resolve)(source));
|
|
5562
|
+
const sourceStat = await (0, import_promises5.stat)(sourceDir);
|
|
5415
5563
|
if (!sourceStat.isDirectory()) throw new TypeError("workspace source must be a directory");
|
|
5416
|
-
const root = await (0,
|
|
5564
|
+
const root = await (0, import_promises5.mkdtemp)((0, import_path4.join)(options.tempRoot ?? (0, import_os2.tmpdir)(), "odla-harness-"));
|
|
5417
5565
|
const baselineDir = (0, import_path4.join)(root, "baseline");
|
|
5418
5566
|
const workspaceDir = (0, import_path4.join)(root, "workspace");
|
|
5419
|
-
await Promise.all([(0,
|
|
5567
|
+
await Promise.all([(0, import_promises5.mkdir)(baselineDir), (0, import_promises5.mkdir)(workspaceDir)]);
|
|
5420
5568
|
try {
|
|
5421
5569
|
const maxFiles = options.maxFiles ?? 2e4;
|
|
5422
5570
|
const maxBytes = options.maxBytes ?? 512 * 1024 * 1024;
|
|
@@ -5429,26 +5577,26 @@ async function stageWorkspace(source, options = {}) {
|
|
|
5429
5577
|
fileCount: files.length,
|
|
5430
5578
|
byteCount: files.reduce((sum, file) => sum + file.bytes, 0),
|
|
5431
5579
|
patch: (maxBytes2) => captureGitDiff(root, maxBytes2),
|
|
5432
|
-
cleanup: () => (0,
|
|
5580
|
+
cleanup: () => (0, import_promises5.rm)(root, { recursive: true, force: true })
|
|
5433
5581
|
};
|
|
5434
5582
|
} catch (error) {
|
|
5435
|
-
await (0,
|
|
5583
|
+
await (0, import_promises5.rm)(root, { recursive: true, force: true });
|
|
5436
5584
|
throw error;
|
|
5437
5585
|
}
|
|
5438
5586
|
}
|
|
5439
5587
|
async function stageWorkspacePair(baselineSource, workspaceSource, options = {}) {
|
|
5440
|
-
const baselineDirSource = await (0,
|
|
5441
|
-
const workspaceDirSource = await (0,
|
|
5588
|
+
const baselineDirSource = await (0, import_promises5.realpath)((0, import_path4.resolve)(baselineSource));
|
|
5589
|
+
const workspaceDirSource = await (0, import_promises5.realpath)((0, import_path4.resolve)(workspaceSource));
|
|
5442
5590
|
const maxFiles = options.maxFiles ?? 2e4;
|
|
5443
5591
|
const maxBytes = options.maxBytes ?? 512 * 1024 * 1024;
|
|
5444
5592
|
const [baselineFiles, workspaceFiles] = await Promise.all([
|
|
5445
5593
|
sourceFiles(baselineDirSource, maxFiles, maxBytes),
|
|
5446
5594
|
sourceFiles(workspaceDirSource, maxFiles, maxBytes)
|
|
5447
5595
|
]);
|
|
5448
|
-
const root = await (0,
|
|
5596
|
+
const root = await (0, import_promises5.mkdtemp)((0, import_path4.join)(options.tempRoot ?? (0, import_os2.tmpdir)(), "odla-harness-"));
|
|
5449
5597
|
const baselineDir = (0, import_path4.join)(root, "baseline");
|
|
5450
5598
|
const workspaceDir = (0, import_path4.join)(root, "workspace");
|
|
5451
|
-
await Promise.all([(0,
|
|
5599
|
+
await Promise.all([(0, import_promises5.mkdir)(baselineDir), (0, import_promises5.mkdir)(workspaceDir)]);
|
|
5452
5600
|
try {
|
|
5453
5601
|
await Promise.all([copyTree(baselineFiles, baselineDir), copyTree(workspaceFiles, workspaceDir)]);
|
|
5454
5602
|
return {
|
|
@@ -5458,17 +5606,17 @@ async function stageWorkspacePair(baselineSource, workspaceSource, options = {})
|
|
|
5458
5606
|
fileCount: workspaceFiles.length,
|
|
5459
5607
|
byteCount: workspaceFiles.reduce((sum, file) => sum + file.bytes, 0),
|
|
5460
5608
|
patch: (maxPatchBytes) => captureGitDiff(root, maxPatchBytes),
|
|
5461
|
-
cleanup: () => (0,
|
|
5609
|
+
cleanup: () => (0, import_promises5.rm)(root, { recursive: true, force: true })
|
|
5462
5610
|
};
|
|
5463
5611
|
} catch (error) {
|
|
5464
|
-
await (0,
|
|
5612
|
+
await (0, import_promises5.rm)(root, { recursive: true, force: true });
|
|
5465
5613
|
throw error;
|
|
5466
5614
|
}
|
|
5467
5615
|
}
|
|
5468
5616
|
|
|
5469
5617
|
// ../harness/dist/chunk-GMVZ4LZH.js
|
|
5470
5618
|
var import_crypto = require("crypto");
|
|
5471
|
-
var
|
|
5619
|
+
var import_promises6 = require("fs/promises");
|
|
5472
5620
|
var import_path5 = require("path");
|
|
5473
5621
|
|
|
5474
5622
|
// ../camel/dist/chunk-7FHPOQVP.js
|
|
@@ -5805,19 +5953,19 @@ function validateSnapshot(snapshot, limits) {
|
|
|
5805
5953
|
|
|
5806
5954
|
// ../harness/dist/chunk-GMVZ4LZH.js
|
|
5807
5955
|
var import_child_process4 = require("child_process");
|
|
5808
|
-
var
|
|
5956
|
+
var import_promises7 = require("fs/promises");
|
|
5809
5957
|
var import_path6 = require("path");
|
|
5810
5958
|
var import_child_process5 = require("child_process");
|
|
5811
5959
|
var import_process2 = require("process");
|
|
5812
5960
|
var import_crypto2 = require("crypto");
|
|
5813
5961
|
var import_crypto3 = require("crypto");
|
|
5814
5962
|
var import_fs2 = require("fs");
|
|
5815
|
-
var import_promises7 = require("fs/promises");
|
|
5816
|
-
var import_path7 = require("path");
|
|
5817
5963
|
var import_promises8 = require("fs/promises");
|
|
5964
|
+
var import_path7 = require("path");
|
|
5965
|
+
var import_promises9 = require("fs/promises");
|
|
5818
5966
|
var import_os3 = require("os");
|
|
5819
5967
|
var import_path8 = require("path");
|
|
5820
|
-
var
|
|
5968
|
+
var import_promises10 = require("fs/promises");
|
|
5821
5969
|
var import_path9 = require("path");
|
|
5822
5970
|
|
|
5823
5971
|
// ../camel/dist/chunk-LAXU2AVK.js
|
|
@@ -6101,7 +6249,7 @@ var import_crypto4 = require("crypto");
|
|
|
6101
6249
|
async function digestStagedWorkspace(root, limits) {
|
|
6102
6250
|
const files = [];
|
|
6103
6251
|
const walk = async (directory) => {
|
|
6104
|
-
const entries = await (0,
|
|
6252
|
+
const entries = await (0, import_promises6.readdir)(directory, { withFileTypes: true });
|
|
6105
6253
|
for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
|
|
6106
6254
|
if (entry.isSymbolicLink()) throw new TypeError("workspace digest refuses symbolic links");
|
|
6107
6255
|
const target = (0, import_path5.resolve)(directory, entry.name);
|
|
@@ -6116,7 +6264,7 @@ async function digestStagedWorkspace(root, limits) {
|
|
|
6116
6264
|
const hash = (0, import_crypto.createHash)("sha256");
|
|
6117
6265
|
let bytes = 0;
|
|
6118
6266
|
for (const file of files.sort((left, right) => left.path.localeCompare(right.path))) {
|
|
6119
|
-
const content2 = await (0,
|
|
6267
|
+
const content2 = await (0, import_promises6.readFile)(file.target);
|
|
6120
6268
|
bytes += Buffer.byteLength(file.path) + content2.byteLength;
|
|
6121
6269
|
if (bytes > limits.maxBytes) throw new TypeError("workspace digest exceeds its byte bound");
|
|
6122
6270
|
hash.update(`${Buffer.byteLength(file.path)}:${file.path}:${content2.byteLength}:`);
|
|
@@ -6442,7 +6590,7 @@ async function applyCodePatch(workspaceDir, patch2, paths) {
|
|
|
6442
6590
|
await gitApply(workspaceDir, patch2, false);
|
|
6443
6591
|
for (const path of paths) {
|
|
6444
6592
|
try {
|
|
6445
|
-
const info = await (0,
|
|
6593
|
+
const info = await (0, import_promises7.lstat)(resolveCodePath(workspaceDir, path));
|
|
6446
6594
|
if (info.isSymbolicLink() || !info.isFile() && !info.isDirectory()) {
|
|
6447
6595
|
throw new TypeError("patch created a non-regular workspace entry");
|
|
6448
6596
|
}
|
|
@@ -6733,7 +6881,7 @@ async function inspectArtifacts(workspaceDir, recipe2) {
|
|
|
6733
6881
|
for (const artifact of recipe2.expectedArtifacts ?? []) {
|
|
6734
6882
|
try {
|
|
6735
6883
|
const path = (0, import_path7.join)(workspaceDir, artifact.path);
|
|
6736
|
-
const info = await (0,
|
|
6884
|
+
const info = await (0, import_promises8.lstat)(path);
|
|
6737
6885
|
if (!info.isFile() || info.isSymbolicLink()) {
|
|
6738
6886
|
receipts.push({ artifactId: artifact.id, status: "invalid", bytes: null, digest: null });
|
|
6739
6887
|
} else if (info.size > artifact.maximumBytes) {
|
|
@@ -6914,9 +7062,9 @@ var RESERVED2 = /* @__PURE__ */ new Set([".git", ".odla", ".wrangler", "node_mod
|
|
|
6914
7062
|
var SECRET2 = /^(?:\.env(?:\..+)?|\.dev\.vars|credentials(?:\..+)?\.json|dev-token(?:\..+)?\.json)$/i;
|
|
6915
7063
|
async function materializeCodeRuntimeSource(snapshot, tempRoot = (0, import_os3.tmpdir)()) {
|
|
6916
7064
|
if (!snapshot.files.length || snapshot.files.length > 1e4) throw new TypeError("Code source file count is invalid");
|
|
6917
|
-
const root = await (0,
|
|
7065
|
+
const root = await (0, import_promises9.mkdtemp)((0, import_path8.join)(tempRoot, "odla-code-source-"));
|
|
6918
7066
|
const sourceDir = (0, import_path8.join)(root, "source");
|
|
6919
|
-
await (0,
|
|
7067
|
+
await (0, import_promises9.mkdir)(sourceDir);
|
|
6920
7068
|
const seen = /* @__PURE__ */ new Set();
|
|
6921
7069
|
let bytes = 0;
|
|
6922
7070
|
try {
|
|
@@ -6928,8 +7076,8 @@ async function materializeCodeRuntimeSource(snapshot, tempRoot = (0, import_os3.
|
|
|
6928
7076
|
if (bytes > 16 * 1024 * 1024) throw new TypeError("Code source exceeds its byte bound");
|
|
6929
7077
|
const target = (0, import_path8.resolve)(sourceDir, file.path);
|
|
6930
7078
|
if (!target.startsWith(`${(0, import_path8.resolve)(sourceDir)}${import_path8.sep}`)) throw new TypeError("Code source path escapes its root");
|
|
6931
|
-
await (0,
|
|
6932
|
-
await (0,
|
|
7079
|
+
await (0, import_promises9.mkdir)((0, import_path8.dirname)(target), { recursive: true });
|
|
7080
|
+
await (0, import_promises9.writeFile)(target, file.content, { flag: "wx", mode: 420 });
|
|
6933
7081
|
}
|
|
6934
7082
|
for (const reference of snapshot.references ?? []) {
|
|
6935
7083
|
validateAlias(reference.alias);
|
|
@@ -6943,13 +7091,13 @@ async function materializeCodeRuntimeSource(snapshot, tempRoot = (0, import_os3.
|
|
|
6943
7091
|
if (bytes > 80 * 1024 * 1024) throw new TypeError("Code source set exceeds its byte bound");
|
|
6944
7092
|
const target = (0, import_path8.resolve)(sourceDir, path);
|
|
6945
7093
|
if (!target.startsWith(`${(0, import_path8.resolve)(sourceDir)}${import_path8.sep}`)) throw new TypeError("Code reference path escapes its root");
|
|
6946
|
-
await (0,
|
|
6947
|
-
await (0,
|
|
7094
|
+
await (0, import_promises9.mkdir)((0, import_path8.dirname)(target), { recursive: true });
|
|
7095
|
+
await (0, import_promises9.writeFile)(target, file.content, { flag: "wx", mode: 292 });
|
|
6948
7096
|
}
|
|
6949
7097
|
}
|
|
6950
|
-
return { sourceDir, cleanup: () => (0,
|
|
7098
|
+
return { sourceDir, cleanup: () => (0, import_promises9.rm)(root, { recursive: true, force: true }) };
|
|
6951
7099
|
} catch (cause) {
|
|
6952
|
-
await (0,
|
|
7100
|
+
await (0, import_promises9.rm)(root, { recursive: true, force: true });
|
|
6953
7101
|
throw cause;
|
|
6954
7102
|
}
|
|
6955
7103
|
}
|
|
@@ -6970,8 +7118,8 @@ async function attachCodeRuntimeReferences(workspace, references) {
|
|
|
6970
7118
|
for (const root of [workspace.baselineDir, workspace.workspaceDir]) {
|
|
6971
7119
|
const target = (0, import_path8.resolve)(root, path);
|
|
6972
7120
|
if (!target.startsWith(`${(0, import_path8.resolve)(root)}${import_path8.sep}`)) throw new TypeError("Code reference path escapes its root");
|
|
6973
|
-
await (0,
|
|
6974
|
-
await (0,
|
|
7121
|
+
await (0, import_promises9.mkdir)((0, import_path8.dirname)(target), { recursive: true });
|
|
7122
|
+
await (0, import_promises9.writeFile)(target, file.content, { flag: "wx", mode: 292 });
|
|
6975
7123
|
}
|
|
6976
7124
|
}
|
|
6977
7125
|
}
|
|
@@ -7157,11 +7305,11 @@ async function read(context, request2, options, policy) {
|
|
|
7157
7305
|
const allowed = await policy.read(policyContext(context, request2, options, { paths, path, startLine, endLine }));
|
|
7158
7306
|
if (!allowed) return response(request2, false, "tool denied by CaMeL policy");
|
|
7159
7307
|
const target = resolveCodePath(context.workspaceDir, path);
|
|
7160
|
-
const info = await (0,
|
|
7308
|
+
const info = await (0, import_promises10.stat)(target);
|
|
7161
7309
|
if (!info.isFile() || info.size > Math.max(options.maxReadBytes ?? 128 * 1024, 2 * 1024 * 1024)) {
|
|
7162
7310
|
throw new TypeError("file is not a bounded regular source file");
|
|
7163
7311
|
}
|
|
7164
|
-
const source = await (0,
|
|
7312
|
+
const source = await (0, import_promises10.readFile)(target);
|
|
7165
7313
|
if (source.includes(0)) throw new TypeError("binary files are not readable through this tool");
|
|
7166
7314
|
const lines = source.toString("utf8").split("\n");
|
|
7167
7315
|
const content2 = lines.slice(startLine - 1, endLine).join("\n");
|
|
@@ -7238,7 +7386,7 @@ function policyContext(context, request2, options, extra) {
|
|
|
7238
7386
|
async function registeredFiles(root, limit) {
|
|
7239
7387
|
const paths = [];
|
|
7240
7388
|
const walk = async (directory) => {
|
|
7241
|
-
for (const entry of await (0,
|
|
7389
|
+
for (const entry of await (0, import_promises10.readdir)(directory, { withFileTypes: true })) {
|
|
7242
7390
|
if (entry.isSymbolicLink()) throw new TypeError("workspace contains a symbolic link");
|
|
7243
7391
|
const target = (0, import_path9.resolve)(directory, entry.name);
|
|
7244
7392
|
if (entry.isDirectory()) await walk(target);
|
|
@@ -7837,8 +7985,8 @@ function hostedPollTimeout(value2 = 10 * 6e4) {
|
|
|
7837
7985
|
}
|
|
7838
7986
|
async function waitForHostedPoll(milliseconds, signal) {
|
|
7839
7987
|
if (signal?.aborted) throw signal.reason ?? new DOMException("aborted", "AbortError");
|
|
7840
|
-
await new Promise((
|
|
7841
|
-
const timer = setTimeout(
|
|
7988
|
+
await new Promise((resolve13, reject) => {
|
|
7989
|
+
const timer = setTimeout(resolve13, milliseconds);
|
|
7842
7990
|
signal?.addEventListener("abort", () => {
|
|
7843
7991
|
clearTimeout(timer);
|
|
7844
7992
|
reject(signal.reason ?? new DOMException("aborted", "AbortError"));
|
|
@@ -8023,9 +8171,9 @@ function digestText(value2) {
|
|
|
8023
8171
|
// src/code-images.ts
|
|
8024
8172
|
var import_node_child_process6 = require("child_process");
|
|
8025
8173
|
var import_node_crypto3 = require("crypto");
|
|
8026
|
-
var
|
|
8174
|
+
var import_promises11 = require("fs/promises");
|
|
8027
8175
|
var import_node_os3 = require("os");
|
|
8028
|
-
var
|
|
8176
|
+
var import_node_path14 = require("path");
|
|
8029
8177
|
var import_node_url3 = require("url");
|
|
8030
8178
|
|
|
8031
8179
|
// src/code-runtime-config.ts
|
|
@@ -8105,16 +8253,16 @@ function embeddedPiAssetPath() {
|
|
|
8105
8253
|
return (0, import_node_url3.fileURLToPath)(new URL("./runtime/pi-agent.js", importMetaUrl));
|
|
8106
8254
|
}
|
|
8107
8255
|
async function embeddedPiImageName() {
|
|
8108
|
-
const bundle = await (0,
|
|
8256
|
+
const bundle = await (0, import_promises11.readFile)(embeddedPiAssetPath()).catch(() => {
|
|
8109
8257
|
throw new Error("CLI-embedded Pi runtime is missing; reinstall this exact @odla-ai/cli version");
|
|
8110
8258
|
});
|
|
8111
8259
|
return `odla-ai/pi-agent:embedded-sha256-${(0, import_node_crypto3.createHash)("sha256").update(bundle).digest("hex")}`;
|
|
8112
8260
|
}
|
|
8113
8261
|
async function buildEmbeddedPiImage(engine, image, run) {
|
|
8114
|
-
const context = await (0,
|
|
8262
|
+
const context = await (0, import_promises11.mkdtemp)((0, import_node_path14.join)((0, import_node_os3.tmpdir)(), "odla-code-pi-"));
|
|
8115
8263
|
try {
|
|
8116
|
-
await (0,
|
|
8117
|
-
await (0,
|
|
8264
|
+
await (0, import_promises11.copyFile)(embeddedPiAssetPath(), (0, import_node_path14.join)(context, "pi-agent.js"));
|
|
8265
|
+
await (0, import_promises11.writeFile)((0, import_node_path14.join)(context, "Dockerfile"), [
|
|
8118
8266
|
`FROM ${CODE_NODE_IMAGE}`,
|
|
8119
8267
|
"COPY pi-agent.js /opt/odla/pi-agent.js",
|
|
8120
8268
|
"WORKDIR /workspace",
|
|
@@ -8123,14 +8271,14 @@ async function buildEmbeddedPiImage(engine, image, run) {
|
|
|
8123
8271
|
].join("\n"), { mode: 384 });
|
|
8124
8272
|
await run(engine, ["build", "--tag", image, context], "inherit");
|
|
8125
8273
|
} finally {
|
|
8126
|
-
await (0,
|
|
8274
|
+
await (0, import_promises11.rm)(context, { recursive: true, force: true });
|
|
8127
8275
|
}
|
|
8128
8276
|
}
|
|
8129
8277
|
|
|
8130
8278
|
// src/code-connect.ts
|
|
8131
8279
|
async function codeConnect(options) {
|
|
8132
8280
|
const cwd = options.cwd ?? process.cwd();
|
|
8133
|
-
const configPath = (0,
|
|
8281
|
+
const configPath = (0, import_node_path15.resolve)(cwd, options.configPath);
|
|
8134
8282
|
const cfg = (0, import_node_fs15.existsSync)(configPath) ? await loadProjectConfig(configPath) : null;
|
|
8135
8283
|
const requestedAppId = options.appId?.trim();
|
|
8136
8284
|
if (requestedAppId && !/^[a-z0-9][a-z0-9-]{1,62}$/.test(requestedAppId)) {
|
|
@@ -8499,10 +8647,8 @@ function requireName(parsed) {
|
|
|
8499
8647
|
return name;
|
|
8500
8648
|
}
|
|
8501
8649
|
|
|
8502
|
-
// src/help.ts
|
|
8503
|
-
|
|
8504
|
-
output.log(`odla-ai
|
|
8505
|
-
|
|
8650
|
+
// src/help-usage.ts
|
|
8651
|
+
var USAGE_SECTION = `
|
|
8506
8652
|
Start here:
|
|
8507
8653
|
odla-ai runbook ask "<question>" The current procedure, from odla's own
|
|
8508
8654
|
runbooks. Ask BEFORE searching the web or
|
|
@@ -8536,6 +8682,7 @@ Usage:
|
|
|
8536
8682
|
odla-ai app owners list [--config odla.config.mjs] [--email <odla-account>] [--json]
|
|
8537
8683
|
odla-ai app owners add <email> [--email <odla-account>] [--json]
|
|
8538
8684
|
odla-ai app owners remove <email> [--email <odla-account>] [--json]
|
|
8685
|
+
odla-ai brand design unpack <bundle.html|-> [--out <dir>] [--json]
|
|
8539
8686
|
odla-ai pm goal list [--app <id>] [--status <s>] [--q <text>] [--limit <n>] [--offset <n>] [--json]
|
|
8540
8687
|
odla-ai pm task list [--app <id>] [--column <c>] [--goal <id>] [--assignee <id>] [--q <text>] [--limit <n>] [--offset <n>] [--json]
|
|
8541
8688
|
odla-ai pm decision list [--app <id>] [--status <s>] [--q <text>] [--limit <n>] [--offset <n>] [--json]
|
|
@@ -8615,8 +8762,12 @@ Usage:
|
|
|
8615
8762
|
odla-ai secrets push --env <env> [--config odla.config.mjs] [--dry-run] [--yes]
|
|
8616
8763
|
odla-ai secrets set <name> --env <env> (--from-env <NAME>|--stdin) [--email <odla-account>] [--config odla.config.mjs] [--yes]
|
|
8617
8764
|
odla-ai secrets set-clerk-key --env <env> (--from-env <NAME>|--stdin) [--email <odla-account>] [--config odla.config.mjs] [--yes]
|
|
8618
|
-
odla-ai version
|
|
8765
|
+
odla-ai version`;
|
|
8619
8766
|
|
|
8767
|
+
// src/help.ts
|
|
8768
|
+
function printHelp(output = console) {
|
|
8769
|
+
output.log(`odla-ai
|
|
8770
|
+
${USAGE_SECTION}
|
|
8620
8771
|
Commands:
|
|
8621
8772
|
agent Inspect durable agent wakeups and explicitly requeue a
|
|
8622
8773
|
dead-lettered job; JSON output is stable for remote operators.
|
|
@@ -9065,7 +9216,7 @@ function jsonl(ctx, parsed, value2) {
|
|
|
9065
9216
|
}
|
|
9066
9217
|
async function discussWatch(ctx, topicId, parsed) {
|
|
9067
9218
|
if (ctx.json && parsed.options.jsonl === true) throw new Error("--json and --jsonl cannot be combined");
|
|
9068
|
-
const sleep = ctx.sleep ?? ((ms) => new Promise((
|
|
9219
|
+
const sleep = ctx.sleep ?? ((ms) => new Promise((resolve13) => setTimeout(resolve13, ms)));
|
|
9069
9220
|
const now = ctx.now ?? Date.now;
|
|
9070
9221
|
const intervalMs = (numberOpt2(parsed, "interval", DEFAULT_INTERVAL_MS / 1e3) ?? DEFAULT_INTERVAL_MS / 1e3) * 1e3;
|
|
9071
9222
|
const timeoutSeconds = numberOpt2(parsed, "timeout");
|
|
@@ -10537,6 +10688,7 @@ var COMMAND_SURFACE = {
|
|
|
10537
10688
|
promote: {},
|
|
10538
10689
|
owners: { list: {}, add: {}, remove: {} }
|
|
10539
10690
|
},
|
|
10691
|
+
brand: { design: { unpack: {} } },
|
|
10540
10692
|
calendar: { status: {}, calendars: {}, connect: {}, disconnect: {} },
|
|
10541
10693
|
capabilities: {},
|
|
10542
10694
|
code: { connect: {} },
|
|
@@ -10833,7 +10985,7 @@ async function runbookRemove(ctx, slug) {
|
|
|
10833
10985
|
|
|
10834
10986
|
// src/runbook-import.ts
|
|
10835
10987
|
var import_node_fs18 = require("fs");
|
|
10836
|
-
var
|
|
10988
|
+
var import_node_path16 = require("path");
|
|
10837
10989
|
function parseRunbook(text2, slug) {
|
|
10838
10990
|
let rest = text2;
|
|
10839
10991
|
const meta = {};
|
|
@@ -10862,8 +11014,8 @@ function readRunbookDir(dir) {
|
|
|
10862
11014
|
const files = (0, import_node_fs18.readdirSync)(dir).filter((f) => f.endsWith(".md")).sort();
|
|
10863
11015
|
if (!files.length) throw new Error(`no .md files in ${dir}`);
|
|
10864
11016
|
return files.map((file) => {
|
|
10865
|
-
const slug = (0,
|
|
10866
|
-
const parsed = parseRunbook((0, import_node_fs18.readFileSync)((0,
|
|
11017
|
+
const slug = (0, import_node_path16.basename)(file, ".md");
|
|
11018
|
+
const parsed = parseRunbook((0, import_node_fs18.readFileSync)((0, import_node_path16.join)(dir, file), "utf8"), slug);
|
|
10867
11019
|
return { file, slug, ...parsed, words: parsed.body.split(/\s+/).filter(Boolean).length };
|
|
10868
11020
|
});
|
|
10869
11021
|
}
|
|
@@ -10937,7 +11089,7 @@ async function upsert(ctx, r, visibility) {
|
|
|
10937
11089
|
// src/runbook-impact.ts
|
|
10938
11090
|
var import_node_child_process7 = require("child_process");
|
|
10939
11091
|
var import_node_fs19 = require("fs");
|
|
10940
|
-
var
|
|
11092
|
+
var import_node_path17 = require("path");
|
|
10941
11093
|
|
|
10942
11094
|
// src/runbook-impact-scan.ts
|
|
10943
11095
|
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$]*)/;
|
|
@@ -11106,7 +11258,7 @@ ${body.split("\n").map((line) => `+${line}`).join("\n")}
|
|
|
11106
11258
|
}
|
|
11107
11259
|
function manifestLabeller(root) {
|
|
11108
11260
|
return (workspace) => {
|
|
11109
|
-
const manifest = (0,
|
|
11261
|
+
const manifest = (0, import_node_path17.join)(root, workspace, "package.json");
|
|
11110
11262
|
if (!(0, import_node_fs19.existsSync)(manifest)) return void 0;
|
|
11111
11263
|
try {
|
|
11112
11264
|
const name = JSON.parse((0, import_node_fs19.readFileSync)(manifest, "utf8")).name;
|
|
@@ -11176,7 +11328,7 @@ function report3(ctx, impacts) {
|
|
|
11176
11328
|
async function runbookImpact(ctx, options, deps = {}) {
|
|
11177
11329
|
const cwd = deps.cwd ?? process.cwd();
|
|
11178
11330
|
const runGit = deps.runGit ?? gitRunner(cwd);
|
|
11179
|
-
const read3 = deps.readRepoFile ?? ((path) => (0, import_node_fs19.readFileSync)((0,
|
|
11331
|
+
const read3 = deps.readRepoFile ?? ((path) => (0, import_node_fs19.readFileSync)((0, import_node_path17.join)(cwd, path), "utf8"));
|
|
11180
11332
|
const surfaces = changedSurfaces(collectDiff(runGit, options.base, read3), manifestLabeller(cwd));
|
|
11181
11333
|
if (!surfaces.length) {
|
|
11182
11334
|
return ctx.out.log(
|
|
@@ -11311,7 +11463,7 @@ async function runbookComment(ctx, slug, body) {
|
|
|
11311
11463
|
var import_node_child_process8 = require("child_process");
|
|
11312
11464
|
var import_node_fs20 = require("fs");
|
|
11313
11465
|
var import_node_os5 = require("os");
|
|
11314
|
-
var
|
|
11466
|
+
var import_node_path18 = require("path");
|
|
11315
11467
|
var import_node_process12 = __toESM(require("process"), 1);
|
|
11316
11468
|
var EDITOR_ENV = ["ODLA_EDITOR", "VISUAL", "EDITOR"];
|
|
11317
11469
|
function resolveEditor(env = import_node_process12.default.env) {
|
|
@@ -11337,8 +11489,8 @@ function editText(initial, slug, deps = {}) {
|
|
|
11337
11489
|
);
|
|
11338
11490
|
if (!interactive())
|
|
11339
11491
|
throw new Error(`cannot open an editor without a terminal \u2014 pass --file <path> or --body "\u2026" instead`);
|
|
11340
|
-
const dir = (0, import_node_fs20.mkdtempSync)((0,
|
|
11341
|
-
const file = (0,
|
|
11492
|
+
const dir = (0, import_node_fs20.mkdtempSync)((0, import_node_path18.join)((0, import_node_os5.tmpdir)(), "odla-runbook-"));
|
|
11493
|
+
const file = (0, import_node_path18.join)(dir, `${slug}.md`);
|
|
11342
11494
|
try {
|
|
11343
11495
|
(0, import_node_fs20.writeFileSync)(file, initial, { mode: 384 });
|
|
11344
11496
|
const code = defaultRunOrInjected(deps)(editor, file);
|
|
@@ -11680,7 +11832,7 @@ async function runbookCommand(parsed, deps = {}) {
|
|
|
11680
11832
|
}
|
|
11681
11833
|
|
|
11682
11834
|
// src/security-command-context.ts
|
|
11683
|
-
var
|
|
11835
|
+
var import_promises12 = require("readline/promises");
|
|
11684
11836
|
async function hostedSecurityContext(parsed, dependencies) {
|
|
11685
11837
|
const configPath = stringOpt(parsed.options.config) ?? "odla.config.mjs";
|
|
11686
11838
|
const cfg = await loadProjectConfig(configPath);
|
|
@@ -11706,7 +11858,7 @@ async function hostedSecurityContext(parsed, dependencies) {
|
|
|
11706
11858
|
async function interactiveConfirmation(message2, dependencies) {
|
|
11707
11859
|
if (dependencies.confirm) return dependencies.confirm(message2);
|
|
11708
11860
|
if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
|
|
11709
|
-
const prompt = (0,
|
|
11861
|
+
const prompt = (0, import_promises12.createInterface)({ input: process.stdin, output: process.stdout });
|
|
11710
11862
|
try {
|
|
11711
11863
|
const answer = await prompt.question(`${message2} [y/N] `);
|
|
11712
11864
|
return /^y(?:es)?$/i.test(answer.trim());
|
|
@@ -11833,7 +11985,7 @@ function hostedSeverity(value2, flag) {
|
|
|
11833
11985
|
var import_security2 = require("@odla-ai/security");
|
|
11834
11986
|
|
|
11835
11987
|
// src/security.ts
|
|
11836
|
-
var
|
|
11988
|
+
var import_node_path19 = require("path");
|
|
11837
11989
|
var import_security = require("@odla-ai/security");
|
|
11838
11990
|
var import_node3 = require("@odla-ai/security/node");
|
|
11839
11991
|
async function runHostedSecurity(options) {
|
|
@@ -11845,9 +11997,9 @@ async function runHostedSecurity(options) {
|
|
|
11845
11997
|
const appId = selfAudit ? "odla-ai" : cfg.app.id;
|
|
11846
11998
|
const env = selfAudit ? "prod" : selectEnv(options.env, cfg.envs, cfg.configPath, cfg.rootDir);
|
|
11847
11999
|
const platform = options.platform ?? cfg?.platformUrl ?? "https://odla.ai";
|
|
11848
|
-
const target = (0,
|
|
11849
|
-
const output = (0,
|
|
11850
|
-
const outputRelative = (0,
|
|
12000
|
+
const target = (0, import_node_path19.resolve)(options.target ?? cfg?.rootDir ?? ".");
|
|
12001
|
+
const output = (0, import_node_path19.resolve)(options.out ?? (0, import_node_path19.resolve)(target, ".odla/security/hosted"));
|
|
12002
|
+
const outputRelative = (0, import_node_path19.relative)(target, output).split(import_node_path19.sep).join("/");
|
|
11851
12003
|
if (!outputRelative) throw new Error("Hosted security output cannot be the repository root");
|
|
11852
12004
|
const profile = profileFor(options.profile ?? "odla", options.maxHuntTasks ?? 12);
|
|
11853
12005
|
const tokenRequest = {
|
|
@@ -11859,7 +12011,7 @@ async function runHostedSecurity(options) {
|
|
|
11859
12011
|
};
|
|
11860
12012
|
const token = await injectedToken(options, tokenRequest);
|
|
11861
12013
|
const snapshot = await (0, import_node3.snapshotDirectory)(target, {
|
|
11862
|
-
exclude: !outputRelative.startsWith("../") && !(0,
|
|
12014
|
+
exclude: !outputRelative.startsWith("../") && !(0, import_node_path19.isAbsolute)(outputRelative) ? [outputRelative] : []
|
|
11863
12015
|
});
|
|
11864
12016
|
const hosted = await (0, import_security.createPlatformSecurityReasoners)({
|
|
11865
12017
|
platform,
|
|
@@ -11877,7 +12029,7 @@ async function runHostedSecurity(options) {
|
|
|
11877
12029
|
});
|
|
11878
12030
|
const harness = (0, import_security.createSecurityHarness)({
|
|
11879
12031
|
profile,
|
|
11880
|
-
store: new import_node3.FileRunStore((0,
|
|
12032
|
+
store: new import_node3.FileRunStore((0, import_node_path19.resolve)(output, "state")),
|
|
11881
12033
|
discoveryReasoner: hosted.discoveryReasoner,
|
|
11882
12034
|
validationReasoner: hosted.validationReasoner,
|
|
11883
12035
|
policy: {
|
|
@@ -11901,7 +12053,7 @@ async function runHostedSecurity(options) {
|
|
|
11901
12053
|
function selectEnv(requested, declared, configPath, rootDir) {
|
|
11902
12054
|
const env = requested ?? (declared.includes("dev") ? "dev" : declared[0]);
|
|
11903
12055
|
if (!env || !declared.includes(env)) {
|
|
11904
|
-
const shown = (0,
|
|
12056
|
+
const shown = (0, import_node_path19.relative)(rootDir, configPath) || configPath;
|
|
11905
12057
|
throw new Error(`env "${env ?? ""}" is not declared in ${shown}`);
|
|
11906
12058
|
}
|
|
11907
12059
|
return env;
|
|
@@ -11930,7 +12082,7 @@ function printSummary(out, appId, env, run, report4, output) {
|
|
|
11930
12082
|
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}`);
|
|
11931
12083
|
if (report4.callBudget) out.log(` calls: discovery=${formatBudget(report4.callBudget.discovery)} validation=${formatBudget(report4.callBudget.validation)}`);
|
|
11932
12084
|
out.log(` findings: confirmed=${report4.metrics.confirmed} needs_reproduction=${report4.metrics.needsReproduction} candidates=${report4.metrics.candidates}`);
|
|
11933
|
-
out.log(` report: ${(0,
|
|
12085
|
+
out.log(` report: ${(0, import_node_path19.resolve)(output, "REPORT.md")}`);
|
|
11934
12086
|
}
|
|
11935
12087
|
function formatBudget(usage) {
|
|
11936
12088
|
return usage ? `${usage.usedCalls}/${usage.maxCalls} skipped=${usage.skippedCalls}` : "caller-managed";
|
|
@@ -12431,6 +12583,10 @@ async function runCli(argv = process.argv.slice(2), dependencies = {}) {
|
|
|
12431
12583
|
await securityCommand(parsed, runtime);
|
|
12432
12584
|
return;
|
|
12433
12585
|
}
|
|
12586
|
+
if (command === "brand") {
|
|
12587
|
+
await brandCommand(parsed, runtime);
|
|
12588
|
+
return;
|
|
12589
|
+
}
|
|
12434
12590
|
if (command === "pm") {
|
|
12435
12591
|
await pmCommand(parsed, runtime);
|
|
12436
12592
|
return;
|