@ggui-ai/mcp-server-handlers 0.24.0 → 0.26.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 (196) hide show
  1. package/README.md +2 -2
  2. package/dist/blueprints/search-blueprints.d.ts +5 -5
  3. package/dist/blueprints/search-blueprints.js +5 -5
  4. package/dist/credits/index.d.ts +2 -2
  5. package/dist/credits/index.d.ts.map +1 -1
  6. package/dist/credits/index.js +1 -1
  7. package/dist/credits/list-credit-transactions.d.ts +21 -7
  8. package/dist/credits/list-credit-transactions.d.ts.map +1 -1
  9. package/dist/credits/list-credit-transactions.js +12 -2
  10. package/dist/index.d.ts +2 -5
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +5 -9
  13. package/dist/ops-apps/create-app.d.ts +10 -11
  14. package/dist/ops-apps/create-app.d.ts.map +1 -1
  15. package/dist/ops-apps/create-app.js +12 -13
  16. package/dist/ops-apps/identity.d.ts +9 -8
  17. package/dist/ops-apps/identity.d.ts.map +1 -1
  18. package/dist/ops-apps/identity.js +2 -1
  19. package/dist/ops-apps/index.d.ts +2 -2
  20. package/dist/ops-apps/index.js +2 -2
  21. package/dist/ops-apps/list-apps.d.ts +5 -6
  22. package/dist/ops-apps/list-apps.d.ts.map +1 -1
  23. package/dist/ops-apps/list-apps.js +6 -7
  24. package/dist/ops-apps/set-app-theme.d.ts +12 -8
  25. package/dist/ops-apps/set-app-theme.d.ts.map +1 -1
  26. package/dist/ops-apps/set-app-theme.js +11 -7
  27. package/dist/ops-apps/set-default-app.d.ts +1 -2
  28. package/dist/ops-apps/set-default-app.d.ts.map +1 -1
  29. package/dist/ops-apps/set-default-app.js +1 -2
  30. package/dist/ops-apps/types.d.ts +20 -23
  31. package/dist/ops-apps/types.d.ts.map +1 -1
  32. package/dist/ops-apps/types.js +4 -6
  33. package/dist/ops-blueprint/cache-mirror.d.ts +41 -0
  34. package/dist/ops-blueprint/cache-mirror.d.ts.map +1 -0
  35. package/dist/ops-blueprint/cache-mirror.js +19 -0
  36. package/dist/ops-blueprint/delete.d.ts +18 -0
  37. package/dist/ops-blueprint/delete.d.ts.map +1 -1
  38. package/dist/ops-blueprint/delete.js +21 -2
  39. package/dist/ops-blueprint/errors.d.ts +23 -0
  40. package/dist/ops-blueprint/errors.d.ts.map +1 -1
  41. package/dist/ops-blueprint/errors.js +29 -0
  42. package/dist/ops-blueprint/generate.d.ts +1 -3
  43. package/dist/ops-blueprint/generate.d.ts.map +1 -1
  44. package/dist/ops-blueprint/generate.js +47 -58
  45. package/dist/ops-blueprint/index.d.ts +1 -1
  46. package/dist/ops-blueprint/index.d.ts.map +1 -1
  47. package/dist/ops-blueprint/index.js +1 -1
  48. package/dist/ops-blueprint/list.d.ts.map +1 -1
  49. package/dist/ops-blueprint/list.js +1 -2
  50. package/dist/ops-blueprint/register.d.ts +83 -6
  51. package/dist/ops-blueprint/register.d.ts.map +1 -1
  52. package/dist/ops-blueprint/register.js +261 -158
  53. package/dist/ops-blueprint/update.d.ts +3 -2
  54. package/dist/ops-blueprint/update.d.ts.map +1 -1
  55. package/dist/ops-blueprint/update.js +4 -3
  56. package/dist/renders/blueprint-coverage.d.ts +23 -4
  57. package/dist/renders/blueprint-coverage.d.ts.map +1 -1
  58. package/dist/renders/blueprint-coverage.js +45 -5
  59. package/dist/renders/blueprint-durability.d.ts.map +1 -1
  60. package/dist/renders/blueprint-durability.js +36 -21
  61. package/dist/renders/blueprint-matcher.d.ts +57 -7
  62. package/dist/renders/blueprint-matcher.d.ts.map +1 -1
  63. package/dist/renders/blueprint-matcher.js +154 -36
  64. package/dist/renders/blueprint-registry.d.ts +154 -1
  65. package/dist/renders/blueprint-registry.d.ts.map +1 -1
  66. package/dist/renders/blueprint-registry.js +337 -10
  67. package/dist/renders/build-seed-pool.d.ts.map +1 -1
  68. package/dist/renders/build-seed-pool.js +6 -0
  69. package/dist/renders/cache-trace-sink.d.ts +12 -0
  70. package/dist/renders/cache-trace-sink.d.ts.map +1 -1
  71. package/dist/renders/cache-trace-sink.js +15 -1
  72. package/dist/renders/consume.d.ts +3 -2
  73. package/dist/renders/consume.d.ts.map +1 -1
  74. package/dist/renders/consume.js +50 -15
  75. package/dist/renders/cross-app-refused.d.ts +17 -0
  76. package/dist/renders/cross-app-refused.d.ts.map +1 -0
  77. package/dist/renders/cross-app-refused.js +23 -0
  78. package/dist/renders/decide-handshake.d.ts +47 -1
  79. package/dist/renders/decide-handshake.d.ts.map +1 -1
  80. package/dist/renders/decide-handshake.js +74 -6
  81. package/dist/renders/declare-tool-catalog.d.ts.map +1 -1
  82. package/dist/renders/declare-tool-catalog.js +20 -17
  83. package/dist/renders/export-registry.d.ts +8 -1
  84. package/dist/renders/export-registry.d.ts.map +1 -1
  85. package/dist/renders/export-registry.js +3 -0
  86. package/dist/renders/fits.d.ts +60 -0
  87. package/dist/renders/fits.d.ts.map +1 -0
  88. package/dist/renders/fits.js +114 -0
  89. package/dist/renders/handshake-generation-inputs.d.ts +89 -0
  90. package/dist/renders/handshake-generation-inputs.d.ts.map +1 -0
  91. package/dist/renders/handshake-generation-inputs.js +65 -0
  92. package/dist/renders/handshake.d.ts +6 -42
  93. package/dist/renders/handshake.d.ts.map +1 -1
  94. package/dist/renders/handshake.js +1 -1
  95. package/dist/renders/index.d.ts +10 -5
  96. package/dist/renders/index.d.ts.map +1 -1
  97. package/dist/renders/index.js +10 -3
  98. package/dist/renders/installed-blueprints-provider.d.ts.map +1 -1
  99. package/dist/renders/installed-blueprints-provider.js +3 -1
  100. package/dist/renders/match-precision/pairs.d.ts +6 -5
  101. package/dist/renders/match-precision/pairs.d.ts.map +1 -1
  102. package/dist/renders/match-precision/run-probe.js +1 -2
  103. package/dist/renders/match-precision/topk-probe.js +13 -8
  104. package/dist/renders/record-committed-one-shot.d.ts +18 -3
  105. package/dist/renders/record-committed-one-shot.d.ts.map +1 -1
  106. package/dist/renders/record-committed-one-shot.js +14 -7
  107. package/dist/renders/refresh-ws-token.d.ts +66 -87
  108. package/dist/renders/refresh-ws-token.d.ts.map +1 -1
  109. package/dist/renders/refresh-ws-token.js +93 -89
  110. package/dist/renders/render-identity.d.ts +16 -5
  111. package/dist/renders/render-identity.d.ts.map +1 -1
  112. package/dist/renders/render-identity.js +26 -10
  113. package/dist/renders/render-read-gate.d.ts +85 -0
  114. package/dist/renders/render-read-gate.d.ts.map +1 -0
  115. package/dist/renders/render-read-gate.js +57 -0
  116. package/dist/renders/render.d.ts +77 -27
  117. package/dist/renders/render.d.ts.map +1 -1
  118. package/dist/renders/render.js +269 -95
  119. package/dist/renders/report-render-failure.d.ts +69 -0
  120. package/dist/renders/report-render-failure.d.ts.map +1 -0
  121. package/dist/renders/report-render-failure.js +83 -0
  122. package/dist/renders/runtime-pull.d.ts.map +1 -1
  123. package/dist/renders/runtime-pull.js +6 -0
  124. package/dist/renders/slice-meta-derivation.d.ts +8 -1
  125. package/dist/renders/slice-meta-derivation.d.ts.map +1 -1
  126. package/dist/renders/slice-meta-derivation.js +1 -0
  127. package/dist/renders/submit-action.d.ts +47 -78
  128. package/dist/renders/submit-action.d.ts.map +1 -1
  129. package/dist/renders/submit-action.js +312 -84
  130. package/dist/renders/sync-context.d.ts +3 -1
  131. package/dist/renders/sync-context.d.ts.map +1 -1
  132. package/dist/renders/sync-context.js +53 -20
  133. package/dist/types.d.ts +71 -1
  134. package/dist/types.d.ts.map +1 -1
  135. package/dist/types.js +32 -0
  136. package/package.json +8 -20
  137. package/dist/ops-connector-keys/in-memory-fake.test-util.d.ts +0 -26
  138. package/dist/ops-connector-keys/in-memory-fake.test-util.d.ts.map +0 -1
  139. package/dist/ops-connector-keys/in-memory-fake.test-util.js +0 -60
  140. package/dist/ops-connector-keys/index.d.ts +0 -19
  141. package/dist/ops-connector-keys/index.d.ts.map +0 -1
  142. package/dist/ops-connector-keys/index.js +0 -14
  143. package/dist/ops-connector-keys/issue-connector-key.d.ts +0 -76
  144. package/dist/ops-connector-keys/issue-connector-key.d.ts.map +0 -1
  145. package/dist/ops-connector-keys/issue-connector-key.js +0 -84
  146. package/dist/ops-connector-keys/list-connector-keys.d.ts +0 -58
  147. package/dist/ops-connector-keys/list-connector-keys.d.ts.map +0 -1
  148. package/dist/ops-connector-keys/list-connector-keys.js +0 -39
  149. package/dist/ops-connector-keys/revoke-connector-key.d.ts +0 -32
  150. package/dist/ops-connector-keys/revoke-connector-key.d.ts.map +0 -1
  151. package/dist/ops-connector-keys/revoke-connector-key.js +0 -49
  152. package/dist/ops-connector-keys/types.d.ts +0 -91
  153. package/dist/ops-connector-keys/types.d.ts.map +0 -1
  154. package/dist/ops-connector-keys/types.js +0 -24
  155. package/dist/ops-coupon/in-memory-fake.test-util.d.ts +0 -28
  156. package/dist/ops-coupon/in-memory-fake.test-util.d.ts.map +0 -1
  157. package/dist/ops-coupon/in-memory-fake.test-util.js +0 -66
  158. package/dist/ops-coupon/index.d.ts +0 -15
  159. package/dist/ops-coupon/index.d.ts.map +0 -1
  160. package/dist/ops-coupon/index.js +0 -12
  161. package/dist/ops-coupon/redeem-coupon.d.ts +0 -51
  162. package/dist/ops-coupon/redeem-coupon.d.ts.map +0 -1
  163. package/dist/ops-coupon/redeem-coupon.js +0 -61
  164. package/dist/ops-coupon/types.d.ts +0 -59
  165. package/dist/ops-coupon/types.d.ts.map +0 -1
  166. package/dist/ops-coupon/types.js +0 -38
  167. package/dist/ops-orgs/create-org.d.ts +0 -45
  168. package/dist/ops-orgs/create-org.d.ts.map +0 -1
  169. package/dist/ops-orgs/create-org.js +0 -55
  170. package/dist/ops-orgs/get-org-balance.d.ts +0 -29
  171. package/dist/ops-orgs/get-org-balance.d.ts.map +0 -1
  172. package/dist/ops-orgs/get-org-balance.js +0 -45
  173. package/dist/ops-orgs/in-memory-fake.test-util.d.ts +0 -84
  174. package/dist/ops-orgs/in-memory-fake.test-util.d.ts.map +0 -1
  175. package/dist/ops-orgs/in-memory-fake.test-util.js +0 -209
  176. package/dist/ops-orgs/index.d.ts +0 -33
  177. package/dist/ops-orgs/index.d.ts.map +0 -1
  178. package/dist/ops-orgs/index.js +0 -24
  179. package/dist/ops-orgs/invite-to-org.d.ts +0 -56
  180. package/dist/ops-orgs/invite-to-org.d.ts.map +0 -1
  181. package/dist/ops-orgs/invite-to-org.js +0 -72
  182. package/dist/ops-orgs/list-orgs.d.ts +0 -53
  183. package/dist/ops-orgs/list-orgs.d.ts.map +0 -1
  184. package/dist/ops-orgs/list-orgs.js +0 -38
  185. package/dist/ops-orgs/remove-org-member.d.ts +0 -42
  186. package/dist/ops-orgs/remove-org-member.d.ts.map +0 -1
  187. package/dist/ops-orgs/remove-org-member.js +0 -67
  188. package/dist/ops-orgs/rename-org.d.ts +0 -33
  189. package/dist/ops-orgs/rename-org.d.ts.map +0 -1
  190. package/dist/ops-orgs/rename-org.js +0 -57
  191. package/dist/ops-orgs/revoke-invite.d.ts +0 -38
  192. package/dist/ops-orgs/revoke-invite.d.ts.map +0 -1
  193. package/dist/ops-orgs/revoke-invite.js +0 -53
  194. package/dist/ops-orgs/types.d.ts +0 -209
  195. package/dist/ops-orgs/types.d.ts.map +0 -1
  196. package/dist/ops-orgs/types.js +0 -60
