@ggui-ai/protocol 0.2.0-alpha.3 → 0.3.0-rc.0

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 (199) hide show
  1. package/README.md +16 -16
  2. package/dist/envelope-adapters.d.ts +6 -5
  3. package/dist/envelope-adapters.d.ts.map +1 -1
  4. package/dist/envelope-adapters.js +3 -3
  5. package/dist/envelopes/builders.d.ts +6 -32
  6. package/dist/envelopes/builders.d.ts.map +1 -1
  7. package/dist/envelopes/builders.js +3 -25
  8. package/dist/errors/version-mismatch.d.ts +1 -1
  9. package/dist/errors/version-mismatch.js +1 -1
  10. package/dist/gadgets/resolve-app-gadgets.d.ts +10 -0
  11. package/dist/gadgets/resolve-app-gadgets.d.ts.map +1 -0
  12. package/dist/gadgets/resolve-app-gadgets.js +19 -0
  13. package/dist/gadgets/resolve-contract-gadgets.d.ts +6 -6
  14. package/dist/gadgets/resolve-contract-gadgets.js +5 -5
  15. package/dist/gadgets/stdlib-gadgets.d.ts +1 -1
  16. package/dist/gadgets/stdlib-gadgets.d.ts.map +1 -1
  17. package/dist/gadgets/stdlib-gadgets.js +43 -22
  18. package/dist/iframe-bridge.d.ts +4 -43
  19. package/dist/iframe-bridge.d.ts.map +1 -1
  20. package/dist/iframe-bridge.js +4 -141
  21. package/dist/index.d.ts +60 -62
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +66 -61
  24. package/dist/integrations/mcp-apps.d.ts +83 -38
  25. package/dist/integrations/mcp-apps.d.ts.map +1 -1
  26. package/dist/integrations/mcp-apps.js +98 -52
  27. package/dist/recommended-prompts.d.ts +1 -1
  28. package/dist/recommended-prompts.js +1 -1
  29. package/dist/registry/blueprint-key.d.ts +3 -0
  30. package/dist/registry/blueprint-key.d.ts.map +1 -1
  31. package/dist/registry/blueprint-key.js +9 -0
  32. package/dist/registry/blueprint-stamp.d.ts +12 -0
  33. package/dist/registry/blueprint-stamp.d.ts.map +1 -0
  34. package/dist/registry/blueprint-stamp.js +12 -0
  35. package/dist/registry/canonicalize-contract.d.ts +31 -2
  36. package/dist/registry/canonicalize-contract.d.ts.map +1 -1
  37. package/dist/registry/canonicalize-contract.js +125 -13
  38. package/dist/registry/portable-blueprint.d.ts +64 -0
  39. package/dist/registry/portable-blueprint.d.ts.map +1 -0
  40. package/dist/registry/portable-blueprint.js +103 -0
  41. package/dist/registry/summarize-contract.d.ts +7 -2
  42. package/dist/registry/summarize-contract.d.ts.map +1 -1
  43. package/dist/registry/summarize-contract.js +12 -3
  44. package/dist/registry/variant-key.d.ts +17 -0
  45. package/dist/registry/variant-key.d.ts.map +1 -0
  46. package/dist/registry/variant-key.js +22 -0
  47. package/dist/schema-learning/derive-contract.d.ts +2 -2
  48. package/dist/schema-learning/derive-contract.js +2 -2
  49. package/dist/schema-learning/merge.d.ts.map +1 -1
  50. package/dist/schema-learning/merge.js +3 -2
  51. package/dist/schemas/app-theme.d.ts +38 -0
  52. package/dist/schemas/app-theme.d.ts.map +1 -0
  53. package/dist/schemas/app-theme.js +43 -0
  54. package/dist/schemas/blueprint.d.ts +30 -11
  55. package/dist/schemas/blueprint.d.ts.map +1 -1
  56. package/dist/schemas/blueprint.js +62 -26
  57. package/dist/schemas/data-contract.d.ts +28 -30
  58. package/dist/schemas/data-contract.d.ts.map +1 -1
  59. package/dist/schemas/data-contract.js +26 -26
  60. package/dist/schemas/handshake-suggestion.d.ts +2 -4
  61. package/dist/schemas/handshake-suggestion.d.ts.map +1 -1
  62. package/dist/schemas/handshake-suggestion.js +5 -14
  63. package/dist/schemas/mcp.d.ts +240 -58
  64. package/dist/schemas/mcp.d.ts.map +1 -1
  65. package/dist/schemas/mcp.js +285 -93
  66. package/dist/schemas/ops-blueprint.d.ts +12 -12
  67. package/dist/schemas/ops-blueprint.d.ts.map +1 -1
  68. package/dist/schemas/ops-blueprint.js +14 -24
  69. package/dist/screen-blueprints/define.d.ts +2 -2
  70. package/dist/screen-blueprints/match.d.ts +12 -7
  71. package/dist/screen-blueprints/match.d.ts.map +1 -1
  72. package/dist/screen-blueprints/match.js +7 -5
  73. package/dist/screen-blueprints/types.d.ts +14 -18
  74. package/dist/screen-blueprints/types.d.ts.map +1 -1
  75. package/dist/transport/websocket.d.ts +5 -26
  76. package/dist/transport/websocket.d.ts.map +1 -1
  77. package/dist/types/app-config.d.ts +0 -1
  78. package/dist/types/app-config.d.ts.map +1 -1
  79. package/dist/types/auth.d.ts +1 -46
  80. package/dist/types/auth.d.ts.map +1 -1
  81. package/dist/types/blueprint-source.d.ts +123 -0
  82. package/dist/types/blueprint-source.d.ts.map +1 -0
  83. package/dist/types/blueprint-source.js +126 -0
  84. package/dist/types/blueprint.d.ts +25 -18
  85. package/dist/types/blueprint.d.ts.map +1 -1
  86. package/dist/types/contract-inference.d.ts +2 -43
  87. package/dist/types/contract-inference.d.ts.map +1 -1
  88. package/dist/types/data-contract.d.ts +59 -344
  89. package/dist/types/data-contract.d.ts.map +1 -1
  90. package/dist/types/data-contract.js +5 -12
  91. package/dist/types/events.d.ts +31 -69
  92. package/dist/types/events.d.ts.map +1 -1
  93. package/dist/types/{render-event.d.ts → ggui-session-event.d.ts} +15 -15
  94. package/dist/types/ggui-session-event.d.ts.map +1 -0
  95. package/dist/types/{render-event.js → ggui-session-event.js} +5 -5
  96. package/dist/types/handshake-suggestion.d.ts +60 -40
  97. package/dist/types/handshake-suggestion.d.ts.map +1 -1
  98. package/dist/types/host-context.d.ts +8 -8
  99. package/dist/types/host-context.d.ts.map +1 -1
  100. package/dist/types/host-context.js +5 -5
  101. package/dist/types/invoke.d.ts +1 -13
  102. package/dist/types/invoke.d.ts.map +1 -1
  103. package/dist/types/{canvas-lifecycle.d.ts → lifecycle.d.ts} +35 -37
  104. package/dist/types/lifecycle.d.ts.map +1 -0
  105. package/dist/types/{canvas-lifecycle.js → lifecycle.js} +12 -14
  106. package/dist/types/live-channel.d.ts +48 -104
  107. package/dist/types/live-channel.d.ts.map +1 -1
  108. package/dist/types/llm.d.ts +13 -24
  109. package/dist/types/llm.d.ts.map +1 -1
  110. package/dist/types/llm.js +23 -53
  111. package/dist/types/mcp.d.ts +55 -176
  112. package/dist/types/mcp.d.ts.map +1 -1
  113. package/dist/types/mcp.js +2 -2
  114. package/dist/types/oauth-user-id.d.ts +12 -0
  115. package/dist/types/oauth-user-id.d.ts.map +1 -0
  116. package/dist/types/oauth-user-id.js +10 -0
  117. package/dist/types/portable-blueprint.d.ts +53 -0
  118. package/dist/types/portable-blueprint.d.ts.map +1 -0
  119. package/dist/types/portable-blueprint.js +8 -0
  120. package/dist/types/{session.d.ts → render.d.ts} +51 -53
  121. package/dist/types/render.d.ts.map +1 -0
  122. package/dist/types/thread.d.ts.map +1 -1
  123. package/dist/types/thread.js +3 -3
  124. package/dist/types/ui-generator.d.ts +5 -46
  125. package/dist/types/ui-generator.d.ts.map +1 -1
  126. package/dist/types/ui-generator.js +1 -53
  127. package/dist/validation/ajv-runtime.d.ts +3 -3
  128. package/dist/validation/ajv-runtime.d.ts.map +1 -1
  129. package/dist/validation/ajv-runtime.js +6 -5
  130. package/dist/validation/contract-validator.d.ts +23 -22
  131. package/dist/validation/contract-validator.d.ts.map +1 -1
  132. package/dist/validation/contract-validator.js +28 -26
  133. package/dist/validation/cross-references.d.ts +3 -3
  134. package/dist/validation/cross-references.js +3 -3
  135. package/dist/validation/hygiene-rules.d.ts +13 -10
  136. package/dist/validation/hygiene-rules.d.ts.map +1 -1
  137. package/dist/validation/hygiene-rules.js +20 -14
  138. package/dist/validation/is-record.d.ts +17 -0
  139. package/dist/validation/is-record.d.ts.map +1 -0
  140. package/dist/validation/is-record.js +18 -0
  141. package/dist/validation/lint-contract.d.ts +9 -8
  142. package/dist/validation/lint-contract.d.ts.map +1 -1
  143. package/dist/validation/lint-contract.js +89 -26
  144. package/dist/validation/name-invariants.d.ts +4 -4
  145. package/dist/validation/name-invariants.js +4 -4
  146. package/dist/validation/reserved-channels.d.ts +43 -46
  147. package/dist/validation/reserved-channels.d.ts.map +1 -1
  148. package/dist/validation/reserved-channels.js +14 -177
  149. package/dist/validation/resolve-stream-channel.d.ts +3 -9
  150. package/dist/validation/resolve-stream-channel.d.ts.map +1 -1
  151. package/dist/validation/resolve-stream-channel.js +3 -4
  152. package/dist/validation/sanitize-error.d.ts +10 -9
  153. package/dist/validation/sanitize-error.d.ts.map +1 -1
  154. package/dist/validation/sanitize-error.js +19 -18
  155. package/dist/validation/schema-compat-invariants.d.ts +1 -1
  156. package/dist/validation/schema-compat-invariants.js +3 -3
  157. package/dist/validation/schema-meta-validation.d.ts +21 -8
  158. package/dist/validation/schema-meta-validation.d.ts.map +1 -1
  159. package/dist/validation/schema-meta-validation.js +28 -14
  160. package/dist/validation/schema-subset.d.ts +9 -8
  161. package/dist/validation/schema-subset.d.ts.map +1 -1
  162. package/dist/validation/ui-security.d.ts +0 -17
  163. package/dist/validation/ui-security.d.ts.map +1 -1
  164. package/dist/validation/ui-security.js +17 -22
  165. package/dist/validation/zod-to-json-schema.d.ts +1 -1
  166. package/dist/validation/zod-to-json-schema.d.ts.map +1 -1
  167. package/dist/validation/zod-to-json-schema.js +4 -3
  168. package/dist/version.d.ts +783 -9
  169. package/dist/version.d.ts.map +1 -1
  170. package/dist/version.js +782 -8
  171. package/package.json +2 -2
  172. package/dist/bridge/invoke-agent.d.ts +0 -65
  173. package/dist/bridge/invoke-agent.d.ts.map +0 -1
  174. package/dist/bridge/invoke-agent.js +0 -113
  175. package/dist/stream/stream-parser.d.ts +0 -62
  176. package/dist/stream/stream-parser.d.ts.map +0 -1
  177. package/dist/stream/stream-parser.js +0 -199
  178. package/dist/types/canvas-lifecycle.d.ts.map +0 -1
  179. package/dist/types/credential.d.ts +0 -41
  180. package/dist/types/credential.d.ts.map +0 -1
  181. package/dist/types/credential.js +0 -32
  182. package/dist/types/data-bindings.d.ts +0 -322
  183. package/dist/types/data-bindings.d.ts.map +0 -1
  184. package/dist/types/data-bindings.js +0 -29
  185. package/dist/types/feedback.d.ts +0 -22
  186. package/dist/types/feedback.d.ts.map +0 -1
  187. package/dist/types/feedback.js +0 -7
  188. package/dist/types/mcp-proxy.d.ts +0 -67
  189. package/dist/types/mcp-proxy.d.ts.map +0 -1
  190. package/dist/types/mcp-proxy.js +0 -46
  191. package/dist/types/openrouter-models.d.ts +0 -23
  192. package/dist/types/openrouter-models.d.ts.map +0 -1
  193. package/dist/types/openrouter-models.js +0 -4843
  194. package/dist/types/region.d.ts +0 -26
  195. package/dist/types/region.d.ts.map +0 -1
  196. package/dist/types/region.js +0 -36
  197. package/dist/types/render-event.d.ts.map +0 -1
  198. package/dist/types/session.d.ts.map +0 -1
  199. /package/dist/types/{session.js → render.js} +0 -0
