@positronic/core 0.0.77 → 0.0.78

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 (130) hide show
  1. package/dist/src/dsl/brain-runner.js +37 -182
  2. package/dist/src/dsl/brain-state-machine.js +58 -112
  3. package/dist/src/dsl/brain.js +1 -0
  4. package/dist/src/dsl/builder/brain.js +250 -412
  5. package/dist/src/dsl/builder/continuation.js +67 -0
  6. package/dist/src/dsl/constants.js +16 -17
  7. package/dist/src/dsl/create-brain.js +29 -45
  8. package/dist/src/dsl/example-webhook.js +1 -1
  9. package/dist/src/dsl/execution/constants.js +0 -4
  10. package/dist/src/dsl/execution/event-channel.js +77 -0
  11. package/dist/src/dsl/execution/event-stream.js +1625 -1474
  12. package/dist/src/dsl/signal-validation.js +0 -1
  13. package/dist/src/dsl/webhook.js +4 -1
  14. package/dist/src/files/event-wrapper.js +268 -0
  15. package/dist/src/files/index.js +1 -0
  16. package/dist/src/files/mime.js +31 -0
  17. package/dist/src/files/types.js +13 -0
  18. package/dist/src/index.js +10 -3
  19. package/dist/src/jsx-runtime.js +49 -0
  20. package/dist/src/memory/{scoped-memory.js → create-memory.js} +5 -5
  21. package/dist/src/plugins/collect-webhooks.js +49 -0
  22. package/dist/src/plugins/define-plugin.js +15 -0
  23. package/dist/src/plugins/index.js +1 -0
  24. package/dist/src/plugins/types.js +4 -0
  25. package/dist/src/store/types.js +2 -3
  26. package/dist/src/template/render-html.js +282 -0
  27. package/dist/src/template/render.js +357 -0
  28. package/dist/src/tools/index.js +88 -27
  29. package/dist/src/ui/generate-page-html.js +6 -6
  30. package/dist/src/ui/{generate-ui.js → generate-page.js} +24 -12
  31. package/dist/src/ui/parse-form-data.js +1 -11
  32. package/dist/src/ui/types.js +0 -123
  33. package/dist/src/yaml/data-validator.js +0 -27
  34. package/dist/src/yaml/type-inference.js +10 -9
  35. package/dist/types/clients/types.d.ts +15 -5
  36. package/dist/types/clients/types.d.ts.map +1 -1
  37. package/dist/types/dsl/brain-runner.d.ts +9 -14
  38. package/dist/types/dsl/brain-runner.d.ts.map +1 -1
  39. package/dist/types/dsl/brain-state-machine.d.ts +18 -28
  40. package/dist/types/dsl/brain-state-machine.d.ts.map +1 -1
  41. package/dist/types/dsl/brain.d.ts +3 -2
  42. package/dist/types/dsl/brain.d.ts.map +1 -1
  43. package/dist/types/dsl/builder/brain.d.ts +85 -228
  44. package/dist/types/dsl/builder/brain.d.ts.map +1 -1
  45. package/dist/types/dsl/builder/continuation.d.ts +16 -0
  46. package/dist/types/dsl/builder/continuation.d.ts.map +1 -0
  47. package/dist/types/dsl/constants.d.ts +12 -12
  48. package/dist/types/dsl/constants.d.ts.map +1 -1
  49. package/dist/types/dsl/create-brain.d.ts +17 -57
  50. package/dist/types/dsl/create-brain.d.ts.map +1 -1
  51. package/dist/types/dsl/definitions/blocks.d.ts +67 -66
  52. package/dist/types/dsl/definitions/blocks.d.ts.map +1 -1
  53. package/dist/types/dsl/definitions/brain-types.d.ts +8 -11
  54. package/dist/types/dsl/definitions/brain-types.d.ts.map +1 -1
  55. package/dist/types/dsl/definitions/events.d.ts +61 -56
  56. package/dist/types/dsl/definitions/events.d.ts.map +1 -1
  57. package/dist/types/dsl/definitions/run-params.d.ts +20 -21
  58. package/dist/types/dsl/definitions/run-params.d.ts.map +1 -1
  59. package/dist/types/dsl/definitions/steps.d.ts +1 -1
  60. package/dist/types/dsl/definitions/steps.d.ts.map +1 -1
  61. package/dist/types/dsl/example-webhook.d.ts +3 -3
  62. package/dist/types/dsl/example-webhook.d.ts.map +1 -1
  63. package/dist/types/dsl/execution/constants.d.ts +0 -5
  64. package/dist/types/dsl/execution/constants.d.ts.map +1 -1
  65. package/dist/types/dsl/execution/event-channel.d.ts +16 -0
  66. package/dist/types/dsl/execution/event-channel.d.ts.map +1 -0
  67. package/dist/types/dsl/execution/event-stream.d.ts +46 -34
  68. package/dist/types/dsl/execution/event-stream.d.ts.map +1 -1
  69. package/dist/types/dsl/signal-validation.d.ts.map +1 -1
  70. package/dist/types/dsl/types.d.ts +21 -83
  71. package/dist/types/dsl/types.d.ts.map +1 -1
  72. package/dist/types/dsl/webhook.d.ts +12 -2
  73. package/dist/types/dsl/webhook.d.ts.map +1 -1
  74. package/dist/types/files/event-wrapper.d.ts +20 -0
  75. package/dist/types/files/event-wrapper.d.ts.map +1 -0
  76. package/dist/types/files/index.d.ts +2 -0
  77. package/dist/types/files/index.d.ts.map +1 -0
  78. package/dist/types/files/mime.d.ts +2 -0
  79. package/dist/types/files/mime.d.ts.map +1 -0
  80. package/dist/types/files/types.d.ts +88 -0
  81. package/dist/types/files/types.d.ts.map +1 -0
  82. package/dist/types/index.d.ts +22 -13
  83. package/dist/types/index.d.ts.map +1 -1
  84. package/dist/types/jsx-runtime.d.ts +35 -0
  85. package/dist/types/jsx-runtime.d.ts.map +1 -0
  86. package/dist/types/memory/{scoped-memory.d.ts → create-memory.d.ts} +7 -7
  87. package/dist/types/memory/create-memory.d.ts.map +1 -0
  88. package/dist/types/memory/types.d.ts +4 -4
  89. package/dist/types/memory/types.d.ts.map +1 -1
  90. package/dist/types/plugins/collect-webhooks.d.ts +8 -0
  91. package/dist/types/plugins/collect-webhooks.d.ts.map +1 -0
  92. package/dist/types/plugins/define-plugin.d.ts +25 -0
  93. package/dist/types/plugins/define-plugin.d.ts.map +1 -0
  94. package/dist/types/plugins/index.d.ts +3 -0
  95. package/dist/types/plugins/index.d.ts.map +1 -0
  96. package/dist/types/plugins/types.d.ts +83 -0
  97. package/dist/types/plugins/types.d.ts.map +1 -0
  98. package/dist/types/store/index.d.ts +1 -1
  99. package/dist/types/store/index.d.ts.map +1 -1
  100. package/dist/types/store/types.d.ts +0 -8
  101. package/dist/types/store/types.d.ts.map +1 -1
  102. package/dist/types/template/render-html.d.ts +9 -0
  103. package/dist/types/template/render-html.d.ts.map +1 -0
  104. package/dist/types/template/render.d.ts +15 -0
  105. package/dist/types/template/render.d.ts.map +1 -0
  106. package/dist/types/tools/index.d.ts +39 -27
  107. package/dist/types/tools/index.d.ts.map +1 -1
  108. package/dist/types/ui/generate-page-html.d.ts +4 -6
  109. package/dist/types/ui/generate-page-html.d.ts.map +1 -1
  110. package/dist/types/ui/{generate-ui.d.ts → generate-page.d.ts} +6 -6
  111. package/dist/types/ui/generate-page.d.ts.map +1 -0
  112. package/dist/types/ui/parse-form-data.d.ts +1 -5
  113. package/dist/types/ui/parse-form-data.d.ts.map +1 -1
  114. package/dist/types/ui/types.d.ts +0 -49
  115. package/dist/types/ui/types.d.ts.map +1 -1
  116. package/dist/types/yaml/data-validator.d.ts +0 -5
  117. package/dist/types/yaml/data-validator.d.ts.map +1 -1
  118. package/dist/types/yaml/type-inference.d.ts +4 -2
  119. package/dist/types/yaml/type-inference.d.ts.map +1 -1
  120. package/dist/types/yaml/types.d.ts +0 -1
  121. package/dist/types/yaml/types.d.ts.map +1 -1
  122. package/package.json +5 -1
  123. package/dist/src/dsl/agent-messages.js +0 -5
  124. package/dist/src/ui/validate-form.js +0 -428
  125. package/dist/types/dsl/agent-messages.d.ts +0 -12
  126. package/dist/types/dsl/agent-messages.d.ts.map +0 -1
  127. package/dist/types/memory/scoped-memory.d.ts.map +0 -1
  128. package/dist/types/ui/generate-ui.d.ts.map +0 -1
  129. package/dist/types/ui/validate-form.d.ts +0 -45
  130. package/dist/types/ui/validate-form.d.ts.map +0 -1
