@anna-ai/cli 0.1.22 → 0.1.26
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 → _lifecycle-shared-BpSOfVCP.js} +1 -1
- package/dist/{agent-Br6zY2qw.js → agent-CaZVCPs6.js} +1 -1
- package/dist/{app-bundle-upload-DuLalcSt.js → app-bundle-upload-BhAYo6yj.js} +3 -3
- package/dist/{apps-BTn9EN0x.js → apps-3VcdHIBK.js} +3 -3
- package/dist/{apps-cut-DtEkddIk.js → apps-cut-BCicQFRY.js} +13 -10
- package/dist/{apps-destructive-DSTrcFUP.js → apps-destructive-DWF4eTHn.js} +4 -4
- package/dist/{apps-discard-y3_IwcbQ.js → apps-discard-BoY4zMJw.js} +13 -10
- package/dist/{apps-grants-BGWlpee0.js → apps-grants-DgvymPBT.js} +3 -3
- package/dist/{apps-publish-CaTCanDu.js → apps-publish-Dgi4lBlu.js} +8 -8
- package/dist/apps-publish-Do7M5je3.js +14 -0
- package/dist/{apps-push-B9XT2uwF.js → apps-push-CixatuQG.js} +27 -12
- package/dist/{apps-release-BLH9XSxB.js → apps-release-DJFG4BV3.js} +5 -5
- package/dist/{apps-status-DQ9RvlME.js → apps-status-F6aVlzDW.js} +3 -3
- package/dist/{apps-submit-review-DLwCxeAs.js → apps-submit-review-BVmZlhmB.js} +4 -4
- package/dist/{apps-sync-meta-D9eKMMUp.js → apps-sync-meta-CQQC_Heb.js} +5 -5
- package/dist/{apps-versions-2Tmk0nsx.js → apps-versions-BIKsJzIT.js} +3 -3
- package/dist/{bridge-BuklhzeE.js → bridge-DxBd0Fl9.js} +1 -1
- package/dist/bridge-hzqNFm9-.js +3 -0
- package/dist/{bundled-executas-BNOKw4kv.js → bundled-executas-B6b8gIfp.js} +1 -1
- package/dist/{bundled-executas-CNaV2C_O.js → bundled-executas-DeBhDjd8.js} +2 -2
- package/dist/cli.js +70 -48
- package/dist/{confirm-DxHkk9Wn.js → confirm-h_qMrx0I.js} +1 -1
- package/dist/{dev-E7mqXj5S.js → dev-3okZmzNM.js} +19 -22
- package/dist/dev-C5r439wM.js +4 -0
- package/dist/{doctor-DKrt-Kda.js → doctor-giNqYnla.js} +10 -22
- package/dist/{executa-cache-WBkCLic7.js → executa-cache-Kx3rfQD-.js} +1 -1
- package/dist/{executa-destructive-COQE4Xqi.js → executa-destructive-PL2ooHpZ.js} +4 -4
- package/dist/{executa-dev-BvS9zTpO.js → executa-dev-Cr9Yepph.js} +10 -9
- package/dist/executa-install-DQIhVHPT.js +90 -0
- package/dist/executa-install-DjXE_-U-.js +7 -0
- package/dist/{executa-publish-Ca5V7MyA.js → executa-publish-CkPAB34b.js} +5 -5
- package/dist/executa-publish-IXWSwva0.js +9 -0
- package/dist/{executa-reads-CQ6S8gHY.js → executa-reads-CjGZq1yP.js} +3 -3
- package/dist/{manifest-DGwRap2i.js → manifest-Bljz8Y6T.js} +74 -15
- package/dist/nexus-root-BlPwOusj.js +49 -0
- package/dist/{publish-C1wcf-qI.js → publish-BYWuujP3.js} +11 -11
- package/dist/{server-_IG8Igje.js → server-Cp7mYV9t.js} +50 -8
- package/dist/{storage-CTkApNQ9.js → storage-CKTmE87u.js} +1 -1
- package/dist/test/index.js +3 -0
- package/dist/{token-B9JUPelx.js → token-Cg7BZGp6.js} +2 -2
- package/dist/{working-orchestration-Dw9u1Vq0.js → working-orchestration-Dd1ETQ3c.js} +54 -7
- package/package.json +5 -4
- package/templates/executa/go/main.go +4 -2
- package/templates/executa/node/plugin.mjs +4 -2
- package/templates/executa/python/__SLUG_PY___plugin.py +4 -2
- package/dist/apps-publish-DfZTOxBJ.js +0 -14
- package/dist/bridge-Id8K8gr-.js +0 -3
- package/dist/dev-BS_8yoSm.js +0 -3
- package/dist/executa-publish-B88_9gbp.js +0 -9
- /package/dist/{app-cache-BEM653Th.js → app-cache-Bl7cE5fm.js} +0 -0
- /package/dist/{apps-B1Nd8l_t.js → apps-CCdtLmxQ.js} +0 -0
- /package/dist/{client-Dn9zThOd.js → client-D-_z1ALk.js} +0 -0
- /package/dist/{credentials-DklPMD22.js → credentials-Chkoidh5.js} +0 -0
- /package/dist/{dev-account-qRaET1Cp.js → dev-account-CGo8k9_2.js} +0 -0
- /package/dist/{dev-app-cache-D-r6ZpEk.js → dev-app-cache-TSjL4D4n.js} +0 -0
- /package/dist/{executa-cache-BFoUtb4J.js → executa-cache-CXiEgFZY.js} +0 -0
- /package/dist/{executa-init-Jp-h9OI7.js → executa-init-DXea7yRN.js} +0 -0
- /package/dist/{executa-register-CulDtwYZ.js → executa-register-BUiPzPIU.js} +0 -0
- /package/dist/{executas-Cep6KEo0.js → executas-CK3er6f9.js} +0 -0
- /package/dist/{fixture-CYwxbiQD.js → fixture-BvP5umlN.js} +0 -0
- /package/dist/{host_upload-GXVkDM5M.js → host_upload-BXeHTgJs.js} +0 -0
- /package/dist/{image-DduR91n5.js → image-CSEXEfD-.js} +0 -0
- /package/dist/{login-BGqFjQwH.js → login-BGZjMAlh.js} +0 -0
- /package/dist/{logout-CGIRKH3y.js → logout-mh2_QlyM.js} +0 -0
- /package/dist/{runner-B-hIqx5L.js → runner-BuYbm-ex.js} +0 -0
- /package/dist/{sampling-CXke7hq1.js → sampling-BcML4teS.js} +0 -0
- /package/dist/{whoami-BoFLEUcp.js → whoami-l_kIkfbI.js} +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "./nexus-root-BlPwOusj.js";
|
|
2
|
+
import { parseExecutaSpec } from "./dev-3okZmzNM.js";
|
|
2
3
|
import { isAbsolute, resolve } from "node:path";
|
|
3
4
|
import { existsSync } from "node:fs";
|
|
4
5
|
import { bold, cyan, dim, green, red, yellow } from "kleur/colors";
|
|
@@ -33,8 +34,8 @@ async function runExecutaDev(opts) {
|
|
|
33
34
|
}
|
|
34
35
|
const oneShot = !!(opts.describe || opts.health || opts.invoke);
|
|
35
36
|
const quiet = oneShot && (opts.json ?? false);
|
|
36
|
-
const { getAccount } = await import("./credentials-
|
|
37
|
-
const { ensureDevExecutaRegistered } = await import("./dev-app-cache-
|
|
37
|
+
const { getAccount } = await import("./credentials-Chkoidh5.js");
|
|
38
|
+
const { ensureDevExecutaRegistered } = await import("./dev-app-cache-TSjL4D4n.js");
|
|
38
39
|
const needsRealMint = !opts.noSampling && !opts.mockSampling || !opts.noAgent && !opts.mockAgent || !opts.noImage && !opts.mockImage || !opts.noUpload && !opts.mockUpload || opts.storage === "real";
|
|
39
40
|
let effectiveAppSlug = opts.appSlug;
|
|
40
41
|
let autoRegistered = false;
|
|
@@ -56,7 +57,7 @@ async function runExecutaDev(opts) {
|
|
|
56
57
|
}
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
|
-
const { SamplingBridge } = await import("./sampling-
|
|
60
|
+
const { SamplingBridge } = await import("./sampling-BcML4teS.js");
|
|
60
61
|
const sampling = opts.noSampling ? new SamplingBridge({ mode: "off" }) : opts.mockSampling ? new SamplingBridge({
|
|
61
62
|
mode: "mock",
|
|
62
63
|
mockFile: opts.mockSampling
|
|
@@ -65,7 +66,7 @@ async function runExecutaDev(opts) {
|
|
|
65
66
|
account: opts.samplingAccount,
|
|
66
67
|
appSlug: effectiveAppSlug
|
|
67
68
|
}) : new SamplingBridge({ mode: "off" });
|
|
68
|
-
const { AgentBridge } = await import("./agent-
|
|
69
|
+
const { AgentBridge } = await import("./agent-CaZVCPs6.js");
|
|
69
70
|
const agent = opts.noAgent ? new AgentBridge({ mode: "off" }) : opts.mockAgent ? new AgentBridge({
|
|
70
71
|
mode: "mock",
|
|
71
72
|
mockFile: opts.mockAgent
|
|
@@ -74,7 +75,7 @@ async function runExecutaDev(opts) {
|
|
|
74
75
|
account: opts.agentAccount ?? opts.samplingAccount,
|
|
75
76
|
appSlug: effectiveAppSlug
|
|
76
77
|
}) : new AgentBridge({ mode: "off" });
|
|
77
|
-
const { StorageBridge } = await import("./storage-
|
|
78
|
+
const { StorageBridge } = await import("./storage-CKTmE87u.js");
|
|
78
79
|
const storageMode = opts.storage ?? (opts.mockStorage ? "mock" : "memory");
|
|
79
80
|
const storage = new StorageBridge({
|
|
80
81
|
mode: storageMode,
|
|
@@ -84,8 +85,8 @@ async function runExecutaDev(opts) {
|
|
|
84
85
|
scopes: opts.storageScopes ? opts.storageScopes.split(",").map((s) => s.trim()).filter(Boolean) : void 0,
|
|
85
86
|
pluginName: parsed.tool_id
|
|
86
87
|
});
|
|
87
|
-
const { ExecutaRunner } = await import("./runner-
|
|
88
|
-
const { ImageBridge } = await import("./image-
|
|
88
|
+
const { ExecutaRunner } = await import("./runner-BuYbm-ex.js");
|
|
89
|
+
const { ImageBridge } = await import("./image-CSEXEfD-.js");
|
|
89
90
|
const image = opts.noImage ? new ImageBridge({ mode: "off" }) : opts.mockImage ? new ImageBridge({
|
|
90
91
|
mode: "mock",
|
|
91
92
|
mockFile: opts.mockImage
|
|
@@ -94,7 +95,7 @@ async function runExecutaDev(opts) {
|
|
|
94
95
|
account: opts.imageAccount ?? opts.samplingAccount,
|
|
95
96
|
appSlug: effectiveAppSlug
|
|
96
97
|
}) : new ImageBridge({ mode: "off" });
|
|
97
|
-
const { HostUploadBridge } = await import("./host_upload-
|
|
98
|
+
const { HostUploadBridge } = await import("./host_upload-BXeHTgJs.js");
|
|
98
99
|
const hostUpload = opts.noUpload ? new HostUploadBridge({ mode: "off" }) : opts.mockUpload ? new HostUploadBridge({
|
|
99
100
|
mode: "mock",
|
|
100
101
|
mockFile: opts.mockUpload
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { readExecutaIdentity } from "./executa-cache-CXiEgFZY.js";
|
|
2
|
+
import { parseExecutaSpec } from "./dev-3okZmzNM.js";
|
|
3
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
4
|
+
import { chmodSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { bold, cyan, dim, green, red, yellow } from "kleur/colors";
|
|
6
|
+
import { homedir } from "node:os";
|
|
7
|
+
|
|
8
|
+
//#region src/commands/executa-install.ts
|
|
9
|
+
/** POSIX single-quote one argument for safe embedding in the shim. */
|
|
10
|
+
function shQuote(arg) {
|
|
11
|
+
return `'${arg.replace(/'/g, "'\\''")}'`;
|
|
12
|
+
}
|
|
13
|
+
function buildShim(projectDir, command) {
|
|
14
|
+
const cd = `cd ${shQuote(projectDir)} || exit 1`;
|
|
15
|
+
const exec = `exec ${command.map(shQuote).join(" ")} "$@"`;
|
|
16
|
+
return [
|
|
17
|
+
"#!/bin/sh",
|
|
18
|
+
"# Auto-generated by `anna-app executa install`.",
|
|
19
|
+
"# Local-dev launcher shim — runs the Executa from source so the Agent",
|
|
20
|
+
"# can discover it via 'Rediscover Local'. Safe to delete; regenerate",
|
|
21
|
+
"# with `anna-app executa install`.",
|
|
22
|
+
cd,
|
|
23
|
+
exec,
|
|
24
|
+
""
|
|
25
|
+
].join("\n");
|
|
26
|
+
}
|
|
27
|
+
async function runExecutaInstall(opts) {
|
|
28
|
+
const json = opts.json ?? false;
|
|
29
|
+
const cwd = opts.dir ? isAbsolute(opts.dir) ? opts.dir : resolve(process.cwd(), opts.dir) : process.cwd();
|
|
30
|
+
if (!existsSync(cwd)) {
|
|
31
|
+
console.error(red(`✗ executa dir not found: ${cwd}`));
|
|
32
|
+
return 2;
|
|
33
|
+
}
|
|
34
|
+
const parsed = parseExecutaSpec(`dir=${cwd}`, process.cwd());
|
|
35
|
+
if (parsed instanceof Error) {
|
|
36
|
+
console.error(red(`✗ ${parsed.message}`));
|
|
37
|
+
return 2;
|
|
38
|
+
}
|
|
39
|
+
if (!parsed.command || parsed.command.length === 0) {
|
|
40
|
+
console.error(red(`✗ could not derive a launch command for ${cwd}`));
|
|
41
|
+
return 2;
|
|
42
|
+
}
|
|
43
|
+
const identity = readExecutaIdentity(cwd);
|
|
44
|
+
const targetId = opts.toolId ?? identity?.tool_id ?? parsed.tool_id;
|
|
45
|
+
if (!targetId) {
|
|
46
|
+
console.error(red("✗ could not resolve a tool_id — pass --tool-id <id>, or run `anna-app executa publish` / `anna-app apps push` first to mint one."));
|
|
47
|
+
return 2;
|
|
48
|
+
}
|
|
49
|
+
if (/[/\\]/.test(targetId) || targetId.startsWith(".")) {
|
|
50
|
+
console.error(red(`✗ invalid tool_id "${targetId}" (no path separators or leading dot)`));
|
|
51
|
+
return 2;
|
|
52
|
+
}
|
|
53
|
+
const binDir = opts.binDir ? isAbsolute(opts.binDir) ? opts.binDir : resolve(process.cwd(), opts.binDir) : join(homedir(), ".anna", "executa", "bin");
|
|
54
|
+
const shimPath = join(binDir, targetId);
|
|
55
|
+
if (existsSync(shimPath) && !opts.force) {
|
|
56
|
+
console.error(red(`✗ shim already exists: ${shimPath}`) + dim(" (pass --force to overwrite)"));
|
|
57
|
+
return 1;
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
mkdirSync(binDir, { recursive: true });
|
|
61
|
+
writeFileSync(shimPath, buildShim(parsed.project_dir, parsed.command), "utf-8");
|
|
62
|
+
chmodSync(shimPath, 493);
|
|
63
|
+
} catch (e) {
|
|
64
|
+
console.error(red(`✗ failed to write shim: ${e.message}`));
|
|
65
|
+
return 1;
|
|
66
|
+
}
|
|
67
|
+
if (json) {
|
|
68
|
+
console.log(JSON.stringify({
|
|
69
|
+
tool_id: targetId,
|
|
70
|
+
shim_path: shimPath,
|
|
71
|
+
project_dir: parsed.project_dir,
|
|
72
|
+
command: parsed.command,
|
|
73
|
+
source: opts.toolId ? "flag" : identity?.tool_id ? "identity-cache" : "discovered"
|
|
74
|
+
}));
|
|
75
|
+
return 0;
|
|
76
|
+
}
|
|
77
|
+
if (opts.quiet) return 0;
|
|
78
|
+
console.log(bold(cyan("anna-app executa install")));
|
|
79
|
+
console.log(` tool_id ${green(targetId)}`);
|
|
80
|
+
console.log(` shim ${dim(shimPath)}`);
|
|
81
|
+
console.log(` dir ${dim(parsed.project_dir)}`);
|
|
82
|
+
console.log(` command ${dim(parsed.command.join(" "))}`);
|
|
83
|
+
if (!opts.toolId && identity?.tool_id) console.log(` source ${dim("minted tool_id from .anna/executa.json")}`);
|
|
84
|
+
else if (!opts.toolId) console.log(yellow(" ! using the placeholder tool_id from executa.json — run `executa publish`/`apps push` to mint the real one, then re-run with --force (or pass --tool-id)."));
|
|
85
|
+
console.log(dim("\n→ open the Agent's Plugin Details modal and click " + bold("Rediscover Local") + dim(" to load it under this tool_id.")));
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
//#endregion
|
|
90
|
+
export { runExecutaInstall };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { canonicalHost } from "./credentials-BTv2IfUZ.js";
|
|
2
|
-
import { CliError } from "./client-
|
|
3
|
-
import { commitDraft, createDraft, getMySkill, getMyTool, listToolVersions, publishToolVersion, setSkillVisibility, setToolVisibility, updateMySkill, updateMyTool } from "./executas-
|
|
4
|
-
import { executaCacheMatches, invalidateExecutaCache, mintIdempotencyKey, readExecutaIdentity, writeExecutaIdentity } from "./executa-cache-
|
|
5
|
-
import { loadExecutaManifest } from "./manifest-
|
|
6
|
-
import { resolveClient, withErrorHandling } from "./_lifecycle-shared-
|
|
2
|
+
import { CliError } from "./client-D-_z1ALk.js";
|
|
3
|
+
import { commitDraft, createDraft, getMySkill, getMyTool, listToolVersions, publishToolVersion, setSkillVisibility, setToolVisibility, updateMySkill, updateMyTool } from "./executas-CK3er6f9.js";
|
|
4
|
+
import { executaCacheMatches, invalidateExecutaCache, mintIdempotencyKey, readExecutaIdentity, writeExecutaIdentity } from "./executa-cache-CXiEgFZY.js";
|
|
5
|
+
import { loadExecutaManifest } from "./manifest-Bljz8Y6T.js";
|
|
6
|
+
import { resolveClient, withErrorHandling } from "./_lifecycle-shared-BpSOfVCP.js";
|
|
7
7
|
import { join, relative, resolve, sep } from "node:path";
|
|
8
8
|
import { readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
9
9
|
import { bold, cyan, dim, green, yellow } from "kleur/colors";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import "./credentials-BTv2IfUZ.js";
|
|
2
|
+
import "./client-D-_z1ALk.js";
|
|
3
|
+
import "./executas-CK3er6f9.js";
|
|
4
|
+
import "./executa-cache-CXiEgFZY.js";
|
|
5
|
+
import { runExecutaPublish } from "./executa-publish-CkPAB34b.js";
|
|
6
|
+
import "./manifest-Bljz8Y6T.js";
|
|
7
|
+
import "./_lifecycle-shared-BpSOfVCP.js";
|
|
8
|
+
|
|
9
|
+
export { runExecutaPublish };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "./credentials-BTv2IfUZ.js";
|
|
2
|
-
import { CliError } from "./client-
|
|
3
|
-
import { getMyTool, listMyTools, listToolVersions } from "./executas-
|
|
4
|
-
import { resolveClient, withErrorHandling } from "./_lifecycle-shared-
|
|
2
|
+
import { CliError } from "./client-D-_z1ALk.js";
|
|
3
|
+
import { getMyTool, listMyTools, listToolVersions } from "./executas-CK3er6f9.js";
|
|
4
|
+
import { resolveClient, withErrorHandling } from "./_lifecycle-shared-BpSOfVCP.js";
|
|
5
5
|
import { bold, cyan, dim, green } from "kleur/colors";
|
|
6
6
|
|
|
7
7
|
//#region src/commands/executa-reads.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CliError } from "./client-
|
|
1
|
+
import { CliError } from "./client-D-_z1ALk.js";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
|
|
@@ -124,23 +124,82 @@ function loadExecutaManifest(cwd, manifestPath) {
|
|
|
124
124
|
* Returns `undefined` when absent (a dev-only Executa). Skills never carry
|
|
125
125
|
* distribution config — they are declarative Markdown, not installable
|
|
126
126
|
* processes — so a `distribution` block on a skill is rejected.
|
|
127
|
+
*
|
|
128
|
+
* Two shapes are accepted:
|
|
129
|
+
*
|
|
130
|
+
* 1. Flat (single mode) — the historical form:
|
|
131
|
+
*
|
|
132
|
+
* "distribution": { "type": "binary", "binary_urls": { … } }
|
|
133
|
+
*
|
|
134
|
+
* 2. Multi-profile (switchable) — keep several modes side by side and flip
|
|
135
|
+
* `active` to choose which one is published:
|
|
136
|
+
*
|
|
137
|
+
* "distribution": {
|
|
138
|
+
* "active": "binary",
|
|
139
|
+
* "profiles": {
|
|
140
|
+
* "local": { "type": "local", "executable_name": "…" },
|
|
141
|
+
* "binary": { "type": "binary", "binary_urls": { … } }
|
|
142
|
+
* }
|
|
143
|
+
* }
|
|
144
|
+
*
|
|
145
|
+
* Every profile is validated (so a typo in an *inactive* profile is
|
|
146
|
+
* still caught), but the returned `ExecutaDistribution` carries the
|
|
147
|
+
* fields of the *active* profile plus `active`/`profiles` for
|
|
148
|
+
* introspection. Downstream publish code stays profile-agnostic.
|
|
127
149
|
*/
|
|
128
150
|
function parseExecutaDistribution(value, executaType) {
|
|
129
151
|
if (value === void 0 || value === null) return void 0;
|
|
130
|
-
if (typeof value !== "object" || Array.isArray(value)) throw new CliError("executa.json `distribution` must be an object with a `type` field", 4);
|
|
152
|
+
if (typeof value !== "object" || Array.isArray(value)) throw new CliError("executa.json `distribution` must be an object with a `type` field (or `profiles` for the switchable multi-mode form)", 4);
|
|
131
153
|
if (executaType === "skill") throw new CliError("executa.json `distribution` is only valid for `executa_type: \"tool\"` — skills are declarative Markdown and are not installed as a process", 4);
|
|
132
154
|
const d = value;
|
|
155
|
+
if (d["profiles"] !== void 0) return parseProfiledDistribution(d);
|
|
156
|
+
return parseDistributionProfile(d, "distribution");
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Resolve the multi-profile `distribution` form into the selected profile.
|
|
160
|
+
* Validates *all* profiles and records them under `profiles`.
|
|
161
|
+
*/
|
|
162
|
+
function parseProfiledDistribution(d) {
|
|
163
|
+
if (d["type"] !== void 0) throw new CliError("executa.json `distribution` cannot set both `type` (flat form) and `profiles` (switchable form) — pick one", 4);
|
|
164
|
+
const profilesRaw = d["profiles"];
|
|
165
|
+
if (profilesRaw === null || typeof profilesRaw !== "object" || Array.isArray(profilesRaw)) throw new CliError("executa.json `distribution.profiles` must be an object mapping a profile name → distribution config", 4);
|
|
166
|
+
const profileEntries = Object.entries(profilesRaw);
|
|
167
|
+
if (profileEntries.length === 0) throw new CliError("executa.json `distribution.profiles` must declare at least one profile", 4);
|
|
168
|
+
const profiles = {};
|
|
169
|
+
for (const [pname, pval] of profileEntries) {
|
|
170
|
+
if (pval === null || typeof pval !== "object" || Array.isArray(pval)) throw new CliError(`executa.json \`distribution.profiles["${pname}"]\` must be an object`, 4);
|
|
171
|
+
profiles[pname] = parseDistributionProfile(pval, `distribution.profiles["${pname}"]`);
|
|
172
|
+
}
|
|
173
|
+
const active = pickString(d, "active");
|
|
174
|
+
let selected;
|
|
175
|
+
if (active !== void 0) {
|
|
176
|
+
if (!(active in profiles)) throw new CliError(`executa.json \`distribution.active\` "${active}" is not a declared profile — expected one of ${Object.keys(profiles).join(" | ")}`, 4);
|
|
177
|
+
selected = active;
|
|
178
|
+
} else if (profileEntries.length === 1) selected = profileEntries[0][0];
|
|
179
|
+
else throw new CliError(`executa.json \`distribution.active\` is required when more than one profile is declared — expected one of ${Object.keys(profiles).join(" | ")}`, 4);
|
|
180
|
+
const resolved = profiles[selected];
|
|
181
|
+
return {
|
|
182
|
+
...resolved,
|
|
183
|
+
active: selected,
|
|
184
|
+
profiles
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Parse + validate a single distribution config (one flat block or one entry
|
|
189
|
+
* of a `profiles` map). `ctx` is the JSON path label used in error messages.
|
|
190
|
+
*/
|
|
191
|
+
function parseDistributionProfile(d, ctx) {
|
|
133
192
|
const type = pickString(d, "type");
|
|
134
|
-
if (!type) throw new CliError(
|
|
135
|
-
if (!DISTRIBUTION_TYPES.has(type)) throw new CliError(`executa.json
|
|
193
|
+
if (!type) throw new CliError(`executa.json \`${ctx}.type\` is required`, 4);
|
|
194
|
+
if (!DISTRIBUTION_TYPES.has(type)) throw new CliError(`executa.json \`${ctx}.type\` "${type}" is invalid — expected one of ` + [...DISTRIBUTION_TYPES].join(" | "), 4);
|
|
136
195
|
const distType = type;
|
|
137
196
|
const packageName = pickString(d, "package_name");
|
|
138
197
|
const executableName = pickString(d, "executable_name");
|
|
139
198
|
const supportsProtocol = pickBool(d, "supports_protocol");
|
|
140
|
-
const binaryUrls = parseBinaryUrls(d["binary_urls"]);
|
|
141
|
-
const capabilities = parseCapabilities(d["capabilities"]);
|
|
142
|
-
if (PACKAGE_BACKED.has(distType) && !packageName) throw new CliError(`executa.json
|
|
143
|
-
if (distType === "binary" && (!binaryUrls || Object.keys(binaryUrls).length === 0)) throw new CliError(
|
|
199
|
+
const binaryUrls = parseBinaryUrls(d["binary_urls"], ctx);
|
|
200
|
+
const capabilities = parseCapabilities(d["capabilities"], ctx);
|
|
201
|
+
if (PACKAGE_BACKED.has(distType) && !packageName) throw new CliError(`executa.json \`${ctx}.package_name\` is required for \`${ctx}.type: "${distType}"\``, 4);
|
|
202
|
+
if (distType === "binary" && (!binaryUrls || Object.keys(binaryUrls).length === 0)) throw new CliError(`executa.json \`${ctx}.binary_urls\` is required (and non-empty) for \`${ctx}.type: "binary"\``, 4);
|
|
144
203
|
return {
|
|
145
204
|
type: distType,
|
|
146
205
|
packageName,
|
|
@@ -150,29 +209,29 @@ function parseExecutaDistribution(value, executaType) {
|
|
|
150
209
|
capabilities
|
|
151
210
|
};
|
|
152
211
|
}
|
|
153
|
-
function parseBinaryUrls(value) {
|
|
212
|
+
function parseBinaryUrls(value, ctx = "distribution") {
|
|
154
213
|
if (value === void 0 || value === null) return void 0;
|
|
155
|
-
if (typeof value !== "object" || Array.isArray(value)) throw new CliError(
|
|
214
|
+
if (typeof value !== "object" || Array.isArray(value)) throw new CliError(`executa.json \`${ctx}.binary_urls\` must be an object mapping platform → URL string or asset dict`, 4);
|
|
156
215
|
const out = {};
|
|
157
216
|
for (const [platform, asset] of Object.entries(value)) {
|
|
158
217
|
if (typeof asset === "string") {
|
|
159
|
-
if (!asset.trim()) throw new CliError(`executa.json
|
|
218
|
+
if (!asset.trim()) throw new CliError(`executa.json \`${ctx}.binary_urls["${platform}"]\` is empty`, 4);
|
|
160
219
|
out[platform] = asset;
|
|
161
220
|
continue;
|
|
162
221
|
}
|
|
163
222
|
if (asset && typeof asset === "object" && !Array.isArray(asset)) {
|
|
164
223
|
const url = pickString(asset, "url");
|
|
165
|
-
if (!url) throw new CliError(`executa.json
|
|
224
|
+
if (!url) throw new CliError(`executa.json \`${ctx}.binary_urls["${platform}"]\` asset dict missing required \`url\``, 4);
|
|
166
225
|
out[platform] = asset;
|
|
167
226
|
continue;
|
|
168
227
|
}
|
|
169
|
-
throw new CliError(`executa.json
|
|
228
|
+
throw new CliError(`executa.json \`${ctx}.binary_urls["${platform}"]\` must be a URL string or an asset dict \`{ url, sha256?, size?, entrypoint?, format? }\``, 4);
|
|
170
229
|
}
|
|
171
230
|
return out;
|
|
172
231
|
}
|
|
173
|
-
function parseCapabilities(value) {
|
|
232
|
+
function parseCapabilities(value, ctx = "distribution") {
|
|
174
233
|
if (value === void 0 || value === null) return void 0;
|
|
175
|
-
if (!Array.isArray(value) || value.some((v) => typeof v !== "string")) throw new CliError(
|
|
234
|
+
if (!Array.isArray(value) || value.some((v) => typeof v !== "string")) throw new CliError(`executa.json \`${ctx}.capabilities\` must be an array of strings`, 4);
|
|
176
235
|
return value;
|
|
177
236
|
}
|
|
178
237
|
function pickBool(o, k) {
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { dirname, isAbsolute, resolve } from "node:path";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
|
|
4
|
+
//#region src/nexus-root.ts
|
|
5
|
+
/**
|
|
6
|
+
* Resolve an absolute matrix-nexus root, or null if none is found.
|
|
7
|
+
*
|
|
8
|
+
* Search order (first hit wins):
|
|
9
|
+
* 1. `explicit` (the `--matrix-nexus-root` flag).
|
|
10
|
+
* 2. `$ANNA_NEXUS_ROOT`.
|
|
11
|
+
* 3. Walk up from `cwd`.
|
|
12
|
+
* 4. Sibling `../matrix-nexus`.
|
|
13
|
+
*
|
|
14
|
+
* A candidate qualifies only if it contains
|
|
15
|
+
* `packages/anna-app-runtime-local/pyproject.toml` (the marker that also
|
|
16
|
+
* gates `nexus-source` runtime mode), so the three escape hatches can
|
|
17
|
+
* never disagree on what counts as "a matrix-nexus checkout".
|
|
18
|
+
*/
|
|
19
|
+
function findMatrixNexusRoot(explicit, cwd) {
|
|
20
|
+
const candidates = [explicit, process.env.ANNA_NEXUS_ROOT];
|
|
21
|
+
let dir = cwd;
|
|
22
|
+
while (true) {
|
|
23
|
+
candidates.push(dir);
|
|
24
|
+
const parent = dirname(dir);
|
|
25
|
+
if (parent === dir) break;
|
|
26
|
+
dir = parent;
|
|
27
|
+
}
|
|
28
|
+
candidates.push(resolve(cwd, "..", "matrix-nexus"));
|
|
29
|
+
for (const c of candidates) {
|
|
30
|
+
if (!c) continue;
|
|
31
|
+
const abs = isAbsolute(c) ? c : resolve(cwd, c);
|
|
32
|
+
if (existsSync(resolve(abs, "packages/anna-app-runtime-local/pyproject.toml"))) return abs;
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Locate the in-tree `@anna-ai/app-schema` bundle inside a matrix-nexus
|
|
38
|
+
* root, or null if it is absent / not built. The returned dir is suitable
|
|
39
|
+
* for `ANNA_APP_SCHEMA_DIR` / `loadSchemaBundle`'s override so contributors
|
|
40
|
+
* can `validate` against an UNPUBLISHED schema bump without waiting for the
|
|
41
|
+
* npm push — parity with the runtime/SDK nexus-source hatches.
|
|
42
|
+
*/
|
|
43
|
+
function nexusSchemaDir(root) {
|
|
44
|
+
const dir = resolve(root, "packages", "anna-app-schema");
|
|
45
|
+
return existsSync(resolve(dir, "dispatcher_version.txt")) ? dir : null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
//#endregion
|
|
49
|
+
export { findMatrixNexusRoot, nexusSchemaDir };
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import "./credentials-BTv2IfUZ.js";
|
|
2
|
-
import "./apps-
|
|
3
|
-
import { CliError } from "./client-
|
|
4
|
-
import "./bundled-executas-
|
|
5
|
-
import "./executas-
|
|
6
|
-
import "./executa-cache-
|
|
7
|
-
import { runExecutaPublish } from "./executa-publish-
|
|
8
|
-
import "./manifest-
|
|
9
|
-
import { withErrorHandling } from "./_lifecycle-shared-
|
|
10
|
-
import "./app-cache-
|
|
11
|
-
import "./app-bundle-upload-
|
|
12
|
-
import { runAppsPublish } from "./apps-publish-
|
|
2
|
+
import "./apps-CCdtLmxQ.js";
|
|
3
|
+
import { CliError } from "./client-D-_z1ALk.js";
|
|
4
|
+
import "./bundled-executas-B6b8gIfp.js";
|
|
5
|
+
import "./executas-CK3er6f9.js";
|
|
6
|
+
import "./executa-cache-CXiEgFZY.js";
|
|
7
|
+
import { runExecutaPublish } from "./executa-publish-CkPAB34b.js";
|
|
8
|
+
import "./manifest-Bljz8Y6T.js";
|
|
9
|
+
import { withErrorHandling } from "./_lifecycle-shared-BpSOfVCP.js";
|
|
10
|
+
import "./app-cache-Bl7cE5fm.js";
|
|
11
|
+
import "./app-bundle-upload-BhAYo6yj.js";
|
|
12
|
+
import { runAppsPublish } from "./apps-publish-Dgi4lBlu.js";
|
|
13
13
|
import { resolve } from "node:path";
|
|
14
14
|
import { existsSync } from "node:fs";
|
|
15
15
|
import { red, yellow } from "kleur/colors";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { canonicalHost, getAccount } from "./credentials-BTv2IfUZ.js";
|
|
2
|
-
import { BridgeRequestError } from "./bridge-
|
|
2
|
+
import { BridgeRequestError } from "./bridge-DxBd0Fl9.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";
|
|
@@ -445,6 +445,26 @@ var LlmBridge = class {
|
|
|
445
445
|
message: "agent.session.history is not exposed over HTTP; available only via in-process store"
|
|
446
446
|
}
|
|
447
447
|
};
|
|
448
|
+
case "session.list": {
|
|
449
|
+
const includeExpired = Boolean(args.args?.include_expired);
|
|
450
|
+
const rawLimit = Number(args.args?.limit ?? 50);
|
|
451
|
+
const limit = Math.max(1, Math.min(100, Number.isFinite(rawLimit) ? rawLimit : 50));
|
|
452
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
453
|
+
const sessions = [...this.mintedAgent.values()].filter((ms) => includeExpired || ms.expiresAt > now).slice(0, limit).map((ms) => ({
|
|
454
|
+
app_session_uuid: ms.appSessionUuid,
|
|
455
|
+
kind: "agent",
|
|
456
|
+
submode: ms.submode,
|
|
457
|
+
fixed_client_id: null,
|
|
458
|
+
label: "anna-app dev",
|
|
459
|
+
created_at: null,
|
|
460
|
+
last_active_at: null,
|
|
461
|
+
expires_at: new Date(ms.expiresAt * 1e3).toISOString()
|
|
462
|
+
}));
|
|
463
|
+
return {
|
|
464
|
+
ok: true,
|
|
465
|
+
result: { sessions }
|
|
466
|
+
};
|
|
467
|
+
}
|
|
448
468
|
case "session.delete": {
|
|
449
469
|
const apsUuid = String(args.args.app_session_uuid ?? "");
|
|
450
470
|
const ms = this.mintedAgent.get(apsUuid);
|
|
@@ -857,6 +877,11 @@ var HarnessServer = class {
|
|
|
857
877
|
"agent",
|
|
858
878
|
"session.delete"
|
|
859
879
|
],
|
|
880
|
+
[
|
|
881
|
+
"host.agent.session.list",
|
|
882
|
+
"agent",
|
|
883
|
+
"session.list"
|
|
884
|
+
],
|
|
860
885
|
[
|
|
861
886
|
"host.image.generate",
|
|
862
887
|
"image",
|
|
@@ -1133,17 +1158,34 @@ var HarnessServer = class {
|
|
|
1133
1158
|
}
|
|
1134
1159
|
async serveSdk(pathname, res) {
|
|
1135
1160
|
const sdkRel = pathname.replace(/^\/static\/anna-apps\/_sdk\/[^/]+\//, "");
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
const req = createRequire(import.meta.url);
|
|
1139
|
-
distRoot = dirname(req.resolve("@anna-ai/app-runtime"));
|
|
1140
|
-
} catch (e) {
|
|
1141
|
-
return this.text(res, 500, `@anna-ai/app-runtime is not installed: ${e.message}`);
|
|
1142
|
-
}
|
|
1161
|
+
const distRoot = this.resolveSdkDistRoot();
|
|
1162
|
+
if (!distRoot) return this.text(res, 500, "@anna-ai/app-runtime is not installed and no in-tree packages/anna-app-runtime/dist was found.");
|
|
1143
1163
|
const abs = resolve(distRoot, sdkRel);
|
|
1144
1164
|
if (!abs.startsWith(distRoot)) return this.text(res, 403, "forbidden");
|
|
1145
1165
|
return this.serveFile(abs, res);
|
|
1146
1166
|
}
|
|
1167
|
+
/**
|
|
1168
|
+
* Resolve the directory the browser SDK (`index.js` + friends) is served
|
|
1169
|
+
* from. When `--matrix-nexus-root` is set we prefer the in-tree
|
|
1170
|
+
* `packages/anna-app-runtime/dist/` so contributors run byte-identical
|
|
1171
|
+
* with the unpublished workspace SDK (parity with the Python bridge, which
|
|
1172
|
+
* already runs in-tree in `nexus-source` mode). Falls back to the
|
|
1173
|
+
* published npm package resolved from anna-app-cli's own node_modules.
|
|
1174
|
+
* Returns null if neither is available.
|
|
1175
|
+
*/
|
|
1176
|
+
resolveSdkDistRoot() {
|
|
1177
|
+
const root = this.cfg.matrixNexusRoot;
|
|
1178
|
+
if (root) {
|
|
1179
|
+
const inTree = resolve(root, "packages", "anna-app-runtime", "dist");
|
|
1180
|
+
if (existsSync(join(inTree, "index.js"))) return inTree;
|
|
1181
|
+
}
|
|
1182
|
+
try {
|
|
1183
|
+
const req = createRequire(import.meta.url);
|
|
1184
|
+
return dirname(req.resolve("@anna-ai/app-runtime"));
|
|
1185
|
+
} catch {
|
|
1186
|
+
return null;
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1147
1189
|
async serveBundleAsset(rel, res) {
|
|
1148
1190
|
const abs = resolve(this.cfg.bundleDir, normalize(rel));
|
|
1149
1191
|
if (!abs.startsWith(resolve(this.cfg.bundleDir))) return this.text(res, 403, "forbidden");
|
|
@@ -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-CGo8k9_2.js";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
import { existsSync, readFileSync } from "node:fs";
|
|
5
5
|
|
package/dist/test/index.js
CHANGED
|
@@ -22,6 +22,9 @@ function deriveAcl(manifest) {
|
|
|
22
22
|
const bare = ref.includes(":") ? ref.split(":", 2)[1] : ref;
|
|
23
23
|
allowedTools.add(bare);
|
|
24
24
|
}
|
|
25
|
+
if (allowedTools.size === 0 && !toolsWildcard) {
|
|
26
|
+
for (const r of [...manifest.required_executas ?? [], ...manifest.optional_executas ?? []]) if (r.tool_id) allowedTools.add(r.tool_id);
|
|
27
|
+
}
|
|
25
28
|
if (allowedTools.size > 0 || toolsWildcard) allowed.add("tools.invoke");
|
|
26
29
|
for (const ns of Object.keys(NAMESPACED)) {
|
|
27
30
|
if (ns === "tools") continue;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "./credentials-BTv2IfUZ.js";
|
|
2
|
-
import "./client-
|
|
3
|
-
import { resolveClient, withErrorHandling } from "./_lifecycle-shared-
|
|
2
|
+
import "./client-D-_z1ALk.js";
|
|
3
|
+
import { resolveClient, withErrorHandling } from "./_lifecycle-shared-BpSOfVCP.js";
|
|
4
4
|
import { bold, cyan, dim, green, red, yellow } from "kleur/colors";
|
|
5
5
|
|
|
6
6
|
//#region src/api/tokens.ts
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { canonicalHost } from "./credentials-BTv2IfUZ.js";
|
|
2
|
-
import { createApp, findAppBySlug, getApp } from "./apps-
|
|
3
|
-
import { CliError } from "./client-
|
|
4
|
-
import { parseExecutaIdOverrides, readExecutasLock, substituteBundledRefs, validateBundledHandles, writeBundleToolIdSidecar, writeExecutasLock } from "./bundled-executas-
|
|
5
|
-
import { runExecutaPublish } from "./executa-publish-
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
2
|
+
import { createApp, findAppBySlug, getApp } from "./apps-CCdtLmxQ.js";
|
|
3
|
+
import { CliError } from "./client-D-_z1ALk.js";
|
|
4
|
+
import { parseExecutaIdOverrides, readExecutasLock, substituteBundledRefs, validateBundledHandles, writeBundleToolIdSidecar, writeExecutasLock } from "./bundled-executas-B6b8gIfp.js";
|
|
5
|
+
import { runExecutaPublish } from "./executa-publish-CkPAB34b.js";
|
|
6
|
+
import { loadExecutaManifest } from "./manifest-Bljz8Y6T.js";
|
|
7
|
+
import { runExecutaInstall } from "./executa-install-DQIhVHPT.js";
|
|
8
|
+
import { appCacheMatches, readAppIdentity, writeAppIdentity } from "./app-cache-Bl7cE5fm.js";
|
|
9
|
+
import { join, resolve } from "node:path";
|
|
8
10
|
import { dim, green, yellow } from "kleur/colors";
|
|
11
|
+
import { homedir } from "node:os";
|
|
9
12
|
|
|
10
13
|
//#region src/publish/working-orchestration.ts
|
|
11
14
|
async function resolveBundledExecutas(params) {
|
|
@@ -104,6 +107,50 @@ async function resolveBundledExecutas(params) {
|
|
|
104
107
|
};
|
|
105
108
|
}
|
|
106
109
|
/**
|
|
110
|
+
* Install a local-dev launcher shim for every bundled executa whose *active*
|
|
111
|
+
* distribution profile is `local`, under its minted `tool_id`. This closes
|
|
112
|
+
* the manual gap after `apps push`: a `local` executa never triggers a server
|
|
113
|
+
* `install_plugin` RPC, so the only way it turns "Running" on an Agent is the
|
|
114
|
+
* **Rediscover Local** flow — which needs an on-disk shim named exactly the
|
|
115
|
+
* minted `tool_id`. Binary/uv/npm/etc. profiles are skipped (the Agent
|
|
116
|
+
* installs those itself), as are skills (no runtime process) and dev-only
|
|
117
|
+
* executas with no distribution block.
|
|
118
|
+
*
|
|
119
|
+
* Failures are non-fatal: a shim that can't be written warns but does not
|
|
120
|
+
* fail the surrounding `apps push`.
|
|
121
|
+
*/
|
|
122
|
+
async function installLocalBundledShims(params) {
|
|
123
|
+
const { manifest, cwd, resolved, json = false } = params;
|
|
124
|
+
const binDir = params.binDir ?? join(homedir(), ".anna", "executa", "bin");
|
|
125
|
+
const installed = [];
|
|
126
|
+
for (const decl of manifest.bundledExecutas) {
|
|
127
|
+
const toolId = resolved[decl.handle];
|
|
128
|
+
if (!toolId) continue;
|
|
129
|
+
const dir = resolve(cwd, decl.path);
|
|
130
|
+
let exManifest;
|
|
131
|
+
try {
|
|
132
|
+
exManifest = loadExecutaManifest(dir);
|
|
133
|
+
} catch {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (exManifest.distribution?.type !== "local") continue;
|
|
137
|
+
const code = await runExecutaInstall({
|
|
138
|
+
dir,
|
|
139
|
+
toolId,
|
|
140
|
+
binDir: params.binDir,
|
|
141
|
+
force: true,
|
|
142
|
+
quiet: true
|
|
143
|
+
});
|
|
144
|
+
if (code === 0) installed.push({
|
|
145
|
+
handle: decl.handle,
|
|
146
|
+
tool_id: toolId,
|
|
147
|
+
shim_path: join(binDir, toolId)
|
|
148
|
+
});
|
|
149
|
+
else if (!json) console.log(yellow(` ! could not install local dev shim for "${decl.handle}" (exit ${code})`));
|
|
150
|
+
}
|
|
151
|
+
return installed;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
107
154
|
* Resolve (creating if absent) the `AnnaApp` row, persisting the identity
|
|
108
155
|
* cache before any subsequent network call. Returns `null` only in dry-run
|
|
109
156
|
* mode when the app does not exist yet (nothing to create).
|
|
@@ -187,4 +234,4 @@ async function resolveAppBySlugOrCache(client, host, opts) {
|
|
|
187
234
|
}
|
|
188
235
|
|
|
189
236
|
//#endregion
|
|
190
|
-
export { resolveAppBySlugOrCache, resolveAppIdentity, resolveBundledExecutas };
|
|
237
|
+
export { installLocalBundledShims, 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.26",
|
|
4
4
|
"description": "Anna App developer CLI: scaffold, validate, harness (Phase 2 MVP: init + validate).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -29,11 +29,12 @@
|
|
|
29
29
|
"test:watch": "vitest",
|
|
30
30
|
"lint": "tsc --noEmit",
|
|
31
31
|
"check:runtime-pin": "node scripts/check-runtime-pin.mjs",
|
|
32
|
-
"
|
|
32
|
+
"check:sdk-pin": "node scripts/check-sdk-pin.mjs",
|
|
33
|
+
"prepublishOnly": "pnpm lint && pnpm test && pnpm build && node scripts/check-runtime-pin.mjs && node scripts/check-sdk-pin.mjs"
|
|
33
34
|
},
|
|
34
35
|
"dependencies": {
|
|
35
|
-
"@anna-ai/app-runtime": "^0.
|
|
36
|
-
"@anna-ai/app-schema": "^0.
|
|
36
|
+
"@anna-ai/app-runtime": "^0.7.0",
|
|
37
|
+
"@anna-ai/app-schema": "^0.9.0",
|
|
37
38
|
"ajv": "^8.17.1",
|
|
38
39
|
"ajv-formats": "^3.0.1",
|
|
39
40
|
"commander": "^12.1.0",
|