@effect-agent/platform-cloudflare 0.1.0-beta.42 → 0.1.0-beta.45
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/browser-quick-action.mjs.map +1 -1
- package/dist/browser-rest-capture.mjs.map +1 -1
- package/dist/browser-rest-crawl.mjs.map +1 -1
- package/dist/browser-session-lifecycle-DqntvG-Y.d.mts +21 -0
- package/dist/browser-session-lifecycle-ZGgb3pnK.mjs +84 -0
- package/dist/browser-session-lifecycle-ZGgb3pnK.mjs.map +1 -0
- package/dist/index.d.mts +47 -34
- package/dist/index.mjs +3 -3
- package/dist/index.mjs.map +1 -1
- package/dist/interactive-browser.d.mts +1 -18
- package/dist/interactive-browser.mjs +2 -81
- package/dist/interactive-browser.mjs.map +1 -1
- package/dist/{prepared-admission-BKp_Upw2.mjs → prepared-admission-BhW2eT_a.mjs} +3 -3
- package/dist/prepared-admission-BhW2eT_a.mjs.map +1 -0
- package/dist/protected-browser.d.mts +62 -0
- package/dist/protected-browser.mjs +714 -0
- package/dist/protected-browser.mjs.map +1 -0
- package/dist/scheduling.mjs +1 -1
- package/dist/scheduling.mjs.map +1 -1
- package/dist/subscriptions.mjs +1 -1
- package/dist/subscriptions.mjs.map +1 -1
- package/package.json +1 -81
- package/src/alarm.ts +277 -242
- package/src/bindings.ts +5 -0
- package/src/boundary.ts +4 -0
- package/src/browser-quick-action.ts +52 -0
- package/src/browser-rest-capture.ts +30 -0
- package/src/browser-rest-crawl.ts +43 -0
- package/src/browser-session-lifecycle.ts +18 -0
- package/src/client.ts +40 -0
- package/src/code-mode-executor.ts +50 -0
- package/src/interactive-browser.ts +176 -0
- package/src/layers.ts +13 -3
- package/src/memory.ts +42 -3
- package/src/prepared-admission.ts +1 -0
- package/src/progress-wait.ts +14 -0
- package/src/protected-browser/binding.ts +185 -0
- package/src/protected-browser/inspect-frame.ts +82 -0
- package/src/protected-browser/native.ts +384 -0
- package/src/protected-browser/policy.ts +594 -0
- package/src/protected-browser.ts +2 -0
- package/src/scheduling.ts +34 -0
- package/src/subscriptions.ts +50 -0
- package/src/thread-object.ts +55 -1
- package/src/transport.ts +1 -0
- package/src/wake-scheduler.ts +1 -0
- package/dist/prepared-admission-BKp_Upw2.mjs.map +0 -1
|
@@ -229,36 +229,45 @@ const HarnessCompleted = Schema.TaggedStruct("completed", {
|
|
|
229
229
|
logBytes: Schema.Natural,
|
|
230
230
|
resultBytes: Schema.Natural,
|
|
231
231
|
});
|
|
232
|
+
|
|
232
233
|
const HarnessSourceInvalid = Schema.TaggedStruct("source-invalid", {
|
|
233
234
|
message: Schema.String,
|
|
234
235
|
});
|
|
236
|
+
|
|
235
237
|
const HarnessNotAFunction = Schema.TaggedStruct("source-not-a-function", {
|
|
236
238
|
actual: Schema.String,
|
|
237
239
|
});
|
|
240
|
+
|
|
238
241
|
const HarnessProgramFailed = Schema.TaggedStruct("program-failed", {
|
|
239
242
|
reason: Schema.Literals(["threw", "rejected", "non-json-result"]),
|
|
240
243
|
thrown: Schema.Json,
|
|
241
244
|
message: Schema.String,
|
|
242
245
|
logs: BoundedLogs,
|
|
243
246
|
});
|
|
247
|
+
|
|
244
248
|
const HarnessLogLimit = Schema.TaggedStruct("log-limit", {
|
|
245
249
|
observed: Schema.Natural,
|
|
246
250
|
logs: BoundedLogs,
|
|
247
251
|
});
|
|
252
|
+
|
|
248
253
|
const HarnessArgumentLimit = Schema.TaggedStruct("argument-limit", {
|
|
249
254
|
observed: Schema.Natural,
|
|
250
255
|
logs: BoundedLogs,
|
|
251
256
|
});
|
|
257
|
+
|
|
252
258
|
const HarnessResultLimit = Schema.TaggedStruct("result-limit", {
|
|
253
259
|
observed: Schema.Natural,
|
|
254
260
|
logs: BoundedLogs,
|
|
255
261
|
});
|
|
262
|
+
|
|
256
263
|
const HarnessHostCallLimit = Schema.TaggedStruct("host-call-limit", {
|
|
257
264
|
logs: BoundedLogs,
|
|
258
265
|
});
|
|
266
|
+
|
|
259
267
|
const HarnessProtocol = Schema.TaggedStruct("protocol", {
|
|
260
268
|
message: Schema.String,
|
|
261
269
|
});
|
|
270
|
+
|
|
262
271
|
const HarnessOutcome = Schema.Union([
|
|
263
272
|
HarnessCompleted,
|
|
264
273
|
HarnessSourceInvalid,
|
|
@@ -321,6 +330,7 @@ export const disposeRpcHandle = (handle: unknown): Effect.Effect<void> =>
|
|
|
321
330
|
if ((typeof handle !== "object" && typeof handle !== "function") || handle === null) return;
|
|
322
331
|
if (!(Symbol.dispose in handle)) return;
|
|
323
332
|
const dispose = Reflect.get(handle, Symbol.dispose);
|
|
333
|
+
|
|
324
334
|
if (typeof dispose === "function") {
|
|
325
335
|
Reflect.apply(dispose, handle, []);
|
|
326
336
|
}
|
|
@@ -353,6 +363,7 @@ const encodeHostResultPayload = (
|
|
|
353
363
|
try {
|
|
354
364
|
const payload = outcome._tag === "CodeHostCallSuccess" ? outcome.value : outcome.error;
|
|
355
365
|
const encodedPayload = encodeJsonPayload(payload);
|
|
366
|
+
|
|
356
367
|
return {
|
|
357
368
|
encodedPayload,
|
|
358
369
|
resultBytes: utf8ByteLength(encodedPayload),
|
|
@@ -364,10 +375,13 @@ const encodeHostResultPayload = (
|
|
|
364
375
|
|
|
365
376
|
const utf8ByteLength = (value: string): number => {
|
|
366
377
|
let total = 0;
|
|
378
|
+
|
|
367
379
|
for (const character of value) {
|
|
368
380
|
const codePoint = character.codePointAt(0) ?? 0;
|
|
381
|
+
|
|
369
382
|
total += codePoint <= 0x7f ? 1 : codePoint <= 0x7ff ? 2 : codePoint <= 0xffff ? 3 : 4;
|
|
370
383
|
}
|
|
384
|
+
|
|
371
385
|
return total;
|
|
372
386
|
};
|
|
373
387
|
|
|
@@ -411,6 +425,7 @@ const makeExecute = (
|
|
|
411
425
|
});
|
|
412
426
|
}
|
|
413
427
|
const sourceBytes = utf8ByteLength(request.source);
|
|
428
|
+
|
|
414
429
|
if (sourceBytes > request.limits.maxSourceBytes) {
|
|
415
430
|
return yield* CodeSourceError.make({
|
|
416
431
|
implementation: dynamicWorkerImplementation,
|
|
@@ -433,22 +448,28 @@ const makeExecute = (
|
|
|
433
448
|
// immediately. The Clock service remains the authority, so tests and hosts can replace it.
|
|
434
449
|
const startedAt = clock.monotonicTimeNanosUnsafe();
|
|
435
450
|
const passDeadline = startedAt + Duration.toNanosUnsafe(request.limits.maxWallTime);
|
|
451
|
+
|
|
436
452
|
const remainingPassWallTime = (): Duration.Duration => {
|
|
437
453
|
const now = clock.monotonicTimeNanosUnsafe();
|
|
454
|
+
|
|
438
455
|
return Duration.nanos(passDeadline > now ? passDeadline - now : 0n);
|
|
439
456
|
};
|
|
457
|
+
|
|
440
458
|
let issuedHostCalls = 0;
|
|
441
459
|
let passOpen = true;
|
|
442
460
|
const queuedHostCalls: Array<QueuedHostCall> = [];
|
|
443
461
|
let passFailure: HostDispatchError | undefined;
|
|
462
|
+
|
|
444
463
|
const failPass = (error: HostDispatchError): void => {
|
|
445
464
|
if (passFailure === undefined) passFailure = error;
|
|
446
465
|
};
|
|
466
|
+
|
|
447
467
|
const rejectQueuedHostCalls = (reason: Error): void => {
|
|
448
468
|
for (const queued of queuedHostCalls.splice(0)) {
|
|
449
469
|
queued.reject(reason);
|
|
450
470
|
}
|
|
451
471
|
};
|
|
472
|
+
|
|
452
473
|
const queue = yield* Queue.unbounded<HostWork>();
|
|
453
474
|
|
|
454
475
|
const deliverHostOutcome = (
|
|
@@ -457,15 +478,19 @@ const makeExecute = (
|
|
|
457
478
|
): Effect.Effect<void, CodeExecutionProtocolError | CodeOutputLimitError> =>
|
|
458
479
|
Effect.gen(function* () {
|
|
459
480
|
const decoded = decodeHostCallResult(outcome);
|
|
481
|
+
|
|
460
482
|
if (Option.isNone(decoded)) {
|
|
461
483
|
const error = CodeExecutionProtocolError.make({
|
|
462
484
|
implementation: dynamicWorkerImplementation,
|
|
463
485
|
message: "The execution host returned a value outside the CodeHostCallResult schema",
|
|
464
486
|
});
|
|
487
|
+
|
|
465
488
|
failPass(error);
|
|
489
|
+
|
|
466
490
|
return yield* error;
|
|
467
491
|
}
|
|
468
492
|
const encoded = encodeHostResultPayload(decoded.value);
|
|
493
|
+
|
|
469
494
|
if (encoded === undefined || encoded.resultBytes > request.limits.maxHostCallResultBytes) {
|
|
470
495
|
const error = CodeOutputLimitError.make({
|
|
471
496
|
implementation: dynamicWorkerImplementation,
|
|
@@ -474,16 +499,21 @@ const makeExecute = (
|
|
|
474
499
|
observed: encoded?.resultBytes ?? 0,
|
|
475
500
|
logs: [],
|
|
476
501
|
});
|
|
502
|
+
|
|
477
503
|
failPass(error);
|
|
504
|
+
|
|
478
505
|
return yield* error;
|
|
479
506
|
}
|
|
480
507
|
const normalizedPayload = decodeJsonPayload(encoded.encodedPayload);
|
|
508
|
+
|
|
481
509
|
if (Option.isNone(normalizedPayload)) {
|
|
482
510
|
const error = CodeExecutionProtocolError.make({
|
|
483
511
|
implementation: dynamicWorkerImplementation,
|
|
484
512
|
message: "The execution host returned a result that could not cross the JSON boundary",
|
|
485
513
|
});
|
|
514
|
+
|
|
486
515
|
failPass(error);
|
|
516
|
+
|
|
487
517
|
return yield* error;
|
|
488
518
|
}
|
|
489
519
|
queued.resolve(
|
|
@@ -499,16 +529,20 @@ const makeExecute = (
|
|
|
499
529
|
const serveHostCalls = Effect.gen(function* () {
|
|
500
530
|
while (true) {
|
|
501
531
|
const work = yield* Queue.take(queue);
|
|
532
|
+
|
|
502
533
|
if (work._tag === "limit") {
|
|
503
534
|
const error = CodeHostCallLimitError.make({
|
|
504
535
|
implementation: dynamicWorkerImplementation,
|
|
505
536
|
limit: request.limits.maxHostCalls,
|
|
506
537
|
logs: [],
|
|
507
538
|
});
|
|
539
|
+
|
|
508
540
|
failPass(error);
|
|
541
|
+
|
|
509
542
|
return yield* error;
|
|
510
543
|
}
|
|
511
544
|
const queued = work.queued;
|
|
545
|
+
|
|
512
546
|
yield* host.call(queued.call).pipe(
|
|
513
547
|
Effect.timeoutOrElse({
|
|
514
548
|
duration: remainingPassWallTime(),
|
|
@@ -519,7 +553,9 @@ const makeExecute = (
|
|
|
519
553
|
maxWallTime: request.limits.maxWallTime,
|
|
520
554
|
logs: [],
|
|
521
555
|
});
|
|
556
|
+
|
|
522
557
|
failPass(error);
|
|
558
|
+
|
|
523
559
|
return error;
|
|
524
560
|
},
|
|
525
561
|
}),
|
|
@@ -533,6 +569,7 @@ const makeExecute = (
|
|
|
533
569
|
);
|
|
534
570
|
}
|
|
535
571
|
});
|
|
572
|
+
|
|
536
573
|
const server = yield* serveHostCalls.pipe(Effect.forkScoped);
|
|
537
574
|
|
|
538
575
|
const dispatch = (hostCall: unknown): Promise<unknown> => {
|
|
@@ -546,16 +583,21 @@ const makeExecute = (
|
|
|
546
583
|
limit: request.limits.maxHostCalls,
|
|
547
584
|
logs: [],
|
|
548
585
|
});
|
|
586
|
+
|
|
549
587
|
failPass(error);
|
|
550
588
|
Queue.offerUnsafe(queue, { _tag: "limit" });
|
|
589
|
+
|
|
551
590
|
return Promise.reject(new Error("host-call limit exceeded"));
|
|
552
591
|
}
|
|
553
592
|
const decoded = decodeHostCall(hostCall);
|
|
593
|
+
|
|
554
594
|
if (Option.isNone(decoded)) {
|
|
555
595
|
return Promise.reject(new TypeError("host calls must match the CodeHostCall schema"));
|
|
556
596
|
}
|
|
597
|
+
|
|
557
598
|
return new Promise((resolve, reject) => {
|
|
558
599
|
const queued = { call: decoded.value, resolve, reject };
|
|
600
|
+
|
|
559
601
|
queuedHostCalls.push(queued);
|
|
560
602
|
Queue.offerUnsafe(queue, { _tag: "call", queued });
|
|
561
603
|
});
|
|
@@ -565,6 +607,7 @@ const makeExecute = (
|
|
|
565
607
|
passOpen = false;
|
|
566
608
|
rejectQueuedHostCalls(new Error("Code Mode pass is closing"));
|
|
567
609
|
});
|
|
610
|
+
|
|
568
611
|
yield* Effect.addFinalizer(() => closeAdmission.pipe(Effect.andThen(Fiber.interrupt(server))));
|
|
569
612
|
|
|
570
613
|
// No `allowExperimental`: the runtime only accepts it when the CALLING
|
|
@@ -608,6 +651,7 @@ const makeExecute = (
|
|
|
608
651
|
try: () => options.loader.load(workerCode),
|
|
609
652
|
catch: (cause) => {
|
|
610
653
|
const text = safeCauseMessage(cause, "The Worker Loader failed without a diagnostic");
|
|
654
|
+
|
|
611
655
|
// Blame the program's source ONLY on a genuine compile diagnostic;
|
|
612
656
|
// any other load rejection is an infrastructure start failure, not
|
|
613
657
|
// the model's fault (see classifyWorkerFailure for the same split).
|
|
@@ -618,6 +662,7 @@ const makeExecute = (
|
|
|
618
662
|
message: text.slice(0, 8_000),
|
|
619
663
|
});
|
|
620
664
|
}
|
|
665
|
+
|
|
621
666
|
return CodeExecutorStartError.make({
|
|
622
667
|
implementation: dynamicWorkerImplementation,
|
|
623
668
|
message: `The Worker Loader rejected the pass: ${text}`.slice(0, 8_000),
|
|
@@ -656,6 +701,7 @@ const makeExecute = (
|
|
|
656
701
|
),
|
|
657
702
|
Fiber.join(server),
|
|
658
703
|
).pipe(Effect.exit);
|
|
704
|
+
|
|
659
705
|
yield* closeAdmission;
|
|
660
706
|
yield* Fiber.interrupt(server);
|
|
661
707
|
if (passFailure !== undefined) {
|
|
@@ -668,6 +714,7 @@ const makeExecute = (
|
|
|
668
714
|
const finishedAt = clock.monotonicTimeNanosUnsafe();
|
|
669
715
|
|
|
670
716
|
const outcome = decodeHarnessOutcome(raw);
|
|
717
|
+
|
|
671
718
|
if (Option.isNone(outcome)) {
|
|
672
719
|
return yield* CodeExecutionProtocolError.make({
|
|
673
720
|
implementation: dynamicWorkerImplementation,
|
|
@@ -768,6 +815,7 @@ const classifyWorkerFailure = (
|
|
|
768
815
|
| CodeExecutorStartError
|
|
769
816
|
| CodeSourceError => {
|
|
770
817
|
const text = safeCauseDiagnostic(cause, "[unserializable worker failure]");
|
|
818
|
+
|
|
771
819
|
// `WorkerLoader.load()` is lazy, so a module-compile error in the generated
|
|
772
820
|
// program surfaces here at first use. Blame the program's source ONLY on a
|
|
773
821
|
// genuine compile diagnostic (a `SyntaxError` or an explicit compile
|
|
@@ -797,6 +845,7 @@ const classifyWorkerFailure = (
|
|
|
797
845
|
cause,
|
|
798
846
|
});
|
|
799
847
|
}
|
|
848
|
+
|
|
800
849
|
return CodeExecutorTerminatedError.make({
|
|
801
850
|
implementation: dynamicWorkerImplementation,
|
|
802
851
|
message: text.slice(0, 8_000),
|
|
@@ -811,6 +860,7 @@ export const dynamicWorkerCodeExecutorLayer = (
|
|
|
811
860
|
CodeExecutor,
|
|
812
861
|
Effect.gen(function* () {
|
|
813
862
|
const clock = yield* Clock.Clock;
|
|
863
|
+
|
|
814
864
|
return CodeExecutor.of({ execute: makeExecute(options, clock) });
|
|
815
865
|
}),
|
|
816
866
|
);
|