@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.
- package/dist/src/api/auth-middleware.js +466 -0
- package/dist/src/api/brains.js +160 -0
- package/dist/src/api/index.js +22 -1
- package/dist/src/api/users.js +582 -0
- package/dist/src/api/webhooks/coordination.js +43 -8
- package/dist/src/api/webhooks/index.js +2 -2
- package/dist/src/api/webhooks/system.js +2 -2
- package/dist/src/auth-do.js +455 -0
- package/dist/src/brain-runner-do.js +255 -97
- package/dist/src/event-loader.js +301 -0
- package/dist/src/index.js +1 -0
- package/dist/src/monitor-do.js +39 -19
- package/dist/src/signal-provider.js +179 -0
- package/dist/src/sqlite-adapter.js +196 -13
- package/dist/types/api/auth-middleware.d.ts +19 -0
- package/dist/types/api/auth-middleware.d.ts.map +1 -0
- package/dist/types/api/brains.d.ts.map +1 -1
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/api/types.d.ts +3 -0
- package/dist/types/api/types.d.ts.map +1 -1
- package/dist/types/api/users.d.ts +7 -0
- package/dist/types/api/users.d.ts.map +1 -0
- package/dist/types/api/webhooks/coordination.d.ts +7 -3
- package/dist/types/api/webhooks/coordination.d.ts.map +1 -1
- package/dist/types/auth-do.d.ts +37 -0
- package/dist/types/auth-do.d.ts.map +1 -0
- package/dist/types/brain-runner-do.d.ts +29 -2
- package/dist/types/brain-runner-do.d.ts.map +1 -1
- package/dist/types/event-loader.d.ts +25 -0
- package/dist/types/event-loader.d.ts.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/monitor-do.d.ts +1 -0
- package/dist/types/monitor-do.d.ts.map +1 -1
- package/dist/types/signal-provider.d.ts +11 -0
- package/dist/types/signal-provider.d.ts.map +1 -0
- package/dist/types/sqlite-adapter.d.ts +6 -3
- package/dist/types/sqlite-adapter.d.ts.map +1 -1
- 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
|
|
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,
|
|
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
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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,
|
|
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: "
|
|
826
|
-
value:
|
|
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,
|
|
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
|
-
//
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
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
|
|
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
|
-
|
|
864
|
-
|
|
865
|
-
|
|
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 =
|
|
872
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
]).
|
|
933
|
-
|
|
934
|
-
initialCompletedSteps: initialCompletedSteps,
|
|
1075
|
+
this.pageAdapter
|
|
1076
|
+
]).resume(brainToRun, {
|
|
1077
|
+
machine: machine,
|
|
935
1078
|
brainRunId: brainRunId,
|
|
936
|
-
|
|
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
|
|
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
|
|
1112
|
+
start: function(controller) {
|
|
970
1113
|
return _async_to_generator(function() {
|
|
971
|
-
var
|
|
1114
|
+
var existingEvents, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, event, err1;
|
|
972
1115
|
return _ts_generator(this, function(_state) {
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
_didIteratorError =
|
|
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
|
-
|
|
995
|
-
|
|
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
|
-
|
|
999
|
-
|
|
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
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
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
|
|
1174
|
+
cancel: function(reason) {
|
|
1017
1175
|
if (streamController) eventStreamAdapter.unsubscribe(streamController);
|
|
1018
1176
|
}
|
|
1019
1177
|
});
|