@positronic/cloudflare 0.0.51 → 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 (42) hide show
  1. package/dist/src/api/brains.js +1003 -0
  2. package/dist/src/api/bundle.js +204 -0
  3. package/dist/src/api/index.js +149 -0
  4. package/dist/src/api/pages.js +681 -0
  5. package/dist/src/api/resources.js +778 -0
  6. package/dist/src/api/secrets.js +707 -0
  7. package/dist/src/api/types.js +1 -0
  8. package/dist/src/api/webhooks/coordination.js +267 -0
  9. package/dist/src/api/webhooks/index.js +277 -0
  10. package/dist/src/api/webhooks/system.js +248 -0
  11. package/dist/src/brain-runner-do.js +5 -5
  12. package/dist/src/dev-server.js +206 -10
  13. package/dist/src/index.js +2 -4
  14. package/dist/src/monitor-do.js +23 -7
  15. package/dist/types/api/brains.d.ts +7 -0
  16. package/dist/types/api/brains.d.ts.map +1 -0
  17. package/dist/types/api/bundle.d.ts +7 -0
  18. package/dist/types/api/bundle.d.ts.map +1 -0
  19. package/dist/types/api/index.d.ts +8 -0
  20. package/dist/types/api/index.d.ts.map +1 -0
  21. package/dist/types/api/pages.d.ts +7 -0
  22. package/dist/types/api/pages.d.ts.map +1 -0
  23. package/dist/types/api/resources.d.ts +7 -0
  24. package/dist/types/api/resources.d.ts.map +1 -0
  25. package/dist/types/api/secrets.d.ts +7 -0
  26. package/dist/types/api/secrets.d.ts.map +1 -0
  27. package/dist/types/{api.d.ts → api/types.d.ts} +15 -9
  28. package/dist/types/api/types.d.ts.map +1 -0
  29. package/dist/types/api/webhooks/coordination.d.ts +32 -0
  30. package/dist/types/api/webhooks/coordination.d.ts.map +1 -0
  31. package/dist/types/api/webhooks/index.d.ts +7 -0
  32. package/dist/types/api/webhooks/index.d.ts.map +1 -0
  33. package/dist/types/api/webhooks/system.d.ts +7 -0
  34. package/dist/types/api/webhooks/system.d.ts.map +1 -0
  35. package/dist/types/dev-server.d.ts +5 -0
  36. package/dist/types/dev-server.d.ts.map +1 -1
  37. package/dist/types/index.d.ts +3 -5
  38. package/dist/types/index.d.ts.map +1 -1
  39. package/dist/types/monitor-do.d.ts.map +1 -1
  40. package/package.json +4 -4
  41. package/dist/src/api.js +0 -2839
  42. package/dist/types/api.d.ts.map +0 -1
