@langgraph-js/pure-graph 2.8.0 → 2.10.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.
- package/dist/adapter/fetch/index.js +2 -2
- package/dist/adapter/nextjs/index.js +1 -1
- package/dist/agents/ask_subagents.d.ts +32 -0
- package/dist/agents/index.d.ts +1 -0
- package/dist/{checkpoint-S8bA03zo.js → checkpoint-1sAx_j1E.js} +2 -2
- package/dist/checkpoint-1sAx_j1E.js.map +1 -0
- package/dist/{createEndpoint-u2dnG_xt.js → createEndpoint-CN_RHDEd.js} +3 -3
- package/dist/createEndpoint-CN_RHDEd.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +75 -17
- package/dist/index.js.map +1 -1
- package/dist/queue/stream_queue.d.ts +2 -2
- package/dist/{queue-kaJOJdKs.js → queue-D6tEGCGs.js} +18 -6
- package/dist/queue-D6tEGCGs.js.map +1 -0
- package/dist/storage/memory/queue.d.ts +1 -1
- package/dist/storage/redis/queue.d.ts +1 -1
- package/dist/{stream-BkrtqGvX.js → stream-D0YD2Pjq.js} +22 -10
- package/dist/stream-D0YD2Pjq.js.map +1 -0
- package/package.json +3 -3
- package/dist/checkpoint-S8bA03zo.js.map +0 -1
- package/dist/createEndpoint-u2dnG_xt.js.map +0 -1
- package/dist/queue-kaJOJdKs.js.map +0 -1
- package/dist/stream-BkrtqGvX.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { s as serialiseAsDict, L as LangGraphGlobal } from '../../stream-
|
|
2
|
-
import { c as createEndpoint } from '../../createEndpoint-
|
|
1
|
+
import { s as serialiseAsDict, L as LangGraphGlobal } from '../../stream-D0YD2Pjq.js';
|
|
2
|
+
import { c as createEndpoint } from '../../createEndpoint-CN_RHDEd.js';
|
|
3
3
|
import z from 'zod';
|
|
4
4
|
import camelcaseKeys from 'camelcase-keys';
|
|
5
5
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Command } from '@langchain/langgraph';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
export declare const SubAgentStateSchema: z.ZodObject<{
|
|
4
|
+
task_store: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
5
|
+
}, z.core.$strip>;
|
|
6
|
+
declare const schema: z.ZodObject<{
|
|
7
|
+
task_id: z.ZodOptional<z.ZodString>;
|
|
8
|
+
subagent_id: z.ZodString;
|
|
9
|
+
task_description: z.ZodString;
|
|
10
|
+
data_transfer: z.ZodOptional<z.ZodAny>;
|
|
11
|
+
}, z.core.$strip>;
|
|
12
|
+
export declare const ask_subagents: (agentCreator: (task_id: string, args: z.infer<typeof schema>, parent_state: any) => Promise<any>, options?: {
|
|
13
|
+
name?: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
pass_through_keys?: string[];
|
|
16
|
+
}) => import("langchain").DynamicStructuredTool<z.ZodObject<{
|
|
17
|
+
task_id: z.ZodOptional<z.ZodString>;
|
|
18
|
+
subagent_id: z.ZodString;
|
|
19
|
+
task_description: z.ZodString;
|
|
20
|
+
data_transfer: z.ZodOptional<z.ZodAny>;
|
|
21
|
+
}, z.core.$strip>, {
|
|
22
|
+
subagent_id: string;
|
|
23
|
+
task_description: string;
|
|
24
|
+
task_id?: string | undefined;
|
|
25
|
+
data_transfer?: any;
|
|
26
|
+
}, {
|
|
27
|
+
subagent_id: string;
|
|
28
|
+
task_description: string;
|
|
29
|
+
task_id?: string | undefined;
|
|
30
|
+
data_transfer?: any;
|
|
31
|
+
}, Command<unknown, any, string>>;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ask_subagents';
|
|
@@ -20,7 +20,7 @@ class SqliteSaver extends BaseCheckpointSaver {
|
|
|
20
20
|
}
|
|
21
21
|
static async fromConnStringAsync(connStringOrLocalPath) {
|
|
22
22
|
let saver;
|
|
23
|
-
if (
|
|
23
|
+
if (globalThis.Bun) {
|
|
24
24
|
console.log("LG | Using BunWorkerDialect " + connStringOrLocalPath);
|
|
25
25
|
const { BunWorkerDialect } = await import('kysely-bun-worker');
|
|
26
26
|
saver = new SqliteSaver(new BunWorkerDialect({ url: connStringOrLocalPath }));
|
|
@@ -381,4 +381,4 @@ CREATE TABLE IF NOT EXISTS writes (
|
|
|
381
381
|
}
|
|
382
382
|
|
|
383
383
|
export { SqliteSaver };
|
|
384
|
-
//# sourceMappingURL=checkpoint-
|
|
384
|
+
//# sourceMappingURL=checkpoint-1sAx_j1E.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkpoint-1sAx_j1E.js","sources":["../src/storage/sqlite/checkpoint.ts"],"sourcesContent":["import { Dialect, Kysely, SqliteDialect, sql } from 'kysely';\nimport type { RunnableConfig } from '@langchain/core/runnables';\n\nimport {\n BaseCheckpointSaver,\n type Checkpoint,\n type CheckpointListOptions,\n type CheckpointTuple,\n type SerializerProtocol,\n type PendingWrite,\n type CheckpointMetadata,\n TASKS,\n copyCheckpoint,\n maxChannelVersion,\n} from '@langchain/langgraph-checkpoint';\n\n// Kysely 数据库表类型定义\ninterface CheckpointsTable {\n thread_id: string;\n checkpoint_ns: string;\n checkpoint_id: string;\n parent_checkpoint_id: string | null;\n type: string | null;\n checkpoint: Uint8Array;\n metadata: Uint8Array;\n}\n\ninterface WritesTable {\n thread_id: string;\n checkpoint_ns: string;\n checkpoint_id: string;\n task_id: string;\n idx: number;\n channel: string;\n type: string | null;\n value: Uint8Array | null;\n}\n\ninterface CheckpointDatabase {\n checkpoints: CheckpointsTable;\n writes: WritesTable;\n}\n\ninterface CheckpointRow {\n checkpoint: string;\n metadata: string;\n parent_checkpoint_id?: string;\n thread_id: string;\n checkpoint_id: string;\n checkpoint_ns?: string;\n type?: string;\n pending_writes: string;\n}\n\ninterface PendingWriteColumn {\n task_id: string;\n channel: string;\n type: string;\n value: string;\n}\n\ninterface PendingSendColumn {\n type: string;\n value: string;\n}\n\n// In the `SqliteSaver.list` method, we need to sanitize the `options.filter` argument to ensure it only contains keys\n// that are part of the `CheckpointMetadata` type. The lines below ensure that we get compile-time errors if the list\n// of keys that we use is out of sync with the `CheckpointMetadata` type.\nconst checkpointMetadataKeys = ['source', 'step', 'parents'] as const;\n\ntype CheckKeys<T, K extends readonly (keyof T)[]> = [K[number]] extends [keyof T]\n ? [keyof T] extends [K[number]]\n ? K\n : never\n : never;\n\nfunction validateKeys<T, K extends readonly (keyof T)[]>(keys: CheckKeys<T, K>): K {\n return keys;\n}\n\n// If this line fails to compile, the list of keys that we use in the `SqliteSaver.list` method is out of sync with the\n// `CheckpointMetadata` type. In that case, just update `checkpointMetadataKeys` to contain all the keys in\n// `CheckpointMetadata`\nconst validCheckpointMetadataKeys = validateKeys<CheckpointMetadata, typeof checkpointMetadataKeys>(\n checkpointMetadataKeys,\n);\n\nexport class SqliteSaver extends BaseCheckpointSaver {\n db: Kysely<CheckpointDatabase>;\n\n protected isSetup: boolean;\n\n constructor(dialect: Dialect, serde?: SerializerProtocol) {\n super(serde);\n this.db = new Kysely<CheckpointDatabase>({\n dialect,\n });\n this.isSetup = false;\n }\n\n static async fromConnStringAsync(connStringOrLocalPath: string): Promise<SqliteSaver> {\n let saver: SqliteSaver;\n /** @ts-ignore */\n if (globalThis.Bun) {\n console.log('LG | Using BunWorkerDialect ' + connStringOrLocalPath);\n const { BunWorkerDialect } = await import('kysely-bun-worker');\n saver = new SqliteSaver(new BunWorkerDialect({ url: connStringOrLocalPath }));\n } else {\n /** @ts-ignore */\n console.log('LG | Using NodeWasmDialect');\n const { default: SqliteDatabase } = await import('node-sqlite3-wasm');\n const { NodeWasmDialect } = await import('kysely-wasm');\n console.log(connStringOrLocalPath);\n const wasm = new NodeWasmDialect({\n database: new SqliteDatabase.Database(connStringOrLocalPath),\n });\n saver = new SqliteSaver(wasm);\n }\n await saver.setup();\n return saver;\n }\n\n protected async setup(): Promise<void> {\n if (this.isSetup) {\n return;\n }\n\n await sql`PRAGMA journal_mode = WAL`.execute(this.db);\n\n await sql`\nCREATE TABLE IF NOT EXISTS checkpoints (\n thread_id TEXT NOT NULL,\n checkpoint_ns TEXT NOT NULL DEFAULT '',\n checkpoint_id TEXT NOT NULL,\n parent_checkpoint_id TEXT,\n type TEXT,\n checkpoint BLOB,\n metadata BLOB,\n PRIMARY KEY (thread_id, checkpoint_ns, checkpoint_id)\n)`.execute(this.db);\n\n await sql`\nCREATE TABLE IF NOT EXISTS writes (\n thread_id TEXT NOT NULL,\n checkpoint_ns TEXT NOT NULL DEFAULT '',\n checkpoint_id TEXT NOT NULL,\n task_id TEXT NOT NULL,\n idx INTEGER NOT NULL,\n channel TEXT NOT NULL,\n type TEXT,\n value BLOB,\n PRIMARY KEY (thread_id, checkpoint_ns, checkpoint_id, task_id, idx)\n)`.execute(this.db);\n this.isSetup = true;\n }\n\n async getTuple(config: RunnableConfig): Promise<CheckpointTuple | undefined> {\n await this.setup();\n const { thread_id, checkpoint_ns = '', checkpoint_id } = config.configurable ?? {};\n\n let query = this.db\n .selectFrom('checkpoints')\n .select([\n 'thread_id',\n 'checkpoint_ns',\n 'checkpoint_id',\n 'parent_checkpoint_id',\n 'type',\n 'checkpoint',\n 'metadata',\n sql<string>`(\n SELECT json_group_array(\n json_object(\n 'task_id', pw.task_id,\n 'channel', pw.channel,\n 'type', pw.type,\n 'value', CAST(pw.value AS TEXT)\n )\n )\n FROM writes as pw\n WHERE pw.thread_id = checkpoints.thread_id\n AND pw.checkpoint_ns = checkpoints.checkpoint_ns\n AND pw.checkpoint_id = checkpoints.checkpoint_id\n )`.as('pending_writes'),\n sql<string>`(\n SELECT json_group_array(\n json_object(\n 'type', ps.type,\n 'value', CAST(ps.value AS TEXT)\n )\n )\n FROM writes as ps\n WHERE ps.thread_id = checkpoints.thread_id\n AND ps.checkpoint_ns = checkpoints.checkpoint_ns\n AND ps.checkpoint_id = checkpoints.parent_checkpoint_id\n AND ps.channel = ${TASKS}\n ORDER BY ps.idx\n )`.as('pending_sends'),\n ])\n .where('thread_id', '=', thread_id)\n .where('checkpoint_ns', '=', checkpoint_ns);\n\n if (checkpoint_id) {\n query = query.where('checkpoint_id', '=', checkpoint_id);\n } else {\n query = query.orderBy('checkpoint_id', 'desc').limit(1);\n }\n\n const row = await query.executeTakeFirst();\n if (!row) return undefined;\n\n let finalConfig = config;\n\n if (!checkpoint_id) {\n finalConfig = {\n configurable: {\n thread_id: row.thread_id,\n checkpoint_ns,\n checkpoint_id: row.checkpoint_id,\n },\n };\n }\n\n if (\n finalConfig.configurable?.thread_id === undefined ||\n finalConfig.configurable?.checkpoint_id === undefined\n ) {\n throw new Error('Missing thread_id or checkpoint_id');\n }\n\n const pendingWrites = await Promise.all(\n (JSON.parse(row.pending_writes) as PendingWriteColumn[]).map(async (write) => {\n return [\n write.task_id,\n write.channel,\n await this.serde.loadsTyped(write.type ?? 'json', write.value ?? ''),\n ] as [string, string, unknown];\n }),\n );\n\n const checkpoint = (await this.serde.loadsTyped(\n row.type ?? 'json',\n new TextDecoder().decode(row.checkpoint),\n )) as Checkpoint;\n\n if (checkpoint.v < 4 && row.parent_checkpoint_id != null) {\n await this.migratePendingSends(checkpoint, row.thread_id, row.parent_checkpoint_id);\n }\n\n return {\n checkpoint,\n config: finalConfig,\n metadata: (await this.serde.loadsTyped(\n row.type ?? 'json',\n new TextDecoder().decode(row.metadata),\n )) as CheckpointMetadata,\n parentConfig: row.parent_checkpoint_id\n ? {\n configurable: {\n thread_id: row.thread_id,\n checkpoint_ns,\n checkpoint_id: row.parent_checkpoint_id,\n },\n }\n : undefined,\n pendingWrites,\n };\n }\n\n async *list(config: RunnableConfig, options?: CheckpointListOptions): AsyncGenerator<CheckpointTuple> {\n const { limit, before, filter } = options ?? {};\n await this.setup();\n const thread_id = config.configurable?.thread_id;\n const checkpoint_ns = config.configurable?.checkpoint_ns;\n\n let query = this.db.selectFrom('checkpoints').select([\n 'thread_id',\n 'checkpoint_ns',\n 'checkpoint_id',\n 'parent_checkpoint_id',\n 'type',\n 'checkpoint',\n 'metadata',\n sql<string>`(\n SELECT json_group_array(\n json_object(\n 'task_id', pw.task_id,\n 'channel', pw.channel,\n 'type', pw.type,\n 'value', CAST(pw.value AS TEXT)\n )\n )\n FROM writes as pw\n WHERE pw.thread_id = checkpoints.thread_id\n AND pw.checkpoint_ns = checkpoints.checkpoint_ns\n AND pw.checkpoint_id = checkpoints.checkpoint_id\n )`.as('pending_writes'),\n sql<string>`(\n SELECT json_group_array(\n json_object(\n 'type', ps.type,\n 'value', CAST(ps.value AS TEXT)\n )\n )\n FROM writes as ps\n WHERE ps.thread_id = checkpoints.thread_id\n AND ps.checkpoint_ns = checkpoints.checkpoint_ns\n AND ps.checkpoint_id = checkpoints.parent_checkpoint_id\n AND ps.channel = ${TASKS}\n ORDER BY ps.idx\n )`.as('pending_sends'),\n ]);\n\n if (thread_id) {\n query = query.where('thread_id', '=', thread_id);\n }\n\n if (checkpoint_ns !== undefined && checkpoint_ns !== null) {\n query = query.where('checkpoint_ns', '=', checkpoint_ns);\n }\n\n if (before?.configurable?.checkpoint_id !== undefined) {\n query = query.where('checkpoint_id', '<', before.configurable.checkpoint_id);\n }\n\n const sanitizedFilter = Object.fromEntries(\n Object.entries(filter ?? {}).filter(\n ([key, value]) =>\n value !== undefined && validCheckpointMetadataKeys.includes(key as keyof CheckpointMetadata),\n ),\n );\n\n for (const [key, value] of Object.entries(sanitizedFilter)) {\n query = query.where(\n sql`json_extract(CAST(metadata AS TEXT), ${sql.lit('$.' + key)})`,\n '=',\n sql.lit(JSON.stringify(value)),\n );\n }\n\n query = query.orderBy('checkpoint_id', 'desc');\n\n if (limit) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n query = query.limit(parseInt(limit as any, 10));\n }\n\n const rows = await query.execute();\n\n for (const row of rows) {\n const pendingWrites = await Promise.all(\n (JSON.parse(row.pending_writes) as PendingWriteColumn[]).map(async (write) => {\n return [\n write.task_id,\n write.channel,\n await this.serde.loadsTyped(write.type ?? 'json', write.value ?? ''),\n ] as [string, string, unknown];\n }),\n );\n\n const checkpoint = (await this.serde.loadsTyped(\n row.type ?? 'json',\n new TextDecoder().decode(row.checkpoint),\n )) as Checkpoint;\n\n if (checkpoint.v < 4 && row.parent_checkpoint_id != null) {\n await this.migratePendingSends(checkpoint, row.thread_id, row.parent_checkpoint_id);\n }\n\n yield {\n config: {\n configurable: {\n thread_id: row.thread_id,\n checkpoint_ns: row.checkpoint_ns,\n checkpoint_id: row.checkpoint_id,\n },\n },\n checkpoint,\n metadata: (await this.serde.loadsTyped(\n row.type ?? 'json',\n new TextDecoder().decode(row.metadata),\n )) as CheckpointMetadata,\n parentConfig: row.parent_checkpoint_id\n ? {\n configurable: {\n thread_id: row.thread_id,\n checkpoint_ns: row.checkpoint_ns,\n checkpoint_id: row.parent_checkpoint_id,\n },\n }\n : undefined,\n pendingWrites,\n };\n }\n }\n\n async put(config: RunnableConfig, checkpoint: Checkpoint, metadata: CheckpointMetadata): Promise<RunnableConfig> {\n await this.setup();\n\n if (!config.configurable) {\n throw new Error('Empty configuration supplied.');\n }\n\n const thread_id = config.configurable?.thread_id;\n const checkpoint_ns = config.configurable?.checkpoint_ns ?? '';\n const parent_checkpoint_id = config.configurable?.checkpoint_id;\n\n if (!thread_id) {\n throw new Error(`Missing \"thread_id\" field in passed \"config.configurable\".`);\n }\n\n const preparedCheckpoint: Partial<Checkpoint> = copyCheckpoint(checkpoint);\n\n const [[type1, serializedCheckpoint], [type2, serializedMetadata]] = await Promise.all([\n this.serde.dumpsTyped(preparedCheckpoint),\n this.serde.dumpsTyped(metadata),\n ]);\n\n if (type1 !== type2) {\n throw new Error('Failed to serialized checkpoint and metadata to the same type.');\n }\n\n await this.db\n .insertInto('checkpoints')\n .values({\n thread_id,\n checkpoint_ns,\n checkpoint_id: checkpoint.id,\n parent_checkpoint_id: parent_checkpoint_id ?? null,\n type: type1,\n checkpoint: new Uint8Array(Buffer.from(serializedCheckpoint)),\n metadata: new Uint8Array(Buffer.from(serializedMetadata)),\n })\n .onConflict((oc) =>\n oc.columns(['thread_id', 'checkpoint_ns', 'checkpoint_id']).doUpdateSet({\n parent_checkpoint_id: parent_checkpoint_id ?? null,\n type: type1,\n checkpoint: new Uint8Array(Buffer.from(serializedCheckpoint)),\n metadata: new Uint8Array(Buffer.from(serializedMetadata)),\n }),\n )\n .execute();\n\n return {\n configurable: {\n thread_id,\n checkpoint_ns,\n checkpoint_id: checkpoint.id,\n },\n };\n }\n\n async putWrites(config: RunnableConfig, writes: PendingWrite[], taskId: string): Promise<void> {\n await this.setup();\n\n if (!config.configurable) {\n throw new Error('Empty configuration supplied.');\n }\n\n if (!config.configurable?.thread_id) {\n throw new Error('Missing thread_id field in config.configurable.');\n }\n\n if (!config.configurable?.checkpoint_id) {\n throw new Error('Missing checkpoint_id field in config.configurable.');\n }\n\n const values = await Promise.all(\n writes.map(async (write, idx) => {\n const [type, serializedWrite] = await this.serde.dumpsTyped(write[1]);\n return {\n thread_id: config.configurable!.thread_id,\n checkpoint_ns: config.configurable!.checkpoint_ns ?? '',\n checkpoint_id: config.configurable!.checkpoint_id,\n task_id: taskId,\n idx,\n channel: write[0],\n type,\n value: new Uint8Array(Buffer.from(serializedWrite)),\n };\n }),\n );\n\n if (values.length > 0) {\n await this.db.transaction().execute(async (trx) => {\n for (const value of values) {\n await trx\n .insertInto('writes')\n .values(value)\n .onConflict((oc) =>\n oc.columns(['thread_id', 'checkpoint_ns', 'checkpoint_id', 'task_id', 'idx']).doUpdateSet({\n channel: value.channel,\n type: value.type,\n value: value.value,\n }),\n )\n .execute();\n }\n });\n }\n }\n\n async deleteThread(threadId: string) {\n await this.db.transaction().execute(async (trx) => {\n await trx.deleteFrom('checkpoints').where('thread_id', '=', threadId).execute();\n await trx.deleteFrom('writes').where('thread_id', '=', threadId).execute();\n });\n }\n\n protected async migratePendingSends(checkpoint: Checkpoint, threadId: string, parentCheckpointId: string) {\n const result = await this.db\n .selectFrom('writes as ps')\n .select([\n 'ps.checkpoint_id',\n sql<string>`json_group_array(\n json_object(\n 'type', ps.type,\n 'value', CAST(ps.value AS TEXT)\n )\n )`.as('pending_sends'),\n ])\n .where('ps.thread_id', '=', threadId)\n .where('ps.checkpoint_id', '=', parentCheckpointId)\n .where('ps.channel', '=', TASKS)\n .orderBy('ps.idx')\n .executeTakeFirst();\n\n if (!result) return;\n\n const mutableCheckpoint = checkpoint;\n\n // add pending sends to checkpoint\n mutableCheckpoint.channel_values ??= {};\n mutableCheckpoint.channel_values[TASKS] = await Promise.all(\n JSON.parse(result.pending_sends).map(({ type, value }: PendingSendColumn) =>\n this.serde.loadsTyped(type, value),\n ),\n );\n\n // add to versions\n mutableCheckpoint.channel_versions[TASKS] =\n Object.keys(checkpoint.channel_versions).length > 0\n ? maxChannelVersion(...Object.values(checkpoint.channel_versions))\n : this.getNextVersion(undefined);\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { L as LangGraphGlobal, a as streamState, g as getGraph, G as GRAPHS } from './stream-
|
|
1
|
+
import { L as LangGraphGlobal, a as streamState, g as getGraph, G as GRAPHS } from './stream-D0YD2Pjq.js';
|
|
2
2
|
|
|
3
3
|
const AssistantEndpoint = {
|
|
4
4
|
async search(query) {
|
|
@@ -55,7 +55,7 @@ const createEndpoint = () => {
|
|
|
55
55
|
return getThreads().listRuns(threadId, options);
|
|
56
56
|
},
|
|
57
57
|
async cancel(threadId, runId, wait, action) {
|
|
58
|
-
return LangGraphGlobal.globalMessageQueue.cancelQueue(runId);
|
|
58
|
+
return await LangGraphGlobal.globalMessageQueue.cancelQueue(runId);
|
|
59
59
|
},
|
|
60
60
|
async *stream(threadId, assistantId, payload) {
|
|
61
61
|
payload.config = {
|
|
@@ -119,4 +119,4 @@ const createEndpoint = () => {
|
|
|
119
119
|
};
|
|
120
120
|
|
|
121
121
|
export { AssistantEndpoint as A, createEndpoint as c };
|
|
122
|
-
//# sourceMappingURL=createEndpoint-
|
|
122
|
+
//# sourceMappingURL=createEndpoint-CN_RHDEd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createEndpoint-CN_RHDEd.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 if (query?.graphId) {\n return [\n {\n assistant_id: query.graphId,\n graph_id: query.graphId,\n config: {},\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n metadata: {},\n version: 1,\n name: query.graphId,\n description: '',\n } as Assistant,\n ];\n }\n return 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 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\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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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,21 +1,10 @@
|
|
|
1
|
-
export { A as AssistantEndpoint, c as createEndpoint } from './createEndpoint-
|
|
2
|
-
export { L as LangGraphGlobal, r as registerGraph } from './stream-
|
|
3
|
-
import {
|
|
1
|
+
export { A as AssistantEndpoint, c as createEndpoint } from './createEndpoint-CN_RHDEd.js';
|
|
2
|
+
export { L as LangGraphGlobal, r as registerGraph } from './stream-D0YD2Pjq.js';
|
|
3
|
+
import { entrypoint, getPreviousState, getConfig, Command } from '@langchain/langgraph';
|
|
4
4
|
import { schemaMetaRegistry } from '@langchain/langgraph/zod';
|
|
5
5
|
import { getDefaultsForSchema } from 'zod-defaults';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
stateSchema,
|
|
9
|
-
config,
|
|
10
|
-
graph,
|
|
11
|
-
checkpointer
|
|
12
|
-
}) => {
|
|
13
|
-
const name = graph.getName();
|
|
14
|
-
return new StateGraph(stateSchema, config).addNode(name, (state, config2) => graph.invoke(state, config2)).addEdge("__start__", name).addEdge(name, "__end__").compile({
|
|
15
|
-
name,
|
|
16
|
-
checkpointer
|
|
17
|
-
});
|
|
18
|
-
};
|
|
6
|
+
import { tool, HumanMessage } from 'langchain';
|
|
7
|
+
import { z } from 'zod';
|
|
19
8
|
|
|
20
9
|
const composeWithState = (oldState, newState, stateSchema) => {
|
|
21
10
|
const channels = schemaMetaRegistry.getChannelsForSchema(stateSchema);
|
|
@@ -68,5 +57,74 @@ const createStateEntrypoint = (options, mainLogic) => {
|
|
|
68
57
|
return res;
|
|
69
58
|
};
|
|
70
59
|
|
|
71
|
-
|
|
60
|
+
const SubAgentStateSchema = z.object({
|
|
61
|
+
task_store: z.record(z.string(), z.any()).default({})
|
|
62
|
+
});
|
|
63
|
+
const schema = z.object({
|
|
64
|
+
task_id: z.string().optional().describe("The task id to ask the subagent, if not provided, will use the tool call id"),
|
|
65
|
+
subagent_id: z.string(),
|
|
66
|
+
task_description: z.string().describe("Describe the user state and what you want the subagent to do."),
|
|
67
|
+
data_transfer: z.any().optional().describe("Data to transfer to the subagent.")
|
|
68
|
+
});
|
|
69
|
+
const ask_subagents = (agentCreator, options) => tool(
|
|
70
|
+
async (args, config) => {
|
|
71
|
+
const state = config.state;
|
|
72
|
+
const taskId = args.task_id || config.toolCall.id;
|
|
73
|
+
let sub_state = {
|
|
74
|
+
messages: []
|
|
75
|
+
};
|
|
76
|
+
if (taskId && state?.["task_store"]?.[taskId]) {
|
|
77
|
+
sub_state = state?.["task_store"][taskId];
|
|
78
|
+
} else {
|
|
79
|
+
sub_state = JSON.parse(JSON.stringify(state));
|
|
80
|
+
sub_state.messages = [];
|
|
81
|
+
sub_state.task_store = {};
|
|
82
|
+
}
|
|
83
|
+
const agent = await agentCreator(taskId, args, state);
|
|
84
|
+
sub_state.messages.push(new HumanMessage({ content: args.task_description }));
|
|
85
|
+
if (args.data_transfer) {
|
|
86
|
+
sub_state.messages.push(
|
|
87
|
+
new HumanMessage({
|
|
88
|
+
content: `Here is the data to help you complete the task: ${JSON.stringify(
|
|
89
|
+
args.data_transfer,
|
|
90
|
+
null,
|
|
91
|
+
2
|
|
92
|
+
)}`
|
|
93
|
+
})
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
const new_state = await agent.invoke(sub_state);
|
|
97
|
+
const last_message = new_state["messages"].at(-1);
|
|
98
|
+
const update = {
|
|
99
|
+
task_store: {
|
|
100
|
+
...state?.["task_store"] || {},
|
|
101
|
+
[taskId]: new_state
|
|
102
|
+
},
|
|
103
|
+
messages: [
|
|
104
|
+
{
|
|
105
|
+
role: "tool",
|
|
106
|
+
content: `task_id: ${taskId}
|
|
107
|
+
---
|
|
108
|
+
` + (last_message?.text || ""),
|
|
109
|
+
tool_call_id: config.toolCall.id
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
};
|
|
113
|
+
options?.pass_through_keys?.forEach((key) => {
|
|
114
|
+
if (key in new_state) {
|
|
115
|
+
update[key] = new_state[key];
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
return new Command({
|
|
119
|
+
update
|
|
120
|
+
});
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: options?.name || "ask_subagents",
|
|
124
|
+
description: options?.description || "ask subagents to help you",
|
|
125
|
+
schema
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
export { SubAgentStateSchema, ask_subagents, createStateEntrypoint };
|
|
72
130
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/utils/createEntrypointGraph.ts","../src/utils/createStateEntrypoint.ts"],"sourcesContent":["import { InteropZodObject } from '@langchain/core/utils/types';\nimport { BaseCheckpointSaver, CompiledStateGraph, Pregel, StateDefinition, StateGraph } from '@langchain/langgraph';\nexport const createEntrypointGraph = <S extends InteropZodObject, C extends InteropZodObject>({\n stateSchema,\n config,\n graph,\n checkpointer,\n}: {\n stateSchema: S;\n config?: C;\n graph: Pregel<any, any>;\n checkpointer?: BaseCheckpointSaver;\n}): CompiledStateGraph<\n {},\n {},\n string,\n StateDefinition,\n StateDefinition,\n StateDefinition,\n {\n [x: string]: any;\n },\n unknown,\n unknown\n> => {\n const name = graph.getName();\n /** @ts-ignore */\n return new StateGraph(stateSchema, config)\n .addNode(name, (state, config) => graph.invoke(state, config))\n .addEdge('__start__', name)\n .addEdge(name, '__end__')\n .compile({\n name,\n checkpointer,\n });\n};\n","import {\n CompiledGraph,\n entrypoint,\n EntrypointOptions,\n getConfig,\n getPreviousState,\n LangGraphRunnableConfig,\n} from '@langchain/langgraph';\nimport { schemaMetaRegistry } from '@langchain/langgraph/zod';\nimport z from 'zod';\nimport { getDefaultsForSchema } from 'zod-defaults';\nconst composeWithState = <T>(oldState: T, newState: T, stateSchema: any) => {\n const channels = schemaMetaRegistry.getChannelsForSchema(stateSchema);\n\n const previewState = stateSchema.parse(oldState || getDefaultsForSchema(stateSchema));\n // 使用 channels 的 reducer 来合并 state\n const mergedState = { ...previewState };\n for (const [channelName, _] of Object.entries(channels)) {\n const currentValue = (previewState as any)[channelName];\n const newValue = (newState as any)[channelName];\n\n // 只有当 update 中包含该 channel 的值时才处理\n if (newValue !== undefined) {\n let reducer;\n // 尝试从 schema 中查找 reducer\n // 需要解包 ZodDefault, ZodOptional 等包装器\n let currentSchema = stateSchema.shape[channelName];\n while (currentSchema) {\n const meta = schemaMetaRegistry.get(currentSchema);\n if (meta?.reducer?.fn) {\n reducer = meta.reducer.fn;\n break;\n }\n if (currentSchema._def?.innerType) {\n currentSchema = currentSchema._def.innerType;\n } else if (currentSchema._def?.schema) {\n currentSchema = currentSchema._def.schema;\n } else {\n break;\n }\n }\n\n if (reducer && typeof reducer === 'function') {\n // 使用 reducer 函数合并值\n (mergedState as any)[channelName] = reducer(currentValue, newValue);\n } else {\n // 如果没有 reducer,直接使用新值覆盖\n (mergedState as any)[channelName] = newValue;\n }\n }\n }\n\n return mergedState;\n};\nexport const createStateEntrypoint = <ZType extends z.ZodType>(\n options: EntrypointOptions & { stateSchema: ZType },\n mainLogic: (state: z.infer<ZType>, config: LangGraphRunnableConfig) => Promise<any>,\n): CompiledGraph<any, any, any, any, any, any, any, any, any> => {\n const res = entrypoint(options, async (state, ...args) => {\n state = composeWithState(getPreviousState<ZType>(), state, options.stateSchema);\n // 更新 state 并保证 state 被推送\n getConfig()?.configurable?.__pregel_stream?.push([[], 'values', state]);\n const newState = await mainLogic(state as z.infer<ZType>, ...args);\n return entrypoint.final({\n value: newState,\n save: newState,\n });\n });\n // entrypoint 的 state 更新逻辑不一样\n const updateState = res.updateState;\n res.updateState = async function (config: any, state: any, ...args) {\n state = composeWithState((await res.getState(config)).values, state, options.stateSchema);\n return updateState.bind(this)(config, state, ...args);\n };\n return res as any;\n};\n"],"names":["config"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/utils/createStateEntrypoint.ts","../src/agents/ask_subagents.ts"],"sourcesContent":["import {\n CompiledGraph,\n entrypoint,\n EntrypointOptions,\n getConfig,\n getPreviousState,\n LangGraphRunnableConfig,\n} from '@langchain/langgraph';\nimport { schemaMetaRegistry } from '@langchain/langgraph/zod';\nimport z from 'zod';\nimport { getDefaultsForSchema } from 'zod-defaults';\nconst composeWithState = <T>(oldState: T, newState: T, stateSchema: any) => {\n const channels = schemaMetaRegistry.getChannelsForSchema(stateSchema);\n\n const previewState = stateSchema.parse(oldState || getDefaultsForSchema(stateSchema));\n // 使用 channels 的 reducer 来合并 state\n const mergedState = { ...previewState };\n for (const [channelName, _] of Object.entries(channels)) {\n const currentValue = (previewState as any)[channelName];\n const newValue = (newState as any)[channelName];\n\n // 只有当 update 中包含该 channel 的值时才处理\n if (newValue !== undefined) {\n let reducer;\n // 尝试从 schema 中查找 reducer\n // 需要解包 ZodDefault, ZodOptional 等包装器\n let currentSchema = stateSchema.shape[channelName];\n while (currentSchema) {\n const meta = schemaMetaRegistry.get(currentSchema);\n if (meta?.reducer?.fn) {\n reducer = meta.reducer.fn;\n break;\n }\n if (currentSchema._def?.innerType) {\n currentSchema = currentSchema._def.innerType;\n } else if (currentSchema._def?.schema) {\n currentSchema = currentSchema._def.schema;\n } else {\n break;\n }\n }\n\n if (reducer && typeof reducer === 'function') {\n // 使用 reducer 函数合并值\n (mergedState as any)[channelName] = reducer(currentValue, newValue);\n } else {\n // 如果没有 reducer,直接使用新值覆盖\n (mergedState as any)[channelName] = newValue;\n }\n }\n }\n\n return mergedState;\n};\nexport const createStateEntrypoint = <ZType extends z.ZodType>(\n options: EntrypointOptions & { stateSchema: ZType },\n mainLogic: (state: z.infer<ZType>, config: LangGraphRunnableConfig) => Promise<any>,\n): CompiledGraph<any, any, any, any, any, any, any, any, any> => {\n const res = entrypoint(options, async (state, ...args) => {\n state = composeWithState(getPreviousState<ZType>(), state, options.stateSchema);\n // 更新 state 并保证 state 被推送\n getConfig()?.configurable?.__pregel_stream?.push([[], 'values', state]);\n const newState = await mainLogic(state as z.infer<ZType>, ...args);\n return entrypoint.final({\n value: newState,\n save: newState,\n });\n });\n // entrypoint 的 state 更新逻辑不一样\n const updateState = res.updateState;\n res.updateState = async function (config: any, state: any, ...args) {\n state = composeWithState((await res.getState(config)).values, state, options.stateSchema);\n return updateState.bind(this)(config, state, ...args);\n };\n return res as any;\n};\n","import { Command } from '@langchain/langgraph';\nimport { HumanMessage, tool } from 'langchain';\nimport { z } from 'zod';\nimport { Message } from '@langchain/core/messages';\nimport { type ToolRuntime } from '@langchain/core/tools';\n\nexport const SubAgentStateSchema = z.object({\n task_store: z.record(z.string(), z.any()).default({}),\n});\n\nconst schema = z.object({\n task_id: z\n .string()\n .optional()\n .describe('The task id to ask the subagent, if not provided, will use the tool call id'),\n subagent_id: z.string(),\n task_description: z.string().describe('Describe the user state and what you want the subagent to do.'),\n data_transfer: z.any().optional().describe('Data to transfer to the subagent.'),\n});\n\nexport const ask_subagents = (\n agentCreator: (task_id: string, args: z.infer<typeof schema>, parent_state: any) => Promise<any>,\n options?: {\n name?: string;\n description?: string;\n pass_through_keys?: string[];\n },\n) =>\n tool(\n async (args, config: ToolRuntime<typeof SubAgentStateSchema, any>) => {\n const state = config.state;\n const taskId: string = args.task_id || config.toolCall!.id!;\n let sub_state = {\n messages: [] as Message[],\n };\n if (taskId && (state as any)?.['task_store']?.[taskId]) {\n sub_state = (state as any)?.['task_store'][taskId];\n } else {\n // 全复制状态\n sub_state = JSON.parse(JSON.stringify(state));\n sub_state.messages = [];\n /** @ts-ignore 不继承 task_store 中的信息 */\n sub_state.task_store = {};\n }\n\n const agent = await agentCreator(taskId, args, state);\n sub_state.messages.push(new HumanMessage({ content: args.task_description }));\n if (args.data_transfer) {\n sub_state.messages.push(\n new HumanMessage({\n content: `Here is the data to help you complete the task: ${JSON.stringify(\n args.data_transfer,\n null,\n 2,\n )}`,\n }),\n );\n }\n const new_state = await agent.invoke(sub_state);\n const last_message = new_state['messages'].at(-1);\n\n const update: any = {\n task_store: {\n ...(state?.['task_store'] || {}),\n [taskId]: new_state,\n },\n messages: [\n {\n role: 'tool',\n content: `task_id: ${taskId}\\n---\\n` + (last_message?.text || ''),\n tool_call_id: config.toolCall!.id!,\n },\n ],\n };\n\n options?.pass_through_keys?.forEach((key) => {\n if (key in new_state) {\n update[key] = new_state[key];\n }\n });\n\n return new Command({\n update,\n });\n },\n {\n name: options?.name || 'ask_subagents',\n description: options?.description || 'ask subagents to help you',\n schema,\n },\n );\n"],"names":[],"mappings":"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"}
|
|
@@ -70,7 +70,7 @@ export interface BaseStreamQueueInterface {
|
|
|
70
70
|
/** 取消信号控制器 / Cancel signal controller */
|
|
71
71
|
cancelSignal: AbortController;
|
|
72
72
|
/** 取消操作 / Cancel operation */
|
|
73
|
-
cancel(): void
|
|
73
|
+
cancel(): Promise<void>;
|
|
74
74
|
/** 复制队列数据 / Copy queue data */
|
|
75
75
|
copyToQueue(toId: string, ttl?: number): Promise<BaseStreamQueueInterface>;
|
|
76
76
|
}
|
|
@@ -119,7 +119,7 @@ export declare class StreamQueueManager<Q extends BaseStreamQueueInterface> {
|
|
|
119
119
|
* Cancel queue with specified id
|
|
120
120
|
* @param id 队列 ID / Queue ID
|
|
121
121
|
*/
|
|
122
|
-
cancelQueue(id: string): void
|
|
122
|
+
cancelQueue(id: string): Promise<void>;
|
|
123
123
|
/**
|
|
124
124
|
* 向指定 id 的队列推送数据
|
|
125
125
|
* Push data to queue with specified id
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as BaseStreamQueue, C as CancelEventMessage } from './stream-
|
|
1
|
+
import { B as BaseStreamQueue, C as CancelEventMessage } from './stream-D0YD2Pjq.js';
|
|
2
2
|
import { createClient } from 'redis';
|
|
3
3
|
|
|
4
4
|
class RedisStreamQueue extends BaseStreamQueue {
|
|
@@ -49,6 +49,9 @@ class RedisStreamQueue extends BaseStreamQueue {
|
|
|
49
49
|
let queue = [];
|
|
50
50
|
let pendingResolve = null;
|
|
51
51
|
let isStreamEnded = false;
|
|
52
|
+
if (this.cancelSignal.signal.aborted) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
52
55
|
const handleMessage = async (message) => {
|
|
53
56
|
const data = await this.decodeData(message);
|
|
54
57
|
queue.push(data);
|
|
@@ -61,7 +64,7 @@ class RedisStreamQueue extends BaseStreamQueue {
|
|
|
61
64
|
}
|
|
62
65
|
}, 300);
|
|
63
66
|
if (data.event === "__stream_cancel__") {
|
|
64
|
-
this.cancel();
|
|
67
|
+
await this.cancel();
|
|
65
68
|
}
|
|
66
69
|
}
|
|
67
70
|
if (pendingResolve) {
|
|
@@ -72,8 +75,16 @@ class RedisStreamQueue extends BaseStreamQueue {
|
|
|
72
75
|
await this.subscriberRedis.subscribe(this.channelKey, (message) => {
|
|
73
76
|
handleMessage(message);
|
|
74
77
|
});
|
|
78
|
+
const abortHandler = () => {
|
|
79
|
+
isStreamEnded = true;
|
|
80
|
+
if (pendingResolve) {
|
|
81
|
+
pendingResolve();
|
|
82
|
+
pendingResolve = null;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
this.cancelSignal.signal.addEventListener("abort", abortHandler);
|
|
75
86
|
try {
|
|
76
|
-
while (!isStreamEnded) {
|
|
87
|
+
while (!isStreamEnded && !this.cancelSignal.signal.aborted) {
|
|
77
88
|
if (queue.length > 0) {
|
|
78
89
|
for (const item of queue) {
|
|
79
90
|
yield item;
|
|
@@ -87,6 +98,7 @@ class RedisStreamQueue extends BaseStreamQueue {
|
|
|
87
98
|
}
|
|
88
99
|
} finally {
|
|
89
100
|
await this.subscriberRedis.unsubscribe(this.channelKey);
|
|
101
|
+
this.cancelSignal.signal.removeEventListener("abort", abortHandler);
|
|
90
102
|
}
|
|
91
103
|
}
|
|
92
104
|
/**
|
|
@@ -118,9 +130,9 @@ class RedisStreamQueue extends BaseStreamQueue {
|
|
|
118
130
|
/**
|
|
119
131
|
* 取消操作
|
|
120
132
|
*/
|
|
121
|
-
cancel() {
|
|
122
|
-
this.push(new CancelEventMessage());
|
|
133
|
+
async cancel() {
|
|
123
134
|
this.cancelSignal.abort("user cancel this run");
|
|
135
|
+
await this.push(new CancelEventMessage());
|
|
124
136
|
}
|
|
125
137
|
async copyToQueue(toId, ttl) {
|
|
126
138
|
const queue = new RedisStreamQueue(toId, this.compressMessages, ttl ?? this.ttl);
|
|
@@ -131,4 +143,4 @@ class RedisStreamQueue extends BaseStreamQueue {
|
|
|
131
143
|
}
|
|
132
144
|
|
|
133
145
|
export { RedisStreamQueue };
|
|
134
|
-
//# sourceMappingURL=queue-
|
|
146
|
+
//# sourceMappingURL=queue-D6tEGCGs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue-D6tEGCGs.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 实现的消息队列,用于存储消息\n */\nexport class RedisStreamQueue extends BaseStreamQueue implements BaseStreamQueueInterface {\n static redis: RedisClientType = createClient({ url: process.env.REDIS_URL! });\n static subscriberRedis: RedisClientType = createClient({ url: process.env.REDIS_URL! });\n static isQueueExist(id: string): Promise<boolean> {\n return this.redis.exists(`queue:${id}`).then((exists) => exists > 0);\n }\n private redis: RedisClientType;\n private subscriberRedis: RedisClientType;\n private queueKey: string;\n private channelKey: string;\n private isConnected = false;\n public cancelSignal: AbortController;\n\n constructor(readonly id: string, readonly compressMessages: boolean = true, readonly ttl: number = 300) {\n super(id, true, ttl);\n this.queueKey = `queue:${this.id}`;\n this.channelKey = `channel:${this.id}`;\n this.redis = RedisStreamQueue.redis;\n this.subscriberRedis = RedisStreamQueue.subscriberRedis;\n this.cancelSignal = new AbortController();\n\n // 连接 Redis 客户端(检查是否已经连接)\n if (!this.redis.isOpen) {\n this.redis.connect();\n }\n if (!this.subscriberRedis.isOpen) {\n this.subscriberRedis.connect();\n }\n this.isConnected = true;\n }\n\n /**\n * 推送消息到 Redis 队列\n */\n async push(item: EventMessage): Promise<void> {\n const data = await this.encodeData(item);\n const serializedData = Buffer.from(data);\n\n // 推送到队列\n await this.redis.rPush(this.queueKey, serializedData);\n\n // 设置队列 TTL 为 300 秒\n await this.redis.expire(this.queueKey, this.ttl);\n\n // 发布到频道通知有新数据\n await this.redis.publish(this.channelKey, serializedData);\n\n this.emit('dataChange', data);\n }\n\n /**\n * 异步生成器:支持 for await...of 方式消费队列数据\n */\n async *onDataReceive(): AsyncGenerator<EventMessage, void, unknown> {\n let queue: EventMessage[] = [];\n let pendingResolve: (() => void) | null = null;\n let isStreamEnded = false;\n \n // 检查是否已取消\n if (this.cancelSignal.signal.aborted) {\n return;\n }\n\n const handleMessage = async (message: string) => {\n const data = (await this.decodeData(message)) as EventMessage;\n queue.push(data);\n // 检查是否为流结束或错误信号\n if (\n data.event === '__stream_end__' ||\n data.event === '__stream_error__' ||\n data.event === '__stream_cancel__'\n ) {\n setTimeout(() => {\n isStreamEnded = true;\n if (pendingResolve) {\n pendingResolve();\n pendingResolve = null;\n }\n }, 300);\n\n if (data.event === '__stream_cancel__') {\n await this.cancel();\n }\n }\n\n if (pendingResolve) {\n pendingResolve();\n pendingResolve = null;\n }\n };\n\n // 订阅 Redis 频道\n await this.subscriberRedis.subscribe(this.channelKey, (message) => {\n handleMessage(message);\n });\n\n // 监听取消信号\n const abortHandler = () => {\n isStreamEnded = true;\n if (pendingResolve) {\n pendingResolve();\n pendingResolve = null;\n }\n };\n this.cancelSignal.signal.addEventListener('abort', abortHandler);\n\n try {\n while (!isStreamEnded && !this.cancelSignal.signal.aborted) {\n if (queue.length > 0) {\n for (const item of queue) {\n yield item;\n }\n queue = [];\n } else {\n await new Promise((resolve) => {\n pendingResolve = resolve as () => void;\n });\n }\n }\n } finally {\n await this.subscriberRedis.unsubscribe(this.channelKey);\n this.cancelSignal.signal.removeEventListener('abort', abortHandler);\n }\n }\n\n /**\n * 获取队列中的所有数据\n */\n async getAll(): Promise<EventMessage[]> {\n const data = await this.redis.lRange(this.queueKey, 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: string) => {\n return this.decodeData(item);\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 this.redis.del(this.queueKey);\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 async copyToQueue(toId: string, ttl?: number): Promise<RedisStreamQueue> {\n const queue = new RedisStreamQueue(toId, this.compressMessages, ttl ?? this.ttl);\n await this.redis.copy(this.queueKey, queue.queueKey);\n await this.redis.expire(queue.queueKey, ttl ?? this.ttl);\n return queue;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,6 @@ export declare class MemoryStreamQueue extends BaseStreamQueue implements BaseSt
|
|
|
13
13
|
getAll(): Promise<EventMessage[]>;
|
|
14
14
|
clear(): void;
|
|
15
15
|
cancelSignal: AbortController;
|
|
16
|
-
cancel(): void
|
|
16
|
+
cancel(): Promise<void>;
|
|
17
17
|
copyToQueue(toId: string, ttl?: number): Promise<MemoryStreamQueue>;
|
|
18
18
|
}
|
|
@@ -318,10 +318,10 @@ class StreamQueueManager {
|
|
|
318
318
|
* Cancel queue with specified id
|
|
319
319
|
* @param id 队列 ID / Queue ID
|
|
320
320
|
*/
|
|
321
|
-
cancelQueue(id) {
|
|
321
|
+
async cancelQueue(id) {
|
|
322
322
|
const queue = this.queues.get(id);
|
|
323
323
|
if (queue) {
|
|
324
|
-
queue.cancel();
|
|
324
|
+
await queue.cancel();
|
|
325
325
|
this.removeQueue(id);
|
|
326
326
|
}
|
|
327
327
|
}
|
|
@@ -686,6 +686,9 @@ class MemoryStreamQueue extends BaseStreamQueue {
|
|
|
686
686
|
let queue = [];
|
|
687
687
|
let pendingResolve = null;
|
|
688
688
|
let isStreamEnded = false;
|
|
689
|
+
if (this.cancelSignal.signal.aborted) {
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
689
692
|
const handleData = async (item) => {
|
|
690
693
|
const data = this.compressMessages ? await this.decodeData(item) : item;
|
|
691
694
|
queue.push(data);
|
|
@@ -698,7 +701,7 @@ class MemoryStreamQueue extends BaseStreamQueue {
|
|
|
698
701
|
}
|
|
699
702
|
}, 300);
|
|
700
703
|
if (data.event === "__stream_cancel__") {
|
|
701
|
-
this.cancel();
|
|
704
|
+
await this.cancel();
|
|
702
705
|
}
|
|
703
706
|
}
|
|
704
707
|
if (pendingResolve) {
|
|
@@ -707,8 +710,16 @@ class MemoryStreamQueue extends BaseStreamQueue {
|
|
|
707
710
|
}
|
|
708
711
|
};
|
|
709
712
|
this.on("dataChange", handleData);
|
|
713
|
+
const abortHandler = () => {
|
|
714
|
+
isStreamEnded = true;
|
|
715
|
+
if (pendingResolve) {
|
|
716
|
+
pendingResolve();
|
|
717
|
+
pendingResolve = null;
|
|
718
|
+
}
|
|
719
|
+
};
|
|
720
|
+
this.cancelSignal.signal.addEventListener("abort", abortHandler);
|
|
710
721
|
try {
|
|
711
|
-
while (!isStreamEnded) {
|
|
722
|
+
while (!isStreamEnded && !this.cancelSignal.signal.aborted) {
|
|
712
723
|
if (queue.length > 0) {
|
|
713
724
|
for (const item of queue) {
|
|
714
725
|
yield item;
|
|
@@ -722,6 +733,7 @@ class MemoryStreamQueue extends BaseStreamQueue {
|
|
|
722
733
|
}
|
|
723
734
|
} finally {
|
|
724
735
|
this.off("dataChange", handleData);
|
|
736
|
+
this.cancelSignal.signal.removeEventListener("abort", abortHandler);
|
|
725
737
|
}
|
|
726
738
|
}
|
|
727
739
|
async getAll() {
|
|
@@ -733,9 +745,9 @@ class MemoryStreamQueue extends BaseStreamQueue {
|
|
|
733
745
|
this.data = [];
|
|
734
746
|
}
|
|
735
747
|
cancelSignal = new AbortController();
|
|
736
|
-
cancel() {
|
|
737
|
-
this.push(new CancelEventMessage());
|
|
748
|
+
async cancel() {
|
|
738
749
|
this.cancelSignal.abort("user cancel this run");
|
|
750
|
+
await this.push(new CancelEventMessage());
|
|
739
751
|
}
|
|
740
752
|
async copyToQueue(toId, ttl) {
|
|
741
753
|
const data = this.data;
|
|
@@ -920,7 +932,7 @@ const createCheckPointer = async () => {
|
|
|
920
932
|
}
|
|
921
933
|
if (process.env.SQLITE_DATABASE_URI) {
|
|
922
934
|
console.debug("LG | Using sqlite as checkpoint");
|
|
923
|
-
const { SqliteSaver } = await import('./checkpoint-
|
|
935
|
+
const { SqliteSaver } = await import('./checkpoint-1sAx_j1E.js');
|
|
924
936
|
const db = await SqliteSaver.fromConnStringAsync(process.env.SQLITE_DATABASE_URI);
|
|
925
937
|
return db;
|
|
926
938
|
}
|
|
@@ -939,7 +951,7 @@ const createMessageQueue = async () => {
|
|
|
939
951
|
let q;
|
|
940
952
|
if (process.env.REDIS_URL) {
|
|
941
953
|
console.debug("LG | Using redis as stream queue");
|
|
942
|
-
const { RedisStreamQueue } = await import('./queue-
|
|
954
|
+
const { RedisStreamQueue } = await import('./queue-D6tEGCGs.js');
|
|
943
955
|
q = RedisStreamQueue;
|
|
944
956
|
} else {
|
|
945
957
|
q = MemoryStreamQueue;
|
|
@@ -1125,7 +1137,7 @@ async function* streamState(threads, run, payload, options) {
|
|
|
1125
1137
|
const queue = LangGraphGlobal.globalMessageQueue.createQueue(queueId);
|
|
1126
1138
|
const state = queue.onDataReceive();
|
|
1127
1139
|
streamStateWithQueue(threads, run, queue, payload, options).catch((error) => {
|
|
1128
|
-
console.error("Queue task error:", error);
|
|
1140
|
+
if (error.message !== "user cancel this run") console.error("Queue task error:", error);
|
|
1129
1141
|
LangGraphGlobal.globalMessageQueue.pushToQueue(queueId, new StreamErrorEventMessage(error));
|
|
1130
1142
|
});
|
|
1131
1143
|
for await (const data of state) {
|
|
@@ -1148,4 +1160,4 @@ async function* streamState(threads, run, payload, options) {
|
|
|
1148
1160
|
}
|
|
1149
1161
|
|
|
1150
1162
|
export { BaseStreamQueue as B, CancelEventMessage as C, GRAPHS as G, LangGraphGlobal as L, streamState as a, getGraph as g, registerGraph as r, serialiseAsDict as s };
|
|
1151
|
-
//# sourceMappingURL=stream-
|
|
1163
|
+
//# sourceMappingURL=stream-D0YD2Pjq.js.map
|