@langgraph-js/sdk 2.0.1 → 3.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.
- package/README.md +93 -34
- package/dist/LangGraphClient.d.ts +24 -63
- package/dist/LangGraphClient.js +16 -3
- package/dist/TestKit.d.ts +95 -4
- package/dist/client/LanggraphServer.d.ts +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/react/ChatContext.d.ts +61 -0
- package/dist/react/ChatContext.js +49 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +1 -0
- package/dist/time-travel/index.d.ts +11 -0
- package/dist/time-travel/index.js +30 -0
- package/dist/types.d.ts +1 -1
- package/dist/ui-store/createChatStore.d.ts +8 -3
- package/dist/ui-store/createChatStore.js +33 -6
- package/dist/vue/ChatContext.d.ts +161 -0
- package/dist/vue/ChatContext.js +121 -0
- package/dist/vue/index.d.ts +1 -0
- package/dist/vue/index.js +1 -0
- package/package.json +43 -3
- package/src/LangGraphClient.ts +21 -12
- package/src/client/LanggraphServer.ts +2 -2
- package/src/index.ts +0 -1
- package/src/react/ChatContext.ts +81 -0
- package/src/react/index.ts +1 -0
- package/src/time-travel/index.ts +32 -0
- package/src/ui-store/createChatStore.ts +27 -7
- package/src/vue/ChatContext.ts +161 -0
- package/src/vue/index.ts +1 -0
- package/src/types.ts +0 -129
|
@@ -31,7 +31,7 @@ export declare const createChatStore: (initClientName: string, config: Partial<L
|
|
|
31
31
|
onInit?: (client: LangGraphClient) => void;
|
|
32
32
|
}) => {
|
|
33
33
|
data: {
|
|
34
|
-
client: import("nanostores").PreinitializedWritableAtom<LangGraphClient<unknown
|
|
34
|
+
client: import("nanostores").PreinitializedWritableAtom<LangGraphClient<unknown> | null> & object;
|
|
35
35
|
renderMessages: import("nanostores").PreinitializedWritableAtom<RenderMessage[]> & object;
|
|
36
36
|
userInput: import("nanostores").PreinitializedWritableAtom<string> & object;
|
|
37
37
|
loading: import("nanostores").PreinitializedWritableAtom<boolean> & object;
|
|
@@ -52,8 +52,8 @@ export declare const createChatStore: (initClientName: string, config: Partial<L
|
|
|
52
52
|
refreshTools: () => Promise<void>;
|
|
53
53
|
setTools(new_tools: UnionTool<any>[]): void;
|
|
54
54
|
isFELocking(): boolean | undefined;
|
|
55
|
-
initClient: () => Promise<LangGraphClient<unknown
|
|
56
|
-
sendMessage: (message?: Message[], extraData?: SendMessageOptions) => Promise<void>;
|
|
55
|
+
initClient: () => Promise<LangGraphClient<unknown>>;
|
|
56
|
+
sendMessage: (message?: Message[], extraData?: SendMessageOptions, withoutCheck?: boolean) => Promise<void>;
|
|
57
57
|
stopGeneration: () => void;
|
|
58
58
|
toggleToolCollapse: (toolId: string) => void;
|
|
59
59
|
toggleHistoryVisible: () => void;
|
|
@@ -61,6 +61,11 @@ export declare const createChatStore: (initClientName: string, config: Partial<L
|
|
|
61
61
|
addToHistory: (thread: Thread<{
|
|
62
62
|
messages: Message[];
|
|
63
63
|
}>) => void;
|
|
64
|
+
/**
|
|
65
|
+
* @zh 回滚到指定的消息。
|
|
66
|
+
* @en Reverts to the specified message.
|
|
67
|
+
*/
|
|
68
|
+
revertChatTo(messageId: string, resend?: boolean, sendOptions?: SendMessageOptions): Promise<void>;
|
|
64
69
|
/**
|
|
65
70
|
* @zh 设置用户输入内容。
|
|
66
71
|
* @en Sets the user input content.
|
|
@@ -158,15 +158,28 @@ export const createChatStore = (initClientName, config, context = {}) => {
|
|
|
158
158
|
* @zh 发送消息。
|
|
159
159
|
* @en Sends a message.
|
|
160
160
|
*/
|
|
161
|
-
const sendMessage = async (message, extraData) => {
|
|
162
|
-
var _a;
|
|
163
|
-
if ((!userInput.get().trim() && !(message === null || message === void 0 ? void 0 : message.length)) || loading.get() || !client.get())
|
|
161
|
+
const sendMessage = async (message, extraData, withoutCheck = false) => {
|
|
162
|
+
var _a, _b;
|
|
163
|
+
if ((!withoutCheck && !userInput.get().trim() && !(message === null || message === void 0 ? void 0 : message.length)) || loading.get() || !client.get())
|
|
164
164
|
return;
|
|
165
165
|
loading.set(true);
|
|
166
166
|
inChatError.set(null);
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
167
|
+
try {
|
|
168
|
+
await ((_a = client.get()) === null || _a === void 0 ? void 0 : _a.sendMessage(message || userInput.get(), extraData));
|
|
169
|
+
}
|
|
170
|
+
catch (e) {
|
|
171
|
+
const isThreadRunning = e.message.includes("422");
|
|
172
|
+
if (isThreadRunning) {
|
|
173
|
+
await ((_b = client.get()) === null || _b === void 0 ? void 0 : _b.resetStream());
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
throw e;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
finally {
|
|
180
|
+
userInput.set("");
|
|
181
|
+
loading.set(false);
|
|
182
|
+
}
|
|
170
183
|
};
|
|
171
184
|
/**
|
|
172
185
|
* @zh 停止当前的消息生成。
|
|
@@ -259,6 +272,20 @@ export const createChatStore = (initClientName, config, context = {}) => {
|
|
|
259
272
|
toggleHistoryVisible,
|
|
260
273
|
refreshHistoryList,
|
|
261
274
|
addToHistory,
|
|
275
|
+
/**
|
|
276
|
+
* @zh 回滚到指定的消息。
|
|
277
|
+
* @en Reverts to the specified message.
|
|
278
|
+
*/
|
|
279
|
+
async revertChatTo(messageId, resend = false, sendOptions) {
|
|
280
|
+
var _a;
|
|
281
|
+
await ((_a = client.get()) === null || _a === void 0 ? void 0 : _a.revertChatTo(messageId));
|
|
282
|
+
if (resend) {
|
|
283
|
+
return sendMessage([], sendOptions, true);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
updateUI(client.get());
|
|
287
|
+
}
|
|
288
|
+
},
|
|
262
289
|
/**
|
|
263
290
|
* @zh 设置用户输入内容。
|
|
264
291
|
* @en Sets the user input content.
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { type PropType, Ref } from "vue";
|
|
2
|
+
import { createChatStore } from "../ui-store/index.js";
|
|
3
|
+
import { PreinitializedWritableAtom, StoreValue } from "nanostores";
|
|
4
|
+
/**
|
|
5
|
+
* @zh UnionStore 类型用于合并 store 的 data 和 mutations,使其可以直接访问。
|
|
6
|
+
* @en The UnionStore type is used to merge the data and mutations of a store, allowing direct access.
|
|
7
|
+
*/
|
|
8
|
+
export type UnionStoreVue<T extends {
|
|
9
|
+
data: Record<string, PreinitializedWritableAtom<any>>;
|
|
10
|
+
mutations: Record<string, any>;
|
|
11
|
+
}> = {
|
|
12
|
+
[k in keyof T["data"]]: Readonly<Ref<StoreValue<T["data"][k]>>>;
|
|
13
|
+
} & T["mutations"];
|
|
14
|
+
/**
|
|
15
|
+
* @zh useUnionStore Hook 用于将 nanostores 的 store 结构转换为更易于在 UI 组件中使用的扁平结构。
|
|
16
|
+
* @en The useUnionStore Hook is used to transform the nanostores store structure into a flatter structure that is easier to use in UI components.
|
|
17
|
+
*/
|
|
18
|
+
export declare const useUnionStoreVue: <T extends {
|
|
19
|
+
data: Record<string, any>;
|
|
20
|
+
mutations: Record<string, any>;
|
|
21
|
+
}>(store: T, useStore: (store: PreinitializedWritableAtom<any>) => Readonly<Ref<any>>) => UnionStoreVue<T>;
|
|
22
|
+
/**
|
|
23
|
+
* 使用 Chat Store 的组合式函数
|
|
24
|
+
* @throws {Error} 如果在 ChatProvider 外部使用会抛出错误
|
|
25
|
+
*/
|
|
26
|
+
export declare const useChat: () => UnionStoreVue<ReturnType<typeof createChatStore>>;
|
|
27
|
+
export interface ChatProviderProps {
|
|
28
|
+
defaultAgent?: string;
|
|
29
|
+
apiUrl?: string;
|
|
30
|
+
defaultHeaders?: Record<string, string>;
|
|
31
|
+
withCredentials?: boolean;
|
|
32
|
+
showHistory?: boolean;
|
|
33
|
+
showGraph?: boolean;
|
|
34
|
+
onInitError?: (error: any, currentAgent: string) => void;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* @zh Chat Provider Hook,用于在 setup 中直接使用
|
|
38
|
+
* @en Chat Provider Hook, used directly in setup
|
|
39
|
+
*/
|
|
40
|
+
export declare const useChatProvider: (props: ChatProviderProps) => {
|
|
41
|
+
unionStore: UnionStoreVue<{
|
|
42
|
+
data: {
|
|
43
|
+
client: PreinitializedWritableAtom<import("../LangGraphClient.js").LangGraphClient<unknown> | null> & object;
|
|
44
|
+
renderMessages: PreinitializedWritableAtom<import("../LangGraphClient.js").RenderMessage[]> & object;
|
|
45
|
+
userInput: PreinitializedWritableAtom<string> & object;
|
|
46
|
+
loading: PreinitializedWritableAtom<boolean> & object;
|
|
47
|
+
inChatError: PreinitializedWritableAtom<string | null> & object;
|
|
48
|
+
currentAgent: PreinitializedWritableAtom<string> & object;
|
|
49
|
+
collapsedTools: PreinitializedWritableAtom<string[]> & object;
|
|
50
|
+
showHistory: PreinitializedWritableAtom<boolean> & object;
|
|
51
|
+
historyList: PreinitializedWritableAtom<import("@langchain/langgraph-sdk").Thread<{
|
|
52
|
+
messages: import("@langchain/langgraph-sdk").Message[];
|
|
53
|
+
}>[]> & object;
|
|
54
|
+
currentChatId: PreinitializedWritableAtom<string | null> & object;
|
|
55
|
+
showGraph: PreinitializedWritableAtom<boolean> & object;
|
|
56
|
+
graphVisualize: PreinitializedWritableAtom<import("@langchain/langgraph-sdk").AssistantGraph | null> & object;
|
|
57
|
+
currentNodeName: PreinitializedWritableAtom<string> & object;
|
|
58
|
+
tools: PreinitializedWritableAtom<import("../index.js").UnionTool<any, Object, any>[]> & object;
|
|
59
|
+
};
|
|
60
|
+
mutations: {
|
|
61
|
+
refreshTools: () => Promise<void>;
|
|
62
|
+
setTools(new_tools: import("../index.js").UnionTool<any>[]): void;
|
|
63
|
+
isFELocking(): boolean | undefined;
|
|
64
|
+
initClient: () => Promise<import("../LangGraphClient.js").LangGraphClient<unknown>>;
|
|
65
|
+
sendMessage: (message?: import("@langchain/langgraph-sdk").Message[], extraData?: import("../LangGraphClient.js").SendMessageOptions, withoutCheck?: boolean) => Promise<void>;
|
|
66
|
+
stopGeneration: () => void;
|
|
67
|
+
toggleToolCollapse: (toolId: string) => void;
|
|
68
|
+
toggleHistoryVisible: () => void;
|
|
69
|
+
refreshHistoryList: () => Promise<void>;
|
|
70
|
+
addToHistory: (thread: import("@langchain/langgraph-sdk").Thread<{
|
|
71
|
+
messages: import("@langchain/langgraph-sdk").Message[];
|
|
72
|
+
}>) => void;
|
|
73
|
+
revertChatTo(messageId: string, resend?: boolean, sendOptions?: import("../LangGraphClient.js").SendMessageOptions): Promise<void>;
|
|
74
|
+
setUserInput(input: string): void;
|
|
75
|
+
setCurrentAgent(agent: string): Promise<void>;
|
|
76
|
+
toggleGraphVisible(): void;
|
|
77
|
+
refreshGraph: () => Promise<void>;
|
|
78
|
+
createNewChat(): void;
|
|
79
|
+
toHistoryChat(thread: import("@langchain/langgraph-sdk").Thread<{
|
|
80
|
+
messages: import("@langchain/langgraph-sdk").Message[];
|
|
81
|
+
}>): Promise<import("@langchain/langgraph-sdk").Thread<unknown> | undefined>;
|
|
82
|
+
deleteHistoryChat(thread: import("@langchain/langgraph-sdk").Thread<{
|
|
83
|
+
messages: import("@langchain/langgraph-sdk").Message[];
|
|
84
|
+
}>): Promise<void>;
|
|
85
|
+
getToolUIRender: (tool_name: string) => ((message: import("../LangGraphClient.js").RenderMessage) => Object) | null;
|
|
86
|
+
};
|
|
87
|
+
}>;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Chat Provider 组件
|
|
91
|
+
* 提供 Chat Store 的上下文
|
|
92
|
+
*/
|
|
93
|
+
export declare const ChatProvider: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
94
|
+
defaultAgent: {
|
|
95
|
+
type: PropType<string>;
|
|
96
|
+
default: string;
|
|
97
|
+
};
|
|
98
|
+
apiUrl: {
|
|
99
|
+
type: PropType<string>;
|
|
100
|
+
default: string;
|
|
101
|
+
};
|
|
102
|
+
defaultHeaders: {
|
|
103
|
+
type: PropType<Record<string, string>>;
|
|
104
|
+
default: () => {};
|
|
105
|
+
};
|
|
106
|
+
withCredentials: {
|
|
107
|
+
type: PropType<boolean>;
|
|
108
|
+
default: boolean;
|
|
109
|
+
};
|
|
110
|
+
showHistory: {
|
|
111
|
+
type: PropType<boolean>;
|
|
112
|
+
default: boolean;
|
|
113
|
+
};
|
|
114
|
+
showGraph: {
|
|
115
|
+
type: PropType<boolean>;
|
|
116
|
+
default: boolean;
|
|
117
|
+
};
|
|
118
|
+
onInitError: {
|
|
119
|
+
type: PropType<(error: any, currentAgent: string) => void>;
|
|
120
|
+
default: undefined;
|
|
121
|
+
};
|
|
122
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
123
|
+
[key: string]: any;
|
|
124
|
+
}>[] | undefined, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
125
|
+
defaultAgent: {
|
|
126
|
+
type: PropType<string>;
|
|
127
|
+
default: string;
|
|
128
|
+
};
|
|
129
|
+
apiUrl: {
|
|
130
|
+
type: PropType<string>;
|
|
131
|
+
default: string;
|
|
132
|
+
};
|
|
133
|
+
defaultHeaders: {
|
|
134
|
+
type: PropType<Record<string, string>>;
|
|
135
|
+
default: () => {};
|
|
136
|
+
};
|
|
137
|
+
withCredentials: {
|
|
138
|
+
type: PropType<boolean>;
|
|
139
|
+
default: boolean;
|
|
140
|
+
};
|
|
141
|
+
showHistory: {
|
|
142
|
+
type: PropType<boolean>;
|
|
143
|
+
default: boolean;
|
|
144
|
+
};
|
|
145
|
+
showGraph: {
|
|
146
|
+
type: PropType<boolean>;
|
|
147
|
+
default: boolean;
|
|
148
|
+
};
|
|
149
|
+
onInitError: {
|
|
150
|
+
type: PropType<(error: any, currentAgent: string) => void>;
|
|
151
|
+
default: undefined;
|
|
152
|
+
};
|
|
153
|
+
}>> & Readonly<{}>, {
|
|
154
|
+
apiUrl: string;
|
|
155
|
+
defaultHeaders: Record<string, string>;
|
|
156
|
+
showHistory: boolean;
|
|
157
|
+
showGraph: boolean;
|
|
158
|
+
defaultAgent: string;
|
|
159
|
+
withCredentials: boolean;
|
|
160
|
+
onInitError: (error: any, currentAgent: string) => void;
|
|
161
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { defineComponent, inject, provide, onMounted } from "vue";
|
|
2
|
+
import { createChatStore } from "../ui-store/index.js";
|
|
3
|
+
import { useStore } from "@nanostores/vue";
|
|
4
|
+
/**
|
|
5
|
+
* @zh useUnionStore Hook 用于将 nanostores 的 store 结构转换为更易于在 UI 组件中使用的扁平结构。
|
|
6
|
+
* @en The useUnionStore Hook is used to transform the nanostores store structure into a flatter structure that is easier to use in UI components.
|
|
7
|
+
*/
|
|
8
|
+
export const useUnionStoreVue = (store, useStore) => {
|
|
9
|
+
const data = Object.fromEntries(Object.entries(store.data).map(([key, value]) => {
|
|
10
|
+
return [key, useStore(value)];
|
|
11
|
+
}));
|
|
12
|
+
return {
|
|
13
|
+
...data,
|
|
14
|
+
...store.mutations,
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
// 定义注入的 key,提供完整类型
|
|
18
|
+
const ChatContextKey = Symbol("ChatContext");
|
|
19
|
+
/**
|
|
20
|
+
* 使用 Chat Store 的组合式函数
|
|
21
|
+
* @throws {Error} 如果在 ChatProvider 外部使用会抛出错误
|
|
22
|
+
*/
|
|
23
|
+
export const useChat = () => {
|
|
24
|
+
const context = inject(ChatContextKey);
|
|
25
|
+
if (!context) {
|
|
26
|
+
throw new Error("useChat must be used within a ChatProvider");
|
|
27
|
+
}
|
|
28
|
+
return context;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* @zh Chat Provider Hook,用于在 setup 中直接使用
|
|
32
|
+
* @en Chat Provider Hook, used directly in setup
|
|
33
|
+
*/
|
|
34
|
+
export const useChatProvider = (props) => {
|
|
35
|
+
const F = props.withCredentials
|
|
36
|
+
? (url, options) => {
|
|
37
|
+
options.credentials = "include";
|
|
38
|
+
return fetch(url, options);
|
|
39
|
+
}
|
|
40
|
+
: fetch;
|
|
41
|
+
const store = createChatStore(props.defaultAgent || "", {
|
|
42
|
+
apiUrl: props.apiUrl,
|
|
43
|
+
defaultHeaders: props.defaultHeaders,
|
|
44
|
+
callerOptions: {
|
|
45
|
+
fetch: F,
|
|
46
|
+
maxRetries: 1,
|
|
47
|
+
},
|
|
48
|
+
}, {
|
|
49
|
+
showHistory: props.showHistory,
|
|
50
|
+
showGraph: props.showGraph,
|
|
51
|
+
});
|
|
52
|
+
const unionStore = useUnionStoreVue(store, useStore);
|
|
53
|
+
// 提供 store 给子组件
|
|
54
|
+
provide(ChatContextKey, unionStore);
|
|
55
|
+
// 初始化客户端
|
|
56
|
+
onMounted(() => {
|
|
57
|
+
unionStore
|
|
58
|
+
.initClient()
|
|
59
|
+
.then(() => {
|
|
60
|
+
if (unionStore.showHistory) {
|
|
61
|
+
unionStore.refreshHistoryList();
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
.catch((err) => {
|
|
65
|
+
console.error(err);
|
|
66
|
+
if (props.onInitError) {
|
|
67
|
+
props.onInitError(err, unionStore.currentAgent.value);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
return {
|
|
72
|
+
unionStore,
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Chat Provider 组件
|
|
77
|
+
* 提供 Chat Store 的上下文
|
|
78
|
+
*/
|
|
79
|
+
export const ChatProvider = defineComponent({
|
|
80
|
+
name: "ChatProvider",
|
|
81
|
+
props: {
|
|
82
|
+
defaultAgent: {
|
|
83
|
+
type: String,
|
|
84
|
+
default: "",
|
|
85
|
+
},
|
|
86
|
+
apiUrl: {
|
|
87
|
+
type: String,
|
|
88
|
+
default: "http://localhost:8123",
|
|
89
|
+
},
|
|
90
|
+
defaultHeaders: {
|
|
91
|
+
type: Object,
|
|
92
|
+
default: () => ({}),
|
|
93
|
+
},
|
|
94
|
+
withCredentials: {
|
|
95
|
+
type: Boolean,
|
|
96
|
+
default: false,
|
|
97
|
+
},
|
|
98
|
+
showHistory: {
|
|
99
|
+
type: Boolean,
|
|
100
|
+
default: false,
|
|
101
|
+
},
|
|
102
|
+
showGraph: {
|
|
103
|
+
type: Boolean,
|
|
104
|
+
default: false,
|
|
105
|
+
},
|
|
106
|
+
onInitError: {
|
|
107
|
+
type: Function,
|
|
108
|
+
default: undefined,
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
setup(props, { slots }) {
|
|
112
|
+
const { unionStore } = useChatProvider(props);
|
|
113
|
+
defineExpose({
|
|
114
|
+
unionStore,
|
|
115
|
+
});
|
|
116
|
+
return () => {
|
|
117
|
+
var _a;
|
|
118
|
+
return (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots);
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./ChatContext.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./ChatContext.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@langgraph-js/sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "The UI SDK for LangGraph - seamlessly integrate your AI agents with frontend interfaces",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -8,6 +8,20 @@
|
|
|
8
8
|
"registry": "https://registry.npmjs.org/",
|
|
9
9
|
"access": "public"
|
|
10
10
|
},
|
|
11
|
+
"exports": {
|
|
12
|
+
"./react": {
|
|
13
|
+
"import": "./dist/react/index.js",
|
|
14
|
+
"types": "./dist/react/index.d.ts"
|
|
15
|
+
},
|
|
16
|
+
"./vue": {
|
|
17
|
+
"import": "./dist/vue/index.js",
|
|
18
|
+
"types": "./dist/vue/index.d.ts"
|
|
19
|
+
},
|
|
20
|
+
".": {
|
|
21
|
+
"import": "./dist/index.js",
|
|
22
|
+
"types": "./dist/index.d.ts"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
11
25
|
"keywords": [
|
|
12
26
|
"langgraph",
|
|
13
27
|
"ui",
|
|
@@ -16,7 +30,8 @@
|
|
|
16
30
|
"ai",
|
|
17
31
|
"agents",
|
|
18
32
|
"langchain",
|
|
19
|
-
"react"
|
|
33
|
+
"react",
|
|
34
|
+
"vue"
|
|
20
35
|
],
|
|
21
36
|
"author": "LangGraph Team",
|
|
22
37
|
"license": "Apache-2.0",
|
|
@@ -29,7 +44,8 @@
|
|
|
29
44
|
"url": "https://github.com/KonghaYao/YaoAgent/issues"
|
|
30
45
|
},
|
|
31
46
|
"dependencies": {
|
|
32
|
-
"@langchain/langgraph-sdk": "^0.
|
|
47
|
+
"@langchain/langgraph-sdk": "^0.1.10",
|
|
48
|
+
"@langgraph-js/pure-graph": "^1.5.2",
|
|
33
49
|
"eventemitter3": "^5.0.1",
|
|
34
50
|
"jsonrepair": "^3.12.0",
|
|
35
51
|
"nanostores": "^1.0.1",
|
|
@@ -37,6 +53,30 @@
|
|
|
37
53
|
"zod": "^3.25.17",
|
|
38
54
|
"zod-to-json-schema": "^3.24.5"
|
|
39
55
|
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@nanostores/react": "^1.0.0",
|
|
58
|
+
"@nanostores/vue": "^1.0.0",
|
|
59
|
+
"react": "^19||^18",
|
|
60
|
+
"vue": "^3.0.0"
|
|
61
|
+
},
|
|
62
|
+
"peerDependenciesMeta": {
|
|
63
|
+
"@nanostores/react": {
|
|
64
|
+
"optional": true
|
|
65
|
+
},
|
|
66
|
+
"@nanostores/vue": {
|
|
67
|
+
"optional": true
|
|
68
|
+
},
|
|
69
|
+
"react": {
|
|
70
|
+
"optional": true
|
|
71
|
+
},
|
|
72
|
+
"vue": {
|
|
73
|
+
"optional": true
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"devDependencies": {
|
|
77
|
+
"@types/react": "^19.1.6",
|
|
78
|
+
"vue": "^3.5.14"
|
|
79
|
+
},
|
|
40
80
|
"scripts": {
|
|
41
81
|
"build": "tsc",
|
|
42
82
|
"prepublish": "pnpm build"
|
package/src/LangGraphClient.ts
CHANGED
|
@@ -2,8 +2,9 @@ import type { Thread, Message, Assistant, HumanMessage, AIMessage, ToolMessage,
|
|
|
2
2
|
import { EventEmitter } from "eventemitter3";
|
|
3
3
|
import { ToolManager } from "./ToolManager.js";
|
|
4
4
|
import { CallToolResult } from "./tool/createTool.js";
|
|
5
|
-
import { ILangGraphClient } from "
|
|
5
|
+
import { type ILangGraphClient } from "@langgraph-js/pure-graph/dist/types.js";
|
|
6
6
|
import { MessageProcessor } from "./MessageProcessor.js";
|
|
7
|
+
import { revertChatTo } from "./time-travel/index.js";
|
|
7
8
|
|
|
8
9
|
export type RenderMessage = Message & {
|
|
9
10
|
/** 对于 AIMessage 来说是节点名称,对于工具节点来说是工具名称 */
|
|
@@ -68,7 +69,7 @@ export interface LangGraphClientConfig {
|
|
|
68
69
|
timeoutMs?: number;
|
|
69
70
|
defaultHeaders?: Record<string, string | null | undefined>;
|
|
70
71
|
/** 自定义客户端实现,如果不提供则使用官方 Client */
|
|
71
|
-
client: ILangGraphClient<any
|
|
72
|
+
client: ILangGraphClient<any>;
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
// 定义事件数据类型
|
|
@@ -91,8 +92,8 @@ export interface LangGraphEvents {
|
|
|
91
92
|
* @zh LangGraphClient 类是与 LangGraph 后端交互的主要客户端。
|
|
92
93
|
* @en The LangGraphClient class is the main client for interacting with the LangGraph backend.
|
|
93
94
|
*/
|
|
94
|
-
export class LangGraphClient<TStateType = unknown
|
|
95
|
-
private client: ILangGraphClient<TStateType
|
|
95
|
+
export class LangGraphClient<TStateType = unknown> extends EventEmitter<LangGraphEvents> {
|
|
96
|
+
private client: ILangGraphClient<TStateType>;
|
|
96
97
|
private currentAssistant: Assistant | null = null;
|
|
97
98
|
private currentThread: Thread<TStateType> | null = null;
|
|
98
99
|
tools: ToolManager = new ToolManager();
|
|
@@ -122,7 +123,7 @@ export class LangGraphClient<TStateType = unknown, TUpdateType = TStateType> ext
|
|
|
122
123
|
}
|
|
123
124
|
|
|
124
125
|
/** 代理 runs 属性到内部 client */
|
|
125
|
-
get runs() {
|
|
126
|
+
get runs(): ILangGraphClient["runs"] {
|
|
126
127
|
return this.client.runs;
|
|
127
128
|
}
|
|
128
129
|
private listAssistants() {
|
|
@@ -162,14 +163,11 @@ export class LangGraphClient<TStateType = unknown, TUpdateType = TStateType> ext
|
|
|
162
163
|
* @zh 创建一个新的 Thread。
|
|
163
164
|
* @en Creates a new Thread.
|
|
164
165
|
*/
|
|
165
|
-
async createThread({
|
|
166
|
-
threadId,
|
|
167
|
-
}: {
|
|
168
|
-
threadId?: string;
|
|
169
|
-
} = {}) {
|
|
166
|
+
async createThread({ threadId, graphId }: { threadId?: string; graphId?: string } = {}) {
|
|
170
167
|
try {
|
|
171
168
|
this.currentThread = await this.threads.create({
|
|
172
169
|
threadId,
|
|
170
|
+
graphId,
|
|
173
171
|
});
|
|
174
172
|
return this.currentThread;
|
|
175
173
|
} catch (error) {
|
|
@@ -284,6 +282,17 @@ export class LangGraphClient<TStateType = unknown, TUpdateType = TStateType> ext
|
|
|
284
282
|
this.runs.cancel((this.currentThread as any)!.thread_id, this.currentRun.run_id);
|
|
285
283
|
}
|
|
286
284
|
}
|
|
285
|
+
/**
|
|
286
|
+
* @zh 回滚到指定的消息。但是不会触发数据的重新更新
|
|
287
|
+
* @en Reverts to the specified message.
|
|
288
|
+
*/
|
|
289
|
+
async revertChatTo(messageId: string) {
|
|
290
|
+
const { state, checkpoint } = await revertChatTo(this.client as any, this.currentThread!.thread_id, messageId);
|
|
291
|
+
this.graphState = state;
|
|
292
|
+
this.messageProcessor.clearStreamingMessages();
|
|
293
|
+
this.messageProcessor.setGraphMessages(state.messages! as RenderMessage[]);
|
|
294
|
+
return state;
|
|
295
|
+
}
|
|
287
296
|
/**
|
|
288
297
|
* @zh 发送消息到 LangGraph 后端。
|
|
289
298
|
* @en Sends a message to the LangGraph backend.
|
|
@@ -293,7 +302,7 @@ export class LangGraphClient<TStateType = unknown, TUpdateType = TStateType> ext
|
|
|
293
302
|
throw new Error("Thread or Assistant not initialized");
|
|
294
303
|
}
|
|
295
304
|
if (!this.currentThread) {
|
|
296
|
-
await this.createThread();
|
|
305
|
+
await this.createThread({ graphId: this.currentAssistant!.graph_id!, threadId: this.currentThread!.thread_id! });
|
|
297
306
|
this.emit("thread", {
|
|
298
307
|
event: "thread/create",
|
|
299
308
|
data: {
|
|
@@ -341,7 +350,7 @@ export class LangGraphClient<TStateType = unknown, TUpdateType = TStateType> ext
|
|
|
341
350
|
streamRecord.push(chunk);
|
|
342
351
|
if (chunk.event === "metadata") {
|
|
343
352
|
this.currentRun = chunk.data;
|
|
344
|
-
} else if (chunk.event === "error") {
|
|
353
|
+
} else if (chunk.event === "error" || chunk.event === "Error" || chunk.event === "__stream_error__") {
|
|
345
354
|
this.emit("error", chunk);
|
|
346
355
|
} else if (chunk.event === "messages/partial") {
|
|
347
356
|
for (const message of chunk.data) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LangGraphClientConfig } from "../LangGraphClient.js";
|
|
2
|
-
import { ILangGraphClient } from "
|
|
2
|
+
import { type ILangGraphClient } from "@langgraph-js/pure-graph/dist/types.js";
|
|
3
3
|
|
|
4
4
|
export const createLangGraphServerClient = async (config: LangGraphClientConfig): Promise<ILangGraphClient> => {
|
|
5
5
|
const { Client } = await import("@langchain/langgraph-sdk");
|
|
6
|
-
return new Client(config) as
|
|
6
|
+
return new Client(config) as ILangGraphClient;
|
|
7
7
|
};
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { createElement, createContext, useContext, useMemo, ReactNode, useEffect } from "react";
|
|
2
|
+
|
|
3
|
+
import { createChatStore, UnionStore, useUnionStore } from "../ui-store/index.js";
|
|
4
|
+
import { useStore } from "@nanostores/react";
|
|
5
|
+
|
|
6
|
+
const ChatContext = createContext<UnionStore<ReturnType<typeof createChatStore>> | undefined>(undefined);
|
|
7
|
+
|
|
8
|
+
export const useChat = () => {
|
|
9
|
+
const context = useContext(ChatContext);
|
|
10
|
+
if (!context) {
|
|
11
|
+
throw new Error("useChat must be used within a ChatProvider");
|
|
12
|
+
}
|
|
13
|
+
return context;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
interface ChatProviderProps {
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
defaultAgent?: string;
|
|
19
|
+
apiUrl?: string;
|
|
20
|
+
defaultHeaders?: Record<string, string>;
|
|
21
|
+
withCredentials?: boolean;
|
|
22
|
+
showHistory?: boolean;
|
|
23
|
+
showGraph?: boolean;
|
|
24
|
+
onInitError?: (error: any, currentAgent: string) => void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const ChatProvider: React.FC<ChatProviderProps> = ({
|
|
28
|
+
children,
|
|
29
|
+
defaultAgent = "",
|
|
30
|
+
apiUrl = "http://localhost:8123",
|
|
31
|
+
defaultHeaders = {},
|
|
32
|
+
withCredentials = false,
|
|
33
|
+
showHistory = false,
|
|
34
|
+
showGraph = false,
|
|
35
|
+
onInitError,
|
|
36
|
+
}) => {
|
|
37
|
+
const store = useMemo(() => {
|
|
38
|
+
const F = withCredentials
|
|
39
|
+
? (url: string, options: RequestInit) => {
|
|
40
|
+
options.credentials = "include";
|
|
41
|
+
return fetch(url, options);
|
|
42
|
+
}
|
|
43
|
+
: fetch;
|
|
44
|
+
|
|
45
|
+
return createChatStore(
|
|
46
|
+
defaultAgent,
|
|
47
|
+
{
|
|
48
|
+
apiUrl,
|
|
49
|
+
defaultHeaders,
|
|
50
|
+
callerOptions: {
|
|
51
|
+
fetch: F,
|
|
52
|
+
maxRetries: 1,
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
showHistory,
|
|
57
|
+
showGraph,
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
}, [defaultAgent, apiUrl, defaultHeaders, withCredentials, showHistory, showGraph]);
|
|
61
|
+
|
|
62
|
+
const unionStore = useUnionStore(store, useStore);
|
|
63
|
+
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
unionStore
|
|
66
|
+
.initClient()
|
|
67
|
+
.then((res) => {
|
|
68
|
+
if (unionStore.showHistory) {
|
|
69
|
+
unionStore.refreshHistoryList();
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
.catch((err) => {
|
|
73
|
+
console.error(err);
|
|
74
|
+
if (onInitError) {
|
|
75
|
+
onInitError(err, unionStore.currentAgent);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}, [unionStore, onInitError]);
|
|
79
|
+
|
|
80
|
+
return createElement(ChatContext.Provider, { value: unionStore }, children);
|
|
81
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./ChatContext.js";
|