@@ -0,0 +1,64 @@
1
+ import type { PortableBlueprint } from '../types/portable-blueprint.js';
2
+ import { PORTABLE_BLUEPRINT_SCHEMA_VERSION } from '../types/portable-blueprint.js';
3
+ import type { DataContract } from '../types/data-contract.js';
4
+ import type { BlueprintVariance } from '../types/blueprint.js';
5
+ import type { BlueprintSource } from '../types/blueprint-source.js';
6
+ import type { ToolCatalogShape } from './blueprint-stamp.js';
7
+ export type { PortableBlueprint };
8
+ export { PORTABLE_BLUEPRINT_SCHEMA_VERSION };
9
+ /** The fields needed to mint a {@link PortableBlueprint} (keys are derived). */
10
+ export interface PortableBlueprintSource {
11
+ readonly contract: DataContract;
12
+ readonly componentCode: string;
13
+ readonly variance: BlueprintVariance;
14
+ /** Provenance of `componentCode` — travels with the artifact. */
15
+ readonly source: BlueprintSource;
16
+ }
17
+ /**
18
+ * Rejection message for schemaVersion-1 artifacts. v1 records predate
19
+ * required provenance, and a blueprint pool is a cache — re-exporting
20
+ * regenerates the records with full provenance, so there is no
21
+ * migration shim.
22
+ */
23
+ export declare const PORTABLE_BLUEPRINT_V1_REJECTION = "re-export the pool: PortableBlueprint schemaVersion 2 requires complete provenance";
24
+ /**
25
+ * Result of {@link fromPortableBlueprint} — the validating narrower at
26
+ * the artifact trust boundary (JSON bytes → typed record).
27
+ *
28
+ * Rejection policy at the call sites: pool loaders SKIP a rejected
29
+ * record with a log line (a rejected seed entry is just a cold-gen);
30
+ * explicit single-artifact import paths hard-error with `reason`.
31
+ * Coercing a rejected record into the typed shape is banned.
32
+ */
33
+ export type PortableBlueprintImportResult = {
34
+ readonly ok: true;
35
+ /** Canonical rebuild of the validated record (stray keys dropped). */
36
+ readonly record: PortableBlueprint;
37
+ /** True if the shipped contractHash/variantKey differed from the recompute. */
38
+ readonly keyMismatch: boolean;
39
+ } | {
40
+ readonly ok: false;
41
+ readonly reason: string;
42
+ };
43
+ /** Options for {@link toPortableBlueprint}. */
44
+ export interface ToPortableBlueprintOpts {
45
+ /**
46
+ * Tool-identity catalog used to canonicalize the contract at export
47
+ * time. When provided, its hash is stamped as
48
+ * `toolIdentityCatalogHash` so importers can detect catalog drift
49
+ * (same intent → different key). When omitted — the offline-export
50
+ * case, where no runtime catalog exists — the stamp is left absent
51
+ * and importers fall back to recomputing keys against their own
52
+ * catalog.
53
+ */
54
+ readonly catalog?: ToolCatalogShape;
55
+ }
56
+ export declare function toPortableBlueprint(src: PortableBlueprintSource, opts?: ToPortableBlueprintOpts): PortableBlueprint;
57
+ /**
58
+ * Validate one artifact record (parsed JSON, untrusted) into a typed
59
+ * {@link PortableBlueprint}. Shipped keys are advisory — they are
60
+ * recomputed here and a divergence is surfaced as `keyMismatch`, never
61
+ * silently trusted.
62
+ */
63
+ export declare function fromPortableBlueprint(record: unknown): PortableBlueprintImportResult;
64
+ //# sourceMappingURL=portable-blueprint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portable-blueprint.d.ts","sourceRoot":"","sources":["../../src/registry/portable-blueprint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,iCAAiC,EAAE,MAAM,gCAAgC,CAAC;AACnF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAMpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAI7D,YAAY,EAAE,iBAAiB,EAAE,CAAC;AAClC,OAAO,EAAE,iCAAiC,EAAE,CAAC;AAE7C,gFAAgF;AAChF,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,iEAAiE;IACjE,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;CAClC;AAED;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,uFAC0C,CAAC;AAEvF;;;;;;;;GAQG;AACH,MAAM,MAAM,6BAA6B,GACrC;IACE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,sEAAsE;IACtE,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,+EAA+E;IAC/E,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC/B,GACD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD,+CAA+C;AAC/C,MAAM,WAAW,uBAAuB;IACtC;;;;;;;;OAQG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAED,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,uBAAuB,EAC5B,IAAI,CAAC,EAAE,uBAAuB,GAC7B,iBAAiB,CAcnB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,6BAA6B,CAmFpF"}
@@ -0,0 +1,103 @@
1
+ import { PORTABLE_BLUEPRINT_SCHEMA_VERSION } from '../types/portable-blueprint.js';
2
+ import { parseBlueprintSource } from '../types/blueprint-source.js';
3
+ import { dataContractSchema } from '../schemas/data-contract.js';
4
+ import { blueprintVarianceSchema } from '../schemas/blueprint.js';
5
+ import { blueprintKey, variantKey } from './blueprint-key.js';
6
+ import { PROTOCOL_VERSION } from '../version.js';
7
+ import { computeToolCatalogHash } from './blueprint-stamp.js';
8
+ import { isRecord } from '../validation/is-record.js';
9
+ export { PORTABLE_BLUEPRINT_SCHEMA_VERSION };
10
+ /**
11
+ * Rejection message for schemaVersion-1 artifacts. v1 records predate
12
+ * required provenance, and a blueprint pool is a cache — re-exporting
13
+ * regenerates the records with full provenance, so there is no
14
+ * migration shim.
15
+ */
16
+ export const PORTABLE_BLUEPRINT_V1_REJECTION = 're-export the pool: PortableBlueprint schemaVersion 2 requires complete provenance';
17
+ export function toPortableBlueprint(src, opts) {
18
+ return {
19
+ schemaVersion: PORTABLE_BLUEPRINT_SCHEMA_VERSION,
20
+ contract: src.contract,
21
+ componentCode: src.componentCode,
22
+ variance: src.variance,
23
+ contractHash: blueprintKey(src.contract),
24
+ variantKey: variantKey(src.variance),
25
+ source: src.source,
26
+ generatorProtocolVersion: PROTOCOL_VERSION,
27
+ ...(opts?.catalog !== undefined
28
+ ? { toolIdentityCatalogHash: computeToolCatalogHash(opts.catalog) }
29
+ : {}),
30
+ };
31
+ }
32
+ /**
33
+ * Validate one artifact record (parsed JSON, untrusted) into a typed
34
+ * {@link PortableBlueprint}. Shipped keys are advisory — they are
35
+ * recomputed here and a divergence is surfaced as `keyMismatch`, never
36
+ * silently trusted.
37
+ */
38
+ export function fromPortableBlueprint(record) {
39
+ if (!isRecord(record)) {
40
+ return { ok: false, reason: 'record is not an object' };
41
+ }
42
+ const r = record;
43
+ if (r['schemaVersion'] !== PORTABLE_BLUEPRINT_SCHEMA_VERSION) {
44
+ if (r['schemaVersion'] === 1) {
45
+ return { ok: false, reason: PORTABLE_BLUEPRINT_V1_REJECTION };
46
+ }
47
+ return {
48
+ ok: false,
49
+ reason: `unsupported PortableBlueprint schemaVersion ${JSON.stringify(r['schemaVersion'])} (expected ${PORTABLE_BLUEPRINT_SCHEMA_VERSION})`,
50
+ };
51
+ }
52
+ const source = parseBlueprintSource(r['source']);
53
+ if (source === null) {
54
+ return {
55
+ ok: false,
56
+ reason: 'missing or malformed `source` provenance (expected a BlueprintSource union value)',
57
+ };
58
+ }
59
+ const generatorProtocolVersion = r['generatorProtocolVersion'];
60
+ if (typeof generatorProtocolVersion !== 'string' ||
61
+ generatorProtocolVersion.length === 0) {
62
+ return { ok: false, reason: 'missing or empty `generatorProtocolVersion`' };
63
+ }
64
+ const componentCode = r['componentCode'];
65
+ if (typeof componentCode !== 'string' || componentCode.length === 0) {
66
+ return { ok: false, reason: 'missing or empty `componentCode`' };
67
+ }
68
+ const shippedContractHash = r['contractHash'];
69
+ const shippedVariantKey = r['variantKey'];
70
+ if (typeof shippedContractHash !== 'string' || typeof shippedVariantKey !== 'string') {
71
+ return { ok: false, reason: 'missing `contractHash` / `variantKey`' };
72
+ }
73
+ const toolIdentityCatalogHash = r['toolIdentityCatalogHash'];
74
+ if (toolIdentityCatalogHash !== undefined &&
75
+ typeof toolIdentityCatalogHash !== 'string') {
76
+ return { ok: false, reason: 'malformed `toolIdentityCatalogHash` (expected string)' };
77
+ }
78
+ const contract = dataContractSchema.safeParse(r['contract']);
79
+ if (!contract.success) {
80
+ return { ok: false, reason: `malformed \`contract\`: ${contract.error.message}` };
81
+ }
82
+ const variance = blueprintVarianceSchema.safeParse(r['variance']);
83
+ if (!variance.success) {
84
+ return { ok: false, reason: `malformed \`variance\`: ${variance.error.message}` };
85
+ }
86
+ const keyMismatch = blueprintKey(contract.data) !== shippedContractHash ||
87
+ variantKey(variance.data) !== shippedVariantKey;
88
+ return {
89
+ ok: true,
90
+ record: {
91
+ schemaVersion: PORTABLE_BLUEPRINT_SCHEMA_VERSION,
92
+ contract: contract.data,
93
+ componentCode,
94
+ variance: variance.data,
95
+ contractHash: shippedContractHash,
96
+ variantKey: shippedVariantKey,
97
+ source,
98
+ generatorProtocolVersion,
99
+ ...(toolIdentityCatalogHash !== undefined ? { toolIdentityCatalogHash } : {}),
100
+ },
101
+ keyMismatch,
102
+ };
103
+ }
@@ -21,7 +21,7 @@
21
21
  *
