@alpaca-editor/core 1.0.4018 → 1.0.4026
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/SimpleLanguageSelector.d.ts +2 -1
- package/dist/components/SimpleLanguageSelector.js +9 -2
- package/dist/components/SimpleLanguageSelector.js.map +1 -1
- package/dist/components/ui/input.js +1 -1
- package/dist/components/ui/input.js.map +1 -1
- package/dist/components/ui/tooltip.d.ts +3 -1
- package/dist/components/ui/tooltip.js +2 -2
- package/dist/components/ui/tooltip.js.map +1 -1
- package/dist/config/config.js +4 -0
- package/dist/config/config.js.map +1 -1
- package/dist/config/types.d.ts +2 -0
- package/dist/editor/ContentTree.js +1 -1
- package/dist/editor/ContentTree.js.map +1 -1
- package/dist/editor/ContextMenu.js +26 -0
- package/dist/editor/ContextMenu.js.map +1 -1
- package/dist/editor/FieldHistory.js +1 -1
- package/dist/editor/FieldHistory.js.map +1 -1
- package/dist/editor/FieldListField.js +2 -2
- package/dist/editor/FieldListField.js.map +1 -1
- package/dist/editor/Terminal.js +3 -1
- package/dist/editor/Terminal.js.map +1 -1
- package/dist/editor/ai/Agents.js +19 -10
- package/dist/editor/ai/Agents.js.map +1 -1
- package/dist/editor/ai/AiResponseMessage.js +63 -5
- package/dist/editor/ai/AiResponseMessage.js.map +1 -1
- package/dist/editor/ai/AiTerminal.js +7 -7
- package/dist/editor/ai/AiTerminal.js.map +1 -1
- package/dist/editor/ai/AiToolCall.js +3 -3
- package/dist/editor/ai/AiToolCall.js.map +1 -1
- package/dist/editor/client/EditorClient.js +5 -1
- package/dist/editor/client/EditorClient.js.map +1 -1
- package/dist/editor/client/editContext.d.ts +2 -0
- package/dist/editor/client/editContext.js.map +1 -1
- package/dist/editor/client/operations.d.ts +1 -0
- package/dist/editor/client/operations.js +7 -0
- package/dist/editor/client/operations.js.map +1 -1
- package/dist/editor/commands/componentCommands.js +1 -1
- package/dist/editor/commands/componentCommands.js.map +1 -1
- package/dist/editor/field-types/ImageFieldEditor.js +1 -1
- package/dist/editor/field-types/ImageFieldEditor.js.map +1 -1
- package/dist/editor/field-types/MultiLineText.js +1 -1
- package/dist/editor/field-types/MultiLineText.js.map +1 -1
- package/dist/editor/field-types/PictureFieldEditor.js +1 -1
- package/dist/editor/field-types/PictureFieldEditor.js.map +1 -1
- package/dist/editor/field-types/RawEditor.js +1 -1
- package/dist/editor/field-types/RawEditor.js.map +1 -1
- package/dist/editor/field-types/RichTextEditorComponent.js +16 -17
- package/dist/editor/field-types/RichTextEditorComponent.js.map +1 -1
- package/dist/editor/field-types/SingleLineText.js +1 -1
- package/dist/editor/field-types/SingleLineText.js.map +1 -1
- package/dist/editor/field-types/richtext/components/SimpleDropdown.d.ts +18 -0
- package/dist/editor/field-types/richtext/components/SimpleDropdown.js +71 -0
- package/dist/editor/field-types/richtext/components/SimpleDropdown.js.map +1 -0
- package/dist/editor/field-types/richtext/components/SimpleRichTextEditor.d.ts +5 -0
- package/dist/editor/field-types/richtext/components/SimpleRichTextEditor.js +359 -0
- package/dist/editor/field-types/richtext/components/SimpleRichTextEditor.js.map +1 -0
- package/dist/editor/field-types/richtext/components/SimpleToolbar.d.ts +16 -0
- package/dist/editor/field-types/richtext/components/SimpleToolbar.js +181 -0
- package/dist/editor/field-types/richtext/components/SimpleToolbar.js.map +1 -0
- package/dist/editor/field-types/richtext/components/SimpleToolbarButton.d.ts +9 -0
- package/dist/editor/field-types/richtext/components/SimpleToolbarButton.js +14 -0
- package/dist/editor/field-types/richtext/components/SimpleToolbarButton.js.map +1 -0
- package/dist/editor/field-types/richtext/contextMenuFactory.d.ts +4 -0
- package/dist/editor/field-types/richtext/contextMenuFactory.js +193 -0
- package/dist/editor/field-types/richtext/contextMenuFactory.js.map +1 -0
- package/dist/editor/field-types/richtext/index.d.ts +6 -5
- package/dist/editor/field-types/richtext/index.js +6 -5
- package/dist/editor/field-types/richtext/index.js.map +1 -1
- package/dist/editor/field-types/richtext/types.d.ts +16 -16
- package/dist/editor/field-types/richtext/types.js +84 -84
- package/dist/editor/field-types/richtext/types.js.map +1 -1
- package/dist/editor/page-editor-chrome/CommentHighlighting.js +1 -1
- package/dist/editor/page-editor-chrome/CommentHighlighting.js.map +1 -1
- package/dist/editor/page-editor-chrome/FrameMenu.js +5 -5
- package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +1 -1
- package/dist/editor/page-viewer/PageViewerFrame.js +3 -2
- package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
- package/dist/editor/services/agentService.d.ts +14 -4
- package/dist/editor/services/agentService.js.map +1 -1
- package/dist/editor/services/aiService.js +1 -0
- package/dist/editor/services/aiService.js.map +1 -1
- package/dist/page-wizard/PageWizard.d.ts +2 -0
- package/dist/page-wizard/PageWizard.js +6 -13
- package/dist/page-wizard/PageWizard.js.map +1 -1
- package/dist/page-wizard/WizardSteps.js +3 -1
- package/dist/page-wizard/WizardSteps.js.map +1 -1
- package/dist/page-wizard/service.d.ts +1 -0
- package/dist/page-wizard/service.js +7 -0
- package/dist/page-wizard/service.js.map +1 -1
- package/dist/page-wizard/steps/ContentStep.js +210 -33
- package/dist/page-wizard/steps/ContentStep.js.map +1 -1
- package/dist/page-wizard/steps/FindItemsStep.js +11 -3
- package/dist/page-wizard/steps/FindItemsStep.js.map +1 -1
- package/dist/page-wizard/steps/LayoutStep.js +1 -1
- package/dist/page-wizard/steps/LayoutStep.js.map +1 -1
- package/dist/page-wizard/steps/MetaDataStep.js +1 -1
- package/dist/page-wizard/steps/MetaDataStep.js.map +1 -1
- package/dist/page-wizard/steps/SchottSelectImagesStep.d.ts +2 -0
- package/dist/page-wizard/steps/SchottSelectImagesStep.js +55 -0
- package/dist/page-wizard/steps/SchottSelectImagesStep.js.map +1 -0
- package/dist/page-wizard/steps/StructureStep.js +20 -5
- package/dist/page-wizard/steps/StructureStep.js.map +1 -1
- package/dist/page-wizard/steps/TranslateStep.d.ts +2 -0
- package/dist/page-wizard/steps/TranslateStep.js +413 -0
- package/dist/page-wizard/steps/TranslateStep.js.map +1 -0
- package/dist/page-wizard/utils/dataAccessor.d.ts +7 -0
- package/dist/page-wizard/utils/dataAccessor.js +76 -0
- package/dist/page-wizard/utils/dataAccessor.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/splash-screen/NewPage.js +5 -4
- package/dist/splash-screen/NewPage.js.map +1 -1
- package/dist/splash-screen/OpenPage.js +2 -1
- package/dist/splash-screen/OpenPage.js.map +1 -1
- package/dist/splash-screen/RecentPages.js +3 -1
- package/dist/splash-screen/RecentPages.js.map +1 -1
- package/dist/styles.css +57 -0
- package/package.json +5 -4
- package/src/components/SimpleLanguageSelector.tsx +11 -1
- package/src/components/ui/input.tsx +1 -1
- package/src/components/ui/tooltip.tsx +3 -2
- package/src/config/config.tsx +4 -0
- package/src/config/types.ts +6 -0
- package/src/editor/ContentTree.tsx +1 -1
- package/src/editor/ContextMenu.tsx +39 -0
- package/src/editor/FieldHistory.tsx +1 -1
- package/src/editor/FieldListField.tsx +2 -6
- package/src/editor/Terminal.tsx +5 -1
- package/src/editor/ai/Agents.tsx +27 -16
- package/src/editor/ai/AiResponseMessage.tsx +138 -23
- package/src/editor/ai/AiTerminal.tsx +43 -29
- package/src/editor/ai/AiToolCall.tsx +14 -4
- package/src/editor/client/EditorClient.tsx +9 -1
- package/src/editor/client/editContext.ts +2 -0
- package/src/editor/client/operations.ts +9 -0
- package/src/editor/commands/componentCommands.tsx +1 -1
- package/src/editor/field-types/ImageFieldEditor.tsx +1 -0
- package/src/editor/field-types/MultiLineText.tsx +1 -0
- package/src/editor/field-types/PictureFieldEditor.tsx +1 -0
- package/src/editor/field-types/RawEditor.tsx +1 -0
- package/src/editor/field-types/RichTextEditorComponent.tsx +27 -25
- package/src/editor/field-types/SingleLineText.tsx +1 -0
- package/src/editor/field-types/richtext/components/SimpleDropdown.tsx +165 -0
- package/src/editor/field-types/richtext/components/SimpleRichTextEditor.css +261 -0
- package/src/editor/field-types/richtext/components/SimpleRichTextEditor.tsx +505 -0
- package/src/editor/field-types/richtext/components/SimpleToolbar.tsx +362 -0
- package/src/editor/field-types/richtext/components/SimpleToolbarButton.tsx +36 -0
- package/src/editor/field-types/richtext/contextMenuFactory.tsx +264 -0
- package/src/editor/field-types/richtext/index.ts +6 -5
- package/src/editor/field-types/richtext/types.ts +168 -148
- package/src/editor/page-editor-chrome/CommentHighlighting.tsx +1 -1
- package/src/editor/page-editor-chrome/FrameMenu.tsx +16 -11
- package/src/editor/page-editor-chrome/PlaceholderDropZone.tsx +1 -1
- package/src/editor/page-viewer/PageViewerFrame.tsx +4 -3
- package/src/editor/services/agentService.ts +16 -5
- package/src/editor/services/aiService.ts +2 -0
- package/src/page-wizard/PageWizard.tsx +10 -13
- package/src/page-wizard/WizardSteps.tsx +3 -1
- package/src/page-wizard/service.ts +11 -0
- package/src/page-wizard/steps/ContentStep.tsx +376 -43
- package/src/page-wizard/steps/FindItemsStep.tsx +23 -3
- package/src/page-wizard/steps/LayoutStep.tsx +1 -1
- package/src/page-wizard/steps/MetaDataStep.tsx +1 -1
- package/src/page-wizard/steps/SchottSelectImagesStep.tsx +141 -0
- package/src/page-wizard/steps/StructureStep.tsx +40 -5
- package/src/page-wizard/steps/TranslateStep.tsx +772 -0
- package/src/page-wizard/utils/dataAccessor.ts +85 -0
- package/src/revision.ts +2 -2
- package/src/splash-screen/NewPage.tsx +18 -3
- package/src/splash-screen/OpenPage.tsx +14 -1
- package/src/splash-screen/RecentPages.tsx +4 -2
- package/tsconfig.build.json +1 -0
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { useState } from "react";
|
|
1
|
+
import { useState, useEffect } from "react";
|
|
2
|
+
import JSONPretty from "react-json-pretty";
|
|
2
3
|
|
|
3
4
|
import { useEditContext } from "../client/editContext";
|
|
4
5
|
import { EditOperation } from "../../types";
|
|
5
6
|
import { Message } from "./AiTerminal";
|
|
6
7
|
import { AiToolCall } from "./AiToolCall";
|
|
8
|
+
import { Popover, PopoverContent, PopoverTrigger } from "../../components/ui/popover";
|
|
9
|
+
import { SimpleTabs, Tab } from "../ui/SimpleTabs";
|
|
7
10
|
|
|
8
11
|
export function AiResponseMessage({
|
|
9
12
|
messages,
|
|
@@ -22,6 +25,23 @@ export function AiResponseMessage({
|
|
|
22
25
|
undefined,
|
|
23
26
|
);
|
|
24
27
|
|
|
28
|
+
// Store tool calls to preserve them during streaming
|
|
29
|
+
const [preservedToolCalls, setPreservedToolCalls] = useState<{[messageIndex: number]: any[]}>({});
|
|
30
|
+
|
|
31
|
+
// Update preserved tool calls when messages change
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
const newPreservedToolCalls = {...preservedToolCalls};
|
|
34
|
+
|
|
35
|
+
messages.forEach((message, index) => {
|
|
36
|
+
if (message.tool_calls && message.tool_calls.length > 0) {
|
|
37
|
+
// Store non-empty tool calls
|
|
38
|
+
newPreservedToolCalls[index] = message.tool_calls;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
setPreservedToolCalls(newPreservedToolCalls);
|
|
43
|
+
}, [messages]);
|
|
44
|
+
|
|
25
45
|
const reversedEditOperations = [...editOperations].reverse();
|
|
26
46
|
|
|
27
47
|
const canReject =
|
|
@@ -32,32 +52,127 @@ export function AiResponseMessage({
|
|
|
32
52
|
!editContext.editHistory[index]?.canUndo,
|
|
33
53
|
) === undefined;
|
|
34
54
|
|
|
55
|
+
// Helper function to render JSON or text
|
|
56
|
+
const renderJsonOrText = (json: string) => {
|
|
57
|
+
try {
|
|
58
|
+
const parsed = JSON.parse(json);
|
|
59
|
+
return (
|
|
60
|
+
<div className="font-mono text-xs whitespace-pre-wrap">
|
|
61
|
+
<pre className="whitespace-pre-wrap break-words">
|
|
62
|
+
{JSON.stringify(parsed, null, 2)}
|
|
63
|
+
</pre>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
} catch (e) {
|
|
67
|
+
return <div className="whitespace-pre-wrap font-mono text-xs break-words">{json}</div>;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// Helper function to create tabs for a tool call
|
|
72
|
+
const createToolCallTabs = (toolCall: any, result: Message | undefined): Tab[] => {
|
|
73
|
+
const tabs: Tab[] = [
|
|
74
|
+
{
|
|
75
|
+
id: `input-${toolCall.id}`,
|
|
76
|
+
label: "Input",
|
|
77
|
+
content: (
|
|
78
|
+
<div className="max-h-96 overflow-auto p-2">
|
|
79
|
+
<div className="text-sm font-semibold text-gray-700 mb-1">Arguments:</div>
|
|
80
|
+
<div className="text-xs">{renderJsonOrText(toolCall.function.arguments)}</div>
|
|
81
|
+
</div>
|
|
82
|
+
),
|
|
83
|
+
},
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
if (result) {
|
|
87
|
+
tabs.push({
|
|
88
|
+
id: `output-${toolCall.id}`,
|
|
89
|
+
label: "Output",
|
|
90
|
+
content: (
|
|
91
|
+
<div className="max-h-96 overflow-auto p-2">
|
|
92
|
+
<div className="text-sm font-semibold text-gray-700 mb-1">Result:</div>
|
|
93
|
+
<div className="text-xs">{renderJsonOrText(result.content || "")}</div>
|
|
94
|
+
</div>
|
|
95
|
+
),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return tabs;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// Helper function to create tool call popover content
|
|
103
|
+
const ToolCallPopover = ({ toolCall, result }: { toolCall: any; result: Message | undefined }) => {
|
|
104
|
+
const [activeTab, setActiveTab] = useState(0);
|
|
105
|
+
const tabs = createToolCallTabs(toolCall, result);
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<div className="w-96">
|
|
109
|
+
<div className="mb-3 pb-2 border-b border-gray-200">
|
|
110
|
+
<div className="text-sm font-semibold text-gray-800">
|
|
111
|
+
{toolCall.displayName || toolCall.function.name}
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
<SimpleTabs
|
|
115
|
+
tabs={tabs}
|
|
116
|
+
activeTab={activeTab}
|
|
117
|
+
setActiveTab={setActiveTab}
|
|
118
|
+
className="border-b border-gray-200 mb-3"
|
|
119
|
+
tabClassName="text-xs"
|
|
120
|
+
/>
|
|
121
|
+
</div>
|
|
122
|
+
);
|
|
123
|
+
};
|
|
124
|
+
|
|
35
125
|
return (
|
|
36
126
|
<div>
|
|
37
127
|
{messages
|
|
38
128
|
.filter((x) => x.role !== "tool")
|
|
39
|
-
.map((message,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
<div
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
129
|
+
.map((message, filteredIndex) => {
|
|
130
|
+
// Find the original index of this message in the unfiltered array
|
|
131
|
+
const originalIndex = messages.findIndex(m => m.id === message.id);
|
|
132
|
+
// Use preserved tool calls if current message has empty tool calls
|
|
133
|
+
const toolCalls = (message.tool_calls && message.tool_calls.length > 0)
|
|
134
|
+
? message.tool_calls
|
|
135
|
+
: (preservedToolCalls[originalIndex] || []);
|
|
136
|
+
return (
|
|
137
|
+
<div key={filteredIndex}>
|
|
138
|
+
<div
|
|
139
|
+
dangerouslySetInnerHTML={{
|
|
140
|
+
__html: message.formattedContent || message.content || "",
|
|
141
|
+
}}
|
|
142
|
+
/>
|
|
143
|
+
{toolCalls.length > 0 && (
|
|
144
|
+
<div className="mt-2 flex flex-wrap gap-2">
|
|
145
|
+
{toolCalls.map((toolCall, toolIndex) => {
|
|
146
|
+
return (
|
|
147
|
+
<Popover key={toolIndex} enableIframeClickDetection={false}>
|
|
148
|
+
<PopoverTrigger asChild>
|
|
149
|
+
<div className="inline-flex cursor-pointer items-center gap-1 text-xs text-gray-500 hover:text-gray-700">
|
|
150
|
+
<i className="pi pi-wrench text-xs" />
|
|
151
|
+
<span>
|
|
152
|
+
{toolCall?.displayName || toolCall?.function?.name || 'tool call'}
|
|
153
|
+
</span>
|
|
154
|
+
</div>
|
|
155
|
+
</PopoverTrigger>
|
|
156
|
+
<PopoverContent
|
|
157
|
+
className="p-3"
|
|
158
|
+
align="start"
|
|
159
|
+
side="bottom"
|
|
160
|
+
sideOffset={8}
|
|
161
|
+
onMouseDown={(e) => e.stopPropagation()}
|
|
162
|
+
onClick={(e) => e.stopPropagation()}
|
|
163
|
+
>
|
|
164
|
+
<div className="max-h-[500px] overflow-hidden">
|
|
165
|
+
<ToolCallPopover toolCall={toolCall} result={toolCall.result} />
|
|
166
|
+
</div>
|
|
167
|
+
</PopoverContent>
|
|
168
|
+
</Popover>
|
|
169
|
+
);
|
|
170
|
+
})}
|
|
171
|
+
</div>
|
|
172
|
+
)}
|
|
173
|
+
</div>
|
|
174
|
+
);
|
|
175
|
+
})}
|
|
61
176
|
{/* <div
|
|
62
177
|
dangerouslySetInnerHTML={{
|
|
63
178
|
__html: responseText.replaceAll("\\n", "<br>"),
|
|
@@ -44,7 +44,7 @@ export type Message = {
|
|
|
44
44
|
name: string;
|
|
45
45
|
role: string;
|
|
46
46
|
tool_calls?: ToolCall[];
|
|
47
|
-
tool_call_id?: string;
|
|
47
|
+
tool_call_id?: string; // For tool response messages
|
|
48
48
|
};
|
|
49
49
|
|
|
50
50
|
export type AiContext = {
|
|
@@ -75,7 +75,9 @@ export function AiTerminal({
|
|
|
75
75
|
|
|
76
76
|
if (!editContext) return null;
|
|
77
77
|
|
|
78
|
-
const [messages, setMessages] = useState<Message[]>(
|
|
78
|
+
const [messages, setMessages] = useState<Message[]>(
|
|
79
|
+
options?.initialMessages || [],
|
|
80
|
+
);
|
|
79
81
|
const [response, setResponse] = useState<Response>();
|
|
80
82
|
const [model, setModel] = useState<string>();
|
|
81
83
|
const [prompt, setPrompt] = useState("");
|
|
@@ -85,7 +87,9 @@ export function AiTerminal({
|
|
|
85
87
|
const [agentId] = useState<string>(() => crypto.randomUUID());
|
|
86
88
|
const selection = editContext.selection;
|
|
87
89
|
const terminalRef = useRef<{ submit: () => void }>(null);
|
|
88
|
-
const [responseMessages, setResponseMessages] = useState<Message[]>(
|
|
90
|
+
const [responseMessages, setResponseMessages] = useState<Message[]>(
|
|
91
|
+
options?.initialMessages || [],
|
|
92
|
+
);
|
|
89
93
|
const [showSettings, setShowSettings] = useState(false);
|
|
90
94
|
const settingsRef = useRef<HTMLDivElement>(null);
|
|
91
95
|
|
|
@@ -125,20 +129,29 @@ export function AiTerminal({
|
|
|
125
129
|
}, [responseMessages]);
|
|
126
130
|
|
|
127
131
|
// State for initial messages to pass to Terminal
|
|
128
|
-
type TerminalMessage = {
|
|
129
|
-
|
|
132
|
+
type TerminalMessage = {
|
|
133
|
+
text: React.ReactNode;
|
|
134
|
+
type: "command" | "response";
|
|
135
|
+
};
|
|
136
|
+
const [initialTerminalMessages, setInitialTerminalMessages] = useState<
|
|
137
|
+
TerminalMessage[] | undefined
|
|
138
|
+
>(undefined);
|
|
130
139
|
|
|
131
|
-
// Effect to set up initial messages for display
|
|
140
|
+
// Effect to set up initial messages for display
|
|
132
141
|
useEffect(() => {
|
|
133
142
|
if (options?.initialMessages && options.initialMessages.length > 0) {
|
|
134
|
-
console.log(
|
|
135
|
-
|
|
143
|
+
console.log(
|
|
144
|
+
"AiTerminal: Loading initial messages",
|
|
145
|
+
options.initialMessages,
|
|
146
|
+
);
|
|
147
|
+
|
|
136
148
|
// Format the initial messages for display
|
|
137
149
|
const formattedMessages = options.initialMessages.map((message) => {
|
|
138
|
-
const formattedContent =
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
150
|
+
const formattedContent =
|
|
151
|
+
message.content
|
|
152
|
+
?.trim()
|
|
153
|
+
?.replaceAll("\n", "<br>")
|
|
154
|
+
?.replace(/\*\*(.*?)\*\*/g, "<b>$1</b>") || "";
|
|
142
155
|
|
|
143
156
|
return {
|
|
144
157
|
...message,
|
|
@@ -153,7 +166,7 @@ export function AiTerminal({
|
|
|
153
166
|
// Update the internal message states
|
|
154
167
|
setMessages(formattedMessages);
|
|
155
168
|
setResponseMessages(formattedMessages);
|
|
156
|
-
|
|
169
|
+
|
|
157
170
|
// Create a response object for internal state
|
|
158
171
|
const initialResponse: Response = {
|
|
159
172
|
messages: formattedMessages,
|
|
@@ -161,21 +174,21 @@ export function AiTerminal({
|
|
|
161
174
|
numInputTokens: 0,
|
|
162
175
|
numOutputTokens: 0,
|
|
163
176
|
numCachedTokens: 0,
|
|
164
|
-
state: "loaded"
|
|
177
|
+
state: "loaded",
|
|
165
178
|
};
|
|
166
|
-
|
|
179
|
+
|
|
167
180
|
console.log("AiTerminal: Setting response", initialResponse);
|
|
168
181
|
setResponse(initialResponse);
|
|
169
|
-
|
|
182
|
+
|
|
170
183
|
// Create individual Terminal messages for each conversation message
|
|
171
184
|
const terminalMessages: TerminalMessage[] = [];
|
|
172
|
-
|
|
185
|
+
|
|
173
186
|
formattedMessages.forEach((message) => {
|
|
174
187
|
if (message.role === "user") {
|
|
175
188
|
// User messages appear as commands
|
|
176
189
|
terminalMessages.push({
|
|
177
190
|
type: "command",
|
|
178
|
-
text: message.content
|
|
191
|
+
text: message.content,
|
|
179
192
|
});
|
|
180
193
|
} else if (message.role === "assistant") {
|
|
181
194
|
// Assistant messages appear as responses
|
|
@@ -187,7 +200,7 @@ export function AiTerminal({
|
|
|
187
200
|
__html: message.formattedContent || message.content || "",
|
|
188
201
|
}}
|
|
189
202
|
/>
|
|
190
|
-
)
|
|
203
|
+
),
|
|
191
204
|
});
|
|
192
205
|
}
|
|
193
206
|
// Add tool calls if present
|
|
@@ -196,15 +209,15 @@ export function AiTerminal({
|
|
|
196
209
|
terminalMessages.push({
|
|
197
210
|
type: "response",
|
|
198
211
|
text: (
|
|
199
|
-
<div className="text-xs text-gray-
|
|
212
|
+
<div className="text-xs text-gray-1">
|
|
200
213
|
🔧 {toolCall.displayName}
|
|
201
214
|
</div>
|
|
202
|
-
)
|
|
203
|
-
})
|
|
215
|
+
),
|
|
216
|
+
})
|
|
204
217
|
});
|
|
205
218
|
}
|
|
206
219
|
});
|
|
207
|
-
|
|
220
|
+
|
|
208
221
|
setInitialTerminalMessages(terminalMessages);
|
|
209
222
|
}
|
|
210
223
|
}, [options?.initialMessages]);
|
|
@@ -238,10 +251,11 @@ export function AiTerminal({
|
|
|
238
251
|
// Replace the conversation history with the authoritative response from AI
|
|
239
252
|
if (updatedMessages && Array.isArray(updatedMessages)) {
|
|
240
253
|
const formattedMessages = updatedMessages.map((message) => {
|
|
241
|
-
const formattedContent =
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
254
|
+
const formattedContent =
|
|
255
|
+
message.content
|
|
256
|
+
?.trim()
|
|
257
|
+
?.replaceAll("\n", "<br>")
|
|
258
|
+
?.replace(/\*\*(.*?)\*\*/g, "<b>$1</b>") || "";
|
|
245
259
|
|
|
246
260
|
return {
|
|
247
261
|
...message,
|
|
@@ -374,7 +388,7 @@ export function AiTerminal({
|
|
|
374
388
|
}}
|
|
375
389
|
initialMessages={initialTerminalMessages}
|
|
376
390
|
infobar={
|
|
377
|
-
response?.numInputTokens && (
|
|
391
|
+
response?.numInputTokens && response?.numInputTokens > 0 ? (
|
|
378
392
|
<div
|
|
379
393
|
className="text-right text-gray-400"
|
|
380
394
|
style={{ fontSize: "10px" }}
|
|
@@ -386,7 +400,7 @@ export function AiTerminal({
|
|
|
386
400
|
: ""}
|
|
387
401
|
{response?.state}
|
|
388
402
|
</div>
|
|
389
|
-
)
|
|
403
|
+
) : null
|
|
390
404
|
}
|
|
391
405
|
prompt={prompt}
|
|
392
406
|
setPrompt={setPrompt}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useEffect, useState } from "react";
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import JSONPretty from "react-json-pretty";
|
|
4
|
+
|
|
4
5
|
import { Message, ToolCall } from "./AiTerminal";
|
|
5
6
|
import { ProgressSpinner } from "primereact/progressspinner";
|
|
6
7
|
export function AiToolCall({
|
|
@@ -34,12 +35,21 @@ export function AiToolCall({
|
|
|
34
35
|
{!result && (
|
|
35
36
|
<ProgressSpinner style={{ width: "1rem", height: "1rem" }} />
|
|
36
37
|
)}
|
|
37
|
-
{toolCall.displayName}
|
|
38
|
+
{toolCall.displayName || toolCall.function.name}
|
|
38
39
|
</div>
|
|
39
40
|
</div>
|
|
40
41
|
{expanded && (
|
|
41
42
|
<div className="ml-4">
|
|
42
|
-
<div>
|
|
43
|
+
<div className="mb-2">
|
|
44
|
+
<div className="font-semibold text-gray-600">Arguments:</div>
|
|
45
|
+
<div className="ml-2">{renderJsonOrText(toolCall.function.arguments)}</div>
|
|
46
|
+
</div>
|
|
47
|
+
{result && (
|
|
48
|
+
<div className="mb-2">
|
|
49
|
+
<div className="font-semibold text-gray-600">Result:</div>
|
|
50
|
+
<div className="ml-2">{renderJsonOrText(result.content || "")}</div>
|
|
51
|
+
</div>
|
|
52
|
+
)}
|
|
43
53
|
{error && (
|
|
44
54
|
<div className="ml-4 text-red-500">
|
|
45
55
|
<div className="italic">Error:</div>
|
|
@@ -54,7 +64,7 @@ export function AiToolCall({
|
|
|
54
64
|
|
|
55
65
|
function renderJsonOrText(json: string) {
|
|
56
66
|
try {
|
|
57
|
-
return <
|
|
67
|
+
return <JSONPretty data={JSON.parse(json)} />;
|
|
58
68
|
} catch (e) {
|
|
59
69
|
return <div>{json}</div>;
|
|
60
70
|
}
|
|
@@ -248,6 +248,9 @@ export function EditorClient({
|
|
|
248
248
|
configuration.editor.views[0]?.name ??
|
|
249
249
|
"splash-screen",
|
|
250
250
|
);
|
|
251
|
+
const [previousViewName, setPreviousViewName] = useState<string | undefined>(
|
|
252
|
+
undefined,
|
|
253
|
+
);
|
|
251
254
|
|
|
252
255
|
const [compareMode, setCompareMode] = useState(false);
|
|
253
256
|
const [compareTo, setCompareTo] = useState<ItemDescriptor>();
|
|
@@ -368,7 +371,7 @@ export function EditorClient({
|
|
|
368
371
|
|
|
369
372
|
useEffect(() => {
|
|
370
373
|
if (mode === "suggestions") {
|
|
371
|
-
setViewName("
|
|
374
|
+
setViewName("comments");
|
|
372
375
|
}
|
|
373
376
|
}, [mode]);
|
|
374
377
|
|
|
@@ -1681,6 +1684,10 @@ export function EditorClient({
|
|
|
1681
1684
|
const result = await currentView.beforeClose(editContext);
|
|
1682
1685
|
if (!result) return;
|
|
1683
1686
|
}
|
|
1687
|
+
|
|
1688
|
+
// Track previous view name before switching
|
|
1689
|
+
setPreviousViewName(editContext.viewName);
|
|
1690
|
+
|
|
1684
1691
|
if (typeof document.startViewTransition === "function") {
|
|
1685
1692
|
document.startViewTransition(() => {
|
|
1686
1693
|
flushSync(() => {
|
|
@@ -2123,6 +2130,7 @@ export function EditorClient({
|
|
|
2123
2130
|
},
|
|
2124
2131
|
executeCommand,
|
|
2125
2132
|
viewName,
|
|
2133
|
+
previousViewName,
|
|
2126
2134
|
switchView,
|
|
2127
2135
|
compareMode,
|
|
2128
2136
|
setCompareMode,
|
|
@@ -134,6 +134,7 @@ export type EditContextType = {
|
|
|
134
134
|
name: string,
|
|
135
135
|
) => Promise<ItemDescriptor | undefined>;
|
|
136
136
|
createVersion: (item: ItemDescriptor) => Promise<void>;
|
|
137
|
+
onFieldBlur: () => void;
|
|
137
138
|
undoing: boolean;
|
|
138
139
|
};
|
|
139
140
|
comments: Comment[];
|
|
@@ -154,6 +155,7 @@ export type EditContextType = {
|
|
|
154
155
|
view?: EditorView;
|
|
155
156
|
|
|
156
157
|
viewName: string;
|
|
158
|
+
previousViewName?: string;
|
|
157
159
|
switchView: (
|
|
158
160
|
viewName: string,
|
|
159
161
|
options?: { skipConfirmation?: boolean },
|
|
@@ -684,6 +684,13 @@ export function getOperationsContext(
|
|
|
684
684
|
},
|
|
685
685
|
[state.itemsRepository],
|
|
686
686
|
);
|
|
687
|
+
|
|
688
|
+
const onFieldBlur = useCallback(() => {
|
|
689
|
+
// Reset the last operation to force creation of a new operation
|
|
690
|
+
// when the user returns to edit any field after losing focus
|
|
691
|
+
lastOp.current = undefined;
|
|
692
|
+
}, []);
|
|
693
|
+
|
|
687
694
|
const ops = useMemo(
|
|
688
695
|
() => ({
|
|
689
696
|
addComponent,
|
|
@@ -704,6 +711,7 @@ export function getOperationsContext(
|
|
|
704
711
|
moveItems,
|
|
705
712
|
copyItems,
|
|
706
713
|
duplicateItem,
|
|
714
|
+
onFieldBlur,
|
|
707
715
|
}),
|
|
708
716
|
[
|
|
709
717
|
addComponent,
|
|
@@ -726,6 +734,7 @@ export function getOperationsContext(
|
|
|
726
734
|
state.page,
|
|
727
735
|
copyItems,
|
|
728
736
|
duplicateItem,
|
|
737
|
+
onFieldBlur,
|
|
729
738
|
],
|
|
730
739
|
);
|
|
731
740
|
|
|
@@ -418,7 +418,7 @@ function getCreateCommentCommand(
|
|
|
418
418
|
visibilityScopes: ["contextMenu"],
|
|
419
419
|
execute: async (context: CommandContext<any>) => {
|
|
420
420
|
context.editContext.addComment();
|
|
421
|
-
context.editContext.switchView("
|
|
421
|
+
context.editContext.switchView("comments");
|
|
422
422
|
},
|
|
423
423
|
};
|
|
424
424
|
}
|
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
import { useThrottledCallback } from "use-debounce";
|
|
9
9
|
import { useEffect, useRef, useState, useMemo } from "react";
|
|
10
10
|
|
|
11
|
-
import { classNames } from "primereact/utils";
|
|
12
11
|
import { ReactSlate } from "./richtext";
|
|
12
|
+
import { SimpleRichTextEditor } from "./richtext/components/SimpleRichTextEditor";
|
|
13
13
|
import { RichTextField, RichTextEditorProfile } from "./richtext/types";
|
|
14
14
|
|
|
15
15
|
// Minimal fallback profile for when profile is null or undefined
|
|
@@ -17,24 +17,21 @@ const FALLBACK_PROFILE: RichTextEditorProfile = {
|
|
|
17
17
|
toolbar: {
|
|
18
18
|
groups: [
|
|
19
19
|
{
|
|
20
|
-
id:
|
|
21
|
-
label:
|
|
22
|
-
display:
|
|
20
|
+
id: "basic-formatting",
|
|
21
|
+
label: "Basic Formatting",
|
|
22
|
+
display: "buttons" as const,
|
|
23
23
|
showIconsOnly: true,
|
|
24
|
-
options: [
|
|
25
|
-
]
|
|
24
|
+
options: [],
|
|
26
25
|
},
|
|
27
26
|
{
|
|
28
|
-
id:
|
|
29
|
-
label:
|
|
30
|
-
display:
|
|
27
|
+
id: "basic-format",
|
|
28
|
+
label: "",
|
|
29
|
+
display: "dropdown" as const,
|
|
31
30
|
showIconsOnly: false,
|
|
32
|
-
options: [
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
]
|
|
37
|
-
}
|
|
31
|
+
options: [{ type: "block" as const, id: "no-tag" }],
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
},
|
|
38
35
|
};
|
|
39
36
|
|
|
40
37
|
export function RichTextEditorComponent({
|
|
@@ -49,11 +46,11 @@ export function RichTextEditorComponent({
|
|
|
49
46
|
updateFieldValue?: (value: string) => void;
|
|
50
47
|
}) {
|
|
51
48
|
const editContextRef = useEditContextRef();
|
|
52
|
-
const modifiedFieldsContext = useModifiedFieldsContext();
|
|
49
|
+
const modifiedFieldsContext = useModifiedFieldsContext();
|
|
53
50
|
const [focused, setFocused] = useState(false);
|
|
54
51
|
const [value, setValue] = useState(field.value as string);
|
|
55
52
|
const editorRef = useRef<HTMLDivElement>(null);
|
|
56
|
-
|
|
53
|
+
|
|
57
54
|
if (!editContextRef.current) return null;
|
|
58
55
|
|
|
59
56
|
const fieldItem = field.descriptor.item;
|
|
@@ -69,11 +66,12 @@ export function RichTextEditorComponent({
|
|
|
69
66
|
|
|
70
67
|
useEffect(() => {
|
|
71
68
|
// Only update if the editor is not currently being edited by the user
|
|
72
|
-
const isEditorActive =
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
69
|
+
const isEditorActive =
|
|
70
|
+
focused && editorRef.current?.contains(document.activeElement);
|
|
71
|
+
const newValue = field.isHistoric
|
|
72
|
+
? (field.value as string)
|
|
73
|
+
: (modifiedField?.value ?? (field.value as string));
|
|
74
|
+
|
|
77
75
|
if (!isEditorActive && newValue !== value) {
|
|
78
76
|
setValue(newValue);
|
|
79
77
|
}
|
|
@@ -95,7 +93,11 @@ export function RichTextEditorComponent({
|
|
|
95
93
|
|
|
96
94
|
const handleChange = (newValue: string) => {
|
|
97
95
|
// Skip empty content patterns for both paragraph and no-tag blocks
|
|
98
|
-
if (
|
|
96
|
+
if (
|
|
97
|
+
(newValue === "<p><br></p>" || newValue === "<br>" || newValue === "") &&
|
|
98
|
+
!field.value
|
|
99
|
+
)
|
|
100
|
+
return;
|
|
99
101
|
if (newValue !== value && !readOnly) {
|
|
100
102
|
setValue(newValue);
|
|
101
103
|
debouncedSetFieldvalue(newValue);
|
|
@@ -104,13 +106,13 @@ export function RichTextEditorComponent({
|
|
|
104
106
|
|
|
105
107
|
// Use the profile directly or fall back to the minimal profile
|
|
106
108
|
const editorProfile = profile ?? FALLBACK_PROFILE;
|
|
107
|
-
|
|
109
|
+
|
|
108
110
|
// const editorProfile = getDebugProfile(); // Debug profile with all options
|
|
109
111
|
// console.log(editorProfile);
|
|
110
112
|
|
|
111
113
|
return (
|
|
112
114
|
<div ref={editorRef}>
|
|
113
|
-
<
|
|
115
|
+
<SimpleRichTextEditor
|
|
114
116
|
value={value}
|
|
115
117
|
onChange={handleChange}
|
|
116
118
|
onFocus={() => setFocused(true)}
|