@alpaca-editor/core 1.0.4027 → 1.0.4031

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 (220) hide show
  1. package/dist/components/ActionButton.js +2 -2
  2. package/dist/components/ActionButton.js.map +1 -1
  3. package/dist/components/SimpleLanguageSelector.js +3 -1
  4. package/dist/components/SimpleLanguageSelector.js.map +1 -1
  5. package/dist/components/ui/button.d.ts +1 -1
  6. package/dist/config/config.js +1 -1
  7. package/dist/config/config.js.map +1 -1
  8. package/dist/config/types.d.ts +1 -1
  9. package/dist/editor/ContextMenu.js +0 -1
  10. package/dist/editor/ContextMenu.js.map +1 -1
  11. package/dist/editor/Editor.js +9 -3
  12. package/dist/editor/Editor.js.map +1 -1
  13. package/dist/editor/FieldListField.js +16 -24
  14. package/dist/editor/FieldListField.js.map +1 -1
  15. package/dist/editor/ImageEditButton.js +1 -1
  16. package/dist/editor/ImageEditButton.js.map +1 -1
  17. package/dist/editor/ImageEditor.js +1 -1
  18. package/dist/editor/ImageEditor.js.map +1 -1
  19. package/dist/editor/MainLayout.js +2 -2
  20. package/dist/editor/MainLayout.js.map +1 -1
  21. package/dist/editor/Terminal.js +1 -1
  22. package/dist/editor/Terminal.js.map +1 -1
  23. package/dist/editor/Titlebar.js +0 -1
  24. package/dist/editor/Titlebar.js.map +1 -1
  25. package/dist/editor/ai/AgentCostDisplay.d.ts +26 -0
  26. package/dist/editor/ai/AgentCostDisplay.js +65 -0
  27. package/dist/editor/ai/AgentCostDisplay.js.map +1 -0
  28. package/dist/editor/ai/Agents.js +59 -15
  29. package/dist/editor/ai/Agents.js.map +1 -1
  30. package/dist/editor/ai/AiPromptPopover.d.ts +7 -0
  31. package/dist/editor/ai/AiPromptPopover.js +111 -0
  32. package/dist/editor/ai/AiPromptPopover.js.map +1 -0
  33. package/dist/editor/ai/AiResponseMessage.d.ts +1 -0
  34. package/dist/editor/ai/AiResponseMessage.js +101 -23
  35. package/dist/editor/ai/AiResponseMessage.js.map +1 -1
  36. package/dist/editor/ai/AiTerminal.d.ts +15 -1
  37. package/dist/editor/ai/AiTerminal.js +379 -48
  38. package/dist/editor/ai/AiTerminal.js.map +1 -1
  39. package/dist/editor/ai/editorAiContext.d.ts +0 -1
  40. package/dist/editor/ai/editorAiContext.js +0 -2
  41. package/dist/editor/ai/editorAiContext.js.map +1 -1
  42. package/dist/editor/client/EditorClient.d.ts +3 -2
  43. package/dist/editor/client/EditorClient.js +326 -68
  44. package/dist/editor/client/EditorClient.js.map +1 -1
  45. package/dist/editor/client/editContext.d.ts +6 -4
  46. package/dist/editor/client/editContext.js.map +1 -1
  47. package/dist/editor/client/fieldModificationStore.d.ts +19 -0
  48. package/dist/editor/client/fieldModificationStore.js +125 -0
  49. package/dist/editor/client/fieldModificationStore.js.map +1 -0
  50. package/dist/editor/client/itemsRepository.d.ts +1 -1
  51. package/dist/editor/client/itemsRepository.js +38 -28
  52. package/dist/editor/client/itemsRepository.js.map +1 -1
  53. package/dist/editor/client/operations.d.ts +1 -0
  54. package/dist/editor/client/operations.js +39 -31
  55. package/dist/editor/client/operations.js.map +1 -1
  56. package/dist/editor/commands/componentCommands.js +5 -3
  57. package/dist/editor/commands/componentCommands.js.map +1 -1
  58. package/dist/editor/commands/itemCommands.js.map +1 -1
  59. package/dist/editor/component-designer/aiContext.js +0 -2
  60. package/dist/editor/component-designer/aiContext.js.map +1 -1
  61. package/dist/editor/field-types/DropLinkEditor.js +1 -1
  62. package/dist/editor/field-types/DropLinkEditor.js.map +1 -1
  63. package/dist/editor/field-types/MultiLineText.js +5 -7
  64. package/dist/editor/field-types/MultiLineText.js.map +1 -1
  65. package/dist/editor/field-types/RichTextEditorComponent.js +5 -7
  66. package/dist/editor/field-types/RichTextEditorComponent.js.map +1 -1
  67. package/dist/editor/field-types/SingleLineText.js +5 -7
  68. package/dist/editor/field-types/SingleLineText.js.map +1 -1
  69. package/dist/editor/hooks/useEditorSettings.d.ts +17 -0
  70. package/dist/editor/hooks/useEditorSettings.js +61 -0
  71. package/dist/editor/hooks/useEditorSettings.js.map +1 -0
  72. package/dist/editor/menubar/ItemActionsMenu.js +2 -2
  73. package/dist/editor/menubar/ItemActionsMenu.js.map +1 -1
  74. package/dist/editor/menubar/PageSelector.js +1 -1
  75. package/dist/editor/menubar/PageSelector.js.map +1 -1
  76. package/dist/editor/menubar/toolbar-sections/EditControls.js +1 -1
  77. package/dist/editor/menubar/toolbar-sections/EditControls.js.map +1 -1
  78. package/dist/editor/menubar/toolbar-sections/InsertControls.js +1 -1
  79. package/dist/editor/menubar/toolbar-sections/InsertControls.js.map +1 -1
  80. package/dist/editor/menubar/toolbar-sections/UtilityControls.js +1 -1
  81. package/dist/editor/menubar/toolbar-sections/UtilityControls.js.map +1 -1
  82. package/dist/editor/menubar/toolbar-sections/ViewportControls.js +1 -1
  83. package/dist/editor/menubar/toolbar-sections/ViewportControls.js.map +1 -1
  84. package/dist/editor/page-editor-chrome/FieldEditedIndicators.js +4 -3
  85. package/dist/editor/page-editor-chrome/FieldEditedIndicators.js.map +1 -1
  86. package/dist/editor/page-editor-chrome/FrameMenu.js +9 -1
  87. package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
  88. package/dist/editor/page-editor-chrome/useInlineAICompletion.js +0 -1
  89. package/dist/editor/page-editor-chrome/useInlineAICompletion.js.map +1 -1
  90. package/dist/editor/page-viewer/EditorForm.js +1 -1
  91. package/dist/editor/page-viewer/EditorForm.js.map +1 -1
  92. package/dist/editor/page-viewer/PageViewer.js +9 -8
  93. package/dist/editor/page-viewer/PageViewer.js.map +1 -1
  94. package/dist/editor/page-viewer/PageViewerFrame.js +7 -1
  95. package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
  96. package/dist/editor/page-viewer/pageViewContext.js +40 -6
  97. package/dist/editor/page-viewer/pageViewContext.js.map +1 -1
  98. package/dist/editor/reviews/Comment.js +7 -6
  99. package/dist/editor/reviews/Comment.js.map +1 -1
  100. package/dist/editor/services/agentService.d.ts +84 -12
  101. package/dist/editor/services/agentService.js +256 -15
  102. package/dist/editor/services/agentService.js.map +1 -1
  103. package/dist/editor/services/aiService.d.ts +17 -3
  104. package/dist/editor/services/aiService.js +5 -3
  105. package/dist/editor/services/aiService.js.map +1 -1
  106. package/dist/editor/services/contextService.js +0 -1
  107. package/dist/editor/services/contextService.js.map +1 -1
  108. package/dist/editor/services/systemService.d.ts +2 -1
  109. package/dist/editor/services/systemService.js +3 -0
  110. package/dist/editor/services/systemService.js.map +1 -1
  111. package/dist/editor/sidebar/ComponentPalette.js +1 -1
  112. package/dist/editor/sidebar/ComponentPalette.js.map +1 -1
  113. package/dist/editor/sidebar/EditHistory.js +2 -2
  114. package/dist/editor/sidebar/EditHistory.js.map +1 -1
  115. package/dist/editor/sidebar/GraphQL.d.ts +1 -0
  116. package/dist/editor/sidebar/GraphQL.js +8 -2
  117. package/dist/editor/sidebar/GraphQL.js.map +1 -1
  118. package/dist/editor/sidebar/MainContentTree.js +1 -1
  119. package/dist/editor/sidebar/MainContentTree.js.map +1 -1
  120. package/dist/editor/sidebar/SEOInfo.js +1 -1
  121. package/dist/editor/sidebar/SEOInfo.js.map +1 -1
  122. package/dist/editor/sidebar/ViewSelector.d.ts +4 -1
  123. package/dist/editor/sidebar/ViewSelector.js +64 -48
  124. package/dist/editor/sidebar/ViewSelector.js.map +1 -1
  125. package/dist/editor/ui/PerfectTree.js +2 -11
  126. package/dist/editor/ui/PerfectTree.js.map +1 -1
  127. package/dist/editor/ui/SimpleIconButton.d.ts +2 -0
  128. package/dist/editor/ui/SimpleIconButton.js +8 -4
  129. package/dist/editor/ui/SimpleIconButton.js.map +1 -1
  130. package/dist/index.d.ts +4 -2
  131. package/dist/index.js +3 -1
  132. package/dist/index.js.map +1 -1
  133. package/dist/page-wizard/steps/CollectStep.js +1 -1
  134. package/dist/page-wizard/steps/CollectStep.js.map +1 -1
  135. package/dist/page-wizard/steps/StructureStep.js +1 -1
  136. package/dist/page-wizard/steps/StructureStep.js.map +1 -1
  137. package/dist/page-wizard/steps/TranslateStep.js +233 -18
  138. package/dist/page-wizard/steps/TranslateStep.js.map +1 -1
  139. package/dist/revision.d.ts +2 -2
  140. package/dist/revision.js +2 -2
  141. package/dist/splash-screen/RecentPages.js +1 -13
  142. package/dist/splash-screen/RecentPages.js.map +1 -1
  143. package/dist/splash-screen/SplashScreen.js +1 -1
  144. package/dist/splash-screen/SplashScreen.js.map +1 -1
  145. package/dist/styles.css +88 -3
  146. package/dist/types.d.ts +6 -0
  147. package/package.json +2 -2
  148. package/src/components/ActionButton.tsx +3 -2
  149. package/src/components/SimpleLanguageSelector.tsx +6 -1
  150. package/src/config/config.tsx +1 -1
  151. package/src/config/types.ts +1 -1
  152. package/src/editor/ContextMenu.tsx +0 -3
  153. package/src/editor/Editor.tsx +11 -3
  154. package/src/editor/FieldListField.tsx +22 -31
  155. package/src/editor/ImageEditButton.tsx +1 -0
  156. package/src/editor/ImageEditor.tsx +1 -0
  157. package/src/editor/MainLayout.tsx +2 -2
  158. package/src/editor/Terminal.tsx +1 -1
  159. package/src/editor/Titlebar.tsx +0 -2
  160. package/src/editor/ai/AgentCostDisplay.tsx +237 -0
  161. package/src/editor/ai/Agents.tsx +69 -20
  162. package/src/editor/ai/AiPromptPopover.tsx +209 -0
  163. package/src/editor/ai/AiResponseMessage.tsx +201 -60
  164. package/src/editor/ai/AiTerminal.tsx +502 -71
  165. package/src/editor/ai/editorAiContext.ts +0 -3
  166. package/src/editor/client/EditorClient.tsx +409 -117
  167. package/src/editor/client/editContext.ts +7 -5
  168. package/src/editor/client/fieldModificationStore.ts +196 -0
  169. package/src/editor/client/itemsRepository.ts +41 -31
  170. package/src/editor/client/operations.ts +95 -76
  171. package/src/editor/commands/componentCommands.tsx +9 -3
  172. package/src/editor/commands/itemCommands.tsx +0 -1
  173. package/src/editor/component-designer/aiContext.ts +0 -2
  174. package/src/editor/field-types/DropLinkEditor.tsx +1 -1
  175. package/src/editor/field-types/MultiLineText.tsx +9 -9
  176. package/src/editor/field-types/RichTextEditorComponent.tsx +8 -8
  177. package/src/editor/field-types/SingleLineText.tsx +9 -9
  178. package/src/editor/hooks/useEditorSettings.ts +68 -0
  179. package/src/editor/menubar/ItemActionsMenu.tsx +3 -2
  180. package/src/editor/menubar/PageSelector.tsx +1 -1
  181. package/src/editor/menubar/toolbar-sections/EditControls.tsx +1 -0
  182. package/src/editor/menubar/toolbar-sections/InsertControls.tsx +1 -0
  183. package/src/editor/menubar/toolbar-sections/UtilityControls.tsx +2 -0
  184. package/src/editor/menubar/toolbar-sections/ViewportControls.tsx +2 -0
  185. package/src/editor/page-editor-chrome/FieldEditedIndicators.tsx +4 -3
  186. package/src/editor/page-editor-chrome/FrameMenu.tsx +10 -1
  187. package/src/editor/page-editor-chrome/useInlineAICompletion.tsx +0 -1
  188. package/src/editor/page-viewer/EditorForm.tsx +1 -0
  189. package/src/editor/page-viewer/PageViewer.tsx +9 -8
  190. package/src/editor/page-viewer/PageViewerFrame.tsx +7 -1
  191. package/src/editor/page-viewer/pageViewContext.ts +40 -5
  192. package/src/editor/reviews/Comment.tsx +7 -7
  193. package/src/editor/services/agentService.ts +405 -31
  194. package/src/editor/services/aiService.ts +22 -5
  195. package/src/editor/services/contextService.ts +0 -1
  196. package/src/editor/services/systemService.ts +7 -1
  197. package/src/editor/sidebar/ComponentPalette.tsx +4 -1
  198. package/src/editor/sidebar/EditHistory.tsx +2 -0
  199. package/src/editor/sidebar/GraphQL.tsx +19 -7
  200. package/src/editor/sidebar/MainContentTree.tsx +1 -1
  201. package/src/editor/sidebar/SEOInfo.tsx +1 -1
  202. package/src/editor/sidebar/ViewSelector.tsx +80 -64
  203. package/src/editor/ui/PerfectTree.tsx +2 -18
  204. package/src/editor/ui/SimpleIconButton.tsx +56 -38
  205. package/src/index.ts +4 -2
  206. package/src/page-wizard/steps/CollectStep.tsx +0 -2
  207. package/src/page-wizard/steps/StructureStep.tsx +3 -0
  208. package/src/page-wizard/steps/TranslateStep.tsx +473 -62
  209. package/src/revision.ts +2 -2
  210. package/src/splash-screen/RecentPages.tsx +0 -14
  211. package/src/splash-screen/SplashScreen.tsx +3 -2
  212. package/src/types.ts +7 -0
  213. package/dist/editor/ai/AiPopup.d.ts +0 -10
  214. package/dist/editor/ai/AiPopup.js +0 -23
  215. package/dist/editor/ai/AiPopup.js.map +0 -1
  216. package/dist/editor/ai/AiToolCall.d.ts +0 -5
  217. package/dist/editor/ai/AiToolCall.js +0 -28
  218. package/dist/editor/ai/AiToolCall.js.map +0 -1
  219. package/src/editor/ai/AiPopup.tsx +0 -59
  220. package/src/editor/ai/AiToolCall.tsx +0 -71
