@positronic/core 0.0.52 → 0.0.53

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 (96) hide show
  1. package/dist/src/dsl/{loop-messages.js → agent-messages.js} +21 -21
  2. package/dist/src/dsl/brain-runner.js +6 -6
  3. package/dist/src/dsl/brain-state-machine.js +2 -2
  4. package/dist/src/dsl/brain.js +5 -1912
  5. package/dist/src/dsl/builder/brain.js +944 -0
  6. package/dist/src/dsl/builder/step.js +75 -0
  7. package/dist/src/dsl/constants.js +9 -10
  8. package/dist/src/dsl/create-brain.js +63 -0
  9. package/dist/src/dsl/definitions/blocks.js +1 -0
  10. package/dist/src/dsl/definitions/brain-types.js +4 -0
  11. package/dist/src/dsl/definitions/events.js +2 -0
  12. package/dist/src/dsl/definitions/run-params.js +1 -0
  13. package/dist/src/dsl/definitions/steps.js +2 -0
  14. package/dist/src/dsl/execution/constants.js +14 -0
  15. package/dist/src/dsl/execution/event-stream.js +1638 -0
  16. package/dist/src/dsl/execution/retry.js +298 -0
  17. package/dist/src/dsl/types.js +2 -2
  18. package/dist/src/index.js +5 -3
  19. package/dist/src/tools/index.js +181 -0
  20. package/dist/src/ui/component-utils.js +107 -0
  21. package/dist/src/ui/generate-page-html.js +36 -0
  22. package/dist/src/ui/generate-ui.js +601 -0
  23. package/dist/src/ui/types.js +165 -0
  24. package/dist/src/ui/validate-form.js +428 -0
  25. package/dist/src/yaml/data-validator.js +302 -0
  26. package/dist/src/yaml/index.js +9 -0
  27. package/dist/src/yaml/parser.js +224 -0
  28. package/dist/src/yaml/schema-extractor.js +330 -0
  29. package/dist/src/yaml/type-inference.js +210 -0
  30. package/dist/src/yaml/types.js +12 -0
  31. package/dist/types/clients/types.d.ts +42 -0
  32. package/dist/types/clients/types.d.ts.map +1 -1
  33. package/dist/types/dsl/agent-messages.d.ts +18 -0
  34. package/dist/types/dsl/agent-messages.d.ts.map +1 -0
  35. package/dist/types/dsl/brain-runner.d.ts +2 -2
  36. package/dist/types/dsl/brain-runner.d.ts.map +1 -1
  37. package/dist/types/dsl/brain-state-machine.d.ts.map +1 -1
  38. package/dist/types/dsl/brain.d.ts +7 -273
  39. package/dist/types/dsl/brain.d.ts.map +1 -1
  40. package/dist/types/dsl/builder/brain.d.ts +200 -0
  41. package/dist/types/dsl/builder/brain.d.ts.map +1 -0
  42. package/dist/types/dsl/builder/step.d.ts +15 -0
  43. package/dist/types/dsl/builder/step.d.ts.map +1 -0
  44. package/dist/types/dsl/constants.d.ts +8 -9
  45. package/dist/types/dsl/constants.d.ts.map +1 -1
  46. package/dist/types/dsl/create-brain.d.ts +80 -0
  47. package/dist/types/dsl/create-brain.d.ts.map +1 -0
  48. package/dist/types/dsl/definitions/blocks.d.ts +62 -0
  49. package/dist/types/dsl/definitions/blocks.d.ts.map +1 -0
  50. package/dist/types/dsl/definitions/brain-types.d.ts +33 -0
  51. package/dist/types/dsl/definitions/brain-types.d.ts.map +1 -0
  52. package/dist/types/dsl/definitions/events.d.ts +129 -0
  53. package/dist/types/dsl/definitions/events.d.ts.map +1 -0
  54. package/dist/types/dsl/definitions/run-params.d.ts +26 -0
  55. package/dist/types/dsl/definitions/run-params.d.ts.map +1 -0
  56. package/dist/types/dsl/definitions/steps.d.ts +20 -0
  57. package/dist/types/dsl/definitions/steps.d.ts.map +1 -0
  58. package/dist/types/dsl/example-webhook.d.ts +1 -1
  59. package/dist/types/dsl/example-webhook.d.ts.map +1 -1
  60. package/dist/types/dsl/execution/constants.d.ts +16 -0
  61. package/dist/types/dsl/execution/constants.d.ts.map +1 -0
  62. package/dist/types/dsl/execution/event-stream.d.ts +44 -0
  63. package/dist/types/dsl/execution/event-stream.d.ts.map +1 -0
  64. package/dist/types/dsl/execution/retry.d.ts +30 -0
  65. package/dist/types/dsl/execution/retry.d.ts.map +1 -0
  66. package/dist/types/dsl/types.d.ts +35 -14
  67. package/dist/types/dsl/types.d.ts.map +1 -1
  68. package/dist/types/index.d.ts +9 -7
  69. package/dist/types/index.d.ts.map +1 -1
  70. package/dist/types/tools/index.d.ts +33 -0
  71. package/dist/types/tools/index.d.ts.map +1 -0
  72. package/dist/types/ui/component-utils.d.ts +19 -0
  73. package/dist/types/ui/component-utils.d.ts.map +1 -0
  74. package/dist/types/ui/generate-page-html.d.ts +39 -0
  75. package/dist/types/ui/generate-page-html.d.ts.map +1 -0
  76. package/dist/types/ui/generate-ui.d.ts +47 -0
  77. package/dist/types/ui/generate-ui.d.ts.map +1 -0
  78. package/dist/types/ui/types.d.ts +138 -0
  79. package/dist/types/ui/types.d.ts.map +1 -0
  80. package/dist/types/ui/validate-form.d.ts +45 -0
  81. package/dist/types/ui/validate-form.d.ts.map +1 -0
  82. package/dist/types/yaml/data-validator.d.ts +35 -0
  83. package/dist/types/yaml/data-validator.d.ts.map +1 -0
  84. package/dist/types/yaml/index.d.ts +11 -0
  85. package/dist/types/yaml/index.d.ts.map +1 -0
  86. package/dist/types/yaml/parser.d.ts +20 -0
  87. package/dist/types/yaml/parser.d.ts.map +1 -0
  88. package/dist/types/yaml/schema-extractor.d.ts +29 -0
  89. package/dist/types/yaml/schema-extractor.d.ts.map +1 -0
  90. package/dist/types/yaml/type-inference.d.ts +50 -0
  91. package/dist/types/yaml/type-inference.d.ts.map +1 -0
  92. package/dist/types/yaml/types.d.ts +89 -0
  93. package/dist/types/yaml/types.d.ts.map +1 -0
  94. package/package.json +4 -2
  95. package/dist/types/dsl/loop-messages.d.ts +0 -18
  96. package/dist/types/dsl/loop-messages.d.ts.map +0 -1
