sa2kit 3.4.0 → 3.6.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 (129) hide show
  1. package/dist/{chunk-KVYHCGRY.js → chunk-7Z3XR2Y4.js} +552 -263
  2. package/dist/chunk-7Z3XR2Y4.js.map +1 -0
  3. package/dist/chunk-XPY45Y75.js +1143 -0
  4. package/dist/chunk-XPY45Y75.js.map +1 -0
  5. package/dist/{chunk-YIRPPMCN.mjs → chunk-XSTMLLJV.mjs} +474 -198
  6. package/dist/chunk-XSTMLLJV.mjs.map +1 -0
  7. package/dist/chunk-ZJLS5JU5.mjs +1090 -0
  8. package/dist/chunk-ZJLS5JU5.mjs.map +1 -0
  9. package/dist/common/aiApi/client/index.d.mts +71 -0
  10. package/dist/common/aiApi/client/index.d.ts +71 -0
  11. package/dist/common/aiApi/client/index.js +165 -0
  12. package/dist/common/aiApi/client/index.js.map +1 -0
  13. package/dist/common/aiApi/client/index.mjs +151 -0
  14. package/dist/common/aiApi/client/index.mjs.map +1 -0
  15. package/dist/common/aiApi/index.d.mts +184 -0
  16. package/dist/common/aiApi/index.d.ts +184 -0
  17. package/dist/common/aiApi/index.js +217 -0
  18. package/dist/common/aiApi/index.mjs +4 -0
  19. package/dist/common/aiApi/server/index.d.mts +3 -0
  20. package/dist/common/aiApi/server/index.d.ts +3 -0
  21. package/dist/common/aiApi/server/index.js +217 -0
  22. package/dist/common/aiApi/server/index.mjs +4 -0
  23. package/dist/common/components/index.js +176 -177
  24. package/dist/common/components/index.mjs +1 -2
  25. package/dist/common/index.js +2 -3
  26. package/dist/common/index.mjs +1 -2
  27. package/dist/index.d.mts +314 -154
  28. package/dist/index.d.ts +314 -154
  29. package/dist/index.js +1055 -369
  30. package/dist/index.js.map +1 -1
  31. package/dist/index.mjs +1005 -360
  32. package/dist/index.mjs.map +1 -1
  33. package/dist/types-CiqMQ-uu.d.mts +166 -0
  34. package/dist/types-CiqMQ-uu.d.ts +166 -0
  35. package/package.json +15 -50
  36. package/dist/chunk-3R6JHA6D.js +0 -120
  37. package/dist/chunk-3R6JHA6D.js.map +0 -1
  38. package/dist/chunk-4PJM4752.js +0 -4
  39. package/dist/chunk-4PJM4752.js.map +0 -1
  40. package/dist/chunk-7PMT4L4I.js +0 -324
  41. package/dist/chunk-7PMT4L4I.js.map +0 -1
  42. package/dist/chunk-FY2X3LYR.mjs +0 -3
  43. package/dist/chunk-FY2X3LYR.mjs.map +0 -1
  44. package/dist/chunk-GS4SAW25.mjs +0 -116
  45. package/dist/chunk-GS4SAW25.mjs.map +0 -1
  46. package/dist/chunk-HL4H2HF6.js +0 -279
  47. package/dist/chunk-HL4H2HF6.js.map +0 -1
  48. package/dist/chunk-IJIQUMAK.mjs +0 -272
  49. package/dist/chunk-IJIQUMAK.mjs.map +0 -1
  50. package/dist/chunk-KVYHCGRY.js.map +0 -1
  51. package/dist/chunk-MMDSZIXD.mjs +0 -286
  52. package/dist/chunk-MMDSZIXD.mjs.map +0 -1
  53. package/dist/chunk-N2O3OX5Y.mjs +0 -243
  54. package/dist/chunk-N2O3OX5Y.mjs.map +0 -1
  55. package/dist/chunk-RRQ2X26Z.js +0 -106
  56. package/dist/chunk-RRQ2X26Z.js.map +0 -1
  57. package/dist/chunk-RVNQI6BI.js +0 -249
  58. package/dist/chunk-RVNQI6BI.js.map +0 -1
  59. package/dist/chunk-UJUWDF7M.mjs +0 -336
  60. package/dist/chunk-UJUWDF7M.mjs.map +0 -1
  61. package/dist/chunk-VCKXK6V5.js +0 -345
  62. package/dist/chunk-VCKXK6V5.js.map +0 -1
  63. package/dist/chunk-VIEXDTNF.mjs +0 -100
  64. package/dist/chunk-VIEXDTNF.mjs.map +0 -1
  65. package/dist/chunk-YIRPPMCN.mjs.map +0 -1
  66. package/dist/common/ai/llm/core/index.d.mts +0 -70
  67. package/dist/common/ai/llm/core/index.d.ts +0 -70
  68. package/dist/common/ai/llm/core/index.js +0 -54
  69. package/dist/common/ai/llm/core/index.mjs +0 -5
  70. package/dist/common/ai/llm/electron/index.d.mts +0 -6
  71. package/dist/common/ai/llm/electron/index.d.ts +0 -6
  72. package/dist/common/ai/llm/electron/index.js +0 -67
  73. package/dist/common/ai/llm/electron/index.mjs +0 -10
  74. package/dist/common/ai/llm/index.d.mts +0 -3
  75. package/dist/common/ai/llm/index.d.ts +0 -3
  76. package/dist/common/ai/llm/index.js +0 -54
  77. package/dist/common/ai/llm/index.js.map +0 -1
  78. package/dist/common/ai/llm/index.mjs +0 -5
  79. package/dist/common/ai/llm/index.mjs.map +0 -1
  80. package/dist/common/ai/llm/miniapp/index.d.mts +0 -6
  81. package/dist/common/ai/llm/miniapp/index.d.ts +0 -6
  82. package/dist/common/ai/llm/miniapp/index.js +0 -59
  83. package/dist/common/ai/llm/miniapp/index.js.map +0 -1
  84. package/dist/common/ai/llm/miniapp/index.mjs +0 -6
  85. package/dist/common/ai/llm/miniapp/index.mjs.map +0 -1
  86. package/dist/common/ai/llm/rn/index.d.mts +0 -6
  87. package/dist/common/ai/llm/rn/index.d.ts +0 -6
  88. package/dist/common/ai/llm/rn/index.js +0 -59
  89. package/dist/common/ai/llm/rn/index.js.map +0 -1
  90. package/dist/common/ai/llm/rn/index.mjs +0 -6
  91. package/dist/common/ai/llm/rn/index.mjs.map +0 -1
  92. package/dist/common/ai/llm/ui/electron/index.d.mts +0 -5
  93. package/dist/common/ai/llm/ui/electron/index.d.ts +0 -5
  94. package/dist/common/ai/llm/ui/electron/index.js +0 -22
  95. package/dist/common/ai/llm/ui/electron/index.js.map +0 -1
  96. package/dist/common/ai/llm/ui/electron/index.mjs +0 -9
  97. package/dist/common/ai/llm/ui/electron/index.mjs.map +0 -1
  98. package/dist/common/ai/llm/ui/miniapp/index.d.mts +0 -9
  99. package/dist/common/ai/llm/ui/miniapp/index.d.ts +0 -9
  100. package/dist/common/ai/llm/ui/miniapp/index.js +0 -14
  101. package/dist/common/ai/llm/ui/miniapp/index.js.map +0 -1
  102. package/dist/common/ai/llm/ui/miniapp/index.mjs +0 -5
  103. package/dist/common/ai/llm/ui/miniapp/index.mjs.map +0 -1
  104. package/dist/common/ai/llm/ui/rn/index.d.mts +0 -9
  105. package/dist/common/ai/llm/ui/rn/index.d.ts +0 -9
  106. package/dist/common/ai/llm/ui/rn/index.js +0 -14
  107. package/dist/common/ai/llm/ui/rn/index.js.map +0 -1
  108. package/dist/common/ai/llm/ui/rn/index.mjs +0 -5
  109. package/dist/common/ai/llm/ui/rn/index.mjs.map +0 -1
  110. package/dist/common/ai/llm/ui/web/index.d.mts +0 -15
  111. package/dist/common/ai/llm/ui/web/index.d.ts +0 -15
  112. package/dist/common/ai/llm/ui/web/index.js +0 -21
  113. package/dist/common/ai/llm/ui/web/index.js.map +0 -1
  114. package/dist/common/ai/llm/ui/web/index.mjs +0 -8
  115. package/dist/common/ai/llm/ui/web/index.mjs.map +0 -1
  116. package/dist/common/ai/llm/web/index.d.mts +0 -6
  117. package/dist/common/ai/llm/web/index.d.ts +0 -6
  118. package/dist/common/ai/llm/web/index.js +0 -66
  119. package/dist/common/ai/llm/web/index.js.map +0 -1
  120. package/dist/common/ai/llm/web/index.mjs +0 -9
  121. package/dist/common/ai/llm/web/index.mjs.map +0 -1
  122. package/dist/types-B2rs_jq1.d.mts +0 -38
  123. package/dist/types-DgACCUpT.d.ts +0 -122
  124. package/dist/types-DwS2Eg0q.d.ts +0 -38
  125. package/dist/types-LU_BGSzk.d.mts +0 -122
  126. /package/dist/common/{ai/llm/core → aiApi}/index.js.map +0 -0
  127. /package/dist/common/{ai/llm/core → aiApi}/index.mjs.map +0 -0
  128. /package/dist/common/{ai/llm/electron → aiApi/server}/index.js.map +0 -0
  129. /package/dist/common/{ai/llm/electron → aiApi/server}/index.mjs.map +0 -0
