@langgraph-js/ui 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +6 -6
  3. package/cli.mjs +36 -36
  4. package/dist/assets/{index-Du4LMUX2.css → index-BlHtM5cu.css} +1 -1
  5. package/dist/assets/index-C7SfDwhG.js +192 -0
  6. package/dist/index.html +14 -14
  7. package/index.html +22 -22
  8. package/package.json +8 -9
  9. package/src/chat/Chat.tsx +151 -164
  10. package/src/chat/FileUpload/index.ts +105 -105
  11. package/src/chat/chat.css +403 -403
  12. package/src/chat/components/FileList.css +128 -128
  13. package/src/chat/components/FileList.tsx +73 -73
  14. package/src/chat/components/HistoryList.tsx +192 -192
  15. package/src/chat/components/JsonEditorPopup.css +80 -80
  16. package/src/chat/components/JsonEditorPopup.tsx +56 -56
  17. package/src/chat/components/JsonToMessage/JsonToMessage.css +104 -0
  18. package/src/chat/components/JsonToMessage/JsonToMessage.tsx +114 -0
  19. package/src/chat/components/JsonToMessage/JsonToMessageButton.tsx +27 -0
  20. package/src/chat/components/JsonToMessage/index.tsx +5 -0
  21. package/src/chat/components/MessageAI.tsx +24 -24
  22. package/src/chat/components/MessageBox.tsx +39 -0
  23. package/src/chat/components/MessageHuman.tsx +55 -55
  24. package/src/chat/components/MessageTool.tsx +46 -46
  25. package/src/chat/components/UsageMetadata.tsx +40 -40
  26. package/src/chat/context/ChatContext.tsx +31 -29
  27. package/src/chat/context/ExtraParamsContext.tsx +41 -41
  28. package/src/chat/store/index.ts +25 -24
  29. package/src/chat/tools.ts +33 -33
  30. package/src/chat/types.ts +16 -16
  31. package/src/hooks/useLocalStorage.ts +27 -27
  32. package/src/index.ts +1 -1
  33. package/src/login/Login.css +93 -93
  34. package/src/login/Login.tsx +92 -92
  35. package/test/App.tsx +9 -9
  36. package/test/main.tsx +5 -5
  37. package/test/vite-env.d.ts +1 -1
  38. package/tsconfig.json +21 -21
  39. package/tsconfig.node.json +9 -9
  40. package/vite.config.ts +17 -17
  41. package/dist/assets/index-BHPbGlnP.js +0 -192
