effect-durable-agent-cloudflare 0.1.0-alpha.4 → 0.1.0-alpha.7
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/README.md +24 -4
- package/dist/durable-object.d.ts +18 -7
- package/dist/durable-object.js +193 -2
- package/dist/durable-object.js.map +1 -0
- package/dist/index.d.ts +5 -11
- package/dist/index.js +6 -25
- package/dist/openai.d.ts +18 -0
- package/dist/openai.js +59 -0
- package/dist/openai.js.map +1 -0
- package/dist/rpc.d.ts +16 -0
- package/dist/rpc.js +26 -0
- package/dist/rpc.js.map +1 -0
- package/dist/{durable-object-runtime-Dehm7PsO.d.ts → session-controller-BCsOxE22.d.ts} +132 -106
- package/dist/{durable-object-runtime-LgOJbsVm.js → session-controller-CMbW7vgf.js} +600 -423
- package/dist/session-controller-CMbW7vgf.js.map +1 -0
- package/dist/session-controller.d.ts +2 -0
- package/dist/session-controller.js +2 -0
- package/package.json +20 -15
- package/dist/chunk-BBjsoOtd.js +0 -27
- package/dist/durable-object-CjWWNyek.js +0 -194
- package/dist/durable-object-CjWWNyek.js.map +0 -1
- package/dist/durable-object-runtime-LgOJbsVm.js.map +0 -1
- package/dist/durable-object-runtime.d.ts +0 -2
- package/dist/durable-object-runtime.js +0 -2
- package/dist/index.js.map +0 -1
- package/dist/websocket-protocol.d.ts +0 -1
- package/dist/websocket-protocol.js +0 -10
- package/dist/websocket-protocol.js.map +0 -1
- /package/dist/{durable-object-storage.d.ts → storage.d.ts} +0 -0
- /package/dist/{durable-object-storage.js → storage.js} +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# effect-durable-agent-cloudflare
|
|
2
2
|
|
|
3
|
-
Cloudflare Durable Objects host for [`effect-durable-agent`](
|
|
3
|
+
Cloudflare Durable Objects host for [`effect-durable-agent`](../effect-durable-agent/README.md).
|
|
4
|
+
|
|
5
|
+
Executable examples live in the repository's shared [`examples`](../../examples) directory.
|
|
4
6
|
|
|
5
7
|
```sh
|
|
6
8
|
pnpm add effect-durable-agent@alpha effect-durable-agent-cloudflare@alpha
|
|
@@ -16,9 +18,23 @@ export class AgentSession extends EDASessionDurableObject<Env> {
|
|
|
16
18
|
}
|
|
17
19
|
```
|
|
18
20
|
|
|
19
|
-
The
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
The adapter maps one session to one SQLite-backed Durable Object. Ownership is
|
|
22
|
+
split deliberately:
|
|
23
|
+
|
|
24
|
+
- `EDASessionDurableObject` maps Cloudflare callbacks and object identity.
|
|
25
|
+
- `EDASessionController` coordinates the session use cases.
|
|
26
|
+
- `EDASessionRuntime` owns the disposable Effect runtime and keep-alive.
|
|
27
|
+
- `EDAWebSocketConnectionManager` owns accepted sockets and hibernation state.
|
|
28
|
+
|
|
29
|
+
Idle sockets use `ctx.acceptWebSocket`, Effect Schema attachments, and
|
|
30
|
+
automatic ping responses. They own no timer or resident subscriber fiber.
|
|
31
|
+
Register only the concrete application subclass in `wrangler.jsonc`.
|
|
32
|
+
|
|
33
|
+
Apps with an existing client wire contract may register one
|
|
34
|
+
`EDAWebSocketProjection`. An authenticated Worker selects it on the internal
|
|
35
|
+
request with `EDA_WEB_SOCKET_PROJECTION_HEADER`; the Durable Object still owns
|
|
36
|
+
the accepted socket and persists the app projection state through hibernation.
|
|
37
|
+
Do not build a Worker-side WebSocket bridge for protocol translation.
|
|
22
38
|
|
|
23
39
|
Durable Object RPC uses structured clone. Encode Schema class instances before
|
|
24
40
|
passing commands or batches across the Worker-to-object boundary with
|
|
@@ -26,3 +42,7 @@ passing commands or batches across the Worker-to-object boundary with
|
|
|
26
42
|
|
|
27
43
|
The core and host packages are published in lockstep and must use the same
|
|
28
44
|
version.
|
|
45
|
+
|
|
46
|
+
Public subpaths are `/durable-object`, `/session-controller`, `/openai`,
|
|
47
|
+
`/rpc`, and `/storage`. The WebSocket protocol and pure delivery machine
|
|
48
|
+
are exported from `effect-durable-agent/websocket`.
|
package/dist/durable-object.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as EDASessionControllerOptions, l as EDAWebSocketProjection } from "./session-controller-BCsOxE22.js";
|
|
2
2
|
import { DurableObject } from "cloudflare:workers";
|
|
3
3
|
import { CommittedCommandTerminalEvent, EDARuntimeConfig } from "effect-durable-agent/services/runtime";
|
|
4
4
|
import { CommittedDurableEvent } from "effect-durable-agent/services/session-store";
|
|
@@ -6,6 +6,8 @@ import { DurableTranscriptMessage } from "effect-durable-agent/domain/message-tr
|
|
|
6
6
|
import { EDASessionSnapshot } from "effect-durable-agent/services/session-query";
|
|
7
7
|
|
|
8
8
|
//#region src/durable-object.d.ts
|
|
9
|
+
/** Internal Worker-to-object header selecting an app-owned WebSocket projection. */
|
|
10
|
+
declare const EDA_WEB_SOCKET_PROJECTION_HEADER = "x-eda-websocket-projection";
|
|
9
11
|
/** Raw RPC shape decoded before admitting one session command. */
|
|
10
12
|
interface EDASessionCommandRpcInput {
|
|
11
13
|
readonly command: unknown;
|
|
@@ -36,10 +38,20 @@ interface EDASessionBlockOnCommandRpcInput {
|
|
|
36
38
|
readonly sessionId: string;
|
|
37
39
|
readonly trace: unknown;
|
|
38
40
|
}
|
|
41
|
+
/** EDA RPC methods required by the session namespace helper. */
|
|
42
|
+
interface EDASessionRpcSurface {
|
|
43
|
+
readonly submit: (input: EDASessionCommandRpcInput) => Promise<CommittedDurableEvent>;
|
|
44
|
+
readonly submitBatch: (input: EDASessionSubmitBatchRpcInput) => Promise<ReadonlyArray<CommittedDurableEvent>>;
|
|
45
|
+
readonly submitAndBlock: (input: EDASessionCommandRpcInput) => Promise<CommittedCommandTerminalEvent>;
|
|
46
|
+
readonly blockOnCommand: (input: EDASessionBlockOnCommandRpcInput) => Promise<CommittedCommandTerminalEvent>;
|
|
47
|
+
readonly snapshot: (input: EDASessionScopedRpcInput) => Promise<EDASessionSnapshot>;
|
|
48
|
+
readonly messages: (input: EDASessionScopedRpcInput) => Promise<ReadonlyArray<DurableTranscriptMessage>>;
|
|
49
|
+
readonly destroySession: (input: EDASessionScopedRpcInput) => Promise<void>;
|
|
50
|
+
}
|
|
39
51
|
/** Constructor options for concrete app subclasses of the EDA Durable Object base. */
|
|
40
|
-
type EDASessionDurableObjectOptions = Omit<
|
|
52
|
+
type EDASessionDurableObjectOptions<ProjectionState extends object = never> = Omit<EDASessionControllerOptions<ProjectionState>, "background" | "getWebSockets" | "storage">;
|
|
41
53
|
/** Resolve a concrete EDA session Durable Object binding by domain session id. */
|
|
42
|
-
declare const getEDASessionDurableObjectByName: <T extends
|
|
54
|
+
declare const getEDASessionDurableObjectByName: <T extends Rpc.DurableObjectBranded & EDASessionRpcSurface>(namespace: DurableObjectNamespace<T>, sessionId: string) => DurableObjectStub<T>;
|
|
43
55
|
/**
|
|
44
56
|
* Base class for raw Cloudflare Durable Object hosts of one EDA session.
|
|
45
57
|
*
|
|
@@ -48,9 +60,9 @@ declare const getEDASessionDurableObjectByName: <T extends EDASessionDurableObje
|
|
|
48
60
|
* class is deliberately not exported from `workers/app.ts` and owns no binding
|
|
49
61
|
* name or routing convention.
|
|
50
62
|
*/
|
|
51
|
-
declare abstract class EDASessionDurableObject<EnvType extends object = object> extends DurableObject<EnvType> {
|
|
63
|
+
declare abstract class EDASessionDurableObject<EnvType extends object = object, ProjectionState extends object = never> extends DurableObject<EnvType> {
|
|
52
64
|
#private;
|
|
53
|
-
protected constructor(ctx: DurableObjectState, env: EnvType, options: EDASessionDurableObjectOptions);
|
|
65
|
+
protected constructor(ctx: DurableObjectState, env: EnvType, options: EDASessionDurableObjectOptions<ProjectionState>);
|
|
54
66
|
fetch(request: Request): Promise<Response>;
|
|
55
67
|
submit(input: EDASessionCommandRpcInput): Promise<CommittedDurableEvent>;
|
|
56
68
|
submitBatch(input: EDASessionSubmitBatchRpcInput): Promise<ReadonlyArray<CommittedDurableEvent>>;
|
|
@@ -65,7 +77,6 @@ declare abstract class EDASessionDurableObject<EnvType extends object = object>
|
|
|
65
77
|
alarm(): Promise<void>;
|
|
66
78
|
private parseSessionId;
|
|
67
79
|
private sessionIdFromObjectName;
|
|
68
|
-
private restoreAcceptedEventWebSockets;
|
|
69
80
|
}
|
|
70
81
|
/** Convenience config constructor for subclasses that need only provider/model ids. */
|
|
71
82
|
declare const edaRuntimeConfig: (input: {
|
|
@@ -79,5 +90,5 @@ declare const encodeEdaRpcCommittedDurableEvent: (event: CommittedDurableEvent)
|
|
|
79
90
|
/** Encode runtime snapshots into structured-clone-safe Durable Object RPC payloads. */
|
|
80
91
|
declare const encodeEdaRpcSessionSnapshot: (snapshot: EDASessionSnapshot) => EDASessionSnapshot;
|
|
81
92
|
//#endregion
|
|
82
|
-
export { EDASessionBlockOnCommandRpcInput, EDASessionCommandRpcInput, EDASessionDurableObject, EDASessionDurableObjectOptions, EDASessionEventsRpcInput, EDASessionScopedRpcInput, EDASessionSubmitBatchRpcInput, edaRuntimeConfig, encodeEdaRpcCommittedDurableEvent, encodeEdaRpcSessionSnapshot, getEDASessionDurableObjectByName };
|
|
93
|
+
export { EDASessionBlockOnCommandRpcInput, EDASessionCommandRpcInput, EDASessionDurableObject, EDASessionDurableObjectOptions, EDASessionEventsRpcInput, EDASessionRpcSurface, EDASessionScopedRpcInput, EDASessionSubmitBatchRpcInput, type EDAWebSocketProjection, EDA_WEB_SOCKET_PROJECTION_HEADER, edaRuntimeConfig, encodeEdaRpcCommittedDurableEvent, encodeEdaRpcSessionSnapshot, getEDASessionDurableObjectByName };
|
|
83
94
|
//# sourceMappingURL=durable-object.d.ts.map
|
package/dist/durable-object.js
CHANGED
|
@@ -1,2 +1,193 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { decodeEdaRpcCommand, decodeEdaRpcSubmittables, encodeEdaRpcDurableEvent } from "./rpc.js";
|
|
2
|
+
import { t as EDASessionController } from "./session-controller-CMbW7vgf.js";
|
|
3
|
+
import { DurableObject } from "cloudflare:workers";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import * as Schema from "effect/Schema";
|
|
6
|
+
import { EDACommand } from "effect-durable-agent/types/commands";
|
|
7
|
+
import { CommandId, SequenceNumber, SessionId } from "effect-durable-agent/types/core";
|
|
8
|
+
import { EDATraceMetadata, makeEDATraceMetadataFromParent, makeRootEDATraceMetadata, parseEDATraceparent } from "effect-durable-agent/types/tracing";
|
|
9
|
+
import { EDA_WEB_SOCKET_PING_MESSAGE, EDA_WEB_SOCKET_PONG_MESSAGE } from "effect-durable-agent/websocket";
|
|
10
|
+
//#region src/durable-object.ts
|
|
11
|
+
/** Internal Worker-to-object header selecting an app-owned WebSocket projection. */
|
|
12
|
+
const EDA_WEB_SOCKET_PROJECTION_HEADER = "x-eda-websocket-projection";
|
|
13
|
+
/** Resolve a concrete EDA session Durable Object binding by domain session id. */
|
|
14
|
+
const getEDASessionDurableObjectByName = (namespace, sessionId) => namespace.getByName(sessionId);
|
|
15
|
+
/**
|
|
16
|
+
* Base class for raw Cloudflare Durable Object hosts of one EDA session.
|
|
17
|
+
*
|
|
18
|
+
* Concrete products should extend this class, pass provider/tool layers from
|
|
19
|
+
* their own constructor, and register only that subclass in Wrangler. The base
|
|
20
|
+
* class is deliberately not exported from `workers/app.ts` and owns no binding
|
|
21
|
+
* name or routing convention.
|
|
22
|
+
*/
|
|
23
|
+
var EDASessionDurableObject = class extends DurableObject {
|
|
24
|
+
#controller;
|
|
25
|
+
#webSocketProjectionId;
|
|
26
|
+
constructor(ctx, env, options) {
|
|
27
|
+
super(ctx, env);
|
|
28
|
+
this.#webSocketProjectionId = options.webSocketProjection?.id;
|
|
29
|
+
const storage = toEDASessionStorage(this.ctx.storage);
|
|
30
|
+
this.#controller = new EDASessionController({
|
|
31
|
+
...options,
|
|
32
|
+
background: this.ctx,
|
|
33
|
+
getWebSockets: () => this.ctx.getWebSockets(),
|
|
34
|
+
storage
|
|
35
|
+
});
|
|
36
|
+
this.ctx.setWebSocketAutoResponse(new WebSocketRequestResponsePair(EDA_WEB_SOCKET_PING_MESSAGE, EDA_WEB_SOCKET_PONG_MESSAGE));
|
|
37
|
+
this.ctx.blockConcurrencyWhile(async () => {
|
|
38
|
+
await Effect.runPromise(EDASessionController.migrate(storage));
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
async fetch(request) {
|
|
42
|
+
if (request.headers.get("Upgrade")?.toLowerCase() !== "websocket") return new Response("Expected WebSocket upgrade.", { status: 426 });
|
|
43
|
+
const url = new URL(request.url);
|
|
44
|
+
const sessionIdRaw = url.searchParams.get("sessionId");
|
|
45
|
+
if (sessionIdRaw === null) return new Response("Missing sessionId.", { status: 400 });
|
|
46
|
+
const afterSeqRaw = url.searchParams.get("afterSeq");
|
|
47
|
+
const afterSeq = afterSeqRaw === null ? void 0 : Number(afterSeqRaw);
|
|
48
|
+
if (afterSeq !== void 0 && (!Number.isInteger(afterSeq) || afterSeq < 0)) return new Response("Invalid afterSeq.", { status: 400 });
|
|
49
|
+
const projectionId = request.headers.get("x-eda-websocket-projection") ?? void 0;
|
|
50
|
+
if (projectionId !== void 0 && projectionId !== this.#webSocketProjectionId) return new Response("Unsupported WebSocket projection.", { status: 400 });
|
|
51
|
+
const sessionId = this.parseSessionId(sessionIdRaw);
|
|
52
|
+
const trace = traceMetadataFromRequest(request);
|
|
53
|
+
const prepared = await this.#controller.prepareEventWebSocket({
|
|
54
|
+
...afterSeq === void 0 ? {} : { afterSeq: SequenceNumber.make(afterSeq) },
|
|
55
|
+
sessionId,
|
|
56
|
+
trace,
|
|
57
|
+
...projectionId === void 0 ? {} : { projectionId }
|
|
58
|
+
});
|
|
59
|
+
const pair = new WebSocketPair();
|
|
60
|
+
const client = pair[0];
|
|
61
|
+
const server = pair[1];
|
|
62
|
+
this.ctx.acceptWebSocket(server);
|
|
63
|
+
await this.#controller.acceptPreparedEventWebSocket({
|
|
64
|
+
...prepared,
|
|
65
|
+
webSocket: server
|
|
66
|
+
});
|
|
67
|
+
return new Response(null, {
|
|
68
|
+
status: 101,
|
|
69
|
+
webSocket: client
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
async submit(input) {
|
|
73
|
+
return encodeEdaRpcCommittedDurableEvent(await this.#controller.submit({
|
|
74
|
+
command: await decodeCommand(input.command),
|
|
75
|
+
sessionId: this.parseSessionId(input.sessionId),
|
|
76
|
+
trace: decodeTraceMetadata(input.trace)
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
async submitBatch(input) {
|
|
80
|
+
return (await this.#controller.submitBatch({
|
|
81
|
+
items: await decodeSubmittables(input.items),
|
|
82
|
+
sessionId: this.parseSessionId(input.sessionId),
|
|
83
|
+
trace: decodeTraceMetadata(input.trace)
|
|
84
|
+
})).map(encodeEdaRpcCommittedDurableEvent);
|
|
85
|
+
}
|
|
86
|
+
async submitAndBlock(input) {
|
|
87
|
+
return encodeEdaRpcCommittedDurableEvent(await this.#controller.submitAndBlock({
|
|
88
|
+
command: await decodeCommand(input.command),
|
|
89
|
+
sessionId: this.parseSessionId(input.sessionId),
|
|
90
|
+
trace: decodeTraceMetadata(input.trace)
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
async blockOnCommand(input) {
|
|
94
|
+
return encodeEdaRpcCommittedDurableEvent(await this.#controller.blockOnCommand({
|
|
95
|
+
...input.afterSeq === void 0 ? {} : { afterSeq: SequenceNumber.make(input.afterSeq) },
|
|
96
|
+
commandId: CommandId.make(input.commandId),
|
|
97
|
+
sessionId: this.parseSessionId(input.sessionId),
|
|
98
|
+
trace: decodeTraceMetadata(input.trace)
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
async snapshot(input) {
|
|
102
|
+
return encodeEdaRpcSessionSnapshot(await this.#controller.snapshot({
|
|
103
|
+
sessionId: this.parseSessionId(input.sessionId),
|
|
104
|
+
trace: decodeTraceMetadata(input.trace)
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
107
|
+
async messages(input) {
|
|
108
|
+
return await this.#controller.messages({
|
|
109
|
+
sessionId: this.parseSessionId(input.sessionId),
|
|
110
|
+
trace: decodeTraceMetadata(input.trace)
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
async webSocketMessage(webSocket, message) {
|
|
114
|
+
await this.#controller.webSocketMessage(webSocket, message);
|
|
115
|
+
}
|
|
116
|
+
async webSocketClose(webSocket, _code, _reason, _wasClean) {
|
|
117
|
+
this.#controller.webSocketClose(webSocket);
|
|
118
|
+
}
|
|
119
|
+
async webSocketError(webSocket, _error) {
|
|
120
|
+
this.#controller.webSocketError(webSocket);
|
|
121
|
+
}
|
|
122
|
+
async destroySession(input) {
|
|
123
|
+
await this.#controller.destroy({
|
|
124
|
+
sessionId: this.parseSessionId(input.sessionId),
|
|
125
|
+
trace: decodeTraceMetadata(input.trace)
|
|
126
|
+
});
|
|
127
|
+
await this.ctx.storage.deleteAlarm();
|
|
128
|
+
await this.ctx.storage.deleteAll();
|
|
129
|
+
}
|
|
130
|
+
async alarm() {
|
|
131
|
+
const sessionId = this.sessionIdFromObjectName();
|
|
132
|
+
await this.#controller.alarm(sessionId === void 0 ? void 0 : {
|
|
133
|
+
sessionId,
|
|
134
|
+
trace: makeRootEDATraceMetadata()
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
parseSessionId(input) {
|
|
138
|
+
const sessionId = SessionId.make(input);
|
|
139
|
+
const objectName = this.ctx.id.name;
|
|
140
|
+
if (objectName !== void 0 && objectName !== sessionId) throw new Error(`EDA Durable Object name ${objectName} cannot serve session ${sessionId}`);
|
|
141
|
+
return sessionId;
|
|
142
|
+
}
|
|
143
|
+
sessionIdFromObjectName() {
|
|
144
|
+
return this.ctx.id.name === void 0 ? void 0 : SessionId.make(this.ctx.id.name);
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
const toEDASessionStorage = (storage) => {
|
|
148
|
+
return storage;
|
|
149
|
+
};
|
|
150
|
+
const decodeTraceMetadata = (input) => Schema.decodeUnknownSync(EDATraceMetadata)(input);
|
|
151
|
+
const traceMetadataFromRequest = (request) => {
|
|
152
|
+
const parent = parseEDATraceparent(request.headers.get("traceparent"), request.headers.get("tracestate"));
|
|
153
|
+
return parent === null ? makeRootEDATraceMetadata() : makeEDATraceMetadataFromParent(parent);
|
|
154
|
+
};
|
|
155
|
+
/** Convenience config constructor for subclasses that need only provider/model ids. */
|
|
156
|
+
const edaRuntimeConfig = (input) => ({
|
|
157
|
+
modelSelection: {
|
|
158
|
+
modelId: input.modelId,
|
|
159
|
+
provider: input.provider
|
|
160
|
+
},
|
|
161
|
+
...input.maxToolCallsPerRun === void 0 ? {} : { maxToolCallsPerRun: input.maxToolCallsPerRun },
|
|
162
|
+
...input.systemPrompt === void 0 ? {} : { systemPrompt: input.systemPrompt }
|
|
163
|
+
});
|
|
164
|
+
/** Encode committed events into structured-clone-safe Durable Object RPC payloads. */
|
|
165
|
+
const encodeEdaRpcCommittedDurableEvent = (event) => ({
|
|
166
|
+
position: event.position,
|
|
167
|
+
event: encodeEdaRpcDurableEvent(event.event)
|
|
168
|
+
});
|
|
169
|
+
/** Encode runtime snapshots into structured-clone-safe Durable Object RPC payloads. */
|
|
170
|
+
const encodeEdaRpcSessionSnapshot = (snapshot) => ({
|
|
171
|
+
...snapshot,
|
|
172
|
+
reducerStates: new Map(snapshot.reducerStates),
|
|
173
|
+
state: {
|
|
174
|
+
...snapshot.state,
|
|
175
|
+
commands: new Map(Array.from(snapshot.state.commands, ([commandId, record]) => [commandId, encodeCommandCarrierForRpc(record)])),
|
|
176
|
+
commandQueues: {
|
|
177
|
+
...snapshot.state.commandQueues,
|
|
178
|
+
activeControlCommands: snapshot.state.commandQueues.activeControlCommands.map(encodeCommandCarrierForRpc),
|
|
179
|
+
pendingCommands: snapshot.state.commandQueues.pendingCommands.map(encodeCommandCarrierForRpc),
|
|
180
|
+
queuedCommands: snapshot.state.commandQueues.queuedCommands.map(encodeCommandCarrierForRpc)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
const encodeCommandCarrierForRpc = (value) => value.command === void 0 ? value : {
|
|
185
|
+
...value,
|
|
186
|
+
command: Schema.encodeSync(EDACommand)(value.command)
|
|
187
|
+
};
|
|
188
|
+
const decodeCommand = (input) => Effect.runPromise(decodeEdaRpcCommand(input));
|
|
189
|
+
const decodeSubmittables = (input) => Effect.runPromise(decodeEdaRpcSubmittables(input));
|
|
190
|
+
//#endregion
|
|
191
|
+
export { EDASessionDurableObject, EDA_WEB_SOCKET_PROJECTION_HEADER, edaRuntimeConfig, encodeEdaRpcCommittedDurableEvent, encodeEdaRpcSessionSnapshot, getEDASessionDurableObjectByName };
|
|
192
|
+
|
|
193
|
+
//# sourceMappingURL=durable-object.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable-object.js","names":["#controller","#webSocketProjectionId"],"sources":["../src/durable-object.ts"],"sourcesContent":["import { DurableObject } from \"cloudflare:workers\";\nimport * as Effect from \"effect/Effect\";\nimport * as Schema from \"effect/Schema\";\n\nimport type { DurableTranscriptMessage } from \"effect-durable-agent/domain/message-transcript\";\nimport {\n decodeEdaRpcCommand,\n decodeEdaRpcSubmittables,\n encodeEdaRpcDurableEvent,\n} from \"./rpc-codec\";\nimport type { EDASessionSnapshot } from \"effect-durable-agent/services/session-query\";\nimport type { CommittedDurableEvent as CommittedDurableEventValue } from \"effect-durable-agent/services/session-store\";\nimport type {\n CommittedCommandTerminalEvent,\n EDARuntimeConfig,\n} from \"effect-durable-agent/services/runtime\";\nimport {\n EDACommand,\n type EDACommand as EDACommandValue,\n} from \"effect-durable-agent/types/commands\";\nimport type { EDASubmittable } from \"effect-durable-agent/services/session-state\";\nimport { CommandId, SequenceNumber, SessionId } from \"effect-durable-agent/types/core\";\nimport {\n EDATraceMetadata,\n makeEDATraceMetadataFromParent,\n makeRootEDATraceMetadata,\n parseEDATraceparent,\n} from \"effect-durable-agent/types/tracing\";\nimport {\n EDASessionController,\n type EDASessionControllerOptions,\n type EDASessionDurableObjectStorage,\n} from \"./session-controller\";\nimport {\n EDA_WEB_SOCKET_PING_MESSAGE,\n EDA_WEB_SOCKET_PONG_MESSAGE,\n} from \"effect-durable-agent/websocket\";\nexport type { EDAWebSocketProjection } from \"./websocket/projection\";\n/** Internal Worker-to-object header selecting an app-owned WebSocket projection. */\nexport const EDA_WEB_SOCKET_PROJECTION_HEADER = \"x-eda-websocket-projection\";\n\n/** Raw RPC shape decoded before admitting one session command. */\nexport interface EDASessionCommandRpcInput {\n readonly command: unknown;\n readonly sessionId: string;\n readonly trace: unknown;\n}\n\n/** Raw RPC shape decoded before admitting a durable command/app-event batch. */\nexport interface EDASessionSubmitBatchRpcInput {\n readonly items: ReadonlyArray<unknown>;\n readonly sessionId: string;\n readonly trace: unknown;\n}\n\n/** Raw RPC shape for read/destroy operations that only need a session id. */\nexport interface EDASessionScopedRpcInput {\n readonly sessionId: string;\n readonly trace: unknown;\n}\n\n/** Raw RPC shape for WebSocket event-stream upgrades with a resume cursor. */\nexport interface EDASessionEventsRpcInput {\n readonly afterSeq?: number;\n readonly sessionId: string;\n readonly trace: unknown;\n}\n\n/** Raw RPC shape decoded before blocking on one command terminal event. */\nexport interface EDASessionBlockOnCommandRpcInput {\n readonly afterSeq?: number;\n readonly commandId: string;\n readonly sessionId: string;\n readonly trace: unknown;\n}\n\n/** EDA RPC methods required by the session namespace helper. */\nexport interface EDASessionRpcSurface {\n readonly submit: (input: EDASessionCommandRpcInput) => Promise<CommittedDurableEventValue>;\n readonly submitBatch: (\n input: EDASessionSubmitBatchRpcInput,\n ) => Promise<ReadonlyArray<CommittedDurableEventValue>>;\n readonly submitAndBlock: (\n input: EDASessionCommandRpcInput,\n ) => Promise<CommittedCommandTerminalEvent>;\n readonly blockOnCommand: (\n input: EDASessionBlockOnCommandRpcInput,\n ) => Promise<CommittedCommandTerminalEvent>;\n readonly snapshot: (input: EDASessionScopedRpcInput) => Promise<EDASessionSnapshot>;\n readonly messages: (\n input: EDASessionScopedRpcInput,\n ) => Promise<ReadonlyArray<DurableTranscriptMessage>>;\n readonly destroySession: (input: EDASessionScopedRpcInput) => Promise<void>;\n}\n\n/** Constructor options for concrete app subclasses of the EDA Durable Object base. */\nexport type EDASessionDurableObjectOptions<ProjectionState extends object = never> = Omit<\n EDASessionControllerOptions<ProjectionState>,\n \"background\" | \"getWebSockets\" | \"storage\"\n>;\n\n/** Resolve a concrete EDA session Durable Object binding by domain session id. */\nexport const getEDASessionDurableObjectByName = <\n T extends Rpc.DurableObjectBranded & EDASessionRpcSurface,\n>(\n namespace: DurableObjectNamespace<T>,\n sessionId: string,\n): DurableObjectStub<T> => namespace.getByName(sessionId);\n\n/**\n * Base class for raw Cloudflare Durable Object hosts of one EDA session.\n *\n * Concrete products should extend this class, pass provider/tool layers from\n * their own constructor, and register only that subclass in Wrangler. The base\n * class is deliberately not exported from `workers/app.ts` and owns no binding\n * name or routing convention.\n */\nexport abstract class EDASessionDurableObject<\n EnvType extends object = object,\n ProjectionState extends object = never,\n> extends DurableObject<EnvType> {\n readonly #controller: EDASessionController<ProjectionState>;\n readonly #webSocketProjectionId: string | undefined;\n\n protected constructor(\n ctx: DurableObjectState,\n env: EnvType,\n options: EDASessionDurableObjectOptions<ProjectionState>,\n ) {\n super(ctx, env);\n this.#webSocketProjectionId = options.webSocketProjection?.id;\n const storage = toEDASessionStorage(this.ctx.storage);\n this.#controller = new EDASessionController({\n ...options,\n background: this.ctx,\n getWebSockets: () => this.ctx.getWebSockets(),\n storage,\n });\n\n // Answer client liveness pings at the runtime layer so idle sockets never\n // wake a hibernated object.\n this.ctx.setWebSocketAutoResponse(\n new WebSocketRequestResponsePair(EDA_WEB_SOCKET_PING_MESSAGE, EDA_WEB_SOCKET_PONG_MESSAGE),\n );\n\n this.ctx.blockConcurrencyWhile(async () => {\n await Effect.runPromise(EDASessionController.migrate(storage));\n });\n }\n\n async fetch(request: Request): Promise<Response> {\n const upgrade = request.headers.get(\"Upgrade\");\n if (upgrade?.toLowerCase() !== \"websocket\") {\n return new Response(\"Expected WebSocket upgrade.\", { status: 426 });\n }\n\n const url = new URL(request.url);\n const sessionIdRaw = url.searchParams.get(\"sessionId\");\n if (sessionIdRaw === null) {\n return new Response(\"Missing sessionId.\", { status: 400 });\n }\n const afterSeqRaw = url.searchParams.get(\"afterSeq\");\n const afterSeq = afterSeqRaw === null ? undefined : Number(afterSeqRaw);\n if (afterSeq !== undefined && (!Number.isInteger(afterSeq) || afterSeq < 0)) {\n return new Response(\"Invalid afterSeq.\", { status: 400 });\n }\n const projectionId = request.headers.get(EDA_WEB_SOCKET_PROJECTION_HEADER) ?? undefined;\n if (projectionId !== undefined && projectionId !== this.#webSocketProjectionId) {\n return new Response(\"Unsupported WebSocket projection.\", { status: 400 });\n }\n\n const sessionId = this.parseSessionId(sessionIdRaw);\n const trace = traceMetadataFromRequest(request);\n const prepared = await this.#controller.prepareEventWebSocket({\n ...(afterSeq === undefined ? {} : { afterSeq: SequenceNumber.make(afterSeq) }),\n sessionId,\n trace,\n ...(projectionId === undefined ? {} : { projectionId }),\n });\n\n const pair = new WebSocketPair();\n const client = pair[0];\n const server = pair[1];\n this.ctx.acceptWebSocket(server);\n await this.#controller.acceptPreparedEventWebSocket({\n ...prepared,\n webSocket: server,\n });\n return new Response(null, { status: 101, webSocket: client });\n }\n\n async submit(input: EDASessionCommandRpcInput): Promise<CommittedDurableEventValue> {\n const committed = await this.#controller.submit({\n command: await decodeCommand(input.command),\n sessionId: this.parseSessionId(input.sessionId),\n trace: decodeTraceMetadata(input.trace),\n });\n return encodeEdaRpcCommittedDurableEvent(committed);\n }\n\n async submitBatch(\n input: EDASessionSubmitBatchRpcInput,\n ): Promise<ReadonlyArray<CommittedDurableEventValue>> {\n const committed = await this.#controller.submitBatch({\n items: await decodeSubmittables(input.items),\n sessionId: this.parseSessionId(input.sessionId),\n trace: decodeTraceMetadata(input.trace),\n });\n return committed.map(encodeEdaRpcCommittedDurableEvent);\n }\n\n async submitAndBlock(input: EDASessionCommandRpcInput): Promise<CommittedCommandTerminalEvent> {\n const committed = await this.#controller.submitAndBlock({\n command: await decodeCommand(input.command),\n sessionId: this.parseSessionId(input.sessionId),\n trace: decodeTraceMetadata(input.trace),\n });\n return encodeEdaRpcCommittedDurableEvent(committed) as CommittedCommandTerminalEvent;\n }\n\n async blockOnCommand(\n input: EDASessionBlockOnCommandRpcInput,\n ): Promise<CommittedCommandTerminalEvent> {\n const committed = await this.#controller.blockOnCommand({\n ...(input.afterSeq === undefined ? {} : { afterSeq: SequenceNumber.make(input.afterSeq) }),\n commandId: CommandId.make(input.commandId),\n sessionId: this.parseSessionId(input.sessionId),\n trace: decodeTraceMetadata(input.trace),\n });\n return encodeEdaRpcCommittedDurableEvent(committed) as CommittedCommandTerminalEvent;\n }\n\n async snapshot(input: EDASessionScopedRpcInput): Promise<EDASessionSnapshot> {\n const snapshot = await this.#controller.snapshot({\n sessionId: this.parseSessionId(input.sessionId),\n trace: decodeTraceMetadata(input.trace),\n });\n return encodeEdaRpcSessionSnapshot(snapshot);\n }\n\n async messages(\n input: EDASessionScopedRpcInput,\n ): Promise<ReadonlyArray<DurableTranscriptMessage>> {\n return await this.#controller.messages({\n sessionId: this.parseSessionId(input.sessionId),\n trace: decodeTraceMetadata(input.trace),\n });\n }\n\n async webSocketMessage(webSocket: WebSocket, message: string | ArrayBuffer): Promise<void> {\n await this.#controller.webSocketMessage(webSocket, message);\n }\n\n async webSocketClose(\n webSocket: WebSocket,\n _code: number,\n _reason: string,\n _wasClean: boolean,\n ): Promise<void> {\n this.#controller.webSocketClose(webSocket);\n }\n\n async webSocketError(webSocket: WebSocket, _error: unknown): Promise<void> {\n this.#controller.webSocketError(webSocket);\n }\n\n async destroySession(input: EDASessionScopedRpcInput): Promise<void> {\n await this.#controller.destroy({\n sessionId: this.parseSessionId(input.sessionId),\n trace: decodeTraceMetadata(input.trace),\n });\n await this.ctx.storage.deleteAlarm();\n await this.ctx.storage.deleteAll();\n }\n\n async alarm(): Promise<void> {\n const sessionId = this.sessionIdFromObjectName();\n await this.#controller.alarm(\n sessionId === undefined ? undefined : { sessionId, trace: makeRootEDATraceMetadata() },\n );\n }\n\n private parseSessionId(input: string): SessionId {\n const sessionId = SessionId.make(input);\n const objectName = this.ctx.id.name;\n if (objectName !== undefined && objectName !== sessionId) {\n throw new Error(`EDA Durable Object name ${objectName} cannot serve session ${sessionId}`);\n }\n return sessionId;\n }\n\n private sessionIdFromObjectName(): SessionId | undefined {\n return this.ctx.id.name === undefined ? undefined : SessionId.make(this.ctx.id.name);\n }\n}\n\nconst toEDASessionStorage = (storage: DurableObjectStorage): EDASessionDurableObjectStorage => {\n // SAFETY: the adapter interface is the exact SQL, transaction, and alarm subset\n // of DurableObjectStorage; its looser row generic also supports test implementations.\n return storage as EDASessionDurableObjectStorage;\n};\n\nconst decodeTraceMetadata = (input: unknown): EDATraceMetadata =>\n Schema.decodeUnknownSync(EDATraceMetadata)(input);\n\nconst traceMetadataFromRequest = (request: Request): EDATraceMetadata => {\n const parent = parseEDATraceparent(\n request.headers.get(\"traceparent\"),\n request.headers.get(\"tracestate\"),\n );\n return parent === null ? makeRootEDATraceMetadata() : makeEDATraceMetadataFromParent(parent);\n};\n\n/** Convenience config constructor for subclasses that need only provider/model ids. */\nexport const edaRuntimeConfig = (input: {\n readonly maxToolCallsPerRun?: number;\n readonly modelId: string;\n readonly provider: string;\n readonly systemPrompt?: string;\n}): EDARuntimeConfig => ({\n modelSelection: { modelId: input.modelId, provider: input.provider },\n ...(input.maxToolCallsPerRun === undefined\n ? {}\n : { maxToolCallsPerRun: input.maxToolCallsPerRun }),\n ...(input.systemPrompt === undefined ? {} : { systemPrompt: input.systemPrompt }),\n});\n\n/** Encode committed events into structured-clone-safe Durable Object RPC payloads. */\nexport const encodeEdaRpcCommittedDurableEvent = (\n event: CommittedDurableEventValue,\n): CommittedDurableEventValue => ({\n position: event.position,\n event: encodeEdaRpcDurableEvent(event.event),\n});\n\n/** Encode runtime snapshots into structured-clone-safe Durable Object RPC payloads. */\nexport const encodeEdaRpcSessionSnapshot = (snapshot: EDASessionSnapshot): EDASessionSnapshot => ({\n ...snapshot,\n reducerStates: new Map(snapshot.reducerStates),\n state: {\n ...snapshot.state,\n commands: new Map(\n Array.from(snapshot.state.commands, ([commandId, record]) => [\n commandId,\n encodeCommandCarrierForRpc(record),\n ]),\n ),\n commandQueues: {\n ...snapshot.state.commandQueues,\n activeControlCommands: snapshot.state.commandQueues.activeControlCommands.map(\n encodeCommandCarrierForRpc,\n ),\n pendingCommands: snapshot.state.commandQueues.pendingCommands.map(encodeCommandCarrierForRpc),\n queuedCommands: snapshot.state.commandQueues.queuedCommands.map(encodeCommandCarrierForRpc),\n },\n },\n});\n\nconst encodeCommandCarrierForRpc = <A extends { readonly command?: EDACommandValue }>(\n value: A,\n): A =>\n value.command === undefined\n ? value\n : {\n ...value,\n command: Schema.encodeSync(EDACommand)(value.command) as EDACommandValue,\n };\n\nconst decodeCommand = (input: unknown): Promise<EDACommandValue> =>\n Effect.runPromise(decodeEdaRpcCommand(input));\n\nconst decodeSubmittables = (\n input: ReadonlyArray<unknown>,\n): Promise<ReadonlyArray<EDASubmittable>> => Effect.runPromise(decodeEdaRpcSubmittables(input));\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
import { _ as encodeEdaRpcCommand, a as EDASessionDurableObjectHostOptions, b as makeEDADurableObjectRuntimeLayer, c as EDASessionScopedInput, d as EDAToolRegistryFactory, f as EDAToolkitFactory, g as decodeEdaRpcSubmittables, h as decodeEdaRpcSubmittable, i as EDASessionDurableObjectHost, l as EDASessionSubmitBatchInput, m as decodeEdaRpcCommand, n as EDAOpenAiModelConfig, o as EDASessionDurableObjectStorage, p as EDATracerFactory, r as EDASessionBlockOnCommandInput, s as EDASessionEventsInput, t as EDADurableObjectRuntimeLayerOptions, u as EDASessionSubmitInput, v as encodeEdaRpcSubmittables, y as makeEDADurableObjectOpenAiModelLayer } from "./durable-object-runtime-Dehm7PsO.js";
|
|
2
1
|
import { i as DurableObjectSqlStorage, n as DurableObjectSessionStoreOptions, r as DurableObjectSqlCursor, t as DurableObjectSessionStorage } from "./durable-object-storage-DCL2IyUe.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export { DurableObjectSessionStorage, DurableObjectSessionStoreOptions, DurableObjectSqlCursor, DurableObjectSqlStorage, EDADurableObjectRuntimeLayerOptions, EDAOpenAiModelConfig, EDASessionBlockOnCommandInput, EDASessionBlockOnCommandRpcInput, EDASessionCommandRpcInput, EDASessionDurableObject, EDASessionDurableObjectHost, EDASessionDurableObjectHostOptions, EDASessionDurableObjectOptions, EDASessionDurableObjectStorage, EDASessionEventsInput, EDASessionEventsRpcInput, EDASessionScopedInput, EDASessionScopedRpcInput, EDASessionSubmitBatchInput, EDASessionSubmitBatchRpcInput, EDASessionSubmitInput, EDAToolRegistryFactory, EDAToolkitFactory, EDATracerFactory, decodeEdaRpcCommand, decodeEdaRpcSubmittable, decodeEdaRpcSubmittables, edaRuntimeConfig, encodeEdaRpcCommand, encodeEdaRpcCommittedDurableEvent, encodeEdaRpcSessionSnapshot, encodeEdaRpcSubmittables, getEDASessionDurableObjectByName, makeEDADurableObjectOpenAiModelLayer, makeEDADurableObjectRuntimeLayer };
|
|
9
|
-
}
|
|
10
|
-
//#endregion
|
|
11
|
-
export { DurableObjectSessionStorage, DurableObjectSessionStoreOptions, DurableObjectSqlCursor, DurableObjectSqlStorage, EDADurableObjectRuntimeLayerOptions, EDAOpenAiModelConfig, EDASessionBlockOnCommandInput, EDASessionBlockOnCommandRpcInput, EDASessionCommandRpcInput, EDASessionDurableObject, EDASessionDurableObjectHost, EDASessionDurableObjectHostOptions, EDASessionDurableObjectOptions, EDASessionDurableObjectStorage, EDASessionEventsInput, EDASessionEventsRpcInput, EDASessionScopedInput, EDASessionScopedRpcInput, EDASessionSubmitBatchInput, EDASessionSubmitBatchRpcInput, EDASessionSubmitInput, EDAToolRegistryFactory, EDAToolkitFactory, EDATracerFactory, decodeEdaRpcCommand, decodeEdaRpcSubmittable, decodeEdaRpcSubmittables, edaRuntimeConfig, encodeEdaRpcCommand, encodeEdaRpcCommittedDurableEvent, encodeEdaRpcSessionSnapshot, encodeEdaRpcSubmittables, getEDASessionDurableObjectByName, makeEDADurableObjectOpenAiModelLayer, makeEDADurableObjectRuntimeLayer };
|
|
12
|
-
//# sourceMappingURL=index.d.ts.map
|
|
2
|
+
import { a as EDASessionEventsInput, c as EDASessionSubmitInput, d as EDAWebSocketProjectionInitial, f as EDAWebSocketProjectionResult, h as makeEDADurableObjectRuntimeLayer, i as EDASessionControllerOptions, l as EDAWebSocketProjection, m as EDASessionDurableObjectStorage, n as EDASessionBlockOnCommandInput, o as EDASessionScopedInput, p as EDADurableObjectRuntimeLayerOptions, r as EDASessionController, s as EDASessionSubmitBatchInput, t as EDAPreparedEventWebSocket, u as EDAWebSocketProjectionId } from "./session-controller-BCsOxE22.js";
|
|
3
|
+
import { EDASessionBlockOnCommandRpcInput, EDASessionCommandRpcInput, EDASessionDurableObject, EDASessionDurableObjectOptions, EDASessionEventsRpcInput, EDASessionRpcSurface, EDASessionScopedRpcInput, EDASessionSubmitBatchRpcInput, EDA_WEB_SOCKET_PROJECTION_HEADER, edaRuntimeConfig, encodeEdaRpcCommittedDurableEvent, encodeEdaRpcSessionSnapshot, getEDASessionDurableObjectByName } from "./durable-object.js";
|
|
4
|
+
import { EDAOpenAiModelConfig, makeEDADurableObjectOpenAiModelLayer } from "./openai.js";
|
|
5
|
+
import { decodeEdaRpcCommand, decodeEdaRpcSubmittables, encodeEdaRpcCommand, encodeEdaRpcDurableEvent, encodeEdaRpcSubmittables } from "./rpc.js";
|
|
6
|
+
export { DurableObjectSessionStorage, DurableObjectSessionStoreOptions, DurableObjectSqlCursor, DurableObjectSqlStorage, EDADurableObjectRuntimeLayerOptions, EDAOpenAiModelConfig, EDAPreparedEventWebSocket, EDASessionBlockOnCommandInput, EDASessionBlockOnCommandRpcInput, EDASessionCommandRpcInput, EDASessionController, EDASessionControllerOptions, EDASessionDurableObject, EDASessionDurableObjectOptions, EDASessionDurableObjectStorage, EDASessionEventsInput, EDASessionEventsRpcInput, EDASessionRpcSurface, EDASessionScopedInput, EDASessionScopedRpcInput, EDASessionSubmitBatchInput, EDASessionSubmitBatchRpcInput, EDASessionSubmitInput, EDAWebSocketProjection, EDAWebSocketProjectionId, EDAWebSocketProjectionInitial, EDAWebSocketProjectionResult, EDA_WEB_SOCKET_PROJECTION_HEADER, decodeEdaRpcCommand, decodeEdaRpcSubmittables, edaRuntimeConfig, encodeEdaRpcCommand, encodeEdaRpcCommittedDurableEvent, encodeEdaRpcDurableEvent, encodeEdaRpcSessionSnapshot, encodeEdaRpcSubmittables, getEDASessionDurableObjectByName, makeEDADurableObjectOpenAiModelLayer, makeEDADurableObjectRuntimeLayer };
|
package/dist/index.js
CHANGED
|
@@ -1,25 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import "./
|
|
6
|
-
export
|
|
7
|
-
__reExport(/* @__PURE__ */ __exportAll({
|
|
8
|
-
EDASessionDurableObject: () => EDASessionDurableObject,
|
|
9
|
-
EDASessionDurableObjectHost: () => EDASessionDurableObjectHost,
|
|
10
|
-
decodeEdaRpcCommand: () => decodeEdaRpcCommand,
|
|
11
|
-
decodeEdaRpcSubmittable: () => decodeEdaRpcSubmittable,
|
|
12
|
-
decodeEdaRpcSubmittables: () => decodeEdaRpcSubmittables,
|
|
13
|
-
edaRuntimeConfig: () => edaRuntimeConfig,
|
|
14
|
-
encodeEdaRpcCommand: () => encodeEdaRpcCommand,
|
|
15
|
-
encodeEdaRpcCommittedDurableEvent: () => encodeEdaRpcCommittedDurableEvent,
|
|
16
|
-
encodeEdaRpcSessionSnapshot: () => encodeEdaRpcSessionSnapshot,
|
|
17
|
-
encodeEdaRpcSubmittables: () => encodeEdaRpcSubmittables,
|
|
18
|
-
getEDASessionDurableObjectByName: () => getEDASessionDurableObjectByName,
|
|
19
|
-
makeEDADurableObjectOpenAiModelLayer: () => makeEDADurableObjectOpenAiModelLayer,
|
|
20
|
-
makeEDADurableObjectRuntimeLayer: () => makeEDADurableObjectRuntimeLayer
|
|
21
|
-
}), websocket_protocol_exports);
|
|
22
|
-
//#endregion
|
|
23
|
-
export { EDASessionDurableObject, EDASessionDurableObjectHost, decodeEdaRpcCommand, decodeEdaRpcSubmittable, decodeEdaRpcSubmittables, edaRuntimeConfig, encodeEdaRpcCommand, encodeEdaRpcCommittedDurableEvent, encodeEdaRpcSessionSnapshot, encodeEdaRpcSubmittables, getEDASessionDurableObjectByName, makeEDADurableObjectOpenAiModelLayer, makeEDADurableObjectRuntimeLayer };
|
|
24
|
-
|
|
25
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
import { decodeEdaRpcCommand, decodeEdaRpcSubmittables, encodeEdaRpcCommand, encodeEdaRpcDurableEvent, encodeEdaRpcSubmittables } from "./rpc.js";
|
|
2
|
+
import { n as EDAWebSocketProjectionId, r as makeEDADurableObjectRuntimeLayer, t as EDASessionController } from "./session-controller-CMbW7vgf.js";
|
|
3
|
+
import { EDASessionDurableObject, EDA_WEB_SOCKET_PROJECTION_HEADER, edaRuntimeConfig, encodeEdaRpcCommittedDurableEvent, encodeEdaRpcSessionSnapshot, getEDASessionDurableObjectByName } from "./durable-object.js";
|
|
4
|
+
import "./storage.js";
|
|
5
|
+
import { makeEDADurableObjectOpenAiModelLayer } from "./openai.js";
|
|
6
|
+
export { EDASessionController, EDASessionDurableObject, EDAWebSocketProjectionId, EDA_WEB_SOCKET_PROJECTION_HEADER, decodeEdaRpcCommand, decodeEdaRpcSubmittables, edaRuntimeConfig, encodeEdaRpcCommand, encodeEdaRpcCommittedDurableEvent, encodeEdaRpcDurableEvent, encodeEdaRpcSessionSnapshot, encodeEdaRpcSubmittables, getEDASessionDurableObjectByName, makeEDADurableObjectOpenAiModelLayer, makeEDADurableObjectRuntimeLayer };
|
package/dist/openai.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as Layer from "effect/Layer";
|
|
2
|
+
import { OpenAiLanguageModel } from "@effect/ai-openai";
|
|
3
|
+
import * as LanguageModel from "effect/unstable/ai/LanguageModel";
|
|
4
|
+
|
|
5
|
+
//#region src/providers/openai.d.ts
|
|
6
|
+
/** Provider request defaults accepted by EDA's OpenAI Responses model adapter. */
|
|
7
|
+
type EDAOpenAiModelConfig = Omit<typeof OpenAiLanguageModel.Config.Service, "model">;
|
|
8
|
+
/** OpenAI-backed Effect AI model layer for a Cloudflare Worker. */
|
|
9
|
+
declare const makeEDADurableObjectOpenAiModelLayer: (options: {
|
|
10
|
+
readonly aiGateway?: AiGateway;
|
|
11
|
+
readonly apiKey?: string;
|
|
12
|
+
readonly apiUrl?: string;
|
|
13
|
+
readonly config?: EDAOpenAiModelConfig;
|
|
14
|
+
readonly modelId: string;
|
|
15
|
+
}) => Layer.Layer<LanguageModel.LanguageModel>;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { EDAOpenAiModelConfig, makeEDADurableObjectOpenAiModelLayer };
|
|
18
|
+
//# sourceMappingURL=openai.d.ts.map
|
package/dist/openai.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Layer from "effect/Layer";
|
|
3
|
+
import { OpenAiClient, OpenAiLanguageModel } from "@effect/ai-openai";
|
|
4
|
+
import * as Redacted from "effect/Redacted";
|
|
5
|
+
import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient";
|
|
6
|
+
import "effect/unstable/http/HttpBody";
|
|
7
|
+
import * as HttpClient from "effect/unstable/http/HttpClient";
|
|
8
|
+
import * as HttpClientError from "effect/unstable/http/HttpClientError";
|
|
9
|
+
import * as HttpClientResponse from "effect/unstable/http/HttpClientResponse";
|
|
10
|
+
//#region src/providers/openai.ts
|
|
11
|
+
/** OpenAI-backed Effect AI model layer for a Cloudflare Worker. */
|
|
12
|
+
const makeEDADurableObjectOpenAiModelLayer = (options) => {
|
|
13
|
+
const apiKey = optionalNonEmptyString(options.apiKey);
|
|
14
|
+
if (apiKey === void 0 && options.aiGateway === void 0) throw new Error("OPENAI_API_KEY is required unless the EDA OpenAI model layer is backed by a Cloudflare AI Gateway binding.");
|
|
15
|
+
const httpClient = options.aiGateway === void 0 ? FetchHttpClient.layer : Layer.succeed(HttpClient.HttpClient, makeAiGatewayHttpClient(options.aiGateway));
|
|
16
|
+
const client = OpenAiClient.layer({
|
|
17
|
+
...apiKey === void 0 ? {} : { apiKey: Redacted.make(apiKey) },
|
|
18
|
+
...options.apiUrl === void 0 ? {} : { apiUrl: options.apiUrl }
|
|
19
|
+
}).pipe(Layer.provide(httpClient));
|
|
20
|
+
return OpenAiLanguageModel.layer({
|
|
21
|
+
model: options.modelId,
|
|
22
|
+
...options.config === void 0 ? {} : { config: options.config }
|
|
23
|
+
}).pipe(Layer.provide(client));
|
|
24
|
+
};
|
|
25
|
+
const makeAiGatewayHttpClient = (gateway) => HttpClient.make((request, url, signal) => Effect.tryPromise({
|
|
26
|
+
try: async () => {
|
|
27
|
+
const response = await gateway.run({
|
|
28
|
+
endpoint: endpointFromUrl(url),
|
|
29
|
+
headers: Object.fromEntries(Object.entries(request.headers).filter((entry) => typeof entry[1] === "string" && entry[0].toLowerCase() !== "host")),
|
|
30
|
+
provider: "openai",
|
|
31
|
+
query: requestBody(request.body)
|
|
32
|
+
}, { signal });
|
|
33
|
+
return HttpClientResponse.fromWeb(request, response);
|
|
34
|
+
},
|
|
35
|
+
catch: (cause) => new HttpClientError.HttpClientError({ reason: new HttpClientError.TransportError({
|
|
36
|
+
request,
|
|
37
|
+
cause,
|
|
38
|
+
description: "Cloudflare AI Gateway request failed"
|
|
39
|
+
}) })
|
|
40
|
+
}));
|
|
41
|
+
const endpointFromUrl = (url) => {
|
|
42
|
+
return `${url.pathname.startsWith("/v1/") ? url.pathname.slice(4) : url.pathname.replace(/^\/+/, "")}${url.search}`;
|
|
43
|
+
};
|
|
44
|
+
const requestBody = (body) => {
|
|
45
|
+
switch (body._tag) {
|
|
46
|
+
case "Empty": return;
|
|
47
|
+
case "Raw": return body.body;
|
|
48
|
+
case "Uint8Array": return JSON.parse(new TextDecoder().decode(body.body));
|
|
49
|
+
default: throw new Error(`Unsupported OpenAI request body for Cloudflare AI Gateway: ${body._tag}`);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const optionalNonEmptyString = (value) => {
|
|
53
|
+
const trimmed = value?.trim();
|
|
54
|
+
return trimmed === void 0 || trimmed.length === 0 ? void 0 : trimmed;
|
|
55
|
+
};
|
|
56
|
+
//#endregion
|
|
57
|
+
export { makeEDADurableObjectOpenAiModelLayer };
|
|
58
|
+
|
|
59
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.js","names":[],"sources":["../src/providers/openai.ts"],"sourcesContent":["import { OpenAiClient, OpenAiLanguageModel } from \"@effect/ai-openai\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Redacted from \"effect/Redacted\";\nimport type * as LanguageModel from \"effect/unstable/ai/LanguageModel\";\nimport * as FetchHttpClient from \"effect/unstable/http/FetchHttpClient\";\nimport * as HttpBody from \"effect/unstable/http/HttpBody\";\nimport * as HttpClient from \"effect/unstable/http/HttpClient\";\nimport * as HttpClientError from \"effect/unstable/http/HttpClientError\";\nimport * as HttpClientResponse from \"effect/unstable/http/HttpClientResponse\";\n\n/** Provider request defaults accepted by EDA's OpenAI Responses model adapter. */\nexport type EDAOpenAiModelConfig = Omit<typeof OpenAiLanguageModel.Config.Service, \"model\">;\n\n/** OpenAI-backed Effect AI model layer for a Cloudflare Worker. */\nexport const makeEDADurableObjectOpenAiModelLayer = (options: {\n readonly aiGateway?: AiGateway;\n readonly apiKey?: string;\n readonly apiUrl?: string;\n readonly config?: EDAOpenAiModelConfig;\n readonly modelId: string;\n}): Layer.Layer<LanguageModel.LanguageModel> => {\n const apiKey = optionalNonEmptyString(options.apiKey);\n if (apiKey === undefined && options.aiGateway === undefined) {\n throw new Error(\n \"OPENAI_API_KEY is required unless the EDA OpenAI model layer is backed by a Cloudflare AI Gateway binding.\",\n );\n }\n\n const httpClient =\n options.aiGateway === undefined\n ? FetchHttpClient.layer\n : Layer.succeed(HttpClient.HttpClient, makeAiGatewayHttpClient(options.aiGateway));\n const client = OpenAiClient.layer({\n ...(apiKey === undefined ? {} : { apiKey: Redacted.make(apiKey) }),\n ...(options.apiUrl === undefined ? {} : { apiUrl: options.apiUrl }),\n }).pipe(Layer.provide(httpClient));\n\n return OpenAiLanguageModel.layer({\n model: options.modelId,\n ...(options.config === undefined ? {} : { config: options.config }),\n }).pipe(Layer.provide(client));\n};\n\nconst makeAiGatewayHttpClient = (gateway: AiGateway): HttpClient.HttpClient =>\n HttpClient.make((request, url, signal) =>\n Effect.tryPromise({\n try: async () => {\n const response = await gateway.run(\n {\n endpoint: endpointFromUrl(url),\n headers: Object.fromEntries(\n Object.entries(request.headers).filter(\n (entry): entry is [string, string] =>\n typeof entry[1] === \"string\" && entry[0].toLowerCase() !== \"host\",\n ),\n ),\n provider: \"openai\",\n query: requestBody(request.body),\n },\n { signal },\n );\n return HttpClientResponse.fromWeb(request, response);\n },\n catch: (cause) =>\n new HttpClientError.HttpClientError({\n reason: new HttpClientError.TransportError({\n request,\n cause,\n description: \"Cloudflare AI Gateway request failed\",\n }),\n }),\n }),\n );\n\nconst endpointFromUrl = (url: URL): string => {\n const path = url.pathname.startsWith(\"/v1/\")\n ? url.pathname.slice(\"/v1/\".length)\n : url.pathname.replace(/^\\/+/, \"\");\n return `${path}${url.search}`;\n};\n\nconst requestBody = (body: HttpBody.HttpBody): unknown => {\n switch (body._tag) {\n case \"Empty\":\n return undefined;\n case \"Raw\":\n return body.body;\n case \"Uint8Array\":\n return JSON.parse(new TextDecoder().decode(body.body)) as unknown;\n default:\n throw new Error(`Unsupported OpenAI request body for Cloudflare AI Gateway: ${body._tag}`);\n }\n};\n\nconst optionalNonEmptyString = (value: string | undefined): string | undefined => {\n const trimmed = value?.trim();\n return trimmed === undefined || trimmed.length === 0 ? undefined : trimmed;\n};\n"],"mappings":";;;;;;;;;;;AAeA,MAAa,wCAAwC,YAML;CAC9C,MAAM,SAAS,uBAAuB,QAAQ,MAAM;CACpD,IAAI,WAAW,KAAA,KAAa,QAAQ,cAAc,KAAA,GAChD,MAAM,IAAI,MACR,4GACF;CAGF,MAAM,aACJ,QAAQ,cAAc,KAAA,IAClB,gBAAgB,QAChB,MAAM,QAAQ,WAAW,YAAY,wBAAwB,QAAQ,SAAS,CAAC;CACrF,MAAM,SAAS,aAAa,MAAM;EAChC,GAAI,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,SAAS,KAAK,MAAM,EAAE;EAChE,GAAI,QAAQ,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO;CACnE,CAAC,EAAE,KAAK,MAAM,QAAQ,UAAU,CAAC;CAEjC,OAAO,oBAAoB,MAAM;EAC/B,OAAO,QAAQ;EACf,GAAI,QAAQ,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO;CACnE,CAAC,EAAE,KAAK,MAAM,QAAQ,MAAM,CAAC;AAC/B;AAEA,MAAM,2BAA2B,YAC/B,WAAW,MAAM,SAAS,KAAK,WAC7B,OAAO,WAAW;CAChB,KAAK,YAAY;EACf,MAAM,WAAW,MAAM,QAAQ,IAC7B;GACE,UAAU,gBAAgB,GAAG;GAC7B,SAAS,OAAO,YACd,OAAO,QAAQ,QAAQ,OAAO,EAAE,QAC7B,UACC,OAAO,MAAM,OAAO,YAAY,MAAM,GAAG,YAAY,MAAM,MAC/D,CACF;GACA,UAAU;GACV,OAAO,YAAY,QAAQ,IAAI;EACjC,GACA,EAAE,OAAO,CACX;EACA,OAAO,mBAAmB,QAAQ,SAAS,QAAQ;CACrD;CACA,QAAQ,UACN,IAAI,gBAAgB,gBAAgB,EAClC,QAAQ,IAAI,gBAAgB,eAAe;EACzC;EACA;EACA,aAAa;CACf,CAAC,EACH,CAAC;AACL,CAAC,CACH;AAEF,MAAM,mBAAmB,QAAqB;CAI5C,OAAO,GAHM,IAAI,SAAS,WAAW,MAAM,IACvC,IAAI,SAAS,MAAM,CAAa,IAChC,IAAI,SAAS,QAAQ,QAAQ,EAAE,IAClB,IAAI;AACvB;AAEA,MAAM,eAAe,SAAqC;CACxD,QAAQ,KAAK,MAAb;EACE,KAAK,SACH;EACF,KAAK,OACH,OAAO,KAAK;EACd,KAAK,cACH,OAAO,KAAK,MAAM,IAAI,YAAY,EAAE,OAAO,KAAK,IAAI,CAAC;EACvD,SACE,MAAM,IAAI,MAAM,8DAA8D,KAAK,MAAM;CAC7F;AACF;AAEA,MAAM,0BAA0B,UAAkD;CAChF,MAAM,UAAU,OAAO,KAAK;CAC5B,OAAO,YAAY,KAAA,KAAa,QAAQ,WAAW,IAAI,KAAA,IAAY;AACrE"}
|
package/dist/rpc.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Schema from "effect/Schema";
|
|
3
|
+
import { EDACommand } from "effect-durable-agent/types/commands";
|
|
4
|
+
import { DurableEventEnvelope } from "effect-durable-agent/types/events";
|
|
5
|
+
import { EDASubmittable } from "effect-durable-agent/services/session-state";
|
|
6
|
+
|
|
7
|
+
//#region src/rpc-codec.d.ts
|
|
8
|
+
/** Encode one durable event into a structured-clone-safe Durable Object RPC value. */
|
|
9
|
+
declare const encodeEdaRpcDurableEvent: (event: DurableEventEnvelope) => DurableEventEnvelope;
|
|
10
|
+
declare const encodeEdaRpcCommand: (input: EDACommand) => unknown;
|
|
11
|
+
declare const encodeEdaRpcSubmittables: (input: ReadonlyArray<EDASubmittable>) => ReadonlyArray<unknown>;
|
|
12
|
+
declare const decodeEdaRpcCommand: (input: unknown) => Effect.Effect<EDACommand, Schema.SchemaError>;
|
|
13
|
+
declare const decodeEdaRpcSubmittables: (input: ReadonlyArray<unknown>) => Effect.Effect<ReadonlyArray<EDASubmittable>, Schema.SchemaError>;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { decodeEdaRpcCommand, decodeEdaRpcSubmittables, encodeEdaRpcCommand, encodeEdaRpcDurableEvent, encodeEdaRpcSubmittables };
|
|
16
|
+
//# sourceMappingURL=rpc.d.ts.map
|
package/dist/rpc.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Schema from "effect/Schema";
|
|
3
|
+
import * as Exit from "effect/Exit";
|
|
4
|
+
import { EDACommand } from "effect-durable-agent/types/commands";
|
|
5
|
+
import { DurableEventEnvelope, EDADurableEvent, effectDurableAgentNamespace } from "effect-durable-agent/types/events";
|
|
6
|
+
//#region src/rpc-codec.ts
|
|
7
|
+
/** Encode one durable event into a structured-clone-safe Durable Object RPC value. */
|
|
8
|
+
const encodeEdaRpcDurableEvent = (event) => {
|
|
9
|
+
const encoded = event.namespace === effectDurableAgentNamespace ? Schema.encodeSync(EDADurableEvent)(Schema.decodeUnknownSync(EDADurableEvent)(event)) : Schema.encodeSync(DurableEventEnvelope)(event);
|
|
10
|
+
return Schema.decodeUnknownSync(DurableEventEnvelope)(encoded);
|
|
11
|
+
};
|
|
12
|
+
const EDARpcSubmittable = Schema.Union([EDACommand, DurableEventEnvelope]);
|
|
13
|
+
const encodeEdaRpcCommand = (input) => Schema.encodeSync(EDACommand)(input);
|
|
14
|
+
const encodeEdaRpcSubmittables = (input) => input.map((item) => Schema.encodeSync(EDARpcSubmittable)(item));
|
|
15
|
+
const decodeEdaRpcCommand = (input) => Schema.decodeUnknownExit(EDACommand)(input).pipe(Exit.match({
|
|
16
|
+
onFailure: Effect.failCause,
|
|
17
|
+
onSuccess: Effect.succeed
|
|
18
|
+
}));
|
|
19
|
+
const decodeEdaRpcSubmittables = (input) => Effect.forEach(input, (item) => Schema.decodeUnknownExit(EDARpcSubmittable)(item).pipe(Exit.match({
|
|
20
|
+
onFailure: Effect.failCause,
|
|
21
|
+
onSuccess: Effect.succeed
|
|
22
|
+
})));
|
|
23
|
+
//#endregion
|
|
24
|
+
export { decodeEdaRpcCommand, decodeEdaRpcSubmittables, encodeEdaRpcCommand, encodeEdaRpcDurableEvent, encodeEdaRpcSubmittables };
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=rpc.js.map
|
package/dist/rpc.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc.js","names":[],"sources":["../src/rpc-codec.ts"],"sourcesContent":["import * as Effect from \"effect/Effect\";\nimport * as Exit from \"effect/Exit\";\nimport * as Schema from \"effect/Schema\";\n\nimport { EDACommand } from \"effect-durable-agent/types/commands\";\nimport type { EDASubmittable } from \"effect-durable-agent/services/session-state\";\nimport {\n DurableEventEnvelope,\n EDADurableEvent,\n effectDurableAgentNamespace,\n} from \"effect-durable-agent/types/events\";\n\n/** Encode one durable event into a structured-clone-safe Durable Object RPC value. */\nexport const encodeEdaRpcDurableEvent = (event: DurableEventEnvelope): DurableEventEnvelope => {\n const encoded =\n event.namespace === effectDurableAgentNamespace\n ? Schema.encodeSync(EDADurableEvent)(Schema.decodeUnknownSync(EDADurableEvent)(event))\n : Schema.encodeSync(DurableEventEnvelope)(event);\n return Schema.decodeUnknownSync(DurableEventEnvelope)(encoded);\n};\n\nconst EDARpcSubmittable = Schema.Union([EDACommand, DurableEventEnvelope]);\n\nexport const encodeEdaRpcCommand = (input: EDACommand): unknown =>\n Schema.encodeSync(EDACommand)(input);\n\nexport const encodeEdaRpcSubmittables = (\n input: ReadonlyArray<EDASubmittable>,\n): ReadonlyArray<unknown> => input.map((item) => Schema.encodeSync(EDARpcSubmittable)(item));\n\nexport const decodeEdaRpcCommand = (\n input: unknown,\n): Effect.Effect<EDACommand, Schema.SchemaError> =>\n Schema.decodeUnknownExit(EDACommand)(input).pipe(\n Exit.match({ onFailure: Effect.failCause, onSuccess: Effect.succeed }),\n );\n\nexport const decodeEdaRpcSubmittables = (\n input: ReadonlyArray<unknown>,\n): Effect.Effect<ReadonlyArray<EDASubmittable>, Schema.SchemaError> =>\n Effect.forEach(input, (item) =>\n Schema.decodeUnknownExit(EDARpcSubmittable)(item).pipe(\n Exit.match({ onFailure: Effect.failCause, onSuccess: Effect.succeed }),\n ),\n );\n"],"mappings":";;;;;;;AAaA,MAAa,4BAA4B,UAAsD;CAC7F,MAAM,UACJ,MAAM,cAAc,8BAChB,OAAO,WAAW,eAAe,EAAE,OAAO,kBAAkB,eAAe,EAAE,KAAK,CAAC,IACnF,OAAO,WAAW,oBAAoB,EAAE,KAAK;CACnD,OAAO,OAAO,kBAAkB,oBAAoB,EAAE,OAAO;AAC/D;AAEA,MAAM,oBAAoB,OAAO,MAAM,CAAC,YAAY,oBAAoB,CAAC;AAEzE,MAAa,uBAAuB,UAClC,OAAO,WAAW,UAAU,EAAE,KAAK;AAErC,MAAa,4BACX,UAC2B,MAAM,KAAK,SAAS,OAAO,WAAW,iBAAiB,EAAE,IAAI,CAAC;AAE3F,MAAa,uBACX,UAEA,OAAO,kBAAkB,UAAU,EAAE,KAAK,EAAE,KAC1C,KAAK,MAAM;CAAE,WAAW,OAAO;CAAW,WAAW,OAAO;AAAQ,CAAC,CACvE;AAEF,MAAa,4BACX,UAEA,OAAO,QAAQ,QAAQ,SACrB,OAAO,kBAAkB,iBAAiB,EAAE,IAAI,EAAE,KAChD,KAAK,MAAM;CAAE,WAAW,OAAO;CAAW,WAAW,OAAO;AAAQ,CAAC,CACvE,CACF"}
|