effect-durable-agent-cloudflare 0.1.0-alpha.20 → 0.1.0-alpha.21

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.
@@ -1,4 +1,6 @@
1
1
  import { t as DurableObjectSessionStorage } from "./durable-object-storage-BZCOHz9p.js";
2
+ import { EDAPromptProjector } from "effect-durable-agent/services/prompt-projector";
3
+ import * as Layer from "effect/Layer";
2
4
  import * as Effect from "effect/Effect";
3
5
  import * as Schema from "effect/Schema";
4
6
  import { EDACommand, GrantRunCommand } from "effect-durable-agent/types/commands";
@@ -8,9 +10,7 @@ import { CommittedDurableEvent, EDAAppEvents } from "effect-durable-agent/servic
8
10
  import { CommittedCommandTerminalEvent, EDARuntime, EDARuntimeConfig } from "effect-durable-agent/services/runtime";
9
11
  import { EDASessionSnapshot } from "effect-durable-agent/services/session-query";
10
12
  import { RunGrantResult, RunRequestOutcome } from "effect-durable-agent/domain/run-scheduling";
11
- import * as Layer from "effect/Layer";
12
13
  import { CompactionExecutor, CompactionPolicy } from "effect-durable-agent/services/compaction";
13
- import { EDAPromptProjector } from "effect-durable-agent/services/prompt-projector";
14
14
  import { EDAReducer } from "effect-durable-agent/services/reducer-registry";
15
15
  import { SessionEventObserver } from "effect-durable-agent/services/session-event-observer";
16
16
  import { EDAWebSocketClientFrame, EDAWebSocketServerFrameEncoder, EDAWebSocketServerFrameInput } from "effect-durable-agent/websocket";
@@ -295,4 +295,4 @@ declare class EDASessionController<ProjectionState extends object = never> {
295
295
  }
296
296
  //#endregion
297
297
  export { EDASessionEventsInput as a, EDASessionSubmitInput as c, EDAWebSocketProjectionInitial as d, EDAWebSocketProjectionResult as f, makeEDADurableObjectRuntimeLayer as h, EDASessionControllerOptions as i, EDAWebSocketProjection as l, EDASessionDurableObjectStorage as m, EDASessionBlockOnCommandInput as n, EDASessionScopedInput as o, EDADurableObjectRuntimeLayerOptions as p, EDASessionController as r, EDASessionSubmitBatchInput as s, EDAPreparedEventWebSocket as t, EDAWebSocketProjectionId as u };
298
- //# sourceMappingURL=session-controller-DCvQY3nj.d.ts.map
298
+ //# sourceMappingURL=session-controller-DoeFP_Ej.d.ts.map
@@ -1,2 +1,2 @@
1
- import { a as EDASessionEventsInput, c as EDASessionSubmitInput, i as EDASessionControllerOptions, m as EDASessionDurableObjectStorage, n as EDASessionBlockOnCommandInput, o as EDASessionScopedInput, r as EDASessionController, s as EDASessionSubmitBatchInput, t as EDAPreparedEventWebSocket } from "./session-controller-DCvQY3nj.js";
1
+ import { a as EDASessionEventsInput, c as EDASessionSubmitInput, i as EDASessionControllerOptions, m as EDASessionDurableObjectStorage, n as EDASessionBlockOnCommandInput, o as EDASessionScopedInput, r as EDASessionController, s as EDASessionSubmitBatchInput, t as EDAPreparedEventWebSocket } from "./session-controller-DoeFP_Ej.js";
2
2
  export { EDAPreparedEventWebSocket, EDASessionBlockOnCommandInput, EDASessionController, EDASessionControllerOptions, type EDASessionDurableObjectStorage, EDASessionEventsInput, EDASessionScopedInput, EDASessionSubmitBatchInput, EDASessionSubmitInput };
@@ -1,2 +1,2 @@
1
- import { t as EDASessionController } from "./session-controller-zTTLb7tt.js";
1
+ import { t as EDASessionController } from "./session-controller-BGfz1DdS.js";
2
2
  export { EDASessionController };
