@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
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import "./credentials-BTv2IfUZ.js";
|
|
2
|
+
import "./apps-B1Nd8l_t.js";
|
|
3
|
+
import { CliError } from "./client-Dn9zThOd.js";
|
|
4
|
+
import "./bundled-executas-BNOKw4kv.js";
|
|
5
|
+
import "./executas-Cep6KEo0.js";
|
|
6
|
+
import "./executa-cache-BFoUtb4J.js";
|
|
7
|
+
import { runExecutaPublish } from "./executa-publish-Ca5V7MyA.js";
|
|
8
|
+
import "./manifest-DGwRap2i.js";
|
|
9
|
+
import { withErrorHandling } from "./_lifecycle-shared-sbea9HtH.js";
|
|
10
|
+
import "./app-cache-BEM653Th.js";
|
|
11
|
+
import "./app-bundle-upload-DuLalcSt.js";
|
|
12
|
+
import { runAppsPublish } from "./apps-publish-CaTCanDu.js";
|
|
13
|
+
import { resolve } from "node:path";
|
|
14
|
+
import { existsSync } from "node:fs";
|
|
15
|
+
import { red, yellow } from "kleur/colors";
|
|
16
|
+
|
|
17
|
+
//#region src/publish/detector.ts
|
|
18
|
+
function detectProjectKind(cwd) {
|
|
19
|
+
const hasManifest = existsSync(resolve(cwd, "manifest.json"));
|
|
20
|
+
const hasExecuta = existsSync(resolve(cwd, "executa.json"));
|
|
21
|
+
if (hasManifest && hasExecuta) return "ambiguous";
|
|
22
|
+
if (hasManifest) return "app";
|
|
23
|
+
if (hasExecuta) return "executa";
|
|
24
|
+
return "unknown";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/commands/publish.ts
|
|
29
|
+
async function runTopLevelPublish(opts) {
|
|
30
|
+
return withErrorHandling(async () => {
|
|
31
|
+
const cwd = resolve(opts.cwd ?? process.cwd());
|
|
32
|
+
const kind = detectProjectKind(cwd);
|
|
33
|
+
if (kind === "ambiguous") throw new CliError(`cannot auto-detect: ${cwd} has BOTH manifest.json and executa.json. Run \`anna-app apps publish\` or \`anna-app executa publish\` explicitly.`, 4);
|
|
34
|
+
if (kind === "unknown") throw new CliError(`no manifest.json or executa.json found in ${cwd}`, 4);
|
|
35
|
+
if (kind === "app") return runAppsPublish({
|
|
36
|
+
cwd,
|
|
37
|
+
bump: opts.bump,
|
|
38
|
+
noWrite: opts.noWrite,
|
|
39
|
+
dryRun: opts.dryRun,
|
|
40
|
+
account: opts.account,
|
|
41
|
+
json: opts.json,
|
|
42
|
+
noBundle: opts.noBundle,
|
|
43
|
+
bundleDir: opts.bundleDir
|
|
44
|
+
});
|
|
45
|
+
return runExecutaPublish({
|
|
46
|
+
cwd,
|
|
47
|
+
bump: opts.bump,
|
|
48
|
+
noWrite: opts.noWrite,
|
|
49
|
+
publish: opts.publish,
|
|
50
|
+
dryRun: opts.dryRun,
|
|
51
|
+
account: opts.account,
|
|
52
|
+
json: opts.json
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
export { runTopLevelPublish };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { canonicalHost, getAccount } from "./credentials-BTv2IfUZ.js";
|
|
2
|
-
import { BridgeRequestError } from "./bridge-
|
|
2
|
+
import { BridgeRequestError } from "./bridge-BuklhzeE.js";
|
|
3
3
|
import { dirname, join, normalize, resolve } from "node:path";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { createReadStream, existsSync, readFileSync, statSync, watch } from "node:fs";
|
|
@@ -10,6 +10,90 @@ import { WebSocketServer } from "ws";
|
|
|
10
10
|
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
11
11
|
|
|
12
12
|
//#region src/harness/llm-bridge.ts
|
|
13
|
+
/** APS-mode ``storage`` methods the bridge forwards to ``/api/v1/storage/*``.
|
|
14
|
+
* ``get/set/delete/list`` are the KV family; ``files_*`` are the object/blob
|
|
15
|
+
* (APS Files) family, forwarded from an executa's ``files/*`` reverse-RPC. */
|
|
16
|
+
const STORAGE_APS_METHODS = new Set([
|
|
17
|
+
"get",
|
|
18
|
+
"set",
|
|
19
|
+
"delete",
|
|
20
|
+
"list",
|
|
21
|
+
"files_init",
|
|
22
|
+
"files_finalize",
|
|
23
|
+
"files_url",
|
|
24
|
+
"files_list",
|
|
25
|
+
"files_delete"
|
|
26
|
+
]);
|
|
27
|
+
/** APS Files method → ``[httpMethod, subPath, payloadKind]``. Mirrors
|
|
28
|
+
* `anna-app-cli/src/executa/storage.ts` ROUTING and matrix `storage.py`
|
|
29
|
+
* so the app-harness path round-trips identically to `executa dev`. */
|
|
30
|
+
const FILES_ROUTES = {
|
|
31
|
+
files_init: [
|
|
32
|
+
"POST",
|
|
33
|
+
"/files/init",
|
|
34
|
+
"body"
|
|
35
|
+
],
|
|
36
|
+
files_finalize: [
|
|
37
|
+
"POST",
|
|
38
|
+
"/files/finalize",
|
|
39
|
+
"body"
|
|
40
|
+
],
|
|
41
|
+
files_url: [
|
|
42
|
+
"GET",
|
|
43
|
+
"/files/url",
|
|
44
|
+
"query"
|
|
45
|
+
],
|
|
46
|
+
files_list: [
|
|
47
|
+
"GET",
|
|
48
|
+
"/files",
|
|
49
|
+
"query"
|
|
50
|
+
],
|
|
51
|
+
files_delete: [
|
|
52
|
+
"DELETE",
|
|
53
|
+
"/files",
|
|
54
|
+
"query"
|
|
55
|
+
]
|
|
56
|
+
};
|
|
57
|
+
/** App-direct ``anna.files.*`` method → ``[httpMethod, subPath, payloadKind]``.
|
|
58
|
+
* These are the iframe-facing method names (ns=``"files"``) the browser SDK
|
|
59
|
+
* emits via ``rt.call("files", method, args)``. Production nexus serves them
|
|
60
|
+
* through ``anna_app_rpc_handlers/files.py`` with ``scope="app"`` /
|
|
61
|
+
* ``owner_id=app_id`` (the handler ignores ``args.scope``); we force the same
|
|
62
|
+
* scope here so the harness round-trips identically. Distinct from
|
|
63
|
+
* ``FILES_ROUTES`` above, which is the executa reverse-RPC method naming
|
|
64
|
+
* (``files_init`` …) forwarded with the executa's own (default ``user``) scope. */
|
|
65
|
+
const FILES_APP_ROUTES = {
|
|
66
|
+
upload_init: [
|
|
67
|
+
"POST",
|
|
68
|
+
"/files/init",
|
|
69
|
+
"body"
|
|
70
|
+
],
|
|
71
|
+
upload_finalize: [
|
|
72
|
+
"POST",
|
|
73
|
+
"/files/finalize",
|
|
74
|
+
"body"
|
|
75
|
+
],
|
|
76
|
+
download_url: [
|
|
77
|
+
"GET",
|
|
78
|
+
"/files/url",
|
|
79
|
+
"query"
|
|
80
|
+
],
|
|
81
|
+
list: [
|
|
82
|
+
"GET",
|
|
83
|
+
"/files",
|
|
84
|
+
"query"
|
|
85
|
+
],
|
|
86
|
+
delete: [
|
|
87
|
+
"DELETE",
|
|
88
|
+
"/files",
|
|
89
|
+
"query"
|
|
90
|
+
]
|
|
91
|
+
};
|
|
92
|
+
const VALID_STORAGE_SCOPES = new Set([
|
|
93
|
+
"user",
|
|
94
|
+
"app",
|
|
95
|
+
"tool"
|
|
96
|
+
]);
|
|
13
97
|
var LlmBridge = class {
|
|
14
98
|
mintedAuto = new Map();
|
|
15
99
|
mintedAgent = new Map();
|
|
@@ -48,7 +132,8 @@ var LlmBridge = class {
|
|
|
48
132
|
if (ns === "agent" && method.startsWith("session.")) return true;
|
|
49
133
|
if (ns === "image" && (method === "generate" || method === "edit")) return true;
|
|
50
134
|
if (ns === "upload" && (method === "inline" || method === "negotiate" || method === "confirm")) return true;
|
|
51
|
-
if (ns === "storage" && this.opts.storageMode === "aps" && this.opts.mode === "real" && (method
|
|
135
|
+
if (ns === "storage" && this.opts.storageMode === "aps" && this.opts.mode === "real" && STORAGE_APS_METHODS.has(method)) return true;
|
|
136
|
+
if (ns === "files" && this.opts.storageMode === "aps" && this.opts.mode === "real" && Object.prototype.hasOwnProperty.call(FILES_APP_ROUTES, method)) return true;
|
|
52
137
|
return false;
|
|
53
138
|
}
|
|
54
139
|
/** Back-compat static alias — older code paths still call
|
|
@@ -503,6 +588,94 @@ var LlmBridge = class {
|
|
|
503
588
|
result: await res.json()
|
|
504
589
|
};
|
|
505
590
|
}
|
|
591
|
+
const froute = FILES_ROUTES[args.method];
|
|
592
|
+
if (froute) {
|
|
593
|
+
const [httpMethod, subPath, payloadKind] = froute;
|
|
594
|
+
const scope = typeof a.scope === "string" && VALID_STORAGE_SCOPES.has(a.scope) ? a.scope : "user";
|
|
595
|
+
const url = new URL(`${base}${subPath}`);
|
|
596
|
+
url.searchParams.set("scope", scope);
|
|
597
|
+
let jsonBody;
|
|
598
|
+
if (payloadKind === "query") for (const [k, v] of Object.entries(a)) {
|
|
599
|
+
if (k === "scope" || v === void 0 || v === null) continue;
|
|
600
|
+
url.searchParams.set(k, typeof v === "string" ? v : JSON.stringify(v));
|
|
601
|
+
}
|
|
602
|
+
else {
|
|
603
|
+
const inner = {};
|
|
604
|
+
for (const [k, v] of Object.entries(a)) {
|
|
605
|
+
if (k === "scope" || v === void 0) continue;
|
|
606
|
+
inner[k] = v;
|
|
607
|
+
}
|
|
608
|
+
jsonBody = JSON.stringify(inner);
|
|
609
|
+
}
|
|
610
|
+
const headers = { authorization: `Bearer ${sm.storageToken}` };
|
|
611
|
+
if (jsonBody !== void 0) headers["content-type"] = "application/json";
|
|
612
|
+
const res = await fetch(url, {
|
|
613
|
+
method: httpMethod,
|
|
614
|
+
headers,
|
|
615
|
+
body: jsonBody
|
|
616
|
+
});
|
|
617
|
+
if (!res.ok) {
|
|
618
|
+
const text = await res.text().catch(() => "");
|
|
619
|
+
throw new Error(`storage.${args.method} HTTP ${res.status}: ${text}`);
|
|
620
|
+
}
|
|
621
|
+
const ct = res.headers.get("content-type") ?? "";
|
|
622
|
+
if (args.method === "files_delete" && (res.status === 204 || !ct.includes("json"))) return {
|
|
623
|
+
ok: true,
|
|
624
|
+
result: { deleted: true }
|
|
625
|
+
};
|
|
626
|
+
return {
|
|
627
|
+
ok: true,
|
|
628
|
+
result: await res.json()
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
if (args.ns === "files") {
|
|
633
|
+
const froute = FILES_APP_ROUTES[args.method];
|
|
634
|
+
if (froute) {
|
|
635
|
+
const sm = await this.mintStorage();
|
|
636
|
+
const a = { ...args.args };
|
|
637
|
+
if (args.method === "upload_init" && a.size !== void 0 && a.size_bytes === void 0) {
|
|
638
|
+
a.size_bytes = a.size;
|
|
639
|
+
delete a.size;
|
|
640
|
+
}
|
|
641
|
+
const base = `${canonicalHost(this.account().host)}/api/v1/storage`;
|
|
642
|
+
const [httpMethod, subPath, payloadKind] = froute;
|
|
643
|
+
const url = new URL(`${base}${subPath}`);
|
|
644
|
+
url.searchParams.set("scope", "app");
|
|
645
|
+
let jsonBody;
|
|
646
|
+
if (payloadKind === "query") for (const [k, v] of Object.entries(a)) {
|
|
647
|
+
if (k === "scope" || v === void 0 || v === null) continue;
|
|
648
|
+
url.searchParams.set(k, typeof v === "string" ? v : JSON.stringify(v));
|
|
649
|
+
}
|
|
650
|
+
else {
|
|
651
|
+
const inner = {};
|
|
652
|
+
for (const [k, v] of Object.entries(a)) {
|
|
653
|
+
if (k === "scope" || v === void 0) continue;
|
|
654
|
+
inner[k] = v;
|
|
655
|
+
}
|
|
656
|
+
jsonBody = JSON.stringify(inner);
|
|
657
|
+
}
|
|
658
|
+
const headers = { authorization: `Bearer ${sm.storageToken}` };
|
|
659
|
+
if (jsonBody !== void 0) headers["content-type"] = "application/json";
|
|
660
|
+
const res = await fetch(url, {
|
|
661
|
+
method: httpMethod,
|
|
662
|
+
headers,
|
|
663
|
+
body: jsonBody
|
|
664
|
+
});
|
|
665
|
+
if (!res.ok) {
|
|
666
|
+
const text = await res.text().catch(() => "");
|
|
667
|
+
throw new Error(`files.${args.method} HTTP ${res.status}: ${text}`);
|
|
668
|
+
}
|
|
669
|
+
const ct = res.headers.get("content-type") ?? "";
|
|
670
|
+
if (args.method === "delete" && (res.status === 204 || !ct.includes("json"))) return {
|
|
671
|
+
ok: true,
|
|
672
|
+
result: { deleted: true }
|
|
673
|
+
};
|
|
674
|
+
return {
|
|
675
|
+
ok: true,
|
|
676
|
+
result: await res.json()
|
|
677
|
+
};
|
|
678
|
+
}
|
|
506
679
|
}
|
|
507
680
|
return {
|
|
508
681
|
ok: false,
|
|
@@ -728,6 +901,31 @@ var HarnessServer = class {
|
|
|
728
901
|
"host.storage.list",
|
|
729
902
|
"storage",
|
|
730
903
|
"list"
|
|
904
|
+
],
|
|
905
|
+
[
|
|
906
|
+
"host.storage.files_init",
|
|
907
|
+
"storage",
|
|
908
|
+
"files_init"
|
|
909
|
+
],
|
|
910
|
+
[
|
|
911
|
+
"host.storage.files_finalize",
|
|
912
|
+
"storage",
|
|
913
|
+
"files_finalize"
|
|
914
|
+
],
|
|
915
|
+
[
|
|
916
|
+
"host.storage.files_url",
|
|
917
|
+
"storage",
|
|
918
|
+
"files_url"
|
|
919
|
+
],
|
|
920
|
+
[
|
|
921
|
+
"host.storage.files_list",
|
|
922
|
+
"storage",
|
|
923
|
+
"files_list"
|
|
924
|
+
],
|
|
925
|
+
[
|
|
926
|
+
"host.storage.files_delete",
|
|
927
|
+
"storage",
|
|
928
|
+
"files_delete"
|
|
731
929
|
]
|
|
732
930
|
];
|
|
733
931
|
for (const [hostMethod, ns, dispatchMethod] of HOST_OUTBOUND_ROUTES) this.bridge.onRequest(hostMethod, async (params) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { canonicalHost } from "./credentials-BTv2IfUZ.js";
|
|
2
|
-
import { hostOf, requireAccount, withCode } from "./dev-account-
|
|
2
|
+
import { hostOf, requireAccount, withCode } from "./dev-account-qRaET1Cp.js";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
import { existsSync, readFileSync } from "node:fs";
|
|
5
5
|
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import "./credentials-BTv2IfUZ.js";
|
|
2
|
+
import "./client-Dn9zThOd.js";
|
|
3
|
+
import { resolveClient, withErrorHandling } from "./_lifecycle-shared-sbea9HtH.js";
|
|
4
|
+
import { bold, cyan, dim, green, red, yellow } from "kleur/colors";
|
|
5
|
+
|
|
6
|
+
//#region src/api/tokens.ts
|
|
7
|
+
async function listTokens(client, includeRevoked = false) {
|
|
8
|
+
const r = await client.request({
|
|
9
|
+
path: "/api/v1/anna-apps/dev/tokens",
|
|
10
|
+
query: { include_revoked: includeRevoked ? "true" : void 0 }
|
|
11
|
+
});
|
|
12
|
+
return r.data?.tokens ?? [];
|
|
13
|
+
}
|
|
14
|
+
async function revokeToken(client, id) {
|
|
15
|
+
await client.request({
|
|
16
|
+
method: "POST",
|
|
17
|
+
path: `/api/v1/anna-apps/dev/tokens/${id}/revoke`,
|
|
18
|
+
allowStatuses: [204]
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
async function listScopes(client) {
|
|
22
|
+
const r = await client.request({ path: "/api/v1/anna-apps/dev/tokens/scopes" });
|
|
23
|
+
return r.data?.scopes ?? [];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/commands/token.ts
|
|
28
|
+
async function runTokenList(opts) {
|
|
29
|
+
return withErrorHandling(async () => {
|
|
30
|
+
const { client, host } = resolveClient({ account: opts.account });
|
|
31
|
+
const tokens = await listTokens(client, opts.includeRevoked ?? false);
|
|
32
|
+
if (opts.json) {
|
|
33
|
+
console.log(JSON.stringify({
|
|
34
|
+
host,
|
|
35
|
+
tokens
|
|
36
|
+
}, null, 2));
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
console.log(bold(cyan(`PATs for ${host}`)));
|
|
40
|
+
if (tokens.length === 0) {
|
|
41
|
+
console.log(dim(` (no tokens — run \`anna-app login\` to mint one)`));
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
for (const t of tokens) {
|
|
45
|
+
const scopes = Array.isArray(t.scopes) ? t.scopes.join(",") : t.scopes ?? "";
|
|
46
|
+
const tag = t.revoked_at ? red("[revoked]") : green("[active]");
|
|
47
|
+
const label = t.label ? ` "${t.label}"` : "";
|
|
48
|
+
console.log(` ${tag} #${t.id}${label} ${dim(`(scopes=[${scopes}], jti=${t.jti})`)}`);
|
|
49
|
+
}
|
|
50
|
+
return 0;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async function runTokenRevoke(opts) {
|
|
54
|
+
return withErrorHandling(async () => {
|
|
55
|
+
const { client, host } = resolveClient({ account: opts.account });
|
|
56
|
+
await revokeToken(client, opts.id);
|
|
57
|
+
if (opts.json) {
|
|
58
|
+
console.log(JSON.stringify({
|
|
59
|
+
host,
|
|
60
|
+
token_id: opts.id,
|
|
61
|
+
revoked: true
|
|
62
|
+
}, null, 2));
|
|
63
|
+
return 0;
|
|
64
|
+
}
|
|
65
|
+
console.log(yellow(`✓ token #${opts.id} revoked on ${host}`));
|
|
66
|
+
return 0;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
async function runTokenScopes(opts) {
|
|
70
|
+
return withErrorHandling(async () => {
|
|
71
|
+
const { client, host } = resolveClient({ account: opts.account });
|
|
72
|
+
const scopes = await listScopes(client);
|
|
73
|
+
if (opts.json) {
|
|
74
|
+
console.log(JSON.stringify({
|
|
75
|
+
host,
|
|
76
|
+
scopes
|
|
77
|
+
}, null, 2));
|
|
78
|
+
return 0;
|
|
79
|
+
}
|
|
80
|
+
console.log(bold(cyan(`available PAT scopes`)) + " " + dim(`(${host})`));
|
|
81
|
+
for (const s of scopes) console.log(` ${green(s.name.padEnd(18))} ${dim(s.description)}`);
|
|
82
|
+
return 0;
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
//#endregion
|
|
87
|
+
export { runTokenList, runTokenRevoke, runTokenScopes };
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { canonicalHost } from "./credentials-BTv2IfUZ.js";
|
|
2
|
+
import { createApp, findAppBySlug, getApp } from "./apps-B1Nd8l_t.js";
|
|
3
|
+
import { CliError } from "./client-Dn9zThOd.js";
|
|
4
|
+
import { parseExecutaIdOverrides, readExecutasLock, substituteBundledRefs, validateBundledHandles, writeBundleToolIdSidecar, writeExecutasLock } from "./bundled-executas-BNOKw4kv.js";
|
|
5
|
+
import { runExecutaPublish } from "./executa-publish-Ca5V7MyA.js";
|
|
6
|
+
import { appCacheMatches, readAppIdentity, writeAppIdentity } from "./app-cache-BEM653Th.js";
|
|
7
|
+
import { resolve } from "node:path";
|
|
8
|
+
import { dim, green, yellow } from "kleur/colors";
|
|
9
|
+
|
|
10
|
+
//#region src/publish/working-orchestration.ts
|
|
11
|
+
async function resolveBundledExecutas(params) {
|
|
12
|
+
const { manifest, cwd, host, dryRun = false, freeze, json = false } = params;
|
|
13
|
+
const overrides = parseExecutaIdOverrides(params.executaId);
|
|
14
|
+
const active = !params.noBundledExecutas && (manifest.bundledExecutas.length > 0 || overrides.length > 0);
|
|
15
|
+
if (!active) return {
|
|
16
|
+
publishManifestRaw: manifest.raw,
|
|
17
|
+
resolved: {}
|
|
18
|
+
};
|
|
19
|
+
const { referenced } = validateBundledHandles(manifest.raw, manifest.bundledExecutas, overrides);
|
|
20
|
+
const overrideMap = new Map(overrides.map((o) => [o.handle, o.toolId]));
|
|
21
|
+
const lock = readExecutasLock(cwd, host);
|
|
22
|
+
const resolved = {};
|
|
23
|
+
const lockEntries = {};
|
|
24
|
+
for (const decl of manifest.bundledExecutas) {
|
|
25
|
+
if (overrideMap.has(decl.handle)) {
|
|
26
|
+
const id = overrideMap.get(decl.handle);
|
|
27
|
+
resolved[decl.handle] = id;
|
|
28
|
+
lockEntries[decl.handle] = {
|
|
29
|
+
tool_id: id,
|
|
30
|
+
path: decl.path,
|
|
31
|
+
source: "override"
|
|
32
|
+
};
|
|
33
|
+
if (!json) console.log(dim(` bundled:${decl.handle} → ${id} (override)`));
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (params.skipExecutaPublish) {
|
|
37
|
+
const cachedId = lock?.executas[decl.handle]?.tool_id;
|
|
38
|
+
if (!cachedId) throw new CliError(`--skip-executa-publish set but no cached tool_id for "${decl.handle}" in .anna/executas.lock.json (run without --skip-executa-publish first, or pass --executa-id ${decl.handle}=<tool-id>)`, 4);
|
|
39
|
+
resolved[decl.handle] = cachedId;
|
|
40
|
+
lockEntries[decl.handle] = {
|
|
41
|
+
tool_id: cachedId,
|
|
42
|
+
path: decl.path,
|
|
43
|
+
source: "cache"
|
|
44
|
+
};
|
|
45
|
+
if (!json) console.log(dim(` bundled:${decl.handle} → ${cachedId} (cache)`));
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const execCwd = resolve(cwd, decl.path);
|
|
49
|
+
if (dryRun) {
|
|
50
|
+
if (!json) console.log(yellow(` [dry-run] would publish bundled executa "${decl.handle}" from ${decl.path}`));
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (!json) console.log(dim(` ${freeze ? "publishing" : "registering"} bundled executa "${decl.handle}" (${decl.path})${freeze ? "" : " [no-freeze]"}…`));
|
|
54
|
+
let captured;
|
|
55
|
+
const code = await runExecutaPublish({
|
|
56
|
+
cwd: execCwd,
|
|
57
|
+
account: params.account,
|
|
58
|
+
quiet: true,
|
|
59
|
+
freeze,
|
|
60
|
+
capture: (r) => {
|
|
61
|
+
captured = r;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
if (code !== 0 || !captured) throw new CliError(`failed to ${freeze ? "publish" : "register"} bundled executa "${decl.handle}" (${decl.path})`, code === 0 ? 4 : code);
|
|
65
|
+
resolved[decl.handle] = captured.tool_id;
|
|
66
|
+
lockEntries[decl.handle] = {
|
|
67
|
+
tool_id: captured.tool_id,
|
|
68
|
+
path: decl.path,
|
|
69
|
+
source: params.lockSource ?? (freeze ? "published" : "working")
|
|
70
|
+
};
|
|
71
|
+
if (!json) console.log(green(` ✓ bundled:${decl.handle} → ${captured.tool_id}`) + dim(` (v${captured.version}${captured.idempotent_hit ? ", unchanged" : ""})`));
|
|
72
|
+
}
|
|
73
|
+
for (const o of overrides) if (!(o.handle in resolved)) {
|
|
74
|
+
resolved[o.handle] = o.toolId;
|
|
75
|
+
lockEntries[o.handle] = {
|
|
76
|
+
tool_id: o.toolId,
|
|
77
|
+
source: "override"
|
|
78
|
+
};
|
|
79
|
+
if (!json) console.log(dim(` bundled:${o.handle} → ${o.toolId} (override)`));
|
|
80
|
+
}
|
|
81
|
+
const missing = [...referenced].filter((h) => !(h in resolved));
|
|
82
|
+
if (missing.length > 0 && !dryRun) throw new CliError(`could not resolve bundled handle(s): ${missing.sort().join(", ")}`, 4);
|
|
83
|
+
let publishManifestRaw = manifest.raw;
|
|
84
|
+
if (!dryRun) {
|
|
85
|
+
const merged = {
|
|
86
|
+
$schema: "anna-executas-lock/v1",
|
|
87
|
+
host: canonicalHost(host),
|
|
88
|
+
executas: {
|
|
89
|
+
...lock?.executas ?? {},
|
|
90
|
+
...lockEntries
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
writeExecutasLock(cwd, merged);
|
|
94
|
+
publishManifestRaw = substituteBundledRefs(manifest.raw, resolved);
|
|
95
|
+
const bundleEntry = manifest.raw.ui?.bundle?.entry;
|
|
96
|
+
if (bundleEntry && Object.keys(resolved).length > 0) {
|
|
97
|
+
const sidecar = writeBundleToolIdSidecar(resolve(cwd, "bundle"), resolved);
|
|
98
|
+
if (!json) console.log(dim(` wrote ${sidecar.replace(cwd + "/", "")}`));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
publishManifestRaw,
|
|
103
|
+
resolved
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Resolve (creating if absent) the `AnnaApp` row, persisting the identity
|
|
108
|
+
* cache before any subsequent network call. Returns `null` only in dry-run
|
|
109
|
+
* mode when the app does not exist yet (nothing to create).
|
|
110
|
+
*/
|
|
111
|
+
async function resolveAppIdentity(params) {
|
|
112
|
+
const { client, cwd, host, manifest, dryRun = false, json = false } = params;
|
|
113
|
+
let cached = readAppIdentity(cwd);
|
|
114
|
+
if (cached && cached.host !== canonicalHost(host)) cached = null;
|
|
115
|
+
if (cached && appCacheMatches(cached, host, manifest.slug)) try {
|
|
116
|
+
const live = await getApp(client, cached.app_id);
|
|
117
|
+
return {
|
|
118
|
+
appId: live.id,
|
|
119
|
+
serverSlug: live.slug,
|
|
120
|
+
firstPublish: false,
|
|
121
|
+
fromCache: true
|
|
122
|
+
};
|
|
123
|
+
} catch (e) {
|
|
124
|
+
if (!(e instanceof CliError && e.status === 404)) throw e;
|
|
125
|
+
if (!json) console.log(yellow(`↻ cached app_id=${cached.app_id} (slug=${cached.slug}) no longer exists on ${host}; re-resolving by slug…`));
|
|
126
|
+
}
|
|
127
|
+
const found = await findAppBySlug(client, manifest.slug);
|
|
128
|
+
let appId;
|
|
129
|
+
let serverSlug;
|
|
130
|
+
let firstPublish = false;
|
|
131
|
+
if (found) {
|
|
132
|
+
appId = found.id;
|
|
133
|
+
serverSlug = found.slug;
|
|
134
|
+
} else {
|
|
135
|
+
if (dryRun) {
|
|
136
|
+
if (!json) console.log(yellow(`[dry-run] would create AnnaApp slug=${manifest.slug}`));
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
const created = await createApp(client, {
|
|
140
|
+
slug: manifest.slug,
|
|
141
|
+
name: manifest.name,
|
|
142
|
+
category: manifest.category,
|
|
143
|
+
tagline: manifest.tagline,
|
|
144
|
+
description: manifest.description
|
|
145
|
+
});
|
|
146
|
+
appId = created.id;
|
|
147
|
+
serverSlug = created.slug;
|
|
148
|
+
firstPublish = true;
|
|
149
|
+
}
|
|
150
|
+
writeAppIdentity(cwd, {
|
|
151
|
+
$schema: "anna-app-identity/v1",
|
|
152
|
+
host: canonicalHost(host),
|
|
153
|
+
app_id: appId,
|
|
154
|
+
slug: serverSlug,
|
|
155
|
+
first_published_at: cached?.first_published_at ?? new Date().toISOString()
|
|
156
|
+
});
|
|
157
|
+
return {
|
|
158
|
+
appId,
|
|
159
|
+
serverSlug,
|
|
160
|
+
firstPublish,
|
|
161
|
+
fromCache: false
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Resolve an EXISTING app via an explicit `slug` or the local
|
|
166
|
+
* `.anna/app.json` identity cache (no create). Used by verbs that operate on
|
|
167
|
+
* an already-pushed app (`cut`, `discard`). Throws `CliError(…, 5)` when the
|
|
168
|
+
* app cannot be resolved.
|
|
169
|
+
*/
|
|
170
|
+
async function resolveAppBySlugOrCache(client, host, opts) {
|
|
171
|
+
if (opts.slug) {
|
|
172
|
+
const app = await findAppBySlug(client, opts.slug);
|
|
173
|
+
if (!app) throw new CliError(`no app with slug "${opts.slug}" on ${host}`, 5);
|
|
174
|
+
return getApp(client, app.id);
|
|
175
|
+
}
|
|
176
|
+
const cwd = resolve(opts.cwd ?? process.cwd());
|
|
177
|
+
const cached = readAppIdentity(cwd);
|
|
178
|
+
if (cached && cached.host === canonicalHost(host)) try {
|
|
179
|
+
return await getApp(client, cached.app_id);
|
|
180
|
+
} catch (e) {
|
|
181
|
+
if (e instanceof CliError && e.status === 404) {
|
|
182
|
+
const app = await findAppBySlug(client, cached.slug);
|
|
183
|
+
if (app) return getApp(client, app.id);
|
|
184
|
+
} else throw e;
|
|
185
|
+
}
|
|
186
|
+
throw new CliError("cannot resolve app — pass --slug <slug> or run from a project dir with a .anna/app.json cache (run `anna-app apps push` first)", 5);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
//#endregion
|
|
190
|
+
export { resolveAppBySlugOrCache, resolveAppIdentity, resolveBundledExecutas };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anna-ai/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.21",
|
|
4
4
|
"description": "Anna App developer CLI: scaffold, validate, harness (Phase 2 MVP: init + validate).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"prepublishOnly": "pnpm lint && pnpm test && pnpm build"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@anna-ai/app-runtime": "^0.
|
|
36
|
-
"@anna-ai/app-schema": "^0.
|
|
35
|
+
"@anna-ai/app-runtime": "^0.5.0",
|
|
36
|
+
"@anna-ai/app-schema": "^0.8.0",
|
|
37
37
|
"ajv": "^8.17.1",
|
|
38
38
|
"ajv-formats": "^3.0.1",
|
|
39
39
|
"commander": "^12.1.0",
|
package/dist/apps-ClgEOdKD.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { getAccount } from "./credentials-BTv2IfUZ.js";
|
|
2
|
-
import { listDevApps } from "./dev-app-cache-3Pfesngr.js";
|
|
3
|
-
import { bold, cyan, dim, green, red, yellow } from "kleur/colors";
|
|
4
|
-
|
|
5
|
-
//#region src/commands/apps.ts
|
|
6
|
-
async function runAppsList(opts) {
|
|
7
|
-
const acc = getAccount(opts.account);
|
|
8
|
-
if (!acc) {
|
|
9
|
-
console.error(red("✗ no PAT on disk — run `anna-app login --host <nexus-url>` first."));
|
|
10
|
-
return 2;
|
|
11
|
-
}
|
|
12
|
-
let apps;
|
|
13
|
-
try {
|
|
14
|
-
apps = await listDevApps({
|
|
15
|
-
host: acc.host,
|
|
16
|
-
pat: acc.pat
|
|
17
|
-
});
|
|
18
|
-
} catch (e) {
|
|
19
|
-
console.error(red(`✗ ${e.message}`));
|
|
20
|
-
return 2;
|
|
21
|
-
}
|
|
22
|
-
if (opts.json) {
|
|
23
|
-
console.log(JSON.stringify({
|
|
24
|
-
host: acc.host,
|
|
25
|
-
apps
|
|
26
|
-
}, null, 2));
|
|
27
|
-
return 0;
|
|
28
|
-
}
|
|
29
|
-
console.log(bold(cyan("dev apps installed for")) + " " + cyan(acc.host));
|
|
30
|
-
if (apps.length === 0) {
|
|
31
|
-
console.log(dim(" (none — run `anna-app dev` in a project to register one)"));
|
|
32
|
-
return 0;
|
|
33
|
-
}
|
|
34
|
-
for (const a of apps) {
|
|
35
|
-
const tag = a.is_dev ? yellow("[dev]") : green("[prod]");
|
|
36
|
-
const enabled = a.is_enabled ? green("✓") : red("✗");
|
|
37
|
-
console.log(` ${tag} ${enabled} ${bold(a.slug)} ${dim(`(app_id=${a.app_id}, v=${a.installed_version})`)}`);
|
|
38
|
-
if (a.name && a.name !== a.slug) console.log(` ${dim(a.name)}`);
|
|
39
|
-
}
|
|
40
|
-
return 0;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
//#endregion
|
|
44
|
-
export { runAppsList };
|
package/dist/bridge-B3Vwr4cg.js
DELETED
package/dist/dev-D8o7xi0W.js
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import "./credentials-BTv2IfUZ.js";
|
|
2
|
-
import { ensureDevAppRegistered, ensureDevExecutaRegistered, invalidateDevAppCache, listDevApps, readDevAppCache, readDevExecutaCache, registerDevApp, registerDevExecuta, writeDevAppCache, writeDevExecutaCache } from "./dev-app-cache-3Pfesngr.js";
|
|
3
|
-
|
|
4
|
-
export { ensureDevAppRegistered, ensureDevExecutaRegistered, invalidateDevAppCache };
|