@odla-ai/cli 0.43.1 → 0.44.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 +263 -249
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-T4OPSRME.js → chunk-7MUWCSGP.js} +251 -260
- package/dist/chunk-7MUWCSGP.js.map +1 -0
- package/dist/{cli-3JOB4OUV.js → cli-ZQBZT6YF.js} +2 -2
- package/dist/index.cjs +244 -253
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-T4OPSRME.js.map +0 -1
- /package/dist/{cli-3JOB4OUV.js.map → cli-ZQBZT6YF.js.map} +0 -0
|
@@ -1147,10 +1147,17 @@ function parseArgv(argv) {
|
|
|
1147
1147
|
function assertArgs(parsed, allowedOptions2, maxPositionals) {
|
|
1148
1148
|
const allowed = new Set(allowedOptions2);
|
|
1149
1149
|
for (const name of Object.keys(parsed.options)) {
|
|
1150
|
-
if (
|
|
1150
|
+
if (allowed.has(name)) continue;
|
|
1151
|
+
const accepts = [...allowed].sort().map((option) => `--${option}`).join(" ");
|
|
1152
|
+
throw new Error(
|
|
1153
|
+
`unknown option "--${name}"` + (accepts ? ` \u2014 this command accepts: ${accepts}` : " \u2014 this command takes no options")
|
|
1154
|
+
);
|
|
1151
1155
|
}
|
|
1152
1156
|
if (parsed.positionals.length > maxPositionals) {
|
|
1153
|
-
|
|
1157
|
+
const taken = parsed.positionals.slice(0, maxPositionals).join(" ");
|
|
1158
|
+
throw new Error(
|
|
1159
|
+
`unexpected argument "${parsed.positionals[maxPositionals]}" \u2014 ` + (maxPositionals ? `"odla-ai ${taken}" takes no further arguments` : "this command takes no arguments")
|
|
1160
|
+
);
|
|
1154
1161
|
}
|
|
1155
1162
|
}
|
|
1156
1163
|
function requiredString(value2, name) {
|
|
@@ -1188,6 +1195,198 @@ function addOption(options, name, value2) {
|
|
|
1188
1195
|
else options[name] = [String(current), String(value2)];
|
|
1189
1196
|
}
|
|
1190
1197
|
|
|
1198
|
+
// src/surface.ts
|
|
1199
|
+
var PM_ACTIONS = {
|
|
1200
|
+
list: {},
|
|
1201
|
+
add: {},
|
|
1202
|
+
create: {},
|
|
1203
|
+
get: {},
|
|
1204
|
+
set: {},
|
|
1205
|
+
update: {},
|
|
1206
|
+
status: {},
|
|
1207
|
+
move: {},
|
|
1208
|
+
done: {},
|
|
1209
|
+
comment: {},
|
|
1210
|
+
comments: {},
|
|
1211
|
+
history: {},
|
|
1212
|
+
link: {},
|
|
1213
|
+
ref: {},
|
|
1214
|
+
rm: {},
|
|
1215
|
+
delete: {}
|
|
1216
|
+
};
|
|
1217
|
+
var PM_TASK_ACTIONS = {
|
|
1218
|
+
...PM_ACTIONS,
|
|
1219
|
+
ready: {},
|
|
1220
|
+
claim: {},
|
|
1221
|
+
release: {}
|
|
1222
|
+
};
|
|
1223
|
+
var PM_ENTITIES = {
|
|
1224
|
+
...Object.fromEntries(
|
|
1225
|
+
["goal", "conformance", "decision", "bug"].map((entity) => [entity, PM_ACTIONS])
|
|
1226
|
+
),
|
|
1227
|
+
task: PM_TASK_ACTIONS,
|
|
1228
|
+
kanban: PM_TASK_ACTIONS
|
|
1229
|
+
};
|
|
1230
|
+
var COMMAND_SURFACE = {
|
|
1231
|
+
agent: { jobs: {}, retry: {} },
|
|
1232
|
+
ai: { models: {} },
|
|
1233
|
+
admin: {
|
|
1234
|
+
ai: {
|
|
1235
|
+
show: {},
|
|
1236
|
+
set: {},
|
|
1237
|
+
credentials: {},
|
|
1238
|
+
models: {},
|
|
1239
|
+
usage: {},
|
|
1240
|
+
audit: {},
|
|
1241
|
+
credential: { set: {} }
|
|
1242
|
+
},
|
|
1243
|
+
spend: { show: {}, reset: {} }
|
|
1244
|
+
},
|
|
1245
|
+
app: {
|
|
1246
|
+
archive: {},
|
|
1247
|
+
restore: {},
|
|
1248
|
+
export: {},
|
|
1249
|
+
import: {},
|
|
1250
|
+
rename: {},
|
|
1251
|
+
"refresh-sandbox": {},
|
|
1252
|
+
"go-live": {},
|
|
1253
|
+
promote: {},
|
|
1254
|
+
owners: { list: {}, add: {}, remove: {} }
|
|
1255
|
+
},
|
|
1256
|
+
auth: { login: {} },
|
|
1257
|
+
brand: { design: { unpack: {} } },
|
|
1258
|
+
bug: { create: {}, list: {}, report: {} },
|
|
1259
|
+
calendar: { status: {}, calendars: {}, connect: {}, disconnect: {} },
|
|
1260
|
+
capabilities: {},
|
|
1261
|
+
code: {
|
|
1262
|
+
connect: {},
|
|
1263
|
+
grant: { request: {}, list: {}, approve: {}, revoke: {} },
|
|
1264
|
+
repository: { show: {}, list: {}, bind: {} }
|
|
1265
|
+
},
|
|
1266
|
+
config: { diff: {}, plan: {}, apply: {} },
|
|
1267
|
+
context: { show: {}, list: {}, save: {}, remove: {} },
|
|
1268
|
+
credentials: { list: {}, revoke: {} },
|
|
1269
|
+
device: { enroll: {}, list: {}, revoke: {} },
|
|
1270
|
+
// `watch`, `read`, `reply`, and `resolve` take a topic id from there on.
|
|
1271
|
+
discuss: {
|
|
1272
|
+
groups: {},
|
|
1273
|
+
list: {},
|
|
1274
|
+
topics: {},
|
|
1275
|
+
read: {},
|
|
1276
|
+
post: {},
|
|
1277
|
+
reply: {},
|
|
1278
|
+
resolve: {},
|
|
1279
|
+
who: {},
|
|
1280
|
+
watch: {}
|
|
1281
|
+
},
|
|
1282
|
+
doctor: {},
|
|
1283
|
+
help: {},
|
|
1284
|
+
init: {},
|
|
1285
|
+
monitor: { plan: {}, apply: {}, run: {}, status: {}, incidents: {}, report: {} },
|
|
1286
|
+
o11y: { status: {} },
|
|
1287
|
+
operations: { get: {}, wait: {} },
|
|
1288
|
+
platform: {
|
|
1289
|
+
status: {}
|
|
1290
|
+
},
|
|
1291
|
+
pm: {
|
|
1292
|
+
...PM_ENTITIES,
|
|
1293
|
+
project: { list: {}, add: {}, create: {}, use: {} },
|
|
1294
|
+
handoff: {},
|
|
1295
|
+
next: {},
|
|
1296
|
+
start: {},
|
|
1297
|
+
watch: {}
|
|
1298
|
+
},
|
|
1299
|
+
provision: {},
|
|
1300
|
+
runbook: {
|
|
1301
|
+
ask: {},
|
|
1302
|
+
search: {},
|
|
1303
|
+
impact: {},
|
|
1304
|
+
list: {},
|
|
1305
|
+
get: {},
|
|
1306
|
+
cat: {},
|
|
1307
|
+
new: {},
|
|
1308
|
+
edit: {},
|
|
1309
|
+
comment: {},
|
|
1310
|
+
import: {},
|
|
1311
|
+
visibility: {},
|
|
1312
|
+
publish: {},
|
|
1313
|
+
archive: {},
|
|
1314
|
+
history: {},
|
|
1315
|
+
revert: {},
|
|
1316
|
+
rm: {},
|
|
1317
|
+
lint: {}
|
|
1318
|
+
},
|
|
1319
|
+
secrets: { push: {}, status: {}, set: {}, "set-clerk-key": {} },
|
|
1320
|
+
security: {
|
|
1321
|
+
plan: {},
|
|
1322
|
+
sources: {},
|
|
1323
|
+
run: {},
|
|
1324
|
+
status: {},
|
|
1325
|
+
report: {},
|
|
1326
|
+
github: { connect: {}, disconnect: {} }
|
|
1327
|
+
},
|
|
1328
|
+
setup: {},
|
|
1329
|
+
skill: { install: {} },
|
|
1330
|
+
smoke: {},
|
|
1331
|
+
version: {},
|
|
1332
|
+
whoami: {}
|
|
1333
|
+
};
|
|
1334
|
+
function acceptedAfter(path) {
|
|
1335
|
+
let node = COMMAND_SURFACE;
|
|
1336
|
+
for (const word of path) {
|
|
1337
|
+
node = node?.[word];
|
|
1338
|
+
if (!node) return [];
|
|
1339
|
+
}
|
|
1340
|
+
return Object.keys(node).sort();
|
|
1341
|
+
}
|
|
1342
|
+
function validateInvocation(words2) {
|
|
1343
|
+
let node = COMMAND_SURFACE;
|
|
1344
|
+
const walked = [];
|
|
1345
|
+
for (const word of words2) {
|
|
1346
|
+
if (Object.keys(node).length === 0) return null;
|
|
1347
|
+
const next = node[word];
|
|
1348
|
+
if (!next) return { validPrefix: walked.join(" "), word, accepted: Object.keys(node).sort() };
|
|
1349
|
+
walked.push(word);
|
|
1350
|
+
node = next;
|
|
1351
|
+
}
|
|
1352
|
+
return null;
|
|
1353
|
+
}
|
|
1354
|
+
function describeProblem(problem) {
|
|
1355
|
+
const where = problem.validPrefix ? `after "${problem.validPrefix}"` : "as a command";
|
|
1356
|
+
if (!problem.accepted.length) return `"${problem.word}" is not accepted ${where}. Run "odla-ai help"`;
|
|
1357
|
+
if (!problem.word) return `"odla-ai ${problem.validPrefix}" needs one of: ${problem.accepted.join(", ")}`;
|
|
1358
|
+
return `"${problem.word}" is not accepted ${where} \u2014 try: ${problem.accepted.join(", ")}`;
|
|
1359
|
+
}
|
|
1360
|
+
function rejectWord(path, word, note) {
|
|
1361
|
+
const sentence = describeProblem({
|
|
1362
|
+
validPrefix: path.join(" "),
|
|
1363
|
+
word: word ?? "",
|
|
1364
|
+
accepted: acceptedAfter(path)
|
|
1365
|
+
});
|
|
1366
|
+
throw new Error(note ? `${sentence}. ${note}` : sentence);
|
|
1367
|
+
}
|
|
1368
|
+
function invocationPath(words2) {
|
|
1369
|
+
let node = COMMAND_SURFACE;
|
|
1370
|
+
const path = [];
|
|
1371
|
+
for (const word of words2) {
|
|
1372
|
+
const next = node[word];
|
|
1373
|
+
if (!next) break;
|
|
1374
|
+
path.push(word);
|
|
1375
|
+
node = next;
|
|
1376
|
+
if (Object.keys(node).length === 0) break;
|
|
1377
|
+
}
|
|
1378
|
+
return path;
|
|
1379
|
+
}
|
|
1380
|
+
function surfacePaths(node = COMMAND_SURFACE, prefix = []) {
|
|
1381
|
+
const paths2 = [];
|
|
1382
|
+
for (const [word, child] of Object.entries(node)) {
|
|
1383
|
+
const path = [...prefix, word];
|
|
1384
|
+
paths2.push(path);
|
|
1385
|
+
paths2.push(...surfacePaths(child, path));
|
|
1386
|
+
}
|
|
1387
|
+
return paths2;
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1191
1390
|
// src/admin-spend.ts
|
|
1192
1391
|
async function call(ctx, method, scope) {
|
|
1193
1392
|
const url = `${ctx.platformUrl.replace(/\/$/, "")}/registry/platform/spend?scope=${encodeURIComponent(scope)}`;
|
|
@@ -1237,9 +1436,7 @@ async function spendReset(ctx, scope) {
|
|
|
1237
1436
|
async function adminSpend(parsed, ctx) {
|
|
1238
1437
|
const action2 = parsed.positionals[2];
|
|
1239
1438
|
const scope = parsed.positionals[3] ?? stringOpt(parsed.options.scope);
|
|
1240
|
-
if (action2 !== "show" && action2 !== "reset")
|
|
1241
|
-
throw new Error('unknown spend command. Try "odla-ai admin spend show <scope>".');
|
|
1242
|
-
}
|
|
1439
|
+
if (action2 !== "show" && action2 !== "reset") rejectWord(["admin", "spend"], action2);
|
|
1243
1440
|
if (!scope) {
|
|
1244
1441
|
throw new Error(
|
|
1245
1442
|
`"admin spend ${action2}" needs a scope, e.g. odla-ai admin spend ${action2} app:my-app:<incarnation>`
|
|
@@ -2038,6 +2235,11 @@ var SET_OPTIONS = [
|
|
|
2038
2235
|
async function adminCommand(parsed, deps = {}) {
|
|
2039
2236
|
const area = parsed.positionals[1];
|
|
2040
2237
|
const action2 = parsed.positionals[2];
|
|
2238
|
+
if (area !== "ai" && area !== "spend") rejectWord(["admin"], area);
|
|
2239
|
+
if (!acceptedAfter(["admin", area]).includes(action2 ?? "")) rejectWord(["admin", area], action2);
|
|
2240
|
+
if (action2 === "credential" && !acceptedAfter(["admin", "ai", "credential"]).includes(parsed.positionals[3] ?? "")) {
|
|
2241
|
+
rejectWord(["admin", "ai", "credential"], parsed.positionals[3]);
|
|
2242
|
+
}
|
|
2041
2243
|
if (area === "spend") {
|
|
2042
2244
|
assertArgs(parsed, JSON_OPTIONS, 4);
|
|
2043
2245
|
const context2 = await resolveOperatorContext(parsed, { allowMissingConfig: true });
|
|
@@ -2063,14 +2265,11 @@ async function adminCommand(parsed, deps = {}) {
|
|
|
2063
2265
|
out
|
|
2064
2266
|
});
|
|
2065
2267
|
}
|
|
2066
|
-
const credentialSet = action2 === "credential"
|
|
2268
|
+
const credentialSet = action2 === "credential";
|
|
2067
2269
|
const credentials = action2 === "credentials";
|
|
2068
2270
|
const models = action2 === "models";
|
|
2069
2271
|
const usage = action2 === "usage";
|
|
2070
2272
|
const audit = action2 === "audit";
|
|
2071
|
-
if (area !== "ai" || action2 !== "show" && action2 !== "set" && !credentialSet && !credentials && !models && !usage && !audit) {
|
|
2072
|
-
throw new Error('unknown admin command. Try "odla-ai admin ai show".');
|
|
2073
|
-
}
|
|
2074
2273
|
const allowed = credentialSet ? [...CONTEXT_OPTIONS, "from-env", "stdin"] : action2 === "set" ? SET_OPTIONS : models ? [...JSON_OPTIONS, "provider"] : usage ? [...JSON_OPTIONS, "app-id", "env", "run-id", "limit"] : audit ? [...JSON_OPTIONS, "limit"] : JSON_OPTIONS;
|
|
2075
2274
|
assertArgs(parsed, allowed, credentialSet ? 5 : action2 === "set" ? 4 : 3);
|
|
2076
2275
|
const context = await resolveOperatorContext(parsed, { allowMissingConfig: true });
|
|
@@ -2284,9 +2483,7 @@ async function authCommand(parsed, deps = {}) {
|
|
|
2284
2483
|
"json"
|
|
2285
2484
|
], 2);
|
|
2286
2485
|
const action2 = parsed.positionals[1] ?? "login";
|
|
2287
|
-
if (action2 !== "login")
|
|
2288
|
-
throw new Error(`unknown auth action "${action2}". Try "odla-ai auth login --app <id> --email <odla-account>".`);
|
|
2289
|
-
}
|
|
2486
|
+
if (action2 !== "login") rejectWord(["auth"], action2);
|
|
2290
2487
|
const context = await resolveOperatorContext(parsed, {
|
|
2291
2488
|
allowMissingConfig: true,
|
|
2292
2489
|
requireApp: true
|
|
@@ -2359,9 +2556,7 @@ function bothTenants(cfg) {
|
|
|
2359
2556
|
// src/agent-command.ts
|
|
2360
2557
|
async function agentCommand(parsed, deps = {}) {
|
|
2361
2558
|
const action2 = parsed.positionals[1];
|
|
2362
|
-
if (action2 !== "jobs" && action2 !== "retry")
|
|
2363
|
-
throw new Error(`unknown agent action "${action2 ?? ""}". Try "odla-ai agent jobs --json".`);
|
|
2364
|
-
}
|
|
2559
|
+
if (action2 !== "jobs" && action2 !== "retry") rejectWord(["agent"], action2);
|
|
2365
2560
|
assertArgs(parsed, ["config", "env", "state", "limit", "json", "token"], action2 === "jobs" ? 2 : 3);
|
|
2366
2561
|
if (action2 === "retry" && (parsed.options.state !== void 0 || parsed.options.limit !== void 0)) {
|
|
2367
2562
|
throw new Error('--state and --limit are supported only by "agent jobs"');
|
|
@@ -2536,9 +2731,7 @@ async function appOwnersCommand(parsed, dependencies = {}) {
|
|
|
2536
2731
|
await (sub === "add" ? ownersAdd(email, options) : ownersRemove(email, options));
|
|
2537
2732
|
return;
|
|
2538
2733
|
}
|
|
2539
|
-
|
|
2540
|
-
`unknown app owners subcommand "${sub}". Try "odla-ai app owners list", "odla-ai app owners add <email>", or "odla-ai app owners remove <email>".`
|
|
2541
|
-
);
|
|
2734
|
+
rejectWord(["app", "owners"], sub);
|
|
2542
2735
|
}
|
|
2543
2736
|
|
|
2544
2737
|
// src/app-rename.ts
|
|
@@ -2644,8 +2837,10 @@ async function appCommand(parsed, dependencies = {}) {
|
|
|
2644
2837
|
return;
|
|
2645
2838
|
}
|
|
2646
2839
|
if (sub !== "archive" && sub !== "restore") {
|
|
2647
|
-
|
|
2648
|
-
|
|
2840
|
+
rejectWord(
|
|
2841
|
+
["app"],
|
|
2842
|
+
sub,
|
|
2843
|
+
"Permanent deletion has no CLI: it requires a signed-in owner in Studio."
|
|
2649
2844
|
);
|
|
2650
2845
|
}
|
|
2651
2846
|
assertArgs(parsed, ["config", "token", "email", "yes", "json"], 2);
|
|
@@ -2811,7 +3006,8 @@ async function brandCommand(parsed, deps) {
|
|
|
2811
3006
|
await designUnpack(parsed, deps);
|
|
2812
3007
|
return;
|
|
2813
3008
|
}
|
|
2814
|
-
|
|
3009
|
+
if (subject !== "design") rejectWord(["brand"], subject);
|
|
3010
|
+
rejectWord(["brand", "design"], action2, USAGE);
|
|
2815
3011
|
}
|
|
2816
3012
|
|
|
2817
3013
|
// src/calendar-errors.ts
|
|
@@ -5620,9 +5816,7 @@ async function secretsCommand(parsed, deps) {
|
|
|
5620
5816
|
return;
|
|
5621
5817
|
}
|
|
5622
5818
|
if (sub !== "push") {
|
|
5623
|
-
|
|
5624
|
-
`unknown secrets subcommand "${sub ?? ""}". Try "odla-ai secrets push --env dev", "odla-ai secrets status --env dev", "odla-ai secrets set <name> --env dev --stdin", or "odla-ai secrets set-clerk-key --env dev --stdin".`
|
|
5625
|
-
);
|
|
5819
|
+
rejectWord(["secrets"], sub);
|
|
5626
5820
|
}
|
|
5627
5821
|
assertArgs(parsed, ["config", "env", "dry-run", "yes"], 2);
|
|
5628
5822
|
await secretsPush({
|
|
@@ -5635,7 +5829,7 @@ async function secretsCommand(parsed, deps) {
|
|
|
5635
5829
|
async function projectCommand(command, parsed, deps) {
|
|
5636
5830
|
if (command === "ai") {
|
|
5637
5831
|
const sub = parsed.positionals[1];
|
|
5638
|
-
if (sub !== "models")
|
|
5832
|
+
if (sub !== "models") rejectWord(["ai"], sub);
|
|
5639
5833
|
assertArgs(parsed, ["config", "env", "provider", "json"], 2);
|
|
5640
5834
|
await aiModels({
|
|
5641
5835
|
configPath: stringOpt(parsed.options.config) ?? "odla.config.mjs",
|
|
@@ -5649,9 +5843,7 @@ async function projectCommand(command, parsed, deps) {
|
|
|
5649
5843
|
}
|
|
5650
5844
|
if (command === "config") {
|
|
5651
5845
|
const sub = parsed.positionals[1];
|
|
5652
|
-
if (sub !== "diff" && sub !== "plan" && sub !== "apply")
|
|
5653
|
-
throw new Error(`unknown config subcommand "${sub ?? ""}". Try "odla-ai config diff --json".`);
|
|
5654
|
-
}
|
|
5846
|
+
if (sub !== "diff" && sub !== "plan" && sub !== "apply") rejectWord(["config"], sub);
|
|
5655
5847
|
assertArgs(
|
|
5656
5848
|
parsed,
|
|
5657
5849
|
sub === "apply" ? ["config", "plan", "idempotency-key", "token", "email", "open", "json"] : ["config", "token", "email", "open", "json"],
|
|
@@ -5679,7 +5871,7 @@ async function projectCommand(command, parsed, deps) {
|
|
|
5679
5871
|
if (command === "operations") {
|
|
5680
5872
|
const sub = parsed.positionals[1];
|
|
5681
5873
|
if (sub !== "get" && sub !== "wait") {
|
|
5682
|
-
|
|
5874
|
+
rejectWord(["operations"], sub);
|
|
5683
5875
|
}
|
|
5684
5876
|
assertArgs(
|
|
5685
5877
|
parsed,
|
|
@@ -5753,7 +5945,7 @@ async function projectCommand(command, parsed, deps) {
|
|
|
5753
5945
|
}
|
|
5754
5946
|
if (command === "skill") {
|
|
5755
5947
|
const sub = parsed.positionals[1];
|
|
5756
|
-
if (sub !== "install")
|
|
5948
|
+
if (sub !== "install") rejectWord(["skill"], sub);
|
|
5757
5949
|
install(parsed, 2, deps);
|
|
5758
5950
|
return true;
|
|
5759
5951
|
}
|
|
@@ -10314,9 +10506,7 @@ function grantsUrl(cfg, suffix = "") {
|
|
|
10314
10506
|
async function codeGrantCommand(parsed, deps = {}) {
|
|
10315
10507
|
const action2 = parsed.positionals[2];
|
|
10316
10508
|
if (!isAction(action2)) {
|
|
10317
|
-
|
|
10318
|
-
`unknown code grant action "${action2 ?? ""}". Try "odla-ai code grant list --env dev".`
|
|
10319
|
-
);
|
|
10509
|
+
rejectWord(["code", "grant"], action2);
|
|
10320
10510
|
}
|
|
10321
10511
|
const decides = action2 === "approve" || action2 === "revoke";
|
|
10322
10512
|
assertArgs(parsed, ["config", "env", "json", "token", "email", "open"], decides ? 4 : 3);
|
|
@@ -10436,9 +10626,7 @@ function repositoryUrl(cfg, suffix = "") {
|
|
|
10436
10626
|
async function codeRepositoryCommand(parsed, deps = {}) {
|
|
10437
10627
|
const action2 = parsed.positionals[2];
|
|
10438
10628
|
if (!isAction2(action2)) {
|
|
10439
|
-
|
|
10440
|
-
`unknown code repository action "${action2 ?? ""}". Try "odla-ai code repository show --env dev".`
|
|
10441
|
-
);
|
|
10629
|
+
rejectWord(["code", "repository"], action2);
|
|
10442
10630
|
}
|
|
10443
10631
|
assertArgs(parsed, ["config", "env", "repo", "json", "token", "email", "open"], 3);
|
|
10444
10632
|
const cfg = await loadProjectConfig(stringOpt(parsed.options.config) ?? "odla.config.mjs");
|
|
@@ -10513,9 +10701,7 @@ async function codeCommand(parsed, dependencies) {
|
|
|
10513
10701
|
});
|
|
10514
10702
|
}
|
|
10515
10703
|
if (sub !== "connect") {
|
|
10516
|
-
|
|
10517
|
-
`unknown code subcommand "${sub ?? ""}". Try "odla-ai code connect --env dev" or "odla-ai code grant list --env dev".`
|
|
10518
|
-
);
|
|
10704
|
+
rejectWord(["code"], sub);
|
|
10519
10705
|
}
|
|
10520
10706
|
assertArgs(parsed, [
|
|
10521
10707
|
"config",
|
|
@@ -10652,9 +10838,7 @@ async function contextCommand(parsed, deps = {}) {
|
|
|
10652
10838
|
return;
|
|
10653
10839
|
}
|
|
10654
10840
|
if (action2 !== "show") {
|
|
10655
|
-
|
|
10656
|
-
`unknown context action "${action2 ?? ""}". Try show|list|save|remove.`
|
|
10657
|
-
);
|
|
10841
|
+
rejectWord(["context"], action2);
|
|
10658
10842
|
}
|
|
10659
10843
|
const context = await resolveOperatorContext(parsed, {
|
|
10660
10844
|
allowMissingConfig: true,
|
|
@@ -10710,9 +10894,7 @@ async function responseError(response2) {
|
|
|
10710
10894
|
}
|
|
10711
10895
|
async function credentialCommand(parsed, deps = {}) {
|
|
10712
10896
|
const action2 = parsed.positionals[1] ?? "list";
|
|
10713
|
-
if (action2 !== "list" && action2 !== "revoke")
|
|
10714
|
-
throw new Error(`unknown credentials action "${action2}". Try "odla-ai credentials list".`);
|
|
10715
|
-
}
|
|
10897
|
+
if (action2 !== "list" && action2 !== "revoke") rejectWord(["credentials"], action2);
|
|
10716
10898
|
assertArgs(parsed, ["config", "env", "all", "json", "token", "email", "open"], action2 === "revoke" ? 3 : 2);
|
|
10717
10899
|
const cfg = await loadProjectConfig(stringOpt(parsed.options.config) ?? "odla.config.mjs");
|
|
10718
10900
|
const doFetch = deps.fetch ?? fetch;
|
|
@@ -11714,7 +11896,7 @@ async function discussCommand(parsed, deps = {}) {
|
|
|
11714
11896
|
assertArgs(parsed, ALLOWED, 3);
|
|
11715
11897
|
const action2 = parsed.positionals[1];
|
|
11716
11898
|
const id2 = parsed.positionals[2];
|
|
11717
|
-
if (!
|
|
11899
|
+
if (!acceptedAfter(["discuss"]).includes(action2 ?? "")) rejectWord(["discuss"], action2);
|
|
11718
11900
|
const ctx = await buildContext(parsed, deps);
|
|
11719
11901
|
switch (action2) {
|
|
11720
11902
|
case "groups":
|
|
@@ -11738,7 +11920,7 @@ async function discussCommand(parsed, deps = {}) {
|
|
|
11738
11920
|
return;
|
|
11739
11921
|
}
|
|
11740
11922
|
default:
|
|
11741
|
-
|
|
11923
|
+
rejectWord(["discuss"], action2);
|
|
11742
11924
|
}
|
|
11743
11925
|
}
|
|
11744
11926
|
|
|
@@ -12648,7 +12830,7 @@ async function pmCommand(parsed, deps = {}) {
|
|
|
12648
12830
|
assertArgs(parsed, COMMON_OPTIONS, 4);
|
|
12649
12831
|
return pmProjectUse(await buildContext2(parsed, deps), requireId2(parsed.positionals[3], action3));
|
|
12650
12832
|
}
|
|
12651
|
-
|
|
12833
|
+
rejectWord(["pm", "project"], action3);
|
|
12652
12834
|
}
|
|
12653
12835
|
if (word === "next") {
|
|
12654
12836
|
assertArgs(parsed, [...COMMON_OPTIONS, "app", "project", "verbose"], 2);
|
|
@@ -12679,10 +12861,10 @@ async function pmCommand(parsed, deps = {}) {
|
|
|
12679
12861
|
return pmHandoff(await buildContext2(parsed, deps), parsed);
|
|
12680
12862
|
}
|
|
12681
12863
|
const entity = ALIASES[word];
|
|
12682
|
-
if (!entity)
|
|
12864
|
+
if (!entity) rejectWord(["pm"], word);
|
|
12683
12865
|
const requestedAction = parsed.positionals[2] ?? "list";
|
|
12684
12866
|
const action2 = canonicalAction(requestedAction);
|
|
12685
|
-
if (!action2)
|
|
12867
|
+
if (!action2) rejectWord(["pm", word], requestedAction);
|
|
12686
12868
|
assertArgs(parsed, allowedOptions(entity, action2), 4);
|
|
12687
12869
|
if ((action2 === "ready" || action2 === "claim" || action2 === "release") && entity !== "task") {
|
|
12688
12870
|
throw new Error(`pm ${action2} is only valid for tasks`);
|
|
@@ -12768,12 +12950,7 @@ async function platformCommand(parsed, deps = {}) {
|
|
|
12768
12950
|
if (action2 === "status") {
|
|
12769
12951
|
return platformStatus(parsed, deps);
|
|
12770
12952
|
}
|
|
12771
|
-
|
|
12772
|
-
`unknown platform action "${[
|
|
12773
|
-
action2,
|
|
12774
|
-
parsed.positionals[2]
|
|
12775
|
-
].filter(Boolean).join(" ")}". Try "odla-ai platform status --json".`
|
|
12776
|
-
);
|
|
12953
|
+
rejectWord(["platform"], action2);
|
|
12777
12954
|
}
|
|
12778
12955
|
async function platformStatus(parsed, deps) {
|
|
12779
12956
|
assertArgs(
|
|
@@ -13110,9 +13287,7 @@ async function o11yCommand(parsed, deps = {}) {
|
|
|
13110
13287
|
);
|
|
13111
13288
|
const action2 = parsed.positionals[1];
|
|
13112
13289
|
if (action2 !== "status") {
|
|
13113
|
-
|
|
13114
|
-
`unknown o11y action "${action2 ?? ""}". Try "odla-ai o11y status --json".`
|
|
13115
|
-
);
|
|
13290
|
+
rejectWord(["o11y"], action2);
|
|
13116
13291
|
}
|
|
13117
13292
|
const minutes = statusMinutes(
|
|
13118
13293
|
numberOpt(parsed.options.minutes, "--minutes") ?? 60
|
|
@@ -13365,9 +13540,7 @@ var OPTIONS = [
|
|
|
13365
13540
|
async function monitorCommand(parsed, deps = {}) {
|
|
13366
13541
|
assertArgs(parsed, OPTIONS, 3);
|
|
13367
13542
|
const action2 = parsed.positionals[1] ?? "status";
|
|
13368
|
-
if (!["
|
|
13369
|
-
throw new Error(`unknown monitor action "${action2}". Try "odla-ai monitor status --json".`);
|
|
13370
|
-
}
|
|
13543
|
+
if (!acceptedAfter(["monitor"]).includes(action2)) rejectWord(["monitor"], action2);
|
|
13371
13544
|
const context = await resolveOperatorContext(parsed, {
|
|
13372
13545
|
allowMissingConfig: action2 !== "plan" && action2 !== "apply",
|
|
13373
13546
|
requireApp: true
|
|
@@ -13997,187 +14170,6 @@ async function provision(options) {
|
|
|
13997
14170
|
// src/record.ts
|
|
13998
14171
|
import { appendFileSync } from "fs";
|
|
13999
14172
|
import process19 from "process";
|
|
14000
|
-
|
|
14001
|
-
// src/surface.ts
|
|
14002
|
-
var PM_ACTIONS = {
|
|
14003
|
-
list: {},
|
|
14004
|
-
add: {},
|
|
14005
|
-
create: {},
|
|
14006
|
-
get: {},
|
|
14007
|
-
set: {},
|
|
14008
|
-
update: {},
|
|
14009
|
-
status: {},
|
|
14010
|
-
move: {},
|
|
14011
|
-
done: {},
|
|
14012
|
-
comment: {},
|
|
14013
|
-
comments: {},
|
|
14014
|
-
ref: {},
|
|
14015
|
-
rm: {},
|
|
14016
|
-
delete: {}
|
|
14017
|
-
};
|
|
14018
|
-
var PM_TASK_ACTIONS = {
|
|
14019
|
-
...PM_ACTIONS,
|
|
14020
|
-
ready: {},
|
|
14021
|
-
claim: {},
|
|
14022
|
-
release: {}
|
|
14023
|
-
};
|
|
14024
|
-
var PM_ENTITIES = {
|
|
14025
|
-
...Object.fromEntries(
|
|
14026
|
-
["goal", "conformance", "decision", "bug"].map((entity) => [entity, PM_ACTIONS])
|
|
14027
|
-
),
|
|
14028
|
-
task: PM_TASK_ACTIONS,
|
|
14029
|
-
kanban: PM_TASK_ACTIONS
|
|
14030
|
-
};
|
|
14031
|
-
var COMMAND_SURFACE = {
|
|
14032
|
-
agent: { jobs: {}, retry: {} },
|
|
14033
|
-
ai: { models: {} },
|
|
14034
|
-
admin: {
|
|
14035
|
-
ai: {
|
|
14036
|
-
show: {},
|
|
14037
|
-
set: {},
|
|
14038
|
-
credentials: {},
|
|
14039
|
-
models: {},
|
|
14040
|
-
usage: {},
|
|
14041
|
-
audit: {},
|
|
14042
|
-
credential: { set: {} }
|
|
14043
|
-
}
|
|
14044
|
-
},
|
|
14045
|
-
app: {
|
|
14046
|
-
archive: {},
|
|
14047
|
-
restore: {},
|
|
14048
|
-
export: {},
|
|
14049
|
-
import: {},
|
|
14050
|
-
rename: {},
|
|
14051
|
-
"refresh-sandbox": {},
|
|
14052
|
-
"go-live": {},
|
|
14053
|
-
promote: {},
|
|
14054
|
-
owners: { list: {}, add: {}, remove: {} }
|
|
14055
|
-
},
|
|
14056
|
-
auth: { login: {} },
|
|
14057
|
-
brand: { design: { unpack: {} } },
|
|
14058
|
-
bug: { create: {}, list: {}, report: {} },
|
|
14059
|
-
calendar: { status: {}, calendars: {}, connect: {}, disconnect: {} },
|
|
14060
|
-
capabilities: {},
|
|
14061
|
-
code: {
|
|
14062
|
-
connect: {},
|
|
14063
|
-
grant: { request: {}, list: {}, approve: {}, revoke: {} },
|
|
14064
|
-
repository: { show: {}, list: {}, bind: {} }
|
|
14065
|
-
},
|
|
14066
|
-
config: { diff: {}, plan: {}, apply: {} },
|
|
14067
|
-
context: { show: {}, list: {}, save: {}, remove: {} },
|
|
14068
|
-
credentials: { list: {}, revoke: {} },
|
|
14069
|
-
device: { enroll: {}, list: {}, revoke: {} },
|
|
14070
|
-
// `watch`, `read`, `reply`, and `resolve` take a topic id from there on.
|
|
14071
|
-
discuss: {
|
|
14072
|
-
groups: {},
|
|
14073
|
-
list: {},
|
|
14074
|
-
topics: {},
|
|
14075
|
-
read: {},
|
|
14076
|
-
post: {},
|
|
14077
|
-
reply: {},
|
|
14078
|
-
resolve: {},
|
|
14079
|
-
who: {},
|
|
14080
|
-
watch: {}
|
|
14081
|
-
},
|
|
14082
|
-
doctor: {},
|
|
14083
|
-
help: {},
|
|
14084
|
-
init: {},
|
|
14085
|
-
monitor: { plan: {}, apply: {}, run: {}, status: {}, incidents: {}, report: {} },
|
|
14086
|
-
o11y: { status: {} },
|
|
14087
|
-
operations: { get: {}, wait: {} },
|
|
14088
|
-
platform: {
|
|
14089
|
-
status: {}
|
|
14090
|
-
},
|
|
14091
|
-
pm: {
|
|
14092
|
-
...PM_ENTITIES,
|
|
14093
|
-
project: { list: {}, add: {}, create: {}, use: {} },
|
|
14094
|
-
handoff: {},
|
|
14095
|
-
next: {},
|
|
14096
|
-
start: {},
|
|
14097
|
-
watch: {}
|
|
14098
|
-
},
|
|
14099
|
-
provision: {},
|
|
14100
|
-
runbook: {
|
|
14101
|
-
ask: {},
|
|
14102
|
-
search: {},
|
|
14103
|
-
impact: {},
|
|
14104
|
-
list: {},
|
|
14105
|
-
get: {},
|
|
14106
|
-
cat: {},
|
|
14107
|
-
new: {},
|
|
14108
|
-
edit: {},
|
|
14109
|
-
comment: {},
|
|
14110
|
-
import: {},
|
|
14111
|
-
visibility: {},
|
|
14112
|
-
publish: {},
|
|
14113
|
-
archive: {},
|
|
14114
|
-
history: {},
|
|
14115
|
-
revert: {},
|
|
14116
|
-
rm: {},
|
|
14117
|
-
lint: {}
|
|
14118
|
-
},
|
|
14119
|
-
secrets: { push: {}, status: {}, set: {}, "set-clerk-key": {} },
|
|
14120
|
-
security: {
|
|
14121
|
-
plan: {},
|
|
14122
|
-
sources: {},
|
|
14123
|
-
run: {},
|
|
14124
|
-
status: {},
|
|
14125
|
-
report: {},
|
|
14126
|
-
github: { connect: {}, disconnect: {} }
|
|
14127
|
-
},
|
|
14128
|
-
setup: {},
|
|
14129
|
-
skill: { install: {} },
|
|
14130
|
-
smoke: {},
|
|
14131
|
-
version: {},
|
|
14132
|
-
whoami: {}
|
|
14133
|
-
};
|
|
14134
|
-
function acceptedAfter(path) {
|
|
14135
|
-
let node = COMMAND_SURFACE;
|
|
14136
|
-
for (const word of path) {
|
|
14137
|
-
node = node?.[word];
|
|
14138
|
-
if (!node) return [];
|
|
14139
|
-
}
|
|
14140
|
-
return Object.keys(node).sort();
|
|
14141
|
-
}
|
|
14142
|
-
function validateInvocation(words2) {
|
|
14143
|
-
let node = COMMAND_SURFACE;
|
|
14144
|
-
const walked = [];
|
|
14145
|
-
for (const word of words2) {
|
|
14146
|
-
if (Object.keys(node).length === 0) return null;
|
|
14147
|
-
const next = node[word];
|
|
14148
|
-
if (!next) return { validPrefix: walked.join(" "), word, accepted: Object.keys(node).sort() };
|
|
14149
|
-
walked.push(word);
|
|
14150
|
-
node = next;
|
|
14151
|
-
}
|
|
14152
|
-
return null;
|
|
14153
|
-
}
|
|
14154
|
-
function describeProblem(problem) {
|
|
14155
|
-
const where = problem.validPrefix ? `after "${problem.validPrefix}"` : "as a command";
|
|
14156
|
-
return `"${problem.word}" is not accepted ${where} \u2014 try: ${problem.accepted.join(", ")}`;
|
|
14157
|
-
}
|
|
14158
|
-
function invocationPath(words2) {
|
|
14159
|
-
let node = COMMAND_SURFACE;
|
|
14160
|
-
const path = [];
|
|
14161
|
-
for (const word of words2) {
|
|
14162
|
-
const next = node[word];
|
|
14163
|
-
if (!next) break;
|
|
14164
|
-
path.push(word);
|
|
14165
|
-
node = next;
|
|
14166
|
-
if (Object.keys(node).length === 0) break;
|
|
14167
|
-
}
|
|
14168
|
-
return path;
|
|
14169
|
-
}
|
|
14170
|
-
function surfacePaths(node = COMMAND_SURFACE, prefix = []) {
|
|
14171
|
-
const paths2 = [];
|
|
14172
|
-
for (const [word, child] of Object.entries(node)) {
|
|
14173
|
-
const path = [...prefix, word];
|
|
14174
|
-
paths2.push(path);
|
|
14175
|
-
paths2.push(...surfacePaths(child, path));
|
|
14176
|
-
}
|
|
14177
|
-
return paths2;
|
|
14178
|
-
}
|
|
14179
|
-
|
|
14180
|
-
// src/record.ts
|
|
14181
14173
|
function recordInvocation(parsed) {
|
|
14182
14174
|
const file = process19.env.ODLA_CLI_RECORD;
|
|
14183
14175
|
if (!file) return;
|
|
@@ -14271,6 +14263,7 @@ async function deviceCommand(parsed, deps) {
|
|
|
14271
14263
|
"wait"
|
|
14272
14264
|
], 3);
|
|
14273
14265
|
const action2 = parsed.positionals[1] ?? "";
|
|
14266
|
+
if (!acceptedAfter(["device"]).includes(action2)) rejectWord(["device"], action2);
|
|
14274
14267
|
const out = deps.stdout ?? console;
|
|
14275
14268
|
const doFetch = deps.fetch ?? fetch;
|
|
14276
14269
|
const cfg = await loadProjectConfig(stringOpt(parsed.options.config));
|
|
@@ -14278,7 +14271,7 @@ async function deviceCommand(parsed, deps) {
|
|
|
14278
14271
|
if (action2 === "enroll") return enroll(parsed, deps, cfg, doFetch, out, json);
|
|
14279
14272
|
if (action2 === "list") return list2(parsed, deps, cfg, doFetch, out, json);
|
|
14280
14273
|
if (action2 === "revoke") return revoke(parsed, deps, cfg, doFetch, out, json);
|
|
14281
|
-
|
|
14274
|
+
rejectWord(["device"], action2);
|
|
14282
14275
|
}
|
|
14283
14276
|
async function enroll(parsed, deps, cfg, doFetch, out, json) {
|
|
14284
14277
|
const name = stringOpt(parsed.options.name) ?? defaultDeviceName();
|
|
@@ -15176,6 +15169,7 @@ async function buildContext3(parsed, deps, action2) {
|
|
|
15176
15169
|
async function runbookCommand(parsed, deps = {}) {
|
|
15177
15170
|
const action2 = parsed.positionals[1] ?? "list";
|
|
15178
15171
|
assertArgs(parsed, ALLOWED2, action2 === "ask" || action2 === "search" ? 64 : 4);
|
|
15172
|
+
if (!acceptedAfter(["runbook"]).includes(action2)) rejectWord(["runbook"], action2);
|
|
15179
15173
|
const ctx = await buildContext3(parsed, deps, action2);
|
|
15180
15174
|
const slug = parsed.positionals[2];
|
|
15181
15175
|
switch (action2) {
|
|
@@ -15265,7 +15259,7 @@ async function runbookCommand(parsed, deps = {}) {
|
|
|
15265
15259
|
case "rm":
|
|
15266
15260
|
return runbookRemove(ctx, requireSlug(slug, "rm"));
|
|
15267
15261
|
default:
|
|
15268
|
-
|
|
15262
|
+
rejectWord(["runbook"], action2);
|
|
15269
15263
|
}
|
|
15270
15264
|
}
|
|
15271
15265
|
|
|
@@ -15886,9 +15880,7 @@ async function securityCommand(parsed, dependencies) {
|
|
|
15886
15880
|
else printHostedReport(context.stdout, report5);
|
|
15887
15881
|
return;
|
|
15888
15882
|
}
|
|
15889
|
-
if (sub !== "run")
|
|
15890
|
-
throw new Error('unknown security command. Try "odla-ai security plan", "security sources", or "security run".');
|
|
15891
|
-
}
|
|
15883
|
+
if (sub !== "run") rejectWord(["security"], sub);
|
|
15892
15884
|
const sourceId = stringOpt(parsed.options.source);
|
|
15893
15885
|
if (sourceId) await runSourceSecurityCommand(parsed, dependencies, sourceId);
|
|
15894
15886
|
else await runLocalSecurityCommand(parsed, dependencies);
|
|
@@ -15905,9 +15897,7 @@ async function githubSecurityCommand(parsed, dependencies) {
|
|
|
15905
15897
|
stringOpt(parsed.options.env)
|
|
15906
15898
|
);
|
|
15907
15899
|
}
|
|
15908
|
-
if (action2 !== "connect")
|
|
15909
|
-
throw new Error('unknown security github command. Try "odla-ai security github connect".');
|
|
15910
|
-
}
|
|
15900
|
+
if (action2 !== "connect") rejectWord(["security", "github"], action2);
|
|
15911
15901
|
assertArgs(parsed, ["config", "env", "platform", "repo", "email", "open"], 3);
|
|
15912
15902
|
await requireStudioHuman(
|
|
15913
15903
|
stringOpt(parsed.options.config) ?? "odla.config.mjs",
|
|
@@ -16050,6 +16040,7 @@ async function dispatchCli(argv, dependencies) {
|
|
|
16050
16040
|
}
|
|
16051
16041
|
if (command === "bug") {
|
|
16052
16042
|
const action2 = parsed.positionals[1] ?? "list";
|
|
16043
|
+
if (!acceptedAfter(["bug"]).includes(action2)) rejectWord(["bug"], action2);
|
|
16053
16044
|
const canonical2 = action2 === "report" || action2 === "create" ? "add" : action2;
|
|
16054
16045
|
await pmCommand({
|
|
16055
16046
|
...parsed,
|
|
@@ -16078,7 +16069,7 @@ async function dispatchCli(argv, dependencies) {
|
|
|
16078
16069
|
return;
|
|
16079
16070
|
}
|
|
16080
16071
|
if (await projectCommand(command, parsed, runtime)) return;
|
|
16081
|
-
|
|
16072
|
+
rejectWord([], command);
|
|
16082
16073
|
}
|
|
16083
16074
|
async function provisionCommand(parsed, dependencies) {
|
|
16084
16075
|
assertArgs(parsed, [
|
|
@@ -16122,7 +16113,7 @@ async function provisionCommand(parsed, dependencies) {
|
|
|
16122
16113
|
async function calendarCommand(parsed, dependencies) {
|
|
16123
16114
|
const sub = parsed.positionals[1];
|
|
16124
16115
|
if (sub !== "status" && sub !== "calendars" && sub !== "connect" && sub !== "disconnect") {
|
|
16125
|
-
|
|
16116
|
+
rejectWord(["calendar"], sub);
|
|
16126
16117
|
}
|
|
16127
16118
|
assertArgs(parsed, ["config", "env", "json", "token", "email", "open", "yes"], 2);
|
|
16128
16119
|
if (sub !== "status" && sub !== "calendars" && parsed.options.json !== void 0) throw new Error(`--json is supported only by calendar status/calendars`);
|
|
@@ -16149,6 +16140,12 @@ export {
|
|
|
16149
16140
|
getScopedPlatformToken,
|
|
16150
16141
|
SYSTEM_AI_PURPOSES,
|
|
16151
16142
|
adminAi,
|
|
16143
|
+
COMMAND_SURFACE,
|
|
16144
|
+
acceptedAfter,
|
|
16145
|
+
validateInvocation,
|
|
16146
|
+
describeProblem,
|
|
16147
|
+
invocationPath,
|
|
16148
|
+
surfacePaths,
|
|
16152
16149
|
calendarServiceConfig,
|
|
16153
16150
|
calendarBookingPageUrl,
|
|
16154
16151
|
GOOGLE_CALENDAR_EVENTS_SCOPE,
|
|
@@ -16186,12 +16183,6 @@ export {
|
|
|
16186
16183
|
monitoringWireConfig,
|
|
16187
16184
|
monitorCommand,
|
|
16188
16185
|
provision,
|
|
16189
|
-
COMMAND_SURFACE,
|
|
16190
|
-
acceptedAfter,
|
|
16191
|
-
validateInvocation,
|
|
16192
|
-
describeProblem,
|
|
16193
|
-
invocationPath,
|
|
16194
|
-
surfacePaths,
|
|
16195
16186
|
runHostedSecurity,
|
|
16196
16187
|
getHostedSecurityIntent,
|
|
16197
16188
|
getHostedSecurityPlan,
|
|
@@ -16203,4 +16194,4 @@ export {
|
|
|
16203
16194
|
isTerminalHostedSecurityStatus,
|
|
16204
16195
|
runCli
|
|
16205
16196
|
};
|
|
16206
|
-
//# sourceMappingURL=chunk-
|
|
16197
|
+
//# sourceMappingURL=chunk-7MUWCSGP.js.map
|