@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
@@ -23,7 +23,7 @@
23
23
  * Returns `undefined` for two distinct cases, both of which are
24
24
  * "nothing to enforce" at call sites:
25
25
  *
26
- * - `spec === undefined` — the stack item has no stream contract.
26
+ * - `spec === undefined` — the render has no stream contract.
27
27
  * - `spec.channels[channelName]` is missing — the channel isn't
28
28
  * declared. Callers MUST NOT assume this means "permissive";
29
29
  * rejection is the downstream responsibility of
@@ -37,8 +37,8 @@ import { DEFAULT_STREAM_CHANNEL_COMPLETE, DEFAULT_STREAM_CHANNEL_MODE, DEFAULT_S
37
37
  * (`mode` / `replay` / `complete`) are filled with their locked
38
38
  * defaults.
39
39
  *
40
- * @param spec The active stack item's stream contract, or undefined
41
- * when the item has no `streamSpec` at all.
40
+ * @param spec The active render's stream contract, or undefined
41
+ * when the render has no `streamSpec` at all.
42
42
  * @param channelName The channel name to resolve — typically read
43
43
  * from the outbound envelope's `channel` field.
44
44
  * @returns `ResolvedStreamChannel` when the channel is declared;
@@ -59,6 +59,5 @@ export function resolveStreamChannel(spec, channelName) {
59
59
  complete: entry.complete ?? DEFAULT_STREAM_CHANNEL_COMPLETE,
60
60
  ...(entry.description !== undefined ? { description: entry.description } : {}),
61
61
  ...(entry.example !== undefined ? { example: entry.example } : {}),
62
- ...(entry.tool !== undefined ? { tool: entry.tool } : {}),
63
62
  };
64
63
  }
@@ -1,13 +1,13 @@
1
1
  /**
2
- * Patterns stripped from stringified errors before emission on
3
- * `_ggui:contract-error`. The default set covers the common credential
2
+ * Patterns stripped from stringified errors before they ride a wire
3
+ * frame. The default set covers the common credential
4
4
  * shapes that show up in stack traces by accident (URLs with token query
5
5
  * params, Bearer headers captured by retry libraries, env-var dumps).
6
6
  *
7
7
  * Each regex replaces the matched span with `[REDACTED]`. Replacement is
8
8
  * conservative — we'd rather over-redact than leak. Operators who need
9
- * finer control inject a custom sanitizer via
10
- * `createSessionChannelServer({ sanitizeCausedBy })`.
9
+ * finer control supply a custom {@link SanitizeCausedBy} function (or
10
+ * pass a stricter pattern set to {@link sanitizeCausedBy}).
11
11
  */
12
12
  export declare const DEFAULT_CREDENTIAL_PATTERNS: readonly RegExp[];
13
13
  /** Default max length for a sanitized `causedBy` string. */
@@ -16,7 +16,8 @@ export declare const DEFAULT_CAUSED_BY_MAX_LENGTH = 2048;
16
16
  export declare const TRUNCATION_MARKER = "\n\u2026[truncated]";
17
17
  /**
18
18
  * Sanitize a stringified error (typically `err.stack`) before it's
19
- * written to `ContractErrorPayload.error.causedBy`.
19
+ * written to a wire-visible diagnostic slot (e.g. the `channel_error`
20
+ * frame's `details`).
20
21
  *
21
22
  * Applies every pattern in {@link DEFAULT_CREDENTIAL_PATTERNS} in order,
22
23
  * replacing matches with `[REDACTED]`. If the result exceeds `maxLength`,
@@ -34,11 +35,11 @@ export declare const TRUNCATION_MARKER = "\n\u2026[truncated]";
34
35
  */
35
36
  export declare function sanitizeCausedBy(raw: string, maxLength?: number, patterns?: readonly RegExp[]): string;
36
37
  /**
37
- * Signature of the sanitizer hook operators can inject into
38
- * `createSessionChannelServer`. Receives the raw stringified error
39
- * (typically `err.stack`) and MUST return a safe-to-emit string.
38
+ * Signature of a `causedBy` sanitizer hook. Receives the raw
39
+ * stringified error (typically `err.stack`) and MUST return a
40
+ * safe-to-emit string.
40
41
  *
41
- * Defaults to {@link sanitizeCausedBy} when no override is supplied. A
42
+ * {@link sanitizeCausedBy} is the canonical implementation. A
42
43
  * pass-through function that returns `raw` unchanged is valid but
43
44
  * discouraged — it re-enables the leak this module was added to close.
44
45
  */