@@ -0,0 +1,298 @@
1
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
2
+ try {
3
+ var info = gen[key](arg);
4
+ var value = info.value;
5
+ } catch (error) {
6
+ reject(error);
7
+ return;
8
+ }
9
+ if (info.done) {
10
+ resolve(value);
11
+ } else {
12
+ Promise.resolve(value).then(_next, _throw);
13
+ }
14
+ }
15
+ function _async_to_generator(fn) {
16
+ return function() {
17
+ var self = this, args = arguments;
18
+ return new Promise(function(resolve, reject) {
19
+ var gen = fn.apply(self, args);
20
+ function _next(value) {
21
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
22
+ }
23
+ function _throw(err) {
24
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
25
+ }
26
+ _next(undefined);
27
+ });
28
+ };
29
+ }
30
+ function _class_call_check(instance, Constructor) {
31
+ if (!(instance instanceof Constructor)) {
32
+ throw new TypeError("Cannot call a class as a function");
33
+ }
34
+ }
35
+ function _defineProperties(target, props) {
36
+ for(var i = 0; i < props.length; i++){
37
+ var descriptor = props[i];
38
+ descriptor.enumerable = descriptor.enumerable || false;
39
+ descriptor.configurable = true;
40
+ if ("value" in descriptor) descriptor.writable = true;
41
+ Object.defineProperty(target, descriptor.key, descriptor);
42
+ }
43
+ }
44
+ function _create_class(Constructor, protoProps, staticProps) {
45
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
46
+ if (staticProps) _defineProperties(Constructor, staticProps);
47
+ return Constructor;
48
+ }
49
+ function _define_property(obj, key, value) {
50
+ if (key in obj) {
51
+ Object.defineProperty(obj, key, {
52
+ value: value,
53
+ enumerable: true,
54
+ configurable: true,
55
+ writable: true
56
+ });
57
+ } else {
58
+ obj[key] = value;
59
+ }
60
+ return obj;
61
+ }
62
+ function _ts_generator(thisArg, body) {
63
+ var f, y, t, _ = {
64
+ label: 0,
65
+ sent: function() {
66
+ if (t[0] & 1) throw t[1];
67
+ return t[1];
68
+ },
69
+ trys: [],
70
+ ops: []
71
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
72
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
73
+ return this;
74
+ }), g;
75
+ function verb(n) {
76
+ return function(v) {
77
+ return step([
78
+ n,
79
+ v
80
+ ]);
81
+ };
82
+ }
83
+ function step(op) {
84
+ if (f) throw new TypeError("Generator is already executing.");
85
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
86
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
87
+ if (y = 0, t) op = [
88
+ op[0] & 2,
89
+ t.value
90
+ ];
91
+ switch(op[0]){
92
+ case 0:
93
+ case 1:
94
+ t = op;
95
+ break;
96
+ case 4:
97
+ _.label++;
98
+ return {
99
+ value: op[1],
100
+ done: false
101
+ };
102
+ case 5:
103
+ _.label++;
104
+ y = op[1];
105
+ op = [
106
+ 0
107
+ ];
108
+ continue;
109
+ case 7:
110
+ op = _.ops.pop();
111
+ _.trys.pop();
112
+ continue;
113
+ default:
114
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
115
+ _ = 0;
116
+ continue;
117
+ }
118
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
119
+ _.label = op[1];
120
+ break;
121
+ }
122
+ if (op[0] === 6 && _.label < t[1]) {
123
+ _.label = t[1];
124
+ t = op;
125
+ break;
126
+ }
127
+ if (t && _.label < t[2]) {
128
+ _.label = t[2];
129
+ _.ops.push(op);
130
+ break;
131
+ }
132
+ if (t[2]) _.ops.pop();
133
+ _.trys.pop();
134
+ continue;
135
+ }
136
+ op = body.call(thisArg, _);
137
+ } catch (e) {
138
+ op = [
139
+ 6,
140
+ e
141
+ ];
142
+ y = 0;
143
+ } finally{
144
+ f = t = 0;
145
+ }
146
+ if (op[0] & 5) throw op[1];
147
+ return {
148
+ value: op[0] ? op[1] : void 0,
149
+ done: true
150
+ };
151
+ }
152
+ }
153
+ /**
154
+ * Simple sleep helper that returns a promise resolving after the specified delay.
155
+ */ export var sleep = function(ms) {
156
+ return new Promise(function(resolve) {
157
+ return setTimeout(resolve, ms);
158
+ });
159
+ };
160
+ /**
161
+ * Simple semaphore for limiting concurrent operations.
162
+ * Used internally by batch prompt execution.
163
+ */ export var Semaphore = /*#__PURE__*/ function() {
164
+ "use strict";
165
+ function Semaphore(max) {
166
+ _class_call_check(this, Semaphore);
167
+ _define_property(this, "max", void 0);
168
+ _define_property(this, "current", void 0);
169
+ _define_property(this, "queue", void 0);
170
+ this.max = max;
171
+ this.current = 0;
172
+ this.queue = [];
173
+ }
174
+ _create_class(Semaphore, [
175
+ {
176
+ key: "acquire",
177
+ value: function acquire() {
178
+ return _async_to_generator(function() {
179
+ var _this;
180
+ return _ts_generator(this, function(_state) {
181
+ _this = this;
182
+ if (this.current < this.max) {
183
+ this.current++;
184
+ return [
185
+ 2
186
+ ];
187
+ }
188
+ return [
189
+ 2,
190
+ new Promise(function(resolve) {
191
+ return _this.queue.push(resolve);
192
+ })
193
+ ];
194
+ });
195
+ }).call(this);
196
+ }
197
+ },
198
+ {
199
+ key: "release",
200
+ value: function release() {
201
+ this.current--;
202
+ var next = this.queue.shift();
203
+ if (next) {
204
+ this.current++;
205
+ next();
206
+ }
207
+ }
208
+ }
209
+ ]);
210
+ return Semaphore;
211
+ }();
212
+ /**
213
+ * Normalize retry config with defaults.
214
+ */ export function normalizeRetryConfig(config) {
215
+ var _config_maxRetries, _config_backoff, _config_initialDelay, _config_maxDelay;
216
+ return {
217
+ maxRetries: (_config_maxRetries = config === null || config === void 0 ? void 0 : config.maxRetries) !== null && _config_maxRetries !== void 0 ? _config_maxRetries : 3,
218
+ backoff: (_config_backoff = config === null || config === void 0 ? void 0 : config.backoff) !== null && _config_backoff !== void 0 ? _config_backoff : 'exponential',
219
+ initialDelay: (_config_initialDelay = config === null || config === void 0 ? void 0 : config.initialDelay) !== null && _config_initialDelay !== void 0 ? _config_initialDelay : 1000,
220
+ maxDelay: (_config_maxDelay = config === null || config === void 0 ? void 0 : config.maxDelay) !== null && _config_maxDelay !== void 0 ? _config_maxDelay : 30000
221
+ };
222
+ }
223
+ /**
224
+ * Calculate backoff delay based on attempt number and config.
225
+ */ export function calculateBackoff(attempt, config) {
226
+ switch(config.backoff){
227
+ case 'none':
228
+ return config.initialDelay;
229
+ case 'linear':
230
+ return Math.min(config.initialDelay * (attempt + 1), config.maxDelay);
231
+ case 'exponential':
232
+ return Math.min(config.initialDelay * Math.pow(2, attempt), config.maxDelay);
233
+ }
234
+ }
235
+ /**
236
+ * Execute a function with retry and exponential backoff.
237
+ */ export function executeWithRetry(fn, config) {
238
+ return _async_to_generator(function() {
239
+ var lastError, attempt, error, delay;
240
+ return _ts_generator(this, function(_state) {
241
+ switch(_state.label){
242
+ case 0:
243
+ attempt = 0;
244
+ _state.label = 1;
245
+ case 1:
246
+ if (!(attempt <= config.maxRetries)) return [
247
+ 3,
248
+ 8
249
+ ];
250
+ _state.label = 2;
251
+ case 2:
252
+ _state.trys.push([
253
+ 2,
254
+ 4,
255
+ ,
256
+ 7
257
+ ]);
258
+ return [
259
+ 4,
260
+ fn()
261
+ ];
262
+ case 3:
263
+ return [
264
+ 2,
265
+ _state.sent()
266
+ ];
267
+ case 4:
268
+ error = _state.sent();
269
+ lastError = error;
270
+ if (!(attempt < config.maxRetries)) return [
271
+ 3,
272
+ 6
273
+ ];
274
+ delay = calculateBackoff(attempt, config);
275
+ return [
276
+ 4,
277
+ sleep(delay)
278
+ ];
279
+ case 5:
280
+ _state.sent();
281
+ _state.label = 6;
282
+ case 6:
283
+ return [
284
+ 3,
285
+ 7
286
+ ];
287
+ case 7:
288
+ attempt++;
289
+ return [
290
+ 3,
291
+ 1
292
+ ];
293
+ case 8:
294
+ throw lastError;
295
+ }
296
+ });
297
+ })();
298
+ }
@@ -1,4 +1,4 @@
1
1
  /**
2
- * Helper type to extract the terminal tool's input type from a tools object.
3
- * Used for typing the result that gets merged into state.
2
+ * Configuration for retry behavior with exponential backoff.
3
+ * Used by batch prompt execution.
4
4
  */ export { };
