@terreno/blocks 57.10.1

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 (237) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +62 -0
  3. package/biome.jsonc +18 -0
  4. package/bunfig.toml +6 -0
  5. package/dist/asks/errors.d.ts +77 -0
  6. package/dist/asks/errors.js +364 -0
  7. package/dist/asks/files.d.ts +53 -0
  8. package/dist/asks/files.js +171 -0
  9. package/dist/asks/formValues.d.ts +32 -0
  10. package/dist/asks/formValues.js +229 -0
  11. package/dist/asks/headless.d.ts +227 -0
  12. package/dist/asks/headless.js +94 -0
  13. package/dist/asks/jsonSchema.d.ts +6 -0
  14. package/dist/asks/jsonSchema.js +62 -0
  15. package/dist/asks/limits.d.ts +58 -0
  16. package/dist/asks/limits.js +61 -0
  17. package/dist/asks/prompt.d.ts +10 -0
  18. package/dist/asks/prompt.js +144 -0
  19. package/dist/asks/schema.d.ts +826 -0
  20. package/dist/asks/schema.js +864 -0
  21. package/dist/asks/simpleCard.d.ts +85 -0
  22. package/dist/asks/simpleCard.js +279 -0
  23. package/dist/asks/validateInput.d.ts +13 -0
  24. package/dist/asks/validateInput.js +19 -0
  25. package/dist/asks/validateResponse.d.ts +13 -0
  26. package/dist/asks/validateResponse.js +278 -0
  27. package/dist/cli.d.ts +11 -0
  28. package/dist/cli.js +58 -0
  29. package/dist/errors.d.ts +51 -0
  30. package/dist/errors.js +106 -0
  31. package/dist/index.d.ts +31 -0
  32. package/dist/index.js +111 -0
  33. package/dist/jsonSchema.d.ts +5 -0
  34. package/dist/jsonSchema.js +12 -0
  35. package/dist/limits.d.ts +27 -0
  36. package/dist/limits.js +30 -0
  37. package/dist/lint.d.ts +21 -0
  38. package/dist/lint.js +388 -0
  39. package/dist/parse.d.ts +16 -0
  40. package/dist/parse.js +95 -0
  41. package/dist/parsePartial.d.ts +12 -0
  42. package/dist/parsePartial.js +105 -0
  43. package/dist/prompt.d.ts +9 -0
  44. package/dist/prompt.js +95 -0
  45. package/dist/schema.d.ts +199 -0
  46. package/dist/schema.js +277 -0
  47. package/dist/validate.d.ts +17 -0
  48. package/dist/validate.js +331 -0
  49. package/package.json +60 -0
  50. package/schemas/pendingAsksResponse.schema.json +195 -0
  51. package/schemas/simpleCard.schema.json +135 -0
  52. package/schemas/turnRequest.schema.json +108 -0
  53. package/schemas/turnResponse.schema.json +204 -0
  54. package/scripts/writeJsonSchemas.ts +11 -0
  55. package/src/asks/docParity.test.ts +65 -0
  56. package/src/asks/errors.test.ts +250 -0
  57. package/src/asks/errors.ts +449 -0
  58. package/src/asks/files.test.ts +294 -0
  59. package/src/asks/files.ts +216 -0
  60. package/src/asks/fixtures/invalid/choice-blank-text.json +20 -0
  61. package/src/asks/fixtures/invalid/choice-default-not-in-options.json +13 -0
  62. package/src/asks/fixtures/invalid/choice-default-selects-two.json +16 -0
  63. package/src/asks/fixtures/invalid/choice-description-too-long.json +24 -0
  64. package/src/asks/fixtures/invalid/choice-duplicate-ids.json +17 -0
  65. package/src/asks/fixtures/invalid/choice-label-too-long.json +23 -0
  66. package/src/asks/fixtures/invalid/choice-many-bounds-not-whole.json +17 -0
  67. package/src/asks/fixtures/invalid/choice-many-bounds-out-of-range.json +17 -0
  68. package/src/asks/fixtures/invalid/choice-many-default-duplicate.json +17 -0
  69. package/src/asks/fixtures/invalid/choice-many-default-too-many.json +15 -0
  70. package/src/asks/fixtures/invalid/choice-many-max-above-options.json +14 -0
  71. package/src/asks/fixtures/invalid/choice-many-min-above-choices.json +13 -0
  72. package/src/asks/fixtures/invalid/choice-many-min-above-max.json +15 -0
  73. package/src/asks/fixtures/invalid/choice-missing-required.json +14 -0
  74. package/src/asks/fixtures/invalid/choice-mixed-errors.json +19 -0
  75. package/src/asks/fixtures/invalid/choice-not-an-object.json +5 -0
  76. package/src/asks/fixtures/invalid/choice-one-with-many-fields.json +19 -0
  77. package/src/asks/fixtures/invalid/choice-option-id-format.json +35 -0
  78. package/src/asks/fixtures/invalid/choice-options-not-objects.json +12 -0
  79. package/src/asks/fixtures/invalid/choice-other-label-too-long.json +25 -0
  80. package/src/asks/fixtures/invalid/choice-other-label-without-allow-other.json +14 -0
  81. package/src/asks/fixtures/invalid/choice-prompt-empty.json +12 -0
  82. package/src/asks/fixtures/invalid/choice-prompt-too-long.json +23 -0
  83. package/src/asks/fixtures/invalid/choice-select-unknown.json +12 -0
  84. package/src/asks/fixtures/invalid/choice-submit-label-too-long.json +13 -0
  85. package/src/asks/fixtures/invalid/choice-title-too-long.json +24 -0
  86. package/src/asks/fixtures/invalid/choice-too-few-options.json +9 -0
  87. package/src/asks/fixtures/invalid/choice-too-many-options.json +219 -0
  88. package/src/asks/fixtures/invalid/choice-unknown-key-option.json +15 -0
  89. package/src/asks/fixtures/invalid/choice-unknown-key-root.json +13 -0
  90. package/src/asks/fixtures/invalid/choice-wrong-types.json +16 -0
  91. package/src/asks/fixtures/invalid/confirm-emoji-label-too-long.json +13 -0
  92. package/src/asks/fixtures/invalid/confirm-label-too-long.json +14 -0
  93. package/src/asks/fixtures/invalid/confirm-labels-alike-after-trim.json +14 -0
  94. package/src/asks/fixtures/invalid/confirm-labels-alike.json +13 -0
  95. package/src/asks/fixtures/invalid/confirm-missing-prompt-blank-label.json +16 -0
  96. package/src/asks/fixtures/invalid/confirm-unknown-keys.json +23 -0
  97. package/src/asks/fixtures/invalid/confirm-wrong-types.json +18 -0
  98. package/src/asks/fixtures/invalid/files-accept-duplicate.json +13 -0
  99. package/src/asks/fixtures/invalid/files-accept-empty.json +13 -0
  100. package/src/asks/fixtures/invalid/files-accept-unknown.json +13 -0
  101. package/src/asks/fixtures/invalid/files-counts-out-of-range.json +19 -0
  102. package/src/asks/fixtures/invalid/files-min-above-max.json +15 -0
  103. package/src/asks/fixtures/invalid/files-missing-accept-unknown-key.json +17 -0
  104. package/src/asks/fixtures/invalid/form-default-bad-format.json +40 -0
  105. package/src/asks/fixtures/invalid/form-default-invalid-date.json +40 -0
  106. package/src/asks/fixtures/invalid/form-default-not-in-options.json +58 -0
  107. package/src/asks/fixtures/invalid/form-default-out-of-range.json +33 -0
  108. package/src/asks/fixtures/invalid/form-default-text-bounds.json +42 -0
  109. package/src/asks/fixtures/invalid/form-default-wrong-type.json +30 -0
  110. package/src/asks/fixtures/invalid/form-duplicate-field-ids.json +24 -0
  111. package/src/asks/fixtures/invalid/form-field-id-format.json +19 -0
  112. package/src/asks/fixtures/invalid/form-field-text-limits.json +33 -0
  113. package/src/asks/fixtures/invalid/form-keys-of-another-type.json +39 -0
  114. package/src/asks/fixtures/invalid/form-length-above-cap.json +30 -0
  115. package/src/asks/fixtures/invalid/form-min-above-max.json +32 -0
  116. package/src/asks/fixtures/invalid/form-no-fields.json +13 -0
  117. package/src/asks/fixtures/invalid/form-select-options.json +44 -0
  118. package/src/asks/fixtures/invalid/form-too-many-fields.json +59 -0
  119. package/src/asks/fixtures/invalid/form-unknown-field-type.json +27 -0
  120. package/src/asks/fixtures/invalid/markdown-bounds-out-of-range.json +18 -0
  121. package/src/asks/fixtures/invalid/markdown-initial-above-cap.json +13 -0
  122. package/src/asks/fixtures/invalid/markdown-max-above-cap.json +13 -0
  123. package/src/asks/fixtures/invalid/markdown-min-above-cap.json +13 -0
  124. package/src/asks/fixtures/invalid/markdown-min-above-max.json +14 -0
  125. package/src/asks/fixtures/invalid/markdown-placeholder-too-long.json +13 -0
  126. package/src/asks/fixtures/invalid/markdown-wrong-types-unknown-key.json +27 -0
  127. package/src/asks/fixtures/valid/choice-emoji-label-cut.json +32 -0
  128. package/src/asks/fixtures/valid/choice-labels-collide-after-cut.json +21 -0
  129. package/src/asks/fixtures/valid/choice-long-text-cut.json +41 -0
  130. package/src/asks/fixtures/valid/choice-many-default-below-min.json +24 -0
  131. package/src/asks/fixtures/valid/choice-many-every-choice-with-other.json +24 -0
  132. package/src/asks/fixtures/valid/choice-many-no-default.json +21 -0
  133. package/src/asks/fixtures/valid/choice-many-optional-no-buttons.json +20 -0
  134. package/src/asks/fixtures/valid/choice-many-options-default-label-collides.json +23 -0
  135. package/src/asks/fixtures/valid/choice-many-options-no-buttons.json +21 -0
  136. package/src/asks/fixtures/valid/choice-many-options-no-default.json +22 -0
  137. package/src/asks/fixtures/valid/choice-many-options-with-default.json +30 -0
  138. package/src/asks/fixtures/valid/choice-many-required-with-default.json +29 -0
  139. package/src/asks/fixtures/valid/choice-many-single-pick-or-other.json +29 -0
  140. package/src/asks/fixtures/valid/choice-many-toppings-with-default.json +36 -0
  141. package/src/asks/fixtures/valid/choice-max-limits.json +245 -0
  142. package/src/asks/fixtures/valid/choice-plan-with-default.json +42 -0
  143. package/src/asks/fixtures/valid/choice-two-options-no-decline.json +32 -0
  144. package/src/asks/fixtures/valid/choice-two-options.json +32 -0
  145. package/src/asks/fixtures/valid/confirm-allow-decline.json +40 -0
  146. package/src/asks/fixtures/valid/confirm-default-labels.json +36 -0
  147. package/src/asks/fixtures/valid/confirm-destructive-delete.json +41 -0
  148. package/src/asks/fixtures/valid/confirm-emoji-labels.json +38 -0
  149. package/src/asks/fixtures/valid/confirm-long-text-cut.json +40 -0
  150. package/src/asks/fixtures/valid/files-every-type.json +28 -0
  151. package/src/asks/fixtures/valid/files-one-csv-no-decline.json +16 -0
  152. package/src/asks/fixtures/valid/files-receipt-photos.json +24 -0
  153. package/src/asks/fixtures/valid/form-boolean-newsletter.json +30 -0
  154. package/src/asks/fixtures/valid/form-date-due.json +44 -0
  155. package/src/asks/fixtures/valid/form-datetime-meeting.json +44 -0
  156. package/src/asks/fixtures/valid/form-datetime-minutes-offset.json +44 -0
  157. package/src/asks/fixtures/valid/form-eight-fields.json +71 -0
  158. package/src/asks/fixtures/valid/form-email-contact.json +44 -0
  159. package/src/asks/fixtures/valid/form-invoice-details.json +68 -0
  160. package/src/asks/fixtures/valid/form-multiselect-channels.json +64 -0
  161. package/src/asks/fixtures/valid/form-number-budget.json +45 -0
  162. package/src/asks/fixtures/valid/form-phone-callback.json +44 -0
  163. package/src/asks/fixtures/valid/form-select-shipping.json +58 -0
  164. package/src/asks/fixtures/valid/form-text-required-default.json +47 -0
  165. package/src/asks/fixtures/valid/form-textarea-notes.json +23 -0
  166. package/src/asks/fixtures/valid/form-time-reminder.json +44 -0
  167. package/src/asks/fixtures/valid/form-url-website.json +30 -0
  168. package/src/asks/fixtures/valid/markdown-announcement-draft.json +39 -0
  169. package/src/asks/fixtures/valid/markdown-empty-draft.json +34 -0
  170. package/src/asks/fixtures/valid/markdown-initial-blank-below-min.json +24 -0
  171. package/src/asks/fixtures/valid/markdown-initial-over-max.json +24 -0
  172. package/src/asks/fixtures/valid/markdown-long-text-cut.json +37 -0
  173. package/src/asks/fixtures/valid/markdown-no-decline.json +28 -0
  174. package/src/asks/fixtures/valid/markdown-no-initial-with-min.json +25 -0
  175. package/src/asks/formValues.ts +320 -0
  176. package/src/asks/headless.test.ts +146 -0
  177. package/src/asks/headless.ts +130 -0
  178. package/src/asks/jsonSchema.test.ts +171 -0
  179. package/src/asks/jsonSchema.ts +89 -0
  180. package/src/asks/limits.ts +58 -0
  181. package/src/asks/prompt.test.ts +200 -0
  182. package/src/asks/prompt.ts +173 -0
  183. package/src/asks/schema.test.ts +198 -0
  184. package/src/asks/schema.ts +1203 -0
  185. package/src/asks/simpleCard.test.ts +998 -0
  186. package/src/asks/simpleCard.ts +341 -0
  187. package/src/asks/validateInput.test.ts +875 -0
  188. package/src/asks/validateInput.ts +24 -0
  189. package/src/asks/validateResponse.test.ts +740 -0
  190. package/src/asks/validateResponse.ts +341 -0
  191. package/src/blocksDocParity.test.ts +21 -0
  192. package/src/cli.test.ts +134 -0
  193. package/src/cli.ts +65 -0
  194. package/src/display.test.ts +68 -0
  195. package/src/errors.test.ts +29 -0
  196. package/src/errors.ts +125 -0
  197. package/src/fixtures/invalid/column-not-found.yaml +14 -0
  198. package/src/fixtures/invalid/column-type.yaml +14 -0
  199. package/src/fixtures/invalid/dataset-not-found.yaml +7 -0
  200. package/src/fixtures/invalid/dataset-too-large.yaml +20 -0
  201. package/src/fixtures/invalid/depth-exceeded.yaml +10 -0
  202. package/src/fixtures/invalid/duplicate-id.yaml +6 -0
  203. package/src/fixtures/invalid/invalid-enum.yaml +5 -0
  204. package/src/fixtures/invalid/key-order.yaml +4 -0
  205. package/src/fixtures/invalid/missing-required.yaml +3 -0
  206. package/src/fixtures/invalid/not-a-document.txt +1 -0
  207. package/src/fixtures/invalid/row-arity.yaml +11 -0
  208. package/src/fixtures/invalid/select-target.yaml +12 -0
  209. package/src/fixtures/invalid/table-too-wide.yaml +9 -0
  210. package/src/fixtures/invalid/too-many-points.yaml +8 -0
  211. package/src/fixtures/invalid/unknown-key.yaml +5 -0
  212. package/src/fixtures/invalid/unsupported-version.yaml +4 -0
  213. package/src/fixtures/invalid/yaml-anchor.yaml +6 -0
  214. package/src/fixtures/partial/cut-after-divider.yaml +5 -0
  215. package/src/fixtures/valid/actions.yaml +32 -0
  216. package/src/fixtures/valid/chart.yaml +20 -0
  217. package/src/fixtures/valid/layout.yaml +26 -0
  218. package/src/fixtures/valid/prose.yaml +4 -0
  219. package/src/html.test.ts +52 -0
  220. package/src/index.test.ts +114 -0
  221. package/src/index.ts +175 -0
  222. package/src/jsonSchema.test.ts +33 -0
  223. package/src/jsonSchema.ts +11 -0
  224. package/src/limits.ts +27 -0
  225. package/src/lint.test.ts +289 -0
  226. package/src/lint.ts +484 -0
  227. package/src/parse.test.ts +281 -0
  228. package/src/parse.ts +104 -0
  229. package/src/parsePartial.test.ts +53 -0
  230. package/src/parsePartial.ts +116 -0
  231. package/src/prompt.test.ts +24 -0
  232. package/src/prompt.ts +104 -0
  233. package/src/schema.ts +509 -0
  234. package/src/tests/askFixtures.ts +40 -0
  235. package/src/validate.perf.test.ts +43 -0
  236. package/src/validate.ts +369 -0
  237. package/tsconfig.json +18 -0
