@alpaca-editor/core 1.0.4013 → 1.0.4015
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/popover.js +6 -3
- package/dist/components/ui/popover.js.map +1 -1
- package/dist/editor/Terminal.d.ts +6 -0
- package/dist/editor/Terminal.js +10 -4
- package/dist/editor/Terminal.js.map +1 -1
- package/dist/editor/ai/Agents.js +133 -13
- package/dist/editor/ai/Agents.js.map +1 -1
- package/dist/editor/ai/AiTerminal.d.ts +2 -1
- package/dist/editor/ai/AiTerminal.js +86 -139
- package/dist/editor/ai/AiTerminal.js.map +1 -1
- package/dist/editor/media-selector/AiImageSearch.js +2 -1
- package/dist/editor/media-selector/AiImageSearch.js.map +1 -1
- package/dist/editor/media-selector/AiImageSearchPrompt.js +2 -1
- package/dist/editor/media-selector/AiImageSearchPrompt.js.map +1 -1
- package/dist/editor/page-editor-chrome/useInlineAICompletion.js +4 -2
- package/dist/editor/page-editor-chrome/useInlineAICompletion.js.map +1 -1
- package/dist/editor/services/agentService.d.ts +59 -0
- package/dist/editor/services/agentService.js +26 -0
- package/dist/editor/services/agentService.js.map +1 -0
- package/dist/editor/services/aiService.d.ts +22 -4
- package/dist/editor/services/aiService.js +131 -20
- package/dist/editor/services/aiService.js.map +1 -1
- package/dist/editor/services/contextService.js +6 -4
- package/dist/editor/services/contextService.js.map +1 -1
- package/dist/editor/sidebar/SidebarView.js +2 -5
- package/dist/editor/sidebar/SidebarView.js.map +1 -1
- package/dist/editor/sidebar/ViewSelector.js +1 -1
- package/dist/editor/sidebar/ViewSelector.js.map +1 -1
- package/dist/editor/ui/SimpleIconButton.d.ts +2 -2
- package/dist/editor/ui/SimpleIconButton.js +5 -3
- package/dist/editor/ui/SimpleIconButton.js.map +1 -1
- package/dist/editor/utils/jsonCleaner.d.ts +8 -0
- package/dist/editor/utils/jsonCleaner.js +76 -0
- package/dist/editor/utils/jsonCleaner.js.map +1 -0
- package/dist/editor/views/CompareView.js +2 -2
- package/dist/editor/views/CompareView.js.map +1 -1
- package/dist/page-wizard/steps/ContentStep.js +7 -2
- package/dist/page-wizard/steps/ContentStep.js.map +1 -1
- package/dist/page-wizard/steps/FindItemsStep.js +4 -1
- package/dist/page-wizard/steps/FindItemsStep.js.map +1 -1
- package/dist/page-wizard/steps/ImagesStep.js +13 -7
- package/dist/page-wizard/steps/ImagesStep.js.map +1 -1
- package/dist/page-wizard/steps/LayoutStep.d.ts +1 -1
- package/dist/page-wizard/steps/LayoutStep.js +22 -20
- package/dist/page-wizard/steps/LayoutStep.js.map +1 -1
- package/dist/page-wizard/steps/MetaDataStep.js +8 -15
- package/dist/page-wizard/steps/MetaDataStep.js.map +1 -1
- package/dist/page-wizard/steps/SelectStep.js +9 -4
- package/dist/page-wizard/steps/SelectStep.js.map +1 -1
- package/dist/page-wizard/steps/StructureStep.js +3 -1
- package/dist/page-wizard/steps/StructureStep.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/styles.css +10 -11
- package/package.json +1 -1
- package/src/components/ui/popover.tsx +6 -3
- package/src/editor/Terminal.tsx +12 -3
- package/src/editor/ai/Agents.tsx +212 -16
- package/src/editor/ai/AiTerminal.tsx +113 -173
- package/src/editor/ai/GhostWriter.tsx_ +3 -3
- package/src/editor/media-selector/AiImageSearch.tsx +2 -2
- package/src/editor/media-selector/AiImageSearchPrompt.tsx +2 -2
- package/src/editor/page-editor-chrome/useInlineAICompletion.tsx +5 -5
- package/src/editor/services/agentService.ts +83 -0
- package/src/editor/services/aiService.ts +176 -33
- package/src/editor/services/contextService.ts +5 -6
- package/src/editor/sidebar/SidebarView.tsx +10 -6
- package/src/editor/sidebar/ViewSelector.tsx +2 -2
- package/src/editor/ui/SimpleIconButton.tsx +20 -14
- package/src/editor/utils/jsonCleaner.ts +92 -0
- package/src/editor/views/CompareView.tsx +2 -2
- package/src/page-wizard/steps/ContentStep.tsx +10 -9
- package/src/page-wizard/steps/FindItemsStep.tsx +7 -5
- package/src/page-wizard/steps/ImagesStep.tsx +16 -11
- package/src/page-wizard/steps/LayoutStep.tsx +24 -28
- package/src/page-wizard/steps/MetaDataStep.tsx +11 -21
- package/src/page-wizard/steps/SelectStep.tsx +11 -8
- package/src/page-wizard/steps/StructureStep.tsx +4 -5
- package/src/revision.ts +2 -2
|
@@ -8,10 +8,13 @@ import { Terminal } from "../Terminal";
|
|
|
8
8
|
import { useEditContext } from "../client/editContext";
|
|
9
9
|
import { Dropdown } from "primereact/dropdown";
|
|
10
10
|
|
|
11
|
-
import Cookies from "universal-cookie";
|
|
12
11
|
import { WizardIcon } from "../ui/Icons";
|
|
13
12
|
import { AiResponseMessage } from "./AiResponseMessage";
|
|
14
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
AiProfile,
|
|
15
|
+
loadAiProfiles,
|
|
16
|
+
executePrompt,
|
|
17
|
+
} from "../services/aiService";
|
|
15
18
|
import { EditOperation } from "../../types";
|
|
16
19
|
import { SimpleIconButton } from "../ui/SimpleIconButton";
|
|
17
20
|
import { Settings } from "lucide-react";
|
|
@@ -35,7 +38,7 @@ export type ToolCall = {
|
|
|
35
38
|
};
|
|
36
39
|
|
|
37
40
|
export type Message = {
|
|
38
|
-
id: number
|
|
41
|
+
id: string; // Changed from number to string for UUID support
|
|
39
42
|
content: string;
|
|
40
43
|
formattedContent?: string;
|
|
41
44
|
name: string;
|
|
@@ -53,6 +56,7 @@ export type AiContext = {
|
|
|
53
56
|
export type AiTerminalOptions = {
|
|
54
57
|
initialPrompt?: string;
|
|
55
58
|
hiddenSystemPrompt?: string;
|
|
59
|
+
initialMessages?: Message[];
|
|
56
60
|
};
|
|
57
61
|
|
|
58
62
|
export function AiTerminal({
|
|
@@ -71,7 +75,7 @@ export function AiTerminal({
|
|
|
71
75
|
|
|
72
76
|
if (!editContext) return null;
|
|
73
77
|
|
|
74
|
-
const [messages, setMessages] = useState<Message[]>([]);
|
|
78
|
+
const [messages, setMessages] = useState<Message[]>(options?.initialMessages || []);
|
|
75
79
|
const [response, setResponse] = useState<Response>();
|
|
76
80
|
const [model, setModel] = useState<string>();
|
|
77
81
|
const [prompt, setPrompt] = useState("");
|
|
@@ -81,7 +85,7 @@ export function AiTerminal({
|
|
|
81
85
|
const [agentId] = useState<string>(() => crypto.randomUUID());
|
|
82
86
|
const selection = editContext.selection;
|
|
83
87
|
const terminalRef = useRef<{ submit: () => void }>(null);
|
|
84
|
-
const [responseMessages, setResponseMessages] = useState<Message[]>([]);
|
|
88
|
+
const [responseMessages, setResponseMessages] = useState<Message[]>(options?.initialMessages || []);
|
|
85
89
|
const [showSettings, setShowSettings] = useState(false);
|
|
86
90
|
const settingsRef = useRef<HTMLDivElement>(null);
|
|
87
91
|
|
|
@@ -120,6 +124,91 @@ export function AiTerminal({
|
|
|
120
124
|
messagesRef.current = responseMessages;
|
|
121
125
|
}, [responseMessages]);
|
|
122
126
|
|
|
127
|
+
// State for initial messages to pass to Terminal
|
|
128
|
+
type TerminalMessage = {text: React.ReactNode, type: "command" | "response"};
|
|
129
|
+
const [initialTerminalMessages, setInitialTerminalMessages] = useState<TerminalMessage[] | undefined>(undefined);
|
|
130
|
+
|
|
131
|
+
// Effect to set up initial messages for display
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
if (options?.initialMessages && options.initialMessages.length > 0) {
|
|
134
|
+
console.log("AiTerminal: Loading initial messages", options.initialMessages);
|
|
135
|
+
|
|
136
|
+
// Format the initial messages for display
|
|
137
|
+
const formattedMessages = options.initialMessages.map((message) => {
|
|
138
|
+
const formattedContent = message.content
|
|
139
|
+
?.trim()
|
|
140
|
+
?.replaceAll("\n", "<br>")
|
|
141
|
+
?.replace(/\*\*(.*?)\*\*/g, "<b>$1</b>") || "";
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
...message,
|
|
145
|
+
content: message.content || "",
|
|
146
|
+
formattedContent: formattedContent,
|
|
147
|
+
tool_calls: message.tool_calls || [],
|
|
148
|
+
};
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
console.log("AiTerminal: Formatted messages", formattedMessages);
|
|
152
|
+
|
|
153
|
+
// Update the internal message states
|
|
154
|
+
setMessages(formattedMessages);
|
|
155
|
+
setResponseMessages(formattedMessages);
|
|
156
|
+
|
|
157
|
+
// Create a response object for internal state
|
|
158
|
+
const initialResponse: Response = {
|
|
159
|
+
messages: formattedMessages,
|
|
160
|
+
editOperations: [],
|
|
161
|
+
numInputTokens: 0,
|
|
162
|
+
numOutputTokens: 0,
|
|
163
|
+
numCachedTokens: 0,
|
|
164
|
+
state: "loaded"
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
console.log("AiTerminal: Setting response", initialResponse);
|
|
168
|
+
setResponse(initialResponse);
|
|
169
|
+
|
|
170
|
+
// Create individual Terminal messages for each conversation message
|
|
171
|
+
const terminalMessages: TerminalMessage[] = [];
|
|
172
|
+
|
|
173
|
+
formattedMessages.forEach((message) => {
|
|
174
|
+
if (message.role === "user") {
|
|
175
|
+
// User messages appear as commands
|
|
176
|
+
terminalMessages.push({
|
|
177
|
+
type: "command",
|
|
178
|
+
text: message.content
|
|
179
|
+
});
|
|
180
|
+
} else if (message.role === "assistant") {
|
|
181
|
+
// Assistant messages appear as responses
|
|
182
|
+
terminalMessages.push({
|
|
183
|
+
type: "response",
|
|
184
|
+
text: (
|
|
185
|
+
<div
|
|
186
|
+
dangerouslySetInnerHTML={{
|
|
187
|
+
__html: message.formattedContent || message.content || "",
|
|
188
|
+
}}
|
|
189
|
+
/>
|
|
190
|
+
)
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
// Add tool calls if present
|
|
194
|
+
if (message.tool_calls && message.tool_calls.length > 0) {
|
|
195
|
+
message.tool_calls.forEach((toolCall) => {
|
|
196
|
+
terminalMessages.push({
|
|
197
|
+
type: "response",
|
|
198
|
+
text: (
|
|
199
|
+
<div className="text-xs text-gray-400">
|
|
200
|
+
🔧 {toolCall.displayName}
|
|
201
|
+
</div>
|
|
202
|
+
)
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
setInitialTerminalMessages(terminalMessages);
|
|
209
|
+
}
|
|
210
|
+
}, [options?.initialMessages]);
|
|
211
|
+
|
|
123
212
|
// Handle click outside for settings popover
|
|
124
213
|
useEffect(() => {
|
|
125
214
|
function handleClickOutside(event: MouseEvent) {
|
|
@@ -150,13 +239,13 @@ export function AiTerminal({
|
|
|
150
239
|
if (updatedMessages && Array.isArray(updatedMessages)) {
|
|
151
240
|
const formattedMessages = updatedMessages.map((message) => {
|
|
152
241
|
const formattedContent = message.content
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
?.replace(/\*\*(.*?)\*\*/g, "<b>$1</b>");
|
|
242
|
+
?.trim()
|
|
243
|
+
?.replaceAll("\n", "<br>")
|
|
244
|
+
?.replace(/\*\*(.*?)\*\*/g, "<b>$1</b>") || "";
|
|
156
245
|
|
|
157
246
|
return {
|
|
158
247
|
...message,
|
|
159
|
-
content: message.content,
|
|
248
|
+
content: message.content || "",
|
|
160
249
|
formattedContent: formattedContent,
|
|
161
250
|
tool_calls: message.tool_calls || [],
|
|
162
251
|
};
|
|
@@ -192,7 +281,7 @@ export function AiTerminal({
|
|
|
192
281
|
callback: (text: React.ReactNode, finished: boolean) => void,
|
|
193
282
|
) {
|
|
194
283
|
const userMessage = {
|
|
195
|
-
id:
|
|
284
|
+
id: crypto.randomUUID(), // Add unique id
|
|
196
285
|
content: text,
|
|
197
286
|
role: "user",
|
|
198
287
|
name: "user",
|
|
@@ -214,7 +303,7 @@ export function AiTerminal({
|
|
|
214
303
|
role: "system",
|
|
215
304
|
name: "system",
|
|
216
305
|
content: options.hiddenSystemPrompt,
|
|
217
|
-
id:
|
|
306
|
+
id: crypto.randomUUID(), // Use UUID instead of hardcoded 0
|
|
218
307
|
toolCalls: [],
|
|
219
308
|
},
|
|
220
309
|
]
|
|
@@ -223,72 +312,21 @@ export function AiTerminal({
|
|
|
223
312
|
];
|
|
224
313
|
|
|
225
314
|
const response = await executePrompt(
|
|
226
|
-
activeProfile.id,
|
|
227
315
|
messages,
|
|
228
|
-
selection,
|
|
229
|
-
editContext!.sessionId,
|
|
230
|
-
model,
|
|
231
|
-
selectedText,
|
|
232
316
|
context,
|
|
233
|
-
|
|
317
|
+
{
|
|
318
|
+
profileId: activeProfile.id,
|
|
319
|
+
selection,
|
|
320
|
+
selectedText,
|
|
321
|
+
model,
|
|
322
|
+
sessionId: editContext!.sessionId,
|
|
323
|
+
agentId,
|
|
324
|
+
addSelectedComponents: true,
|
|
325
|
+
},
|
|
326
|
+
undefined,
|
|
234
327
|
(response: any) => {
|
|
235
328
|
setResponse(response);
|
|
236
329
|
handleResponse(response, callback, false);
|
|
237
|
-
// if (response.editOperations.length) {
|
|
238
|
-
// if (!editContext) return;
|
|
239
|
-
|
|
240
|
-
// const newOps = response.editOperations.slice(lastOpIndex);
|
|
241
|
-
|
|
242
|
-
// if (newOps.length === 0) return;
|
|
243
|
-
|
|
244
|
-
// const isEditTextFieldOp = (op: EditOperation) => {
|
|
245
|
-
// if (op.type !== "edit-field") return false;
|
|
246
|
-
// const editFieldOp = op as EditFieldOperation;
|
|
247
|
-
// return (
|
|
248
|
-
// editFieldOp.fieldType &&
|
|
249
|
-
// editFieldOp.fieldType.indexOf("text") !== -1
|
|
250
|
-
// );
|
|
251
|
-
// };
|
|
252
|
-
|
|
253
|
-
// const isEditTextField = isEditTextFieldOp(newOps[newOps.length - 1]);
|
|
254
|
-
|
|
255
|
-
// if (isEditTextField) lastOpIndex = response.editOperations.length - 1;
|
|
256
|
-
// else lastOpIndex = response.editOperations.length;
|
|
257
|
-
|
|
258
|
-
// newOps.forEach((op: EditOperation) => {
|
|
259
|
-
// if (isEditTextFieldOp(op)) {
|
|
260
|
-
// const editFieldOp = op as EditFieldOperation;
|
|
261
|
-
|
|
262
|
-
// if (editFieldOp.itemId) {
|
|
263
|
-
// const fieldDescriptor = {
|
|
264
|
-
// item: {
|
|
265
|
-
// ...editFieldOp.mainItem,
|
|
266
|
-
// id: editFieldOp.itemId,
|
|
267
|
-
// },
|
|
268
|
-
// fieldId: editFieldOp.fieldId,
|
|
269
|
-
// };
|
|
270
|
-
// editContext.itemsRepository.updateFieldValue(
|
|
271
|
-
// fieldDescriptor,
|
|
272
|
-
// editFieldOp.user ?? { name: "unknown", ai: false },
|
|
273
|
-
// false,
|
|
274
|
-
// editFieldOp.value,
|
|
275
|
-
// );
|
|
276
|
-
|
|
277
|
-
// editContext.select([editFieldOp.itemId]);
|
|
278
|
-
// editContext.setScrollIntoView(editFieldOp.itemId);
|
|
279
|
-
|
|
280
|
-
// editContext?.setFocusedField(fieldDescriptor, false);
|
|
281
|
-
// }
|
|
282
|
-
// } else {
|
|
283
|
-
// const addOp = op as AddComponentOperation;
|
|
284
|
-
// if (op.type === "add-component" && addOp.componentId) {
|
|
285
|
-
// const newComponentId = addOp.componentId;
|
|
286
|
-
// editContext.select([newComponentId]);
|
|
287
|
-
// editContext.setScrollIntoView(newComponentId);
|
|
288
|
-
// }
|
|
289
|
-
// }
|
|
290
|
-
// });
|
|
291
|
-
// }
|
|
292
330
|
},
|
|
293
331
|
);
|
|
294
332
|
|
|
@@ -320,7 +358,7 @@ export function AiTerminal({
|
|
|
320
358
|
|
|
321
359
|
return (
|
|
322
360
|
<div
|
|
323
|
-
className="relative flex h-full flex-1 flex-col
|
|
361
|
+
className="relative flex h-full flex-1 flex-col"
|
|
324
362
|
data-testid="ai-terminal"
|
|
325
363
|
>
|
|
326
364
|
<div className="relative flex-1">
|
|
@@ -332,7 +370,9 @@ export function AiTerminal({
|
|
|
332
370
|
setMessages([]);
|
|
333
371
|
setResponseMessages([]);
|
|
334
372
|
setResponse(undefined);
|
|
373
|
+
setInitialTerminalMessages(undefined);
|
|
335
374
|
}}
|
|
375
|
+
initialMessages={initialTerminalMessages}
|
|
336
376
|
infobar={
|
|
337
377
|
response?.numInputTokens && (
|
|
338
378
|
<div
|
|
@@ -448,103 +488,3 @@ export function AiTerminal({
|
|
|
448
488
|
</div>
|
|
449
489
|
);
|
|
450
490
|
}
|
|
451
|
-
|
|
452
|
-
async function executePrompt(
|
|
453
|
-
profileId: string,
|
|
454
|
-
messages: Message[],
|
|
455
|
-
selection: string[],
|
|
456
|
-
session: string | null,
|
|
457
|
-
model: string | null,
|
|
458
|
-
selectedText: string | null,
|
|
459
|
-
context: AiContext,
|
|
460
|
-
agentId: string,
|
|
461
|
-
callback: (response: any) => void,
|
|
462
|
-
): Promise<Response | null> {
|
|
463
|
-
const response = await fetch(context.endpoint, {
|
|
464
|
-
method: "POST",
|
|
465
|
-
body: JSON.stringify({
|
|
466
|
-
...context.promptData,
|
|
467
|
-
profileId,
|
|
468
|
-
messages,
|
|
469
|
-
selection,
|
|
470
|
-
addSelectedComponents: true,
|
|
471
|
-
selectedText,
|
|
472
|
-
model,
|
|
473
|
-
sessionId: session,
|
|
474
|
-
agentId,
|
|
475
|
-
}),
|
|
476
|
-
credentials: "include",
|
|
477
|
-
headers: {
|
|
478
|
-
"Content-Type": "application/json",
|
|
479
|
-
Cookie: new Cookies().getAll(),
|
|
480
|
-
},
|
|
481
|
-
});
|
|
482
|
-
|
|
483
|
-
if (!response.ok) {
|
|
484
|
-
const text = await response.text();
|
|
485
|
-
return {
|
|
486
|
-
messages: [
|
|
487
|
-
{
|
|
488
|
-
content: "There was an error processing your request: " + text,
|
|
489
|
-
id: 0,
|
|
490
|
-
name: "assistant",
|
|
491
|
-
role: "assistant",
|
|
492
|
-
},
|
|
493
|
-
],
|
|
494
|
-
editOperations: [],
|
|
495
|
-
numInputTokens: 0,
|
|
496
|
-
numOutputTokens: 0,
|
|
497
|
-
numCachedTokens: 0,
|
|
498
|
-
state: "error",
|
|
499
|
-
};
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
if (!response?.body) return null;
|
|
503
|
-
|
|
504
|
-
const reader = response.body.getReader();
|
|
505
|
-
const decoder = new TextDecoder();
|
|
506
|
-
let buffer = "";
|
|
507
|
-
|
|
508
|
-
let result = null;
|
|
509
|
-
|
|
510
|
-
while (true) {
|
|
511
|
-
const { done, value } = await reader.read();
|
|
512
|
-
|
|
513
|
-
if (done) {
|
|
514
|
-
break;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
buffer += decoder.decode(value, { stream: true }); // 'stream: true' ensures that any incomplete multi-byte characters aren't malformed.
|
|
518
|
-
|
|
519
|
-
// Split the buffer by newline and keep the last partial line for the next iteration.
|
|
520
|
-
const lines = buffer.split("\n");
|
|
521
|
-
|
|
522
|
-
if (lines.length > 0) {
|
|
523
|
-
buffer = lines.pop() || ""; // Incomplete line (if any) is kept for the next iteration.
|
|
524
|
-
|
|
525
|
-
for (let line of lines) {
|
|
526
|
-
if (line.trim() === "") continue; // Skip empty lines if any.
|
|
527
|
-
|
|
528
|
-
try {
|
|
529
|
-
const jsonData = JSON.parse(line);
|
|
530
|
-
callback(jsonData);
|
|
531
|
-
result = jsonData;
|
|
532
|
-
} catch (e) {
|
|
533
|
-
console.error("Error parsing line:" + line, e);
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
// If there's any remaining content in the buffer after processing all chunks, try to process it.
|
|
540
|
-
if (buffer.trim() !== "") {
|
|
541
|
-
try {
|
|
542
|
-
const jsonData = JSON.parse(buffer);
|
|
543
|
-
result = jsonData;
|
|
544
|
-
} catch (e) {
|
|
545
|
-
console.error("Error parsing the final buffer content:", e);
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
return result;
|
|
550
|
-
}
|
|
@@ -267,16 +267,16 @@ export function GhostWriter() {
|
|
|
267
267
|
|
|
268
268
|
role: "user",
|
|
269
269
|
name: "user",
|
|
270
|
+
id: Date.now(),
|
|
270
271
|
},
|
|
271
272
|
],
|
|
272
|
-
editContext,
|
|
273
|
-
createEditorAiContext,
|
|
273
|
+
{ editContext, createAiContext: createEditorAiContext },
|
|
274
274
|
{
|
|
275
275
|
addAllContent: true,
|
|
276
276
|
profile: "ghostwriter",
|
|
277
|
+
model: "gpt-4.1",
|
|
277
278
|
},
|
|
278
279
|
undefined,
|
|
279
|
-
"gpt-4.1",
|
|
280
280
|
handleAiResponse,
|
|
281
281
|
);
|
|
282
282
|
|
|
@@ -61,10 +61,10 @@ export function AiImageSearch({
|
|
|
61
61
|
"Reply with search terms only!",
|
|
62
62
|
name: "user",
|
|
63
63
|
role: "user",
|
|
64
|
+
id: crypto.randomUUID(), // Use proper UUID instead of Date.now()
|
|
64
65
|
},
|
|
65
66
|
],
|
|
66
|
-
editContext,
|
|
67
|
-
createEditorAiContext,
|
|
67
|
+
{ editContext, createAiContext: createEditorAiContext },
|
|
68
68
|
{ allowedFunctions: ["get-content"], addContextContent: true },
|
|
69
69
|
{ signal: abortController.signal },
|
|
70
70
|
);
|
|
@@ -44,10 +44,10 @@ export function AiImageSearchPrompt({
|
|
|
44
44
|
"Reply with search terms only!",
|
|
45
45
|
name: "user",
|
|
46
46
|
role: "user",
|
|
47
|
+
id: crypto.randomUUID(), // Use proper UUID instead of Date.now()
|
|
47
48
|
},
|
|
48
49
|
],
|
|
49
|
-
editContext,
|
|
50
|
-
createEditorAiContext,
|
|
50
|
+
{ editContext, createAiContext: createEditorAiContext },
|
|
51
51
|
{ allowedFunctions: ["get-content"], addContextContent: true },
|
|
52
52
|
{ signal: abortController.signal },
|
|
53
53
|
);
|
|
@@ -350,11 +350,13 @@ ONLY provide the completion text (what comes after the user's text), never repea
|
|
|
350
350
|
name: "system",
|
|
351
351
|
role: "system",
|
|
352
352
|
content: systemPrompt,
|
|
353
|
+
id: crypto.randomUUID(), // Use proper UUID instead of Date.now()
|
|
353
354
|
},
|
|
354
355
|
{
|
|
355
356
|
name: "user",
|
|
356
357
|
role: "user",
|
|
357
358
|
content: `Complete this text. ONLY provide the completion (do not repeat my text): ${contentUpToCursor}`,
|
|
359
|
+
id: crypto.randomUUID(), // Use proper UUID instead of Date.now()
|
|
358
360
|
},
|
|
359
361
|
];
|
|
360
362
|
|
|
@@ -365,8 +367,7 @@ ONLY provide the completion text (what comes after the user's text), never repea
|
|
|
365
367
|
try {
|
|
366
368
|
const result = await executePrompt(
|
|
367
369
|
messages,
|
|
368
|
-
|
|
369
|
-
() => ({
|
|
370
|
+
{
|
|
370
371
|
endpoint: "/alpaca/editor/ai/complete",
|
|
371
372
|
promptData: {
|
|
372
373
|
itemid: itemId,
|
|
@@ -376,10 +377,9 @@ ONLY provide the completion text (what comes after the user's text), never repea
|
|
|
376
377
|
fieldname: fieldName,
|
|
377
378
|
content: contentUpToCursor,
|
|
378
379
|
},
|
|
379
|
-
}
|
|
380
|
-
{},
|
|
380
|
+
},
|
|
381
|
+
{ model: "gpt-4.1-nano" },
|
|
381
382
|
{ signal },
|
|
382
|
-
"gpt-4.1-nano",
|
|
383
383
|
);
|
|
384
384
|
|
|
385
385
|
return result;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { get } from "./serviceHelper";
|
|
2
|
+
|
|
3
|
+
export interface AgentChat {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
sessionId: string;
|
|
7
|
+
userId: string;
|
|
8
|
+
userDisplayName: string;
|
|
9
|
+
itemId: string;
|
|
10
|
+
itemPath: string;
|
|
11
|
+
language: string;
|
|
12
|
+
version: number;
|
|
13
|
+
profileId?: string;
|
|
14
|
+
profileName: string;
|
|
15
|
+
model: string;
|
|
16
|
+
status: "active" | "completed" | "error" | "abandoned";
|
|
17
|
+
createdDate: string;
|
|
18
|
+
updatedDate: string;
|
|
19
|
+
lastMessageDate?: string;
|
|
20
|
+
totalTokensUsed: number;
|
|
21
|
+
totalInputTokens: number;
|
|
22
|
+
totalOutputTokens: number;
|
|
23
|
+
messageCount: number;
|
|
24
|
+
metadata?: string;
|
|
25
|
+
messages?: AgentChatMessage[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface AgentChatMessage {
|
|
29
|
+
id: string;
|
|
30
|
+
agentId: string;
|
|
31
|
+
messageIndex: number;
|
|
32
|
+
role: string;
|
|
33
|
+
content: string;
|
|
34
|
+
name: string;
|
|
35
|
+
toolCallId?: string;
|
|
36
|
+
functionName?: string;
|
|
37
|
+
functionArguments?: string;
|
|
38
|
+
functionResult?: any;
|
|
39
|
+
functionError?: string;
|
|
40
|
+
isCompleted: boolean;
|
|
41
|
+
model?: string;
|
|
42
|
+
tokensUsed: number;
|
|
43
|
+
inputTokens: number;
|
|
44
|
+
outputTokens: number;
|
|
45
|
+
responseTimeMs?: number;
|
|
46
|
+
createdDate: string;
|
|
47
|
+
editOperations?: any[];
|
|
48
|
+
longRunningTaskIds?: string[];
|
|
49
|
+
metadata?: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Gets all agents for the current user
|
|
54
|
+
*/
|
|
55
|
+
export async function getAgents(
|
|
56
|
+
status?: "active" | "completed" | "error" | "abandoned",
|
|
57
|
+
limit = 100
|
|
58
|
+
) {
|
|
59
|
+
const url = `/alpaca/editor/ai/GetAgents${status ? `?status=${status}` : ""}${limit ? `${status ? "&" : "?"}limit=${limit}` : ""}`;
|
|
60
|
+
const response = await get<AgentChat[]>(url);
|
|
61
|
+
return response;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Gets a specific agent with its messages
|
|
66
|
+
*/
|
|
67
|
+
export async function getAgent(agentId: string) {
|
|
68
|
+
const url = `/alpaca/editor/ai/GetAgent?agentId=${agentId}`;
|
|
69
|
+
const response = await get<AgentChat>(url);
|
|
70
|
+
return response;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Gets chat history for the current user
|
|
75
|
+
*/
|
|
76
|
+
export async function getChatHistory(
|
|
77
|
+
status?: "active" | "completed" | "error" | "abandoned",
|
|
78
|
+
limit = 50
|
|
79
|
+
) {
|
|
80
|
+
const url = `/alpaca/editor/ai/GetChatHistory${status ? `?status=${status}` : ""}${limit ? `${status ? "&" : "?"}limit=${limit}` : ""}`;
|
|
81
|
+
const response = await get<AgentChat[]>(url);
|
|
82
|
+
return response;
|
|
83
|
+
}
|