@anna-ai/cli 0.1.19 → 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +346 -23
- 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,83 @@
|
|
|
1
|
+
import { canonicalHost } from "./credentials-BTv2IfUZ.js";
|
|
2
|
+
import { cutWorkingDraft } from "./apps-B1Nd8l_t.js";
|
|
3
|
+
import { CliError } from "./client-Dn9zThOd.js";
|
|
4
|
+
import { readExecutasLock, writeExecutasLock } from "./bundled-executas-BNOKw4kv.js";
|
|
5
|
+
import "./executas-Cep6KEo0.js";
|
|
6
|
+
import "./executa-cache-BFoUtb4J.js";
|
|
7
|
+
import "./executa-publish-Ca5V7MyA.js";
|
|
8
|
+
import "./manifest-DGwRap2i.js";
|
|
9
|
+
import { resolveClient, withErrorHandling } from "./_lifecycle-shared-sbea9HtH.js";
|
|
10
|
+
import "./app-cache-BEM653Th.js";
|
|
11
|
+
import { resolveAppBySlugOrCache } from "./working-orchestration-Dw9u1Vq0.js";
|
|
12
|
+
import { resolve } from "node:path";
|
|
13
|
+
import { bold, cyan, dim, green, yellow } from "kleur/colors";
|
|
14
|
+
|
|
15
|
+
//#region src/commands/apps-cut.ts
|
|
16
|
+
async function runAppsCut(opts) {
|
|
17
|
+
return withErrorHandling(async () => {
|
|
18
|
+
const { client, host } = resolveClient({ account: opts.account });
|
|
19
|
+
const app = await resolveAppBySlugOrCache(client, host, {
|
|
20
|
+
slug: opts.slug,
|
|
21
|
+
cwd: opts.cwd
|
|
22
|
+
});
|
|
23
|
+
if (opts.dryRun) {
|
|
24
|
+
if (!opts.json) console.log(yellow(`[dry-run] would cut version ${opts.version} for apps/${app.slug} (app_id=${app.id})`));
|
|
25
|
+
return 0;
|
|
26
|
+
}
|
|
27
|
+
let result;
|
|
28
|
+
try {
|
|
29
|
+
result = await cutWorkingDraft(client, app.id, {
|
|
30
|
+
version: opts.version,
|
|
31
|
+
changelog: opts.changelog
|
|
32
|
+
});
|
|
33
|
+
} catch (e) {
|
|
34
|
+
if (e instanceof CliError && e.status === 409) throw new CliError(`version ${opts.version} already cut for apps/${app.slug}; choose a higher SemVer (e.g. bump patch/minor) and retry`, 9);
|
|
35
|
+
if (e instanceof CliError && (e.status === 400 || e.status === 422)) throw new CliError(`cannot cut: ${e.message} — fix the working draft and \`apps push\` again`, 4);
|
|
36
|
+
throw e;
|
|
37
|
+
}
|
|
38
|
+
if (result.frozen_executas.length > 0) {
|
|
39
|
+
const cwd = resolve(opts.cwd ?? process.cwd());
|
|
40
|
+
const lock = readExecutasLock(cwd, host);
|
|
41
|
+
if (lock) {
|
|
42
|
+
const byToolId = new Map(Object.entries(lock.executas).map(([h, e]) => [e.tool_id, h]));
|
|
43
|
+
for (const fr of result.frozen_executas) {
|
|
44
|
+
const handle = byToolId.get(fr.tool_id);
|
|
45
|
+
if (handle && lock.executas[handle]) lock.executas[handle] = {
|
|
46
|
+
...lock.executas[handle],
|
|
47
|
+
tool_id: fr.tool_id,
|
|
48
|
+
source: "cut"
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
writeExecutasLock(cwd, {
|
|
52
|
+
$schema: "anna-executas-lock/v1",
|
|
53
|
+
host: canonicalHost(host),
|
|
54
|
+
executas: lock.executas
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (opts.json) {
|
|
59
|
+
console.log(JSON.stringify({
|
|
60
|
+
app_id: app.id,
|
|
61
|
+
slug: app.slug,
|
|
62
|
+
host,
|
|
63
|
+
version_id: result.version_id,
|
|
64
|
+
version: result.version,
|
|
65
|
+
frozen_executas: result.frozen_executas,
|
|
66
|
+
bundle: result.bundle
|
|
67
|
+
}, null, 2));
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
70
|
+
console.log(green(`✓ apps/${app.slug}: cut immutable version ${result.version} `) + dim(`(version_id=${result.version_id})`));
|
|
71
|
+
for (const fr of result.frozen_executas) console.log(dim(` froze ${fr.tool_id} → executa_version=${fr.executa_version_id}`) + (fr.version ? dim(` (v${fr.version})`) : ""));
|
|
72
|
+
if (result.bundle && typeof result.bundle === "object") {
|
|
73
|
+
const prefix = result.bundle.object_prefix;
|
|
74
|
+
if (prefix) console.log(dim(` bundle frozen at ${prefix}`));
|
|
75
|
+
}
|
|
76
|
+
console.log(dim(`→ run `) + cyan(`anna-app apps release ${result.version}`) + dim(` to go live`));
|
|
77
|
+
console.log(bold(cyan(`status: ${app.status}`)));
|
|
78
|
+
return 0;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
//#endregion
|
|
83
|
+
export { runAppsCut };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import "./credentials-BTv2IfUZ.js";
|
|
2
|
+
import { archiveApp, deleteApp, findAppBySlug, unarchiveApp, unpublishApp } from "./apps-B1Nd8l_t.js";
|
|
3
|
+
import { CliError } from "./client-Dn9zThOd.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/apps-destructive.ts
|
|
9
|
+
async function resolveAppId(account, slug) {
|
|
10
|
+
const { client, host } = resolveClient({ account });
|
|
11
|
+
const app = await findAppBySlug(client, slug);
|
|
12
|
+
if (!app) throw new CliError(`no app with slug "${slug}" on ${host}`, 5);
|
|
13
|
+
return {
|
|
14
|
+
client,
|
|
15
|
+
host,
|
|
16
|
+
appId: app.id,
|
|
17
|
+
serverSlug: app.slug
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
async function runAppsUnpublish(opts) {
|
|
21
|
+
return withErrorHandling(async () => {
|
|
22
|
+
await ensureDestructiveAllowed({
|
|
23
|
+
verb: "apps unpublish",
|
|
24
|
+
...opts
|
|
25
|
+
});
|
|
26
|
+
const { client, host, appId, serverSlug } = await resolveAppId(opts.account, opts.slug);
|
|
27
|
+
const updated = await unpublishApp(client, appId);
|
|
28
|
+
if (opts.json) {
|
|
29
|
+
console.log(JSON.stringify({
|
|
30
|
+
host,
|
|
31
|
+
app_id: appId,
|
|
32
|
+
slug: serverSlug,
|
|
33
|
+
status: updated.status
|
|
34
|
+
}, null, 2));
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
console.log(green(`✓ apps/${serverSlug}: unpublished (status=${updated.status})`));
|
|
38
|
+
return 0;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
async function runAppsArchive(opts) {
|
|
42
|
+
return withErrorHandling(async () => {
|
|
43
|
+
await ensureDestructiveAllowed({
|
|
44
|
+
verb: "apps archive",
|
|
45
|
+
...opts
|
|
46
|
+
});
|
|
47
|
+
const { client, host, appId, serverSlug } = await resolveAppId(opts.account, opts.slug);
|
|
48
|
+
const updated = await archiveApp(client, appId);
|
|
49
|
+
if (opts.json) {
|
|
50
|
+
console.log(JSON.stringify({
|
|
51
|
+
host,
|
|
52
|
+
app_id: appId,
|
|
53
|
+
slug: serverSlug,
|
|
54
|
+
status: updated.status
|
|
55
|
+
}, null, 2));
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
console.log(yellow(`✓ apps/${serverSlug}: archived (status=${updated.status})`));
|
|
59
|
+
return 0;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
async function runAppsUnarchive(opts) {
|
|
63
|
+
return withErrorHandling(async () => {
|
|
64
|
+
if (!opts.yes) throw new CliError(`\`apps unarchive\` refused: pass --yes to acknowledge`, 7);
|
|
65
|
+
const { client, host, appId, serverSlug } = await resolveAppId(opts.account, opts.slug);
|
|
66
|
+
const updated = await unarchiveApp(client, appId);
|
|
67
|
+
if (opts.json) {
|
|
68
|
+
console.log(JSON.stringify({
|
|
69
|
+
host,
|
|
70
|
+
app_id: appId,
|
|
71
|
+
slug: serverSlug,
|
|
72
|
+
status: updated.status
|
|
73
|
+
}, null, 2));
|
|
74
|
+
return 0;
|
|
75
|
+
}
|
|
76
|
+
console.log(green(`✓ apps/${serverSlug}: unarchived (status=${updated.status})`));
|
|
77
|
+
return 0;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
async function runAppsDelete(opts) {
|
|
81
|
+
return withErrorHandling(async () => {
|
|
82
|
+
await ensureDestructiveAllowed({
|
|
83
|
+
verb: "apps delete",
|
|
84
|
+
...opts
|
|
85
|
+
});
|
|
86
|
+
const { client, host, appId, serverSlug } = await resolveAppId(opts.account, opts.slug);
|
|
87
|
+
await deleteApp(client, appId);
|
|
88
|
+
if (opts.json) {
|
|
89
|
+
console.log(JSON.stringify({
|
|
90
|
+
host,
|
|
91
|
+
app_id: appId,
|
|
92
|
+
slug: serverSlug,
|
|
93
|
+
deleted: true
|
|
94
|
+
}, null, 2));
|
|
95
|
+
return 0;
|
|
96
|
+
}
|
|
97
|
+
console.log(yellow(`✓ apps/${serverSlug}: deleted`));
|
|
98
|
+
console.log(dim(` (local .anna/app.json may now be stale; remove it manually if you no longer need it)`));
|
|
99
|
+
return 0;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
//#endregion
|
|
104
|
+
export { runAppsArchive, runAppsDelete, runAppsUnarchive, runAppsUnpublish };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import "./credentials-BTv2IfUZ.js";
|
|
2
|
+
import { deleteWorkingDraft, getWorkingDraft } from "./apps-B1Nd8l_t.js";
|
|
3
|
+
import "./client-Dn9zThOd.js";
|
|
4
|
+
import "./bundled-executas-BNOKw4kv.js";
|
|
5
|
+
import "./executas-Cep6KEo0.js";
|
|
6
|
+
import "./executa-cache-BFoUtb4J.js";
|
|
7
|
+
import "./executa-publish-Ca5V7MyA.js";
|
|
8
|
+
import "./manifest-DGwRap2i.js";
|
|
9
|
+
import { resolveClient, withErrorHandling } from "./_lifecycle-shared-sbea9HtH.js";
|
|
10
|
+
import "./app-cache-BEM653Th.js";
|
|
11
|
+
import { resolveAppBySlugOrCache } from "./working-orchestration-Dw9u1Vq0.js";
|
|
12
|
+
import { dim, green, yellow } from "kleur/colors";
|
|
13
|
+
|
|
14
|
+
//#region src/commands/apps-discard.ts
|
|
15
|
+
async function runAppsDiscard(opts) {
|
|
16
|
+
return withErrorHandling(async () => {
|
|
17
|
+
const { client, host } = resolveClient({ account: opts.account });
|
|
18
|
+
const app = await resolveAppBySlugOrCache(client, host, {
|
|
19
|
+
slug: opts.slug,
|
|
20
|
+
cwd: opts.cwd
|
|
21
|
+
});
|
|
22
|
+
const existing = await getWorkingDraft(client, app.id);
|
|
23
|
+
if (opts.dryRun) {
|
|
24
|
+
if (!opts.json) console.log(yellow(existing ? `[dry-run] would discard working draft (rev ${existing.revision}) for apps/${app.slug}` : `[dry-run] no working draft for apps/${app.slug} (nothing to discard)`));
|
|
25
|
+
return 0;
|
|
26
|
+
}
|
|
27
|
+
await deleteWorkingDraft(client, app.id);
|
|
28
|
+
if (opts.json) {
|
|
29
|
+
console.log(JSON.stringify({
|
|
30
|
+
app_id: app.id,
|
|
31
|
+
slug: app.slug,
|
|
32
|
+
host,
|
|
33
|
+
discarded: existing !== null
|
|
34
|
+
}, null, 2));
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
if (existing) console.log(green(`✓ apps/${app.slug}: discarded working draft `) + dim(`(was rev ${existing.revision})`));
|
|
38
|
+
else console.log(dim(`apps/${app.slug}: no working draft — nothing to discard`));
|
|
39
|
+
return 0;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
export { runAppsDiscard };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import "./credentials-BTv2IfUZ.js";
|
|
2
|
+
import { findAppBySlug, getAppGrants } from "./apps-B1Nd8l_t.js";
|
|
3
|
+
import { CliError } from "./client-Dn9zThOd.js";
|
|
4
|
+
import { resolveClient, withErrorHandling } from "./_lifecycle-shared-sbea9HtH.js";
|
|
5
|
+
import { bold, cyan, dim } from "kleur/colors";
|
|
6
|
+
|
|
7
|
+
//#region src/commands/apps-grants.ts
|
|
8
|
+
async function runAppsGrants(opts) {
|
|
9
|
+
return withErrorHandling(async () => {
|
|
10
|
+
const { client, host } = resolveClient({ account: opts.account });
|
|
11
|
+
const app = await findAppBySlug(client, opts.slug);
|
|
12
|
+
if (!app) throw new CliError(`no app with slug "${opts.slug}" on ${host}`, 5);
|
|
13
|
+
const grants = await getAppGrants(client, app.id);
|
|
14
|
+
if (opts.json) {
|
|
15
|
+
console.log(JSON.stringify({
|
|
16
|
+
host,
|
|
17
|
+
app_id: app.id,
|
|
18
|
+
slug: app.slug,
|
|
19
|
+
grants
|
|
20
|
+
}, null, 2));
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
23
|
+
console.log(bold(cyan(`apps/${app.slug}`)) + " " + dim(`grants`));
|
|
24
|
+
if (!grants) {
|
|
25
|
+
console.log(dim(" (no grants endpoint data available)"));
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
console.log(JSON.stringify(grants, null, 2));
|
|
29
|
+
return 0;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
34
|
+
export { runAppsGrants };
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { canonicalHost } from "./credentials-BTv2IfUZ.js";
|
|
2
|
+
import { createApp, createVersion, 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 { bumpVersion, bundleHash, manifestHash, rewriteVersion, runExecutaPublish } from "./executa-publish-Ca5V7MyA.js";
|
|
6
|
+
import { loadAppManifest } from "./manifest-DGwRap2i.js";
|
|
7
|
+
import { resolveClient, withErrorHandling } from "./_lifecycle-shared-sbea9HtH.js";
|
|
8
|
+
import { appCacheMatches, readAppIdentity, writeAppIdentity } from "./app-cache-BEM653Th.js";
|
|
9
|
+
import { isExistingDir, uploadAppBundle } from "./app-bundle-upload-DuLalcSt.js";
|
|
10
|
+
import { resolve } from "node:path";
|
|
11
|
+
import { bold, cyan, dim, green, yellow } from "kleur/colors";
|
|
12
|
+
|
|
13
|
+
//#region src/commands/apps-publish.ts
|
|
14
|
+
async function runAppsPublish(opts) {
|
|
15
|
+
return withErrorHandling(async () => {
|
|
16
|
+
const cwd = resolve(opts.cwd ?? process.cwd());
|
|
17
|
+
const manifest = loadAppManifest(cwd, opts.manifest);
|
|
18
|
+
const { client, host, source } = resolveClient({ account: opts.account });
|
|
19
|
+
if (!opts.json) {
|
|
20
|
+
console.log(dim(`using PAT from ${source} (host=${host})`));
|
|
21
|
+
console.log(yellow("⚠ `apps publish` mints an immutable version directly. The Option-C working-draft flow is now preferred:"));
|
|
22
|
+
console.log(dim(" anna-app apps push ") + dim("# upsert the mutable working draft (safe every commit)"));
|
|
23
|
+
console.log(dim(" anna-app apps cut <version> ") + dim("# snapshot + freeze executa deps"));
|
|
24
|
+
}
|
|
25
|
+
if (opts.bump) {
|
|
26
|
+
const next = bumpVersion(manifest.version, opts.bump);
|
|
27
|
+
if (!opts.json) console.log(yellow(`↑ bumping manifest.version: ${manifest.version} → ${next}`));
|
|
28
|
+
if (!opts.noWrite && !opts.dryRun) rewriteVersion(manifest.metadataPath, manifest.metadataRaw, next);
|
|
29
|
+
manifest.version = next;
|
|
30
|
+
manifest.metadataRaw.version = next;
|
|
31
|
+
if (manifest.metadataRaw !== manifest.raw && "version" in manifest.raw) manifest.raw.version = next;
|
|
32
|
+
}
|
|
33
|
+
const overrides = parseExecutaIdOverrides(opts.executaId);
|
|
34
|
+
const bundledActive = !opts.noBundledExecutas && (manifest.bundledExecutas.length > 0 || overrides.length > 0);
|
|
35
|
+
let publishManifestRaw = manifest.raw;
|
|
36
|
+
if (bundledActive) {
|
|
37
|
+
const { referenced } = validateBundledHandles(manifest.raw, manifest.bundledExecutas, overrides);
|
|
38
|
+
const overrideMap = new Map(overrides.map((o) => [o.handle, o.toolId]));
|
|
39
|
+
const lock = readExecutasLock(cwd, host);
|
|
40
|
+
const resolved = {};
|
|
41
|
+
const lockEntries = {};
|
|
42
|
+
for (const decl of manifest.bundledExecutas) {
|
|
43
|
+
if (overrideMap.has(decl.handle)) {
|
|
44
|
+
const id = overrideMap.get(decl.handle);
|
|
45
|
+
resolved[decl.handle] = id;
|
|
46
|
+
lockEntries[decl.handle] = {
|
|
47
|
+
tool_id: id,
|
|
48
|
+
path: decl.path,
|
|
49
|
+
source: "override"
|
|
50
|
+
};
|
|
51
|
+
if (!opts.json) console.log(dim(` bundled:${decl.handle} → ${id} (override)`));
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (opts.skipExecutaPublish) {
|
|
55
|
+
const cachedId = lock?.executas[decl.handle]?.tool_id;
|
|
56
|
+
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);
|
|
57
|
+
resolved[decl.handle] = cachedId;
|
|
58
|
+
lockEntries[decl.handle] = {
|
|
59
|
+
tool_id: cachedId,
|
|
60
|
+
path: decl.path,
|
|
61
|
+
source: "cache"
|
|
62
|
+
};
|
|
63
|
+
if (!opts.json) console.log(dim(` bundled:${decl.handle} → ${cachedId} (cache)`));
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const execCwd = resolve(cwd, decl.path);
|
|
67
|
+
if (opts.dryRun) {
|
|
68
|
+
if (!opts.json) console.log(yellow(` [dry-run] would publish bundled executa "${decl.handle}" from ${decl.path}`));
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (!opts.json) console.log(dim(` publishing bundled executa "${decl.handle}" (${decl.path})…`));
|
|
72
|
+
let captured;
|
|
73
|
+
const code = await runExecutaPublish({
|
|
74
|
+
cwd: execCwd,
|
|
75
|
+
account: opts.account,
|
|
76
|
+
quiet: true,
|
|
77
|
+
capture: (r) => {
|
|
78
|
+
captured = r;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
if (code !== 0 || !captured) throw new CliError(`failed to publish bundled executa "${decl.handle}" (${decl.path})`, code === 0 ? 4 : code);
|
|
82
|
+
resolved[decl.handle] = captured.tool_id;
|
|
83
|
+
lockEntries[decl.handle] = {
|
|
84
|
+
tool_id: captured.tool_id,
|
|
85
|
+
path: decl.path,
|
|
86
|
+
source: "published"
|
|
87
|
+
};
|
|
88
|
+
if (!opts.json) console.log(green(` ✓ bundled:${decl.handle} → ${captured.tool_id}`) + dim(` (v${captured.version}${captured.idempotent_hit ? ", unchanged" : ""})`));
|
|
89
|
+
}
|
|
90
|
+
for (const o of overrides) if (!(o.handle in resolved)) {
|
|
91
|
+
resolved[o.handle] = o.toolId;
|
|
92
|
+
lockEntries[o.handle] = {
|
|
93
|
+
tool_id: o.toolId,
|
|
94
|
+
source: "override"
|
|
95
|
+
};
|
|
96
|
+
if (!opts.json) console.log(dim(` bundled:${o.handle} → ${o.toolId} (override)`));
|
|
97
|
+
}
|
|
98
|
+
const missing = [...referenced].filter((h) => !(h in resolved));
|
|
99
|
+
if (missing.length > 0 && !opts.dryRun) throw new CliError(`could not resolve bundled handle(s): ${missing.sort().join(", ")}`, 4);
|
|
100
|
+
if (!opts.dryRun) {
|
|
101
|
+
const merged = {
|
|
102
|
+
$schema: "anna-executas-lock/v1",
|
|
103
|
+
host: canonicalHost(host),
|
|
104
|
+
executas: {
|
|
105
|
+
...lock?.executas ?? {},
|
|
106
|
+
...lockEntries
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
writeExecutasLock(cwd, merged);
|
|
110
|
+
publishManifestRaw = substituteBundledRefs(manifest.raw, resolved);
|
|
111
|
+
const bundleEntry = manifest.raw.ui?.bundle?.entry;
|
|
112
|
+
if (bundleEntry) {
|
|
113
|
+
const bundleDir$1 = resolve(cwd, "bundle");
|
|
114
|
+
if (Object.keys(resolved).length > 0) {
|
|
115
|
+
const sidecar = writeBundleToolIdSidecar(bundleDir$1, resolved);
|
|
116
|
+
if (!opts.json) console.log(dim(` wrote ${sidecar.replace(cwd + "/", "")}`));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
let cached = readAppIdentity(cwd);
|
|
122
|
+
if (cached && cached.host !== canonicalHost(host)) cached = null;
|
|
123
|
+
let appId;
|
|
124
|
+
let serverSlug;
|
|
125
|
+
let firstPublish = false;
|
|
126
|
+
let appIdFromCache = false;
|
|
127
|
+
if (cached && appCacheMatches(cached, host, manifest.slug)) {
|
|
128
|
+
appId = cached.app_id;
|
|
129
|
+
serverSlug = cached.slug;
|
|
130
|
+
appIdFromCache = true;
|
|
131
|
+
} else {
|
|
132
|
+
const found = await findAppBySlug(client, manifest.slug);
|
|
133
|
+
if (found) {
|
|
134
|
+
appId = found.id;
|
|
135
|
+
serverSlug = found.slug;
|
|
136
|
+
} else {
|
|
137
|
+
if (opts.dryRun) {
|
|
138
|
+
if (!opts.json) console.log(yellow(`[dry-run] would create AnnaApp slug=${manifest.slug}, then upload version ${manifest.version}`));
|
|
139
|
+
return 0;
|
|
140
|
+
}
|
|
141
|
+
const created = await createApp(client, {
|
|
142
|
+
slug: manifest.slug,
|
|
143
|
+
name: manifest.name,
|
|
144
|
+
category: manifest.category,
|
|
145
|
+
tagline: manifest.tagline,
|
|
146
|
+
description: manifest.description
|
|
147
|
+
});
|
|
148
|
+
appId = created.id;
|
|
149
|
+
serverSlug = created.slug;
|
|
150
|
+
firstPublish = true;
|
|
151
|
+
}
|
|
152
|
+
writeAppIdentity(cwd, {
|
|
153
|
+
$schema: "anna-app-identity/v1",
|
|
154
|
+
host: canonicalHost(host),
|
|
155
|
+
app_id: appId,
|
|
156
|
+
slug: serverSlug,
|
|
157
|
+
first_published_at: cached?.first_published_at ?? new Date().toISOString()
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (opts.dryRun) {
|
|
161
|
+
if (!opts.json) {
|
|
162
|
+
console.log(yellow(`[dry-run] resolved app_id=${appId} slug=${serverSlug}; would POST version ${manifest.version}`));
|
|
163
|
+
const uiEntry = publishManifestRaw.ui?.bundle?.entry;
|
|
164
|
+
const dryBundleDir = resolve(cwd, opts.bundleDir ?? "bundle");
|
|
165
|
+
if (uiEntry && !opts.noBundle && isExistingDir(dryBundleDir)) console.log(yellow(`[dry-run] would upload UI bundle from ${dryBundleDir} (entry=${uiEntry})`));
|
|
166
|
+
}
|
|
167
|
+
return 0;
|
|
168
|
+
}
|
|
169
|
+
const hashInput = {
|
|
170
|
+
version: manifest.version,
|
|
171
|
+
manifest: publishManifestRaw
|
|
172
|
+
};
|
|
173
|
+
const hashBundleEntry = publishManifestRaw.ui?.bundle?.entry;
|
|
174
|
+
const hashBundleDir = resolve(cwd, opts.bundleDir ?? "bundle");
|
|
175
|
+
const hash = hashBundleEntry && !opts.noBundle && isExistingDir(hashBundleDir) ? bundleHash(hashInput, hashBundleDir) : manifestHash(hashInput);
|
|
176
|
+
let verResp;
|
|
177
|
+
try {
|
|
178
|
+
verResp = await createVersion(client, appId, {
|
|
179
|
+
version: manifest.version,
|
|
180
|
+
changelog: manifest.changelog,
|
|
181
|
+
manifest: publishManifestRaw
|
|
182
|
+
}, hash);
|
|
183
|
+
} catch (e) {
|
|
184
|
+
if (appIdFromCache && e instanceof CliError && e.status === 404) {
|
|
185
|
+
if (!opts.json) console.log(yellow(`\u26a0 cached app_id=${appId} not found on server (deleted?); re-resolving identity and retrying\u2026`));
|
|
186
|
+
const found = await findAppBySlug(client, manifest.slug);
|
|
187
|
+
if (found) {
|
|
188
|
+
appId = found.id;
|
|
189
|
+
serverSlug = found.slug;
|
|
190
|
+
} else {
|
|
191
|
+
const created = await createApp(client, {
|
|
192
|
+
slug: manifest.slug,
|
|
193
|
+
name: manifest.name,
|
|
194
|
+
category: manifest.category,
|
|
195
|
+
tagline: manifest.tagline,
|
|
196
|
+
description: manifest.description
|
|
197
|
+
});
|
|
198
|
+
appId = created.id;
|
|
199
|
+
serverSlug = created.slug;
|
|
200
|
+
firstPublish = true;
|
|
201
|
+
}
|
|
202
|
+
writeAppIdentity(cwd, {
|
|
203
|
+
$schema: "anna-app-identity/v1",
|
|
204
|
+
host: canonicalHost(host),
|
|
205
|
+
app_id: appId,
|
|
206
|
+
slug: serverSlug,
|
|
207
|
+
first_published_at: cached?.first_published_at ?? new Date().toISOString()
|
|
208
|
+
});
|
|
209
|
+
verResp = await createVersion(client, appId, {
|
|
210
|
+
version: manifest.version,
|
|
211
|
+
changelog: manifest.changelog,
|
|
212
|
+
manifest: publishManifestRaw
|
|
213
|
+
}, hash);
|
|
214
|
+
} else throw e;
|
|
215
|
+
}
|
|
216
|
+
let bundleResult = null;
|
|
217
|
+
const uiBundle = publishManifestRaw.ui?.bundle;
|
|
218
|
+
const bundleDir = resolve(cwd, opts.bundleDir ?? "bundle");
|
|
219
|
+
if (uiBundle?.entry && !opts.noBundle) if (!isExistingDir(bundleDir)) {
|
|
220
|
+
if (!opts.json) console.log(yellow(`⚠ manifest declares ui.bundle.entry="${uiBundle.entry}" but bundle dir not found (${bundleDir}); skipping UI bundle upload`));
|
|
221
|
+
} else bundleResult = await uploadAppBundle({
|
|
222
|
+
client,
|
|
223
|
+
appId,
|
|
224
|
+
versionId: verResp.version.id,
|
|
225
|
+
bundleDir,
|
|
226
|
+
entryPath: uiBundle.entry,
|
|
227
|
+
bundleFormat: uiBundle.format,
|
|
228
|
+
externalOrigins: Array.isArray(uiBundle.external_origins) ? uiBundle.external_origins : [],
|
|
229
|
+
log: opts.json ? void 0 : (m) => console.log(dim(m))
|
|
230
|
+
});
|
|
231
|
+
const finalApp = await getApp(client, appId);
|
|
232
|
+
if (opts.json) {
|
|
233
|
+
console.log(JSON.stringify({
|
|
234
|
+
app_id: appId,
|
|
235
|
+
slug: serverSlug,
|
|
236
|
+
host,
|
|
237
|
+
version: verResp.version.version,
|
|
238
|
+
version_id: verResp.version.id,
|
|
239
|
+
content_hash: hash,
|
|
240
|
+
idempotent_hit: verResp.idempotentHit,
|
|
241
|
+
first_publish: firstPublish,
|
|
242
|
+
status: finalApp.status,
|
|
243
|
+
bundle: bundleResult ? {
|
|
244
|
+
status: bundleResult.status,
|
|
245
|
+
bundle_status: bundleResult.detail.status,
|
|
246
|
+
file_count: bundleResult.detail.file_count,
|
|
247
|
+
total_size_bytes: bundleResult.detail.total_size_bytes,
|
|
248
|
+
sha256_manifest: bundleResult.detail.sha256_manifest
|
|
249
|
+
} : null
|
|
250
|
+
}, null, 2));
|
|
251
|
+
return 0;
|
|
252
|
+
}
|
|
253
|
+
if (verResp.idempotentHit) console.log(green(`✓ apps/${serverSlug}: version ${manifest.version} already live (content hash unchanged)`));
|
|
254
|
+
else console.log(green(`✓ apps/${serverSlug}: version ${manifest.version} published (id=${verResp.version.id})`));
|
|
255
|
+
if (firstPublish) console.log(dim(` first publish — wrote .anna/app.json`));
|
|
256
|
+
if (bundleResult) if (bundleResult.status === "skipped") console.log(dim(` UI bundle unchanged — skipped`));
|
|
257
|
+
else console.log(green(` ✓ UI bundle: ${bundleResult.fileCount} files, ${(bundleResult.totalBytes / 1024).toFixed(1)} KB → ${bundleResult.detail.status}`));
|
|
258
|
+
console.log(bold(cyan(`status: ${finalApp.status}`)));
|
|
259
|
+
if (!verResp.idempotentHit) console.log(dim(`→ run `) + cyan(`anna-app apps release ${manifest.version}`) + dim(` to freeze & publish this version`));
|
|
260
|
+
return 0;
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
//#endregion
|
|
265
|
+
export { runAppsPublish };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import "./credentials-BTv2IfUZ.js";
|
|
2
|
+
import "./apps-B1Nd8l_t.js";
|
|
3
|
+
import "./client-Dn9zThOd.js";
|
|
4
|
+
import "./bundled-executas-BNOKw4kv.js";
|
|
5
|
+
import "./executas-Cep6KEo0.js";
|
|
6
|
+
import "./executa-cache-BFoUtb4J.js";
|
|
7
|
+
import "./executa-publish-Ca5V7MyA.js";
|
|
8
|
+
import "./manifest-DGwRap2i.js";
|
|
9
|
+
import "./_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
|
+
|
|
14
|
+
export { runAppsPublish };
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import "./credentials-BTv2IfUZ.js";
|
|
2
|
+
import { getApp, getWorkingDraft, upsertWorkingDraft } from "./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 { bumpVersion, bundleHash, manifestHash, rewriteVersion } from "./executa-publish-Ca5V7MyA.js";
|
|
8
|
+
import { loadAppManifest } from "./manifest-DGwRap2i.js";
|
|
9
|
+
import { resolveClient, withErrorHandling } from "./_lifecycle-shared-sbea9HtH.js";
|
|
10
|
+
import "./app-cache-BEM653Th.js";
|
|
11
|
+
import { resolveAppIdentity, resolveBundledExecutas } from "./working-orchestration-Dw9u1Vq0.js";
|
|
12
|
+
import { isExistingDir, uploadWorkingBundle } from "./app-bundle-upload-DuLalcSt.js";
|
|
13
|
+
import { resolve } from "node:path";
|
|
14
|
+
import { bold, cyan, dim, green, yellow } from "kleur/colors";
|
|
15
|
+
|
|
16
|
+
//#region src/commands/apps-push.ts
|
|
17
|
+
async function runAppsPush(opts) {
|
|
18
|
+
return withErrorHandling(async () => {
|
|
19
|
+
const cwd = resolve(opts.cwd ?? process.cwd());
|
|
20
|
+
const manifest = loadAppManifest(cwd, opts.manifest);
|
|
21
|
+
const { client, host, source } = resolveClient({ account: opts.account });
|
|
22
|
+
if (!opts.json) console.log(dim(`using PAT from ${source} (host=${host})`));
|
|
23
|
+
if (opts.bump) {
|
|
24
|
+
const next = bumpVersion(manifest.version, opts.bump);
|
|
25
|
+
if (!opts.json) console.log(yellow(`↑ bumping manifest.version: ${manifest.version} → ${next}`));
|
|
26
|
+
if (!opts.noWrite && !opts.dryRun) rewriteVersion(manifest.metadataPath, manifest.metadataRaw, next);
|
|
27
|
+
manifest.version = next;
|
|
28
|
+
manifest.metadataRaw.version = next;
|
|
29
|
+
}
|
|
30
|
+
const { publishManifestRaw } = await resolveBundledExecutas({
|
|
31
|
+
manifest,
|
|
32
|
+
cwd,
|
|
33
|
+
host,
|
|
34
|
+
executaId: opts.executaId,
|
|
35
|
+
skipExecutaPublish: opts.skipExecutaPublish,
|
|
36
|
+
noBundledExecutas: opts.noBundledExecutas,
|
|
37
|
+
dryRun: opts.dryRun,
|
|
38
|
+
freeze: false,
|
|
39
|
+
lockSource: "working",
|
|
40
|
+
account: opts.account,
|
|
41
|
+
json: opts.json
|
|
42
|
+
});
|
|
43
|
+
const identity = await resolveAppIdentity({
|
|
44
|
+
client,
|
|
45
|
+
cwd,
|
|
46
|
+
host,
|
|
47
|
+
manifest,
|
|
48
|
+
dryRun: opts.dryRun,
|
|
49
|
+
json: opts.json
|
|
50
|
+
});
|
|
51
|
+
if (!identity) return 0;
|
|
52
|
+
const { appId, serverSlug, firstPublish } = identity;
|
|
53
|
+
const hashInput = {
|
|
54
|
+
version: manifest.version,
|
|
55
|
+
manifest: publishManifestRaw
|
|
56
|
+
};
|
|
57
|
+
const bundleEntry = publishManifestRaw.ui?.bundle?.entry;
|
|
58
|
+
const bundleDir = resolve(cwd, opts.bundleDir ?? "bundle");
|
|
59
|
+
const hasBundle = !!bundleEntry && !opts.noBundle && isExistingDir(bundleDir);
|
|
60
|
+
const hash = hasBundle ? bundleHash(hashInput, bundleDir) : manifestHash(hashInput);
|
|
61
|
+
if (opts.dryRun) {
|
|
62
|
+
if (!opts.json) console.log(yellow(`[dry-run] app_id=${appId} slug=${serverSlug}; would PUT /working (content_hash=${hash.slice(0, 12)}…)` + (hasBundle ? ` + stage working bundle from ${bundleDir}` : "")));
|
|
63
|
+
return 0;
|
|
64
|
+
}
|
|
65
|
+
let resp;
|
|
66
|
+
try {
|
|
67
|
+
resp = await upsertWorkingDraft(client, appId, {
|
|
68
|
+
manifest: publishManifestRaw,
|
|
69
|
+
changelog: manifest.changelog,
|
|
70
|
+
content_hash: hash
|
|
71
|
+
}, opts.ifMatch);
|
|
72
|
+
} catch (e) {
|
|
73
|
+
if (e instanceof CliError && e.status === 409) throw new CliError(`working draft was modified concurrently (If-Match=${opts.ifMatch} is stale); re-run \`apps push\` without --if-match for last-writer-wins, or fetch the current revision with \`apps status\``, 4);
|
|
74
|
+
throw e;
|
|
75
|
+
}
|
|
76
|
+
let bundleResult = null;
|
|
77
|
+
if (hasBundle) {
|
|
78
|
+
const uiBundle = publishManifestRaw.ui.bundle;
|
|
79
|
+
const skipStage = resp.unchanged && resp.bundle_status === "ready";
|
|
80
|
+
if (!skipStage) bundleResult = await uploadWorkingBundle({
|
|
81
|
+
client,
|
|
82
|
+
appId,
|
|
83
|
+
bundleDir,
|
|
84
|
+
entryPath: uiBundle.entry,
|
|
85
|
+
bundleFormat: uiBundle.format,
|
|
86
|
+
externalOrigins: Array.isArray(uiBundle.external_origins) ? uiBundle.external_origins : [],
|
|
87
|
+
log: opts.json ? void 0 : (m) => console.log(dim(m))
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
const finalApp = await getApp(client, appId);
|
|
91
|
+
const draft = await getWorkingDraft(client, appId);
|
|
92
|
+
if (opts.json) {
|
|
93
|
+
console.log(JSON.stringify({
|
|
94
|
+
app_id: appId,
|
|
95
|
+
slug: serverSlug,
|
|
96
|
+
host,
|
|
97
|
+
revision: resp.revision,
|
|
98
|
+
content_hash: resp.content_hash,
|
|
99
|
+
unchanged: resp.unchanged,
|
|
100
|
+
bundle_status: resp.bundle_status,
|
|
101
|
+
first_publish: firstPublish,
|
|
102
|
+
status: finalApp.status,
|
|
103
|
+
dirty_vs_latest_cut: draft?.dirty_vs_latest_cut ?? null,
|
|
104
|
+
bundle: bundleResult ? {
|
|
105
|
+
status: bundleResult.status,
|
|
106
|
+
file_count: bundleResult.fileCount,
|
|
107
|
+
total_size_bytes: bundleResult.totalBytes,
|
|
108
|
+
bundle_status: bundleResult.bundleStatus
|
|
109
|
+
} : null
|
|
110
|
+
}, null, 2));
|
|
111
|
+
return 0;
|
|
112
|
+
}
|
|
113
|
+
if (resp.unchanged) console.log(green(`✓ apps/${serverSlug}: working draft unchanged (rev ${resp.revision})`));
|
|
114
|
+
else console.log(green(`✓ apps/${serverSlug}: working draft updated (rev ${resp.revision})`));
|
|
115
|
+
if (firstPublish) console.log(dim(` first push — wrote .anna/app.json`));
|
|
116
|
+
if (bundleResult) if (bundleResult.status === "skipped") console.log(dim(` working bundle unchanged — skipped`));
|
|
117
|
+
else console.log(green(` ✓ working bundle: ${bundleResult.fileCount} files, ${(bundleResult.totalBytes / 1024).toFixed(1)} KB → ${bundleResult.bundleStatus}`));
|
|
118
|
+
console.log(bold(cyan(`status: ${finalApp.status}`)));
|
|
119
|
+
if (draft?.dirty_vs_latest_cut) console.log(dim(` (uncommitted changes vs latest cut version)`));
|
|
120
|
+
console.log(dim(`→ install & test the draft (reserved `) + cyan(`0.0.0-draft`) + dim(`) from the Developer Console`));
|
|
121
|
+
console.log(dim(`→ run `) + cyan(`anna-app apps cut ${manifest.version}`) + dim(` to snapshot an immutable version`));
|
|
122
|
+
return 0;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
//#endregion
|
|
127
|
+
export { runAppsPush };
|