@positronic/cloudflare 0.0.56 → 0.0.57

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 (39) hide show
  1. package/dist/src/api/auth-middleware.js +466 -0
  2. package/dist/src/api/brains.js +160 -0
  3. package/dist/src/api/index.js +22 -1
  4. package/dist/src/api/users.js +582 -0
  5. package/dist/src/api/webhooks/coordination.js +43 -8
  6. package/dist/src/api/webhooks/index.js +2 -2
  7. package/dist/src/api/webhooks/system.js +2 -2
  8. package/dist/src/auth-do.js +455 -0
  9. package/dist/src/brain-runner-do.js +255 -97
  10. package/dist/src/event-loader.js +301 -0
  11. package/dist/src/index.js +1 -0
  12. package/dist/src/monitor-do.js +39 -19
  13. package/dist/src/signal-provider.js +179 -0
  14. package/dist/src/sqlite-adapter.js +196 -13
  15. package/dist/types/api/auth-middleware.d.ts +19 -0
  16. package/dist/types/api/auth-middleware.d.ts.map +1 -0
  17. package/dist/types/api/brains.d.ts.map +1 -1
  18. package/dist/types/api/index.d.ts.map +1 -1
  19. package/dist/types/api/types.d.ts +3 -0
  20. package/dist/types/api/types.d.ts.map +1 -1
  21. package/dist/types/api/users.d.ts +7 -0
  22. package/dist/types/api/users.d.ts.map +1 -0
  23. package/dist/types/api/webhooks/coordination.d.ts +7 -3
  24. package/dist/types/api/webhooks/coordination.d.ts.map +1 -1
  25. package/dist/types/auth-do.d.ts +37 -0
  26. package/dist/types/auth-do.d.ts.map +1 -0
  27. package/dist/types/brain-runner-do.d.ts +29 -2
  28. package/dist/types/brain-runner-do.d.ts.map +1 -1
  29. package/dist/types/event-loader.d.ts +25 -0
  30. package/dist/types/event-loader.d.ts.map +1 -0
  31. package/dist/types/index.d.ts +1 -0
  32. package/dist/types/index.d.ts.map +1 -1
  33. package/dist/types/monitor-do.d.ts +1 -0
  34. package/dist/types/monitor-do.d.ts.map +1 -1
  35. package/dist/types/signal-provider.d.ts +11 -0
  36. package/dist/types/signal-provider.d.ts.map +1 -0
  37. package/dist/types/sqlite-adapter.d.ts +6 -3
  38. package/dist/types/sqlite-adapter.d.ts.map +1 -1
  39. package/package.json +5 -4
@@ -289,11 +289,13 @@ function _ts_generator(thisArg, body) {
289
289
  };
290
290
  }
291
291
  }
292
- import { STATUS, BRAIN_EVENTS, createBrainExecutionMachine, sendEvent, getCompletedSteps } from '@positronic/core';
292
+ import { STATUS, BRAIN_EVENTS, createBrainExecutionMachine, sendEvent } from '@positronic/core';
293
293
  import { DurableObject } from 'cloudflare:workers';
294
+ import { CloudflareSignalProvider } from './signal-provider.js';
294
295
  import { BrainRunSQLiteAdapter } from './sqlite-adapter.js';
295
296
  import { WebhookAdapter } from './webhook-adapter.js';
296
297
  import { PageAdapter } from './page-adapter.js';
298
+ import { EventLoader } from './event-loader.js';
297
299
  import { createPagesService } from './pages-service.js';
298
300
  import { CloudflareR2Loader } from './r2-loader.js';
299
301
  import { createResources } from '@positronic/core';
@@ -436,6 +438,8 @@ var ScheduleAdapter = /*#__PURE__*/ function() {
436
438
  ]);
437
439
  return ScheduleAdapter;
438
440
  }();
441
+ // SQL to initialize the signals table
442
+ var signalsTableSQL = "\nCREATE TABLE IF NOT EXISTS brain_signals (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n signal_type TEXT NOT NULL,\n content TEXT,\n queued_at INTEGER NOT NULL\n);\n";
439
443
  export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
440
444
  "use strict";
441
445
  _inherits(BrainRunnerDO, DurableObject);