@@ -1,29 +1,31 @@
1
- import React, { createContext, useContext, useState, useCallback, ReactNode, useEffect } from "react";
2
- type ChatContextType = UnionStore<typeof globalChatStore>;
3
-
4
- const ChatContext = createContext<ChatContextType | undefined>(undefined);
5
-
6
- export const useChat = () => {
7
- const context = useContext(ChatContext);
8
- if (!context) {
9
- throw new Error("useChat must be used within a ChatProvider");
10
- }
11
- return context;
12
- };
13
-
14
- interface ChatProviderProps {
15
- children: ReactNode;
16
- }
17
- import { globalChatStore } from "../store";
18
- import { UnionStore, useUnionStore } from "@langgraph-js/sdk";
19
- import { useStore } from "@nanostores/react";
20
- export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
21
- const store = useUnionStore(globalChatStore, useStore);
22
- useEffect(() => {
23
- store.initClient().then((res) => {
24
- store.refreshHistoryList();
25
- });
26
- }, [store.currentAgent]);
27
-
28
- return <ChatContext.Provider value={store}>{children}</ChatContext.Provider>;
29
- };
1
+ import React, { createContext, useContext, useState, useCallback, ReactNode, useEffect } from "react";
2
+ type ChatContextType = UnionStore<typeof globalChatStore>;
3
+
4
+ const ChatContext = createContext<ChatContextType | undefined>(undefined);
5
+
6
+ export const useChat = () => {
7
+ const context = useContext(ChatContext);
8
+ if (!context) {
9
+ throw new Error("useChat must be used within a ChatProvider");
10
+ }
11
+ return context;
12
+ };
13
+
14
+ interface ChatProviderProps {
15
+ children: ReactNode;
16
+ }
17
+ import { globalChatStore } from "../store";
18
+ import { UnionStore, useUnionStore } from "@langgraph-js/sdk";
19
+ import { useStore } from "@nanostores/react";
20
+ export const ChatProvider: React.FC<ChatProviderProps> = ({ children }) => {
21
+ const store = useUnionStore(globalChatStore, useStore);
22
+ useEffect(() => {
23
+ store.initClient().then((res) => {
24
+ if (store.showHistory) {
25
+ store.refreshHistoryList();
26
+ }
27
+ });
28
+ }, []);
29
+
30
+ return <ChatContext.Provider value={store}>{children}</ChatContext.Provider>;
31
+ };
@@ -1,42 +1,42 @@
1
- import React, { createContext, useState, useEffect, useContext, ReactNode } from 'react';
2
-
3
- interface ExtraParamsContextType {
4
- extraParams: object;
5
- setExtraParams: (params: object) => void;
6
- }
7
-
8
- const ExtraParamsContext = createContext<ExtraParamsContextType | undefined>(undefined);
9
-
10
- export const ExtraParamsProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
11
- const [extraParams, setExtraParamsState] = useState<object>(() => {
12
- const savedParams = localStorage.getItem("extraParams");
13
- try {
14
- return savedParams ? JSON.parse(savedParams) : {};
15
- } catch (e) {
16
- console.error("Failed to parse extraParams from localStorage", e);
17
- return {};
18
- }
19
- });
20
-
21
- useEffect(() => {
22
- localStorage.setItem("extraParams", JSON.stringify(extraParams));
23
- }, [extraParams]);
24
-
25
- const setExtraParams = (params: object) => {
26
- setExtraParamsState(params);
27
- };
28
-
29
- return (
30
- <ExtraParamsContext.Provider value={{ extraParams, setExtraParams }}>
31
- {children}
32
- </ExtraParamsContext.Provider>
33
- );
34
- };
35
-
36
- export const useExtraParams = (): ExtraParamsContextType => {
37
- const context = useContext(ExtraParamsContext);
38
- if (context === undefined) {
39
- throw new Error('useExtraParams must be used within an ExtraParamsProvider');
40
- }
41
- return context;
1
+ import React, { createContext, useState, useEffect, useContext, ReactNode } from 'react';
2
+
3
+ interface ExtraParamsContextType {
4
+ extraParams: object;
5
+ setExtraParams: (params: object) => void;
6
+ }
7
+
8
+ const ExtraParamsContext = createContext<ExtraParamsContextType | undefined>(undefined);
9
+
10
+ export const ExtraParamsProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
11
+ const [extraParams, setExtraParamsState] = useState<object>(() => {
12
+ const savedParams = localStorage.getItem("extraParams");
13
+ try {
14
+ return savedParams ? JSON.parse(savedParams) : {};
15
+ } catch (e) {
16
+ console.error("Failed to parse extraParams from localStorage", e);
17
+ return {};
18
+ }
19
+ });
20
+
21
+ useEffect(() => {
22
+ localStorage.setItem("extraParams", JSON.stringify(extraParams));
23
+ }, [extraParams]);
24
+
25
+ const setExtraParams = (params: object) => {
26
+ setExtraParamsState(params);
27
+ };
28
+
29
+ return (
30
+ <ExtraParamsContext.Provider value={{ extraParams, setExtraParams }}>
31
+ {children}
32
+ </ExtraParamsContext.Provider>
33
+ );
34
+ };
35
+
36
+ export const useExtraParams = (): ExtraParamsContextType => {
37
+ const context = useContext(ExtraParamsContext);
38
+ if (context === undefined) {
39
+ throw new Error('useExtraParams must be used within an ExtraParamsProvider');
40
+ }
41
+ return context;
42
42
  };
