@langchain/langgraph-sdk 1.9.8 → 1.9.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/stream/transport/utils.cjs +2 -1
- package/dist/client/stream/transport/utils.cjs.map +1 -1
- package/dist/client/stream/transport/utils.js +2 -1
- package/dist/client/stream/transport/utils.js.map +1 -1
- package/dist/client/stream/transport/websocket.cjs +1 -1
- package/dist/client/stream/transport/websocket.cjs.map +1 -1
- package/dist/client/stream/transport/websocket.d.cts.map +1 -1
- package/dist/client/stream/transport/websocket.d.ts.map +1 -1
- package/dist/client/stream/transport/websocket.js +2 -2
- package/dist/client/stream/transport/websocket.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
//#region src/client/stream/transport/utils.ts
|
|
2
2
|
const isRecord = (value) => typeof value === "object" && value !== null;
|
|
3
|
-
|
|
3
|
+
/** Match {@link BaseClient.prepareFetchOptions}: preserve any apiUrl path prefix. */
|
|
4
|
+
const toAbsoluteUrl = (apiUrl, path) => new URL(`${apiUrl.replace(/\/$/, "")}${path}`);
|
|
4
5
|
const toError = (error) => error instanceof Error ? error : new Error(String(error));
|
|
5
6
|
const toWebSocketUrl = (apiUrl) => {
|
|
6
7
|
const url = new URL(apiUrl);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.cjs","names":[],"sources":["../../../../src/client/stream/transport/utils.ts"],"sourcesContent":["import type { HeaderValue } from \"./types.js\";\nimport type { CommandResponse, ErrorResponse } from \"@langchain/protocol\";\n\nexport const isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\nexport const toAbsoluteUrl = (apiUrl: string, path: string) =>\n new URL(
|
|
1
|
+
{"version":3,"file":"utils.cjs","names":[],"sources":["../../../../src/client/stream/transport/utils.ts"],"sourcesContent":["import type { HeaderValue } from \"./types.js\";\nimport type { CommandResponse, ErrorResponse } from \"@langchain/protocol\";\n\nexport const isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\n/** Match {@link BaseClient.prepareFetchOptions}: preserve any apiUrl path prefix. */\nexport const toAbsoluteUrl = (apiUrl: string, path: string) =>\n new URL(`${apiUrl.replace(/\\/$/, \"\")}${path}`);\n\nexport const toError = (error: unknown) =>\n // oxlint-disable-next-line no-instanceof/no-instanceof\n error instanceof Error ? error : new Error(String(error));\n\nexport const toWebSocketUrl = (apiUrl: string): string => {\n // Extract path from the input (e.g. \"http://host/threads/X/stream\") and\n // swap the scheme to ws/wss. The caller passes a fully-formed URL\n // with the desired path.\n const url = new URL(apiUrl);\n url.protocol = url.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n url.search = \"\";\n url.hash = \"\";\n return url.toString();\n};\n\nexport const hasHeaders = (headers?: Record<string, HeaderValue>) =>\n Object.values(headers ?? {}).some((value) => value != null);\n\nexport function mergeHeaders(\n ...headerGroups: Array<\n HeadersInit | Record<string, HeaderValue> | undefined | null\n >\n): Headers {\n const merged = new Headers();\n\n for (const group of headerGroups) {\n if (!group) {\n continue;\n }\n\n // oxlint-disable-next-line no-instanceof/no-instanceof\n if (group instanceof Headers) {\n group.forEach((value, key) => {\n merged.set(key, value);\n });\n continue;\n }\n\n if (Array.isArray(group)) {\n for (const [key, value] of group) {\n if (value == null) {\n merged.delete(key);\n } else {\n merged.set(key, value);\n }\n }\n continue;\n }\n\n for (const [key, value] of Object.entries(group)) {\n if (value == null) {\n merged.delete(key);\n } else {\n merged.set(key, value);\n }\n }\n }\n\n return merged;\n}\n\nexport function isProtocolResponse(\n value: unknown\n): value is CommandResponse | ErrorResponse {\n return (\n isRecord(value) &&\n typeof value.type === \"string\" &&\n (value.type === \"success\" || value.type === \"error\")\n );\n}\n"],"mappings":";AAGA,MAAa,YAAY,UACvB,OAAO,UAAU,YAAY,UAAU;;AAGzC,MAAa,iBAAiB,QAAgB,SAC5C,IAAI,IAAI,GAAG,OAAO,QAAQ,OAAO,GAAG,GAAG,OAAO;AAEhD,MAAa,WAAW,UAEtB,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC;AAE3D,MAAa,kBAAkB,WAA2B;CAIxD,MAAM,MAAM,IAAI,IAAI,OAAO;AAC3B,KAAI,WAAW,IAAI,aAAa,WAAW,SAAS;AACpD,KAAI,SAAS;AACb,KAAI,OAAO;AACX,QAAO,IAAI,UAAU;;AAGvB,MAAa,cAAc,YACzB,OAAO,OAAO,WAAW,EAAE,CAAC,CAAC,MAAM,UAAU,SAAS,KAAK;AAE7D,SAAgB,aACd,GAAG,cAGM;CACT,MAAM,SAAS,IAAI,SAAS;AAE5B,MAAK,MAAM,SAAS,cAAc;AAChC,MAAI,CAAC,MACH;AAIF,MAAI,iBAAiB,SAAS;AAC5B,SAAM,SAAS,OAAO,QAAQ;AAC5B,WAAO,IAAI,KAAK,MAAM;KACtB;AACF;;AAGF,MAAI,MAAM,QAAQ,MAAM,EAAE;AACxB,QAAK,MAAM,CAAC,KAAK,UAAU,MACzB,KAAI,SAAS,KACX,QAAO,OAAO,IAAI;OAElB,QAAO,IAAI,KAAK,MAAM;AAG1B;;AAGF,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,CAC9C,KAAI,SAAS,KACX,QAAO,OAAO,IAAI;MAElB,QAAO,IAAI,KAAK,MAAM;;AAK5B,QAAO;;AAGT,SAAgB,mBACd,OAC0C;AAC1C,QACE,SAAS,MAAM,IACf,OAAO,MAAM,SAAS,aACrB,MAAM,SAAS,aAAa,MAAM,SAAS"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
//#region src/client/stream/transport/utils.ts
|
|
2
2
|
const isRecord = (value) => typeof value === "object" && value !== null;
|
|
3
|
-
|
|
3
|
+
/** Match {@link BaseClient.prepareFetchOptions}: preserve any apiUrl path prefix. */
|
|
4
|
+
const toAbsoluteUrl = (apiUrl, path) => new URL(`${apiUrl.replace(/\/$/, "")}${path}`);
|
|
4
5
|
const toError = (error) => error instanceof Error ? error : new Error(String(error));
|
|
5
6
|
const toWebSocketUrl = (apiUrl) => {
|
|
6
7
|
const url = new URL(apiUrl);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","names":[],"sources":["../../../../src/client/stream/transport/utils.ts"],"sourcesContent":["import type { HeaderValue } from \"./types.js\";\nimport type { CommandResponse, ErrorResponse } from \"@langchain/protocol\";\n\nexport const isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\nexport const toAbsoluteUrl = (apiUrl: string, path: string) =>\n new URL(
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../../../../src/client/stream/transport/utils.ts"],"sourcesContent":["import type { HeaderValue } from \"./types.js\";\nimport type { CommandResponse, ErrorResponse } from \"@langchain/protocol\";\n\nexport const isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\n/** Match {@link BaseClient.prepareFetchOptions}: preserve any apiUrl path prefix. */\nexport const toAbsoluteUrl = (apiUrl: string, path: string) =>\n new URL(`${apiUrl.replace(/\\/$/, \"\")}${path}`);\n\nexport const toError = (error: unknown) =>\n // oxlint-disable-next-line no-instanceof/no-instanceof\n error instanceof Error ? error : new Error(String(error));\n\nexport const toWebSocketUrl = (apiUrl: string): string => {\n // Extract path from the input (e.g. \"http://host/threads/X/stream\") and\n // swap the scheme to ws/wss. The caller passes a fully-formed URL\n // with the desired path.\n const url = new URL(apiUrl);\n url.protocol = url.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n url.search = \"\";\n url.hash = \"\";\n return url.toString();\n};\n\nexport const hasHeaders = (headers?: Record<string, HeaderValue>) =>\n Object.values(headers ?? {}).some((value) => value != null);\n\nexport function mergeHeaders(\n ...headerGroups: Array<\n HeadersInit | Record<string, HeaderValue> | undefined | null\n >\n): Headers {\n const merged = new Headers();\n\n for (const group of headerGroups) {\n if (!group) {\n continue;\n }\n\n // oxlint-disable-next-line no-instanceof/no-instanceof\n if (group instanceof Headers) {\n group.forEach((value, key) => {\n merged.set(key, value);\n });\n continue;\n }\n\n if (Array.isArray(group)) {\n for (const [key, value] of group) {\n if (value == null) {\n merged.delete(key);\n } else {\n merged.set(key, value);\n }\n }\n continue;\n }\n\n for (const [key, value] of Object.entries(group)) {\n if (value == null) {\n merged.delete(key);\n } else {\n merged.set(key, value);\n }\n }\n }\n\n return merged;\n}\n\nexport function isProtocolResponse(\n value: unknown\n): value is CommandResponse | ErrorResponse {\n return (\n isRecord(value) &&\n typeof value.type === \"string\" &&\n (value.type === \"success\" || value.type === \"error\")\n );\n}\n"],"mappings":";AAGA,MAAa,YAAY,UACvB,OAAO,UAAU,YAAY,UAAU;;AAGzC,MAAa,iBAAiB,QAAgB,SAC5C,IAAI,IAAI,GAAG,OAAO,QAAQ,OAAO,GAAG,GAAG,OAAO;AAEhD,MAAa,WAAW,UAEtB,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC;AAE3D,MAAa,kBAAkB,WAA2B;CAIxD,MAAM,MAAM,IAAI,IAAI,OAAO;AAC3B,KAAI,WAAW,IAAI,aAAa,WAAW,SAAS;AACpD,KAAI,SAAS;AACb,KAAI,OAAO;AACX,QAAO,IAAI,UAAU;;AAGvB,MAAa,cAAc,YACzB,OAAO,OAAO,WAAW,EAAE,CAAC,CAAC,MAAM,UAAU,SAAS,KAAK;AAE7D,SAAgB,aACd,GAAG,cAGM;CACT,MAAM,SAAS,IAAI,SAAS;AAE5B,MAAK,MAAM,SAAS,cAAc;AAChC,MAAI,CAAC,MACH;AAIF,MAAI,iBAAiB,SAAS;AAC5B,SAAM,SAAS,OAAO,QAAQ;AAC5B,WAAO,IAAI,KAAK,MAAM;KACtB;AACF;;AAGF,MAAI,MAAM,QAAQ,MAAM,EAAE;AACxB,QAAK,MAAM,CAAC,KAAK,UAAU,MACzB,KAAI,SAAS,KACX,QAAO,OAAO,IAAI;OAElB,QAAO,IAAI,KAAK,MAAM;AAG1B;;AAGF,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,CAC9C,KAAI,SAAS,KACX,QAAO,OAAO,IAAI;MAElB,QAAO,IAAI,KAAK,MAAM;;AAK5B,QAAO;;AAGT,SAAgB,mBACd,OAC0C;AAC1C,QACE,SAAS,MAAM,IACf,OAAO,MAAM,SAAS,aACrB,MAAM,SAAS,aAAa,MAAM,SAAS"}
|
|
@@ -29,7 +29,7 @@ var ProtocolWebSocketTransportAdapter = class {
|
|
|
29
29
|
async open() {
|
|
30
30
|
if (this.socket != null) return;
|
|
31
31
|
this.assertBrowserSafeTransportConfig();
|
|
32
|
-
const wsUrl = require_utils.toWebSocketUrl(
|
|
32
|
+
const wsUrl = require_utils.toWebSocketUrl(require_utils.toAbsoluteUrl(this.apiUrl, this.streamUrl).toString());
|
|
33
33
|
const socket = this.webSocketFactory(wsUrl);
|
|
34
34
|
this.socket = socket;
|
|
35
35
|
this.closed = false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket.cjs","names":["AsyncQueue","toWebSocketUrl","hasHeaders","toError","isRecord"],"sources":["../../../../src/client/stream/transport/websocket.ts"],"sourcesContent":["import { AsyncQueue } from \"./queue.js\";\nimport type {\n Message,\n Command,\n CommandResponse,\n ErrorResponse,\n} from \"@langchain/protocol\";\n\nimport {
|
|
1
|
+
{"version":3,"file":"websocket.cjs","names":["AsyncQueue","toWebSocketUrl","toAbsoluteUrl","hasHeaders","toError","isRecord"],"sources":["../../../../src/client/stream/transport/websocket.ts"],"sourcesContent":["import { AsyncQueue } from \"./queue.js\";\nimport type {\n Message,\n Command,\n CommandResponse,\n ErrorResponse,\n} from \"@langchain/protocol\";\n\nimport {\n toAbsoluteUrl,\n toWebSocketUrl,\n isRecord,\n hasHeaders,\n toError,\n} from \"./utils.js\";\nimport type {\n HeaderValue,\n ProtocolRequestHook,\n PendingResponse,\n ProtocolWebSocketTransportOptions,\n} from \"./types.js\";\nimport type { TransportAdapter } from \"../transport.js\";\n\n/**\n * Transport adapter that speaks the thread-centric protocol over a\n * bidirectional WebSocket. Bound to a specific `threadId` — the socket\n * connects to `ws://.../threads/:thread_id/stream/events`.\n */\nexport class ProtocolWebSocketTransportAdapter implements TransportAdapter {\n readonly threadId: string;\n\n private readonly queue = new AsyncQueue<Message>();\n\n private readonly apiUrl: string;\n\n private readonly defaultHeaders?: Record<string, HeaderValue>;\n\n private readonly onRequest?: ProtocolRequestHook;\n\n private readonly webSocketFactory: (url: string) => WebSocket;\n\n private readonly streamUrl: string;\n\n private readonly pending = new Map<number, PendingResponse>();\n\n private socket: WebSocket | null = null;\n\n private closed = false;\n\n private intentionalClose = false;\n\n constructor(options: ProtocolWebSocketTransportOptions) {\n this.apiUrl = options.apiUrl;\n this.threadId = options.threadId;\n this.defaultHeaders = options.defaultHeaders;\n this.onRequest = options.onRequest;\n this.webSocketFactory =\n options.webSocketFactory ?? ((url) => new WebSocket(url));\n this.streamUrl =\n options.paths?.stream ?? `/threads/${this.threadId}/stream/events`;\n }\n\n async open(): Promise<void> {\n if (this.socket != null) return;\n this.assertBrowserSafeTransportConfig();\n\n const wsUrl = toWebSocketUrl(\n toAbsoluteUrl(this.apiUrl, this.streamUrl).toString()\n );\n const socket = this.webSocketFactory(wsUrl);\n this.socket = socket;\n this.closed = false;\n this.intentionalClose = false;\n\n socket.addEventListener(\"message\", this.handleMessage);\n socket.addEventListener(\"close\", this.handleClose);\n socket.addEventListener(\"error\", this.handleSocketError);\n\n await new Promise<void>((resolve, reject) => {\n const onOpen = () => {\n cleanup();\n resolve();\n };\n const onError = () => {\n cleanup();\n reject(new Error(\"Failed to open protocol WebSocket.\"));\n };\n const cleanup = () => {\n socket.removeEventListener(\"open\", onOpen);\n socket.removeEventListener(\"error\", onError);\n };\n socket.addEventListener(\"open\", onOpen, { once: true });\n socket.addEventListener(\"error\", onError, { once: true });\n });\n }\n\n async send(\n command: Command\n ): Promise<CommandResponse | ErrorResponse | void> {\n return await this.sendCommand(command);\n }\n\n events(): AsyncIterable<Message> {\n const queue = this.queue;\n return {\n [Symbol.asyncIterator]: () => ({\n next: async () => await queue.shift(),\n return: async () => {\n queue.close();\n return { done: true, value: undefined };\n },\n }),\n };\n }\n\n async close(): Promise<void> {\n if (this.closed) {\n return;\n }\n\n this.closed = true;\n this.intentionalClose = true;\n\n for (const { reject } of this.pending.values()) {\n reject(new Error(\"Protocol WebSocket connection closed.\"));\n }\n this.pending.clear();\n this.queue.close();\n\n const socket = this.socket;\n this.socket = null;\n if (!socket) {\n return;\n }\n\n await new Promise<void>((resolve) => {\n if (socket.readyState === WebSocket.CLOSED) {\n resolve();\n return;\n }\n\n const onClose = () => {\n socket.removeEventListener(\"close\", onClose);\n resolve();\n };\n\n socket.addEventListener(\"close\", onClose, { once: true });\n if (\n socket.readyState === WebSocket.OPEN ||\n socket.readyState === WebSocket.CONNECTING\n ) {\n socket.close();\n } else {\n resolve();\n }\n });\n }\n\n private assertBrowserSafeTransportConfig(): void {\n if (hasHeaders(this.defaultHeaders) || this.onRequest != null) {\n throw new Error(\n \"Browser WebSocket protocol transport does not support defaultHeaders or onRequest hooks. Supply a custom protocolWebSocketFactory if you need custom WebSocket setup.\"\n );\n }\n }\n\n private async sendCommand(\n command: Command\n ): Promise<CommandResponse | ErrorResponse> {\n const socket = this.socket;\n if (socket == null || socket.readyState !== WebSocket.OPEN) {\n throw new Error(\"Protocol WebSocket is not open.\");\n }\n\n return await new Promise<CommandResponse | ErrorResponse>(\n (resolve, reject) => {\n this.pending.set(command.id, { resolve, reject });\n\n try {\n socket.send(JSON.stringify(command));\n } catch (error) {\n this.pending.delete(command.id);\n reject(toError(error));\n }\n }\n );\n }\n\n private readonly handleMessage = (event: MessageEvent): void => {\n let payload: unknown;\n try {\n payload = JSON.parse(String(event.data));\n } catch {\n return;\n }\n\n if (\n isRecord(payload) &&\n typeof payload.id === \"number\" &&\n (payload.type === \"success\" || payload.type === \"error\")\n ) {\n const pending = this.pending.get(payload.id);\n if (pending) {\n this.pending.delete(payload.id);\n pending.resolve(payload as CommandResponse | ErrorResponse);\n }\n return;\n }\n\n if (isRecord(payload) && payload.type === \"event\") {\n this.queue.push(payload as Message);\n }\n };\n\n private readonly handleClose = (): void => {\n this.socket = null;\n\n if (this.intentionalClose || this.closed) {\n this.queue.close();\n return;\n }\n\n const error = new Error(\"Protocol WebSocket closed unexpectedly.\");\n for (const { reject } of this.pending.values()) {\n reject(error);\n }\n this.pending.clear();\n this.queue.close(error);\n };\n\n private readonly handleSocketError = (): void => {\n if (this.closed || this.intentionalClose) {\n return;\n }\n\n const error = new Error(\"Protocol WebSocket encountered an error.\");\n for (const { reject } of this.pending.values()) {\n reject(error);\n }\n this.pending.clear();\n this.queue.close(error);\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket.d.cts","names":[],"sources":["../../../../src/client/stream/transport/websocket.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"websocket.d.cts","names":[],"sources":["../../../../src/client/stream/transport/websocket.ts"],"mappings":";;;;;;;AA4BA;;;cAAa,iCAAA,YAA6C,gBAAA;EAAA,SAC/C,QAAA;EAAA,iBAEQ,KAAA;EAAA,iBAEA,MAAA;EAAA,iBAEA,cAAA;EAAA,iBAEA,SAAA;EAAA,iBAEA,gBAAA;EAAA,iBAEA,SAAA;EAAA,iBAEA,OAAA;EAAA,QAET,MAAA;EAAA,QAEA,MAAA;EAAA,QAEA,gBAAA;EAER,WAAA,CAAY,OAAA,EAAS,iCAAA;EAWf,IAAA,CAAA,GAAQ,OAAA;EAkCR,IAAA,CACJ,OAAA,EAAS,OAAA,GACR,OAAA,CAAQ,eAAA,GAAkB,aAAA;EAI7B,MAAA,CAAA,GAAU,aAAA,CAAc,OAAA;EAalB,KAAA,CAAA,GAAS,OAAA;EAAA,QA2CP,gCAAA;EAAA,QAQM,WAAA;EAAA,iBAsBG,aAAA;EAAA,iBA0BA,WAAA;EAAA,iBAgBA,iBAAA;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket.d.ts","names":[],"sources":["../../../../src/client/stream/transport/websocket.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"websocket.d.ts","names":[],"sources":["../../../../src/client/stream/transport/websocket.ts"],"mappings":";;;;;;;AA4BA;;;cAAa,iCAAA,YAA6C,gBAAA;EAAA,SAC/C,QAAA;EAAA,iBAEQ,KAAA;EAAA,iBAEA,MAAA;EAAA,iBAEA,cAAA;EAAA,iBAEA,SAAA;EAAA,iBAEA,gBAAA;EAAA,iBAEA,SAAA;EAAA,iBAEA,OAAA;EAAA,QAET,MAAA;EAAA,QAEA,MAAA;EAAA,QAEA,gBAAA;EAER,WAAA,CAAY,OAAA,EAAS,iCAAA;EAWf,IAAA,CAAA,GAAQ,OAAA;EAkCR,IAAA,CACJ,OAAA,EAAS,OAAA,GACR,OAAA,CAAQ,eAAA,GAAkB,aAAA;EAI7B,MAAA,CAAA,GAAU,aAAA,CAAc,OAAA;EAalB,KAAA,CAAA,GAAS,OAAA;EAAA,QA2CP,gCAAA;EAAA,QAQM,WAAA;EAAA,iBAsBG,aAAA;EAAA,iBA0BA,WAAA;EAAA,iBAgBA,iBAAA;AAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AsyncQueue } from "./queue.js";
|
|
2
|
-
import { hasHeaders, isRecord, toError, toWebSocketUrl } from "./utils.js";
|
|
2
|
+
import { hasHeaders, isRecord, toAbsoluteUrl, toError, toWebSocketUrl } from "./utils.js";
|
|
3
3
|
//#region src/client/stream/transport/websocket.ts
|
|
4
4
|
/**
|
|
5
5
|
* Transport adapter that speaks the thread-centric protocol over a
|
|
@@ -29,7 +29,7 @@ var ProtocolWebSocketTransportAdapter = class {
|
|
|
29
29
|
async open() {
|
|
30
30
|
if (this.socket != null) return;
|
|
31
31
|
this.assertBrowserSafeTransportConfig();
|
|
32
|
-
const wsUrl = toWebSocketUrl(
|
|
32
|
+
const wsUrl = toWebSocketUrl(toAbsoluteUrl(this.apiUrl, this.streamUrl).toString());
|
|
33
33
|
const socket = this.webSocketFactory(wsUrl);
|
|
34
34
|
this.socket = socket;
|
|
35
35
|
this.closed = false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket.js","names":[],"sources":["../../../../src/client/stream/transport/websocket.ts"],"sourcesContent":["import { AsyncQueue } from \"./queue.js\";\nimport type {\n Message,\n Command,\n CommandResponse,\n ErrorResponse,\n} from \"@langchain/protocol\";\n\nimport {
|
|
1
|
+
{"version":3,"file":"websocket.js","names":[],"sources":["../../../../src/client/stream/transport/websocket.ts"],"sourcesContent":["import { AsyncQueue } from \"./queue.js\";\nimport type {\n Message,\n Command,\n CommandResponse,\n ErrorResponse,\n} from \"@langchain/protocol\";\n\nimport {\n toAbsoluteUrl,\n toWebSocketUrl,\n isRecord,\n hasHeaders,\n toError,\n} from \"./utils.js\";\nimport type {\n HeaderValue,\n ProtocolRequestHook,\n PendingResponse,\n ProtocolWebSocketTransportOptions,\n} from \"./types.js\";\nimport type { TransportAdapter } from \"../transport.js\";\n\n/**\n * Transport adapter that speaks the thread-centric protocol over a\n * bidirectional WebSocket. Bound to a specific `threadId` — the socket\n * connects to `ws://.../threads/:thread_id/stream/events`.\n */\nexport class ProtocolWebSocketTransportAdapter implements TransportAdapter {\n readonly threadId: string;\n\n private readonly queue = new AsyncQueue<Message>();\n\n private readonly apiUrl: string;\n\n private readonly defaultHeaders?: Record<string, HeaderValue>;\n\n private readonly onRequest?: ProtocolRequestHook;\n\n private readonly webSocketFactory: (url: string) => WebSocket;\n\n private readonly streamUrl: string;\n\n private readonly pending = new Map<number, PendingResponse>();\n\n private socket: WebSocket | null = null;\n\n private closed = false;\n\n private intentionalClose = false;\n\n constructor(options: ProtocolWebSocketTransportOptions) {\n this.apiUrl = options.apiUrl;\n this.threadId = options.threadId;\n this.defaultHeaders = options.defaultHeaders;\n this.onRequest = options.onRequest;\n this.webSocketFactory =\n options.webSocketFactory ?? ((url) => new WebSocket(url));\n this.streamUrl =\n options.paths?.stream ?? `/threads/${this.threadId}/stream/events`;\n }\n\n async open(): Promise<void> {\n if (this.socket != null) return;\n this.assertBrowserSafeTransportConfig();\n\n const wsUrl = toWebSocketUrl(\n toAbsoluteUrl(this.apiUrl, this.streamUrl).toString()\n );\n const socket = this.webSocketFactory(wsUrl);\n this.socket = socket;\n this.closed = false;\n this.intentionalClose = false;\n\n socket.addEventListener(\"message\", this.handleMessage);\n socket.addEventListener(\"close\", this.handleClose);\n socket.addEventListener(\"error\", this.handleSocketError);\n\n await new Promise<void>((resolve, reject) => {\n const onOpen = () => {\n cleanup();\n resolve();\n };\n const onError = () => {\n cleanup();\n reject(new Error(\"Failed to open protocol WebSocket.\"));\n };\n const cleanup = () => {\n socket.removeEventListener(\"open\", onOpen);\n socket.removeEventListener(\"error\", onError);\n };\n socket.addEventListener(\"open\", onOpen, { once: true });\n socket.addEventListener(\"error\", onError, { once: true });\n });\n }\n\n async send(\n command: Command\n ): Promise<CommandResponse | ErrorResponse | void> {\n return await this.sendCommand(command);\n }\n\n events(): AsyncIterable<Message> {\n const queue = this.queue;\n return {\n [Symbol.asyncIterator]: () => ({\n next: async () => await queue.shift(),\n return: async () => {\n queue.close();\n return { done: true, value: undefined };\n },\n }),\n };\n }\n\n async close(): Promise<void> {\n if (this.closed) {\n return;\n }\n\n this.closed = true;\n this.intentionalClose = true;\n\n for (const { reject } of this.pending.values()) {\n reject(new Error(\"Protocol WebSocket connection closed.\"));\n }\n this.pending.clear();\n this.queue.close();\n\n const socket = this.socket;\n this.socket = null;\n if (!socket) {\n return;\n }\n\n await new Promise<void>((resolve) => {\n if (socket.readyState === WebSocket.CLOSED) {\n resolve();\n return;\n }\n\n const onClose = () => {\n socket.removeEventListener(\"close\", onClose);\n resolve();\n };\n\n socket.addEventListener(\"close\", onClose, { once: true });\n if (\n socket.readyState === WebSocket.OPEN ||\n socket.readyState === WebSocket.CONNECTING\n ) {\n socket.close();\n } else {\n resolve();\n }\n });\n }\n\n private assertBrowserSafeTransportConfig(): void {\n if (hasHeaders(this.defaultHeaders) || this.onRequest != null) {\n throw new Error(\n \"Browser WebSocket protocol transport does not support defaultHeaders or onRequest hooks. Supply a custom protocolWebSocketFactory if you need custom WebSocket setup.\"\n );\n }\n }\n\n private async sendCommand(\n command: Command\n ): Promise<CommandResponse | ErrorResponse> {\n const socket = this.socket;\n if (socket == null || socket.readyState !== WebSocket.OPEN) {\n throw new Error(\"Protocol WebSocket is not open.\");\n }\n\n return await new Promise<CommandResponse | ErrorResponse>(\n (resolve, reject) => {\n this.pending.set(command.id, { resolve, reject });\n\n try {\n socket.send(JSON.stringify(command));\n } catch (error) {\n this.pending.delete(command.id);\n reject(toError(error));\n }\n }\n );\n }\n\n private readonly handleMessage = (event: MessageEvent): void => {\n let payload: unknown;\n try {\n payload = JSON.parse(String(event.data));\n } catch {\n return;\n }\n\n if (\n isRecord(payload) &&\n typeof payload.id === \"number\" &&\n (payload.type === \"success\" || payload.type === \"error\")\n ) {\n const pending = this.pending.get(payload.id);\n if (pending) {\n this.pending.delete(payload.id);\n pending.resolve(payload as CommandResponse | ErrorResponse);\n }\n return;\n }\n\n if (isRecord(payload) && payload.type === \"event\") {\n this.queue.push(payload as Message);\n }\n };\n\n private readonly handleClose = (): void => {\n this.socket = null;\n\n if (this.intentionalClose || this.closed) {\n this.queue.close();\n return;\n }\n\n const error = new Error(\"Protocol WebSocket closed unexpectedly.\");\n for (const { reject } of this.pending.values()) {\n reject(error);\n }\n this.pending.clear();\n this.queue.close(error);\n };\n\n private readonly handleSocketError = (): void => {\n if (this.closed || this.intentionalClose) {\n return;\n }\n\n const error = new Error(\"Protocol WebSocket encountered an error.\");\n for (const { reject } of this.pending.values()) {\n reject(error);\n }\n this.pending.clear();\n this.queue.close(error);\n };\n}\n"],"mappings":"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"}
|