@langgraph-js/pure-graph 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +16 -0
  2. package/dist/adapter/hono/assistants.d.ts +3 -0
  3. package/dist/adapter/hono/assistants.js +27 -0
  4. package/dist/adapter/hono/endpoint.d.ts +1 -0
  5. package/dist/adapter/hono/endpoint.js +3 -0
  6. package/dist/adapter/hono/index.d.ts +3 -0
  7. package/dist/adapter/hono/index.js +11 -0
  8. package/dist/adapter/hono/runs.d.ts +3 -0
  9. package/dist/adapter/hono/runs.js +71 -0
  10. package/dist/adapter/hono/threads.d.ts +3 -0
  11. package/dist/adapter/hono/threads.js +71 -0
  12. package/dist/adapter/hono/zod.d.ts +203 -0
  13. package/dist/adapter/hono/zod.js +43 -0
  14. package/dist/createEndpoint.d.ts +5 -0
  15. package/dist/createEndpoint.js +77 -0
  16. package/dist/global.d.ts +4 -0
  17. package/dist/global.js +5 -0
  18. package/dist/graph/stream.d.ts +39 -0
  19. package/dist/graph/stream.js +187 -0
  20. package/dist/graph/stringify.d.ts +1 -0
  21. package/dist/graph/stringify.js +214 -0
  22. package/dist/index.d.ts +4 -0
  23. package/dist/index.js +4 -0
  24. package/dist/queue/JsonPlusSerializer.d.ts +7 -0
  25. package/dist/queue/JsonPlusSerializer.js +138 -0
  26. package/dist/queue/event_message.d.ts +15 -0
  27. package/dist/queue/event_message.js +27 -0
  28. package/dist/queue/stream_queue.d.ts +161 -0
  29. package/dist/queue/stream_queue.js +175 -0
  30. package/dist/storage/index.d.ts +5 -0
  31. package/dist/storage/index.js +11 -0
  32. package/dist/storage/memory/checkpoint.d.ts +2 -0
  33. package/dist/storage/memory/checkpoint.js +2 -0
  34. package/dist/storage/memory/queue.d.ts +17 -0
  35. package/dist/storage/memory/queue.js +72 -0
  36. package/dist/storage/memory/threads.d.ts +39 -0
  37. package/dist/storage/memory/threads.js +115 -0
  38. package/dist/threads/index.d.ts +36 -0
  39. package/dist/threads/index.js +26 -0
  40. package/dist/types.d.ts +94 -0
  41. package/dist/types.js +1 -0
  42. package/dist/utils/getGraph.d.ts +10 -0
  43. package/dist/utils/getGraph.js +18 -0
  44. package/dist/utils/getLangGraphCommand.d.ts +9 -0
  45. package/dist/utils/getLangGraphCommand.js +13 -0
  46. package/package.json +39 -0
  47. package/src/adapter/hono/assistants.ts +41 -0
  48. package/src/adapter/hono/endpoint.ts +4 -0
  49. package/src/adapter/hono/index.ts +14 -0
  50. package/src/adapter/hono/runs.ts +102 -0
  51. package/src/adapter/hono/threads.ts +92 -0
  52. package/src/adapter/hono/zod.ts +49 -0
  53. package/src/createEndpoint.ts +106 -0
  54. package/src/global.ts +6 -0
  55. package/src/graph/stream.ts +253 -0
  56. package/src/graph/stringify.ts +219 -0
  57. package/src/index.ts +5 -0
  58. package/src/queue/JsonPlusSerializer.ts +143 -0
  59. package/src/queue/event_message.ts +30 -0
  60. package/src/queue/stream_queue.ts +236 -0
  61. package/src/storage/index.ts +14 -0
  62. package/src/storage/memory/checkpoint.ts +2 -0
  63. package/src/storage/memory/queue.ts +83 -0
  64. package/src/storage/memory/threads.ts +154 -0
  65. package/src/threads/index.ts +51 -0
  66. package/src/types.ts +116 -0
  67. package/src/utils/getGraph.ts +44 -0
  68. package/src/utils/getLangGraphCommand.ts +21 -0
  69. package/test/graph/index.ts +21 -0
  70. package/test/hono.ts +10 -0
  71. package/tsconfig.json +20 -0
