@anna-ai/cli 0.1.17 → 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.
Files changed (63) hide show
  1. package/dist/_lifecycle-shared-sbea9HtH.js +65 -0
  2. package/dist/{agent-DUmINbo4.js → agent-Br6zY2qw.js} +1 -1
  3. package/dist/app-bundle-upload-DuLalcSt.js +213 -0
  4. package/dist/app-cache-BEM653Th.js +53 -0
  5. package/dist/apps-B1Nd8l_t.js +221 -0
  6. package/dist/apps-BTn9EN0x.js +53 -0
  7. package/dist/apps-cut-DtEkddIk.js +83 -0
  8. package/dist/apps-destructive-DSTrcFUP.js +104 -0
  9. package/dist/apps-discard-y3_IwcbQ.js +44 -0
  10. package/dist/apps-grants-BGWlpee0.js +34 -0
  11. package/dist/apps-publish-CaTCanDu.js +265 -0
  12. package/dist/apps-publish-DfZTOxBJ.js +14 -0
  13. package/dist/apps-push-B9XT2uwF.js +127 -0
  14. package/dist/apps-release-BLH9XSxB.js +135 -0
  15. package/dist/apps-status-DQ9RvlME.js +58 -0
  16. package/dist/apps-submit-review-DLwCxeAs.js +45 -0
  17. package/dist/apps-sync-meta-D9eKMMUp.js +72 -0
  18. package/dist/apps-versions-2Tmk0nsx.js +43 -0
  19. package/dist/{bridge-Dffh9JUd.js → bridge-BuklhzeE.js} +1 -1
  20. package/dist/bridge-Id8K8gr-.js +3 -0
  21. package/dist/bundled-executas-BNOKw4kv.js +161 -0
  22. package/dist/bundled-executas-CNaV2C_O.js +5 -0
  23. package/dist/cli.js +334 -20
  24. package/dist/client-Dn9zThOd.js +150 -0
  25. package/dist/confirm-DxHkk9Wn.js +37 -0
  26. package/dist/dev-BS_8yoSm.js +3 -0
  27. package/dist/{dev-BUetXnfG.js → dev-E7mqXj5S.js} +95 -26
  28. package/dist/{dev-app-cache-3Pfesngr.js → dev-app-cache-D-r6ZpEk.js} +11 -2
  29. package/dist/{doctor-Dxkx0eqv.js → doctor-DKrt-Kda.js} +1 -1
  30. package/dist/executa-cache-BFoUtb4J.js +86 -0
  31. package/dist/executa-cache-WBkCLic7.js +4 -0
  32. package/dist/executa-destructive-COQE4Xqi.js +104 -0
  33. package/dist/{executa-dev-BzhSd_A2.js → executa-dev-BvS9zTpO.js} +11 -11
  34. package/dist/executa-publish-B88_9gbp.js +9 -0
  35. package/dist/executa-publish-Ca5V7MyA.js +258 -0
  36. package/dist/executa-reads-CQ6S8gHY.js +107 -0
  37. package/dist/executas-Cep6KEo0.js +109 -0
  38. package/dist/manifest-DGwRap2i.js +188 -0
  39. package/dist/publish-C1wcf-qI.js +58 -0
  40. package/dist/{server-6WHNkydc.js → server-_IG8Igje.js} +215 -4
  41. package/dist/{storage-EQJA_0UW.js → storage-CTkApNQ9.js} +1 -1
  42. package/dist/token-B9JUPelx.js +87 -0
  43. package/dist/working-orchestration-Dw9u1Vq0.js +190 -0
  44. package/package.json +3 -3
  45. package/templates/executa/go/executa.json +5 -0
  46. package/templates/executa/node/executa.json +5 -0
  47. package/templates/executa/python/executa.json +5 -0
  48. package/dist/apps-ClgEOdKD.js +0 -44
  49. package/dist/bridge-B1vq1oG3.js +0 -3
  50. package/dist/dev-Bi6rkb1x.js +0 -3
  51. package/dist/dev-app-cache-CZ1UjMz0.js +0 -4
  52. /package/dist/{credentials-DDqx6XMQ.js → credentials-DklPMD22.js} +0 -0
  53. /package/dist/{dev-account-DCyjamBa.js → dev-account-qRaET1Cp.js} +0 -0
  54. /package/dist/{executa-init-COEmKDOE.js → executa-init-Jp-h9OI7.js} +0 -0
  55. /package/dist/{executa-register-66WKIwQQ.js → executa-register-CulDtwYZ.js} +0 -0
  56. /package/dist/{fixture-CATHyLLI.js → fixture-CYwxbiQD.js} +0 -0
  57. /package/dist/{host_upload-C_pGOS6p.js → host_upload-GXVkDM5M.js} +0 -0
  58. /package/dist/{image-bwolX7pa.js → image-DduR91n5.js} +0 -0
  59. /package/dist/{login-CsIVbrmf.js → login-BGqFjQwH.js} +0 -0
  60. /package/dist/{logout-gfmKQxMj.js → logout-CGIRKH3y.js} +0 -0
  61. /package/dist/{runner-DmGLdat0.js → runner-B-hIqx5L.js} +0 -0
  62. /package/dist/{sampling-CJUDG-mf.js → sampling-CXke7hq1.js} +0 -0
  63. /package/dist/{whoami-BS5wy-Nh.js → whoami-BoFLEUcp.js} +0 -0
@@ -0,0 +1,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 };