@@ -1,279 +0,0 @@
1
- 'use strict';
2
-
3
- var chunk3R6JHA6D_js = require('./chunk-3R6JHA6D.js');
4
- var chunk7PMT4L4I_js = require('./chunk-7PMT4L4I.js');
5
- var chunkY7WHUKJF_js = require('./chunk-Y7WHUKJF.js');
6
- var React2 = require('react');
7
-
8
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
-
10
- var React2__default = /*#__PURE__*/_interopDefault(React2);
11
-
12
- var AiChatDialog = ({
13
- open,
14
- onOpenChange,
15
- client,
16
- title = "AI \u5BF9\u8BDD",
17
- placeholder = "\u8F93\u5165\u4F60\u60F3\u54A8\u8BE2\u7684\u95EE\u9898...",
18
- systemPrompt,
19
- template,
20
- templateVariables,
21
- initialMessages,
22
- requestOptions,
23
- onResponse,
24
- onError,
25
- className,
26
- contentClassName
27
- }) => {
28
- const { messages, sendMessage, isLoading, error } = chunk3R6JHA6D_js.useAiChat({
29
- client,
30
- systemPrompt,
31
- template,
32
- initialMessages
33
- });
34
- const [input, setInput] = React2.useState("");
35
- const listRef = React2.useRef(null);
36
- const hasMessages = messages.length > 0;
37
- const helperText = React2.useMemo(() => {
38
- return template ? "\u6A21\u677F\u5DF2\u542F\u7528\uFF0C\u652F\u6301 {{input}} \u53D8\u91CF\u3002" : "\u76F4\u63A5\u8F93\u5165\u5373\u53EF\u5F00\u59CB\u5BF9\u8BDD\u3002";
39
- }, [template]);
40
- React2.useEffect(() => {
41
- if (!listRef.current) return;
42
- listRef.current.scrollTop = listRef.current.scrollHeight;
43
- }, [messages, open, isLoading]);
44
- const handleSend = async () => {
45
- const content = input.trim();
46
- if (!content || isLoading) return;
47
- setInput("");
48
- try {
49
- const response = await sendMessage(content, {
50
- ...requestOptions,
51
- template,
52
- variables: templateVariables
53
- });
54
- onResponse?.(response);
55
- } catch (err) {
56
- const nextError = err instanceof Error ? err : new Error(String(err));
57
- onError?.(nextError);
58
- }
59
- };
60
- const handleKeyDown = (event) => {
61
- if (event.key === "Enter" && !event.shiftKey) {
62
- event.preventDefault();
63
- handleSend();
64
- }
65
- };
66
- return /* @__PURE__ */ React2__default.default.createElement(chunk7PMT4L4I_js.Dialog, { open, onOpenChange }, /* @__PURE__ */ React2__default.default.createElement(
67
- chunk7PMT4L4I_js.DialogContent,
68
- {
69
- className: chunkY7WHUKJF_js.cn(
70
- "max-w-3xl border border-slate-200 bg-white p-0",
71
- contentClassName
72
- )
73
- },
74
- /* @__PURE__ */ React2__default.default.createElement("div", { className: chunkY7WHUKJF_js.cn("flex flex-col", className) }, /* @__PURE__ */ React2__default.default.createElement(chunk7PMT4L4I_js.DialogHeader, { className: "border-b border-slate-100 px-6 py-4" }, /* @__PURE__ */ React2__default.default.createElement(chunk7PMT4L4I_js.DialogTitle, { className: "text-base font-semibold text-slate-900" }, title)), /* @__PURE__ */ React2__default.default.createElement("div", { className: "flex flex-1 flex-col gap-4 px-6 py-4" }, /* @__PURE__ */ React2__default.default.createElement(
75
- "div",
76
- {
77
- ref: listRef,
78
- className: "max-h-[60vh] min-h-[240px] overflow-y-auto rounded-xl border border-slate-100 bg-slate-50/60 p-4"
79
- },
80
- !hasMessages && /* @__PURE__ */ React2__default.default.createElement("div", { className: "flex h-full flex-col items-center justify-center gap-2 text-sm text-slate-400" }, /* @__PURE__ */ React2__default.default.createElement("span", null, "\u6682\u65E0\u5BF9\u8BDD\u5185\u5BB9"), /* @__PURE__ */ React2__default.default.createElement("span", null, "\u8F93\u5165\u6D88\u606F\u5F00\u59CB\u4F53\u9A8C AI \u5BF9\u8BDD\u3002")),
81
- /* @__PURE__ */ React2__default.default.createElement("div", { className: "flex flex-col gap-3" }, messages.map((message, index) => {
82
- const isUser = message.role === "user";
83
- return /* @__PURE__ */ React2__default.default.createElement(
84
- "div",
85
- {
86
- key: `${message.role}-${index}`,
87
- className: chunkY7WHUKJF_js.cn(
88
- "max-w-[85%] whitespace-pre-wrap rounded-2xl px-4 py-2 text-sm leading-relaxed",
89
- isUser ? "ml-auto bg-slate-900 text-white" : "mr-auto border border-slate-200 bg-white text-slate-800"
90
- )
91
- },
92
- message.content
93
- );
94
- }), isLoading && /* @__PURE__ */ React2__default.default.createElement("div", { className: "mr-auto max-w-[70%] rounded-2xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-500" }, "AI \u6B63\u5728\u601D\u8003..."))
95
- ), /* @__PURE__ */ React2__default.default.createElement("div", { className: "rounded-xl border border-slate-100 bg-white p-4 shadow-sm" }, /* @__PURE__ */ React2__default.default.createElement(
96
- "textarea",
97
- {
98
- value: input,
99
- onChange: (event) => setInput(event.target.value),
100
- onKeyDown: handleKeyDown,
101
- placeholder,
102
- className: "min-h-[96px] w-full resize-none rounded-lg border border-slate-200 px-3 py-2 text-sm text-slate-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-300"
103
- }
104
- ), /* @__PURE__ */ React2__default.default.createElement("div", { className: "mt-3 flex flex-wrap items-center justify-between gap-3" }, /* @__PURE__ */ React2__default.default.createElement("span", { className: "text-xs text-slate-400" }, helperText), /* @__PURE__ */ React2__default.default.createElement(chunk7PMT4L4I_js.Button, { onClick: handleSend, disabled: !input.trim() || isLoading }, isLoading ? "\u53D1\u9001\u4E2D..." : "\u53D1\u9001")), error && /* @__PURE__ */ React2__default.default.createElement("div", { className: "mt-2 rounded-md border border-rose-200 bg-rose-50 px-3 py-2 text-xs text-rose-600" }, error.message || "\u5BF9\u8BDD\u51FA\u9519\uFF0C\u8BF7\u91CD\u8BD5\u3002"))))
105
- ));
106
- };
107
- var DEFAULT_AI_CONFIG = {
108
- apiKey: "",
109
- baseUrl: "https://api.openai.com/v1",
110
- model: "gpt-3.5-turbo",
111
- systemPrompt: "",
112
- template: "{{input}}",
113
- temperature: 0.7,
114
- topP: 1,
115
- maxTokens: 1024
116
- };
117
- var mergeConfig = (base, overrides, stored) => {
118
- return {
119
- ...base,
120
- ...overrides ?? {},
121
- ...stored ?? {}
122
- };
123
- };
124
- var AiConfigPage = ({
125
- storageKey = "sa2kit-ai-config",
126
- initialConfig,
127
- title = "AI \u914D\u7F6E",
128
- description = "\u914D\u7F6E API Key\u3001\u6A21\u578B\u4E0E\u63D0\u793A\u8BCD\u6A21\u677F\uFF0C\u7528\u4E8E AI \u5BF9\u8BDD\u80FD\u529B\u3002",
129
- onSave,
130
- onChange
131
- }) => {
132
- const baseConfig = React2.useMemo(
133
- () => mergeConfig(DEFAULT_AI_CONFIG, initialConfig),
134
- [initialConfig]
135
- );
136
- const [config, setConfig] = React2.useState(baseConfig);
137
- const [status, setStatus] = React2.useState(null);
138
- const [showApiKey, setShowApiKey] = React2.useState(false);
139
- React2.useEffect(() => {
140
- if (typeof window === "undefined") {
141
- return;
142
- }
143
- if (!storageKey) {
144
- return;
145
- }
146
- const storedRaw = localStorage.getItem(storageKey);
147
- if (!storedRaw) {
148
- return;
149
- }
150
- try {
151
- const stored = JSON.parse(storedRaw);
152
- setConfig(mergeConfig(DEFAULT_AI_CONFIG, initialConfig, stored));
153
- } catch (error) {
154
- console.warn("[AiConfigPage] Failed to parse stored config:", error);
155
- }
156
- }, [storageKey, initialConfig]);
157
- const updateConfig = (updates) => {
158
- setConfig((prev) => {
159
- const next = { ...prev, ...updates };
160
- onChange?.(next);
161
- return next;
162
- });
163
- };
164
- const updateNumber = (key, value) => {
165
- const nextValue = Number(value);
166
- if (Number.isNaN(nextValue)) {
167
- return;
168
- }
169
- updateConfig({ [key]: nextValue });
170
- };
171
- const saveConfig = () => {
172
- if (typeof window !== "undefined" && storageKey) {
173
- try {
174
- localStorage.setItem(storageKey, JSON.stringify(config));
175
- } catch (error) {
176
- setStatus({ type: "error", text: "\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u6D4F\u89C8\u5668\u5B58\u50A8\u6743\u9650\u3002" });
177
- return;
178
- }
179
- }
180
- setStatus({ type: "success", text: "\u5DF2\u4FDD\u5B58\u914D\u7F6E\u3002" });
181
- onSave?.(config);
182
- };
183
- const resetConfig = () => {
184
- const next = mergeConfig(DEFAULT_AI_CONFIG, initialConfig);
185
- setConfig(next);
186
- onChange?.(next);
187
- if (typeof window !== "undefined" && storageKey) {
188
- localStorage.removeItem(storageKey);
189
- }
190
- setStatus({ type: "success", text: "\u5DF2\u6062\u590D\u9ED8\u8BA4\u914D\u7F6E\u3002" });
191
- };
192
- return /* @__PURE__ */ React2__default.default.createElement("div", { className: "w-full rounded-2xl border border-slate-200 bg-white p-6 shadow-sm" }, /* @__PURE__ */ React2__default.default.createElement("div", { className: "flex flex-col gap-2 border-b border-slate-100 pb-4" }, /* @__PURE__ */ React2__default.default.createElement("h2", { className: "text-xl font-semibold text-slate-900" }, title), /* @__PURE__ */ React2__default.default.createElement("p", { className: "text-sm text-slate-500" }, description)), /* @__PURE__ */ React2__default.default.createElement("div", { className: "mt-6 grid gap-6" }, /* @__PURE__ */ React2__default.default.createElement("section", { className: "rounded-xl border border-slate-100 bg-slate-50/60 p-4" }, /* @__PURE__ */ React2__default.default.createElement("h3", { className: "text-sm font-semibold text-slate-700" }, "API \u4FE1\u606F"), /* @__PURE__ */ React2__default.default.createElement("div", { className: "mt-4 grid gap-4" }, /* @__PURE__ */ React2__default.default.createElement("div", null, /* @__PURE__ */ React2__default.default.createElement("label", { className: "text-xs font-medium text-slate-500" }, "Base URL"), /* @__PURE__ */ React2__default.default.createElement(
193
- chunk7PMT4L4I_js.Input,
194
- {
195
- value: config.baseUrl,
196
- onChange: (event) => updateConfig({ baseUrl: event.target.value }),
197
- placeholder: "https://api.openai.com/v1",
198
- className: "mt-2"
199
- }
200
- )), /* @__PURE__ */ React2__default.default.createElement("div", null, /* @__PURE__ */ React2__default.default.createElement("label", { className: "text-xs font-medium text-slate-500" }, "API Key"), /* @__PURE__ */ React2__default.default.createElement("div", { className: "mt-2 flex gap-2" }, /* @__PURE__ */ React2__default.default.createElement(
201
- chunk7PMT4L4I_js.Input,
202
- {
203
- value: config.apiKey,
204
- onChange: (event) => updateConfig({ apiKey: event.target.value }),
205
- placeholder: "sk-...",
206
- type: showApiKey ? "text" : "password"
207
- }
208
- ), /* @__PURE__ */ React2__default.default.createElement(
209
- chunk7PMT4L4I_js.Button,
210
- {
211
- type: "button",
212
- variant: "outline",
213
- onClick: () => setShowApiKey((prev) => !prev)
214
- },
215
- showApiKey ? "\u9690\u85CF" : "\u663E\u793A"
216
- ))), /* @__PURE__ */ React2__default.default.createElement("div", null, /* @__PURE__ */ React2__default.default.createElement("label", { className: "text-xs font-medium text-slate-500" }, "\u6A21\u578B"), /* @__PURE__ */ React2__default.default.createElement(
217
- chunk7PMT4L4I_js.Input,
218
- {
219
- value: config.model,
220
- onChange: (event) => updateConfig({ model: event.target.value }),
221
- placeholder: "gpt-3.5-turbo",
222
- className: "mt-2"
223
- }
224
- )))), /* @__PURE__ */ React2__default.default.createElement("section", { className: "rounded-xl border border-slate-100 bg-white p-4 shadow-sm" }, /* @__PURE__ */ React2__default.default.createElement("h3", { className: "text-sm font-semibold text-slate-700" }, "\u63D0\u793A\u8BCD\u4E0E\u4E0A\u4E0B\u6587"), /* @__PURE__ */ React2__default.default.createElement("div", { className: "mt-4 grid gap-4" }, /* @__PURE__ */ React2__default.default.createElement("div", null, /* @__PURE__ */ React2__default.default.createElement("label", { className: "text-xs font-medium text-slate-500" }, "\u7CFB\u7EDF\u63D0\u793A\u8BCD"), /* @__PURE__ */ React2__default.default.createElement(
225
- "textarea",
226
- {
227
- value: config.systemPrompt,
228
- onChange: (event) => updateConfig({ systemPrompt: event.target.value }),
229
- placeholder: "\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684 AI \u52A9\u624B...",
230
- className: "mt-2 min-h-[96px] w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-900 shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-300"
231
- }
232
- )), /* @__PURE__ */ React2__default.default.createElement("div", null, /* @__PURE__ */ React2__default.default.createElement("label", { className: "text-xs font-medium text-slate-500" }, "\u63D0\u793A\u8BCD\u6A21\u677F"), /* @__PURE__ */ React2__default.default.createElement(
233
- "textarea",
234
- {
235
- value: config.template,
236
- onChange: (event) => updateConfig({ template: event.target.value }),
237
- placeholder: "\u8BF7\u56DE\u7B54\uFF1A{{input}}",
238
- className: "mt-2 min-h-[96px] w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-900 shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-300"
239
- }
240
- ), /* @__PURE__ */ React2__default.default.createElement("p", { className: "mt-2 text-xs text-slate-400" }, "\u652F\u6301\u53D8\u91CF\u63D2\u5165\uFF1A", /* @__PURE__ */ React2__default.default.createElement("code", { className: "rounded bg-slate-100 px-1" }, "{{input}}"))))), /* @__PURE__ */ React2__default.default.createElement("section", { className: "rounded-xl border border-slate-100 bg-slate-50/60 p-4" }, /* @__PURE__ */ React2__default.default.createElement("h3", { className: "text-sm font-semibold text-slate-700" }, "\u6A21\u578B\u53C2\u6570"), /* @__PURE__ */ React2__default.default.createElement("div", { className: "mt-4 grid gap-4 md:grid-cols-3" }, /* @__PURE__ */ React2__default.default.createElement("div", null, /* @__PURE__ */ React2__default.default.createElement("label", { className: "text-xs font-medium text-slate-500" }, "Temperature"), /* @__PURE__ */ React2__default.default.createElement(
241
- chunk7PMT4L4I_js.Input,
242
- {
243
- type: "number",
244
- value: config.temperature,
245
- onChange: (event) => updateNumber("temperature", event.target.value),
246
- className: "mt-2"
247
- }
248
- )), /* @__PURE__ */ React2__default.default.createElement("div", null, /* @__PURE__ */ React2__default.default.createElement("label", { className: "text-xs font-medium text-slate-500" }, "Top P"), /* @__PURE__ */ React2__default.default.createElement(
249
- chunk7PMT4L4I_js.Input,
250
- {
251
- type: "number",
252
- value: config.topP,
253
- onChange: (event) => updateNumber("topP", event.target.value),
254
- className: "mt-2"
255
- }
256
- )), /* @__PURE__ */ React2__default.default.createElement("div", null, /* @__PURE__ */ React2__default.default.createElement("label", { className: "text-xs font-medium text-slate-500" }, "Max Tokens"), /* @__PURE__ */ React2__default.default.createElement(
257
- chunk7PMT4L4I_js.Input,
258
- {
259
- type: "number",
260
- value: config.maxTokens,
261
- onChange: (event) => updateNumber("maxTokens", event.target.value),
262
- className: "mt-2"
263
- }
264
- )))), /* @__PURE__ */ React2__default.default.createElement("div", { className: "flex flex-wrap items-center gap-3" }, /* @__PURE__ */ React2__default.default.createElement(chunk7PMT4L4I_js.Button, { onClick: saveConfig }, "\u4FDD\u5B58\u914D\u7F6E"), /* @__PURE__ */ React2__default.default.createElement(chunk7PMT4L4I_js.Button, { variant: "outline", onClick: resetConfig }, "\u6062\u590D\u9ED8\u8BA4"), status && /* @__PURE__ */ React2__default.default.createElement(
265
- "span",
266
- {
267
- className: chunkY7WHUKJF_js.cn(
268
- "text-xs",
269
- status.type === "success" ? "text-emerald-600" : "text-rose-600"
270
- )
271
- },
272
- status.text
273
- ))));
274
- };
275
-
276
- exports.AiChatDialog = AiChatDialog;
277
- exports.AiConfigPage = AiConfigPage;
278
- //# sourceMappingURL=chunk-HL4H2HF6.js.map
279
- //# sourceMappingURL=chunk-HL4H2HF6.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/common/ai/llm/ui/web/components/AiChatDialog.tsx","../src/common/ai/llm/ui/web/components/AiConfigPage.tsx"],"names":["useAiChat","useState","useRef","useMemo","useEffect","React","Dialog","DialogContent","cn","DialogHeader","DialogTitle","Button","Input"],"mappings":"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","file":"chunk-HL4H2HF6.js","sourcesContent":["'use client';\n\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport { Button } from '../../../../../components/Button';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../../../../components/Dialog';\nimport { cn } from '../../../../../utils/cn';\nimport { useAiChat } from '../../../hooks/useAiChat';\nimport type { AiChatDialogProps } from '../../types';\n\ntype WebAiChatDialogProps = AiChatDialogProps & {\n className?: string;\n contentClassName?: string;\n};\n\nexport const AiChatDialog: React.FC<WebAiChatDialogProps> = ({\n open,\n onOpenChange,\n client,\n title = 'AI 对话',\n placeholder = '输入你想咨询的问题...',\n systemPrompt,\n template,\n templateVariables,\n initialMessages,\n requestOptions,\n onResponse,\n onError,\n className,\n contentClassName,\n}) => {\n const { messages, sendMessage, isLoading, error } = useAiChat({\n client,\n systemPrompt,\n template,\n initialMessages,\n });\n const [input, setInput] = useState('');\n const listRef = useRef<HTMLDivElement>(null);\n\n const hasMessages = messages.length > 0;\n const helperText = useMemo(() => {\n return template ? '模板已启用,支持 {{input}} 变量。' : '直接输入即可开始对话。';\n }, [template]);\n\n useEffect(() => {\n if (!listRef.current) return;\n listRef.current.scrollTop = listRef.current.scrollHeight;\n }, [messages, open, isLoading]);\n\n const handleSend = async () => {\n const content = input.trim();\n if (!content || isLoading) return;\n setInput('');\n try {\n const response = await sendMessage(content, {\n ...requestOptions,\n template,\n variables: templateVariables,\n });\n onResponse?.(response);\n } catch (err) {\n const nextError = err instanceof Error ? err : new Error(String(err));\n onError?.(nextError);\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n handleSend();\n }\n };\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n className={cn(\n 'max-w-3xl border border-slate-200 bg-white p-0',\n contentClassName\n )}\n >\n <div className={cn('flex flex-col', className)}>\n <DialogHeader className=\"border-b border-slate-100 px-6 py-4\">\n <DialogTitle className=\"text-base font-semibold text-slate-900\">{title}</DialogTitle>\n </DialogHeader>\n\n <div className=\"flex flex-1 flex-col gap-4 px-6 py-4\">\n <div\n ref={listRef}\n className=\"max-h-[60vh] min-h-[240px] overflow-y-auto rounded-xl border border-slate-100 bg-slate-50/60 p-4\"\n >\n {!hasMessages && (\n <div className=\"flex h-full flex-col items-center justify-center gap-2 text-sm text-slate-400\">\n <span>暂无对话内容</span>\n <span>输入消息开始体验 AI 对话。</span>\n </div>\n )}\n <div className=\"flex flex-col gap-3\">\n {messages.map((message, index) => {\n const isUser = message.role === 'user';\n return (\n <div\n key={`${message.role}-${index}`}\n className={cn(\n 'max-w-[85%] whitespace-pre-wrap rounded-2xl px-4 py-2 text-sm leading-relaxed',\n isUser\n ? 'ml-auto bg-slate-900 text-white'\n : 'mr-auto border border-slate-200 bg-white text-slate-800'\n )}\n >\n {message.content}\n </div>\n );\n })}\n {isLoading && (\n <div className=\"mr-auto max-w-[70%] rounded-2xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-500\">\n AI 正在思考...\n </div>\n )}\n </div>\n </div>\n\n <div className=\"rounded-xl border border-slate-100 bg-white p-4 shadow-sm\">\n <textarea\n value={input}\n onChange={(event) => setInput(event.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n className=\"min-h-[96px] w-full resize-none rounded-lg border border-slate-200 px-3 py-2 text-sm text-slate-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-300\"\n />\n <div className=\"mt-3 flex flex-wrap items-center justify-between gap-3\">\n <span className=\"text-xs text-slate-400\">{helperText}</span>\n <Button onClick={handleSend} disabled={!input.trim() || isLoading}>\n {isLoading ? '发送中...' : '发送'}\n </Button>\n </div>\n {error && (\n <div className=\"mt-2 rounded-md border border-rose-200 bg-rose-50 px-3 py-2 text-xs text-rose-600\">\n {error.message || '对话出错,请重试。'}\n </div>\n )}\n </div>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n );\n};\n","'use client';\n\nimport React, { useEffect, useMemo, useState } from 'react';\nimport { Button } from '../../../../../components/Button';\nimport { Input } from '../../../../../components/Input';\nimport { cn } from '../../../../../utils/cn';\nimport type { AiConfigPageProps, AiUiConfig } from '../../types';\n\nconst DEFAULT_AI_CONFIG: AiUiConfig = {\n apiKey: '',\n baseUrl: 'https://api.openai.com/v1',\n model: 'gpt-3.5-turbo',\n systemPrompt: '',\n template: '{{input}}',\n temperature: 0.7,\n topP: 1,\n maxTokens: 1024,\n};\n\nconst mergeConfig = (\n base: AiUiConfig,\n overrides?: Partial<AiUiConfig>,\n stored?: Partial<AiUiConfig>\n): AiUiConfig => {\n return {\n ...base,\n ...(overrides ?? {}),\n ...(stored ?? {}),\n };\n};\n\nexport const AiConfigPage: React.FC<AiConfigPageProps> = ({\n storageKey = 'sa2kit-ai-config',\n initialConfig,\n title = 'AI 配置',\n description = '配置 API Key、模型与提示词模板,用于 AI 对话能力。',\n onSave,\n onChange,\n}) => {\n const baseConfig = useMemo(\n () => mergeConfig(DEFAULT_AI_CONFIG, initialConfig),\n [initialConfig]\n );\n const [config, setConfig] = useState<AiUiConfig>(baseConfig);\n const [status, setStatus] = useState<{ type: 'success' | 'error'; text: string } | null>(null);\n const [showApiKey, setShowApiKey] = useState(false);\n\n useEffect(() => {\n if (typeof window === 'undefined') {\n return;\n }\n if (!storageKey) {\n return;\n }\n const storedRaw = localStorage.getItem(storageKey);\n if (!storedRaw) {\n return;\n }\n try {\n const stored = JSON.parse(storedRaw) as Partial<AiUiConfig>;\n setConfig(mergeConfig(DEFAULT_AI_CONFIG, initialConfig, stored));\n } catch (error) {\n console.warn('[AiConfigPage] Failed to parse stored config:', error);\n }\n }, [storageKey, initialConfig]);\n\n const updateConfig = (updates: Partial<AiUiConfig>) => {\n setConfig((prev) => {\n const next = { ...prev, ...updates };\n onChange?.(next);\n return next;\n });\n };\n\n const updateNumber = (key: keyof AiUiConfig, value: string) => {\n const nextValue = Number(value);\n if (Number.isNaN(nextValue)) {\n return;\n }\n updateConfig({ [key]: nextValue } as Partial<AiUiConfig>);\n };\n\n const saveConfig = () => {\n if (typeof window !== 'undefined' && storageKey) {\n try {\n localStorage.setItem(storageKey, JSON.stringify(config));\n } catch (error) {\n setStatus({ type: 'error', text: '保存失败,请检查浏览器存储权限。' });\n return;\n }\n }\n setStatus({ type: 'success', text: '已保存配置。' });\n onSave?.(config);\n };\n\n const resetConfig = () => {\n const next = mergeConfig(DEFAULT_AI_CONFIG, initialConfig);\n setConfig(next);\n onChange?.(next);\n if (typeof window !== 'undefined' && storageKey) {\n localStorage.removeItem(storageKey);\n }\n setStatus({ type: 'success', text: '已恢复默认配置。' });\n };\n\n return (\n <div className=\"w-full rounded-2xl border border-slate-200 bg-white p-6 shadow-sm\">\n <div className=\"flex flex-col gap-2 border-b border-slate-100 pb-4\">\n <h2 className=\"text-xl font-semibold text-slate-900\">{title}</h2>\n <p className=\"text-sm text-slate-500\">{description}</p>\n </div>\n\n <div className=\"mt-6 grid gap-6\">\n <section className=\"rounded-xl border border-slate-100 bg-slate-50/60 p-4\">\n <h3 className=\"text-sm font-semibold text-slate-700\">API 信息</h3>\n <div className=\"mt-4 grid gap-4\">\n <div>\n <label className=\"text-xs font-medium text-slate-500\">Base URL</label>\n <Input\n value={config.baseUrl}\n onChange={(event) => updateConfig({ baseUrl: event.target.value })}\n placeholder=\"https://api.openai.com/v1\"\n className=\"mt-2\"\n />\n </div>\n <div>\n <label className=\"text-xs font-medium text-slate-500\">API Key</label>\n <div className=\"mt-2 flex gap-2\">\n <Input\n value={config.apiKey}\n onChange={(event) => updateConfig({ apiKey: event.target.value })}\n placeholder=\"sk-...\"\n type={showApiKey ? 'text' : 'password'}\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setShowApiKey((prev) => !prev)}\n >\n {showApiKey ? '隐藏' : '显示'}\n </Button>\n </div>\n </div>\n <div>\n <label className=\"text-xs font-medium text-slate-500\">模型</label>\n <Input\n value={config.model}\n onChange={(event) => updateConfig({ model: event.target.value })}\n placeholder=\"gpt-3.5-turbo\"\n className=\"mt-2\"\n />\n </div>\n </div>\n </section>\n\n <section className=\"rounded-xl border border-slate-100 bg-white p-4 shadow-sm\">\n <h3 className=\"text-sm font-semibold text-slate-700\">提示词与上下文</h3>\n <div className=\"mt-4 grid gap-4\">\n <div>\n <label className=\"text-xs font-medium text-slate-500\">系统提示词</label>\n <textarea\n value={config.systemPrompt}\n onChange={(event) => updateConfig({ systemPrompt: event.target.value })}\n placeholder=\"你是一个专业的 AI 助手...\"\n className=\"mt-2 min-h-[96px] w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-900 shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-300\"\n />\n </div>\n <div>\n <label className=\"text-xs font-medium text-slate-500\">提示词模板</label>\n <textarea\n value={config.template}\n onChange={(event) => updateConfig({ template: event.target.value })}\n placeholder=\"请回答:{{input}}\"\n className=\"mt-2 min-h-[96px] w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-900 shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-300\"\n />\n <p className=\"mt-2 text-xs text-slate-400\">\n 支持变量插入:<code className=\"rounded bg-slate-100 px-1\">{\"{{input}}\"}</code>\n </p>\n </div>\n </div>\n </section>\n\n <section className=\"rounded-xl border border-slate-100 bg-slate-50/60 p-4\">\n <h3 className=\"text-sm font-semibold text-slate-700\">模型参数</h3>\n <div className=\"mt-4 grid gap-4 md:grid-cols-3\">\n <div>\n <label className=\"text-xs font-medium text-slate-500\">Temperature</label>\n <Input\n type=\"number\"\n value={config.temperature}\n onChange={(event) => updateNumber('temperature', event.target.value)}\n className=\"mt-2\"\n />\n </div>\n <div>\n <label className=\"text-xs font-medium text-slate-500\">Top P</label>\n <Input\n type=\"number\"\n value={config.topP}\n onChange={(event) => updateNumber('topP', event.target.value)}\n className=\"mt-2\"\n />\n </div>\n <div>\n <label className=\"text-xs font-medium text-slate-500\">Max Tokens</label>\n <Input\n type=\"number\"\n value={config.maxTokens}\n onChange={(event) => updateNumber('maxTokens', event.target.value)}\n className=\"mt-2\"\n />\n </div>\n </div>\n </section>\n\n <div className=\"flex flex-wrap items-center gap-3\">\n <Button onClick={saveConfig}>保存配置</Button>\n <Button variant=\"outline\" onClick={resetConfig}>\n 恢复默认\n </Button>\n {status && (\n <span\n className={cn(\n 'text-xs',\n status.type === 'success' ? 'text-emerald-600' : 'text-rose-600'\n )}\n >\n {status.text}\n </span>\n )}\n </div>\n </div>\n </div>\n );\n};\n"]}
@@ -1,272 +0,0 @@
1
- import { useAiChat } from './chunk-GS4SAW25.mjs';
2
- import { Dialog, DialogContent, DialogHeader, DialogTitle, Button, Input } from './chunk-MMDSZIXD.mjs';
3
- import { cn } from './chunk-FUA6ZGMI.mjs';
4
- import React2, { useState, useRef, useMemo, useEffect } from 'react';
5
-
6
- var AiChatDialog = ({
7
- open,
8
- onOpenChange,
9
- client,
10
- title = "AI \u5BF9\u8BDD",
11
- placeholder = "\u8F93\u5165\u4F60\u60F3\u54A8\u8BE2\u7684\u95EE\u9898...",
12
- systemPrompt,
13
- template,
14
- templateVariables,
15
- initialMessages,
16
- requestOptions,
17
- onResponse,
18
- onError,
19
- className,
20
- contentClassName
21
- }) => {
22
- const { messages, sendMessage, isLoading, error } = useAiChat({
23
- client,
24
- systemPrompt,
25
- template,
26
- initialMessages
27
- });
28
- const [input, setInput] = useState("");
29
- const listRef = useRef(null);
30
- const hasMessages = messages.length > 0;
31
- const helperText = useMemo(() => {
32
- return template ? "\u6A21\u677F\u5DF2\u542F\u7528\uFF0C\u652F\u6301 {{input}} \u53D8\u91CF\u3002" : "\u76F4\u63A5\u8F93\u5165\u5373\u53EF\u5F00\u59CB\u5BF9\u8BDD\u3002";
33
- }, [template]);
34
- useEffect(() => {
35
- if (!listRef.current) return;
36
- listRef.current.scrollTop = listRef.current.scrollHeight;
37
- }, [messages, open, isLoading]);
38
- const handleSend = async () => {
39
- const content = input.trim();
40
- if (!content || isLoading) return;
41
- setInput("");
42
- try {
43
- const response = await sendMessage(content, {
44
- ...requestOptions,
45
- template,
46
- variables: templateVariables
47
- });
48
- onResponse?.(response);
49
- } catch (err) {
50
- const nextError = err instanceof Error ? err : new Error(String(err));
51
- onError?.(nextError);
52
- }
53
- };
54
- const handleKeyDown = (event) => {
55
- if (event.key === "Enter" && !event.shiftKey) {
56
- event.preventDefault();
57
- handleSend();
58
- }
59
- };
60
- return /* @__PURE__ */ React2.createElement(Dialog, { open, onOpenChange }, /* @__PURE__ */ React2.createElement(
61
- DialogContent,
62
- {
63
- className: cn(
64
- "max-w-3xl border border-slate-200 bg-white p-0",
65
- contentClassName
66
- )
67
- },
68
- /* @__PURE__ */ React2.createElement("div", { className: cn("flex flex-col", className) }, /* @__PURE__ */ React2.createElement(DialogHeader, { className: "border-b border-slate-100 px-6 py-4" }, /* @__PURE__ */ React2.createElement(DialogTitle, { className: "text-base font-semibold text-slate-900" }, title)), /* @__PURE__ */ React2.createElement("div", { className: "flex flex-1 flex-col gap-4 px-6 py-4" }, /* @__PURE__ */ React2.createElement(
69
- "div",
70
- {
71
- ref: listRef,
72
- className: "max-h-[60vh] min-h-[240px] overflow-y-auto rounded-xl border border-slate-100 bg-slate-50/60 p-4"
73
- },
74
- !hasMessages && /* @__PURE__ */ React2.createElement("div", { className: "flex h-full flex-col items-center justify-center gap-2 text-sm text-slate-400" }, /* @__PURE__ */ React2.createElement("span", null, "\u6682\u65E0\u5BF9\u8BDD\u5185\u5BB9"), /* @__PURE__ */ React2.createElement("span", null, "\u8F93\u5165\u6D88\u606F\u5F00\u59CB\u4F53\u9A8C AI \u5BF9\u8BDD\u3002")),
75
- /* @__PURE__ */ React2.createElement("div", { className: "flex flex-col gap-3" }, messages.map((message, index) => {
76
- const isUser = message.role === "user";
77
- return /* @__PURE__ */ React2.createElement(
78
- "div",
79
- {
80
- key: `${message.role}-${index}`,
81
- className: cn(
82
- "max-w-[85%] whitespace-pre-wrap rounded-2xl px-4 py-2 text-sm leading-relaxed",
83
- isUser ? "ml-auto bg-slate-900 text-white" : "mr-auto border border-slate-200 bg-white text-slate-800"
84
- )
85
- },
86
- message.content
87
- );
88
- }), isLoading && /* @__PURE__ */ React2.createElement("div", { className: "mr-auto max-w-[70%] rounded-2xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-500" }, "AI \u6B63\u5728\u601D\u8003..."))
89
- ), /* @__PURE__ */ React2.createElement("div", { className: "rounded-xl border border-slate-100 bg-white p-4 shadow-sm" }, /* @__PURE__ */ React2.createElement(
90
- "textarea",
91
- {
92
- value: input,
93
- onChange: (event) => setInput(event.target.value),
94
- onKeyDown: handleKeyDown,
95
- placeholder,
96
- className: "min-h-[96px] w-full resize-none rounded-lg border border-slate-200 px-3 py-2 text-sm text-slate-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-300"
97
- }
98
- ), /* @__PURE__ */ React2.createElement("div", { className: "mt-3 flex flex-wrap items-center justify-between gap-3" }, /* @__PURE__ */ React2.createElement("span", { className: "text-xs text-slate-400" }, helperText), /* @__PURE__ */ React2.createElement(Button, { onClick: handleSend, disabled: !input.trim() || isLoading }, isLoading ? "\u53D1\u9001\u4E2D..." : "\u53D1\u9001")), error && /* @__PURE__ */ React2.createElement("div", { className: "mt-2 rounded-md border border-rose-200 bg-rose-50 px-3 py-2 text-xs text-rose-600" }, error.message || "\u5BF9\u8BDD\u51FA\u9519\uFF0C\u8BF7\u91CD\u8BD5\u3002"))))
99
- ));
100
- };
101
- var DEFAULT_AI_CONFIG = {
102
- apiKey: "",
103
- baseUrl: "https://api.openai.com/v1",
104
- model: "gpt-3.5-turbo",
105
- systemPrompt: "",
106
- template: "{{input}}",
107
- temperature: 0.7,
108
- topP: 1,
109
- maxTokens: 1024
110
- };
111
- var mergeConfig = (base, overrides, stored) => {
112
- return {
113
- ...base,
114
- ...overrides ?? {},
115
- ...stored ?? {}
116
- };
117
- };
118
- var AiConfigPage = ({
119
- storageKey = "sa2kit-ai-config",
120
- initialConfig,
121
- title = "AI \u914D\u7F6E",
122
- description = "\u914D\u7F6E API Key\u3001\u6A21\u578B\u4E0E\u63D0\u793A\u8BCD\u6A21\u677F\uFF0C\u7528\u4E8E AI \u5BF9\u8BDD\u80FD\u529B\u3002",
123
- onSave,
124
- onChange
125
- }) => {
126
- const baseConfig = useMemo(
127
- () => mergeConfig(DEFAULT_AI_CONFIG, initialConfig),
128
- [initialConfig]
129
- );
130
- const [config, setConfig] = useState(baseConfig);
131
- const [status, setStatus] = useState(null);
132
- const [showApiKey, setShowApiKey] = useState(false);
133
- useEffect(() => {
134
- if (typeof window === "undefined") {
135
- return;
136
- }
137
- if (!storageKey) {
138
- return;
139
- }
140
- const storedRaw = localStorage.getItem(storageKey);
141
- if (!storedRaw) {
142
- return;
143
- }
144
- try {
145
- const stored = JSON.parse(storedRaw);
146
- setConfig(mergeConfig(DEFAULT_AI_CONFIG, initialConfig, stored));
147
- } catch (error) {
148
- console.warn("[AiConfigPage] Failed to parse stored config:", error);
149
- }
150
- }, [storageKey, initialConfig]);
151
- const updateConfig = (updates) => {
152
- setConfig((prev) => {
153
- const next = { ...prev, ...updates };
154
- onChange?.(next);
155
- return next;
156
- });
157
- };
158
- const updateNumber = (key, value) => {
159
- const nextValue = Number(value);
160
- if (Number.isNaN(nextValue)) {
161
- return;
162
- }
163
- updateConfig({ [key]: nextValue });
164
- };
165
- const saveConfig = () => {
166
- if (typeof window !== "undefined" && storageKey) {
167
- try {
168
- localStorage.setItem(storageKey, JSON.stringify(config));
169
- } catch (error) {
170
- setStatus({ type: "error", text: "\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u6D4F\u89C8\u5668\u5B58\u50A8\u6743\u9650\u3002" });
171
- return;
172
- }
173
- }
174
- setStatus({ type: "success", text: "\u5DF2\u4FDD\u5B58\u914D\u7F6E\u3002" });
175
- onSave?.(config);
176
- };
177
- const resetConfig = () => {
178
- const next = mergeConfig(DEFAULT_AI_CONFIG, initialConfig);
179
- setConfig(next);
180
- onChange?.(next);
181
- if (typeof window !== "undefined" && storageKey) {
182
- localStorage.removeItem(storageKey);
183
- }
184
- setStatus({ type: "success", text: "\u5DF2\u6062\u590D\u9ED8\u8BA4\u914D\u7F6E\u3002" });
185
- };
186
- return /* @__PURE__ */ React2.createElement("div", { className: "w-full rounded-2xl border border-slate-200 bg-white p-6 shadow-sm" }, /* @__PURE__ */ React2.createElement("div", { className: "flex flex-col gap-2 border-b border-slate-100 pb-4" }, /* @__PURE__ */ React2.createElement("h2", { className: "text-xl font-semibold text-slate-900" }, title), /* @__PURE__ */ React2.createElement("p", { className: "text-sm text-slate-500" }, description)), /* @__PURE__ */ React2.createElement("div", { className: "mt-6 grid gap-6" }, /* @__PURE__ */ React2.createElement("section", { className: "rounded-xl border border-slate-100 bg-slate-50/60 p-4" }, /* @__PURE__ */ React2.createElement("h3", { className: "text-sm font-semibold text-slate-700" }, "API \u4FE1\u606F"), /* @__PURE__ */ React2.createElement("div", { className: "mt-4 grid gap-4" }, /* @__PURE__ */ React2.createElement("div", null, /* @__PURE__ */ React2.createElement("label", { className: "text-xs font-medium text-slate-500" }, "Base URL"), /* @__PURE__ */ React2.createElement(
187
- Input,
188
- {
189
- value: config.baseUrl,
190
- onChange: (event) => updateConfig({ baseUrl: event.target.value }),
191
- placeholder: "https://api.openai.com/v1",
192
- className: "mt-2"
193
- }
194
- )), /* @__PURE__ */ React2.createElement("div", null, /* @__PURE__ */ React2.createElement("label", { className: "text-xs font-medium text-slate-500" }, "API Key"), /* @__PURE__ */ React2.createElement("div", { className: "mt-2 flex gap-2" }, /* @__PURE__ */ React2.createElement(
195
- Input,
196
- {
197
- value: config.apiKey,
198
- onChange: (event) => updateConfig({ apiKey: event.target.value }),
199
- placeholder: "sk-...",
200
- type: showApiKey ? "text" : "password"
201
- }
202
- ), /* @__PURE__ */ React2.createElement(
203
- Button,
204
- {
205
- type: "button",
206
- variant: "outline",
207
- onClick: () => setShowApiKey((prev) => !prev)
208
- },
209
- showApiKey ? "\u9690\u85CF" : "\u663E\u793A"
210
- ))), /* @__PURE__ */ React2.createElement("div", null, /* @__PURE__ */ React2.createElement("label", { className: "text-xs font-medium text-slate-500" }, "\u6A21\u578B"), /* @__PURE__ */ React2.createElement(
211
- Input,
212
- {
213
- value: config.model,
214
- onChange: (event) => updateConfig({ model: event.target.value }),
215
- placeholder: "gpt-3.5-turbo",
216
- className: "mt-2"
217
- }
218
- )))), /* @__PURE__ */ React2.createElement("section", { className: "rounded-xl border border-slate-100 bg-white p-4 shadow-sm" }, /* @__PURE__ */ React2.createElement("h3", { className: "text-sm font-semibold text-slate-700" }, "\u63D0\u793A\u8BCD\u4E0E\u4E0A\u4E0B\u6587"), /* @__PURE__ */ React2.createElement("div", { className: "mt-4 grid gap-4" }, /* @__PURE__ */ React2.createElement("div", null, /* @__PURE__ */ React2.createElement("label", { className: "text-xs font-medium text-slate-500" }, "\u7CFB\u7EDF\u63D0\u793A\u8BCD"), /* @__PURE__ */ React2.createElement(
219
- "textarea",
220
- {
221
- value: config.systemPrompt,
222
- onChange: (event) => updateConfig({ systemPrompt: event.target.value }),
223
- placeholder: "\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684 AI \u52A9\u624B...",
224
- className: "mt-2 min-h-[96px] w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-900 shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-300"
225
- }
226
- )), /* @__PURE__ */ React2.createElement("div", null, /* @__PURE__ */ React2.createElement("label", { className: "text-xs font-medium text-slate-500" }, "\u63D0\u793A\u8BCD\u6A21\u677F"), /* @__PURE__ */ React2.createElement(
227
- "textarea",
228
- {
229
- value: config.template,
230
- onChange: (event) => updateConfig({ template: event.target.value }),
231
- placeholder: "\u8BF7\u56DE\u7B54\uFF1A{{input}}",
232
- className: "mt-2 min-h-[96px] w-full rounded-md border border-slate-200 bg-white px-3 py-2 text-sm text-slate-900 shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-300"
233
- }
234
- ), /* @__PURE__ */ React2.createElement("p", { className: "mt-2 text-xs text-slate-400" }, "\u652F\u6301\u53D8\u91CF\u63D2\u5165\uFF1A", /* @__PURE__ */ React2.createElement("code", { className: "rounded bg-slate-100 px-1" }, "{{input}}"))))), /* @__PURE__ */ React2.createElement("section", { className: "rounded-xl border border-slate-100 bg-slate-50/60 p-4" }, /* @__PURE__ */ React2.createElement("h3", { className: "text-sm font-semibold text-slate-700" }, "\u6A21\u578B\u53C2\u6570"), /* @__PURE__ */ React2.createElement("div", { className: "mt-4 grid gap-4 md:grid-cols-3" }, /* @__PURE__ */ React2.createElement("div", null, /* @__PURE__ */ React2.createElement("label", { className: "text-xs font-medium text-slate-500" }, "Temperature"), /* @__PURE__ */ React2.createElement(
235
- Input,
236
- {
237
- type: "number",
238
- value: config.temperature,
239
- onChange: (event) => updateNumber("temperature", event.target.value),
240
- className: "mt-2"
241
- }
242
- )), /* @__PURE__ */ React2.createElement("div", null, /* @__PURE__ */ React2.createElement("label", { className: "text-xs font-medium text-slate-500" }, "Top P"), /* @__PURE__ */ React2.createElement(
243
- Input,
244
- {
245
- type: "number",
246
- value: config.topP,
247
- onChange: (event) => updateNumber("topP", event.target.value),
248
- className: "mt-2"
249
- }
250
- )), /* @__PURE__ */ React2.createElement("div", null, /* @__PURE__ */ React2.createElement("label", { className: "text-xs font-medium text-slate-500" }, "Max Tokens"), /* @__PURE__ */ React2.createElement(
251
- Input,
252
- {
253
- type: "number",
254
- value: config.maxTokens,
255
- onChange: (event) => updateNumber("maxTokens", event.target.value),
256
- className: "mt-2"
257
- }
258
- )))), /* @__PURE__ */ React2.createElement("div", { className: "flex flex-wrap items-center gap-3" }, /* @__PURE__ */ React2.createElement(Button, { onClick: saveConfig }, "\u4FDD\u5B58\u914D\u7F6E"), /* @__PURE__ */ React2.createElement(Button, { variant: "outline", onClick: resetConfig }, "\u6062\u590D\u9ED8\u8BA4"), status && /* @__PURE__ */ React2.createElement(
259
- "span",
260
- {
261
- className: cn(
262
- "text-xs",
263
- status.type === "success" ? "text-emerald-600" : "text-rose-600"
264
- )
265
- },
266
- status.text
267
- ))));
268
- };
269
-
270
- export { AiChatDialog, AiConfigPage };
271
- //# sourceMappingURL=chunk-IJIQUMAK.mjs.map
272
- //# sourceMappingURL=chunk-IJIQUMAK.mjs.map