@@ -0,0 +1,248 @@
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 _define_property(obj, key, value) {
31
+ if (key in obj) {
32
+ Object.defineProperty(obj, key, {
33
+ value: value,
34
+ enumerable: true,
35
+ configurable: true,
36
+ writable: true
37
+ });
38
+ } else {
39
+ obj[key] = value;
40
+ }
41
+ return obj;
42
+ }
43
+ function _object_spread(target) {
44
+ for(var i = 1; i < arguments.length; i++){
45
+ var source = arguments[i] != null ? arguments[i] : {};
46
+ var ownKeys = Object.keys(source);
47
+ if (typeof Object.getOwnPropertySymbols === "function") {
48
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
49
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
50
+ }));
51
+ }
52
+ ownKeys.forEach(function(key) {
53
+ _define_property(target, key, source[key]);
54
+ });
55
+ }
56
+ return target;
57
+ }
58
+ function ownKeys(object, enumerableOnly) {
59
+ var keys = Object.keys(object);
60
+ if (Object.getOwnPropertySymbols) {
61
+ var symbols = Object.getOwnPropertySymbols(object);
62
+ if (enumerableOnly) {
63
+ symbols = symbols.filter(function(sym) {
64
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
65
+ });
66
+ }
67
+ keys.push.apply(keys, symbols);
68
+ }
69
+ return keys;
70
+ }
71
+ function _object_spread_props(target, source) {
72
+ source = source != null ? source : {};
73
+ if (Object.getOwnPropertyDescriptors) {
74
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
75
+ } else {
76
+ ownKeys(Object(source)).forEach(function(key) {
77
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
78
+ });
79
+ }
80
+ return target;
81
+ }
82
+ function _ts_generator(thisArg, body) {
83
+ var f, y, t, _ = {
84
+ label: 0,
85
+ sent: function() {
86
+ if (t[0] & 1) throw t[1];
87
+ return t[1];
88
+ },
89
+ trys: [],
90
+ ops: []
91
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
92
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
93
+ return this;
94
+ }), g;
95
+ function verb(n) {
96
+ return function(v) {
97
+ return step([
98
+ n,
99
+ v
100
+ ]);
101
+ };
102
+ }
103
+ function step(op) {
104
+ if (f) throw new TypeError("Generator is already executing.");
105
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
106
+ 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;
107
+ if (y = 0, t) op = [
108
+ op[0] & 2,
109
+ t.value
110
+ ];
111
+ switch(op[0]){
112
+ case 0:
113
+ case 1:
114
+ t = op;
115
+ break;
116
+ case 4:
117
+ _.label++;
118
+ return {
119
+ value: op[1],
120
+ done: false
121
+ };
122
+ case 5:
123
+ _.label++;
124
+ y = op[1];
125
+ op = [
126
+ 0
127
+ ];
128
+ continue;
129
+ case 7:
130
+ op = _.ops.pop();
131
+ _.trys.pop();
132
+ continue;
133
+ default:
134
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
135
+ _ = 0;
136
+ continue;
137
+ }
138
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
139
+ _.label = op[1];
140
+ break;
141
+ }
142
+ if (op[0] === 6 && _.label < t[1]) {
143
+ _.label = t[1];
144
+ t = op;
145
+ break;
146
+ }
147
+ if (t && _.label < t[2]) {
148
+ _.label = t[2];
149
+ _.ops.push(op);
150
+ break;
151
+ }
152
+ if (t[2]) _.ops.pop();
153
+ _.trys.pop();
154
+ continue;
155
+ }
156
+ op = body.call(thisArg, _);
157
+ } catch (e) {
158
+ op = [
159
+ 6,
160
+ e
161
+ ];
162
+ y = 0;
163
+ } finally{
164
+ f = t = 0;
165
+ }
166
+ if (op[0] & 5) throw op[1];
167
+ return {
168
+ value: op[0] ? op[1] : void 0,
169
+ done: true
170
+ };
171
+ }
172
+ }
173
+ import { Hono } from 'hono';
174
+ import { findAndResumeBrain, parseFormData } from './coordination.js';
175
+ var system = new Hono();
176
+ /**
177
+ * Built-in webhook for UI form submissions.
178
+ * This handles form POSTs from pages generated by .ui() steps.
179
+ *
180
+ * POST /webhooks/system/ui-form?identifier=<identifier>
181
+ * Content-Type: application/x-www-form-urlencoded or multipart/form-data
182
+ */ system.post('/ui-form', function(context) {
183
+ return _async_to_generator(function() {
184
+ var identifier, formData, response, result, error;
185
+ return _ts_generator(this, function(_state) {
186
+ switch(_state.label){
187
+ case 0:
188
+ identifier = context.req.query('identifier');
189
+ if (!identifier) {
190
+ return [
191
+ 2,
192
+ context.json({
193
+ error: 'Missing required query parameter "identifier"'
194
+ }, 400)
195
+ ];
196
+ }
197
+ _state.label = 1;
198
+ case 1:
199
+ _state.trys.push([
200
+ 1,
201
+ 4,
202
+ ,
203
+ 5
204
+ ]);
205
+ return [
206
+ 4,
207
+ context.req.formData()
208
+ ];
209
+ case 2:
210
+ formData = _state.sent();
211
+ response = parseFormData(formData);
212
+ return [
213
+ 4,
214
+ findAndResumeBrain(context, 'ui-form', identifier, response)
215
+ ];
216
+ case 3:
217
+ result = _state.sent();
218
+ // Return 404 if no brain was waiting
219
+ if (result.action === 'not_found') {
220
+ return [
221
+ 2,
222
+ context.json(_object_spread_props(_object_spread({}, result), {
223
+ message: 'No brain waiting for this form submission'
224
+ }), 404)
225
+ ];
226
+ }
227
+ return [
228
+ 2,
229
+ context.json(result)
230
+ ];
231
+ case 4:
232
+ error = _state.sent();
233
+ console.error('Error processing UI form submission:', error);
234
+ return [
235
+ 2,
236
+ context.json({
237
+ error: 'Failed to process form submission'
238
+ }, 500)
239
+ ];
240
+ case 5:
241
+ return [
242
+ 2
243
+ ];
244
+ }
245
+ });
246
+ })();
247
+ });
248
+ export default system;
@@ -825,7 +825,7 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
825
825
  key: "resume",
