@anna-ai/cli 0.1.19 → 0.1.22

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.
Files changed (63) hide show
  1. package/dist/_lifecycle-shared-sbea9HtH.js +65 -0
  2. package/dist/{agent-DUmINbo4.js → agent-Br6zY2qw.js} +1 -1
  3. package/dist/app-bundle-upload-DuLalcSt.js +213 -0
  4. package/dist/app-cache-BEM653Th.js +53 -0
  5. package/dist/apps-B1Nd8l_t.js +221 -0
  6. package/dist/apps-BTn9EN0x.js +53 -0
  7. package/dist/apps-cut-DtEkddIk.js +83 -0
  8. package/dist/apps-destructive-DSTrcFUP.js +104 -0
  9. package/dist/apps-discard-y3_IwcbQ.js +44 -0
  10. package/dist/apps-grants-BGWlpee0.js +34 -0
  11. package/dist/apps-publish-CaTCanDu.js +265 -0
  12. package/dist/apps-publish-DfZTOxBJ.js +14 -0
  13. package/dist/apps-push-B9XT2uwF.js +127 -0
  14. package/dist/apps-release-BLH9XSxB.js +135 -0
  15. package/dist/apps-status-DQ9RvlME.js +58 -0
  16. package/dist/apps-submit-review-DLwCxeAs.js +45 -0
  17. package/dist/apps-sync-meta-D9eKMMUp.js +72 -0
  18. package/dist/apps-versions-2Tmk0nsx.js +43 -0
  19. package/dist/bridge-Id8K8gr-.js +3 -0
  20. package/dist/bundled-executas-BNOKw4kv.js +161 -0
  21. package/dist/bundled-executas-CNaV2C_O.js +5 -0
  22. package/dist/cli.js +346 -23
  23. package/dist/client-Dn9zThOd.js +150 -0
  24. package/dist/confirm-DxHkk9Wn.js +37 -0
  25. package/dist/dev-BS_8yoSm.js +3 -0
  26. package/dist/{dev-b1j-dEM2.js → dev-E7mqXj5S.js} +95 -26
  27. package/dist/{dev-app-cache-3Pfesngr.js → dev-app-cache-D-r6ZpEk.js} +11 -2
  28. package/dist/{doctor-CgJYokiR.js → doctor-DKrt-Kda.js} +1 -1
  29. package/dist/executa-cache-BFoUtb4J.js +86 -0
  30. package/dist/executa-cache-WBkCLic7.js +4 -0
  31. package/dist/executa-destructive-COQE4Xqi.js +104 -0
  32. package/dist/{executa-dev-BeC6a8S8.js → executa-dev-BvS9zTpO.js} +11 -11
  33. package/dist/executa-publish-B88_9gbp.js +9 -0
  34. package/dist/executa-publish-Ca5V7MyA.js +258 -0
  35. package/dist/executa-reads-CQ6S8gHY.js +107 -0
  36. package/dist/executas-Cep6KEo0.js +109 -0
  37. package/dist/manifest-DGwRap2i.js +188 -0
  38. package/dist/publish-C1wcf-qI.js +58 -0
  39. package/dist/{server-BgJGmEpv.js → server-_IG8Igje.js} +200 -2
  40. package/dist/{storage-EQJA_0UW.js → storage-CTkApNQ9.js} +1 -1
  41. package/dist/token-B9JUPelx.js +87 -0
  42. package/dist/working-orchestration-Dw9u1Vq0.js +190 -0
  43. package/package.json +3 -3
  44. package/templates/executa/go/executa.json +5 -0
  45. package/templates/executa/node/executa.json +5 -0
  46. package/templates/executa/python/executa.json +5 -0
  47. package/dist/apps-ClgEOdKD.js +0 -44
  48. package/dist/bridge-B3Vwr4cg.js +0 -3
  49. package/dist/dev-D8o7xi0W.js +0 -3
  50. package/dist/dev-app-cache-CZ1UjMz0.js +0 -4
  51. /package/dist/{bridge-mkb_EM-y.js → bridge-BuklhzeE.js} +0 -0
  52. /package/dist/{credentials-DDqx6XMQ.js → credentials-DklPMD22.js} +0 -0
  53. /package/dist/{dev-account-DCyjamBa.js → dev-account-qRaET1Cp.js} +0 -0
  54. /package/dist/{executa-init-COEmKDOE.js → executa-init-Jp-h9OI7.js} +0 -0
  55. /package/dist/{executa-register-66WKIwQQ.js → executa-register-CulDtwYZ.js} +0 -0
  56. /package/dist/{fixture-CATHyLLI.js → fixture-CYwxbiQD.js} +0 -0
  57. /package/dist/{host_upload-C_pGOS6p.js → host_upload-GXVkDM5M.js} +0 -0
  58. /package/dist/{image-bwolX7pa.js → image-DduR91n5.js} +0 -0
  59. /package/dist/{login-CsIVbrmf.js → login-BGqFjQwH.js} +0 -0
  60. /package/dist/{logout-gfmKQxMj.js → logout-CGIRKH3y.js} +0 -0
  61. /package/dist/{runner-DmGLdat0.js → runner-B-hIqx5L.js} +0 -0
  62. /package/dist/{sampling-CJUDG-mf.js → sampling-CXke7hq1.js} +0 -0
  63. /package/dist/{whoami-BS5wy-Nh.js → whoami-BoFLEUcp.js} +0 -0