22
22
  * slots=<name:type,...>;
23
23
  * actions=<name(payloadFields)?,...>; streams=<name,...>;
24
- * props=<name:type,...>
24
+ * props=<name:type[!],...>
25
25
  *
26
26
  * Format details:
27
27
  * - slots: `name:type` (e.g. `count:number,draft:string`). Bare
@@ -36,7 +36,12 @@
36
36
  * in the summary lets the judge see this distinction.
37
37
  * - streams: bare `name` (channel schemas vary a lot and are usually
38
38
  * emitted by the agent later; including them adds noise).
39
- * - props: `name:type` (initial render shape).
39
+ * - props: `name:type` (initial render shape). A trailing `!` marks a
40
+ * required prop (e.g. `name:type!` = required; `name:type` =
41
+ * optional). Bare `name!` when a required prop's schema has no
42
+ * `type` field. Only props the component MUST accept are marked;
43
+ * surfacing required-vs-optional lets the rerank judge tell a
44
+ * mandatory prop apart from an optional one instead of guessing.
40
45
  *
41
46
  * Empty slots/actions/streams/props collapse to `∅`.
42
47
  */
@@ -1 +1 @@
1
- {"version":3,"file":"summarize-contract.d.ts","sourceRoot":"","sources":["../../src/registry/summarize-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D,iEAAiE;AACjE,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,YAAY,GAAG,SAAS,GACjC,MAAM,CA6CR"}
1
+ {"version":3,"file":"summarize-contract.d.ts","sourceRoot":"","sources":["../../src/registry/summarize-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAG9D,iEAAiE;AACjE,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,YAAY,GAAG,SAAS,GACjC,MAAM,CAqDR"}
@@ -1,3 +1,4 @@
1
+ import { isRecord } from '../validation/is-record.js';
1
2
  /** Stable summary of `contract` for embedding + rerank input. */
2
3
  export function summarizeContract(contract) {
3
4
  if (!contract)
@@ -27,8 +28,16 @@ export function summarizeContract(contract) {
27
28
  ? Object.entries(contract.propsSpec.properties)
28
29
  .sort(([a], [b]) => a.localeCompare(b))
29
30
  .map(([name, entry]) => {
31
+ // `entry` is a `PropEntry` (PropsSpec.properties is
32
+ // `Record<string, PropEntry>`), so `schema` and `required`
33
+ // read directly — no cast.
30
34
  const t = readType(entry.schema);
31
- return t ? `${name}:${t}` : name;
35
+ const base = t ? `${name}:${t}` : name;
36
+ // A trailing `!` marks a mandatory prop so the rerank judge
37
+ // (and the agent) can tell required from optional. Only the
38
+ // literal `true` earns the marker; `undefined`/`false` = not
39
+ // required.
40
+ return entry.required === true ? `${base}!` : base;
32
41
  })
33
42
  .join(',')
34
43
  : '';
@@ -50,10 +59,10 @@ function readType(schema) {
50
59
  * or `null` when the action takes no payload. Empty `properties` →
51
60
  * null (payload-less). */
52
61
  function readPayloadFields(schema) {
53
- if (typeof schema !== 'object' || schema === null)
62
+ if (!isRecord(schema))
54
63
  return null;
55
64
  const props = schema.properties;
56
- if (typeof props !== 'object' || props === null || Array.isArray(props)) {
65
+ if (!isRecord(props)) {
57
66
  return null;
58
67
  }
59
68
  const keys = Object.keys(props);
@@ -0,0 +1,17 @@
1
+ import type { BlueprintVariance } from '../types/blueprint.js';
2
+ /**
3
+ * Identity hash of the design-time variance block — the variant axis of
4
+ * the reuse key. `(contractKey, variantKey)` identifies one reusable
5
+ * component; runtime props are never an input. Spec §8.
6
+ *
7
+ * 16-char sha256 prefix of {@link canonicalizeVariance}'s output, which
8
+ * is self-normalizing (D9): `undefined`, `{}`, `{persona:''}`, and any
9
+ * all-empty variance hash to one stable "default variant" sentinel, so
10
+ * the accept path (verbatim `blueprintMeta.variance`) and the override
11
+ * path never false-miss on equivalent variance.
12
+ *
13
+ * Server-only — depends on `node:crypto`. Exposed at the
14
+ * `@ggui-ai/protocol/blueprint-key` subpath (see `blueprint-key.ts`).
15
+ */
16
+ export declare function variantKey(variance: BlueprintVariance | undefined): string;
17
+ //# sourceMappingURL=variant-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"variant-key.d.ts","sourceRoot":"","sources":["../../src/registry/variant-key.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG/D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,iBAAiB,GAAG,SAAS,GAAG,MAAM,CAK1E"}
@@ -0,0 +1,22 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { canonicalizeVariance } from './canonicalize-contract.js';
3
+ /**
4
+ * Identity hash of the design-time variance block — the variant axis of
5
+ * the reuse key. `(contractKey, variantKey)` identifies one reusable
6
+ * component; runtime props are never an input. Spec §8.
7
+ *
8
+ * 16-char sha256 prefix of {@link canonicalizeVariance}'s output, which
9
+ * is self-normalizing (D9): `undefined`, `{}`, `{persona:''}`, and any
10
+ * all-empty variance hash to one stable "default variant" sentinel, so
11
+ * the accept path (verbatim `blueprintMeta.variance`) and the override
12
+ * path never false-miss on equivalent variance.
13
+ *
14
+ * Server-only — depends on `node:crypto`. Exposed at the
15
+ * `@ggui-ai/protocol/blueprint-key` subpath (see `blueprint-key.ts`).
16
+ */
17
+ export function variantKey(variance) {
18
+ return createHash('sha256')
19
+ .update(canonicalizeVariance(variance))
20
+ .digest('hex')
21
+ .slice(0, 16);
22
+ }
@@ -43,8 +43,8 @@ export interface DeriveContractInput {
43
43
  * - `intent` — "<serverName> — <humanized tool verb>" unless overridden.
44
44
  * - `props` — each top-level property of dataTool.outputSchema becomes a PropEntry.
45
45
  * If outputSchema is not an object schema, a single `data` prop wraps the whole thing.
46
- * - `actions` — one ActionEntry per actionTool, with `tool` wired to the MCP tool name
47
- * and `schema` set to the tool's inputSchema (if present).
46
+ * - `actions` — one ActionEntry per actionTool, with `nextStep` set to the MCP tool
47
+ * name (advisory hint) and `schema` set to the tool's inputSchema (if present).
48
48
  *
49
49
  * Pure — deterministic given identical input.
50
50
  */
@@ -5,8 +5,8 @@
5
5
  * - `intent` — "<serverName> — <humanized tool verb>" unless overridden.
6
6
  * - `props` — each top-level property of dataTool.outputSchema becomes a PropEntry.
7
7
  * If outputSchema is not an object schema, a single `data` prop wraps the whole thing.
8
- * - `actions` — one ActionEntry per actionTool, with `tool` wired to the MCP tool name
9
- * and `schema` set to the tool's inputSchema (if present).
8
+ * - `actions` — one ActionEntry per actionTool, with `nextStep` set to the MCP tool
9
+ * name (advisory hint) and `schema` set to the tool's inputSchema (if present).
10
10
  *
11
11
  * Pure — deterministic given identical input.
12
12
  */
@@ -1 +1 @@
1
- {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/schema-learning/merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAc,UAAU,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAEnF,oDAAoD;AACpD,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,UAAU,CA4BxD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,EAAE,MAAM,EAAE,SAAS,GAAG,UAAU,CAIlG;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,UAAU,CA0BxE"}
1
+ {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/schema-learning/merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAc,UAAU,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAGnF,oDAAoD;AACpD,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,UAAU,CA4BxD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,EAAE,MAAM,EAAE,SAAS,GAAG,UAAU,CAIlG;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,GAAG,UAAU,CA0BxE"}
@@ -1,3 +1,4 @@
1
+ import { isRecord } from "../validation/is-record.js";
1
2
  /** Infer a JSON Schema from a single JSON value. */
2
3
  export function inferSchema(value) {
3
4
  if (value === null)
@@ -136,10 +137,10 @@ function dedupeAnyOf(list) {
136
137
  }
137
138
  /** Deterministic stable key — recursive, sorts object keys at every depth. */
138
139
  function canonicalKey(v) {
139
- if (v === null || typeof v !== "object")
140
- return JSON.stringify(v);
141
140
  if (Array.isArray(v))
142
141
  return "[" + v.map(canonicalKey).join(",") + "]";
142
+ if (!isRecord(v))
143
+ return JSON.stringify(v);
143
144
  const obj = v;
144
145
  const keys = Object.keys(obj).sort();
145
146
  return "{" + keys.map((k) => JSON.stringify(k) + ":" + canonicalKey(obj[k])).join(",") + "}";
@@ -0,0 +1,38 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Platform CSS-variable namespace — only `--ggui-*` custom properties.
4
+ *
5
+ * The charset allows mixed-case ASCII because the canonical theme parser
6
+ * (`@ggui-ai/design`) emits camelCase token segments verbatim into the
7
+ * variable name (e.g. `--ggui-color-onSurface`, `--ggui-zIndex-modal`,
8
+ * `--ggui-font-lineHeight-tight`) — and the design system both EMITS and
9
+ * CONSUMES those exact keys (`var(--ggui-color-onSurface)`). Case has no
10
+ * bearing on injection safety; the `--ggui-` prefix is the namespace guard
11
+ * and value-level breakout characters are forbidden by {@link CSS_VALUE_SAFE_RE}.
12
+ */
13
+ export declare const GGUI_CSS_VAR_KEY_RE: RegExp;
14
+ /**
15
+ * A single safe CSS value. The map is serialized into a `:root { --k: v; }`
16
+ * declaration block inside the rendered iframe, so a value MUST NOT be able to
17
+ * terminate the declaration or open a new rule/comment. Forbid the breakout
18
+ * characters `; { } < > @` and the comment opener `/*`. Everything else
19
+ * (colors, lengths, `calc(...)`, `var(...)`, font-family lists) is allowed.
20
+ *
21
+ * PARTIAL gate — this regex alone is NOT a complete validator. Bare `/` and
22
+ * `*` are intentionally allowed (legal in `16px/1.5`, `calc(2 * 4px)`); only
23
+ * the `/*` comment-opener SEQUENCE is forbidden, and that check lives in
24
+ * {@link appThemeSchema}'s `.refine`, not here. Callers MUST validate values
25
+ * through `appThemeSchema` (the complete validator) — never against this
26
+ * bare regex on its own.
27
+ */
28
+ export declare const CSS_VALUE_SAFE_RE: RegExp;
29
+ export declare const appThemeSchema: z.ZodObject<{
30
+ mode: z.ZodEnum<{
31
+ light: "light";
32
+ dark: "dark";
33
+ }>;
34
+ cssVariables: z.ZodRecord<z.ZodString, z.ZodString>;
35
+ name: z.ZodOptional<z.ZodString>;
36
+ }, z.core.$strict>;
37
+ export type AppTheme = z.infer<typeof appThemeSchema>;
38
+ //# sourceMappingURL=app-theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-theme.d.ts","sourceRoot":"","sources":["../../src/schemas/app-theme.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,QAA2B,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,QAAiB,CAAC;AAShD,eAAO,MAAM,cAAc;;;;;;;kBAQhB,CAAC;AAEZ,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Platform CSS-variable namespace — only `--ggui-*` custom properties.
4
+ *
5
+ * The charset allows mixed-case ASCII because the canonical theme parser
6
+ * (`@ggui-ai/design`) emits camelCase token segments verbatim into the
7
+ * variable name (e.g. `--ggui-color-onSurface`, `--ggui-zIndex-modal`,
8
+ * `--ggui-font-lineHeight-tight`) — and the design system both EMITS and
9
+ * CONSUMES those exact keys (`var(--ggui-color-onSurface)`). Case has no
10
+ * bearing on injection safety; the `--ggui-` prefix is the namespace guard
11
+ * and value-level breakout characters are forbidden by {@link CSS_VALUE_SAFE_RE}.
12
+ */
13
+ export const GGUI_CSS_VAR_KEY_RE = /^--ggui-[a-zA-Z0-9-]+$/;
14
+ /**
15
+ * A single safe CSS value. The map is serialized into a `:root { --k: v; }`
16
+ * declaration block inside the rendered iframe, so a value MUST NOT be able to
17
+ * terminate the declaration or open a new rule/comment. Forbid the breakout
18
+ * characters `; { } < > @` and the comment opener `/*`. Everything else
19
+ * (colors, lengths, `calc(...)`, `var(...)`, font-family lists) is allowed.
20
+ *
21
+ * PARTIAL gate — this regex alone is NOT a complete validator. Bare `/` and
22
+ * `*` are intentionally allowed (legal in `16px/1.5`, `calc(2 * 4px)`); only
23
+ * the `/*` comment-opener SEQUENCE is forbidden, and that check lives in
24
+ * {@link appThemeSchema}'s `.refine`, not here. Callers MUST validate values
25
+ * through `appThemeSchema` (the complete validator) — never against this
26
+ * bare regex on its own.
27
+ */
28
+ export const CSS_VALUE_SAFE_RE = /^[^;{}<>@]*$/;
29
+ const cssValue = z
30
+ .string()
31
+ .min(1)
32
+ .max(256)
33
+ .regex(CSS_VALUE_SAFE_RE, 'css value contains a disallowed character')
34
+ .refine((v) => !v.includes('/*'), 'css value may not contain a comment');
35
+ export const appThemeSchema = z
36
+ .object({
37
+ mode: z.enum(['light', 'dark']),
38
+ cssVariables: z
39
+ .record(z.string().regex(GGUI_CSS_VAR_KEY_RE, 'css var key must be --ggui-*'), cssValue)
40
+ .refine((m) => Object.keys(m).length <= 200, 'too many css variables (max 200)'),
41
+ name: z.string().min(1).max(64).optional(),
42
+ })
43
+ .strict();
@@ -5,8 +5,36 @@
5
5
  * here is `z.ZodType<Blueprint>` so any drift fails compile.
6
6
  */
7
7
  import { z } from 'zod';
8
- import type { AppBlueprintSearchConfig, Blueprint, BlueprintSearchWeights, BlueprintVariance } from '../types/blueprint';
9
- /** Zod mirror of {@link BlueprintVariance}. */
8
+ import type { AppBlueprintSearchConfig, Blueprint, BlueprintVariance } from '../types/blueprint';
9
+ import type { BlueprintSource, CuratedBlueprintSource, LlmBlueprintSource, UserBlueprintSource } from '../types/blueprint-source';
10
+ /**
11
+ * Zod mirror of {@link LlmBlueprintSource} — the engine-generated arm.
12
+ * Both provenance fields are REQUIRED: every generation mint site has
13
+ * them in scope, and an engine-generated artifact that cannot name its
14
+ * engine + model is not a real state.
15
+ */
16
+ export declare const llmBlueprintSourceSchema: z.ZodType<LlmBlueprintSource>;
17
+ /** Zod mirror of {@link UserBlueprintSource} — no engine claim exists. */
18
+ export declare const userBlueprintSourceSchema: z.ZodType<UserBlueprintSource>;
19
+ /** Zod mirror of {@link CuratedBlueprintSource}. */
20
+ export declare const curatedBlueprintSourceSchema: z.ZodType<CuratedBlueprintSource>;
21
+ /**
22
+ * Zod mirror of {@link BlueprintSource} — the single provenance
23
+ * vocabulary for blueprints. Mirrors `parseBlueprintSource`'s arms;
24
+ * `.strict()` members so stray keys surface at the wire layer rather
25
+ * than riding through.
26
+ */
27
+ export declare const blueprintSourceSchema: z.ZodType<BlueprintSource>;
28
+ /**
29
+ * Zod mirror of {@link BlueprintVariance}. The single shared variance
30
+ * schema: every seam that accepts a variance block (handshake draft,
31
+ * render override, operator blueprint tools) reuses this one
32
+ * rather than re-declaring the shape inline. `.strict()` so an unknown
33
+ * key surfaces as a typo at the wire layer rather than being silently
34
+ * dropped. The per-field `.describe()` strings ship as JSON-Schema
35
+ * metadata via `tools/list`, so they stay mechanism-only and
36
+ * vendor-neutral.
37
+ */
10
38
  export declare const blueprintVarianceSchema: z.ZodType<BlueprintVariance>;
11
39
  /**
12
40
  * Zod mirror of {@link Blueprint}. Required fields are listed first;
@@ -15,15 +43,6 @@ export declare const blueprintVarianceSchema: z.ZodType<BlueprintVariance>;
15
43
  * in persisted rows are a bug worth surfacing rather than tolerating.
16
44
  */
17
45
  export declare const blueprintSchema: z.ZodType<Blueprint>;
18
- /**
19
- * Zod mirror of {@link BlueprintSearchWeights}. Every axis is a
20
- * non-negative finite number. Per-axis defaults are applied at the
21
- * impl layer (see `DEFAULT_BLUEPRINT_SEARCH_WEIGHTS` in
22
- * `@ggui-ai/mcp-server-core`); this schema only validates the shape
23
- * an operator passes through `App.blueprintSearchConfig.weights`
24
- * when the operator provides EVERY axis.
25
- */
26
- export declare const blueprintSearchWeightsSchema: z.ZodType<BlueprintSearchWeights>;
27
46
  /**
28
47
  * Zod mirror of {@link AppBlueprintSearchConfig}. All fields optional;
29
48
  * server applies the global default for any axis the operator omits.
@@ -1 +1 @@
1
- {"version":3,"file":"blueprint.d.ts","sourceRoot":"","sources":["../../src/schemas/blueprint.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EACV,wBAAwB,EACxB,SAAS,EACT,sBAAsB,EACtB,iBAAiB,EAClB,MAAM,oBAAoB,CAAC;AAG5B,+CAA+C;AAC/C,eAAO,MAAM,uBAAuB,EAAE,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAOtB,CAAC;AAE5C;;;;;GAKG;AACH,eAAO,MAAM,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAwBd,CAAC;AAEpC;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,EAAE,CAAC,CAAC,OAAO,CAAC,sBAAsB,CAQ3B,CAAC;AAmBjD;;;GAGG;AACH,eAAO,MAAM,8BAA8B,EAAE,CAAC,CAAC,OAAO,CAAC,wBAAwB,CAM7B,CAAC"}
1
+ {"version":3,"file":"blueprint.d.ts","sourceRoot":"","sources":["../../src/schemas/blueprint.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EACV,wBAAwB,EACxB,SAAS,EACT,iBAAiB,EAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EACV,eAAe,EACf,sBAAsB,EACtB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,2BAA2B,CAAC;AAGnC;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,EAAE,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAMvB,CAAC;AAE7C,0EAA0E;AAC1E,eAAO,MAAM,yBAAyB,EAAE,CAAC,CAAC,OAAO,CAAC,mBAAmB,CAExB,CAAC;AAE9C,oDAAoD;AACpD,eAAO,MAAM,4BAA4B,EAAE,CAAC,CAAC,OAAO,CAAC,sBAAsB,CAE3B,CAAC;AAEjD;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,CAAC,CAAC,OAAO,CAAC,eAAe,CAI7B,CAAC;AAEjC;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,EAAE,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAqBtB,CAAC;AAE5C;;;;;GAKG;AACH,eAAO,MAAM,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAwBd,CAAC;AAmBpC;;;GAGG;AACH,eAAO,MAAM,8BAA8B,EAAE,CAAC,CAAC,OAAO,CAAC,wBAAwB,CAM7B,CAAC"}
@@ -6,13 +6,66 @@
6
6
  */
7
7
  import { z } from 'zod';
8
8
  import { dataContractSchema, jsonValueSchema } from './data-contract.js';
9
- /** Zod mirror of {@link BlueprintVariance}. */
9
+ /**
10
+ * Zod mirror of {@link LlmBlueprintSource} — the engine-generated arm.
11
+ * Both provenance fields are REQUIRED: every generation mint site has
12
+ * them in scope, and an engine-generated artifact that cannot name its
13
+ * engine + model is not a real state.
14
+ */
15
+ export const llmBlueprintSourceSchema = z
16
+ .object({
17
+ kind: z.literal('llm'),
18
+ generator: z.string().min(1),
19
+ model: z.string().min(1),
20
+ })
21
+ .strict();
22
+ /** Zod mirror of {@link UserBlueprintSource} — no engine claim exists. */
23
+ export const userBlueprintSourceSchema = z
24
+ .object({ kind: z.literal('user') })
25
+ .strict();
26
+ /** Zod mirror of {@link CuratedBlueprintSource}. */
27
+ export const curatedBlueprintSourceSchema = z
28
+ .object({ kind: z.literal('curated') })
29
+ .strict();
30
+ /**
31
+ * Zod mirror of {@link BlueprintSource} — the single provenance
32
+ * vocabulary for blueprints. Mirrors `parseBlueprintSource`'s arms;
33
+ * `.strict()` members so stray keys surface at the wire layer rather
34
+ * than riding through.
35
+ */
36
+ export const blueprintSourceSchema = z.union([
37
+ llmBlueprintSourceSchema,
38
+ userBlueprintSourceSchema,
39
+ curatedBlueprintSourceSchema,
40
+ ]);
41
+ /**
42
+ * Zod mirror of {@link BlueprintVariance}. The single shared variance
43
+ * schema: every seam that accepts a variance block (handshake draft,
44
+ * render override, operator blueprint tools) reuses this one
45
+ * rather than re-declaring the shape inline. `.strict()` so an unknown
46
+ * key surfaces as a typo at the wire layer rather than being silently
47
+ * dropped. The per-field `.describe()` strings ship as JSON-Schema
48
+ * metadata via `tools/list`, so they stay mechanism-only and
49
+ * vendor-neutral.
50
+ */
10
51
  export const blueprintVarianceSchema = z
11
52
  .object({
12
- persona: z.string().optional(),
13
- aesthetic: z.string().optional(),
14
- context: z.record(z.string(), jsonValueSchema).optional(),
15
- seedPrompt: z.string().optional(),
53
+ persona: z
54
+ .string()
55
+ .optional()
56
+ .describe('Design persona, e.g. "minimalist" / "data-dense". Part of cache identity.'),
57
+ aesthetic: z
58
+ .string()
59
+ .optional()
60
+ .describe('Visual aesthetic, e.g. "calm" / "ornate". Part of cache identity.'),
61
+ context: z
62
+ .record(z.string(), jsonValueSchema)
63
+ .optional()
64
+ .describe('Deliberate design-shaping signals (e.g. {situation:"sad"}) — part of cache identity. NOT for per-user runtime data; put that in propsSpec/contextSpec.'),
65
+ seedPrompt: z
66
+ .string()
67
+ .optional()
68
+ .describe('Generation seed directive. Part of cache identity.'),
16
69
  })
17
70
  .strict();
18
71
  /**
@@ -28,7 +81,7 @@ export const blueprintSchema = z
28
81
  appId: z.string().min(1),
29
82
  codeS3Url: z.string().optional(),
30
83
  codeHash: z.string().optional(),
31
- generator: z.string().min(1),
84
+ source: blueprintSourceSchema,
32
85
  validatorScore: z.number().min(0).max(1).optional(),
33
86
  variance: blueprintVarianceSchema,
34
87
  // `true | undefined` — store-level invariant: at most one row per
@@ -47,28 +100,11 @@ export const blueprintSchema = z
47
100
  })
48
101
  .strict();
49
102
  /**
50
- * Zod mirror of {@link BlueprintSearchWeights}. Every axis is a
103
+ * Zod mirror of the partial-weights shape on
104
+ * {@link AppBlueprintSearchConfig.weights}. Every axis is a
51
105
  * non-negative finite number. Per-axis defaults are applied at the
52
106
  * impl layer (see `DEFAULT_BLUEPRINT_SEARCH_WEIGHTS` in
53
- * `@ggui-ai/mcp-server-core`); this schema only validates the shape
54
- * an operator passes through `App.blueprintSearchConfig.weights`
55
- * when the operator provides EVERY axis.
56
- */
57
- export const blueprintSearchWeightsSchema = z
58
- .object({
59
- hash: z.number().min(0),
60
- embed: z.number().min(0),
61
- struct: z.number().min(0),
62
- variance: z.number().min(0),
63
- intent: z.number().min(0),
64
- })
65
- .strict();
66
- /**
67
- * Zod mirror of the partial-weights shape on
68
- * {@link AppBlueprintSearchConfig.weights}. Built directly rather
69
- * than as `.partial()` on `blueprintSearchWeightsSchema` because
70
- * that schema is typed `z.ZodType<...>` for cross-zod-version
71
- * compatibility — `.partial()` only exists on `z.ZodObject`.
107
+ * `@ggui-ai/mcp-server-core`) for any axis the operator omits.
72
108
  */
73
109
  const partialBlueprintSearchWeightsSchema = z
74
110
  .object({