@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
|
@@ -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-
|
|
47
|
-
const { HarnessServer } = await import("./server-
|
|
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-
|
|
140
|
-
const { ensureDevAppRegistered } = await import("./dev-app-cache-
|
|
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-
|
|
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":
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
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
|
|
382
|
+
if (!scripts || typeof scripts !== "object") return null;
|
|
303
383
|
const keys = Object.keys(scripts);
|
|
304
|
-
if (keys.length === 0) return
|
|
305
|
-
|
|
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)
|
|
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
|
|
198
|
+
export { ensureDevAppRegistered, ensureDevExecutaRegistered, invalidateDevAppCache };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PINNED_RUNTIME_VERSION } from "./bridge-
|
|
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,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-
|
|
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-
|
|
37
|
-
const { ensureDevExecutaRegistered } = await import("./dev-app-cache-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
88
|
-
const { ImageBridge } = await import("./image-
|
|
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-
|
|
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
|
|
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 };
|