@scenemesh/entity-engine-aimodule 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +854 -0
  3. package/dist/ai-core-LBGYFGOK.mjs +17 -0
  4. package/dist/ai-core-LBGYFGOK.mjs.map +1 -0
  5. package/dist/ai-core-UGJWSCQN.js +17 -0
  6. package/dist/ai-core-UGJWSCQN.js.map +1 -0
  7. package/dist/ai-core-manager-B3Z34RHA.mjs +9 -0
  8. package/dist/ai-core-manager-B3Z34RHA.mjs.map +1 -0
  9. package/dist/ai-core-manager-W7SSDCG5.js +9 -0
  10. package/dist/ai-core-manager-W7SSDCG5.js.map +1 -0
  11. package/dist/ai-embeddings-5ED5LDXX.mjs +17 -0
  12. package/dist/ai-embeddings-5ED5LDXX.mjs.map +1 -0
  13. package/dist/ai-embeddings-WCXZMMTZ.js +17 -0
  14. package/dist/ai-embeddings-WCXZMMTZ.js.map +1 -0
  15. package/dist/ai-form-renderer-24IWNMX5.js +233 -0
  16. package/dist/ai-form-renderer-24IWNMX5.js.map +1 -0
  17. package/dist/ai-form-renderer-BORQABF2.mjs +233 -0
  18. package/dist/ai-form-renderer-BORQABF2.mjs.map +1 -0
  19. package/dist/ai-provider-3PSCVEEN.mjs +17 -0
  20. package/dist/ai-provider-3PSCVEEN.mjs.map +1 -0
  21. package/dist/ai-provider-WMPMVZFL.js +17 -0
  22. package/dist/ai-provider-WMPMVZFL.js.map +1 -0
  23. package/dist/ai-renderer-7WGGWH5D.mjs +134 -0
  24. package/dist/ai-renderer-7WGGWH5D.mjs.map +1 -0
  25. package/dist/ai-renderer-OILYWAJV.js +134 -0
  26. package/dist/ai-renderer-OILYWAJV.js.map +1 -0
  27. package/dist/ai-settings-DGCFPK3U.js +15 -0
  28. package/dist/ai-settings-DGCFPK3U.js.map +1 -0
  29. package/dist/ai-settings-DTXEAB64.mjs +15 -0
  30. package/dist/ai-settings-DTXEAB64.mjs.map +1 -0
  31. package/dist/ai-structured-EGZ26ZS4.mjs +13 -0
  32. package/dist/ai-structured-EGZ26ZS4.mjs.map +1 -0
  33. package/dist/ai-structured-N2FZLO4A.js +13 -0
  34. package/dist/ai-structured-N2FZLO4A.js.map +1 -0
  35. package/dist/ai-tools-B3R77HZ3.js +19 -0
  36. package/dist/ai-tools-B3R77HZ3.js.map +1 -0
  37. package/dist/ai-tools-JAPVYQGE.mjs +19 -0
  38. package/dist/ai-tools-JAPVYQGE.mjs.map +1 -0
  39. package/dist/ai.module-GAHVCBTP.js +7 -0
  40. package/dist/ai.module-GAHVCBTP.js.map +1 -0
  41. package/dist/ai.module-TTPMTPB3.mjs +7 -0
  42. package/dist/ai.module-TTPMTPB3.mjs.map +1 -0
  43. package/dist/chunk-25C2NRSD.mjs +611 -0
  44. package/dist/chunk-25C2NRSD.mjs.map +1 -0
  45. package/dist/chunk-4JQ7UOXH.js +427 -0
  46. package/dist/chunk-4JQ7UOXH.js.map +1 -0
  47. package/dist/chunk-6IUKES2L.js +290 -0
  48. package/dist/chunk-6IUKES2L.js.map +1 -0
  49. package/dist/chunk-COWPK7XN.mjs +834 -0
  50. package/dist/chunk-COWPK7XN.mjs.map +1 -0
  51. package/dist/chunk-CTEXPMVZ.js +512 -0
  52. package/dist/chunk-CTEXPMVZ.js.map +1 -0
  53. package/dist/chunk-DXQTHA75.js +573 -0
  54. package/dist/chunk-DXQTHA75.js.map +1 -0
  55. package/dist/chunk-DZFQ6I23.js +72 -0
  56. package/dist/chunk-DZFQ6I23.js.map +1 -0
  57. package/dist/chunk-J323UTPE.mjs +650 -0
  58. package/dist/chunk-J323UTPE.mjs.map +1 -0
  59. package/dist/chunk-LHNNALVF.js +834 -0
  60. package/dist/chunk-LHNNALVF.js.map +1 -0
  61. package/dist/chunk-O7SZSMXV.js +1621 -0
  62. package/dist/chunk-O7SZSMXV.js.map +1 -0
  63. package/dist/chunk-OTNOFOVW.js +650 -0
  64. package/dist/chunk-OTNOFOVW.js.map +1 -0
  65. package/dist/chunk-PRIGZEI4.mjs +72 -0
  66. package/dist/chunk-PRIGZEI4.mjs.map +1 -0
  67. package/dist/chunk-SBSZ3IPB.mjs +573 -0
  68. package/dist/chunk-SBSZ3IPB.mjs.map +1 -0
  69. package/dist/chunk-SXPA6SSD.mjs +1621 -0
  70. package/dist/chunk-SXPA6SSD.mjs.map +1 -0
  71. package/dist/chunk-T5A4KAVS.mjs +512 -0
  72. package/dist/chunk-T5A4KAVS.mjs.map +1 -0
  73. package/dist/chunk-TDRKKUNT.mjs +357 -0
  74. package/dist/chunk-TDRKKUNT.mjs.map +1 -0
  75. package/dist/chunk-TJFNODPE.js +357 -0
  76. package/dist/chunk-TJFNODPE.js.map +1 -0
  77. package/dist/chunk-V2SSI3SL.mjs +427 -0
  78. package/dist/chunk-V2SSI3SL.mjs.map +1 -0
  79. package/dist/chunk-X42L6MTY.mjs +290 -0
  80. package/dist/chunk-X42L6MTY.mjs.map +1 -0
  81. package/dist/chunk-YSVMY77H.js +611 -0
  82. package/dist/chunk-YSVMY77H.js.map +1 -0
  83. package/dist/core-ANYRS6EF.mjs +73 -0
  84. package/dist/core-ANYRS6EF.mjs.map +1 -0
  85. package/dist/core-K5K34DCS.js +73 -0
  86. package/dist/core-K5K34DCS.js.map +1 -0
  87. package/dist/core-index.d.mts +1668 -0
  88. package/dist/core-index.d.ts +1668 -0
  89. package/dist/core-index.js +101 -0
  90. package/dist/core-index.js.map +1 -0
  91. package/dist/core-index.mjs +101 -0
  92. package/dist/core-index.mjs.map +1 -0
  93. package/dist/index.d.mts +2911 -0
  94. package/dist/index.d.ts +2911 -0
  95. package/dist/index.js +1177 -0
  96. package/dist/index.js.map +1 -0
  97. package/dist/index.mjs +1177 -0
  98. package/dist/index.mjs.map +1 -0
  99. package/dist/tools-352X7A6X.mjs +366 -0
  100. package/dist/tools-352X7A6X.mjs.map +1 -0
  101. package/dist/tools-YLEX6GNO.js +366 -0
  102. package/dist/tools-YLEX6GNO.js.map +1 -0
  103. package/dist/ui-index.d.mts +627 -0
  104. package/dist/ui-index.d.ts +627 -0
  105. package/dist/ui-index.js +2354 -0
  106. package/dist/ui-index.js.map +1 -0
  107. package/dist/ui-index.mjs +2353 -0
  108. package/dist/ui-index.mjs.map +1 -0
  109. package/package.json +105 -0
