@odla-ai/cli 0.27.12 → 0.27.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/dist/bin.cjs +118 -19
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +76 -2
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-ECRBOR66.js → chunk-3SQ2XUBB.js} +49 -20
- package/dist/chunk-3SQ2XUBB.js.map +1 -0
- package/dist/index.cjs +45 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/skills/odla/references/build.md +8 -0
- package/dist/chunk-ECRBOR66.js.map +0 -1
package/dist/bin.js
CHANGED
|
@@ -1,12 +1,86 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
cliVersion,
|
|
4
|
+
compareVersions,
|
|
3
5
|
exitCodeFor,
|
|
4
6
|
redactSecrets,
|
|
5
7
|
runCli
|
|
6
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-3SQ2XUBB.js";
|
|
9
|
+
|
|
10
|
+
// src/cli-update.ts
|
|
11
|
+
import { realpathSync } from "fs";
|
|
12
|
+
var DEFAULT_REGISTRY_URL = "https://registry.npmjs.org/@odla-ai%2fcli/latest";
|
|
13
|
+
var VERSION = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
|
|
14
|
+
async function requireCurrentCliForProvision(argv, options = {}) {
|
|
15
|
+
if (argv[0] !== "provision" || argv.includes("--dry-run")) return;
|
|
16
|
+
const current = options.currentVersion ?? cliVersion();
|
|
17
|
+
if (!VERSION.test(current)) return;
|
|
18
|
+
const latest = await fetchLatestCliVersion(options);
|
|
19
|
+
if (!latest || compareVersions(current, latest) >= 0) return;
|
|
20
|
+
const entryPath = resolvedEntryPath(options.entryPath ?? process.argv[1]);
|
|
21
|
+
const workspace = isWorkspaceCli(entryPath);
|
|
22
|
+
const rerun = renderReleasedProvisionCommand(latest, argv);
|
|
23
|
+
const source = workspace ? ` This executable resolves to the workspace build at ${entryPath}; update/rebase that worktree and rebuild it before using the linked CLI again.` : " Update the installed dependency before using its CLI again.";
|
|
24
|
+
throw new Error(
|
|
25
|
+
`provision blocked: @odla-ai/cli ${current} is older than the released ${latest}. Provisioning grant requests are security-sensitive, and a stale client can omit required authority.${source}
|
|
26
|
+
Run the current release now:
|
|
27
|
+
${rerun}`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
async function fetchLatestCliVersion(options) {
|
|
31
|
+
const controller = new AbortController();
|
|
32
|
+
const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? 2500);
|
|
33
|
+
timeout.unref?.();
|
|
34
|
+
try {
|
|
35
|
+
const response = await (options.fetch ?? fetch)(
|
|
36
|
+
options.registryUrl ?? process.env.ODLA_CLI_REGISTRY_URL ?? DEFAULT_REGISTRY_URL,
|
|
37
|
+
{
|
|
38
|
+
headers: {
|
|
39
|
+
accept: "application/json",
|
|
40
|
+
"user-agent": `odla-ai-cli/${options.currentVersion ?? cliVersion()}`
|
|
41
|
+
},
|
|
42
|
+
signal: controller.signal
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
if (!response.ok) return null;
|
|
46
|
+
const body = await response.json();
|
|
47
|
+
return typeof body.version === "string" && VERSION.test(body.version) ? body.version : null;
|
|
48
|
+
} catch {
|
|
49
|
+
return null;
|
|
50
|
+
} finally {
|
|
51
|
+
clearTimeout(timeout);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function resolvedEntryPath(entryPath) {
|
|
55
|
+
if (!entryPath) return "unknown executable";
|
|
56
|
+
try {
|
|
57
|
+
return realpathSync(entryPath);
|
|
58
|
+
} catch {
|
|
59
|
+
return entryPath;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function isWorkspaceCli(entryPath) {
|
|
63
|
+
const normalized = entryPath.replaceAll("\\", "/");
|
|
64
|
+
return normalized.includes("/packages/cli/dist/bin.") && !normalized.includes("/node_modules/");
|
|
65
|
+
}
|
|
66
|
+
function renderReleasedProvisionCommand(latest, argv) {
|
|
67
|
+
const safeArgs = [];
|
|
68
|
+
for (let index = 0; index < argv.length; index++) {
|
|
69
|
+
const value = argv[index];
|
|
70
|
+
safeArgs.push(value);
|
|
71
|
+
if (value === "--token" && index + 1 < argv.length) {
|
|
72
|
+
safeArgs.push("<redacted-token>");
|
|
73
|
+
index++;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return ["npx", "--yes", `@odla-ai/cli@${latest}`, ...safeArgs].map(shellQuote).join(" ");
|
|
77
|
+
}
|
|
78
|
+
function shellQuote(value) {
|
|
79
|
+
return /^[A-Za-z0-9_@%+=:,./-]+$/.test(value) ? value : `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
80
|
+
}
|
|
7
81
|
|
|
8
82
|
// src/bin.ts
|
|
9
|
-
runCli().catch((err) => {
|
|
83
|
+
requireCurrentCliForProvision(process.argv.slice(2)).then(() => runCli()).catch((err) => {
|
|
10
84
|
console.error(redactSecrets(`odla-ai: ${err instanceof Error ? err.message : String(err)}`));
|
|
11
85
|
process.exitCode = exitCodeFor(err);
|
|
12
86
|
});
|
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/bin.ts"],"sourcesContent":["import { exitCodeFor, runCli } from \"./cli\";\nimport { redactSecrets } from \"./redact\";\n\
|
|
1
|
+
{"version":3,"sources":["../src/cli-update.ts","../src/bin.ts"],"sourcesContent":["import { realpathSync } from \"node:fs\";\nimport { compareVersions } from \"./runbook-requires\";\nimport { cliVersion } from \"./version\";\n\nconst DEFAULT_REGISTRY_URL = \"https://registry.npmjs.org/@odla-ai%2fcli/latest\";\nconst VERSION = /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?$/;\n\nexport interface CliUpdateCheckOptions {\n currentVersion?: string;\n entryPath?: string;\n fetch?: typeof fetch;\n registryUrl?: string;\n timeoutMs?: number;\n}\n\n/**\n * Provisioning handshakes are security-sensitive protocol requests. Before a\n * real provision run, stop a CLI which is confirmed older than npm's current\n * release so an agent cannot unknowingly submit an obsolete grant shape.\n * Registry unavailability remains fail-open: npm must not become a production\n * availability dependency for an otherwise current CLI.\n */\nexport async function requireCurrentCliForProvision(\n argv: readonly string[],\n options: CliUpdateCheckOptions = {},\n): Promise<void> {\n if (argv[0] !== \"provision\" || argv.includes(\"--dry-run\")) return;\n\n const current = options.currentVersion ?? cliVersion();\n if (!VERSION.test(current)) return;\n const latest = await fetchLatestCliVersion(options);\n if (!latest || compareVersions(current, latest) >= 0) return;\n\n const entryPath = resolvedEntryPath(options.entryPath ?? process.argv[1]);\n const workspace = isWorkspaceCli(entryPath);\n const rerun = renderReleasedProvisionCommand(latest, argv);\n const source = workspace\n ? ` This executable resolves to the workspace build at ${entryPath}; update/rebase that worktree and rebuild it before using the linked CLI again.`\n : \" Update the installed dependency before using its CLI again.\";\n throw new Error(\n `provision blocked: @odla-ai/cli ${current} is older than the released ${latest}. ` +\n `Provisioning grant requests are security-sensitive, and a stale client can omit required authority.${source}\\n` +\n `Run the current release now:\\n ${rerun}`,\n );\n}\n\nasync function fetchLatestCliVersion(\n options: CliUpdateCheckOptions,\n): Promise<string | null> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? 2_500);\n timeout.unref?.();\n try {\n const response = await (options.fetch ?? fetch)(\n options.registryUrl ?? process.env.ODLA_CLI_REGISTRY_URL ?? DEFAULT_REGISTRY_URL,\n {\n headers: {\n accept: \"application/json\",\n \"user-agent\": `odla-ai-cli/${options.currentVersion ?? cliVersion()}`,\n },\n signal: controller.signal,\n },\n );\n if (!response.ok) return null;\n const body = await response.json() as { version?: unknown };\n return typeof body.version === \"string\" && VERSION.test(body.version)\n ? body.version\n : null;\n } catch {\n return null;\n } finally {\n clearTimeout(timeout);\n }\n}\n\nfunction resolvedEntryPath(entryPath: string | undefined): string {\n if (!entryPath) return \"unknown executable\";\n try {\n return realpathSync(entryPath);\n } catch {\n return entryPath;\n }\n}\n\nfunction isWorkspaceCli(entryPath: string): boolean {\n const normalized = entryPath.replaceAll(\"\\\\\", \"/\");\n return normalized.includes(\"/packages/cli/dist/bin.\") &&\n !normalized.includes(\"/node_modules/\");\n}\n\nfunction renderReleasedProvisionCommand(\n latest: string,\n argv: readonly string[],\n): string {\n const safeArgs: string[] = [];\n for (let index = 0; index < argv.length; index++) {\n const value = argv[index]!;\n safeArgs.push(value);\n if (value === \"--token\" && index + 1 < argv.length) {\n safeArgs.push(\"<redacted-token>\");\n index++;\n }\n }\n return [\"npx\", \"--yes\", `@odla-ai/cli@${latest}`, ...safeArgs]\n .map(shellQuote)\n .join(\" \");\n}\n\nfunction shellQuote(value: string): string {\n return /^[A-Za-z0-9_@%+=:,./-]+$/.test(value)\n ? value\n : `'${value.replaceAll(\"'\", `'\"'\"'`)}'`;\n}\n","import { exitCodeFor, runCli } from \"./cli\";\nimport { requireCurrentCliForProvision } from \"./cli-update\";\nimport { redactSecrets } from \"./redact\";\n\nrequireCurrentCliForProvision(process.argv.slice(2))\n .then(() => runCli())\n .catch((err) => {\n console.error(redactSecrets(`odla-ai: ${err instanceof Error ? err.message : String(err)}`));\n process.exitCode = exitCodeFor(err);\n });\n"],"mappings":";;;;;;;;;;AAAA,SAAS,oBAAoB;AAI7B,IAAM,uBAAuB;AAC7B,IAAM,UAAU;AAiBhB,eAAsB,8BACpB,MACA,UAAiC,CAAC,GACnB;AACf,MAAI,KAAK,CAAC,MAAM,eAAe,KAAK,SAAS,WAAW,EAAG;AAE3D,QAAM,UAAU,QAAQ,kBAAkB,WAAW;AACrD,MAAI,CAAC,QAAQ,KAAK,OAAO,EAAG;AAC5B,QAAM,SAAS,MAAM,sBAAsB,OAAO;AAClD,MAAI,CAAC,UAAU,gBAAgB,SAAS,MAAM,KAAK,EAAG;AAEtD,QAAM,YAAY,kBAAkB,QAAQ,aAAa,QAAQ,KAAK,CAAC,CAAC;AACxE,QAAM,YAAY,eAAe,SAAS;AAC1C,QAAM,QAAQ,+BAA+B,QAAQ,IAAI;AACzD,QAAM,SAAS,YACX,uDAAuD,SAAS,oFAChE;AACJ,QAAM,IAAI;AAAA,IACR,mCAAmC,OAAO,+BAA+B,MAAM,wGACuB,MAAM;AAAA;AAAA,IACzE,KAAK;AAAA,EAC1C;AACF;AAEA,eAAe,sBACb,SACwB;AACxB,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,QAAQ,aAAa,IAAK;AAC/E,UAAQ,QAAQ;AAChB,MAAI;AACF,UAAM,WAAW,OAAO,QAAQ,SAAS;AAAA,MACvC,QAAQ,eAAe,QAAQ,IAAI,yBAAyB;AAAA,MAC5D;AAAA,QACE,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,cAAc,eAAe,QAAQ,kBAAkB,WAAW,CAAC;AAAA,QACrE;AAAA,QACA,QAAQ,WAAW;AAAA,MACrB;AAAA,IACF;AACA,QAAI,CAAC,SAAS,GAAI,QAAO;AACzB,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,WAAO,OAAO,KAAK,YAAY,YAAY,QAAQ,KAAK,KAAK,OAAO,IAChE,KAAK,UACL;AAAA,EACN,QAAQ;AACN,WAAO;AAAA,EACT,UAAE;AACA,iBAAa,OAAO;AAAA,EACtB;AACF;AAEA,SAAS,kBAAkB,WAAuC;AAChE,MAAI,CAAC,UAAW,QAAO;AACvB,MAAI;AACF,WAAO,aAAa,SAAS;AAAA,EAC/B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,eAAe,WAA4B;AAClD,QAAM,aAAa,UAAU,WAAW,MAAM,GAAG;AACjD,SAAO,WAAW,SAAS,yBAAyB,KAClD,CAAC,WAAW,SAAS,gBAAgB;AACzC;AAEA,SAAS,+BACP,QACA,MACQ;AACR,QAAM,WAAqB,CAAC;AAC5B,WAAS,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS;AAChD,UAAM,QAAQ,KAAK,KAAK;AACxB,aAAS,KAAK,KAAK;AACnB,QAAI,UAAU,aAAa,QAAQ,IAAI,KAAK,QAAQ;AAClD,eAAS,KAAK,kBAAkB;AAChC;AAAA,IACF;AAAA,EACF;AACA,SAAO,CAAC,OAAO,SAAS,gBAAgB,MAAM,IAAI,GAAG,QAAQ,EAC1D,IAAI,UAAU,EACd,KAAK,GAAG;AACb;AAEA,SAAS,WAAW,OAAuB;AACzC,SAAO,2BAA2B,KAAK,KAAK,IACxC,QACA,IAAI,MAAM,WAAW,KAAK,OAAO,CAAC;AACxC;;;AC5GA,8BAA8B,QAAQ,KAAK,MAAM,CAAC,CAAC,EAChD,KAAK,MAAM,OAAO,CAAC,EACnB,MAAM,CAAC,QAAQ;AACd,UAAQ,MAAM,cAAc,YAAY,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE,CAAC;AAC3F,UAAQ,WAAW,YAAY,GAAG;AACpC,CAAC;","names":[]}
|
|
@@ -292,23 +292,30 @@ function handshakeWaitMs(waitSeconds, interactive = process4.stdout.isTTY === tr
|
|
|
292
292
|
|
|
293
293
|
// src/token.ts
|
|
294
294
|
async function getDeveloperToken(cfg, options, doFetch, out, grantRequest = {}) {
|
|
295
|
-
if (options.token) return options.token;
|
|
296
295
|
const audience = platformAudience(cfg.platformUrl);
|
|
297
|
-
if (process5.env.ODLA_DEV_TOKEN) {
|
|
298
|
-
const declared = process5.env.ODLA_DEV_TOKEN_AUDIENCE;
|
|
299
|
-
if (declared) {
|
|
300
|
-
if (platformAudience(declared) !== audience) throw new Error("ODLA_DEV_TOKEN_AUDIENCE does not match the configured platform");
|
|
301
|
-
} else if (audience !== "https://odla.ai") {
|
|
302
|
-
throw new Error("ODLA_DEV_TOKEN_AUDIENCE is required for a non-default platform");
|
|
303
|
-
}
|
|
304
|
-
return process5.env.ODLA_DEV_TOKEN;
|
|
305
|
-
}
|
|
306
296
|
const optionalProjectCapabilities = grantRequest.optionalProjectCapabilities ?? [];
|
|
307
297
|
const grantIntent = { projectIds: [cfg.app.id], optionalProjectCapabilities };
|
|
308
298
|
const cached = readJsonFile(cfg.local.tokenFile);
|
|
309
|
-
if (
|
|
310
|
-
|
|
311
|
-
|
|
299
|
+
if (!grantRequest.forceReview) {
|
|
300
|
+
if (options.token) return options.token;
|
|
301
|
+
if (process5.env.ODLA_DEV_TOKEN) {
|
|
302
|
+
const declared = process5.env.ODLA_DEV_TOKEN_AUDIENCE;
|
|
303
|
+
if (declared) {
|
|
304
|
+
if (platformAudience(declared) !== audience) throw new Error("ODLA_DEV_TOKEN_AUDIENCE does not match the configured platform");
|
|
305
|
+
} else if (audience !== "https://odla.ai") {
|
|
306
|
+
throw new Error("ODLA_DEV_TOKEN_AUDIENCE is required for a non-default platform");
|
|
307
|
+
}
|
|
308
|
+
return process5.env.ODLA_DEV_TOKEN;
|
|
309
|
+
}
|
|
310
|
+
if (cached?.token && cached.platform === audience && (cached.expiresAt ?? 0) > Date.now() + 6e4 && cachedGrantCovers(cached, grantIntent)) {
|
|
311
|
+
out.error(`auth: using cached developer token (${displayPath(cfg.local.tokenFile, cfg.rootDir)})`);
|
|
312
|
+
return cached.token;
|
|
313
|
+
}
|
|
314
|
+
} else {
|
|
315
|
+
if (options.token) {
|
|
316
|
+
throw new Error("--request-grant cannot be combined with --token; remove --token so the approved replacement credential can be collected and cached");
|
|
317
|
+
}
|
|
318
|
+
out.error(`auth: requesting fresh owner review for app.manage on exact project "${cfg.app.id}"`);
|
|
312
319
|
}
|
|
313
320
|
const ctx = {
|
|
314
321
|
cfg,
|
|
@@ -1810,11 +1817,11 @@ async function assertTenantAdminAccess(doFetch, cfg, env, token) {
|
|
|
1810
1817
|
}
|
|
1811
1818
|
if (code === "provision_approval_required") {
|
|
1812
1819
|
throw new Error(
|
|
1813
|
-
`${env}: the agent credential does not carry the owner-reviewed app.manage grant required to provision "${cfg.app.id}" (tenant ${tenantId}). The human owner id on the token is accountability, not agent authority.
|
|
1820
|
+
`${env}: the agent credential does not carry the owner-reviewed app.manage grant required to provision "${cfg.app.id}" (tenant ${tenantId}). The human owner id on the token is accountability, not agent authority. Run "odla-ai provision --request-grant --email <odla-account>" to open one fresh exact-project owner review; do not change app ownership unless the human account itself is not an owner`
|
|
1814
1821
|
);
|
|
1815
1822
|
}
|
|
1816
1823
|
throw new Error(
|
|
1817
|
-
`${env}: this credential lacks live app.manage authority for "${cfg.app.id}" (tenant ${tenantId}) \u2014 nothing was minted or written;
|
|
1824
|
+
`${env}: this credential lacks live app.manage authority for "${cfg.app.id}" (tenant ${tenantId}) \u2014 nothing was minted or written; run "odla-ai provision --request-grant --email <odla-account>" to open a fresh owner review. If the human account is not an owner, an existing owner must add it in signed-in Studio; an agent token cannot repair ownership`
|
|
1818
1825
|
);
|
|
1819
1826
|
}
|
|
1820
1827
|
throw new Error(`${env}: tenant access preflight (${tenantId}) failed: ${res.status} ${await safeText4(res)}`);
|
|
@@ -7241,7 +7248,7 @@ function record6(value2) {
|
|
|
7241
7248
|
}
|
|
7242
7249
|
|
|
7243
7250
|
// src/provision.ts
|
|
7244
|
-
import { createAppsClient as createAppsClient3, orderAppServices as orderAppServices3, tenantIdFor as tenantIdFor4 } from "@odla-ai/apps";
|
|
7251
|
+
import { AppsError as AppsError2, createAppsClient as createAppsClient3, orderAppServices as orderAppServices3, tenantIdFor as tenantIdFor4 } from "@odla-ai/apps";
|
|
7245
7252
|
import { putSecret as putSecret2 } from "@odla-ai/ai";
|
|
7246
7253
|
import process9 from "process";
|
|
7247
7254
|
|
|
@@ -7462,14 +7469,25 @@ async function provision(options) {
|
|
|
7462
7469
|
}
|
|
7463
7470
|
const doFetch = options.fetch ?? fetch;
|
|
7464
7471
|
const token = await getDeveloperToken(cfg, options, doFetch, out, {
|
|
7465
|
-
optionalProjectCapabilities: ["app.manage"]
|
|
7472
|
+
optionalProjectCapabilities: ["app.manage"],
|
|
7473
|
+
forceReview: options.requestGrant
|
|
7466
7474
|
});
|
|
7467
7475
|
const apps = createAppsClient3({ endpoint: cfg.platformUrl, token, fetcher: { fetch: doFetch } });
|
|
7468
7476
|
const existing = await apps.resolveApp(cfg.app.id);
|
|
7469
7477
|
if (existing) {
|
|
7470
7478
|
out.log(`app: ${cfg.app.id} already exists`);
|
|
7471
7479
|
} else {
|
|
7472
|
-
|
|
7480
|
+
try {
|
|
7481
|
+
await apps.createApp({ name: cfg.app.name, appId: cfg.app.id });
|
|
7482
|
+
} catch (error) {
|
|
7483
|
+
if (error instanceof AppsError2 && error.status === 403) {
|
|
7484
|
+
throw new Error(
|
|
7485
|
+
`app "${cfg.app.id}" does not exist, and this authenticated agent credential has no owner-reviewed app.manage bootstrap grant for that exact id. Run "odla-ai provision --request-grant --email <odla-account>" to open the review URL and continue; developer ownership alone is not agent authority`,
|
|
7486
|
+
{ cause: error }
|
|
7487
|
+
);
|
|
7488
|
+
}
|
|
7489
|
+
throw error;
|
|
7490
|
+
}
|
|
7473
7491
|
out.log(`app: created ${cfg.app.id}`);
|
|
7474
7492
|
}
|
|
7475
7493
|
for (const env of cfg.envs) {
|
|
@@ -9360,7 +9378,7 @@ Usage:
|
|
|
9360
9378
|
odla-ai security report <job-id> [--json]
|
|
9361
9379
|
odla-ai security run [target] --ack-redacted-source [--env dev] [--profile odla] [--fail-on high]
|
|
9362
9380
|
odla-ai security run [target] --self --ack-redacted-source
|
|
9363
|
-
odla-ai provision [--config odla.config.mjs] [--email <odla-account>] [--wait <seconds>] [--dry-run] [--push-secrets] [--rotate-o11y-token] [--write-dev-vars[=path]] [--yes]
|
|
9381
|
+
odla-ai provision [--config odla.config.mjs] [--email <odla-account>] [--request-grant] [--wait <seconds>] [--dry-run] [--push-secrets] [--rotate-o11y-token] [--write-dev-vars[=path]] [--yes]
|
|
9364
9382
|
odla-ai smoke [--config odla.config.mjs] [--env dev] [--email <odla-account>] [--no-open]
|
|
9365
9383
|
odla-ai skill install [--dir <project>] [--agent <name>] [--global] [--force]
|
|
9366
9384
|
odla-ai secrets push --env <env> [--config odla.config.mjs] [--dry-run] [--yes]
|
|
@@ -9495,6 +9513,13 @@ Safety:
|
|
|
9495
9513
|
The email is a non-secret identity hint: never provide a password or session
|
|
9496
9514
|
token. The matching account must already exist, be signed in, explicitly
|
|
9497
9515
|
review the exact code, and finish any current request before claiming another.
|
|
9516
|
+
If provision reports that the current agent principal has no live app.manage
|
|
9517
|
+
grant, run it once with --request-grant. That flag ignores ODLA_DEV_TOKEN and
|
|
9518
|
+
the local cache, prints and opens a fresh exact-project owner-review URL, then
|
|
9519
|
+
continues provisioning with the approved replacement credential.
|
|
9520
|
+
Before a non-dry-run provision, the executable checks npm's current CLI
|
|
9521
|
+
release. A confirmed stale client stops with a safe npx rerun command; a
|
|
9522
|
+
workspace-linked client also identifies the worktree that must be updated.
|
|
9498
9523
|
Run Code from a GitHub checkout already connected to an app in Studio; an
|
|
9499
9524
|
odla.config.mjs may select the app explicitly but is not required. Code host
|
|
9500
9525
|
approval and credential hashes live in odla-ai/db. The host
|
|
@@ -12796,6 +12821,7 @@ async function provisionCommand(parsed, dependencies) {
|
|
|
12796
12821
|
"write-credentials",
|
|
12797
12822
|
"write-dev-vars",
|
|
12798
12823
|
"token",
|
|
12824
|
+
"request-grant",
|
|
12799
12825
|
"email",
|
|
12800
12826
|
"open",
|
|
12801
12827
|
"wait",
|
|
@@ -12811,6 +12837,7 @@ async function provisionCommand(parsed, dependencies) {
|
|
|
12811
12837
|
writeCredentials: parsed.options["write-credentials"] !== false,
|
|
12812
12838
|
writeDevVars: typeof writeDevVars2 === "string" ? writeDevVars2 : writeDevVars2 === true,
|
|
12813
12839
|
token: stringOpt(parsed.options.token),
|
|
12840
|
+
requestGrant: parsed.options["request-grant"] === true,
|
|
12814
12841
|
email: stringOpt(parsed.options.email),
|
|
12815
12842
|
open: parsed.options.open === false ? false : parsed.options.open === true ? true : void 0,
|
|
12816
12843
|
wait: numberOpt(parsed.options.wait, "--wait"),
|
|
@@ -12861,6 +12888,7 @@ export {
|
|
|
12861
12888
|
calendarDisconnect,
|
|
12862
12889
|
CAPABILITIES,
|
|
12863
12890
|
printCapabilities,
|
|
12891
|
+
cliVersion,
|
|
12864
12892
|
ConfigOperationCommandError,
|
|
12865
12893
|
desiredRegistryState,
|
|
12866
12894
|
configApply,
|
|
@@ -12894,6 +12922,7 @@ export {
|
|
|
12894
12922
|
describeProblem,
|
|
12895
12923
|
invocationPath,
|
|
12896
12924
|
surfacePaths,
|
|
12925
|
+
compareVersions,
|
|
12897
12926
|
runHostedSecurity,
|
|
12898
12927
|
getHostedSecurityIntent,
|
|
12899
12928
|
getHostedSecurityPlan,
|
|
@@ -12906,4 +12935,4 @@ export {
|
|
|
12906
12935
|
exitCodeFor,
|
|
12907
12936
|
runCli
|
|
12908
12937
|
};
|
|
12909
|
-
//# sourceMappingURL=chunk-
|
|
12938
|
+
//# sourceMappingURL=chunk-3SQ2XUBB.js.map
|