@@ -0,0 +1,94 @@
1
+ import { Thread, Assistant, Run, StreamMode, Command, Metadata, AssistantGraph, OnConflictBehavior, ThreadStatus, Checkpoint } from '@langchain/langgraph-sdk';
2
+ import { StreamEvent } from '@langchain/core/tracers/log_stream';
3
+ import { EventMessage } from './queue/event_message';
4
+ import { RunnableConfig } from '@langchain/core/runnables';
5
+ export type AssistantSortBy = 'assistant_id' | 'graph_id' | 'name' | 'created_at' | 'updated_at';
6
+ export type ThreadSortBy = 'thread_id' | 'status' | 'created_at' | 'updated_at';
7
+ export type SortOrder = 'asc' | 'desc';
8
+ export type RunStatus = 'pending' | 'running' | 'error' | 'success' | 'timeout' | 'interrupted';
9
+ export type MultitaskStrategy = 'reject' | 'interrupt' | 'rollback' | 'enqueue';
10
+ export type DisconnectMode = 'cancel' | 'continue';
11
+ export type OnCompletionBehavior = 'complete' | 'continue';
12
+ export type CancelAction = 'interrupt' | 'rollback';
13
+ export type StreamInputData = {
14
+ input?: Record<string, unknown> | null;
15
+ metadata?: Metadata;
16
+ config?: RunnableConfig;
17
+ checkpointId?: string;
18
+ checkpoint?: Omit<Checkpoint, 'thread_id'>;
19
+ checkpoint_during?: boolean;
20
+ interrupt_before?: '*' | string[];
21
+ interrupt_after?: '*' | string[];
22
+ multitask_strategy?: MultitaskStrategy;
23
+ on_completion?: OnCompletionBehavior;
24
+ signal?: AbortController['signal'];
25
+ webhook?: string;
26
+ on_disconnect?: DisconnectMode;
27
+ after_seconds?: number;
28
+ if_not_exists?: 'create' | 'reject';
29
+ command?: Command;
30
+ onRunCreated?: (params: {
31
+ run_id: string;
32
+ thread_id?: string;
33
+ }) => void;
34
+ stream_mode?: StreamMode[];
35
+ stream_subgraphs?: boolean;
36
+ stream_resumable?: boolean;
37
+ feedback_keys?: string[];
38
+ temporary?: boolean;
39
+ };
40
+ /**
41
+ * 兼容 LangGraph SDK 的接口定义,方便进行无侵入式的扩展
42
+ */
43
+ export interface ILangGraphClient<TStateType = unknown> {
44
+ assistants: {
45
+ search(query?: {
46
+ graphId?: string;
47
+ metadata?: Metadata;
48
+ limit?: number;
49
+ offset?: number;
50
+ sortBy?: AssistantSortBy;
51
+ sortOrder?: SortOrder;
52
+ }): Promise<Assistant[]>;
53
+ getGraph(assistantId: string, options?: {
54
+ xray?: boolean | number;
55
+ }): Promise<AssistantGraph>;
56
+ };
57
+ threads: {
58
+ create(payload?: {
59
+ metadata?: Metadata;
60
+ thread_id?: string;
61
+ if_exists?: OnConflictBehavior;
62
+ graph_id?: string;
63
+ }): Promise<Thread<TStateType>>;
64
+ search(query?: {
65
+ metadata?: Metadata;
66
+ limit?: number;
67
+ offset?: number;
68
+ status?: ThreadStatus;
69
+ sortBy?: ThreadSortBy;
70
+ sortOrder?: SortOrder;
71
+ }): Promise<Thread<TStateType>[]>;
72
+ get(threadId: string): Promise<Thread<TStateType>>;
73
+ delete(threadId: string): Promise<void>;
74
+ };
75
+ runs: {
76
+ list(threadId: string, options?: {
77
+ limit?: number;
78
+ offset?: number;
79
+ status?: RunStatus;
80
+ }): Promise<Run[]>;
81
+ stream(threadId: string, assistantId: string, payload?: StreamInputData): AsyncGenerator<EventMessage>;
82
+ joinStream(threadId: string, runId: string, options?: {
83
+ signal?: AbortSignal;
84
+ cancelOnDisconnect?: boolean;
85
+ lastEventId?: string;
86
+ streamMode?: StreamMode | StreamMode[];
87
+ } | AbortSignal): AsyncGenerator<{
88
+ id?: string;
89
+ event: StreamEvent;
90
+ data: any;
91
+ }>;
92
+ cancel(threadId: string, runId: string, wait?: boolean, action?: CancelAction): Promise<void>;
93
+ };
94
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ import { BaseCheckpointSaver, BaseStore, CompiledGraph, CompiledStateGraph, LangGraphRunnableConfig } from '@langchain/langgraph';
2
+ export type CompiledGraphFactory<T extends string> = (config: {
3
+ configurable?: Record<string, unknown>;
4
+ }) => Promise<CompiledGraph<T>>;
5
+ export declare const GRAPHS: Record<string, CompiledGraph<string> | CompiledGraphFactory<string>>;
6
+ export declare function registerGraph(graphId: string, graph: CompiledGraph<any> | CompiledStateGraph<any, any, any, any, any, any, any> | CompiledGraphFactory<any>): Promise<void>;
7
+ export declare function getGraph(graphId: string, config: LangGraphRunnableConfig | undefined, options?: {
8
+ checkpointer?: BaseCheckpointSaver | null;
9
+ store?: BaseStore;
10
+ }): Promise<CompiledGraph<string, any, any, Record<string, any>, any, any, unknown>>;
@@ -0,0 +1,18 @@
1
+ import { globalCheckPointer } from '../global';
2
+ export const GRAPHS = {};
3
+ export async function registerGraph(graphId, graph) {
4
+ GRAPHS[graphId] = graph;
5
+ }
6
+ export async function getGraph(graphId, config, options) {
7
+ if (!GRAPHS[graphId])
8
+ throw new Error(`Graph "${graphId}" not found`);
9
+ const compiled = typeof GRAPHS[graphId] === 'function' ? await GRAPHS[graphId](config ?? { configurable: {} }) : GRAPHS[graphId];
10
+ if (typeof options?.checkpointer !== 'undefined') {
11
+ compiled.checkpointer = options?.checkpointer ?? globalCheckPointer;
12
+ }
13
+ else {
14
+ compiled.checkpointer = globalCheckPointer;
15
+ }
16
+ compiled.store = options?.store ?? undefined;
17
+ return compiled;
18
+ }
@@ -0,0 +1,9 @@
1
+ import { Command } from '@langchain/langgraph';
2
+ import { Command as ClientCommand } from '@langgraph-js/sdk';
3
+ export interface RunSend {
4
+ node: string;
5
+ input?: unknown;
6
+ }
7
+ export interface RunCommand extends ClientCommand {
8
+ }
9
+ export declare const getLangGraphCommand: (command: RunCommand) => Command<unknown, Record<string, unknown>, string>;
@@ -0,0 +1,13 @@
1
+ import { Command, Send } from '@langchain/langgraph';
2
+ export const getLangGraphCommand = (command) => {
3
+ let goto = command.goto != null && !Array.isArray(command.goto) ? [command.goto] : command.goto;
4
+ return new Command({
5
+ goto: goto?.map((item) => {
6
+ if (typeof item !== 'string')
7
+ return new Send(item.node, item.input);
8
+ return item;
9
+ }),
10
+ update: command.update ?? undefined,
11
+ resume: command.resume,
12
+ });
13
+ };
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@langgraph-js/pure-graph",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "dist/index.js",
6
+ "exports": {
7
+ ".": {
8
+ "import": "./dist/index.js"
9
+ },
10
+ "/hono": {
11
+ "import": "./dist/adapter/hono/index.js"
12
+ }
13
+ },
14
+ "keywords": [],
15
+ "author": "",
16
+ "license": "MIT",
17
+ "dependencies": {
18
+ "@langchain/core": "^0.3.77",
19
+ "@langchain/langgraph": "^0.4.9",
20
+ "@langchain/langgraph-checkpoint": "^0.1.1",
21
+ "@langgraph-js/pro": "^1.8.1",
22
+ "eventemitter3": "^5.0.1",
23
+ "zod": "^3"
24
+ },
25
+ "optionalDependencies": {
26
+ "@hono/zod-validator": "^0.7.3",
27
+ "hono": "^4.9.9"
28
+ },
29
+ "devDependencies": {
30
+ "@langchain/langgraph-sdk": "^0.1.7",
31
+ "@langgraph-js/sdk": "^2.0.1",
32
+ "@types/node": "^22.13.5",
33
+ "typescript": "^5.9.2"
34
+ },
35
+ "scripts": {
36
+ "dev": "bun run test/hono.ts",
37
+ "build": "tsc"
38
+ }
39
+ }
@@ -0,0 +1,41 @@
1
+ import { zValidator } from '@hono/zod-validator';
2
+ import { Hono } from 'hono';
3
+ import { z } from 'zod';
4
+ import { client } from './endpoint';
5
+ import { MetadataSchema } from './zod';
6
+ const api = new Hono();
7
+
8
+ api.post(
9
+ '/assistants/search',
10
+ zValidator(
11
+ 'json',
12
+ z.object({
13
+ graph_id: z.string().optional(),
14
+ metadata: MetadataSchema.optional(),
15
+ limit: z.number().int().optional(),
16
+ offset: z.number().int().optional(),
17
+ }),
18
+ ),
19
+ async (c) => {
20
+ // Search Assistants
21
+ const payload = c.req.valid('json');
22
+ let total = 0;
23
+ const data = await client.assistants.search(payload);
24
+ c.res.headers.set('X-Pagination-Total', total.toString());
25
+ return c.json(data);
26
+ },
27
+ );
28
+
29
+ api.get(
30
+ '/assistants/:assistant_id/graph',
31
+ zValidator('query', z.object({ xray: z.string().optional() })),
32
+ async (c) => {
33
+ const xray = c.req.valid('query').xray;
34
+ const data = await client.assistants.getGraph(c.req.param('assistant_id'), {
35
+ xray: xray !== undefined ? xray === 'true' : undefined,
36
+ });
37
+ return c.json(data);
38
+ },
39
+ );
40
+
41
+ export default api;
@@ -0,0 +1,4 @@
1
+ import { createEndpoint } from '../../createEndpoint.js';
2
+ import { MemoryThreadsManager } from '../../storage/memory/threads.js';
3
+
4
+ export const client = createEndpoint(new MemoryThreadsManager());
@@ -0,0 +1,14 @@
1
+ import { Hono } from 'hono';
2
+ import Assistants from './assistants';
3
+ import Runs from './runs';
4
+ import Threads from './threads';
5
+ import { cors } from 'hono/cors';
6
+ const app = new Hono();
7
+
8
+ app.use(cors());
9
+
10
+ app.route('/', Assistants);
11
+ app.route('/', Runs);
12
+ app.route('/', Threads);
13
+
14
+ export default app;
@@ -0,0 +1,102 @@
1
+ import { zValidator } from '@hono/zod-validator';
2
+ import { Hono } from 'hono';
3
+
4
+ import { streamSSE } from 'hono/streaming';
5
+ import { z } from 'zod';
6
+ import { client } from './endpoint';
7
+ import { AssistantConfig, CommandSchema, MetadataSchema } from './zod';
8
+ import { serialiseAsDict } from '../../graph/stream';
9
+
10
+ const api = new Hono();
11
+
12
+ // 最常用的对话接口
13
+ api.post(
14
+ '/threads/:thread_id/runs/stream',
15
+ zValidator('param', z.object({ thread_id: z.string().uuid() })),
16
+ zValidator(
17
+ 'json',
18
+ z
19
+ .object({
20
+ assistant_id: z.union([z.string().uuid(), z.string()]),
21
+ checkpoint_id: z.string().optional(),
22
+ // checkpoint: CheckpointSchema.optional(),
23
+ input: z.any().optional(),
24
+ command: CommandSchema.optional(),
25
+ metadata: MetadataSchema.optional(),
26
+ config: AssistantConfig.optional(),
27
+ webhook: z.string().optional(),
28
+ interrupt_before: z.union([z.literal('*'), z.array(z.string())]).optional(),
29
+ interrupt_after: z.union([z.literal('*'), z.array(z.string())]).optional(),
30
+ on_disconnect: z.enum(['cancel', 'continue']).optional().default('continue'),
31
+ multitask_strategy: z.enum(['reject', 'rollback', 'interrupt', 'enqueue']).optional(),
32
+ stream_mode: z
33
+ .array(z.enum(['values', 'messages', 'messages-tuple', 'updates', 'events', 'debug', 'custom']))
34
+ .optional(),
35
+ stream_subgraphs: z.boolean().optional(),
36
+ stream_resumable: z.boolean().optional(),
37
+ after_seconds: z.number().optional(),
38
+ if_not_exists: z.enum(['create', 'reject']).optional(),
39
+ on_completion: z.enum(['complete', 'continue']).optional(),
40
+ feedback_keys: z.array(z.string()).optional(),
41
+ langsmith_tracer: z.unknown().optional(),
42
+ })
43
+ .describe('Payload for creating a stateful run.'),
44
+ ),
45
+ async (c) => {
46
+ // Stream Run
47
+ const { thread_id } = c.req.valid('param');
48
+ const payload = c.req.valid('json');
49
+
50
+ // c.header('Content-Location', `/threads/${thread_id}/runs/${run.run_id}`);
51
+ return streamSSE(c, async (stream) => {
52
+ /** @ts-ignore zod v3 的问题,与 ts 类型不一致 */
53
+ for await (const { event, data } of client.runs.stream(thread_id, payload.assistant_id, payload)) {
54
+ await stream.writeSSE({ data: serialiseAsDict(data), event });
55
+ }
56
+ // await stream.sleep(500); // 不知为何要等
57
+ });
58
+ },
59
+ );
60
+
61
+ api.get(
62
+ '/threads/:thread_id/runs',
63
+ zValidator('param', z.object({ thread_id: z.string().uuid() })),
64
+ zValidator(
65
+ 'query',
66
+ z.object({
67
+ limit: z.string().optional(),
68
+ offset: z.string().optional(),
69
+ status: z.enum(['pending', 'running', 'error', 'success', 'timeout', 'interrupted']).optional(),
70
+ }),
71
+ ),
72
+ async (c) => {
73
+ const { thread_id } = c.req.valid('param');
74
+ const { limit, offset, status } = c.req.valid('query');
75
+ const runs = await client.runs.list(thread_id, { limit: Number(limit), offset: Number(offset), status });
76
+ return c.json(runs);
77
+ },
78
+ );
79
+
80
+ api.post(
81
+ '/threads/:thread_id/runs/:run_id/cancel',
82
+ zValidator('param', z.object({ thread_id: z.string().uuid(), run_id: z.string().uuid() })),
83
+ zValidator(
84
+ 'query',
85
+ z.object({
86
+ wait: z.coerce.boolean().optional().default(false),
87
+ action: z.enum(['interrupt', 'rollback']).optional().default('interrupt'),
88
+ }),
89
+ ),
90
+ async (c) => {
91
+ // Cancel Run Http
92
+ const { thread_id, run_id } = c.req.valid('param');
93
+ const { wait, action } = c.req.valid('query');
94
+ const cancel = client.runs.cancel(thread_id, run_id, wait, action);
95
+ if (wait) {
96
+ await cancel;
97
+ }
98
+ return c.body(null, wait ? 204 : 202);
99
+ },
100
+ );
101
+
102
+ export default api;
@@ -0,0 +1,92 @@
1
+ import { zValidator } from '@hono/zod-validator';
2
+ import { Hono } from 'hono';
3
+ import { z } from 'zod';
4
+ import { client } from './endpoint';
5
+ import { CommandSchema, MetadataSchema } from './zod';
6
+
7
+ const api = new Hono();
8
+
9
+ // Threads Routes
10
+ api.post(
11
+ '/threads',
12
+ zValidator(
13
+ 'json',
14
+ z
15
+ .object({
16
+ // supersteps: z
17
+ // .array(
18
+ // z.object({
19
+ // updates: z.array(
20
+ // z.object({
21
+ // values: z.unknown(),
22
+ // command: CommandSchema.optional(),
23
+ // as_node: z.string(),
24
+ // }),
25
+ // ),
26
+ // }),
27
+ // )
28
+ // .describe('The supersteps to apply to the thread.')
29
+ // .optional(),
30
+ thread_id: z
31
+ .string()
32
+ .uuid()
33
+ .describe('The ID of the thread. If not provided, an ID is generated.')
34
+ .optional(),
35
+ metadata: MetadataSchema.optional(),
36
+ if_exists: z.union([z.literal('raise'), z.literal('do_nothing')]).optional(),
37
+ })
38
+ .describe('Payload for creating a thread.'),
39
+ ),
40
+ async (c) => {
41
+ const payload = c.req.valid('json');
42
+ const thread = await client.threads.create(payload);
43
+
44
+ return c.json(thread);
45
+ },
46
+ );
47
+
48
+ api.post(
49
+ '/threads/search',
50
+ zValidator(
51
+ 'json',
52
+ z
53
+ .object({
54
+ metadata: z.record(z.unknown()).describe('Metadata to search for.').optional(),
55
+ status: z
56
+ .enum(['idle', 'busy', 'interrupted', 'error'])
57
+ .describe('Filter by thread status.')
58
+ .optional(),
59
+ values: z.record(z.unknown()).describe('Filter by thread values.').optional(),
60
+ limit: z.number().int().gte(1).lte(1000).describe('Maximum number to return.').optional(),
61
+ offset: z.number().int().gte(0).describe('Offset to start from.').optional(),
62
+ sort_by: z
63
+ .enum(['thread_id', 'status', 'created_at', 'updated_at'])
64
+ .describe('Sort by field.')
65
+ .optional(),
66
+ sort_order: z.enum(['asc', 'desc']).describe('Sort order.').optional(),
67
+ })
68
+ .describe('Payload for listing threads.'),
69
+ ),
70
+ async (c) => {
71
+ // Search Threads
72
+ const payload = c.req.valid('json');
73
+ const result = await client.threads.search(payload as any);
74
+ c.res.headers.set('X-Pagination-Total', result.length.toString());
75
+ return c.json(result);
76
+ },
77
+ );
78
+
79
+ api.get('/threads/:thread_id', zValidator('param', z.object({ thread_id: z.string().uuid() })), async (c) => {
80
+ // Get Thread
81
+ const { thread_id } = c.req.valid('param');
82
+ return c.json(await client.threads.get(thread_id));
83
+ });
84
+
85
+ api.delete('/threads/:thread_id', zValidator('param', z.object({ thread_id: z.string().uuid() })), async (c) => {
86
+ // Delete Thread
87
+ const { thread_id } = c.req.valid('param');
88
+ await client.threads.delete(thread_id);
89
+ return new Response(null, { status: 204 });
90
+ });
91
+
92
+ export default api;
@@ -0,0 +1,49 @@
1
+ import z from 'zod';
2
+
3
+ export const AssistantConfigurable = z
4
+ .object({
5
+ thread_id: z.string().optional(),
6
+ thread_ts: z.string().optional(),
7
+ })
8
+ .catchall(z.unknown());
9
+
10
+ export const AssistantConfig = z
11
+ .object({
12
+ tags: z.array(z.string()).optional(),
13
+ recursion_limit: z.number().int().optional(),
14
+ configurable: AssistantConfigurable.optional(),
15
+ })
16
+ .catchall(z.unknown())
17
+ .describe('The configuration of an assistant.');
18
+
19
+ export const Assistant = z.object({
20
+ assistant_id: z.string().uuid(),
21
+ graph_id: z.string(),
22
+ config: AssistantConfig,
23
+ created_at: z.string(),
24
+ updated_at: z.string(),
25
+ metadata: z.object({}).catchall(z.any()),
26
+ });
27
+
28
+ export const MetadataSchema = z
29
+ .object({
30
+ source: z.union([z.literal('input'), z.literal('loop'), z.literal('update'), z.string()]).optional(),
31
+ step: z.number().optional(),
32
+ writes: z.record(z.unknown()).nullable().optional(),
33
+ parents: z.record(z.string()).optional(),
34
+ })
35
+ .catchall(z.unknown());
36
+
37
+ export const SendSchema = z.object({
38
+ node: z.string(),
39
+ input: z.unknown().nullable(),
40
+ });
41
+
42
+ export const CommandSchema = z.object({
43
+ update: z
44
+ .union([z.record(z.unknown()), z.array(z.tuple([z.string(), z.unknown()]))])
45
+ .nullable()
46
+ .optional(),
47
+ resume: z.unknown().optional(),
48
+ goto: z.union([SendSchema, z.array(SendSchema), z.string(), z.array(z.string())]).optional(),
49
+ });
@@ -0,0 +1,106 @@
1
+ import { StreamEvent } from '@langchain/core/tracers/log_stream';
2
+ import { streamState } from './graph/stream.js';
3
+ import { Assistant, Run, StreamMode, Metadata, AssistantGraph } from '@langchain/langgraph-sdk';
4
+ import { getGraph, GRAPHS } from './utils/getGraph.js';
5
+ import { BaseThreadsManager } from './threads/index.js';
6
+ import { globalMessageQueue } from './global.js';
7
+ import { AssistantSortBy, CancelAction, ILangGraphClient, RunStatus, SortOrder, StreamInputData } from './types.js';
8
+ export { registerGraph } from './utils/getGraph.js';
9
+
10
+ export const AssistantEndpoint: ILangGraphClient['assistants'] = {
11
+ async search(query?: {
12
+ graphId?: string;
13
+ metadata?: Metadata;
14
+ limit?: number;
15
+ offset?: number;
16
+ sortBy?: AssistantSortBy;
17
+ sortOrder?: SortOrder;
18
+ }): Promise<Assistant[]> {
19
+ if (query?.graphId) {
20
+ return [
21
+ {
22
+ assistant_id: query.graphId,
23
+ graph_id: query.graphId,
24
+ config: {},
25
+ created_at: new Date().toISOString(),
26
+ updated_at: new Date().toISOString(),
27
+ metadata: {},
28
+ version: 1,
29
+ name: query.graphId,
30
+ description: '',
31
+ } as Assistant,
32
+ ];
33
+ }
34
+ return Object.entries(GRAPHS).map(
35
+ ([graphId, _]) =>
36
+ ({
37
+ assistant_id: graphId,
38
+ graph_id: graphId,
39
+ config: {},
40
+ metadata: {},
41
+ version: 1,
42
+ name: graphId,
43
+ description: '',
44
+ created_at: new Date().toISOString(),
45
+ updated_at: new Date().toISOString(),
46
+ } as Assistant),
47
+ );
48
+ },
49
+ async getGraph(assistantId: string, options?: { xray?: boolean | number }): Promise<AssistantGraph> {
50
+ const config = {};
51
+ const graph = await getGraph(assistantId, config);
52
+ const drawable = await graph.getGraphAsync({
53
+ ...config,
54
+ xray: options?.xray ?? undefined,
55
+ });
56
+ return drawable.toJSON() as AssistantGraph;
57
+ },
58
+ };
59
+
60
+ export const createEndpoint = (threads: BaseThreadsManager): ILangGraphClient => {
61
+ return {
62
+ assistants: AssistantEndpoint,
63
+ threads,
64
+ runs: {
65
+ list(threadId: string, options?: { limit?: number; offset?: number; status?: RunStatus }): Promise<Run[]> {
66
+ return threads.listRuns(threadId, options);
67
+ },
68
+ async cancel(threadId: string, runId: string, wait?: boolean, action?: CancelAction): Promise<void> {
69
+ return globalMessageQueue.cancelQueue(runId);
70
+ },
71
+ async *stream(threadId: string, assistantId: string, payload: StreamInputData) {
72
+ if (!payload.config) {
73
+ payload.config = {
74
+ configurable: {
75
+ graph_id: assistantId,
76
+ thread_id: threadId,
77
+ },
78
+ };
79
+ }
80
+
81
+ const run = threads.createRun(threadId, assistantId, payload);
82
+
83
+ for await (const data of streamState(threads, run, payload, {
84
+ attempt: 0,
85
+ getGraph,
86
+ })) {
87
+ yield data;
88
+ }
89
+ },
90
+ joinStream(
91
+ threadId: string,
92
+ runId: string,
93
+ options?:
94
+ | {
95
+ signal?: AbortSignal;
96
+ cancelOnDisconnect?: boolean;
97
+ lastEventId?: string;
98
+ streamMode?: StreamMode | StreamMode[];
99
+ }
100
+ | AbortSignal,
101
+ ): AsyncGenerator<{ id?: string; event: StreamEvent; data: any }> {
102
+ throw new Error('Function not implemented.');
103
+ },
104
+ },
105
+ };
106
+ };
package/src/global.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { createCheckPointer, createMessageQueue } from './storage/index.js';
2
+
3
+ /** 全局队列管理器 */
4
+ export const globalMessageQueue = createMessageQueue();
5
+ /** 全局 Checkpointer */
6
+ export const globalCheckPointer = createCheckPointer();