@anna-ai/cli 0.1.19 → 0.1.21
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/_lifecycle-shared-sbea9HtH.js +65 -0
- package/dist/{agent-DUmINbo4.js → agent-Br6zY2qw.js} +1 -1
- package/dist/app-bundle-upload-DuLalcSt.js +213 -0
- package/dist/app-cache-BEM653Th.js +53 -0
- package/dist/apps-B1Nd8l_t.js +221 -0
- package/dist/apps-BTn9EN0x.js +53 -0
- package/dist/apps-cut-DtEkddIk.js +83 -0
- package/dist/apps-destructive-DSTrcFUP.js +104 -0
- package/dist/apps-discard-y3_IwcbQ.js +44 -0
- package/dist/apps-grants-BGWlpee0.js +34 -0
- package/dist/apps-publish-CaTCanDu.js +265 -0
- package/dist/apps-publish-DfZTOxBJ.js +14 -0
- package/dist/apps-push-B9XT2uwF.js +127 -0
- package/dist/apps-release-BLH9XSxB.js +135 -0
- package/dist/apps-status-DQ9RvlME.js +58 -0
- package/dist/apps-submit-review-DLwCxeAs.js +45 -0
- package/dist/apps-sync-meta-D9eKMMUp.js +72 -0
- package/dist/apps-versions-2Tmk0nsx.js +43 -0
- package/dist/bridge-Id8K8gr-.js +3 -0
- package/dist/bundled-executas-BNOKw4kv.js +161 -0
- package/dist/bundled-executas-CNaV2C_O.js +5 -0
- package/dist/cli.js +334 -20
- package/dist/client-Dn9zThOd.js +150 -0
- package/dist/confirm-DxHkk9Wn.js +37 -0
- package/dist/dev-BS_8yoSm.js +3 -0
- package/dist/{dev-b1j-dEM2.js → dev-E7mqXj5S.js} +95 -26
- package/dist/{dev-app-cache-3Pfesngr.js → dev-app-cache-D-r6ZpEk.js} +11 -2
- package/dist/{doctor-CgJYokiR.js → doctor-DKrt-Kda.js} +1 -1
- package/dist/executa-cache-BFoUtb4J.js +86 -0
- package/dist/executa-cache-WBkCLic7.js +4 -0
- package/dist/executa-destructive-COQE4Xqi.js +104 -0
- package/dist/{executa-dev-BeC6a8S8.js → executa-dev-BvS9zTpO.js} +11 -11
- package/dist/executa-publish-B88_9gbp.js +9 -0
- package/dist/executa-publish-Ca5V7MyA.js +258 -0
- package/dist/executa-reads-CQ6S8gHY.js +107 -0
- package/dist/executas-Cep6KEo0.js +109 -0
- package/dist/manifest-DGwRap2i.js +188 -0
- package/dist/publish-C1wcf-qI.js +58 -0
- package/dist/{server-BgJGmEpv.js → server-_IG8Igje.js} +200 -2
- package/dist/{storage-EQJA_0UW.js → storage-CTkApNQ9.js} +1 -1
- package/dist/token-B9JUPelx.js +87 -0
- package/dist/working-orchestration-Dw9u1Vq0.js +190 -0
- package/package.json +3 -3
- package/templates/executa/go/executa.json +5 -0
- package/templates/executa/node/executa.json +5 -0
- package/templates/executa/python/executa.json +5 -0
- package/dist/apps-ClgEOdKD.js +0 -44
- package/dist/bridge-B3Vwr4cg.js +0 -3
- package/dist/dev-D8o7xi0W.js +0 -3
- package/dist/dev-app-cache-CZ1UjMz0.js +0 -4
- /package/dist/{bridge-mkb_EM-y.js → bridge-BuklhzeE.js} +0 -0
- /package/dist/{credentials-DDqx6XMQ.js → credentials-DklPMD22.js} +0 -0
- /package/dist/{dev-account-DCyjamBa.js → dev-account-qRaET1Cp.js} +0 -0
- /package/dist/{executa-init-COEmKDOE.js → executa-init-Jp-h9OI7.js} +0 -0
- /package/dist/{executa-register-66WKIwQQ.js → executa-register-CulDtwYZ.js} +0 -0
- /package/dist/{fixture-CATHyLLI.js → fixture-CYwxbiQD.js} +0 -0
- /package/dist/{host_upload-C_pGOS6p.js → host_upload-GXVkDM5M.js} +0 -0
- /package/dist/{image-bwolX7pa.js → image-DduR91n5.js} +0 -0
- /package/dist/{login-CsIVbrmf.js → login-BGqFjQwH.js} +0 -0
- /package/dist/{logout-gfmKQxMj.js → logout-CGIRKH3y.js} +0 -0
- /package/dist/{runner-DmGLdat0.js → runner-B-hIqx5L.js} +0 -0
- /package/dist/{sampling-CJUDG-mf.js → sampling-CXke7hq1.js} +0 -0
- /package/dist/{whoami-BS5wy-Nh.js → whoami-BoFLEUcp.js} +0 -0
package/dist/cli.js
CHANGED
|
@@ -451,7 +451,7 @@ program.command("validate").description("Run schema + ACL checks on a manifest+b
|
|
|
451
451
|
process.exit(code);
|
|
452
452
|
});
|
|
453
453
|
program.command("dev").description("Run a local harness (in-process dispatcher + iframe + SSE relay)").option("--manifest <path>", "manifest.json path", "manifest.json").option("--bundle <dir>", "bundle directory (default: ./bundle)").option("--slug <slug>", "App slug (overrides manifest.slug/name)").option("--view <name>", "View name to open (default: manifest default)").option("--matrix-nexus-root <path>", "matrix-nexus checkout (auto-detected if omitted; can also use $ANNA_NEXUS_ROOT)").option("--port <number>", "HTTP port", "5180").option("--user-id <id>", "Harness user_id", "1").option("--cwd <dir>", "Project root (default: cwd)").option("--no-watch", "Disable bundle file watcher (default: enabled)").option("--executa <spec>", "Explicit executa registration; repeatable. Spec: comma-separated key=value (dir=<path>[,tool_id=<id>][,type=python|node|go|binary][,command=\"<argv>\"]). When only `dir=` is given, the executa is auto-detected from executa.json / pyproject.toml / package.json / go.mod. Overrides directory auto-discovery under <manifest-dir>/executas/.", (val, prev) => prev ? [...prev, val] : [val]).option("--no-llm", "Disable LLM bridge (anna.llm/agent return llm_disabled)").option("--mock-llm <fixture>", "Serve canned LLM responses from a JSONL fixture").option("--llm-account <host>", "Saved account host to use (default: current)").option("--llm-app-slug <slug>", "Override the manifest slug used to register / look up the dev AnnaApp (default: manifest.slug)").option("--storage <mode>", "Storage backend: \"legacy\" (in-memory runtime_state, default) or \"aps\" (real nexus APS via /api/v1/storage/* — requires `anna-app login`).", "legacy").action(async (opts) => {
|
|
454
|
-
const { runDev, parseExecutaSpec } = await import("./dev-
|
|
454
|
+
const { runDev, parseExecutaSpec } = await import("./dev-BS_8yoSm.js");
|
|
455
455
|
const cwd = opts.cwd ?? process.cwd();
|
|
456
456
|
let executas;
|
|
457
457
|
if (opts.executa && opts.executa.length > 0) {
|
|
@@ -486,7 +486,7 @@ program.command("dev").description("Run a local harness (in-process dispatcher +
|
|
|
486
486
|
});
|
|
487
487
|
const fixture = program.command("fixture").description("Inspect / replay harness recordings (Phase 6)");
|
|
488
488
|
fixture.command("verify <file>").description("Schema + invariant checks on a harness JSONL recording").option("--json", "Emit machine-readable JSON", false).action(async (file, opts) => {
|
|
489
|
-
const { runFixtureVerify } = await import("./fixture-
|
|
489
|
+
const { runFixtureVerify } = await import("./fixture-CYwxbiQD.js");
|
|
490
490
|
const code = await runFixtureVerify({
|
|
491
491
|
file,
|
|
492
492
|
json: opts.json
|
|
@@ -494,7 +494,7 @@ fixture.command("verify <file>").description("Schema + invariant checks on a har
|
|
|
494
494
|
process.exit(code);
|
|
495
495
|
});
|
|
496
496
|
fixture.command("summarize <file>").description("Print a human-readable digest of a harness recording").option("--json", "Emit machine-readable JSON", false).action(async (file, opts) => {
|
|
497
|
-
const { runFixtureSummarize } = await import("./fixture-
|
|
497
|
+
const { runFixtureSummarize } = await import("./fixture-CYwxbiQD.js");
|
|
498
498
|
const code = await runFixtureSummarize({
|
|
499
499
|
file,
|
|
500
500
|
json: opts.json
|
|
@@ -502,7 +502,7 @@ fixture.command("summarize <file>").description("Print a human-readable digest o
|
|
|
502
502
|
process.exit(code);
|
|
503
503
|
});
|
|
504
504
|
fixture.command("replay <file>").description("Dry-run replay of a harness recording (Phase 6 MVP)").option("--manifest <path>", "manifest.json path", "manifest.json").action(async (file, opts) => {
|
|
505
|
-
const { runFixtureReplay } = await import("./fixture-
|
|
505
|
+
const { runFixtureReplay } = await import("./fixture-CYwxbiQD.js");
|
|
506
506
|
const code = await runFixtureReplay({
|
|
507
507
|
file,
|
|
508
508
|
manifest: opts.manifest
|
|
@@ -510,12 +510,12 @@ fixture.command("replay <file>").description("Dry-run replay of a harness record
|
|
|
510
510
|
process.exit(code);
|
|
511
511
|
});
|
|
512
512
|
program.command("doctor").description("Check environment for `anna-app dev` (uv, matrix-nexus, dev key)").option("--matrix-nexus-root <path>", "matrix-nexus checkout (optional)").action(async (opts) => {
|
|
513
|
-
const { runDoctor } = await import("./doctor-
|
|
513
|
+
const { runDoctor } = await import("./doctor-DKrt-Kda.js");
|
|
514
514
|
const code = await runDoctor({ matrixNexusRoot: opts.matrixNexusRoot });
|
|
515
515
|
process.exit(code);
|
|
516
516
|
});
|
|
517
517
|
program.command("login").description("Device-flow login against a nexus host; saves a PAT to ~/.config/anna/credentials.json").requiredOption("--host <url>", "nexus base URL, e.g. https://nexus.example.com").option("--no-browser", "Do not open a browser window automatically", false).action(async (opts) => {
|
|
518
|
-
const { runLogin } = await import("./login-
|
|
518
|
+
const { runLogin } = await import("./login-BGqFjQwH.js");
|
|
519
519
|
const code = await runLogin({
|
|
520
520
|
host: opts.host,
|
|
521
521
|
noBrowser: opts.browser === false
|
|
@@ -523,7 +523,7 @@ program.command("login").description("Device-flow login against a nexus host; sa
|
|
|
523
523
|
process.exit(code);
|
|
524
524
|
});
|
|
525
525
|
program.command("logout").description("Remove a saved PAT entry").option("--host <url>", "Account to remove (default: current)").option("--all", "Remove every saved account", false).action(async (opts) => {
|
|
526
|
-
const { runLogout } = await import("./logout-
|
|
526
|
+
const { runLogout } = await import("./logout-CGIRKH3y.js");
|
|
527
527
|
const code = await runLogout({
|
|
528
528
|
host: opts.host,
|
|
529
529
|
all: opts.all
|
|
@@ -531,18 +531,10 @@ program.command("logout").description("Remove a saved PAT entry").option("--host
|
|
|
531
531
|
process.exit(code);
|
|
532
532
|
});
|
|
533
533
|
program.command("whoami").description("Show the current account (and any others)").option("--json", "Emit machine-readable JSON", false).action(async (opts) => {
|
|
534
|
-
const { runWhoami } = await import("./whoami-
|
|
534
|
+
const { runWhoami } = await import("./whoami-BoFLEUcp.js");
|
|
535
535
|
const code = await runWhoami({ json: opts.json });
|
|
536
536
|
process.exit(code);
|
|
537
537
|
});
|
|
538
|
-
program.command("apps:list").description("List dev apps installed for the current PAT").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (opts) => {
|
|
539
|
-
const { runAppsList } = await import("./apps-ClgEOdKD.js");
|
|
540
|
-
const code = await runAppsList({
|
|
541
|
-
account: opts.account,
|
|
542
|
-
json: opts.json
|
|
543
|
-
});
|
|
544
|
-
process.exit(code);
|
|
545
|
-
});
|
|
546
538
|
const executa = program.command("executa").description("Standalone Executa plugin scaffolding + local runner");
|
|
547
539
|
executa.command("init <dir>").description("Scaffold a standalone Executa plugin (python | node | go)").option("--slug <slug>", "Plugin slug (lowercase, hyphens)", "").option("--template <name>", "Language template: python | node | go", "python").option("--tool-id <id>", "Override the minted tool_id (default: tool-dev-<slug>)").option("--force", "Overwrite existing dir if non-empty", false).action(async (dir, opts) => {
|
|
548
540
|
const slug = opts.slug || dir.split(/[\\/]/).pop() || "my-executa";
|
|
@@ -555,7 +547,7 @@ executa.command("init <dir>").description("Scaffold a standalone Executa plugin
|
|
|
555
547
|
console.error(`✗ unknown template "${opts.template}" — expected python | node | go`);
|
|
556
548
|
process.exit(2);
|
|
557
549
|
}
|
|
558
|
-
const { runExecutaInit } = await import("./executa-init-
|
|
550
|
+
const { runExecutaInit } = await import("./executa-init-Jp-h9OI7.js");
|
|
559
551
|
const code = runExecutaInit({
|
|
560
552
|
targetDir: dir,
|
|
561
553
|
slug,
|
|
@@ -565,13 +557,13 @@ executa.command("init <dir>").description("Scaffold a standalone Executa plugin
|
|
|
565
557
|
});
|
|
566
558
|
process.exit(code);
|
|
567
559
|
});
|
|
568
|
-
executa.command("register").description("Register a
|
|
569
|
-
const { runExecutaRegister } = await import("./executa-register-
|
|
560
|
+
executa.command("register").description("Register a HARNESS AnnaApp(kind=executa) so `executa dev --storage real` (and agent / sampling / image / upload real-mode flows) can mint tokens for a local executa subprocess. Does NOT publish the executa itself — use `executa publish` for that. Lists/deletes via `apps list` / `apps delete`.").requiredOption("--tool-id <id>", "Executa tool_id (matches manifest.name)").option("--slug <slug>", "App slug (default: executa-<tool_id>; must be lowercase + hyphens)").option("--name <name>", "Human-readable display name (default: <tool_id>)").option("--account <host>", "Saved account host (default: current)").action(async (opts) => {
|
|
561
|
+
const { runExecutaRegister } = await import("./executa-register-CulDtwYZ.js");
|
|
570
562
|
const code = await runExecutaRegister(opts);
|
|
571
563
|
process.exit(code);
|
|
572
564
|
});
|
|
573
565
|
executa.command("dev").description("Run one Executa plugin in isolation (REPL or one-shot describe/invoke)").option("--dir <path>", "Executa project dir (default: CWD)").option("--spec <spec>", "Override discovery: comma-separated key=value (tool_id=...,type=...,command=\"...\")").option("--describe", "Print MANIFEST and exit", false).option("--health", "Print health and exit", false).option("--invoke <tool>", "Invoke one tool and exit").option("--args <json>", "JSON object passed as tool arguments", "{}").option("--json", "One-shot: emit compact JSON (no banners)", false).option("--no-sampling", "Hard-disable sampling reverse RPC (returns sampling_disabled)").option("--mock-sampling <fixture>", "Serve canned sampling responses from a JSONL fixture (offline)").option("--app-slug <slug>", "Forward sampling to nexus on behalf of this dev AnnaApp slug").option("--sampling-account <host>", "Saved account host for nexus sampling (default: current)").option("--no-agent", "Hard-disable agent reverse RPC (returns agent_not_granted)").option("--mock-agent <fixture>", "Serve canned agent/* responses from a JSONL fixture (offline)").option("--agent-account <host>", "Saved account host for nexus agent (default: --sampling-account or current)").option("--storage <mode>", "Storage backend: off | memory | mock | real (default: memory)").option("--mock-storage <fixture>", "Serve canned storage/* + files/* responses from a JSONL fixture").option("--storage-account <host>", "Saved account host for nexus storage (default: --sampling-account or current)").option("--storage-scopes <list>", "Comma-separated scopes for real storage tokens (default: user,app,tool)").option("--no-image", "Hard-disable image reverse RPC (returns image_not_granted)").option("--mock-image <fixture>", "Serve canned image/generate + image/edit responses from a JSONL fixture").option("--image-account <host>", "Saved account host for nexus image (default: --sampling-account or current)").option("--no-upload", "Hard-disable host/uploadFile reverse RPC (returns upload_not_granted)").option("--mock-upload <fixture>", "Serve canned host/uploadFile responses from a JSONL fixture").option("--upload-account <host>", "Saved account host for nexus uploads (default: --sampling-account or current)").action(async (opts) => {
|
|
574
|
-
const { runExecutaDev } = await import("./executa-dev-
|
|
566
|
+
const { runExecutaDev } = await import("./executa-dev-BvS9zTpO.js");
|
|
575
567
|
const storageMode = opts.storage === void 0 ? void 0 : (() => {
|
|
576
568
|
const m = opts.storage;
|
|
577
569
|
if (m === "off" || m === "memory" || m === "mock" || m === "real") return m;
|
|
@@ -606,6 +598,328 @@ executa.command("dev").description("Run one Executa plugin in isolation (REPL or
|
|
|
606
598
|
});
|
|
607
599
|
process.exit(code);
|
|
608
600
|
});
|
|
601
|
+
const apps = program.command("apps").description("Anna App publish lifecycle commands");
|
|
602
|
+
apps.command("list").description("List the Anna Apps you authored, with lifecycle status").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (opts) => {
|
|
603
|
+
const { runAppsList } = await import("./apps-BTn9EN0x.js");
|
|
604
|
+
process.exit(await runAppsList({
|
|
605
|
+
account: opts.account,
|
|
606
|
+
json: opts.json
|
|
607
|
+
}));
|
|
608
|
+
});
|
|
609
|
+
apps.command("publish").description("Publish or update an Anna App (manifest.json in cwd)").option("--cwd <dir>", "Project root (default: cwd)").option("--manifest <path>", "manifest.json path", "manifest.json").option("--bump <kind>", "Bump version: patch|minor|major").option("--no-write", "Skip writing the bumped version back to disk", false).option("--dry-run", "Resolve identity + diff but don't upload", false).option("--executa-id <handle=id>", "Override a bundled executa handle with a real tool_id (repeatable)", (val, prev) => [...prev, val], []).option("--skip-executa-publish", "Use cached/overridden tool_ids; don't recursively publish bundled executas", false).option("--no-bundled-executas", "Disable bundled-executa orchestration (legacy behaviour)").option("--no-bundle", "Skip UI bundle upload even if the manifest declares a UI").option("--bundle-dir <dir>", "UI bundle directory (default: <cwd>/bundle)").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (opts) => {
|
|
610
|
+
if (opts.bump && ![
|
|
611
|
+
"patch",
|
|
612
|
+
"minor",
|
|
613
|
+
"major"
|
|
614
|
+
].includes(opts.bump)) {
|
|
615
|
+
console.error(`✗ --bump must be patch|minor|major (got: ${opts.bump})`);
|
|
616
|
+
process.exit(2);
|
|
617
|
+
}
|
|
618
|
+
const { runAppsPublish } = await import("./apps-publish-DfZTOxBJ.js");
|
|
619
|
+
process.exit(await runAppsPublish({
|
|
620
|
+
cwd: opts.cwd,
|
|
621
|
+
manifest: opts.manifest,
|
|
622
|
+
bump: opts.bump,
|
|
623
|
+
noWrite: opts.write === false,
|
|
624
|
+
dryRun: opts.dryRun,
|
|
625
|
+
executaId: opts.executaId,
|
|
626
|
+
skipExecutaPublish: opts.skipExecutaPublish,
|
|
627
|
+
noBundledExecutas: opts.bundledExecutas === false,
|
|
628
|
+
noBundle: opts.bundle === false,
|
|
629
|
+
bundleDir: opts.bundleDir,
|
|
630
|
+
account: opts.account,
|
|
631
|
+
json: opts.json
|
|
632
|
+
}));
|
|
633
|
+
});
|
|
634
|
+
apps.command("push").description("Upsert the mutable working draft (manifest + bundle, no freeze)").option("--cwd <dir>", "Project root (default: cwd)").option("--manifest <path>", "manifest.json path", "manifest.json").option("--bump <kind>", "Bump version: patch|minor|major").option("--no-write", "Skip writing the bumped version back to disk", false).option("--dry-run", "Resolve identity + diff but don't upsert", false).option("--executa-id <handle=id>", "Override a bundled executa handle with a real tool_id (repeatable)", (val, prev) => [...prev, val], []).option("--skip-executa-publish", "Use cached/overridden tool_ids; don't recursively register bundled executas", false).option("--no-bundled-executas", "Disable bundled-executa orchestration (legacy behaviour)").option("--no-bundle", "Skip working UI bundle upload even if the manifest declares a UI").option("--bundle-dir <dir>", "UI bundle directory (default: <cwd>/bundle)").option("--if-match <revision>", "Optimistic-lock: require this working revision").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (opts) => {
|
|
635
|
+
if (opts.bump && ![
|
|
636
|
+
"patch",
|
|
637
|
+
"minor",
|
|
638
|
+
"major"
|
|
639
|
+
].includes(opts.bump)) {
|
|
640
|
+
console.error(`✗ --bump must be patch|minor|major (got: ${opts.bump})`);
|
|
641
|
+
process.exit(2);
|
|
642
|
+
}
|
|
643
|
+
let ifMatch;
|
|
644
|
+
if (opts.ifMatch !== void 0) {
|
|
645
|
+
ifMatch = Number.parseInt(opts.ifMatch, 10);
|
|
646
|
+
if (!Number.isFinite(ifMatch)) {
|
|
647
|
+
console.error(`✗ --if-match must be an integer revision (got: ${opts.ifMatch})`);
|
|
648
|
+
process.exit(2);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
const { runAppsPush } = await import("./apps-push-B9XT2uwF.js");
|
|
652
|
+
process.exit(await runAppsPush({
|
|
653
|
+
cwd: opts.cwd,
|
|
654
|
+
manifest: opts.manifest,
|
|
655
|
+
bump: opts.bump,
|
|
656
|
+
noWrite: opts.write === false,
|
|
657
|
+
dryRun: opts.dryRun,
|
|
658
|
+
executaId: opts.executaId,
|
|
659
|
+
skipExecutaPublish: opts.skipExecutaPublish,
|
|
660
|
+
noBundledExecutas: opts.bundledExecutas === false,
|
|
661
|
+
noBundle: opts.bundle === false,
|
|
662
|
+
bundleDir: opts.bundleDir,
|
|
663
|
+
ifMatch,
|
|
664
|
+
account: opts.account,
|
|
665
|
+
json: opts.json
|
|
666
|
+
}));
|
|
667
|
+
});
|
|
668
|
+
apps.command("cut <version>").description("Snapshot the working draft into an immutable version (freeze deps)").option("--changelog <text>", "Override the working draft changelog for this version").option("--slug <slug>", "App slug (default: resolve from .anna/app.json cache)").option("--cwd <dir>", "Project root for identity cache (default: cwd)").option("--dry-run", "Resolve target but don't cut", false).option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (version, opts) => {
|
|
669
|
+
const { runAppsCut } = await import("./apps-cut-DtEkddIk.js");
|
|
670
|
+
process.exit(await runAppsCut({
|
|
671
|
+
version,
|
|
672
|
+
changelog: opts.changelog,
|
|
673
|
+
slug: opts.slug,
|
|
674
|
+
cwd: opts.cwd,
|
|
675
|
+
dryRun: opts.dryRun,
|
|
676
|
+
account: opts.account,
|
|
677
|
+
json: opts.json
|
|
678
|
+
}));
|
|
679
|
+
});
|
|
680
|
+
apps.command("discard").description("Drop the mutable working draft (leaves cut versions intact)").option("--slug <slug>", "App slug (default: resolve from .anna/app.json cache)").option("--cwd <dir>", "Project root for identity cache (default: cwd)").option("--dry-run", "Resolve target but don't discard", false).option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (opts) => {
|
|
681
|
+
const { runAppsDiscard } = await import("./apps-discard-y3_IwcbQ.js");
|
|
682
|
+
process.exit(await runAppsDiscard({
|
|
683
|
+
slug: opts.slug,
|
|
684
|
+
cwd: opts.cwd,
|
|
685
|
+
dryRun: opts.dryRun,
|
|
686
|
+
account: opts.account,
|
|
687
|
+
json: opts.json
|
|
688
|
+
}));
|
|
689
|
+
});
|
|
690
|
+
apps.command("release <version>").description("Freeze & publish an existing remote version (go live)").option("--slug <slug>", "App slug (default: resolve from .anna/app.json cache)").option("--cwd <dir>", "Project root for identity cache (default: cwd)").option("--allow-create", "If the version isn't on the server, run 'apps publish' first, then release", false).option("--dry-run", "Resolve target + pre-flight but don't publish", false).option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (version, opts) => {
|
|
691
|
+
const { runAppsRelease } = await import("./apps-release-BLH9XSxB.js");
|
|
692
|
+
process.exit(await runAppsRelease({
|
|
693
|
+
version,
|
|
694
|
+
slug: opts.slug,
|
|
695
|
+
cwd: opts.cwd,
|
|
696
|
+
allowCreate: opts.allowCreate,
|
|
697
|
+
dryRun: opts.dryRun,
|
|
698
|
+
account: opts.account,
|
|
699
|
+
json: opts.json
|
|
700
|
+
}));
|
|
701
|
+
});
|
|
702
|
+
apps.command("sync-meta").description("Push mutable store metadata (name/tagline/…) from the manifest").option("--cwd <dir>", "Project root (default: cwd)").option("--manifest <path>", "manifest.json path", "manifest.json").option("--dry-run", "Print the metadata diff but don't PATCH", false).option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (opts) => {
|
|
703
|
+
const { runAppsSyncMeta } = await import("./apps-sync-meta-D9eKMMUp.js");
|
|
704
|
+
process.exit(await runAppsSyncMeta({
|
|
705
|
+
cwd: opts.cwd,
|
|
706
|
+
manifest: opts.manifest,
|
|
707
|
+
dryRun: opts.dryRun,
|
|
708
|
+
account: opts.account,
|
|
709
|
+
json: opts.json
|
|
710
|
+
}));
|
|
711
|
+
});
|
|
712
|
+
apps.command("submit-review [slug]").description("Move an app into review (DRAFT/REJECTED → PENDING_REVIEW)").option("--cwd <dir>", "Project root for identity cache (default: cwd)").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (slug, opts) => {
|
|
713
|
+
const { runAppsSubmitReview } = await import("./apps-submit-review-DLwCxeAs.js");
|
|
714
|
+
process.exit(await runAppsSubmitReview({
|
|
715
|
+
slug,
|
|
716
|
+
cwd: opts.cwd,
|
|
717
|
+
account: opts.account,
|
|
718
|
+
json: opts.json
|
|
719
|
+
}));
|
|
720
|
+
});
|
|
721
|
+
apps.command("status <slug>").description("Show server-known state for one Anna App").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (slug, opts) => {
|
|
722
|
+
const { runAppsStatus } = await import("./apps-status-DQ9RvlME.js");
|
|
723
|
+
process.exit(await runAppsStatus({
|
|
724
|
+
slug,
|
|
725
|
+
account: opts.account,
|
|
726
|
+
json: opts.json
|
|
727
|
+
}));
|
|
728
|
+
});
|
|
729
|
+
apps.command("versions <slug>").description("List all server versions of one Anna App").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (slug, opts) => {
|
|
730
|
+
const { runAppsVersions } = await import("./apps-versions-2Tmk0nsx.js");
|
|
731
|
+
process.exit(await runAppsVersions({
|
|
732
|
+
slug,
|
|
733
|
+
account: opts.account,
|
|
734
|
+
json: opts.json
|
|
735
|
+
}));
|
|
736
|
+
});
|
|
737
|
+
apps.command("grants <slug>").description("Show currently granted scopes/quota for one Anna App").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (slug, opts) => {
|
|
738
|
+
const { runAppsGrants } = await import("./apps-grants-BGWlpee0.js");
|
|
739
|
+
process.exit(await runAppsGrants({
|
|
740
|
+
slug,
|
|
741
|
+
account: opts.account,
|
|
742
|
+
json: opts.json
|
|
743
|
+
}));
|
|
744
|
+
});
|
|
745
|
+
apps.command("unpublish <slug>").description("Flip a PUBLISHED app back to APPROVED (private)").option("--yes", "Acknowledge the destructive operation", false).option("--confirm <slug>", "Slug confirmation (must match target)").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (slug, opts) => {
|
|
746
|
+
const { runAppsUnpublish } = await import("./apps-destructive-DSTrcFUP.js");
|
|
747
|
+
process.exit(await runAppsUnpublish({
|
|
748
|
+
slug,
|
|
749
|
+
yes: opts.yes,
|
|
750
|
+
confirm: opts.confirm,
|
|
751
|
+
account: opts.account,
|
|
752
|
+
json: opts.json
|
|
753
|
+
}));
|
|
754
|
+
});
|
|
755
|
+
apps.command("archive <slug>").description("Archive an Anna App (hides it from end users)").option("--yes", "Acknowledge the destructive operation", false).option("--confirm <slug>", "Slug confirmation (must match target)").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (slug, opts) => {
|
|
756
|
+
const { runAppsArchive } = await import("./apps-destructive-DSTrcFUP.js");
|
|
757
|
+
process.exit(await runAppsArchive({
|
|
758
|
+
slug,
|
|
759
|
+
yes: opts.yes,
|
|
760
|
+
confirm: opts.confirm,
|
|
761
|
+
account: opts.account,
|
|
762
|
+
json: opts.json
|
|
763
|
+
}));
|
|
764
|
+
});
|
|
765
|
+
apps.command("unarchive <slug>").description("Restore an archived Anna App back to APPROVED").option("--yes", "Acknowledge the operation", false).option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (slug, opts) => {
|
|
766
|
+
const { runAppsUnarchive } = await import("./apps-destructive-DSTrcFUP.js");
|
|
767
|
+
process.exit(await runAppsUnarchive({
|
|
768
|
+
slug,
|
|
769
|
+
yes: opts.yes,
|
|
770
|
+
account: opts.account,
|
|
771
|
+
json: opts.json
|
|
772
|
+
}));
|
|
773
|
+
});
|
|
774
|
+
apps.command("delete <slug>").description("Hard-delete an Anna App (refused by server if installs exist)").option("--yes", "Acknowledge the destructive operation", false).option("--confirm <slug>", "Slug confirmation (must match target)").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (slug, opts) => {
|
|
775
|
+
const { runAppsDelete } = await import("./apps-destructive-DSTrcFUP.js");
|
|
776
|
+
process.exit(await runAppsDelete({
|
|
777
|
+
slug,
|
|
778
|
+
yes: opts.yes,
|
|
779
|
+
confirm: opts.confirm,
|
|
780
|
+
account: opts.account,
|
|
781
|
+
json: opts.json
|
|
782
|
+
}));
|
|
783
|
+
});
|
|
784
|
+
executa.command("list").description("List Executas owned by the current PAT").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (opts) => {
|
|
785
|
+
const { runExecutaList } = await import("./executa-reads-CQ6S8gHY.js");
|
|
786
|
+
process.exit(await runExecutaList({
|
|
787
|
+
account: opts.account,
|
|
788
|
+
json: opts.json
|
|
789
|
+
}));
|
|
790
|
+
});
|
|
791
|
+
executa.command("status <ref>").description("Show server-known state for one Executa (slug or tool_id)").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (ref, opts) => {
|
|
792
|
+
const { runExecutaStatus } = await import("./executa-reads-CQ6S8gHY.js");
|
|
793
|
+
process.exit(await runExecutaStatus({
|
|
794
|
+
ref,
|
|
795
|
+
account: opts.account,
|
|
796
|
+
json: opts.json
|
|
797
|
+
}));
|
|
798
|
+
});
|
|
799
|
+
executa.command("versions <ref>").description("List immutable version snapshots for one Executa").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (ref, opts) => {
|
|
800
|
+
const { runExecutaVersions } = await import("./executa-reads-CQ6S8gHY.js");
|
|
801
|
+
process.exit(await runExecutaVersions({
|
|
802
|
+
ref,
|
|
803
|
+
account: opts.account,
|
|
804
|
+
json: opts.json
|
|
805
|
+
}));
|
|
806
|
+
});
|
|
807
|
+
executa.command("publish").description("Mint or update an Executa (executa.json in cwd)").option("--cwd <dir>", "Project root (default: cwd)").option("--manifest <path>", "executa.json path", "executa.json").option("--bump <kind>", "Bump version: patch|minor|major").option("--no-write", "Skip writing the bumped version back to disk", false).option("--publish", "After freezing the version, flip visibility to PUBLIC", false).option("--dry-run", "Resolve identity + diff but don't upload", false).option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (opts) => {
|
|
808
|
+
if (opts.bump && ![
|
|
809
|
+
"patch",
|
|
810
|
+
"minor",
|
|
811
|
+
"major"
|
|
812
|
+
].includes(opts.bump)) {
|
|
813
|
+
console.error(`✗ --bump must be patch|minor|major (got: ${opts.bump})`);
|
|
814
|
+
process.exit(2);
|
|
815
|
+
}
|
|
816
|
+
const { runExecutaPublish } = await import("./executa-publish-B88_9gbp.js");
|
|
817
|
+
process.exit(await runExecutaPublish({
|
|
818
|
+
cwd: opts.cwd,
|
|
819
|
+
manifest: opts.manifest,
|
|
820
|
+
bump: opts.bump,
|
|
821
|
+
noWrite: opts.write === false,
|
|
822
|
+
publish: opts.publish,
|
|
823
|
+
dryRun: opts.dryRun,
|
|
824
|
+
account: opts.account,
|
|
825
|
+
json: opts.json
|
|
826
|
+
}));
|
|
827
|
+
});
|
|
828
|
+
executa.command("unpublish <slug>").description("Flip an Executa's visibility back to private").option("--yes", "Acknowledge the destructive operation", false).option("--confirm <slug>", "Slug confirmation (must match target)").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (slug, opts) => {
|
|
829
|
+
const { runExecutaUnpublish } = await import("./executa-destructive-COQE4Xqi.js");
|
|
830
|
+
process.exit(await runExecutaUnpublish({
|
|
831
|
+
slug,
|
|
832
|
+
yes: opts.yes,
|
|
833
|
+
confirm: opts.confirm,
|
|
834
|
+
account: opts.account,
|
|
835
|
+
json: opts.json
|
|
836
|
+
}));
|
|
837
|
+
});
|
|
838
|
+
executa.command("yank <ref>").description("Hard-delete one Executa version (<slug>@<version>)").option("--yes", "Acknowledge the destructive operation", false).option("--confirm <slug>", "Slug confirmation (must match target)").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (ref, opts) => {
|
|
839
|
+
const { runExecutaYank } = await import("./executa-destructive-COQE4Xqi.js");
|
|
840
|
+
process.exit(await runExecutaYank({
|
|
841
|
+
ref,
|
|
842
|
+
yes: opts.yes,
|
|
843
|
+
confirm: opts.confirm,
|
|
844
|
+
account: opts.account,
|
|
845
|
+
json: opts.json
|
|
846
|
+
}));
|
|
847
|
+
});
|
|
848
|
+
executa.command("delete <slug>").description("Hard-delete an Executa").option("--yes", "Acknowledge the destructive operation", false).option("--confirm <slug>", "Slug confirmation (must match target)").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (slug, opts) => {
|
|
849
|
+
const { runExecutaDelete } = await import("./executa-destructive-COQE4Xqi.js");
|
|
850
|
+
process.exit(await runExecutaDelete({
|
|
851
|
+
slug,
|
|
852
|
+
yes: opts.yes,
|
|
853
|
+
confirm: opts.confirm,
|
|
854
|
+
account: opts.account,
|
|
855
|
+
json: opts.json
|
|
856
|
+
}));
|
|
857
|
+
});
|
|
858
|
+
executa.command("cache-clear").description("Delete the local `.anna/executa.json` identity cache. Use after the server-side Executa has been deleted/recreated, or when switching host. Next `executa publish` will re-mint via the idempotency key.").option("--cwd <dir>", "Project root (default: cwd)").action(async (opts) => {
|
|
859
|
+
const { resolve: resolve$1 } = await import("node:path");
|
|
860
|
+
const { existsSync: existsSync$1 } = await import("node:fs");
|
|
861
|
+
const { executaCachePath, invalidateExecutaCache } = await import("./executa-cache-WBkCLic7.js");
|
|
862
|
+
const cwd = resolve$1(opts.cwd ?? process.cwd());
|
|
863
|
+
const p = executaCachePath(cwd);
|
|
864
|
+
if (!existsSync$1(p)) {
|
|
865
|
+
console.log(`(no cache at ${p})`);
|
|
866
|
+
process.exit(0);
|
|
867
|
+
}
|
|
868
|
+
invalidateExecutaCache(cwd);
|
|
869
|
+
console.log(`✓ removed ${p}`);
|
|
870
|
+
process.exit(0);
|
|
871
|
+
});
|
|
872
|
+
const token = program.command("token").description("Manage developer PATs (list / revoke / scopes)");
|
|
873
|
+
token.command("list").description("List the caller's PATs (most-recent first)").option("--include-revoked", "Also show revoked PATs", false).option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (opts) => {
|
|
874
|
+
const { runTokenList } = await import("./token-B9JUPelx.js");
|
|
875
|
+
process.exit(await runTokenList({
|
|
876
|
+
includeRevoked: opts.includeRevoked,
|
|
877
|
+
account: opts.account,
|
|
878
|
+
json: opts.json
|
|
879
|
+
}));
|
|
880
|
+
});
|
|
881
|
+
token.command("revoke <id>").description("Revoke one of the caller's PATs by id").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (id, opts) => {
|
|
882
|
+
const idNum = Number.parseInt(id, 10);
|
|
883
|
+
if (!Number.isFinite(idNum) || idNum <= 0) {
|
|
884
|
+
console.error(`✗ token id must be a positive integer (got: ${id})`);
|
|
885
|
+
process.exit(2);
|
|
886
|
+
}
|
|
887
|
+
const { runTokenRevoke } = await import("./token-B9JUPelx.js");
|
|
888
|
+
process.exit(await runTokenRevoke({
|
|
889
|
+
id: idNum,
|
|
890
|
+
account: opts.account,
|
|
891
|
+
json: opts.json
|
|
892
|
+
}));
|
|
893
|
+
});
|
|
894
|
+
token.command("scopes").description("Print the available PAT scope catalogue").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (opts) => {
|
|
895
|
+
const { runTokenScopes } = await import("./token-B9JUPelx.js");
|
|
896
|
+
process.exit(await runTokenScopes({
|
|
897
|
+
account: opts.account,
|
|
898
|
+
json: opts.json
|
|
899
|
+
}));
|
|
900
|
+
});
|
|
901
|
+
program.command("publish").description("Auto-detect cwd and publish (apps publish OR executa publish)").option("--cwd <dir>", "Project root (default: cwd)").option("--bump <kind>", "Bump version: patch|minor|major").option("--no-write", "Skip writing the bumped version back to disk", false).option("--publish", "(executa) flip visibility to PUBLIC after upload", false).option("--dry-run", "Resolve identity + diff but don't upload", false).option("--no-bundle", "(apps) skip UI bundle upload").option("--bundle-dir <dir>", "(apps) UI bundle directory (default: <cwd>/bundle)").option("--account <host>", "Saved account host (default: current)").option("--json", "Emit machine-readable JSON", false).action(async (opts) => {
|
|
902
|
+
if (opts.bump && ![
|
|
903
|
+
"patch",
|
|
904
|
+
"minor",
|
|
905
|
+
"major"
|
|
906
|
+
].includes(opts.bump)) {
|
|
907
|
+
console.error(`✗ --bump must be patch|minor|major (got: ${opts.bump})`);
|
|
908
|
+
process.exit(2);
|
|
909
|
+
}
|
|
910
|
+
const { runTopLevelPublish } = await import("./publish-C1wcf-qI.js");
|
|
911
|
+
process.exit(await runTopLevelPublish({
|
|
912
|
+
cwd: opts.cwd,
|
|
913
|
+
bump: opts.bump,
|
|
914
|
+
noWrite: opts.write === false,
|
|
915
|
+
publish: opts.publish,
|
|
916
|
+
dryRun: opts.dryRun,
|
|
917
|
+
noBundle: opts.bundle === false,
|
|
918
|
+
bundleDir: opts.bundleDir,
|
|
919
|
+
account: opts.account,
|
|
920
|
+
json: opts.json
|
|
921
|
+
}));
|
|
922
|
+
});
|
|
609
923
|
program.parseAsync(process.argv).catch((e) => {
|
|
610
924
|
console.error(e);
|
|
611
925
|
process.exit(2);
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { canonicalHost } from "./credentials-BTv2IfUZ.js";
|
|
2
|
+
|
|
3
|
+
//#region src/api/client.ts
|
|
4
|
+
var CliError = class extends Error {
|
|
5
|
+
exitCode;
|
|
6
|
+
status;
|
|
7
|
+
body;
|
|
8
|
+
constructor(message, exitCode, opts) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.exitCode = exitCode;
|
|
11
|
+
this.status = opts?.status;
|
|
12
|
+
this.body = opts?.body;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
var ScopeError = class extends CliError {
|
|
16
|
+
needed;
|
|
17
|
+
missing;
|
|
18
|
+
have;
|
|
19
|
+
constructor(opts) {
|
|
20
|
+
super(`missing PAT scope(s): ${opts.missing.join(", ") || "(unknown)"}`, 3, {
|
|
21
|
+
status: 403,
|
|
22
|
+
body: opts.body
|
|
23
|
+
});
|
|
24
|
+
this.needed = opts.needed;
|
|
25
|
+
this.missing = opts.missing;
|
|
26
|
+
this.have = opts.have;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var NexusClient = class {
|
|
30
|
+
host;
|
|
31
|
+
pat;
|
|
32
|
+
fetchImpl;
|
|
33
|
+
userAgent;
|
|
34
|
+
constructor(opts) {
|
|
35
|
+
this.host = canonicalHost(opts.host);
|
|
36
|
+
this.pat = opts.pat;
|
|
37
|
+
this.fetchImpl = opts.fetchImpl ?? fetch;
|
|
38
|
+
this.userAgent = opts.userAgent ?? "anna-app-cli";
|
|
39
|
+
}
|
|
40
|
+
async request(opts) {
|
|
41
|
+
const url = new URL(this.host + opts.path);
|
|
42
|
+
if (opts.query) for (const [k, v] of Object.entries(opts.query)) {
|
|
43
|
+
if (v === void 0 || v === null) continue;
|
|
44
|
+
url.searchParams.set(k, String(v));
|
|
45
|
+
}
|
|
46
|
+
const headers = {
|
|
47
|
+
authorization: `Bearer ${this.pat}`,
|
|
48
|
+
"user-agent": this.userAgent,
|
|
49
|
+
accept: "application/json",
|
|
50
|
+
...opts.headers ?? {}
|
|
51
|
+
};
|
|
52
|
+
let body;
|
|
53
|
+
if (opts.multipart) {
|
|
54
|
+
const fd = new FormData();
|
|
55
|
+
for (const [k, v] of Object.entries(opts.multipart.fields)) fd.append(k, v);
|
|
56
|
+
body = fd;
|
|
57
|
+
} else if (opts.body !== void 0) {
|
|
58
|
+
headers["content-type"] = "application/json";
|
|
59
|
+
body = JSON.stringify(opts.body);
|
|
60
|
+
}
|
|
61
|
+
const method = opts.method ?? "GET";
|
|
62
|
+
const allowed = new Set(opts.allowStatuses ?? []);
|
|
63
|
+
let res;
|
|
64
|
+
try {
|
|
65
|
+
res = await this.fetchImpl(url, {
|
|
66
|
+
method,
|
|
67
|
+
headers,
|
|
68
|
+
body
|
|
69
|
+
});
|
|
70
|
+
} catch (e) {
|
|
71
|
+
throw new CliError(`network error contacting ${this.host}: ${e.message}`, 6);
|
|
72
|
+
}
|
|
73
|
+
if (res.status >= 500 && !opts.noRetry && !allowed.has(res.status) && method === "GET") try {
|
|
74
|
+
res = await this.fetchImpl(url, {
|
|
75
|
+
method,
|
|
76
|
+
headers,
|
|
77
|
+
body
|
|
78
|
+
});
|
|
79
|
+
} catch (e) {
|
|
80
|
+
throw new CliError(`network error contacting ${this.host}: ${e.message}`, 6);
|
|
81
|
+
}
|
|
82
|
+
const idempotentHit = res.headers.get("x-anna-idempotent") === "hit";
|
|
83
|
+
let parsed = null;
|
|
84
|
+
const text = await res.text();
|
|
85
|
+
if (text.length > 0) try {
|
|
86
|
+
parsed = JSON.parse(text);
|
|
87
|
+
} catch {
|
|
88
|
+
parsed = text;
|
|
89
|
+
}
|
|
90
|
+
if (!res.ok && !allowed.has(res.status)) this.throwForStatus(res.status, parsed);
|
|
91
|
+
return {
|
|
92
|
+
data: parsed,
|
|
93
|
+
status: res.status,
|
|
94
|
+
headers: res.headers,
|
|
95
|
+
idempotentHit
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
throwForStatus(status, body) {
|
|
99
|
+
if (status === 401) throw new CliError("PAT rejected by server (401). Run `anna-app login --host …` to refresh.", 2, {
|
|
100
|
+
status,
|
|
101
|
+
body
|
|
102
|
+
});
|
|
103
|
+
if (status === 403) {
|
|
104
|
+
const det = extractDetail(body);
|
|
105
|
+
if (det && typeof det === "object" && det.detail === "missing_scope") {
|
|
106
|
+
const dd = det;
|
|
107
|
+
throw new ScopeError({
|
|
108
|
+
needed: dd.needed ?? [],
|
|
109
|
+
missing: dd.missing ?? [],
|
|
110
|
+
have: dd.have ?? [],
|
|
111
|
+
body
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
throw new CliError(`forbidden (403): ${describeBody(body)}`, 3, {
|
|
115
|
+
status,
|
|
116
|
+
body
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
if (status >= 500) throw new CliError(`server error (${status}): ${describeBody(body)}`, 6, {
|
|
120
|
+
status,
|
|
121
|
+
body
|
|
122
|
+
});
|
|
123
|
+
throw new CliError(`request failed (${status}): ${describeBody(body)}`, 5, {
|
|
124
|
+
status,
|
|
125
|
+
body
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
function extractDetail(body) {
|
|
130
|
+
if (body && typeof body === "object" && "detail" in body) {
|
|
131
|
+
const d = body.detail;
|
|
132
|
+
if (typeof d === "string") return { detail: d };
|
|
133
|
+
if (d && typeof d === "object") return d;
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
function describeBody(body) {
|
|
138
|
+
if (typeof body === "string") return body.slice(0, 240);
|
|
139
|
+
if (body && typeof body === "object") {
|
|
140
|
+
const det = body.detail;
|
|
141
|
+
if (typeof det === "string") return det;
|
|
142
|
+
try {
|
|
143
|
+
return JSON.stringify(body).slice(0, 240);
|
|
144
|
+
} catch {}
|
|
145
|
+
}
|
|
146
|
+
return String(body ?? "(empty body)");
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
//#endregion
|
|
150
|
+
export { CliError, NexusClient, ScopeError };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { CliError } from "./client-Dn9zThOd.js";
|
|
2
|
+
import { yellow } from "kleur/colors";
|
|
3
|
+
import { createInterface } from "node:readline/promises";
|
|
4
|
+
|
|
5
|
+
//#region src/publish/confirm.ts
|
|
6
|
+
function isInteractive() {
|
|
7
|
+
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
8
|
+
}
|
|
9
|
+
async function promptForSlug(verb, slug) {
|
|
10
|
+
const rl = createInterface({
|
|
11
|
+
input: process.stdin,
|
|
12
|
+
output: process.stdout
|
|
13
|
+
});
|
|
14
|
+
try {
|
|
15
|
+
process.stdout.write(yellow(`About to \`${verb}\` "${slug}" — this is irreversible.\nType the slug to confirm (or empty to abort): `));
|
|
16
|
+
const answer = (await rl.question("")).trim();
|
|
17
|
+
if (answer !== slug) throw new CliError(`\`${verb}\` aborted: typed "${answer}" does not match target slug "${slug}"`, 7);
|
|
18
|
+
} finally {
|
|
19
|
+
rl.close();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async function ensureDestructiveAllowed(opts) {
|
|
23
|
+
if (process.env.ANNA_CLI_NO_DESTRUCTIVE === "1") throw new CliError(`\`${opts.verb}\` refused: ANNA_CLI_NO_DESTRUCTIVE=1 is set`, 7);
|
|
24
|
+
if (opts.confirm !== void 0) {
|
|
25
|
+
if (opts.confirm !== opts.slug) throw new CliError(`\`${opts.verb}\` refused: --confirm "${opts.confirm}" does not match target slug "${opts.slug}"`, 7);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (opts.yes) return;
|
|
29
|
+
if (isInteractive()) {
|
|
30
|
+
await promptForSlug(opts.verb, opts.slug);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
throw new CliError(`\`${opts.verb}\` refused: non-interactive shell — pass --confirm ${opts.slug} (or --yes) to proceed`, 7);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//#endregion
|
|
37
|
+
export { ensureDestructiveAllowed };
|