@@ -0,0 +1,205 @@
1
+ import { getNativeCompaction } from "effect-durable-agent/services/prompt-projector";
2
+ import * as Prompt from "effect/ai/Prompt";
3
+ import * as HttpClient from "effect/http/HttpClient";
4
+ import * as Context from "effect/Context";
5
+ import * as Effect from "effect/Effect";
6
+ import "effect/http/HttpBody";
7
+ import * as HttpClientError from "effect/http/HttpClientError";
8
+ import * as HttpClientResponse from "effect/http/HttpClientResponse";
9
+ //#region src/providers/transport.ts
10
+ /** Override in effect for the current model call, if any. */
11
+ const EDAProviderRequestOverride = Context.Reference("effect-durable-agent-cloudflare/EDAProviderRequestOverride", { defaultValue: () => void 0 });
12
+ const NATIVE_COMPACTION_SENTINEL = "⁣eda-native-compaction:v1:";
13
+ /**
14
+ * Replace stored native compaction messages for `provider` with a transport sentinel the provider
15
+ * transport swaps for the native items. Other providers' native items stay as readable summaries.
16
+ */
17
+ const prepareNativeCompaction = (provider, prompt) => Prompt.fromMessages(prompt.content.map((message) => {
18
+ const native = getNativeCompaction(message);
19
+ if (native === void 0 || native.provider !== provider || message.role !== "user") return message;
20
+ return Prompt.makeMessage("user", {
21
+ content: [Prompt.textPart({ text: encodeSentinel(native.items) })],
22
+ options: message.options
23
+ });
24
+ }));
25
+ const encodeSentinel = (items) => `${NATIVE_COMPACTION_SENTINEL}${bytesToBase64(new TextEncoder().encode(JSON.stringify(items)))}`;
26
+ const decodeSentinel = (text) => {
27
+ if (!text.startsWith(NATIVE_COMPACTION_SENTINEL)) return void 0;
28
+ const parsed = JSON.parse(new TextDecoder().decode(base64ToBytes(text.slice(26))));
29
+ return Array.isArray(parsed) ? parsed : void 0;
30
+ };
31
+ const bytesToBase64 = (bytes) => {
32
+ let binary = "";
33
+ for (const byte of bytes) binary += String.fromCharCode(byte);
34
+ return btoa(binary);
35
+ };
36
+ const base64ToBytes = (value) => Uint8Array.from(atob(value), (char) => char.charCodeAt(0));
37
+ /** Anthropic beta that lets requests carry on-demand compaction blocks. */
38
+ const ANTHROPIC_COMPACTION_BETA = "compact-2026-09-04";
39
+ /** Rewrite provider request bodies that carry native compaction sentinels. */
40
+ const rehydrateNativeCompaction = (provider, request) => {
41
+ if (!isRecord(request.body)) return request;
42
+ if (provider === "anthropic") {
43
+ const messages = request.body.messages;
44
+ if (!Array.isArray(messages)) return request;
45
+ let found = false;
46
+ const rewritten = messages.map((message) => {
47
+ if (!isRecord(message) || !Array.isArray(message.content)) return message;
48
+ const content = message.content.flatMap((block) => {
49
+ if (!isRecord(block) || block.type !== "text" || typeof block.text !== "string") return [block];
50
+ const items = decodeSentinel(block.text);
51
+ if (items === void 0) return [block];
52
+ found = true;
53
+ return block.cache_control === void 0 ? items : items.map((item, index) => index === items.length - 1 && isRecord(item) ? {
54
+ ...item,
55
+ cache_control: block.cache_control
56
+ } : item);
57
+ });
58
+ const role = content.length > 0 && content.every((block) => isRecord(block) && block.type === "compaction") ? "assistant" : message.role;
59
+ return {
60
+ ...message,
61
+ role,
62
+ content
63
+ };
64
+ });
65
+ if (!found) return request;
66
+ return {
67
+ ...request,
68
+ headers: withBeta(request.headers, ANTHROPIC_COMPACTION_BETA),
69
+ body: {
70
+ ...request.body,
71
+ messages: rewritten
72
+ }
73
+ };
74
+ }
75
+ const input = request.body.input;
76
+ if (!Array.isArray(input)) return request;
77
+ let found = false;
78
+ const rewritten = input.flatMap((item) => {
79
+ const items = sentinelItems(item);
80
+ if (items === void 0) return [item];
81
+ found = true;
82
+ return items;
83
+ });
84
+ return found ? {
85
+ ...request,
86
+ body: {
87
+ ...request.body,
88
+ input: rewritten
89
+ }
90
+ } : request;
91
+ };
92
+ const sentinelItems = (item) => {
93
+ if (!isRecord(item) || item.role !== "user") return void 0;
94
+ const content = item.content;
95
+ if (typeof content === "string") return decodeSentinel(content);
96
+ if (!Array.isArray(content) || content.length !== 1) return void 0;
97
+ const [part] = content;
98
+ return isRecord(part) && typeof part.text === "string" ? decodeSentinel(part.text) : void 0;
99
+ };
100
+ /** Add a beta flag to an `anthropic-beta` header without duplicating existing flags. */
101
+ const withBeta = (headers, beta) => {
102
+ const key = Object.keys(headers).find((name) => name.toLowerCase() === "anthropic-beta");
103
+ const existing = key === void 0 ? [] : (headers[key] ?? "").split(",").map((value) => value.trim());
104
+ const flags = [.../* @__PURE__ */ new Set([...existing.filter((value) => value.length > 0), beta])];
105
+ return {
106
+ ...Object.fromEntries(Object.entries(headers).filter(([name]) => name.toLowerCase() !== "anthropic-beta")),
107
+ "anthropic-beta": flags.join(",")
108
+ };
109
+ };
110
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
111
+ /**
112
+ * HttpClient for provider SDK clients. It replays native compaction items, applies the current
113
+ * request override, and sends through the Cloudflare AI Gateway binding or `fetch`.
114
+ */
115
+ const makeEDAProviderHttpClient = (options) => HttpClient.make((request, url, signal) => Effect.gen(function* () {
116
+ const override = yield* EDAProviderRequestOverride;
117
+ const prepared = yield* Effect.try({
118
+ try: () => {
119
+ const headers = options.provider === "anthropic" ? (options.anthropicBetas ?? []).reduce(withBeta, stringHeaders(request)) : stringHeaders(request);
120
+ const base = rehydrateNativeCompaction(options.provider, {
121
+ url,
122
+ headers,
123
+ body: requestBody(request.body)
124
+ });
125
+ return override === void 0 ? base : override.rewrite(base);
126
+ },
127
+ catch: (cause) => transportError(request, cause, "EDA provider request preparation failed")
128
+ });
129
+ const response = yield* Effect.tryPromise({
130
+ try: () => send(options, request, prepared, signal),
131
+ catch: (cause) => transportError(request, cause, options.aiGateway === void 0 ? "Provider request failed" : "Cloudflare AI Gateway request failed")
132
+ });
133
+ if (override === void 0) return HttpClientResponse.fromWeb(request, response);
134
+ const text = yield* Effect.tryPromise({
135
+ try: () => response.text(),
136
+ catch: (cause) => transportError(request, cause, "Provider response read failed")
137
+ });
138
+ override.onResponse(response.status, parseJson(text));
139
+ return HttpClientResponse.fromWeb(request, new Response(text, {
140
+ status: response.status,
141
+ headers: response.headers
142
+ }));
143
+ }));
144
+ /**
145
+ * Connection failures before any response are retried like the provider SDKs do (two retries with
146
+ * backoff); a request that reached the provider and failed is returned as its HTTP response.
147
+ */
148
+ const send = async (options, request, prepared, signal) => {
149
+ for (let attempt = 1;; attempt++) try {
150
+ return await sendOnce(options, request, prepared, signal);
151
+ } catch (error) {
152
+ if (attempt >= 3 || signal.aborted) throw error;
153
+ await new Promise((resolve) => setTimeout(resolve, 500 * 2 ** (attempt - 1)));
154
+ }
155
+ };
156
+ const sendOnce = async (options, request, prepared, signal) => {
157
+ const body = prepared.body === void 0 ? void 0 : JSON.stringify(prepared.body);
158
+ if (options.aiGateway === void 0) return fetch(prepared.url, {
159
+ method: request.method,
160
+ headers: prepared.headers,
161
+ ...body === void 0 ? {} : { body },
162
+ signal
163
+ });
164
+ return options.aiGateway.run({
165
+ endpoint: gatewayEndpoint(options.provider, prepared.url),
166
+ headers: prepared.headers,
167
+ provider: options.provider,
168
+ query: prepared.body
169
+ }, { signal });
170
+ };
171
+ /** AI Gateway endpoint for a provider URL: OpenAI paths drop `/v1/`, Anthropic keeps it. */
172
+ const gatewayEndpoint = (provider, url) => {
173
+ return `${provider === "openai" && url.pathname.startsWith("/v1/") ? url.pathname.slice(4) : url.pathname.replace(/^\/+/, "")}${url.search}`;
174
+ };
175
+ /** Headers that describe the original body; the transport may rewrite it, so fetch recomputes them. */
176
+ const BODY_FRAMING_HEADERS = /* @__PURE__ */ new Set([
177
+ "host",
178
+ "content-length",
179
+ "transfer-encoding"
180
+ ]);
181
+ const stringHeaders = (request) => Object.fromEntries(Object.entries(request.headers).filter((entry) => typeof entry[1] === "string" && !BODY_FRAMING_HEADERS.has(entry[0].toLowerCase())));
182
+ const requestBody = (body) => {
183
+ switch (body._tag) {
184
+ case "Empty": return;
185
+ case "Raw": return typeof body.body === "string" ? parseJson(body.body) : body.body;
186
+ case "Uint8Array": return parseJson(new TextDecoder().decode(body.body));
187
+ default: throw new Error(`Unsupported provider request body: ${body._tag}`);
188
+ }
189
+ };
190
+ const parseJson = (text) => {
191
+ try {
192
+ return JSON.parse(text);
193
+ } catch {
194
+ return text;
195
+ }
196
+ };
197
+ const transportError = (request, cause, description) => new HttpClientError.HttpClientError({ reason: new HttpClientError.TransportError({
198
+ request,
199
+ cause,
200
+ description
201
+ }) });
202
+ //#endregion
203
+ export { withBeta as a, prepareNativeCompaction as i, EDAProviderRequestOverride as n, makeEDAProviderHttpClient as r, ANTHROPIC_COMPACTION_BETA as t };
204
+
205
+ //# sourceMappingURL=transport-BzgK07l4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport-BzgK07l4.js","names":[],"sources":["../src/providers/transport.ts"],"sourcesContent":["import * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport * as HttpBody from \"effect/http/HttpBody\";\nimport * as HttpClient from \"effect/http/HttpClient\";\nimport * as HttpClientError from \"effect/http/HttpClientError\";\nimport type * as HttpClientRequest from \"effect/http/HttpClientRequest\";\nimport * as HttpClientResponse from \"effect/http/HttpClientResponse\";\nimport type * as Schema from \"effect/Schema\";\nimport * as Prompt from \"effect/ai/Prompt\";\nimport { getNativeCompaction } from \"effect-durable-agent/services/prompt-projector\";\n\n/** Providers whose HTTP traffic EDA's transport understands. */\nexport type EDAProvider = \"openai\" | \"anthropic\";\n\n/** Request about to leave EDA's transport, as decoded JSON. */\nexport interface EDAProviderRequest {\n readonly url: URL;\n readonly headers: Readonly<Record<string, string>>;\n readonly body: unknown;\n}\n\n/**\n * One-shot rewrite an executor installs around a single model call, for provider endpoints the\n * Effect AI adapters do not model (OpenAI `/responses/compact`, Anthropic on-demand compaction).\n * The adapter still builds the request from the EDA prompt; the override rewrites it and receives\n * the raw provider response. The adapter's own handling of that response is then ignored.\n */\nexport interface EDAProviderRequestOverride {\n readonly rewrite: (request: EDAProviderRequest) => EDAProviderRequest;\n readonly onResponse: (status: number, body: unknown) => void;\n}\n\n/** Override in effect for the current model call, if any. */\nexport const EDAProviderRequestOverride = Context.Reference<EDAProviderRequestOverride | undefined>(\n \"effect-durable-agent-cloudflare/EDAProviderRequestOverride\",\n { defaultValue: () => undefined },\n);\n\nconst NATIVE_COMPACTION_SENTINEL = \"⁣eda-native-compaction:v1:\";\n\n/**\n * Replace stored native compaction messages for `provider` with a transport sentinel the provider\n * transport swaps for the native items. Other providers' native items stay as readable summaries.\n */\nexport const prepareNativeCompaction = (\n provider: EDAProvider,\n prompt: Prompt.Prompt,\n): Prompt.Prompt =>\n Prompt.fromMessages(\n prompt.content.map((message) => {\n const native = getNativeCompaction(message);\n if (native === undefined || native.provider !== provider || message.role !== \"user\") {\n return message;\n }\n return Prompt.makeMessage(\"user\", {\n content: [Prompt.textPart({ text: encodeSentinel(native.items) })],\n options: message.options,\n });\n }),\n );\n\nconst encodeSentinel = (items: ReadonlyArray<Schema.Json>): string =>\n `${NATIVE_COMPACTION_SENTINEL}${bytesToBase64(new TextEncoder().encode(JSON.stringify(items)))}`;\n\nconst decodeSentinel = (text: string): ReadonlyArray<unknown> | undefined => {\n if (!text.startsWith(NATIVE_COMPACTION_SENTINEL)) return undefined;\n const parsed: unknown = JSON.parse(\n new TextDecoder().decode(base64ToBytes(text.slice(NATIVE_COMPACTION_SENTINEL.length))),\n );\n return Array.isArray(parsed) ? parsed : undefined;\n};\n\nconst bytesToBase64 = (bytes: Uint8Array): string => {\n let binary = \"\";\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary);\n};\n\nconst base64ToBytes = (value: string): Uint8Array =>\n Uint8Array.from(atob(value), (char) => char.charCodeAt(0));\n\n/** Anthropic beta that lets requests carry on-demand compaction blocks. */\nexport const ANTHROPIC_COMPACTION_BETA = \"compact-2026-09-04\";\n\n/** Rewrite provider request bodies that carry native compaction sentinels. */\nexport const rehydrateNativeCompaction = (\n provider: EDAProvider,\n request: EDAProviderRequest,\n): EDAProviderRequest => {\n if (!isRecord(request.body)) return request;\n if (provider === \"anthropic\") {\n const messages = request.body.messages;\n if (!Array.isArray(messages)) return request;\n let found = false;\n const rewritten = messages.map((message: unknown) => {\n if (!isRecord(message) || !Array.isArray(message.content)) return message;\n const content = message.content.flatMap((block: unknown) => {\n if (!isRecord(block) || block.type !== \"text\" || typeof block.text !== \"string\") {\n return [block];\n }\n const items = decodeSentinel(block.text);\n if (items === undefined) return [block];\n found = true;\n // A breakpoint on the summary moves onto the block (\"a breakpoint after the summary\").\n return block.cache_control === undefined\n ? items\n : items.map((item, index) =>\n index === items.length - 1 && isRecord(item)\n ? { ...item, cache_control: block.cache_control }\n : item,\n );\n });\n // The block stands as an assistant message of its own when nothing else shares the message.\n const role =\n content.length > 0 &&\n content.every((block) => isRecord(block) && block.type === \"compaction\")\n ? \"assistant\"\n : message.role;\n return { ...message, role, content };\n });\n if (!found) return request;\n return {\n ...request,\n headers: withBeta(request.headers, ANTHROPIC_COMPACTION_BETA),\n body: { ...request.body, messages: rewritten },\n };\n }\n const input = request.body.input;\n if (!Array.isArray(input)) return request;\n let found = false;\n const rewritten = input.flatMap((item: unknown) => {\n const items = sentinelItems(item);\n if (items === undefined) return [item];\n found = true;\n return items;\n });\n return found ? { ...request, body: { ...request.body, input: rewritten } } : request;\n};\n\nconst sentinelItems = (item: unknown): ReadonlyArray<unknown> | undefined => {\n if (!isRecord(item) || item.role !== \"user\") return undefined;\n const content = item.content;\n if (typeof content === \"string\") return decodeSentinel(content);\n if (!Array.isArray(content) || content.length !== 1) return undefined;\n const [part] = content;\n return isRecord(part) && typeof part.text === \"string\" ? decodeSentinel(part.text) : undefined;\n};\n\n/** Add a beta flag to an `anthropic-beta` header without duplicating existing flags. */\nexport const withBeta = (\n headers: Readonly<Record<string, string>>,\n beta: string,\n): Readonly<Record<string, string>> => {\n const key = Object.keys(headers).find((name) => name.toLowerCase() === \"anthropic-beta\");\n const existing =\n key === undefined ? [] : (headers[key] ?? \"\").split(\",\").map((value) => value.trim());\n const flags = [...new Set([...existing.filter((value) => value.length > 0), beta])];\n const rest = Object.fromEntries(\n Object.entries(headers).filter(([name]) => name.toLowerCase() !== \"anthropic-beta\"),\n );\n return { ...rest, \"anthropic-beta\": flags.join(\",\") };\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/** Transport options shared by EDA's provider clients. */\nexport interface EDAProviderTransportOptions {\n readonly provider: EDAProvider;\n /** Cloudflare AI Gateway binding; requests go direct over `fetch` when absent. */\n readonly aiGateway?: AiGateway | undefined;\n /** Anthropic beta flags added to every Anthropic request. */\n readonly anthropicBetas?: ReadonlyArray<string> | undefined;\n}\n\n/**\n * HttpClient for provider SDK clients. It replays native compaction items, applies the current\n * request override, and sends through the Cloudflare AI Gateway binding or `fetch`.\n */\nexport const makeEDAProviderHttpClient = (\n options: EDAProviderTransportOptions,\n): HttpClient.HttpClient =>\n HttpClient.make((request, url, signal) =>\n Effect.gen(function* () {\n const override = yield* EDAProviderRequestOverride;\n const prepared = yield* Effect.try({\n try: () => {\n const headers =\n options.provider === \"anthropic\"\n ? (options.anthropicBetas ?? []).reduce(withBeta, stringHeaders(request))\n : stringHeaders(request);\n const base = rehydrateNativeCompaction(options.provider, {\n url,\n headers,\n body: requestBody(request.body),\n });\n return override === undefined ? base : override.rewrite(base);\n },\n catch: (cause) => transportError(request, cause, \"EDA provider request preparation failed\"),\n });\n const response = yield* Effect.tryPromise({\n try: () => send(options, request, prepared, signal),\n catch: (cause) =>\n transportError(\n request,\n cause,\n options.aiGateway === undefined\n ? \"Provider request failed\"\n : \"Cloudflare AI Gateway request failed\",\n ),\n });\n if (override === undefined) {\n return HttpClientResponse.fromWeb(request, response);\n }\n // Overridden calls hand the raw body to the executor; the adapter then sees the same bytes.\n const text = yield* Effect.tryPromise({\n try: () => response.text(),\n catch: (cause) => transportError(request, cause, \"Provider response read failed\"),\n });\n override.onResponse(response.status, parseJson(text));\n return HttpClientResponse.fromWeb(\n request,\n new Response(text, { status: response.status, headers: response.headers }),\n );\n }),\n );\n\n/**\n * Connection failures before any response are retried like the provider SDKs do (two retries with\n * backoff); a request that reached the provider and failed is returned as its HTTP response.\n */\nconst send = async (\n options: EDAProviderTransportOptions,\n request: HttpClientRequest.HttpClientRequest,\n prepared: EDAProviderRequest,\n signal: AbortSignal,\n): Promise<Response> => {\n for (let attempt = 1; ; attempt++) {\n try {\n return await sendOnce(options, request, prepared, signal);\n } catch (error) {\n if (attempt >= 3 || signal.aborted) throw error;\n await new Promise((resolve) => setTimeout(resolve, 500 * 2 ** (attempt - 1)));\n }\n }\n};\n\nconst sendOnce = async (\n options: EDAProviderTransportOptions,\n request: HttpClientRequest.HttpClientRequest,\n prepared: EDAProviderRequest,\n signal: AbortSignal,\n): Promise<Response> => {\n const body = prepared.body === undefined ? undefined : JSON.stringify(prepared.body);\n if (options.aiGateway === undefined) {\n return fetch(prepared.url, {\n method: request.method,\n headers: prepared.headers,\n ...(body === undefined ? {} : { body }),\n signal,\n });\n }\n return options.aiGateway.run(\n {\n endpoint: gatewayEndpoint(options.provider, prepared.url),\n headers: prepared.headers,\n provider: options.provider,\n query: prepared.body,\n },\n { signal },\n );\n};\n\n/** AI Gateway endpoint for a provider URL: OpenAI paths drop `/v1/`, Anthropic keeps it. */\nexport const gatewayEndpoint = (provider: EDAProvider, url: URL): string => {\n const path =\n provider === \"openai\" && url.pathname.startsWith(\"/v1/\")\n ? url.pathname.slice(\"/v1/\".length)\n : url.pathname.replace(/^\\/+/, \"\");\n return `${path}${url.search}`;\n};\n\n/** Headers that describe the original body; the transport may rewrite it, so fetch recomputes them. */\nconst BODY_FRAMING_HEADERS = new Set([\"host\", \"content-length\", \"transfer-encoding\"]);\n\nconst stringHeaders = (request: HttpClientRequest.HttpClientRequest): Record<string, string> =>\n Object.fromEntries(\n Object.entries(request.headers).filter(\n (entry): entry is [string, string] =>\n typeof entry[1] === \"string\" && !BODY_FRAMING_HEADERS.has(entry[0].toLowerCase()),\n ),\n );\n\nconst requestBody = (body: HttpBody.HttpBody): unknown => {\n switch (body._tag) {\n case \"Empty\":\n return undefined;\n case \"Raw\":\n return typeof body.body === \"string\" ? parseJson(body.body) : body.body;\n case \"Uint8Array\":\n return parseJson(new TextDecoder().decode(body.body));\n default:\n throw new Error(`Unsupported provider request body: ${body._tag}`);\n }\n};\n\nconst parseJson = (text: string): unknown => {\n try {\n const parsed: unknown = JSON.parse(text);\n return parsed;\n } catch {\n return text;\n }\n};\n\nconst transportError = (\n request: HttpClientRequest.HttpClientRequest,\n cause: unknown,\n description: string,\n) =>\n new HttpClientError.HttpClientError({\n reason: new HttpClientError.TransportError({ request, cause, description }),\n });\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "effect-durable-agent-cloudflare",
3
- "version": "0.1.0-alpha.20",
3
+ "version": "0.1.0-alpha.21",
4
4
  "description": "Cloudflare Durable Objects host for effect-durable-agent.",
