@zuplo/cli 7.9.12 → 7.9.14

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 (59) hide show
  1. package/dist/__tests__/integration/source-upgrade.integration.test.d.ts +2 -0
  2. package/dist/__tests__/integration/source-upgrade.integration.test.d.ts.map +1 -0
  3. package/dist/__tests__/integration/source-upgrade.integration.test.js +100 -0
  4. package/dist/__tests__/integration/source-upgrade.integration.test.js.map +1 -0
  5. package/dist/cmds/source/upgrade.d.ts.map +1 -1
  6. package/dist/cmds/source/upgrade.js +45 -2
  7. package/dist/cmds/source/upgrade.js.map +1 -1
  8. package/dist/source/ai-gateway/catalog.json +411 -0
  9. package/dist/source/ai-gateway/files.d.ts +16 -0
  10. package/dist/source/ai-gateway/files.d.ts.map +1 -0
  11. package/dist/source/ai-gateway/files.js +174 -0
  12. package/dist/source/ai-gateway/files.js.map +1 -0
  13. package/dist/source/ai-gateway/files.test.d.ts +2 -0
  14. package/dist/source/ai-gateway/files.test.d.ts.map +1 -0
  15. package/dist/source/ai-gateway/files.test.js +135 -0
  16. package/dist/source/ai-gateway/files.test.js.map +1 -0
  17. package/dist/source/ai-gateway/handler.d.ts +31 -0
  18. package/dist/source/ai-gateway/handler.d.ts.map +1 -0
  19. package/dist/source/ai-gateway/handler.js +140 -0
  20. package/dist/source/ai-gateway/handler.js.map +1 -0
  21. package/dist/source/ai-gateway/handler.test.d.ts +2 -0
  22. package/dist/source/ai-gateway/handler.test.d.ts.map +1 -0
  23. package/dist/source/ai-gateway/handler.test.js +113 -0
  24. package/dist/source/ai-gateway/handler.test.js.map +1 -0
  25. package/dist/source/ai-gateway/package.test.d.ts +2 -0
  26. package/dist/source/ai-gateway/package.test.d.ts.map +1 -0
  27. package/dist/source/ai-gateway/package.test.js +30 -0
  28. package/dist/source/ai-gateway/package.test.js.map +1 -0
  29. package/dist/source/ai-gateway/planner.d.ts +132 -0
  30. package/dist/source/ai-gateway/planner.d.ts.map +1 -0
  31. package/dist/source/ai-gateway/planner.js +365 -0
  32. package/dist/source/ai-gateway/planner.js.map +1 -0
  33. package/dist/source/ai-gateway/planner.test.d.ts +2 -0
  34. package/dist/source/ai-gateway/planner.test.d.ts.map +1 -0
  35. package/dist/source/ai-gateway/planner.test.js +282 -0
  36. package/dist/source/ai-gateway/planner.test.js.map +1 -0
  37. package/dist/source/ai-gateway/release.d.ts +19 -0
  38. package/dist/source/ai-gateway/release.d.ts.map +1 -0
  39. package/dist/source/ai-gateway/release.js +75 -0
  40. package/dist/source/ai-gateway/release.js.map +1 -0
  41. package/dist/source/ai-gateway/release.test.d.ts +2 -0
  42. package/dist/source/ai-gateway/release.test.d.ts.map +1 -0
  43. package/dist/source/ai-gateway/release.test.js +62 -0
  44. package/dist/source/ai-gateway/release.test.js.map +1 -0
  45. package/dist/tsconfig.tsbuildinfo +1 -1
  46. package/node_modules/@zuplo/core/package.json +1 -1
  47. package/node_modules/@zuplo/graphql/package.json +1 -1
  48. package/node_modules/@zuplo/openapi-tools/package.json +1 -1
  49. package/node_modules/@zuplo/otel/package.json +1 -1
  50. package/node_modules/@zuplo/runtime/out/esm/{chunk-2XSPVUOE.js → chunk-Q3IDJ2WR.js} +107 -107
  51. package/node_modules/@zuplo/runtime/out/esm/chunk-Q3IDJ2WR.js.map +1 -0
  52. package/node_modules/@zuplo/runtime/out/esm/index.js +1 -1
  53. package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js +1 -1
  54. package/node_modules/@zuplo/runtime/out/esm/mocks/index.js +1 -1
  55. package/node_modules/@zuplo/runtime/out/types/index.d.ts +39 -38
  56. package/node_modules/@zuplo/runtime/package.json +1 -1
  57. package/package.json +11 -11
  58. package/node_modules/@zuplo/runtime/out/esm/chunk-2XSPVUOE.js.map +0 -1
  59. /package/node_modules/@zuplo/runtime/out/esm/{chunk-2XSPVUOE.js.LEGAL.txt → chunk-Q3IDJ2WR.js.LEGAL.txt} +0 -0
