agents 0.23.0 → 0.25.0

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.
Files changed (187) hide show
  1. package/dist/{agent-routing-DE5zmCQ8.d.ts → agent-routing-0DR0Tk2v.d.ts} +270 -190
  2. package/dist/agent-routing.d.ts +1 -1
  3. package/dist/agent-routing.js.map +1 -1
  4. package/dist/agent-tool-types.d.ts +13 -7
  5. package/dist/agent-tool-types.js +23 -1
  6. package/dist/agent-tool-types.js.map +1 -1
  7. package/dist/{agent-tools-y7zLfw4Q.js → agent-tools-CdJC-8Dc.js} +72 -9
  8. package/dist/agent-tools-CdJC-8Dc.js.map +1 -0
  9. package/dist/{agent-tools-DtXMTDGM.d.ts → agent-tools-YrATZJu2.d.ts} +29 -15
  10. package/dist/agent-tools.d.ts +6 -4
  11. package/dist/agent-tools.js.map +1 -1
  12. package/dist/ai-fm7xx1BK.js +312 -0
  13. package/dist/ai-fm7xx1BK.js.map +1 -0
  14. package/dist/base64-redaction-C1Uu29t5.js +59 -0
  15. package/dist/base64-redaction-C1Uu29t5.js.map +1 -0
  16. package/dist/browser/ai-sdk.d.ts +90 -0
  17. package/dist/browser/ai-sdk.js +51 -0
  18. package/dist/browser/ai-sdk.js.map +1 -0
  19. package/dist/browser/ai.d.ts +4 -4
  20. package/dist/browser/ai.js +1 -347
  21. package/dist/browser/index.d.ts +81 -79
  22. package/dist/browser/index.js +361 -2
  23. package/dist/browser/index.js.map +1 -0
  24. package/dist/browser/tanstack-ai.d.ts +96 -1
  25. package/dist/browser/tanstack-ai.js +62 -2
  26. package/dist/browser/tanstack-ai.js.map +1 -1
  27. package/dist/browser-DE3d-RLk.d.ts +275 -0
  28. package/dist/browser-tool-CQ10e6Kj.js +480 -0
  29. package/dist/browser-tool-CQ10e6Kj.js.map +1 -0
  30. package/dist/browser-tool-DuNdlwZ9.d.ts +73 -0
  31. package/dist/{capability-BjSKYpzg.js → capability-B4WbF81e.js} +2 -1
  32. package/dist/capability-B4WbF81e.js.map +1 -0
  33. package/dist/{capability-runner-Be_-PLR1.d.ts → capability-runner-DBAnGr6L.d.ts} +45 -15
  34. package/dist/chat/index.d.ts +341 -232
  35. package/dist/chat/index.js +602 -72
  36. package/dist/chat/index.js.map +1 -1
  37. package/dist/chat/react.d.ts +42 -2
  38. package/dist/chat/react.js +191 -35
  39. package/dist/chat/react.js.map +1 -1
  40. package/dist/chat/transport.d.ts +1 -1
  41. package/dist/chat/transport.js +1 -1
  42. package/dist/chat-sdk/index.d.ts +17 -3
  43. package/dist/chat-sdk/index.js +28 -2
  44. package/dist/chat-sdk/index.js.map +1 -1
  45. package/dist/client-4OlMIJx-.js +591 -0
  46. package/dist/client-4OlMIJx-.js.map +1 -0
  47. package/dist/{client-jagG8a9_.js → client-fyQrLGkD.js} +2 -2
  48. package/dist/{client-jagG8a9_.js.map → client-fyQrLGkD.js.map} +1 -1
  49. package/dist/client-je3koD9Z.d.ts +446 -0
  50. package/dist/client.d.ts +29 -283
  51. package/dist/client.js +2 -274
  52. package/dist/{connector-CptFKzRh.js → connector-58XDGvc3.js} +251 -120
  53. package/dist/connector-58XDGvc3.js.map +1 -0
  54. package/dist/{connector-CkQD4MK3.d.ts → connector-Cl-VqPmA.d.ts} +244 -146
  55. package/dist/context/index.d.ts +29 -0
  56. package/dist/context/index.js +64 -17
  57. package/dist/context/index.js.map +1 -1
  58. package/dist/current-agent-DhoDkSnH.js.map +1 -1
  59. package/dist/current-agent-vAk_5JMt.d.ts +93 -0
  60. package/dist/{current-agent-Da_C9a3b.d.ts → durable-object-lifecycle-HhgOMWq9.d.ts} +26 -127
  61. package/dist/harnesses/pi/index.d.ts +348 -0
  62. package/dist/harnesses/pi/index.js +754 -0
  63. package/dist/harnesses/pi/index.js.map +1 -0
  64. package/dist/images-iiTDSyRu.js +1631 -0
  65. package/dist/images-iiTDSyRu.js.map +1 -0
  66. package/dist/index-BreL0YrQ.d.ts +78 -0
  67. package/dist/index-kbSUIer3.d.ts +343 -0
  68. package/dist/index.d.ts +43 -41
  69. package/dist/index.js +2 -2
  70. package/dist/internal_context.d.ts +1 -1
  71. package/dist/lifecycle/index.d.ts +19 -17
  72. package/dist/lifecycle/index.js +2 -2
  73. package/dist/{lifecycle-CMRGjZdw.js → lifecycle-CFu6OV03.js} +73 -29
  74. package/dist/lifecycle-CFu6OV03.js.map +1 -0
  75. package/dist/mcp/client/index.d.ts +20 -20
  76. package/dist/mcp/client/index.js +1 -1
  77. package/dist/mcp/client/x402.js +21 -19
  78. package/dist/mcp/client/x402.js.map +1 -1
  79. package/dist/mcp/index.d.ts +35 -35
  80. package/dist/mcp/index.js +2 -2
  81. package/dist/{message-builder-BymO4N_D.js → message-builder-DAl9AhHH.js} +89 -4
  82. package/dist/message-builder-DAl9AhHH.js.map +1 -0
  83. package/dist/models/ai-sdk/index.d.ts +353 -0
  84. package/dist/models/ai-sdk/index.js +2443 -0
  85. package/dist/models/ai-sdk/index.js.map +1 -0
  86. package/dist/models/pi-ai/index.d.ts +313 -0
  87. package/dist/models/pi-ai/index.js +1795 -0
  88. package/dist/models/pi-ai/index.js.map +1 -0
  89. package/dist/observability/ai/index.js +20 -4
  90. package/dist/observability/ai/index.js.map +1 -1
  91. package/dist/{protocol-B0nh6KNf.js → protocol-kHsr-f0X.js} +26 -12
  92. package/dist/{protocol-B0nh6KNf.js.map → protocol-kHsr-f0X.js.map} +1 -1
  93. package/dist/queue/index.d.ts +123 -0
  94. package/dist/queue/index.js +2 -0
  95. package/dist/queue-BB-zfIYF.js +406 -0
  96. package/dist/queue-BB-zfIYF.js.map +1 -0
  97. package/dist/react.d.ts +31 -13
  98. package/dist/react.js +190 -71
  99. package/dist/react.js.map +1 -1
  100. package/dist/{retries-D9Ds-1lz.d.ts → retries-CV6AkXmQ.d.ts} +23 -8
  101. package/dist/retries.d.ts +12 -8
  102. package/dist/retries.js +19 -1
  103. package/dist/retries.js.map +1 -1
  104. package/dist/routing/index.d.ts +2 -2
  105. package/dist/routing/index.js +1 -1
  106. package/dist/{scheduler-DD9NdYbF.js → scheduler-DZ3xQfeK.js} +4 -11
  107. package/dist/scheduler-DZ3xQfeK.js.map +1 -0
  108. package/dist/{scheduler-Dwh85ZGl.d.ts → scheduler-RdACNXDP.d.ts} +6 -6
  109. package/dist/schedules/index.d.ts +1 -1
  110. package/dist/schedules/index.js +1 -1
  111. package/dist/serializable.d.ts +1 -1
  112. package/dist/sessions/index.d.ts +70 -3
  113. package/dist/sessions/index.js +276 -67
  114. package/dist/sessions/index.js.map +1 -1
  115. package/dist/skills/index.d.ts +29 -314
  116. package/dist/socket-address.d.ts +16 -0
  117. package/dist/socket-address.js +19 -0
  118. package/dist/socket-address.js.map +1 -0
  119. package/dist/{src-DlSHshb2.js → src-BZeu-SCD.js} +541 -500
  120. package/dist/src-BZeu-SCD.js.map +1 -0
  121. package/dist/state/index.d.ts +6 -0
  122. package/dist/state/index.js +137 -0
  123. package/dist/state/index.js.map +1 -0
  124. package/dist/streams/index.d.ts +1 -1
  125. package/dist/streams/index.js +1 -1
  126. package/dist/{streams-D6tJ0NN9.d.ts → streams-Cmkj9QfW.d.ts} +4 -2
  127. package/dist/{streams-DZKgAj9b.js → streams-DW-UCOUc.js} +9 -2
  128. package/dist/streams-DW-UCOUc.js.map +1 -0
  129. package/dist/sub-routing.d.ts +12 -12
  130. package/dist/tasks/index.d.ts +1 -1
  131. package/dist/tasks/index.js +1 -1
  132. package/dist/{tasks-ylZgBjhj.js → tasks-68DESxf0.js} +3 -3
  133. package/dist/{tasks-ylZgBjhj.js.map → tasks-68DESxf0.js.map} +1 -1
  134. package/dist/{tasks-BRJ5zgya.d.ts → tasks-9YxYtByh.d.ts} +5 -5
  135. package/dist/transport-PfFnt-Ld.d.ts +525 -0
  136. package/dist/transport-protocol-BxyngQ_R.js +25 -0
  137. package/dist/transport-protocol-BxyngQ_R.js.map +1 -0
  138. package/dist/transport-protocol-ZTew5Wso.d.ts +27 -0
  139. package/dist/types-BA4anrjI.d.ts +70 -0
  140. package/dist/voice/index.d.ts +2 -2
  141. package/dist/websockets/index.d.ts +195 -69
  142. package/dist/websockets/index.js +3 -2
  143. package/dist/websockets-Ci-LZFHH.js +1030 -0
  144. package/dist/websockets-Ci-LZFHH.js.map +1 -0
  145. package/dist/wire-types-CnMt6_HR.js.map +1 -1
  146. package/dist/wire-types-CrjKvDyi.d.ts +300 -0
  147. package/dist/workflow-types.d.ts +25 -25
  148. package/dist/workflows.d.ts +21 -21
  149. package/dist/workflows.js +1 -1
  150. package/dist/{ws-chat-transport-UNRIS2xl.d.ts → ws-chat-transport-BbT1A5Lc.d.ts} +51 -2
  151. package/dist/{ws-chat-transport-rWwta645.js → ws-chat-transport-cqMKq3IY.js} +143 -16
  152. package/dist/ws-chat-transport-cqMKq3IY.js.map +1 -0
  153. package/docs/agent-class.md +2 -2
  154. package/docs/agent-tools.md +29 -4
  155. package/docs/browse-the-web.md +87 -5
  156. package/docs/chat-agents.md +124 -16
  157. package/docs/client-sdk.md +30 -0
  158. package/docs/context.md +27 -0
  159. package/docs/durable-execution.md +2 -0
  160. package/docs/harnesses/pi.md +91 -0
  161. package/docs/human-in-the-loop.md +4 -0
  162. package/docs/index.md +4 -1
  163. package/docs/lifecycle.md +114 -23
  164. package/docs/models-pi-ai.md +325 -0
  165. package/docs/models.md +504 -0
  166. package/docs/queue.md +135 -241
  167. package/docs/resumable-streaming.md +2 -0
  168. package/docs/retries.md +1 -1
  169. package/docs/routing.md +13 -13
  170. package/docs/sessions.md +36 -1
  171. package/docs/state.md +1 -0
  172. package/docs/sub-agents.md +12 -3
  173. package/package.json +51 -3
  174. package/dist/agent-tools-y7zLfw4Q.js.map +0 -1
  175. package/dist/browser/ai.js.map +0 -1
  176. package/dist/capability-BjSKYpzg.js.map +0 -1
  177. package/dist/client-tools-aIBO0Fk7.d.ts +0 -53
  178. package/dist/client.js.map +0 -1
  179. package/dist/connector-CptFKzRh.js.map +0 -1
  180. package/dist/lifecycle-CMRGjZdw.js.map +0 -1
  181. package/dist/message-builder-BymO4N_D.js.map +0 -1
  182. package/dist/scheduler-DD9NdYbF.js.map +0 -1
  183. package/dist/src-DlSHshb2.js.map +0 -1
  184. package/dist/streams-DZKgAj9b.js.map +0 -1
  185. package/dist/websockets-DUfRHPRq.js +0 -502
  186. package/dist/websockets-DUfRHPRq.js.map +0 -1
  187. package/dist/ws-chat-transport-rWwta645.js.map +0 -1
