@effect-agent/platform-cloudflare 0.1.0-beta.24 → 0.1.0-beta.25
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 +36 -32
- package/dist/index.mjs +234 -171
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
- package/src/alarm.ts +2 -1
- package/src/bindings.ts +31 -30
- package/src/boundary.ts +51 -0
- package/src/client.ts +86 -187
- package/src/code-mode-executor.ts +128 -62
- package/src/conversation-object.ts +46 -20
- package/src/layers.ts +17 -33
- package/src/wake-scheduler.ts +2 -1
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Clock, Context, Crypto, Deferred, Duration, Effect, Exit, Fiber, Layer, Option, PubSub, Queue, Random, Ref, Schema, Semaphore, Stream } from "effect";
|
|
1
|
+
import { Clock, Context, Crypto, Deferred, Duration, Effect, Exit, Fiber, Layer, Option, Predicate, PubSub, Queue, Random, Ref, Schema, Semaphore, 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, makeWakeSubscriptionHub, operationAuthorizerLayer } from "@effect-agent/session";
|
|
3
|
-
import { ConversationPortTransport, DEFAULT_MAX_STORED_VALUE_BYTES, conversationStoreLayer,
|
|
3
|
+
import { ConversationPortTransport, DEFAULT_MAX_STORED_VALUE_BYTES, conversationStoreLayer, decodePortRequest, encodePortResponse, executePortRequest, 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 { RunContextPreparationPassthrough } from "@effect-agent/engine";
|
|
6
6
|
import { BrowserCrypto } from "@effect/platform-browser";
|
|
@@ -36,17 +36,29 @@ var ConversationObjectNamespace = class ConversationObjectNamespace extends Cont
|
|
|
36
36
|
* narrowest-boundary check (structural probe for the namespace surface the transport uses);
|
|
37
37
|
* a missing or misshaped binding fails typed before any Layer is built.
|
|
38
38
|
*/
|
|
39
|
-
const conversationNamespaceFromEnv = (env, binding)
|
|
40
|
-
if (
|
|
39
|
+
const conversationNamespaceFromEnv = Effect.fn("conversationNamespaceFromEnv")(function* (env, binding) {
|
|
40
|
+
if (!Predicate.isObjectKeyword(env)) return yield* CloudflareBindingError.make({
|
|
41
41
|
binding,
|
|
42
42
|
message: "The Worker environment is not an object; no bindings are available."
|
|
43
|
-
})
|
|
44
|
-
const candidate =
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
});
|
|
44
|
+
const candidate = yield* Effect.try({
|
|
45
|
+
try: () => {
|
|
46
|
+
const value = Reflect.get(env, binding);
|
|
47
|
+
if (!Predicate.isObjectKeyword(value)) return void 0;
|
|
48
|
+
const idFromName = Reflect.get(value, "idFromName");
|
|
49
|
+
const get = Reflect.get(value, "get");
|
|
50
|
+
return typeof idFromName === "function" && typeof get === "function" ? value : void 0;
|
|
51
|
+
},
|
|
52
|
+
catch: () => CloudflareBindingError.make({
|
|
53
|
+
binding,
|
|
54
|
+
message: `env.${binding} could not be inspected as a DurableObjectNamespace binding.`
|
|
55
|
+
})
|
|
56
|
+
});
|
|
57
|
+
if (candidate !== void 0) return candidate;
|
|
58
|
+
return yield* CloudflareBindingError.make({
|
|
47
59
|
binding,
|
|
48
60
|
message: `env.${binding} is not a DurableObjectNamespace binding; declare the Conversation Object class under this binding in the Worker configuration.`
|
|
49
|
-
})
|
|
61
|
+
});
|
|
50
62
|
});
|
|
51
63
|
/** `ConversationObjectNamespace` built from the untyped Worker `env` (fails typed). */
|
|
52
64
|
const conversationNamespaceLayer = (env, binding) => Layer.effect(ConversationObjectNamespace)(Effect.map(conversationNamespaceFromEnv(env, binding), (namespace) => ({ namespace })));
|
|
@@ -174,6 +186,44 @@ const CLOUDFLARE_RUNTIME_DEFAULTS = {
|
|
|
174
186
|
maxDatabaseBytes: DEFAULT_MAX_DATABASE_BYTES
|
|
175
187
|
};
|
|
176
188
|
//#endregion
|
|
189
|
+
//#region src/boundary.ts
|
|
190
|
+
const MAX_FOREIGN_DIAGNOSTIC_LENGTH = 8192;
|
|
191
|
+
const boundForeignDiagnostic = (message) => message.slice(0, MAX_FOREIGN_DIAGNOSTIC_LENGTH);
|
|
192
|
+
/** Render a foreign failure without trusting accessors or coercion hooks on the value. */
|
|
193
|
+
const safeCauseMessage = (cause, fallback) => {
|
|
194
|
+
try {
|
|
195
|
+
const message = cause instanceof Error ? cause.message : cause;
|
|
196
|
+
return boundForeignDiagnostic(typeof message === "string" ? message : String(message));
|
|
197
|
+
} catch {
|
|
198
|
+
return boundForeignDiagnostic(fallback);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
/** Include an Error name when worker-failure classification needs it. */
|
|
202
|
+
const safeCauseDiagnostic = (cause, fallback) => {
|
|
203
|
+
try {
|
|
204
|
+
return cause instanceof Error ? boundForeignDiagnostic(`${cause.name}: ${cause.message}`) : safeCauseMessage(cause, fallback);
|
|
205
|
+
} catch {
|
|
206
|
+
return boundForeignDiagnostic(fallback);
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
/** Read Cloudflare RPC classifications without letting a hostile proxy defect the client. */
|
|
210
|
+
const cloudflareFailureSignals = (cause) => {
|
|
211
|
+
if (!Predicate.isObjectKeyword(cause)) return {};
|
|
212
|
+
try {
|
|
213
|
+
const retryableValue = Reflect.get(cause, "retryable");
|
|
214
|
+
const overloadedValue = Reflect.get(cause, "overloaded");
|
|
215
|
+
const resetValue = Reflect.get(cause, "durableObjectReset");
|
|
216
|
+
const retryable = typeof retryableValue === "boolean" ? retryableValue : resetValue === true ? true : void 0;
|
|
217
|
+
const overloaded = typeof overloadedValue === "boolean" ? overloadedValue : void 0;
|
|
218
|
+
return {
|
|
219
|
+
...retryable === void 0 ? {} : { retryable },
|
|
220
|
+
...overloaded === void 0 ? {} : { overloaded }
|
|
221
|
+
};
|
|
222
|
+
} catch {
|
|
223
|
+
return {};
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
//#endregion
|
|
177
227
|
//#region src/alarm.ts
|
|
178
228
|
/**
|
|
179
229
|
* The single multiplexed Durable Object alarm (decision D-P6-2). A Durable Object has ONE
|
|
@@ -194,7 +244,7 @@ var DurableAlarmError = class extends Schema.TaggedError()("DurableAlarmError",
|
|
|
194
244
|
}) {};
|
|
195
245
|
const alarmFailure = (operation) => (cause) => DurableAlarmError.make({
|
|
196
246
|
operation,
|
|
197
|
-
message: cause
|
|
247
|
+
message: safeCauseMessage(cause, "The Cloudflare alarm API failed without a diagnostic"),
|
|
198
248
|
cause
|
|
199
249
|
});
|
|
200
250
|
/** `ctx.storage` alarm slot as an Effect service; storage is truth, never a memory field. */
|
|
@@ -505,7 +555,7 @@ const cloudflareWakeSchedulerLayer = Layer.effect(WakeScheduler)(Effect.gen(func
|
|
|
505
555
|
try: () => namespace.get(namespace.idFromName(conversationId)).wake(),
|
|
506
556
|
catch: (cause) => RemoteWakeDropped.make({
|
|
507
557
|
conversationId,
|
|
508
|
-
message: cause
|
|
558
|
+
message: safeCauseMessage(cause, "The remote wake failed without a diagnostic"),
|
|
509
559
|
cause
|
|
510
560
|
})
|
|
511
561
|
}).pipe(Effect.catch((error) => Effect.logWarning(`CloudflareWakeScheduler: remote wake of ${conversationId} dropped`, error)), Effect.asVoid);
|
|
@@ -605,10 +655,10 @@ const conversationPortTransportLayer = Layer.effect(ConversationPortTransport)(E
|
|
|
605
655
|
//#endregion
|
|
606
656
|
//#region src/layers.ts
|
|
607
657
|
/**
|
|
608
|
-
* Owner-side
|
|
609
|
-
*
|
|
610
|
-
* request cannot bounce between Objects — and
|
|
611
|
-
*
|
|
658
|
+
* Owner-side execution port for a `portCall` request the wire endpoint has already decoded.
|
|
659
|
+
* It executes against THIS Object's LOCAL port facets — never the routed decorators, so a
|
|
660
|
+
* request cannot bounce between Objects — and returns the typed response for the endpoint to
|
|
661
|
+
* encode.
|
|
612
662
|
*/
|
|
613
663
|
var ConversationObjectPorts = class extends Context.Service()("@effect-agent/platform-cloudflare/ConversationObjectPorts") {};
|
|
614
664
|
const decodeConfigValue = Schema.decodeUnknownEffect(CloudflareDurableRuntimeConfigValue);
|
|
@@ -645,10 +695,7 @@ const conversationIdFromState = (ctx) => ctx.id.name === void 0 ? Effect.fail(Cl
|
|
|
645
695
|
message: `The Durable Object name is not a valid ConversationId: ${error.message}`,
|
|
646
696
|
cause: error
|
|
647
697
|
})));
|
|
648
|
-
const resolveBindings = (source, context) => source === void 0 ? Effect.succeed([]) : Effect.
|
|
649
|
-
const bindings = source(context);
|
|
650
|
-
return Effect.isEffect(bindings) ? bindings : Effect.succeed(bindings);
|
|
651
|
-
}) : Effect.succeed(source);
|
|
698
|
+
const resolveBindings = (source, context) => source === void 0 ? Effect.succeed([]) : Effect.suspend(() => source(context));
|
|
652
699
|
const resolveRunContext = (source, context) => typeof source === "function" ? source(context) : source;
|
|
653
700
|
/**
|
|
654
701
|
* The DC Layer assembly (deployment §12: a Layer-assembly library, not an app entrypoint;
|
|
@@ -699,7 +746,7 @@ var CloudflareDurableRuntime = class {
|
|
|
699
746
|
const localPorts = Layer.mergeAll(conversationStoreLayer, submissionLedgerLayer).pipe(Layer.provide(infrastructure));
|
|
700
747
|
const portsEndpointLayer = Layer.effect(ConversationObjectPorts)(Effect.gen(function* () {
|
|
701
748
|
const local = yield* Effect.context();
|
|
702
|
-
return ConversationObjectPorts.of({ handle: (
|
|
749
|
+
return ConversationObjectPorts.of({ handle: (request) => executePortRequest(request).pipe(Effect.provide(local)) });
|
|
703
750
|
})).pipe(Layer.provide(localPorts));
|
|
704
751
|
const routedPorts = Layer.mergeAll(routedSubmissionLedgerLayer({ localConversationId: conversationId }), routedConversationStoreLayer({ localConversationId: conversationId })).pipe(Layer.provide(localPorts), Layer.provide(conversationPortTransportLayer));
|
|
705
752
|
const runtimeConfigLayer = Layer.succeed(DurableRuntimeConfig)(DurableRuntimeConfig.make({
|
|
@@ -852,107 +899,88 @@ const decodeUnknownResolutionCommand = Schema.decodeUnknownEffect(UnknownResolut
|
|
|
852
899
|
const encodeUnknownResolutionCommand = Schema.encodeEffect(UnknownResolutionCommand);
|
|
853
900
|
const encodeHostResponse = Schema.encodeEffect(HostResponse);
|
|
854
901
|
const decodeHostResponse = Schema.decodeUnknownEffect(HostResponse);
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
902
|
+
/** Failure surface of `CloudflareConversationClient.submit`. */
|
|
903
|
+
const ClientSubmitHostFailure = Schema.Union([
|
|
904
|
+
AgentInputError,
|
|
905
|
+
DigestError,
|
|
906
|
+
AdmissionConflict,
|
|
907
|
+
LedgerError,
|
|
908
|
+
ConversationStoreError,
|
|
909
|
+
ConversationNotMaterialized,
|
|
910
|
+
AppendConflict,
|
|
911
|
+
FenceRejected,
|
|
912
|
+
DurableRuntimeFailpointError,
|
|
913
|
+
AdmissionLimitExceeded,
|
|
914
|
+
DurableAlarmError,
|
|
915
|
+
HostProtocolError
|
|
868
916
|
]);
|
|
869
|
-
const
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
917
|
+
const ClientAwaitHostFailure = Schema.Union([
|
|
918
|
+
LedgerError,
|
|
919
|
+
SettlementConflict,
|
|
920
|
+
HostProtocolError
|
|
873
921
|
]);
|
|
874
|
-
const
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
922
|
+
const ClientObserveHostFailure = Schema.Union([
|
|
923
|
+
ConversationStoreError,
|
|
924
|
+
ConversationNotMaterialized,
|
|
925
|
+
OperationDenied,
|
|
926
|
+
HostProtocolError
|
|
879
927
|
]);
|
|
880
|
-
const
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
"HostProtocolError"
|
|
928
|
+
const ClientAbortHostFailure = Schema.Union([
|
|
929
|
+
LedgerError,
|
|
930
|
+
SettlementConflict,
|
|
931
|
+
JoinedToHost,
|
|
932
|
+
DurableRuntimeFailpointError,
|
|
933
|
+
DurableAlarmError,
|
|
934
|
+
HostProtocolError
|
|
888
935
|
]);
|
|
889
|
-
const
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
936
|
+
const ClientApprovalHostFailure = Schema.Union([
|
|
937
|
+
LedgerError,
|
|
938
|
+
SettlementConflict,
|
|
939
|
+
ApprovalConflict,
|
|
940
|
+
OperationDenied,
|
|
941
|
+
DurableAlarmError,
|
|
942
|
+
HostProtocolError
|
|
896
943
|
]);
|
|
897
|
-
const
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
944
|
+
const ClientUnknownHostFailure = Schema.Union([
|
|
945
|
+
LedgerError,
|
|
946
|
+
SettlementConflict,
|
|
947
|
+
UnknownResolutionConflict,
|
|
948
|
+
JoinedToHost,
|
|
949
|
+
DurableRuntimeFailpointError,
|
|
950
|
+
OperationDenied,
|
|
951
|
+
DurableAlarmError,
|
|
952
|
+
HostProtocolError
|
|
906
953
|
]);
|
|
907
954
|
const outOfContract = (conversationId, operation, observed) => ConversationClientError.make({
|
|
908
955
|
conversationId,
|
|
909
956
|
message: boundHostDiagnostic(`The Conversation Object answered ${operation} with the out-of-contract ${observed}.`)
|
|
910
957
|
});
|
|
911
|
-
/**
|
|
912
|
-
* Narrow one decoded `HostFailed.failure` to the operation's declared failure family; an
|
|
913
|
-
* out-of-contract tag folds into `ConversationClientError` instead of being erased or
|
|
914
|
-
* re-thrown raw (the WP2 discipline). The predicate is the single documented narrowing over
|
|
915
|
-
* the closed `HostFailure` union.
|
|
916
|
-
*/
|
|
917
|
-
const narrowFailure = (tags) => (failure) => tags.has(failure._tag);
|
|
918
958
|
/** Worker-side client over the Conversation Object namespace (DEPLOY-010). */
|
|
919
959
|
var CloudflareConversationClient = class CloudflareConversationClient extends Context.Service()("@effect-agent/platform-cloudflare/CloudflareConversationClient") {
|
|
920
960
|
static layer = Layer.effect(CloudflareConversationClient)(Effect.gen(function* () {
|
|
921
961
|
const { namespace } = yield* ConversationObjectNamespace;
|
|
922
962
|
const crypto = yield* Crypto.Crypto;
|
|
923
|
-
const platformSignals = (cause) => {
|
|
924
|
-
let retryable;
|
|
925
|
-
let overloaded;
|
|
926
|
-
if (typeof cause === "object" && cause !== null) {
|
|
927
|
-
if ("retryable" in cause && typeof cause.retryable === "boolean") retryable = cause.retryable;
|
|
928
|
-
if ("overloaded" in cause && typeof cause.overloaded === "boolean") overloaded = cause.overloaded;
|
|
929
|
-
if (retryable === void 0 && "durableObjectReset" in cause && cause.durableObjectReset === true) retryable = true;
|
|
930
|
-
}
|
|
931
|
-
return {
|
|
932
|
-
...retryable === void 0 ? {} : { retryable },
|
|
933
|
-
...overloaded === void 0 ? {} : { overloaded }
|
|
934
|
-
};
|
|
935
|
-
};
|
|
936
963
|
const call = (conversationId, operation, invoke) => Effect.tryPromise({
|
|
937
964
|
try: () => invoke(namespace.get(namespace.idFromName(conversationId))),
|
|
938
965
|
catch: (cause) => ConversationClientError.make({
|
|
939
966
|
conversationId,
|
|
940
|
-
message: boundHostDiagnostic(`${operation} did not reach the Conversation Object: ${cause
|
|
967
|
+
message: boundHostDiagnostic(`${operation} did not reach the Conversation Object: ${safeCauseMessage(cause, "the RPC failed without a diagnostic")}`),
|
|
941
968
|
cause,
|
|
942
|
-
...
|
|
969
|
+
...cloudflareFailureSignals(cause)
|
|
943
970
|
})
|
|
944
971
|
}).pipe(Effect.flatMap((raw) => decodeHostResponse(raw).pipe(Effect.mapError((error) => HostProtocolError.make({ message: boundHostDiagnostic(`The ${operation} answer could not be decoded: ${error.message}`) })))), Effect.withSpan("CloudflareConversationClient.call", { attributes: {
|
|
945
972
|
conversationId,
|
|
946
973
|
operation
|
|
947
974
|
} }));
|
|
948
|
-
const expect = (conversationId, operation,
|
|
949
|
-
const
|
|
975
|
+
const expect = (conversationId, operation, resultSchema, failureSchema) => {
|
|
976
|
+
const isExpectedResult = Schema.is(resultSchema);
|
|
977
|
+
const isExpectedFailure = Schema.is(failureSchema);
|
|
950
978
|
return (response) => {
|
|
951
979
|
if (response._tag === "HostFailed") {
|
|
952
980
|
const failure = response.failure;
|
|
953
|
-
return
|
|
981
|
+
return isExpectedFailure(failure) ? Effect.fail(failure) : Effect.fail(outOfContract(conversationId, operation, `failure ${failure._tag}`));
|
|
954
982
|
}
|
|
955
|
-
if (response
|
|
983
|
+
if (!isExpectedResult(response)) return Effect.fail(outOfContract(conversationId, operation, `result ${response._tag}`));
|
|
956
984
|
return Effect.succeed(response);
|
|
957
985
|
};
|
|
958
986
|
};
|
|
@@ -963,7 +991,7 @@ var CloudflareConversationClient = class CloudflareConversationClient extends Co
|
|
|
963
991
|
});
|
|
964
992
|
const encoded = yield* encodeObservePageRequest(request).pipe(Effect.mapError((error) => HostProtocolError.make({ message: boundHostDiagnostic(`observePage request encode failed: ${error.message}`) })));
|
|
965
993
|
const response = yield* call(conversationId, "observePage", (stub) => stub.observePage(encoded));
|
|
966
|
-
return (yield* expect(conversationId, "observePage",
|
|
994
|
+
return (yield* expect(conversationId, "observePage", ObservedPage, ClientObserveHostFailure)(response)).records;
|
|
967
995
|
});
|
|
968
996
|
const cancelProgress = (conversationId, waiterId) => encodeCancelProgressRequest(CancelProgressRequest.make({ waiterId })).pipe(Effect.mapError(() => void 0), Effect.flatMap((encoded) => call(conversationId, "cancelProgress", (stub) => stub.cancelProgressEncoded(encoded))), Effect.asVoid, Effect.ignore);
|
|
969
997
|
return CloudflareConversationClient.of({
|
|
@@ -979,12 +1007,12 @@ var CloudflareConversationClient = class CloudflareConversationClient extends Co
|
|
|
979
1007
|
});
|
|
980
1008
|
const encoded = yield* encodeSubmitRequest(request).pipe(Effect.mapError((error) => HostProtocolError.make({ message: boundHostDiagnostic(`submit request encode failed: ${error.message}`) })));
|
|
981
1009
|
const response = yield* call(options.conversationId, "submit", (stub) => stub.submitEncoded(encoded));
|
|
982
|
-
return (yield* expect(options.conversationId, "submit",
|
|
1010
|
+
return (yield* expect(options.conversationId, "submit", SubmitSucceeded, ClientSubmitHostFailure)(response)).receipt;
|
|
983
1011
|
}),
|
|
984
1012
|
awaitSettlement: (receipt) => Effect.gen(function* () {
|
|
985
1013
|
const encoded = yield* encodeReceipt(receipt).pipe(Effect.mapError((error) => HostProtocolError.make({ message: boundHostDiagnostic(`receipt encode failed: ${error.message}`) })));
|
|
986
1014
|
const response = yield* call(receipt.conversationId, "awaitSettlement", (stub) => stub.awaitSettlementEncoded(encoded));
|
|
987
|
-
return (yield* expect(receipt.conversationId, "awaitSettlement",
|
|
1015
|
+
return (yield* expect(receipt.conversationId, "awaitSettlement", SettlementReached, ClientAwaitHostFailure)(response)).settlement;
|
|
988
1016
|
}),
|
|
989
1017
|
awaitProgress: (conversationId, afterSequence) => Effect.gen(function* () {
|
|
990
1018
|
const waiterId = yield* crypto.randomUUIDv4.pipe(Effect.mapError((error) => HostProtocolError.make({ message: boundHostDiagnostic(`awaitProgress cancellation identity generation failed: ${error.message}`) })));
|
|
@@ -993,7 +1021,7 @@ var CloudflareConversationClient = class CloudflareConversationClient extends Co
|
|
|
993
1021
|
waiterId
|
|
994
1022
|
});
|
|
995
1023
|
const encoded = yield* encodeAwaitProgressRequest(request).pipe(Effect.mapError((error) => HostProtocolError.make({ message: boundHostDiagnostic(`awaitProgress request encode failed: ${error.message}`) })));
|
|
996
|
-
const attempt = (retry) => call(conversationId, "awaitProgress", (stub) => stub.awaitProgressEncoded(encoded)).pipe(Effect.flatMap(expect(conversationId, "awaitProgress",
|
|
1024
|
+
const attempt = (retry) => call(conversationId, "awaitProgress", (stub) => stub.awaitProgressEncoded(encoded)).pipe(Effect.flatMap(expect(conversationId, "awaitProgress", ProgressObserved, ClientObserveHostFailure)), Effect.asVoid, Effect.catchTag("ConversationClientError", (error) => error.retryable === true && error.overloaded !== true && retry < 5 ? Effect.sleep(Duration.millis(10 * 2 ** retry)).pipe(Effect.andThen(attempt(retry + 1))) : Effect.fail(error)));
|
|
997
1025
|
yield* attempt(0).pipe(Effect.onInterrupt(() => cancelProgress(conversationId, waiterId)));
|
|
998
1026
|
}),
|
|
999
1027
|
readPage,
|
|
@@ -1014,33 +1042,40 @@ var CloudflareConversationClient = class CloudflareConversationClient extends Co
|
|
|
1014
1042
|
abort: (conversationId, command) => Effect.gen(function* () {
|
|
1015
1043
|
const encoded = yield* encodeAbortCommand(command).pipe(Effect.mapError((error) => HostProtocolError.make({ message: boundHostDiagnostic(`abort command encode failed: ${error.message}`) })));
|
|
1016
1044
|
const response = yield* call(conversationId, "abort", (stub) => stub.abortEncoded(encoded));
|
|
1017
|
-
return (yield* expect(conversationId, "abort",
|
|
1045
|
+
return (yield* expect(conversationId, "abort", AbortRecorded, ClientAbortHostFailure)(response)).intent;
|
|
1018
1046
|
}),
|
|
1019
1047
|
resolveApproval: (conversationId, command) => Effect.gen(function* () {
|
|
1020
1048
|
const encoded = yield* encodeApprovalDecisionCommand(command).pipe(Effect.mapError((error) => HostProtocolError.make({ message: boundHostDiagnostic(`approval command encode failed: ${error.message}`) })));
|
|
1021
1049
|
const response = yield* call(conversationId, "resolveApproval", (stub) => stub.resolveApprovalEncoded(encoded));
|
|
1022
|
-
return (yield* expect(conversationId, "resolveApproval",
|
|
1050
|
+
return (yield* expect(conversationId, "resolveApproval", ApprovalRecorded, ClientApprovalHostFailure)(response)).intent;
|
|
1023
1051
|
}),
|
|
1024
1052
|
resolveUnknown: (conversationId, command) => Effect.gen(function* () {
|
|
1025
1053
|
const encoded = yield* encodeUnknownResolutionCommand(command).pipe(Effect.mapError((error) => HostProtocolError.make({ message: boundHostDiagnostic(`resolution command encode failed: ${error.message}`) })));
|
|
1026
1054
|
const response = yield* call(conversationId, "resolveUnknown", (stub) => stub.resolveUnknownEncoded(encoded));
|
|
1027
|
-
return (yield* expect(conversationId, "resolveUnknown",
|
|
1055
|
+
return (yield* expect(conversationId, "resolveUnknown", UnknownResolutionRecorded, ClientUnknownHostFailure)(response)).intent;
|
|
1028
1056
|
})
|
|
1029
1057
|
});
|
|
1030
1058
|
}));
|
|
1031
1059
|
};
|
|
1032
1060
|
//#endregion
|
|
1033
1061
|
//#region src/conversation-object.ts
|
|
1034
|
-
/**
|
|
1035
|
-
const
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1062
|
+
/** Classify only a decoded port request so new protocol members cannot bypass pre-arming. */
|
|
1063
|
+
const isMutatingPortRequest = (request) => {
|
|
1064
|
+
switch (request._tag) {
|
|
1065
|
+
case "LedgerAdmit":
|
|
1066
|
+
case "LedgerMarkReady":
|
|
1067
|
+
case "LedgerRequestAbort":
|
|
1068
|
+
case "LedgerRecordChildSettled":
|
|
1069
|
+
case "StoreMaterialize":
|
|
1070
|
+
case "StoreAppend": return true;
|
|
1071
|
+
case "LedgerLookup":
|
|
1072
|
+
case "LedgerResolveAdmission":
|
|
1073
|
+
case "StoreReadPage":
|
|
1074
|
+
case "StoreInspectTail":
|
|
1075
|
+
case "StoreExport": return false;
|
|
1076
|
+
}
|
|
1077
|
+
return false;
|
|
1078
|
+
};
|
|
1044
1079
|
/** The literal encoded `PortFailed(PortProtocolError)` fallback (same shape as WP2's). */
|
|
1045
1080
|
const encodedPortProtocolFailure = (message) => ({
|
|
1046
1081
|
_tag: "PortFailed",
|
|
@@ -1253,10 +1288,18 @@ const portCallEndpoint = (encoded) => Effect.gen(function* () {
|
|
|
1253
1288
|
const ports = yield* ConversationObjectPorts;
|
|
1254
1289
|
const maintenance = yield* ConversationMaintenance;
|
|
1255
1290
|
const alarm = yield* DurableAlarmService;
|
|
1256
|
-
const
|
|
1257
|
-
|
|
1291
|
+
const decoded = yield* decodePortRequest(encoded).pipe(Effect.map((request) => ({
|
|
1292
|
+
_tag: "success",
|
|
1293
|
+
request
|
|
1294
|
+
})), Effect.catch((error) => Effect.succeed({
|
|
1295
|
+
_tag: "failure",
|
|
1296
|
+
message: error.message
|
|
1297
|
+
})));
|
|
1298
|
+
if (decoded._tag === "failure") return encodedPortProtocolFailure(`The port request could not be decoded: ${decoded.message}`);
|
|
1299
|
+
const mutating = isMutatingPortRequest(decoded.request);
|
|
1300
|
+
const handled = yield* (mutating ? maintenance.withMutation(ports.handle(decoded.request)) : ports.handle(decoded.request)).pipe(Effect.exit);
|
|
1258
1301
|
if (handled._tag === "Failure") return encodedPortProtocolFailure("The owner Object could not arm its maintenance alarm before the mutation.");
|
|
1259
|
-
const response = handled.value;
|
|
1302
|
+
const response = yield* encodePortResponse(handled.value).pipe(Effect.catch((error) => Effect.succeed(encodedPortProtocolFailure(`The port response could not be encoded: ${error.message}`))));
|
|
1260
1303
|
if (mutating) yield* alarm.scheduleNow.pipe(Effect.catch((error) => Effect.logWarning("ConversationObject.portCall: immediate re-arm failed", error)));
|
|
1261
1304
|
return response;
|
|
1262
1305
|
});
|
|
@@ -1370,7 +1413,8 @@ const passRegistry = /* @__PURE__ */ new Map();
|
|
|
1370
1413
|
*/
|
|
1371
1414
|
var CodeModeHostEntrypoint = class extends WorkerEntrypoint {
|
|
1372
1415
|
async call(passId, hostCall) {
|
|
1373
|
-
|
|
1416
|
+
if (typeof passId !== "string") throw new TypeError("Code Mode pass identities must be strings");
|
|
1417
|
+
const pass = passRegistry.get(passId);
|
|
1374
1418
|
if (pass === void 0) throw new Error("Unknown Code Mode pass");
|
|
1375
1419
|
return pass.dispatch(hostCall);
|
|
1376
1420
|
}
|
|
@@ -1408,7 +1452,7 @@ const safeJson = (value) => {
|
|
|
1408
1452
|
|
|
1409
1453
|
export default class CodeModeHarness extends WorkerEntrypoint {
|
|
1410
1454
|
async run() {
|
|
1411
|
-
const config =
|
|
1455
|
+
const config = this.env.CODE_MODE_PASS;
|
|
1412
1456
|
const host = this.env.CODE_MODE_HOST;
|
|
1413
1457
|
const limits = config.limits;
|
|
1414
1458
|
const logs = [];
|
|
@@ -1527,24 +1571,16 @@ export default class CodeModeHarness extends WorkerEntrypoint {
|
|
|
1527
1571
|
}
|
|
1528
1572
|
`;
|
|
1529
1573
|
const BoundedLogs = Schema.Array(Schema.String.check(Schema.isMaxLength(16 * 1024))).check(Schema.isMaxLength(4096));
|
|
1530
|
-
const HarnessCompleted = Schema.
|
|
1531
|
-
_tag: Schema.Literal("completed"),
|
|
1574
|
+
const HarnessCompleted = Schema.TaggedStruct("completed", {
|
|
1532
1575
|
value: Schema.Json,
|
|
1533
1576
|
logs: BoundedLogs,
|
|
1534
1577
|
hostCalls: Schema.Natural,
|
|
1535
1578
|
logBytes: Schema.Natural,
|
|
1536
1579
|
resultBytes: Schema.Natural
|
|
1537
1580
|
});
|
|
1538
|
-
const HarnessSourceInvalid = Schema.
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
});
|
|
1542
|
-
const HarnessNotAFunction = Schema.Struct({
|
|
1543
|
-
_tag: Schema.Literal("source-not-a-function"),
|
|
1544
|
-
actual: Schema.String
|
|
1545
|
-
});
|
|
1546
|
-
const HarnessProgramFailed = Schema.Struct({
|
|
1547
|
-
_tag: Schema.Literal("program-failed"),
|
|
1581
|
+
const HarnessSourceInvalid = Schema.TaggedStruct("source-invalid", { message: Schema.String });
|
|
1582
|
+
const HarnessNotAFunction = Schema.TaggedStruct("source-not-a-function", { actual: Schema.String });
|
|
1583
|
+
const HarnessProgramFailed = Schema.TaggedStruct("program-failed", {
|
|
1548
1584
|
reason: Schema.Literals([
|
|
1549
1585
|
"threw",
|
|
1550
1586
|
"rejected",
|
|
@@ -1554,29 +1590,20 @@ const HarnessProgramFailed = Schema.Struct({
|
|
|
1554
1590
|
message: Schema.String,
|
|
1555
1591
|
logs: BoundedLogs
|
|
1556
1592
|
});
|
|
1557
|
-
const HarnessLogLimit = Schema.
|
|
1558
|
-
_tag: Schema.Literal("log-limit"),
|
|
1593
|
+
const HarnessLogLimit = Schema.TaggedStruct("log-limit", {
|
|
1559
1594
|
observed: Schema.Natural,
|
|
1560
1595
|
logs: BoundedLogs
|
|
1561
1596
|
});
|
|
1562
|
-
const HarnessArgumentLimit = Schema.
|
|
1563
|
-
_tag: Schema.Literal("argument-limit"),
|
|
1597
|
+
const HarnessArgumentLimit = Schema.TaggedStruct("argument-limit", {
|
|
1564
1598
|
observed: Schema.Natural,
|
|
1565
1599
|
logs: BoundedLogs
|
|
1566
1600
|
});
|
|
1567
|
-
const HarnessResultLimit = Schema.
|
|
1568
|
-
_tag: Schema.Literal("result-limit"),
|
|
1601
|
+
const HarnessResultLimit = Schema.TaggedStruct("result-limit", {
|
|
1569
1602
|
observed: Schema.Natural,
|
|
1570
1603
|
logs: BoundedLogs
|
|
1571
1604
|
});
|
|
1572
|
-
const HarnessHostCallLimit = Schema.
|
|
1573
|
-
|
|
1574
|
-
logs: BoundedLogs
|
|
1575
|
-
});
|
|
1576
|
-
const HarnessProtocol = Schema.Struct({
|
|
1577
|
-
_tag: Schema.Literal("protocol"),
|
|
1578
|
-
message: Schema.String
|
|
1579
|
-
});
|
|
1605
|
+
const HarnessHostCallLimit = Schema.TaggedStruct("host-call-limit", { logs: BoundedLogs });
|
|
1606
|
+
const HarnessProtocol = Schema.TaggedStruct("protocol", { message: Schema.String });
|
|
1580
1607
|
const HarnessOutcome = Schema.Union([
|
|
1581
1608
|
HarnessCompleted,
|
|
1582
1609
|
HarnessSourceInvalid,
|
|
@@ -1588,6 +1615,22 @@ const HarnessOutcome = Schema.Union([
|
|
|
1588
1615
|
HarnessHostCallLimit,
|
|
1589
1616
|
HarnessProtocol
|
|
1590
1617
|
]);
|
|
1618
|
+
const HarnessPassConfig = Schema.Struct({
|
|
1619
|
+
passId: Schema.NonEmptyString,
|
|
1620
|
+
namespaces: Schema.Array(Schema.Struct({
|
|
1621
|
+
name: Schema.NonEmptyString,
|
|
1622
|
+
methods: Schema.Array(Schema.NonEmptyString).check(Schema.isMaxLength(64))
|
|
1623
|
+
})).check(Schema.isMaxLength(32)),
|
|
1624
|
+
limits: Schema.Struct({
|
|
1625
|
+
maxLogBytes: Schema.Natural,
|
|
1626
|
+
maxResultBytes: Schema.Natural,
|
|
1627
|
+
maxHostCalls: Schema.Natural,
|
|
1628
|
+
maxHostCallArgumentBytes: Schema.Natural
|
|
1629
|
+
})
|
|
1630
|
+
});
|
|
1631
|
+
const encodeHarnessPassConfig = Schema.encodeSync(HarnessPassConfig);
|
|
1632
|
+
const encodeJsonPayload = Schema.encodeSync(Schema.fromJsonString(Schema.Json));
|
|
1633
|
+
const decodeJsonPayload = Schema.decodeUnknownOption(Schema.fromJsonString(Schema.Json));
|
|
1591
1634
|
const decodeHarnessOutcome = (value) => {
|
|
1592
1635
|
try {
|
|
1593
1636
|
return Schema.decodeUnknownOption(HarnessOutcome)(value);
|
|
@@ -1609,11 +1652,20 @@ const decodeHostCallResult = (value) => {
|
|
|
1609
1652
|
return Option.none();
|
|
1610
1653
|
}
|
|
1611
1654
|
};
|
|
1655
|
+
/** Dispose a Cloudflare RPC handle when the runtime supplies its untyped disposal hook. @internal */
|
|
1656
|
+
const disposeRpcHandle = (handle) => Effect.try({
|
|
1657
|
+
try: () => {
|
|
1658
|
+
if (typeof handle !== "object" && typeof handle !== "function" || handle === null) return;
|
|
1659
|
+
if (!(Symbol.dispose in handle)) return;
|
|
1660
|
+
const dispose = Reflect.get(handle, Symbol.dispose);
|
|
1661
|
+
if (typeof dispose === "function") Reflect.apply(dispose, handle, []);
|
|
1662
|
+
},
|
|
1663
|
+
catch: (cause) => safeCauseDiagnostic(cause, "The Cloudflare RPC disposal hook failed without a diagnostic")
|
|
1664
|
+
}).pipe(Effect.catch((diagnostic) => Effect.logWarning(`Cloudflare RPC handle disposal failed: ${diagnostic}`).pipe(Effect.ignoreCause)));
|
|
1612
1665
|
const encodeHostResultPayload = (outcome) => {
|
|
1613
1666
|
try {
|
|
1614
1667
|
const payload = outcome._tag === "CodeHostCallSuccess" ? outcome.value : outcome.error;
|
|
1615
|
-
const encodedPayload =
|
|
1616
|
-
if (encodedPayload === void 0) return void 0;
|
|
1668
|
+
const encodedPayload = encodeJsonPayload(payload);
|
|
1617
1669
|
return {
|
|
1618
1670
|
encodedPayload,
|
|
1619
1671
|
resultBytes: utf8ByteLength(encodedPayload)
|
|
@@ -1632,8 +1684,7 @@ const utf8ByteLength = (value) => {
|
|
|
1632
1684
|
};
|
|
1633
1685
|
/** Reserved global names the harness owns inside the dynamic worker. */
|
|
1634
1686
|
const reservedHarnessGlobals = /* @__PURE__ */ new Set(["console"]);
|
|
1635
|
-
const
|
|
1636
|
-
const makeExecute = (options) => Effect.fn("DynamicWorkerCodeExecutor.execute")(function* (request) {
|
|
1687
|
+
const makeExecute = (options, crypto, clock) => Effect.fn("DynamicWorkerCodeExecutor.execute")(function* (request) {
|
|
1637
1688
|
if (request.network._tag !== "NetworkDisabled") return yield* CodeExecutorUnsupportedError.make({
|
|
1638
1689
|
implementation: dynamicWorkerImplementation,
|
|
1639
1690
|
feature: "network",
|
|
@@ -1651,11 +1702,17 @@ const makeExecute = (options) => Effect.fn("DynamicWorkerCodeExecutor.execute")(
|
|
|
1651
1702
|
message: `Namespace ${namespace.name} collides with a harness binding`
|
|
1652
1703
|
});
|
|
1653
1704
|
const host = yield* CodeExecutionHost;
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1705
|
+
const passId = yield* crypto.randomUUIDv4.pipe(Effect.mapError((cause) => CodeExecutorStartError.make({
|
|
1706
|
+
implementation: dynamicWorkerImplementation,
|
|
1707
|
+
message: `Could not mint the Code Mode pass identity: ${safeCauseMessage(cause, "the crypto service failed without a diagnostic")}`.slice(0, 8e3),
|
|
1708
|
+
cause
|
|
1709
|
+
})), Effect.map((uuid) => `code-mode-pass-${uuid}`));
|
|
1710
|
+
const startedAt = clock.monotonicTimeNanosUnsafe();
|
|
1711
|
+
const passDeadline = startedAt + Duration.toNanosUnsafe(request.limits.maxWallTime);
|
|
1712
|
+
const remainingPassWallTime = () => {
|
|
1713
|
+
const now = clock.monotonicTimeNanosUnsafe();
|
|
1714
|
+
return Duration.nanos(passDeadline > now ? passDeadline - now : 0n);
|
|
1715
|
+
};
|
|
1659
1716
|
let issuedHostCalls = 0;
|
|
1660
1717
|
let passOpen = true;
|
|
1661
1718
|
const queuedHostCalls = [];
|
|
@@ -1689,13 +1746,21 @@ const makeExecute = (options) => Effect.fn("DynamicWorkerCodeExecutor.execute")(
|
|
|
1689
1746
|
failPass(error);
|
|
1690
1747
|
return yield* error;
|
|
1691
1748
|
}
|
|
1692
|
-
const normalizedPayload =
|
|
1749
|
+
const normalizedPayload = decodeJsonPayload(encoded.encodedPayload);
|
|
1750
|
+
if (Option.isNone(normalizedPayload)) {
|
|
1751
|
+
const error = CodeExecutionProtocolError.make({
|
|
1752
|
+
implementation: dynamicWorkerImplementation,
|
|
1753
|
+
message: "The execution host returned a result that could not cross the JSON boundary"
|
|
1754
|
+
});
|
|
1755
|
+
failPass(error);
|
|
1756
|
+
return yield* error;
|
|
1757
|
+
}
|
|
1693
1758
|
queued.resolve(decoded.value._tag === "CodeHostCallSuccess" ? {
|
|
1694
1759
|
_tag: "CodeHostCallSuccess",
|
|
1695
|
-
value: normalizedPayload
|
|
1760
|
+
value: normalizedPayload.value
|
|
1696
1761
|
} : {
|
|
1697
1762
|
_tag: "CodeHostCallFailure",
|
|
1698
|
-
error: normalizedPayload
|
|
1763
|
+
error: normalizedPayload.value
|
|
1699
1764
|
});
|
|
1700
1765
|
});
|
|
1701
1766
|
const server = yield* Effect.gen(function* () {
|
|
@@ -1771,7 +1836,7 @@ const makeExecute = (options) => Effect.fn("DynamicWorkerCodeExecutor.execute")(
|
|
|
1771
1836
|
},
|
|
1772
1837
|
env: {
|
|
1773
1838
|
CODE_MODE_HOST: options.hostStub,
|
|
1774
|
-
CODE_MODE_PASS:
|
|
1839
|
+
CODE_MODE_PASS: encodeHarnessPassConfig({
|
|
1775
1840
|
passId,
|
|
1776
1841
|
namespaces: request.namespaces.map((namespace) => ({
|
|
1777
1842
|
name: namespace.name,
|
|
@@ -1794,7 +1859,7 @@ const makeExecute = (options) => Effect.fn("DynamicWorkerCodeExecutor.execute")(
|
|
|
1794
1859
|
const worker = yield* Effect.acquireRelease(Effect.try({
|
|
1795
1860
|
try: () => options.loader.load(workerCode),
|
|
1796
1861
|
catch: (cause) => {
|
|
1797
|
-
const text = cause
|
|
1862
|
+
const text = safeCauseMessage(cause, "The Worker Loader failed without a diagnostic");
|
|
1798
1863
|
if (/syntaxerror|failed to (compile|parse)/i.test(text)) return CodeSourceError.make({
|
|
1799
1864
|
implementation: dynamicWorkerImplementation,
|
|
1800
1865
|
reason: "invalid",
|
|
@@ -1806,13 +1871,13 @@ const makeExecute = (options) => Effect.fn("DynamicWorkerCodeExecutor.execute")(
|
|
|
1806
1871
|
cause
|
|
1807
1872
|
});
|
|
1808
1873
|
}
|
|
1809
|
-
}),
|
|
1810
|
-
|
|
1811
|
-
|
|
1874
|
+
}), disposeRpcHandle);
|
|
1875
|
+
const entrypoint = yield* Effect.acquireRelease(Effect.try({
|
|
1876
|
+
try: () => worker.getEntrypoint(),
|
|
1877
|
+
catch: (cause) => classifyWorkerFailure(cause, request.limits.maxWallTime)
|
|
1878
|
+
}), disposeRpcHandle);
|
|
1812
1879
|
const rpc = Effect.tryPromise({
|
|
1813
|
-
try:
|
|
1814
|
-
return await worker.getEntrypoint().run();
|
|
1815
|
-
},
|
|
1880
|
+
try: () => entrypoint.run(),
|
|
1816
1881
|
catch: (cause) => classifyWorkerFailure(cause, request.limits.maxWallTime)
|
|
1817
1882
|
});
|
|
1818
1883
|
const exit = yield* Effect.raceFirst(rpc.pipe(Effect.timeoutOrElse({
|
|
@@ -1829,7 +1894,7 @@ const makeExecute = (options) => Effect.fn("DynamicWorkerCodeExecutor.execute")(
|
|
|
1829
1894
|
if (passFailure !== void 0) return yield* passFailure;
|
|
1830
1895
|
if (Exit.isFailure(exit)) return yield* Effect.failCause(exit.cause);
|
|
1831
1896
|
const raw = exit.value;
|
|
1832
|
-
const finishedAt =
|
|
1897
|
+
const finishedAt = clock.monotonicTimeNanosUnsafe();
|
|
1833
1898
|
const outcome = decodeHarnessOutcome(raw);
|
|
1834
1899
|
if (Option.isNone(outcome)) return yield* CodeExecutionProtocolError.make({
|
|
1835
1900
|
implementation: dynamicWorkerImplementation,
|
|
@@ -1841,7 +1906,7 @@ const makeExecute = (options) => Effect.fn("DynamicWorkerCodeExecutor.execute")(
|
|
|
1841
1906
|
value: outcome.value.value,
|
|
1842
1907
|
logs: outcome.value.logs,
|
|
1843
1908
|
resourceUse: CodeExecutionResourceUse.make({
|
|
1844
|
-
wallTime: Duration.
|
|
1909
|
+
wallTime: Duration.nanos(finishedAt > startedAt ? finishedAt - startedAt : 0n),
|
|
1845
1910
|
hostCalls: outcome.value.hostCalls,
|
|
1846
1911
|
logBytes: outcome.value.logBytes,
|
|
1847
1912
|
resultBytes: outcome.value.resultBytes
|
|
@@ -1902,13 +1967,7 @@ const makeExecute = (options) => Effect.fn("DynamicWorkerCodeExecutor.execute")(
|
|
|
1902
1967
|
* than a fabricated program result.
|
|
1903
1968
|
*/
|
|
1904
1969
|
const classifyWorkerFailure = (cause, maxWallTime) => {
|
|
1905
|
-
const text = (
|
|
1906
|
-
try {
|
|
1907
|
-
return cause instanceof Error ? `${cause.name}: ${cause.message}` : String(cause);
|
|
1908
|
-
} catch {
|
|
1909
|
-
return "[unserializable worker failure]";
|
|
1910
|
-
}
|
|
1911
|
-
})();
|
|
1970
|
+
const text = safeCauseDiagnostic(cause, "[unserializable worker failure]");
|
|
1912
1971
|
if (/syntaxerror|failed to (compile|parse)/i.test(text)) return CodeSourceError.make({
|
|
1913
1972
|
implementation: dynamicWorkerImplementation,
|
|
1914
1973
|
reason: "invalid",
|
|
@@ -1931,8 +1990,12 @@ const classifyWorkerFailure = (cause, maxWallTime) => {
|
|
|
1931
1990
|
});
|
|
1932
1991
|
};
|
|
1933
1992
|
/** Layer building the Dynamic Worker `CodeExecutor` from resolved bindings. */
|
|
1934
|
-
const dynamicWorkerCodeExecutorLayer = (options) => Layer.
|
|
1993
|
+
const dynamicWorkerCodeExecutorLayer = (options) => Layer.effect(CodeExecutor, Effect.gen(function* () {
|
|
1994
|
+
const crypto = yield* Crypto.Crypto;
|
|
1995
|
+
const clock = yield* Clock.Clock;
|
|
1996
|
+
return CodeExecutor.of({ execute: makeExecute(options, crypto, clock) });
|
|
1997
|
+
})).pipe(Layer.provide(BrowserCrypto.layer));
|
|
1935
1998
|
//#endregion
|
|
1936
|
-
export { AbortRecorded, AdminExplainRequest, AdminFailed, AdminFailure, AdminResponse, AdminVerifyRequest, AdmissionLimitExceeded, ApprovalRecorded, AwaitProgressRequest, CLOUDFLARE_DATABASE_CAP_BYTES, CLOUDFLARE_RUNTIME_DEFAULTS, CancelProgressRequest, CloudflareAdmissionLimitsValue, CloudflareBindingError, CloudflareConversationClient, CloudflareDurableRuntime, CloudflareDurableRuntimeConfig, CloudflareDurableRuntimeConfigValue, CloudflarePlatformConfigError, CodeModeHostEntrypoint, ConversationClientError, ConversationMaintenance, ConversationMaintenanceFailpoint, ConversationObjectIdentity, ConversationObjectNamespace, ConversationObjectPorts, DEFAULT_MAX_DATABASE_BYTES, DurableAlarmError, DurableAlarmService, DurableObjectContext, ExplainedRecovery, HostFailed, HostFailure, HostProtocolError, HostResponse, MaintenancePassReport, ObligationsScanned, ObservePageRequest, ObservedPage, ProgressCancelled, ProgressObserved, ProgressWaitRegistry, RetryExecuted, SettlementReached, SubmitRequest, SubmitSucceeded, UnknownResolutionRecorded, VerifiedIntegrity, boundHostDiagnostic, cloudflareWakeSchedulerLayer, conversationNamespaceFromEnv, conversationNamespaceLayer, conversationPortTransportLayer, decodeAbortCommand, decodeAdminExplainRequest, decodeAdminResponse, decodeAdminVerifyRequest, decodeApprovalDecisionCommand, decodeAwaitProgressRequest, decodeCancelProgressRequest, decodeHostResponse, decodeObligationThresholds, decodeObservePageRequest, decodeReceipt, decodeRetryCommand, decodeSubmitRequest, decodeUnknownResolutionCommand, dynamicWorkerCodeExecutorLayer, dynamicWorkerImplementation, encodeAbortCommand, encodeAdminResponse, encodeApprovalDecisionCommand, encodeAwaitProgressRequest, encodeCancelProgressRequest, encodeHostResponse, encodeObservePageRequest, encodeReceipt, encodeSubmitRequest, encodeUnknownResolutionCommand, makeConversationObjectClass };
|
|
1999
|
+
export { AbortRecorded, AdminExplainRequest, AdminFailed, AdminFailure, AdminResponse, AdminVerifyRequest, AdmissionLimitExceeded, ApprovalRecorded, AwaitProgressRequest, CLOUDFLARE_DATABASE_CAP_BYTES, CLOUDFLARE_RUNTIME_DEFAULTS, CancelProgressRequest, CloudflareAdmissionLimitsValue, CloudflareBindingError, CloudflareConversationClient, CloudflareDurableRuntime, CloudflareDurableRuntimeConfig, CloudflareDurableRuntimeConfigValue, CloudflarePlatformConfigError, CodeModeHostEntrypoint, ConversationClientError, ConversationMaintenance, ConversationMaintenanceFailpoint, ConversationObjectIdentity, ConversationObjectNamespace, ConversationObjectPorts, DEFAULT_MAX_DATABASE_BYTES, DurableAlarmError, DurableAlarmService, DurableObjectContext, ExplainedRecovery, HostFailed, HostFailure, HostProtocolError, HostResponse, MaintenancePassReport, ObligationsScanned, ObservePageRequest, ObservedPage, ProgressCancelled, ProgressObserved, ProgressWaitRegistry, RetryExecuted, SettlementReached, SubmitRequest, SubmitSucceeded, UnknownResolutionRecorded, VerifiedIntegrity, boundHostDiagnostic, cloudflareWakeSchedulerLayer, conversationNamespaceFromEnv, conversationNamespaceLayer, conversationPortTransportLayer, decodeAbortCommand, decodeAdminExplainRequest, decodeAdminResponse, decodeAdminVerifyRequest, decodeApprovalDecisionCommand, decodeAwaitProgressRequest, decodeCancelProgressRequest, decodeHostResponse, decodeObligationThresholds, decodeObservePageRequest, decodeReceipt, decodeRetryCommand, decodeSubmitRequest, decodeUnknownResolutionCommand, disposeRpcHandle, dynamicWorkerCodeExecutorLayer, dynamicWorkerImplementation, encodeAbortCommand, encodeAdminResponse, encodeApprovalDecisionCommand, encodeAwaitProgressRequest, encodeCancelProgressRequest, encodeHostResponse, encodeObservePageRequest, encodeReceipt, encodeSubmitRequest, encodeUnknownResolutionCommand, makeConversationObjectClass };
|
|
1937
2000
|
|
|
1938
2001
|
//# sourceMappingURL=index.mjs.map
|