@@ -1,5 +1,6 @@
1
- import { useState, useEffect } from "react";
2
- import JSONPretty from "react-json-pretty";
1
+ import React, { useState, useEffect } from "react";
2
+ import { JsonView, defaultStyles } from "react-json-view-lite";
3
+ import "react-json-view-lite/dist/index.css";
3
4
 
4
5
  import { useEditContext } from "../client/editContext";
5
6
  import { EditOperation } from "../../types";
@@ -11,6 +12,67 @@ import {
11
12
  PopoverTrigger,
12
13
  } from "../../components/ui/popover";
13
14
  import { SimpleTabs, Tab } from "../ui/SimpleTabs";
15
+ import { Spinner } from "../ui/Spinner";
16
+ import { SimpleIconButton } from "../ui/SimpleIconButton";
17
+ import {
18
+ X,
19
+ FileText,
20
+ Search,
21
+ Code,
22
+ Terminal,
23
+ FolderOpen,
24
+ FileSearch,
25
+ Trash2,
26
+ Globe,
27
+ Brain,
28
+ CheckSquare,
29
+ Edit,
30
+ FileEdit,
31
+ Wrench,
32
+ } from "lucide-react";
33
+
34
+ // Function to get the appropriate icon for each tool
35
+ const getToolIcon = (toolName: string) => {
36
+ const iconMap: { [key: string]: React.ReactElement } = {
37
+ // Content operations
38
+ "get-content": <FileText strokeWidth={1} size={14} />,
39
+ "edit-field": <Edit strokeWidth={1} size={14} />,
40
+ "suggest-field-edit": <Edit strokeWidth={1} size={14} />,
41
+
42
+ // Item operations
43
+ "create-item": <FileEdit strokeWidth={1} size={14} />,
44
+ "load-item": <FileText strokeWidth={1} size={14} />,
45
+ "get-items": <FolderOpen strokeWidth={1} size={14} />,
46
+ "get-children": <FolderOpen strokeWidth={1} size={14} />,
47
+ "get-insertoptions": <FolderOpen strokeWidth={1} size={14} />,
48
+
49
+ // Component operations
50
+ "add-component": <Code strokeWidth={1} size={14} />,
51
+ "remove-component": <Trash2 strokeWidth={1} size={14} />,
52
+ "move-components": <Edit strokeWidth={1} size={14} />,
53
+ "get-placeholders": <Code strokeWidth={1} size={14} />,
54
+ "get-component-props-and-placeholders": <Code strokeWidth={1} size={14} />,
55
+
56
+ // Search operations
57
+ "search-content": <Search strokeWidth={1} size={14} />,
58
+ "search-images": <FileSearch strokeWidth={1} size={14} />,
59
+ "google-search": <Globe strokeWidth={1} size={14} />,
60
+
61
+ // Image operations
62
+ "edit-image": <FileEdit strokeWidth={1} size={14} />,
63
+ "get-picture-description": <FileText strokeWidth={1} size={14} />,
64
+
65
+ // Comments and suggestions
66
+ "add-comment": <CheckSquare strokeWidth={1} size={14} />,
67
+ "get-comments": <CheckSquare strokeWidth={1} size={14} />,
68
+ "get-suggestions": <Brain strokeWidth={1} size={14} />,
69
+
70
+ // Default fallback
71
+ default: <Wrench strokeWidth={1} size={14} />,
72
+ };
73
+
74
+ return iconMap[toolName] || iconMap.default;
75
+ };
14
76
 