@@ -42,8 +42,7 @@ const opsOutputSchema = {
42
42
  };
43
43
  /**
44
44
  * Sort blueprints by `createdAt desc`, then `blueprintId asc` as
45
- * stable tiebreaker. Mirrors the `BlueprintSelector` deterministic
46
- * ladder ordering (see `@ggui-ai/mcp-server-core/blueprint-selector`).
45
+ * stable tiebreaker.
47
46
  */
48
47
  function sortBlueprintsByCreatedAtDesc(rows) {
49
48
  return [...rows].sort((a, b) => {
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * Sibling of `ggui_ops_generate_blueprint`. Same persistence seams +
6
6
  * dual-write (BlueprintStore + cache vectorStore via registerBlueprint),
7
- * same variance + default-pin semantics. The only difference is the
7
+ * same variance + operator-default mark semantics. The only difference is the
8
8
  * code body: instead of dispatching through `generator.generate(...)`
9
9
  * to produce componentCode, the operator supplies the bytes directly
10
10
  * and the handler persists them verbatim.
@@ -36,16 +36,19 @@
36
36
  * ops_generate — schema-compat + hygiene-3 lint live elsewhere.
37
37
  */
38
38
  import type { AppMetadataStore, BlueprintStore, TelemetrySink } from "@ggui-ai/mcp-server-core";
39
- import { type Blueprint, type DataContract, type UserBlueprintSource } from "@ggui-ai/protocol";
39
+ import { type Blueprint, type DataContract, type GeneratorBuild, type LlmBlueprintSource, type UserBlueprintSource } from "@ggui-ai/protocol";
40
40
  import { z } from "zod";
41
41
  import { type BlueprintRegistryDeps } from "../renders/index.js";
42
+ import { type HandlerContext } from "../types.js";
42
43
  import { type OpsBlueprintAppAuthorizer } from "./app-access.js";
43
44
  import type { PutCodeHook } from "./generate.js";
44
45
  /**
45
- * Deps for `ggui_ops_register_blueprint`. Mirrors `*_generate_*`'s
46
- * deps minus `resolveLlm`, `blueprints`, and `registry` (no generator
47
- * dispatch — provenance is structurally `{kind: 'user'}`, so there is
48
- * no slug to resolve).
46
+ * Deps shared by `ggui_ops_register_blueprint` and the in-process
47
+ * {@link createRegisterGeneratedBlueprint}. Mirrors `*_generate_*`'s deps
48
+ * minus `resolveLlm`, `blueprints` and `registry`: neither entry dispatches
49
+ * a generator, so there is no slug to resolve. The operator door stamps
50
+ * `{kind: 'user'}`; the generated entry takes the generation's own `llm`
51
+ * record.
49
52
  */
50
53
  export interface GguiOpsRegisterBlueprintDeps {
51
54
  /**
@@ -117,7 +120,19 @@ export declare function createGguiOpsRegisterBlueprintHandler(deps: GguiOpsRegis
117
120
  aesthetic: z.ZodOptional<z.ZodString>;
118
121
  context: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodType<import("@ggui-ai/protocol").JsonValue, unknown, z.core.$ZodTypeInternals<import("@ggui-ai/protocol").JsonValue, unknown>>>>;
119
122
  seedPrompt: z.ZodOptional<z.ZodString>;
123
+ intent: z.ZodOptional<z.ZodString>;
124
+ judgedCanvases: z.ZodOptional<z.ZodArray<z.ZodString>>;
125
+ aestheticPreset: z.ZodOptional<z.ZodObject<{
126
+ id: z.ZodString;
127
+ version: z.ZodOptional<z.ZodString>;
128
+ }, z.core.$strict>>;
129
+ directionDigest: z.ZodOptional<z.ZodString>;
130
+ directionScope: z.ZodOptional<z.ZodEnum<{
131
+ app: "app";
132
+ request: "request";
133
+ }>>;
120
134
  setAsOperatorDefault: z.ZodOptional<z.ZodBoolean>;
135
+ clonedFrom: z.ZodOptional<z.ZodString>;
121
136
  }, {
122
137
  blueprintId: z.ZodString;
123
138
  codeHash: z.ZodString;
@@ -129,4 +144,66 @@ export declare function createGguiOpsRegisterBlueprintHandler(deps: GguiOpsRegis
129
144
  codeHash: string;
130
145
  source: UserBlueprintSource;
131
146
  }>;
147
+ /**
148
+ * Engine-generated bytes and the authored source they were compiled
149
+ * from — what {@link createRegisterGeneratedBlueprint} registers.
150
+ */
151
+ export interface GeneratedBlueprintBytes {
152
+ /**
153
+ * The authored (pre-compile) source that `componentCode` was compiled
154
+ * from. **Caller obligation:** it MUST be that exact pair, produced by
155
+ * one generation (for example, the authored `.tsx` a generation wrote
156
+ * and the module compiled from it). Nothing here recompiles it to check — that is why
157
+ * this entry is in-process only and the public operator door takes no
158
+ * source. A pair that is byte-identical records no source (the
159
+ * registry's collapse rule), which is the honest answer for a
160
+ * generation that produced no distinct authored form.
161
+ */
162
+ readonly sourceCode: string;
163
+ /**
164
+ * The generation's own provenance, read from what the generation itself
165
+ * reported — never a placeholder or a configured default. An `llm` record with a guessed model is a provenance
166
+ * claim nobody made. Validated against the protocol's schema.
167
+ */
168
+ readonly source: LlmBlueprintSource;
169
+ /**
170
+ * ggui#1280 — the build the generation reported (`metadata.build`),
171
+ * verbatim. Admitted by the registry's one rule (`admitGeneratorBuild`):
172
+ * a stamp that fails the protocol's `generatorBuildSchema` is dropped
173
+ * with a `blueprint_build_stamp_dropped` line and the row registers
174
+ * unstamped, so a bad stamp never refuses a registration.
175
+ */
176
+ readonly build?: GeneratorBuild;
177
+ }
178
+ /** What {@link createRegisterGeneratedBlueprint}'s entry returns. */
179
+ export interface RegisterGeneratedBlueprintOutput {
180
+ readonly blueprintId: string;
181
+ readonly codeHash: string;
182
+ readonly source: LlmBlueprintSource;
183
+ }
184
+ /**
185
+ * The in-process generated-bytes registration entry. `input` is the same
186
+ * RAW input `ggui_ops_register_blueprint` takes — parsed with its schema
187
+ * on entry, so a value the schema refuses throws, exactly as it would
188
+ * through the operator door.
189
+ */
190
+ export type RegisterGeneratedBlueprint = (input: Record<string, unknown>, generated: GeneratedBlueprintBytes, ctx: HandlerContext) => Promise<RegisterGeneratedBlueprintOutput>;
191
+ /**
192
+ * ggui#1493 (ggui#1477's source half) — register ENGINE-GENERATED bytes
193
+ * with the authored source they were compiled from, in-process.
194
+ *
195
+ * Same body as `ggui_ops_register_blueprint` (one durable row, one cache
196
+ * mirror, the same gates and variance), with three differences: provenance
197
+ * is the generation's `llm` arm; the authored source reaches the cache
198
+ * registry, so a render that reuses the registration serves it
199
+ * (`ggui_get_render_source`, save-to-library); and the generation's build,
200
+ * when the caller passes one, is stamped on the durable rows (ggui#1280).
201
+ * It is NOT an MCP tool and
202
+ * is on no wire: the public operator door stays source-free, because it
203
+ * cannot verify that supplied source compiles to the supplied code.
204
+ *
205
+ * Refuses, before anything is persisted, provenance the protocol's
206
+ * `llmBlueprintSourceSchema` rejects and an empty `sourceCode`.
207
+ */
208
+ export declare function createRegisterGeneratedBlueprint(deps: GguiOpsRegisterBlueprintDeps): RegisterGeneratedBlueprint;
132
209
  //# sourceMappingURL=register.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/ops-blueprint/register.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,aAAa,EACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,YAAY,EAGjB,KAAK,mBAAmB,EACzB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAqB,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEpF,OAAO,EAAyB,KAAK,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AACxF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAiBjD;;;;;GAKG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;;OAGG;IACH,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,SAAS,EAAE,CAAC,CAAC;IAC1E;;;;;;;OAOG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IAC7C;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC;IAC/B;;;;;;;;OAQG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,qBAAqB,CAAC;IAC/C;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC;IACnC;;OAEG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B;;OAEG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,MAAM,CAAC;IACxC;;;;;;;OAOG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,yBAAyB,CAAC;CACzD;AAED,wBAAgB,qCAAqC,CACnD,IAAI,EAAE,4BAA4B;;;;;;;;;;;;;;;;;;;GAsMnC"}
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/ops-blueprint/register.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,aAAa,EACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAGL,KAAK,SAAS,EAEd,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EAGvB,KAAK,mBAAmB,EACzB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAuB,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEtF,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAyB,KAAK,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AACxF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAkBjD;;;;;;;GAOG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;;OAGG;IACH,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,SAAS,EAAE,CAAC,CAAC;IAC1E;;;;;;;OAOG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IAC7C;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC;IAC/B;;;;;;;;OAQG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,qBAAqB,CAAC;IAC/C;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC;IACnC;;OAEG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B;;OAEG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,MAAM,CAAC;IACxC;;;;;;;OAOG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,yBAAyB,CAAC;CACzD;AA0QD,wBAAgB,qCAAqC,CACnD,IAAI,EAAE,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BnC;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;;;;;;OASG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,qEAAqE;AACrE,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;CACrC;AAED;;;;;GAKG;AACH,MAAM,MAAM,0BAA0B,GAAG,CACvC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,SAAS,EAAE,uBAAuB,EAClC,GAAG,EAAE,cAAc,KAChB,OAAO,CAAC,gCAAgC,CAAC,CAAC;AAE/C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gCAAgC,CAC9C,IAAI,EAAE,4BAA4B,GACjC,0BAA0B,CAkB5B"}
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * Sibling of `ggui_ops_generate_blueprint`. Same persistence seams +
6
6
  * dual-write (BlueprintStore + cache vectorStore via registerBlueprint),
7
- * same variance + default-pin semantics. The only difference is the
7
+ * same variance + operator-default mark semantics. The only difference is the
8
8
  * code body: instead of dispatching through `generator.generate(...)`
9
9
  * to produce componentCode, the operator supplies the bytes directly
10
10
  * and the handler persists them verbatim.
@@ -35,15 +35,17 @@
35
35
  * - Validate the contract beyond Zod parsing. Same posture as
36
36
  * ops_generate — schema-compat + hygiene-3 lint live elsewhere.
37
37
  */
38
- import { opsRegisterBlueprintInputSchema, } from "@ggui-ai/protocol";
38
+ import { llmBlueprintSourceSchema, opsRegisterBlueprintInputSchema, } from "@ggui-ai/protocol";
39
39
  import { blueprintKey } from "@ggui-ai/protocol/blueprint-key";
40
40
  import { createHash, randomUUID } from "node:crypto";
41
41
  import { z } from "zod";
42
42
  import { assertContractNoRetiredFields } from "../renders/assert-contract-no-retired-fields.js";
43
43
  import { assertGadgetsRegistered } from "../renders/assert-gadgets.js";
44
- import { registerBlueprint } from "../renders/index.js";
44
+ import { admitGeneratorBuild } from "../renders/index.js";
45
+ import { mirrorIntoCache } from "./cache-mirror.js";
45
46
  import { defineHandler } from "../types.js";
46
47
  import { resolveEffectiveAppId } from "./app-access.js";
48
+ import { ClonedFromRefusedError, DirectionScopeWithoutDigestError } from "./errors.js";
47
49
  import { findNearDuplicatePersona, normalizePersona } from "./persona-normalization.js";
48
50
  const opsInputSchema = opsRegisterBlueprintInputSchema.shape;
49
51
  const opsOutputSchema = z.object({
@@ -57,153 +59,58 @@ const opsOutputSchema = z.object({
57
59
  * no engine claim because none exists to record.
58
60
  */
59
61
  const USER_SOURCE = { kind: "user" };
60
- export function createGguiOpsRegisterBlueprintHandler(deps) {
62
+ /**
63
+ * The registration body both entries share: app resolution, the
64
+ * contract gates, the durable row, the cache mirror, the operator-default mark and
65
+ * the event. The two entries differ only in the provenance they pass.
66
+ */
67
+ function makeRegisterCore(deps) {
61
68
  const now = deps.now ?? (() => new Date().toISOString());
62
69
  const mintBlueprintId = deps.mintBlueprintId ?? (() => `bp_${randomUUID()}`);
63
- return defineHandler({
64
- name: "ggui_ops_register_blueprint",
65
- title: "Register blueprint",
66
- audience: ["ops"],
67
- description: "Register a pre-built blueprint variant (operator-supplied componentCode bytes, no LLM dispatch). Sibling of `ggui_ops_generate_blueprint` — same persistence + dual-write semantics, same variance + default-pin behavior. Use for fixture seeding, export/reimport round-trips, and manual recovery. Returns `{blueprintId, codeHash, source}` where `source` is always `{kind: 'user'}` — hand-supplied bytes carry no engine claim, so none is recorded. App-scoped variant curation for an app you operate — distinct from the personal saved-blueprint library (the _my_ tools).",
68
- inputSchema: opsInputSchema,
69
- outputSchema: opsOutputSchema,
70
- async handler(rawInput, ctx) {
71
- const parsed = opsRegisterBlueprintInputSchema.parse(rawInput);
72
- const appId = await resolveEffectiveAppId({
73
- toolName: "ggui_ops_register_blueprint",
74
- inputAppId: parsed.appId,
75
- ctx,
76
- ...(deps.authorizeAppAccess ? { authorize: deps.authorizeAppAccess } : {}),
77
- });
78
- // Reject retired top-level contract fields BEFORE any
79
- // persistence so an operator-supplied row can't smuggle
80
- // deprecated vocabulary (`terminal`, `consumeSpec`,
81
- // `interaction`, `commandSpec`, `behaviorSpec`) into the
82
- // registry. The same gate fires on the render + handshake seams
83
- // in `renders/`.
84
- assertContractNoRetiredFields(parsed.contract);
85
- // Every `contract.clientCapabilities.gadgets[*]` MUST resolve
86
- // in `App.gadgets` by `(package, export name)` — the wire
87
- // carries no version; the operator's catalog is the version
88
- // pin. Fails fast with a precise reject before any state
89
- // mutation. No-op when no `appMetadataStore` is bound.
90
- if (deps.appMetadataStore) {
91
- const appRecord = await deps.appMetadataStore.get(appId);
92
- assertGadgetsRegistered(parsed.contract, appRecord?.gadgets);
93
- }
94
- // 1. Normalize the persona + run near-dup detection. Same
95
- // posture as ops_generate.
96
- const normalizedPersona = normalizePersona(parsed.persona);
97
- if (normalizedPersona !== undefined && deps.listAllForApp) {
98
- try {
99
- const allForApp = await deps.listAllForApp(appId);
100
- const existingPersonas = allForApp
101
- .map((bp) => bp.variance.persona)
102
- .filter((p) => typeof p === "string");
103
- const dup = findNearDuplicatePersona(normalizedPersona, existingPersonas);
104
- if (dup && dup.nearestExisting !== null) {
105
- try {
106
- deps.telemetry?.emit({
107
- name: "near-duplicate-persona",
108
- at: Date.now(),
109
- attributes: {
110
- appId,
111
- requestId: ctx.requestId,
112
- candidate: normalizedPersona,
113
- existing: dup.nearestExisting,
114
- distance: dup.nearestDistance,
115
- },
116
- });
117
- }
118
- catch {
119
- // Swallow telemetry-side throws.
120
- }
121
- }
122
- }
123
- catch {
124
- // Swallow enumeration failures — the near-dup warning is
125
- // an early-detection signal, not a gate.
126
- }
127
- }
128
- // 2. Compute canonical hashes.
129
- const contract = parsed.contract;
130
- const contractHash = blueprintKey(contract);
131
- const componentCode = parsed.componentCode;
132
- const codeHash = createHash("sha256").update(componentCode).digest("hex");
133
- const blueprintId = mintBlueprintId();
134
- // ONE variance for BOTH stores. The cache row's exact key is
135
- // `variantKey(variance)`; omitting it on the cache call filed every
136
- // variant under the default-variant key, where an earlier registration
137
- // of the same contract already sat — the mirror then returned THAT row
138
- // and the new variant was never bound (the durable row said one thing,
139
- // the served index another). Same rule as ops_generate.
140
- const variance = {
141
- ...(normalizedPersona !== undefined ? { persona: normalizedPersona } : {}),
142
- ...(parsed.aesthetic !== undefined ? { aesthetic: parsed.aesthetic } : {}),
143
- ...(parsed.context !== undefined ? { context: parsed.context } : {}),
144
- ...(parsed.seedPrompt !== undefined ? { seedPrompt: parsed.seedPrompt } : {}),
145
- };
146
- const blueprint = {
147
- blueprintId,
148
- contractHash,
149
- appId,
150
- codeHash,
151
- // Operator-supplied bytes, no LLM dispatch — provenance is the
152
- // user arm on BOTH stores this handler writes (MVB row here,
153
- // cache mirror below). No engine claim exists to record.
154
- source: USER_SOURCE,
155
- variance,
156
- createdAt: now(),
157
- createdBy: "operator",
158
- contract,
159
- };
160
- // 3. Persist the blueprint + code body.
161
- await deps.blueprintStore.put(blueprint);
162
- if (deps.putCode) {
163
- await deps.putCode(codeHash, componentCode);
164
- }
165
- // 3.5 Mirror into the cache vectorStore so the agent-facing
166
- // matchBlueprint exact-key probe (handshake + render) finds this
167
- // operator-registered blueprint. Symmetric with ops_generate's
168
- // dual-write — see #358.
169
- if (deps.cacheRegistry) {
170
- try {
171
- const intentForCache = parsed.seedPrompt ??
172
- normalizedPersona ??
173
- `operator-registered blueprint (${blueprintId})`;
174
- await registerBlueprint(deps.cacheRegistry, appId, {
175
- kind: "template",
176
- contract,
177
- intent: intentForCache,
178
- // ggui#1275 — only a seed prompt states the UI's task. A
179
- // persona describes the agent and the placeholder describes
180
- // nothing: both are stand-ins the matcher's judge never sees.
181
- intentSource: parsed.seedPrompt !== undefined ? "authored" : "fallback",
182
- componentCode,
183
- // Same user-arm provenance as the MVB row above — one
184
- // handler call, one provenance claim across both stores.
185
- source: USER_SOURCE,
186
- // The cache row MUST carry the same variance as the MVB row —
187
- // its exact key is `variantKey(variance)`.
188
- variance,
189
- // An operator invoked this tool. Without it the durable
190
- // record would claim the standard agent flow minted a row
191
- // that is retained permanently.
192
- createdBy: "operator",
193
- });
194
- }
195
- catch (err) {
70
+ return async function registerVariant(parsed, ctx, provenance) {
71
+ const appId = await resolveEffectiveAppId({
72
+ toolName: "ggui_ops_register_blueprint",
73
+ inputAppId: parsed.appId,
74
+ ctx,
75
+ ...(deps.authorizeAppAccess ? { authorize: deps.authorizeAppAccess } : {}),
76
+ });
77
+ // Reject retired top-level contract fields BEFORE any
78
+ // persistence so an operator-supplied row can't smuggle
79
+ // deprecated vocabulary (`terminal`, `consumeSpec`,
80
+ // `interaction`, `commandSpec`, `behaviorSpec`) into the
81
+ // registry. The same gate fires on the render + handshake seams
82
+ // in `renders/`.
83
+ assertContractNoRetiredFields(parsed.contract);
84
+ // Every `contract.clientCapabilities.gadgets[*]` MUST resolve
85
+ // in `App.gadgets` by `(package, export name)` — the wire
86
+ // carries no version; the operator's catalog is the version
87
+ // pin. Fails fast with a precise reject before any state
88
+ // mutation. No-op when no `appMetadataStore` is bound.
89
+ if (deps.appMetadataStore) {
90
+ const appRecord = await deps.appMetadataStore.get(appId);
91
+ assertGadgetsRegistered(parsed.contract, appRecord?.gadgets);
92
+ }
93
+ // 1. Normalize the persona + run near-dup detection. Same
94
+ // posture as ops_generate.
95
+ const normalizedPersona = normalizePersona(parsed.persona);
96
+ if (normalizedPersona !== undefined && deps.listAllForApp) {
97
+ try {
98
+ const allForApp = await deps.listAllForApp(appId);
99
+ const existingPersonas = allForApp
100
+ .map((bp) => bp.variance.persona)
101
+ .filter((p) => typeof p === "string");
102
+ const dup = findNearDuplicatePersona(normalizedPersona, existingPersonas);
103
+ if (dup && dup.nearestExisting !== null) {
196
104
  try {
197
105
  deps.telemetry?.emit({
198
- name: "blueprint.cache_mirror_failed",
106
+ name: "near-duplicate-persona",
199
107
  at: Date.now(),
200
108
  attributes: {
201
109
  appId,
202
110
  requestId: ctx.requestId,
203
- blueprintId,
204
- contractHash,
205
- errorClass: err instanceof Error ? err.name : "unknown",
206
- errorMessage: err instanceof Error ? err.message : String(err),
111
+ candidate: normalizedPersona,
112
+ existing: dup.nearestExisting,
113
+ distance: dup.nearestDistance,
207
114
  },
208
115
  });
209
116
  }
@@ -212,29 +119,191 @@ export function createGguiOpsRegisterBlueprintHandler(deps) {
212
119
  }
213
120
  }
214
121
  }
215
- // 4. Pin as operator default when requested.
216
- if (parsed.setAsOperatorDefault === true) {
217
- await deps.blueprintStore.setOperatorDefault(blueprintId);
122
+ catch {
123
+ // Swallow enumeration failures — the near-dup warning is
124
+ // an early-detection signal, not a gate.
218
125
  }
126
+ }
127
+ // 2. Compute canonical hashes.
128
+ const contract = parsed.contract;
129
+ const contractHash = blueprintKey(contract);
130
+ const componentCode = parsed.componentCode;
131
+ const codeHash = createHash("sha256").update(componentCode).digest("hex");
132
+ // ggui#1427 — a scope without a digest is a scope for nothing: refused
133
+ // before anything is persisted (see DirectionScopeWithoutDigestError).
134
+ if (parsed.directionScope !== undefined && parsed.directionDigest === undefined) {
135
+ throw new DirectionScopeWithoutDigestError();
136
+ }
137
+ const blueprintId = mintBlueprintId();
138
+ // ggui#1570 — a copy (`clonedFrom`, the door's input member, which the
139
+ // in-process generated-bytes entry parses too) names another row of this
140
+ // app that the store holds. Checked after the id is minted (a copy never
141
+ // names itself) and before anything is persisted. The cache mirror's own
142
+ // durable write-through, when it writes to a store other than this one,
143
+ // does not carry it: that copy serves re-mint, which ignores provenance.
144
+ if (parsed.clonedFrom !== undefined) {
145
+ const parentId = parsed.clonedFrom;
146
+ const parent = parentId.length > 0 && parentId !== blueprintId ? await deps.blueprintStore.get(parentId) : null;
147
+ if (parent === null || parent.appId !== appId)
148
+ throw new ClonedFromRefusedError(parentId);
149
+ }
150
+ // ONE variance for BOTH stores. The cache row's exact key is
151
+ // `variantKey(variance)`; omitting it on the cache call filed every
152
+ // variant under the default-variant key, where an earlier registration
153
+ // of the same contract already sat — the mirror then returned THAT row
154
+ // and the new variant was never bound (the durable row said one thing,
155
+ // the served index another). Same rule as ops_generate.
156
+ const variance = {
157
+ ...(normalizedPersona !== undefined ? { persona: normalizedPersona } : {}),
158
+ ...(parsed.aesthetic !== undefined ? { aesthetic: parsed.aesthetic } : {}),
159
+ ...(parsed.context !== undefined ? { context: parsed.context } : {}),
160
+ ...(parsed.seedPrompt !== undefined ? { seedPrompt: parsed.seedPrompt } : {}),
161
+ };
162
+ const blueprint = {
163
+ blueprintId,
164
+ contractHash,
165
+ appId,
166
+ codeHash,
167
+ // The caller's provenance, on BOTH stores this call writes (MVB
168
+ // row here, cache mirror below): the user arm for operator-
169
+ // supplied bytes, the llm arm for engine-generated ones.
170
+ source: provenance.source,
171
+ // ggui#1280 — the minting build, on a generation mint's bytes only.
172
+ ...(provenance.build !== undefined ? { build: provenance.build } : {}),
173
+ // ggui#1570 — provenance about the row: the row whose bytes it copies.
174
+ ...(parsed.clonedFrom !== undefined ? { clonedFrom: parsed.clonedFrom } : {}),
175
+ variance,
176
+ createdAt: now(),
177
+ createdBy: "operator",
178
+ contract,
179
+ };
180
+ // 3. Persist the blueprint + code body.
181
+ await deps.blueprintStore.put(blueprint);
182
+ if (deps.putCode) {
183
+ await deps.putCode(codeHash, componentCode);
184
+ }
185
+ // 3.5 Mirror into the cache vectorStore so the agent-facing
186
+ // matchBlueprint exact-key probe (handshake + render) finds this
187
+ // operator-registered blueprint. Symmetric with ops_generate's
188
+ // dual-write — see #358.
189
+ if (deps.cacheRegistry) {
219
190
  try {
220
- deps.telemetry?.emit({
221
- name: "blueprint.registered",
222
- at: Date.now(),
223
- attributes: {
224
- appId,
225
- requestId: ctx.requestId,
226
- blueprintId,
227
- contractHash,
228
- // Flat-codec provenance key — always 'user' on this path.
229
- sourceKind: USER_SOURCE.kind,
191
+ // ggui#1427 — the request's own sentence, when the caller has it
192
+ // (symmetric with `*_generate_*`'s `intent`): prompt-only, never
193
+ // part of the cache identity.
194
+ const intentForCache = parsed.intent ??
195
+ parsed.seedPrompt ??
196
+ normalizedPersona ??
197
+ `operator-registered blueprint (${blueprintId})`;
198
+ // ggui#1497 — ONE id per registration: the cache row serves the
199
+ // durable row's id (see `mirrorIntoCache` for what else it writes).
200
+ await mirrorIntoCache({
201
+ cacheRegistry: deps.cacheRegistry,
202
+ writerStore: deps.blueprintStore,
203
+ appId,
204
+ blueprintId,
205
+ input: {
206
+ kind: "template",
207
+ contract,
208
+ intent: intentForCache,
209
+ // ggui#1275 — an explicit intent or a seed prompt states the
210
+ // UI's task. A persona describes the agent and the placeholder
211
+ // describes nothing: both are stand-ins the matcher's judge
212
+ // never sees.
213
+ intentSource: parsed.intent !== undefined || parsed.seedPrompt !== undefined
214
+ ? "authored"
215
+ : "fallback",
216
+ // ggui#1427 — the fit facts `fits()` reads before the judge
217
+ // ranks this row. Absent inputs write nothing (not-evaluated).
218
+ ...(parsed.judgedCanvases !== undefined ? { judgedCanvases: parsed.judgedCanvases } : {}),
219
+ ...(parsed.aestheticPreset !== undefined ? { aestheticPreset: parsed.aestheticPreset } : {}),
220
+ ...(parsed.directionDigest !== undefined ? { directionDigest: parsed.directionDigest } : {}),
221
+ ...(parsed.directionDigest !== undefined && parsed.directionScope !== undefined
222
+ ? { directionScope: parsed.directionScope }
223
+ : {}),
224
+ componentCode,
225
+ // ggui#1493 — the authored form of `componentCode`, when the
226
+ // caller has one (the in-process generated-bytes path only).
227
+ // The registry persists its hash and body only when a code
228
+ // store is bound and the pair is not byte-identical.
229
+ ...(provenance.sourceCode !== undefined ? { sourceCode: provenance.sourceCode } : {}),
230
+ // Same provenance as the MVB row above — one call, one
231
+ // provenance claim across both stores.
232
+ source: provenance.source,
233
+ // ggui#1280 — the same stamp, onto the durable row a mirror
234
+ // writes through to (never onto its vector-store row).
235
+ ...(provenance.build !== undefined ? { build: provenance.build } : {}),
236
+ // The cache row MUST carry the same variance as the MVB row —
237
+ // its exact key is `variantKey(variance)`.
238
+ variance,
239
+ // An operator invoked this tool. Without it the durable
240
+ // record would claim the standard agent flow minted a row
241
+ // that is retained permanently.
230
242
  createdBy: "operator",
231
- setAsOperatorDefault: parsed.setAsOperatorDefault === true,
232
243
  },
233
244
  });
234
245
  }
235
- catch {
236
- // Swallow telemetry-side throws.
246
+ catch (err) {
247
+ try {
248
+ deps.telemetry?.emit({
249
+ name: "blueprint.cache_mirror_failed",
250
+ at: Date.now(),
251
+ attributes: {
252
+ appId,
253
+ requestId: ctx.requestId,
254
+ blueprintId,
255
+ contractHash,
256
+ errorClass: err instanceof Error ? err.name : "unknown",
257
+ errorMessage: err instanceof Error ? err.message : String(err),
258
+ },
259
+ });
260
+ }
261
+ catch {
262
+ // Swallow telemetry-side throws.
263
+ }
237
264
  }
265
+ }
266
+ // 4. Mark as operator default when requested.
267
+ if (parsed.setAsOperatorDefault === true) {
268
+ await deps.blueprintStore.setOperatorDefault(blueprintId);
269
+ }
270
+ try {
271
+ deps.telemetry?.emit({
272
+ name: "blueprint.registered",
273
+ at: Date.now(),
274
+ attributes: {
275
+ appId,
276
+ requestId: ctx.requestId,
277
+ blueprintId,
278
+ contractHash,
279
+ // Flat-codec provenance key — 'user' on the operator door,
280
+ // 'llm' on the generated-bytes path.
281
+ sourceKind: provenance.source.kind,
282
+ createdBy: "operator",
283
+ setAsOperatorDefault: parsed.setAsOperatorDefault === true,
284
+ },
285
+ });
286
+ }
287
+ catch {
288
+ // Swallow telemetry-side throws.
289
+ }
290
+ return { blueprintId, codeHash };
291
+ };
292
+ }
293
+ export function createGguiOpsRegisterBlueprintHandler(deps) {
294
+ const registerVariant = makeRegisterCore(deps);
295
+ return defineHandler({
296
+ name: "ggui_ops_register_blueprint",
297
+ title: "Register blueprint",
298
+ audience: ["ops"],
299
+ description: "Register a pre-built blueprint variant (operator-supplied componentCode bytes, no LLM dispatch). Sibling of `ggui_ops_generate_blueprint` — same persistence + dual-write semantics, same variance + operator-default mark behavior (the mark orders blueprint listings; it does not decide which blueprint serves a render). Use for fixture seeding, export/reimport round-trips, and manual recovery. Returns `{blueprintId, codeHash, source}` where `source` is always `{kind: 'user'}` — hand-supplied bytes carry no engine claim, so none is recorded. App-scoped variant curation for an app you operate — distinct from the personal saved-blueprint library (the _my_ tools).",
300
+ inputSchema: opsInputSchema,
301
+ outputSchema: opsOutputSchema,
302
+ async handler(rawInput, ctx) {
303
+ const parsed = opsRegisterBlueprintInputSchema.parse(rawInput);
304
+ // Operator-supplied bytes, no LLM dispatch: the user arm, and no
305
+ // authored source (this door never carries one — ggui#1477).
306
+ const { blueprintId, codeHash } = await registerVariant(parsed, ctx, { source: USER_SOURCE });
238
307
  return {
239
308
  blueprintId,
240
309
  codeHash,
@@ -243,3 +312,37 @@ export function createGguiOpsRegisterBlueprintHandler(deps) {
243
312
  },
244
313
  });
245
314
  }
315
+ /**
316
+ * ggui#1493 (ggui#1477's source half) — register ENGINE-GENERATED bytes
317
+ * with the authored source they were compiled from, in-process.
318
+ *
319
+ * Same body as `ggui_ops_register_blueprint` (one durable row, one cache
320
+ * mirror, the same gates and variance), with three differences: provenance
321
+ * is the generation's `llm` arm; the authored source reaches the cache
322
+ * registry, so a render that reuses the registration serves it
323
+ * (`ggui_get_render_source`, save-to-library); and the generation's build,
324
+ * when the caller passes one, is stamped on the durable rows (ggui#1280).
325
+ * It is NOT an MCP tool and
326
+ * is on no wire: the public operator door stays source-free, because it
327
+ * cannot verify that supplied source compiles to the supplied code.
328
+ *
329
+ * Refuses, before anything is persisted, provenance the protocol's
330
+ * `llmBlueprintSourceSchema` rejects and an empty `sourceCode`.
331
+ */
332
+ export function createRegisterGeneratedBlueprint(deps) {
333
+ const registerVariant = makeRegisterCore(deps);
334
+ return async (input, generated, ctx) => {
335
+ const parsed = opsRegisterBlueprintInputSchema.parse(input);
336
+ const source = llmBlueprintSourceSchema.parse(generated.source);
337
+ if (generated.sourceCode.length === 0) {
338
+ throw new Error("registerGeneratedBlueprint: sourceCode must be the non-empty authored source componentCode was compiled from");
339
+ }
340
+ const build = admitGeneratorBuild(source, generated.build);
341
+ const { blueprintId, codeHash } = await registerVariant(parsed, ctx, {
342
+ source,
343
+ sourceCode: generated.sourceCode,
344
+ ...(build !== undefined ? { build } : {}),
345
+ });
346
+ return { blueprintId, codeHash, source };
347
+ };
348
+ }
@@ -3,8 +3,9 @@
3
3
  *
4
4
  * Patches the two mutable surfaces of a blueprint:
5
5
  *
6
- * 1. `isOperatorDefault` — pin as the operator default for the
7
- * blueprint's `(appId, contractHash)` group. The store
6
+ * 1. `isOperatorDefault` — mark as the operator default for the
7
+ * blueprint's `(appId, contractHash)` group (orders listings; no
8
+ * render path reads it to choose what serves). The store
8
9
  * automatically clears any prior default in the same group
9
10
  * (see `BlueprintStore.setOperatorDefault`).
10
11
  * 2. `variance` — partial merge into the persisted variance. Keys
@@ -1 +1 @@
1
- {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/ops-blueprint/update.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAGL,KAAK,iBAAiB,EAGvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EACV,cAAc,EACf,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAyB,KAAK,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AASxF;;;;;;;;;GASG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,EAAG,wBAAwB,CAAU;gBACtC,WAAW,EAAE,MAAM;CAMhC;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC;;;OAGG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,yBAAyB,CAAC;CACzD;AAuCD,wBAAgB,mCAAmC,CACjD,IAAI,EAAE,0BAA0B;;;;;;;;;;;GAwEjC"}
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/ops-blueprint/update.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAGL,KAAK,iBAAiB,EAGvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EACV,cAAc,EACf,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAyB,KAAK,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AASxF;;;;;;;;;GASG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,EAAG,wBAAwB,CAAU;gBACtC,WAAW,EAAE,MAAM;CAMhC;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC;;;OAGG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,yBAAyB,CAAC;CACzD;AAuCD,wBAAgB,mCAAmC,CACjD,IAAI,EAAE,0BAA0B;;;;;;;;;;;GAwEjC"}