@@ -0,0 +1,1030 @@
1
+ import { camelCaseToKebabCase } from "./utils.js";
2
+ import "./types.js";
3
+ import { a as isCapnWebTransportUpgrade, n as CAPNWEB_TRANSPORT_SEND } from "./transport-protocol-BxyngQ_R.js";
4
+ import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "./classPrivateFieldGet2-DZBYAB34.js";
5
+ import { t as _classPrivateMethodInitSpec } from "./classPrivateMethodInitSpec-qMjJ6sHQ.js";
6
+ import { t as LifecycleCapability } from "./capability-B4WbF81e.js";
7
+ import "./lifecycle-CFu6OV03.js";
8
+ import { newWebSocketRpcSession } from "capnweb";
9
+ import { RpcTarget as RpcTarget$1 } from "cloudflare:workers";
10
+ import { nanoid } from "nanoid";
11
+ //#region src/websockets/connection-flags.ts
12
+ /**
13
+ * Internal per-connection flags, stored inside the connection's own state
14
+ * under `_cf_`-prefixed keys so they ride the hibernation attachment (or a
15
+ * bridged connection's synced state) and survive a wake. The state wrapper
16
+ * installed by {@link ensureConnectionWrapped} hides them from
17
+ * `connection.state` and preserves them across user `setState` calls.
18
+ *
19
+ * Owned by the WebSockets capability; `Agent` and framework mixins reach it
20
+ * through the capability or, for their own keys, through
21
+ * {@link registerInternalConnectionKeys}.
22
+ */
23
+ /** A readonly connection may not update host state. */
24
+ const CF_READONLY_KEY = "_cf_readonly";
25
+ /**
26
+ * A no-protocol connection receives no protocol text frames (identity,
27
+ * state sync, MCP servers) — neither on connect nor via broadcasts.
28
+ */
29
+ const CF_NO_PROTOCOL_KEY = "_cf_no_protocol";
30
+ const internalKeys = /* @__PURE__ */ new Set([CF_READONLY_KEY, CF_NO_PROTOCOL_KEY]);
31
+ /**
32
+ * Register additional `_cf_`-prefixed keys a host or mixin stores in
33
+ * connection state, so they are hidden from `connection.state` and kept
34
+ * across user `setState` calls like the capability's own flags.
35
+ */
36
+ function registerInternalConnectionKeys(...keys) {
37
+ for (const key of keys) internalKeys.add(key);
38
+ }
39
+ function rawHasInternalKeys(raw) {
40
+ for (const key of Object.keys(raw)) if (internalKeys.has(key)) return true;
41
+ return false;
42
+ }
43
+ /** A copy of `raw` without internal keys, or null when no user keys remain. */
44
+ function stripInternalKeys(raw) {
45
+ const result = {};
46
+ let hasUserKeys = false;
47
+ for (const key of Object.keys(raw)) if (!internalKeys.has(key)) {
48
+ result[key] = raw[key];
49
+ hasUserKeys = true;
50
+ }
51
+ return hasUserKeys ? result : null;
52
+ }
53
+ /** A copy containing only the internal keys present in `raw`. */
54
+ function extractInternalFlags(raw) {
55
+ const result = {};
56
+ for (const key of Object.keys(raw)) if (internalKeys.has(key)) result[key] = raw[key];
57
+ return result;
58
+ }
59
+ /**
60
+ * Per-connection raw accessors, keyed by the live connection object. The
61
+ * map is in-memory: after hibernation it is empty, and every entry point
62
+ * re-wraps the connection on first use.
63
+ */
64
+ const rawStateAccessors = /* @__PURE__ */ new WeakMap();
65
+ /**
66
+ * Wrap `connection.state` / `connection.setState` so internal flags are
67
+ * hidden from user code and preserved when user code sets state.
68
+ * Idempotent, and safe to call after hibernation.
69
+ */
70
+ function ensureConnectionWrapped(connection) {
71
+ if (rawStateAccessors.has(connection)) return;
72
+ const descriptor = Object.getOwnPropertyDescriptor(connection, "state");
73
+ let getRaw;
74
+ let setRaw;
75
+ if (descriptor?.get) {
76
+ getRaw = descriptor.get.bind(connection);
77
+ setRaw = connection.setState.bind(connection);
78
+ } else {
79
+ let rawState = connection.state ?? null;
80
+ getRaw = () => rawState;
81
+ setRaw = (state) => {
82
+ rawState = state;
83
+ return rawState;
84
+ };
85
+ }
86
+ rawStateAccessors.set(connection, {
87
+ getRaw,
88
+ setRaw
89
+ });
90
+ Object.defineProperty(connection, "state", {
91
+ configurable: true,
92
+ enumerable: true,
93
+ get() {
94
+ const raw = getRaw();
95
+ if (raw != null && typeof raw === "object" && rawHasInternalKeys(raw)) return stripInternalKeys(raw);
96
+ return raw;
97
+ }
98
+ });
99
+ Object.defineProperty(connection, "setState", {
100
+ configurable: true,
101
+ writable: true,
102
+ value(stateOrFn) {
103
+ const raw = getRaw();
104
+ const flags = raw != null && typeof raw === "object" ? extractInternalFlags(raw) : {};
105
+ const hasFlags = Object.keys(flags).length > 0;
106
+ let newUserState;
107
+ if (typeof stateOrFn === "function") newUserState = stateOrFn(hasFlags ? stripInternalKeys(raw) : raw);
108
+ else newUserState = stateOrFn;
109
+ if (hasFlags) {
110
+ if (newUserState != null && typeof newUserState === "object") return setRaw({
111
+ ...newUserState,
112
+ ...flags
113
+ });
114
+ return setRaw(flags);
115
+ }
116
+ return setRaw(newUserState);
117
+ }
118
+ });
119
+ }
120
+ /** The raw connection state, internal flags included. */
121
+ function getConnectionRawState(connection) {
122
+ ensureConnectionWrapped(connection);
123
+ return rawStateAccessors.get(connection).getRaw();
124
+ }
125
+ /** Read an internal flag from the raw connection state. */
126
+ function getConnectionFlag(connection, key) {
127
+ ensureConnectionWrapped(connection);
128
+ return rawStateAccessors.get(connection).getRaw()?.[key];
129
+ }
130
+ /**
131
+ * Write an internal flag to the raw connection state. `undefined` removes
132
+ * the key rather than storing a dead value; the last key removed leaves
133
+ * `null`.
134
+ */
135
+ function setConnectionFlag(connection, key, value) {
136
+ ensureConnectionWrapped(connection);
137
+ const accessors = rawStateAccessors.get(connection);
138
+ const raw = accessors.getRaw() ?? {};
139
+ if (value === void 0) {
140
+ const { [key]: _, ...rest } = raw;
141
+ accessors.setRaw(Object.keys(rest).length > 0 ? rest : null);
142
+ } else accessors.setRaw({
143
+ ...raw,
144
+ [key]: value
145
+ });
146
+ }
147
+ function isConnectionReadonly(connection) {
148
+ return !!getConnectionFlag(connection, CF_READONLY_KEY);
149
+ }
150
+ function setConnectionReadonly(connection, readonly) {
151
+ setConnectionFlag(connection, CF_READONLY_KEY, readonly ? true : void 0);
152
+ }
153
+ function isConnectionProtocolEnabled(connection) {
154
+ return !getConnectionFlag(connection, CF_NO_PROTOCOL_KEY);
155
+ }
156
+ function setConnectionProtocolEnabled(connection, enabled) {
157
+ setConnectionFlag(connection, CF_NO_PROTOCOL_KEY, enabled ? void 0 : true);
158
+ }
159
+ //#endregion
160
+ //#region src/websockets/connection.ts
161
+ let _Symbol$iterator;
162
+ if (!("OPEN" in WebSocket)) {
163
+ const WebSocketStatus = {
164
+ CONNECTING: WebSocket.READY_STATE_CONNECTING,
165
+ OPEN: WebSocket.READY_STATE_OPEN,
166
+ CLOSING: WebSocket.READY_STATE_CLOSING,
167
+ CLOSED: WebSocket.READY_STATE_CLOSED
168
+ };
169
+ Object.assign(WebSocket, WebSocketStatus);
170
+ Object.assign(WebSocket.prototype, WebSocketStatus);
171
+ }
172
+ function tryGetManagedWebSocketMeta(ws) {
173
+ try {
174
+ const attachment = WebSocket.prototype.deserializeAttachment.call(ws);
175
+ if (!attachment || typeof attachment !== "object") return null;
176
+ if (!("__pk" in attachment)) return null;
177
+ const pk = attachment.__pk;
178
+ if (!pk || typeof pk !== "object") return null;
179
+ const { id, tags } = pk;
180
+ if (typeof id !== "string") return null;
181
+ const { uri } = pk;
182
+ return {
183
+ id,
184
+ tags: Array.isArray(tags) ? tags : [],
185
+ uri: typeof uri === "string" ? uri : void 0
186
+ };
187
+ } catch {
188
+ return null;
189
+ }
190
+ }
191
+ function isManagedWebSocket(ws) {
192
+ return tryGetManagedWebSocketMeta(ws) !== null;
193
+ }
194
+ var _cache = /* @__PURE__ */ new WeakMap();
195
+ /**
196
+ * Cache websocket attachments to avoid having to rehydrate them on every property access.
197
+ */
198
+ var AttachmentCache = class {
199
+ constructor() {
200
+ _classPrivateFieldInitSpec(this, _cache, /* @__PURE__ */ new WeakMap());
201
+ }
202
+ get(ws) {
203
+ let attachment = _classPrivateFieldGet2(_cache, this).get(ws);
204
+ if (!attachment) {
205
+ attachment = WebSocket.prototype.deserializeAttachment.call(ws);
206
+ if (attachment !== void 0) _classPrivateFieldGet2(_cache, this).set(ws, attachment);
207
+ else throw new Error("Missing managed WebSocket lifecycle attachment");
208
+ }
209
+ return attachment;
210
+ }
211
+ set(ws, attachment) {
212
+ _classPrivateFieldGet2(_cache, this).set(ws, attachment);
213
+ WebSocket.prototype.serializeAttachment.call(ws, attachment);
214
+ }
215
+ };
216
+ const attachments = new AttachmentCache();
217
+ const connections = /* @__PURE__ */ new WeakSet();
218
+ const isWrapped = (ws) => {
219
+ return connections.has(ws);
220
+ };
221
+ /**
222
+ * Wraps a WebSocket with Connection fields that rehydrate the
223
+ * socket attachments lazily only when requested.
224
+ */
225
+ const createConnection = (ws) => {
226
+ if (isWrapped(ws)) return ws;
227
+ let initialState;
228
+ if ("state" in ws) {
229
+ initialState = ws.state;
230
+ delete ws.state;
231
+ }
232
+ const connection = Object.defineProperties(ws, {
233
+ id: {
234
+ configurable: true,
235
+ get() {
236
+ return attachments.get(ws).__pk.id;
237
+ }
238
+ },
239
+ uri: {
240
+ configurable: true,
241
+ get() {
242
+ return attachments.get(ws).__pk.uri ?? null;
243
+ }
244
+ },
245
+ tags: {
246
+ configurable: true,
247
+ get() {
248
+ return attachments.get(ws).__pk.tags ?? [];
249
+ }
250
+ },
251
+ state: {
252
+ configurable: true,
253
+ get() {
254
+ return attachments.get(ws).__user ?? null;
255
+ }
256
+ },
257
+ setState: {
258
+ configurable: true,
259
+ value: function setState(setState) {
260
+ const state = setState instanceof Function ? setState(this.state) : setState;
261
+ attachments.set(ws, {
262
+ ...attachments.get(ws),
263
+ __user: state ?? null
264
+ });
265
+ return state;
266
+ }
267
+ }
268
+ });
269
+ if (initialState) connection.setState(initialState);
270
+ connections.add(connection);
271
+ return connection;
272
+ };
273
+ var _sockets = /* @__PURE__ */ new WeakMap();
274
+ _Symbol$iterator = Symbol.iterator;
275
+ var ConnectionIterator = class {
276
+ constructor(sockets, tag) {
277
+ this.sockets = sockets;
278
+ this.tag = tag;
279
+ this.index = 0;
280
+ _classPrivateFieldInitSpec(this, _sockets, void 0);
281
+ }
282
+ [_Symbol$iterator]() {
283
+ return this;
284
+ }
285
+ next() {
286
+ const sockets = _classPrivateFieldGet2(_sockets, this) ?? _classPrivateFieldSet2(_sockets, this, this.sockets.get(this.tag));
287
+ let socket;
288
+ while (socket = sockets[this.index++]) if (socket.readyState === WebSocket.OPEN) {
289
+ if (!isManagedWebSocket(socket)) continue;
290
+ return {
291
+ done: false,
292
+ value: createConnection(socket)
293
+ };
294
+ }
295
+ return {
296
+ done: true,
297
+ value: void 0
298
+ };
299
+ }
300
+ };
301
+ /**
302
+ * Deduplicate and validate connection tags.
303
+ * Returns the final tag array (always includes the connection id as the first tag).
304
+ */
305
+ function prepareTags(connectionId, userTags) {
306
+ const tags = [connectionId, ...userTags.filter((t) => t !== connectionId)];
307
+ if (tags.length > 10) throw new Error("A connection can only have 10 tags, including the default id tag.");
308
+ for (const tag of tags) {
309
+ if (typeof tag !== "string") throw new Error(`A connection tag must be a string. Received: ${tag}`);
310
+ if (tag === "") throw new Error("A connection tag must not be an empty string.");
311
+ if (tag.length > 256) throw new Error("A connection tag must not exceed 256 characters");
312
+ }
313
+ return tags;
314
+ }
315
+ /** The platform-backed manager for hibernating WebSockets. */
316
+ var ConnectionManager = class {
317
+ constructor(controller) {
318
+ this.controller = controller;
319
+ }
320
+ getConnection(id) {
321
+ const matching = this.controller.get(id).filter((ws) => {
322
+ return tryGetManagedWebSocketMeta(ws)?.id === id;
323
+ });
324
+ if (matching.length === 0) return void 0;
325
+ if (matching.length === 1) return createConnection(matching[0]);
326
+ throw new Error(`More than one connection found for id ${id}. Did you mean to use getConnections(tag) instead?`);
327
+ }
328
+ getConnections(tag) {
329
+ return new ConnectionIterator(this.controller, tag);
330
+ }
331
+ accept(connection, options) {
332
+ const tags = prepareTags(connection.id, options.tags);
333
+ this.controller.accept(connection, tags);
334
+ attachments.set(connection, {
335
+ __pk: {
336
+ id: connection.id,
337
+ tags,
338
+ uri: connection.uri ?? void 0
339
+ },
340
+ __user: null
341
+ });
342
+ return createConnection(connection);
343
+ }
344
+ };
345
+ //#endregion
346
+ //#region src/websockets/callables-target.ts
347
+ /**
348
+ * The single exposure policy for callable names. `Object.prototype` and
349
+ * `RpcTarget.prototype` members are unreachable over Cap'n Web anyway
350
+ * and are silently excluded; `then` is rejected loudly because exposing
351
+ * it would make the remote stub thenable.
352
+ */
353
+ function assertExposable(name) {
354
+ if (name === "then") throw new Error("A callables target cannot expose a method named \"then\" — it would make the remote stub thenable");
355
+ if (name === "__cf_agent_send") throw new Error(`A callables target cannot expose "${CAPNWEB_TRANSPORT_SEND}"; it is the transport's frame pipe`);
356
+ return !(name === "constructor" || name in Object.prototype || name in RpcTarget$1.prototype);
357
+ }
358
+ /**
359
+ * The exposable prototype methods of a callables target, each bound to
360
+ * invoke on the real instance (so private fields and `this` behave).
361
+ *
362
+ * Cap'n Web resolves methods on the prototype chain and rejects own
363
+ * instance properties, so only prototype methods participate. The
364
+ * nearest declaration wins for overridden names.
365
+ *
366
+ * @param target - The callables target to enumerate.
367
+ * @returns Method names mapped to invokers on the target.
368
+ */
369
+ function exposableMethods(target) {
370
+ const methods = /* @__PURE__ */ new Map();
371
+ const seen = /* @__PURE__ */ new Set();
372
+ let prototype = Object.getPrototypeOf(target);
373
+ while (prototype && prototype !== RpcTarget$1.prototype && prototype !== Object.prototype) {
374
+ for (const name of Object.getOwnPropertyNames(prototype)) {
375
+ if (seen.has(name)) continue;
376
+ seen.add(name);
377
+ if (!assertExposable(name)) continue;
378
+ const descriptor = Object.getOwnPropertyDescriptor(prototype, name);
379
+ if (!descriptor || typeof descriptor.value !== "function") continue;
380
+ const method = descriptor.value;
381
+ methods.set(name, (...args) => Reflect.apply(method, target, args));
382
+ }
383
+ prototype = Object.getPrototypeOf(prototype);
384
+ }
385
+ return methods;
386
+ }
387
+ /**
388
+ * Build a Cap'n Web session root exposing exactly the given methods.
389
+ *
390
+ * Cap'n Web resolves methods on the prototype chain, rejects own
391
+ * instance properties, and breaks on Proxy-wrapped roots — so the root
392
+ * is a private `RpcTarget` subclass whose prototype carries the methods
393
+ * and nothing else.
394
+ */
395
+ function buildRoot(methods) {
396
+ class Root extends RpcTarget$1 {}
397
+ for (const [name, invoke] of methods) Object.defineProperty(Root.prototype, name, {
398
+ value: invoke,
399
+ writable: true,
400
+ configurable: true,
401
+ enumerable: false
402
+ });
403
+ return new Root();
404
+ }
405
+ //#endregion
406
+ //#region src/websockets/transport.ts
407
+ /**
408
+ * A non-hibernating connection with the public `Connection` contract,
409
+ * backed by a Cap'n Web session instead of a hibernating socket. It lives
410
+ * only in memory and disappears with the isolate.
411
+ */
412
+ var CapnWebConnection = class extends EventTarget {
413
+ constructor(id, uri, pipe) {
414
+ super();
415
+ this.id = id;
416
+ this.uri = uri;
417
+ this.pipe = pipe;
418
+ this.CONNECTING = WebSocket.CONNECTING;
419
+ this.OPEN = WebSocket.OPEN;
420
+ this.CLOSING = WebSocket.CLOSING;
421
+ this.CLOSED = WebSocket.CLOSED;
422
+ this.readyState = WebSocket.OPEN;
423
+ this.state = null;
424
+ this.tags = [];
425
+ }
426
+ send(message) {
427
+ if (this.readyState !== WebSocket.OPEN) throw new TypeError("WebSocket send() after close");
428
+ this.pipe.send(message);
429
+ }
430
+ close(code, reason) {
431
+ if (this.readyState >= WebSocket.CLOSING) return;
432
+ this.pipe.close(code, reason);
433
+ this.readyState = WebSocket.CLOSING;
434
+ }
435
+ setState(next) {
436
+ const state = typeof next === "function" ? next(this.state) : next;
437
+ this.state = state;
438
+ return state;
439
+ }
440
+ };
441
+ /**
442
+ * Accept a Cap'n Web transport upgrade.
443
+ *
444
+ * The session root carries the frame pipe plus the host's native
445
+ * callables. The client's protocol frames arrive through the pipe and are
446
+ * handed to `onMessage`; the host's frames go out through the client's
447
+ * `message` callback; `useAgent().stub` calls hit the callables directly.
448
+ * The socket is a plain in-memory `WebSocketPair`, so it pins the Durable
449
+ * Object and does not survive hibernation.
450
+ */
451
+ async function openCapnWebSession(options) {
452
+ const { request, connectionId } = options;
453
+ const pair = new WebSocketPair();
454
+ const server = pair[0];
455
+ server.accept();
456
+ let client;
457
+ let closed = false;
458
+ let close = {
459
+ code: 1e3,
460
+ reason: "",
461
+ wasClean: true
462
+ };
463
+ const connection = new CapnWebConnection(connectionId, request.url, {
464
+ send: (message) => {
465
+ client?.message(message).catch((error) => {
466
+ if (!closed) console.error("Cap'n Web frame delivery failed:", error);
467
+ });
468
+ },
469
+ close: (code = 1e3, reason = "") => {
470
+ server.close(code, reason);
471
+ close = {
472
+ code,
473
+ reason,
474
+ wasClean: true
475
+ };
476
+ finish();
477
+ }
478
+ });
479
+ const session = {
480
+ connection,
481
+ dispose: () => connection.close(1001, "Session replaced")
482
+ };
483
+ const finish = async () => {
484
+ if (closed) return;
485
+ closed = true;
486
+ connection.readyState = WebSocket.CLOSED;
487
+ try {
488
+ client?.[Symbol.dispose]();
489
+ } catch {}
490
+ options.onDispose(session);
491
+ await options.onClose(connection, close.code, close.reason, close.wasClean);
492
+ };
493
+ const rootMethods = new Map(options.callables(connection));
494
+ rootMethods.set(CAPNWEB_TRANSPORT_SEND, (message) => options.onMessage(connection, message));
495
+ client = newWebSocketRpcSession(server, buildRoot(rootMethods));
496
+ server.addEventListener("close", (event) => {
497
+ close = {
498
+ code: event.code,
499
+ reason: event.reason,
500
+ wasClean: event.wasClean
501
+ };
502
+ finish();
503
+ }, { once: true });
504
+ server.addEventListener("error", (event) => {
505
+ if (closed) return;
506
+ close = {
507
+ ...close,
508
+ wasClean: false
509
+ };
510
+ const error = event instanceof ErrorEvent ? event.error ?? new Error(event.message) : /* @__PURE__ */ new Error("Cap'n Web transport socket error");
511
+ options.onError(connection, error).catch((handlerError) => {
512
+ console.error("Cap'n Web onError handler failed:", handlerError);
513
+ }).finally(finish);
514
+ }, { once: true });
515
+ const ctx = { request };
516
+ connection.tags = prepareTags(connectionId, await options.tags(connection, ctx));
517
+ options.onOpen(session);
518
+ try {
519
+ await options.onConnect(connection, ctx);
520
+ } catch (error) {
521
+ connection.close(1011, "onConnect failed");
522
+ throw error;
523
+ }
524
+ return {
525
+ response: new Response(null, {
526
+ status: 101,
527
+ webSocket: pair[1]
528
+ }),
529
+ session
530
+ };
531
+ }
532
+ //#endregion
533
+ //#region src/websockets/websockets.ts
534
+ /**
535
+ * Reserved close codes the runtime synthesizes when there was no real
536
+ * Close frame from the peer (1005 NoStatusReceived, 1006 AbnormalClosure,
537
+ * 1015 TLSHandshake). They cannot appear in an outgoing Close frame, and
538
+ * there is no peer left to receive a reciprocation.
539
+ */
540
+ function isReservedCloseCode(code) {
541
+ return code === 1005 || code === 1006 || code === 1015;
542
+ }
543
+ /**
544
+ * Reciprocate a peer-initiated Close frame to complete the handshake, as
545
+ * the Hibernation API contract requires. Best-effort: swallows errors
546
+ * from already-closed sockets or invalid codes/reasons, and skips
547
+ * reciprocation entirely for reserved codes (dead transport).
548
+ */
549
+ function reciprocateClose(ws, code, reason) {
550
+ if (isReservedCloseCode(code)) return;
551
+ try {
552
+ ws.close(code, reason);
553
+ } catch {}
554
+ }
555
+ function isStateFrame(value) {
556
+ if (typeof value !== "object" || value === null) return false;
557
+ const frame = value;
558
+ return frame.type === "cf_agent_state" && "state" in frame;
559
+ }
560
+ /** Parse a text frame; anything that is not JSON is `undefined`. */
561
+ function parseJson(text) {
562
+ try {
563
+ return JSON.parse(text);
564
+ } catch {
565
+ return;
566
+ }
567
+ }
568
+ function isRpcRequest(value) {
569
+ if (typeof value !== "object" || value === null) return false;
570
+ const frame = value;
571
+ return frame.type === "rpc" && typeof frame.id === "string" && typeof frame.method === "string" && Array.isArray(frame.args);
572
+ }
573
+ var _handlers = /* @__PURE__ */ new WeakMap();
574
+ var _getConnectionTags = /* @__PURE__ */ new WeakMap();
575
+ var _protocol = /* @__PURE__ */ new WeakMap();
576
+ var _readonly = /* @__PURE__ */ new WeakMap();
577
+ var _state = /* @__PURE__ */ new WeakMap();
578
+ var _connecting = /* @__PURE__ */ new WeakMap();
579
+ var _callables = /* @__PURE__ */ new WeakMap();
580
+ var _sessions = /* @__PURE__ */ new WeakMap();
581
+ var _manager = /* @__PURE__ */ new WeakMap();
582
+ var _WebSockets_brand = /* @__PURE__ */ new WeakSet();
583
+ /**
584
+ * Opt-in WebSocket support for Lifecycle Objects.
585
+ *
586
+ * Lifecycle itself does not model WebSockets — hosts that want them
587
+ * install this capability, which owns the connection subsystem end to
588
+ * end: it claims upgrades, dispatches `onConnect`/`onMessage`/`onClose`
589
+ * inside the host invocation boundary, reciprocates close handshakes,
590
+ * and answers `getConnections()`/`getConnection()`.
591
+ *
592
+ * ```ts
593
+ * class Room extends DurableObject<Env> {
594
+ * readonly webSockets = new WebSockets({
595
+ * handlers: {
596
+ * onConnect: (connection) => connection.send("welcome"),
597
+ * onMessage: (connection, message) => { ... }
598
+ * },
599
+ * callables: new RoomCallables()
600
+ * });
601
+ * readonly lifecycle = Lifecycle.install(this).use(this.webSockets);
602
+ * }
603
+ * ```
604
+ *
605
+ * Connections arrive on one of two wires, chosen by the client:
606
+ *
607
+ * - **cf-websocket** (default): accepted with the Hibernation API. Idle
608
+ * clients stay connected while the Durable Object leaves memory.
609
+ * - **capnweb** (`?__agents_transport=capnweb`): protocol frames through
610
+ * one pipe method on a Cap'n Web session whose root also carries the
611
+ * host's callables natively. Non-hibernating — the object stays pinned
612
+ * while the connection is open.
613
+ *
614
+ * Both wires dispatch the same handlers and appear in `getConnections()`.
615
+ * On both, the capability speaks the Agent protocol a plain host needs
616
+ * for `useAgent` and `AgentClient`: it sends the identity frame on
617
+ * connect, and it serves `callables` — as `rpc` JSON frames on the
618
+ * WebSocket wire, and natively on the Cap'n Web session root, where an
619
+ * `RpcTarget` result becomes a live stub and calls pipeline. `call()`
620
+ * and `stub` work against a plain Durable Object exactly as against an
621
+ * `Agent`. Pass a `State` capability as `state` and the hook's
622
+ * `state`/`setState` work too: the current value is pushed on connect
623
+ * and client updates are validated and applied; the state owner
624
+ * broadcasts changes with `broadcastState()`. Per-connection readonly
625
+ * and no-protocol flags live here as well, for every host.
626
+ *
627
+ * @experimental The API surface may change before stabilizing.
628
+ */
629
+ var WebSockets = class extends LifecycleCapability {
630
+ constructor(options = {}) {
631
+ super("websockets");
632
+ _classPrivateMethodInitSpec(this, _WebSockets_brand);
633
+ this.claims = "catch-all";
634
+ _classPrivateFieldInitSpec(this, _handlers, void 0);
635
+ _classPrivateFieldInitSpec(this, _getConnectionTags, void 0);
636
+ _classPrivateFieldInitSpec(this, _protocol, void 0);
637
+ _classPrivateFieldInitSpec(this, _readonly, void 0);
638
+ _classPrivateFieldInitSpec(this, _state, void 0);
639
+ _classPrivateFieldInitSpec(this, _connecting, /* @__PURE__ */ new Set());
640
+ _classPrivateFieldInitSpec(this, _callables, void 0);
641
+ _classPrivateFieldInitSpec(this, _sessions, /* @__PURE__ */ new Map());
642
+ _classPrivateFieldInitSpec(this, _manager, void 0);
643
+ _classPrivateFieldSet2(_handlers, this, options.handlers);
644
+ _classPrivateFieldSet2(_getConnectionTags, this, options.getConnectionTags);
645
+ _classPrivateFieldSet2(_protocol, this, options.protocol ?? true);
646
+ _classPrivateFieldSet2(_readonly, this, options.readonly);
647
+ _classPrivateFieldSet2(_state, this, options.state);
648
+ _classPrivateFieldSet2(_callables, this, options.callables ? exposableMethods(options.callables) : /* @__PURE__ */ new Map());
649
+ }
650
+ /**
651
+ * Claim every upgrade, never declining: a Cap'n Web transport upgrade
652
+ * becomes a session, everything else a tracked hibernating connection,
653
+ * whether or not handlers or callables are configured. Handlers only add
654
+ * behavior on connect, message, close, and error.
655
+ */
656
+ onWebSocketUpgrade({ request }) {
657
+ return isCapnWebTransportUpgrade(request) ? _assertClassBrand(_WebSockets_brand, this, _acceptCapnWebSession).call(this, request) : _assertClassBrand(_WebSockets_brand, this, _acceptConnection).call(this, request);
658
+ }
659
+ /** Dispatch a platform message wake for a capability-owned socket. */
660
+ async onWebSocketMessage(ws, message) {
661
+ if (!isManagedWebSocket(ws)) return false;
662
+ await _assertClassBrand(_WebSockets_brand, this, _message).call(this, createConnection(ws), message);
663
+ return true;
664
+ }
665
+ /** Dispatch and reciprocate a close wake for an owned socket. */
666
+ async onWebSocketClose(ws, code, reason, wasClean) {
667
+ if (!isManagedWebSocket(ws)) return false;
668
+ try {
669
+ await _assertClassBrand(_WebSockets_brand, this, _close).call(this, createConnection(ws), code, reason, wasClean);
670
+ } finally {
671
+ reciprocateClose(ws, code, reason);
672
+ }
673
+ return true;
674
+ }
675
+ /** Dispatch an error wake for an owned socket. */
676
+ async onWebSocketError(ws, error) {
677
+ if (!isManagedWebSocket(ws)) return false;
678
+ await _assertClassBrand(_WebSockets_brand, this, _error).call(this, createConnection(ws), error);
679
+ return true;
680
+ }
681
+ /**
682
+ * Close every owned connection during explicit host destruction. The
683
+ * capability owns its sockets' lifetimes, so it also owns tearing
684
+ * them down.
685
+ */
686
+ dispose() {
687
+ for (const connection of this.getConnections()) try {
688
+ connection.close(1001, "Durable Object destroyed");
689
+ } catch {}
690
+ }
691
+ /** Open connections on either wire, optionally by tag. */
692
+ *getConnections(tag) {
693
+ for (const { connection } of _classPrivateFieldGet2(_sessions, this).values()) {
694
+ if (connection.readyState !== WebSocket.OPEN) continue;
695
+ if (!tag || connection.tags.includes(tag)) yield connection;
696
+ }
697
+ yield* _get_connectionManager.call(_assertClassBrand(_WebSockets_brand, this)).getConnections(tag);
698
+ }
699
+ /** One connection on either wire, by id. */
700
+ getConnection(id) {
701
+ const session = _classPrivateFieldGet2(_sessions, this).get(id)?.connection;
702
+ if (session && session.readyState === WebSocket.OPEN) return session;
703
+ return _get_connectionManager.call(_assertClassBrand(_WebSockets_brand, this)).getConnection(id);
704
+ }
705
+ /**
706
+ * Send the connect sequence: the identity frame, then the current state
707
+ * when one is stored. The identity carries `stateFollows` in that case,
708
+ * so clients resolve `ready` only once the state has landed. Nothing is
709
+ * sent to a no-protocol connection. Identity defaults as for
710
+ * `sendIdentity()`.
711
+ */
712
+ sendConnectFrames(connection, identity = _assertClassBrand(_WebSockets_brand, this, _defaultIdentity).call(this)) {
713
+ if (!isConnectionProtocolEnabled(connection)) return;
714
+ _classPrivateFieldGet2(_connecting, this).add(connection);
715
+ try {
716
+ const current = _classPrivateFieldGet2(_state, this)?.get();
717
+ const stateFrame = current === void 0 ? void 0 : JSON.stringify({
718
+ type: "cf_agent_state",
719
+ state: current
720
+ });
721
+ _assertClassBrand(_WebSockets_brand, this, _sendFrame).call(this, connection, {
722
+ type: "cf_agent_identity",
723
+ name: identity.name,
724
+ agent: identity.agent,
725
+ ...stateFrame !== void 0 && { stateFollows: true }
726
+ });
727
+ if (stateFrame !== void 0) _assertClassBrand(_WebSockets_brand, this, _send).call(this, connection, stateFrame);
728
+ } finally {
729
+ _classPrivateFieldGet2(_connecting, this).delete(connection);
730
+ }
731
+ }
732
+ /**
733
+ * Send the identity frame alone, unless the connection is no-protocol.
734
+ * Clients resolve `ready` on it, so a host that also pushes state on
735
+ * connect should use `sendConnectFrames()`. The defaults are the Durable
736
+ * Object's routed name and host class; a host whose public identity
737
+ * differs — an `Agent` facet, whose routed name is an internal encoding
738
+ * of its logical name — passes its own.
739
+ */
740
+ sendIdentity(connection, identity = _assertClassBrand(_WebSockets_brand, this, _defaultIdentity).call(this)) {
741
+ if (!isConnectionProtocolEnabled(connection)) return;
742
+ _assertClassBrand(_WebSockets_brand, this, _sendFrame).call(this, connection, {
743
+ type: "cf_agent_identity",
744
+ name: identity.name,
745
+ agent: identity.agent
746
+ });
747
+ }
748
+ /**
749
+ * Send the current state to one connection, unless nothing is stored
750
+ * or the connection is no-protocol. Reading the state may seed the
751
+ * initial value; see `#connecting`.
752
+ */
753
+ sendState(connection) {
754
+ if (!_classPrivateFieldGet2(_state, this) || !isConnectionProtocolEnabled(connection)) return;
755
+ const current = _classPrivateFieldGet2(_state, this).get();
756
+ if (current === void 0) return;
757
+ _assertClassBrand(_WebSockets_brand, this, _sendFrame).call(this, connection, {
758
+ type: "cf_agent_state",
759
+ state: current
760
+ });
761
+ }
762
+ /**
763
+ * Apply a parsed `cf_agent_state` frame from a client. A readonly
764
+ * connection is refused; a change the host's validator rejects is
765
+ * logged in full server-side and answered with a generic
766
+ * `cf_agent_state_error`. Broadcasting the accepted change is the state
767
+ * owner's call, through its `onChanged` hook. Callers that drive the
768
+ * protocol themselves call this inside their own invocation context;
769
+ * the capability's automatic path does so via `runInHostContext`.
770
+ *
771
+ * @returns Whether the frame was a state frame (handled either way).
772
+ */
773
+ applyStateFrame(connection, frame) {
774
+ if (!_classPrivateFieldGet2(_state, this) || !isStateFrame(frame)) return false;
775
+ if (isConnectionReadonly(connection)) {
776
+ _assertClassBrand(_WebSockets_brand, this, _sendFrame).call(this, connection, {
777
+ type: "cf_agent_state_error",
778
+ error: "Connection is readonly"
779
+ });
780
+ return true;
781
+ }
782
+ try {
783
+ _classPrivateFieldGet2(_state, this).set(frame.state, connection);
784
+ } catch (error) {
785
+ console.error("[WebSockets] State update rejected:", error);
786
+ _assertClassBrand(_WebSockets_brand, this, _sendFrame).call(this, connection, {
787
+ type: "cf_agent_state_error",
788
+ error: "State update rejected"
789
+ });
790
+ }
791
+ return true;
792
+ }
793
+ /**
794
+ * Push the current state to every protocol-enabled connection except
795
+ * the one a change came from, which already has the value it sent.
796
+ * Wire a `State`'s `onChanged` to this.
797
+ */
798
+ broadcastState(except) {
799
+ if (!_classPrivateFieldGet2(_state, this)) return;
800
+ const current = _classPrivateFieldGet2(_state, this).get();
801
+ if (current === void 0) return;
802
+ const frame = {
803
+ type: "cf_agent_state",
804
+ state: current
805
+ };
806
+ for (const connection of this.getConnections()) {
807
+ if (connection === except) continue;
808
+ if (_classPrivateFieldGet2(_connecting, this).has(connection)) continue;
809
+ if (!isConnectionProtocolEnabled(connection)) continue;
810
+ _assertClassBrand(_WebSockets_brand, this, _sendFrame).call(this, connection, frame);
811
+ }
812
+ }
813
+ /** Whether the connection may update host state over the wire. */
814
+ isReadonly(connection) {
815
+ return isConnectionReadonly(connection);
816
+ }
817
+ /** Mark a connection readonly, or writable again. */
818
+ setReadonly(connection, readonly = true) {
819
+ setConnectionReadonly(connection, readonly);
820
+ }
821
+ /** Whether protocol text frames reach the connection. */
822
+ isProtocolEnabled(connection) {
823
+ return isConnectionProtocolEnabled(connection);
824
+ }
825
+ /** Enable or suppress protocol text frames for a connection. */
826
+ setProtocolEnabled(connection, enabled) {
827
+ setConnectionProtocolEnabled(connection, enabled);
828
+ }
829
+ };
830
+ function _get_connectionManager() {
831
+ _classPrivateFieldGet2(_manager, this) ?? _classPrivateFieldSet2(_manager, this, new ConnectionManager(this.lifecycle.sockets));
832
+ return _classPrivateFieldGet2(_manager, this);
833
+ }
834
+ async function _connect(connection, ctx) {
835
+ ensureConnectionWrapped(connection);
836
+ if (_classPrivateFieldGet2(_readonly, this)?.call(this, connection, ctx)) setConnectionReadonly(connection, true);
837
+ if (_classPrivateFieldGet2(_protocol, this) !== false) if (typeof _classPrivateFieldGet2(_protocol, this) === "function" ? _classPrivateFieldGet2(_protocol, this).call(this, connection, ctx) : true) this.sendConnectFrames(connection);
838
+ else setConnectionProtocolEnabled(connection, false);
839
+ await this.lifecycle.runInHostContext(() => _classPrivateFieldGet2(_handlers, this)?.onConnect?.(connection, ctx), {
840
+ connection,
841
+ request: ctx.request
842
+ });
843
+ }
844
+ async function _message(connection, message) {
845
+ if (_classPrivateFieldGet2(_state, this) && _classPrivateFieldGet2(_protocol, this) !== false && typeof message === "string") {
846
+ const frame = parseJson(message);
847
+ if (isStateFrame(frame)) {
848
+ await this.lifecycle.runInHostContext(() => this.applyStateFrame(connection, frame), { connection });
849
+ return;
850
+ }
851
+ }
852
+ if (_classPrivateFieldGet2(_callables, this).size > 0 && await _assertClassBrand(_WebSockets_brand, this, _answerRpc).call(this, connection, message)) return;
853
+ await this.lifecycle.runInHostContext(() => _classPrivateFieldGet2(_handlers, this)?.onMessage?.(connection, message), { connection });
854
+ }
855
+ function _close(connection, code, reason, wasClean) {
856
+ return this.lifecycle.runInHostContext(() => _classPrivateFieldGet2(_handlers, this)?.onClose?.(connection, code, reason, wasClean), { connection });
857
+ }
858
+ function _error(connection, error) {
859
+ return this.lifecycle.runInHostContext(() => _classPrivateFieldGet2(_handlers, this)?.onError?.(connection, error), { connection });
860
+ }
861
+ async function _acceptConnection(request) {
862
+ const { 0: clientWebSocket, 1: serverWebSocket } = new WebSocketPair();
863
+ const connectionId = new URL(request.url).searchParams.get("_pk") || nanoid();
864
+ let connection = Object.assign(serverWebSocket, {
865
+ id: connectionId,
866
+ uri: request.url,
867
+ tags: [],
868
+ state: null,
869
+ setState(setState) {
870
+ const state = setState instanceof Function ? setState(this.state) : setState;
871
+ this.state = state;
872
+ return this.state;
873
+ }
874
+ });
875
+ const ctx = { request };
876
+ const tags = _classPrivateFieldGet2(_getConnectionTags, this) ? await _classPrivateFieldGet2(_getConnectionTags, this).call(this, connection, ctx) : [];
877
+ connection = _get_connectionManager.call(_assertClassBrand(_WebSockets_brand, this)).accept(connection, { tags });
878
+ await _assertClassBrand(_WebSockets_brand, this, _connect).call(this, connection, ctx);
879
+ return new Response(null, {
880
+ status: 101,
881
+ webSocket: clientWebSocket
882
+ });
883
+ }
884
+ async function _acceptCapnWebSession(request) {
885
+ const connectionId = new URL(request.url).searchParams.get("_pk") || nanoid();
886
+ _classPrivateFieldGet2(_sessions, this).get(connectionId)?.dispose();
887
+ const { response } = await openCapnWebSession({
888
+ request,
889
+ connectionId,
890
+ tags: (connection, ctx) => _classPrivateFieldGet2(_getConnectionTags, this)?.call(this, connection, ctx) ?? [],
891
+ onConnect: (connection, ctx) => _assertClassBrand(_WebSockets_brand, this, _connect).call(this, connection, ctx),
892
+ onMessage: (connection, message) => _assertClassBrand(_WebSockets_brand, this, _message).call(this, connection, message),
893
+ onClose: (connection, code, reason, wasClean) => _assertClassBrand(_WebSockets_brand, this, _close).call(this, connection, code, reason, wasClean).then(() => void 0),
894
+ onError: (connection, error) => _assertClassBrand(_WebSockets_brand, this, _error).call(this, connection, error).then(() => void 0),
895
+ callables: (connection) => _assertClassBrand(_WebSockets_brand, this, _nativeCallables).call(this, connection),
896
+ onOpen: (session) => _classPrivateFieldGet2(_sessions, this).set(connectionId, session),
897
+ onDispose: (ended) => {
898
+ if (_classPrivateFieldGet2(_sessions, this).get(connectionId) === ended) _classPrivateFieldGet2(_sessions, this).delete(connectionId);
899
+ }
900
+ });
901
+ return response;
902
+ }
903
+ function _defaultIdentity() {
904
+ return {
905
+ name: this.lifecycle.name,
906
+ agent: camelCaseToKebabCase(this.lifecycle.className)
907
+ };
908
+ }
909
+ /**
910
+ * Send one protocol frame. Serialization is the caller's contract — every
911
+ * frame built here is plain JSON — while a send failure is tolerated: the
912
+ * peer may have disconnected between the wake and the send.
913
+ */
914
+ function _sendFrame(connection, frame) {
915
+ _assertClassBrand(_WebSockets_brand, this, _send).call(this, connection, JSON.stringify(frame));
916
+ }
917
+ /** Write one already-serialized frame, tolerating a closed peer. */
918
+ function _send(connection, text) {
919
+ try {
920
+ connection.send(text);
921
+ } catch {}
922
+ }
923
+ /**
924
+ * The `callables` target as native Cap'n Web methods for one session:
925
+ * every method dispatches through the host boundary with this
926
+ * connection in scope and emits `rpc`/`rpc:error` events. Return values
927
+ * keep Cap'n Web semantics — an `RpcTarget` comes back as a live stub.
928
+ */
929
+ function _nativeCallables(connection) {
930
+ const methods = /* @__PURE__ */ new Map();
931
+ for (const [name, invoke] of _classPrivateFieldGet2(_callables, this)) methods.set(name, (...args) => _assertClassBrand(_WebSockets_brand, this, _dispatchCallable).call(this, name, () => invoke(...args), connection));
932
+ return methods;
933
+ }
934
+ /**
935
+ * Answer one `rpc` frame against `callables`. A `ReadableStream`
936
+ * result streams as `done: false` chunks followed by a final
937
+ * `done: true` frame, matching the client's stream callbacks.
938
+ *
939
+ * @returns Whether the message was an `rpc` frame (answered or not).
940
+ */
941
+ async function _answerRpc(connection, raw) {
942
+ if (typeof raw !== "string") return false;
943
+ let frame;
944
+ try {
945
+ frame = JSON.parse(raw);
946
+ } catch {
947
+ return false;
948
+ }
949
+ if (!isRpcRequest(frame)) return false;
950
+ const { id, method, args } = frame;
951
+ const invoke = _classPrivateFieldGet2(_callables, this).get(method);
952
+ if (!invoke) {
953
+ _assertClassBrand(_WebSockets_brand, this, _reply).call(this, connection, {
954
+ type: "rpc",
955
+ id,
956
+ success: false,
957
+ error: `Method ${method} does not exist`
958
+ });
959
+ return true;
960
+ }
961
+ try {
962
+ const result = await _assertClassBrand(_WebSockets_brand, this, _dispatchCallable).call(this, method, () => invoke(...args), connection);
963
+ if (result instanceof RpcTarget$1) throw new Error(`Method ${method} returns an RpcTarget, which only the capnweb transport can carry`);
964
+ if (result instanceof ReadableStream) {
965
+ for await (const chunk of result) _assertClassBrand(_WebSockets_brand, this, _reply).call(this, connection, {
966
+ type: "rpc",
967
+ id,
968
+ success: true,
969
+ done: false,
970
+ result: chunk
971
+ });
972
+ _assertClassBrand(_WebSockets_brand, this, _reply).call(this, connection, {
973
+ type: "rpc",
974
+ id,
975
+ success: true,
976
+ done: true,
977
+ result: void 0
978
+ });
979
+ } else _assertClassBrand(_WebSockets_brand, this, _reply).call(this, connection, {
980
+ type: "rpc",
981
+ id,
982
+ success: true,
983
+ done: true,
984
+ result
985
+ });
986
+ } catch (error) {
987
+ _assertClassBrand(_WebSockets_brand, this, _reply).call(this, connection, {
988
+ type: "rpc",
989
+ id,
990
+ success: false,
991
+ error: error instanceof Error ? error.message : String(error)
992
+ });
993
+ }
994
+ return true;
995
+ }
996
+ function _reply(connection, response) {
997
+ let text;
998
+ try {
999
+ text = JSON.stringify(response);
1000
+ } catch (error) {
1001
+ text = JSON.stringify({
1002
+ type: "rpc",
1003
+ id: response.id,
1004
+ success: false,
1005
+ error: `Result is not JSON-serializable: ${error instanceof Error ? error.message : String(error)}`
1006
+ });
1007
+ }
1008
+ _assertClassBrand(_WebSockets_brand, this, _send).call(this, connection, text);
1009
+ }
1010
+ async function _dispatchCallable(name, invoke, connection) {
1011
+ const services = this.lifecycle;
1012
+ try {
1013
+ const result = await services.runInHostContext(invoke, { connection });
1014
+ services.events.emit("rpc", {
1015
+ method: name,
1016
+ streaming: result instanceof ReadableStream
1017
+ });
1018
+ return result;
1019
+ } catch (error) {
1020
+ services.events.emit("rpc:error", {
1021
+ method: name,
1022
+ error: error instanceof Error ? error.message : String(error)
1023
+ });
1024
+ throw error;
1025
+ }
1026
+ }
1027
+ //#endregion
1028
+ export { getConnectionFlag as a, isConnectionReadonly as c, setConnectionProtocolEnabled as d, setConnectionReadonly as f, ensureConnectionWrapped as i, registerInternalConnectionKeys as l, CF_NO_PROTOCOL_KEY as n, getConnectionRawState as o, CF_READONLY_KEY as r, isConnectionProtocolEnabled as s, WebSockets as t, setConnectionFlag as u };
1029
+
1030
+ //# sourceMappingURL=websockets-Ci-LZFHH.js.map