@@ -119,7 +119,7 @@ function _ts_generator(thisArg, body) {
119
119
  }
120
120
  }
121
121
  import { z } from 'zod';
122
- import { generateUI as generateUICore } from '../ui/generate-ui.js';
122
+ import { generatePage as generatePageCore } from '../ui/generate-page.js';
123
123
  import { generatePageHtml } from '../ui/generate-page-html.js';
124
124
  import { parseDuration } from '../dsl/duration.js';
125
125
  /**
@@ -145,7 +145,7 @@ import { parseDuration } from '../dsl/duration.js';
145
145
  */ export function createTool(config) {
146
146
  return config;
147
147
  }
148
- var generateUIInputSchema = z.object({
148
+ var generatePageInputSchema = z.object({
149
149
  prompt: z.string().describe('Natural language instructions describing the UI to generate. ' + 'Include: (1) the purpose of the page, (2) what information to display from the data parameter, ' + '(3) what input fields are needed if collecting data, (4) labels and placeholders for fields, ' + '(5) any specific layout preferences. Example: "Create a form to collect user feedback with ' + 'fields for rating (1-5 scale), comments (text area), and email. Show the product name at the top."'),
150
150
  hasForm: z.boolean().optional().describe('Whether to include a form that can be submitted. Defaults to true. ' + 'Set to true when: collecting user input, approval workflows, any interactive data entry. ' + 'Set to false when: displaying read-only information, confirmation pages, dashboards. ' + 'When true, the tool returns webhook info that must be used with waitForWebhook to receive the submission.'),
151
151
  persist: z.boolean().optional().describe('Whether to keep the page after the brain run completes. Defaults to false. ' + 'Set to false (default): Page is automatically cleaned up when the brain run finishes. Use for one-time forms, approvals, or temporary displays. ' + 'Set to true: Page survives brain completion and remains accessible. Use for shared dashboards, permanent reference pages, or pages that need to outlive the workflow.'),
@@ -166,9 +166,9 @@ var generateUIInputSchema = z.object({
166
166
  * Requires components and pages to be configured via createBrain or withComponents().
167
167
  *
168
168
  * The description is enriched at runtime with available component information.
169
- */ export var generateUI = {
170
- description: "Generate a web page for displaying rich content or collecting user input.\n\nSometimes you need more than simple notifications to communicate with users. This tool creates web pages that can display formatted content, dashboards, or forms to collect information.\n\nPass structured data via the 'data' parameter to populate the page with dynamic content. The UI generator uses {{path.to.value}} template bindings to render your data.\n\nRETURNS: { url: string, webhook: { slug: string, identifier: string, token: string } | null }\n- url: The page URL\n- webhook: For forms (hasForm=true), contains slug, identifier, and token that must be passed to waitForWebhook to pause execution until the user submits the form\n\nIMPORTANT: Users have no way to discover the page URL on their own. After generating a page, you must tell them the URL using whatever communication tools are available.",
171
- inputSchema: generateUIInputSchema,
169
+ */ export var generatePage = {
170
+ description: "Generate a web page for displaying rich content or collecting user input.\n\nSometimes you need more than simple notifications to communicate with users. This tool creates web pages that can display formatted content, dashboards, or forms to collect information.\n\nPass structured data via the 'data' parameter to populate the page with dynamic content. The page generator uses {{path.to.value}} template bindings to render your data.\n\nRETURNS: { url: string, webhook: { slug: string, identifier: string, token: string } | null }\n- url: The page URL\n- webhook: For forms (hasForm=true), contains slug, identifier, and token that must be passed to waitForWebhook to pause execution until the user submits the form\n\nIMPORTANT: Users have no way to discover the page URL on their own. After generating a page, you must tell them the URL using whatever communication tools are available.",
171
+ inputSchema: generatePageInputSchema,
172
172
  execute: function execute(input, context) {
173
173
  return _async_to_generator(function() {
174
174
  var components, pages, client, state, env, brainRunId, stepId, _input_hasForm, hasForm, _input_data, uiResult, placementCount, webhookInfo, formAction, formToken, webhookIdentifier, _input_data1, html, page;
@@ -178,11 +178,11 @@ var generateUIInputSchema = z.object({
178
178
  components = context.components, pages = context.pages, client = context.client, state = context.state, env = context.env, brainRunId = context.brainRunId, stepId = context.stepId;
179
179
  hasForm = (_input_hasForm = input.hasForm) !== null && _input_hasForm !== void 0 ? _input_hasForm : true;
180
180
  if (!components || Object.keys(components).length === 0) {
181
- throw new Error('generateUI requires components to be configured. ' + 'Use createBrain({ components }) or brain.withComponents() to register UI components.');
181
+ throw new Error('generatePage requires components to be configured. ' + 'Use createBrain({ components }) or brain.withComponents() to register UI components.');
182
182
  }
183
183
  return [
184
184
  4,
185
- generateUICore({
185
+ generatePageCore({
186
186
  client: client,
187
187
  prompt: input.prompt,
188
188
  components: components,
@@ -194,19 +194,19 @@ var generateUIInputSchema = z.object({
194
194
  if (!uiResult.rootId) {
195
195
  placementCount = uiResult.placements.length;
196
196
  if (placementCount === 0) {
197
- throw new Error("UI generation failed - no components were generated. " + "The LLM may not have understood the prompt. Try being more specific.");
197
+ throw new Error("Page generation failed - no components were generated. " + "The LLM may not have understood the prompt. Try being more specific.");
198
198
  } else {
199
- throw new Error("UI generation failed - no root component found. " + "".concat(placementCount, " component(s) were placed but all have a parentId."));
199
+ throw new Error("Page generation failed - no root component found. " + "".concat(placementCount, " component(s) were placed but all have a parentId."));
200
200
  }
201
201
  }
202
202
  // Create webhook info only if hasForm is true
203
203
  webhookInfo = null;
204
204
  if (hasForm) {
205
- webhookIdentifier = "".concat(brainRunId, "-").concat(stepId, "-generateui-").concat(Date.now());
205
+ webhookIdentifier = "".concat(brainRunId, "-").concat(stepId, "-generatepage-").concat(Date.now());
206
206
  formToken = crypto.randomUUID();
207
- formAction = "".concat(env.origin, "/webhooks/system/ui-form?identifier=").concat(encodeURIComponent(webhookIdentifier));
207
+ formAction = "".concat(env.origin, "/webhooks/system/page-form?identifier=").concat(encodeURIComponent(webhookIdentifier), "&token=").concat(encodeURIComponent(formToken));
208
208
  webhookInfo = {
209
- slug: 'ui-form',
209
+ slug: 'page-form',
210
210
  identifier: webhookIdentifier,
211
211
  token: formToken
212
212
  };
@@ -217,8 +217,7 @@ var generateUIInputSchema = z.object({
217
217
  rootId: uiResult.rootId,
218
218
  data: (_input_data1 = input.data) !== null && _input_data1 !== void 0 ? _input_data1 : {},
219
219
  title: hasForm ? 'Generated Form' : 'Generated Page',
220
- formAction: formAction,
221
- formToken: formToken
220
+ formAction: formAction
222
221
  });
223
222
  return [
224
223
  4,
@@ -242,21 +241,21 @@ var generateUIInputSchema = z.object({
242
241
  }
243
242
  };
244
243
  var waitForWebhookInputSchema = z.object({
245
- slug: z.string().describe('The webhook slug that identifies the type of webhook. ' + 'For generateUI forms, this is always "ui-form". ' + 'Use the exact slug value returned by the tool that created the webhook.'),
246
- identifier: z.string().describe('The unique identifier for this specific webhook instance. ' + 'This is returned by generateUI in webhook.identifier. ' + 'Each generateUI call creates a unique identifier - use the one from the specific page you want to wait for.'),
247
- token: z.string().optional().describe('The CSRF token for form submission validation. ' + 'This is returned by generateUI in webhook.token. ' + 'Pass it through to ensure only submissions from the actual page are accepted.'),
244
+ slug: z.string().describe('The webhook slug that identifies the type of webhook. ' + 'For generatePage forms, this is always "page-form". ' + 'Use the exact slug value returned by the tool that created the webhook.'),
245
+ identifier: z.string().describe('The unique identifier for this specific webhook instance. ' + 'This is returned by generatePage in webhook.identifier. ' + 'Each generatePage call creates a unique identifier - use the one from the specific page you want to wait for.'),
246
+ token: z.string().optional().describe('The CSRF token for form submission validation. ' + 'This is returned by generatePage in webhook.token. ' + 'Pass it through to ensure only submissions from the actual page are accepted.'),
248
247
  timeout: z.string().optional().describe('How long to wait before timing out. Defaults to "1h". ' + 'Accepts durations like "30m", "1h", "24h", "7d". ' + 'If the timeout elapses without a response, the brain is cancelled.')
249
248
  });
250
249
  /**
251
250
  * Wait for webhook tool - pauses execution until a webhook receives a response.
252
251
  *
253
- * Use this after generating a UI page with a form to wait for the user's submission.
252
+ * Use this after generating a page with a form to wait for the user's submission.
254
253
  * The form data will be returned as the tool result when the webhook fires.
255
254
  *
256
255
  * IMPORTANT: Before calling this tool, ensure the user knows the page URL
257
256
  * so they can access and submit the form.
258
257
  */ export var waitForWebhook = {
259
- description: 'Pause agent execution and wait for an external event (webhook response).\n\nPURPOSE: Suspend the agent until a user action occurs, such as submitting a form generated by generateUI.\n\n⚠️ CRITICAL - BEFORE CALLING THIS TOOL:\nYou MUST have already communicated the page URL to the user in your response. The user has no other way to discover the URL. If you call this tool without first telling the user where to go, the job will freeze with no easy recovery.\n\nCORRECT SEQUENCE:\n1. Call generateUI to create the page\n2. In your response text, tell the user the URL (e.g., "Please complete the form at: {url}")\n3. THEN call waitForWebhook\n\nBEHAVIOR:\n- Calling this tool immediately pauses execution\n- The agent will NOT continue until the webhook receives data or the timeout elapses\n- Default timeout is 1 hour. Use the timeout parameter to customize (e.g., "30m", "24h", "7d")\n- If the timeout elapses without a response, the brain is cancelled\n- When the webhook fires, execution resumes with the webhook payload as this tool\'s result\n- The form data will be available as key-value pairs (e.g., { name: "John", email: "john@example.com" })\n\nWHEN TO USE:\n- After generateUI with hasForm=true, to wait for form submission\n- Any workflow requiring human input or approval before continuing\n\nFAILURE MODE: If the user doesn\'t know the URL, they cannot submit the form, and the agent waits until timeout. The only recovery is to kill the job or manually inspect the event stream for the URL.\n\nRETURNS: The webhook payload when triggered. For UI forms, this contains all form field values as an object.',
258
+ description: 'Pause agent execution and wait for an external event (webhook response).\n\nPURPOSE: Suspend the agent until a user action occurs, such as submitting a form generated by generatePage.\n\n⚠️ CRITICAL - BEFORE CALLING THIS TOOL:\nYou MUST have already communicated the page URL to the user in your response. The user has no other way to discover the URL. If you call this tool without first telling the user where to go, the job will freeze with no easy recovery.\n\nCORRECT SEQUENCE:\n1. Call generatePage to create the page\n2. In your response text, tell the user the URL (e.g., "Please complete the form at: {url}")\n3. THEN call waitForWebhook\n\nBEHAVIOR:\n- Calling this tool immediately pauses execution\n- The agent will NOT continue until the webhook receives data or the timeout elapses\n- Default timeout is 1 hour. Use the timeout parameter to customize (e.g., "30m", "24h", "7d")\n- If the timeout elapses without a response, the brain is cancelled\n- When the webhook fires, execution resumes with the webhook payload as this tool\'s result\n- The form data will be available as key-value pairs (e.g., { name: "John", email: "john@example.com" })\n\nWHEN TO USE:\n- After generatePage with hasForm=true, to wait for form submission\n- Any workflow requiring human input or approval before continuing\n\nFAILURE MODE: If the user doesn\'t know the URL, they cannot submit the form, and the agent waits until timeout. The only recovery is to kill the job or manually inspect the event stream for the URL.\n\nRETURNS: The webhook payload when triggered. For UI forms, this contains all form field values as an object.',
260
259
  inputSchema: waitForWebhookInputSchema,
261
260
  execute: function execute(input) {
262
261
  var webhook = {
@@ -312,10 +311,73 @@ var waitForWebhookInputSchema = z.object({
312
311
  }
313
312
  });
314
313
  /**
315
- * Default schema for the auto-generated 'done' tool when no outputSchema is provided.
316
- * Used internally by the framework.
317
- */ export var defaultDoneSchema = z.object({
318
- result: z.string().describe('A clear summary of what was accomplished. ' + 'Include: key outcomes, any important values or findings, and confirmation that the task is complete. ' + 'Be specific but concise. Example: "Successfully processed 15 orders totaling $1,234.56. All items shipped."')
314
+ * Read a file by name. The agent decides which files to read.
315
+ * Returns the file content as text.
316
+ */ export var readFile = createTool({
317
+ description: 'Read the contents of a file by name. Returns the file content as text.',
318
+ inputSchema: z.object({
319
+ name: z.string().describe('The file name to read')
320
+ }),
321
+ execute: function execute(_0, _1) {
322
+ return _async_to_generator(function(param, context) {
323
+ var name, _tmp;
324
+ return _ts_generator(this, function(_state) {
325
+ switch(_state.label){
326
+ case 0:
327
+ name = param.name;
328
+ if (!context.files) {
329
+ throw new Error('readFile tool requires a files service to be configured');
330
+ }
331
+ _tmp = {};
332
+ return [
333
+ 4,
334
+ context.files.open(name).read()
335
+ ];
336
+ case 1:
337
+ return [
338
+ 2,
339
+ (_tmp.content = _state.sent(), _tmp)
340
+ ];
341
+ }
342
+ });
343
+ }).apply(this, arguments);
344
+ }
345
+ });
346
+ /**
347
+ * Write text content to a file. The agent decides what to write and where.
348
+ */ export var writeFile = createTool({
349
+ description: 'Write text content to a file. Creates or overwrites the file.',
350
+ inputSchema: z.object({
351
+ name: z.string().describe('The file name to write'),
352
+ content: z.string().describe('The text content to write')
353
+ }),
354
+ execute: function execute(_0, _1) {
355
+ return _async_to_generator(function(param, context) {
356
+ var name, content;
357
+ return _ts_generator(this, function(_state) {
358
+ switch(_state.label){
359
+ case 0:
360
+ name = param.name, content = param.content;
361
+ if (!context.files) {
362
+ throw new Error('writeFile tool requires a files service to be configured');
363
+ }
364
+ return [
365
+ 4,
366
+ context.files.write(name, content)
367
+ ];
368
+ case 1:
369
+ _state.sent();
370
+ return [
371
+ 2,
372
+ {
373
+ written: true,
374
+ name: name
375
+ }
376
+ ];
377
+ }
378
+ });
379
+ }).apply(this, arguments);
380
+ }
319
381
  });
320
382
  /**
321
383
  * Default tools bundle.
@@ -324,9 +386,8 @@ var waitForWebhookInputSchema = z.object({
324
386
  * standard tools in your brain. Tools can be extended or overridden in
325
387
  * individual agent steps.
326
388
  *
327
- * Note: A 'done' terminal tool is automatically generated for every agent.
328
- * If you provide an outputSchema, 'done' will use that schema. Otherwise,
329
- * it uses a default schema expecting { result: string }.
389
+ * Note: A 'done' terminal tool is automatically generated for every agent
390
+ * using the required outputSchema.
330
391
  *
331
392
  * @example
332
393
  * ```typescript
@@ -347,7 +408,7 @@ var waitForWebhookInputSchema = z.object({
347
408
  * }));
348
409
  * ```
349
410
  */ export var defaultTools = {
350
- generateUI: generateUI,
411
+ generatePage: generatePage,
351
412
  waitForWebhook: waitForWebhook,
352
413
  print: print,
353
414
  consoleLog: consoleLog
@@ -2,9 +2,9 @@
2
2
  * Generate a CSRF token for form submissions.
3
3
  * Use this when building custom HTML pages with forms that submit to webhook endpoints.
4
4
  *
5
- * Include the returned token as a hidden input field:
6
- * ```html
7
- * <input type="hidden" name="__positronic_token" value="${token}">
5
+ * Include the returned token as a query parameter in the form action URL:
6
+ * ```
7
+ * /webhooks/system/ui-form?identifier=...&token=${token}
8
8
  * ```
9
9
  * And include it in the WebhookRegistration's `token` field.
10
10
  */ export function generateFormToken() {
@@ -13,7 +13,7 @@
13
13
  /**
14
14
  * Bootstrap runtime that builds and renders the React tree from placements.
15
15
  * This is inlined into the generated page.
16
- */ var bootstrapRuntime = "\n(function() {\n const components = window.PositronicComponents;\n const data = window.__POSITRONIC_DATA__;\n const tree = window.__POSITRONIC_TREE__;\n const rootId = window.__POSITRONIC_ROOT__;\n const formAction = window.__POSITRONIC_FORM_ACTION__;\n const formToken = window.__POSITRONIC_FORM_TOKEN__;\n\n if (!components) {\n console.error('PositronicComponents not loaded');\n return;\n }\n\n /**\n * Resolve a binding path against a data context.\n * e.g., \"email.subject\" against { email: { subject: \"Hello\" } } -> \"Hello\"\n */\n function resolveBinding(path, ctx) {\n return path.split('.').reduce(function(obj, key) {\n return obj && obj[key];\n }, ctx);\n }\n\n /**\n * Resolve a prop value - handle both full bindings and embedded bindings.\n * - \"{{path}}\" -> resolved value (preserves type - arrays, objects, etc.)\n * - \"Hello {{name}}, score: {{score}}\" -> \"Hello John, score: 42\"\n */\n function resolveProp(value, ctx) {\n if (typeof value !== 'string') {\n return value;\n }\n // Check if the entire value is a single binding - return the actual value (preserves arrays/objects)\n var fullBindingMatch = value.match(/^{{([^}]+)}}$/);\n if (fullBindingMatch) {\n var resolved = resolveBinding(fullBindingMatch[1].trim(), ctx);\n return resolved !== undefined ? resolved : value;\n }\n // Otherwise replace embedded bindings as strings\n return value.replace(/{{([^}]+)}}/g, function(match, path) {\n var resolved = resolveBinding(path.trim(), ctx);\n return resolved !== undefined ? String(resolved) : match;\n });\n }\n\n /**\n * Build a React element from a placement.\n */\n function buildElement(placementId, ctx) {\n var placement = tree.find(function(p) { return p.id === placementId; });\n if (!placement) {\n console.error('Placement not found:', placementId);\n return null;\n }\n\n // Resolve props first (needed for List handling)\n var props = {};\n for (var key in placement.props) {\n props[key] = resolveProp(placement.props[key], ctx);\n }\n\n // Handle List component specially - it's a virtual component that creates a loop context\n if (placement.component === 'List') {\n var items = Array.isArray(props.items) ? props.items : [];\n var itemVarName = props.as || 'item';\n\n // Find direct children of this List\n var childIds = tree\n .filter(function(p) { return p.parentId === placementId; })\n .map(function(p) { return p.id; });\n\n var listItems = items.map(function(item, index) {\n // Create new context with loop variable\n var itemCtx = Object.assign({}, ctx);\n itemCtx[itemVarName] = item;\n itemCtx[itemVarName + 'Index'] = index;\n\n var children = childIds.map(function(childId) {\n return buildElement(childId, itemCtx);\n });\n\n return React.createElement('div', { key: index, className: 'p-4 bg-white border border-gray-200 rounded-lg' }, children);\n });\n\n return React.createElement('div', { className: 'flex flex-col gap-4' }, listItems);\n }\n\n // Look up the component (after handling virtual components like List)\n var Component = components[placement.component];\n if (!Component) {\n console.error('Component not found:', placement.component);\n return null;\n }\n\n // Handle Form component - inject action URL and CSRF token\n if (placement.component === 'Form' && formAction) {\n props.action = formAction;\n }\n\n // Find direct children\n var childIds = tree\n .filter(function(p) { return p.parentId === placementId; })\n .map(function(p) { return p.id; });\n\n var children = childIds.map(function(childId) {\n return buildElement(childId, ctx);\n });\n\n // Prepend hidden CSRF token input to Form components\n if (placement.component === 'Form' && formToken) {\n children = [React.createElement('input', {\n type: 'hidden', name: '__positronic_token', value: formToken, key: '__positronic_token'\n })].concat(children);\n }\n\n return React.createElement(Component, props, children.length > 0 ? children : undefined);\n }\n\n // Render the tree\n var root = document.getElementById('root');\n if (root && rootId) {\n var element = buildElement(rootId, data);\n ReactDOM.render(element, root);\n }\n})();\n";
16
+ */ var bootstrapRuntime = "\n(function() {\n const components = window.PositronicComponents;\n const data = window.__POSITRONIC_DATA__;\n const tree = window.__POSITRONIC_TREE__;\n const rootId = window.__POSITRONIC_ROOT__;\n const formAction = window.__POSITRONIC_FORM_ACTION__;\n\n if (!components) {\n console.error('PositronicComponents not loaded');\n return;\n }\n\n /**\n * Resolve a binding path against a data context.\n * e.g., \"email.subject\" against { email: { subject: \"Hello\" } } -> \"Hello\"\n */\n function resolveBinding(path, ctx) {\n return path.split('.').reduce(function(obj, key) {\n return obj && obj[key];\n }, ctx);\n }\n\n /**\n * Resolve a prop value - handle both full bindings and embedded bindings.\n * - \"{{path}}\" -> resolved value (preserves type - arrays, objects, etc.)\n * - \"Hello {{name}}, score: {{score}}\" -> \"Hello John, score: 42\"\n */\n function resolveProp(value, ctx) {\n if (typeof value !== 'string') {\n return value;\n }\n // Check if the entire value is a single binding - return the actual value (preserves arrays/objects)\n var fullBindingMatch = value.match(/^{{([^}]+)}}$/);\n if (fullBindingMatch) {\n var resolved = resolveBinding(fullBindingMatch[1].trim(), ctx);\n return resolved !== undefined ? resolved : value;\n }\n // Otherwise replace embedded bindings as strings\n return value.replace(/{{([^}]+)}}/g, function(match, path) {\n var resolved = resolveBinding(path.trim(), ctx);\n return resolved !== undefined ? String(resolved) : match;\n });\n }\n\n /**\n * Build a React element from a placement.\n */\n function buildElement(placementId, ctx) {\n var placement = tree.find(function(p) { return p.id === placementId; });\n if (!placement) {\n console.error('Placement not found:', placementId);\n return null;\n }\n\n // Resolve props first (needed for List handling)\n var props = {};\n for (var key in placement.props) {\n props[key] = resolveProp(placement.props[key], ctx);\n }\n\n // Handle List component specially - it's a virtual component that creates a loop context\n if (placement.component === 'List') {\n var items = Array.isArray(props.items) ? props.items : [];\n var itemVarName = props.as || 'item';\n\n // Find direct children of this List\n var childIds = tree\n .filter(function(p) { return p.parentId === placementId; })\n .map(function(p) { return p.id; });\n\n var listItems = items.map(function(item, index) {\n // Create new context with loop variable\n var itemCtx = Object.assign({}, ctx);\n itemCtx[itemVarName] = item;\n itemCtx[itemVarName + 'Index'] = index;\n\n var children = childIds.map(function(childId) {\n return buildElement(childId, itemCtx);\n });\n\n return React.createElement('div', { key: index, className: 'p-4 bg-white border border-gray-200 rounded-lg' }, children);\n });\n\n return React.createElement('div', { className: 'flex flex-col gap-4' }, listItems);\n }\n\n // Look up the component (after handling virtual components like List)\n var Component = components[placement.component];\n if (!Component) {\n console.error('Component not found:', placement.component);\n return null;\n }\n\n // Handle Form component - inject action URL and CSRF token\n if (placement.component === 'Form' && formAction) {\n props.action = formAction;\n }\n\n // Find direct children\n var childIds = tree\n .filter(function(p) { return p.parentId === placementId; })\n .map(function(p) { return p.id; });\n\n var children = childIds.map(function(childId) {\n return buildElement(childId, ctx);\n });\n\n return React.createElement(Component, props, children.length > 0 ? children : undefined);\n }\n\n // Render the tree\n var root = document.getElementById('root');\n if (root && rootId) {\n var element = buildElement(rootId, data);\n ReactDOM.render(element, root);\n }\n})();\n";
17
17
  /**
18
18
  * Generate a complete HTML page from placements.
19
19
  *
@@ -35,7 +35,7 @@
35
35
  * });
36
36
  * ```
37
37
  */ export function generatePageHtml(options) {
38
- var placements = options.placements, rootId = options.rootId, data = options.data, _options_title = options.title, title = _options_title === void 0 ? 'Generated Page' : _options_title, formAction = options.formAction, formToken = options.formToken;
38
+ var placements = options.placements, rootId = options.rootId, data = options.data, _options_title = options.title, title = _options_title === void 0 ? 'Generated Page' : _options_title, formAction = options.formAction;
39
39
  // Escape for embedding in HTML
40
40
  var escapeHtml = function(str) {
41
41
  return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
@@ -44,5 +44,5 @@
44
44
  var safeJsonStringify = function(obj) {
45
45
  return JSON.stringify(obj).replace(/</g, '\\u003c').replace(/>/g, '\\u003e').replace(/&/g, '\\u0026');
46
46
  };
47
- return '<!DOCTYPE html>\n<html lang="en">\n<head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <title>'.concat(escapeHtml(title), '</title>\n <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>\n <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>\n <script src="https://cdn.tailwindcss.com"></script>\n</head>\n<body class="bg-gray-50 min-h-screen">\n <div id="root" class="max-w-4xl mx-auto p-6"></div>\n\n <!-- Pre-bundled components -->\n <script src="/bundle/components.js"></script>\n\n <!-- Data and placements -->\n <script>\n window.__POSITRONIC_DATA__ = ').concat(safeJsonStringify(data), ";\n window.__POSITRONIC_TREE__ = ").concat(safeJsonStringify(placements), ";\n window.__POSITRONIC_ROOT__ = ").concat(safeJsonStringify(rootId), ";\n window.__POSITRONIC_FORM_ACTION__ = ").concat(formAction ? safeJsonStringify(formAction) : 'null', ";\n window.__POSITRONIC_FORM_TOKEN__ = ").concat(formToken ? safeJsonStringify(formToken) : 'null', ";\n </script>\n\n <!-- Bootstrap runtime -->\n <script>\n").concat(bootstrapRuntime, "\n </script>\n</body>\n</html>");
47
+ return '<!DOCTYPE html>\n<html lang="en">\n<head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <title>'.concat(escapeHtml(title), '</title>\n <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>\n <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>\n <script src="https://cdn.tailwindcss.com"></script>\n</head>\n<body class="bg-gray-50 min-h-screen">\n <div id="root" class="max-w-4xl mx-auto p-6"></div>\n\n <!-- Pre-bundled components -->\n <script src="/bundle/components.js"></script>\n\n <!-- Data and placements -->\n <script>\n window.__POSITRONIC_DATA__ = ').concat(safeJsonStringify(data), ";\n window.__POSITRONIC_TREE__ = ").concat(safeJsonStringify(placements), ";\n window.__POSITRONIC_ROOT__ = ").concat(safeJsonStringify(rootId), ";\n window.__POSITRONIC_FORM_ACTION__ = ").concat(formAction ? safeJsonStringify(formAction) : 'null', ";\n </script>\n\n <!-- Bootstrap runtime -->\n <script>\n").concat(bootstrapRuntime, "\n </script>\n</body>\n</html>");
48
48
  }
@@ -185,6 +185,7 @@ function _ts_generator(thisArg, body) {
185
185
  }
186
186
  import { v4 as uuidv4 } from 'uuid';
187
187
  import { z } from 'zod';
188
+ import { IterateResult } from '../dsl/iterate-result.js';
188
189
  import { parseTemplate } from '../yaml/parser.js';
189
190
  import { inferDataType, resolveBindings, validateDataBindings } from '../yaml/data-validator.js';
190
191
  import { extractFormSchema, validateAgainstZod } from '../yaml/schema-extractor.js';
@@ -319,7 +320,7 @@ import { describeDataShape } from '../yaml/type-inference.js';
319
320
  */ function createValidateTemplateTool(components, schema, data) {
320
321
  var dataType = inferDataType(data);
321
322
  return {
322
- description: "Validate a YAML template. Checks that:\n1. The YAML is valid and can be parsed\n2. All component names are valid\n3. All data bindings (like {{email.subject}}) reference valid paths in the provided data\n4. Form components have a Button for submission\n5. The form fields will produce data matching the expected schema (if schema provided)\n\nReturns resolvedBindings showing what each binding resolves to in the actual data. Use this to verify bindings point to the right values.\n\nCall this after generating your YAML template to verify it's correct before finalizing.",
323
+ description: "Validate a YAML template. Checks that:\n1. The YAML is valid and can be parsed\n2. All component names are valid\n3. All data bindings (like {{email.subject}}) reference valid paths in the provided data\n4. Form components have a Button for submission\n5. The form fields will produce data matching the expected schema (if schema provided)\n\nReturns resolvedBindings showing whether each binding path is valid. Use this to verify bindings reference valid data paths.\n\nCall this after generating your YAML template to verify it's correct before finalizing.",
323
324
  inputSchema: z.object({
324
325
  yaml: z.string().describe('The complete YAML template to validate')
325
326
  }),
@@ -499,18 +500,21 @@ import { describeDataShape } from '../yaml/type-inference.js';
499
500
  /**
500
501
  * Build the user prompt with data shape and instructions.
501
502
  */ function buildUserPrompt(prompt, data, schema) {
502
- var dataShape = describeDataShape(data);
503
- var userPrompt = "## Available Data\n```typescript\n".concat(dataShape, "\n```\n\n## Instructions\n").concat(prompt);
503
+ var hasData = Object.keys(data).length > 0;
504
+ var userPrompt = '';
505
+ if (hasData) {
506
+ var dataShape = describeDataShape(data, {
507
+ includeExamples: false
508
+ });
509
+ userPrompt += "## Available Data\n```typescript\n".concat(dataShape, "\n```\n\n");
510
+ }
511
+ userPrompt += "## Instructions\n".concat(prompt);
504
512
  if (schema) {
505
513
  var schemaFields = Object.entries(schema.shape).map(function(param) {
506
514
  var _param = _sliced_to_array(param, 2), name = _param[0], field = _param[1];
507
515
  var isOptional = _instanceof(field, z.ZodOptional);
508
516
  var baseType = isOptional ? field.unwrap() : field;
509
- var typeName = 'unknown';
510
- if (_instanceof(baseType, z.ZodString)) typeName = 'string';
511
- else if (_instanceof(baseType, z.ZodNumber)) typeName = 'number';
512
- else if (_instanceof(baseType, z.ZodBoolean)) typeName = 'boolean';
513
- else if (_instanceof(baseType, z.ZodArray)) typeName = "".concat(typeName, "[]");
517
+ var typeName = getZodTypeName(baseType);
514
518
  return "- ".concat(name, ": ").concat(typeName).concat(isOptional ? ' (optional)' : '');
515
519
  }).join('\n');
516
520
  userPrompt += "\n\n## Expected Form Output\nThe form must collect these fields:\n".concat(schemaFields, "\n\nCall validate_template after generating your YAML to verify correctness.");
@@ -527,7 +531,7 @@ import { describeDataShape } from '../yaml/type-inference.js';
527
531
  * ```typescript
528
532
  * import { components } from '@positronic/gen-ui-components';
529
533
  *
530
- * const result = await generateUI({
534
+ * const result = await generatePage({
531
535
  * client,
532
536
  * prompt: 'Create a form to collect user name and email',
533
537
  * components,
@@ -539,13 +543,21 @@ import { describeDataShape } from '../yaml/type-inference.js';
539
543
  * // result.rootId is the ID of the root component
540
544
  * // result.yaml is the generated YAML template
541
545
  * ```
542
- */ export function generateUI(params) {
546
+ */ export function generatePage(params) {
543
547
  return _async_to_generator(function() {
544
- var client, prompt, components, schema, _params_data, data, _params_maxSteps, maxSteps, _params_system, systemPrompt, userPrompt, validateTool, result, _result_text, yamlContent, yamlMatch, placements, rootId, _placements_find, template;
548
+ var client, prompt, components, schema, tmp, rawData, _params_maxSteps, maxSteps, data, _params_system, systemPrompt, userPrompt, validateTool, result, _result_text, yamlContent, yamlMatch, placements, rootId, _placements_find, template;
545
549
  return _ts_generator(this, function(_state) {
546
550
  switch(_state.label){
547
551
  case 0:
548
- client = params.client, prompt = params.prompt, components = params.components, schema = params.schema, _params_data = params.data, data = _params_data === void 0 ? {} : _params_data, _params_maxSteps = params.maxSteps, maxSteps = _params_maxSteps === void 0 ? 10 : _params_maxSteps;
552
+ client = params.client, prompt = params.prompt, components = params.components, schema = params.schema, tmp = params.data, rawData = tmp === void 0 ? {} : tmp, _params_maxSteps = params.maxSteps, maxSteps = _params_maxSteps === void 0 ? 10 : _params_maxSteps;
553
+ // Unwrap IterateResult values to plain arrays so the LLM sees a clean data shape
554
+ data = Object.fromEntries(Object.entries(rawData).map(function(param) {
555
+ var _param = _sliced_to_array(param, 2), k = _param[0], v = _param[1];
556
+ return [
557
+ k,
558
+ _instanceof(v, IterateResult) ? v.values : v
559
+ ];
560
+ }));
549
561
  systemPrompt = (_params_system = params.system) !== null && _params_system !== void 0 ? _params_system : buildSystemPrompt(components, !!schema);
550
562
  userPrompt = buildUserPrompt(prompt, data, schema);
551
563
  // Create the validate_template tool
@@ -1,6 +1,5 @@
1
1
  /**
2
2
  * Parse form data into a plain object, handling array fields.
3
- * Extracts and strips the __positronic_token CSRF field.
4
3
  * Supports:
5
4
  * - name[] syntax for explicit arrays
6
5
  * - Multiple values with same key (converted to array)
@@ -52,16 +51,10 @@ function _unsupported_iterable_to_array(o, minLen) {
52
51
  }
53
52
  export function parseFormData(formData) {
54
53
  var result = {};
55
- var token = null;
56
54
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
57
55
  try {
58
56
  for(var _iterator = formData.entries()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
59
57
  var _step_value = _sliced_to_array(_step.value, 2), key = _step_value[0], value = _step_value[1];
60
- // Extract CSRF token and exclude from response data
61
- if (key === '__positronic_token') {
62
- token = value;
63
- continue;
64
- }
65
58
  // Handle array fields (e.g., name[] for multi-select)
66
59
  if (key.endsWith('[]')) {
67
60
  var baseKey = key.slice(0, -2);
@@ -95,8 +88,5 @@ export function parseFormData(formData) {
95
88
  }
96
89
  }
97
90
  }
98
- return {
99
- data: result,
100
- token: token
101
- };
91
+ return result;
102
92
  }
@@ -1,11 +1,3 @@
1
- function _array_like_to_array(arr, len) {
2
- if (len == null || len > arr.length) len = arr.length;
3
- for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
4
- return arr2;
5
- }
6
- function _array_with_holes(arr) {
7
- if (Array.isArray(arr)) return arr;
8
- }
9
1
  function _instanceof(left, right) {
10
2
  if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
11
3
  return !!right[Symbol.hasInstance](left);
@@ -13,122 +5,7 @@ function _instanceof(left, right) {
13
5
  return left instanceof right;
14
6
  }
15
7
  }
16
- function _iterable_to_array_limit(arr, i) {
17
- var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
18
- if (_i == null) return;
19
- var _arr = [];
20
- var _n = true;
21
- var _d = false;
22
- var _s, _e;
23
- try {
24
- for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
25
- _arr.push(_s.value);
26
- if (i && _arr.length === i) break;
27
- }
28
- } catch (err) {
29
- _d = true;
30
- _e = err;
31
- } finally{
32
- try {
33
- if (!_n && _i["return"] != null) _i["return"]();
34
- } finally{
35
- if (_d) throw _e;
36
- }
37
- }
38
- return _arr;
39
- }
40
- function _non_iterable_rest() {
41
- throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
42
- }
43
- function _sliced_to_array(arr, i) {
44
- return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
45
- }
46
- function _type_of(obj) {
47
- "@swc/helpers - typeof";
48
- return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
49
- }
50
- function _unsupported_iterable_to_array(o, minLen) {
51
- if (!o) return;
52
- if (typeof o === "string") return _array_like_to_array(o, minLen);
53
- var n = Object.prototype.toString.call(o).slice(8, -1);
54
- if (n === "Object" && o.constructor) n = o.constructor.name;
55
- if (n === "Map" || n === "Set") return Array.from(n);
56
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
57
- }
58
8
  import { z } from 'zod';
59
- /**
60
- * Infer the DataType from a sample value.
61
- */ export function inferDataType(value) {
62
- if (value === null) {
63
- return {
64
- kind: 'primitive',
65
- type: 'null'
66
- };
67
- }
68
- if (typeof value === 'string') {
69
- return {
70
- kind: 'primitive',
71
- type: 'string'
72
- };
73
- }
74
- if (typeof value === 'number') {
75
- return {
76
- kind: 'primitive',
77
- type: 'number'
78
- };
79
- }
80
- if (typeof value === 'boolean') {
81
- return {
82
- kind: 'primitive',
83
- type: 'boolean'
84
- };
85
- }
86
- if (Array.isArray(value)) {
87
- if (value.length === 0) {
88
- return {
89
- kind: 'array',
90
- elementType: {
91
- kind: 'unknown'
92
- }
93
- };
94
- }
95
- // Infer from first element
96
- return {
97
- kind: 'array',
98
- elementType: inferDataType(value[0])
99
- };
100
- }
101
- if ((typeof value === "undefined" ? "undefined" : _type_of(value)) === 'object') {
102
- var properties = {};
103
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
104
- try {
105
- for(var _iterator = Object.entries(value)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
106
- var _step_value = _sliced_to_array(_step.value, 2), key = _step_value[0], val = _step_value[1];
107
- properties[key] = inferDataType(val);
108
- }
109
- } catch (err) {
110
- _didIteratorError = true;
111
- _iteratorError = err;
112
- } finally{
113
- try {
114
- if (!_iteratorNormalCompletion && _iterator.return != null) {
115
- _iterator.return();
116
- }
117
- } finally{
118
- if (_didIteratorError) {
119
- throw _iteratorError;
120
- }
121
- }
122
- }
123
- return {
124
- kind: 'object',
125
- properties: properties
126
- };
127
- }
128
- return {
129
- kind: 'unknown'
130
- };
131
- }
132
9
  /**
133
10
  * Type guard to check if a schema is form-compatible at runtime.
134
11
  * Used as a backup validation when TypeScript inference isn't sufficient.
@@ -366,32 +366,6 @@ function _unsupported_iterable_to_array(o, minLen) {
366
366
  }
367
367
  return current;
368
368
  }
369
- /**
370
- * Summarize a value for LLM consumption.
371
- * Keeps output compact — no full data dumps.
372
- */ export function summarizeValue(value) {
373
- if (value === undefined) return 'undefined';
374
- if (value === null) return 'null';
375
- if (typeof value === 'string') {
376
- if (value.length <= 60) return JSON.stringify(value);
377
- return JSON.stringify(value.slice(0, 57) + '...');
378
- }
379
- if (typeof value === 'number' || typeof value === 'boolean') {
380
- return String(value);
381
- }
382
- if (Array.isArray(value)) {
383
- if (value.length === 0) return 'Array(0) []';
384
- var firstPreview = summarizeValue(value[0]);
385
- return "Array(".concat(value.length, ") [").concat(firstPreview, ", ...]");
386
- }
387
- if ((typeof value === "undefined" ? "undefined" : _type_of(value)) === 'object') {
388
- var keys = Object.keys(value);
389
- var keyPreview = keys.slice(0, 5).join(', ');
390
- var suffix = keys.length > 5 ? ', ...' : '';
391
- return "{ ".concat(keyPreview).concat(suffix, " } (").concat(keys.length, " keys)");
392
- }
393
- return String(value);
394
- }
395
369
  /**
396
370
  * Walk the ComponentNode tree and resolve every binding against real data.
397
371
  *
@@ -412,7 +386,6 @@ function _unsupported_iterable_to_array(o, minLen) {
412
386
  path: propValue.path,
413
387
  component: node.component,
414
388
  prop: propName,
415
- value: summarizeValue(value),
416
389
  resolved: value !== undefined
417
390
  });
418
391
  }
@@ -114,7 +114,7 @@ export function inferTypeDescription(value) {
114
114
  * @param indent - Current indentation level
115
115
  * @returns Multi-line string describing the type with examples
116
116
  */ export function inferTypeWithExamples(value) {
117
- var indent = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 0;
117
+ var indent = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 0, includeExamples = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : true;
118
118
  var spaces = ' '.repeat(indent);
119
119
  if (value === null) {
120
120
  return 'null';
@@ -123,23 +123,23 @@ export function inferTypeDescription(value) {
123
123
  return 'undefined';
124
124
  }
125
125
  if (typeof value === 'string') {
126
- return "string // e.g., ".concat(formatExample(value));
126
+ return includeExamples ? "string // e.g., ".concat(formatExample(value)) : 'string';
127
127
  }
128
128
  if (typeof value === 'number') {
129
- return "number // e.g., ".concat(value);
129
+ return includeExamples ? "number // e.g., ".concat(value) : 'number';
130
130
  }
131
131
  if (typeof value === 'boolean') {
132
- return "boolean // e.g., ".concat(value);
132
+ return includeExamples ? "boolean // e.g., ".concat(value) : 'boolean';
133
133
  }
134
134
  if (Array.isArray(value)) {
135
135
  if (value.length === 0) {
136
136
  return 'unknown[] // empty array';
137
137
  }
138
138
  var firstElement = value[0];
139
- var elementType = inferTypeWithExamples(firstElement, indent + 1);
139
+ var elementType = inferTypeWithExamples(firstElement, indent + 1, includeExamples);
140
140
  // For primitive arrays, keep it compact
141
141
  if (typeof firstElement === 'string' || typeof firstElement === 'number' || typeof firstElement === 'boolean') {
142
- return "Array<".concat(inferTypeDescription(firstElement), "> // ").concat(value.length, " items, e.g., ").concat(formatExample(firstElement));
142
+ return includeExamples ? "Array<".concat(inferTypeDescription(firstElement), "> // ").concat(value.length, " items, e.g., ").concat(formatExample(firstElement)) : "Array<".concat(inferTypeDescription(firstElement), "> // ").concat(value.length, " items");
143
143
  }
144
144
  // For object arrays, show the structure
145
145
  return "Array<".concat(elementType, "> // ").concat(value.length, " items");
@@ -156,7 +156,7 @@ export function inferTypeDescription(value) {
156
156
  try {
157
157
  for(var _iterator = entries[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
158
158
  var _step_value = _sliced_to_array(_step.value, 2), key = _step_value[0], val = _step_value[1];
159
- var valType = inferTypeWithExamples(val, indent + 1);
159
+ var valType = inferTypeWithExamples(val, indent + 1, includeExamples);
160
160
  lines.push("".concat(spaces, " ").concat(key, ": ").concat(valType));
161
161
  }
162
162
  } catch (err) {
@@ -205,6 +205,7 @@ export function inferTypeDescription(value) {
205
205
  * // sessionId: string // e.g., "abc123"
206
206
  * // }
207
207
  * ```
208
- */ export function describeDataShape(data) {
209
- return inferTypeWithExamples(data, 0);
208
+ */ export function describeDataShape(data, options) {
209
+ var _options_includeExamples;
210
+ return inferTypeWithExamples(data, 0, (_options_includeExamples = options === null || options === void 0 ? void 0 : options.includeExamples) !== null && _options_includeExamples !== void 0 ? _options_includeExamples : true);
210
211
  }