@alpaca-editor/core 1.0.4102 → 1.0.4104
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ui/context-menu.d.ts +1 -1
- package/dist/components/ui/context-menu.js +8 -8
- package/dist/components/ui/context-menu.js.map +1 -1
- package/dist/config/config.js +8 -1
- package/dist/config/config.js.map +1 -1
- package/dist/config/types.d.ts +1 -0
- package/dist/editor/ContentTree.js +15 -16
- package/dist/editor/ContentTree.js.map +1 -1
- package/dist/editor/ContextMenu.js +37 -6
- package/dist/editor/ContextMenu.js.map +1 -1
- package/dist/editor/MainLayout.js +1 -1
- package/dist/editor/MainLayout.js.map +1 -1
- package/dist/editor/ai/AgentHistory.js +1 -1
- package/dist/editor/ai/AgentTerminal.js +187 -13
- package/dist/editor/ai/AgentTerminal.js.map +1 -1
- package/dist/editor/ai/AiResponseMessage.d.ts +1 -1
- package/dist/editor/ai/types.d.ts +25 -0
- package/dist/editor/ai/types.js +2 -0
- package/dist/editor/ai/types.js.map +1 -0
- package/dist/editor/client/EditorShell.js +29 -0
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/client/editContext.d.ts +3 -0
- package/dist/editor/client/editContext.js.map +1 -1
- package/dist/editor/commands/agentCommands.d.ts +9 -0
- package/dist/editor/commands/agentCommands.js +30 -0
- package/dist/editor/commands/agentCommands.js.map +1 -0
- package/dist/editor/commands/itemCommands.js +14 -14
- package/dist/editor/commands/itemCommands.js.map +1 -1
- package/dist/editor/component-designer/aiContext.d.ts +1 -1
- package/dist/editor/context-menu/InsertMenu.d.ts +2 -1
- package/dist/editor/context-menu/InsertMenu.js +20 -15
- package/dist/editor/context-menu/InsertMenu.js.map +1 -1
- package/dist/editor/field-types/NameValueListEditor.d.ts +7 -0
- package/dist/editor/field-types/NameValueListEditor.js +99 -0
- package/dist/editor/field-types/NameValueListEditor.js.map +1 -0
- package/dist/editor/fieldTypes.d.ts +1 -1
- package/dist/editor/page-editor-chrome/FrameMenu.js +47 -10
- package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.d.ts +3 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +30 -4
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js +44 -5
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -1
- package/dist/editor/services/agentService.d.ts +22 -2
- package/dist/editor/services/agentService.js +26 -1
- package/dist/editor/services/agentService.js.map +1 -1
- package/dist/editor/services/aiService.d.ts +2 -1
- package/dist/editor/services/aiService.js.map +1 -1
- package/dist/editor/sidebar/GraphQL.js +47 -90
- package/dist/editor/sidebar/GraphQL.js.map +1 -1
- package/dist/editor/ui/DragPreview.d.ts +13 -0
- package/dist/editor/ui/DragPreview.js +35 -0
- package/dist/editor/ui/DragPreview.js.map +1 -0
- package/dist/editor/ui/ItemNameDialogNew.js +2 -2
- package/dist/editor/ui/ItemNameDialogNew.js.map +1 -1
- package/dist/editor/ui/PerfectTree.js +3 -15
- package/dist/editor/ui/PerfectTree.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/styles.css +37 -9
- package/dist/tour/default-tour.js +34 -38
- package/dist/tour/default-tour.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ui/context-menu.tsx +31 -19
- package/src/config/config.tsx +9 -1
- package/src/config/types.ts +1 -0
- package/src/editor/ContentTree.tsx +13 -18
- package/src/editor/ContextMenu.tsx +112 -19
- package/src/editor/MainLayout.tsx +1 -1
- package/src/editor/ai/AgentHistory.tsx +2 -2
- package/src/editor/ai/AgentTerminal.tsx +226 -15
- package/src/editor/ai/AiResponseMessage.tsx +1 -1
- package/src/editor/ai/types.ts +27 -0
- package/src/editor/client/EditorShell.tsx +31 -0
- package/src/editor/client/editContext.ts +12 -1
- package/src/editor/commands/agentCommands.tsx +49 -0
- package/src/editor/commands/itemCommands.tsx +26 -14
- package/src/editor/component-designer/aiContext.ts +1 -1
- package/src/editor/context-menu/InsertMenu.tsx +64 -39
- package/src/editor/field-types/NameValueListEditor.tsx +197 -0
- package/src/editor/fieldTypes.ts +1 -1
- package/src/editor/page-editor-chrome/FrameMenu.tsx +61 -13
- package/src/editor/page-editor-chrome/PlaceholderDropZone.tsx +82 -20
- package/src/editor/page-editor-chrome/PlaceholderDropZones.tsx +77 -24
- package/src/editor/services/agentService.ts +53 -2
- package/src/editor/services/aiService.ts +3 -1
- package/src/editor/sidebar/GraphQL.tsx +50 -99
- package/src/editor/ui/DragPreview.tsx +44 -0
- package/src/editor/ui/ItemNameDialogNew.tsx +7 -3
- package/src/editor/ui/PerfectTree.tsx +2 -17
- package/src/revision.ts +2 -2
- package/src/tour/default-tour.tsx +34 -46
- package/dist/editor/ai/AiTerminal.d.ts +0 -47
- package/dist/editor/ai/AiTerminal.js +0 -300
- package/dist/editor/ai/AiTerminal.js.map +0 -1
- package/src/editor/ai/AiTerminal.tsx +0 -570
- package/src/editor/component-designer/ComponentDesignerAiTerminal.tsx_ +0 -11
|
@@ -1,570 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { useEffect, useRef, useState } from "react";
|
|
4
|
-
|
|
5
|
-
import { TerminalService } from "primereact/terminalservice";
|
|
6
|
-
|
|
7
|
-
import { Terminal } from "../Terminal";
|
|
8
|
-
import { EditContextType, useEditContext } from "../client/editContext";
|
|
9
|
-
import { Dropdown } from "primereact/dropdown";
|
|
10
|
-
|
|
11
|
-
import { WizardIcon } from "../ui/Icons";
|
|
12
|
-
import { AiResponseMessage } from "./AiResponseMessage";
|
|
13
|
-
import {
|
|
14
|
-
AiProfile,
|
|
15
|
-
loadAiProfiles,
|
|
16
|
-
executePrompt,
|
|
17
|
-
} from "../services/aiService";
|
|
18
|
-
import { EditOperation } from "../../types";
|
|
19
|
-
import { SimpleIconButton } from "../ui/SimpleIconButton";
|
|
20
|
-
import { Settings } from "lucide-react";
|
|
21
|
-
|
|
22
|
-
type Response = {
|
|
23
|
-
messages: Message[];
|
|
24
|
-
editOperations: EditOperation[];
|
|
25
|
-
numInputTokens: number;
|
|
26
|
-
numOutputTokens: number;
|
|
27
|
-
numCachedTokens: number;
|
|
28
|
-
state: string;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export type ToolCall = {
|
|
32
|
-
id: string;
|
|
33
|
-
displayName: string;
|
|
34
|
-
function: {
|
|
35
|
-
name: string;
|
|
36
|
-
arguments: string;
|
|
37
|
-
};
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export type Message = {
|
|
41
|
-
id: string; // Changed from number to string for UUID support
|
|
42
|
-
content: string;
|
|
43
|
-
formattedContent?: string;
|
|
44
|
-
name: string;
|
|
45
|
-
role: string;
|
|
46
|
-
tool_calls?: ToolCall[];
|
|
47
|
-
tool_call_id?: string; // For tool response messages
|
|
48
|
-
createdDate?: string; // Timestamp from the original message
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export type AiContext = {
|
|
52
|
-
promptData: any;
|
|
53
|
-
endpoint?: string;
|
|
54
|
-
callback?: (response: Response) => void;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export type AiTerminalOptions = {
|
|
58
|
-
initialPrompt?: string;
|
|
59
|
-
hiddenSystemPrompt?: string;
|
|
60
|
-
initialMessages?: Message[];
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
export function AiTerminal({
|
|
64
|
-
closeButton,
|
|
65
|
-
createAiContext,
|
|
66
|
-
defaultProfile,
|
|
67
|
-
options,
|
|
68
|
-
}: {
|
|
69
|
-
closeButton?: React.ReactNode;
|
|
70
|
-
createAiContext: ({
|
|
71
|
-
editContext,
|
|
72
|
-
}: {
|
|
73
|
-
editContext: EditContextType;
|
|
74
|
-
}) => AiContext;
|
|
75
|
-
defaultProfile?: string;
|
|
76
|
-
options?: AiTerminalOptions;
|
|
77
|
-
}) {
|
|
78
|
-
const editContext = useEditContext();
|
|
79
|
-
const [showPredefined, setShowPredefined] = useState(false);
|
|
80
|
-
|
|
81
|
-
if (!editContext) return null;
|
|
82
|
-
|
|
83
|
-
const [messages, setMessages] = useState<Message[]>(
|
|
84
|
-
options?.initialMessages || [],
|
|
85
|
-
);
|
|
86
|
-
const [response, setResponse] = useState<Response>();
|
|
87
|
-
const [model, setModel] = useState<string>();
|
|
88
|
-
const [prompt, setPrompt] = useState("");
|
|
89
|
-
const [profiles, setProfiles] = useState<AiProfile[]>([]);
|
|
90
|
-
const [activeProfile, setActiveProfile] = useState<AiProfile>();
|
|
91
|
-
const [initialPromptExecuted, setInitialPromptExecuted] = useState(false);
|
|
92
|
-
const [agentId] = useState<string>(() => crypto.randomUUID());
|
|
93
|
-
const selection = editContext.selection;
|
|
94
|
-
const terminalRef = useRef<{ submit: () => void; focusPrompt: () => void }>(
|
|
95
|
-
null,
|
|
96
|
-
);
|
|
97
|
-
const [responseMessages, setResponseMessages] = useState<Message[]>(
|
|
98
|
-
options?.initialMessages || [],
|
|
99
|
-
);
|
|
100
|
-
const [showSettings, setShowSettings] = useState(false);
|
|
101
|
-
const settingsRef = useRef<HTMLDivElement>(null);
|
|
102
|
-
const [inputPlaceholder, setInputPlaceholder] = useState<string | undefined>(
|
|
103
|
-
undefined,
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
useEffect(() => {
|
|
107
|
-
if (options?.initialPrompt && !initialPromptExecuted && model) {
|
|
108
|
-
// Set the initial prompt text into the terminal's state.
|
|
109
|
-
console.log("setting prompt", options.initialPrompt);
|
|
110
|
-
setPrompt(options.initialPrompt);
|
|
111
|
-
setInitialPromptExecuted(true);
|
|
112
|
-
// Wait for the Terminal to update, then programmatically submit.
|
|
113
|
-
setTimeout(() => {
|
|
114
|
-
terminalRef.current?.submit();
|
|
115
|
-
}, 100);
|
|
116
|
-
}
|
|
117
|
-
}, [options?.initialPrompt, initialPromptExecuted, model]);
|
|
118
|
-
|
|
119
|
-
useEffect(() => {
|
|
120
|
-
async function fetchProfiles() {
|
|
121
|
-
if (!editContext?.currentItemDescriptor) return;
|
|
122
|
-
const profiles = await loadAiProfiles(editContext.currentItemDescriptor);
|
|
123
|
-
setProfiles(profiles);
|
|
124
|
-
if (!activeProfile)
|
|
125
|
-
setActiveProfile(
|
|
126
|
-
profiles.find((x) => x.name == defaultProfile) || profiles[0],
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
fetchProfiles();
|
|
130
|
-
}, [editContext?.currentItemDescriptor]);
|
|
131
|
-
|
|
132
|
-
useEffect(() => {
|
|
133
|
-
if (activeProfile?.defaultModelId) setModel(activeProfile.defaultModelId);
|
|
134
|
-
}, [activeProfile]);
|
|
135
|
-
|
|
136
|
-
const messagesRef = useRef(messages);
|
|
137
|
-
useEffect(() => {
|
|
138
|
-
messagesRef.current = responseMessages;
|
|
139
|
-
}, [responseMessages]);
|
|
140
|
-
|
|
141
|
-
// State for initial messages to pass to Terminal
|
|
142
|
-
type TerminalMessage = {
|
|
143
|
-
text: React.ReactNode;
|
|
144
|
-
type: "command" | "response";
|
|
145
|
-
};
|
|
146
|
-
const [initialTerminalMessages, setInitialTerminalMessages] = useState<
|
|
147
|
-
TerminalMessage[] | undefined
|
|
148
|
-
>(undefined);
|
|
149
|
-
|
|
150
|
-
// Effect to set up initial messages for display
|
|
151
|
-
useEffect(() => {
|
|
152
|
-
if (options?.initialMessages && options.initialMessages.length > 0) {
|
|
153
|
-
console.log(
|
|
154
|
-
"AiTerminal: Loading initial messages",
|
|
155
|
-
options.initialMessages,
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
// Format the initial messages for display
|
|
159
|
-
const formattedMessages = options.initialMessages.map((message) => {
|
|
160
|
-
const formattedContent =
|
|
161
|
-
message.content
|
|
162
|
-
?.trim()
|
|
163
|
-
?.replaceAll("\n", "<br>")
|
|
164
|
-
?.replace(/\*\*(.*?)\*\*/g, "<b>$1</b>") || "";
|
|
165
|
-
|
|
166
|
-
return {
|
|
167
|
-
...message,
|
|
168
|
-
content: message.content || "",
|
|
169
|
-
formattedContent: formattedContent,
|
|
170
|
-
tool_calls: message.tool_calls || [],
|
|
171
|
-
};
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
console.log("AiTerminal: Formatted messages", formattedMessages);
|
|
175
|
-
|
|
176
|
-
// Update the internal message states
|
|
177
|
-
setMessages(formattedMessages);
|
|
178
|
-
setResponseMessages(formattedMessages);
|
|
179
|
-
|
|
180
|
-
// Create a response object for internal state
|
|
181
|
-
const initialResponse: Response = {
|
|
182
|
-
messages: formattedMessages,
|
|
183
|
-
editOperations: [],
|
|
184
|
-
numInputTokens: 0,
|
|
185
|
-
numOutputTokens: 0,
|
|
186
|
-
numCachedTokens: 0,
|
|
187
|
-
state: "loaded",
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
console.log("AiTerminal: Setting response", initialResponse);
|
|
191
|
-
setResponse(initialResponse);
|
|
192
|
-
|
|
193
|
-
// Create individual Terminal messages for each conversation message
|
|
194
|
-
const terminalMessages: TerminalMessage[] = [];
|
|
195
|
-
|
|
196
|
-
formattedMessages.forEach((message) => {
|
|
197
|
-
if (message.role === "user") {
|
|
198
|
-
// User messages appear as commands
|
|
199
|
-
terminalMessages.push({
|
|
200
|
-
type: "command",
|
|
201
|
-
text: message.content,
|
|
202
|
-
});
|
|
203
|
-
} else if (message.role === "assistant") {
|
|
204
|
-
// Assistant messages appear as responses
|
|
205
|
-
terminalMessages.push({
|
|
206
|
-
type: "response",
|
|
207
|
-
text: (
|
|
208
|
-
<div
|
|
209
|
-
dangerouslySetInnerHTML={{
|
|
210
|
-
__html: message.formattedContent || message.content || "",
|
|
211
|
-
}}
|
|
212
|
-
/>
|
|
213
|
-
),
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
// Add tool calls if present
|
|
217
|
-
if (message.tool_calls && message.tool_calls.length > 0) {
|
|
218
|
-
message.tool_calls.forEach((toolCall) => {
|
|
219
|
-
terminalMessages.push({
|
|
220
|
-
type: "response",
|
|
221
|
-
text: (
|
|
222
|
-
<div className="text-gray-1 text-xs">
|
|
223
|
-
🔧 {toolCall.displayName}
|
|
224
|
-
</div>
|
|
225
|
-
),
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
setInitialTerminalMessages(terminalMessages);
|
|
232
|
-
}
|
|
233
|
-
}, [options?.initialMessages]);
|
|
234
|
-
|
|
235
|
-
// Handle click outside for settings popover
|
|
236
|
-
useEffect(() => {
|
|
237
|
-
function handleClickOutside(event: MouseEvent) {
|
|
238
|
-
if (
|
|
239
|
-
settingsRef.current &&
|
|
240
|
-
!settingsRef.current.contains(event.target as Node)
|
|
241
|
-
) {
|
|
242
|
-
setShowSettings(false);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
if (showSettings) {
|
|
247
|
-
document.addEventListener("click", handleClickOutside);
|
|
248
|
-
return () => {
|
|
249
|
-
document.removeEventListener("click", handleClickOutside);
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
}, [showSettings]);
|
|
253
|
-
|
|
254
|
-
function handleResponse(
|
|
255
|
-
response: Response,
|
|
256
|
-
terminalCallback: (text: React.ReactNode, finished: boolean) => void,
|
|
257
|
-
isFinished: boolean,
|
|
258
|
-
) {
|
|
259
|
-
const updatedMessages = response.messages;
|
|
260
|
-
|
|
261
|
-
// Replace the conversation history with the authoritative response from AI
|
|
262
|
-
if (updatedMessages && Array.isArray(updatedMessages)) {
|
|
263
|
-
const formattedMessages = updatedMessages.map((message) => {
|
|
264
|
-
const formattedContent =
|
|
265
|
-
message.content
|
|
266
|
-
?.trim()
|
|
267
|
-
?.replaceAll("\n", "<br>")
|
|
268
|
-
?.replace(/\*\*(.*?)\*\*/g, "<b>$1</b>") || "";
|
|
269
|
-
|
|
270
|
-
return {
|
|
271
|
-
...message,
|
|
272
|
-
content: message.content || "",
|
|
273
|
-
formattedContent: formattedContent,
|
|
274
|
-
tool_calls: message.tool_calls || [],
|
|
275
|
-
};
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
// Update the messages state with the complete conversation from AI
|
|
279
|
-
setMessages([...formattedMessages]);
|
|
280
|
-
setResponseMessages([...formattedMessages]);
|
|
281
|
-
|
|
282
|
-
terminalCallback(
|
|
283
|
-
<AiResponseMessage
|
|
284
|
-
messages={formattedMessages}
|
|
285
|
-
editOperations={response.editOperations}
|
|
286
|
-
finished={isFinished}
|
|
287
|
-
onQuickAction={(action) => {
|
|
288
|
-
const text = (
|
|
289
|
-
action.prompt ||
|
|
290
|
-
action.value ||
|
|
291
|
-
action.label ||
|
|
292
|
-
""
|
|
293
|
-
).trim();
|
|
294
|
-
if (!text) return;
|
|
295
|
-
if (action.behavior === "compose") {
|
|
296
|
-
setPrompt(text);
|
|
297
|
-
setInputPlaceholder(action.placeholder);
|
|
298
|
-
setTimeout(() => terminalRef.current?.focusPrompt(), 0);
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
// Submit this as a new command
|
|
302
|
-
commandHandler(text, (node, done) => {
|
|
303
|
-
TerminalService.emit("response", node);
|
|
304
|
-
if (done) TerminalService.emit("response", undefined);
|
|
305
|
-
});
|
|
306
|
-
}}
|
|
307
|
-
/>,
|
|
308
|
-
isFinished,
|
|
309
|
-
);
|
|
310
|
-
} else {
|
|
311
|
-
// Fallback: if no messages in response, keep current state
|
|
312
|
-
terminalCallback(
|
|
313
|
-
<AiResponseMessage
|
|
314
|
-
messages={messagesRef.current}
|
|
315
|
-
editOperations={response.editOperations}
|
|
316
|
-
finished={isFinished}
|
|
317
|
-
onQuickAction={(action) => {
|
|
318
|
-
const text = (
|
|
319
|
-
action.prompt ||
|
|
320
|
-
action.value ||
|
|
321
|
-
action.label ||
|
|
322
|
-
""
|
|
323
|
-
).trim();
|
|
324
|
-
if (!text) return;
|
|
325
|
-
if (action.behavior === "compose") {
|
|
326
|
-
setPrompt(text);
|
|
327
|
-
setInputPlaceholder(action.placeholder);
|
|
328
|
-
setTimeout(() => terminalRef.current?.focusPrompt(), 0);
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
331
|
-
commandHandler(text, (node, done) => {
|
|
332
|
-
TerminalService.emit("response", node);
|
|
333
|
-
if (done) TerminalService.emit("response", undefined);
|
|
334
|
-
});
|
|
335
|
-
}}
|
|
336
|
-
/>,
|
|
337
|
-
isFinished,
|
|
338
|
-
);
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
async function commandHandler(
|
|
343
|
-
text: string,
|
|
344
|
-
callback: (text: React.ReactNode, finished: boolean) => void,
|
|
345
|
-
) {
|
|
346
|
-
const userMessage = {
|
|
347
|
-
id: crypto.randomUUID(), // Add unique id
|
|
348
|
-
content: text,
|
|
349
|
-
role: "user",
|
|
350
|
-
name: "user",
|
|
351
|
-
tool_calls: [], // Add empty toolCalls array
|
|
352
|
-
};
|
|
353
|
-
|
|
354
|
-
const context = createAiContext({ editContext: editContext! });
|
|
355
|
-
|
|
356
|
-
let lastOpIndex = 0;
|
|
357
|
-
const selectedText = editContext?.selectedRange?.text || null;
|
|
358
|
-
if (!activeProfile || !model) return;
|
|
359
|
-
|
|
360
|
-
// Build complete message history for API call
|
|
361
|
-
const conversationHistory = [...messagesRef.current, userMessage];
|
|
362
|
-
const shouldAddTodoFormat = /\b(to-?do|check\s*list|task\s*list)\b/i.test(
|
|
363
|
-
text,
|
|
364
|
-
);
|
|
365
|
-
const todoFormatInstructions =
|
|
366
|
-
"If you produce a to-do list, output it as a 'todo_list' JSON block. Prefer one of these two forms only, with no extra commentary before/after it: \n" +
|
|
367
|
-
'```todo_list\n{ "title": "<optional title>", "items": [ { "text": "<task>", "done": false, "note": "<optional>" } ] }\n```\n' +
|
|
368
|
-
"or a plain header: todo_list: { ... }. Include only fields: title (optional), items (array of {text, done?, note?}).";
|
|
369
|
-
const systemMessages = options?.hiddenSystemPrompt
|
|
370
|
-
? [
|
|
371
|
-
{
|
|
372
|
-
role: "system",
|
|
373
|
-
name: "system",
|
|
374
|
-
content: options.hiddenSystemPrompt,
|
|
375
|
-
id: crypto.randomUUID(),
|
|
376
|
-
toolCalls: [],
|
|
377
|
-
},
|
|
378
|
-
]
|
|
379
|
-
: [];
|
|
380
|
-
const todoSystem = shouldAddTodoFormat
|
|
381
|
-
? [
|
|
382
|
-
{
|
|
383
|
-
role: "system",
|
|
384
|
-
name: "system",
|
|
385
|
-
content: todoFormatInstructions,
|
|
386
|
-
id: crypto.randomUUID(),
|
|
387
|
-
toolCalls: [],
|
|
388
|
-
},
|
|
389
|
-
]
|
|
390
|
-
: [];
|
|
391
|
-
const messages = [...systemMessages, ...todoSystem, ...conversationHistory];
|
|
392
|
-
|
|
393
|
-
const response = await executePrompt(
|
|
394
|
-
messages,
|
|
395
|
-
context,
|
|
396
|
-
{
|
|
397
|
-
profileId: activeProfile.id,
|
|
398
|
-
selection,
|
|
399
|
-
selectedText,
|
|
400
|
-
model,
|
|
401
|
-
sessionId: editContext!.sessionId,
|
|
402
|
-
agentId,
|
|
403
|
-
addSelectedComponents: true,
|
|
404
|
-
},
|
|
405
|
-
undefined,
|
|
406
|
-
(response: any) => {
|
|
407
|
-
setResponse(response);
|
|
408
|
-
handleResponse(response, callback, false);
|
|
409
|
-
},
|
|
410
|
-
);
|
|
411
|
-
|
|
412
|
-
if (response) {
|
|
413
|
-
handleResponse(response, callback, true);
|
|
414
|
-
if (context.callback) context.callback(response);
|
|
415
|
-
editContext?.requestRefresh("immediate");
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
// if (response?.responseText)
|
|
419
|
-
// newMessages.push({
|
|
420
|
-
// content: response.responseText,
|
|
421
|
-
// role: "assistant",
|
|
422
|
-
// name: "assistant",
|
|
423
|
-
// });
|
|
424
|
-
|
|
425
|
-
setResponse(response ? response : undefined);
|
|
426
|
-
|
|
427
|
-
// setMessages(newMessages);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
useEffect(() => {
|
|
431
|
-
TerminalService.on("command", commandHandler);
|
|
432
|
-
|
|
433
|
-
return () => {
|
|
434
|
-
TerminalService.off("command", commandHandler);
|
|
435
|
-
};
|
|
436
|
-
}, []);
|
|
437
|
-
|
|
438
|
-
return (
|
|
439
|
-
<div
|
|
440
|
-
className="relative flex h-full flex-1 flex-col"
|
|
441
|
-
data-testid="ai-terminal"
|
|
442
|
-
>
|
|
443
|
-
<div className="relative flex-1">
|
|
444
|
-
<div className="tour-ai-terminal absolute inset-0">
|
|
445
|
-
<Terminal
|
|
446
|
-
disabled={!model}
|
|
447
|
-
ref={terminalRef}
|
|
448
|
-
onReset={() => {
|
|
449
|
-
setMessages([]);
|
|
450
|
-
setResponseMessages([]);
|
|
451
|
-
setResponse(undefined);
|
|
452
|
-
setInitialTerminalMessages(undefined);
|
|
453
|
-
}}
|
|
454
|
-
initialMessages={initialTerminalMessages}
|
|
455
|
-
infobar={
|
|
456
|
-
response?.numInputTokens && response?.numInputTokens > 0 ? (
|
|
457
|
-
<div
|
|
458
|
-
className="text-right text-gray-400"
|
|
459
|
-
style={{ fontSize: "10px" }}
|
|
460
|
-
>
|
|
461
|
-
Tokens in: {response?.numInputTokens?.toLocaleString()} out:{" "}
|
|
462
|
-
{response?.numOutputTokens?.toLocaleString()}{" "}
|
|
463
|
-
{response?.numCachedTokens
|
|
464
|
-
? `cached: ${response?.numCachedTokens?.toLocaleString()} `
|
|
465
|
-
: ""}
|
|
466
|
-
{response?.state}
|
|
467
|
-
</div>
|
|
468
|
-
) : null
|
|
469
|
-
}
|
|
470
|
-
prompt={prompt}
|
|
471
|
-
setPrompt={setPrompt}
|
|
472
|
-
placeholder={inputPlaceholder}
|
|
473
|
-
statusbar=<div className="flex flex-1 items-center justify-between gap-1">
|
|
474
|
-
<a
|
|
475
|
-
className="ml-1 flex cursor-pointer items-center gap-1 text-xs"
|
|
476
|
-
onClick={() => {
|
|
477
|
-
setShowPredefined(!showPredefined);
|
|
478
|
-
}}
|
|
479
|
-
>
|
|
480
|
-
<WizardIcon className="h-5 w-5" />
|
|
481
|
-
Predefined prompts
|
|
482
|
-
</a>
|
|
483
|
-
{editContext.selection?.length > 0 && (
|
|
484
|
-
<div className="mr-2 flex items-center text-xs text-red-400">
|
|
485
|
-
{editContext.selection.length} items selected
|
|
486
|
-
<SimpleIconButton
|
|
487
|
-
icon="pi pi-times"
|
|
488
|
-
label="Clear selection"
|
|
489
|
-
onClick={() => {
|
|
490
|
-
editContext.select([]);
|
|
491
|
-
}}
|
|
492
|
-
/>
|
|
493
|
-
</div>
|
|
494
|
-
)}
|
|
495
|
-
{showPredefined && (
|
|
496
|
-
<div className="absolute right-0 bottom-8 left-0 flex flex-col gap-1 overflow-y-auto bg-white p-3 pb-1 text-sm">
|
|
497
|
-
{activeProfile &&
|
|
498
|
-
activeProfile.prompts.map((p, index) => (
|
|
499
|
-
<div
|
|
500
|
-
key={index}
|
|
501
|
-
className="mb-1 cursor-pointer rounded-lg border border-gray-200 p-1.5 text-xs text-gray-700"
|
|
502
|
-
onClick={() => {
|
|
503
|
-
setPrompt(p.prompt);
|
|
504
|
-
setShowPredefined(false);
|
|
505
|
-
}}
|
|
506
|
-
>
|
|
507
|
-
{p.title}
|
|
508
|
-
</div>
|
|
509
|
-
))}
|
|
510
|
-
</div>
|
|
511
|
-
)}
|
|
512
|
-
</div>
|
|
513
|
-
toolbar=<div className="flex items-stretch gap-1">
|
|
514
|
-
<div className="relative" ref={settingsRef}>
|
|
515
|
-
<SimpleIconButton
|
|
516
|
-
icon={<Settings size={16} strokeWidth={1} />}
|
|
517
|
-
label="Settings"
|
|
518
|
-
onClick={() => setShowSettings(!showSettings)}
|
|
519
|
-
/>
|
|
520
|
-
{showSettings && (
|
|
521
|
-
<div className="absolute top-8 right-0 z-50 flex flex-col gap-2 rounded-lg border border-gray-200 bg-white p-3 shadow-lg">
|
|
522
|
-
<div className="flex flex-col gap-1">
|
|
523
|
-
<label className="text-xs font-medium text-gray-700">
|
|
524
|
-
Profile
|
|
525
|
-
</label>
|
|
526
|
-
<Dropdown
|
|
527
|
-
className="text-sm"
|
|
528
|
-
value={activeProfile}
|
|
529
|
-
onChange={(e) => setActiveProfile(e.value)}
|
|
530
|
-
optionLabel="name"
|
|
531
|
-
options={profiles}
|
|
532
|
-
/>
|
|
533
|
-
</div>
|
|
534
|
-
{activeProfile && (
|
|
535
|
-
<div className="flex flex-col gap-1">
|
|
536
|
-
<label className="text-xs font-medium text-gray-700">
|
|
537
|
-
Model
|
|
538
|
-
</label>
|
|
539
|
-
<Dropdown
|
|
540
|
-
className="text-sm"
|
|
541
|
-
value={model}
|
|
542
|
-
onChange={(e) => setModel(e.value)}
|
|
543
|
-
options={activeProfile.models}
|
|
544
|
-
/>
|
|
545
|
-
</div>
|
|
546
|
-
)}
|
|
547
|
-
</div>
|
|
548
|
-
)}
|
|
549
|
-
</div>
|
|
550
|
-
{closeButton}
|
|
551
|
-
</div>
|
|
552
|
-
commandHandler={(v, callback) => {
|
|
553
|
-
commandHandler(v, callback);
|
|
554
|
-
}}
|
|
555
|
-
/>
|
|
556
|
-
</div>
|
|
557
|
-
{activeProfile?.errorMessage && (
|
|
558
|
-
<div className="absolute inset-0 grid items-center justify-center p-2 text-sm text-red-500">
|
|
559
|
-
{activeProfile?.errorMessage}
|
|
560
|
-
</div>
|
|
561
|
-
)}
|
|
562
|
-
{!model && (
|
|
563
|
-
<div className="absolute inset-0 grid items-center justify-center text-sm text-gray-400">
|
|
564
|
-
{!activeProfile ? "No profile selected" : "No model selected"}
|
|
565
|
-
</div>
|
|
566
|
-
)}
|
|
567
|
-
</div>
|
|
568
|
-
</div>
|
|
569
|
-
);
|
|
570
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { AiTerminal } from "../ai/AiTerminal";
|
|
2
|
-
import { createDesignerAiContext } from "./aiContext";
|
|
3
|
-
|
|
4
|
-
export function ComponentDesignerAiTerminal() {
|
|
5
|
-
return (
|
|
6
|
-
<AiTerminal
|
|
7
|
-
createAiContext={createDesignerAiContext}
|
|
8
|
-
defaultProfile="Component Designer"
|
|
9
|
-
/>
|
|
10
|
-
);
|
|
11
|
-
}
|