5
5
  "keywords": [
6
6
  "agents",
@@ -33,6 +33,10 @@
33
33
  "types": "./dist/index.d.ts",
34
34
  "import": "./dist/index.js"
35
35
  },
36
+ "./anthropic": {
37
+ "types": "./dist/anthropic.d.ts",
38
+ "import": "./dist/anthropic.js"
39
+ },
36
40
  "./durable-object": {
37
41
  "types": "./dist/durable-object.d.ts",
38
42
  "import": "./dist/durable-object.js"
@@ -41,6 +45,10 @@
41
45
  "types": "./dist/openai.d.ts",
42
46
  "import": "./dist/openai.js"
43
47
  },
48
+ "./providers": {
49
+ "types": "./dist/providers.d.ts",
50
+ "import": "./dist/providers.js"
51
+ },
44
52
  "./rpc": {
45
53
  "types": "./dist/rpc.d.ts",
46
54
  "import": "./dist/rpc.js"
@@ -61,21 +69,31 @@
61
69
  "tag": "alpha"
62
70
  },
63
71
  "dependencies": {
64
- "effect-durable-agent": "0.1.0-alpha.20"
72
+ "effect-durable-agent": "0.1.0-alpha.21"
65
73
  },
66
74
  "peerDependencies": {
75
+ "@effect/ai-anthropic": "4.0.3",
67
76
  "@effect/ai-openai": "4.0.3",
68
77
  "effect": "4.0.3"
69
78
  },
70
79
  "devDependencies": {
71
80
  "@cloudflare/vitest-pool-workers": "0.18.8",
72
81
  "@cloudflare/workers-types": "5.20260813.1",
82
+ "@effect/ai-anthropic": "4.0.3",
73
83
  "@effect/ai-openai": "4.0.3",
74
84
  "@effect/vitest": "4.0.3",
75
85
  "effect": "4.0.3",
76
86
  "vite-plus": "0.3.0",
77
87
  "vitest": "^4.1.8"
78
88
  },
89
+ "peerDependenciesMeta": {
90
+ "@effect/ai-anthropic": {
91
+ "optional": true
92
+ },
93
+ "@effect/ai-openai": {
94
+ "optional": true
95
+ }
96
+ },
79
97
  "scripts": {
80
98
  "build": "vp pack",
81
99
  "check": "pnpm run lint && pnpm run typecheck",