@effect-agent/platform-cloudflare 0.1.0-beta.11 → 0.1.0-beta.13

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/index.d.mts CHANGED
@@ -594,6 +594,50 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
594
594
  readonly createdAt: string;
595
595
  readonly deploymentId: string;
596
596
  readonly payload: {
597
+ readonly _tag: "ToolCallPrepared";
598
+ readonly runId: string;
599
+ readonly turnId: string;
600
+ readonly turn: number;
601
+ readonly toolCallId: string;
602
+ readonly toolName: string;
603
+ readonly parameters: Schema.Json;
604
+ readonly parametersDigest: string;
605
+ } | {
606
+ readonly _tag: "ToolCallUnknown";
607
+ readonly runId: string;
608
+ readonly turn: number;
609
+ readonly toolCallId: string;
610
+ readonly toolName: string;
611
+ readonly reason: string;
612
+ } | {
613
+ readonly _tag: "ToolApprovalDecided";
614
+ readonly runId: string;
615
+ readonly turn: number;
616
+ readonly toolCallId: string;
617
+ readonly decision: "approved" | "denied";
618
+ readonly resolver: string;
619
+ readonly reason: string;
620
+ } | {
621
+ readonly _tag: "ToolCallResolved";
622
+ readonly runId: string;
623
+ readonly toolCallId: string;
624
+ readonly resolution: "completed-with-result" | "failed-with-error" | "never-started" | "safe-retry";
625
+ readonly author: string;
626
+ readonly reason: string;
627
+ } | {
628
+ readonly _tag: "AbortRequested";
629
+ readonly submissionId: string;
630
+ readonly author: string;
631
+ readonly reason: string;
632
+ } | {
633
+ readonly _tag: "SubagentStarted";
634
+ readonly runId: string;
635
+ readonly toolCallId: string;
636
+ readonly childConversationId: string;
637
+ readonly childSubmissionId: string;
638
+ readonly childReceiptId: string;
639
+ readonly childRunId: string;
640
+ } | {
597
641
  readonly _tag: "ConversationCreated";
598
642
  readonly agentId: string;
599
643
  readonly definitions: {
@@ -621,15 +665,6 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
621
665
  readonly inputTokens?: number | undefined;
622
666
  readonly outputTokens?: number | undefined;
623
667
  readonly costMicrousd?: number | undefined;
624
- } | {
625
- readonly _tag: "ToolCallPrepared";
626
- readonly runId: string;
627
- readonly turnId: string;
628
- readonly turn: number;
629
- readonly toolCallId: string;
630
- readonly toolName: string;
631
- readonly parameters: Schema.Json;
632
- readonly parametersDigest: string;
633
668
  } | {
634
669
  readonly _tag: "ToolCallSettled";
635
670
  readonly runId: string;
@@ -637,20 +672,6 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
637
672
  readonly toolName: string;
638
673
  readonly result: Schema.Json;
639
674
  readonly isFailure: boolean;
640
- } | {
641
- readonly _tag: "ToolCallUnknown";
642
- readonly runId: string;
643
- readonly turn: number;
644
- readonly toolCallId: string;
645
- readonly toolName: string;
646
- readonly reason: string;
647
- } | {
648
- readonly _tag: "ToolCallResolved";
649
- readonly runId: string;
650
- readonly toolCallId: string;
651
- readonly resolution: "completed-with-result" | "failed-with-error" | "never-started" | "safe-retry";
652
- readonly author: string;
653
- readonly reason: string;
654
675
  } | {
655
676
  readonly _tag: "ToolStepSettled";
656
677
  readonly runId: string;
@@ -666,14 +687,6 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
666
687
  readonly toolCallId: string;
667
688
  readonly toolName: string;
668
689
  readonly parametersDigest: string;
669
- } | {
670
- readonly _tag: "ToolApprovalDecided";
671
- readonly runId: string;
672
- readonly turn: number;
673
- readonly toolCallId: string;
674
- readonly decision: "approved" | "denied";
675
- readonly resolver: string;
676
- readonly reason: string;
677
690
  } | {
678
691
  readonly _tag: "ModelResponseInterrupted";
679
692
  readonly runId: string;
@@ -695,11 +708,6 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
695
708
  readonly _tag: "RunCompleted";
696
709
  readonly runId: string;
697
710
  readonly output: Schema.Json;
698
- } | {
699
- readonly _tag: "AbortRequested";
700
- readonly submissionId: string;
701
- readonly author: string;
702
- readonly reason: string;
703
711
  } | {
704
712
  readonly _tag: "SubmissionSettled";
705
713
  readonly submissionId: string;
@@ -709,6 +717,8 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
709
717
  readonly runId?: string | undefined;
710
718
  readonly result?: Schema.Json | undefined;
711
719
  readonly finishReason?: "budget-exhausted" | undefined;
720
+ readonly exhausted?: "tokens" | "tool-calls" | "turns" | undefined;
721
+ readonly policyLimit?: "cost" | "duration" | "repeated-failures" | "tokens" | "tool-calls" | "turns" | "usage" | undefined;
712
722
  } | {
713
723
  readonly _tag: "SubagentRequested";
714
724
  readonly runId: string;
@@ -730,14 +740,6 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
730
740
  readonly childConversationId: string;
731
741
  readonly childPrincipal: string;
732
742
  readonly childIdempotencyKey: string;
733
- } | {
734
- readonly _tag: "SubagentStarted";
735
- readonly runId: string;
736
- readonly toolCallId: string;
737
- readonly childConversationId: string;
738
- readonly childSubmissionId: string;
739
- readonly childReceiptId: string;
740
- readonly childRunId: string;
741
743
  } | {
742
744
  readonly _tag: "SubagentJoined";
743
745
  readonly runId: string;
@@ -819,44 +821,18 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
819
821
  } | {
820
822
  readonly _tag: "HostFailed";
821
823
  readonly failure: {
822
- readonly _tag: "HostProtocolError";
823
- readonly message: string;
824
- } | {
825
- readonly _tag: "AgentInputError";
824
+ readonly _tag: "LedgerError";
825
+ readonly operation: string;
826
826
  readonly message: string;
827
+ readonly cause?: Schema.Json | undefined;
827
828
  } | {
828
829
  readonly _tag: "DigestError";
829
830
  readonly message: string;
830
831
  readonly cause?: Schema.Json | undefined;
831
- } | {
832
- readonly _tag: "AdmissionConflict";
833
- readonly conversationId: string;
834
- readonly principal: string;
835
- readonly idempotencyKey: string;
836
- readonly existingInputDigest: string;
837
- readonly attemptedInputDigest: string;
838
832
  } | {
839
833
  readonly _tag: "SettlementConflict";
840
834
  readonly submissionId: string;
841
835
  readonly existingOutcome: "aborted" | "completed" | "failed";
842
- } | {
843
- readonly _tag: "ApprovalConflict";
844
- readonly submissionId: string;
845
- readonly toolCallId: string;
846
- readonly existingDecision: "approved" | "denied";
847
- } | {
848
- readonly _tag: "UnknownResolutionConflict";
849
- readonly submissionId: string;
850
- readonly toolCallId: string;
851
- } | {
852
- readonly _tag: "JoinedToHost";
853
- readonly submissionId: string;
854
- readonly hostSubmissionId: string;
855
- } | {
856
- readonly _tag: "LedgerError";
857
- readonly operation: string;
858
- readonly message: string;
859
- readonly cause?: Schema.Json | undefined;
860
836
  } | {
861
837
  readonly _tag: "ConversationStoreError";
862
838
  readonly operation: string;
@@ -880,16 +856,42 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
880
856
  } | {
881
857
  readonly _tag: "DurableRuntimeFailpointError";
882
858
  readonly location: "abort:after-intent" | "approval:after-request-append" | "approval:after-suspend" | "claim:after-claim" | "compaction:after-canonical-append" | "input:after-canonical-append" | "join:after-canonical-append" | "join:after-claim" | "resolve:after-intent" | "step:after-step-append" | "subagent:after-admit" | "subagent:after-child-abort-intent" | "subagent:after-child-ready" | "subagent:after-join-append" | "subagent:after-release" | "subagent:after-release-pending" | "subagent:after-request-append" | "subagent:after-reserve" | "subagent:after-sibling-settle" | "subagent:after-start-append" | "subagent:after-suspend" | "submit:after-admit" | "submit:after-materialize" | "terminalize:after-canonical-append" | "terminalize:after-reserve" | "tools:after-prepared-append" | "turn:after-canonical-append" | "turn:after-response-append" | "turn:after-results-append";
883
- } | {
884
- readonly _tag: "AdmissionLimitExceeded";
885
- readonly limit: "database-bytes" | "input-bytes" | "queue-depth";
886
- readonly actual: number;
887
- readonly maximum: number;
888
859
  } | {
889
860
  readonly _tag: "DurableAlarmError";
890
861
  readonly operation: string;
891
862
  readonly message: string;
892
863
  readonly cause?: Schema.Json | undefined;
864
+ } | {
865
+ readonly _tag: "HostProtocolError";
866
+ readonly message: string;
867
+ } | {
868
+ readonly _tag: "AgentInputError";
869
+ readonly message: string;
870
+ } | {
871
+ readonly _tag: "AdmissionConflict";
872
+ readonly conversationId: string;
873
+ readonly principal: string;
874
+ readonly idempotencyKey: string;
875
+ readonly existingInputDigest: string;
876
+ readonly attemptedInputDigest: string;
877
+ } | {
878
+ readonly _tag: "ApprovalConflict";
879
+ readonly submissionId: string;
880
+ readonly toolCallId: string;
881
+ readonly existingDecision: "approved" | "denied";
882
+ } | {
883
+ readonly _tag: "UnknownResolutionConflict";
884
+ readonly submissionId: string;
885
+ readonly toolCallId: string;
886
+ } | {
887
+ readonly _tag: "JoinedToHost";
888
+ readonly submissionId: string;
889
+ readonly hostSubmissionId: string;
890
+ } | {
891
+ readonly _tag: "AdmissionLimitExceeded";
892
+ readonly limit: "database-bytes" | "input-bytes" | "queue-depth";
893
+ readonly actual: number;
894
+ readonly maximum: number;
893
895
  };
894
896
  }, Schema.SchemaError, never>;
895
897
  declare const decodeHostResponse: (input: unknown, options?: import("effect/SchemaAST").ParseOptions) => Effect.Effect<AbortRecorded | ApprovalRecorded | HostFailed | ObservedPage | SettlementReached | SubmitSucceeded | UnknownResolutionRecorded, Schema.SchemaError, never>;
package/dist/index.mjs CHANGED
@@ -1,11 +1,11 @@
1
- import { Clock, Context, Duration, Effect, Fiber, Layer, Option, PubSub, Random, Ref, Schema, Stream } from "effect";
1
+ import { Cause, Clock, Context, Duration, Effect, Exit, Fiber, Layer, Option, PubSub, Random, Ref, Schema, Stream } from "effect";
2
2
  import { AbortCommand, AbortIntent, AdmissionConflict, AgentBindingResolver, AppendConflict, ApprovalConflict, ApprovalDecisionCommand, ApprovalDecisionIntent, CanonicalRecordEnvelope, CanonicalSequence, ConversationNotMaterialized, ConversationRead, ConversationStore, ConversationStoreError, DEFAULT_OWNERSHIP_LEASE_DURATION, DefinitionDigests, DeploymentId, DigestError, DurableAgentRuntime, DurableRuntimeConfig, DurableRuntimeFailpoint, DurableRuntimeFailpointError, FenceRejected, IdempotencyKey, IntegrityReport, JoinedToHost, LedgerError, ObligationReport, ObligationThresholds, OperationAuthorizationRequest, OperationAuthorizer, OperationDenied, OwnershipLost, PersistedJson, Principal, ProducerId, Receipt, RecoveryExplanation, RecoveryReport, RetryCommand, RetryRefused, RunJournalError, Settlement, SettlementConflict, SubmissionLedger, SubmissionLookupByKey, ToolReconciler, UnknownResolutionCommand, UnknownResolutionConflict, UnknownResolutionIntent, WakeScheduler } from "@effect-agent/session";
3
3
  import { ConversationPortTransport, DEFAULT_MAX_STORED_VALUE_BYTES, conversationStoreLayer, handleEncodedPortRequest, portTransportFailure, routedConversationStoreLayer, routedSubmissionLedgerLayer, storageConfigLayer, storageFailpointLayer, submissionLedgerLayer } from "@effect-agent/storage-cloudflare";
4
4
  import { AgentId, AgentInputError, ConversationId, SubmissionId } from "@effect-agent/core";
5
5
  import { BrowserCrypto } from "@effect/platform-browser";
6
6
  import { SqliteClient } from "@effect/sql-sqlite-do";
7
7
  import { DurableObject, DurableObjectState, WorkerEnvironment } from "effect-cf";
8
- import { CodeExecutionHost, CodeExecutionProtocolError, CodeExecutionResourceUse, CodeExecutionResult, CodeExecutionTimeoutError, CodeExecutor, CodeExecutorStartError, CodeExecutorTerminatedError, CodeExecutorUnsupportedError, CodeHostCall, CodeHostCallLimitError, CodeOutputLimitError, CodeProgramFailedError, CodeSourceError, SandboxImplementation } from "@effect-agent/sandbox";
8
+ import { CodeExecutionHost, CodeExecutionProtocolError, CodeExecutionResourceUse, CodeExecutionResult, CodeExecutionTimeoutError, CodeExecutor, CodeExecutorStartError, CodeExecutorTerminatedError, CodeExecutorUnsupportedError, CodeHostCall, CodeHostCallLimitError, CodeHostCallResult, CodeOutputLimitError, CodeProgramFailedError, CodeSourceError, SandboxImplementation } from "@effect-agent/sandbox";
9
9
  import { WorkerEntrypoint } from "cloudflare:workers";
10
10
  //#region src/bindings.ts
11
11
  /**
@@ -1348,19 +1348,25 @@ const decodeHostCall = (value) => {
1348
1348
  return Option.none();
1349
1349
  }
1350
1350
  };
1351
- /**
1352
- * Project a host outcome to the plain JSON envelope the harness reads. A
1353
- * `CodeExecutionHost` may return either real `CodeHostCallResult` instances
1354
- * (the substitute and conformance kit) or plain-object equivalents (the Code
1355
- * Mode capability's broker route), so this reads the shared fields rather than
1356
- * `Schema.encodeSync`, which would reject a plain object.
1357
- */
1358
- const hostResultEnvelope = (outcome) => outcome._tag === "CodeHostCallSuccess" ? {
1359
- _tag: "CodeHostCallSuccess",
1360
- value: outcome.value
1361
- } : {
1362
- _tag: "CodeHostCallFailure",
1363
- error: outcome.error
1351
+ const decodeHostCallResult = (value) => {
1352
+ try {
1353
+ return Schema.decodeUnknownOption(CodeHostCallResult)(value);
1354
+ } catch {
1355
+ return Option.none();
1356
+ }
1357
+ };
1358
+ const encodeHostResultPayload = (outcome) => {
1359
+ try {
1360
+ const payload = outcome._tag === "CodeHostCallSuccess" ? outcome.value : outcome.error;
1361
+ const encodedPayload = JSON.stringify(payload);
1362
+ if (encodedPayload === void 0) return void 0;
1363
+ return {
1364
+ encodedPayload,
1365
+ resultBytes: utf8ByteLength(encodedPayload)
1366
+ };
1367
+ } catch {
1368
+ return;
1369
+ }
1364
1370
  };
1365
1371
  const utf8ByteLength = (value) => {
1366
1372
  let total = 0;
@@ -1370,14 +1376,6 @@ const utf8ByteLength = (value) => {
1370
1376
  }
1371
1377
  return total;
1372
1378
  };
1373
- const encodedJsonByteLength = (value) => {
1374
- try {
1375
- const encoded = JSON.stringify(value);
1376
- return encoded === void 0 ? void 0 : utf8ByteLength(encoded);
1377
- } catch {
1378
- return;
1379
- }
1380
- };
1381
1379
  /** Reserved global names the harness owns inside the dynamic worker. */
1382
1380
  const reservedHarnessGlobals = /* @__PURE__ */ new Set(["console"]);
1383
1381
  const passCounterState = { next: 0 };
@@ -1401,67 +1399,149 @@ const makeExecute = (options) => Effect.fn("DynamicWorkerCodeExecutor.execute")(
1401
1399
  const host = yield* CodeExecutionHost;
1402
1400
  passCounterState.next += 1;
1403
1401
  const passId = `code-mode-pass-${passCounterState.next}-${crypto.randomUUID()}`;
1404
- const pending = [];
1405
- let wake;
1402
+ const startedAt = performance.now();
1403
+ const passDeadline = startedAt + Duration.toMillis(request.limits.maxWallTime);
1404
+ const remainingPassWallTime = () => Duration.millis(Math.max(0, passDeadline - performance.now()));
1406
1405
  let issuedHostCalls = 0;
1407
- const dispatch = (hostCall) => new Promise((resolve, reject) => {
1408
- issuedHostCalls += 1;
1409
- if (issuedHostCalls > request.limits.maxHostCalls + 1) {
1410
- reject(/* @__PURE__ */ new Error("host-call limit exceeded"));
1411
- return;
1412
- }
1413
- pending.push({
1414
- hostCall,
1415
- resolve,
1416
- reject
1417
- });
1418
- wake?.();
1419
- });
1420
- yield* Effect.acquireRelease(Effect.sync(() => {
1421
- passRegistry.set(passId, { dispatch });
1422
- }), () => Effect.sync(() => {
1423
- passRegistry.delete(passId);
1424
- }));
1425
- const nextPending = Effect.suspend(() => {
1426
- const item = pending.shift();
1427
- if (item !== void 0) return Effect.succeed(item);
1428
- return Effect.callback((resume) => {
1429
- wake = () => {
1430
- wake = void 0;
1431
- const next = pending.shift();
1432
- if (next !== void 0) resume(Effect.succeed(next));
1433
- };
1434
- });
1406
+ let passOpen = true;
1407
+ const queuedHostCalls = [];
1408
+ let activeHostCall;
1409
+ let hostDispatchFailure;
1410
+ let propagatedHostDispatchFailure;
1411
+ let signalHostDispatchFailure = (_failure) => void 0;
1412
+ const hostDispatchFailureSignal = new Promise((resolve) => {
1413
+ signalHostDispatchFailure = resolve;
1435
1414
  });
1436
- const serveHostCalls = Effect.gen(function* () {
1437
- let served = 0;
1438
- while (true) {
1439
- const item = yield* nextPending;
1440
- served += 1;
1441
- if (served > request.limits.maxHostCalls) return yield* CodeHostCallLimitError.make({
1415
+ const rejectQueuedHostCalls = (reason) => {
1416
+ for (const queued of queuedHostCalls.splice(0)) queued.reject(reason);
1417
+ };
1418
+ const recordHostDispatchFailure = (failure) => {
1419
+ if (hostDispatchFailure !== void 0) return;
1420
+ hostDispatchFailure = failure;
1421
+ signalHostDispatchFailure(failure);
1422
+ rejectQueuedHostCalls(/* @__PURE__ */ new Error("Code Mode pass failed"));
1423
+ };
1424
+ const failHostDispatch = (failure) => {
1425
+ switch (failure._tag) {
1426
+ case "host-call-limit": return Effect.fail(CodeHostCallLimitError.make({
1442
1427
  implementation: dynamicWorkerImplementation,
1443
1428
  limit: request.limits.maxHostCalls,
1444
1429
  logs: []
1445
- });
1446
- const decoded = decodeHostCall(item.hostCall);
1430
+ }));
1431
+ case "host-call-result-limit": return Effect.fail(CodeOutputLimitError.make({
1432
+ implementation: dynamicWorkerImplementation,
1433
+ surface: "host-call-result",
1434
+ limit: request.limits.maxHostCallResultBytes,
1435
+ observed: failure.observed,
1436
+ logs: []
1437
+ }));
1438
+ case "host-call-protocol": return Effect.fail(CodeExecutionProtocolError.make({
1439
+ implementation: dynamicWorkerImplementation,
1440
+ message: "The execution host returned a value outside the CodeHostCallResult schema"
1441
+ }));
1442
+ case "wall-clock-timeout": return Effect.fail(CodeExecutionTimeoutError.make({
1443
+ implementation: dynamicWorkerImplementation,
1444
+ kind: "wall-clock",
1445
+ maxWallTime: request.limits.maxWallTime,
1446
+ logs: []
1447
+ }));
1448
+ case "host-call-defect": return Effect.failCause(failure.cause);
1449
+ }
1450
+ };
1451
+ const propagateHostDispatchFailure = (failure) => Effect.gen(function* () {
1452
+ propagatedHostDispatchFailure = failure;
1453
+ return yield* failHostDispatch(failure);
1454
+ });
1455
+ const startNextHostCall = () => {
1456
+ if (!passOpen || hostDispatchFailure !== void 0 || activeHostCall !== void 0) return;
1457
+ const queued = queuedHostCalls.shift();
1458
+ if (queued === void 0) return;
1459
+ const fiber = Effect.runFork(Effect.yieldNow.pipe(Effect.andThen(host.call(queued.call)), Effect.timeoutOrElse({
1460
+ duration: remainingPassWallTime(),
1461
+ orElse: () => Effect.sync(() => {
1462
+ recordHostDispatchFailure({ _tag: "wall-clock-timeout" });
1463
+ throw new Error("code-mode host call exceeded the pass wall-clock limit");
1464
+ })
1465
+ }), Effect.map((outcome) => {
1466
+ const decoded = decodeHostCallResult(outcome);
1447
1467
  if (Option.isNone(decoded)) {
1448
- item.reject(/* @__PURE__ */ new TypeError("host calls must match the CodeHostCall schema"));
1449
- continue;
1468
+ recordHostDispatchFailure({ _tag: "host-call-protocol" });
1469
+ throw new Error("host-call protocol violation");
1450
1470
  }
1451
- const outcome = yield* host.call(decoded.value);
1452
- if (outcome._tag === "CodeHostCallSuccess") {
1453
- const bytes = encodedJsonByteLength(outcome.value);
1454
- if (bytes === void 0 || bytes > request.limits.maxHostCallResultBytes) return yield* CodeOutputLimitError.make({
1455
- implementation: dynamicWorkerImplementation,
1456
- surface: "host-call-result",
1457
- limit: request.limits.maxHostCallResultBytes,
1458
- observed: bytes ?? 0,
1459
- logs: []
1471
+ const encoded = encodeHostResultPayload(decoded.value);
1472
+ if (encoded === void 0 || encoded.resultBytes > request.limits.maxHostCallResultBytes) {
1473
+ recordHostDispatchFailure({
1474
+ _tag: "host-call-result-limit",
1475
+ observed: encoded?.resultBytes ?? 0
1460
1476
  });
1477
+ throw new Error("host-call result limit exceeded");
1461
1478
  }
1462
- item.resolve(hostResultEnvelope(outcome));
1479
+ const normalizedPayload = JSON.parse(encoded.encodedPayload);
1480
+ return decoded.value._tag === "CodeHostCallSuccess" ? {
1481
+ _tag: "CodeHostCallSuccess",
1482
+ value: normalizedPayload
1483
+ } : {
1484
+ _tag: "CodeHostCallFailure",
1485
+ error: normalizedPayload
1486
+ };
1487
+ })));
1488
+ activeHostCall = {
1489
+ fiber,
1490
+ settlement: Effect.runPromise(Fiber.await(fiber)).then((exit) => {
1491
+ if (Exit.isSuccess(exit)) {
1492
+ queued.resolve(exit.value);
1493
+ return;
1494
+ }
1495
+ if (!Cause.hasInterruptsOnly(exit.cause)) recordHostDispatchFailure({
1496
+ _tag: "host-call-defect",
1497
+ cause: exit.cause
1498
+ });
1499
+ queued.reject(/* @__PURE__ */ new Error("Code Mode host call failed"));
1500
+ }).finally(() => {
1501
+ if (activeHostCall?.fiber === fiber) activeHostCall = void 0;
1502
+ startNextHostCall();
1503
+ })
1504
+ };
1505
+ };
1506
+ const dispatch = (hostCall) => {
1507
+ if (!passOpen) return Promise.reject(/* @__PURE__ */ new Error("Code Mode pass is closing"));
1508
+ issuedHostCalls += 1;
1509
+ if (issuedHostCalls > request.limits.maxHostCalls) {
1510
+ recordHostDispatchFailure({ _tag: "host-call-limit" });
1511
+ return Promise.reject(/* @__PURE__ */ new Error("host-call limit exceeded"));
1512
+ }
1513
+ const decoded = decodeHostCall(hostCall);
1514
+ if (Option.isNone(decoded)) return Promise.reject(/* @__PURE__ */ new TypeError("host calls must match the CodeHostCall schema"));
1515
+ return new Promise((resolve, reject) => {
1516
+ queuedHostCalls.push({
1517
+ call: decoded.value,
1518
+ resolve,
1519
+ reject
1520
+ });
1521
+ startNextHostCall();
1522
+ });
1523
+ };
1524
+ const closeHostDispatch = Effect.gen(function* () {
1525
+ passOpen = false;
1526
+ passRegistry.delete(passId);
1527
+ rejectQueuedHostCalls(/* @__PURE__ */ new Error("Code Mode pass is closing"));
1528
+ const active = activeHostCall;
1529
+ if (active !== void 0) {
1530
+ yield* Fiber.interrupt(active.fiber);
1531
+ yield* Effect.promise(() => active.settlement);
1532
+ if (activeHostCall === active) activeHostCall = void 0;
1463
1533
  }
1534
+ return hostDispatchFailure;
1464
1535
  });
1536
+ const stopHostDispatch = closeHostDispatch.pipe(Effect.flatMap((failure) => failure !== void 0 && propagatedHostDispatchFailure !== failure ? propagateHostDispatchFailure(failure) : Effect.void));
1537
+ const releaseHostDispatch = closeHostDispatch.pipe(Effect.flatMap((failure) => {
1538
+ if (failure?._tag !== "host-call-defect" || propagatedHostDispatchFailure === failure) return Effect.void;
1539
+ propagatedHostDispatchFailure = failure;
1540
+ return Effect.failCause(failure.cause);
1541
+ }));
1542
+ yield* Effect.acquireRelease(Effect.sync(() => {
1543
+ passRegistry.set(passId, { dispatch });
1544
+ }), () => releaseHostDispatch);
1465
1545
  const workerCode = {
1466
1546
  compatibilityDate: options.compatibilityDate ?? "2025-05-01",
1467
1547
  allowExperimental: true,
@@ -1492,7 +1572,6 @@ const makeExecute = (options) => Effect.fn("DynamicWorkerCodeExecutor.execute")(
1492
1572
  subRequests: request.limits.maxHostCalls + 8
1493
1573
  } }
1494
1574
  };
1495
- const startedAt = yield* Clock.currentTimeMillis;
1496
1575
  const worker = yield* Effect.acquireRelease(Effect.try({
1497
1576
  try: () => options.loader.load(workerCode),
1498
1577
  catch: (cause) => {
@@ -1511,23 +1590,24 @@ const makeExecute = (options) => Effect.fn("DynamicWorkerCodeExecutor.execute")(
1511
1590
  }), (stub) => Effect.sync(() => {
1512
1591
  stub[Symbol.dispose]?.();
1513
1592
  }));
1514
- const server = yield* serveHostCalls.pipe(Effect.forkScoped);
1515
1593
  const rpc = Effect.tryPromise({
1516
1594
  try: async () => {
1517
1595
  return await worker.getEntrypoint().run();
1518
1596
  },
1519
1597
  catch: (cause) => classifyWorkerFailure(cause, request.limits.maxWallTime)
1520
1598
  });
1521
- const raw = yield* Effect.raceFirst(rpc, Fiber.join(server)).pipe(Effect.timeoutOrElse({
1522
- duration: request.limits.maxWallTime,
1599
+ const raw = yield* Effect.raceFirst(rpc.pipe(Effect.timeoutOrElse({
1600
+ duration: remainingPassWallTime(),
1523
1601
  orElse: () => CodeExecutionTimeoutError.make({
1524
1602
  implementation: dynamicWorkerImplementation,
1525
1603
  kind: "wall-clock",
1526
1604
  maxWallTime: request.limits.maxWallTime,
1527
1605
  logs: []
1528
1606
  })
1529
- }), Effect.ensuring(Fiber.interrupt(server)));
1530
- const finishedAt = yield* Clock.currentTimeMillis;
1607
+ })), Effect.promise(() => hostDispatchFailureSignal).pipe(Effect.flatMap(propagateHostDispatchFailure)));
1608
+ yield* stopHostDispatch;
1609
+ const finishedAt = performance.now();
1610
+ if (hostDispatchFailure !== void 0) return yield* propagateHostDispatchFailure(hostDispatchFailure);
1531
1611
  const outcome = decodeHarnessOutcome(raw);
1532
1612
  if (Option.isNone(outcome)) return yield* CodeExecutionProtocolError.make({
1533
1613
  implementation: dynamicWorkerImplementation,