@@ -1,24 +1,25 @@
1
- import { createChatStore } from "@langgraph-js/sdk";
2
- const F =
3
- localStorage.getItem("withCredentials") === "true"
4
- ? (url: string, options: RequestInit) => {
5
- options.credentials = "include";
6
- return fetch(url, options);
7
- }
8
- : fetch;
9
- export const globalChatStore = createChatStore(
10
- "agent",
11
- {
12
- apiUrl: localStorage.getItem("apiUrl") || "http://localhost:8123",
13
- defaultHeaders: JSON.parse(localStorage.getItem("code") || "{}"),
14
- callerOptions: {
15
- // 携带 cookie 的写法
16
- fetch: F,
17
- },
18
- },
19
- {
20
- onInit(client) {
21
- client.tools.bindTools([]);
22
- },
23
- }
24
- );
1
+ import { createChatStore } from "@langgraph-js/sdk";
2
+ const F =
3
+ localStorage.getItem("withCredentials") === "true"
4
+ ? (url: string, options: RequestInit) => {
5
+ options.credentials = "include";
6
+ return fetch(url, options);
7
+ }
8
+ : fetch;
9
+
10
+ export const globalChatStore = createChatStore(
11
+ localStorage.getItem("agent_name") || "",
12
+ {
13
+ apiUrl: localStorage.getItem("apiUrl") || "http://localhost:8123",
14
+ defaultHeaders: JSON.parse(localStorage.getItem("code") || "{}"),
15
+ callerOptions: {
16
+ // 携带 cookie 的写法
17
+ fetch: F,
18
+ },
19
+ },
20
+ {
21
+ onInit(client) {
22
+ client.tools.bindTools([]);
23
+ },
24
+ }
25
+ );
package/src/chat/tools.ts CHANGED
@@ -1,33 +1,33 @@
1
- import { createFETool, ToolManager } from "@langgraph-js/sdk";
2
-
3
- // 文件操作工具
4
- export const fileTool = createFETool({
5
- name: "file_operation",
6
- description: "执行文件操作,包括读取和写入",
7
- parameters: [
8
- {
9
- name: "filePath",
10
- type: "string",
11
- description: "文件的完整路径",
12
- },
13
- ],
14
- returnDirect: true,
15
- callbackMessage: () => [{ type: "ai", content: "工作完成" }],
16
- async handler(args) {
17
- await new Promise((resolve) => setTimeout(resolve, 3000));
18
- return [{ type: "text", text: "执行文件操作 " + args.filePath }];
19
- },
20
- });
21
-
22
- export const askUserTool = createFETool({
23
- name: "ask_user",
24
- description: "询问用户",
25
- parameters: [
26
- {
27
- name: "question",
28
- type: "string",
29
- description: "问题",
30
- },
31
- ],
32
- handler: ToolManager.waitForUIDone,
33
- });
1
+ import { createFETool, ToolManager } from "@langgraph-js/sdk";
2
+
3
+ // 文件操作工具
4
+ export const fileTool = createFETool({
5
+ name: "file_operation",
6
+ description: "执行文件操作,包括读取和写入",
7
+ parameters: [
8
+ {
9
+ name: "filePath",
10
+ type: "string",
11
+ description: "文件的完整路径",
12
+ },
13
+ ],
14
+ returnDirect: true,
15
+ callbackMessage: () => [{ type: "ai", content: "工作完成" }],
16
+ async handler(args) {
17
+ await new Promise((resolve) => setTimeout(resolve, 3000));
18
+ return [{ type: "text", text: "执行文件操作 " + args.filePath }];
19
+ },
20
+ });
21
+
22
+ export const askUserTool = createFETool({
23
+ name: "ask_user",
24
+ description: "询问用户",
25
+ parameters: [
26
+ {
27
+ name: "question",
28
+ type: "string",
29
+ description: "问题",
30
+ },
31
+ ],
32
+ handler: ToolManager.waitForUIDone,
33
+ });
package/src/chat/types.ts CHANGED
@@ -1,16 +1,16 @@
1
- export interface Message {
2
- content: string;
3
- role: string;
4
- name?: string;
5
- metadata?: {
6
- graph_id?: string;
7
- };
8
- thread_id?: string;
9
- usage_metadata?: {
10
- input_tokens: number;
11
- output_tokens: number;
12
- total_tokens: number;
13
- };
14
- spend_time?: number;
15
- tool_input?: string;
16
- }
1
+ export interface Message {
2
+ content: string;
3
+ role: string;
4
+ name?: string;
5
+ metadata?: {
6
+ graph_id?: string;
7
+ };
8
+ thread_id?: string;
9
+ usage_metadata?: {
10
+ input_tokens: number;
11
+ output_tokens: number;
12
+ total_tokens: number;
13
+ };
14
+ spend_time?: number;
15
+ tool_input?: string;
16
+ }
@@ -1,27 +1,27 @@
1
- import { useState, useEffect } from "react";
2
-
3
- function useLocalStorage<T>(key: string, initialValue: T) {
4
- // 从 localStorage 获取初始值
5
- const [storedValue, setStoredValue] = useState<T>(() => {
6
- try {
7
- const item = window.localStorage.getItem(key);
8
- return item ? JSON.parse(item) : initialValue;
9
- } catch (error) {
10
- console.error("Error reading from localStorage:", error);
11
- return initialValue;
12
- }
13
- });
14
-
15
- // 当值改变时,自动同步到 localStorage
16
- useEffect(() => {
17
- try {
18
- window.localStorage.setItem(key, JSON.stringify(storedValue));
19
- } catch (error) {
20
- console.error("Error writing to localStorage:", error);
21
- }
22
- }, [key, storedValue]);
23
-
24
- return [storedValue, setStoredValue] as const;
25
- }
26
-
27
- export default useLocalStorage;
1
+ import { useState, useEffect } from "react";
2
+
3
+ function useLocalStorage<T>(key: string, initialValue: T) {
4
+ // 从 localStorage 获取初始值
5
+ const [storedValue, setStoredValue] = useState<T>(() => {
6
+ try {
7
+ const item = window.localStorage.getItem(key);
8
+ return item ? JSON.parse(item) : initialValue;
9
+ } catch (error) {
10
+ console.error("Error reading from localStorage:", error);
11
+ return initialValue;
12
+ }
13
+ });
14
+
15
+ // 当值改变时,自动同步到 localStorage
16
+ useEffect(() => {
17
+ try {
18
+ window.localStorage.setItem(key, JSON.stringify(storedValue));
19
+ } catch (error) {
20
+ console.error("Error writing to localStorage:", error);
21
+ }
22
+ }, [key, storedValue]);
23
+
24
+ return [storedValue, setStoredValue] as const;
25
+ }
26
+
27
+ export default useLocalStorage;
package/src/index.ts CHANGED
@@ -1 +1 @@
1
- export { default as Chat } from "./chat/Chat";
1
+ export { default as Chat } from "./chat/Chat";
@@ -1,93 +1,93 @@
1
- .login-container {
2
- max-width: 600px;
3
- margin: 2rem auto;
4
- padding: 2rem;
5
- background: #fff;
6
- border-radius: 8px;
7
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
8
- }
9
-
10
- .header-group {
11
- display: flex;
12
- gap: 1rem;
13
- align-items: flex-start;
14
- padding: 1rem;
15
- background: #f8f9fa;
16
- border-radius: 4px;
17
- position: relative;
18
- }
19
-
20
- .form-group {
21
- flex: 1;
22
- }
23
-
24
- .form-group label {
25
- display: block;
26
- margin-bottom: 0.5rem;
27
- color: #333;
28
- font-weight: 500;
29
- }
30
-
31
- .form-group input {
32
- width: 100%;
33
- padding: 0.5rem;
34
- border: 1px solid #ddd;
35
- border-radius: 4px;
36
- font-size: 1rem;
37
- }
38
-
39
- .form-group input:focus {
40
- outline: none;
41
- border-color: #007bff;
42
- box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
43
- }
44
-
45
- .button-group {
46
- display: flex;
47
- gap: 1rem;
48
- margin-top: 1rem;
49
- }
50
-
51
- button {
52
- padding: 0.5rem 1rem;
53
- border: none;
54
- border-radius: 4px;
55
- font-size: 1rem;
56
- cursor: pointer;
57
- transition: background-color 0.2s;
58
- }
59
-
60
- button[type="submit"] {
61
- background-color: #007bff;
62
- color: white;
63
- }
64
-
65
- button[type="submit"]:hover {
66
- background-color: #0056b3;
67
- }
68
-
69
- button[type="button"] {
70
- background-color: #6c757d;
71
- color: white;
72
- }
73
-
74
- button[type="button"]:hover {
75
- background-color: #5a6268;
76
- }
77
-
78
- .remove-header {
79
- background-color: #dc3545;
80
- color: white;
81
- padding: 0.25rem 0.5rem;
82
- font-size: 0.875rem;
83
- }
84
-
85
- .remove-header:hover {
86
- background-color: #c82333;
87
- }
88
-
89
- p {
90
- margin-bottom: 1.5rem;
91
- color: #666;
92
- text-align: center;
93
- }
1
+ .login-container {
2
+ max-width: 600px;
3
+ margin: 2rem auto;
4
+ padding: 2rem;
5
+ background: #fff;
6
+ border-radius: 8px;
7
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
8
+ }
9
+
10
+ .header-group {
11
+ display: flex;
12
+ gap: 1rem;
13
+ align-items: flex-start;
14
+ padding: 1rem;
15
+ background: #f8f9fa;
16
+ border-radius: 4px;
17
+ position: relative;
18
+ }
19
+
20
+ .form-group {
21
+ flex: 1;
22
+ }
23
+
24
+ .form-group label {
25
+ display: block;
26
+ margin-bottom: 0.5rem;
27
+ color: #333;
28
+ font-weight: 500;
29
+ }
30
+
31
+ .form-group input {
32
+ width: 100%;
33
+ padding: 0.5rem;
34
+ border: 1px solid #ddd;
35
+ border-radius: 4px;
36
+ font-size: 1rem;
37
+ }
38
+
39
+ .form-group input:focus {
40
+ outline: none;
41
+ border-color: #007bff;
42
+ box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
43
+ }
44
+
45
+ .button-group {
46
+ display: flex;
47
+ gap: 1rem;
48
+ margin-top: 1rem;
49
+ }
50
+
51
+ button {
52
+ padding: 0.5rem 1rem;
53
+ border: none;
54
+ border-radius: 4px;
55
+ font-size: 1rem;
56
+ cursor: pointer;
57
+ transition: background-color 0.2s;
58
+ }
59
+
60
+ button[type="submit"] {
61
+ background-color: #007bff;
62
+ color: white;
63
+ }
64
+
65
+ button[type="submit"]:hover {
66
+ background-color: #0056b3;
67
+ }
68
+
69
+ button[type="button"] {
70
+ background-color: #6c757d;
71
+ color: white;
72
+ }
73
+
74
+ button[type="button"]:hover {
75
+ background-color: #5a6268;
76
+ }
77
+
78
+ .remove-header {
79
+ background-color: #dc3545;
80
+ color: white;
81
+ padding: 0.25rem 0.5rem;
82
+ font-size: 0.875rem;
83
+ }
84
+
85
+ .remove-header:hover {
86
+ background-color: #c82333;
87
+ }
88
+
89
+ p {
90
+ margin-bottom: 1.5rem;
91
+ color: #666;
92
+ text-align: center;
93
+ }