@@ -445,13 +449,99 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
445
449
  _this = _call_super(this, BrainRunnerDO, [
446
450
  state,
447
451
  env
448
- ]), _define_property(_this, "sql", void 0), _define_property(_this, "brainRunId", void 0), _define_property(_this, "eventStreamAdapter", new EventStreamAdapter()), _define_property(_this, "abortController", null);
452
+ ]), _define_property(_this, "sql", void 0), _define_property(_this, "brainRunId", void 0), _define_property(_this, "eventStreamAdapter", new EventStreamAdapter()), _define_property(_this, "abortController", null), _define_property(_this, "pageAdapter", null), _define_property(_this, "signalsTableInitialized", false);
449
453
  _this.sql = state.storage.sql;
450
454
  _this.brainRunId = state.id.toString();
451
455
  _this.env = env;
452
456
  return _this;
453
457
  }
454
458
  _create_class(BrainRunnerDO, [
459
+ {
460
+ key: "initializeSignalsTable",
461
+ value: function initializeSignalsTable() {
462
+ if (!this.signalsTableInitialized) {
463
+ this.sql.exec(signalsTableSQL);
464
+ this.signalsTableInitialized = true;
465
+ }
466
+ }
467
+ },
468
+ {
469
+ key: "queueSignal",
470
+ value: /**
471
+ * Queue a signal for this brain run.
472
+ * Returns the queued signal with timestamp.
473
+ * For WEBHOOK_RESPONSE signals, the response object is JSON-stringified and stored in content.
474
+ */ function queueSignal(signal) {
475
+ return _async_to_generator(function() {
476
+ var _signal_content, content, queuedAt;
477
+ return _ts_generator(this, function(_state) {
478
+ this.initializeSignalsTable();
479
+ // For WEBHOOK_RESPONSE, store the response as JSON in the content field
480
+ content = signal.type === 'WEBHOOK_RESPONSE' && signal.response ? JSON.stringify(signal.response) : (_signal_content = signal.content) !== null && _signal_content !== void 0 ? _signal_content : null;
481
+ queuedAt = Date.now();
482
+ this.sql.exec("INSERT INTO brain_signals (signal_type, content, queued_at) VALUES (?, ?, ?)", signal.type, content, queuedAt);
483
+ return [
484
+ 2,
485
+ {
486
+ type: signal.type,
487
+ queuedAt: queuedAt
488
+ }
489
+ ];
490
+ });
491
+ }).call(this);
492
+ }
493
+ },
494
+ {
495
+ /**
496
+ * Get and consume (delete) pending signals.
497
+ * Signals are returned in priority order: KILL > PAUSE > WEBHOOK_RESPONSE > RESUME > USER_MESSAGE
498
+ * @param filter 'CONTROL' returns only KILL/PAUSE, 'WEBHOOK' returns only WEBHOOK_RESPONSE, 'ALL' includes all signal types
499
+ */ key: "getAndConsumeSignals",
500
+ value: function getAndConsumeSignals(filter) {
501
+ this.initializeSignalsTable();
502
+ // Query signals ordered by priority
503
+ var whereClause = '';
504
+ if (filter === 'CONTROL') {
505
+ whereClause = "WHERE signal_type IN ('KILL', 'PAUSE')";
506
+ } else if (filter === 'WEBHOOK') {
507
+ whereClause = "WHERE signal_type = 'WEBHOOK_RESPONSE'";
508
+ }
509
+ var results = this.sql.exec("SELECT id, signal_type, content FROM brain_signals ".concat(whereClause, "\n ORDER BY CASE signal_type\n WHEN 'KILL' THEN 1\n WHEN 'PAUSE' THEN 2\n WHEN 'WEBHOOK_RESPONSE' THEN 3\n WHEN 'RESUME' THEN 4\n WHEN 'USER_MESSAGE' THEN 5\n END")).toArray();
510
+ if (results.length === 0) {
511
+ return [];
512
+ }
513
+ // Delete the returned signals (consume them)
514
+ var ids = results.map(function(r) {
515
+ return r.id;
516
+ });
517
+ this.sql.exec("DELETE FROM brain_signals WHERE id IN (".concat(ids.join(','), ")"));
518
+ // Convert to BrainSignal format
519
+ return results.map(function(r) {
520
+ if (r.signal_type === 'USER_MESSAGE') {
521
+ var _r_content;
522
+ return {
523
+ type: 'USER_MESSAGE',
524
+ content: (_r_content = r.content) !== null && _r_content !== void 0 ? _r_content : ''
525
+ };
526
+ }
527
+ if (r.signal_type === 'WEBHOOK_RESPONSE') {
528
+ var _r_content1;
529
+ return {
530
+ type: 'WEBHOOK_RESPONSE',
531
+ response: JSON.parse((_r_content1 = r.content) !== null && _r_content1 !== void 0 ? _r_content1 : '{}')
532
+ };
533
+ }
534
+ if (r.signal_type === 'RESUME') {
535
+ return {
536
+ type: 'RESUME'
537
+ };
538
+ }
539
+ return {
540
+ type: r.signal_type
541
+ };
542
+ });
543
+ }
544
+ },
455
545
  {
456
546
  key: "loadResourcesFromR2",
457
547
  value: function loadResourcesFromR2() {
@@ -633,7 +723,7 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
633
723
  * SQLite state is missing (zombie brain scenario).
634
724
  */ function kill(brainRunId, brainTitle) {
635
725
  return _async_to_generator(function() {
636
- var monitorStub, actualBrainRunId, actualBrainTitle, startEvent, sql, startEventResult, existingRun, cancelledEvent;
726
+ var monitorStub, actualBrainRunId, actualBrainTitle, startEvent, eventLoader, err, existingRun, activeStatuses, cancelledEvent, _this_pageAdapter, pageAdapter;
637
727
  return _ts_generator(this, function(_state) {
638
728
  switch(_state.label){
639
729
  case 0:
@@ -654,21 +744,43 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
654
744
  actualBrainRunId = brainRunId;
655
745
  actualBrainTitle = brainTitle;
656
746
  startEvent = null;
657
- // Only query SQLite if we don't have the brainRunId from the API
658
- if (!actualBrainRunId) {
659
- sql = this.sql;
660
- try {
661
- startEventResult = sql.exec("SELECT serialized_event FROM brain_events WHERE event_type IN (?, ?) ORDER BY event_id DESC LIMIT 1", BRAIN_EVENTS.START, BRAIN_EVENTS.RESTART).toArray();
662
- if (startEventResult.length > 0) {
663
- startEvent = JSON.parse(startEventResult[0].serialized_event);
664
- actualBrainRunId = startEvent.brainRunId;
665
- actualBrainTitle = startEvent.brainTitle;
666
- }
667
- } catch (err) {
668
- // Table doesn't exist - brain was killed before any events were written to DO's SQLite
669
- console.log("[DO ".concat(this.brainRunId, "] kill() could not query brain_events (table may not exist)"));
670
- }
747
+ if (!!actualBrainRunId) return [
748
+ 3,
749
+ 4
750
+ ];
751
+ _state.label = 1;
752
+ case 1:
753
+ _state.trys.push([
754
+ 1,
755
+ 3,
756
+ ,
757
+ 4
758
+ ]);
759
+ // Use EventLoader to handle R2 overflow transparently
760
+ eventLoader = new EventLoader(this.sql, this.env.RESOURCES_BUCKET);
761
+ return [
762
+ 4,
763
+ eventLoader.loadEventByType(BRAIN_EVENTS.START, 'DESC')
764
+ ];
765
+ case 2:
766
+ startEvent = _state.sent();
767
+ if (startEvent) {
768
+ actualBrainRunId = startEvent.brainRunId;
769
+ actualBrainTitle = startEvent.brainTitle;
671
770
  }
771
+ return [
772
+ 3,
773
+ 4
774
+ ];
775
+ case 3:
776
+ err = _state.sent();
777
+ // Table doesn't exist - brain was killed before any events were written to DO's SQLite
778
+ console.log("[DO ".concat(this.brainRunId, "] kill() could not query brain_events (table may not exist)"));
779
+ return [
780
+ 3,
781
+ 4
782
+ ];
783
+ case 4:
672
784
  // If we still don't have a brainRunId, we can't proceed
673
785
  if (!actualBrainRunId) {
674
786
  return [
@@ -683,7 +795,7 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
683
795
  4,
684
796
  monitorStub.getLastEvent(actualBrainRunId)
685
797
  ];
686
- case 1:
798
+ case 5:
687
799
  existingRun = _state.sent();
688
800
  if (!existingRun) {
689
801
  return [
@@ -695,7 +807,13 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
695
807
  ];
696
808
  }
697
809
  // If already completed/cancelled/errored, nothing to do
698
- if (existingRun.status !== STATUS.RUNNING) {
810
+ // Active statuses that can be killed: RUNNING, PAUSED, WAITING
811
+ activeStatuses = [
812
+ STATUS.RUNNING,
813
+ STATUS.PAUSED,
814
+ STATUS.WAITING
815
+ ];
816
+ if (!activeStatuses.includes(existingRun.status)) {
699
817
  return [
700
818
  2,
701
819
  {
@@ -704,7 +822,7 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
704
822
  }
705
823
  ];
706
824
  }
707
- // Emit CANCELLED event to MonitorDO
825
+ // Emit CANCELLED event
708
826
  cancelledEvent = {
709
827
  type: BRAIN_EVENTS.CANCELLED,
710
828
  status: STATUS.CANCELLED,
@@ -713,11 +831,22 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
713
831
  brainRunId: actualBrainRunId,
714
832
  options: (startEvent === null || startEvent === void 0 ? void 0 : startEvent.options) || {}
715
833
  };
834
+ // Dispatch to PageAdapter for cleanup (deletes non-persistent pages from R2)
835
+ // This is needed because when a brain is paused (waiting for webhook), the BrainRunner
836
+ // has already returned and adapters aren't receiving events through the normal pipeline.
837
+ // For zombie brains (server restarted), pageAdapter may be null, so we create one on the fly.
838
+ pageAdapter = (_this_pageAdapter = this.pageAdapter) !== null && _this_pageAdapter !== void 0 ? _this_pageAdapter : new PageAdapter(monitorStub, this.env.RESOURCES_BUCKET);
839
+ return [
840
+ 4,
841
+ pageAdapter.dispatch(cancelledEvent)
842
+ ];
843
+ case 6:
844
+ _state.sent();
716
845
  return [
717
846
  4,
718
847
  monitorStub.handleBrainEvent(cancelledEvent)
719
848
  ];
720
- case 2:
849
+ case 7:
721
850
  _state.sent();
722
851
  return [
723
852
  2,
@@ -735,7 +864,7 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
735
864
  key: "start",
736
865
  value: function start(brainTitle, brainRunId, initialData) {
737
866
  return _async_to_generator(function() {
738
- var _this, sql, resolution, brainToRun, sqliteAdapter, eventStreamAdapter, monitorDOStub, monitorAdapter, scheduleAdapter, webhookAdapter, pageAdapter, env, pagesService, r2Resources, runnerWithResources, options, initialState;
867
+ var _this, sql, resolution, brainToRun, sqliteAdapter, eventStreamAdapter, monitorDOStub, monitorAdapter, scheduleAdapter, webhookAdapter, env, pagesService, r2Resources, runnerWithResources, signalProvider, options, initialState;
739
868
  return _ts_generator(this, function(_state) {
740
869
  switch(_state.label){
741
870
  case 0:
@@ -759,13 +888,13 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
759
888
  if (!brainToRun) {
760
889
  throw new Error("Brain ".concat(brainTitle, " resolved but brain object is missing"));
761
890
  }
762
- sqliteAdapter = new BrainRunSQLiteAdapter(sql);
891
+ sqliteAdapter = new BrainRunSQLiteAdapter(sql, this.env.RESOURCES_BUCKET, brainRunId);
763
892
  eventStreamAdapter = this.eventStreamAdapter;
764
893
  monitorDOStub = this.env.MONITOR_DO.get(this.env.MONITOR_DO.idFromName('singleton'));
765
894
  monitorAdapter = new MonitorAdapter(monitorDOStub);
766
895
  scheduleAdapter = new ScheduleAdapter(this.env.SCHEDULE_DO.get(this.env.SCHEDULE_DO.idFromName('singleton')));
767
896
  webhookAdapter = new WebhookAdapter(monitorDOStub);
768
- pageAdapter = new PageAdapter(monitorDOStub, this.env.RESOURCES_BUCKET);
897
+ this.pageAdapter = new PageAdapter(monitorDOStub, this.env.RESOURCES_BUCKET);
769
898
  // Create runtime environment with origin and secrets
770
899
  env = this.buildRuntimeEnv();
771
900
  // Create pages service for brain to use
@@ -787,6 +916,11 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
787
916
  }
788
917
  // Add pages service and runtime env
789
918
  runnerWithResources = runnerWithResources.withPages(pagesService).withEnv(env);
919
+ // Add signal provider for signal handling
920
+ signalProvider = new CloudflareSignalProvider(function(filter) {
921
+ return _this.getAndConsumeSignals(filter);
922
+ });
923
+ runnerWithResources = runnerWithResources.withSignalProvider(signalProvider);
790
924
  // Extract options from initialData if present
791
925
  options = initialData === null || initialData === void 0 ? void 0 : initialData.options;
792
926
  initialState = initialData && !initialData.options ? initialData : {};
@@ -798,7 +932,7 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
798
932
  monitorAdapter,
799
933
  scheduleAdapter,
800
934
  webhookAdapter,
801
- pageAdapter
935
+ this.pageAdapter
802
936
  ]).run(brainToRun, _object_spread_props(_object_spread({
803
937
  initialState: initialState,
804
938
  brainRunId: brainRunId
@@ -822,10 +956,14 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
822
956
  }
823
957
  },
824
958
  {
825
- key: "resume",
826
- value: function resume(brainRunId, webhookResponse) {
959
+ key: "wakeUp",
960
+ value: /**
961
+ * Wake up (resume) a brain from a previous execution point.
962
+ * Webhook response data comes from signals, not as a parameter.
963
+ * This method reconstructs state and calls BrainRunner.resume().
964
+ */ function wakeUp(brainRunId) {
827
965
  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, agentEventsResult, agentEvents, sqliteAdapter, eventStreamAdapter, monitorDOStub, monitorAdapter, scheduleAdapter, webhookAdapter, pageAdapter, env, pagesService, r2Resources, runnerWithResources;
966
+ var _this, sql, eventLoader, startEvent, brainTitle, initialState, resolution, brainToRun, allEvents, machine, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, event, sqliteAdapter, eventStreamAdapter, monitorDOStub, monitorAdapter, scheduleAdapter, webhookAdapter, env, pagesService, r2Resources, runnerWithResources, signalProvider;
829
967
  return _ts_generator(this, function(_state) {
830
968
  switch(_state.label){
831
969
  case 0:
@@ -834,17 +972,21 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
834
972
  if (!manifest) {
835
973
  throw new Error('Runtime manifest not initialized');
836
974
  }
837
- // Get the initial state and brain title by loading the FIRST START or RESTART event
838
- // (the outer brain's event, not an inner brain's)
839
- startEventResult = sql.exec("SELECT serialized_event FROM brain_events WHERE event_type IN (?, ?) ORDER BY event_id ASC LIMIT 1", BRAIN_EVENTS.START, BRAIN_EVENTS.RESTART).toArray();
840
- if (startEventResult.length === 0) {
841
- throw new Error("No START or RESTART event found for brain run ".concat(brainRunId));
975
+ // Use EventLoader to load events (handles R2 overflow transparently)
976
+ eventLoader = new EventLoader(sql, this.env.RESOURCES_BUCKET);
977
+ return [
978
+ 4,
979
+ eventLoader.loadEventByType(BRAIN_EVENTS.START, 'ASC')
980
+ ];
981
+ case 1:
982
+ startEvent = _state.sent();
983
+ if (!startEvent) {
984
+ throw new Error("No START event found for brain run ".concat(brainRunId));
842
985
  }
843
- startEvent = JSON.parse(startEventResult[0].serialized_event);
844
986
  brainTitle = startEvent.brainTitle;
845
987
  initialState = startEvent.initialState || {};
846
988
  if (!brainTitle) {
847
- throw new Error("Brain title not found in START/RESTART event for brain run ".concat(brainRunId));
989
+ throw new Error("Brain title not found in START event for brain run ".concat(brainRunId));
848
990
  }
849
991
  // Resolve the brain using the title
850
992
  resolution = manifest.resolve(brainTitle);
@@ -860,17 +1002,20 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
860
1002
  if (!brainToRun) {
861
1003
  throw new Error("Brain ".concat(brainTitle, " resolved but brain object is missing"));
862
1004
  }
863
- // Load all events and feed them to the state machine to build nested initialCompletedSteps
864
- allEventsResult = sql.exec("SELECT serialized_event FROM brain_events ORDER BY event_id ASC").toArray();
865
- // Create state machine and feed all historical events to reconstruct step hierarchy
1005
+ return [
1006
+ 4,
1007
+ eventLoader.loadAllEvents()
1008
+ ];
1009
+ case 2:
1010
+ allEvents = _state.sent();
1011
+ // Create state machine and feed all historical events to reconstruct execution state
866
1012
  machine = createBrainExecutionMachine({
867
1013
  initialState: initialState
868
1014
  });
869
1015
  _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
870
1016
  try {
871
- for(_iterator = allEventsResult[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
872
- row = _step.value;
873
- event = JSON.parse(row.serialized_event);
1017
+ for(_iterator = allEvents[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1018
+ event = _step.value;
874
1019
  sendEvent(machine, event);
875
1020
  }
876
1021
  } catch (err) {
@@ -887,20 +1032,13 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
887
1032
  }
888
1033
  }
889
1034
  }
890
- // Get the reconstructed step hierarchy from the state machine
891
- initialCompletedSteps = getCompletedSteps(machine);
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
- return JSON.parse(row.serialized_event);
896
- });
897
- sqliteAdapter = new BrainRunSQLiteAdapter(sql);
1035
+ sqliteAdapter = new BrainRunSQLiteAdapter(sql, this.env.RESOURCES_BUCKET, brainRunId);
898
1036
  eventStreamAdapter = this.eventStreamAdapter;
899
1037
  monitorDOStub = this.env.MONITOR_DO.get(this.env.MONITOR_DO.idFromName('singleton'));
900
1038
  monitorAdapter = new MonitorAdapter(monitorDOStub);
901
1039
  scheduleAdapter = new ScheduleAdapter(this.env.SCHEDULE_DO.get(this.env.SCHEDULE_DO.idFromName('singleton')));
902
1040
  webhookAdapter = new WebhookAdapter(monitorDOStub);
903
- pageAdapter = new PageAdapter(monitorDOStub, this.env.RESOURCES_BUCKET);
1041
+ this.pageAdapter = new PageAdapter(monitorDOStub, this.env.RESOURCES_BUCKET);
904
1042
  // Create runtime environment with origin and secrets
905
1043
  env = this.buildRuntimeEnv();
906
1044
  // Create pages service for brain to use
@@ -912,7 +1050,7 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
912
1050
  4,
913
1051
  this.loadResourcesFromR2()
914
1052
  ];
915
- case 1:
1053
+ case 3:
916
1054
  r2Resources = _state.sent();
917
1055
  runnerWithResources = brainRunner;
918
1056
  if (r2Resources) {
@@ -920,6 +1058,12 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
920
1058
  }
921
1059
  // Add pages service and runtime env
922
1060
  runnerWithResources = runnerWithResources.withPages(pagesService).withEnv(env);
1061
+ // Add signal provider for signal handling
1062
+ // Webhook response comes from signals, consumed by the brain during execution
1063
+ signalProvider = new CloudflareSignalProvider(function(filter) {
1064
+ return _this.getAndConsumeSignals(filter);
1065
+ });
1066
+ runnerWithResources = runnerWithResources.withSignalProvider(signalProvider);
923
1067
  // Create abort controller for this run
924
1068
  this.abortController = new AbortController();
925
1069
  runnerWithResources.withAdapters([
@@ -928,16 +1072,13 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
928
1072
  monitorAdapter,
929
1073
  scheduleAdapter,
930
1074
  webhookAdapter,
931
- pageAdapter
932
- ]).run(brainToRun, {
933
- initialState: initialState,
934
- initialCompletedSteps: initialCompletedSteps,
1075
+ this.pageAdapter
1076
+ ]).resume(brainToRun, {
1077
+ machine: machine,
935
1078
  brainRunId: brainRunId,
936
- response: webhookResponse,
937
- signal: this.abortController.signal,
938
- agentEvents: agentEvents
1079
+ signal: this.abortController.signal
939
1080
  }).catch(function(err) {
940
- console.error("[DO ".concat(brainRunId, "] BrainRunner resume failed:"), err);
1081
+ console.error("[DO ".concat(brainRunId, "] BrainRunner wakeUp failed:"), err);
941
1082
  throw err;
942
1083
  }).finally(function() {
943
1084
  _this.abortController = null;
@@ -954,7 +1095,7 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
954
1095
  key: "fetch",
955
1096
  value: function fetch(request) {
956
1097
  return _async_to_generator(function() {
957
- var _this, sql, eventStreamAdapter, brainRunId, url, encoder, sendEvent, streamController, stream;
1098
+ var _this, sql, eventStreamAdapter, brainRunId, url, encoder, sendEvent, streamController, eventLoader, stream;
958
1099
  return _ts_generator(this, function(_state) {
959
1100
  _this = this, sql = _this.sql, eventStreamAdapter = _this.eventStreamAdapter, brainRunId = _this.brainRunId;
960
1101
  url = new URL(request.url);
@@ -965,55 +1106,72 @@ export var BrainRunnerDO = /*#__PURE__*/ function(DurableObject) {
965
1106
  streamController = null;
966
1107
  try {
967
1108
  if (url.pathname === '/watch') {
1109
+ // Create EventLoader for loading historical events (handles R2 overflow)
1110
+ eventLoader = new EventLoader(sql, this.env.RESOURCES_BUCKET);
968
1111
  stream = new ReadableStream({
969
- start: function start(controller) {
1112
+ start: function(controller) {
970
1113
  return _async_to_generator(function() {
971
- var existingEventsSql, existingEventsResult, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, row, event;
1114
+ var existingEvents, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, event, err1;
972
1115
  return _ts_generator(this, function(_state) {
973
- streamController = controller;
974
- try {
975
- streamController = controller;
976
- existingEventsSql = "\n SELECT serialized_event\n FROM brain_events\n ORDER BY event_id ASC;\n ";
977
- existingEventsResult = sql.exec(existingEventsSql).toArray();
978
- _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
979
- try {
980
- for(_iterator = existingEventsResult[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
981
- row = _step.value;
982
- try {
983
- event = JSON.parse(row.serialized_event);
984
- sendEvent(controller, event);
985
- } catch (parseError) {
986
- console.error("[DO ".concat(brainRunId, " WATCH] Failed to parse historical event JSON: ").concat(row.serialized_event), parseError);
987
- }
988
- }
989
- } catch (err) {
990
- _didIteratorError = true;
991
- _iteratorError = err;
992
- } finally{
1116
+ switch(_state.label){
1117
+ case 0:
1118
+ streamController = controller;
1119
+ _state.label = 1;
1120
+ case 1:
1121
+ _state.trys.push([
1122
+ 1,
1123
+ 3,
1124
+ ,
1125
+ 4
1126
+ ]);
1127
+ return [
1128
+ 4,
1129
+ eventLoader.loadAllEvents()
1130
+ ];
1131
+ case 2:
1132
+ existingEvents = _state.sent();
1133
+ _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
993
1134
  try {
994
- if (!_iteratorNormalCompletion && _iterator.return != null) {
995
- _iterator.return();
1135
+ for(_iterator = existingEvents[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1136
+ event = _step.value;
1137
+ sendEvent(controller, event);
996
1138
  }
1139
+ } catch (err) {
1140
+ _didIteratorError = true;
1141
+ _iteratorError = err;
997
1142
  } finally{
998
- if (_didIteratorError) {
999
- throw _iteratorError;
1143
+ try {
1144
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1145
+ _iterator.return();
1146
+ }
1147
+ } finally{
1148
+ if (_didIteratorError) {
1149
+ throw _iteratorError;
1150
+ }
1000
1151
  }
1001
1152
  }
1002
- }
1003
- eventStreamAdapter.subscribe(controller);
1004
- } catch (err) {
1005
- console.error("[DO ".concat(brainRunId, " WATCH] Error during stream start:"), err);
1006
- controller.close();
1007
- eventStreamAdapter.unsubscribe(streamController);
1008
- throw err;
1153
+ eventStreamAdapter.subscribe(controller);
1154
+ return [
1155
+ 3,
1156
+ 4
1157
+ ];
1158
+ case 3:
1159
+ err1 = _state.sent();
1160
+ console.error("[DO ".concat(brainRunId, " WATCH] Error during stream start:"), err1);
1161
+ controller.close();
1162
+ if (streamController) {
1163
+ eventStreamAdapter.unsubscribe(streamController);
1164
+ }
1165
+ throw err1;
1166
+ case 4:
1167
+ return [
1168
+ 2
1169
+ ];
1009
1170
  }
1010
- return [
1011
- 2
1012
- ];
1013
1171
  });
1014
1172
  })();
1015
1173
  },
1016
- cancel: function cancel(reason) {
1174
+ cancel: function(reason) {
1017
1175
  if (streamController) eventStreamAdapter.unsubscribe(streamController);
1018
1176
  }
1019
1177
  });