@odla-ai/cli 0.20.2 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.cjs +181 -150
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-XBPDHNWO.js → chunk-DINDRUDA.js} +55 -25
- package/dist/chunk-DINDRUDA.js.map +1 -0
- package/dist/index.cjs +192 -159
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -3
- package/dist/index.d.ts +11 -3
- package/dist/index.js +3 -1
- package/package.json +1 -1
- package/dist/chunk-XBPDHNWO.js.map +0 -1
package/dist/bin.js
CHANGED
|
@@ -179,7 +179,7 @@ function approvalLines(prompt) {
|
|
|
179
179
|
return lines;
|
|
180
180
|
}
|
|
181
181
|
function printApproval(out, prompt) {
|
|
182
|
-
for (const line of approvalLines(prompt)) out.
|
|
182
|
+
for (const line of approvalLines(prompt)) out.error(line);
|
|
183
183
|
}
|
|
184
184
|
function reminderLines(prompt) {
|
|
185
185
|
return [
|
|
@@ -251,7 +251,7 @@ async function getDeveloperToken(cfg, options, doFetch, out) {
|
|
|
251
251
|
}
|
|
252
252
|
const cached = readJsonFile(cfg.local.tokenFile);
|
|
253
253
|
if (cached?.token && cached.platform === audience && (cached.expiresAt ?? 0) > Date.now() + 6e4) {
|
|
254
|
-
out.
|
|
254
|
+
out.error(`auth: using cached developer token (${displayPath(cfg.local.tokenFile, cfg.rootDir)})`);
|
|
255
255
|
return cached.token;
|
|
256
256
|
}
|
|
257
257
|
const ctx = {
|
|
@@ -268,16 +268,16 @@ async function getDeveloperToken(cfg, options, doFetch, out) {
|
|
|
268
268
|
const { token, expiresAt } = await resumePendingHandshake(ctx, waitMs) ?? await freshHandshake(ctx, waitMs);
|
|
269
269
|
clearPendingHandshake(ctx.pendingFile);
|
|
270
270
|
writePrivateJson(cfg.local.tokenFile, { platform: audience, email: ctx.email, token, expiresAt });
|
|
271
|
-
out.
|
|
271
|
+
out.error(`auth: developer token cached (${displayPath(cfg.local.tokenFile, cfg.rootDir)})`);
|
|
272
272
|
return token;
|
|
273
273
|
}
|
|
274
274
|
async function resumePendingHandshake(ctx, waitMs) {
|
|
275
275
|
const pending = readPendingHandshake(ctx.pendingFile, ctx.audience, ctx.email);
|
|
276
276
|
if (!pending) return null;
|
|
277
|
-
ctx.out.
|
|
278
|
-
ctx.out.
|
|
277
|
+
ctx.out.error("");
|
|
278
|
+
ctx.out.error(`auth: resuming pending handshake \u2014 ${approvalHint(pending)}`);
|
|
279
279
|
await launchApproval(ctx, pending.approvalUrl);
|
|
280
|
-
ctx.out.
|
|
280
|
+
ctx.out.error("");
|
|
281
281
|
const stopReminder = approvalReminder(ctx.out, pending);
|
|
282
282
|
try {
|
|
283
283
|
return await collectToken({
|
|
@@ -293,7 +293,7 @@ async function resumePendingHandshake(ctx, waitMs) {
|
|
|
293
293
|
if (code === "handshake_pending") throw stillPending(pending, ctx.email);
|
|
294
294
|
if (code === "handshake_expired" || code === "handshake_timeout") {
|
|
295
295
|
clearPendingHandshake(ctx.pendingFile);
|
|
296
|
-
ctx.out.
|
|
296
|
+
ctx.out.error("auth: pending handshake lapsed unapproved; starting a fresh one");
|
|
297
297
|
return null;
|
|
298
298
|
}
|
|
299
299
|
if (code === "handshake_denied") clearPendingHandshake(ctx.pendingFile);
|
|
@@ -351,12 +351,12 @@ async function launchApproval(ctx, approvalUrl) {
|
|
|
351
351
|
if (ctx.browser.open) {
|
|
352
352
|
try {
|
|
353
353
|
await (ctx.options.openApprovalUrl ?? openUrl)(approvalUrl);
|
|
354
|
-
ctx.out.
|
|
354
|
+
ctx.out.error(`auth: asked the OS to open a browser${ctx.browser.mode === "auto" ? " (auto)" : ""} \u2014 if no tab appeared, use the URL above`);
|
|
355
355
|
} catch (err) {
|
|
356
|
-
ctx.out.
|
|
356
|
+
ctx.out.error(`auth: could not open browser (${err instanceof Error ? err.message : String(err)})`);
|
|
357
357
|
}
|
|
358
358
|
} else if (ctx.browser.reason) {
|
|
359
|
-
ctx.out.
|
|
359
|
+
ctx.out.error(`auth: browser launch skipped (${ctx.browser.reason}) \u2014 show the human the URL above`);
|
|
360
360
|
}
|
|
361
361
|
}
|
|
362
362
|
function stillPending(pending, email) {
|
|
@@ -454,7 +454,7 @@ async function scopedToken(platform, scope, options, doFetch, out) {
|
|
|
454
454
|
const cache = options.cache === false ? null : readJsonFile(tokenFile);
|
|
455
455
|
const cached = cache?.platform === audience ? cache.tokens?.[scope] : void 0;
|
|
456
456
|
if (cached?.token && (cached.expiresAt ?? 0) > Date.now() + 6e4) {
|
|
457
|
-
out.
|
|
457
|
+
out.error(`auth: using cached ${scope} grant (${tokenFile})`);
|
|
458
458
|
return cached.token;
|
|
459
459
|
}
|
|
460
460
|
const email = handshakeEmail(options.email, cache?.platform === audience ? cache.email : void 0);
|
|
@@ -485,9 +485,9 @@ async function scopedToken(platform, scope, options, doFetch, out) {
|
|
|
485
485
|
tokens[scope] = { token, expiresAt };
|
|
486
486
|
if (existsSync2(join2(rootDir, ".git"))) ensureGitignore(rootDir, [tokenFile]);
|
|
487
487
|
writePrivateJson(tokenFile, { platform: audience, email, tokens });
|
|
488
|
-
out.
|
|
488
|
+
out.error(`auth: cached ${scope} grant (${tokenFile}; mode 0600)`);
|
|
489
489
|
} else {
|
|
490
|
-
out.
|
|
490
|
+
out.error(`auth: ${scope} grant is in memory only; its credential record remains in odla-ai/db`);
|
|
491
491
|
}
|
|
492
492
|
return token;
|
|
493
493
|
}
|
|
@@ -6844,6 +6844,18 @@ function describeProblem(problem) {
|
|
|
6844
6844
|
const where = problem.validPrefix ? `after "${problem.validPrefix}"` : "as a command";
|
|
6845
6845
|
return `"${problem.word}" is not accepted ${where} \u2014 try: ${problem.accepted.join(", ")}`;
|
|
6846
6846
|
}
|
|
6847
|
+
function invocationPath(words2) {
|
|
6848
|
+
let node = COMMAND_SURFACE;
|
|
6849
|
+
const path = [];
|
|
6850
|
+
for (const word of words2) {
|
|
6851
|
+
const next = node[word];
|
|
6852
|
+
if (!next) break;
|
|
6853
|
+
path.push(word);
|
|
6854
|
+
node = next;
|
|
6855
|
+
if (Object.keys(node).length === 0) break;
|
|
6856
|
+
}
|
|
6857
|
+
return path;
|
|
6858
|
+
}
|
|
6847
6859
|
function surfacePaths(node = COMMAND_SURFACE, prefix = []) {
|
|
6848
6860
|
const paths = [];
|
|
6849
6861
|
for (const [word, child] of Object.entries(node)) {
|
|
@@ -8167,10 +8179,28 @@ async function pmCommand(parsed, deps = {}) {
|
|
|
8167
8179
|
}
|
|
8168
8180
|
}
|
|
8169
8181
|
|
|
8182
|
+
// src/record.ts
|
|
8183
|
+
import { appendFileSync } from "fs";
|
|
8184
|
+
import process9 from "process";
|
|
8185
|
+
function recordInvocation(parsed) {
|
|
8186
|
+
const file = process9.env.ODLA_CLI_RECORD;
|
|
8187
|
+
if (!file) return;
|
|
8188
|
+
try {
|
|
8189
|
+
const entry = {
|
|
8190
|
+
path: invocationPath(parsed.positionals),
|
|
8191
|
+
options: Object.keys(parsed.options).sort()
|
|
8192
|
+
};
|
|
8193
|
+
if (!entry.path.length) return;
|
|
8194
|
+
appendFileSync(file, `${JSON.stringify(entry)}
|
|
8195
|
+
`);
|
|
8196
|
+
} catch {
|
|
8197
|
+
}
|
|
8198
|
+
}
|
|
8199
|
+
|
|
8170
8200
|
// src/runbook-command.ts
|
|
8171
8201
|
import { existsSync as existsSync10 } from "fs";
|
|
8172
8202
|
import { join as join12, resolve as resolve10 } from "path";
|
|
8173
|
-
import
|
|
8203
|
+
import process11 from "process";
|
|
8174
8204
|
|
|
8175
8205
|
// src/runbook-actions.ts
|
|
8176
8206
|
import { readFileSync as readFileSync8 } from "fs";
|
|
@@ -8824,9 +8854,9 @@ import { spawnSync } from "child_process";
|
|
|
8824
8854
|
import { mkdtempSync, readFileSync as readFileSync11, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
8825
8855
|
import { tmpdir as tmpdir4 } from "os";
|
|
8826
8856
|
import { join as join11 } from "path";
|
|
8827
|
-
import
|
|
8857
|
+
import process10 from "process";
|
|
8828
8858
|
var EDITOR_ENV = ["ODLA_EDITOR", "VISUAL", "EDITOR"];
|
|
8829
|
-
function resolveEditor(env =
|
|
8859
|
+
function resolveEditor(env = process10.env) {
|
|
8830
8860
|
for (const name of EDITOR_ENV) {
|
|
8831
8861
|
const value = env[name];
|
|
8832
8862
|
if (value && value.trim()) return value.trim();
|
|
@@ -8840,8 +8870,8 @@ function defaultRun(command, path) {
|
|
|
8840
8870
|
return result.status ?? 0;
|
|
8841
8871
|
}
|
|
8842
8872
|
function editText(initial, slug, deps = {}) {
|
|
8843
|
-
const env = deps.env ??
|
|
8844
|
-
const interactive = deps.interactive ?? (() => Boolean(
|
|
8873
|
+
const env = deps.env ?? process10.env;
|
|
8874
|
+
const interactive = deps.interactive ?? (() => Boolean(process10.stdin.isTTY));
|
|
8845
8875
|
const editor = resolveEditor(env);
|
|
8846
8876
|
if (!editor)
|
|
8847
8877
|
throw new Error(
|
|
@@ -8959,10 +8989,10 @@ var CONFIG_FREE = /* @__PURE__ */ new Set(["list", "search", "ask", "get", "cat"
|
|
|
8959
8989
|
async function loadOrDefaultConfig(configPath, action, appId) {
|
|
8960
8990
|
const projectScoped = appId !== void 0;
|
|
8961
8991
|
if (!projectScoped && CONFIG_FREE.has(action) && !existsSync10(resolve10(configPath))) {
|
|
8962
|
-
const rootDir =
|
|
8992
|
+
const rootDir = process11.cwd();
|
|
8963
8993
|
return {
|
|
8964
8994
|
configPath,
|
|
8965
|
-
platformUrl:
|
|
8995
|
+
platformUrl: process11.env.ODLA_PLATFORM_URL ?? "https://odla.ai",
|
|
8966
8996
|
rootDir,
|
|
8967
8997
|
app: { id: "", name: "" },
|
|
8968
8998
|
local: { tokenFile: join12(rootDir, ".odla/dev-token.json") }
|
|
@@ -8970,13 +9000,11 @@ async function loadOrDefaultConfig(configPath, action, appId) {
|
|
|
8970
9000
|
}
|
|
8971
9001
|
return loadProjectConfig(configPath);
|
|
8972
9002
|
}
|
|
8973
|
-
var PURE_STDOUT = /* @__PURE__ */ new Set(["get", "cat"]);
|
|
8974
9003
|
async function buildContext2(parsed, deps, action) {
|
|
8975
9004
|
const configPath = stringOpt(parsed.options.config) ?? "odla.config.mjs";
|
|
8976
9005
|
const cfg = await loadOrDefaultConfig(configPath, action, stringOpt(parsed.options.app));
|
|
8977
9006
|
const doFetch = deps.fetch ?? fetch;
|
|
8978
9007
|
const out = deps.stdout ?? console;
|
|
8979
|
-
const authOut = PURE_STDOUT.has(action) ? { log: (line) => out.error(line), error: (line) => out.error(line) } : out;
|
|
8980
9008
|
const appId = stringOpt(parsed.options.app) ?? PLATFORM_SCOPE;
|
|
8981
9009
|
const dryRun = parsed.options["dry-run"] === true;
|
|
8982
9010
|
if (action === "import" && dryRun) {
|
|
@@ -8996,7 +9024,7 @@ async function buildContext2(parsed, deps, action) {
|
|
|
8996
9024
|
email: stringOpt(parsed.options.email),
|
|
8997
9025
|
label: `odla CLI (runbook ${action})`,
|
|
8998
9026
|
fetch: doFetch,
|
|
8999
|
-
stdout:
|
|
9027
|
+
stdout: out,
|
|
9000
9028
|
openApprovalUrl: deps.openUrl,
|
|
9001
9029
|
// Anchor the grant cache to this project, not the shell's cwd.
|
|
9002
9030
|
rootDir: cfg.rootDir
|
|
@@ -9013,7 +9041,7 @@ async function buildContext2(parsed, deps, action) {
|
|
|
9013
9041
|
open: void 0
|
|
9014
9042
|
},
|
|
9015
9043
|
doFetch,
|
|
9016
|
-
|
|
9044
|
+
out
|
|
9017
9045
|
);
|
|
9018
9046
|
return {
|
|
9019
9047
|
platformUrl: cfg.platformUrl,
|
|
@@ -9556,6 +9584,7 @@ function exitCodeFor(err) {
|
|
|
9556
9584
|
}
|
|
9557
9585
|
async function runCli(argv = process.argv.slice(2), dependencies = {}) {
|
|
9558
9586
|
const parsed = parseArgv(argv);
|
|
9587
|
+
recordInvocation(parsed);
|
|
9559
9588
|
const command = parsed.positionals[0] ?? "help";
|
|
9560
9589
|
if (command === "version" || command === "-v" || parsed.options.version === true) {
|
|
9561
9590
|
assertArgs(parsed, ["version"], 1);
|
|
@@ -9704,6 +9733,7 @@ export {
|
|
|
9704
9733
|
acceptedAfter,
|
|
9705
9734
|
validateInvocation,
|
|
9706
9735
|
describeProblem,
|
|
9736
|
+
invocationPath,
|
|
9707
9737
|
surfacePaths,
|
|
9708
9738
|
runHostedSecurity,
|
|
9709
9739
|
getHostedSecurityIntent,
|
|
@@ -9717,4 +9747,4 @@ export {
|
|
|
9717
9747
|
exitCodeFor,
|
|
9718
9748
|
runCli
|
|
9719
9749
|
};
|
|
9720
|
-
//# sourceMappingURL=chunk-
|
|
9750
|
+
//# sourceMappingURL=chunk-DINDRUDA.js.map
|