@langgraph-js/pure-graph 1.2.0 → 1.4.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 (79) hide show
  1. package/README.md +22 -14
  2. package/dist/adapter/hono/runs.js +18 -1
  3. package/dist/adapter/nextjs/router.js +18 -7
  4. package/dist/adapter/zod.d.ts +15 -8
  5. package/dist/adapter/zod.js +8 -0
  6. package/dist/global.d.ts +3 -2
  7. package/dist/storage/index.d.ts +4 -3
  8. package/dist/storage/index.js +13 -1
  9. package/dist/storage/memory/threads.d.ts +3 -2
  10. package/dist/storage/memory/threads.js +29 -2
  11. package/dist/storage/pg/checkpoint.d.ts +2 -0
  12. package/dist/storage/pg/checkpoint.js +9 -0
  13. package/dist/storage/pg/threads.d.ts +43 -0
  14. package/dist/storage/pg/threads.js +304 -0
  15. package/dist/storage/sqlite/threads.d.ts +3 -2
  16. package/dist/storage/sqlite/threads.js +37 -3
  17. package/dist/threads/index.d.ts +3 -2
  18. package/dist/threads/index.js +1 -26
  19. package/dist/tsconfig.tsbuildinfo +1 -0
  20. package/dist/types.d.ts +2 -1
  21. package/package.json +38 -5
  22. package/.prettierrc +0 -11
  23. package/bun.lock +0 -209
  24. package/dist/adapter/nextjs/zod.d.ts +0 -203
  25. package/dist/adapter/nextjs/zod.js +0 -60
  26. package/examples/nextjs/README.md +0 -36
  27. package/examples/nextjs/app/api/langgraph/[...path]/route.ts +0 -10
  28. package/examples/nextjs/app/favicon.ico +0 -0
  29. package/examples/nextjs/app/globals.css +0 -26
  30. package/examples/nextjs/app/layout.tsx +0 -34
  31. package/examples/nextjs/app/page.tsx +0 -211
  32. package/examples/nextjs/next.config.ts +0 -26
  33. package/examples/nextjs/package.json +0 -24
  34. package/examples/nextjs/postcss.config.mjs +0 -5
  35. package/examples/nextjs/tsconfig.json +0 -27
  36. package/packages/agent-graph/demo.json +0 -35
  37. package/packages/agent-graph/package.json +0 -18
  38. package/packages/agent-graph/src/index.ts +0 -47
  39. package/packages/agent-graph/src/tools/tavily.ts +0 -9
  40. package/packages/agent-graph/src/tools.ts +0 -38
  41. package/packages/agent-graph/src/types.ts +0 -42
  42. package/pnpm-workspace.yaml +0 -4
  43. package/src/adapter/hono/assistants.ts +0 -24
  44. package/src/adapter/hono/endpoint.ts +0 -3
  45. package/src/adapter/hono/index.ts +0 -14
  46. package/src/adapter/hono/runs.ts +0 -65
  47. package/src/adapter/hono/threads.ts +0 -37
  48. package/src/adapter/nextjs/endpoint.ts +0 -2
  49. package/src/adapter/nextjs/index.ts +0 -2
  50. package/src/adapter/nextjs/router.ts +0 -193
  51. package/src/adapter/nextjs/zod.ts +0 -66
  52. package/src/adapter/zod.ts +0 -135
  53. package/src/createEndpoint.ts +0 -116
  54. package/src/e.d.ts +0 -3
  55. package/src/global.ts +0 -11
  56. package/src/graph/stream.ts +0 -263
  57. package/src/graph/stringify.ts +0 -219
  58. package/src/index.ts +0 -6
  59. package/src/queue/JsonPlusSerializer.ts +0 -143
  60. package/src/queue/event_message.ts +0 -30
  61. package/src/queue/stream_queue.ts +0 -237
  62. package/src/storage/index.ts +0 -52
  63. package/src/storage/memory/checkpoint.ts +0 -2
  64. package/src/storage/memory/queue.ts +0 -91
  65. package/src/storage/memory/threads.ts +0 -154
  66. package/src/storage/redis/queue.ts +0 -148
  67. package/src/storage/sqlite/DB.ts +0 -16
  68. package/src/storage/sqlite/checkpoint.ts +0 -503
  69. package/src/storage/sqlite/threads.ts +0 -366
  70. package/src/storage/sqlite/type.ts +0 -12
  71. package/src/threads/index.ts +0 -51
  72. package/src/types.ts +0 -116
  73. package/src/utils/createEntrypointGraph.ts +0 -20
  74. package/src/utils/getGraph.ts +0 -44
  75. package/src/utils/getLangGraphCommand.ts +0 -21
  76. package/test/graph/entrypoint.ts +0 -21
  77. package/test/graph/index.ts +0 -60
  78. package/test/hono.ts +0 -15
  79. package/tsconfig.json +0 -20