@@ -0,0 +1,113 @@
1
+ import assert from "node:assert/strict";
2
+ import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import path from "node:path";
5
+ import { afterEach, describe, it, mock } from "node:test";
6
+ import { git, readProject } from "./files.js";
7
+ import { upgradeGateway } from "./handler.js";
8
+ import { AI_OAS, catalog } from "./planner.js";
9
+ const roots = [];
10
+ afterEach(async () => {
11
+ mock.restoreAll();
12
+ for (const root of roots.splice(0))
13
+ await rm(root, { recursive: true, force: true });
14
+ });
15
+ async function fixture() {
16
+ mock.method(console, "log", () => { });
17
+ mock.method(console, "error", () => { });
18
+ const root = await mkdtemp(path.join(tmpdir(), "gateway-flow-"));
19
+ roots.push(root);
20
+ const dir = path.join(root, "project");
21
+ for (const [file, value] of Object.entries(catalog.snapshots[1].files)) {
22
+ await mkdir(path.dirname(path.join(dir, file)), { recursive: true });
23
+ await writeFile(path.join(dir, file), value);
24
+ }
25
+ await git(dir, ["init"]);
26
+ await git(dir, ["add", "./*"]);
27
+ await git(dir, [
28
+ "-c",
29
+ "user.name=Test",
30
+ "-c",
31
+ "user.email=test@example.com",
32
+ "-c",
33
+ "commit.gpgsign=false",
34
+ "commit",
35
+ "-m",
36
+ "baseline",
37
+ ]);
38
+ const before = await readProject(dir);
39
+ const services = {
40
+ version: async () => "1.2.3",
41
+ release: async () => ({ latest: "1.2.3" }),
42
+ runtime: async () => ({
43
+ version: "1.2.3",
44
+ manifest: "fake-runtime/package.json",
45
+ contents: '{"version":"1.2.3"}',
46
+ }),
47
+ backupRoot: path.join(root, "backups"),
48
+ };
49
+ return { dir, before, services };
50
+ }
51
+ describe("AI Gateway upgrade workflow", () => {
52
+ it("previews without writing and applies only with explicit action", async () => {
53
+ const { dir, before, services } = await fixture();
54
+ assert.equal(await upgradeGateway({ dir, prompt: false }, services), 0);
55
+ assert.deepEqual(await readProject(dir), before);
56
+ assert.equal(await upgradeGateway({ dir, prompt: false, apply: true }, services), 0);
57
+ assert.notEqual((await readProject(dir))[AI_OAS], before[AI_OAS]);
58
+ });
59
+ it("shows an exact preview without an installed runtime but blocks application", async () => {
60
+ const { dir, before, services } = await fixture();
61
+ const unavailable = {
62
+ ...services,
63
+ runtime: async () => {
64
+ throw new Error("not installed");
65
+ },
66
+ };
67
+ assert.equal(await upgradeGateway({ dir, prompt: false }, unavailable), 0);
68
+ const output = console.log.mock.calls
69
+ .map((call) => call.arguments.join(" "))
70
+ .join("\n");
71
+ assert.match(output, /diff --git/);
72
+ assert.equal(await upgradeGateway({ dir, prompt: false, apply: true }, unavailable), 2);
73
+ assert.deepEqual(await readProject(dir), before);
74
+ });
75
+ it("allows an offline preview but refuses offline application", async () => {
76
+ const { dir, before, services } = await fixture();
77
+ const offline = {
78
+ ...services,
79
+ release: async () => ({ blocker: "offline: latest release unverified" }),
80
+ };
81
+ assert.equal(await upgradeGateway({ dir, prompt: false }, offline), 0);
82
+ assert.equal(await upgradeGateway({ dir, prompt: false, apply: true }, offline), 2);
83
+ assert.deepEqual(await readProject(dir), before);
84
+ });
85
+ it("does not write after declined confirmation or a release change during confirmation", async () => {
86
+ const { dir, before, services } = await fixture();
87
+ assert.equal(await upgradeGateway({ dir, prompt: true, apply: true }, { ...services, interactive: () => true, confirm: async () => false }), 0);
88
+ let checks = 0;
89
+ assert.equal(await upgradeGateway({ dir, prompt: true, apply: true }, {
90
+ ...services,
91
+ interactive: () => true,
92
+ confirm: async () => true,
93
+ release: async () => ++checks === 1
94
+ ? { latest: "1.2.3" }
95
+ : { latest: "1.2.4", blocker: "release changed" },
96
+ }), 2);
97
+ assert.deepEqual(await readProject(dir), before);
98
+ });
99
+ it("blocks incompatible runtime and noninteractive confirmation", async () => {
100
+ const { dir, before, services } = await fixture();
101
+ assert.equal(await upgradeGateway({ dir, prompt: false, apply: true }, {
102
+ ...services,
103
+ runtime: async () => ({
104
+ version: "1.0.0",
105
+ manifest: "runtime",
106
+ contents: "old",
107
+ }),
108
+ }), 2);
109
+ assert.equal(await upgradeGateway({ dir, prompt: true, apply: true }, { ...services, interactive: () => false }), 2);
110
+ assert.deepEqual(await readProject(dir), before);
111
+ });
112
+ });
113
+ //# sourceMappingURL=handler.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.test.js","sourceRoot":"","sources":["../../../src/source/ai-gateway/handler.test.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert/strict\";\nimport { mkdir, mkdtemp, rm, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { afterEach, describe, it, mock } from \"node:test\";\nimport { git, readProject } from \"./files.js\";\nimport { upgradeGateway } from \"./handler.js\";\nimport { AI_OAS, catalog } from \"./planner.js\";\n\nconst roots: string[] = [];\nafterEach(async () => {\n mock.restoreAll();\n for (const root of roots.splice(0))\n await rm(root, { recursive: true, force: true });\n});\nasync function fixture() {\n mock.method(console, \"log\", () => {});\n mock.method(console, \"error\", () => {});\n const root = await mkdtemp(path.join(tmpdir(), \"gateway-flow-\"));\n roots.push(root);\n const dir = path.join(root, \"project\");\n for (const [file, value] of Object.entries(catalog.snapshots[1].files)) {\n await mkdir(path.dirname(path.join(dir, file)), { recursive: true });\n await writeFile(path.join(dir, file), value);\n }\n await git(dir, [\"init\"]);\n await git(dir, [\"add\", \"./*\"]);\n await git(dir, [\n \"-c\",\n \"user.name=Test\",\n \"-c\",\n \"user.email=test@example.com\",\n \"-c\",\n \"commit.gpgsign=false\",\n \"commit\",\n \"-m\",\n \"baseline\",\n ]);\n const before = await readProject(dir);\n const services = {\n version: async () => \"1.2.3\",\n release: async () => ({ latest: \"1.2.3\" }),\n runtime: async () => ({\n version: \"1.2.3\",\n manifest: \"fake-runtime/package.json\",\n contents: '{\"version\":\"1.2.3\"}',\n }),\n backupRoot: path.join(root, \"backups\"),\n };\n return { dir, before, services };\n}\n\ndescribe(\"AI Gateway upgrade workflow\", () => {\n it(\"previews without writing and applies only with explicit action\", async () => {\n const { dir, before, services } = await fixture();\n assert.equal(await upgradeGateway({ dir, prompt: false }, services), 0);\n assert.deepEqual(await readProject(dir), before);\n assert.equal(\n await upgradeGateway({ dir, prompt: false, apply: true }, services),\n 0\n );\n assert.notEqual((await readProject(dir))[AI_OAS], before[AI_OAS]);\n });\n it(\"shows an exact preview without an installed runtime but blocks application\", async () => {\n const { dir, before, services } = await fixture();\n const unavailable = {\n ...services,\n runtime: async () => {\n throw new Error(\"not installed\");\n },\n };\n assert.equal(await upgradeGateway({ dir, prompt: false }, unavailable), 0);\n const output = (\n console.log as unknown as { mock: { calls: { arguments: unknown[] }[] } }\n ).mock.calls\n .map((call) => call.arguments.join(\" \"))\n .join(\"\\n\");\n assert.match(output, /diff --git/);\n assert.equal(\n await upgradeGateway({ dir, prompt: false, apply: true }, unavailable),\n 2\n );\n assert.deepEqual(await readProject(dir), before);\n });\n it(\"allows an offline preview but refuses offline application\", async () => {\n const { dir, before, services } = await fixture();\n const offline = {\n ...services,\n release: async () => ({ blocker: \"offline: latest release unverified\" }),\n };\n assert.equal(await upgradeGateway({ dir, prompt: false }, offline), 0);\n assert.equal(\n await upgradeGateway({ dir, prompt: false, apply: true }, offline),\n 2\n );\n assert.deepEqual(await readProject(dir), before);\n });\n it(\"does not write after declined confirmation or a release change during confirmation\", async () => {\n const { dir, before, services } = await fixture();\n assert.equal(\n await upgradeGateway(\n { dir, prompt: true, apply: true },\n { ...services, interactive: () => true, confirm: async () => false }\n ),\n 0\n );\n let checks = 0;\n assert.equal(\n await upgradeGateway(\n { dir, prompt: true, apply: true },\n {\n ...services,\n interactive: () => true,\n confirm: async () => true,\n release: async () =>\n ++checks === 1\n ? { latest: \"1.2.3\" }\n : { latest: \"1.2.4\", blocker: \"release changed\" },\n }\n ),\n 2\n );\n assert.deepEqual(await readProject(dir), before);\n });\n it(\"blocks incompatible runtime and noninteractive confirmation\", async () => {\n const { dir, before, services } = await fixture();\n assert.equal(\n await upgradeGateway(\n { dir, prompt: false, apply: true },\n {\n ...services,\n runtime: async () => ({\n version: \"1.0.0\",\n manifest: \"runtime\",\n contents: \"old\",\n }),\n }\n ),\n 2\n );\n assert.equal(\n await upgradeGateway(\n { dir, prompt: true, apply: true },\n { ...services, interactive: () => false }\n ),\n 2\n );\n assert.deepEqual(await readProject(dir), before);\n });\n});\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=package.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.test.d.ts","sourceRoot":"","sources":["../../../src/source/ai-gateway/package.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,30 @@
1
+ import assert from "node:assert/strict";
2
+ import { execFile } from "node:child_process";
3
+ import { cp, mkdir, mkdtemp, rm, symlink, writeFile } from "node:fs/promises";
4
+ import { tmpdir } from "node:os";
5
+ import path from "node:path";
6
+ import { it } from "node:test";
7
+ import { fileURLToPath, pathToFileURL } from "node:url";
8
+ import { promisify } from "node:util";
9
+ it("loads the compiled catalog from an isolated published-package layout", async () => {
10
+ const root = await mkdtemp(path.join(tmpdir(), "gateway-package-"));
11
+ try {
12
+ const directory = path.join(root, "dist/source/ai-gateway");
13
+ await mkdir(directory, { recursive: true });
14
+ for (const name of ["planner.js", "catalog.json"])
15
+ await cp(new URL(name, import.meta.url), path.join(directory, name));
16
+ await writeFile(path.join(root, "package.json"), '{"type":"module"}');
17
+ await symlink(fileURLToPath(new URL("../../../../../node_modules", import.meta.url)), path.join(root, "node_modules"), "dir");
18
+ const script = `const { catalog, planUpgrade } = await import(${JSON.stringify(pathToFileURL(path.join(directory, "planner.js")).href)}); const plan = planUpgrade(catalog.snapshots[1].files, "1.0.0"); if (plan.blockers.length || !plan.additions.length) process.exit(1);`;
19
+ const result = await promisify(execFile)(process.execPath, [
20
+ "--input-type=module",
21
+ "-e",
22
+ script,
23
+ ]);
24
+ assert.equal(result.stderr, "");
25
+ }
26
+ finally {
27
+ await rm(root, { recursive: true, force: true });
28
+ }
29
+ });
30
+ //# sourceMappingURL=package.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.test.js","sourceRoot":"","sources":["../../../src/source/ai-gateway/package.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;IACpF,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,CAAC,CAAC;IACpE,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC;QAC5D,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,KAAK,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC;YAC/C,MAAM,EAAE,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;QACvE,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,mBAAmB,CAAC,CAAC;QACtE,MAAM,OAAO,CACX,aAAa,CAAC,IAAI,GAAG,CAAC,6BAA6B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EACtE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,EAC/B,KAAK,CACN,CAAC;QACF,MAAM,MAAM,GAAG,iDAAiD,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,wIAAwI,CAAC;QAC/Q,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE;YACzD,qBAAqB;YACrB,IAAI;YACJ,MAAM;SACP,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAClC,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC,CAAC,CAAC","sourcesContent":["import assert from \"node:assert/strict\";\nimport { execFile } from \"node:child_process\";\nimport { cp, mkdir, mkdtemp, rm, symlink, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { it } from \"node:test\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { promisify } from \"node:util\";\n\nit(\"loads the compiled catalog from an isolated published-package layout\", async () => {\n const root = await mkdtemp(path.join(tmpdir(), \"gateway-package-\"));\n try {\n const directory = path.join(root, \"dist/source/ai-gateway\");\n await mkdir(directory, { recursive: true });\n for (const name of [\"planner.js\", \"catalog.json\"])\n await cp(new URL(name, import.meta.url), path.join(directory, name));\n await writeFile(path.join(root, \"package.json\"), '{\"type\":\"module\"}');\n await symlink(\n fileURLToPath(new URL(\"../../../../../node_modules\", import.meta.url)),\n path.join(root, \"node_modules\"),\n \"dir\"\n );\n const script = `const { catalog, planUpgrade } = await import(${JSON.stringify(pathToFileURL(path.join(directory, \"planner.js\")).href)}); const plan = planUpgrade(catalog.snapshots[1].files, \"1.0.0\"); if (plan.blockers.length || !plan.additions.length) process.exit(1);`;\n const result = await promisify(execFile)(process.execPath, [\n \"--input-type=module\",\n \"-e\",\n script,\n ]);\n assert.equal(result.stderr, \"\");\n } finally {\n await rm(root, { recursive: true, force: true });\n }\n});\n"]}
@@ -0,0 +1,132 @@
1
+ import { z } from "zod";
2
+ declare const stepSchema: z.ZodObject<
3
+ {
4
+ id: z.ZodString;
5
+ kind: z.ZodEnum<{
6
+ route: "route";
7
+ policy: "policy";
8
+ }>;
9
+ key: z.ZodString;
10
+ target: z.ZodString;
11
+ runtime: z.ZodString;
12
+ instructions: z.ZodString;
13
+ },
14
+ z.core.$strip
15
+ >;
16
+ export declare const catalogSchema: z.ZodObject<
17
+ {
18
+ formatVersion: z.ZodLiteral<1>;
19
+ target: z.ZodString;
20
+ aliases: z.ZodRecord<z.ZodString, z.ZodString>;
21
+ snapshots: z.ZodArray<
22
+ z.ZodObject<
23
+ {
24
+ revision: z.ZodString;
25
+ sourceCommit: z.ZodString;
26
+ files: z.ZodRecord<z.ZodString, z.ZodString>;
27
+ },
28
+ z.core.$strip
29
+ >
30
+ >;
31
+ steps: z.ZodArray<
32
+ z.ZodObject<
33
+ {
34
+ id: z.ZodString;
35
+ kind: z.ZodEnum<{
36
+ route: "route";
37
+ policy: "policy";
38
+ }>;
39
+ key: z.ZodString;
40
+ target: z.ZodString;
41
+ runtime: z.ZodString;
42
+ instructions: z.ZodString;
43
+ },
44
+ z.core.$strip
45
+ >
46
+ >;
47
+ assessments: z.ZodArray<
48
+ z.ZodObject<
49
+ {
50
+ revision: z.ZodString;
51
+ classification: z.ZodEnum<{
52
+ additions: "additions";
53
+ manual: "manual";
54
+ "documentation-only": "documentation-only";
55
+ }>;
56
+ instructions: z.ZodString;
57
+ },
58
+ z.core.$strip
59
+ >
60
+ >;
61
+ },
62
+ z.core.$strip
63
+ >;
64
+ export type Catalog = z.infer<typeof catalogSchema>;
65
+ export declare const catalog: {
66
+ formatVersion: 1;
67
+ target: string;
68
+ aliases: Record<string, string>;
69
+ snapshots: {
70
+ revision: string;
71
+ sourceCommit: string;
72
+ files: Record<string, string>;
73
+ }[];
74
+ steps: {
75
+ id: string;
76
+ kind: "route" | "policy";
77
+ key: string;
78
+ target: string;
79
+ runtime: string;
80
+ instructions: string;
81
+ }[];
82
+ assessments: {
83
+ revision: string;
84
+ classification: "additions" | "manual" | "documentation-only";
85
+ instructions: string;
86
+ }[];
87
+ };
88
+ export declare const provenanceSchema: z.ZodObject<
89
+ {
90
+ formatVersion: z.ZodLiteral<1>;
91
+ template: z.ZodLiteral<"ai-gateway">;
92
+ origin: z.ZodNullable<
93
+ z.ZodObject<
94
+ {
95
+ revision: z.ZodString;
96
+ release: z.ZodString;
97
+ },
98
+ z.core.$strip
99
+ >
100
+ >;
101
+ appliedSteps: z.ZodArray<z.ZodString>;
102
+ },
103
+ z.core.$strict
104
+ >;
105
+ export declare const AI_OAS = "config/ai.oas.json";
106
+ export declare const POLICIES = "config/policies.json";
107
+ export declare const PROVENANCE = ".zuplo-template.json";
108
+ export type Files = Record<string, string>;
109
+ export interface Addition {
110
+ step: z.infer<typeof stepSchema>;
111
+ file: string;
112
+ key: string;
113
+ value: unknown;
114
+ }
115
+ export interface UpgradePlan {
116
+ target: string;
117
+ release: string;
118
+ blockers: string[];
119
+ notes: string[];
120
+ additions: Addition[];
121
+ before: Files;
122
+ after: Files;
123
+ }
124
+ export declare function readJson(text: string, file: string): unknown;
125
+ export declare function contentHash(text: string): string;
126
+ export declare function planUpgrade(
127
+ files: Files,
128
+ release: string,
129
+ data?: Catalog
130
+ ): UpgradePlan;
131
+ export {};
132
+ //# sourceMappingURL=planner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner.d.ts","sourceRoot":"","sources":["../../../src/source/ai-gateway/planner.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAyBxB,QAAA,MAAM,UAAU;;;;;;;;;;iBAOd,CAAC;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmBxB,CAAC;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AACpD,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;CAAsC,CAAC;AAC3D,eAAO,MAAM,gBAAgB;;;;;;;;kBAOlB,CAAC;AACZ,eAAO,MAAM,MAAM,uBAAuB,CAAC;AAC3C,eAAO,MAAM,QAAQ,yBAAyB,CAAC;AAC/C,eAAO,MAAM,UAAU,yBAAyB,CAAC;AAUjD,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAC3C,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;CAChB;AACD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,MAAM,EAAE,KAAK,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;CACd;AAGD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAqC5D;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAuBD,wBAAgB,WAAW,CACzB,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,OAAiB,GACtB,WAAW,CAqWb"}