package/dist/src/index.js CHANGED
@@ -1,7 +1,8 @@
1
- export { Brain, brain, DEFAULT_ENV } from './dsl/brain.js';
1
+ export { Brain, brain } from './dsl/brain.js';
2
2
  export { BrainRunner } from './dsl/brain-runner.js';
3
+ export { createBrain } from './dsl/create-brain.js';
3
4
  export { STATUS, BRAIN_EVENTS } from './dsl/constants.js';
4
- export { createPatch, applyPatches } from './dsl/json-patch.js';
5
+ export { applyPatches } from './dsl/json-patch.js';
5
6
  // Only needed for development to ensure that zod version numbers are the same, it's a peer
6
7
  // dependency so when not using file://..path/to/package links the version numbers
7
8
  // will match just fine if the user has the same version of zod installed.
@@ -10,6 +11,7 @@ export { z } from 'zod';
10
11
  export { createResources } from './resources/resources.js';
11
12
  export { createWebhook } from './dsl/webhook.js';
12
13
  export { RESOURCE_TYPES } from './resources/resources.js';
13
- export { reconstructLoopContext } from './dsl/loop-messages.js';
14
+ // Default tools
15
+ export { defaultTools, generateUI } from './tools/index.js';
14
16
  // Brain state machine
15
17
  export { createBrainExecutionMachine, createBrainMachine, sendEvent, getDepth, isTopLevel, getCurrentStep, getBrainStack, getBrainRunId, getExecutionState, getPendingWebhooks, getError, getCompletedSteps } from './dsl/brain-state-machine.js';