@@ -1 +1 @@
1
- {"version":3,"file":"sanitize-error.d.ts","sourceRoot":"","sources":["../../src/validation/sanitize-error.ts"],"names":[],"mappings":"AA0BA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,2BAA2B,EAAE,SAAS,MAAM,EAWxD,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAEjD,yEAAyE;AACzE,eAAO,MAAM,iBAAiB,wBAAmB,CAAC;AAElD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,SAAS,GAAE,MAAqC,EAChD,QAAQ,GAAE,SAAS,MAAM,EAAgC,GACxD,MAAM,CAgBR;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC"}
1
+ {"version":3,"file":"sanitize-error.d.ts","sourceRoot":"","sources":["../../src/validation/sanitize-error.ts"],"names":[],"mappings":"AA0BA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,2BAA2B,EAAE,SAAS,MAAM,EAWxD,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAEjD,yEAAyE;AACzE,eAAO,MAAM,iBAAiB,wBAAmB,CAAC;AAElD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,SAAS,GAAE,MAAqC,EAChD,QAAQ,GAAE,SAAS,MAAM,EAAgC,GACxD,MAAM,CAgBR;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC"}
@@ -1,22 +1,22 @@
1
1
  // packages/protocol/src/validation/sanitize-error.ts
2
2
  //
3
- // Credential-leak sanitizer for `ContractErrorPayload.error.causedBy`.
3
+ // Credential-leak sanitizer for stringified errors bound for the wire.
4
4
  //
5
- // The `causedBy` field on a contract-error envelope carries the
6
- // stringified original error — typically `Error.stack`. Stacks frequently
5
+ // A diagnostic cause string carries the stringified original error —
6
+ // typically `Error.stack`. Stacks frequently
7
7
  // contain URLs with query-param tokens (`?token=...`, `?api_key=...`),
8
8
  // Authorization header values captured by over-eager logging libraries,
9
- // and env-var dumps. The envelope flows on the reserved
10
- // `_ggui:contract-error` channel with `replay: 'all'`, so anything that
11
- // lands in `causedBy` persists in the session ring buffer and is visible
12
- // in operator tools (RenderInspector activity panels). If an operator
13
- // shares a bug report with that data, the credential leaks externally.
9
+ // and env-var dumps. The primary consumer is the live channel's
10
+ // `channel_error` frame: a `POLL_FAILED` emission threads the polled
11
+ // tool's failure into the frame's `details` slot, where it is visible
12
+ // to the subscribed client and in operator tools (RenderInspector
13
+ // activity panels). If an operator shares a bug report with that data,
14
+ // the credential leaks externally.
14
15
  //
15
- // This module's default posture is "sanitize before emission": the
16
- // session-channel router pipes every `err.stack` through
17
- // {@link sanitizeCausedBy} before populating `causedBy`. Operators who
18
- // need stricter sanitization can inject their own function via
19
- // `createSessionChannelServer({ sanitizeCausedBy })`.
16
+ // This module's default posture is "sanitize before emission": every
17
+ // producer pipes the raw `err.stack` through {@link sanitizeCausedBy}
18
+ // before putting it on the wire. Producers that need stricter
19
+ // sanitization substitute their own {@link SanitizeCausedBy} function.
20
20
  //
21
21
  // Scope: this is a DEFENSE-IN-DEPTH belt, not the sole line. Libraries
22
22
  // that handle secrets should already avoid embedding them in error
@@ -24,15 +24,15 @@
24
24
  // opportunistically by code that didn't think about leaking and we'd
25
25
  // rather redact conservatively than ship raw stacks.
