@positronic/cloudflare 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.
- package/dist/src/api/brains.js +1003 -0
- package/dist/src/api/bundle.js +204 -0
- package/dist/src/api/index.js +149 -0
- package/dist/src/api/pages.js +681 -0
- package/dist/src/api/resources.js +778 -0
- package/dist/src/api/secrets.js +707 -0
- package/dist/src/api/types.js +1 -0
- package/dist/src/api/webhooks/coordination.js +267 -0
- package/dist/src/api/webhooks/index.js +277 -0
- package/dist/src/api/webhooks/system.js +248 -0
- package/dist/src/brain-runner-do.js +5 -5
- package/dist/src/dev-server.js +202 -9
- package/dist/src/index.js +2 -4
- package/dist/types/api/brains.d.ts +7 -0
- package/dist/types/api/brains.d.ts.map +1 -0
- package/dist/types/api/bundle.d.ts +7 -0
- package/dist/types/api/bundle.d.ts.map +1 -0
- package/dist/types/api/index.d.ts +8 -0
- package/dist/types/api/index.d.ts.map +1 -0
- package/dist/types/api/pages.d.ts +7 -0
- package/dist/types/api/pages.d.ts.map +1 -0
- package/dist/types/api/resources.d.ts +7 -0
- package/dist/types/api/resources.d.ts.map +1 -0
- package/dist/types/api/secrets.d.ts +7 -0
- package/dist/types/api/secrets.d.ts.map +1 -0
- package/dist/types/{api.d.ts → api/types.d.ts} +15 -9
- package/dist/types/api/types.d.ts.map +1 -0
- package/dist/types/api/webhooks/coordination.d.ts +32 -0
- package/dist/types/api/webhooks/coordination.d.ts.map +1 -0
- package/dist/types/api/webhooks/index.d.ts +7 -0
- package/dist/types/api/webhooks/index.d.ts.map +1 -0
- package/dist/types/api/webhooks/system.d.ts +7 -0
- package/dist/types/api/webhooks/system.d.ts.map +1 -0
- package/dist/types/dev-server.d.ts +5 -0
- package/dist/types/dev-server.d.ts.map +1 -1
- package/dist/types/index.d.ts +3 -5
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +4 -4
- package/dist/src/api.js +0 -2839
- package/dist/types/api.d.ts.map +0 -1
|
@@ -0,0 +1,1003 @@
|
|
|
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 _instanceof(left, right) {
|
|
44
|
+
if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
|
|
45
|
+
return !!right[Symbol.hasInstance](left);
|
|
46
|
+
} else {
|
|
47
|
+
return left instanceof right;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function _object_spread(target) {
|
|
51
|
+
for(var i = 1; i < arguments.length; i++){
|
|
52
|
+
var source = arguments[i] != null ? arguments[i] : {};
|
|
53
|
+
var ownKeys = Object.keys(source);
|
|
54
|
+
if (typeof Object.getOwnPropertySymbols === "function") {
|
|
55
|
+
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
56
|
+
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
ownKeys.forEach(function(key) {
|
|
60
|
+
_define_property(target, key, source[key]);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return target;
|
|
64
|
+
}
|
|
65
|
+
function _ts_generator(thisArg, body) {
|
|
66
|
+
var f, y, t, _ = {
|
|
67
|
+
label: 0,
|
|
68
|
+
sent: function() {
|
|
69
|
+
if (t[0] & 1) throw t[1];
|
|
70
|
+
return t[1];
|
|
71
|
+
},
|
|
72
|
+
trys: [],
|
|
73
|
+
ops: []
|
|
74
|
+
}, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
75
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
|
|
76
|
+
return this;
|
|
77
|
+
}), g;
|
|
78
|
+
function verb(n) {
|
|
79
|
+
return function(v) {
|
|
80
|
+
return step([
|
|
81
|
+
n,
|
|
82
|
+
v
|
|
83
|
+
]);
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function step(op) {
|
|
87
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
88
|
+
while(g && (g = 0, op[0] && (_ = 0)), _)try {
|
|
89
|
+
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;
|
|
90
|
+
if (y = 0, t) op = [
|
|
91
|
+
op[0] & 2,
|
|
92
|
+
t.value
|
|
93
|
+
];
|
|
94
|
+
switch(op[0]){
|
|
95
|
+
case 0:
|
|
96
|
+
case 1:
|
|
97
|
+
t = op;
|
|
98
|
+
break;
|
|
99
|
+
case 4:
|
|
100
|
+
_.label++;
|
|
101
|
+
return {
|
|
102
|
+
value: op[1],
|
|
103
|
+
done: false
|
|
104
|
+
};
|
|
105
|
+
case 5:
|
|
106
|
+
_.label++;
|
|
107
|
+
y = op[1];
|
|
108
|
+
op = [
|
|
109
|
+
0
|
|
110
|
+
];
|
|
111
|
+
continue;
|
|
112
|
+
case 7:
|
|
113
|
+
op = _.ops.pop();
|
|
114
|
+
_.trys.pop();
|
|
115
|
+
continue;
|
|
116
|
+
default:
|
|
117
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
118
|
+
_ = 0;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
122
|
+
_.label = op[1];
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
126
|
+
_.label = t[1];
|
|
127
|
+
t = op;
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
if (t && _.label < t[2]) {
|
|
131
|
+
_.label = t[2];
|
|
132
|
+
_.ops.push(op);
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
if (t[2]) _.ops.pop();
|
|
136
|
+
_.trys.pop();
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
op = body.call(thisArg, _);
|
|
140
|
+
} catch (e) {
|
|
141
|
+
op = [
|
|
142
|
+
6,
|
|
143
|
+
e
|
|
144
|
+
];
|
|
145
|
+
y = 0;
|
|
146
|
+
} finally{
|
|
147
|
+
f = t = 0;
|
|
148
|
+
}
|
|
149
|
+
if (op[0] & 5) throw op[1];
|
|
150
|
+
return {
|
|
151
|
+
value: op[0] ? op[1] : void 0,
|
|
152
|
+
done: true
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
import { Hono } from 'hono';
|
|
157
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
158
|
+
import { parseCronExpression } from 'cron-schedule';
|
|
159
|
+
import Fuse from 'fuse.js';
|
|
160
|
+
import { getManifest } from '../brain-runner-do.js';
|
|
161
|
+
var brains = new Hono();
|
|
162
|
+
brains.post('/runs', function(context) {
|
|
163
|
+
return _async_to_generator(function() {
|
|
164
|
+
var requestBody, options, identifier, manifest, resolution, brain, brainRunId, namespace, doId, stub, initialData, brainTitle, response;
|
|
165
|
+
return _ts_generator(this, function(_state) {
|
|
166
|
+
switch(_state.label){
|
|
167
|
+
case 0:
|
|
168
|
+
return [
|
|
169
|
+
4,
|
|
170
|
+
context.req.json()
|
|
171
|
+
];
|
|
172
|
+
case 1:
|
|
173
|
+
requestBody = _state.sent();
|
|
174
|
+
options = requestBody.options;
|
|
175
|
+
// Support both identifier and brainTitle for backward compatibility
|
|
176
|
+
identifier = requestBody.identifier || requestBody.brainTitle;
|
|
177
|
+
if (!identifier) {
|
|
178
|
+
return [
|
|
179
|
+
2,
|
|
180
|
+
context.json({
|
|
181
|
+
error: 'Missing identifier or brainTitle in request body'
|
|
182
|
+
}, 400)
|
|
183
|
+
];
|
|
184
|
+
}
|
|
185
|
+
// Validate that the brain exists before starting it
|
|
186
|
+
manifest = getManifest();
|
|
187
|
+
if (!manifest) {
|
|
188
|
+
return [
|
|
189
|
+
2,
|
|
190
|
+
context.json({
|
|
191
|
+
error: 'Manifest not initialized'
|
|
192
|
+
}, 500)
|
|
193
|
+
];
|
|
194
|
+
}
|
|
195
|
+
// Resolve the identifier to find the brain
|
|
196
|
+
resolution = manifest.resolve(identifier);
|
|
197
|
+
if (resolution.matchType === 'none') {
|
|
198
|
+
return [
|
|
199
|
+
2,
|
|
200
|
+
context.json({
|
|
201
|
+
error: "Brain '".concat(identifier, "' not found")
|
|
202
|
+
}, 404)
|
|
203
|
+
];
|
|
204
|
+
}
|
|
205
|
+
if (resolution.matchType === 'multiple') {
|
|
206
|
+
return [
|
|
207
|
+
2,
|
|
208
|
+
context.json({
|
|
209
|
+
error: 'Multiple brains match the identifier',
|
|
210
|
+
matchType: 'multiple',
|
|
211
|
+
candidates: resolution.candidates
|
|
212
|
+
}, 409)
|
|
213
|
+
];
|
|
214
|
+
}
|
|
215
|
+
brain = resolution.brain;
|
|
216
|
+
brainRunId = uuidv4();
|
|
217
|
+
namespace = context.env.BRAIN_RUNNER_DO;
|
|
218
|
+
doId = namespace.idFromName(brainRunId);
|
|
219
|
+
stub = namespace.get(doId);
|
|
220
|
+
// Pass options to the brain runner if provided
|
|
221
|
+
initialData = options ? {
|
|
222
|
+
options: options
|
|
223
|
+
} : undefined;
|
|
224
|
+
// Get the actual brain title from the resolved brain
|
|
225
|
+
brainTitle = brain.title || identifier;
|
|
226
|
+
return [
|
|
227
|
+
4,
|
|
228
|
+
stub.start(brainTitle, brainRunId, initialData)
|
|
229
|
+
];
|
|
230
|
+
case 2:
|
|
231
|
+
_state.sent();
|
|
232
|
+
response = {
|
|
233
|
+
brainRunId: brainRunId
|
|
234
|
+
};
|
|
235
|
+
return [
|
|
236
|
+
2,
|
|
237
|
+
context.json(response, 201)
|
|
238
|
+
];
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
})();
|
|
242
|
+
});
|
|
243
|
+
brains.post('/runs/rerun', function(context) {
|
|
244
|
+
return _async_to_generator(function() {
|
|
245
|
+
var requestBody, runId, startsAt, stopsAfter, identifier, manifest, resolution, brain, monitorId, monitorStub, existingRun, newBrainRunId, namespace, doId, stub, rerunOptions, brainTitle, response;
|
|
246
|
+
return _ts_generator(this, function(_state) {
|
|
247
|
+
switch(_state.label){
|
|
248
|
+
case 0:
|
|
249
|
+
return [
|
|
250
|
+
4,
|
|
251
|
+
context.req.json()
|
|
252
|
+
];
|
|
253
|
+
case 1:
|
|
254
|
+
requestBody = _state.sent();
|
|
255
|
+
runId = requestBody.runId, startsAt = requestBody.startsAt, stopsAfter = requestBody.stopsAfter;
|
|
256
|
+
// Support both identifier and brainTitle for backward compatibility
|
|
257
|
+
identifier = requestBody.identifier || requestBody.brainTitle;
|
|
258
|
+
if (!identifier) {
|
|
259
|
+
return [
|
|
260
|
+
2,
|
|
261
|
+
context.json({
|
|
262
|
+
error: 'Missing identifier or brainTitle in request body'
|
|
263
|
+
}, 400)
|
|
264
|
+
];
|
|
265
|
+
}
|
|
266
|
+
// Validate that the brain exists
|
|
267
|
+
manifest = getManifest();
|
|
268
|
+
if (!manifest) {
|
|
269
|
+
return [
|
|
270
|
+
2,
|
|
271
|
+
context.json({
|
|
272
|
+
error: 'Manifest not initialized'
|
|
273
|
+
}, 500)
|
|
274
|
+
];
|
|
275
|
+
}
|
|
276
|
+
// Resolve the identifier to find the brain
|
|
277
|
+
resolution = manifest.resolve(identifier);
|
|
278
|
+
if (resolution.matchType === 'none') {
|
|
279
|
+
return [
|
|
280
|
+
2,
|
|
281
|
+
context.json({
|
|
282
|
+
error: "Brain '".concat(identifier, "' not found")
|
|
283
|
+
}, 404)
|
|
284
|
+
];
|
|
285
|
+
}
|
|
286
|
+
if (resolution.matchType === 'multiple') {
|
|
287
|
+
return [
|
|
288
|
+
2,
|
|
289
|
+
context.json({
|
|
290
|
+
error: 'Multiple brains match the identifier',
|
|
291
|
+
matchType: 'multiple',
|
|
292
|
+
candidates: resolution.candidates
|
|
293
|
+
}, 409)
|
|
294
|
+
];
|
|
295
|
+
}
|
|
296
|
+
brain = resolution.brain;
|
|
297
|
+
if (!runId) return [
|
|
298
|
+
3,
|
|
299
|
+
3
|
|
300
|
+
];
|
|
301
|
+
monitorId = context.env.MONITOR_DO.idFromName('singleton');
|
|
302
|
+
monitorStub = context.env.MONITOR_DO.get(monitorId);
|
|
303
|
+
return [
|
|
304
|
+
4,
|
|
305
|
+
monitorStub.getLastEvent(runId)
|
|
306
|
+
];
|
|
307
|
+
case 2:
|
|
308
|
+
existingRun = _state.sent();
|
|
309
|
+
if (!existingRun) {
|
|
310
|
+
return [
|
|
311
|
+
2,
|
|
312
|
+
context.json({
|
|
313
|
+
error: "Brain run '".concat(runId, "' not found")
|
|
314
|
+
}, 404)
|
|
315
|
+
];
|
|
316
|
+
}
|
|
317
|
+
_state.label = 3;
|
|
318
|
+
case 3:
|
|
319
|
+
// Create a new brain run with rerun parameters
|
|
320
|
+
newBrainRunId = uuidv4();
|
|
321
|
+
namespace = context.env.BRAIN_RUNNER_DO;
|
|
322
|
+
doId = namespace.idFromName(newBrainRunId);
|
|
323
|
+
stub = namespace.get(doId);
|
|
324
|
+
// Start the brain with rerun options
|
|
325
|
+
rerunOptions = _object_spread({}, runId && {
|
|
326
|
+
originalRunId: runId
|
|
327
|
+
}, startsAt !== undefined && {
|
|
328
|
+
startsAt: startsAt
|
|
329
|
+
}, stopsAfter !== undefined && {
|
|
330
|
+
stopsAfter: stopsAfter
|
|
331
|
+
});
|
|
332
|
+
// Get the actual brain title from the resolved brain
|
|
333
|
+
brainTitle = brain.title || identifier;
|
|
334
|
+
return [
|
|
335
|
+
4,
|
|
336
|
+
stub.start(brainTitle, newBrainRunId, rerunOptions)
|
|
337
|
+
];
|
|
338
|
+
case 4:
|
|
339
|
+
_state.sent();
|
|
340
|
+
response = {
|
|
341
|
+
brainRunId: newBrainRunId
|
|
342
|
+
};
|
|
343
|
+
return [
|
|
344
|
+
2,
|
|
345
|
+
context.json(response, 201)
|
|
346
|
+
];
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
})();
|
|
350
|
+
});
|
|
351
|
+
brains.get('/runs/:runId/watch', function(context) {
|
|
352
|
+
return _async_to_generator(function() {
|
|
353
|
+
var runId, namespace, doId, stub, response;
|
|
354
|
+
return _ts_generator(this, function(_state) {
|
|
355
|
+
switch(_state.label){
|
|
356
|
+
case 0:
|
|
357
|
+
runId = context.req.param('runId');
|
|
358
|
+
namespace = context.env.BRAIN_RUNNER_DO;
|
|
359
|
+
doId = namespace.idFromName(runId);
|
|
360
|
+
stub = namespace.get(doId);
|
|
361
|
+
return [
|
|
362
|
+
4,
|
|
363
|
+
stub.fetch(new Request("http://do/watch"))
|
|
364
|
+
];
|
|
365
|
+
case 1:
|
|
366
|
+
response = _state.sent();
|
|
367
|
+
return [
|
|
368
|
+
2,
|
|
369
|
+
response
|
|
370
|
+
];
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
})();
|
|
374
|
+
});
|
|
375
|
+
brains.get('/runs/:runId', function(context) {
|
|
376
|
+
return _async_to_generator(function() {
|
|
377
|
+
var runId, monitorId, monitorStub, run;
|
|
378
|
+
return _ts_generator(this, function(_state) {
|
|
379
|
+
switch(_state.label){
|
|
380
|
+
case 0:
|
|
381
|
+
runId = context.req.param('runId');
|
|
382
|
+
monitorId = context.env.MONITOR_DO.idFromName('singleton');
|
|
383
|
+
monitorStub = context.env.MONITOR_DO.get(monitorId);
|
|
384
|
+
return [
|
|
385
|
+
4,
|
|
386
|
+
monitorStub.getRun(runId)
|
|
387
|
+
];
|
|
388
|
+
case 1:
|
|
389
|
+
run = _state.sent();
|
|
390
|
+
if (!run) {
|
|
391
|
+
return [
|
|
392
|
+
2,
|
|
393
|
+
context.json({
|
|
394
|
+
error: "Brain run '".concat(runId, "' not found")
|
|
395
|
+
}, 404)
|
|
396
|
+
];
|
|
397
|
+
}
|
|
398
|
+
return [
|
|
399
|
+
2,
|
|
400
|
+
context.json(run)
|
|
401
|
+
];
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
})();
|
|
405
|
+
});
|
|
406
|
+
brains.delete('/runs/:runId', function(context) {
|
|
407
|
+
return _async_to_generator(function() {
|
|
408
|
+
var runId, monitorId, monitorStub, existingRun, namespace, doId, stub, result, error;
|
|
409
|
+
return _ts_generator(this, function(_state) {
|
|
410
|
+
switch(_state.label){
|
|
411
|
+
case 0:
|
|
412
|
+
runId = context.req.param('runId');
|
|
413
|
+
// First check if the run exists in the monitor
|
|
414
|
+
monitorId = context.env.MONITOR_DO.idFromName('singleton');
|
|
415
|
+
monitorStub = context.env.MONITOR_DO.get(monitorId);
|
|
416
|
+
return [
|
|
417
|
+
4,
|
|
418
|
+
monitorStub.getLastEvent(runId)
|
|
419
|
+
];
|
|
420
|
+
case 1:
|
|
421
|
+
existingRun = _state.sent();
|
|
422
|
+
if (!existingRun) {
|
|
423
|
+
return [
|
|
424
|
+
2,
|
|
425
|
+
context.json({
|
|
426
|
+
error: "Brain run '".concat(runId, "' not found")
|
|
427
|
+
}, 404)
|
|
428
|
+
];
|
|
429
|
+
}
|
|
430
|
+
// Now try to kill it - pass runId and brainTitle as fallbacks in case
|
|
431
|
+
// the DO's SQLite state is missing (zombie brain scenario)
|
|
432
|
+
namespace = context.env.BRAIN_RUNNER_DO;
|
|
433
|
+
doId = namespace.idFromName(runId);
|
|
434
|
+
stub = namespace.get(doId);
|
|
435
|
+
_state.label = 2;
|
|
436
|
+
case 2:
|
|
437
|
+
_state.trys.push([
|
|
438
|
+
2,
|
|
439
|
+
4,
|
|
440
|
+
,
|
|
441
|
+
5
|
|
442
|
+
]);
|
|
443
|
+
return [
|
|
444
|
+
4,
|
|
445
|
+
stub.kill(runId, existingRun.brain_title)
|
|
446
|
+
];
|
|
447
|
+
case 3:
|
|
448
|
+
result = _state.sent();
|
|
449
|
+
if (!result.success) {
|
|
450
|
+
return [
|
|
451
|
+
2,
|
|
452
|
+
context.json({
|
|
453
|
+
error: result.message
|
|
454
|
+
}, 409)
|
|
455
|
+
];
|
|
456
|
+
}
|
|
457
|
+
// Return 204 No Content on success
|
|
458
|
+
return [
|
|
459
|
+
2,
|
|
460
|
+
new Response(null, {
|
|
461
|
+
status: 204
|
|
462
|
+
})
|
|
463
|
+
];
|
|
464
|
+
case 4:
|
|
465
|
+
error = _state.sent();
|
|
466
|
+
console.error("Error killing brain run ".concat(runId, ":"), error);
|
|
467
|
+
return [
|
|
468
|
+
2,
|
|
469
|
+
context.json({
|
|
470
|
+
error: 'Failed to kill brain run'
|
|
471
|
+
}, 500)
|
|
472
|
+
];
|
|
473
|
+
case 5:
|
|
474
|
+
return [
|
|
475
|
+
2
|
|
476
|
+
];
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
})();
|
|
480
|
+
});
|
|
481
|
+
brains.get('/:identifier/history', function(context) {
|
|
482
|
+
return _async_to_generator(function() {
|
|
483
|
+
var identifier, limit, manifest, resolution, brain, brainTitle, monitorId, monitorStub, runs;
|
|
484
|
+
return _ts_generator(this, function(_state) {
|
|
485
|
+
switch(_state.label){
|
|
486
|
+
case 0:
|
|
487
|
+
identifier = context.req.param('identifier');
|
|
488
|
+
limit = Number(context.req.query('limit') || '10');
|
|
489
|
+
// Resolve the identifier to get the actual brain title
|
|
490
|
+
manifest = getManifest();
|
|
491
|
+
if (!manifest) {
|
|
492
|
+
return [
|
|
493
|
+
2,
|
|
494
|
+
context.json({
|
|
495
|
+
error: 'Manifest not initialized'
|
|
496
|
+
}, 500)
|
|
497
|
+
];
|
|
498
|
+
}
|
|
499
|
+
resolution = manifest.resolve(identifier);
|
|
500
|
+
if (resolution.matchType === 'none') {
|
|
501
|
+
return [
|
|
502
|
+
2,
|
|
503
|
+
context.json({
|
|
504
|
+
error: "Brain '".concat(identifier, "' not found")
|
|
505
|
+
}, 404)
|
|
506
|
+
];
|
|
507
|
+
}
|
|
508
|
+
if (resolution.matchType === 'multiple') {
|
|
509
|
+
return [
|
|
510
|
+
2,
|
|
511
|
+
context.json({
|
|
512
|
+
error: 'Multiple brains match the identifier',
|
|
513
|
+
matchType: 'multiple',
|
|
514
|
+
candidates: resolution.candidates
|
|
515
|
+
}, 300)
|
|
516
|
+
];
|
|
517
|
+
}
|
|
518
|
+
// Get the actual brain title
|
|
519
|
+
brain = resolution.brain;
|
|
520
|
+
brainTitle = brain.title || identifier;
|
|
521
|
+
// Get the monitor singleton instance
|
|
522
|
+
monitorId = context.env.MONITOR_DO.idFromName('singleton');
|
|
523
|
+
monitorStub = context.env.MONITOR_DO.get(monitorId);
|
|
524
|
+
return [
|
|
525
|
+
4,
|
|
526
|
+
monitorStub.history(brainTitle, limit)
|
|
527
|
+
];
|
|
528
|
+
case 1:
|
|
529
|
+
runs = _state.sent();
|
|
530
|
+
return [
|
|
531
|
+
2,
|
|
532
|
+
context.json({
|
|
533
|
+
runs: runs
|
|
534
|
+
})
|
|
535
|
+
];
|
|
536
|
+
}
|
|
537
|
+
});
|
|
538
|
+
})();
|
|
539
|
+
});
|
|
540
|
+
brains.get('/:identifier/active-runs', function(context) {
|
|
541
|
+
return _async_to_generator(function() {
|
|
542
|
+
var identifier, manifest, resolution, brain, brainTitle, monitorId, monitorStub, runs;
|
|
543
|
+
return _ts_generator(this, function(_state) {
|
|
544
|
+
switch(_state.label){
|
|
545
|
+
case 0:
|
|
546
|
+
identifier = context.req.param('identifier');
|
|
547
|
+
// Resolve the identifier to get the actual brain title
|
|
548
|
+
manifest = getManifest();
|
|
549
|
+
if (!manifest) {
|
|
550
|
+
return [
|
|
551
|
+
2,
|
|
552
|
+
context.json({
|
|
553
|
+
error: 'Manifest not initialized'
|
|
554
|
+
}, 500)
|
|
555
|
+
];
|
|
556
|
+
}
|
|
557
|
+
resolution = manifest.resolve(identifier);
|
|
558
|
+
if (resolution.matchType === 'none') {
|
|
559
|
+
return [
|
|
560
|
+
2,
|
|
561
|
+
context.json({
|
|
562
|
+
error: "Brain '".concat(identifier, "' not found")
|
|
563
|
+
}, 404)
|
|
564
|
+
];
|
|
565
|
+
}
|
|
566
|
+
if (resolution.matchType === 'multiple') {
|
|
567
|
+
return [
|
|
568
|
+
2,
|
|
569
|
+
context.json({
|
|
570
|
+
error: 'Multiple brains match the identifier',
|
|
571
|
+
matchType: 'multiple',
|
|
572
|
+
candidates: resolution.candidates
|
|
573
|
+
}, 300)
|
|
574
|
+
];
|
|
575
|
+
}
|
|
576
|
+
// Get the actual brain title
|
|
577
|
+
brain = resolution.brain;
|
|
578
|
+
brainTitle = brain.title || identifier;
|
|
579
|
+
// Get the monitor singleton instance
|
|
580
|
+
monitorId = context.env.MONITOR_DO.idFromName('singleton');
|
|
581
|
+
monitorStub = context.env.MONITOR_DO.get(monitorId);
|
|
582
|
+
return [
|
|
583
|
+
4,
|
|
584
|
+
monitorStub.activeRuns(brainTitle)
|
|
585
|
+
];
|
|
586
|
+
case 1:
|
|
587
|
+
runs = _state.sent();
|
|
588
|
+
return [
|
|
589
|
+
2,
|
|
590
|
+
context.json({
|
|
591
|
+
runs: runs
|
|
592
|
+
})
|
|
593
|
+
];
|
|
594
|
+
}
|
|
595
|
+
});
|
|
596
|
+
})();
|
|
597
|
+
});
|
|
598
|
+
brains.get('/watch', function(context) {
|
|
599
|
+
return _async_to_generator(function() {
|
|
600
|
+
var monitorId, monitorStub, response;
|
|
601
|
+
return _ts_generator(this, function(_state) {
|
|
602
|
+
switch(_state.label){
|
|
603
|
+
case 0:
|
|
604
|
+
monitorId = context.env.MONITOR_DO.idFromName('singleton');
|
|
605
|
+
monitorStub = context.env.MONITOR_DO.get(monitorId);
|
|
606
|
+
return [
|
|
607
|
+
4,
|
|
608
|
+
monitorStub.fetch(new Request("http://do/watch"))
|
|
609
|
+
];
|
|
610
|
+
case 1:
|
|
611
|
+
response = _state.sent();
|
|
612
|
+
return [
|
|
613
|
+
2,
|
|
614
|
+
response
|
|
615
|
+
];
|
|
616
|
+
}
|
|
617
|
+
});
|
|
618
|
+
})();
|
|
619
|
+
});
|
|
620
|
+
brains.get('/', function(context) {
|
|
621
|
+
return _async_to_generator(function() {
|
|
622
|
+
var _context_req_query, manifest, query, brainFilenames, brainList, validBrains, queryLower, exactMatch, fuse, results;
|
|
623
|
+
return _ts_generator(this, function(_state) {
|
|
624
|
+
switch(_state.label){
|
|
625
|
+
case 0:
|
|
626
|
+
manifest = getManifest();
|
|
627
|
+
if (!manifest) {
|
|
628
|
+
return [
|
|
629
|
+
2,
|
|
630
|
+
context.json({
|
|
631
|
+
error: 'Manifest not initialized'
|
|
632
|
+
}, 500)
|
|
633
|
+
];
|
|
634
|
+
}
|
|
635
|
+
query = (_context_req_query = context.req.query('q')) === null || _context_req_query === void 0 ? void 0 : _context_req_query.trim();
|
|
636
|
+
brainFilenames = manifest.list();
|
|
637
|
+
return [
|
|
638
|
+
4,
|
|
639
|
+
Promise.all(brainFilenames.map(function(filename) {
|
|
640
|
+
return _async_to_generator(function() {
|
|
641
|
+
var brain, structure;
|
|
642
|
+
return _ts_generator(this, function(_state) {
|
|
643
|
+
switch(_state.label){
|
|
644
|
+
case 0:
|
|
645
|
+
return [
|
|
646
|
+
4,
|
|
647
|
+
manifest.import(filename)
|
|
648
|
+
];
|
|
649
|
+
case 1:
|
|
650
|
+
brain = _state.sent();
|
|
651
|
+
if (!brain) {
|
|
652
|
+
return [
|
|
653
|
+
2,
|
|
654
|
+
null
|
|
655
|
+
];
|
|
656
|
+
}
|
|
657
|
+
structure = brain.structure;
|
|
658
|
+
return [
|
|
659
|
+
2,
|
|
660
|
+
{
|
|
661
|
+
filename: filename,
|
|
662
|
+
title: structure.title,
|
|
663
|
+
description: structure.description || "".concat(structure.title, " brain")
|
|
664
|
+
}
|
|
665
|
+
];
|
|
666
|
+
}
|
|
667
|
+
});
|
|
668
|
+
})();
|
|
669
|
+
}))
|
|
670
|
+
];
|
|
671
|
+
case 1:
|
|
672
|
+
brainList = _state.sent();
|
|
673
|
+
// Filter out any null entries
|
|
674
|
+
validBrains = brainList.filter(function(brain) {
|
|
675
|
+
return brain !== null;
|
|
676
|
+
});
|
|
677
|
+
// If no query, return all brains
|
|
678
|
+
if (!query) {
|
|
679
|
+
return [
|
|
680
|
+
2,
|
|
681
|
+
context.json({
|
|
682
|
+
brains: validBrains,
|
|
683
|
+
count: validBrains.length
|
|
684
|
+
})
|
|
685
|
+
];
|
|
686
|
+
}
|
|
687
|
+
// Check for exact match on title or filename first
|
|
688
|
+
queryLower = query.toLowerCase();
|
|
689
|
+
exactMatch = validBrains.find(function(brain) {
|
|
690
|
+
return brain.title.toLowerCase() === queryLower || brain.filename.toLowerCase() === queryLower;
|
|
691
|
+
});
|
|
692
|
+
if (exactMatch) {
|
|
693
|
+
return [
|
|
694
|
+
2,
|
|
695
|
+
context.json({
|
|
696
|
+
brains: [
|
|
697
|
+
exactMatch
|
|
698
|
+
],
|
|
699
|
+
count: 1
|
|
700
|
+
})
|
|
701
|
+
];
|
|
702
|
+
}
|
|
703
|
+
// Use fuse.js for fuzzy matching with weighted keys
|
|
704
|
+
fuse = new Fuse(validBrains, {
|
|
705
|
+
keys: [
|
|
706
|
+
{
|
|
707
|
+
name: 'title',
|
|
708
|
+
weight: 2
|
|
709
|
+
},
|
|
710
|
+
{
|
|
711
|
+
name: 'filename',
|
|
712
|
+
weight: 2
|
|
713
|
+
},
|
|
714
|
+
{
|
|
715
|
+
name: 'description',
|
|
716
|
+
weight: 0.5
|
|
717
|
+
}
|
|
718
|
+
],
|
|
719
|
+
includeScore: true,
|
|
720
|
+
threshold: 0.4,
|
|
721
|
+
ignoreLocation: true
|
|
722
|
+
});
|
|
723
|
+
results = fuse.search(query);
|
|
724
|
+
// If no results, return empty
|
|
725
|
+
if (results.length === 0) {
|
|
726
|
+
return [
|
|
727
|
+
2,
|
|
728
|
+
context.json({
|
|
729
|
+
brains: [],
|
|
730
|
+
count: 0
|
|
731
|
+
})
|
|
732
|
+
];
|
|
733
|
+
}
|
|
734
|
+
// If top result is significantly better than others (score difference > 0.2),
|
|
735
|
+
// or there's only one result, return just that one
|
|
736
|
+
if (results.length === 1 || results.length > 1 && results[1].score - results[0].score > 0.2) {
|
|
737
|
+
return [
|
|
738
|
+
2,
|
|
739
|
+
context.json({
|
|
740
|
+
brains: [
|
|
741
|
+
results[0].item
|
|
742
|
+
],
|
|
743
|
+
count: 1
|
|
744
|
+
})
|
|
745
|
+
];
|
|
746
|
+
}
|
|
747
|
+
// Return all matching results, sorted by score (best first)
|
|
748
|
+
return [
|
|
749
|
+
2,
|
|
750
|
+
context.json({
|
|
751
|
+
brains: results.map(function(r) {
|
|
752
|
+
return r.item;
|
|
753
|
+
}),
|
|
754
|
+
count: results.length
|
|
755
|
+
})
|
|
756
|
+
];
|
|
757
|
+
}
|
|
758
|
+
});
|
|
759
|
+
})();
|
|
760
|
+
});
|
|
761
|
+
// Schedule endpoints
|
|
762
|
+
// Create a new schedule
|
|
763
|
+
brains.post('/schedules', function(context) {
|
|
764
|
+
return _async_to_generator(function() {
|
|
765
|
+
var body, cronExpression, identifier, manifest, resolution, brain, brainTitle, scheduleId, scheduleStub, schedule, error, errorMessage;
|
|
766
|
+
return _ts_generator(this, function(_state) {
|
|
767
|
+
switch(_state.label){
|
|
768
|
+
case 0:
|
|
769
|
+
_state.trys.push([
|
|
770
|
+
0,
|
|
771
|
+
3,
|
|
772
|
+
,
|
|
773
|
+
4
|
|
774
|
+
]);
|
|
775
|
+
return [
|
|
776
|
+
4,
|
|
777
|
+
context.req.json()
|
|
778
|
+
];
|
|
779
|
+
case 1:
|
|
780
|
+
body = _state.sent();
|
|
781
|
+
cronExpression = body.cronExpression;
|
|
782
|
+
// Support both identifier and brainTitle for backward compatibility
|
|
783
|
+
identifier = body.identifier || body.brainTitle;
|
|
784
|
+
if (!identifier) {
|
|
785
|
+
return [
|
|
786
|
+
2,
|
|
787
|
+
context.json({
|
|
788
|
+
error: 'Missing required field "identifier" or "brainTitle"'
|
|
789
|
+
}, 400)
|
|
790
|
+
];
|
|
791
|
+
}
|
|
792
|
+
if (!cronExpression) {
|
|
793
|
+
return [
|
|
794
|
+
2,
|
|
795
|
+
context.json({
|
|
796
|
+
error: 'Missing required field "cronExpression"'
|
|
797
|
+
}, 400)
|
|
798
|
+
];
|
|
799
|
+
}
|
|
800
|
+
// Validate cron expression before calling DO
|
|
801
|
+
try {
|
|
802
|
+
parseCronExpression(cronExpression);
|
|
803
|
+
} catch (e) {
|
|
804
|
+
return [
|
|
805
|
+
2,
|
|
806
|
+
context.json({
|
|
807
|
+
error: "Invalid cron expression: ".concat(cronExpression)
|
|
808
|
+
}, 400)
|
|
809
|
+
];
|
|
810
|
+
}
|
|
811
|
+
// Resolve the identifier to get the actual brain title
|
|
812
|
+
manifest = getManifest();
|
|
813
|
+
if (!manifest) {
|
|
814
|
+
return [
|
|
815
|
+
2,
|
|
816
|
+
context.json({
|
|
817
|
+
error: 'Manifest not initialized'
|
|
818
|
+
}, 500)
|
|
819
|
+
];
|
|
820
|
+
}
|
|
821
|
+
resolution = manifest.resolve(identifier);
|
|
822
|
+
if (resolution.matchType === 'none') {
|
|
823
|
+
return [
|
|
824
|
+
2,
|
|
825
|
+
context.json({
|
|
826
|
+
error: "Brain '".concat(identifier, "' not found")
|
|
827
|
+
}, 404)
|
|
828
|
+
];
|
|
829
|
+
}
|
|
830
|
+
if (resolution.matchType === 'multiple') {
|
|
831
|
+
return [
|
|
832
|
+
2,
|
|
833
|
+
context.json({
|
|
834
|
+
error: 'Multiple brains match the identifier',
|
|
835
|
+
matchType: 'multiple',
|
|
836
|
+
candidates: resolution.candidates
|
|
837
|
+
}, 409)
|
|
838
|
+
];
|
|
839
|
+
}
|
|
840
|
+
// Get the actual brain title
|
|
841
|
+
brain = resolution.brain;
|
|
842
|
+
brainTitle = brain.title || identifier;
|
|
843
|
+
// Get the schedule singleton instance
|
|
844
|
+
scheduleId = context.env.SCHEDULE_DO.idFromName('singleton');
|
|
845
|
+
scheduleStub = context.env.SCHEDULE_DO.get(scheduleId);
|
|
846
|
+
return [
|
|
847
|
+
4,
|
|
848
|
+
scheduleStub.createSchedule(brainTitle, cronExpression)
|
|
849
|
+
];
|
|
850
|
+
case 2:
|
|
851
|
+
schedule = _state.sent();
|
|
852
|
+
return [
|
|
853
|
+
2,
|
|
854
|
+
context.json(schedule, 201)
|
|
855
|
+
];
|
|
856
|
+
case 3:
|
|
857
|
+
error = _state.sent();
|
|
858
|
+
errorMessage = _instanceof(error, Error) ? error.message : 'Failed to create schedule';
|
|
859
|
+
return [
|
|
860
|
+
2,
|
|
861
|
+
context.json({
|
|
862
|
+
error: errorMessage
|
|
863
|
+
}, 400)
|
|
864
|
+
];
|
|
865
|
+
case 4:
|
|
866
|
+
return [
|
|
867
|
+
2
|
|
868
|
+
];
|
|
869
|
+
}
|
|
870
|
+
});
|
|
871
|
+
})();
|
|
872
|
+
});
|
|
873
|
+
// List all schedules
|
|
874
|
+
brains.get('/schedules', function(context) {
|
|
875
|
+
return _async_to_generator(function() {
|
|
876
|
+
var scheduleId, scheduleStub, result;
|
|
877
|
+
return _ts_generator(this, function(_state) {
|
|
878
|
+
switch(_state.label){
|
|
879
|
+
case 0:
|
|
880
|
+
scheduleId = context.env.SCHEDULE_DO.idFromName('singleton');
|
|
881
|
+
scheduleStub = context.env.SCHEDULE_DO.get(scheduleId);
|
|
882
|
+
return [
|
|
883
|
+
4,
|
|
884
|
+
scheduleStub.listSchedules()
|
|
885
|
+
];
|
|
886
|
+
case 1:
|
|
887
|
+
result = _state.sent();
|
|
888
|
+
return [
|
|
889
|
+
2,
|
|
890
|
+
context.json(result)
|
|
891
|
+
];
|
|
892
|
+
}
|
|
893
|
+
});
|
|
894
|
+
})();
|
|
895
|
+
});
|
|
896
|
+
// Get scheduled run history - MUST be before :scheduleId route
|
|
897
|
+
brains.get('/schedules/runs', function(context) {
|
|
898
|
+
return _async_to_generator(function() {
|
|
899
|
+
var scheduleIdParam, limit, scheduleDoId, scheduleStub, result;
|
|
900
|
+
return _ts_generator(this, function(_state) {
|
|
901
|
+
switch(_state.label){
|
|
902
|
+
case 0:
|
|
903
|
+
scheduleIdParam = context.req.query('scheduleId');
|
|
904
|
+
limit = Number(context.req.query('limit') || '100');
|
|
905
|
+
scheduleDoId = context.env.SCHEDULE_DO.idFromName('singleton');
|
|
906
|
+
scheduleStub = context.env.SCHEDULE_DO.get(scheduleDoId);
|
|
907
|
+
return [
|
|
908
|
+
4,
|
|
909
|
+
scheduleStub.getAllRuns(scheduleIdParam, limit)
|
|
910
|
+
];
|
|
911
|
+
case 1:
|
|
912
|
+
result = _state.sent();
|
|
913
|
+
return [
|
|
914
|
+
2,
|
|
915
|
+
context.json(result)
|
|
916
|
+
];
|
|
917
|
+
}
|
|
918
|
+
});
|
|
919
|
+
})();
|
|
920
|
+
});
|
|
921
|
+
// Delete a schedule
|
|
922
|
+
brains.delete('/schedules/:scheduleId', function(context) {
|
|
923
|
+
return _async_to_generator(function() {
|
|
924
|
+
var scheduleIdParam, scheduleDoId, scheduleStub, deleted;
|
|
925
|
+
return _ts_generator(this, function(_state) {
|
|
926
|
+
switch(_state.label){
|
|
927
|
+
case 0:
|
|
928
|
+
scheduleIdParam = context.req.param('scheduleId');
|
|
929
|
+
scheduleDoId = context.env.SCHEDULE_DO.idFromName('singleton');
|
|
930
|
+
scheduleStub = context.env.SCHEDULE_DO.get(scheduleDoId);
|
|
931
|
+
return [
|
|
932
|
+
4,
|
|
933
|
+
scheduleStub.deleteSchedule(scheduleIdParam)
|
|
934
|
+
];
|
|
935
|
+
case 1:
|
|
936
|
+
deleted = _state.sent();
|
|
937
|
+
if (!deleted) {
|
|
938
|
+
return [
|
|
939
|
+
2,
|
|
940
|
+
context.json({
|
|
941
|
+
error: 'Schedule not found'
|
|
942
|
+
}, 404)
|
|
943
|
+
];
|
|
944
|
+
}
|
|
945
|
+
return [
|
|
946
|
+
2,
|
|
947
|
+
new Response(null, {
|
|
948
|
+
status: 204
|
|
949
|
+
})
|
|
950
|
+
];
|
|
951
|
+
}
|
|
952
|
+
});
|
|
953
|
+
})();
|
|
954
|
+
});
|
|
955
|
+
brains.get('/:identifier', function(context) {
|
|
956
|
+
return _async_to_generator(function() {
|
|
957
|
+
var identifier, manifest, resolution, brain, structure;
|
|
958
|
+
return _ts_generator(this, function(_state) {
|
|
959
|
+
identifier = context.req.param('identifier');
|
|
960
|
+
manifest = getManifest();
|
|
961
|
+
if (!manifest) {
|
|
962
|
+
return [
|
|
963
|
+
2,
|
|
964
|
+
context.json({
|
|
965
|
+
error: 'Manifest not initialized'
|
|
966
|
+
}, 500)
|
|
967
|
+
];
|
|
968
|
+
}
|
|
969
|
+
// Resolve the identifier to find the brain
|
|
970
|
+
resolution = manifest.resolve(identifier);
|
|
971
|
+
if (resolution.matchType === 'none') {
|
|
972
|
+
return [
|
|
973
|
+
2,
|
|
974
|
+
context.json({
|
|
975
|
+
error: "Brain '".concat(identifier, "' not found")
|
|
976
|
+
}, 404)
|
|
977
|
+
];
|
|
978
|
+
}
|
|
979
|
+
if (resolution.matchType === 'multiple') {
|
|
980
|
+
return [
|
|
981
|
+
2,
|
|
982
|
+
context.json({
|
|
983
|
+
error: 'Multiple brains match the identifier',
|
|
984
|
+
matchType: 'multiple',
|
|
985
|
+
candidates: resolution.candidates
|
|
986
|
+
}, 300)
|
|
987
|
+
];
|
|
988
|
+
}
|
|
989
|
+
brain = resolution.brain;
|
|
990
|
+
// Get the brain structure
|
|
991
|
+
structure = brain.structure;
|
|
992
|
+
return [
|
|
993
|
+
2,
|
|
994
|
+
context.json({
|
|
995
|
+
title: structure.title,
|
|
996
|
+
description: structure.description || "".concat(structure.title, " brain"),
|
|
997
|
+
steps: structure.steps
|
|
998
|
+
})
|
|
999
|
+
];
|
|
1000
|
+
});
|
|
1001
|
+
})();
|
|
1002
|
+
});
|
|
1003
|
+
export default brains;
|