@langgraph-js/pure-graph 3.0.0 → 3.1.1
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/adapter/fetch/index.js +2 -2
- package/dist/adapter/nextjs/index.js +1 -1
- package/dist/{createEndpoint-BViLxrhh.js → createEndpoint-YeQDXg5B.js} +2 -2
- package/dist/{createEndpoint-BViLxrhh.js.map → createEndpoint-YeQDXg5B.js.map} +1 -1
- package/dist/index.js +2 -2
- package/dist/{queue-CtVch_az.js → queue-8-m4OzOj.js} +2 -2
- package/dist/{queue-CtVch_az.js.map → queue-8-m4OzOj.js.map} +1 -1
- package/dist/remote/index.js +1 -1
- package/dist/{sqlite-adapter-5PeLHaxe.js → sqlite-adapter-Bbonr5S5.js} +8 -4
- package/dist/sqlite-adapter-Bbonr5S5.js.map +1 -0
- package/dist/storage/index.d.ts +4 -2
- package/dist/storage/memory/checkpoint.d.ts +1 -0
- package/dist/storage/memory/shallow-memory.d.ts +54 -0
- package/dist/{stream-umoA6h4q.js → stream-3xunCZso.js} +300 -5
- package/dist/stream-3xunCZso.js.map +1 -0
- package/package.json +1 -1
- package/dist/sqlite-adapter-5PeLHaxe.js.map +0 -1
- package/dist/stream-umoA6h4q.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { s as serialiseAsDict, a as streamState, g as getGraph, L as LangGraphGlobal } from '../../stream-
|
|
2
|
-
import { c as createEndpoint } from '../../createEndpoint-
|
|
1
|
+
import { s as serialiseAsDict, a as streamState, g as getGraph, L as LangGraphGlobal } from '../../stream-3xunCZso.js';
|
|
2
|
+
import { c as createEndpoint } from '../../createEndpoint-YeQDXg5B.js';
|
|
3
3
|
import z from 'zod';
|
|
4
4
|
import camelcaseKeys from 'camelcase-keys';
|
|
5
5
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { L as LangGraphGlobal, a as streamState, G as GRAPHS, g as getGraph } from './stream-
|
|
1
|
+
import { L as LangGraphGlobal, a as streamState, G as GRAPHS, g as getGraph } from './stream-3xunCZso.js';
|
|
2
2
|
|
|
3
3
|
const AssistantEndpoint = {
|
|
4
4
|
async search(query) {
|
|
@@ -205,4 +205,4 @@ const createEndpoint = () => {
|
|
|
205
205
|
};
|
|
206
206
|
|
|
207
207
|
export { AssistantEndpoint as A, createEndpoint as c };
|
|
208
|
-
//# sourceMappingURL=createEndpoint-
|
|
208
|
+
//# sourceMappingURL=createEndpoint-YeQDXg5B.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createEndpoint-BViLxrhh.js","sources":["../src/createEndpoint.ts"],"sourcesContent":["import { StreamEvent } from '@langchain/core/tracers/log_stream';\nimport { streamState } from './graph/stream.js';\nimport { Assistant, Run, StreamMode, Metadata, AssistantGraph } from '@langchain/langgraph-sdk';\nimport { getGraph, GRAPHS } from './utils/getGraph.js';\nimport { LangGraphGlobal } from './global.js';\nimport { AssistantSortBy, CancelAction, ILangGraphClient, RunStatus, SortOrder, StreamInputData } from './types.js';\nexport { registerGraph } from './utils/getGraph.js';\n\nexport const AssistantEndpoint: ILangGraphClient['assistants'] = {\n async search(query?: {\n graphId?: string;\n metadata?: Metadata;\n limit?: number;\n offset?: number;\n sortBy?: AssistantSortBy;\n sortOrder?: SortOrder;\n }): Promise<Assistant[]> {\n let results = Object.entries(GRAPHS).map(\n ([graphId, _]) =>\n ({\n assistant_id: graphId,\n graph_id: graphId,\n config: {},\n metadata: {},\n version: 1,\n name: graphId,\n description: '',\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n } as Assistant),\n );\n\n // Filter by graphId\n if (query?.graphId) {\n results = results.filter((a) => a.graph_id === query.graphId);\n }\n\n // Filter by metadata (simple implementation - check if all metadata keys/values match)\n if (query?.metadata && Object.keys(query.metadata).length > 0) {\n results = results.filter((assistant) => {\n return Object.entries(query.metadata!).every(([key, value]) => {\n return assistant.metadata && assistant.metadata[key] === value;\n });\n });\n }\n\n // Sort results\n if (query?.sortBy) {\n results.sort((a, b) => {\n const aValue = a[query.sortBy!];\n const bValue = b[query.sortBy!];\n const comparison = aValue < bValue ? -1 : aValue > bValue ? 1 : 0;\n return query.sortOrder === 'desc' ? -comparison : comparison;\n });\n }\n\n // Pagination\n const offset = query?.offset ?? 0;\n const limit = query?.limit;\n const paginatedResults = limit ? results.slice(offset, offset + limit) : results.slice(offset);\n\n return paginatedResults;\n },\n\n async count(query?: { graphId?: string; metadata?: Metadata }): Promise<number> {\n const results = await this.search(query);\n return results.length;\n },\n\n async get(assistantId: string): Promise<Assistant> {\n const assistant = Object.entries(GRAPHS).find(([graphId, _]) => graphId === assistantId);\n if (!assistant) {\n throw new Error(`Assistant not found: ${assistantId}`);\n }\n return {\n assistant_id: assistantId,\n graph_id: assistantId,\n config: {},\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n metadata: {},\n version: 1,\n name: assistantId,\n description: '',\n } as Assistant;\n },\n\n async delete(assistantId: string): Promise<void> {\n // ⚠️ 删除 assistant 不可用 - assistants 是从注册的图中生成的,不能删除\n throw new Error('Deleting assistants is not supported. Assistants are generated from registered graphs.');\n },\n\n async update(\n assistantId: string,\n updates: Partial<Pick<Assistant, 'name' | 'description' | 'metadata' | 'config'>>,\n ): Promise<Assistant> {\n // ⚠️ 更新 assistant 不可用 - assistants 是从注册的图中生成的,不能更新\n throw new Error('Updating assistants is not supported. Assistants are generated from registered graphs.');\n },\n\n async getGraph(assistantId: string, options?: { xray?: boolean | number }): Promise<AssistantGraph> {\n const config = {};\n const graph = await getGraph(assistantId, config);\n const drawable = await graph.getGraphAsync({\n ...config,\n xray: options?.xray ?? undefined,\n });\n return drawable.toJSON() as AssistantGraph;\n },\n\n async getSchemas(assistantId: string): Promise<{ graph_id: string; state_schema: any }> {\n const compiledGraph = await getGraph(assistantId, {});\n const builder = compiledGraph.builder;\n console.log(builder);\n return {\n graph_id: assistantId,\n /** @ts-ignore */\n state_schema: builder._inputDefinition,\n /** @ts-ignore */\n input_schema: builder._inputDefinition,\n /** @ts-ignore */\n output_schema: builder._outputDefinition,\n /** @ts-ignore */\n config_schema: builder._configSchema,\n /** @ts-ignoreß */\n context_schema: builder._configSchema,\n };\n },\n\n async getVersions(assistantId: string, options?: { limit?: number; offset?: number }): Promise<Assistant[]> {\n // ⚠️ 版本管理不可用 - 当前实现不支持多版本\n const assistant = await this.get(assistantId);\n const offset = options?.offset ?? 0;\n const limit = options?.limit;\n const results = limit ? [assistant].slice(offset, offset + limit) : [assistant].slice(offset);\n return results;\n },\n\n async setLatest(assistantId: string, version: number): Promise<Assistant> {\n // Fake\n const item = await this.get(assistantId);\n item.version = version;\n return item;\n },\n\n async create(params: {\n assistantId?: string;\n graphId: string;\n name?: string;\n description?: string;\n metadata?: Metadata;\n config?: any;\n ifExists?: 'raise' | 'do_nothing';\n }): Promise<Assistant> {\n // ⚠️ 创建 assistant 不可用 - assistants 是从注册的图中自动生成的,不能动态创建\n // 返回假数据以通过测试\n console.warn(\n '⚠️ Creating assistants is not supported. Assistants are generated from registered graphs. Returning mock data.',\n );\n const graphExists = Object.keys(GRAPHS).includes(params.graphId);\n\n if (!graphExists) {\n if (params.ifExists === 'raise') {\n throw new Error(`Graph not found: ${params.graphId}`);\n }\n // 如果 graph 不存在,我们仍然返回假数据\n }\n\n return {\n assistant_id: params.assistantId || params.graphId,\n graph_id: params.graphId,\n name: params.name || params.graphId,\n description: params.description || '',\n metadata: params.metadata || {},\n config: params.config || {},\n version: 1,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n } as Assistant;\n },\n};\n\nexport const createEndpoint = () => {\n const getThreads = () => {\n return LangGraphGlobal.globalThreadsManager;\n };\n return {\n assistants: AssistantEndpoint,\n get threads() {\n return LangGraphGlobal.globalThreadsManager;\n },\n runs: {\n list(\n threadId: string,\n options?: {\n limit?: number;\n offset?: number;\n status?: RunStatus;\n },\n ): Promise<Run[]> {\n return getThreads().listRuns(threadId, options);\n },\n async cancel(threadId: string, runId: string, wait?: boolean, action?: CancelAction): Promise<void> {\n return await LangGraphGlobal.globalMessageQueue.cancelQueue(runId);\n },\n async *stream(threadId: string, assistantId: string, payload: StreamInputData) {\n payload.config = {\n ...(payload.config ?? {}),\n configurable: {\n ...(payload.config?.configurable ?? {}),\n graph_id: assistantId,\n thread_id: threadId,\n },\n };\n const threads = getThreads();\n for await (const data of streamState(\n threads,\n threads.createRun(threadId, assistantId, payload),\n payload,\n {\n attempt: 0,\n getGraph,\n },\n )) {\n yield data;\n }\n },\n async *joinStream(\n threadId: string,\n runId: string,\n options?:\n | {\n signal?: AbortSignal;\n cancelOnDisconnect?: boolean;\n lastEventId?: string;\n streamMode?: StreamMode | StreamMode[];\n }\n | AbortSignal,\n ): AsyncGenerator<{ id?: string; event: StreamEvent; data: any }> {\n // 处理参数兼容性\n const config = options && typeof options === 'object' && 'signal' in options ? options : {};\n const signal =\n (options instanceof AbortSignal ? options : config.signal) || new AbortController().signal;\n\n try {\n // 获取 Redis 队列实例\n const queue = await LangGraphGlobal.globalMessageQueue.getQueue(runId);\n const allData = await queue.getAll();\n for (const eventMessage of allData) {\n yield {\n id: eventMessage.id,\n event: eventMessage.event as unknown as StreamEvent,\n data: eventMessage.data,\n };\n // 如果是流结束信号,停止监听\n if (\n eventMessage.event === '__stream_end__' ||\n eventMessage.event === '__stream_error__' ||\n eventMessage.event === '__stream_cancel__'\n ) {\n return;\n }\n }\n // 监听队列数据并转换格式\n for await (const eventMessage of queue.onDataReceive()) {\n // 检查是否被取消\n if (signal.aborted) {\n break;\n }\n\n // 转换 EventMessage 为期望的格式\n const event = eventMessage.event as unknown as StreamEvent;\n const data = eventMessage.data;\n\n yield {\n id: eventMessage.id,\n event,\n data,\n };\n\n // 如果是流结束信号,停止监听\n if (\n eventMessage.event === '__stream_end__' ||\n eventMessage.event === '__stream_error__' ||\n eventMessage.event === '__stream_cancel__'\n ) {\n break;\n }\n }\n } catch (error) {\n // 如果队列不存在或其他错误,记录警告但不抛出错误\n console.warn('Join stream failed:', error);\n }\n },\n },\n };\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createEndpoint-YeQDXg5B.js","sources":["../src/createEndpoint.ts"],"sourcesContent":["import { StreamEvent } from '@langchain/core/tracers/log_stream';\nimport { streamState } from './graph/stream.js';\nimport { Assistant, Run, StreamMode, Metadata, AssistantGraph } from '@langchain/langgraph-sdk';\nimport { getGraph, GRAPHS } from './utils/getGraph.js';\nimport { LangGraphGlobal } from './global.js';\nimport { AssistantSortBy, CancelAction, ILangGraphClient, RunStatus, SortOrder, StreamInputData } from './types.js';\nexport { registerGraph } from './utils/getGraph.js';\n\nexport const AssistantEndpoint: ILangGraphClient['assistants'] = {\n async search(query?: {\n graphId?: string;\n metadata?: Metadata;\n limit?: number;\n offset?: number;\n sortBy?: AssistantSortBy;\n sortOrder?: SortOrder;\n }): Promise<Assistant[]> {\n let results = Object.entries(GRAPHS).map(\n ([graphId, _]) =>\n ({\n assistant_id: graphId,\n graph_id: graphId,\n config: {},\n metadata: {},\n version: 1,\n name: graphId,\n description: '',\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n } as Assistant),\n );\n\n // Filter by graphId\n if (query?.graphId) {\n results = results.filter((a) => a.graph_id === query.graphId);\n }\n\n // Filter by metadata (simple implementation - check if all metadata keys/values match)\n if (query?.metadata && Object.keys(query.metadata).length > 0) {\n results = results.filter((assistant) => {\n return Object.entries(query.metadata!).every(([key, value]) => {\n return assistant.metadata && assistant.metadata[key] === value;\n });\n });\n }\n\n // Sort results\n if (query?.sortBy) {\n results.sort((a, b) => {\n const aValue = a[query.sortBy!];\n const bValue = b[query.sortBy!];\n const comparison = aValue < bValue ? -1 : aValue > bValue ? 1 : 0;\n return query.sortOrder === 'desc' ? -comparison : comparison;\n });\n }\n\n // Pagination\n const offset = query?.offset ?? 0;\n const limit = query?.limit;\n const paginatedResults = limit ? results.slice(offset, offset + limit) : results.slice(offset);\n\n return paginatedResults;\n },\n\n async count(query?: { graphId?: string; metadata?: Metadata }): Promise<number> {\n const results = await this.search(query);\n return results.length;\n },\n\n async get(assistantId: string): Promise<Assistant> {\n const assistant = Object.entries(GRAPHS).find(([graphId, _]) => graphId === assistantId);\n if (!assistant) {\n throw new Error(`Assistant not found: ${assistantId}`);\n }\n return {\n assistant_id: assistantId,\n graph_id: assistantId,\n config: {},\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n metadata: {},\n version: 1,\n name: assistantId,\n description: '',\n } as Assistant;\n },\n\n async delete(assistantId: string): Promise<void> {\n // ⚠️ 删除 assistant 不可用 - assistants 是从注册的图中生成的,不能删除\n throw new Error('Deleting assistants is not supported. Assistants are generated from registered graphs.');\n },\n\n async update(\n assistantId: string,\n updates: Partial<Pick<Assistant, 'name' | 'description' | 'metadata' | 'config'>>,\n ): Promise<Assistant> {\n // ⚠️ 更新 assistant 不可用 - assistants 是从注册的图中生成的,不能更新\n throw new Error('Updating assistants is not supported. Assistants are generated from registered graphs.');\n },\n\n async getGraph(assistantId: string, options?: { xray?: boolean | number }): Promise<AssistantGraph> {\n const config = {};\n const graph = await getGraph(assistantId, config);\n const drawable = await graph.getGraphAsync({\n ...config,\n xray: options?.xray ?? undefined,\n });\n return drawable.toJSON() as AssistantGraph;\n },\n\n async getSchemas(assistantId: string): Promise<{ graph_id: string; state_schema: any }> {\n const compiledGraph = await getGraph(assistantId, {});\n const builder = compiledGraph.builder;\n console.log(builder);\n return {\n graph_id: assistantId,\n /** @ts-ignore */\n state_schema: builder._inputDefinition,\n /** @ts-ignore */\n input_schema: builder._inputDefinition,\n /** @ts-ignore */\n output_schema: builder._outputDefinition,\n /** @ts-ignore */\n config_schema: builder._configSchema,\n /** @ts-ignoreß */\n context_schema: builder._configSchema,\n };\n },\n\n async getVersions(assistantId: string, options?: { limit?: number; offset?: number }): Promise<Assistant[]> {\n // ⚠️ 版本管理不可用 - 当前实现不支持多版本\n const assistant = await this.get(assistantId);\n const offset = options?.offset ?? 0;\n const limit = options?.limit;\n const results = limit ? [assistant].slice(offset, offset + limit) : [assistant].slice(offset);\n return results;\n },\n\n async setLatest(assistantId: string, version: number): Promise<Assistant> {\n // Fake\n const item = await this.get(assistantId);\n item.version = version;\n return item;\n },\n\n async create(params: {\n assistantId?: string;\n graphId: string;\n name?: string;\n description?: string;\n metadata?: Metadata;\n config?: any;\n ifExists?: 'raise' | 'do_nothing';\n }): Promise<Assistant> {\n // ⚠️ 创建 assistant 不可用 - assistants 是从注册的图中自动生成的,不能动态创建\n // 返回假数据以通过测试\n console.warn(\n '⚠️ Creating assistants is not supported. Assistants are generated from registered graphs. Returning mock data.',\n );\n const graphExists = Object.keys(GRAPHS).includes(params.graphId);\n\n if (!graphExists) {\n if (params.ifExists === 'raise') {\n throw new Error(`Graph not found: ${params.graphId}`);\n }\n // 如果 graph 不存在,我们仍然返回假数据\n }\n\n return {\n assistant_id: params.assistantId || params.graphId,\n graph_id: params.graphId,\n name: params.name || params.graphId,\n description: params.description || '',\n metadata: params.metadata || {},\n config: params.config || {},\n version: 1,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n } as Assistant;\n },\n};\n\nexport const createEndpoint = () => {\n const getThreads = () => {\n return LangGraphGlobal.globalThreadsManager;\n };\n return {\n assistants: AssistantEndpoint,\n get threads() {\n return LangGraphGlobal.globalThreadsManager;\n },\n runs: {\n list(\n threadId: string,\n options?: {\n limit?: number;\n offset?: number;\n status?: RunStatus;\n },\n ): Promise<Run[]> {\n return getThreads().listRuns(threadId, options);\n },\n async cancel(threadId: string, runId: string, wait?: boolean, action?: CancelAction): Promise<void> {\n return await LangGraphGlobal.globalMessageQueue.cancelQueue(runId);\n },\n async *stream(threadId: string, assistantId: string, payload: StreamInputData) {\n payload.config = {\n ...(payload.config ?? {}),\n configurable: {\n ...(payload.config?.configurable ?? {}),\n graph_id: assistantId,\n thread_id: threadId,\n },\n };\n const threads = getThreads();\n for await (const data of streamState(\n threads,\n threads.createRun(threadId, assistantId, payload),\n payload,\n {\n attempt: 0,\n getGraph,\n },\n )) {\n yield data;\n }\n },\n async *joinStream(\n threadId: string,\n runId: string,\n options?:\n | {\n signal?: AbortSignal;\n cancelOnDisconnect?: boolean;\n lastEventId?: string;\n streamMode?: StreamMode | StreamMode[];\n }\n | AbortSignal,\n ): AsyncGenerator<{ id?: string; event: StreamEvent; data: any }> {\n // 处理参数兼容性\n const config = options && typeof options === 'object' && 'signal' in options ? options : {};\n const signal =\n (options instanceof AbortSignal ? options : config.signal) || new AbortController().signal;\n\n try {\n // 获取 Redis 队列实例\n const queue = await LangGraphGlobal.globalMessageQueue.getQueue(runId);\n const allData = await queue.getAll();\n for (const eventMessage of allData) {\n yield {\n id: eventMessage.id,\n event: eventMessage.event as unknown as StreamEvent,\n data: eventMessage.data,\n };\n // 如果是流结束信号,停止监听\n if (\n eventMessage.event === '__stream_end__' ||\n eventMessage.event === '__stream_error__' ||\n eventMessage.event === '__stream_cancel__'\n ) {\n return;\n }\n }\n // 监听队列数据并转换格式\n for await (const eventMessage of queue.onDataReceive()) {\n // 检查是否被取消\n if (signal.aborted) {\n break;\n }\n\n // 转换 EventMessage 为期望的格式\n const event = eventMessage.event as unknown as StreamEvent;\n const data = eventMessage.data;\n\n yield {\n id: eventMessage.id,\n event,\n data,\n };\n\n // 如果是流结束信号,停止监听\n if (\n eventMessage.event === '__stream_end__' ||\n eventMessage.event === '__stream_error__' ||\n eventMessage.event === '__stream_cancel__'\n ) {\n break;\n }\n }\n } catch (error) {\n // 如果队列不存在或其他错误,记录警告但不抛出错误\n console.warn('Join stream failed:', error);\n }\n },\n },\n };\n};\n"],"names":[],"mappings":";;AAQO,MAAM,iBAAA,GAAoD;AAAA,EAC7D,MAAM,OAAO,KAAA,EAOY;AACrB,IAAA,IAAI,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,CAAE,GAAA;AAAA,MACjC,CAAC,CAAC,OAAA,EAAS,CAAC,CAAA,MACP;AAAA,QACG,YAAA,EAAc,OAAA;AAAA,QACd,QAAA,EAAU,OAAA;AAAA,QACV,QAAQ,EAAC;AAAA,QACT,UAAU,EAAC;AAAA,QACX,OAAA,EAAS,CAAA;AAAA,QACT,IAAA,EAAM,OAAA;AAAA,QACN,WAAA,EAAa,EAAA;AAAA,QACb,UAAA,EAAA,iBAAY,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,QACnC,UAAA,EAAA,iBAAY,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,OACvC;AAAA,KACR;AAGA,IAAA,IAAI,OAAO,OAAA,EAAS;AAChB,MAAA,OAAA,GAAU,QAAQ,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,QAAA,KAAa,MAAM,OAAO,CAAA;AAAA,IAChE;AAGA,IAAA,IAAI,KAAA,EAAO,YAAY,MAAA,CAAO,IAAA,CAAK,MAAM,QAAQ,CAAA,CAAE,SAAS,CAAA,EAAG;AAC3D,MAAA,OAAA,GAAU,OAAA,CAAQ,MAAA,CAAO,CAAC,SAAA,KAAc;AACpC,QAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,KAAA,CAAM,QAAS,CAAA,CAAE,MAAM,CAAC,CAAC,GAAA,EAAK,KAAK,CAAA,KAAM;AAC3D,UAAA,OAAO,SAAA,CAAU,QAAA,IAAY,SAAA,CAAU,QAAA,CAAS,GAAG,CAAA,KAAM,KAAA;AAAA,QAC7D,CAAC,CAAA;AAAA,MACL,CAAC,CAAA;AAAA,IACL;AAGA,IAAA,IAAI,OAAO,MAAA,EAAQ;AACf,MAAA,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM;AACnB,QAAA,MAAM,MAAA,GAAS,CAAA,CAAE,KAAA,CAAM,MAAO,CAAA;AAC9B,QAAA,MAAM,MAAA,GAAS,CAAA,CAAE,KAAA,CAAM,MAAO,CAAA;AAC9B,QAAA,MAAM,aAAa,MAAA,GAAS,MAAA,GAAS,EAAA,GAAK,MAAA,GAAS,SAAS,CAAA,GAAI,CAAA;AAChE,QAAA,OAAO,KAAA,CAAM,SAAA,KAAc,MAAA,GAAS,CAAC,UAAA,GAAa,UAAA;AAAA,MACtD,CAAC,CAAA;AAAA,IACL;AAGA,IAAA,MAAM,MAAA,GAAS,OAAO,MAAA,IAAU,CAAA;AAChC,IAAA,MAAM,QAAQ,KAAA,EAAO,KAAA;AACrB,IAAA,MAAM,gBAAA,GAAmB,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,MAAA,EAAQ,SAAS,KAAK,CAAA,GAAI,OAAA,CAAQ,KAAA,CAAM,MAAM,CAAA;AAE7F,IAAA,OAAO,gBAAA;AAAA,EACX,CAAA;AAAA,EAEA,MAAM,MAAM,KAAA,EAAoE;AAC5E,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA;AACvC,IAAA,OAAO,OAAA,CAAQ,MAAA;AAAA,EACnB,CAAA;AAAA,EAEA,MAAM,IAAI,WAAA,EAAyC;AAC/C,IAAA,MAAM,SAAA,GAAY,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,CAAE,IAAA,CAAK,CAAC,CAAC,OAAA,EAAS,CAAC,CAAA,KAAM,OAAA,KAAY,WAAW,CAAA;AACvF,IAAA,IAAI,CAAC,SAAA,EAAW;AACZ,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qBAAA,EAAwB,WAAW,CAAA,CAAE,CAAA;AAAA,IACzD;AACA,IAAA,OAAO;AAAA,MACH,YAAA,EAAc,WAAA;AAAA,MACd,QAAA,EAAU,WAAA;AAAA,MACV,QAAQ,EAAC;AAAA,MACT,UAAA,EAAA,iBAAY,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,MACnC,UAAA,EAAA,iBAAY,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,MACnC,UAAU,EAAC;AAAA,MACX,OAAA,EAAS,CAAA;AAAA,MACT,IAAA,EAAM,WAAA;AAAA,MACN,WAAA,EAAa;AAAA,KACjB;AAAA,EACJ,CAAA;AAAA,EAEA,MAAM,OAAO,WAAA,EAAoC;AAE7C,IAAA,MAAM,IAAI,MAAM,wFAAwF,CAAA;AAAA,EAC5G,CAAA;AAAA,EAEA,MAAM,MAAA,CACF,WAAA,EACA,OAAA,EACkB;AAElB,IAAA,MAAM,IAAI,MAAM,wFAAwF,CAAA;AAAA,EAC5G,CAAA;AAAA,EAEA,MAAM,QAAA,CAAS,WAAA,EAAqB,OAAA,EAAgE;AAChG,IAAA,MAAM,SAAS,EAAC;AAChB,IAAA,MAAM,KAAA,GAAQ,MAAM,QAAA,CAAS,WAAA,EAAa,MAAM,CAAA;AAChD,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,aAAA,CAAc;AAAA,MACvC,GAAG,MAAA;AAAA,MACH,IAAA,EAAM,SAAS,IAAA,IAAQ;AAAA,KAC1B,CAAA;AACD,IAAA,OAAO,SAAS,MAAA,EAAO;AAAA,EAC3B,CAAA;AAAA,EAEA,MAAM,WAAW,WAAA,EAAuE;AACpF,IAAA,MAAM,aAAA,GAAgB,MAAM,QAAA,CAAS,WAAA,EAAa,EAAE,CAAA;AACpD,IAAA,MAAM,UAAU,aAAA,CAAc,OAAA;AAC9B,IAAA,OAAA,CAAQ,IAAI,OAAO,CAAA;AACnB,IAAA,OAAO;AAAA,MACH,QAAA,EAAU,WAAA;AAAA;AAAA,MAEV,cAAc,OAAA,CAAQ,gBAAA;AAAA;AAAA,MAEtB,cAAc,OAAA,CAAQ,gBAAA;AAAA;AAAA,MAEtB,eAAe,OAAA,CAAQ,iBAAA;AAAA;AAAA,MAEvB,eAAe,OAAA,CAAQ,aAAA;AAAA;AAAA,MAEvB,gBAAgB,OAAA,CAAQ;AAAA,KAC5B;AAAA,EACJ,CAAA;AAAA,EAEA,MAAM,WAAA,CAAY,WAAA,EAAqB,OAAA,EAAqE;AAExG,IAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,GAAA,CAAI,WAAW,CAAA;AAC5C,IAAA,MAAM,MAAA,GAAS,SAAS,MAAA,IAAU,CAAA;AAClC,IAAA,MAAM,QAAQ,OAAA,EAAS,KAAA;AACvB,IAAA,MAAM,OAAA,GAAU,KAAA,GAAQ,CAAC,SAAS,EAAE,KAAA,CAAM,MAAA,EAAQ,MAAA,GAAS,KAAK,CAAA,GAAI,CAAC,SAAS,CAAA,CAAE,MAAM,MAAM,CAAA;AAC5F,IAAA,OAAO,OAAA;AAAA,EACX,CAAA;AAAA,EAEA,MAAM,SAAA,CAAU,WAAA,EAAqB,OAAA,EAAqC;AAEtE,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,GAAA,CAAI,WAAW,CAAA;AACvC,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACf,IAAA,OAAO,IAAA;AAAA,EACX,CAAA;AAAA,EAEA,MAAM,OAAO,MAAA,EAQU;AAGnB,IAAA,OAAA,CAAQ,IAAA;AAAA,MACJ;AAAA,KACJ;AACA,IAAA,MAAM,cAAc,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,QAAA,CAAS,OAAO,OAAO,CAAA;AAE/D,IAAA,IAAI,CAAC,WAAA,EAAa;AACd,MAAA,IAAI,MAAA,CAAO,aAAa,OAAA,EAAS;AAC7B,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,iBAAA,EAAoB,MAAA,CAAO,OAAO,CAAA,CAAE,CAAA;AAAA,MACxD;AAAA,IAEJ;AAEA,IAAA,OAAO;AAAA,MACH,YAAA,EAAc,MAAA,CAAO,WAAA,IAAe,MAAA,CAAO,OAAA;AAAA,MAC3C,UAAU,MAAA,CAAO,OAAA;AAAA,MACjB,IAAA,EAAM,MAAA,CAAO,IAAA,IAAQ,MAAA,CAAO,OAAA;AAAA,MAC5B,WAAA,EAAa,OAAO,WAAA,IAAe,EAAA;AAAA,MACnC,QAAA,EAAU,MAAA,CAAO,QAAA,IAAY,EAAC;AAAA,MAC9B,MAAA,EAAQ,MAAA,CAAO,MAAA,IAAU,EAAC;AAAA,MAC1B,OAAA,EAAS,CAAA;AAAA,MACT,UAAA,EAAA,iBAAY,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,MACnC,UAAA,EAAA,iBAAY,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,KACvC;AAAA,EACJ;AACJ;AAEO,MAAM,iBAAiB,MAAM;AAChC,EAAA,MAAM,aAAa,MAAM;AACrB,IAAA,OAAO,eAAA,CAAgB,oBAAA;AAAA,EAC3B,CAAA;AACA,EAAA,OAAO;AAAA,IACH,UAAA,EAAY,iBAAA;AAAA,IACZ,IAAI,OAAA,GAAU;AACV,MAAA,OAAO,eAAA,CAAgB,oBAAA;AAAA,IAC3B,CAAA;AAAA,IACA,IAAA,EAAM;AAAA,MACF,IAAA,CACI,UACA,OAAA,EAKc;AACd,QAAA,OAAO,UAAA,EAAW,CAAE,QAAA,CAAS,QAAA,EAAU,OAAO,CAAA;AAAA,MAClD,CAAA;AAAA,MACA,MAAM,MAAA,CAAO,QAAA,EAAkB,KAAA,EAAe,MAAgB,MAAA,EAAsC;AAChG,QAAA,OAAO,MAAM,eAAA,CAAgB,kBAAA,CAAmB,WAAA,CAAY,KAAK,CAAA;AAAA,MACrE,CAAA;AAAA,MACA,OAAO,MAAA,CAAO,QAAA,EAAkB,WAAA,EAAqB,OAAA,EAA0B;AAC3E,QAAA,OAAA,CAAQ,MAAA,GAAS;AAAA,UACb,GAAI,OAAA,CAAQ,MAAA,IAAU,EAAC;AAAA,UACvB,YAAA,EAAc;AAAA,YACV,GAAI,OAAA,CAAQ,MAAA,EAAQ,YAAA,IAAgB,EAAC;AAAA,YACrC,QAAA,EAAU,WAAA;AAAA,YACV,SAAA,EAAW;AAAA;AACf,SACJ;AACA,QAAA,MAAM,UAAU,UAAA,EAAW;AAC3B,QAAA,WAAA,MAAiB,IAAA,IAAQ,WAAA;AAAA,UACrB,OAAA;AAAA,UACA,OAAA,CAAQ,SAAA,CAAU,QAAA,EAAU,WAAA,EAAa,OAAO,CAAA;AAAA,UAChD,OAAA;AAAA,UACA;AAAA,YACI,OAAA,EAAS,CAAA;AAAA,YACT;AAAA;AACJ,SACJ,EAAG;AACC,UAAA,MAAM,IAAA;AAAA,QACV;AAAA,MACJ,CAAA;AAAA,MACA,OAAO,UAAA,CACH,QAAA,EACA,KAAA,EACA,OAAA,EAQ8D;AAE9D,QAAA,MAAM,MAAA,GAAS,WAAW,OAAO,OAAA,KAAY,YAAY,QAAA,IAAY,OAAA,GAAU,UAAU,EAAC;AAC1F,QAAA,MAAM,MAAA,GAAA,CACD,mBAAmB,WAAA,GAAc,OAAA,GAAU,OAAO,MAAA,KAAW,IAAI,iBAAgB,CAAE,MAAA;AAExF,QAAA,IAAI;AAEA,UAAA,MAAM,KAAA,GAAQ,MAAM,eAAA,CAAgB,kBAAA,CAAmB,SAAS,KAAK,CAAA;AACrE,UAAA,MAAM,OAAA,GAAU,MAAM,KAAA,CAAM,MAAA,EAAO;AACnC,UAAA,KAAA,MAAW,gBAAgB,OAAA,EAAS;AAChC,YAAA,MAAM;AAAA,cACF,IAAI,YAAA,CAAa,EAAA;AAAA,cACjB,OAAO,YAAA,CAAa,KAAA;AAAA,cACpB,MAAM,YAAA,CAAa;AAAA,aACvB;AAEA,YAAA,IACI,YAAA,CAAa,UAAU,gBAAA,IACvB,YAAA,CAAa,UAAU,kBAAA,IACvB,YAAA,CAAa,UAAU,mBAAA,EACzB;AACE,cAAA;AAAA,YACJ;AAAA,UACJ;AAEA,UAAA,WAAA,MAAiB,YAAA,IAAgB,KAAA,CAAM,aAAA,EAAc,EAAG;AAEpD,YAAA,IAAI,OAAO,OAAA,EAAS;AAChB,cAAA;AAAA,YACJ;AAGA,YAAA,MAAM,QAAQ,YAAA,CAAa,KAAA;AAC3B,YAAA,MAAM,OAAO,YAAA,CAAa,IAAA;AAE1B,YAAA,MAAM;AAAA,cACF,IAAI,YAAA,CAAa,EAAA;AAAA,cACjB,KAAA;AAAA,cACA;AAAA,aACJ;AAGA,YAAA,IACI,YAAA,CAAa,UAAU,gBAAA,IACvB,YAAA,CAAa,UAAU,kBAAA,IACvB,YAAA,CAAa,UAAU,mBAAA,EACzB;AACE,cAAA;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ,SAAS,KAAA,EAAO;AAEZ,UAAA,OAAA,CAAQ,IAAA,CAAK,uBAAuB,KAAK,CAAA;AAAA,QAC7C;AAAA,MACJ;AAAA;AACJ,GACJ;AACJ;;;;"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { A as AssistantEndpoint, c as createEndpoint } from './createEndpoint-
|
|
2
|
-
export { L as LangGraphGlobal, r as registerGraph } from './stream-
|
|
1
|
+
export { A as AssistantEndpoint, c as createEndpoint } from './createEndpoint-YeQDXg5B.js';
|
|
2
|
+
export { L as LangGraphGlobal, r as registerGraph } from './stream-3xunCZso.js';
|
|
3
3
|
import { entrypoint, getPreviousState, getConfig, Command } from '@langchain/langgraph';
|
|
4
4
|
import { schemaMetaRegistry } from '@langchain/langgraph/zod';
|
|
5
5
|
import { getDefaultsForSchema } from 'zod-defaults';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as BaseStreamQueue, C as CancelEventMessage } from './stream-
|
|
1
|
+
import { B as BaseStreamQueue, C as CancelEventMessage } from './stream-3xunCZso.js';
|
|
2
2
|
import { createClient } from 'redis';
|
|
3
3
|
|
|
4
4
|
class RedisStreamQueue extends BaseStreamQueue {
|
|
@@ -150,4 +150,4 @@ class RedisStreamQueue extends BaseStreamQueue {
|
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
export { RedisStreamQueue };
|
|
153
|
-
//# sourceMappingURL=queue-
|
|
153
|
+
//# sourceMappingURL=queue-8-m4OzOj.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue-CtVch_az.js","sources":["../src/storage/redis/queue.ts"],"sourcesContent":["import { CancelEventMessage, EventMessage } from '../../queue/event_message.js';\nimport { BaseStreamQueue } from '../../queue/stream_queue.js';\nimport { BaseStreamQueueInterface } from '../../queue/stream_queue.js';\nimport { createClient, RedisClientType } from 'redis';\n\n/**\n * Redis Stream 实现的消息队列,用于存储消息\n * 使用 Redis Streams 替代 pub/sub,支持集群模式\n */\nexport class RedisStreamQueue extends BaseStreamQueue implements BaseStreamQueueInterface {\n private redis: RedisClientType;\n private streamKey: string;\n private listKey: string;\n private isConnected = false;\n public cancelSignal: AbortController;\n private lastStreamId: string = '0'; // 最后读取的 Stream ID\n private pollInterval: number = 100; // 轮询间隔(毫秒)\n\n constructor(readonly id: string, readonly compressMessages: boolean = true, readonly ttl: number = 300) {\n super(id, true, ttl);\n this.streamKey = `stream:${this.id}`;\n this.listKey = `queue:${this.id}`;\n this.redis = createClient({\n url: process.env.REDIS_URL,\n });\n this.cancelSignal = new AbortController();\n\n // 连接 Redis 客户端(检查是否已经连接)\n if (!this.redis.isOpen) {\n this.redis.connect();\n }\n this.isConnected = true;\n }\n\n /**\n * 推送消息到 Redis Stream 和 List\n * - Stream: 用于实时推送(集群友好)\n * - List: 用于 getAll() 批量获取历史数据\n */\n async push(item: EventMessage): Promise<void> {\n const encodedData = await this.encodeData(item);\n // 将 Uint8Array 转换为 base64 字符串,以便存储到 Redis Stream\n const dataString = Buffer.from(encodedData).toString('base64');\n const serializedData = Buffer.from(encodedData);\n\n // 推送到 Stream(实时推送)\n // 注意:xAdd 的第三个参数必须是简单的键值对对象,值必须是字符串\n await this.redis.xAdd(this.streamKey, '*', { data: dataString });\n\n // 设置 Stream TTL\n await this.redis.expire(this.streamKey, this.ttl);\n\n // 同时推送到 List(用于 getAll)\n await this.redis.rPush(this.listKey, serializedData);\n await this.redis.expire(this.listKey, this.ttl);\n\n this.emit('dataChange', dataString);\n }\n\n /**\n * 异步生成器:使用 Redis Streams XREAD 轮询消费队列数据\n */\n async *onDataReceive(): AsyncGenerator<EventMessage, void, unknown> {\n let isStreamEnded = false;\n\n // 检查是否已取消\n if (this.cancelSignal.signal.aborted) {\n return;\n }\n\n // 监听取消信号\n const abortHandler = () => {\n isStreamEnded = true;\n };\n this.cancelSignal.signal.addEventListener('abort', abortHandler);\n\n try {\n while (!isStreamEnded && !this.cancelSignal.signal.aborted) {\n // 从 Stream 读取新消息(XREAD 阻塞读取)\n const streams = await this.redis.xRead([{ key: this.streamKey, id: this.lastStreamId }], {\n BLOCK: this.pollInterval,\n COUNT: 10,\n });\n\n if (streams && streams.length > 0) {\n for (const stream of streams) {\n for (const message of stream.messages) {\n // 更新最后读取的 ID\n this.lastStreamId = message.id;\n\n // 解析消息:从 base64 字符串转换回 Uint8Array\n const dataString = message.message.data as string;\n const data = Buffer.from(dataString, 'base64');\n const item = (await this.decodeData(data)) as EventMessage;\n\n // 检查是否为流结束或错误信号\n if (\n item.event === '__stream_end__' ||\n item.event === '__stream_error__' ||\n item.event === '__stream_cancel__'\n ) {\n // 延迟 300ms 后结束,确保消息被消费\n await new Promise((resolve) => setTimeout(resolve, 300));\n isStreamEnded = true;\n\n if (item.event === '__stream_cancel__') {\n await this.cancel();\n }\n }\n\n yield item;\n\n if (isStreamEnded) {\n break;\n }\n }\n if (isStreamEnded) {\n break;\n }\n }\n }\n\n // 轮询间隔\n if (!isStreamEnded && !this.cancelSignal.signal.aborted) {\n await new Promise((resolve) => setTimeout(resolve, this.pollInterval));\n }\n }\n } finally {\n this.cancelSignal.signal.removeEventListener('abort', abortHandler);\n }\n }\n\n /**\n * 获取队列中的所有数据(从 List 获取历史数据)\n */\n async getAll(): Promise<EventMessage[]> {\n const data = await this.redis.lRange(this.listKey, 0, -1);\n\n if (!data || data.length === 0) {\n return [];\n }\n\n if (this.compressMessages) {\n return (await Promise.all(\n data.map((item: Buffer | string) => {\n // 处理 Buffer 或字符串类型\n const buffer = typeof item === 'string' ? Buffer.from(item, 'binary') : item;\n return this.decodeData(buffer);\n }),\n )) as EventMessage[];\n } else {\n return data.map((item: string) => JSON.parse(item) as EventMessage);\n }\n }\n\n /**\n * 清空队列\n */\n clear(): void {\n if (this.isConnected) {\n // 同时清空 Stream 和 List\n this.redis.del(this.streamKey);\n this.redis.del(this.listKey);\n }\n }\n\n /**\n * 取消操作\n */\n async cancel(): Promise<void> {\n // First abort to stop any waiting generators\n this.cancelSignal.abort('user cancel this run');\n // Then push the cancel message to signal other consumers\n await this.push(new CancelEventMessage());\n }\n\n /**\n * 复制队列到另一个队列\n */\n async copyToQueue(toId: string, ttl?: number): Promise<RedisStreamQueue> {\n const queue = new RedisStreamQueue(toId, this.compressMessages, ttl ?? this.ttl);\n\n // 复制 List\n await this.redis.copy(this.listKey, queue.listKey);\n await this.redis.expire(queue.listKey, ttl ?? this.ttl);\n\n // 复制 Stream(需要遍历并重新添加)\n const allStreamData = await this.redis.xRange(this.streamKey, '-', '+');\n if (allStreamData && allStreamData.length > 0) {\n for (const message of allStreamData) {\n // 确保所有值都是字符串,Redis Streams 只支持 string 值\n const fields: Record<string, string> = {};\n for (const [key, value] of Object.entries(message.message)) {\n fields[key] = String(value);\n }\n await this.redis.xAdd(queue.streamKey, '*', fields);\n }\n await this.redis.expire(queue.streamKey, ttl ?? this.ttl);\n }\n\n return queue;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"queue-8-m4OzOj.js","sources":["../src/storage/redis/queue.ts"],"sourcesContent":["import { CancelEventMessage, EventMessage } from '../../queue/event_message.js';\nimport { BaseStreamQueue } from '../../queue/stream_queue.js';\nimport { BaseStreamQueueInterface } from '../../queue/stream_queue.js';\nimport { createClient, RedisClientType } from 'redis';\n\n/**\n * Redis Stream 实现的消息队列,用于存储消息\n * 使用 Redis Streams 替代 pub/sub,支持集群模式\n */\nexport class RedisStreamQueue extends BaseStreamQueue implements BaseStreamQueueInterface {\n private redis: RedisClientType;\n private streamKey: string;\n private listKey: string;\n private isConnected = false;\n public cancelSignal: AbortController;\n private lastStreamId: string = '0'; // 最后读取的 Stream ID\n private pollInterval: number = 100; // 轮询间隔(毫秒)\n\n constructor(readonly id: string, readonly compressMessages: boolean = true, readonly ttl: number = 300) {\n super(id, true, ttl);\n this.streamKey = `stream:${this.id}`;\n this.listKey = `queue:${this.id}`;\n this.redis = createClient({\n url: process.env.REDIS_URL,\n });\n this.cancelSignal = new AbortController();\n\n // 连接 Redis 客户端(检查是否已经连接)\n if (!this.redis.isOpen) {\n this.redis.connect();\n }\n this.isConnected = true;\n }\n\n /**\n * 推送消息到 Redis Stream 和 List\n * - Stream: 用于实时推送(集群友好)\n * - List: 用于 getAll() 批量获取历史数据\n */\n async push(item: EventMessage): Promise<void> {\n const encodedData = await this.encodeData(item);\n // 将 Uint8Array 转换为 base64 字符串,以便存储到 Redis Stream\n const dataString = Buffer.from(encodedData).toString('base64');\n const serializedData = Buffer.from(encodedData);\n\n // 推送到 Stream(实时推送)\n // 注意:xAdd 的第三个参数必须是简单的键值对对象,值必须是字符串\n await this.redis.xAdd(this.streamKey, '*', { data: dataString });\n\n // 设置 Stream TTL\n await this.redis.expire(this.streamKey, this.ttl);\n\n // 同时推送到 List(用于 getAll)\n await this.redis.rPush(this.listKey, serializedData);\n await this.redis.expire(this.listKey, this.ttl);\n\n this.emit('dataChange', dataString);\n }\n\n /**\n * 异步生成器:使用 Redis Streams XREAD 轮询消费队列数据\n */\n async *onDataReceive(): AsyncGenerator<EventMessage, void, unknown> {\n let isStreamEnded = false;\n\n // 检查是否已取消\n if (this.cancelSignal.signal.aborted) {\n return;\n }\n\n // 监听取消信号\n const abortHandler = () => {\n isStreamEnded = true;\n };\n this.cancelSignal.signal.addEventListener('abort', abortHandler);\n\n try {\n while (!isStreamEnded && !this.cancelSignal.signal.aborted) {\n // 从 Stream 读取新消息(XREAD 阻塞读取)\n const streams = await this.redis.xRead([{ key: this.streamKey, id: this.lastStreamId }], {\n BLOCK: this.pollInterval,\n COUNT: 10,\n });\n\n if (streams && streams.length > 0) {\n for (const stream of streams) {\n for (const message of stream.messages) {\n // 更新最后读取的 ID\n this.lastStreamId = message.id;\n\n // 解析消息:从 base64 字符串转换回 Uint8Array\n const dataString = message.message.data as string;\n const data = Buffer.from(dataString, 'base64');\n const item = (await this.decodeData(data)) as EventMessage;\n\n // 检查是否为流结束或错误信号\n if (\n item.event === '__stream_end__' ||\n item.event === '__stream_error__' ||\n item.event === '__stream_cancel__'\n ) {\n // 延迟 300ms 后结束,确保消息被消费\n await new Promise((resolve) => setTimeout(resolve, 300));\n isStreamEnded = true;\n\n if (item.event === '__stream_cancel__') {\n await this.cancel();\n }\n }\n\n yield item;\n\n if (isStreamEnded) {\n break;\n }\n }\n if (isStreamEnded) {\n break;\n }\n }\n }\n\n // 轮询间隔\n if (!isStreamEnded && !this.cancelSignal.signal.aborted) {\n await new Promise((resolve) => setTimeout(resolve, this.pollInterval));\n }\n }\n } finally {\n this.cancelSignal.signal.removeEventListener('abort', abortHandler);\n }\n }\n\n /**\n * 获取队列中的所有数据(从 List 获取历史数据)\n */\n async getAll(): Promise<EventMessage[]> {\n const data = await this.redis.lRange(this.listKey, 0, -1);\n\n if (!data || data.length === 0) {\n return [];\n }\n\n if (this.compressMessages) {\n return (await Promise.all(\n data.map((item: Buffer | string) => {\n // 处理 Buffer 或字符串类型\n const buffer = typeof item === 'string' ? Buffer.from(item, 'binary') : item;\n return this.decodeData(buffer);\n }),\n )) as EventMessage[];\n } else {\n return data.map((item: string) => JSON.parse(item) as EventMessage);\n }\n }\n\n /**\n * 清空队列\n */\n clear(): void {\n if (this.isConnected) {\n // 同时清空 Stream 和 List\n this.redis.del(this.streamKey);\n this.redis.del(this.listKey);\n }\n }\n\n /**\n * 取消操作\n */\n async cancel(): Promise<void> {\n // First abort to stop any waiting generators\n this.cancelSignal.abort('user cancel this run');\n // Then push the cancel message to signal other consumers\n await this.push(new CancelEventMessage());\n }\n\n /**\n * 复制队列到另一个队列\n */\n async copyToQueue(toId: string, ttl?: number): Promise<RedisStreamQueue> {\n const queue = new RedisStreamQueue(toId, this.compressMessages, ttl ?? this.ttl);\n\n // 复制 List\n await this.redis.copy(this.listKey, queue.listKey);\n await this.redis.expire(queue.listKey, ttl ?? this.ttl);\n\n // 复制 Stream(需要遍历并重新添加)\n const allStreamData = await this.redis.xRange(this.streamKey, '-', '+');\n if (allStreamData && allStreamData.length > 0) {\n for (const message of allStreamData) {\n // 确保所有值都是字符串,Redis Streams 只支持 string 值\n const fields: Record<string, string> = {};\n for (const [key, value] of Object.entries(message.message)) {\n fields[key] = String(value);\n }\n await this.redis.xAdd(queue.streamKey, '*', fields);\n }\n await this.redis.expire(queue.streamKey, ttl ?? this.ttl);\n }\n\n return queue;\n }\n}\n"],"names":[],"mappings":"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"}
|
package/dist/remote/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
2
|
import { PostgresAdapter } from '../pg-adapter-BFtir1GE.js';
|
|
3
|
-
import { K as KyselyThreadsManager } from '../stream-
|
|
3
|
+
import { K as KyselyThreadsManager } from '../stream-3xunCZso.js';
|
|
4
4
|
import { Pool } from 'pg';
|
|
5
5
|
|
|
6
6
|
class RemoteServer {
|
|
@@ -25,9 +25,13 @@ class SQLiteAdapter {
|
|
|
25
25
|
return dbValue;
|
|
26
26
|
}
|
|
27
27
|
buildJsonQuery(db, field, key, value) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
const jsonString = JSON.stringify(value);
|
|
29
|
+
return sql`(
|
|
30
|
+
json_extract(${sql.ref(field)}, ${sql.lit("$." + key)}) = ${sql.lit(jsonString)}
|
|
31
|
+
) OR (
|
|
32
|
+
json_extract(${sql.ref(field)}, ${sql.lit("$." + key)}) IS NULL
|
|
33
|
+
AND ${sql.lit(jsonString)} IS NULL
|
|
34
|
+
)`;
|
|
31
35
|
}
|
|
32
36
|
now() {
|
|
33
37
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -68,4 +72,4 @@ class SQLiteAdapter {
|
|
|
68
72
|
}
|
|
69
73
|
|
|
70
74
|
export { SQLiteAdapter };
|
|
71
|
-
//# sourceMappingURL=sqlite-adapter-
|
|
75
|
+
//# sourceMappingURL=sqlite-adapter-Bbonr5S5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-adapter-Bbonr5S5.js","sources":["../src/storage/kysely/sqlite-adapter.ts"],"sourcesContent":["import { Kysely, sql, SqlBool, Expression, SqliteDialect } from 'kysely';\nimport { DatabaseAdapter } from './adapter';\nimport { Database } from './types';\n\n/**\n * SQLite 适配器\n * - 时间类型:TEXT (ISO 8601 字符串)\n * - JSON 类型:TEXT\n * - JSON 查询:使用 json_extract 函数\n */\nexport class SQLiteAdapter implements DatabaseAdapter {\n db: Kysely<Database>;\n constructor(database: Kysely<any>) {\n this.db = database;\n }\n dateToDb(date: Date): string {\n // SQLite 存储为 ISO 8601 字符串\n return date.toISOString();\n }\n\n dbToDate(dbValue: any): Date {\n // SQLite 返回字符串,需要转换为 Date\n return new Date(dbValue);\n }\n\n jsonToDb(obj: any): string {\n // SQLite 存储为 JSON 字符串\n return JSON.stringify(obj);\n }\n\n dbToJson(dbValue: any): any {\n // SQLite 返回字符串,需要解析\n if (typeof dbValue === 'string') {\n try {\n return JSON.parse(dbValue);\n } catch {\n return dbValue;\n }\n }\n return dbValue;\n }\n\n buildJsonQuery(\n db: Kysely<Database>,\n field: 'metadata' | 'interrupts',\n key: string,\n value: any,\n ): Expression<SqlBool> {\n const jsonString = JSON.stringify(value);\n \n // 改进的 JSON 查询,添加 NULL 值处理\n // json_extract 会返回 NULL 当键不存在或值为 NULL\n return sql<boolean>`(\n json_extract(${sql.ref(field)}, ${sql.lit('$.' + key)}) = ${sql.lit(jsonString)}\n ) OR (\n json_extract(${sql.ref(field)}, ${sql.lit('$.' + key)}) IS NULL\n AND ${sql.lit(jsonString)} IS NULL\n )`;\n }\n\n now(): string {\n return new Date().toISOString();\n }\n\n async createTables(db: Kysely<Database>): Promise<void> {\n // 创建 threads 表\n await sql`\n CREATE TABLE IF NOT EXISTS threads (\n thread_id TEXT PRIMARY KEY,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n metadata TEXT NOT NULL DEFAULT '{}',\n status TEXT NOT NULL DEFAULT 'idle',\n \"values\" TEXT,\n interrupts TEXT NOT NULL DEFAULT '{}'\n )\n `.execute(db);\n\n // 创建 runs 表\n await sql`\n CREATE TABLE IF NOT EXISTS runs (\n run_id TEXT PRIMARY KEY,\n thread_id TEXT NOT NULL,\n assistant_id TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'pending',\n metadata TEXT NOT NULL DEFAULT '{}',\n multitask_strategy TEXT NOT NULL DEFAULT 'reject',\n FOREIGN KEY (thread_id) REFERENCES threads(thread_id) ON DELETE CASCADE\n )\n `.execute(db);\n }\n\n async createIndexes(db: Kysely<Database>): Promise<void> {\n await sql`CREATE INDEX IF NOT EXISTS idx_threads_status ON threads(status)`.execute(db);\n await sql`CREATE INDEX IF NOT EXISTS idx_threads_created_at ON threads(created_at)`.execute(db);\n await sql`CREATE INDEX IF NOT EXISTS idx_threads_updated_at ON threads(updated_at)`.execute(db);\n await sql`CREATE INDEX IF NOT EXISTS idx_runs_thread_id ON runs(thread_id)`.execute(db);\n await sql`CREATE INDEX IF NOT EXISTS idx_runs_status ON runs(status)`.execute(db);\n }\n}\n"],"names":[],"mappings":";;AAUO,MAAM,aAAA,CAAyC;AAAA,EAClD,EAAA;AAAA,EACA,YAAY,QAAA,EAAuB;AAC/B,IAAA,IAAA,CAAK,EAAA,GAAK,QAAA;AAAA,EACd;AAAA,EACA,SAAS,IAAA,EAAoB;AAEzB,IAAA,OAAO,KAAK,WAAA,EAAY;AAAA,EAC5B;AAAA,EAEA,SAAS,OAAA,EAAoB;AAEzB,IAAA,OAAO,IAAI,KAAK,OAAO,CAAA;AAAA,EAC3B;AAAA,EAEA,SAAS,GAAA,EAAkB;AAEvB,IAAA,OAAO,IAAA,CAAK,UAAU,GAAG,CAAA;AAAA,EAC7B;AAAA,EAEA,SAAS,OAAA,EAAmB;AAExB,IAAA,IAAI,OAAO,YAAY,QAAA,EAAU;AAC7B,MAAA,IAAI;AACA,QAAA,OAAO,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,MAC7B,CAAA,CAAA,MAAQ;AACJ,QAAA,OAAO,OAAA;AAAA,MACX;AAAA,IACJ;AACA,IAAA,OAAO,OAAA;AAAA,EACX;AAAA,EAEA,cAAA,CACI,EAAA,EACA,KAAA,EACA,GAAA,EACA,KAAA,EACmB;AACnB,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA;AAIvC,IAAA,OAAO,GAAA,CAAA;AAAA,yBAAA,EACY,GAAA,CAAI,GAAA,CAAI,KAAK,CAAC,KAAK,GAAA,CAAI,GAAA,CAAI,IAAA,GAAO,GAAG,CAAC,CAAA,IAAA,EAAO,GAAA,CAAI,GAAA,CAAI,UAAU,CAAC;AAAA;AAAA,yBAAA,EAEhE,GAAA,CAAI,IAAI,KAAK,CAAC,KAAK,GAAA,CAAI,GAAA,CAAI,IAAA,GAAO,GAAG,CAAC,CAAA;AAAA,gBAAA,EAC/C,GAAA,CAAI,GAAA,CAAI,UAAU,CAAC,CAAA;AAAA,SAAA,CAAA;AAAA,EAEjC;AAAA,EAEA,GAAA,GAAc;AACV,IAAA,OAAA,iBAAO,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,EAClC;AAAA,EAEA,MAAM,aAAa,EAAA,EAAqC;AAEpD,IAAA,MAAM,GAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA,CAUJ,QAAQ,EAAE,CAAA;AAGZ,IAAA,MAAM,GAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA,CAYJ,QAAQ,EAAE,CAAA;AAAA,EAChB;AAAA,EAEA,MAAM,cAAc,EAAA,EAAqC;AACrD,IAAA,MAAM,GAAA,CAAA,gEAAA,CAAA,CAAsE,QAAQ,EAAE,CAAA;AACtF,IAAA,MAAM,GAAA,CAAA,wEAAA,CAAA,CAA8E,QAAQ,EAAE,CAAA;AAC9F,IAAA,MAAM,GAAA,CAAA,wEAAA,CAAA,CAA8E,QAAQ,EAAE,CAAA;AAC9F,IAAA,MAAM,GAAA,CAAA,gEAAA,CAAA,CAAsE,QAAQ,EAAE,CAAA;AACtF,IAAA,MAAM,GAAA,CAAA,0DAAA,CAAA,CAAgE,QAAQ,EAAE,CAAA;AAAA,EACpF;AACJ;;;;"}
|
package/dist/storage/index.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { BaseStreamQueueInterface, StreamQueueManager } from '../queue/stream_queue';
|
|
2
2
|
import { KyselyThreadsManager } from './kysely/threads';
|
|
3
|
-
import {
|
|
3
|
+
import { ShallowMemorySaver } from './memory/shallow-memory';
|
|
4
4
|
import { MemoryThreadsManager } from './memory/threads';
|
|
5
5
|
import type { SqliteSaver as SqliteSaverType } from './sqlite/checkpoint';
|
|
6
6
|
import type { PostgresSaver } from '@langchain/langgraph-checkpoint-postgres';
|
|
7
|
-
export
|
|
7
|
+
export { ShallowMemorySaver } from './memory/shallow-memory';
|
|
8
|
+
export { MemorySaver } from './memory/checkpoint';
|
|
9
|
+
export declare const createCheckPointer: () => Promise<ShallowMemorySaver | SqliteSaverType | PostgresSaver | import("@langchain/langgraph-checkpoint-redis").RedisSaver | import("@langchain/langgraph-checkpoint-redis/shallow").ShallowRedisSaver>;
|
|
8
10
|
export declare const createMessageQueue: () => Promise<StreamQueueManager<BaseStreamQueueInterface>>;
|
|
9
11
|
export declare const createThreadManager: (config: {
|
|
10
12
|
checkpointer?: SqliteSaverType | PostgresSaver;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { RunnableConfig } from '@langchain/core/runnables';
|
|
2
|
+
import { BaseCheckpointSaver, ChannelVersions, Checkpoint, CheckpointListOptions, CheckpointTuple } from '@langchain/langgraph-checkpoint';
|
|
3
|
+
import { SerializerProtocol } from '@langchain/langgraph-checkpoint';
|
|
4
|
+
import { CheckpointMetadata, PendingWrite } from '@langchain/langgraph-checkpoint';
|
|
5
|
+
type CheckPointType = {
|
|
6
|
+
checkpoint: Uint8Array;
|
|
7
|
+
metadata: Uint8Array;
|
|
8
|
+
checkpoint_id: string;
|
|
9
|
+
parent_checkpoint_id: string | undefined;
|
|
10
|
+
checkpoint_ts: number;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* ShallowMemorySaver - A memory checkpoint saver that only keeps the latest checkpoint per thread/namespace.
|
|
14
|
+
*
|
|
15
|
+
* This is a memory-optimized variant that:
|
|
16
|
+
* - Only stores the most recent checkpoint for each thread/namespace combination
|
|
17
|
+
* - Automatically cleans up old writes when new checkpoint is added
|
|
18
|
+
* - Reduces memory usage for applications that don't need checkpoint history
|
|
19
|
+
* - Provides the same API as MemorySaver for seamless replacement
|
|
20
|
+
*/
|
|
21
|
+
export declare class ShallowMemorySaver extends BaseCheckpointSaver {
|
|
22
|
+
storage: Record<string, Record<string, CheckPointType>>;
|
|
23
|
+
writes: Record<string, Record<string, [string, string, Uint8Array]>>;
|
|
24
|
+
constructor(serde?: SerializerProtocol);
|
|
25
|
+
/**
|
|
26
|
+
* Get just the checkpoint without metadata
|
|
27
|
+
* Convenience method matching ShallowRedisSaver API
|
|
28
|
+
*/
|
|
29
|
+
get(config: RunnableConfig): Promise<Checkpoint | undefined>;
|
|
30
|
+
/**
|
|
31
|
+
* Migrate pending sends for checkpoints with version < 4
|
|
32
|
+
* @internal
|
|
33
|
+
*/
|
|
34
|
+
_migratePendingSends(mutableCheckpoint: Checkpoint, threadId: string, checkpointNs: string, parentCheckpointId: string): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Load pending writes for a specific checkpoint
|
|
37
|
+
*/
|
|
38
|
+
private _loadPendingWrites;
|
|
39
|
+
/**
|
|
40
|
+
* Clean up old writes for a checkpoint
|
|
41
|
+
*/
|
|
42
|
+
private _cleanupOldWrites;
|
|
43
|
+
/**
|
|
44
|
+
* Check metadata filter matches (with deep comparison support)
|
|
45
|
+
* Matches ShallowRedisSaver behavior
|
|
46
|
+
*/
|
|
47
|
+
private _checkMetadataFilterMatch;
|
|
48
|
+
getTuple(config: RunnableConfig): Promise<CheckpointTuple | undefined>;
|
|
49
|
+
list(config: RunnableConfig, options?: CheckpointListOptions): AsyncGenerator<CheckpointTuple>;
|
|
50
|
+
put(config: RunnableConfig, checkpoint: Checkpoint, metadata: CheckpointMetadata, _newVersions?: ChannelVersions): Promise<RunnableConfig>;
|
|
51
|
+
putWrites(config: RunnableConfig, writes: PendingWrite[], taskId: string): Promise<void>;
|
|
52
|
+
deleteThread(threadId: string): Promise<void>;
|
|
53
|
+
}
|
|
54
|
+
export {};
|