@effect-agent/platform-cloudflare 0.0.1-beta.6 → 0.1.0-beta.8
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 +24 -57
- package/dist/index.mjs +63 -368
- package/dist/index.mjs.map +1 -1
- package/package.json +20 -19
- package/src/config.ts +0 -3
- package/src/conversation-object.ts +139 -218
- package/src/index.ts +0 -1
- package/src/layers.ts +5 -14
- package/src/telemetry-internal.ts +0 -432
- package/src/telemetry.ts +0 -37
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Clock, Context, Duration, Effect, 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
|
-
import { DurableObject,
|
|
7
|
+
import { DurableObject, DurableObjectState, WorkerEnvironment } from "effect-cf";
|
|
8
8
|
import { CodeExecutionHost, CodeExecutionProtocolError, CodeExecutionResourceUse, CodeExecutionResult, CodeExecutionTimeoutError, CodeExecutor, CodeExecutorStartError, CodeExecutorTerminatedError, CodeExecutorUnsupportedError, CodeHostCall, CodeHostCallLimitError, CodeOutputLimitError, CodeProgramFailedError, CodeSourceError, SandboxImplementation } from "@effect-agent/sandbox";
|
|
9
|
+
import { WorkerEntrypoint } from "cloudflare:workers";
|
|
9
10
|
//#region src/bindings.ts
|
|
10
11
|
/**
|
|
11
12
|
* Cloudflare platform bindings as Effect services (DEPLOY-010: "Cloudflare platform bindings
|
|
@@ -147,8 +148,6 @@ var CloudflareDurableRuntimeConfigValue = class extends Schema.Class("@effect-ag
|
|
|
147
148
|
abortPollInterval: PositiveMillis,
|
|
148
149
|
/** Canonical observation poll cadence of the Durable Object store. */
|
|
149
150
|
observationPollInterval: NonNegativeMillis,
|
|
150
|
-
/** Cooperative background-export budget; native Object delivery never awaits the flush. */
|
|
151
|
-
telemetryFlushTimeout: PositiveMillis,
|
|
152
151
|
/** Per-value byte bound; must stay under the platform's 2 MB SQLite value limit. */
|
|
153
152
|
maxStoredValueBytes: Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(2e6)),
|
|
154
153
|
/** Opt-in full payload/digest-chain audit while opening the store. */
|
|
@@ -167,7 +166,6 @@ const CLOUDFLARE_RUNTIME_DEFAULTS = {
|
|
|
167
166
|
leaseRenewalInterval: 1e4,
|
|
168
167
|
abortPollInterval: 500,
|
|
169
168
|
observationPollInterval: 25,
|
|
170
|
-
telemetryFlushTimeout: 2e3,
|
|
171
169
|
maxStoredValueBytes: DEFAULT_MAX_STORED_VALUE_BYTES,
|
|
172
170
|
verifyOnOpen: false,
|
|
173
171
|
maxQueueDepthPerLane: 256,
|
|
@@ -415,31 +413,6 @@ const conversationPortTransportLayer = Layer.effect(ConversationPortTransport)(E
|
|
|
415
413
|
}).pipe(Effect.withSpan("CloudflarePortTransport.call", { attributes: { conversationId } })) });
|
|
416
414
|
}));
|
|
417
415
|
//#endregion
|
|
418
|
-
//#region src/telemetry.ts
|
|
419
|
-
/** A host exporter failed during one coalesced background export attempt. */
|
|
420
|
-
var CloudflareTelemetryExportError = class extends Schema.TaggedError()("CloudflareTelemetryExportError", {
|
|
421
|
-
/** The original exporter failure, retained for host-side diagnostics. */
|
|
422
|
-
cause: Schema.Defect() }) {};
|
|
423
|
-
/**
|
|
424
|
-
* Host-owned exporter lifecycle for one Cloudflare Conversation Object incarnation.
|
|
425
|
-
*
|
|
426
|
-
* The platform package creates measurements but deliberately does not select an exporter or
|
|
427
|
-
* vendor. Native entrypoint instrumentation consumes this service at the Worker composition edge;
|
|
428
|
-
* applications pass its provider as the second `makeConversationObjectClass` argument together
|
|
429
|
-
* with their Effect Logger, Tracer, and Metric layers. That provider may read `DurableObjectContext` or
|
|
430
|
-
* `ConversationObjectNamespace`, and its typed acquisition error remains visible in construction.
|
|
431
|
-
* `flush` must attempt to export every configured signal. After the native span closes, the
|
|
432
|
-
* Conversation Object reserves it into a shared post-settlement batch before `ctx.waitUntil` under
|
|
433
|
-
* a cooperative timeout. Only each pending/trailing/queued batch's first owner registers its
|
|
434
|
-
* shared Promise. Cycles remain capped at one first exporter attempt plus at most one trailing
|
|
435
|
-
* attempt, with one queued cycle while trailing runs; exporter completion never holds endpoint
|
|
436
|
-
* delivery open and exporter failure never replaces endpoint behavior.
|
|
437
|
-
*/
|
|
438
|
-
var CloudflareRuntimeTelemetry = class CloudflareRuntimeTelemetry extends Context.Service()("@effect-agent/platform-cloudflare/CloudflareRuntimeTelemetry") {
|
|
439
|
-
/** Content-free default selected by `makeConversationObjectClass` when no host Layer is passed. */
|
|
440
|
-
static layerNoop = Layer.succeed(CloudflareRuntimeTelemetry)({ flush: Effect.void });
|
|
441
|
-
};
|
|
442
|
-
//#endregion
|
|
443
416
|
//#region src/layers.ts
|
|
444
417
|
/**
|
|
445
418
|
* Owner-side endpoint body for the Conversation Object's `portCall` (plan §1.3): decode,
|
|
@@ -462,7 +435,6 @@ const configFromOptions = (options) => decodeConfigValue({
|
|
|
462
435
|
leaseRenewalInterval: options.leaseRenewalInterval ?? CLOUDFLARE_RUNTIME_DEFAULTS.leaseRenewalInterval,
|
|
463
436
|
abortPollInterval: options.abortPollInterval ?? CLOUDFLARE_RUNTIME_DEFAULTS.abortPollInterval,
|
|
464
437
|
observationPollInterval: options.observationPollInterval ?? CLOUDFLARE_RUNTIME_DEFAULTS.observationPollInterval,
|
|
465
|
-
telemetryFlushTimeout: options.telemetryFlushTimeout ?? CLOUDFLARE_RUNTIME_DEFAULTS.telemetryFlushTimeout,
|
|
466
438
|
maxStoredValueBytes: options.maxStoredValueBytes ?? CLOUDFLARE_RUNTIME_DEFAULTS.maxStoredValueBytes,
|
|
467
439
|
verifyOnOpen: options.verifyOnOpen ?? CLOUDFLARE_RUNTIME_DEFAULTS.verifyOnOpen,
|
|
468
440
|
limits: {
|
|
@@ -500,9 +472,9 @@ const resolveBindings = (source, context) => source === void 0 ? Effect.succeed(
|
|
|
500
472
|
* Storage compatibility is verified during construction: an incompatible database fails the
|
|
501
473
|
* Layer typed (`DoStorageCompatibilityError`) before anything is mutated (DEPLOY-008).
|
|
502
474
|
*
|
|
503
|
-
* Requires the two binding services (`DurableObjectContext`,
|
|
504
|
-
*
|
|
505
|
-
*
|
|
475
|
+
* Requires only the two binding services (`DurableObjectContext`,
|
|
476
|
+
* `ConversationObjectNamespace`) — platform values enter exclusively through Layers
|
|
477
|
+
* (DEPLOY-010).
|
|
506
478
|
*/
|
|
507
479
|
var CloudflareDurableRuntime = class {
|
|
508
480
|
static layer(options) {
|
|
@@ -808,258 +780,6 @@ var CloudflareConversationClient = class CloudflareConversationClient extends Co
|
|
|
808
780
|
}));
|
|
809
781
|
};
|
|
810
782
|
//#endregion
|
|
811
|
-
//#region src/telemetry-internal.ts
|
|
812
|
-
/** Bounded typed control signal used only while a native entrypoint span is active. */
|
|
813
|
-
var CloudflareNativeSpanFailure = class extends Error {
|
|
814
|
-
name = "ConversationObjectDeliveryFailed";
|
|
815
|
-
constructor() {
|
|
816
|
-
super("Cloudflare Conversation Object delivery failed");
|
|
817
|
-
}
|
|
818
|
-
};
|
|
819
|
-
const stripCloudflareNativeSpanFailures = (cause) => {
|
|
820
|
-
if (!cause.reasons.some((reason) => Cause.isFailReason(reason) && reason.error instanceof CloudflareNativeSpanFailure)) return {
|
|
821
|
-
found: false,
|
|
822
|
-
residual: cause
|
|
823
|
-
};
|
|
824
|
-
const reasons = cause.reasons.filter((reason) => {
|
|
825
|
-
if (Cause.isFailReason(reason) && reason.error instanceof CloudflareNativeSpanFailure) return false;
|
|
826
|
-
return true;
|
|
827
|
-
});
|
|
828
|
-
return {
|
|
829
|
-
found: true,
|
|
830
|
-
residual: Cause.fromReasons(reasons)
|
|
831
|
-
};
|
|
832
|
-
};
|
|
833
|
-
/**
|
|
834
|
-
* @internal Replace an entrypoint Cause with a bounded typed marker inside a span, then remove
|
|
835
|
-
* only that marker and restore the exact invocation-local Cause plus any newly composed reasons.
|
|
836
|
-
*/
|
|
837
|
-
const withCloudflareNativeSpanFailure = (effect, trace) => Effect.suspend(() => {
|
|
838
|
-
let original;
|
|
839
|
-
return trace(effect.pipe(Effect.catchCause((cause) => {
|
|
840
|
-
original = cause;
|
|
841
|
-
return Effect.fail(new CloudflareNativeSpanFailure());
|
|
842
|
-
}))).pipe(Effect.catchCause((cause) => {
|
|
843
|
-
const { found, residual } = stripCloudflareNativeSpanFailures(cause);
|
|
844
|
-
if (!found) return Effect.failCause(residual);
|
|
845
|
-
const restored = original === void 0 ? residual : Cause.combine(original, residual);
|
|
846
|
-
return Effect.failCause(restored);
|
|
847
|
-
}));
|
|
848
|
-
});
|
|
849
|
-
const logCloudflareTelemetryCause = (cause) => {
|
|
850
|
-
const kinds = /* @__PURE__ */ new Set();
|
|
851
|
-
for (const reason of cause.reasons) if (Cause.isFailReason(reason)) kinds.add(Cause.isTimeoutError(reason.error) ? "timeout" : "exporter");
|
|
852
|
-
else if (Cause.isDieReason(reason)) kinds.add("defect");
|
|
853
|
-
else kinds.add("interrupted");
|
|
854
|
-
return Effect.forEach(kinds, (kind) => {
|
|
855
|
-
return (kind === "defect" ? Effect.logError("Cloudflare telemetry flush defect") : Effect.logWarning(kind === "exporter" ? "Cloudflare telemetry exporter failed" : kind === "timeout" ? "Cloudflare telemetry flush exceeded its time budget" : "Cloudflare telemetry flush interrupted")).pipe(Effect.annotateLogs({ "effect_agent.cloudflare.telemetry.failure_kind": kind }));
|
|
856
|
-
}, { discard: true });
|
|
857
|
-
};
|
|
858
|
-
/**
|
|
859
|
-
* @internal Cooperative background flush budget. Interruptible exporters stop at the configured
|
|
860
|
-
* timeout; uninterruptible exporters remain bounded by Cloudflare's waitUntil lifecycle instead
|
|
861
|
-
* of holding the native delivery open.
|
|
862
|
-
*/
|
|
863
|
-
const flushCloudflareRuntimeTelemetry = (timeoutMillis) => Effect.flatMap(CloudflareRuntimeTelemetry, ({ flush }) => flush).pipe(Effect.interruptible, Effect.timeout(Duration.millis(timeoutMillis)), Effect.onExit((exit) => Exit.isFailure(exit) ? logCloudflareTelemetryCause(exit.cause) : Effect.void), Effect.asVoid);
|
|
864
|
-
/** @internal Convert the shared exporter result into the always-fulfilled waitUntil bridge. */
|
|
865
|
-
const fulfillCloudflareTelemetryBackground = (result) => result.then(() => void 0, () => void 0);
|
|
866
|
-
const makeFlushBatch = () => {
|
|
867
|
-
let resolveResult = () => void 0;
|
|
868
|
-
let rejectResult = (_cause) => void 0;
|
|
869
|
-
const result = new Promise((resolve, reject) => {
|
|
870
|
-
resolveResult = resolve;
|
|
871
|
-
rejectResult = reject;
|
|
872
|
-
});
|
|
873
|
-
let resolveReady = () => void 0;
|
|
874
|
-
const ready = new Promise((resolve) => {
|
|
875
|
-
resolveReady = resolve;
|
|
876
|
-
});
|
|
877
|
-
return {
|
|
878
|
-
result,
|
|
879
|
-
background: fulfillCloudflareTelemetryBackground(result),
|
|
880
|
-
resolveResult,
|
|
881
|
-
rejectResult,
|
|
882
|
-
ready,
|
|
883
|
-
resolveReady,
|
|
884
|
-
phase: "pending",
|
|
885
|
-
reservations: 0,
|
|
886
|
-
unsettledDeliveries: 0,
|
|
887
|
-
dropDiagnosed: false
|
|
888
|
-
};
|
|
889
|
-
};
|
|
890
|
-
const makeFlushCycle = () => {
|
|
891
|
-
let resolveCycle = () => void 0;
|
|
892
|
-
let rejectCycle = (_cause) => void 0;
|
|
893
|
-
const promise = new Promise((resolve, reject) => {
|
|
894
|
-
resolveCycle = resolve;
|
|
895
|
-
rejectCycle = reject;
|
|
896
|
-
});
|
|
897
|
-
fulfillCloudflareTelemetryBackground(promise);
|
|
898
|
-
return {
|
|
899
|
-
promise,
|
|
900
|
-
resolve: resolveCycle,
|
|
901
|
-
reject: rejectCycle,
|
|
902
|
-
first: makeFlushBatch(),
|
|
903
|
-
phase: "pending",
|
|
904
|
-
trailing: void 0
|
|
905
|
-
};
|
|
906
|
-
};
|
|
907
|
-
/**
|
|
908
|
-
* @internal Coordinate exporter attempts for one Conversation Object incarnation. Each cycle is
|
|
909
|
-
* capped at a first attempt plus one trailing attempt. Each batch is reserved synchronously and
|
|
910
|
-
* waits for every delivery assigned to it before exporting. Only the first owner of the pending,
|
|
911
|
-
* trailing, or queued batch registers that batch's shared background Promise, so a stalled
|
|
912
|
-
* exporter cannot accumulate per-delivery waitUntil registrations. Each batch retains at most
|
|
913
|
-
* `MAX_CLOUDFLARE_TELEMETRY_BATCH_DELIVERIES` settlement Promises; excess deliveries are lossy-
|
|
914
|
-
* coalesced into the already-requested export without settlement ownership and diagnosed once for
|
|
915
|
-
* that batch. Failures remain rejected by the raw cycle after every requested attempt runs; each
|
|
916
|
-
* shared waitUntil bridge always fulfills.
|
|
917
|
-
*/
|
|
918
|
-
const makeCloudflareTelemetryFlushCoordinator = (flush, options = {}) => {
|
|
919
|
-
let active;
|
|
920
|
-
let queued;
|
|
921
|
-
const closeBatch = (batch) => {
|
|
922
|
-
if (batch.phase !== "pending") return;
|
|
923
|
-
batch.phase = "waiting";
|
|
924
|
-
if (batch.unsettledDeliveries === 0) batch.resolveReady();
|
|
925
|
-
};
|
|
926
|
-
const cancelBatch = (batch) => {
|
|
927
|
-
if (batch.phase === "settled" || batch.phase === "cancelled") return;
|
|
928
|
-
batch.phase = "cancelled";
|
|
929
|
-
batch.resolveReady();
|
|
930
|
-
batch.resolveResult();
|
|
931
|
-
};
|
|
932
|
-
const reserveDelivery = (batch, delivery) => {
|
|
933
|
-
if (batch.reservations >= 64) {
|
|
934
|
-
if (!batch.dropDiagnosed) {
|
|
935
|
-
batch.dropDiagnosed = true;
|
|
936
|
-
try {
|
|
937
|
-
options.onReservationDropped?.();
|
|
938
|
-
} catch {}
|
|
939
|
-
}
|
|
940
|
-
return {
|
|
941
|
-
owner: false,
|
|
942
|
-
dropped: true
|
|
943
|
-
};
|
|
944
|
-
}
|
|
945
|
-
const owner = batch.reservations === 0;
|
|
946
|
-
batch.reservations += 1;
|
|
947
|
-
batch.unsettledDeliveries += 1;
|
|
948
|
-
const settled = () => {
|
|
949
|
-
batch.unsettledDeliveries -= 1;
|
|
950
|
-
if (batch.phase === "waiting" && batch.unsettledDeliveries === 0) batch.resolveReady();
|
|
951
|
-
};
|
|
952
|
-
delivery.then(settled, settled);
|
|
953
|
-
return {
|
|
954
|
-
owner,
|
|
955
|
-
dropped: false
|
|
956
|
-
};
|
|
957
|
-
};
|
|
958
|
-
const runCycle = async (cycle) => {
|
|
959
|
-
const failures = [];
|
|
960
|
-
const runAttempt = async () => {
|
|
961
|
-
try {
|
|
962
|
-
await flush();
|
|
963
|
-
} catch (cause) {
|
|
964
|
-
failures.push(cause);
|
|
965
|
-
}
|
|
966
|
-
};
|
|
967
|
-
const runBatch = async (batch) => {
|
|
968
|
-
closeBatch(batch);
|
|
969
|
-
await batch.ready;
|
|
970
|
-
if (batch.phase === "cancelled") return;
|
|
971
|
-
batch.phase = "running";
|
|
972
|
-
const failureStart = failures.length;
|
|
973
|
-
await runAttempt();
|
|
974
|
-
batch.phase = "settled";
|
|
975
|
-
if (failures.length === failureStart) batch.resolveResult();
|
|
976
|
-
else batch.rejectResult(failures[failures.length - 1]);
|
|
977
|
-
};
|
|
978
|
-
try {
|
|
979
|
-
cycle.phase = "first";
|
|
980
|
-
await runBatch(cycle.first);
|
|
981
|
-
const trailing = cycle.trailing;
|
|
982
|
-
if (trailing !== void 0) {
|
|
983
|
-
cycle.phase = "trailing";
|
|
984
|
-
await runBatch(trailing);
|
|
985
|
-
}
|
|
986
|
-
cycle.phase = "settling";
|
|
987
|
-
options.onSettling?.();
|
|
988
|
-
} finally {
|
|
989
|
-
const next = queued;
|
|
990
|
-
queued = void 0;
|
|
991
|
-
active = next;
|
|
992
|
-
if (next !== void 0) startCycle(next);
|
|
993
|
-
}
|
|
994
|
-
if (failures.length === 0) return;
|
|
995
|
-
if (failures.length === 1) throw failures[0];
|
|
996
|
-
throw new AggregateError(failures, `${failures.length} Cloudflare telemetry flush attempts failed`);
|
|
997
|
-
};
|
|
998
|
-
const startCycle = (cycle) => {
|
|
999
|
-
Promise.resolve().then(() => runCycle(cycle)).then(cycle.resolve, cycle.reject);
|
|
1000
|
-
};
|
|
1001
|
-
const reserve = (delivery) => {
|
|
1002
|
-
let cycle;
|
|
1003
|
-
let batch;
|
|
1004
|
-
let shouldStart = false;
|
|
1005
|
-
if (active === void 0) {
|
|
1006
|
-
cycle = makeFlushCycle();
|
|
1007
|
-
active = cycle;
|
|
1008
|
-
batch = cycle.first;
|
|
1009
|
-
shouldStart = true;
|
|
1010
|
-
} else if (active.phase === "pending" && active.first.phase !== "cancelled") {
|
|
1011
|
-
cycle = active;
|
|
1012
|
-
batch = active.first;
|
|
1013
|
-
} else if (active.phase === "first") {
|
|
1014
|
-
cycle = active;
|
|
1015
|
-
batch = active.trailing ??= makeFlushBatch();
|
|
1016
|
-
} else {
|
|
1017
|
-
if (queued === void 0) queued = makeFlushCycle();
|
|
1018
|
-
cycle = queued;
|
|
1019
|
-
batch = queued.first;
|
|
1020
|
-
}
|
|
1021
|
-
const { dropped, owner } = reserveDelivery(batch, delivery);
|
|
1022
|
-
if (shouldStart) startCycle(cycle);
|
|
1023
|
-
return {
|
|
1024
|
-
background: batch.background,
|
|
1025
|
-
cycle: cycle.promise,
|
|
1026
|
-
owner,
|
|
1027
|
-
dropped,
|
|
1028
|
-
cancel: () => {
|
|
1029
|
-
if (!owner) return;
|
|
1030
|
-
cancelBatch(batch);
|
|
1031
|
-
if (cycle.trailing === batch && cycle.phase === "first") cycle.trailing = void 0;
|
|
1032
|
-
else if (queued === cycle && active !== cycle) {
|
|
1033
|
-
queued = void 0;
|
|
1034
|
-
cycle.resolve();
|
|
1035
|
-
}
|
|
1036
|
-
}
|
|
1037
|
-
};
|
|
1038
|
-
};
|
|
1039
|
-
return { reserve };
|
|
1040
|
-
};
|
|
1041
|
-
/**
|
|
1042
|
-
* @internal Reserve telemetry before registration without allowing a synchronous platform failure
|
|
1043
|
-
* to replace the already-running native delivery Promise. Only a batch owner calls waitUntil; its
|
|
1044
|
-
* shared bridge is already always fulfilled, and registration failure cancels export for that
|
|
1045
|
-
* unowned batch.
|
|
1046
|
-
*/
|
|
1047
|
-
const registerCloudflareTelemetryAfterNativeSettlement = (waitUntil, delivery, reserve, diagnoseRegistrationFailure) => {
|
|
1048
|
-
const reservation = reserve(delivery);
|
|
1049
|
-
if (!reservation.owner) return delivery;
|
|
1050
|
-
try {
|
|
1051
|
-
waitUntil(reservation.background);
|
|
1052
|
-
} catch (cause) {
|
|
1053
|
-
reservation.cancel();
|
|
1054
|
-
try {
|
|
1055
|
-
diagnoseRegistrationFailure(cause);
|
|
1056
|
-
} catch {}
|
|
1057
|
-
}
|
|
1058
|
-
return delivery;
|
|
1059
|
-
};
|
|
1060
|
-
/** @internal Content-free diagnostic for a rejected Cloudflare waitUntil registration. */
|
|
1061
|
-
const logCloudflareWaitUntilRegistrationFailure = (_cause) => Effect.logError("Cloudflare telemetry waitUntil registration failed").pipe(Effect.annotateLogs({ "effect_agent.cloudflare.telemetry.failure_kind": "wait_until_registration" }));
|
|
1062
|
-
//#endregion
|
|
1063
783
|
//#region src/conversation-object.ts
|
|
1064
784
|
/** Port envelope tags whose owner-side execution durably mutates this Object's lane. */
|
|
1065
785
|
const MUTATING_PORT_TAGS = /* @__PURE__ */ new Set([
|
|
@@ -1299,91 +1019,66 @@ const gateEndpoint = Effect.gen(function* () {
|
|
|
1299
1019
|
yield* (yield* ConversationMaintenance).ensureAlarm;
|
|
1300
1020
|
});
|
|
1301
1021
|
/**
|
|
1302
|
-
*
|
|
1303
|
-
*
|
|
1022
|
+
* Adapter from effect-cf's native Durable Object services to Effect Agent's existing platform
|
|
1023
|
+
* ports. effect-cf owns the cached ManagedRuntime and supplies these values once per Object
|
|
1024
|
+
* incarnation; the durable runtime continues to depend only on the narrow services below.
|
|
1304
1025
|
*/
|
|
1305
|
-
const
|
|
1306
|
-
const
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
});
|
|
1318
|
-
|
|
1026
|
+
const effectCfPlatformLayer = (namespaceBinding) => {
|
|
1027
|
+
const context = Layer.effect(DurableObjectContext)(Effect.gen(function* () {
|
|
1028
|
+
const state = yield* DurableObjectState.DurableObjectState;
|
|
1029
|
+
const env = yield* WorkerEnvironment;
|
|
1030
|
+
return DurableObjectContext.of({
|
|
1031
|
+
ctx: state.raw,
|
|
1032
|
+
env
|
|
1033
|
+
});
|
|
1034
|
+
}));
|
|
1035
|
+
const namespace = Layer.effect(ConversationObjectNamespace)(Effect.gen(function* () {
|
|
1036
|
+
const binding = yield* conversationNamespaceFromEnv(yield* WorkerEnvironment, namespaceBinding);
|
|
1037
|
+
return ConversationObjectNamespace.of({ namespace: binding });
|
|
1038
|
+
}));
|
|
1039
|
+
return Layer.merge(context, namespace);
|
|
1040
|
+
};
|
|
1319
1041
|
/**
|
|
1320
1042
|
* Build the application's Conversation Object class (export it from the Worker entry).
|
|
1321
|
-
*
|
|
1322
|
-
*
|
|
1323
|
-
*
|
|
1324
|
-
*
|
|
1325
|
-
* The explicit return type is what makes declaration emit possible: the class body carries a
|
|
1326
|
-
* private runtime field, and TS4094 rejects inferring an exported anonymous class type around it.
|
|
1043
|
+
* effect-cf owns the cached ManagedRuntime, native RPC methods, event scopes, and post-handler
|
|
1044
|
+
* OTLP flush scheduling for RPC and alarm events. The optional outer Layer is built per native
|
|
1045
|
+
* event, so a host can install Tracer/Logger/Metric services and `OtlpExporter.Flusher` without
|
|
1046
|
+
* Effect Agent owning exporter lifecycle machinery.
|
|
1327
1047
|
*/
|
|
1328
|
-
const makeConversationObjectClass = (options,
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
}
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
return this.#runNative("resolve_approval", resolveApprovalEndpoint(encoded));
|
|
1363
|
-
}
|
|
1364
|
-
async resolveUnknownEncoded(encoded) {
|
|
1365
|
-
return this.#runNative("resolve_unknown", resolveUnknownEndpoint(encoded));
|
|
1366
|
-
}
|
|
1367
|
-
async explainEncoded(encoded) {
|
|
1368
|
-
return this.#runNative("explain", explainEndpoint(encoded));
|
|
1369
|
-
}
|
|
1370
|
-
async verifyEncoded(encoded) {
|
|
1371
|
-
return this.#runNative("verify", verifyEndpoint(encoded));
|
|
1372
|
-
}
|
|
1373
|
-
async retryEncoded(encoded) {
|
|
1374
|
-
return this.#runNative("retry", retryEndpoint(encoded));
|
|
1375
|
-
}
|
|
1376
|
-
async obligationsEncoded(encoded) {
|
|
1377
|
-
return this.#runNative("obligations", obligationsEndpoint(encoded));
|
|
1378
|
-
}
|
|
1379
|
-
async portCall(encoded) {
|
|
1380
|
-
return this.#runNative("port_call", portCallEndpoint(encoded));
|
|
1381
|
-
}
|
|
1382
|
-
async wake() {
|
|
1383
|
-
await this.#runNative("wake", wakeEndpoint);
|
|
1384
|
-
}
|
|
1385
|
-
async alarm() {
|
|
1386
|
-
await this.#runNative("alarm", alarmEndpoint);
|
|
1048
|
+
const makeConversationObjectClass = (options, observability) => {
|
|
1049
|
+
const application = CloudflareDurableRuntime.layer(options).pipe(Layer.provideMerge(effectCfPlatformLayer(options.namespaceBinding)));
|
|
1050
|
+
const runtime = Layer.effectContext(Effect.gen(function* () {
|
|
1051
|
+
const state = yield* DurableObjectState.DurableObjectState;
|
|
1052
|
+
const scope = yield* Effect.scope;
|
|
1053
|
+
return yield* state.blockConcurrencyWhile(Effect.gen(function* () {
|
|
1054
|
+
const services = yield* Layer.buildWithScope(application, scope);
|
|
1055
|
+
yield* gateEndpoint.pipe(Effect.provide(services));
|
|
1056
|
+
return services;
|
|
1057
|
+
}));
|
|
1058
|
+
}));
|
|
1059
|
+
const rpc = {
|
|
1060
|
+
submitEncoded: (encoded) => submitEndpoint(encoded),
|
|
1061
|
+
awaitSettlementEncoded: (encoded) => awaitSettlementEndpoint(encoded),
|
|
1062
|
+
observePage: (encoded) => observePageEndpoint(encoded),
|
|
1063
|
+
abortEncoded: (encoded) => abortEndpoint(encoded),
|
|
1064
|
+
resolveApprovalEncoded: (encoded) => resolveApprovalEndpoint(encoded),
|
|
1065
|
+
resolveUnknownEncoded: (encoded) => resolveUnknownEndpoint(encoded),
|
|
1066
|
+
explainEncoded: (encoded) => explainEndpoint(encoded),
|
|
1067
|
+
verifyEncoded: (encoded) => verifyEndpoint(encoded),
|
|
1068
|
+
retryEncoded: (encoded) => retryEndpoint(encoded),
|
|
1069
|
+
obligationsEncoded: (encoded) => obligationsEndpoint(encoded),
|
|
1070
|
+
portCall: (encoded) => portCallEndpoint(encoded),
|
|
1071
|
+
wake: () => wakeEndpoint
|
|
1072
|
+
};
|
|
1073
|
+
const EffectCfConversationObject = DurableObject.make(runtime, {
|
|
1074
|
+
...observability === void 0 ? {} : { eventLayer: observability },
|
|
1075
|
+
initialize: Effect.void,
|
|
1076
|
+
rpc,
|
|
1077
|
+
alarm: () => alarmEndpoint
|
|
1078
|
+
});
|
|
1079
|
+
class ConversationObject extends EffectCfConversationObject {
|
|
1080
|
+
alarm(alarmInfo) {
|
|
1081
|
+
return super.alarm?.(alarmInfo);
|
|
1387
1082
|
}
|
|
1388
1083
|
}
|
|
1389
1084
|
return ConversationObject;
|
|
@@ -1936,6 +1631,6 @@ const classifyWorkerFailure = (cause, maxWallTime) => {
|
|
|
1936
1631
|
/** Layer building the Dynamic Worker `CodeExecutor` from resolved bindings. */
|
|
1937
1632
|
const dynamicWorkerCodeExecutorLayer = (options) => Layer.succeed(CodeExecutor)(CodeExecutor.of({ execute: makeExecute(options) }));
|
|
1938
1633
|
//#endregion
|
|
1939
|
-
export { AbortRecorded, AdminExplainRequest, AdminFailed, AdminFailure, AdminResponse, AdminVerifyRequest, AdmissionLimitExceeded, ApprovalRecorded, CLOUDFLARE_DATABASE_CAP_BYTES, CLOUDFLARE_RUNTIME_DEFAULTS, CloudflareAdmissionLimitsValue, CloudflareBindingError, CloudflareConversationClient, CloudflareDurableRuntime, CloudflareDurableRuntimeConfig, CloudflareDurableRuntimeConfigValue, CloudflarePlatformConfigError,
|
|
1634
|
+
export { AbortRecorded, AdminExplainRequest, AdminFailed, AdminFailure, AdminResponse, AdminVerifyRequest, AdmissionLimitExceeded, ApprovalRecorded, CLOUDFLARE_DATABASE_CAP_BYTES, CLOUDFLARE_RUNTIME_DEFAULTS, CloudflareAdmissionLimitsValue, CloudflareBindingError, CloudflareConversationClient, CloudflareDurableRuntime, CloudflareDurableRuntimeConfig, CloudflareDurableRuntimeConfigValue, CloudflarePlatformConfigError, CodeModeHostEntrypoint, ConversationClientError, ConversationMaintenance, ConversationObjectIdentity, ConversationObjectNamespace, ConversationObjectPorts, DEFAULT_MAX_DATABASE_BYTES, DurableAlarmError, DurableAlarmService, DurableObjectContext, ExplainedRecovery, HostFailed, HostFailure, HostProtocolError, HostResponse, MaintenancePassReport, ObligationsScanned, ObservePageRequest, ObservedPage, RetryExecuted, SettlementReached, SubmitRequest, SubmitSucceeded, UnknownResolutionRecorded, VerifiedIntegrity, boundHostDiagnostic, cloudflareWakeSchedulerLayer, conversationNamespaceFromEnv, conversationNamespaceLayer, conversationPortTransportLayer, decodeAbortCommand, decodeAdminExplainRequest, decodeAdminResponse, decodeAdminVerifyRequest, decodeApprovalDecisionCommand, decodeHostResponse, decodeObligationThresholds, decodeObservePageRequest, decodeReceipt, decodeRetryCommand, decodeSubmitRequest, decodeUnknownResolutionCommand, dynamicWorkerCodeExecutorLayer, dynamicWorkerImplementation, encodeAbortCommand, encodeAdminResponse, encodeApprovalDecisionCommand, encodeHostResponse, encodeObservePageRequest, encodeReceipt, encodeSubmitRequest, encodeUnknownResolutionCommand, makeConversationObjectClass };
|
|
1940
1635
|
|
|
1941
1636
|
//# sourceMappingURL=index.mjs.map
|