@effect-agent/platform-cloudflare 0.1.0-beta.42 → 0.1.0-beta.44
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 +69 -56
- 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.map +1 -1
- 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.map +1 -1
- package/dist/subscriptions.mjs.map +1 -1
- package/package.json +1 -81
- package/src/alarm.ts +41 -0
- 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 +10 -0
- 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/src/client.ts
CHANGED
|
@@ -156,6 +156,7 @@ export const HostFailure = Schema.Union([
|
|
|
156
156
|
OperationDenied,
|
|
157
157
|
HostProtocolError,
|
|
158
158
|
]);
|
|
159
|
+
|
|
159
160
|
export type HostFailure = typeof HostFailure.Type;
|
|
160
161
|
|
|
161
162
|
export class SubmitSucceeded extends Schema.TaggedClass<SubmitSucceeded>(
|
|
@@ -222,6 +223,7 @@ export const HostResponse = Schema.Union([
|
|
|
222
223
|
UnknownResolutionRecorded,
|
|
223
224
|
HostFailed,
|
|
224
225
|
]);
|
|
226
|
+
|
|
225
227
|
export type HostResponse = typeof HostResponse.Type;
|
|
226
228
|
|
|
227
229
|
// ---------------------------------------------------------------------------
|
|
@@ -266,18 +268,21 @@ const ClientSubmitHostFailure = Schema.Union([
|
|
|
266
268
|
DurableAlarmError,
|
|
267
269
|
HostProtocolError,
|
|
268
270
|
]);
|
|
271
|
+
|
|
269
272
|
const ClientAwaitHostFailure = Schema.Union([
|
|
270
273
|
LedgerError,
|
|
271
274
|
SettlementConflict,
|
|
272
275
|
OperationDenied,
|
|
273
276
|
HostProtocolError,
|
|
274
277
|
]);
|
|
278
|
+
|
|
275
279
|
const ClientObserveHostFailure = Schema.Union([
|
|
276
280
|
ThreadStoreError,
|
|
277
281
|
ThreadNotMaterialized,
|
|
278
282
|
OperationDenied,
|
|
279
283
|
HostProtocolError,
|
|
280
284
|
]);
|
|
285
|
+
|
|
281
286
|
const ClientAbortHostFailure = Schema.Union([
|
|
282
287
|
OperationDenied,
|
|
283
288
|
LedgerError,
|
|
@@ -287,6 +292,7 @@ const ClientAbortHostFailure = Schema.Union([
|
|
|
287
292
|
DurableAlarmError,
|
|
288
293
|
HostProtocolError,
|
|
289
294
|
]);
|
|
295
|
+
|
|
290
296
|
const ClientApprovalHostFailure = Schema.Union([
|
|
291
297
|
LedgerError,
|
|
292
298
|
SettlementConflict,
|
|
@@ -295,6 +301,7 @@ const ClientApprovalHostFailure = Schema.Union([
|
|
|
295
301
|
DurableAlarmError,
|
|
296
302
|
HostProtocolError,
|
|
297
303
|
]);
|
|
304
|
+
|
|
298
305
|
const ClientUnknownHostFailure = Schema.Union([
|
|
299
306
|
LedgerError,
|
|
300
307
|
SettlementConflict,
|
|
@@ -420,9 +427,11 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
420
427
|
// Empty arguments preserve native arity. Passing `undefined` still adds an argument.
|
|
421
428
|
const traceArgs =
|
|
422
429
|
rpcTracing === undefined ? [] : yield* RpcTracing.withRpcTraceContext([]);
|
|
430
|
+
|
|
423
431
|
const raw = yield* Effect.tryPromise({
|
|
424
432
|
try: () => {
|
|
425
433
|
const stub = namespace.get(namespace.idFromName(threadId));
|
|
434
|
+
|
|
426
435
|
return stub[hostRpcMethods[operation]](encoded, ...traceArgs);
|
|
427
436
|
},
|
|
428
437
|
catch: (cause) =>
|
|
@@ -438,6 +447,7 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
438
447
|
...cloudflareFailureSignals(cause),
|
|
439
448
|
}),
|
|
440
449
|
});
|
|
450
|
+
|
|
441
451
|
return yield* decodeHostResponse(raw).pipe(
|
|
442
452
|
Effect.mapError((error): HostProtocolError =>
|
|
443
453
|
HostProtocolError.make({
|
|
@@ -464,11 +474,13 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
464
474
|
) => {
|
|
465
475
|
const isExpectedResult = Schema.is(resultSchema);
|
|
466
476
|
const isExpectedFailure = Schema.is(failureSchema);
|
|
477
|
+
|
|
467
478
|
return (
|
|
468
479
|
response: HostResponse,
|
|
469
480
|
): Effect.Effect<ResultSchema["Type"], FailureSchema["Type"] | ThreadClientError> => {
|
|
470
481
|
if (response._tag === "HostFailed") {
|
|
471
482
|
const failure = response.failure;
|
|
483
|
+
|
|
472
484
|
return isExpectedFailure(failure)
|
|
473
485
|
? Effect.fail(failure)
|
|
474
486
|
: Effect.fail(outOfContract(threadId, operation, `failure ${failure._tag}`));
|
|
@@ -476,6 +488,7 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
476
488
|
if (!isExpectedResult(response)) {
|
|
477
489
|
return Effect.fail(outOfContract(threadId, operation, `result ${response._tag}`));
|
|
478
490
|
}
|
|
491
|
+
|
|
479
492
|
return Effect.succeed(response);
|
|
480
493
|
};
|
|
481
494
|
};
|
|
@@ -494,6 +507,7 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
494
507
|
: { afterSequence: options.afterSequence }),
|
|
495
508
|
limit: options?.limit ?? 256,
|
|
496
509
|
});
|
|
510
|
+
|
|
497
511
|
const encoded = yield* encodeObservePageRequest(request).pipe(
|
|
498
512
|
Effect.mapError((error) =>
|
|
499
513
|
HostProtocolError.make({
|
|
@@ -501,13 +515,16 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
501
515
|
}),
|
|
502
516
|
),
|
|
503
517
|
);
|
|
518
|
+
|
|
504
519
|
const response = yield* call(threadId, "observePage", encoded);
|
|
520
|
+
|
|
505
521
|
const page = yield* expect(
|
|
506
522
|
threadId,
|
|
507
523
|
"observePage",
|
|
508
524
|
ObservedPage,
|
|
509
525
|
ClientObserveHostFailure,
|
|
510
526
|
)(response);
|
|
527
|
+
|
|
511
528
|
return page.records;
|
|
512
529
|
});
|
|
513
530
|
|
|
@@ -533,6 +550,7 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
533
550
|
AgentInputError.make({ message: `Unable to encode Agent input: ${cause.message}` }),
|
|
534
551
|
),
|
|
535
552
|
);
|
|
553
|
+
|
|
536
554
|
const inputPayload = yield* Schema.decodeUnknownEffect(PersistedJson)(
|
|
537
555
|
encodedInput,
|
|
538
556
|
).pipe(
|
|
@@ -542,6 +560,7 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
542
560
|
}),
|
|
543
561
|
),
|
|
544
562
|
);
|
|
563
|
+
|
|
545
564
|
const request = SubmitRequest.make({
|
|
546
565
|
agentId: agent.definition.id,
|
|
547
566
|
principal: options.principal,
|
|
@@ -549,6 +568,7 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
549
568
|
definitions: options.definitions,
|
|
550
569
|
inputPayload,
|
|
551
570
|
});
|
|
571
|
+
|
|
552
572
|
const encoded = yield* encodeSubmitRequest(request).pipe(
|
|
553
573
|
Effect.mapError((error) =>
|
|
554
574
|
HostProtocolError.make({
|
|
@@ -556,13 +576,16 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
556
576
|
}),
|
|
557
577
|
),
|
|
558
578
|
);
|
|
579
|
+
|
|
559
580
|
const response = yield* call(options.threadId, "submit", encoded);
|
|
581
|
+
|
|
560
582
|
const succeeded = yield* expect(
|
|
561
583
|
options.threadId,
|
|
562
584
|
"submit",
|
|
563
585
|
SubmitSucceeded,
|
|
564
586
|
ClientSubmitHostFailure,
|
|
565
587
|
)(response);
|
|
588
|
+
|
|
566
589
|
return succeeded.receipt;
|
|
567
590
|
}),
|
|
568
591
|
|
|
@@ -575,13 +598,16 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
575
598
|
}),
|
|
576
599
|
),
|
|
577
600
|
);
|
|
601
|
+
|
|
578
602
|
const response = yield* call(receipt.threadId, "awaitSettlement", encoded);
|
|
603
|
+
|
|
579
604
|
const settled = yield* expect(
|
|
580
605
|
receipt.threadId,
|
|
581
606
|
"awaitSettlement",
|
|
582
607
|
SettlementReached,
|
|
583
608
|
ClientAwaitHostFailure,
|
|
584
609
|
)(response);
|
|
610
|
+
|
|
585
611
|
return settled.settlement;
|
|
586
612
|
}),
|
|
587
613
|
|
|
@@ -596,7 +622,9 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
596
622
|
}),
|
|
597
623
|
),
|
|
598
624
|
);
|
|
625
|
+
|
|
599
626
|
const request = AwaitProgressRequest.make({ afterSequence, waiterId });
|
|
627
|
+
|
|
600
628
|
const encoded = yield* encodeAwaitProgressRequest(request).pipe(
|
|
601
629
|
Effect.mapError((error) =>
|
|
602
630
|
HostProtocolError.make({
|
|
@@ -631,10 +659,13 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
631
659
|
Effect.gen(function* () {
|
|
632
660
|
const all: Array<CanonicalRecordEnvelope> = [];
|
|
633
661
|
let after: CanonicalSequence | undefined;
|
|
662
|
+
|
|
634
663
|
for (;;) {
|
|
635
664
|
const page = yield* readPage(threadId, { afterSequence: after, limit: 1_024 });
|
|
665
|
+
|
|
636
666
|
all.push(...page);
|
|
637
667
|
const last = page.at(-1);
|
|
668
|
+
|
|
638
669
|
if (page.length < 1_024 || last === undefined) return all;
|
|
639
670
|
after = last.sequence;
|
|
640
671
|
}
|
|
@@ -649,13 +680,16 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
649
680
|
}),
|
|
650
681
|
),
|
|
651
682
|
);
|
|
683
|
+
|
|
652
684
|
const response = yield* call(threadId, "abort", encoded);
|
|
685
|
+
|
|
653
686
|
const recorded = yield* expect(
|
|
654
687
|
threadId,
|
|
655
688
|
"abort",
|
|
656
689
|
AbortRecorded,
|
|
657
690
|
ClientAbortHostFailure,
|
|
658
691
|
)(response);
|
|
692
|
+
|
|
659
693
|
return recorded.intent;
|
|
660
694
|
}),
|
|
661
695
|
|
|
@@ -668,13 +702,16 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
668
702
|
}),
|
|
669
703
|
),
|
|
670
704
|
);
|
|
705
|
+
|
|
671
706
|
const response = yield* call(threadId, "resolveApproval", encoded);
|
|
707
|
+
|
|
672
708
|
const recorded = yield* expect(
|
|
673
709
|
threadId,
|
|
674
710
|
"resolveApproval",
|
|
675
711
|
ApprovalRecorded,
|
|
676
712
|
ClientApprovalHostFailure,
|
|
677
713
|
)(response);
|
|
714
|
+
|
|
678
715
|
return recorded.intent;
|
|
679
716
|
}),
|
|
680
717
|
|
|
@@ -689,13 +726,16 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
689
726
|
}),
|
|
690
727
|
),
|
|
691
728
|
);
|
|
729
|
+
|
|
692
730
|
const response = yield* call(threadId, "resolveUnknown", encoded);
|
|
731
|
+
|
|
693
732
|
const recorded = yield* expect(
|
|
694
733
|
threadId,
|
|
695
734
|
"resolveUnknown",
|
|
696
735
|
UnknownResolutionRecorded,
|
|
697
736
|
ClientUnknownHostFailure,
|
|
698
737
|
)(response);
|
|
738
|
+
|
|
699
739
|
return recorded.intent;
|
|
700
740
|
}),
|
|
701
741
|
});
|
|
@@ -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
|
);
|