@@ -0,0 +1,2353 @@
1
+ "use client";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __esm = (fn, res) => function __init() {
7
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
+ };
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
+
23
+ // src/hooks/useChat.ts
24
+ import { useChat as useAIChat } from "@ai-sdk/react";
25
+ var useChat;
26
+ var init_useChat = __esm({
27
+ "src/hooks/useChat.ts"() {
28
+ "use strict";
29
+ useChat = useAIChat;
30
+ }
31
+ });
32
+
33
+ // src/hooks/useObject.ts
34
+ import { experimental_useObject as useAIObject } from "@ai-sdk/react";
35
+ var useObject;
36
+ var init_useObject = __esm({
37
+ "src/hooks/useObject.ts"() {
38
+ "use strict";
39
+ useObject = useAIObject;
40
+ }
41
+ });
42
+
43
+ // src/hooks/useCompletion.ts
44
+ import { useCompletion as useAICompletion } from "@ai-sdk/react";
45
+ var useCompletion;
46
+ var init_useCompletion = __esm({
47
+ "src/hooks/useCompletion.ts"() {
48
+ "use strict";
49
+ useCompletion = useAICompletion;
50
+ }
51
+ });
52
+
53
+ // src/hooks/index.ts
54
+ var hooks_exports = {};
55
+ __export(hooks_exports, {
56
+ useChat: () => useChat,
57
+ useCompletion: () => useCompletion,
58
+ useObject: () => useObject
59
+ });
60
+ var init_hooks = __esm({
61
+ "src/hooks/index.ts"() {
62
+ "use strict";
63
+ init_useChat();
64
+ init_useObject();
65
+ init_useCompletion();
66
+ }
67
+ });
68
+
69
+ // src/components/DynamicUI/EntityEngineDynamicComponents.tsx
70
+ import { EntityViewContainer } from "@scenemesh/entity-engine";
71
+ import { jsx, jsxs } from "react/jsx-runtime";
72
+ var DynamicEntityGridComponent, DynamicEntityFormComponent, DynamicEntityKanbanComponent, DynamicEntityDashboardComponent, DynamicEntityMastailComponent, DynamicErrorDisplayComponent, ENTITY_DYNAMIC_COMPONENTS;
73
+ var init_EntityEngineDynamicComponents = __esm({
74
+ "src/components/DynamicUI/EntityEngineDynamicComponents.tsx"() {
75
+ "use strict";
76
+ DynamicEntityGridComponent = ({
77
+ modelName = "",
78
+ displayMode = "table",
79
+ toolName,
80
+ _renderHint
81
+ }) => {
82
+ if (!modelName) {
83
+ return /* @__PURE__ */ jsxs("div", { style: {
84
+ padding: "1rem",
85
+ border: "1px solid #e2e8f0",
86
+ borderRadius: "0.5rem",
87
+ backgroundColor: "#f8fafc"
88
+ }, children: [
89
+ /* @__PURE__ */ jsxs("h4", { children: [
90
+ "\u26A0\uFE0F ",
91
+ toolName,
92
+ " \u9519\u8BEF"
93
+ ] }),
94
+ /* @__PURE__ */ jsx("p", { children: "\u7F3A\u5C11\u5FC5\u9700\u7684 modelName \u53C2\u6570" })
95
+ ] });
96
+ }
97
+ return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
98
+ EntityViewContainer,
99
+ {
100
+ modelName,
101
+ viewType: "grid",
102
+ behavior: { mode: "display" },
103
+ viewOptions: {
104
+ mode: displayMode,
105
+ hideToolbar: false,
106
+ hideEditColumn: false,
107
+ hidePagination: false
108
+ }
109
+ }
110
+ ) });
111
+ };
112
+ DynamicEntityFormComponent = ({
113
+ modelName = "",
114
+ baseObjectId,
115
+ mode = "display",
116
+ toCreating = false,
117
+ toolName
118
+ }) => {
119
+ if (!modelName) {
120
+ return /* @__PURE__ */ jsxs("div", { style: {
121
+ padding: "1rem",
122
+ border: "1px solid #e2e8f0",
123
+ borderRadius: "0.5rem",
124
+ backgroundColor: "#f8fafc"
125
+ }, children: [
126
+ /* @__PURE__ */ jsxs("h4", { children: [
127
+ "\u26A0\uFE0F ",
128
+ toolName,
129
+ " \u9519\u8BEF"
130
+ ] }),
131
+ /* @__PURE__ */ jsx("p", { children: "\u7F3A\u5C11\u5FC5\u9700\u7684 modelName \u53C2\u6570" })
132
+ ] });
133
+ }
134
+ return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
135
+ EntityViewContainer,
136
+ {
137
+ modelName,
138
+ viewType: "form",
139
+ baseObjectId,
140
+ behavior: {
141
+ mode,
142
+ toCreating
143
+ }
144
+ }
145
+ ) });
146
+ };
147
+ DynamicEntityKanbanComponent = ({
148
+ modelName = "",
149
+ toolName,
150
+ _renderHint
151
+ }) => {
152
+ if (!modelName) {
153
+ return /* @__PURE__ */ jsxs("div", { style: {
154
+ padding: "1rem",
155
+ border: "1px solid #e2e8f0",
156
+ borderRadius: "0.5rem",
157
+ backgroundColor: "#f8fafc"
158
+ }, children: [
159
+ /* @__PURE__ */ jsxs("h4", { children: [
160
+ "\u26A0\uFE0F ",
161
+ toolName,
162
+ " \u9519\u8BEF"
163
+ ] }),
164
+ /* @__PURE__ */ jsx("p", { children: "\u7F3A\u5C11\u5FC5\u9700\u7684 modelName \u53C2\u6570" })
165
+ ] });
166
+ }
167
+ return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
168
+ EntityViewContainer,
169
+ {
170
+ modelName,
171
+ viewType: "kanban",
172
+ behavior: { mode: "display" },
173
+ viewOptions: {
174
+ hideToolbar: false,
175
+ hideEditColumn: false,
176
+ hidePagination: false
177
+ }
178
+ }
179
+ ) });
180
+ };
181
+ DynamicEntityDashboardComponent = ({
182
+ modelName = "",
183
+ toolName,
184
+ _renderHint
185
+ }) => {
186
+ if (!modelName) {
187
+ return /* @__PURE__ */ jsxs("div", { style: {
188
+ padding: "1rem",
189
+ border: "1px solid #e2e8f0",
190
+ borderRadius: "0.5rem",
191
+ backgroundColor: "#f8fafc"
192
+ }, children: [
193
+ /* @__PURE__ */ jsxs("h4", { children: [
194
+ "\u26A0\uFE0F ",
195
+ toolName,
196
+ " \u9519\u8BEF"
197
+ ] }),
198
+ /* @__PURE__ */ jsx("p", { children: "\u7F3A\u5C11\u5FC5\u9700\u7684 modelName \u53C2\u6570" })
199
+ ] });
200
+ }
201
+ return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
202
+ EntityViewContainer,
203
+ {
204
+ modelName,
205
+ viewType: "dashboard",
206
+ behavior: { mode: "display" },
207
+ viewOptions: {
208
+ hideToolbar: false,
209
+ hideEditColumn: false,
210
+ hidePagination: false
211
+ }
212
+ }
213
+ ) });
214
+ };
215
+ DynamicEntityMastailComponent = ({
216
+ modelName = "",
217
+ baseObjectId,
218
+ toolName,
219
+ _renderHint
220
+ }) => {
221
+ if (!modelName) {
222
+ return /* @__PURE__ */ jsxs("div", { style: {
223
+ padding: "1rem",
224
+ border: "1px solid #e2e8f0",
225
+ borderRadius: "0.5rem",
226
+ backgroundColor: "#f8fafc"
227
+ }, children: [
228
+ /* @__PURE__ */ jsxs("h4", { children: [
229
+ "\u26A0\uFE0F ",
230
+ toolName,
231
+ " \u9519\u8BEF"
232
+ ] }),
233
+ /* @__PURE__ */ jsx("p", { children: "\u7F3A\u5C11\u5FC5\u9700\u7684 modelName \u53C2\u6570" })
234
+ ] });
235
+ }
236
+ return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
237
+ EntityViewContainer,
238
+ {
239
+ modelName,
240
+ viewType: "mastail",
241
+ baseObjectId,
242
+ behavior: { mode: "display" },
243
+ viewOptions: {
244
+ hideToolbar: false,
245
+ hideEditColumn: false,
246
+ hidePagination: false
247
+ }
248
+ }
249
+ ) });
250
+ };
251
+ DynamicErrorDisplayComponent = ({
252
+ toolName,
253
+ error,
254
+ errorDetails,
255
+ errorType,
256
+ executedAt,
257
+ _renderHint
258
+ }) => /* @__PURE__ */ jsxs("div", { style: {
259
+ padding: "1rem",
260
+ backgroundColor: "#fee2e2",
261
+ border: "1px solid #fecaca",
262
+ borderRadius: "0.5rem",
263
+ color: "#dc2626",
264
+ margin: "0.5rem 0"
265
+ }, children: [
266
+ /* @__PURE__ */ jsxs("div", { style: { fontWeight: "500", marginBottom: "0.5rem" }, children: [
267
+ "\u274C ",
268
+ toolName,
269
+ " \u6267\u884C\u5931\u8D25"
270
+ ] }),
271
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "0.875rem" }, children: error }),
272
+ errorDetails && /* @__PURE__ */ jsxs("details", { style: { marginTop: "0.5rem" }, children: [
273
+ /* @__PURE__ */ jsx("summary", { style: { cursor: "pointer", fontSize: "0.875rem" }, children: "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F" }),
274
+ /* @__PURE__ */ jsx("pre", { style: {
275
+ marginTop: "0.25rem",
276
+ fontSize: "0.75rem",
277
+ backgroundColor: "#fef2f2",
278
+ padding: "0.5rem",
279
+ borderRadius: "0.25rem",
280
+ overflow: "auto",
281
+ whiteSpace: "pre-wrap"
282
+ }, children: errorDetails })
283
+ ] }),
284
+ executedAt && /* @__PURE__ */ jsxs("div", { style: {
285
+ fontSize: "0.75rem",
286
+ color: "#991b1b",
287
+ marginTop: "0.5rem",
288
+ opacity: 0.8
289
+ }, children: [
290
+ "\u6267\u884C\u65F6\u95F4: ",
291
+ new Date(executedAt).toLocaleString()
292
+ ] })
293
+ ] });
294
+ ENTITY_DYNAMIC_COMPONENTS = {
295
+ "DynamicDataTable": DynamicEntityGridComponent,
296
+ "DynamicDataGrid": DynamicEntityGridComponent,
297
+ "DynamicDataList": DynamicEntityGridComponent,
298
+ "DynamicEntityForm": DynamicEntityFormComponent,
299
+ "DynamicEntityKanban": DynamicEntityKanbanComponent,
300
+ "DynamicEntityDashboard": DynamicEntityDashboardComponent,
301
+ "DynamicEntityMastail": DynamicEntityMastailComponent,
302
+ "DynamicErrorDisplay": DynamicErrorDisplayComponent
303
+ };
304
+ }
305
+ });
306
+
307
+ // src/components/DynamicUI/DynamicToolRenderer.tsx
308
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
309
+ function DynamicToolRenderer({ toolName, input, output, state }) {
310
+ switch (state) {
311
+ case "input-streaming":
312
+ return /* @__PURE__ */ jsxs2("div", { style: { padding: "0.75rem", background: "#f8fafc", borderRadius: "0.5rem", border: "1px solid #e2e8f0" }, children: [
313
+ /* @__PURE__ */ jsxs2("div", { style: { fontWeight: "500", marginBottom: "0.25rem" }, children: [
314
+ "\u26A1 ",
315
+ toolName,
316
+ " - \u51C6\u5907\u4E2D..."
317
+ ] }),
318
+ /* @__PURE__ */ jsx2("div", { style: { fontSize: "0.875rem", color: "#64748b" }, children: "\u6B63\u5728\u89E3\u6790\u5DE5\u5177\u53C2\u6570..." })
319
+ ] });
320
+ case "input-available":
321
+ return /* @__PURE__ */ jsxs2("div", { style: { padding: "0.75rem", background: "#fef3c7", borderRadius: "0.5rem", border: "1px solid #f59e0b" }, children: [
322
+ /* @__PURE__ */ jsxs2("div", { style: { fontWeight: "500", marginBottom: "0.25rem" }, children: [
323
+ "\u{1F527} ",
324
+ toolName,
325
+ " - \u6267\u884C\u4E2D"
326
+ ] }),
327
+ /* @__PURE__ */ jsxs2("div", { style: { fontSize: "0.875rem", color: "#92400e" }, children: [
328
+ input?.modelName && `\u67E5\u8BE2\u6A21\u578B\uFF1A${input.modelName}`,
329
+ input?.displayMode && ` | \u663E\u793A\u6A21\u5F0F\uFF1A${input.displayMode}`
330
+ ] })
331
+ ] });
332
+ case "output-available":
333
+ return /* @__PURE__ */ jsx2(
334
+ DynamicOutputRenderer,
335
+ {
336
+ toolName,
337
+ input,
338
+ output
339
+ }
340
+ );
341
+ case "output-error":
342
+ return /* @__PURE__ */ jsxs2("div", { style: {
343
+ padding: "1rem",
344
+ background: "#fee2e2",
345
+ borderRadius: "0.5rem",
346
+ border: "1px solid #fecaca",
347
+ color: "#dc2626"
348
+ }, children: [
349
+ /* @__PURE__ */ jsxs2("div", { style: { fontWeight: "500", marginBottom: "0.5rem" }, children: [
350
+ "\u274C ",
351
+ toolName,
352
+ " \u6267\u884C\u5931\u8D25"
353
+ ] }),
354
+ /* @__PURE__ */ jsx2("p", { style: { margin: 0 }, children: output?.error || "\u672A\u77E5\u9519\u8BEF" }),
355
+ output?.errorDetails && /* @__PURE__ */ jsxs2("details", { style: { marginTop: "0.5rem" }, children: [
356
+ /* @__PURE__ */ jsx2("summary", { style: { cursor: "pointer" }, children: "\u8BE6\u7EC6\u4FE1\u606F" }),
357
+ /* @__PURE__ */ jsx2("p", { style: { marginTop: "0.25rem", fontSize: "0.875rem" }, children: output.errorDetails })
358
+ ] })
359
+ ] });
360
+ default:
361
+ return /* @__PURE__ */ jsxs2("div", { style: { padding: "0.75rem", background: "#f1f5f9", borderRadius: "0.5rem" }, children: [
362
+ /* @__PURE__ */ jsxs2("h4", { children: [
363
+ "\u{1F527} ",
364
+ toolName
365
+ ] }),
366
+ /* @__PURE__ */ jsxs2("p", { children: [
367
+ "\u672A\u77E5\u72B6\u6001: ",
368
+ state
369
+ ] })
370
+ ] });
371
+ }
372
+ }
373
+ function DynamicOutputRenderer({ toolName, input, output }) {
374
+ const renderHint = output?._renderHint;
375
+ const componentType = renderHint?.componentType;
376
+ const displayMode = input?.displayMode || output?.displayMode;
377
+ let selectedComponentType;
378
+ if (componentType && componentType in ENTITY_DYNAMIC_COMPONENTS) {
379
+ selectedComponentType = componentType;
380
+ } else {
381
+ switch (displayMode) {
382
+ case "table":
383
+ selectedComponentType = "DynamicDataTable";
384
+ break;
385
+ case "list":
386
+ selectedComponentType = "DynamicDataGrid";
387
+ break;
388
+ case "grid":
389
+ selectedComponentType = "DynamicDataGrid";
390
+ break;
391
+ case "form":
392
+ selectedComponentType = "DynamicEntityForm";
393
+ break;
394
+ case "kanban":
395
+ selectedComponentType = "DynamicEntityKanban";
396
+ break;
397
+ case "dashboard":
398
+ selectedComponentType = "DynamicEntityDashboard";
399
+ break;
400
+ case "mastail":
401
+ selectedComponentType = "DynamicEntityMastail";
402
+ break;
403
+ default:
404
+ if (input?.baseObjectId || output?.baseObjectId) {
405
+ selectedComponentType = "DynamicEntityForm";
406
+ } else {
407
+ selectedComponentType = "DynamicDataGrid";
408
+ }
409
+ }
410
+ }
411
+ const SelectedComponent = ENTITY_DYNAMIC_COMPONENTS[selectedComponentType];
412
+ const componentProps = {
413
+ toolName,
414
+ modelName: input?.modelName || output?.modelName,
415
+ displayMode: displayMode || "table",
416
+ data: output?.data,
417
+ totalCount: output?.totalCount,
418
+ pagination: output?.pagination,
419
+ query: output?.query || {
420
+ sortBy: input?.sortBy,
421
+ filters: input?.filters
422
+ },
423
+ baseObjectId: input?.baseObjectId,
424
+ mode: input?.mode === "create" ? "edit" : input?.mode || "display",
425
+ toCreating: input?.mode === "create",
426
+ executedAt: output?.executedAt,
427
+ toolCallId: output?.toolCallId,
428
+ _renderHint: renderHint
429
+ };
430
+ if (selectedComponentType === "DynamicErrorDisplay") {
431
+ componentProps.error = output?.error || "Unknown error";
432
+ componentProps.errorDetails = output?.errorDetails || renderHint?.errorDetails;
433
+ componentProps.errorType = output?.errorType || renderHint?.errorType || "unknown";
434
+ }
435
+ return /* @__PURE__ */ jsxs2("div", { style: { margin: "0.5rem 0" }, children: [
436
+ /* @__PURE__ */ jsxs2("div", { style: {
437
+ fontWeight: "500",
438
+ marginBottom: "0.75rem",
439
+ padding: "0.5rem",
440
+ background: "#f0f9ff",
441
+ borderRadius: "0.375rem",
442
+ border: "1px solid #e0f2fe"
443
+ }, children: [
444
+ "\u{1F527} ",
445
+ toolName,
446
+ " \u7ED3\u679C",
447
+ output?.executedAt && /* @__PURE__ */ jsx2("span", { style: {
448
+ fontSize: "0.75rem",
449
+ color: "#64748b",
450
+ marginLeft: "0.5rem"
451
+ }, children: new Date(output.executedAt).toLocaleString() })
452
+ ] }),
453
+ /* @__PURE__ */ jsx2(SelectedComponent, { ...componentProps })
454
+ ] });
455
+ }
456
+ var init_DynamicToolRenderer = __esm({
457
+ "src/components/DynamicUI/DynamicToolRenderer.tsx"() {
458
+ "use strict";
459
+ init_EntityEngineDynamicComponents();
460
+ }
461
+ });
462
+
463
+ // src/components/DynamicUI/index.ts
464
+ var init_DynamicUI = __esm({
465
+ "src/components/DynamicUI/index.ts"() {
466
+ "use strict";
467
+ init_DynamicToolRenderer();
468
+ init_EntityEngineDynamicComponents();
469
+ }
470
+ });
471
+
472
+ // src/components/GenerativeUI/PrebuiltComponents.tsx
473
+ import { EntityViewContainer as EntityViewContainer2 } from "@scenemesh/entity-engine";
474
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
475
+ var WeatherComponent, LocationComponent, CodeExecutionComponent;
476
+ var init_PrebuiltComponents = __esm({
477
+ "src/components/GenerativeUI/PrebuiltComponents.tsx"() {
478
+ "use strict";
479
+ WeatherComponent = ({
480
+ temperature = 0,
481
+ weather = "",
482
+ location = "",
483
+ humidity,
484
+ windSpeed
485
+ }) => (
486
+ // <div style={{
487
+ // background: 'linear-gradient(135deg, #74b9ff 0%, #0984e3 100%)',
488
+ // color: 'white',
489
+ // padding: '1.5rem',
490
+ // borderRadius: '0.75rem',
491
+ // margin: '0.5rem 0',
492
+ // boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)'
493
+ // }}>
494
+ // <div style={{ display: 'flex', alignItems: 'center', marginBottom: '0.5rem' }}>
495
+ // <span style={{ fontSize: '1.5rem', marginRight: '0.5rem' }}>🌤️</span>
496
+ // <h3 style={{ margin: 0, fontSize: '1.25rem' }}>{location}</h3>
497
+ // </div>
498
+ // <p style={{ margin: '0.25rem 0', fontSize: '1rem' }}>{weather}</p>
499
+ // <p style={{ margin: '0.25rem 0', fontSize: '1.5rem', fontWeight: 'bold' }}>{temperature}°C</p>
500
+ // {humidity && <p style={{ margin: '0.25rem 0', fontSize: '0.875rem' }}>湿度: {humidity}%</p>}
501
+ // {windSpeed && <p style={{ margin: '0.25rem 0', fontSize: '0.875rem' }}>风速: {windSpeed} km/h</p>}
502
+ // </div>
503
+ /* @__PURE__ */ jsx3(EntityViewContainer2, { modelName: "product", viewType: "grid", behavior: { mode: "edit" } })
504
+ );
505
+ LocationComponent = ({
506
+ city = "",
507
+ country = "",
508
+ province = "",
509
+ coordinates,
510
+ timezone = "",
511
+ population,
512
+ area
513
+ }) => /* @__PURE__ */ jsxs3("div", { style: {
514
+ background: "linear-gradient(135deg, #fd79a8 0%, #e84393 100%)",
515
+ color: "white",
516
+ padding: "1.5rem",
517
+ borderRadius: "0.75rem",
518
+ margin: "0.5rem 0",
519
+ boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)"
520
+ }, children: [
521
+ /* @__PURE__ */ jsxs3("div", { style: { display: "flex", alignItems: "center", marginBottom: "0.5rem" }, children: [
522
+ /* @__PURE__ */ jsx3("span", { style: { fontSize: "1.5rem", marginRight: "0.5rem" }, children: "\u{1F4CD}" }),
523
+ /* @__PURE__ */ jsx3("h3", { style: { margin: 0, fontSize: "1.25rem" }, children: city })
524
+ ] }),
525
+ province && /* @__PURE__ */ jsxs3("p", { style: { margin: "0.25rem 0", fontSize: "1rem" }, children: [
526
+ province,
527
+ ", ",
528
+ country
529
+ ] }),
530
+ coordinates && /* @__PURE__ */ jsxs3("p", { style: { margin: "0.25rem 0", fontSize: "0.875rem" }, children: [
531
+ "\u5750\u6807: ",
532
+ coordinates.lat.toFixed(4),
533
+ ", ",
534
+ coordinates.lng.toFixed(4)
535
+ ] }),
536
+ timezone && /* @__PURE__ */ jsxs3("p", { style: { margin: "0.25rem 0", fontSize: "0.875rem" }, children: [
537
+ "\u65F6\u533A: ",
538
+ timezone
539
+ ] }),
540
+ population && /* @__PURE__ */ jsxs3("p", { style: { margin: "0.25rem 0", fontSize: "0.875rem" }, children: [
541
+ "\u4EBA\u53E3: ",
542
+ population.toLocaleString(),
543
+ "\u4E07\u4EBA"
544
+ ] }),
545
+ area && /* @__PURE__ */ jsxs3("p", { style: { margin: "0.25rem 0", fontSize: "0.875rem" }, children: [
546
+ "\u9762\u79EF: ",
547
+ area.toLocaleString(),
548
+ " km\xB2"
549
+ ] })
550
+ ] });
551
+ CodeExecutionComponent = ({
552
+ code = "",
553
+ language = "javascript",
554
+ output = "",
555
+ status = "success"
556
+ }) => /* @__PURE__ */ jsxs3("div", { style: {
557
+ background: "#f8fafc",
558
+ border: "1px solid #e2e8f0",
559
+ borderRadius: "0.75rem",
560
+ margin: "0.5rem 0",
561
+ overflow: "hidden"
562
+ }, children: [
563
+ /* @__PURE__ */ jsxs3("div", { style: {
564
+ background: "#334155",
565
+ color: "white",
566
+ padding: "0.75rem 1rem",
567
+ fontSize: "0.875rem",
568
+ display: "flex",
569
+ alignItems: "center"
570
+ }, children: [
571
+ /* @__PURE__ */ jsx3("span", { style: { marginRight: "0.5rem" }, children: "\u{1F4BB}" }),
572
+ /* @__PURE__ */ jsxs3("span", { children: [
573
+ "\u4EE3\u7801\u6267\u884C (",
574
+ language,
575
+ ")"
576
+ ] }),
577
+ /* @__PURE__ */ jsx3("span", { style: {
578
+ marginLeft: "auto",
579
+ fontSize: "0.75rem",
580
+ color: status === "success" ? "#10b981" : status === "error" ? "#ef4444" : "#f59e0b"
581
+ }, children: status === "success" ? "\u2705 \u6210\u529F" : status === "error" ? "\u274C \u9519\u8BEF" : "\u23F3 \u8FD0\u884C\u4E2D" })
582
+ ] }),
583
+ code && /* @__PURE__ */ jsx3("div", { style: { padding: "1rem" }, children: /* @__PURE__ */ jsx3("pre", { style: {
584
+ background: "#1e293b",
585
+ color: "#e2e8f0",
586
+ padding: "1rem",
587
+ borderRadius: "0.5rem",
588
+ fontSize: "0.875rem",
589
+ overflow: "auto",
590
+ margin: "0 0 1rem 0"
591
+ }, children: code }) }),
592
+ output && /* @__PURE__ */ jsxs3("div", { style: { padding: "0 1rem 1rem" }, children: [
593
+ /* @__PURE__ */ jsx3("h4", { style: { margin: "0 0 0.5rem 0", fontSize: "0.875rem", color: "#64748b" }, children: "\u8F93\u51FA:" }),
594
+ /* @__PURE__ */ jsx3("pre", { style: {
595
+ background: status === "error" ? "#fef2f2" : "#f0f9ff",
596
+ color: status === "error" ? "#dc2626" : "#0f172a",
597
+ padding: "1rem",
598
+ borderRadius: "0.5rem",
599
+ fontSize: "0.875rem",
600
+ overflow: "auto",
601
+ margin: 0,
602
+ border: `1px solid ${status === "error" ? "#fecaca" : "#e0f2fe"}`
603
+ }, children: output })
604
+ ] })
605
+ ] });
606
+ }
607
+ });
608
+
609
+ // src/components/MessageBubble/MessageBubble.tsx
610
+ import { Box, Text, Badge, Group, Paper, Stack } from "@mantine/core";
611
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
612
+ function MessageBubble({
613
+ message,
614
+ showAvatar = false,
615
+ // 不再使用头像
616
+ showTimestamp = true,
617
+ onToolResult,
618
+ enableReasoning = true,
619
+ enableGenerativeUI = true,
620
+ showReasoningByDefault = false
621
+ }) {
622
+ const isUser = message.role === "user";
623
+ return /* @__PURE__ */ jsxs4(Stack, { gap: "xs", mb: "md", style: { width: "100%" }, children: [
624
+ /* @__PURE__ */ jsxs4(
625
+ Group,
626
+ {
627
+ gap: "xs",
628
+ align: "center",
629
+ justify: isUser ? "flex-end" : "flex-start",
630
+ children: [
631
+ /* @__PURE__ */ jsx4(
632
+ Badge,
633
+ {
634
+ variant: "light",
635
+ color: isUser ? "blue" : "gray",
636
+ size: "xs",
637
+ radius: "sm",
638
+ children: isUser ? "You" : "AI"
639
+ }
640
+ ),
641
+ showTimestamp && /* @__PURE__ */ jsx4(Text, { size: "xs", c: "var(--mantine-color-gray-5)", children: (/* @__PURE__ */ new Date()).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }) })
642
+ ]
643
+ }
644
+ ),
645
+ /* @__PURE__ */ jsx4(
646
+ Box,
647
+ {
648
+ style: {
649
+ width: "100%",
650
+ display: "flex",
651
+ justifyContent: isUser ? "flex-end" : "flex-start"
652
+ },
653
+ children: /* @__PURE__ */ jsx4(
654
+ Box,
655
+ {
656
+ style: {
657
+ maxWidth: "100%",
658
+ width: isUser ? "fit-content" : "100%"
659
+ },
660
+ children: message.parts.map((part, index) => {
661
+ if (part.type === "text") {
662
+ return /* @__PURE__ */ jsx4(
663
+ Text,
664
+ {
665
+ size: "sm",
666
+ style: {
667
+ lineHeight: 1.5,
668
+ whiteSpace: "pre-wrap",
669
+ wordBreak: "break-word",
670
+ textAlign: isUser ? "right" : "left"
671
+ },
672
+ c: "var(--mantine-color-text)",
673
+ children: part.text
674
+ },
675
+ index
676
+ );
677
+ }
678
+ if (part.type === "file") {
679
+ return /* @__PURE__ */ jsx4(FileDisplay, { file: part }, index);
680
+ }
681
+ if (part.type === "data") {
682
+ if (part.data?.type === "reasoning" && enableReasoning) {
683
+ return /* @__PURE__ */ jsx4(
684
+ ReasoningDisplay,
685
+ {
686
+ reasoning: part.data.content,
687
+ step: part.data.step
688
+ },
689
+ index
690
+ );
691
+ }
692
+ return null;
693
+ }
694
+ if (part.type === "tool-getWeather") {
695
+ switch (part.state) {
696
+ case "input-streaming":
697
+ return /* @__PURE__ */ jsx4(Text, { size: "xs", c: "var(--mantine-color-gray-6)", children: "Preparing weather request..." }, index);
698
+ case "input-available":
699
+ return /* @__PURE__ */ jsxs4(Text, { size: "xs", c: "var(--mantine-color-gray-6)", children: [
700
+ "Getting weather for ",
701
+ part.input?.location,
702
+ "..."
703
+ ] }, index);
704
+ case "output-available": {
705
+ if (onToolResult) {
706
+ onToolResult({
707
+ toolName: "getWeather",
708
+ input: part.input,
709
+ output: part.output,
710
+ state: part.state
711
+ });
712
+ }
713
+ const rawData = part.output.data || part.output;
714
+ const weatherData = {
715
+ ...rawData,
716
+ weather: rawData.condition || rawData.weather
717
+ };
718
+ return /* @__PURE__ */ jsx4("div", { children: /* @__PURE__ */ jsx4(WeatherComponent, { ...weatherData }) }, index);
719
+ }
720
+ case "output-error":
721
+ return /* @__PURE__ */ jsx4(Paper, { p: "sm", withBorder: true, style: {
722
+ backgroundColor: "var(--mantine-color-red-0)",
723
+ borderColor: "var(--mantine-color-red-2)",
724
+ borderLeft: "3px solid var(--mantine-color-red-4)"
725
+ }, children: /* @__PURE__ */ jsxs4(Text, { size: "xs", c: "var(--mantine-color-red-8)", children: [
726
+ "\u274C Weather Error: ",
727
+ part.errorText
728
+ ] }) }, index);
729
+ default:
730
+ return null;
731
+ }
732
+ }
733
+ if (part.type === "tool-getLocation") {
734
+ switch (part.state) {
735
+ case "input-streaming":
736
+ return /* @__PURE__ */ jsx4(Text, { size: "xs", c: "var(--mantine-color-gray-6)", children: "Preparing location request..." }, index);
737
+ case "input-available":
738
+ return /* @__PURE__ */ jsxs4(Text, { size: "xs", c: "var(--mantine-color-gray-6)", children: [
739
+ "Getting location for ",
740
+ part.input?.city,
741
+ "..."
742
+ ] }, index);
743
+ case "output-available": {
744
+ if (onToolResult) {
745
+ onToolResult({
746
+ toolName: "getLocation",
747
+ input: part.input,
748
+ output: part.output,
749
+ state: part.state
750
+ });
751
+ }
752
+ const locationData = part.output.data || part.output;
753
+ return /* @__PURE__ */ jsx4("div", { children: /* @__PURE__ */ jsx4(LocationComponent, { ...locationData }) }, index);
754
+ }
755
+ case "output-error":
756
+ return /* @__PURE__ */ jsx4(Paper, { p: "sm", withBorder: true, style: {
757
+ backgroundColor: "var(--mantine-color-red-0)",
758
+ borderColor: "var(--mantine-color-red-2)",
759
+ borderLeft: "3px solid var(--mantine-color-red-4)"
760
+ }, children: /* @__PURE__ */ jsxs4(Text, { size: "xs", c: "var(--mantine-color-red-8)", children: [
761
+ "\u274C Location Error: ",
762
+ part.errorText
763
+ ] }) }, index);
764
+ default:
765
+ return null;
766
+ }
767
+ }
768
+ if (part.type === "tool-displayWeather") {
769
+ switch (part.state) {
770
+ case "input-streaming":
771
+ return /* @__PURE__ */ jsx4(Text, { size: "xs", c: "var(--mantine-color-gray-6)", children: "Preparing weather display..." }, index);
772
+ case "input-available":
773
+ return /* @__PURE__ */ jsxs4(Text, { size: "xs", c: "var(--mantine-color-gray-6)", children: [
774
+ "Loading weather display for ",
775
+ part.input?.location,
776
+ "..."
777
+ ] }, index);
778
+ case "output-available":
779
+ return /* @__PURE__ */ jsx4("div", { children: /* @__PURE__ */ jsx4(WeatherComponent, { ...part.output }) }, index);
780
+ case "output-error":
781
+ return /* @__PURE__ */ jsx4(Paper, { p: "sm", withBorder: true, style: {
782
+ backgroundColor: "var(--mantine-color-red-0)",
783
+ borderColor: "var(--mantine-color-red-2)",
784
+ borderLeft: "3px solid var(--mantine-color-red-4)"
785
+ }, children: /* @__PURE__ */ jsxs4(Text, { size: "xs", c: "var(--mantine-color-red-8)", children: [
786
+ "\u274C Weather Display Error: ",
787
+ part.errorText
788
+ ] }) }, index);
789
+ default:
790
+ return null;
791
+ }
792
+ }
793
+ if (part.type === "tool-executeCode") {
794
+ switch (part.state) {
795
+ case "input-streaming":
796
+ return /* @__PURE__ */ jsx4(Text, { size: "xs", c: "var(--mantine-color-gray-6)", children: "Preparing code execution..." }, index);
797
+ case "input-available":
798
+ return /* @__PURE__ */ jsx4(Text, { size: "xs", c: "var(--mantine-color-gray-6)", children: "Executing code..." }, index);
799
+ case "output-available":
800
+ if (onToolResult) {
801
+ onToolResult({
802
+ toolName: "executeCode",
803
+ input: part.input,
804
+ output: part.output,
805
+ state: part.state
806
+ });
807
+ }
808
+ return /* @__PURE__ */ jsx4("div", { children: /* @__PURE__ */ jsx4(CodeExecutionComponent, { ...part.output }) }, index);
809
+ case "output-error":
810
+ return /* @__PURE__ */ jsx4(Paper, { p: "sm", withBorder: true, style: {
811
+ backgroundColor: "var(--mantine-color-red-0)",
812
+ borderColor: "var(--mantine-color-red-2)",
813
+ borderLeft: "3px solid var(--mantine-color-red-4)"
814
+ }, children: /* @__PURE__ */ jsxs4(Text, { size: "xs", c: "var(--mantine-color-red-8)", children: [
815
+ "\u274C Code Execution Error: ",
816
+ part.errorText
817
+ ] }) }, index);
818
+ default:
819
+ return null;
820
+ }
821
+ }
822
+ if (part.type === "dynamic-tool") {
823
+ return /* @__PURE__ */ jsx4(
824
+ DynamicToolRenderer,
825
+ {
826
+ toolName: part.toolName,
827
+ input: part.input,
828
+ output: part.output,
829
+ state: part.state
830
+ },
831
+ index
832
+ );
833
+ }
834
+ if (part.type === "tool-result") {
835
+ return /* @__PURE__ */ jsxs4(Paper, { p: "sm", withBorder: true, style: {
836
+ backgroundColor: "var(--mantine-color-blue-0)",
837
+ borderColor: "var(--mantine-color-blue-2)",
838
+ borderLeft: "3px solid var(--mantine-color-blue-4)"
839
+ }, children: [
840
+ /* @__PURE__ */ jsx4(Text, { size: "xs", fw: 500, c: "var(--mantine-color-blue-8)", mb: 4, children: "\u{1F527} Tool Result" }),
841
+ /* @__PURE__ */ jsx4(Text, { component: "pre", size: "xs", style: {
842
+ fontFamily: "monospace",
843
+ margin: 0,
844
+ lineHeight: 1.3,
845
+ overflow: "auto"
846
+ }, c: "var(--mantine-color-gray-7)", children: JSON.stringify(part.result, null, 2) })
847
+ ] }, index);
848
+ }
849
+ return null;
850
+ })
851
+ }
852
+ )
853
+ }
854
+ )
855
+ ] });
856
+ }
857
+ var ReasoningDisplay, FileDisplay;
858
+ var init_MessageBubble = __esm({
859
+ "src/components/MessageBubble/MessageBubble.tsx"() {
860
+ "use strict";
861
+ init_DynamicUI();
862
+ init_PrebuiltComponents();
863
+ ReasoningDisplay = ({ reasoning, step }) => /* @__PURE__ */ jsxs4(
864
+ Paper,
865
+ {
866
+ p: "sm",
867
+ withBorder: true,
868
+ style: {
869
+ backgroundColor: "var(--mantine-color-yellow-0)",
870
+ borderColor: "var(--mantine-color-yellow-2)",
871
+ borderLeft: "3px solid var(--mantine-color-yellow-4)"
872
+ },
873
+ children: [
874
+ /* @__PURE__ */ jsxs4(Text, { size: "xs", fw: 500, c: "var(--mantine-color-yellow-8)", mb: 4, children: [
875
+ "\u{1F4AD} ",
876
+ step ? `Step ${step}:` : "Reasoning:"
877
+ ] }),
878
+ /* @__PURE__ */ jsx4(Text, { size: "xs", c: "var(--mantine-color-gray-7)", style: { lineHeight: 1.3 }, children: reasoning })
879
+ ]
880
+ }
881
+ );
882
+ FileDisplay = ({ file }) => {
883
+ if (!file) return null;
884
+ return /* @__PURE__ */ jsx4(
885
+ Paper,
886
+ {
887
+ p: "sm",
888
+ withBorder: true,
889
+ style: {
890
+ backgroundColor: "var(--mantine-color-gray-0)",
891
+ borderColor: "var(--mantine-color-gray-3)"
892
+ },
893
+ children: /* @__PURE__ */ jsxs4(Group, { gap: "xs", align: "center", children: [
894
+ /* @__PURE__ */ jsx4(
895
+ Box,
896
+ {
897
+ w: 24,
898
+ h: 24,
899
+ bg: "var(--mantine-color-gray-1)",
900
+ style: {
901
+ borderRadius: "4px",
902
+ display: "flex",
903
+ alignItems: "center",
904
+ justifyContent: "center",
905
+ fontSize: "12px"
906
+ },
907
+ children: "\u{1F4CE}"
908
+ }
909
+ ),
910
+ /* @__PURE__ */ jsxs4(Box, { style: { flex: 1 }, children: [
911
+ /* @__PURE__ */ jsx4(Text, { size: "xs", fw: 500, c: "var(--mantine-color-gray-8)", children: file.name || "File" }),
912
+ file.size && /* @__PURE__ */ jsxs4(Text, { size: "xs", c: "var(--mantine-color-gray-6)", children: [
913
+ Math.round(file.size / 1024),
914
+ "KB"
915
+ ] }),
916
+ file.url && /* @__PURE__ */ jsx4(
917
+ Text,
918
+ {
919
+ size: "xs",
920
+ component: "a",
921
+ href: file.url,
922
+ target: "_blank",
923
+ rel: "noopener noreferrer",
924
+ c: "var(--mantine-color-blue-6)",
925
+ td: "none",
926
+ style: { cursor: "pointer" },
927
+ children: "View File"
928
+ }
929
+ )
930
+ ] })
931
+ ] })
932
+ }
933
+ );
934
+ };
935
+ }
936
+ });
937
+
938
+ // src/utils/theme.ts
939
+ function getThemedTextProps(variant = "primary") {
940
+ switch (variant) {
941
+ case "primary":
942
+ return { c: aiThemeColors.primaryText };
943
+ case "secondary":
944
+ return { c: aiThemeColors.secondaryText };
945
+ case "heading":
946
+ return { c: aiThemeColors.headingText, fw: 600 };
947
+ case "muted":
948
+ return { c: "var(--mantine-color-gray-6)" };
949
+ // 深色模式下更清晰
950
+ case "subtitle":
951
+ return { c: "var(--mantine-color-gray-7)", fw: 500 };
952
+ case "caption":
953
+ return { c: "var(--mantine-color-gray-6)" };
954
+ case "success":
955
+ return { c: aiThemeColors.success };
956
+ case "warning":
957
+ return { c: aiThemeColors.warning };
958
+ case "error":
959
+ return { c: aiThemeColors.error };
960
+ case "info":
961
+ return { c: aiThemeColors.info };
962
+ default:
963
+ return { c: aiThemeColors.primaryText };
964
+ }
965
+ }
966
+ var aiThemeColors, componentStyles;
967
+ var init_theme = __esm({
968
+ "src/utils/theme.ts"() {
969
+ "use strict";
970
+ aiThemeColors = {
971
+ // 主要文本颜色 - 使用 Mantine CSS 变量
972
+ primaryText: "var(--mantine-color-text)",
973
+ // 主要文本颜色,自动适配主题
974
+ secondaryText: "var(--mantine-color-dimmed)",
975
+ // 次要文本颜色
976
+ headingText: "var(--mantine-color-text)",
977
+ // 标题文本颜色
978
+ // 语义化文本颜色 - 优化深色模式
979
+ mutedText: "var(--mantine-color-dimmed)",
980
+ // 静音文本,使用dimmed确保深色模式协调
981
+ placeholderText: "var(--mantine-color-placeholder)",
982
+ // 占位符文本
983
+ // 状态颜色 - 使用 Mantine 预定义颜色
984
+ success: "var(--mantine-color-green-filled)",
985
+ warning: "var(--mantine-color-yellow-filled)",
986
+ error: "var(--mantine-color-red-filled)",
987
+ info: "var(--mantine-color-blue-filled)",
988
+ // 浅色状态颜色(用于背景)- 深色模式自动适配
989
+ successLight: "var(--mantine-color-green-light)",
990
+ warningLight: "var(--mantine-color-yellow-light)",
991
+ errorLight: "var(--mantine-color-red-light)",
992
+ infoLight: "var(--mantine-color-blue-light)",
993
+ // 背景颜色 - 深色模式自动切换
994
+ bodyBackground: "var(--mantine-color-body)",
995
+ // 主体背景
996
+ cardBackground: "var(--mantine-color-default)",
997
+ // 卡片背景,使用default确保深色模式协调
998
+ paperBackground: "var(--mantine-color-default)",
999
+ // 纸张背景
1000
+ codeBackground: "var(--mantine-color-default)",
1001
+ // 代码背景,深色模式下自动变深
1002
+ // 边框和分隔线 - 深色模式自动适配
1003
+ border: "var(--mantine-color-default-border)",
1004
+ // 默认边框
1005
+ borderLight: "var(--mantine-color-default-border)",
1006
+ // 统一使用default-border
1007
+ divider: "var(--mantine-color-default-border)",
1008
+ // 分隔线
1009
+ // 交互状态 - 深色模式友好
1010
+ hoverBackground: "var(--mantine-color-default-hover)",
1011
+ // 悬浮背景,深色模式自动调整
1012
+ selectedBackground: "var(--mantine-color-blue-light)",
1013
+ // 选中背景 - 使用蓝色,深色模式下更清晰
1014
+ selectedText: "var(--mantine-color-blue-filled)",
1015
+ // 选中文本 - 使用蓝色,深色模式下更清晰
1016
+ // 输入组件 - 深色模式协调
1017
+ inputBackground: "var(--mantine-color-default)",
1018
+ // 输入框背景
1019
+ inputBorder: "var(--mantine-color-default-border)",
1020
+ // 输入框边框
1021
+ inputPlaceholder: "var(--mantine-color-placeholder)"
1022
+ // 输入框占位符
1023
+ };
1024
+ componentStyles = {
1025
+ // 共享基础样式
1026
+ cardBackground: aiThemeColors.cardBackground,
1027
+ // 聊天对话框样式 - 深色模式优化
1028
+ chatDialog: {
1029
+ titleColor: aiThemeColors.headingText,
1030
+ descriptionColor: aiThemeColors.secondaryText,
1031
+ cardBackground: aiThemeColors.cardBackground,
1032
+ border: aiThemeColors.border
1033
+ },
1034
+ // 消息气泡样式
1035
+ messageBubble: {
1036
+ userBackground: "var(--mantine-color-blue-filled)",
1037
+ userText: "var(--mantine-color-white)",
1038
+ aiBackground: aiThemeColors.cardBackground,
1039
+ aiText: aiThemeColors.primaryText,
1040
+ border: aiThemeColors.border
1041
+ },
1042
+ // 文件查看器样式
1043
+ fileViewer: {
1044
+ background: aiThemeColors.cardBackground,
1045
+ border: aiThemeColors.borderLight,
1046
+ text: aiThemeColors.primaryText
1047
+ },
1048
+ // 代码背景
1049
+ codeBackground: aiThemeColors.codeBackground,
1050
+ // 工具栏样式
1051
+ toolbar: {
1052
+ background: aiThemeColors.bodyBackground,
1053
+ border: aiThemeColors.border,
1054
+ text: aiThemeColors.primaryText
1055
+ },
1056
+ // 状态样式配置 - 深色模式完美适配
1057
+ status: {
1058
+ error: {
1059
+ background: "var(--mantine-color-red-light)",
1060
+ border: "var(--mantine-color-red-outline)",
1061
+ text: "var(--mantine-color-red-light-color)",
1062
+ textSecondary: "var(--mantine-color-red-light-color)",
1063
+ textLight: "var(--mantine-color-red-light-color)",
1064
+ icon: "var(--mantine-color-red-light-color)",
1065
+ progressColor: "red"
1066
+ },
1067
+ warning: {
1068
+ background: "var(--mantine-color-yellow-light)",
1069
+ border: "var(--mantine-color-yellow-outline)",
1070
+ text: "var(--mantine-color-yellow-light-color)",
1071
+ textSecondary: "var(--mantine-color-yellow-light-color)",
1072
+ textLight: "var(--mantine-color-yellow-light-color)",
1073
+ icon: "var(--mantine-color-yellow-light-color)",
1074
+ progressColor: "yellow"
1075
+ },
1076
+ success: {
1077
+ background: "var(--mantine-color-green-light)",
1078
+ border: "var(--mantine-color-green-outline)",
1079
+ text: "var(--mantine-color-green-light-color)",
1080
+ textSecondary: "var(--mantine-color-green-light-color)",
1081
+ textLight: "var(--mantine-color-green-light-color)",
1082
+ icon: "var(--mantine-color-green-light-color)",
1083
+ progressColor: "green"
1084
+ },
1085
+ info: {
1086
+ background: "var(--mantine-color-blue-light)",
1087
+ border: "var(--mantine-color-blue-outline)",
1088
+ text: "var(--mantine-color-blue-light-color)",
1089
+ textSecondary: "var(--mantine-color-blue-light-color)",
1090
+ textLight: "var(--mantine-color-blue-light-color)",
1091
+ icon: "var(--mantine-color-blue-light-color)",
1092
+ progressColor: "blue"
1093
+ }
1094
+ },
1095
+ // 文字颜色标准化系统 - 深色模式优化
1096
+ text: {
1097
+ // 主要文字级别
1098
+ primary: aiThemeColors.primaryText,
1099
+ // 主标题、重要内容
1100
+ heading: aiThemeColors.headingText,
1101
+ // 页面标题、section标题
1102
+ subtitle: "var(--mantine-color-gray-7)",
1103
+ // 副标题,清晰但次要
1104
+ // 次要文字级别
1105
+ secondary: aiThemeColors.secondaryText,
1106
+ // 正文内容
1107
+ caption: "var(--mantine-color-gray-6)",
1108
+ // 说明文字,比dimmed更清晰
1109
+ label: "var(--mantine-color-gray-7)",
1110
+ // 标签文字
1111
+ // 弱化文字级别
1112
+ muted: "var(--mantine-color-gray-6)",
1113
+ // 静音文字,深色模式优化
1114
+ placeholder: aiThemeColors.placeholderText,
1115
+ // 占位符文字
1116
+ disabled: "var(--mantine-color-gray-5)",
1117
+ // 禁用状态文字
1118
+ // 状态文字
1119
+ success: aiThemeColors.success,
1120
+ warning: aiThemeColors.warning,
1121
+ error: aiThemeColors.error,
1122
+ info: aiThemeColors.info
1123
+ }
1124
+ };
1125
+ }
1126
+ });
1127
+
1128
+ // src/components/ChatDialog/ChatDialog.tsx
1129
+ import { motion, AnimatePresence } from "framer-motion";
1130
+ import React, { useRef, useState, useEffect, useCallback } from "react";
1131
+ import {
1132
+ X,
1133
+ Send,
1134
+ Square,
1135
+ Paperclip,
1136
+ AlertCircle,
1137
+ SparklesIcon
1138
+ } from "lucide-react";
1139
+ import { Box as Box2, Text as Text2, Badge as Badge2, Group as Group2, Paper as Paper2, Stack as Stack2, Title, Button, Textarea, ActionIcon, ScrollArea } from "@mantine/core";
1140
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1141
+ function ChatDialog({
1142
+ chatOptions = {},
1143
+ title = "AI Assistant",
1144
+ description = "Chat with your AI assistant",
1145
+ open = false,
1146
+ onOpenChange,
1147
+ placeholder = "Type your message here...",
1148
+ className,
1149
+ showHeader = true,
1150
+ allowFileUpload = true,
1151
+ acceptedFileTypes = ["image/*", "text/*", "application/pdf"],
1152
+ maxFileSize = 10 * 1024 * 1024,
1153
+ // 10MB
1154
+ messageRenderer,
1155
+ theme = "system",
1156
+ // 新增的增强功能选项
1157
+ enableReasoning = true,
1158
+ enableGenerativeUI = true,
1159
+ showReasoningByDefault = false
1160
+ }) {
1161
+ const [frontendToolStatus, setFrontendToolStatus] = useState({
1162
+ isProcessing: false,
1163
+ currentTool: void 0,
1164
+ processedTools: /* @__PURE__ */ new Set()
1165
+ // 防止重复处理
1166
+ });
1167
+ const handleError = useCallback((err) => {
1168
+ console.error("ChatDialog useChat error:", err);
1169
+ let friendlyError = err;
1170
+ const originalMessage = err.message || "Unknown occurred";
1171
+ if (originalMessage.includes("<!DOCTYPE") || originalMessage.includes("<html>") || originalMessage.includes("<body>")) {
1172
+ friendlyError = new Error("AI\u670D\u52A1\u8FDE\u63A5\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u670D\u52A1\u5668\u662F\u5426\u6B63\u5728\u8FD0\u884C");
1173
+ friendlyError.name = err.name;
1174
+ } else if (originalMessage.includes("fetch") || originalMessage.includes("NetworkError") || originalMessage.includes("Failed to fetch")) {
1175
+ friendlyError = new Error("AI\u670D\u52A1\u8FDE\u63A5\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5");
1176
+ friendlyError.name = err.name;
1177
+ } else if (originalMessage.includes("404") || originalMessage.includes("Not Found")) {
1178
+ friendlyError = new Error("AI API\u7AEF\u70B9\u672A\u627E\u5230\uFF0C\u8BF7\u786E\u4FDDAI\u670D\u52A1\u5668\u6B63\u5728\u8FD0\u884C\u5E76\u4E14\u7AEF\u70B9\u914D\u7F6E\u6B63\u786E");
1179
+ friendlyError.name = err.name;
1180
+ } else if (originalMessage.includes("ECONNREFUSED") || originalMessage.includes("Connection refused")) {
1181
+ friendlyError = new Error("AI\u670D\u52A1\u5668\u8FDE\u63A5\u88AB\u62D2\u7EDD");
1182
+ friendlyError.name = err.name;
1183
+ }
1184
+ chatOptions.onError?.(friendlyError);
1185
+ }, [chatOptions]);
1186
+ const {
1187
+ messages,
1188
+ status,
1189
+ error,
1190
+ sendMessage,
1191
+ stop,
1192
+ clearError,
1193
+ resumeStream,
1194
+ addToolResult,
1195
+ setMessages
1196
+ } = useChat({
1197
+ // Use standard properties from chatOptions
1198
+ ...chatOptions,
1199
+ // Standard onFinish callback
1200
+ onFinish: (options) => {
1201
+ setTimeout(() => {
1202
+ inputRef.current?.focus();
1203
+ }, 100);
1204
+ chatOptions.onFinish?.(options);
1205
+ },
1206
+ onError: handleError,
1207
+ // Standard onToolCall - for listening only, no return value
1208
+ onToolCall: chatOptions.onToolCall
1209
+ });
1210
+ useEffect(() => {
1211
+ const handleFrontendToolCall = async (toolName, input2) => {
1212
+ const frontendToolNames = [
1213
+ "recordGetValues",
1214
+ "recordSetValues",
1215
+ "recordGetFieldInfo",
1216
+ "recordResetForm",
1217
+ "recordValidateForm"
1218
+ ];
1219
+ if (!frontendToolNames.includes(toolName)) {
1220
+ return;
1221
+ }
1222
+ setFrontendToolStatus((prev) => ({
1223
+ ...prev,
1224
+ isProcessing: true,
1225
+ currentTool: toolName
1226
+ }));
1227
+ const waitId = `frontend-${toolName}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
1228
+ try {
1229
+ if (window.__ENTITY_ENGINE_AI_BRIDGE__) {
1230
+ const result = await window.__ENTITY_ENGINE_AI_BRIDGE__.executeViewControllerTool(
1231
+ toolName,
1232
+ input2 || {}
1233
+ );
1234
+ const finalResult = typeof result === "string" ? result : JSON.stringify(result, null, 2);
1235
+ await fetch("/api/ee/servlet/ai/frontend-tool-result", {
1236
+ method: "POST",
1237
+ headers: {
1238
+ "Content-Type": "application/json"
1239
+ },
1240
+ body: JSON.stringify({
1241
+ waitId: `frontend-${toolName}`,
1242
+ // 简化waitId匹配
1243
+ result: finalResult,
1244
+ timestamp: Date.now()
1245
+ })
1246
+ });
1247
+ }
1248
+ } catch (_error) {
1249
+ await fetch("/api/ee/servlet/ai/frontend-tool-result", {
1250
+ method: "POST",
1251
+ headers: {
1252
+ "Content-Type": "application/json"
1253
+ },
1254
+ body: JSON.stringify({
1255
+ waitId: `frontend-${toolName}`,
1256
+ error: error.message,
1257
+ timestamp: Date.now()
1258
+ })
1259
+ });
1260
+ } finally {
1261
+ setFrontendToolStatus((prev) => ({
1262
+ ...prev,
1263
+ isProcessing: false,
1264
+ currentTool: void 0
1265
+ }));
1266
+ }
1267
+ };
1268
+ window.__FRONTEND_TOOL_HANDLER__ = handleFrontendToolCall;
1269
+ return () => {
1270
+ if (window.__FRONTEND_TOOL_HANDLER__) {
1271
+ delete window.__FRONTEND_TOOL_HANDLER__;
1272
+ }
1273
+ };
1274
+ }, []);
1275
+ const [input, setInput] = useState("");
1276
+ const [attachedFiles, setAttachedFiles] = useState([]);
1277
+ const inputRef = useRef(null);
1278
+ const fileInputRef = useRef(null);
1279
+ const messagesEndRef = useRef(null);
1280
+ useEffect(() => {
1281
+ if (messagesEndRef.current) {
1282
+ messagesEndRef.current.scrollIntoView({ behavior: "smooth" });
1283
+ }
1284
+ }, [messages, status]);
1285
+ useEffect(() => {
1286
+ if (open && inputRef.current) {
1287
+ const timer = setTimeout(() => {
1288
+ inputRef.current?.focus();
1289
+ }, 100);
1290
+ return () => clearTimeout(timer);
1291
+ }
1292
+ return void 0;
1293
+ }, [open]);
1294
+ const handleFormSubmit = useCallback((e) => {
1295
+ e.preventDefault();
1296
+ if (!input.trim() && attachedFiles.length === 0) return;
1297
+ if (status === "streaming") return;
1298
+ try {
1299
+ if (attachedFiles.length > 0) {
1300
+ sendMessage({
1301
+ text: input.trim(),
1302
+ files: attachedFiles
1303
+ });
1304
+ } else {
1305
+ sendMessage({
1306
+ text: input.trim()
1307
+ });
1308
+ }
1309
+ setInput("");
1310
+ setAttachedFiles([]);
1311
+ if (fileInputRef.current) {
1312
+ fileInputRef.current.value = "";
1313
+ }
1314
+ } catch (sendError) {
1315
+ console.error("Failed to send message:", sendError);
1316
+ }
1317
+ }, [input, attachedFiles, status, sendMessage]);
1318
+ const handleFileUpload = useCallback((e) => {
1319
+ const files = e.target.files;
1320
+ if (!files) return;
1321
+ const newFiles = [];
1322
+ Array.from(files).forEach((file, index) => {
1323
+ if (file.size > maxFileSize) {
1324
+ return;
1325
+ }
1326
+ const isAccepted = acceptedFileTypes.some((type) => {
1327
+ if (type.endsWith("/*")) {
1328
+ return file.type.startsWith(type.slice(0, -1));
1329
+ }
1330
+ return file.type === type;
1331
+ });
1332
+ if (!isAccepted) {
1333
+ return;
1334
+ }
1335
+ const fileUrl = URL.createObjectURL(file);
1336
+ newFiles.push({
1337
+ type: "file",
1338
+ filename: file.name,
1339
+ mediaType: file.type,
1340
+ url: fileUrl
1341
+ });
1342
+ });
1343
+ setAttachedFiles((prev) => [...prev, ...newFiles]);
1344
+ }, [maxFileSize, acceptedFileTypes]);
1345
+ const removeFile = useCallback((index) => {
1346
+ setAttachedFiles((prev) => {
1347
+ const newFiles = prev.slice();
1348
+ URL.revokeObjectURL(newFiles[index].url);
1349
+ newFiles.splice(index, 1);
1350
+ return newFiles;
1351
+ });
1352
+ }, []);
1353
+ const handleKeyPress = useCallback((e) => {
1354
+ if (e.key === "Enter" && !e.shiftKey) {
1355
+ e.preventDefault();
1356
+ handleFormSubmit(e);
1357
+ }
1358
+ }, [handleFormSubmit]);
1359
+ const isLoading = status === "streaming" || status === "submitted";
1360
+ const canSend = !isLoading && (input.trim() || attachedFiles.length > 0);
1361
+ return /* @__PURE__ */ jsxs5(
1362
+ Box2,
1363
+ {
1364
+ style: {
1365
+ height: "100%",
1366
+ width: "100%",
1367
+ display: "flex",
1368
+ flexDirection: "column",
1369
+ position: "relative",
1370
+ zIndex: "auto",
1371
+ minHeight: 0,
1372
+ overflow: "hidden",
1373
+ background: `
1374
+ radial-gradient(
1375
+ circle at 85% 85%,
1376
+ rgba(34, 139, 230, 0.18) 0%,
1377
+ rgba(34, 139, 230, 0.09) 25%,
1378
+ rgba(34, 139, 230, 0.03) 50%,
1379
+ rgba(255, 255, 255, 1) 75%
1380
+ )
1381
+ `
1382
+ },
1383
+ children: [
1384
+ showHeader && /* @__PURE__ */ jsx5(
1385
+ Paper2,
1386
+ {
1387
+ p: "lg",
1388
+ bg: "white",
1389
+ radius: 0,
1390
+ style: {
1391
+ position: "sticky",
1392
+ top: 0,
1393
+ zIndex: 100
1394
+ },
1395
+ children: /* @__PURE__ */ jsxs5(Group2, { justify: "space-between", align: "center", style: { width: "100%" }, children: [
1396
+ /* @__PURE__ */ jsxs5(Group2, { gap: "md", style: { flex: 1 }, children: [
1397
+ /* @__PURE__ */ jsx5(
1398
+ Box2,
1399
+ {
1400
+ style: {
1401
+ width: "40px",
1402
+ height: "40px",
1403
+ borderRadius: "8px",
1404
+ display: "flex",
1405
+ alignItems: "center",
1406
+ justifyContent: "center",
1407
+ boxShadow: "0 2px 8px rgba(25, 118, 210, 0.3)"
1408
+ },
1409
+ children: /* @__PURE__ */ jsx5(SparklesIcon, { size: 24, color: "#1976d2" })
1410
+ }
1411
+ ),
1412
+ /* @__PURE__ */ jsxs5("div", { children: [
1413
+ /* @__PURE__ */ jsx5(Title, { order: 4, c: "var(--mantine-color-gray-9)", mb: 2, children: title }),
1414
+ /* @__PURE__ */ jsxs5(Group2, { gap: "xs", align: "center", children: [
1415
+ /* @__PURE__ */ jsx5(
1416
+ Badge2,
1417
+ {
1418
+ size: "xs",
1419
+ color: error ? "red" : "green",
1420
+ variant: "light",
1421
+ leftSection: /* @__PURE__ */ jsx5(Box2, { w: 6, h: 6, bg: error ? "red" : "green", style: { borderRadius: "50%" } }),
1422
+ children: error ? "Offline" : "Online"
1423
+ }
1424
+ ),
1425
+ description && /* @__PURE__ */ jsx5(Text2, { size: "xs", c: "var(--mantine-color-gray-6)", children: description })
1426
+ ] })
1427
+ ] })
1428
+ ] }),
1429
+ /* @__PURE__ */ jsx5(
1430
+ ActionIcon,
1431
+ {
1432
+ variant: "subtle",
1433
+ color: "gray",
1434
+ size: "lg",
1435
+ onClick: () => onOpenChange?.(false),
1436
+ "aria-label": "\u5173\u95ED\u5BF9\u8BDD\u6846",
1437
+ style: { flexShrink: 0 },
1438
+ children: /* @__PURE__ */ jsx5(X, { size: 18 })
1439
+ }
1440
+ )
1441
+ ] })
1442
+ }
1443
+ ),
1444
+ /* @__PURE__ */ jsx5(ScrollArea, { style: { flex: 1 }, p: "xl", children: /* @__PURE__ */ jsxs5(Stack2, { gap: "md", maw: "none", w: "100%", children: [
1445
+ /* @__PURE__ */ jsx5(AnimatePresence, { mode: "popLayout", children: messages.map((message, index) => /* @__PURE__ */ jsx5(
1446
+ motion.div,
1447
+ {
1448
+ initial: { opacity: 0, y: 20 },
1449
+ animate: { opacity: 1, y: 0 },
1450
+ exit: { opacity: 0, y: -20 },
1451
+ transition: { duration: 0.3, delay: index * 0.1 },
1452
+ children: messageRenderer ? React.createElement(messageRenderer, { message }) : /* @__PURE__ */ jsx5(
1453
+ MessageBubble,
1454
+ {
1455
+ message,
1456
+ showAvatar: true,
1457
+ showTimestamp: true,
1458
+ enableReasoning,
1459
+ enableGenerativeUI,
1460
+ showReasoningByDefault
1461
+ }
1462
+ )
1463
+ },
1464
+ message.id
1465
+ )) }),
1466
+ isLoading && /* @__PURE__ */ jsx5(
1467
+ motion.div,
1468
+ {
1469
+ initial: { opacity: 0 },
1470
+ animate: { opacity: 1 },
1471
+ children: /* @__PURE__ */ jsxs5(Group2, { gap: "sm", justify: "space-between", children: [
1472
+ /* @__PURE__ */ jsxs5(Group2, { gap: "sm", children: [
1473
+ /* @__PURE__ */ jsxs5(Group2, { gap: "xs", children: [
1474
+ /* @__PURE__ */ jsx5(Box2, { w: 8, h: 8, bg: "gray.4", style: { borderRadius: "50%", animation: "bounce 1s infinite" } }),
1475
+ /* @__PURE__ */ jsx5(Box2, { w: 8, h: 8, bg: "gray.4", style: { borderRadius: "50%", animation: "bounce 1s infinite 0.1s" } }),
1476
+ /* @__PURE__ */ jsx5(Box2, { w: 8, h: 8, bg: "gray.4", style: { borderRadius: "50%", animation: "bounce 1s infinite 0.2s" } })
1477
+ ] }),
1478
+ /* @__PURE__ */ jsx5(Text2, { size: "sm", ...getThemedTextProps("muted"), children: "AI is thinking..." })
1479
+ ] }),
1480
+ /* @__PURE__ */ jsx5(
1481
+ ActionIcon,
1482
+ {
1483
+ variant: "subtle",
1484
+ color: "red",
1485
+ onClick: stop,
1486
+ size: "sm",
1487
+ children: /* @__PURE__ */ jsx5(Square, { size: 16 })
1488
+ }
1489
+ )
1490
+ ] })
1491
+ }
1492
+ ),
1493
+ /* @__PURE__ */ jsx5("div", { ref: messagesEndRef })
1494
+ ] }) }),
1495
+ error && /* @__PURE__ */ jsx5(
1496
+ motion.div,
1497
+ {
1498
+ initial: { opacity: 0, height: 0 },
1499
+ animate: { opacity: 1, height: "auto" },
1500
+ style: { margin: "1rem" },
1501
+ children: /* @__PURE__ */ jsx5(
1502
+ Paper2,
1503
+ {
1504
+ p: "md",
1505
+ style: {
1506
+ backgroundColor: componentStyles.status.error.background,
1507
+ borderLeft: `4px solid ${componentStyles.status.error.border}`
1508
+ },
1509
+ children: /* @__PURE__ */ jsxs5(Group2, { align: "flex-start", gap: "sm", children: [
1510
+ /* @__PURE__ */ jsx5(AlertCircle, { size: 20, color: componentStyles.status.error.text }),
1511
+ /* @__PURE__ */ jsxs5(Box2, { style: { flex: 1 }, children: [
1512
+ /* @__PURE__ */ jsx5(Text2, { size: "sm", fw: 500, c: componentStyles.status.error.text, children: "Connection Error" }),
1513
+ /* @__PURE__ */ jsx5(Text2, { size: "sm", c: componentStyles.status.error.text, mt: "xs", children: error.message }),
1514
+ /* @__PURE__ */ jsxs5(Group2, { gap: "sm", mt: "md", children: [
1515
+ /* @__PURE__ */ jsx5(
1516
+ Button,
1517
+ {
1518
+ size: "xs",
1519
+ variant: "light",
1520
+ color: "red",
1521
+ onClick: () => clearError(),
1522
+ children: "Dismiss"
1523
+ }
1524
+ ),
1525
+ /* @__PURE__ */ jsx5(
1526
+ Button,
1527
+ {
1528
+ size: "xs",
1529
+ variant: "light",
1530
+ color: "blue",
1531
+ onClick: () => resumeStream(),
1532
+ children: "Retry Connection"
1533
+ }
1534
+ )
1535
+ ] })
1536
+ ] })
1537
+ ] })
1538
+ }
1539
+ )
1540
+ }
1541
+ ),
1542
+ attachedFiles.length > 0 && /* @__PURE__ */ jsxs5(
1543
+ Paper2,
1544
+ {
1545
+ p: "lg",
1546
+ shadow: "xs",
1547
+ style: {
1548
+ borderTop: "1px solid var(--mantine-color-gray-2)",
1549
+ backgroundColor: "var(--mantine-color-gray-0)"
1550
+ },
1551
+ children: [
1552
+ /* @__PURE__ */ jsx5(Text2, { size: "sm", fw: 500, c: "var(--mantine-color-gray-7)", mb: "md", children: "\u{1F4CE} \u9644\u4EF6\u9884\u89C8" }),
1553
+ /* @__PURE__ */ jsx5(Group2, { gap: "md", wrap: "wrap", children: attachedFiles.map((file, index) => /* @__PURE__ */ jsx5(
1554
+ Paper2,
1555
+ {
1556
+ p: "sm",
1557
+ shadow: "xs",
1558
+ withBorder: true,
1559
+ style: {
1560
+ maxWidth: "280px",
1561
+ backgroundColor: "white",
1562
+ position: "relative"
1563
+ },
1564
+ children: /* @__PURE__ */ jsxs5(Group2, { gap: "sm", align: "center", children: [
1565
+ /* @__PURE__ */ jsx5(
1566
+ Box2,
1567
+ {
1568
+ w: 32,
1569
+ h: 32,
1570
+ bg: "var(--mantine-color-blue-light)",
1571
+ style: {
1572
+ borderRadius: "6px",
1573
+ display: "flex",
1574
+ alignItems: "center",
1575
+ justifyContent: "center"
1576
+ },
1577
+ children: /* @__PURE__ */ jsx5(Paperclip, { size: 16, color: "var(--mantine-color-blue-6)" })
1578
+ }
1579
+ ),
1580
+ /* @__PURE__ */ jsxs5(Box2, { style: { flex: 1, minWidth: 0 }, children: [
1581
+ /* @__PURE__ */ jsx5(Text2, { size: "sm", fw: 500, truncate: true, c: "var(--mantine-color-gray-8)", children: file.filename }),
1582
+ /* @__PURE__ */ jsx5(Text2, { size: "xs", c: "var(--mantine-color-gray-6)", children: file.mediaType })
1583
+ ] }),
1584
+ /* @__PURE__ */ jsx5(
1585
+ ActionIcon,
1586
+ {
1587
+ variant: "subtle",
1588
+ color: "red",
1589
+ size: "sm",
1590
+ onClick: () => removeFile(index),
1591
+ style: { flexShrink: 0 },
1592
+ children: /* @__PURE__ */ jsx5(X, { size: 14 })
1593
+ }
1594
+ )
1595
+ ] })
1596
+ },
1597
+ `${file.filename}-${index}`
1598
+ )) })
1599
+ ]
1600
+ }
1601
+ ),
1602
+ /* @__PURE__ */ jsx5(
1603
+ Paper2,
1604
+ {
1605
+ p: "lg",
1606
+ shadow: "md",
1607
+ style: {
1608
+ borderTop: "1px solid var(--mantine-color-gray-2)",
1609
+ backgroundColor: "white",
1610
+ position: "sticky",
1611
+ bottom: 0,
1612
+ zIndex: 50
1613
+ },
1614
+ children: /* @__PURE__ */ jsx5("form", { onSubmit: handleFormSubmit, children: /* @__PURE__ */ jsxs5(Stack2, { gap: "sm", children: [
1615
+ /* @__PURE__ */ jsxs5(Group2, { align: "center", gap: "md", children: [
1616
+ allowFileUpload && /* @__PURE__ */ jsxs5(Box2, { children: [
1617
+ /* @__PURE__ */ jsx5(
1618
+ "input",
1619
+ {
1620
+ ref: fileInputRef,
1621
+ type: "file",
1622
+ multiple: true,
1623
+ accept: acceptedFileTypes.join(","),
1624
+ onChange: handleFileUpload,
1625
+ style: { display: "none" }
1626
+ }
1627
+ ),
1628
+ /* @__PURE__ */ jsx5(
1629
+ ActionIcon,
1630
+ {
1631
+ variant: "light",
1632
+ color: "gray",
1633
+ size: "lg",
1634
+ onClick: () => fileInputRef.current?.click(),
1635
+ disabled: isLoading,
1636
+ style: {
1637
+ border: "2px solid var(--mantine-color-gray-3)",
1638
+ backgroundColor: "var(--mantine-color-gray-0)",
1639
+ transition: "all 0.2s ease"
1640
+ },
1641
+ children: /* @__PURE__ */ jsx5(Paperclip, { size: 20 })
1642
+ }
1643
+ )
1644
+ ] }),
1645
+ /* @__PURE__ */ jsx5(Box2, { style: { flex: 1 }, children: /* @__PURE__ */ jsx5(
1646
+ Textarea,
1647
+ {
1648
+ ref: inputRef,
1649
+ value: input,
1650
+ onChange: (e) => setInput(e.target.value),
1651
+ onKeyDown: handleKeyPress,
1652
+ placeholder,
1653
+ disabled: isLoading,
1654
+ minRows: 1,
1655
+ maxRows: 4,
1656
+ autosize: true,
1657
+ variant: "filled",
1658
+ styles: {
1659
+ input: {
1660
+ backgroundColor: "var(--mantine-color-gray-0)",
1661
+ border: "2px solid var(--mantine-color-gray-2)",
1662
+ borderRadius: "12px",
1663
+ padding: "12px 16px",
1664
+ fontSize: "14px",
1665
+ lineHeight: "1.4",
1666
+ transition: "all 0.2s ease",
1667
+ "&:focus": {
1668
+ backgroundColor: "white",
1669
+ borderColor: "var(--mantine-color-blue-4)",
1670
+ boxShadow: "0 0 0 3px var(--mantine-color-blue-1)"
1671
+ },
1672
+ "&::placeholder": {
1673
+ color: "var(--mantine-color-gray-5)"
1674
+ }
1675
+ }
1676
+ }
1677
+ }
1678
+ ) }),
1679
+ /* @__PURE__ */ jsx5(
1680
+ ActionIcon,
1681
+ {
1682
+ type: "submit",
1683
+ disabled: !canSend,
1684
+ size: "lg",
1685
+ variant: "filled",
1686
+ style: {
1687
+ background: canSend ? "linear-gradient(45deg, var(--mantine-color-blue-6), var(--mantine-color-blue-5))" : "var(--mantine-color-gray-4)",
1688
+ color: "white",
1689
+ border: "none",
1690
+ borderRadius: "12px",
1691
+ boxShadow: canSend ? "0 4px 12px var(--mantine-color-blue-2)" : "none",
1692
+ transform: canSend ? "scale(1)" : "scale(0.95)",
1693
+ transition: "all 0.2s ease",
1694
+ cursor: canSend ? "pointer" : "not-allowed",
1695
+ "&:hover": canSend ? {
1696
+ transform: "scale(1.05)",
1697
+ boxShadow: "0 6px 16px var(--mantine-color-blue-3)"
1698
+ } : {}
1699
+ },
1700
+ children: /* @__PURE__ */ jsx5(Send, { size: 20 })
1701
+ }
1702
+ )
1703
+ ] }),
1704
+ input.length > 0 && /* @__PURE__ */ jsxs5(Group2, { justify: "space-between", align: "center", children: [
1705
+ /* @__PURE__ */ jsx5(Text2, { size: "xs", c: "var(--mantine-color-gray-6)", children: isLoading ? "AI\u6B63\u5728\u56DE\u590D..." : "Enter\u53D1\u9001\uFF0CShift+Enter\u6362\u884C" }),
1706
+ /* @__PURE__ */ jsxs5(Text2, { size: "xs", c: "var(--mantine-color-gray-5)", children: [
1707
+ input.length,
1708
+ "/2000"
1709
+ ] })
1710
+ ] })
1711
+ ] }) })
1712
+ }
1713
+ )
1714
+ ]
1715
+ }
1716
+ );
1717
+ }
1718
+ var init_ChatDialog = __esm({
1719
+ "src/components/ChatDialog/ChatDialog.tsx"() {
1720
+ "use strict";
1721
+ init_useChat();
1722
+ init_MessageBubble();
1723
+ init_theme();
1724
+ }
1725
+ });
1726
+
1727
+ // src/components/FileViewer/FileViewer.tsx
1728
+ import { useMemo, useState as useState2 } from "react";
1729
+ import { motion as motion2, AnimatePresence as AnimatePresence2 } from "framer-motion";
1730
+ import { Box as Box3, Text as Text3, Modal, Title as Title2, Group as Group3, Stack as Stack3, Paper as Paper3, Badge as Badge3, Image, Button as Button2, ActionIcon as ActionIcon2 } from "@mantine/core";
1731
+ import {
1732
+ X as X2,
1733
+ Eye,
1734
+ File,
1735
+ Code,
1736
+ Music,
1737
+ Video,
1738
+ Archive,
1739
+ FileText,
1740
+ Download,
1741
+ AlertTriangle
1742
+ } from "lucide-react";
1743
+ import { Fragment, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1744
+ function FileViewer({
1745
+ file,
1746
+ showDownload = false,
1747
+ showRemove = false,
1748
+ onRemove,
1749
+ className
1750
+ }) {
1751
+ const [isPreviewOpen, setIsPreviewOpen] = useState2(false);
1752
+ const [imageLoadError, setImageLoadError] = useState2(false);
1753
+ const [isLoading, setIsLoading] = useState2(false);
1754
+ const fileInfo = useMemo(() => {
1755
+ const extension = file.filename?.split(".").pop()?.toLowerCase() || "";
1756
+ const mediaType = file.mediaType || "";
1757
+ let category = "document";
1758
+ let icon = /* @__PURE__ */ jsx6(File, { className: "w-5 h-5" });
1759
+ let color = "text-gray-600 dark:text-gray-400";
1760
+ let bgColor = "bg-gray-100 dark:bg-gray-800";
1761
+ if (mediaType.startsWith("image/")) {
1762
+ category = "image";
1763
+ icon = /* @__PURE__ */ jsx6(Image, { className: "w-5 h-5" });
1764
+ color = "text-blue-600 dark:text-blue-400";
1765
+ bgColor = "bg-blue-50 dark:bg-blue-900/20";
1766
+ } else if (mediaType.startsWith("text/") || ["txt", "md", "json", "xml", "csv"].includes(extension)) {
1767
+ category = "text";
1768
+ icon = /* @__PURE__ */ jsx6(FileText, { className: "w-5 h-5" });
1769
+ color = "text-green-600 dark:text-green-400";
1770
+ bgColor = "bg-green-50 dark:bg-green-900/20";
1771
+ } else if (["js", "ts", "jsx", "tsx", "py", "java", "cpp", "c", "html", "css", "php"].includes(extension)) {
1772
+ category = "code";
1773
+ icon = /* @__PURE__ */ jsx6(Code, { className: "w-5 h-5" });
1774
+ color = "text-purple-600 dark:text-purple-400";
1775
+ bgColor = "bg-purple-50 dark:bg-purple-900/20";
1776
+ } else if (mediaType.startsWith("audio/")) {
1777
+ category = "audio";
1778
+ icon = /* @__PURE__ */ jsx6(Music, { className: "w-5 h-5" });
1779
+ color = "text-pink-600 dark:text-pink-400";
1780
+ bgColor = "bg-pink-50 dark:bg-pink-900/20";
1781
+ } else if (mediaType.startsWith("video/")) {
1782
+ category = "video";
1783
+ icon = /* @__PURE__ */ jsx6(Video, { className: "w-5 h-5" });
1784
+ color = "text-red-600 dark:text-red-400";
1785
+ bgColor = "bg-red-50 dark:bg-red-900/20";
1786
+ } else if (["zip", "rar", "7z", "tar", "gz"].includes(extension)) {
1787
+ category = "archive";
1788
+ icon = /* @__PURE__ */ jsx6(Archive, { className: "w-5 h-5" });
1789
+ color = "text-orange-600 dark:text-orange-400";
1790
+ bgColor = "bg-orange-50 dark:bg-orange-900/20";
1791
+ }
1792
+ return {
1793
+ extension,
1794
+ category,
1795
+ icon,
1796
+ color,
1797
+ bgColor,
1798
+ canPreview: ["image", "text"].includes(category),
1799
+ size: formatFileSize2(getFileSizeFromUrl(file.url))
1800
+ };
1801
+ }, [file]);
1802
+ function formatFileSize2(bytes) {
1803
+ if (bytes === 0) return "0 B";
1804
+ const k = 1024;
1805
+ const sizes = ["B", "KB", "MB", "GB"];
1806
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
1807
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + " " + sizes[i];
1808
+ }
1809
+ function getFileSizeFromUrl(url) {
1810
+ return 0;
1811
+ }
1812
+ const handleDownload = async () => {
1813
+ try {
1814
+ setIsLoading(true);
1815
+ const response = await fetch(file.url);
1816
+ if (!response.ok) throw new Error("Download failed");
1817
+ const blob = await response.blob();
1818
+ const downloadUrl = URL.createObjectURL(blob);
1819
+ const a = document.createElement("a");
1820
+ a.href = downloadUrl;
1821
+ a.download = file.filename || "download";
1822
+ document.body.appendChild(a);
1823
+ a.click();
1824
+ document.body.removeChild(a);
1825
+ URL.revokeObjectURL(downloadUrl);
1826
+ } catch {
1827
+ } finally {
1828
+ setIsLoading(false);
1829
+ }
1830
+ };
1831
+ const handleRemove = () => {
1832
+ if (onRemove) {
1833
+ onRemove(file);
1834
+ }
1835
+ };
1836
+ const renderPreviewContent = () => {
1837
+ if (fileInfo.category === "image") {
1838
+ return /* @__PURE__ */ jsx6(Box3, { style: { display: "flex", alignItems: "center", justifyContent: "center", maxHeight: "24rem" }, children: /* @__PURE__ */ jsx6(
1839
+ Image,
1840
+ {
1841
+ src: file.url,
1842
+ alt: file.filename,
1843
+ style: { maxWidth: "100%", maxHeight: "100%", objectFit: "contain" },
1844
+ radius: "md",
1845
+ onError: () => setImageLoadError(true)
1846
+ }
1847
+ ) });
1848
+ }
1849
+ if (fileInfo.category === "text") {
1850
+ return /* @__PURE__ */ jsx6(Box3, { style: { maxHeight: "24rem", overflow: "auto" }, children: /* @__PURE__ */ jsx6(
1851
+ "iframe",
1852
+ {
1853
+ src: file.url,
1854
+ style: {
1855
+ width: "100%",
1856
+ height: "20rem",
1857
+ border: `1px solid ${componentStyles.fileViewer.border}`,
1858
+ borderRadius: "0.5rem"
1859
+ },
1860
+ title: file.filename
1861
+ }
1862
+ ) });
1863
+ }
1864
+ return /* @__PURE__ */ jsxs6(Stack3, { align: "center", justify: "center", style: { padding: "2rem" }, children: [
1865
+ /* @__PURE__ */ jsx6(AlertTriangle, { size: 48, color: componentStyles.text.muted }),
1866
+ /* @__PURE__ */ jsx6(Text3, { ...getThemedTextProps("muted"), children: "Preview not available for this file type" }),
1867
+ /* @__PURE__ */ jsx6(Text3, { size: "sm", ...getThemedTextProps("muted"), children: "Click download to view the file" })
1868
+ ] });
1869
+ };
1870
+ return /* @__PURE__ */ jsxs6(Fragment, { children: [
1871
+ /* @__PURE__ */ jsx6(
1872
+ motion2.div,
1873
+ {
1874
+ initial: { opacity: 0, scale: 0.95 },
1875
+ animate: { opacity: 1, scale: 1 },
1876
+ children: /* @__PURE__ */ jsxs6(
1877
+ Paper3,
1878
+ {
1879
+ p: "md",
1880
+ style: {
1881
+ position: "relative",
1882
+ border: `1px solid ${componentStyles.fileViewer.border}`,
1883
+ borderRadius: "0.5rem",
1884
+ backgroundColor: componentStyles.fileViewer.background,
1885
+ boxShadow: "0 1px 2px 0 rgb(0 0 0 / 0.05)",
1886
+ transition: "box-shadow 0.2s"
1887
+ },
1888
+ children: [
1889
+ showRemove && /* @__PURE__ */ jsx6(
1890
+ ActionIcon2,
1891
+ {
1892
+ size: "sm",
1893
+ color: "red",
1894
+ variant: "filled",
1895
+ onClick: handleRemove,
1896
+ style: {
1897
+ position: "absolute",
1898
+ top: "0.25rem",
1899
+ right: "0.25rem",
1900
+ opacity: 0.7
1901
+ },
1902
+ title: "Remove file",
1903
+ children: /* @__PURE__ */ jsx6(X2, { size: 12 })
1904
+ }
1905
+ ),
1906
+ /* @__PURE__ */ jsxs6(Group3, { align: "flex-start", gap: "sm", children: [
1907
+ /* @__PURE__ */ jsx6(Box3, { style: { flexShrink: 0 }, children: fileInfo.category === "image" && !imageLoadError ? /* @__PURE__ */ jsx6(
1908
+ Box3,
1909
+ {
1910
+ w: 48,
1911
+ h: 48,
1912
+ style: {
1913
+ borderRadius: "0.25rem",
1914
+ overflow: "hidden",
1915
+ backgroundColor: componentStyles.codeBackground
1916
+ },
1917
+ children: /* @__PURE__ */ jsx6(
1918
+ Image,
1919
+ {
1920
+ src: file.url,
1921
+ alt: file.filename,
1922
+ style: { width: "100%", height: "100%", objectFit: "cover" },
1923
+ onError: () => setImageLoadError(true)
1924
+ }
1925
+ )
1926
+ }
1927
+ ) : /* @__PURE__ */ jsx6(
1928
+ Box3,
1929
+ {
1930
+ w: 48,
1931
+ h: 48,
1932
+ style: {
1933
+ display: "flex",
1934
+ alignItems: "center",
1935
+ justifyContent: "center"
1936
+ },
1937
+ children: fileInfo.icon
1938
+ }
1939
+ ) }),
1940
+ /* @__PURE__ */ jsxs6(Box3, { style: { flex: 1, minWidth: 0 }, children: [
1941
+ /* @__PURE__ */ jsx6(Text3, { size: "sm", fw: 500, ...getThemedTextProps("primary"), truncate: true, children: file.filename }),
1942
+ /* @__PURE__ */ jsxs6(Group3, { gap: "xs", mt: "xs", children: [
1943
+ /* @__PURE__ */ jsx6(Badge3, { size: "xs", variant: "light", color: "gray", children: fileInfo.extension || "Unknown" }),
1944
+ fileInfo.size !== "0 B" && /* @__PURE__ */ jsx6(Text3, { size: "xs", ...getThemedTextProps("muted"), children: fileInfo.size })
1945
+ ] }),
1946
+ file.mediaType && /* @__PURE__ */ jsx6(Text3, { size: "xs", ...getThemedTextProps("muted"), mt: "xs", children: file.mediaType })
1947
+ ] })
1948
+ ] }),
1949
+ /* @__PURE__ */ jsxs6(Group3, { justify: "flex-end", gap: "xs", mt: "sm", style: { opacity: 0.7 }, children: [
1950
+ fileInfo.canPreview && /* @__PURE__ */ jsx6(
1951
+ Button2,
1952
+ {
1953
+ variant: "subtle",
1954
+ size: "xs",
1955
+ onClick: () => setIsPreviewOpen(true),
1956
+ leftSection: /* @__PURE__ */ jsx6(Eye, { size: 12 }),
1957
+ children: "Preview"
1958
+ }
1959
+ ),
1960
+ showDownload && /* @__PURE__ */ jsx6(
1961
+ Button2,
1962
+ {
1963
+ variant: "subtle",
1964
+ size: "xs",
1965
+ onClick: handleDownload,
1966
+ disabled: isLoading,
1967
+ leftSection: /* @__PURE__ */ jsx6(Download, { size: 12 }),
1968
+ children: isLoading ? "Downloading..." : "Download"
1969
+ }
1970
+ )
1971
+ ] })
1972
+ ]
1973
+ }
1974
+ )
1975
+ }
1976
+ ),
1977
+ /* @__PURE__ */ jsx6(AnimatePresence2, { children: isPreviewOpen && /* @__PURE__ */ jsx6(
1978
+ Modal,
1979
+ {
1980
+ opened: isPreviewOpen,
1981
+ onClose: () => setIsPreviewOpen(false),
1982
+ size: "xl",
1983
+ styles: {
1984
+ content: { maxHeight: "90vh" },
1985
+ body: { overflow: "auto" }
1986
+ },
1987
+ children: /* @__PURE__ */ jsxs6(
1988
+ motion2.div,
1989
+ {
1990
+ initial: { opacity: 0, scale: 0.95 },
1991
+ animate: { opacity: 1, scale: 1 },
1992
+ exit: { opacity: 0, scale: 0.95 },
1993
+ transition: { duration: 0.2 },
1994
+ children: [
1995
+ /* @__PURE__ */ jsxs6(Group3, { gap: "sm", mb: "md", children: [
1996
+ /* @__PURE__ */ jsx6(Box3, { children: fileInfo.icon }),
1997
+ /* @__PURE__ */ jsx6(Title2, { order: 3, ...getThemedTextProps("heading"), children: file.filename })
1998
+ ] }),
1999
+ /* @__PURE__ */ jsx6(Box3, { mt: "md", children: renderPreviewContent() }),
2000
+ /* @__PURE__ */ jsx6(Group3, { justify: "flex-end", gap: "sm", mt: "md", pt: "md", style: { borderTop: `1px solid ${componentStyles.fileViewer.border}` }, children: /* @__PURE__ */ jsx6(
2001
+ Button2,
2002
+ {
2003
+ onClick: handleDownload,
2004
+ disabled: isLoading,
2005
+ leftSection: /* @__PURE__ */ jsx6(Download, { size: 16 }),
2006
+ children: isLoading ? "Downloading..." : "Download"
2007
+ }
2008
+ ) })
2009
+ ]
2010
+ }
2011
+ )
2012
+ }
2013
+ ) })
2014
+ ] });
2015
+ }
2016
+ var init_FileViewer = __esm({
2017
+ "src/components/FileViewer/FileViewer.tsx"() {
2018
+ "use strict";
2019
+ init_theme();
2020
+ }
2021
+ });
2022
+
2023
+ // src/components/index.ts
2024
+ var components_exports = {};
2025
+ __export(components_exports, {
2026
+ ChatDialog: () => ChatDialog,
2027
+ FileViewer: () => FileViewer,
2028
+ MessageBubble: () => MessageBubble
2029
+ });
2030
+ var init_components = __esm({
2031
+ "src/components/index.ts"() {
2032
+ "use strict";
2033
+ init_ChatDialog();
2034
+ init_FileViewer();
2035
+ init_MessageBubble();
2036
+ }
2037
+ });
2038
+
2039
+ // src/ui-index.ts
2040
+ init_hooks();
2041
+ init_components();
2042
+ init_PrebuiltComponents();
2043
+ init_DynamicUI();
2044
+ import {
2045
+ readUIMessageStream,
2046
+ DefaultChatTransport,
2047
+ createUIMessageStream,
2048
+ convertToModelMessages,
2049
+ TextStreamChatTransport,
2050
+ createUIMessageStreamResponse,
2051
+ lastAssistantMessageIsCompleteWithToolCalls
2052
+ } from "ai";
2053
+
2054
+ // src/utils/index.ts
2055
+ function extractMessageText(message) {
2056
+ return message.parts.filter((part) => part.type === "text").map((part) => part.text).join("\n");
2057
+ }
2058
+ function hasToolCalls(message) {
2059
+ return message.parts.some(
2060
+ (part) => part.type.startsWith("tool-") || part.type === "dynamic-tool"
2061
+ );
2062
+ }
2063
+ function getToolCalls(message) {
2064
+ return message.parts.filter((part) => part.type.startsWith("tool-") || part.type === "dynamic-tool").map((part) => ({
2065
+ toolName: part.type === "dynamic-tool" ? part.toolName : part.type.replace("tool-", ""),
2066
+ state: part.state || "unknown",
2067
+ input: part.input,
2068
+ output: part.output
2069
+ }));
2070
+ }
2071
+ function hasFileAttachments(message) {
2072
+ return message.parts.some((part) => part.type === "file");
2073
+ }
2074
+ function getFileAttachments(message) {
2075
+ return message.parts.filter((part) => part.type === "file").map((part) => part);
2076
+ }
2077
+ function formatTimestamp(timestamp, options) {
2078
+ if (!timestamp) return "";
2079
+ const date = new Date(timestamp);
2080
+ const { format = "short", includeDate = false } = options || {};
2081
+ switch (format) {
2082
+ case "short":
2083
+ return date.toLocaleTimeString([], {
2084
+ hour: "2-digit",
2085
+ minute: "2-digit",
2086
+ ...includeDate && {
2087
+ month: "short",
2088
+ day: "numeric"
2089
+ }
2090
+ });
2091
+ case "long":
2092
+ return date.toLocaleString();
2093
+ case "relative":
2094
+ return formatRelativeTime(timestamp);
2095
+ default:
2096
+ return date.toLocaleTimeString();
2097
+ }
2098
+ }
2099
+ function formatRelativeTime(timestamp) {
2100
+ const now = Date.now();
2101
+ const diff = now - timestamp;
2102
+ const minute = 60 * 1e3;
2103
+ const hour = minute * 60;
2104
+ const day = hour * 24;
2105
+ const week = day * 7;
2106
+ const month = day * 30;
2107
+ const year = day * 365;
2108
+ if (diff < minute) {
2109
+ return "Just now";
2110
+ } else if (diff < hour) {
2111
+ const minutes = Math.floor(diff / minute);
2112
+ return `${minutes}m ago`;
2113
+ } else if (diff < day) {
2114
+ const hours = Math.floor(diff / hour);
2115
+ return `${hours}h ago`;
2116
+ } else if (diff < week) {
2117
+ const days = Math.floor(diff / day);
2118
+ return `${days}d ago`;
2119
+ } else if (diff < month) {
2120
+ const weeks = Math.floor(diff / week);
2121
+ return `${weeks}w ago`;
2122
+ } else if (diff < year) {
2123
+ const months = Math.floor(diff / month);
2124
+ return `${months}mo ago`;
2125
+ } else {
2126
+ const years = Math.floor(diff / year);
2127
+ return `${years}y ago`;
2128
+ }
2129
+ }
2130
+ function formatFileSize(bytes) {
2131
+ if (bytes === 0) return "0 B";
2132
+ const k = 1024;
2133
+ const sizes = ["B", "KB", "MB", "GB", "TB"];
2134
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
2135
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + " " + sizes[i];
2136
+ }
2137
+ function getFileExtension(filename) {
2138
+ return filename.split(".").pop()?.toLowerCase() || "";
2139
+ }
2140
+ function isFileTypeAccepted(file, acceptedTypes) {
2141
+ return acceptedTypes.some((type) => {
2142
+ if (type.endsWith("/*")) {
2143
+ return file.type.startsWith(type.slice(0, -1));
2144
+ }
2145
+ return file.type === type;
2146
+ });
2147
+ }
2148
+ function createFileUrl(file) {
2149
+ return URL.createObjectURL(file);
2150
+ }
2151
+ function revokeFileUrl(url) {
2152
+ URL.revokeObjectURL(url);
2153
+ }
2154
+ function truncateText(text, maxLength) {
2155
+ if (text.length <= maxLength) return text;
2156
+ return text.slice(0, maxLength - 3) + "...";
2157
+ }
2158
+ function highlightSearchTerms(text, searchTerms) {
2159
+ if (!searchTerms.length) return text;
2160
+ let highlightedText = text;
2161
+ searchTerms.forEach((term) => {
2162
+ const regex = new RegExp(`(${term})`, "gi");
2163
+ highlightedText = highlightedText.replace(regex, "<mark>$1</mark>");
2164
+ });
2165
+ return highlightedText;
2166
+ }
2167
+ function camelToSpaced(str) {
2168
+ return str.replace(/([A-Z])/g, " $1").trim();
2169
+ }
2170
+ function isValidUrl(string) {
2171
+ try {
2172
+ new URL(string);
2173
+ return true;
2174
+ } catch {
2175
+ return false;
2176
+ }
2177
+ }
2178
+ function isValidJson(string) {
2179
+ try {
2180
+ JSON.parse(string);
2181
+ return true;
2182
+ } catch {
2183
+ return false;
2184
+ }
2185
+ }
2186
+ function safeJsonParse(string, fallback) {
2187
+ try {
2188
+ return JSON.parse(string);
2189
+ } catch {
2190
+ return fallback;
2191
+ }
2192
+ }
2193
+ function cn(...classes) {
2194
+ return classes.filter(Boolean).join(" ");
2195
+ }
2196
+ async function safeAsync(fn, fallback) {
2197
+ try {
2198
+ const data = await fn();
2199
+ return { data };
2200
+ } catch (error) {
2201
+ return {
2202
+ error: error instanceof Error ? error : new Error(String(error)),
2203
+ ...fallback !== void 0 && { data: fallback }
2204
+ };
2205
+ }
2206
+ }
2207
+ function createErrorMessage(error) {
2208
+ if (error instanceof Error) {
2209
+ return error.message;
2210
+ }
2211
+ if (typeof error === "string") {
2212
+ return error;
2213
+ }
2214
+ return "An unknown error occurred";
2215
+ }
2216
+ function debounce(func, delay) {
2217
+ let timeoutId;
2218
+ return function debouncedFunction(...args) {
2219
+ clearTimeout(timeoutId);
2220
+ timeoutId = setTimeout(() => func.apply(this, args), delay);
2221
+ };
2222
+ }
2223
+ function throttle(func, delay) {
2224
+ let inThrottle;
2225
+ return function throttledFunction(...args) {
2226
+ if (!inThrottle) {
2227
+ func.apply(this, args);
2228
+ inThrottle = true;
2229
+ setTimeout(() => inThrottle = false, delay);
2230
+ }
2231
+ };
2232
+ }
2233
+ var storage = {
2234
+ get(key, fallback) {
2235
+ if (typeof window === "undefined") return fallback || null;
2236
+ try {
2237
+ const item = localStorage.getItem(key);
2238
+ return item ? JSON.parse(item) : fallback || null;
2239
+ } catch {
2240
+ return fallback || null;
2241
+ }
2242
+ },
2243
+ set(key, value) {
2244
+ if (typeof window === "undefined") return false;
2245
+ try {
2246
+ localStorage.setItem(key, JSON.stringify(value));
2247
+ return true;
2248
+ } catch {
2249
+ return false;
2250
+ }
2251
+ },
2252
+ remove(key) {
2253
+ if (typeof window === "undefined") return false;
2254
+ try {
2255
+ localStorage.removeItem(key);
2256
+ return true;
2257
+ } catch {
2258
+ return false;
2259
+ }
2260
+ },
2261
+ clear() {
2262
+ if (typeof window === "undefined") return false;
2263
+ try {
2264
+ localStorage.clear();
2265
+ return true;
2266
+ } catch {
2267
+ return false;
2268
+ }
2269
+ }
2270
+ };
2271
+
2272
+ // src/ui-index.ts
2273
+ var version = "1.0.0";
2274
+ var packageName = "entity-engine-aiui";
2275
+ var EntityEngineAIUI = {
2276
+ // Hooks - imported dynamically to avoid server-side issues
2277
+ get useChat() {
2278
+ return (init_hooks(), __toCommonJS(hooks_exports)).useChat;
2279
+ },
2280
+ get useCompletion() {
2281
+ return (init_hooks(), __toCommonJS(hooks_exports)).useCompletion;
2282
+ },
2283
+ get useObject() {
2284
+ return (init_hooks(), __toCommonJS(hooks_exports)).useObject;
2285
+ },
2286
+ // Components - imported dynamically to avoid server-side React imports
2287
+ get ChatDialog() {
2288
+ return (init_components(), __toCommonJS(components_exports)).ChatDialog;
2289
+ },
2290
+ get MessageBubble() {
2291
+ return (init_components(), __toCommonJS(components_exports)).MessageBubble;
2292
+ },
2293
+ get FileViewer() {
2294
+ return (init_components(), __toCommonJS(components_exports)).FileViewer;
2295
+ },
2296
+ // Version info
2297
+ version,
2298
+ packageName
2299
+ };
2300
+ var ui_index_default = EntityEngineAIUI;
2301
+ export {
2302
+ ChatDialog,
2303
+ CodeExecutionComponent,
2304
+ DefaultChatTransport,
2305
+ DynamicEntityDashboardComponent,
2306
+ DynamicEntityFormComponent,
2307
+ DynamicEntityGridComponent,
2308
+ DynamicEntityKanbanComponent,
2309
+ DynamicEntityMastailComponent,
2310
+ DynamicToolRenderer,
2311
+ ENTITY_DYNAMIC_COMPONENTS,
2312
+ FileViewer,
2313
+ LocationComponent,
2314
+ MessageBubble,
2315
+ TextStreamChatTransport,
2316
+ WeatherComponent,
2317
+ camelToSpaced,
2318
+ cn,
2319
+ convertToModelMessages,
2320
+ createErrorMessage,
2321
+ createFileUrl,
2322
+ createUIMessageStream,
2323
+ createUIMessageStreamResponse,
2324
+ debounce,
2325
+ ui_index_default as default,
2326
+ extractMessageText,
2327
+ formatFileSize,
2328
+ formatRelativeTime,
2329
+ formatTimestamp,
2330
+ getFileAttachments,
2331
+ getFileExtension,
2332
+ getToolCalls,
2333
+ hasFileAttachments,
2334
+ hasToolCalls,
2335
+ highlightSearchTerms,
2336
+ isFileTypeAccepted,
2337
+ isValidJson,
2338
+ isValidUrl,
2339
+ lastAssistantMessageIsCompleteWithToolCalls,
2340
+ packageName,
2341
+ readUIMessageStream,
2342
+ revokeFileUrl,
2343
+ safeAsync,
2344
+ safeJsonParse,
2345
+ storage,
2346
+ throttle,
2347
+ truncateText,
2348
+ useChat,
2349
+ useCompletion,
2350
+ useObject,
2351
+ version
2352
+ };
2353
+ //# sourceMappingURL=ui-index.mjs.map