@@ -1,263 +0,0 @@
1
- import { BaseMessageChunk, isBaseMessage } from '@langchain/core/messages';
2
- import type { BaseCheckpointSaver, LangGraphRunnableConfig } from '@langchain/langgraph';
3
- import type { Pregel } from '@langchain/langgraph/pregel';
4
- import { getLangGraphCommand } from '../utils/getLangGraphCommand.js';
5
- import type { BaseStreamQueueInterface } from '../queue/stream_queue.js';
6
-
7
- import { LangGraphGlobal } from '../global.js';
8
- import { Run } from '@langgraph-js/sdk';
9
- import { EventMessage, StreamErrorEventMessage, StreamEndEventMessage } from '../queue/event_message.js';
10
-
11
- import { BaseThreadsManager } from '../threads/index.js';
12
- import { StreamInputData } from '../types.js';
13
-
14
- export type LangGraphStreamMode = Pregel<any, any>['streamMode'][number];
15
-
16
- export async function streamStateWithQueue(
17
- threads: BaseThreadsManager,
18
- run: Run,
19
- queue: BaseStreamQueueInterface,
20
- payload: StreamInputData,
21
- options: {
22
- attempt: number;
23
- getGraph: (
24
- graphId: string,
25
- config: LangGraphRunnableConfig | undefined,
26
- options?: { checkpointer?: BaseCheckpointSaver | null },
27
- ) => Promise<Pregel<any, any, any, any, any>>;
28
- compressMessages?: boolean;
29
- },
30
- ): Promise<void> {
31
- const kwargs = payload;
32
- const graphId = kwargs.config?.configurable?.graph_id;
33
-
34
- if (!graphId || typeof graphId !== 'string') {
35
- throw new Error('Invalid or missing graph_id');
36
- }
37
-
38
- const graph = await options.getGraph(graphId, payload.config, {
39
- checkpointer: payload.temporary ? null : undefined,
40
- });
41
-
42
- const userStreamMode = payload.stream_mode ?? [];
43
-
44
- const libStreamMode: Set<LangGraphStreamMode> = new Set([
45
- 'values',
46
- ...userStreamMode.filter((mode) => mode !== 'events' && mode !== 'messages-tuple'),
47
- ]);
48
-
49
- if (userStreamMode.includes('messages-tuple')) {
50
- libStreamMode.add('messages');
51
- }
52
-
53
- if (userStreamMode.includes('messages')) {
54
- libStreamMode.add('values');
55
- }
56
-
57
- await queue.push(
58
- new EventMessage('metadata', {
59
- run_id: run.run_id,
60
- attempt: options.attempt,
61
- graph_id: graphId,
62
- }),
63
- );
64
-
65
- const metadata = {
66
- ...payload.config?.metadata,
67
- run_attempt: options.attempt,
68
- };
69
- const events = graph.streamEvents(
70
- payload.command != null ? getLangGraphCommand(payload.command) : payload.input ?? null,
71
- {
72
- version: 'v2' as const,
73
-
74
- interruptAfter: payload.interrupt_after,
75
- interruptBefore: payload.interrupt_before,
76
-
77
- tags: payload.config?.tags,
78
- configurable: payload.config?.configurable,
79
- recursionLimit: payload.config?.recursionLimit,
80
- subgraphs: payload.stream_subgraphs,
81
- metadata,
82
-
83
- runId: run.run_id,
84
- streamMode: [...libStreamMode],
85
- signal: queue.cancelSignal.signal,
86
- },
87
- );
88
-
89
- const messages: Record<string, BaseMessageChunk> = {};
90
- const completedIds = new Set<string>();
91
-
92
- try {
93
- for await (const event of events) {
94
- // console.log(event);
95
- if (event.tags?.includes('langsmith:hidden')) continue;
96
- if (event.event === 'on_chain_stream' && event.run_id === run.run_id) {
97
- const [ns, mode, chunk] = (
98
- payload.stream_subgraphs ? event.data.chunk : [null, ...event.data.chunk]
99
- ) as [string[] | null, LangGraphStreamMode, unknown];
100
-
101
- // Listen for debug events and capture checkpoint
102
- let data: unknown = chunk;
103
-
104
- if (mode === 'messages') {
105
- if (userStreamMode.includes('messages-tuple')) {
106
- await queue.push(new EventMessage('messages', data));
107
- }
108
- } else if (userStreamMode.includes(mode)) {
109
- if (payload.stream_subgraphs && ns?.length) {
110
- await queue.push(new EventMessage(`${mode}|${ns.join('|')}`, data));
111
- } else {
112
- await queue.push(new EventMessage(mode, data));
113
- }
114
- }
115
- if (mode === 'values') {
116
- await threads.set(run.thread_id, {
117
- values: data ? JSON.parse(serialiseAsDict(data)) : '',
118
- });
119
- }
120
- } else if (userStreamMode.includes('events')) {
121
- await queue.push(new EventMessage('events', event));
122
- }
123
-
124
- // TODO: we still rely on old messages mode based of streamMode=values
125
- // In order to fully switch to library messages mode, we need to do ensure that
126
- // `StreamMessagesHandler` sends the final message, which requires the following:
127
- // - handleLLMEnd does not send the final message b/c handleLLMNewToken sets the this.emittedChatModelRunIds[runId] flag. Python does not do that
128
- // - handleLLMEnd receives the final message as BaseMessageChunk rather than BaseMessage, which from the outside will become indistinguishable.
129
- // - handleLLMEnd should not dedupe the message
130
- // - Don't think there's an utility that would convert a BaseMessageChunk to a BaseMessage?
131
- if (userStreamMode.includes('messages')) {
132
- if (event.event === 'on_chain_stream' && event.run_id === run.run_id) {
133
- const newMessages: Array<BaseMessageChunk> = [];
134
- const [_, chunk]: [string, any] = event.data.chunk;
135
-
136
- let chunkMessages: Array<BaseMessageChunk> = [];
137
- if (typeof chunk === 'object' && chunk != null && 'messages' in chunk && !isBaseMessage(chunk)) {
138
- chunkMessages = chunk?.messages;
139
- }
140
-
141
- if (!Array.isArray(chunkMessages)) {
142
- chunkMessages = [chunkMessages];
143
- }
144
-
145
- for (const message of chunkMessages) {
146
- if (!message.id || completedIds.has(message.id)) continue;
147
- completedIds.add(message.id);
148
- newMessages.push(message);
149
- }
150
-
151
- if (newMessages.length > 0) {
152
- await queue.push(new EventMessage('messages/complete', newMessages));
153
- }
154
- } else if (event.event === 'on_chat_model_stream' && !event.tags?.includes('nostream')) {
155
- const message: BaseMessageChunk = event.data.chunk;
156
-
157
- if (!message.id) continue;
158
-
159
- if (messages[message.id] == null) {
160
- messages[message.id] = message;
161
- await queue.push(
162
- new EventMessage('messages/metadata', {
163
- [message.id]: { metadata: event.metadata },
164
- }),
165
- );
166
- } else {
167
- messages[message.id] = messages[message.id].concat(message);
168
- }
169
-
170
- await queue.push(new EventMessage('messages/partial', [messages[message.id]]));
171
- }
172
- }
173
- }
174
- } finally {
175
- // 发送流结束信号
176
- await queue.push(new StreamEndEventMessage());
177
- }
178
- }
179
-
180
- /**
181
- * 从队列创建数据流生成器
182
- * @param queueId 队列 ID
183
- * @param signal 中止信号
184
- * @returns 数据流生成器
185
- */
186
- export async function* createStreamFromQueue(queueId: string): AsyncGenerator<{ event: string; data: unknown }> {
187
- const queue = LangGraphGlobal.globalMessageQueue.getQueue(queueId);
188
- return queue.onDataReceive();
189
- }
190
-
191
- export const serialiseAsDict = (obj: unknown, indent = 2) => {
192
- return JSON.stringify(
193
- obj,
194
- function (key: string | number, value: unknown) {
195
- const rawValue = this[key];
196
- if (
197
- rawValue != null &&
198
- typeof rawValue === 'object' &&
199
- 'toDict' in rawValue &&
200
- typeof rawValue.toDict === 'function'
201
- ) {
202
- // TODO: we need to upstream this to LangChainJS
203
- const { type, data } = rawValue.toDict();
204
- return { ...data, type };
205
- }
206
-
207
- return value;
208
- },
209
- indent,
210
- );
211
- };
212
- /**
213
- * 兼容性函数:保持原有 API,同时使用队列模式
214
- * @param run 运行配置
215
- * @param options 选项
216
- * @returns 数据流生成器
217
- */
218
- export async function* streamState(
219
- threads: BaseThreadsManager,
220
- run: Run | Promise<Run>,
221
- payload: StreamInputData,
222
- options: {
223
- attempt: number;
224
- getGraph: (
225
- graphId: string,
226
- config: LangGraphRunnableConfig | undefined,
227
- options?: { checkpointer?: BaseCheckpointSaver | null },
228
- ) => Promise<Pregel<any, any, any, any, any>>;
229
- compressMessages?: boolean;
230
- },
231
- ) {
232
- run = await run;
233
- // 生成唯一的队列 ID
234
- const queueId = run.run_id;
235
- const threadId = run.thread_id;
236
- try {
237
- // 启动队列推送任务(在后台异步执行)
238
- await threads.set(threadId, { status: 'busy' });
239
- await threads.updateRun(run.run_id, { status: 'running' });
240
- const queue = LangGraphGlobal.globalMessageQueue.createQueue(queueId);
241
- const state = queue.onDataReceive();
242
- streamStateWithQueue(threads, run, queue, payload, options).catch((error) => {
243
- console.error('Queue task error:', error);
244
- // 如果生产者出错,向队列推送错误信号
245
- LangGraphGlobal.globalMessageQueue.pushToQueue(queueId, new StreamErrorEventMessage(error));
246
- // TODO 不知道这里需不需要错误处理
247
- });
248
- for await (const data of state) {
249
- yield data;
250
- }
251
- await threads.updateRun(run.run_id, { status: 'success' });
252
- } catch (error) {
253
- // 如果发生错误,确保清理资源
254
- console.error('Stream error:', error);
255
- await threads.updateRun(run.run_id, { status: 'error' });
256
- await threads.set(threadId, { status: 'error' });
257
- // throw error;
258
- } finally {
259
- // 在完成后清理队列
260
- await threads.set(threadId, { status: 'idle' });
261
- LangGraphGlobal.globalMessageQueue.removeQueue(queueId);
262
- }
263
- }
@@ -1,219 +0,0 @@
1
- /* eslint-disable */
2
- // @ts-nocheck
3
-
4
- // Stringify that can handle circular references.
5
- // Inlined due to ESM import issues
6
- // Source: https://www.npmjs.com/package/fast-safe-stringify
7
-
8
- var LIMIT_REPLACE_NODE = '[...]';
9
- var CIRCULAR_REPLACE_NODE = '[Circular]';
10
-
11
- var arr = [];
12
- var replacerStack = [];
13
-
14
- function defaultOptions() {
15
- return {
16
- depthLimit: Number.MAX_SAFE_INTEGER,
17
- edgesLimit: Number.MAX_SAFE_INTEGER,
18
- };
19
- }
20
-
21
- // Regular stringify
22
- export function stringify(obj, replacer?, spacer?, options?) {
23
- if (typeof options === 'undefined') {
24
- options = defaultOptions();
25
- }
26
-
27
- decirc(obj, '', 0, [], undefined, 0, options);
28
- var res;
29
- try {
30
- if (replacerStack.length === 0) {
31
- res = JSON.stringify(obj, replacer, spacer);
32
- } else {
33
- res = JSON.stringify(obj, replaceGetterValues(replacer), spacer);
34
- }
35
- } catch (_) {
36
- return JSON.stringify('[unable to serialize, circular reference is too complex to analyze]');
37
- } finally {
38
- while (arr.length !== 0) {
39
- var part = arr.pop();
40
- if (part.length === 4) {
41
- Object.defineProperty(part[0], part[1], part[3]);
42
- } else {
43
- part[0][part[1]] = part[2];
44
- }
45
- }
46
- }
47
- return res;
48
- }
49
-
50
- function setReplace(replace, val, k, parent) {
51
- var propertyDescriptor = Object.getOwnPropertyDescriptor(parent, k);
52
- if (propertyDescriptor.get !== undefined) {
53
- if (propertyDescriptor.configurable) {
54
- Object.defineProperty(parent, k, { value: replace });
55
- arr.push([parent, k, val, propertyDescriptor]);
56
- } else {
57
- replacerStack.push([val, k, replace]);
58
- }
59
- } else {
60
- parent[k] = replace;
61
- arr.push([parent, k, val]);
62
- }
63
- }
64
-
65
- function decirc(val, k, edgeIndex, stack, parent, depth, options) {
66
- depth += 1;
67
- var i;
68
- if (typeof val === 'object' && val !== null) {
69
- for (i = 0; i < stack.length; i++) {
70
- if (stack[i] === val) {
71
- setReplace(CIRCULAR_REPLACE_NODE, val, k, parent);
72
- return;
73
- }
74
- }
75
-
76
- if (typeof options.depthLimit !== 'undefined' && depth > options.depthLimit) {
77
- setReplace(LIMIT_REPLACE_NODE, val, k, parent);
78
- return;
79
- }
80
-
81
- if (typeof options.edgesLimit !== 'undefined' && edgeIndex + 1 > options.edgesLimit) {
82
- setReplace(LIMIT_REPLACE_NODE, val, k, parent);
83
- return;
84
- }
85
-
86
- stack.push(val);
87
- // Optimize for Arrays. Big arrays could kill the performance otherwise!
88
- if (Array.isArray(val)) {
89
- for (i = 0; i < val.length; i++) {
90
- decirc(val[i], i, i, stack, val, depth, options);
91
- }
92
- } else {
93
- var keys = Object.keys(val);
94
- for (i = 0; i < keys.length; i++) {
95
- var key = keys[i];
96
- decirc(val[key], key, i, stack, val, depth, options);
97
- }
98
- }
99
- stack.pop();
100
- }
101
- }
102
-
103
- // Stable-stringify
104
- function compareFunction(a, b) {
105
- if (a < b) {
106
- return -1;
107
- }
108
- if (a > b) {
109
- return 1;
110
- }
111
- return 0;
112
- }
113
-
114
- function deterministicStringify(obj, replacer, spacer, options) {
115
- if (typeof options === 'undefined') {
116
- options = defaultOptions();
117
- }
118
-
119
- var tmp = deterministicDecirc(obj, '', 0, [], undefined, 0, options) || obj;
120
- var res;
121
- try {
122
- if (replacerStack.length === 0) {
123
- res = JSON.stringify(tmp, replacer, spacer);
124
- } else {
125
- res = JSON.stringify(tmp, replaceGetterValues(replacer), spacer);
126
- }
127
- } catch (_) {
128
- return JSON.stringify('[unable to serialize, circular reference is too complex to analyze]');
129
- } finally {
130
- // Ensure that we restore the object as it was.
131
- while (arr.length !== 0) {
132
- var part = arr.pop();
133
- if (part.length === 4) {
134
- Object.defineProperty(part[0], part[1], part[3]);
135
- } else {
136
- part[0][part[1]] = part[2];
137
- }
138
- }
139
- }
140
- return res;
141
- }
142
-
143
- function deterministicDecirc(val, k, edgeIndex, stack, parent, depth, options) {
144
- depth += 1;
145
- var i;
146
- if (typeof val === 'object' && val !== null) {
147
- for (i = 0; i < stack.length; i++) {
148
- if (stack[i] === val) {
149
- setReplace(CIRCULAR_REPLACE_NODE, val, k, parent);
150
- return;
151
- }
152
- }
153
- try {
154
- if (typeof val.toJSON === 'function') {
155
- return;
156
- }
157
- } catch (_) {
158
- return;
159
- }
160
-
161
- if (typeof options.depthLimit !== 'undefined' && depth > options.depthLimit) {
162
- setReplace(LIMIT_REPLACE_NODE, val, k, parent);
163
- return;
164
- }
165
-
166
- if (typeof options.edgesLimit !== 'undefined' && edgeIndex + 1 > options.edgesLimit) {
167
- setReplace(LIMIT_REPLACE_NODE, val, k, parent);
168
- return;
169
- }
170
-
171
- stack.push(val);
172
- // Optimize for Arrays. Big arrays could kill the performance otherwise!
173
- if (Array.isArray(val)) {
174
- for (i = 0; i < val.length; i++) {
175
- deterministicDecirc(val[i], i, i, stack, val, depth, options);
176
- }
177
- } else {
178
- // Create a temporary object in the required way
179
- var tmp = {};
180
- var keys = Object.keys(val).sort(compareFunction);
181
- for (i = 0; i < keys.length; i++) {
182
- var key = keys[i];
183
- deterministicDecirc(val[key], key, i, stack, val, depth, options);
184
- tmp[key] = val[key];
185
- }
186
- if (typeof parent !== 'undefined') {
187
- arr.push([parent, k, val]);
188
- parent[k] = tmp;
189
- } else {
190
- return tmp;
191
- }
192
- }
193
- stack.pop();
194
- }
195
- }
196
-
197
- // wraps replacer function to handle values we couldn't replace
198
- // and mark them as replaced value
199
- function replaceGetterValues(replacer) {
200
- replacer =
201
- typeof replacer !== 'undefined'
202
- ? replacer
203
- : function (k, v) {
204
- return v;
205
- };
206
- return function (key, val) {
207
- if (replacerStack.length > 0) {
208
- for (var i = 0; i < replacerStack.length; i++) {
209
- var part = replacerStack[i];
210
- if (part[1] === key && part[0] === val) {
211
- val = part[2];
212
- replacerStack.splice(i, 1);
213
- break;
214
- }
215
- }
216
- }
217
- return replacer.call(this, key, val);
218
- };
219
- }
package/src/index.ts DELETED
@@ -1,6 +0,0 @@
1
- export * from './createEndpoint';
2
- export * from './types';
3
- export * from './global';
4
-
5
- export * from './threads/index';
6
- export * from './utils/createEntrypointGraph';
@@ -1,143 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- /* eslint-disable no-instanceof/no-instanceof */
3
- import { load } from '@langchain/core/load';
4
- import type { SerializerProtocol } from '@langchain/langgraph-checkpoint';
5
- import { stringify } from '../graph/stringify.js';
6
-
7
- function isLangChainSerializedObject(value: Record<string, unknown>) {
8
- return value !== null && value.lc === 1 && value.type === 'constructor' && Array.isArray(value.id);
9
- }
10
-
11
- /**
12
- * The replacer in stringify does not allow delegation to built-in LangChain
13
- * serialization methods, and instead immediately calls `.toJSON()` and
14
- * continues to stringify subfields.
15
- *
16
- * We therefore must start from the most nested elements in the input and
17
- * deserialize upwards rather than top-down.
18
- */
19
- async function _reviver(value: any): Promise<any> {
20
- if (value && typeof value === 'object') {
21
- if (Array.isArray(value)) {
22
- const revivedArray = await Promise.all(value.map((item) => _reviver(item)));
23
- return revivedArray;
24
- } else {
25
- const revivedObj: any = {};
26
- for (const [k, v] of Object.entries(value)) {
27
- revivedObj[k] = await _reviver(v);
28
- }
29
-
30
- if (revivedObj.lc === 2 && revivedObj.type === 'undefined') {
31
- return undefined;
32
- } else if (revivedObj.lc === 2 && revivedObj.type === 'constructor' && Array.isArray(revivedObj.id)) {
33
- try {
34
- const constructorName = revivedObj.id[revivedObj.id.length - 1];
35
- let constructor: any;
36
-
37
- switch (constructorName) {
38
- case 'Set':
39
- constructor = Set;
40
- break;
41
- case 'Map':
42
- constructor = Map;
43
- break;
44
- case 'RegExp':
45
- constructor = RegExp;
46
- break;
47
- case 'Error':
48
- constructor = Error;
49
- break;
50
- default:
51
- return revivedObj;
52
- }
53
- if (revivedObj.method) {
54
- return (constructor as any)[revivedObj.method](...(revivedObj.args || []));
55
- } else {
56
- return new (constructor as any)(...(revivedObj.args || []));
57
- }
58
- } catch (error) {
59
- return revivedObj;
60
- }
61
- } else if (isLangChainSerializedObject(revivedObj)) {
62
- return load(JSON.stringify(revivedObj));
63
- }
64
-
65
- return revivedObj;
66
- }
67
- }
68
- return value;
69
- }
70
-
71
- function _encodeConstructorArgs(
72
- // eslint-disable-next-line @typescript-eslint/ban-types
73
- constructor: Function,
74
- method?: string,
75
- args?: any[],
76
- kwargs?: Record<string, any>,
77
- ): object {
78
- return {
79
- lc: 2,
80
- type: 'constructor',
81
- id: [constructor.name],
82
- method: method ?? null,
83
- args: args ?? [],
84
- kwargs: kwargs ?? {},
85
- };
86
- }
87
-
88
- function _default(obj: any): any {
89
- if (obj === undefined) {
90
- return {
91
- lc: 2,
92
- type: 'undefined',
93
- };
94
- } else if (obj instanceof Set || obj instanceof Map) {
95
- return _encodeConstructorArgs(obj.constructor, undefined, [Array.from(obj)]);
96
- } else if (obj instanceof RegExp) {
97
- return _encodeConstructorArgs(RegExp, undefined, [obj.source, obj.flags]);
98
- } else if (obj instanceof Error) {
99
- return _encodeConstructorArgs(obj.constructor, undefined, [obj.message]);
100
- // TODO: Remove special case
101
- } else if (obj?.lg_name === 'Send') {
102
- return {
103
- node: obj.node,
104
- args: obj.args,
105
- };
106
- } else {
107
- return obj;
108
- }
109
- }
110
-
111
- export class JsonPlusSerializer implements SerializerProtocol {
112
- protected _dumps(obj: any): Uint8Array {
113
- const encoder = new TextEncoder();
114
- return encoder.encode(
115
- stringify(obj, (_: string, value: any) => {
116
- return _default(value);
117
- }),
118
- );
119
- }
120
-
121
- async dumpsTyped(obj: any): Promise<[string, Uint8Array]> {
122
- if (obj instanceof Uint8Array) {
123
- return ['bytes', obj];
124
- } else {
125
- return ['json', this._dumps(obj)];
126
- }
127
- }
128
-
129
- protected async _loads(data: string): Promise<any> {
130
- const parsed = JSON.parse(data);
131
- return _reviver(parsed);
132
- }
133
-
134
- async loadsTyped(type: string, data: Uint8Array | string): Promise<any> {
135
- if (type === 'bytes') {
136
- return typeof data === 'string' ? new TextEncoder().encode(data) : data;
137
- } else if (type === 'json') {
138
- return this._loads(typeof data === 'string' ? data : new TextDecoder().decode(data));
139
- } else {
140
- throw new Error(`Unknown serialization type: ${type}`);
141
- }
142
- }
143
- }
@@ -1,30 +0,0 @@
1
- export class EventMessage {
2
- event: string;
3
- data: unknown;
4
- id?: string;
5
- constructor(event: string, data?: unknown) {
6
- this.event = event;
7
- this.data = data;
8
- }
9
- }
10
-
11
- export class CancelEventMessage extends EventMessage {
12
- constructor() {
13
- super('__system_cancel__', 'user cancel this run');
14
- }
15
- }
16
-
17
- export class StreamEndEventMessage extends EventMessage {
18
- constructor() {
19
- super('__stream_end__', 'stream end');
20
- }
21
- }
22
-
23
- export class StreamErrorEventMessage extends EventMessage {
24
- public constructor(error: Error) {
25
- super('__stream_error__', {
26
- error: error.name,
27
- message: error.message,
28
- });
29
- }
30
- }