package/dist/index.js ADDED
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.filesAskInputSchema = exports.filesAnswerSchema = exports.FORM_FIELD_TYPES = exports.confirmButtonLabels = exports.confirmAskResponseSchema = exports.confirmAskInputSchema = exports.confirmAnswerSchema = exports.compactChoiceAskInputSchema = exports.compactAskInputSchemas = exports.choiceSelectionBounds = exports.choiceOptionSchema = exports.choiceAskResponseSchema = exports.choiceAskInputSchema = exports.choiceAnswerSchema = exports.COMPACT_ASK_KINDS = exports.CHOICE_SELECT_MODES = exports.askResponseSchema = exports.askOutputSchemas = exports.askKindsForSurface = exports.askInputSchemas = exports.askInputSchemaFor = exports.askFileRefSchema = exports.askDeclineResponseSchema = exports.askCancelResponseSchema = exports.askAllowsDecline = exports.askAcceptResponseSchema = exports.ASK_SURFACES = exports.ASK_KINDS = exports.ASK_CANCEL_REASONS = exports.askPromptSection = exports.ASK_LIMITS = exports.askJsonSchemas = exports.turnResultSchema = exports.turnRequestSchema = exports.pendingAskSummarySchema = exports.pendingAskListSchema = exports.pendingAskListItemSchema = exports.askSurfaceSchema = exports.askResponseWithToolCallIdSchema = exports.formTextMaxLength = exports.formDefaultValues = exports.sniffFileBytes = exports.parseAskDataUrl = exports.isTextFileMimeType = exports.fileNotOwnedError = exports.checkAskFileBytes = exports.acceptedFileMimeTypes = exports.ASK_FILE_ACCEPT_MIME_TYPES = exports.ASK_FILE_ACCEPT = exports.ASK_ERROR_CODES = void 0;
4
+ exports.validateBlocks = exports.wrapAsTextDocument = exports.METRIC_TRENDS = exports.HTML_HEIGHTS = exports.HEADING_SIZES = exports.DATASET_GRAINS = exports.DATASET_COLUMN_TYPES = exports.CHART_KINDS = exports.CHART_HEIGHTS = exports.CALLOUT_STATUSES = exports.blocksSchema = exports.BUTTON_VARIANTS = exports.BADGE_STATUSES = exports.blocksPromptSection = exports.parseBlocksPartial = exports.parseBlocks = exports.BLOCK_LIMITS = exports.blocksJsonSchema = exports.BLOCK_WARNING_CODES = exports.BLOCK_ERROR_CODES = exports.validateAskResponse = exports.validateAskInput = exports.toSimpleCard = exports.simpleCardSchema = exports.simpleCardButtonSchema = exports.SIMPLE_CARD_BUTTON_STYLES = exports.resolveButtonAnswer = exports.markdownLengthBounds = exports.markdownAskResponseSchema = exports.markdownAskInputSchema = exports.markdownAnswerSchema = exports.isCompactAskKind = exports.formFieldSchema = exports.formAskResponseSchema = exports.formAskInputSchema = exports.formAnswerSchema = exports.filesCountBounds = exports.filesAskResponseSchema = void 0;
5
+ var errors_1 = require("./asks/errors");
6
+ Object.defineProperty(exports, "ASK_ERROR_CODES", { enumerable: true, get: function () { return errors_1.ASK_ERROR_CODES; } });
7
+ var files_1 = require("./asks/files");
8
+ Object.defineProperty(exports, "ASK_FILE_ACCEPT", { enumerable: true, get: function () { return files_1.ASK_FILE_ACCEPT; } });
9
+ Object.defineProperty(exports, "ASK_FILE_ACCEPT_MIME_TYPES", { enumerable: true, get: function () { return files_1.ASK_FILE_ACCEPT_MIME_TYPES; } });
10
+ Object.defineProperty(exports, "acceptedFileMimeTypes", { enumerable: true, get: function () { return files_1.acceptedFileMimeTypes; } });
11
+ Object.defineProperty(exports, "checkAskFileBytes", { enumerable: true, get: function () { return files_1.checkAskFileBytes; } });
12
+ Object.defineProperty(exports, "fileNotOwnedError", { enumerable: true, get: function () { return files_1.fileNotOwnedError; } });
13
+ Object.defineProperty(exports, "isTextFileMimeType", { enumerable: true, get: function () { return files_1.isTextFileMimeType; } });
14
+ Object.defineProperty(exports, "parseAskDataUrl", { enumerable: true, get: function () { return files_1.parseAskDataUrl; } });
15
+ Object.defineProperty(exports, "sniffFileBytes", { enumerable: true, get: function () { return files_1.sniffFileBytes; } });
16
+ var formValues_1 = require("./asks/formValues");
17
+ Object.defineProperty(exports, "formDefaultValues", { enumerable: true, get: function () { return formValues_1.formDefaultValues; } });
18
+ Object.defineProperty(exports, "formTextMaxLength", { enumerable: true, get: function () { return formValues_1.formTextMaxLength; } });
19
+ var headless_1 = require("./asks/headless");
20
+ Object.defineProperty(exports, "askResponseWithToolCallIdSchema", { enumerable: true, get: function () { return headless_1.askResponseWithToolCallIdSchema; } });
21
+ Object.defineProperty(exports, "askSurfaceSchema", { enumerable: true, get: function () { return headless_1.askSurfaceSchema; } });
22
+ Object.defineProperty(exports, "pendingAskListItemSchema", { enumerable: true, get: function () { return headless_1.pendingAskListItemSchema; } });
23
+ Object.defineProperty(exports, "pendingAskListSchema", { enumerable: true, get: function () { return headless_1.pendingAskListSchema; } });
24
+ Object.defineProperty(exports, "pendingAskSummarySchema", { enumerable: true, get: function () { return headless_1.pendingAskSummarySchema; } });
25
+ Object.defineProperty(exports, "turnRequestSchema", { enumerable: true, get: function () { return headless_1.turnRequestSchema; } });
26
+ Object.defineProperty(exports, "turnResultSchema", { enumerable: true, get: function () { return headless_1.turnResultSchema; } });
27
+ var jsonSchema_1 = require("./asks/jsonSchema");
28
+ Object.defineProperty(exports, "askJsonSchemas", { enumerable: true, get: function () { return jsonSchema_1.askJsonSchemas; } });
29
+ var limits_1 = require("./asks/limits");
30
+ Object.defineProperty(exports, "ASK_LIMITS", { enumerable: true, get: function () { return limits_1.ASK_LIMITS; } });
31
+ var prompt_1 = require("./asks/prompt");
32
+ Object.defineProperty(exports, "askPromptSection", { enumerable: true, get: function () { return prompt_1.askPromptSection; } });
33
+ var schema_1 = require("./asks/schema");
34
+ Object.defineProperty(exports, "ASK_CANCEL_REASONS", { enumerable: true, get: function () { return schema_1.ASK_CANCEL_REASONS; } });
35
+ Object.defineProperty(exports, "ASK_KINDS", { enumerable: true, get: function () { return schema_1.ASK_KINDS; } });
36
+ Object.defineProperty(exports, "ASK_SURFACES", { enumerable: true, get: function () { return schema_1.ASK_SURFACES; } });
37
+ Object.defineProperty(exports, "askAcceptResponseSchema", { enumerable: true, get: function () { return schema_1.askAcceptResponseSchema; } });
38
+ Object.defineProperty(exports, "askAllowsDecline", { enumerable: true, get: function () { return schema_1.askAllowsDecline; } });
39
+ Object.defineProperty(exports, "askCancelResponseSchema", { enumerable: true, get: function () { return schema_1.askCancelResponseSchema; } });
40
+ Object.defineProperty(exports, "askDeclineResponseSchema", { enumerable: true, get: function () { return schema_1.askDeclineResponseSchema; } });
41
+ Object.defineProperty(exports, "askFileRefSchema", { enumerable: true, get: function () { return schema_1.askFileRefSchema; } });
42
+ Object.defineProperty(exports, "askInputSchemaFor", { enumerable: true, get: function () { return schema_1.askInputSchemaFor; } });
43
+ Object.defineProperty(exports, "askInputSchemas", { enumerable: true, get: function () { return schema_1.askInputSchemas; } });
44
+ Object.defineProperty(exports, "askKindsForSurface", { enumerable: true, get: function () { return schema_1.askKindsForSurface; } });
45
+ Object.defineProperty(exports, "askOutputSchemas", { enumerable: true, get: function () { return schema_1.askOutputSchemas; } });
46
+ Object.defineProperty(exports, "askResponseSchema", { enumerable: true, get: function () { return schema_1.askResponseSchema; } });
47
+ Object.defineProperty(exports, "CHOICE_SELECT_MODES", { enumerable: true, get: function () { return schema_1.CHOICE_SELECT_MODES; } });
48
+ Object.defineProperty(exports, "COMPACT_ASK_KINDS", { enumerable: true, get: function () { return schema_1.COMPACT_ASK_KINDS; } });
49
+ Object.defineProperty(exports, "choiceAnswerSchema", { enumerable: true, get: function () { return schema_1.choiceAnswerSchema; } });
50
+ Object.defineProperty(exports, "choiceAskInputSchema", { enumerable: true, get: function () { return schema_1.choiceAskInputSchema; } });
51
+ Object.defineProperty(exports, "choiceAskResponseSchema", { enumerable: true, get: function () { return schema_1.choiceAskResponseSchema; } });
52
+ Object.defineProperty(exports, "choiceOptionSchema", { enumerable: true, get: function () { return schema_1.choiceOptionSchema; } });
53
+ Object.defineProperty(exports, "choiceSelectionBounds", { enumerable: true, get: function () { return schema_1.choiceSelectionBounds; } });
54
+ Object.defineProperty(exports, "compactAskInputSchemas", { enumerable: true, get: function () { return schema_1.compactAskInputSchemas; } });
55
+ Object.defineProperty(exports, "compactChoiceAskInputSchema", { enumerable: true, get: function () { return schema_1.compactChoiceAskInputSchema; } });
56
+ Object.defineProperty(exports, "confirmAnswerSchema", { enumerable: true, get: function () { return schema_1.confirmAnswerSchema; } });
57
+ Object.defineProperty(exports, "confirmAskInputSchema", { enumerable: true, get: function () { return schema_1.confirmAskInputSchema; } });
58
+ Object.defineProperty(exports, "confirmAskResponseSchema", { enumerable: true, get: function () { return schema_1.confirmAskResponseSchema; } });
59
+ Object.defineProperty(exports, "confirmButtonLabels", { enumerable: true, get: function () { return schema_1.confirmButtonLabels; } });
60
+ Object.defineProperty(exports, "FORM_FIELD_TYPES", { enumerable: true, get: function () { return schema_1.FORM_FIELD_TYPES; } });
61
+ Object.defineProperty(exports, "filesAnswerSchema", { enumerable: true, get: function () { return schema_1.filesAnswerSchema; } });
62
+ Object.defineProperty(exports, "filesAskInputSchema", { enumerable: true, get: function () { return schema_1.filesAskInputSchema; } });
63
+ Object.defineProperty(exports, "filesAskResponseSchema", { enumerable: true, get: function () { return schema_1.filesAskResponseSchema; } });
64
+ Object.defineProperty(exports, "filesCountBounds", { enumerable: true, get: function () { return schema_1.filesCountBounds; } });
65
+ Object.defineProperty(exports, "formAnswerSchema", { enumerable: true, get: function () { return schema_1.formAnswerSchema; } });
66
+ Object.defineProperty(exports, "formAskInputSchema", { enumerable: true, get: function () { return schema_1.formAskInputSchema; } });
67
+ Object.defineProperty(exports, "formAskResponseSchema", { enumerable: true, get: function () { return schema_1.formAskResponseSchema; } });
68
+ Object.defineProperty(exports, "formFieldSchema", { enumerable: true, get: function () { return schema_1.formFieldSchema; } });
69
+ Object.defineProperty(exports, "isCompactAskKind", { enumerable: true, get: function () { return schema_1.isCompactAskKind; } });
70
+ Object.defineProperty(exports, "markdownAnswerSchema", { enumerable: true, get: function () { return schema_1.markdownAnswerSchema; } });
71
+ Object.defineProperty(exports, "markdownAskInputSchema", { enumerable: true, get: function () { return schema_1.markdownAskInputSchema; } });
72
+ Object.defineProperty(exports, "markdownAskResponseSchema", { enumerable: true, get: function () { return schema_1.markdownAskResponseSchema; } });
73
+ Object.defineProperty(exports, "markdownLengthBounds", { enumerable: true, get: function () { return schema_1.markdownLengthBounds; } });
74
+ var simpleCard_1 = require("./asks/simpleCard");
75
+ Object.defineProperty(exports, "resolveButtonAnswer", { enumerable: true, get: function () { return simpleCard_1.resolveButtonAnswer; } });
76
+ Object.defineProperty(exports, "SIMPLE_CARD_BUTTON_STYLES", { enumerable: true, get: function () { return simpleCard_1.SIMPLE_CARD_BUTTON_STYLES; } });
77
+ Object.defineProperty(exports, "simpleCardButtonSchema", { enumerable: true, get: function () { return simpleCard_1.simpleCardButtonSchema; } });
78
+ Object.defineProperty(exports, "simpleCardSchema", { enumerable: true, get: function () { return simpleCard_1.simpleCardSchema; } });
79
+ Object.defineProperty(exports, "toSimpleCard", { enumerable: true, get: function () { return simpleCard_1.toSimpleCard; } });
80
+ var validateInput_1 = require("./asks/validateInput");
81
+ Object.defineProperty(exports, "validateAskInput", { enumerable: true, get: function () { return validateInput_1.validateAskInput; } });
82
+ var validateResponse_1 = require("./asks/validateResponse");
83
+ Object.defineProperty(exports, "validateAskResponse", { enumerable: true, get: function () { return validateResponse_1.validateAskResponse; } });
84
+ var errors_2 = require("./errors");
85
+ Object.defineProperty(exports, "BLOCK_ERROR_CODES", { enumerable: true, get: function () { return errors_2.BLOCK_ERROR_CODES; } });
86
+ Object.defineProperty(exports, "BLOCK_WARNING_CODES", { enumerable: true, get: function () { return errors_2.BLOCK_WARNING_CODES; } });
87
+ var jsonSchema_2 = require("./jsonSchema");
88
+ Object.defineProperty(exports, "blocksJsonSchema", { enumerable: true, get: function () { return jsonSchema_2.blocksJsonSchema; } });
89
+ var limits_2 = require("./limits");
90
+ Object.defineProperty(exports, "BLOCK_LIMITS", { enumerable: true, get: function () { return limits_2.BLOCK_LIMITS; } });
91
+ var parse_1 = require("./parse");
92
+ Object.defineProperty(exports, "parseBlocks", { enumerable: true, get: function () { return parse_1.parseBlocks; } });
93
+ var parsePartial_1 = require("./parsePartial");
94
+ Object.defineProperty(exports, "parseBlocksPartial", { enumerable: true, get: function () { return parsePartial_1.parseBlocksPartial; } });
95
+ var prompt_2 = require("./prompt");
96
+ Object.defineProperty(exports, "blocksPromptSection", { enumerable: true, get: function () { return prompt_2.blocksPromptSection; } });
97
+ var schema_2 = require("./schema");
98
+ Object.defineProperty(exports, "BADGE_STATUSES", { enumerable: true, get: function () { return schema_2.BADGE_STATUSES; } });
99
+ Object.defineProperty(exports, "BUTTON_VARIANTS", { enumerable: true, get: function () { return schema_2.BUTTON_VARIANTS; } });
100
+ Object.defineProperty(exports, "blocksSchema", { enumerable: true, get: function () { return schema_2.blocksSchema; } });
101
+ Object.defineProperty(exports, "CALLOUT_STATUSES", { enumerable: true, get: function () { return schema_2.CALLOUT_STATUSES; } });
102
+ Object.defineProperty(exports, "CHART_HEIGHTS", { enumerable: true, get: function () { return schema_2.CHART_HEIGHTS; } });
103
+ Object.defineProperty(exports, "CHART_KINDS", { enumerable: true, get: function () { return schema_2.CHART_KINDS; } });
104
+ Object.defineProperty(exports, "DATASET_COLUMN_TYPES", { enumerable: true, get: function () { return schema_2.DATASET_COLUMN_TYPES; } });
105
+ Object.defineProperty(exports, "DATASET_GRAINS", { enumerable: true, get: function () { return schema_2.DATASET_GRAINS; } });
106
+ Object.defineProperty(exports, "HEADING_SIZES", { enumerable: true, get: function () { return schema_2.HEADING_SIZES; } });
107
+ Object.defineProperty(exports, "HTML_HEIGHTS", { enumerable: true, get: function () { return schema_2.HTML_HEIGHTS; } });
108
+ Object.defineProperty(exports, "METRIC_TRENDS", { enumerable: true, get: function () { return schema_2.METRIC_TRENDS; } });
109
+ Object.defineProperty(exports, "wrapAsTextDocument", { enumerable: true, get: function () { return schema_2.wrapAsTextDocument; } });
110
+ var validate_1 = require("./validate");
111
+ Object.defineProperty(exports, "validateBlocks", { enumerable: true, get: function () { return validate_1.validateBlocks; } });
@@ -0,0 +1,5 @@
1
+ /**
2
+ * JSON Schema for the same document `blocksSchema` checks.
3
+ * Semantic lint (dataset columns, select targets, host callbacks) is not expressible here.
4
+ */
5
+ export declare const blocksJsonSchema: Record<string, unknown>;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.blocksJsonSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ const schema_1 = require("./schema");
6
+ /**
7
+ * JSON Schema for the same document `blocksSchema` checks.
8
+ * Semantic lint (dataset columns, select targets, host callbacks) is not expressible here.
9
+ */
10
+ exports.blocksJsonSchema = zod_1.z.toJSONSchema(schema_1.blocksSchema, {
11
+ target: "draft-07",
12
+ });
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Caps shared by the schema, the prompt, and the reference page.
3
+ */
4
+ export declare const BLOCK_LIMITS: {
5
+ readonly actionElementsMax: 25;
6
+ readonly badgeTextMaxLength: 80;
7
+ readonly barCategoryWarning: 60;
8
+ readonly blockTextMaxLength: 4000;
9
+ readonly cardTitleMaxLength: 120;
10
+ readonly columnsMax: 4;
11
+ readonly columnsMin: 2;
12
+ readonly contextTextMaxLength: 280;
13
+ readonly datasetColumnMax: 12;
14
+ readonly datasetRowMax: 500;
15
+ readonly documentTextMaxLength: 20000;
16
+ readonly donutSliceWarning: 8;
17
+ readonly headingTextMaxLength: 200;
18
+ readonly htmlMaxBytes: 100000;
19
+ readonly maxBlocks: 50;
20
+ readonly maxDatasets: 8;
21
+ readonly maxDepth: 2;
22
+ readonly metricDeltaMaxLength: 40;
23
+ readonly metricHelperMaxLength: 120;
24
+ readonly metricLabelMaxLength: 80;
25
+ readonly metricValueMaxLength: 80;
26
+ readonly refLimitMax: 1000;
27
+ };
package/dist/limits.js ADDED
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BLOCK_LIMITS = void 0;
4
+ /**
5
+ * Caps shared by the schema, the prompt, and the reference page.
6
+ */
7
+ exports.BLOCK_LIMITS = {
8
+ actionElementsMax: 25,
9
+ badgeTextMaxLength: 80,
10
+ barCategoryWarning: 60,
11
+ blockTextMaxLength: 4_000,
12
+ cardTitleMaxLength: 120,
13
+ columnsMax: 4,
14
+ columnsMin: 2,
15
+ contextTextMaxLength: 280,
16
+ datasetColumnMax: 12,
17
+ datasetRowMax: 500,
18
+ documentTextMaxLength: 20_000,
19
+ donutSliceWarning: 8,
20
+ headingTextMaxLength: 200,
21
+ htmlMaxBytes: 100_000,
22
+ maxBlocks: 50,
23
+ maxDatasets: 8,
24
+ maxDepth: 2,
25
+ metricDeltaMaxLength: 40,
26
+ metricHelperMaxLength: 120,
27
+ metricLabelMaxLength: 80,
28
+ metricValueMaxLength: 80,
29
+ refLimitMax: 1_000,
30
+ };
package/dist/lint.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ import { type BlockError } from "./errors";
2
+ import type { BlocksDocument, DatasetColumn } from "./schema";
3
+ export interface KnownDataset {
4
+ columns: DatasetColumn[];
5
+ }
6
+ export interface LintBlocksOptions {
7
+ /** When false or omitted, an `html` block fails with `HTML_DISABLED`. */
8
+ allowHtml?: boolean;
9
+ hostActions?: readonly string[];
10
+ /** Hostnames allowed on `https` image `src` values. Empty means no https images. */
11
+ imageHosts?: readonly string[];
12
+ knownDatasets?: Record<string, KnownDataset>;
13
+ }
14
+ /**
15
+ * Semantic checks for datasets, charts, and tables.
16
+ * Structural schema errors are handled before this runs.
17
+ */
18
+ export declare const lintDocument: (doc: BlocksDocument, options?: LintBlocksOptions) => {
19
+ errors: BlockError[];
20
+ warnings: BlockError[];
21
+ };
package/dist/lint.js ADDED
@@ -0,0 +1,388 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.lintDocument = void 0;
4
+ const errors_1 = require("./errors");
5
+ const limits_1 = require("./limits");
6
+ const issue = ({ code, fix, message, path }) => ({ code, fix, message, path });
7
+ const imageSourceIssue = (src, hosts, path) => {
8
+ if (src.startsWith("file:") && src.slice("file:".length).trim().length > 0) {
9
+ return undefined;
10
+ }
11
+ if (/^data:image\//i.test(src)) {
12
+ return undefined;
13
+ }
14
+ let hostname = "";
15
+ try {
16
+ const url = new URL(src);
17
+ if (url.protocol === "https:") {
18
+ hostname = url.hostname.toLowerCase();
19
+ }
20
+ }
21
+ catch {
22
+ hostname = "";
23
+ }
24
+ const allowed = (hosts ?? []).some((host) => host.toLowerCase() === hostname);
25
+ if (hostname !== "" && allowed) {
26
+ return undefined;
27
+ }
28
+ return issue({
29
+ code: "IMAGE_HOST_NOT_ALLOWED",
30
+ fix: "Use a data:image URL, a file: ref, or an https URL whose host is in uiBlocks.imageHosts.",
31
+ message: errors_1.BLOCK_ERROR_CODES.IMAGE_HOST_NOT_ALLOWED,
32
+ path: `${path}.src`,
33
+ });
34
+ };
35
+ const isInline = (dataset) => dataset.source !== "ref";
36
+ const columnsFor = (dataset, options) => {
37
+ if (isInline(dataset)) {
38
+ return dataset.columns;
39
+ }
40
+ return options?.knownDatasets?.[dataset.id]?.columns;
41
+ };
42
+ const cellMatches = (type, value) => {
43
+ if (type === "number") {
44
+ return typeof value === "number" && Number.isFinite(value);
45
+ }
46
+ return typeof value === "string" && value.trim().length > 0;
47
+ };
48
+ const walk = (blocks, prefix) => {
49
+ const found = [];
50
+ blocks.forEach((block, index) => {
51
+ const path = `${prefix}[${index}]`;
52
+ found.push({ block, path });
53
+ if (block.type === "columns" || block.type === "card") {
54
+ found.push(...walk(block.children, `${path}.children`));
55
+ }
56
+ });
57
+ return found;
58
+ };
59
+ const renderedCount = (dataset, points) => {
60
+ if (points !== undefined) {
61
+ return points;
62
+ }
63
+ if (dataset === undefined) {
64
+ return undefined;
65
+ }
66
+ if (isInline(dataset)) {
67
+ return dataset.rows.length;
68
+ }
69
+ return dataset.limit;
70
+ };
71
+ /**
72
+ * Semantic checks for datasets, charts, and tables.
73
+ * Structural schema errors are handled before this runs.
74
+ */
75
+ const lintDocument = (doc, options) => {
76
+ const errors = [];
77
+ const warnings = [];
78
+ const datasets = doc.datasets ?? {};
79
+ const names = Object.keys(datasets);
80
+ if (names.length > limits_1.BLOCK_LIMITS.maxDatasets) {
81
+ errors.push(issue({
82
+ code: "TOO_MANY",
83
+ fix: `Keep ${limits_1.BLOCK_LIMITS.maxDatasets} datasets or fewer.`,
84
+ message: `The document has more than ${limits_1.BLOCK_LIMITS.maxDatasets} datasets.`,
85
+ path: "datasets",
86
+ }));
87
+ }
88
+ for (const name of names) {
89
+ const dataset = datasets[name];
90
+ if (dataset === undefined || !isInline(dataset)) {
91
+ if (dataset?.source === "ref" &&
92
+ dataset.limit !== undefined &&
93
+ dataset.limit > limits_1.BLOCK_LIMITS.refLimitMax) {
94
+ errors.push(issue({
95
+ code: "TOO_MANY_POINTS",
96
+ fix: `Set grain to a coarser bucket, or set limit to ${limits_1.BLOCK_LIMITS.refLimitMax} or less.`,
97
+ message: errors_1.BLOCK_ERROR_CODES.TOO_MANY_POINTS,
98
+ path: `datasets.${name}.limit`,
99
+ }));
100
+ }
101
+ continue;
102
+ }
103
+ if (dataset.columns.length > limits_1.BLOCK_LIMITS.datasetColumnMax) {
104
+ errors.push(issue({
105
+ code: "DATASET_TOO_LARGE",
106
+ fix: `Use ${limits_1.BLOCK_LIMITS.datasetColumnMax} columns or fewer.`,
107
+ message: errors_1.BLOCK_ERROR_CODES.DATASET_TOO_LARGE,
108
+ path: `datasets.${name}.columns`,
109
+ }));
110
+ }
111
+ if (dataset.rows.length > limits_1.BLOCK_LIMITS.datasetRowMax) {
112
+ errors.push(issue({
113
+ code: "DATASET_TOO_LARGE",
114
+ fix: `Use ${limits_1.BLOCK_LIMITS.datasetRowMax} rows or fewer, or return a ref dataset from a tool.`,
115
+ message: errors_1.BLOCK_ERROR_CODES.DATASET_TOO_LARGE,
116
+ path: `datasets.${name}.rows`,
117
+ }));
118
+ }
119
+ const seenColumns = new Set();
120
+ dataset.columns.forEach((column, index) => {
121
+ if (seenColumns.has(column.name)) {
122
+ errors.push(issue({
123
+ code: "DUPLICATE_ID",
124
+ fix: `Rename the duplicate column "${column.name}".`,
125
+ message: errors_1.BLOCK_ERROR_CODES.DUPLICATE_ID,
126
+ path: `datasets.${name}.columns[${index}].name`,
127
+ }));
128
+ }
129
+ seenColumns.add(column.name);
130
+ });
131
+ dataset.rows.forEach((row, rowIndex) => {
132
+ if (row.length !== dataset.columns.length) {
133
+ errors.push(issue({
134
+ code: "ROW_ARITY_MISMATCH",
135
+ fix: `Give the row ${dataset.columns.length} values, one per column.`,
136
+ message: errors_1.BLOCK_ERROR_CODES.ROW_ARITY_MISMATCH,
137
+ path: `datasets.${name}.rows[${rowIndex}]`,
138
+ }));
139
+ return;
140
+ }
141
+ row.forEach((value, columnIndex) => {
142
+ const column = dataset.columns[columnIndex];
143
+ if (column === undefined || cellMatches(column.type, value)) {
144
+ return;
145
+ }
146
+ errors.push(issue({
147
+ code: "COLUMN_TYPE_MISMATCH",
148
+ fix: `Make datasets.${name}.rows[${rowIndex}][${columnIndex}] a ${column.type}.`,
149
+ message: errors_1.BLOCK_ERROR_CODES.COLUMN_TYPE_MISMATCH,
150
+ path: `datasets.${name}.rows[${rowIndex}][${columnIndex}]`,
151
+ }));
152
+ });
153
+ });
154
+ }
155
+ const seenIds = new Set();
156
+ const selectableIds = new Set();
157
+ const walked = walk(doc.blocks, "blocks");
158
+ for (const { block } of walked) {
159
+ if ((block.type === "chart" || block.type === "table") && block.id !== undefined) {
160
+ selectableIds.add(block.id);
161
+ }
162
+ }
163
+ for (const { block, path } of walked) {
164
+ if (block.type === "html") {
165
+ if (options?.allowHtml !== true) {
166
+ errors.push(issue({
167
+ code: "HTML_DISABLED",
168
+ fix: "Turn on uiBlocks.html before sending an html block, or use a text block.",
169
+ message: errors_1.BLOCK_ERROR_CODES.HTML_DISABLED,
170
+ path,
171
+ }));
172
+ }
173
+ const bytes = new TextEncoder().encode(block.html).length;
174
+ if (bytes > limits_1.BLOCK_LIMITS.htmlMaxBytes) {
175
+ errors.push(issue({
176
+ code: "HTML_TOO_LARGE",
177
+ fix: `Keep the html field at or under ${limits_1.BLOCK_LIMITS.htmlMaxBytes} bytes.`,
178
+ message: errors_1.BLOCK_ERROR_CODES.HTML_TOO_LARGE,
179
+ path: `${path}.html`,
180
+ }));
181
+ }
182
+ }
183
+ if (block.type === "image") {
184
+ const imageIssue = imageSourceIssue(block.src, options?.imageHosts, path);
185
+ if (imageIssue) {
186
+ errors.push(imageIssue);
187
+ }
188
+ }
189
+ if (block.id !== undefined) {
190
+ if (seenIds.has(block.id)) {
191
+ errors.push(issue({
192
+ code: "DUPLICATE_ID",
193
+ fix: `Give ${path} a unique id.`,
194
+ message: errors_1.BLOCK_ERROR_CODES.DUPLICATE_ID,
195
+ path: `${path}.id`,
196
+ }));
197
+ }
198
+ seenIds.add(block.id);
199
+ }
200
+ if (block.type === "chart") {
201
+ const hasPoints = block.points !== undefined;
202
+ const hasData = block.data !== undefined || block.x !== undefined || block.y !== undefined;
203
+ if (hasPoints && hasData) {
204
+ errors.push(issue({
205
+ code: "INVALID_TYPE",
206
+ fix: "Use data, x, and y, or use points. Do not set both.",
207
+ message: "A chart binds to a dataset or lists points.",
208
+ path: `${path}.points`,
209
+ }));
210
+ }
211
+ else if (!hasPoints &&
212
+ (block.data === undefined || block.x === undefined || block.y === undefined)) {
213
+ errors.push(issue({
214
+ code: "MISSING_REQUIRED",
215
+ fix: "Set data, x, and y, or set points.",
216
+ message: errors_1.BLOCK_ERROR_CODES.MISSING_REQUIRED,
217
+ path: `${path}.data`,
218
+ }));
219
+ }
220
+ const dataset = block.data === undefined ? undefined : datasets[block.data];
221
+ if (block.data !== undefined && dataset === undefined) {
222
+ errors.push(issue({
223
+ code: "DATASET_NOT_FOUND",
224
+ fix: `Define datasets.${block.data}, or use a dataset name that exists.`,
225
+ message: errors_1.BLOCK_ERROR_CODES.DATASET_NOT_FOUND,
226
+ path: `${path}.data`,
227
+ }));
228
+ }
229
+ const columns = dataset === undefined ? undefined : columnsFor(dataset, options);
230
+ if (dataset !== undefined &&
231
+ columns !== undefined &&
232
+ block.x !== undefined &&
233
+ block.y !== undefined) {
234
+ const xColumn = columns.find((column) => column.name === block.x);
235
+ const yColumn = columns.find((column) => column.name === block.y);
236
+ if (xColumn === undefined) {
237
+ errors.push(issue({
238
+ code: "COLUMN_NOT_FOUND",
239
+ fix: `Set x to a column of ${block.data}.`,
240
+ message: errors_1.BLOCK_ERROR_CODES.COLUMN_NOT_FOUND,
241
+ path: `${path}.x`,
242
+ }));
243
+ }
244
+ else if (xColumn.type === "number") {
245
+ errors.push(issue({
246
+ code: "COLUMN_TYPE_MISMATCH",
247
+ fix: "Use a string or date column for x.",
248
+ message: errors_1.BLOCK_ERROR_CODES.COLUMN_TYPE_MISMATCH,
249
+ path: `${path}.x`,
250
+ }));
251
+ }
252
+ if (yColumn === undefined) {
253
+ errors.push(issue({
254
+ code: "COLUMN_NOT_FOUND",
255
+ fix: `Set y to a column of ${block.data}.`,
256
+ message: errors_1.BLOCK_ERROR_CODES.COLUMN_NOT_FOUND,
257
+ path: `${path}.y`,
258
+ }));
259
+ }
260
+ else if (yColumn.type !== "number") {
261
+ errors.push(issue({
262
+ code: "COLUMN_TYPE_MISMATCH",
263
+ fix: "Use a number column for y.",
264
+ message: errors_1.BLOCK_ERROR_CODES.COLUMN_TYPE_MISMATCH,
265
+ path: `${path}.y`,
266
+ }));
267
+ }
268
+ }
269
+ const count = renderedCount(dataset, block.points?.length);
270
+ if (block.kind === "bar" && count !== undefined && count > limits_1.BLOCK_LIMITS.barCategoryWarning) {
271
+ warnings.push(issue({
272
+ code: "BAR_TOO_MANY_CATEGORIES",
273
+ fix: "Group the categories, or use a line chart.",
274
+ message: errors_1.BLOCK_WARNING_CODES.BAR_TOO_MANY_CATEGORIES,
275
+ path,
276
+ }));
277
+ }
278
+ if (block.kind === "donut" && count !== undefined && count > limits_1.BLOCK_LIMITS.donutSliceWarning) {
279
+ warnings.push(issue({
280
+ code: "DONUT_TOO_MANY_SLICES",
281
+ fix: "Keep 8 slices or fewer.",
282
+ message: errors_1.BLOCK_WARNING_CODES.DONUT_TOO_MANY_SLICES,
283
+ path,
284
+ }));
285
+ }
286
+ if (block.kind === "line" && count === 1) {
287
+ warnings.push(issue({
288
+ code: "LINE_SINGLE_POINT",
289
+ fix: "Add another point, or use a metric block.",
290
+ message: errors_1.BLOCK_WARNING_CODES.LINE_SINGLE_POINT,
291
+ path,
292
+ }));
293
+ }
294
+ }
295
+ if (block.type === "actions") {
296
+ block.elements.forEach((element, index) => {
297
+ const elementPath = `${path}.elements[${index}]`;
298
+ if (seenIds.has(element.id)) {
299
+ errors.push(issue({
300
+ code: "DUPLICATE_ID",
301
+ fix: `Give ${elementPath} a unique id.`,
302
+ message: errors_1.BLOCK_ERROR_CODES.DUPLICATE_ID,
303
+ path: `${elementPath}.id`,
304
+ }));
305
+ }
306
+ seenIds.add(element.id);
307
+ if (element.type === "segmented" && !selectableIds.has(element.target)) {
308
+ errors.push(issue({
309
+ code: "SELECT_TARGET_INVALID",
310
+ fix: "Set target to the id of a chart or table in this document.",
311
+ message: errors_1.BLOCK_ERROR_CODES.SELECT_TARGET_INVALID,
312
+ path: `${elementPath}.target`,
313
+ }));
314
+ }
315
+ if (element.type === "button" &&
316
+ element.action.kind === "select" &&
317
+ !selectableIds.has(element.action.target)) {
318
+ errors.push(issue({
319
+ code: "SELECT_TARGET_INVALID",
320
+ fix: "Set target to the id of a chart or table in this document.",
321
+ message: errors_1.BLOCK_ERROR_CODES.SELECT_TARGET_INVALID,
322
+ path: `${elementPath}.action.target`,
323
+ }));
324
+ }
325
+ if (element.type === "button" &&
326
+ element.action.kind === "callback" &&
327
+ options?.hostActions !== undefined &&
328
+ !options.hostActions.includes(element.action.name)) {
329
+ errors.push(issue({
330
+ code: "UNKNOWN_HOST_ACTION",
331
+ fix: `Use one of: ${options.hostActions.join(", ") || "(none registered)"}.`,
332
+ message: errors_1.BLOCK_ERROR_CODES.UNKNOWN_HOST_ACTION,
333
+ path: `${elementPath}.action.name`,
334
+ }));
335
+ }
336
+ if (element.type === "button" && element.action.kind === "open") {
337
+ const hasRoute = element.action.route !== undefined;
338
+ const hasUrl = element.action.url !== undefined;
339
+ if (hasRoute === hasUrl) {
340
+ errors.push(issue({
341
+ code: "MISSING_REQUIRED",
342
+ fix: "Set either url or route on an open action.",
343
+ message: errors_1.BLOCK_ERROR_CODES.MISSING_REQUIRED,
344
+ path: `${elementPath}.action`,
345
+ }));
346
+ }
347
+ }
348
+ });
349
+ }
350
+ if (block.type === "table") {
351
+ const dataset = datasets[block.data];
352
+ if (dataset === undefined) {
353
+ errors.push(issue({
354
+ code: "DATASET_NOT_FOUND",
355
+ fix: `Define datasets.${block.data}.`,
356
+ message: errors_1.BLOCK_ERROR_CODES.DATASET_NOT_FOUND,
357
+ path: `${path}.data`,
358
+ }));
359
+ continue;
360
+ }
361
+ const columns = columnsFor(dataset, options);
362
+ const listed = block.columns ?? columns?.map((column) => column.name);
363
+ if (listed !== undefined && listed.length > limits_1.BLOCK_LIMITS.datasetColumnMax) {
364
+ errors.push(issue({
365
+ code: "TABLE_TOO_WIDE",
366
+ fix: `List ${limits_1.BLOCK_LIMITS.datasetColumnMax} columns or fewer.`,
367
+ message: errors_1.BLOCK_ERROR_CODES.TABLE_TOO_WIDE,
368
+ path: `${path}.columns`,
369
+ }));
370
+ }
371
+ if (columns === undefined || block.columns === undefined) {
372
+ continue;
373
+ }
374
+ for (const [index, columnName] of block.columns.entries()) {
375
+ if (!columns.some((column) => column.name === columnName)) {
376
+ errors.push(issue({
377
+ code: "COLUMN_NOT_FOUND",
378
+ fix: `Remove "${columnName}" or add it to the dataset.`,
379
+ message: errors_1.BLOCK_ERROR_CODES.COLUMN_NOT_FOUND,
380
+ path: `${path}.columns[${index}]`,
381
+ }));
382
+ }
383
+ }
384
+ }
385
+ }
386
+ return { errors, warnings };
387
+ };
388
+ exports.lintDocument = lintDocument;
@@ -0,0 +1,16 @@
1
+ import { type BlockError } from "./errors";
2
+ /** Drops one surrounding markdown fence so a model that adds one still parses. */
3
+ export declare const stripBlocksFence: (text: string) => string;
4
+ export type ParseBlocksResult = {
5
+ errors: BlockError[];
6
+ ok: false;
7
+ } | {
8
+ ok: true;
9
+ value: unknown;
10
+ };
11
+ /**
12
+ * Parses one assistant reply into a plain value.
13
+ * A surrounding markdown fence is ignored. Anchors, aliases, and custom tags are rejected.
14
+ * Anything that is not a mapping with `v` is `NOT_A_DOCUMENT`.
15
+ */
16
+ export declare const parseBlocks: (text: string) => ParseBlocksResult;