15
77
  export function AiResponseMessage({
16
78
  messages,
@@ -34,7 +96,10 @@ export function AiResponseMessage({
34
96
  [messageIndex: number]: any[];
35
97
  }>({});
36
98
 
37
- console.log(messages);
99
+ // Track popover open state for each tool call
100
+ const [openPopovers, setOpenPopovers] = useState<{
101
+ [key: string]: boolean;
102
+ }>({});
38
103
 
39
104
  // Update preserved tool calls when messages change
40
105
  useEffect(() => {
@@ -61,41 +126,91 @@ export function AiResponseMessage({
61
126
  ) === undefined;
62
127
 
63
128
  // Helper function to render JSON or text
64
- const renderJsonOrText = (json: string) => {
65
- try {
66
- const parsed = JSON.parse(json);
129
+ const renderJsonOrText = (json: string | object) => {
130
+ // If it's already an object, use it directly
131
+ if (typeof json === "object" && json !== null) {
67
132
  return (
68
- <div className="font-mono text-xs whitespace-pre-wrap">
69
- <pre className="break-words whitespace-pre-wrap">
70
- {JSON.stringify(parsed, null, 2)}
71
- </pre>
133
+ <div className="font-mono text-xs" style={{ fontSize: "12px" }}>
134
+ <JsonView
135
+ data={json}
136
+ shouldExpandNode={(level) => level < 2}
137
+ style={defaultStyles}
138
+ />
72
139
  </div>
73
140
  );
74
- } catch (e) {
141
+ }
142
+
143
+ // Convert to string if not already
144
+ const jsonString = typeof json === "string" ? json : String(json);
145
+
146
+ // Try to parse as JSON
147
+ try {
148
+ let parsed = JSON.parse(jsonString);
149
+
150
+ // If the result is still a string that looks like JSON, parse it again
151
+ if (
152
+ typeof parsed === "string" &&
153
+ (parsed.startsWith("{") || parsed.startsWith("["))
154
+ ) {
155
+ try {
156
+ parsed = JSON.parse(parsed);
157
+ } catch (e2) {
158
+ console.log("Second parse failed, using first result");
159
+ }
160
+ }
161
+
75
162
  return (
76
- <div className="font-mono text-xs break-words whitespace-pre-wrap">
77
- {json}
163
+ <div className="font-mono text-xs" style={{ fontSize: "12px" }}>
164
+ <JsonView
165
+ data={parsed}
166
+ shouldExpandNode={(level) => level < 2}
167
+ style={defaultStyles}
168
+ />
78
169
  </div>
79
170
  );
171
+ } catch (e) {
172
+ console.log("JSON parse failed:", e, "Trying to handle as string...");
173
+
174
+ // Try to handle double-escaped JSON
175
+ try {
176
+ const unescaped = jsonString
177
+ .replace(/\\"/g, '"')
178
+ .replace(/\\\\/g, "\\");
179
+ const parsed = JSON.parse(unescaped);
180
+
181
+ return (
182
+ <div className="font-mono text-xs" style={{ fontSize: "12px" }}>
183
+ <JsonView
184
+ data={parsed}
185
+ shouldExpandNode={(level) => level < 2}
186
+ style={defaultStyles}
187
+ />
188
+ </div>
189
+ );
190
+ } catch (e2) {
191
+ console.log("Unescaping also failed:", e2);
192
+ // If all parsing fails, display as plain text
193
+ return (
194
+ <div className="font-mono text-xs break-words whitespace-pre-wrap">
195
+ {jsonString}
196
+ </div>
197
+ );
198
+ }
80
199
  }
81
200
  };
82
201
 
83
202
  // Helper function to create tabs for a tool call
84
- const createToolCallTabs = (
85
- toolCall: any,
86
- result: Message | undefined,
87
- ): Tab[] => {
203
+ const createToolCallTabs = (toolCall: any, result: string): Tab[] => {
88
204
  const tabs: Tab[] = [
89
205
  {
90
206
  id: `input-${toolCall.id}`,
91
207
  label: "Input",
92
208
  content: (
93
- <div className="max-h-96 overflow-auto p-2">
94
- <div className="mb-1 text-sm font-semibold text-gray-700">
95
- Arguments:
96
- </div>
97
- <div className="text-xs">
98
- {renderJsonOrText(toolCall.function.arguments)}
209
+ <div className="relative h-full w-full p-2">
210
+ <div className="absolute inset-2 overflow-auto">
211
+ <div className="text-xs">
212
+ {renderJsonOrText(toolCall.function.arguments)}
213
+ </div>
99
214
  </div>
100
215
  </div>
101
216
  ),
@@ -107,12 +222,9 @@ export function AiResponseMessage({
107
222
  id: `output-${toolCall.id}`,
108
223
  label: "Output",
109
224
  content: (
110
- <div className="max-h-96 overflow-auto p-2">
111
- <div className="mb-1 text-sm font-semibold text-gray-700">
112
- Result:
113
- </div>
114
- <div className="text-xs">
115
- {renderJsonOrText(result.content || "")}
225
+ <div className="relative h-full w-full p-2">
226
+ <div className="absolute inset-2 overflow-y-auto">
227
+ <div className="text-xs">{renderJsonOrText(result || "")}</div>
116
228
  </div>
117
229
  </div>
118
230
  ),
@@ -126,19 +238,29 @@ export function AiResponseMessage({
126
238
  const ToolCallPopover = ({
127
239
  toolCall,
128
240
  result,
241
+ onClose,
129
242
  }: {
130
243
  toolCall: any;
131
- result: Message | undefined;
244
+ result?: string;
245
+ onClose: () => void;
132
246
  }) => {
133
247
  const [activeTab, setActiveTab] = useState(0);
134
- const tabs = createToolCallTabs(toolCall, result);
248
+ const tabs = createToolCallTabs(toolCall, result || "");
135
249
 
136
250
  return (
137
- <div className="w-96">
138
- <div className="mb-3 border-b border-gray-200 pb-2">
139
- <div className="text-sm font-semibold text-gray-800">
140
- {toolCall.displayName || toolCall.function.name}
251
+ <div className="h-[400px]">
252
+ <div className="mb-3 flex items-center justify-between border-b border-gray-200 px-2 pb-1">
253
+ <div className="flex items-center gap-2 text-sm font-semibold text-gray-800">
254
+ {getToolIcon(toolCall?.function?.name || "")}
255
+ <span>{toolCall.displayName || toolCall.function.name}</span>
141
256
  </div>
257
+ <SimpleIconButton
258
+ onClick={onClose}
259
+ icon={<X strokeWidth={1} size={16} />}
260
+ label="Close"
261
+ showTooltip={false}
262
+ size="small"
263
+ />
142
264
  </div>
143
265
  <SimpleTabs
144
266
  tabs={tabs}
@@ -151,17 +273,10 @@ export function AiResponseMessage({
151
273
  );
152
274
  };
153
275
 
154
- // Helper function to find tool result by tool call id
155
- const findToolResult = (toolCallId: string): Message | undefined => {
156
- return messages.find(
157
- (msg) => msg.role === "tool" && msg.tool_call_id === toolCallId,
158
- );
159
- };
160
-
161
276
  return (
162
277
  <div>
163
278
  {messages
164
- .filter((x) => x.role !== "tool")
279
+ .filter((x) => x.role !== "tool" && x.role !== "user")
165
280
  .map((message, filteredIndex) => {
166
281
  // Find the original index of this message in the unfiltered array
167
282
  const originalIndex = messages.findIndex((m) => m.id === message.id);
@@ -171,19 +286,46 @@ export function AiResponseMessage({
171
286
  ? message.tool_calls
172
287
  : preservedToolCalls[originalIndex] || [];
173
288
  return (
174
- <div key={filteredIndex}>
289
+ <div
290
+ key={filteredIndex}
291
+ className={toolCalls.length > 0 ? "mb-2" : ""}
292
+ >
293
+ <div
294
+ dangerouslySetInnerHTML={{
295
+ __html: message.formattedContent || message.content || "",
296
+ }}
297
+ />
175
298
  {toolCalls.length > 0 && (
176
- <div className="mb-2 flex flex-wrap gap-2">
299
+ <div className="mt-2 flex flex-col gap-2">
177
300
  {toolCalls.map((toolCall, toolIndex) => {
178
- const toolResult = findToolResult(toolCall.id);
301
+ const toolResult = toolCall.function.result;
302
+ const popoverKey = `${originalIndex}-${toolIndex}`;
303
+
179
304
  return (
180
305
  <Popover
181
306
  key={toolIndex}
182
307
  enableIframeClickDetection={false}
308
+ open={openPopovers[popoverKey] || false}
309
+ onOpenChange={(open) => {
310
+ setOpenPopovers((prev) => ({
311
+ ...prev,
312
+ [popoverKey]: open,
313
+ }));
314
+ }}
183
315
  >
184
316
  <PopoverTrigger asChild>
185
317
  <div className="inline-flex cursor-pointer items-center gap-1 text-xs text-gray-500 hover:text-gray-700">
186
- <i className="pi pi-wrench text-xs" />
318
+ {toolResult ? (
319
+ <div className="flex items-center">
320
+ {getToolIcon(toolCall?.function?.name || "")}
321
+ </div>
322
+ ) : finished ? (
323
+ <div className="flex items-center opacity-50">
324
+ {getToolIcon(toolCall?.function?.name || "")}
325
+ </div>
326
+ ) : (
327
+ <Spinner size="xs" />
328
+ )}
187
329
  <span>
188
330
  {toolCall?.displayName ||
189
331
  toolCall?.function?.name ||
@@ -192,30 +334,29 @@ export function AiResponseMessage({
192
334
  </div>
193
335
  </PopoverTrigger>
194
336
  <PopoverContent
195
- className="p-3"
337
+ className="w-[400px] p-3"
196
338
  align="start"
197
339
  side="bottom"
198
340
  sideOffset={8}
199
341
  onMouseDown={(e) => e.stopPropagation()}
200
342
  onClick={(e) => e.stopPropagation()}
201
343
  >
202
- <div className="max-h-[500px] overflow-hidden">
203
- <ToolCallPopover
204
- toolCall={toolCall}
205
- result={toolResult}
206
- />
207
- </div>
344
+ <ToolCallPopover
345
+ toolCall={toolCall}
346
+ result={toolResult}
347
+ onClose={() => {
348
+ setOpenPopovers((prev) => ({
349
+ ...prev,
350
+ [popoverKey]: false,
351
+ }));
352
+ }}
353
+ />
208
354
  </PopoverContent>
209
355
  </Popover>
210
356
  );
211
357
  })}
212
358
  </div>
213
359
  )}
214
- <div
215
- dangerouslySetInnerHTML={{
216
- __html: message.formattedContent || message.content || "",
217
- }}
218
- />
219
360
  </div>
220
361
  );
221
362
  })}
@@ -254,7 +395,7 @@ export function AiResponseMessage({
254
395
  setChangesRejected(true);
255
396
  }}
256
397
  >
257
- <i className="pi pi-times" /> Reject
398
+ <X strokeWidth={1} size={14} /> Reject
258
399
  </div>
259
400
  )}
260
401
  {changesRejected && (