@@ -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 };
@@ -0,0 +1,3 @@
1
+ import { parseExecutaSpec, runDev } from "./dev-E7mqXj5S.js";
2
+
3
+ export { parseExecutaSpec, runDev };
@@ -43,8 +43,8 @@ async function runDev(opts) {
43
43
  }
44
44
  process.env.ANNA_APP_RUNTIME_STORAGE_MODE = "aps";
45
45
  }
46
- const { PythonBridge, PINNED_RUNTIME_VERSION } = await import("./bridge-B3Vwr4cg.js");
47
- const { HarnessServer } = await import("./server-BgJGmEpv.js");
46
+ const { PythonBridge, PINNED_RUNTIME_VERSION } = await import("./bridge-Id8K8gr-.js");
47
+ const { HarnessServer } = await import("./server-_IG8Igje.js");
48
48
  const bridge = new PythonBridge({
49
49
  mode,
50
50
  matrixNexusRoot: matrixNexusRoot ?? void 0,
@@ -77,6 +77,19 @@ async function runDev(opts) {
77
77
  console.log(green(" ✓ bridge ready"));
78
78
  const executas = opts.executas ?? autoDiscoverExecutas(dirname(manifestPath));
79
79
  if (executas.length > 0) console.log(` executas ${dim(executas.map((e) => e.tool_id).join(", "))}`);
80
+ const bundledResolved = resolveBundledHandles(dirname(manifestPath), executas);
81
+ if (Object.keys(bundledResolved).length > 0) {
82
+ const { substituteBundledRefs, writeBundleToolIdSidecar } = await import("./bundled-executas-CNaV2C_O.js");
83
+ try {
84
+ manifest = substituteBundledRefs(manifest, bundledResolved);
85
+ writeBundleToolIdSidecar(bundleDir, bundledResolved);
86
+ console.log(` bundled handles ${dim(Object.entries(bundledResolved).map(([h, id]) => `${h}→${id}`).join(", "))}`);
87
+ } catch (e) {
88
+ console.error(red(`✗ bundled handle resolution failed: ${e.message}`));
89
+ await bridge.stop();
90
+ return 2;
91
+ }
92
+ }
80
93
  const llm = opts.noLlm ? { mode: "off" } : opts.mockLlm ? {
81
94
  mode: "mock",
82
95
  mockFile: opts.mockLlm
@@ -136,8 +149,8 @@ async function runDev(opts) {
136
149
  * registered `appSlug`.
137
150
  */
138
151
  async function resolveRealLlm(args) {
139
- const { getAccount } = await import("./credentials-DDqx6XMQ.js");
140
- const { ensureDevAppRegistered } = await import("./dev-app-cache-CZ1UjMz0.js");
152
+ const { getAccount } = await import("./credentials-DklPMD22.js");
153
+ const { ensureDevAppRegistered } = await import("./dev-app-cache-D-r6ZpEk.js");
141
154
  const acc = getAccount(args.account);
142
155
  if (!acc) {
143
156
  console.error(red("✗ no developer PAT on disk — run `anna-app login --host <nexus-url>` first.\n (or use `--no-llm` / `--mock-llm <fixture>` to develop offline.)"));
@@ -166,7 +179,7 @@ async function resolveRealLlm(args) {
166
179
  account: args.account,
167
180
  appSlug: entry.slug,
168
181
  onAppSlugNotFound: async () => {
169
- const { invalidateDevAppCache } = await import("./dev-app-cache-CZ1UjMz0.js");
182
+ const { invalidateDevAppCache } = await import("./dev-app-cache-D-r6ZpEk.js");
170
183
  invalidateDevAppCache(args.cwd);
171
184
  const fresh = getAccount(args.account);
172
185
  if (!fresh) throw new Error("PAT not found while re-registering dev app — run `anna-app login` again");
@@ -188,6 +201,46 @@ function deriveSlug(manifest, path) {
188
201
  if (typeof fromMan === "string" && fromMan) return fromMan;
189
202
  return dirname(path).split(/[\\/]/).pop() || "anna-app-dev";
190
203
  }
204
+ /**
205
+ * Map each `app.json` `bundled_executas` handle to the concrete dev
206
+ * `tool_id` of the executa discovered at its `path`. Mirrors PUBLISH's
207
+ * handle→minted-id resolution so `anna-app dev` can rewrite
208
+ * `bundled:<handle>` refs in the manifest. Returns `{}` when there is no
209
+ * `app.json` or no `bundled_executas`. Unresolvable handles are warned and
210
+ * skipped (the leftover `bundled:` ref will then fail the whitelist, which
211
+ * surfaces the misconfiguration loudly).
212
+ */
213
+ function resolveBundledHandles(manifestDir, executas) {
214
+ const appJsonPath = resolve(manifestDir, "app.json");
215
+ if (!existsSync(appJsonPath)) return {};
216
+ let appJson;
217
+ try {
218
+ appJson = JSON.parse(readFileSync(appJsonPath, "utf-8"));
219
+ } catch (e) {
220
+ console.warn(yellow(`⚠ app.json is not valid json: ${e.message}`));
221
+ return {};
222
+ }
223
+ const bundled = appJson.bundled_executas;
224
+ if (!bundled || typeof bundled !== "object") return {};
225
+ const byDir = new Map();
226
+ for (const ex of executas) byDir.set(resolve(ex.project_dir), ex.tool_id);
227
+ const resolved = {};
228
+ for (const [handle, spec] of Object.entries(bundled)) {
229
+ const p = spec?.path;
230
+ if (!p) {
231
+ console.warn(yellow(`⚠ bundled_executas["${handle}"] missing "path"`));
232
+ continue;
233
+ }
234
+ const dir = isAbsolute(p) ? p : resolve(manifestDir, p);
235
+ const toolId = byDir.get(resolve(dir));
236
+ if (!toolId) {
237
+ console.warn(yellow(`⚠ bundled handle "${handle}" → ${p}: no executa discovered at that path (check executas/<dir>/executa.json "tool_id")`));
238
+ continue;
239
+ }
240
+ resolved[handle] = toolId;
241
+ }
242
+ return resolved;
243
+ }
191
244
  function autoDiscoverExecutas(manifestDir) {
192
245
  const root = resolve(manifestDir, "executas");
193
246
  if (!existsSync(root)) return [];
@@ -257,13 +310,17 @@ function discoverOne(dir, name, opts = { respectEnabled: true }) {
257
310
  }
258
311
  function defaultCommand(type, dir, toolId) {
259
312
  switch (type) {
260
- case "python": return [
261
- "uv",
262
- "run",
263
- "--project",
264
- dir,
265
- toolId
266
- ];
313
+ case "python": {
314
+ const script = pythonScriptName(dir);
315
+ if (script instanceof Error) return script;
316
+ return [
317
+ "uv",
318
+ "run",
319
+ "--project",
320
+ dir,
321
+ script ?? toolId
322
+ ];
323
+ }
267
324
  case "node": {
268
325
  const pkg = readPackageJson(dir);
269
326
  if (!pkg) return new Error("type=node but no package.json found");
@@ -285,7 +342,30 @@ function defaultCommand(type, dir, toolId) {
285
342
  }
286
343
  }
287
344
  function discoverPython(dir, name) {
345
+ const script = pythonScriptName(dir);
346
+ if (script instanceof Error) return script;
347
+ if (script === null) return new Error("no [project.scripts] entry in pyproject.toml");
348
+ return {
349
+ tool_id: script,
350
+ project_dir: dir,
351
+ command: [
352
+ "uv",
353
+ "run",
354
+ "--project",
355
+ dir,
356
+ script
357
+ ]
358
+ };
359
+ }
360
+ /**
361
+ * First `[project.scripts]` entry name from a dir's pyproject.toml — the
362
+ * console-script `uv run` should launch. Returns `null` when there's no
363
+ * pyproject / no scripts table (caller decides the fallback), or an Error
364
+ * when pyproject exists but can't be parsed.
365
+ */
366
+ function pythonScriptName(dir) {
288
367
  const py = resolve(dir, "pyproject.toml");
368
+ if (!existsSync(py)) return null;
289
369
  let body;
290
370
  try {
291
371
  body = readFileSync(py, "utf-8");
@@ -299,21 +379,10 @@ function discoverPython(dir, name) {
299
379
  return new Error(`failed to parse pyproject.toml (${err.message})`);
300
380
  }
301
381
  const scripts = parsed?.project?.scripts;
302
- if (!scripts || typeof scripts !== "object") return new Error("no [project.scripts] entry in pyproject.toml");
382
+ if (!scripts || typeof scripts !== "object") return null;
303
383
  const keys = Object.keys(scripts);
304
- if (keys.length === 0) return new Error("[project.scripts] is empty");
305
- const toolId = keys[0];
306
- return {
307
- tool_id: toolId,
308
- project_dir: dir,
309
- command: [
310
- "uv",
311
- "run",
312
- "--project",
313
- dir,
314
- toolId
315
- ]
316
- };
384
+ if (keys.length === 0) return null;
385
+ return keys[0];
317
386
  }
318
387
  function discoverNode(dir, name) {
319
388
  const pkg = readPackageJson(dir);
@@ -82,7 +82,16 @@ async function listDevApps(args) {
82
82
  async function ensureDevAppRegistered(args) {
83
83
  const canonical = canonicalHost(args.host);
84
84
  const cached = readDevAppCache(args.cwd);
85
- if (cached && cached.host === canonical && cached.slug === args.input.slug) return cached;
85
+ if (cached && cached.host === canonical && cached.slug === args.input.slug) try {
86
+ const apps = await listDevApps({
87
+ host: args.host,
88
+ pat: args.pat
89
+ });
90
+ if (apps.some((a) => a.slug === args.input.slug)) return cached;
91
+ invalidateDevAppCache(args.cwd);
92
+ } catch {
93
+ return cached;
94
+ }
86
95
  const r = await registerDevApp({
87
96
  host: args.host,
88
97
  pat: args.pat,
@@ -186,4 +195,4 @@ async function ensureDevExecutaRegistered(args) {
186
195
  }
187
196
 
188
197
  //#endregion
189
- export { ensureDevAppRegistered, ensureDevExecutaRegistered, invalidateDevAppCache, listDevApps, readDevAppCache, readDevExecutaCache, registerDevApp, registerDevExecuta, writeDevAppCache, writeDevExecutaCache };
198
+ export { ensureDevAppRegistered, ensureDevExecutaRegistered, invalidateDevAppCache };
@@ -1,4 +1,4 @@
1
- import { PINNED_RUNTIME_VERSION } from "./bridge-mkb_EM-y.js";
1
+ import { PINNED_RUNTIME_VERSION } from "./bridge-BuklhzeE.js";
2
2
  import { dirname, isAbsolute, resolve } from "node:path";
3
3
  import { existsSync, statSync } from "node:fs";
4
4
  import { spawnSync } from "node:child_process";
@@ -0,0 +1,86 @@
1
+ import { canonicalHost } from "./credentials-BTv2IfUZ.js";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
4
+ import { createHash } from "node:crypto";
5
+
6
+ //#region src/identity/executa-cache.ts
7
+ const CACHE_DIR = ".anna";
8
+ const CACHE_FILE = "executa.json";
9
+ function executaCachePath(cwd) {
10
+ return resolve(cwd, CACHE_DIR, CACHE_FILE);
11
+ }
12
+ function readExecutaIdentity(cwd) {
13
+ const p = executaCachePath(cwd);
14
+ if (!existsSync(p)) return null;
15
+ try {
16
+ const raw = JSON.parse(readFileSync(p, "utf-8"));
17
+ if (typeof raw.host === "string" && typeof raw.tool_id === "string" && typeof raw.executa_id === "number" && typeof raw.slug === "string" && (raw.executa_type === "tool" || raw.executa_type === "skill")) return {
18
+ $schema: "anna-executa-identity/v1",
19
+ host: canonicalHost(raw.host),
20
+ executa_id: raw.executa_id,
21
+ tool_id: raw.tool_id,
22
+ slug: raw.slug,
23
+ executa_type: raw.executa_type,
24
+ first_published_at: raw.first_published_at
25
+ };
26
+ } catch {}
27
+ return null;
28
+ }
29
+ function writeExecutaIdentity(cwd, identity) {
30
+ const p = executaCachePath(cwd);
31
+ mkdirSync(dirname(p), { recursive: true });
32
+ const tmp = `${p}.tmp.${process.pid}`;
33
+ writeFileSync(tmp, JSON.stringify({
34
+ ...identity,
35
+ host: canonicalHost(identity.host)
36
+ }, null, 2) + "\n", "utf-8");
37
+ try {
38
+ renameSync(tmp, p);
39
+ } catch (e) {
40
+ try {
41
+ unlinkSync(tmp);
42
+ } catch {}
43
+ throw e;
44
+ }
45
+ }
46
+ function executaCacheMatches(identity, host, slug) {
47
+ if (!identity) return false;
48
+ return identity.host === canonicalHost(host) && identity.slug === slug;
49
+ }
50
+ /**
51
+ * Remove the cache file (best-effort). Used when a cached identity
52
+ * points at a server-side row that no longer exists (404 on
53
+ * GET/PUT/POST against `executa_id`), so the next `executa publish`
54
+ * re-runs the draft+commit mint path with the idempotency key instead
55
+ * of dying with "Tool not found".
56
+ */
57
+ function invalidateExecutaCache(cwd) {
58
+ const p = executaCachePath(cwd);
59
+ try {
60
+ if (existsSync(p)) unlinkSync(p);
61
+ } catch {}
62
+ }
63
+ /**
64
+ * Stable mint idempotency key — `sha256(host|slug|type)`.
65
+ *
66
+ * Sent on every `POST /my/drafts` so that a fresh CI runner without the
67
+ * `.anna/executa.json` cache short-circuits onto the existing draft /
68
+ * Executa instead of minting a brand-new `tool_id`.
69
+ */
70
+ function mintIdempotencyKey(host, slug, executaType) {
71
+ const canonical = canonicalHost(host);
72
+ const h = createHash("sha256");
73
+ h.update(canonical);
74
+ h.update("|");
75
+ h.update(slug);
76
+ h.update("|");
77
+ h.update(executaType);
78
+ return h.digest("hex");
79
+ }
80
+ const _internal = {
81
+ CACHE_DIR,
82
+ CACHE_FILE: join(CACHE_DIR, CACHE_FILE)
83
+ };
84
+
85
+ //#endregion
86
+ export { executaCacheMatches, executaCachePath, invalidateExecutaCache, mintIdempotencyKey, readExecutaIdentity, writeExecutaIdentity };
@@ -0,0 +1,4 @@
1
+ import "./credentials-BTv2IfUZ.js";
2
+ import { executaCacheMatches, executaCachePath, invalidateExecutaCache, mintIdempotencyKey, readExecutaIdentity, writeExecutaIdentity } from "./executa-cache-BFoUtb4J.js";
3
+
4
+ export { executaCachePath, invalidateExecutaCache };
@@ -0,0 +1,104 @@
1
+ import "./credentials-BTv2IfUZ.js";
2
+ import { CliError } from "./client-Dn9zThOd.js";
3
+ import { deleteMyTool, listMyTools, listToolVersions, unpublishTool, yankToolVersion } from "./executas-Cep6KEo0.js";
4
+ import { resolveClient, withErrorHandling } from "./_lifecycle-shared-sbea9HtH.js";
5
+ import { ensureDestructiveAllowed } from "./confirm-DxHkk9Wn.js";
6
+ import { dim, green, yellow } from "kleur/colors";
7
+
8
+ //#region src/commands/executa-destructive.ts
9
+ async function findBySlug(client, ref) {
10
+ const rows = await listMyTools(client);
11
+ const exact = rows.find((r) => r.tool_id === ref);
12
+ if (exact) return exact;
13
+ const matches = rows.filter((r) => r.tool_id.includes(ref));
14
+ if (matches.length === 0) return null;
15
+ if (matches.length === 1) return matches[0] ?? null;
16
+ const list = matches.map((r) => ` - ${r.tool_id}`).join("\n");
17
+ throw new CliError(`ref "${ref}" is ambiguous (${matches.length} matches):\n${list}\nPlease pass the full tool_id.`, 5);
18
+ }
19
+ /**
20
+ * Confirm-token UX: accept the slug the user typed OR the real server
21
+ * tool_id. Validating against tool_id is the safer match because the
22
+ * user has just been told what it is by the resolver.
23
+ */
24
+ async function checkConfirm(verb, refTyped, toolId, opts) {
25
+ await ensureDestructiveAllowed({
26
+ verb,
27
+ slug: toolId,
28
+ yes: opts.yes,
29
+ confirm: opts.confirm === refTyped ? toolId : opts.confirm
30
+ });
31
+ }
32
+ async function runExecutaUnpublish(opts) {
33
+ return withErrorHandling(async () => {
34
+ const { client, host } = resolveClient({ account: opts.account });
35
+ const ex = await findBySlug(client, opts.slug);
36
+ if (!ex) throw new CliError(`no executa matching "${opts.slug}" on ${host}`, 5);
37
+ await checkConfirm("executa unpublish", opts.slug, ex.tool_id, opts);
38
+ const updated = await unpublishTool(client, ex.id);
39
+ if (opts.json) {
40
+ console.log(JSON.stringify({
41
+ host,
42
+ executa_id: ex.id,
43
+ tool_id: ex.tool_id,
44
+ visibility: updated.visibility ?? null
45
+ }, null, 2));
46
+ return 0;
47
+ }
48
+ console.log(green(`✓ executas/${ex.tool_id}: unpublished (visibility=${updated.visibility})`));
49
+ return 0;
50
+ });
51
+ }
52
+ async function runExecutaYank(opts) {
53
+ return withErrorHandling(async () => {
54
+ const at = opts.ref.lastIndexOf("@");
55
+ if (at < 1) throw new CliError(`\`executa yank\` expects <slug>@<version> (got "${opts.ref}")`, 4);
56
+ const slug = opts.ref.slice(0, at);
57
+ const version = opts.ref.slice(at + 1);
58
+ const { client, host } = resolveClient({ account: opts.account });
59
+ const ex = await findBySlug(client, slug);
60
+ if (!ex) throw new CliError(`no executa matching "${slug}" on ${host}`, 5);
61
+ await checkConfirm("executa yank", slug, ex.tool_id, opts);
62
+ const versions = await listToolVersions(client, ex.id);
63
+ const ver = versions.find((v) => v.version === version);
64
+ if (!ver) throw new CliError(`no version "${version}" for executa "${slug}" (have: ${versions.map((v) => v.version).join(", ") || "(none)"})`, 5);
65
+ await yankToolVersion(client, ex.id, ver.id);
66
+ if (opts.json) {
67
+ console.log(JSON.stringify({
68
+ host,
69
+ executa_id: ex.id,
70
+ tool_id: ex.tool_id,
71
+ version,
72
+ version_id: ver.id,
73
+ yanked: true
74
+ }, null, 2));
75
+ return 0;
76
+ }
77
+ console.log(yellow(`✓ executas/${ex.tool_id}@${version}: yanked (version_id=${ver.id})`));
78
+ return 0;
79
+ });
80
+ }
81
+ async function runExecutaDelete(opts) {
82
+ return withErrorHandling(async () => {
83
+ const { client, host } = resolveClient({ account: opts.account });
84
+ const ex = await findBySlug(client, opts.slug);
85
+ if (!ex) throw new CliError(`no executa matching "${opts.slug}" on ${host}`, 5);
86
+ await checkConfirm("executa delete", opts.slug, ex.tool_id, opts);
87
+ await deleteMyTool(client, ex.id);
88
+ if (opts.json) {
89
+ console.log(JSON.stringify({
90
+ host,
91
+ executa_id: ex.id,
92
+ tool_id: ex.tool_id,
93
+ deleted: true
94
+ }, null, 2));
95
+ return 0;
96
+ }
97
+ console.log(yellow(`✓ executas/${ex.tool_id}: deleted`));
98
+ console.log(dim(` (local .anna/executa.json is now stale; remove it manually if you no longer need it)`));
99
+ return 0;
100
+ });
101
+ }
102
+
103
+ //#endregion
104
+ export { runExecutaDelete, runExecutaUnpublish, runExecutaYank };
@@ -1,9 +1,9 @@
1
- import { parseExecutaSpec } from "./dev-b1j-dEM2.js";
1
+ import { parseExecutaSpec } from "./dev-E7mqXj5S.js";
2
2
  import { isAbsolute, resolve } from "node:path";
3
3
  import { existsSync } from "node:fs";
4
4
  import { bold, cyan, dim, green, red, yellow } from "kleur/colors";
5
+ import { createInterface } from "node:readline/promises";
5
6
  import * as readline from "node:readline";
6
- import { createInterface as createInterface$1 } from "node:readline/promises";
7
7
 
8
8
  //#region src/commands/executa-dev.ts
9
9
  /**
@@ -33,8 +33,8 @@ async function runExecutaDev(opts) {
33
33
  }
34
34
  const oneShot = !!(opts.describe || opts.health || opts.invoke);
35
35
  const quiet = oneShot && (opts.json ?? false);
36
- const { getAccount } = await import("./credentials-DDqx6XMQ.js");
37
- const { ensureDevExecutaRegistered } = await import("./dev-app-cache-CZ1UjMz0.js");
36
+ const { getAccount } = await import("./credentials-DklPMD22.js");
37
+ const { ensureDevExecutaRegistered } = await import("./dev-app-cache-D-r6ZpEk.js");
38
38
  const needsRealMint = !opts.noSampling && !opts.mockSampling || !opts.noAgent && !opts.mockAgent || !opts.noImage && !opts.mockImage || !opts.noUpload && !opts.mockUpload || opts.storage === "real";
39
39
  let effectiveAppSlug = opts.appSlug;
40
40
  let autoRegistered = false;
@@ -56,7 +56,7 @@ async function runExecutaDev(opts) {
56
56
  }
57
57
  }
58
58
  }
59
- const { SamplingBridge } = await import("./sampling-CJUDG-mf.js");
59
+ const { SamplingBridge } = await import("./sampling-CXke7hq1.js");
60
60
  const sampling = opts.noSampling ? new SamplingBridge({ mode: "off" }) : opts.mockSampling ? new SamplingBridge({
61
61
  mode: "mock",
62
62
  mockFile: opts.mockSampling
@@ -65,7 +65,7 @@ async function runExecutaDev(opts) {
65
65
  account: opts.samplingAccount,
66
66
  appSlug: effectiveAppSlug
67
67
  }) : new SamplingBridge({ mode: "off" });
68
- const { AgentBridge } = await import("./agent-DUmINbo4.js");
68
+ const { AgentBridge } = await import("./agent-Br6zY2qw.js");
69
69
  const agent = opts.noAgent ? new AgentBridge({ mode: "off" }) : opts.mockAgent ? new AgentBridge({
70
70
  mode: "mock",
71
71
  mockFile: opts.mockAgent
@@ -74,7 +74,7 @@ async function runExecutaDev(opts) {
74
74
  account: opts.agentAccount ?? opts.samplingAccount,
75
75
  appSlug: effectiveAppSlug
76
76
  }) : new AgentBridge({ mode: "off" });
77
- const { StorageBridge } = await import("./storage-EQJA_0UW.js");
77
+ const { StorageBridge } = await import("./storage-CTkApNQ9.js");
78
78
  const storageMode = opts.storage ?? (opts.mockStorage ? "mock" : "memory");
79
79
  const storage = new StorageBridge({
80
80
  mode: storageMode,
@@ -84,8 +84,8 @@ async function runExecutaDev(opts) {
84
84
  scopes: opts.storageScopes ? opts.storageScopes.split(",").map((s) => s.trim()).filter(Boolean) : void 0,
85
85
  pluginName: parsed.tool_id
86
86
  });
87
- const { ExecutaRunner } = await import("./runner-DmGLdat0.js");
88
- const { ImageBridge } = await import("./image-bwolX7pa.js");
87
+ const { ExecutaRunner } = await import("./runner-B-hIqx5L.js");
88
+ const { ImageBridge } = await import("./image-DduR91n5.js");
89
89
  const image = opts.noImage ? new ImageBridge({ mode: "off" }) : opts.mockImage ? new ImageBridge({
90
90
  mode: "mock",
91
91
  mockFile: opts.mockImage
@@ -94,7 +94,7 @@ async function runExecutaDev(opts) {
94
94
  account: opts.imageAccount ?? opts.samplingAccount,
95
95
  appSlug: effectiveAppSlug
96
96
  }) : new ImageBridge({ mode: "off" });
97
- const { HostUploadBridge } = await import("./host_upload-C_pGOS6p.js");
97
+ const { HostUploadBridge } = await import("./host_upload-GXVkDM5M.js");
98
98
  const hostUpload = opts.noUpload ? new HostUploadBridge({ mode: "off" }) : opts.mockUpload ? new HostUploadBridge({
99
99
  mode: "mock",
100
100
  mockFile: opts.mockUpload
@@ -183,7 +183,7 @@ async function runOneShot(runner, opts, quiet) {
183
183
  }
184
184
  }
185
185
  async function runRepl(runner) {
186
- const rl = createInterface$1({
186
+ const rl = createInterface({
187
187
  input: process.stdin,
188
188
  output: process.stdout
189
189
  });
@@ -0,0 +1,9 @@
1
+ import "./credentials-BTv2IfUZ.js";
2
+ import "./client-Dn9zThOd.js";
3
+ import "./executas-Cep6KEo0.js";
4
+ import "./executa-cache-BFoUtb4J.js";
5
+ import { runExecutaPublish } from "./executa-publish-Ca5V7MyA.js";
6
+ import "./manifest-DGwRap2i.js";
7
+ import "./_lifecycle-shared-sbea9HtH.js";
8
+
9
+ export { runExecutaPublish };