@@ -0,0 +1,181 @@
1
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
2
+ try {
3
+ var info = gen[key](arg);
4
+ var value = info.value;
5
+ } catch (error) {
6
+ reject(error);
7
+ return;
8
+ }
9
+ if (info.done) {
10
+ resolve(value);
11
+ } else {
12
+ Promise.resolve(value).then(_next, _throw);
13
+ }
14
+ }
15
+ function _async_to_generator(fn) {
16
+ return function() {
17
+ var self = this, args = arguments;
18
+ return new Promise(function(resolve, reject) {
19
+ var gen = fn.apply(self, args);
20
+ function _next(value) {
21
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
22
+ }
23
+ function _throw(err) {
24
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
25
+ }
26
+ _next(undefined);
27
+ });
28
+ };
29
+ }
30
+ function _ts_generator(thisArg, body) {
31
+ var f, y, t, _ = {
32
+ label: 0,
33
+ sent: function() {
34
+ if (t[0] & 1) throw t[1];
35
+ return t[1];
36
+ },
37
+ trys: [],
38
+ ops: []
39
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
40
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
41
+ return this;
42
+ }), g;
43
+ function verb(n) {
44
+ return function(v) {
45
+ return step([
46
+ n,
47
+ v
48
+ ]);
49
+ };
50
+ }
51
+ function step(op) {
52
+ if (f) throw new TypeError("Generator is already executing.");
53
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
54
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
55
+ if (y = 0, t) op = [
56
+ op[0] & 2,
57
+ t.value
58
+ ];
59
+ switch(op[0]){
60
+ case 0:
61
+ case 1:
62
+ t = op;
63
+ break;
64
+ case 4:
65
+ _.label++;
66
+ return {
67
+ value: op[1],
68
+ done: false
69
+ };
70
+ case 5:
71
+ _.label++;
72
+ y = op[1];
73
+ op = [
74
+ 0
75
+ ];
76
+ continue;
77
+ case 7:
78
+ op = _.ops.pop();
79
+ _.trys.pop();
80
+ continue;
81
+ default:
82
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
83
+ _ = 0;
84
+ continue;
85
+ }
86
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
87
+ _.label = op[1];
88
+ break;
89
+ }
90
+ if (op[0] === 6 && _.label < t[1]) {
91
+ _.label = t[1];
92
+ t = op;
93
+ break;
94
+ }
95
+ if (t && _.label < t[2]) {
96
+ _.label = t[2];
97
+ _.ops.push(op);
98
+ break;
99
+ }
100
+ if (t[2]) _.ops.pop();
101
+ _.trys.pop();
102
+ continue;
103
+ }
104
+ op = body.call(thisArg, _);
105
+ } catch (e) {
106
+ op = [
107
+ 6,
108
+ e
109
+ ];
110
+ y = 0;
111
+ } finally{
112
+ f = t = 0;
113
+ }
114
+ if (op[0] & 5) throw op[1];
115
+ return {
116
+ value: op[0] ? op[1] : void 0,
117
+ done: true
118
+ };
119
+ }
120
+ }
121
+ import { z } from 'zod';
122
+ import { createWebhook } from '../dsl/webhook.js';
123
+ /**
124
+ * Default generateUI tool - gets enriched with component metadata at runtime.
125
+ *
126
+ * This tool allows the LLM to generate a UI and wait for user response.
127
+ * The actual component list and descriptions are injected at runtime
128
+ * based on the components registered with .withComponents().
129
+ */ export var generateUI = {
130
+ description: 'Generate a UI to display to the user and wait for their response',
131
+ inputSchema: z.object({
132
+ component: z.string().describe('The component name to render'),
133
+ props: z.record(z.unknown()).describe('Props to pass to the component')
134
+ }),
135
+ execute: function execute(input) {
136
+ // Return waitFor to pause execution until user responds
137
+ // The actual webhook handling is done by the runtime
138
+ var uiWebhook = createWebhook('ui-response', z.object({
139
+ userResponse: z.unknown()
140
+ }), function() {
141
+ return _async_to_generator(function() {
142
+ return _ts_generator(this, function(_state) {
143
+ return [
144
+ 2,
145
+ {
146
+ type: 'webhook',
147
+ identifier: 'pending',
148
+ response: {
149
+ userResponse: null
150
+ }
151
+ }
152
+ ];
153
+ });
154
+ })();
155
+ });
156
+ return {
157
+ waitFor: uiWebhook('pending')
158
+ };
159
+ }
160
+ };
161
+ /**
162
+ * Default tools bundle.
163
+ *
164
+ * Use with .withTools(defaultTools) to include standard tools in your brain.
165
+ * Tools can be extended or overridden in individual agent steps.
166
+ *
167
+ * @example
168
+ * ```typescript
169
+ * import { brain, defaultTools } from '@positronic/core';
170
+ *
171
+ * const myBrain = brain('my-brain')
172
+ * .withTools(defaultTools)
173
+ * .brain('agent', ({ tools }) => ({
174
+ * system: 'You are helpful',
175
+ * prompt: 'Help the user',
176
+ * tools // uses defaultTools
177
+ * }));
178
+ * ```
179
+ */ export var defaultTools = {
180
+ generateUI: generateUI
181
+ };
@@ -0,0 +1,107 @@
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
+ function _iterable_to_array_limit(arr, i) {
10
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
11
+ if (_i == null) return;
12
+ var _arr = [];
13
+ var _n = true;
14
+ var _d = false;
15
+ var _s, _e;
16
+ try {
17
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
18
+ _arr.push(_s.value);
19
+ if (i && _arr.length === i) break;
20
+ }
21
+ } catch (err) {
22
+ _d = true;
23
+ _e = err;
24
+ } finally{
25
+ try {
26
+ if (!_n && _i["return"] != null) _i["return"]();
27
+ } finally{
28
+ if (_d) throw _e;
29
+ }
30
+ }
31
+ return _arr;
32
+ }
33
+ function _non_iterable_rest() {
34
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
35
+ }
36
+ function _sliced_to_array(arr, i) {
37
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
38
+ }
39
+ function _unsupported_iterable_to_array(o, minLen) {
40
+ if (!o) return;
41
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
42
+ var n = Object.prototype.toString.call(o).slice(8, -1);
43
+ if (n === "Object" && o.constructor) n = o.constructor.name;
44
+ if (n === "Map" || n === "Set") return Array.from(n);
45
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
46
+ }
47
+ /**
48
+ * Merge multiple component objects into one.
49
+ * Later objects override earlier ones for component definitions.
50
+ *
51
+ * @param componentSets - Component objects to merge
52
+ * @returns A merged component object
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * import { components } from '@positronic/gen-ui-components';
57
+ * import { myComponents } from './my-components';
58
+ *
59
+ * const merged = mergeComponents(components, myComponents);
60
+ * brain.withComponents(merged);
61
+ * ```
62
+ */ export function mergeComponents() {
63
+ for(var _len = arguments.length, componentSets = new Array(_len), _key = 0; _key < _len; _key++){
64
+ componentSets[_key] = arguments[_key];
65
+ }
66
+ var merged = {};
67
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
68
+ try {
69
+ for(var _iterator = componentSets[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
70
+ var set = _step.value;
71
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
72
+ try {
73
+ for(var _iterator1 = Object.entries(set)[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
74
+ var _step_value = _sliced_to_array(_step1.value, 2), name = _step_value[0], component = _step_value[1];
75
+ merged[name] = component;
76
+ }
77
+ } catch (err) {
78
+ _didIteratorError1 = true;
79
+ _iteratorError1 = err;
80
+ } finally{
81
+ try {
82
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
83
+ _iterator1.return();
84
+ }
85
+ } finally{
86
+ if (_didIteratorError1) {
87
+ throw _iteratorError1;
88
+ }
89
+ }
90
+ }
91
+ }
92
+ } catch (err) {
93
+ _didIteratorError = true;
94
+ _iteratorError = err;
95
+ } finally{
96
+ try {
97
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
98
+ _iterator.return();
99
+ }
100
+ } finally{
101
+ if (_didIteratorError) {
102
+ throw _iteratorError;
103
+ }
104
+ }
105
+ }
106
+ return merged;
107
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Bootstrap runtime that builds and renders the React tree from placements.
3
+ * This is inlined into the generated page.
4
+ */ 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\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";
5
+ /**
6
+ * Generate a complete HTML page from placements.
7
+ *
8
+ * The generated page includes:
9
+ * - React and ReactDOM from CDN
10
+ * - Tailwind CSS from CDN
11
+ * - Reference to component bundle at /bundle/components.js
12
+ * - Data and placements embedded as JSON
13
+ * - Bootstrap runtime that builds and renders the React tree
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const html = generatePageHtml({
18
+ * placements: result.placements,
19
+ * rootId: result.rootId,
20
+ * data: brainState,
21
+ * title: 'My Generated Page',
22
+ * formAction: '/api/submit',
23
+ * });
24
+ * ```
25
+ */ export function generatePageHtml(options) {
26
+ 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;
27
+ // Escape for embedding in HTML
28
+ var escapeHtml = function(str) {
29
+ return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
30
+ };
31
+ // Serialize data safely for embedding in script tag
32
+ var safeJsonStringify = function(obj) {
33
+ return JSON.stringify(obj).replace(/</g, '\\u003c').replace(/>/g, '\\u003e').replace(/&/g, '\\u0026');
34
+ };
35
+ 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>");
36
+ }