826
826
  value: function resume(brainRunId, webhookResponse) {
827
827
  return _async_to_generator(function() {
828
- var _this, sql, startEventResult, startEvent, brainTitle, initialState, resolution, brainToRun, allEventsResult, machine, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, row, event, initialCompletedSteps, loopEventsResult, loopEvents, sqliteAdapter, eventStreamAdapter, monitorDOStub, monitorAdapter, scheduleAdapter, webhookAdapter, pageAdapter, env, pagesService, r2Resources, runnerWithResources;
828
+ var _this, sql, startEventResult, startEvent, brainTitle, initialState, resolution, brainToRun, allEventsResult, machine, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, row, event, initialCompletedSteps, agentEventsResult, agentEvents, sqliteAdapter, eventStreamAdapter, monitorDOStub, monitorAdapter, scheduleAdapter, webhookAdapter, pageAdapter, env, pagesService, r2Resources, runnerWithResources;
829
829
  return _ts_generator(this, function(_state) {
830
830
  switch(_state.label){
831
831
  case 0:
@@ -889,9 +889,9 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
889
889
  }
890
890
  // Get the reconstructed step hierarchy from the state machine
891
891
  initialCompletedSteps = getCompletedSteps(machine);
892
- // Load LOOP_* events for potential loop resume
893
- loopEventsResult = sql.exec("SELECT serialized_event FROM brain_events WHERE event_type LIKE 'loop:%' ORDER BY event_id ASC").toArray();
894
- loopEvents = loopEventsResult.map(function(row) {
892
+ // Load AGENT_* events for potential agent resume
893
+ agentEventsResult = sql.exec("SELECT serialized_event FROM brain_events WHERE event_type LIKE 'agent:%' ORDER BY event_id ASC").toArray();
894
+ agentEvents = agentEventsResult.map(function(row) {
895
895
  return JSON.parse(row.serialized_event);
896
896
  });
897
897
  sqliteAdapter = new BrainRunSQLiteAdapter(sql);
@@ -935,7 +935,7 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
935
935
  brainRunId: brainRunId,
936
936
  response: webhookResponse,
937
937
  signal: this.abortController.signal,
938
- loopEvents: loopEvents
938
+ agentEvents: agentEvents
939
939
  }).catch(function(err) {
940
940
  console.error("[DO ".concat(brainRunId, "] BrainRunner resume failed:"), err);
941
941
  throw err;
@@ -70,6 +70,13 @@ function _define_property(obj, key, value) {
70
70
  }
71
71
  return obj;
72
72
  }
73
+ function _instanceof(left, right) {
74
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
75
+ return !!right[Symbol.hasInstance](left);
76
+ } else {
77
+ return left instanceof right;
78
+ }
79
+ }
73
80
  function _iterable_to_array(iter) {
74
81
  if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
75
82
  }
@@ -251,7 +258,7 @@ import * as path from 'path';
251
258
  import * as fsPromises from 'fs/promises';
252
259
  import * as fs from 'fs';
253
260
  import * as os from 'os';
254
- import { spawn } from 'child_process';
261
+ import { spawn, execSync } from 'child_process';
255
262
  import * as dotenv from 'dotenv';
256
263
  import caz from 'caz';
257
264
  import { createRequire } from 'module';
@@ -804,6 +811,13 @@ export var CloudflareDevServer = /*#__PURE__*/ function() {
804
811
  this.updateWranglerConfiguration(projectRoot, serverDir)
805
812
  ];
806
813
  case 4:
814
+ _state.sent();
815
+ // Build and upload component bundle
816
+ return [
817
+ 4,
818
+ this.buildAndUploadBundle(projectRoot)
819
+ ];
820
+ case 5:
807
821
  _state.sent();
808
822
  return [
809
823
  2
@@ -1072,8 +1086,8 @@ export var CloudflareDevServer = /*#__PURE__*/ function() {
1072
1086
  config.r2_buckets[0].bucket_name = env.R2_BUCKET_NAME;
1073
1087
  changed = true;
1074
1088
  }
1075
- if (!config.r2_buckets[0].experimental_remote) {
1076
- config.r2_buckets[0].experimental_remote = true;
1089
+ if (!config.r2_buckets[0].remote) {
1090
+ config.r2_buckets[0].remote = true;
1077
1091
  changed = true;
1078
1092
  }
1079
1093
  }
@@ -1093,8 +1107,8 @@ export var CloudflareDevServer = /*#__PURE__*/ function() {
1093
1107
  // Get project name from the wrangler config name (remove "positronic-dev-" prefix)
1094
1108
  var configName = config.name || 'local-project';
1095
1109
  var projectName = configName.replace(/^positronic-dev-/, '') || 'local-project';
1096
- if (config.r2_buckets[0].experimental_remote) {
1097
- delete config.r2_buckets[0].experimental_remote;
1110
+ if (config.r2_buckets[0].remote) {
1111
+ delete config.r2_buckets[0].remote;
1098
1112
  changed = true;
1099
1113
  }
1100
1114
  if (config.r2_buckets[0].bucket_name !== projectName) {
@@ -1110,6 +1124,161 @@ export var CloudflareDevServer = /*#__PURE__*/ function() {
1110
1124
  return changed;
1111
1125
  }
1112
1126
  },
1127
+ {
1128
+ key: "buildAndUploadBundle",
1129
+ value: /**
1130
+ * Build the component bundle and upload it to local R2.
1131
+ * Uses esbuild to bundle components/bundle.ts and uploads to R2 for serving.
1132
+ */ function buildAndUploadBundle(_0) {
1133
+ return _async_to_generator(function(projectRoot) {
1134
+ var options, bundleEntryPath, distDir, bundleOutputPath, componentsDir, hasComponents, hasBundleEntry, _wranglerConfig_r2_buckets_, _wranglerConfig_r2_buckets, bundleContent, serverDir, wranglerConfigPath, wranglerConfig, bucketName, r2Key, r2Path, tempBundlePath, localFlag, target, error;
1135
+ var _arguments = arguments;
1136
+ return _ts_generator(this, function(_state) {
1137
+ switch(_state.label){
1138
+ case 0:
1139
+ options = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {
1140
+ local: true
1141
+ };
1142
+ bundleEntryPath = path.join(projectRoot, 'components', 'bundle.ts');
1143
+ distDir = path.join(projectRoot, 'dist');
1144
+ bundleOutputPath = path.join(distDir, 'components.js');
1145
+ // Check if components directory exists
1146
+ componentsDir = path.join(projectRoot, 'components');
1147
+ return [
1148
+ 4,
1149
+ fsPromises.access(componentsDir).then(function() {
1150
+ return true;
1151
+ }).catch(function() {
1152
+ return false;
1153
+ })
1154
+ ];
1155
+ case 1:
1156
+ hasComponents = _state.sent();
1157
+ if (!hasComponents) {
1158
+ console.log('📦 No components/ directory found, skipping bundle build');
1159
+ return [
1160
+ 2
1161
+ ];
1162
+ }
1163
+ return [
1164
+ 4,
1165
+ fsPromises.access(bundleEntryPath).then(function() {
1166
+ return true;
1167
+ }).catch(function() {
1168
+ return false;
1169
+ })
1170
+ ];
1171
+ case 2:
1172
+ hasBundleEntry = _state.sent();
1173
+ if (!hasBundleEntry) {
1174
+ console.log('📦 No components/bundle.ts found, skipping bundle build');
1175
+ return [
1176
+ 2
1177
+ ];
1178
+ }
1179
+ _state.label = 3;
1180
+ case 3:
1181
+ _state.trys.push([
1182
+ 3,
1183
+ 11,
1184
+ ,
1185
+ 12
1186
+ ]);
1187
+ console.log('📦 Building component bundle...');
1188
+ // Ensure dist directory exists
1189
+ return [
1190
+ 4,
1191
+ fsPromises.mkdir(distDir, {
1192
+ recursive: true
1193
+ })
1194
+ ];
1195
+ case 4:
1196
+ _state.sent();
1197
+ // Run esbuild to build the bundle
1198
+ execSync('npx esbuild "'.concat(bundleEntryPath, '" --bundle --external:react --external:react-dom --format=iife --outfile="').concat(bundleOutputPath, '" --jsx=transform --jsx-factory=React.createElement --jsx-fragment=React.Fragment'), {
1199
+ cwd: projectRoot,
1200
+ stdio: 'inherit'
1201
+ });
1202
+ return [
1203
+ 4,
1204
+ fsPromises.readFile(bundleOutputPath, 'utf-8')
1205
+ ];
1206
+ case 5:
1207
+ bundleContent = _state.sent();
1208
+ // Upload to local R2 using wrangler
1209
+ serverDir = path.join(projectRoot, '.positronic');
1210
+ // Get bucket name from wrangler config
1211
+ wranglerConfigPath = path.join(serverDir, 'wrangler.jsonc');
1212
+ wranglerConfig = JSON.parse(fs.readFileSync(wranglerConfigPath, 'utf-8'));
1213
+ bucketName = (_wranglerConfig_r2_buckets = wranglerConfig.r2_buckets) === null || _wranglerConfig_r2_buckets === void 0 ? void 0 : (_wranglerConfig_r2_buckets_ = _wranglerConfig_r2_buckets[0]) === null || _wranglerConfig_r2_buckets_ === void 0 ? void 0 : _wranglerConfig_r2_buckets_.bucket_name;
1214
+ if (!bucketName) {
1215
+ console.warn('⚠️ Warning: No R2 bucket configured, skipping bundle upload');
1216
+ return [
1217
+ 2
1218
+ ];
1219
+ }
1220
+ r2Key = 'bundle/components.js';
1221
+ r2Path = "".concat(bucketName, "/").concat(r2Key);
1222
+ // Write bundle to a temp file for wrangler r2 object put
1223
+ tempBundlePath = path.join(os.tmpdir(), "positronic-bundle-".concat(Date.now(), ".js"));
1224
+ return [
1225
+ 4,
1226
+ fsPromises.writeFile(tempBundlePath, bundleContent)
1227
+ ];
1228
+ case 6:
1229
+ _state.sent();
1230
+ _state.label = 7;
1231
+ case 7:
1232
+ _state.trys.push([
1233
+ 7,
1234
+ ,
1235
+ 8,
1236
+ 10
1237
+ ]);
1238
+ localFlag = options.local ? ' --local' : '';
1239
+ execSync('npx wrangler r2 object put "'.concat(r2Path, '" --file="').concat(tempBundlePath, '"').concat(localFlag), {
1240
+ cwd: serverDir,
1241
+ stdio: 'pipe'
1242
+ });
1243
+ target = options.local ? 'local' : 'production';
1244
+ console.log("✅ Component bundle built and uploaded to ".concat(target));
1245
+ return [
1246
+ 3,
1247
+ 10
1248
+ ];
1249
+ case 8:
1250
+ // Clean up temp file
1251
+ return [
1252
+ 4,
1253
+ fsPromises.unlink(tempBundlePath).catch(function() {})
1254
+ ];
1255
+ case 9:
1256
+ _state.sent();
1257
+ return [
1258
+ 7
1259
+ ];
1260
+ case 10:
1261
+ return [
1262
+ 3,
1263
+ 12
1264
+ ];
1265
+ case 11:
1266
+ error = _state.sent();
1267
+ console.warn('⚠️ Warning: Failed to build component bundle:', _instanceof(error, Error) ? error.message : error);
1268
+ console.warn(' Pages may not render correctly without the bundle.');
1269
+ return [
1270
+ 3,
1271
+ 12
1272
+ ];
1273
+ case 12:
1274
+ return [
1275
+ 2
1276
+ ];
1277
+ }
1278
+ });
1279
+ }).apply(this, arguments);
1280
+ }
1281
+ },
1113
1282
  {
1114
1283
  key: "start",
1115
1284
  value: function start(port) {
@@ -1122,8 +1291,7 @@ export var CloudflareDevServer = /*#__PURE__*/ function() {
1122
1291
  serverDir = path.join(this.projectRootDir, '.positronic');
1123
1292
  // Start wrangler dev server
1124
1293
  wranglerArgs = [
1125
- 'dev',
1126
- '--x-remote-bindings'
1294
+ 'dev'
1127
1295
  ];
1128
1296
  // Always specify a port - use 8787 as default if not provided
1129
1297
  serverPort = port || 8787;
@@ -1132,8 +1300,11 @@ export var CloudflareDevServer = /*#__PURE__*/ function() {
1132
1300
  'wrangler'
1133
1301
  ].concat(_to_consumable_array(wranglerArgs)), {
1134
1302
  cwd: serverDir,
1303
+ // Don't inherit stdin - this prevents wrangler from:
1304
+ // 1. Setting terminal to raw mode (which breaks Ctrl-A, Ctrl-E after exit)
1305
+ // 2. Receiving SIGINT directly (we handle Ctrl-C in the parent process)
1135
1306
  stdio: [
1136
- 'inherit',
1307
+ 'ignore',
1137
1308
  'pipe',
1138
1309
  'pipe'
1139
1310
  ]
@@ -1202,7 +1373,7 @@ export var CloudflareDevServer = /*#__PURE__*/ function() {
1202
1373
  _state.sent();
1203
1374
  return [
1204
1375
  3,
1205
- 4
1376
+ 6
1206
1377
  ];
1207
1378
  case 2:
1208
1379
  if (!(relativePath.startsWith('webhooks/') || relativePath.startsWith('webhooks\\'))) return [
@@ -1216,8 +1387,24 @@ export var CloudflareDevServer = /*#__PURE__*/ function() {
1216
1387
  ];
1217
1388
  case 3:
1218
1389
  _state.sent();
1219
- _state.label = 4;
1390
+ return [
1391
+ 3,
1392
+ 6
1393
+ ];
1220
1394
  case 4:
1395
+ if (!(relativePath.startsWith('components/') || relativePath.startsWith('components\\'))) return [
1396
+ 3,
1397
+ 6
1398
+ ];
1399
+ console.log("Component file ".concat(event, ": ").concat(relativePath));
1400
+ return [
1401
+ 4,
1402
+ this.buildAndUploadBundle(projectRoot)
1403
+ ];
1404
+ case 5:
1405
+ _state.sent();
1406
+ _state.label = 6;
1407
+ case 6:
1221
1408
  return [
1222
1409
  2
1223
1410
  ];
@@ -1355,6 +1542,15 @@ export var CloudflareDevServer = /*#__PURE__*/ function() {
1355
1542
  this.ensureR2BucketExists(bucketName)
1356
1543
  ];
1357
1544
  case 3:
1545
+ _state.sent();
1546
+ // Build and upload component bundle to production R2
1547
+ return [
1548
+ 4,
1549
+ this.buildAndUploadBundle(projectRoot, {
1550
+ local: false
1551
+ })
1552
+ ];
1553
+ case 4:
1358
1554
  _state.sent();
1359
1555
  console.log('🚀 Deploying to Cloudflare Workers (production)...');
1360
1556
  // Deploy to production using wrangler
package/dist/src/index.js CHANGED
@@ -1,7 +1,5 @@
1
- export { BrainRunnerDO, setBrainRunner, setManifest, getManifest, setWebhookManifest } from './brain-runner-do.js';
1
+ export { BrainRunnerDO, setBrainRunner, setManifest, setWebhookManifest } from './brain-runner-do.js';
2
2
  export { MonitorDO } from './monitor-do.js';
3
3
  export { ScheduleDO } from './schedule-do.js';
4
4
  export { PositronicManifest } from './manifest.js';
5
- export { default as api } from './api.js';
6
- export { CloudflareR2Loader } from './r2-loader.js';
7
- export { createPagesService } from './pages-service.js';
5
+ export { default as api } from './api/index.js';
@@ -244,7 +244,7 @@ function _ts_generator(thisArg, body) {
244
244
  }
245
245
  }
246
246
  import { DurableObject } from 'cloudflare:workers';
247
- import { BRAIN_EVENTS, STATUS } from '@positronic/core';
247
+ import { BRAIN_EVENTS, STATUS, createBrainExecutionMachine } from '@positronic/core';
248
248
  export var MonitorDO = /*#__PURE__*/ function(DurableObject) {
249
249
  "use strict";
250
250
  _inherits(MonitorDO, DurableObject);
@@ -257,7 +257,7 @@ export var MonitorDO = /*#__PURE__*/ function(DurableObject) {
257
257
  ]), _define_property(_this, "storage", void 0), _define_property(_this, "eventStreamHandler", new EventStreamHandler());
258
258
  _this.storage = state.storage.sql;
259
259
  // Update table schema and indexes
260
- _this.storage.exec("\n CREATE TABLE IF NOT EXISTS brain_runs (\n run_id TEXT PRIMARY KEY,\n brain_title TEXT NOT NULL, -- Renamed column\n brain_description TEXT, -- Renamed column\n type TEXT NOT NULL,\n status TEXT NOT NULL,\n options TEXT,\n error TEXT,\n created_at INTEGER NOT NULL,\n started_at INTEGER,\n completed_at INTEGER\n );\n\n CREATE INDEX IF NOT EXISTS idx_brain_status -- Renamed index\n ON brain_runs(brain_title, status);\n\n CREATE INDEX IF NOT EXISTS idx_brain_time -- Renamed index\n ON brain_runs(created_at DESC);\n\n CREATE TABLE IF NOT EXISTS webhook_registrations (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n slug TEXT NOT NULL,\n identifier TEXT NOT NULL,\n brain_run_id TEXT NOT NULL,\n created_at INTEGER NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_webhook_lookup\n ON webhook_registrations(slug, identifier);\n\n CREATE INDEX IF NOT EXISTS idx_webhook_brain_run\n ON webhook_registrations(brain_run_id);\n\n CREATE TABLE IF NOT EXISTS page_registrations (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n slug TEXT NOT NULL UNIQUE,\n brain_run_id TEXT NOT NULL,\n persist INTEGER NOT NULL DEFAULT 0,\n created_at INTEGER NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_page_brain_run\n ON page_registrations(brain_run_id);\n\n CREATE INDEX IF NOT EXISTS idx_page_persist\n ON page_registrations(persist);\n ");
260
+ _this.storage.exec("\n CREATE TABLE IF NOT EXISTS brain_runs (\n run_id TEXT PRIMARY KEY,\n brain_title TEXT NOT NULL,\n brain_description TEXT,\n type TEXT NOT NULL,\n status TEXT NOT NULL,\n options TEXT,\n error TEXT,\n created_at INTEGER NOT NULL,\n started_at INTEGER,\n completed_at INTEGER\n );\n\n CREATE TABLE IF NOT EXISTS brain_events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n run_id TEXT NOT NULL,\n event_type TEXT NOT NULL,\n event_data TEXT NOT NULL,\n created_at INTEGER NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_brain_events_run\n ON brain_events(run_id, id);\n\n CREATE INDEX IF NOT EXISTS idx_brain_status -- Renamed index\n ON brain_runs(brain_title, status);\n\n CREATE INDEX IF NOT EXISTS idx_brain_time -- Renamed index\n ON brain_runs(created_at DESC);\n\n CREATE TABLE IF NOT EXISTS webhook_registrations (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n slug TEXT NOT NULL,\n identifier TEXT NOT NULL,\n brain_run_id TEXT NOT NULL,\n created_at INTEGER NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_webhook_lookup\n ON webhook_registrations(slug, identifier);\n\n CREATE INDEX IF NOT EXISTS idx_webhook_brain_run\n ON webhook_registrations(brain_run_id);\n\n CREATE TABLE IF NOT EXISTS page_registrations (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n slug TEXT NOT NULL UNIQUE,\n brain_run_id TEXT NOT NULL,\n persist INTEGER NOT NULL DEFAULT 0,\n created_at INTEGER NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_page_brain_run\n ON page_registrations(brain_run_id);\n\n CREATE INDEX IF NOT EXISTS idx_page_persist\n ON page_registrations(persist);\n ");
261
261
  return _this;
262
262
  }
263
263
  _create_class(MonitorDO, [
@@ -265,15 +265,31 @@ export var MonitorDO = /*#__PURE__*/ function(DurableObject) {
265
265
  key: "handleBrainEvent",
266
266
  value: function handleBrainEvent(event) {
267
267
  if (event.type === BRAIN_EVENTS.START || event.type === BRAIN_EVENTS.RESTART || event.type === BRAIN_EVENTS.COMPLETE || event.type === BRAIN_EVENTS.ERROR || event.type === BRAIN_EVENTS.CANCELLED) {
268
+ var brainRunId = event.brainRunId;
268
269
  var currentTime = Date.now();
270
+ // Store the event in the event stream (append-only)
271
+ this.storage.exec("INSERT INTO brain_events (run_id, event_type, event_data, created_at) VALUES (?, ?, ?, ?)", brainRunId, event.type, JSON.stringify(event), currentTime);
272
+ // Load all events for this brain run and create state machine with history
273
+ var storedEvents = this.storage.exec("SELECT event_data FROM brain_events WHERE run_id = ? ORDER BY id", brainRunId).toArray();
274
+ var events = storedEvents.map(function(param) {
275
+ var event_data = param.event_data;
276
+ return JSON.parse(event_data);
277
+ });
278
+ var machine = createBrainExecutionMachine({
279
+ events: events
280
+ });
281
+ // Use the state machine's computed status (depth-aware)
282
+ var status = machine.context.status;
269
283
  var startTime = event.type === BRAIN_EVENTS.START || event.type === BRAIN_EVENTS.RESTART ? currentTime : null;
270
- var completeTime = event.type === BRAIN_EVENTS.COMPLETE || event.type === BRAIN_EVENTS.ERROR || event.type === BRAIN_EVENTS.CANCELLED ? currentTime : null;
284
+ // Only set completedAt when status is terminal
285
+ var isTerminalStatus = status === STATUS.COMPLETE || status === STATUS.ERROR || status === STATUS.CANCELLED;
286
+ var completeTime = isTerminalStatus ? currentTime : null;
271
287
  var error = event.type === BRAIN_EVENTS.ERROR ? JSON.stringify(event.error) : null;
272
- // Update SQL insert/update with new column names, read from existing event fields
273
- this.storage.exec("\n INSERT INTO brain_runs (\n run_id, brain_title, brain_description, type, status,\n options, error, created_at, started_at, completed_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(run_id) DO UPDATE SET\n type = excluded.type,\n status = excluded.status,\n error = excluded.error,\n completed_at = excluded.completed_at\n ", event.brainRunId, event.brainTitle, event.brainDescription || null, event.type, event.status, JSON.stringify(event.options || {}), error, currentTime, startTime, completeTime);
288
+ // Update the brain_runs summary table
289
+ this.storage.exec("\n INSERT INTO brain_runs (\n run_id, brain_title, brain_description, type, status,\n options, error, created_at, started_at, completed_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(run_id) DO UPDATE SET\n type = excluded.type,\n status = excluded.status,\n error = excluded.error,\n completed_at = excluded.completed_at\n ", brainRunId, event.brainTitle, event.brainDescription || null, event.type, status, JSON.stringify(event.options || {}), error, currentTime, startTime, completeTime);
274
290
  // Clean up registrations when brain terminates
275
- if (event.type === BRAIN_EVENTS.COMPLETE || event.type === BRAIN_EVENTS.ERROR || event.type === BRAIN_EVENTS.CANCELLED) {
276
- this.clearWebhookRegistrations(event.brainRunId);
291
+ if (isTerminalStatus) {
292
+ this.clearWebhookRegistrations(brainRunId);
277
293
  // Note: Non-persistent page cleanup is handled by PageAdapter which has access to R2
278
294
  // We just track pages here, actual R2 deletion happens in the adapter
279
295
  }
@@ -0,0 +1,7 @@
1
+ import { Hono } from 'hono';
2
+ import type { Bindings } from './types.js';
3
+ declare const brains: Hono<{
4
+ Bindings: Bindings;
5
+ }, import("hono/types").BlankSchema, "/">;
6
+ export default brains;
7
+ //# sourceMappingURL=brains.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brains.d.ts","sourceRoot":"","sources":["../../../src/api/brains.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAgB,MAAM,MAAM,CAAC;AAK1C,OAAO,KAAK,EAAE,QAAQ,EAAiD,MAAM,YAAY,CAAC;AAE1F,QAAA,MAAM,MAAM;cAAwB,QAAQ;yCAAK,CAAC;AAwelD,eAAe,MAAM,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { Hono } from 'hono';
2
+ import type { Bindings } from './types.js';
3
+ declare const bundle: Hono<{
4
+ Bindings: Bindings;
5
+ }, import("hono/types").BlankSchema, "/">;
6
+ export default bundle;
7
+ //# sourceMappingURL=bundle.d.ts.map