26
26
  /**
27
- * Patterns stripped from stringified errors before emission on
28
- * `_ggui:contract-error`. The default set covers the common credential
27
+ * Patterns stripped from stringified errors before they ride a wire
28
+ * frame. The default set covers the common credential
29
29
  * shapes that show up in stack traces by accident (URLs with token query
30
30
  * params, Bearer headers captured by retry libraries, env-var dumps).
31
31
  *
32
32
  * Each regex replaces the matched span with `[REDACTED]`. Replacement is
33
33
  * conservative — we'd rather over-redact than leak. Operators who need
34
- * finer control inject a custom sanitizer via
35
- * `createSessionChannelServer({ sanitizeCausedBy })`.
34
+ * finer control supply a custom {@link SanitizeCausedBy} function (or
35
+ * pass a stricter pattern set to {@link sanitizeCausedBy}).
36
36
  */
37
37
  export const DEFAULT_CREDENTIAL_PATTERNS = [
38
38
  // Bearer / Basic header values. `Bearer <token>` / `Authorization: Basic <base64>`.
@@ -52,7 +52,8 @@ export const DEFAULT_CAUSED_BY_MAX_LENGTH = 2048;
52
52
  export const TRUNCATION_MARKER = '\n…[truncated]';
53
53
  /**
54
54
  * Sanitize a stringified error (typically `err.stack`) before it's
55
- * written to `ContractErrorPayload.error.causedBy`.
55
+ * written to a wire-visible diagnostic slot (e.g. the `channel_error`
56
+ * frame's `details`).
56
57
  *
57
58
  * Applies every pattern in {@link DEFAULT_CREDENTIAL_PATTERNS} in order,
58
59
  * replacing matches with `[REDACTED]`. If the result exceeds `maxLength`,
@@ -131,7 +131,7 @@ export declare class SchemaCompatInvariantError extends Error {
131
131
  * agentCapabilities catalog.
132
132
  *
133
133
  * Slots alongside `assertCrossReferences` + `assertNameInvariants`
134
- * at push time. Different scope from the server-level
134
+ * at render time. Different scope from the server-level
135
135
  * `SchemaCompatError` thrown by `checkRenderSchemaCompat` in
136
136
  * `@ggui-ai/mcp-server`: this check uses ONLY the contract's own
137
137
  * catalog; the server-level check uses the runtime tool registry.
@@ -88,7 +88,7 @@ export function checkActionSchemaCompat(actionSpec, agentCapabilities) {
88
88
  const tool = tools.get(toolName);
89
89
  if (!tool)
90
90
  continue; // CTR_REF_NEXT_STEP covers this
91
- const toolInput = tool.inputSchema;
91
+ const toolInput = tool.toolInfo.inputSchema;
92
92
  if (!toolInput)
93
93
  continue; // catalog entry incomplete — no anchor
94
94
  const actionSchema = entry.schema ?? {
@@ -143,7 +143,7 @@ export function checkStreamSchemaCompat(streamSpec, agentCapabilities) {
143
143
  const tool = tools.get(toolName);
144
144
  if (!tool)
145
145
  continue; // CTR_REF_STREAM_SOURCE covers this
146
- const toolOutput = tool.outputSchema;
146
+ const toolOutput = tool.toolInfo.outputSchema;
147
147
  if (!toolOutput)
148
148
  continue;
149
149
  const channelSchema = entry.schema;
@@ -207,7 +207,7 @@ export class SchemaCompatInvariantError extends Error {
207
207
  * agentCapabilities catalog.
208
208
  *
209
209
  * Slots alongside `assertCrossReferences` + `assertNameInvariants`
210
- * at push time. Different scope from the server-level
210
+ * at render time. Different scope from the server-level
211
211
  * `SchemaCompatError` thrown by `checkRenderSchemaCompat` in
212
212
  * `@ggui-ai/mcp-server`: this check uses ONLY the contract's own
213
213
  * catalog; the server-level check uses the runtime tool registry.
@@ -6,8 +6,8 @@
6
6
  * 2. `actionSpec[*].schema` (optional per entry)
7
7
  * 3. `streamSpec[*].schema`
8
8
  * 4. `contextSpec[*].schema`
9
- * 5. `agentCapabilities.tools[*].inputSchema` (optional per entry)
10
- * 6. `agentCapabilities.tools[*].outputSchema` (optional per entry)
9
+ * 5. `agentCapabilities.tools[*].toolInfo.inputSchema` (required per entry)
10
+ * 6. `agentCapabilities.tools[*].toolInfo.outputSchema` (optional per entry)
11
11
  *
12
12
  * For each present schema, runs `compileForValidation()` from
13
13
  * `ajv-runtime`. Ajv's `strict: true` mode throws on malformed JSON
@@ -40,7 +40,7 @@ export interface SchemaMetaViolation {
40
40
  /**
41
41
  * Typed error for contract schema meta-validation failures. Mirrors
42
42
  * the shape of `CrossReferenceError` / `ContractViolationError` for
43
- * symmetry — push/handshake catch and surface a structured
43
+ * symmetry — render/handshake catch and surface a structured
44
44
  * `contract_schema_invalid` error to the agent.
45
45
  */
46
46
  export declare class ContractSchemaMetaError extends Error {
@@ -50,11 +50,24 @@ export declare class ContractSchemaMetaError extends Error {
50
50
  constructor(violations: readonly SchemaMetaViolation[]);
51
51
  }
52
52
  /**
53
- * Walks the contract's six inner JSON Schema fields and asserts
54
- * each compiles cleanly under Ajv's strict mode. Throws
55
- * {@link ContractSchemaMetaError} on the first push attempt that
56
- * smuggles a malformed schema; collects every offender in one pass
57
- * before throwing so the agent sees the full list.
53
+ * Walks the contract's six inner JSON Schema fields and collects a
54
+ * {@link SchemaMetaViolation} for each that does not compile cleanly
55
+ * under Ajv's strict mode (unknown keyword, missing `items`, a
56
+ * non-schema `properties` value, or a missing `schema:` wrapper). Pure
57
+ * check — returns the full list so callers can either repair (the
58
+ * handshake repair loop) or throw (see {@link assertContractSchemasValid}).
59
+ *
60
+ * This is the inner-schema validity check folded into the unified
61
+ * `validateContract` gate (lint-contract.ts `phaseSchemaMeta`) — the
62
+ * one check the strict linter was previously missing relative to the
63
+ * render/handshake assert set.
64
+ */
65
+ export declare function checkContractSchemasValid(contract: DataContract): SchemaMetaViolation[];
66
+ /**
67
+ * Throwable wrapper around {@link checkContractSchemasValid}. Throws
68
+ * {@link ContractSchemaMetaError} (collecting every malformed schema in
69
+ * one pass) when any inner JSON Schema fails Ajv strict-mode
70
+ * compilation. No-op when all schemas are well-formed.
58
71
  */
59
72
  export declare function assertContractSchemasValid(contract: DataContract): void;
60
73
  //# sourceMappingURL=schema-meta-validation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema-meta-validation.d.ts","sourceRoot":"","sources":["../../src/validation/schema-meta-validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG3D,MAAM,WAAW,mBAAmB;IAClC,sFAAsF;IACtF,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,IAAI,EAAG,yBAAyB,CAAU;IACnD,QAAQ,CAAC,UAAU,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,UAAU,EAAE,SAAS,mBAAmB,EAAE;CAWvD;AAmCD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAuDvE"}
1
+ {"version":3,"file":"schema-meta-validation.d.ts","sourceRoot":"","sources":["../../src/validation/schema-meta-validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG3D,MAAM,WAAW,mBAAmB;IAClC,sFAAsF;IACtF,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,IAAI,EAAG,yBAAyB,CAAU;IACnD,QAAQ,CAAC,UAAU,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,UAAU,EAAE,SAAS,mBAAmB,EAAE;CAWvD;AAmCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,YAAY,GACrB,mBAAmB,EAAE,CAmDvB;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAKvE"}
@@ -6,8 +6,8 @@
6
6
  * 2. `actionSpec[*].schema` (optional per entry)
7
7
  * 3. `streamSpec[*].schema`
8
8
  * 4. `contextSpec[*].schema`
9
- * 5. `agentCapabilities.tools[*].inputSchema` (optional per entry)
10
- * 6. `agentCapabilities.tools[*].outputSchema` (optional per entry)
9
+ * 5. `agentCapabilities.tools[*].toolInfo.inputSchema` (required per entry)
10
+ * 6. `agentCapabilities.tools[*].toolInfo.outputSchema` (optional per entry)
11
11
  *
12
12
  * For each present schema, runs `compileForValidation()` from
13
13
  * `ajv-runtime`. Ajv's `strict: true` mode throws on malformed JSON
@@ -34,7 +34,7 @@ import { compileForValidation } from './ajv-runtime.js';
34
34
  /**
35
35
  * Typed error for contract schema meta-validation failures. Mirrors
36
36
  * the shape of `CrossReferenceError` / `ContractViolationError` for
37
- * symmetry — push/handshake catch and surface a structured
37
+ * symmetry — render/handshake catch and surface a structured
38
38
  * `contract_schema_invalid` error to the agent.
39
39
  */
40
40
  export class ContractSchemaMetaError extends Error {
@@ -81,13 +81,19 @@ function truncate(s, max) {
81
81
  return s.length > max ? `${s.slice(0, max - 1)}…` : s;
82
82
  }
83
83
  /**
84
- * Walks the contract's six inner JSON Schema fields and asserts
85
- * each compiles cleanly under Ajv's strict mode. Throws
86
- * {@link ContractSchemaMetaError} on the first push attempt that
87
- * smuggles a malformed schema; collects every offender in one pass
88
- * before throwing so the agent sees the full list.
84
+ * Walks the contract's six inner JSON Schema fields and collects a
85
+ * {@link SchemaMetaViolation} for each that does not compile cleanly
86
+ * under Ajv's strict mode (unknown keyword, missing `items`, a
87
+ * non-schema `properties` value, or a missing `schema:` wrapper). Pure
88
+ * check — returns the full list so callers can either repair (the
89
+ * handshake repair loop) or throw (see {@link assertContractSchemasValid}).
90
+ *
91
+ * This is the inner-schema validity check folded into the unified
92
+ * `validateContract` gate (lint-contract.ts `phaseSchemaMeta`) — the
93
+ * one check the strict linter was previously missing relative to the
94
+ * render/handshake assert set.
89
95
  */
90
- export function assertContractSchemasValid(contract) {
96
+ export function checkContractSchemasValid(contract) {
91
97
  const violations = [];
92
98
  if (contract.propsSpec?.properties) {
93
99
  for (const [name, entry] of Object.entries(contract.propsSpec.properties)) {
@@ -117,14 +123,22 @@ export function assertContractSchemasValid(contract) {
117
123
  }
118
124
  if (contract.agentCapabilities?.tools) {
119
125
  for (const [name, entry] of Object.entries(contract.agentCapabilities.tools)) {
120
- if (entry.inputSchema) {
121
- tryCompile(`agentCapabilities.tools.${name}.inputSchema`, entry.inputSchema, violations);
122
- }
123
- if (entry.outputSchema) {
124
- tryCompile(`agentCapabilities.tools.${name}.outputSchema`, entry.outputSchema, violations);
126
+ tryCompile(`agentCapabilities.tools.${name}.inputSchema`, entry.toolInfo.inputSchema, violations);
127
+ if (entry.toolInfo.outputSchema) {
128
+ tryCompile(`agentCapabilities.tools.${name}.outputSchema`, entry.toolInfo.outputSchema, violations);
125
129
  }
126
130
  }
127
131
  }
132
+ return violations;
133
+ }
134
+ /**
135
+ * Throwable wrapper around {@link checkContractSchemasValid}. Throws
136
+ * {@link ContractSchemaMetaError} (collecting every malformed schema in
137
+ * one pass) when any inner JSON Schema fails Ajv strict-mode
138
+ * compilation. No-op when all schemas are well-formed.
139
+ */
140
+ export function assertContractSchemasValid(contract) {
141
+ const violations = checkContractSchemasValid(contract);
128
142
  if (violations.length > 0) {
129
143
  throw new ContractSchemaMetaError(violations);
130
144
  }
@@ -3,16 +3,17 @@
3
3
  * schema accepts also pass the `superset` schema?".
4
4
  *
5
5
  * **Why this lives in the protocol package.** The schema-alignment
6
- * contract is enforced at push-time + blueprint-registration; the
7
- * canonical failure is {@link ContractErrorCode}
8
- * `'SCHEMA_MISMATCH_ERROR'` — same envelope shape + channel as every
9
- * other named contract violation. See the schema-compat docstrings
6
+ * contract is enforced at render-time + blueprint-registration; the
7
+ * canonical failure is the named `'SCHEMA_MISMATCH_ERROR'` rejection
8
+ * the push / registration call answers with — fail-loud at
9
+ * declaration time, before a malformed payload reaches the agentic
10
+ * loop. See the schema-compat docstrings
10
11
  * on {@link ActionEntry.schema} and {@link StreamChannelEntry.schema}
11
12
  * for the author-invariant the check enforces.
12
13
  *
13
14
  * **Check points.**
14
15
  *
15
- * - Pre-commit of a `Render` with `actionSpec` / `streamSpec`
16
+ * - Pre-commit of a `GguiSession` with `actionSpec` / `streamSpec`
16
17
  * entries that reference tools: each action's declared schema
17
18
  * MUST be a subset of the tool's inputSchema (what the action
18
19
  * payload is allowed to send ⊆ what the tool accepts). Each
@@ -71,13 +72,13 @@
71
72
  * **Determinism contract.** No randomness, no IO, no thrown
72
73
  * exceptions for normal violations. Every incompatibility is
73
74
  * reported as a {@link SubsetViolation} with enough field-path
74
- * context for the emitted `SCHEMA_MISMATCH_ERROR` to name the
75
+ * context for the `SCHEMA_MISMATCH_ERROR` rejection to name the
75
76
  * mismatch cleanly. Thrown errors are reserved for programmer-
76
77
  * bug conditions (a caller passes `null` where a JsonSchema is
77
78
  * expected).
78
79
  *
79
80
  * @see ./schema-compat-invariants.ts — the protocol-level invariants
80
- * that call this algorithm at push-time.
81
+ * that call this algorithm at render-time.
81
82
  */
82
83
  import type { JsonSchema, JsonValue } from '../types/data-contract.js';
83
84
  /**
@@ -132,7 +133,7 @@ export interface SubsetViolation {
132
133
  * {@link SubsetViolation.superset}. */
133
134
  readonly subset?: string;
134
135
  /** Human-readable summary suitable for inclusion in a
135
- * `SCHEMA_MISMATCH_ERROR` envelope. Producers MAY ignore this
136
+ * `SCHEMA_MISMATCH_ERROR` rejection. Producers MAY ignore this
136
137
  * and render their own message from `path` + `reason` if they
137
138
  * prefer a consistent localized format. */
138
139
  readonly message: string;
@@ -1 +1 @@
1
- {"version":3,"file":"schema-subset.d.ts","sourceRoot":"","sources":["../../src/validation/schema-subset.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAEvE;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,GAC7B,eAAe;AACjB;sDACsD;GACpD,gBAAgB;AAClB;;;;mDAImD;GACjD,iBAAiB;AACnB;sEACsE;GACpE,kBAAkB;AACpB,mCAAmC;GACjC,gBAAgB;AAClB,sEAAsE;GACpE,8BAA8B;AAChC;;mDAEmD;GACjD,aAAa,CAAC;AAElB;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;;OAOG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,6BAA6B;IAC7B,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IACvC;;sDAEkD;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;4CACwC;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;gDAG4C;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,SAAS,eAAe,EAAE,CAAC;CACjD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,UAAU,EACpB,MAAM,EAAE,UAAU,GACjB,kBAAkB,CAiBpB;AAoTD,YAAY,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"schema-subset.d.ts","sourceRoot":"","sources":["../../src/validation/schema-subset.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiFG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAEvE;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,GAC7B,eAAe;AACjB;sDACsD;GACpD,gBAAgB;AAClB;;;;mDAImD;GACjD,iBAAiB;AACnB;sEACsE;GACpE,kBAAkB;AACpB,mCAAmC;GACjC,gBAAgB;AAClB,sEAAsE;GACpE,8BAA8B;AAChC;;mDAEmD;GACjD,aAAa,CAAC;AAElB;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;;OAOG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,6BAA6B;IAC7B,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IACvC;;sDAEkD;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;4CACwC;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;gDAG4C;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,SAAS,eAAe,EAAE,CAAC;CACjD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,UAAU,EACpB,MAAM,EAAE,UAAU,GACjB,kBAAkB,CAiBpB;AAoTD,YAAY,EAAE,SAAS,EAAE,CAAC"}
@@ -25,8 +25,6 @@ export interface DangerousPattern {
25
25
  * These are security-critical — changes here affect every validation consumer.
26
26
  */
27
27
  export declare const DANGEROUS_PATTERNS: DangerousPattern[];
28
- /** Import prefixes that indicate a fullstack UI (requires client bundle). */
29
- export declare const FULLSTACK_IMPORT_PREFIXES: readonly ["@ggui-ai/wire", "@ggui-ai/react", "@app/components"];
30
28
  /**
31
29
  * Classify a component as sandboxed or fullstack based on its imports.
32
30
  *
@@ -36,19 +34,4 @@ export declare const FULLSTACK_IMPORT_PREFIXES: readonly ["@ggui-ai/wire", "@ggu
36
34
  * Works on both source (.tsx) and compiled (.js) code.
37
35
  */
38
36
  export declare function classifyUi(code: string): UiClass;
39
- export interface SecurityCheckResult {
40
- /** True if no dangerous patterns found. */
41
- safe: boolean;
42
- /** List of violations found. */
43
- violations: Array<{
44
- name: string;
45
- suggestion: string;
46
- line?: number;
47
- }>;
48
- }
49
- /**
50
- * Check code for dangerous patterns.
51
- * Works on both source and compiled code.
52
- */
53
- export declare function checkSecurity(code: string): SecurityCheckResult;
54
37
  //# sourceMappingURL=ui-security.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ui-security.d.ts","sourceRoot":"","sources":["../../src/validation/ui-security.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,OAAO,GAAG,WAAW,GAAG,WAAW,CAAC;AAMhD,MAAM,WAAW,gBAAgB;IAC/B,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,EAiFhD,CAAC;AAIF,6EAA6E;AAC7E,eAAO,MAAM,yBAAyB,iEAI5B,CAAC;AAEX;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAUhD;AAUD,MAAM,WAAW,mBAAmB;IAClC,2CAA2C;IAC3C,IAAI,EAAE,OAAO,CAAC;IACd,gCAAgC;IAChC,UAAU,EAAE,KAAK,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;CACJ;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAc/D"}
1
+ {"version":3,"file":"ui-security.d.ts","sourceRoot":"","sources":["../../src/validation/ui-security.ts"],"names":[],"mappings":"AAkBA;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,OAAO,GAAG,WAAW,GAAG,WAAW,CAAC;AAMhD,MAAM,WAAW,gBAAgB;IAC/B,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,EAiFhD,CAAC;AAcF;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAUhD"}
@@ -2,9 +2,13 @@
2
2
  //
3
3
  // Shared UI security validation — single source of truth for dangerous
4
4
  // patterns and UI classification. Used by:
5
- // - core/src/tools/validation.ts (generator pipeline)
6
- // - core/src/validation/ui-compiler.ts (CLI compiler)
7
- // - cloud/amplify/functions/rest-api/cli-api/ui-register-handler.ts (register endpoint)
5
+ // - @ggui-ai/ui-gen src/validation/component-detailed.ts
6
+ // (validateComponentDetailed — the generator/compiler validation
7
+ // pipeline, consumes DANGEROUS_PATTERNS)
8
+ // - @ggui-ai/ui-gen src/validation/ui-compiler.ts (standalone
9
+ // compileUi/validateUi — consumes classifyUi + UiClass)
10
+ // - @ggui-ai/project-config src/ui-manifest.ts (UiManifest schema —
11
+ // validates against the UiClass vocabulary owned here)
8
12
  //
9
13
  // This module is PUBLIC (@ggui-ai/protocol) — keep it dependency-free.
10
14
  /**
@@ -94,8 +98,11 @@ export const DANGEROUS_PATTERNS = [
94
98
  },
95
99
  ];
96
100
  // ── UI Classification ───────────────────────────────────────────────
97
- /** Import prefixes that indicate a fullstack UI (requires client bundle). */
98
- export const FULLSTACK_IMPORT_PREFIXES = [
101
+ /**
102
+ * Import prefixes that indicate a fullstack UI (requires client bundle).
103
+ * Internal input of {@link classifyUi} — not part of the published API.
104
+ */
105
+ const FULLSTACK_IMPORT_PREFIXES = [
99
106
  '@ggui-ai/wire',
100
107
  '@ggui-ai/react',
101
108
  '@app/components',
@@ -119,20 +126,8 @@ export function classifyUi(code) {
119
126
  }
120
127
  return 'sandboxed';
121
128
  }
122
- /**
123
- * Check code for dangerous patterns.
124
- * Works on both source and compiled code.
125
- */
126
- export function checkSecurity(code) {
127
- const violations = [];
128
- for (const { pattern, name, suggestion } of DANGEROUS_PATTERNS) {
129
- // Reset lastIndex for global regexes
130
- const re = new RegExp(pattern.source, pattern.flags);
131
- const match = re.exec(code);
132
- if (match) {
133
- const line = code.substring(0, match.index).split('\n').length;
134
- violations.push({ name, suggestion, line });
135
- }
136
- }
137
- return { safe: violations.length === 0, violations };
138
- }
129
+ // ── Content Hash ────────────────────────────────────────────────────
130
+ //
131
+ // Moved to `./content-hash` because it depends on `node:crypto`. Server-
132
+ // only callers import it via `@ggui-ai/protocol/content-hash` — see that
133
+ // file's header for rationale.
@@ -33,7 +33,7 @@
33
33
  *
34
34
  * **Intended call sites.**
35
35
  *
36
- * - Push-time + blueprint-registration schema-compat checks in
36
+ * - render-time + blueprint-registration schema-compat checks in
37
37
  * `@ggui-ai/mcp-server`: a mount-registered tool handler exposes
38
38
  * its `inputSchema` as a {@link ZodRawShape}; wrapping it in
39
39
  * `z.object(shape)` and converting gives the JsonSchema that
@@ -1 +1 @@
1
- {"version":3,"file":"zod-to-json-schema.d.ts","sourceRoot":"","sources":["../../src/validation/zod-to-json-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,OAAO,EAAK,KAAK,WAAW,EAAE,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,GAAG,UAAU,CAQxE"}
1
+ {"version":3,"file":"zod-to-json-schema.d.ts","sourceRoot":"","sources":["../../src/validation/zod-to-json-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,OAAO,EAAK,KAAK,WAAW,EAAE,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAG5D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,GAAG,UAAU,CAQxE"}
@@ -33,7 +33,7 @@
33
33
  *
34
34
  * **Intended call sites.**
35
35
  *
36
- * - Push-time + blueprint-registration schema-compat checks in
36
+ * - render-time + blueprint-registration schema-compat checks in
37
37
  * `@ggui-ai/mcp-server`: a mount-registered tool handler exposes
38
38
  * its `inputSchema` as a {@link ZodRawShape}; wrapping it in
39
39
  * `z.object(shape)` and converting gives the JsonSchema that
@@ -44,6 +44,7 @@
44
44
  * @see ./schema-subset.ts
45
45
  */
46
46
  import { z } from 'zod';
47
+ import { isRecord } from './is-record.js';
47
48
  /**
48
49
  * Convert a zod schema (or raw shape) to a {@link JsonSchema} suitable
49
50
  * for the subset algorithm.
@@ -78,13 +79,13 @@ export function zodToJsonSchema(input) {
78
79
  function normalize(value) {
79
80
  if (Array.isArray(value))
80
81
  return value.map(normalize);
81
- if (value === null || typeof value !== 'object')
82
+ if (!isRecord(value))
82
83
  return value;
83
84
  const out = {};
84
85
  for (const [key, v] of Object.entries(value)) {
85
86
  if (key === '$schema')
86
87
  continue;
87
- if (key === 'properties' && v !== null && typeof v === 'object') {
88
+ if (key === 'properties' && isRecord(v)) {
88
89
  const props = {};
89
90
  for (const [pkey, pval] of Object.entries(v)) {
90
91
  props[pkey] = normalize(pval);