@alpaca-editor/core 1.0.4096 → 1.0.4098
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/button.d.ts +1 -1
- package/dist/components/ui/button.js +1 -0
- package/dist/components/ui/button.js.map +1 -1
- package/dist/components/ui/context-menu.d.ts +2 -2
- package/dist/components/ui/context-menu.js +16 -16
- package/dist/components/ui/context-menu.js.map +1 -1
- package/dist/editor/Editor.js +1 -1
- package/dist/editor/Editor.js.map +1 -1
- package/dist/editor/FieldActionsOverlay.js +40 -26
- package/dist/editor/FieldActionsOverlay.js.map +1 -1
- package/dist/editor/FieldListField.js +1 -1
- package/dist/editor/FieldListField.js.map +1 -1
- package/dist/editor/LinkEditorDialog.js +1 -1
- package/dist/editor/ai/AgentTerminal.js +56 -5
- package/dist/editor/ai/AgentTerminal.js.map +1 -1
- package/dist/editor/ai/Agents.js +23 -9
- package/dist/editor/ai/Agents.js.map +1 -1
- package/dist/editor/ai/ContextInfoBar.js +15 -5
- package/dist/editor/ai/ContextInfoBar.js.map +1 -1
- package/dist/editor/ai/ToolCallDisplay.js +2 -0
- package/dist/editor/ai/ToolCallDisplay.js.map +1 -1
- package/dist/editor/client/AboutDialog.js +7 -5
- package/dist/editor/client/AboutDialog.js.map +1 -1
- package/dist/editor/client/EditorShell.js +7 -2
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/client/editContext.d.ts +2 -2
- package/dist/editor/client/hooks/useSocketMessageHandler.js +5 -0
- package/dist/editor/client/hooks/useSocketMessageHandler.js.map +1 -1
- package/dist/editor/client/itemsRepository.js +1 -0
- package/dist/editor/client/itemsRepository.js.map +1 -1
- package/dist/editor/control-center/Setup.js +1 -1
- package/dist/editor/control-center/Setup.js.map +1 -1
- package/dist/editor/control-center/setup-steps/AiSetupStep/EmbeddingsModelSection.d.ts +2 -0
- package/dist/editor/control-center/setup-steps/AiSetupStep/EmbeddingsModelSection.js +195 -0
- package/dist/editor/control-center/setup-steps/AiSetupStep/EmbeddingsModelSection.js.map +1 -0
- package/dist/editor/control-center/setup-steps/AiSetupStep/index.d.ts +0 -1
- package/dist/editor/control-center/setup-steps/AiSetupStep/index.js +3 -506
- package/dist/editor/control-center/setup-steps/AiSetupStep/index.js.map +1 -1
- package/dist/editor/control-center/setup-steps/AiSetupStep/provider/ProviderSection.d.ts +1 -15
- package/dist/editor/control-center/setup-steps/AiSetupStep/provider/ProviderSection.js +226 -3
- package/dist/editor/control-center/setup-steps/AiSetupStep/provider/ProviderSection.js.map +1 -1
- package/dist/editor/control-center/setup-steps/AiSetupStep/required-containers/RequiredContainersList.d.ts +1 -1
- package/dist/editor/control-center/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.d.ts +1 -0
- package/dist/editor/control-center/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.js +94 -0
- package/dist/editor/control-center/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.js.map +1 -0
- package/dist/editor/control-center/setup-steps/AiSetupStep/tools/GenerateToolsSection.d.ts +1 -7
- package/dist/editor/control-center/setup-steps/AiSetupStep/tools/GenerateToolsSection.js +323 -3
- package/dist/editor/control-center/setup-steps/AiSetupStep/tools/GenerateToolsSection.js.map +1 -1
- package/dist/editor/control-center/setup-steps/AiSetupStep/types.d.ts +1 -0
- package/dist/editor/control-center/setup-steps/AiSetupStep/types.js +2 -0
- package/dist/editor/control-center/setup-steps/AiSetupStep/types.js.map +1 -0
- package/dist/editor/control-center/setup-steps/AiSetupStep/utils.d.ts +4 -0
- package/dist/editor/control-center/setup-steps/AiSetupStep/utils.js +25 -0
- package/dist/editor/control-center/setup-steps/AiSetupStep/utils.js.map +1 -0
- package/dist/editor/control-center/setup-steps/IndexSetupStep.js +2 -1
- package/dist/editor/control-center/setup-steps/IndexSetupStep.js.map +1 -1
- package/dist/editor/field-types/SingleLineText.js.map +1 -1
- package/dist/editor/field-types/TreeListEditor.js +102 -16
- package/dist/editor/field-types/TreeListEditor.js.map +1 -1
- package/dist/editor/field-types/richtext/components/ReactSlate.js +1 -1
- package/dist/editor/field-types/richtext/components/SimpleRichTextEditor.js +1 -1
- package/dist/editor/menubar/toolbar-sections/EditControls.js +2 -2
- package/dist/editor/menubar/toolbar-sections/EditControls.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/InsertControls.js +1 -1
- package/dist/editor/menubar/toolbar-sections/InsertControls.js.map +1 -1
- package/dist/editor/page-editor-chrome/FrameMenu.js +25 -12
- package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
- package/dist/editor/page-editor-chrome/SuggestionHighlighting.js +2 -2
- package/dist/editor/page-editor-chrome/SuggestionHighlighting.js.map +1 -1
- package/dist/editor/page-viewer/PageViewer.js +2 -1
- package/dist/editor/page-viewer/PageViewer.js.map +1 -1
- package/dist/editor/reviews/Comments.js +4 -4
- package/dist/editor/reviews/Comments.js.map +1 -1
- package/dist/editor/services/agentService.d.ts +2 -0
- package/dist/editor/services/agentService.js.map +1 -1
- package/dist/editor/services/aiService.d.ts +1 -0
- package/dist/editor/services/aiService.js.map +1 -1
- package/dist/editor/sidebar/ComponentTree.js +18 -6
- package/dist/editor/sidebar/ComponentTree.js.map +1 -1
- package/dist/editor/sidebar/Insert.js +1 -1
- package/dist/editor/ui/Splitter.js +2 -1
- package/dist/editor/ui/Splitter.js.map +1 -1
- package/dist/editor/utils.js +0 -1
- package/dist/editor/utils.js.map +1 -1
- package/dist/page-wizard/steps/MetaDataStep.js +43 -41
- package/dist/page-wizard/steps/MetaDataStep.js.map +1 -1
- package/dist/page-wizard/steps/SelectStep.js +19 -4
- package/dist/page-wizard/steps/SelectStep.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/styles.css +15 -18
- package/package.json +1 -1
- package/src/components/ui/button.tsx +1 -0
- package/src/components/ui/context-menu.tsx +44 -20
- package/src/editor/Editor.tsx +1 -1
- package/src/editor/FieldActionsOverlay.tsx +113 -91
- package/src/editor/FieldListField.tsx +4 -1
- package/src/editor/LinkEditorDialog.tsx +1 -1
- package/src/editor/ai/AgentTerminal.tsx +84 -4
- package/src/editor/ai/Agents.tsx +18 -5
- package/src/editor/ai/ContextInfoBar.tsx +22 -6
- package/src/editor/ai/ToolCallDisplay.tsx +2 -0
- package/src/editor/client/AboutDialog.tsx +22 -17
- package/src/editor/client/EditorShell.tsx +8 -2
- package/src/editor/client/editContext.ts +2 -2
- package/src/editor/client/hooks/useSocketMessageHandler.ts +8 -0
- package/src/editor/client/itemsRepository.ts +1 -0
- package/src/editor/control-center/Setup.tsx +1 -1
- package/src/editor/control-center/setup-steps/AiSetupStep/EmbeddingsModelSection.tsx +296 -0
- package/src/editor/control-center/setup-steps/AiSetupStep/index.tsx +7 -660
- package/src/editor/control-center/setup-steps/AiSetupStep/provider/ProviderSection.tsx +363 -24
- package/src/editor/control-center/setup-steps/AiSetupStep/required-containers/RequiredContainersList.tsx +1 -1
- package/src/editor/control-center/setup-steps/AiSetupStep/required-containers/RequiredContainersSection.tsx +139 -0
- package/src/editor/control-center/setup-steps/AiSetupStep/tools/GenerateToolsSection.tsx +385 -8
- package/src/editor/control-center/setup-steps/AiSetupStep/types.ts +1 -0
- package/src/editor/control-center/setup-steps/AiSetupStep/utils.ts +43 -0
- package/src/editor/control-center/setup-steps/IndexSetupStep.tsx +2 -0
- package/src/editor/field-types/SingleLineText.tsx +0 -9
- package/src/editor/field-types/TreeListEditor.tsx +115 -16
- package/src/editor/field-types/richtext/components/ReactSlate.tsx +1 -1
- package/src/editor/field-types/richtext/components/SimpleRichTextEditor.tsx +1 -1
- package/src/editor/menubar/toolbar-sections/EditControls.tsx +2 -2
- package/src/editor/menubar/toolbar-sections/InsertControls.tsx +1 -1
- package/src/editor/page-editor-chrome/FrameMenu.tsx +81 -68
- package/src/editor/page-editor-chrome/SuggestionHighlighting.tsx +5 -5
- package/src/editor/page-viewer/PageViewer.tsx +3 -2
- package/src/editor/reviews/Comments.tsx +13 -8
- package/src/editor/services/agentService.ts +3 -0
- package/src/editor/services/aiService.ts +2 -0
- package/src/editor/sidebar/ComponentTree.tsx +20 -6
- package/src/editor/sidebar/Insert.tsx +1 -1
- package/src/editor/ui/Splitter.tsx +2 -2
- package/src/editor/utils.ts +0 -1
- package/src/page-wizard/steps/MetaDataStep.tsx +61 -50
- package/src/page-wizard/steps/SelectStep.tsx +37 -4
- package/src/revision.ts +2 -2
|
@@ -1,106 +1,17 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useState } from "react";
|
|
2
2
|
import { Card } from "../../../../components/ui/card";
|
|
3
3
|
import { useEditContext } from "../../../client/editContext";
|
|
4
|
-
import { ItemDescriptor } from "../../../pageModel";
|
|
5
|
-
import { getChildren } from "../../../services/contentService";
|
|
6
|
-
import type { ItemTreeNodeData } from "../../../services/contentService";
|
|
7
4
|
import { SparklesIcon } from "lucide-react";
|
|
8
|
-
import {
|
|
9
|
-
import { RequiredContainersList } from "./required-containers/RequiredContainersList";
|
|
5
|
+
import { RequiredContainersSection } from "./required-containers/RequiredContainersSection";
|
|
10
6
|
import { ProviderSection } from "./provider/ProviderSection";
|
|
11
7
|
import { GenerateToolsSection } from "./tools/GenerateToolsSection";
|
|
12
|
-
|
|
13
|
-
export type StepState = "idle" | "checking" | "success" | "error";
|
|
14
|
-
|
|
15
|
-
function findByName(
|
|
16
|
-
items: ItemTreeNodeData[],
|
|
17
|
-
name: string,
|
|
18
|
-
): ItemTreeNodeData | undefined {
|
|
19
|
-
const target = name.toLowerCase();
|
|
20
|
-
return items.find(
|
|
21
|
-
(x) =>
|
|
22
|
-
(((x.displayName as string) || x.name || "") as string).toLowerCase() ===
|
|
23
|
-
target,
|
|
24
|
-
);
|
|
25
|
-
}
|
|
8
|
+
import type { StepState } from "./types";
|
|
26
9
|
|
|
27
10
|
export function AiSetupStep() {
|
|
28
11
|
const editContext = useEditContext();
|
|
29
12
|
const [aiState, setAiState] = useState<StepState>("idle");
|
|
30
|
-
const [aiProvider, setAiProvider] = useState<string>("");
|
|
31
|
-
const [aiBusy, setAiBusy] = useState(false);
|
|
32
|
-
const [aiError, setAiError] = useState<string | null>(null);
|
|
33
|
-
const [apiKey, setApiKey] = useState<string>("");
|
|
34
|
-
|
|
35
|
-
const [editorSettingsItem, setEditorSettingsItem] =
|
|
36
|
-
useState<ItemDescriptor | null>(null);
|
|
37
|
-
const [containersError, setContainersError] = useState<string | null>(null);
|
|
38
|
-
const requiredContainers = useMemo(
|
|
39
|
-
() => [
|
|
40
|
-
{ name: "Ai Models", templateId: "e5f6a7b8-9c0d-1e2f-3a4b-5c6d7e8f9a0b" },
|
|
41
|
-
{
|
|
42
|
-
name: "Ai Endpoints",
|
|
43
|
-
templateId: "4592f2e0-06e4-470e-9820-7fd4ea148e00",
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
name: "Ai Profiles",
|
|
47
|
-
templateId: "4298ab78-2aaa-4d5f-bb3a-0bd321b86063",
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
name: "Ai Schemas",
|
|
51
|
-
templateId: "5214a52b-6c45-4671-97f2-703fe24e3d09",
|
|
52
|
-
},
|
|
53
|
-
{ name: "Ai Quotas", templateId: "7a08ff28-70ed-459b-a7f2-db2a78d88f46" },
|
|
54
|
-
{
|
|
55
|
-
name: "AI Generators",
|
|
56
|
-
templateId: "9430a3e9-7397-4598-9a55-2b263c927497",
|
|
57
|
-
},
|
|
58
|
-
{ name: "AI Tools", templateId: "7e3f9d9d-8e84-4e57-b12e-6e9c99d4fd11" },
|
|
59
|
-
],
|
|
60
|
-
[],
|
|
61
|
-
);
|
|
62
|
-
const [containerStates, setContainerStates] = useState<
|
|
63
|
-
Record<string, StepState>
|
|
64
|
-
>({});
|
|
65
|
-
const [busyMap, setBusyMap] = useState<Record<string, boolean>>({});
|
|
66
|
-
|
|
67
13
|
const userLang = editContext?.contentEditorItem?.language || "en";
|
|
68
14
|
|
|
69
|
-
const aiOptions = useMemo(
|
|
70
|
-
() => [
|
|
71
|
-
{ value: "openai", label: "OpenAI" },
|
|
72
|
-
{ value: "azure-openai", label: "Azure OpenAI" },
|
|
73
|
-
{ value: "openrouter", label: "OpenRouter" },
|
|
74
|
-
],
|
|
75
|
-
[],
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
const resolvePathUnderContent = React.useCallback(
|
|
79
|
-
async (names: string[]): Promise<ItemDescriptor | null> => {
|
|
80
|
-
if (!editContext?.sessionId) return null;
|
|
81
|
-
let currentId = contentItemId;
|
|
82
|
-
for (const segment of names) {
|
|
83
|
-
const children = (await getChildren(
|
|
84
|
-
currentId,
|
|
85
|
-
editContext.sessionId,
|
|
86
|
-
[],
|
|
87
|
-
false,
|
|
88
|
-
userLang,
|
|
89
|
-
"path",
|
|
90
|
-
)) as unknown as ItemTreeNodeData[];
|
|
91
|
-
const next = findByName(children, segment);
|
|
92
|
-
if (!next) return null;
|
|
93
|
-
currentId = next.id;
|
|
94
|
-
}
|
|
95
|
-
return {
|
|
96
|
-
id: currentId,
|
|
97
|
-
language: userLang,
|
|
98
|
-
version: 0,
|
|
99
|
-
} as ItemDescriptor;
|
|
100
|
-
},
|
|
101
|
-
[editContext?.sessionId, userLang],
|
|
102
|
-
);
|
|
103
|
-
|
|
104
15
|
// IDs for tool templates/fields
|
|
105
16
|
const AI_TOOLS_TEMPLATE_ID = "7e3f9d9d-8e84-4e57-b12e-6e9c99d4fd11"; // container
|
|
106
17
|
const AI_TOOL_TEMPLATE_ID = "a2e8a0d9-7b1f-4d1a-a2d8-8f3ea6d6f0b1"; // item template
|
|
@@ -108,582 +19,18 @@ export function AiSetupStep() {
|
|
|
108
19
|
const FIELD_LABEL_ID = "5a19f5a5-1d21-4b6a-9f83-6f3fc0b34b2e";
|
|
109
20
|
const FIELD_DESCRIPTION_ID = "6b2e4b8e-8a9f-4d8f-9f6e-1a2b3c4d5e6f";
|
|
110
21
|
|
|
111
|
-
const [toolsBusy, setToolsBusy] = useState(false);
|
|
112
|
-
const [toolsError, setToolsError] = useState<string | null>(null);
|
|
113
|
-
|
|
114
|
-
const ensureAiToolsAndGenerate = useCallback(async () => {
|
|
115
|
-
if (!editContext) return;
|
|
116
|
-
try {
|
|
117
|
-
setToolsBusy(true);
|
|
118
|
-
setToolsError(null);
|
|
119
|
-
|
|
120
|
-
// Resolve /Settings/Editor
|
|
121
|
-
const settingsItem = await resolvePathUnderContent([
|
|
122
|
-
"Settings",
|
|
123
|
-
"Editor",
|
|
124
|
-
]);
|
|
125
|
-
if (!settingsItem)
|
|
126
|
-
throw new Error("Editor settings item not found. Create it first.");
|
|
127
|
-
|
|
128
|
-
// Ensure AI Tools container exists
|
|
129
|
-
const editorChildren = (await getChildren(
|
|
130
|
-
settingsItem.id,
|
|
131
|
-
editContext.sessionId!,
|
|
132
|
-
[],
|
|
133
|
-
false,
|
|
134
|
-
userLang,
|
|
135
|
-
"path",
|
|
136
|
-
)) as unknown as ItemTreeNodeData[];
|
|
137
|
-
|
|
138
|
-
let aiToolsParent = findByName(editorChildren, "AI Tools");
|
|
139
|
-
if (!aiToolsParent) {
|
|
140
|
-
const created = await editContext.operations.createItem(
|
|
141
|
-
settingsItem,
|
|
142
|
-
AI_TOOLS_TEMPLATE_ID,
|
|
143
|
-
"AI Tools",
|
|
144
|
-
);
|
|
145
|
-
if (!created) throw new Error("Failed to create 'AI Tools' container");
|
|
146
|
-
aiToolsParent = {
|
|
147
|
-
id: created.id,
|
|
148
|
-
name: "AI Tools",
|
|
149
|
-
displayName: "AI Tools",
|
|
150
|
-
thumbUrl: "",
|
|
151
|
-
previewUrl: "",
|
|
152
|
-
templateId: "",
|
|
153
|
-
icon: "",
|
|
154
|
-
hasChildren: false,
|
|
155
|
-
isComponent: false,
|
|
156
|
-
language: userLang,
|
|
157
|
-
version: 0,
|
|
158
|
-
hasLayout: false,
|
|
159
|
-
} as unknown as ItemTreeNodeData;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Get existing tool items under AI Tools
|
|
163
|
-
const toolChildren = (await getChildren(
|
|
164
|
-
aiToolsParent.id,
|
|
165
|
-
editContext.sessionId!,
|
|
166
|
-
[],
|
|
167
|
-
false,
|
|
168
|
-
userLang,
|
|
169
|
-
"path",
|
|
170
|
-
)) as unknown as ItemTreeNodeData[];
|
|
171
|
-
|
|
172
|
-
const findChildByLabel = (label: string) =>
|
|
173
|
-
findByName(toolChildren, label);
|
|
174
|
-
|
|
175
|
-
// Known tool functions (aligned with backend function names)
|
|
176
|
-
const tools: {
|
|
177
|
-
functionName: string;
|
|
178
|
-
label: string;
|
|
179
|
-
description?: string;
|
|
180
|
-
}[] = [
|
|
181
|
-
{
|
|
182
|
-
functionName: "get-content",
|
|
183
|
-
label: "Get Content",
|
|
184
|
-
description: "Returns page content or selected components",
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
functionName: "edit-field",
|
|
188
|
-
label: "Edit Field",
|
|
189
|
-
description: "Edits a field on the page or datasource",
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
functionName: "suggest-field-edit",
|
|
193
|
-
label: "Suggest Field Edit",
|
|
194
|
-
description: "Suggests changes to a field's content",
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
functionName: "create-item",
|
|
198
|
-
label: "Create Item",
|
|
199
|
-
description: "Creates a new item using a template",
|
|
200
|
-
},
|
|
201
|
-
{
|
|
202
|
-
functionName: "load-item",
|
|
203
|
-
label: "Load Item",
|
|
204
|
-
description: "Loads an item for context",
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
functionName: "get-items",
|
|
208
|
-
label: "Get Items",
|
|
209
|
-
description: "Finds items by criteria",
|
|
210
|
-
},
|
|
211
|
-
{
|
|
212
|
-
functionName: "get-children",
|
|
213
|
-
label: "Get Children",
|
|
214
|
-
description: "Lists child items under a parent",
|
|
215
|
-
},
|
|
216
|
-
{
|
|
217
|
-
functionName: "get-insertoptions",
|
|
218
|
-
label: "Get Insert Options",
|
|
219
|
-
description: "Lists available insert templates for an item",
|
|
220
|
-
},
|
|
221
|
-
{
|
|
222
|
-
functionName: "add-component",
|
|
223
|
-
label: "Add Component",
|
|
224
|
-
description: "Adds a component to a placeholder",
|
|
225
|
-
},
|
|
226
|
-
{
|
|
227
|
-
functionName: "remove-component",
|
|
228
|
-
label: "Remove Component",
|
|
229
|
-
description: "Removes a component from the page",
|
|
230
|
-
},
|
|
231
|
-
{
|
|
232
|
-
functionName: "move-components",
|
|
233
|
-
label: "Move Components",
|
|
234
|
-
description: "Moves components between placeholders",
|
|
235
|
-
},
|
|
236
|
-
{
|
|
237
|
-
functionName: "get-placeholders",
|
|
238
|
-
label: "Get Placeholders",
|
|
239
|
-
description: "Lists placeholders for a component",
|
|
240
|
-
},
|
|
241
|
-
{
|
|
242
|
-
functionName: "get-component-props-and-placeholders",
|
|
243
|
-
label: "Get Component Props and Placeholders",
|
|
244
|
-
description: "Returns component prop schema and placeholders",
|
|
245
|
-
},
|
|
246
|
-
{
|
|
247
|
-
functionName: "search-content",
|
|
248
|
-
label: "Search Content",
|
|
249
|
-
description: "Searches content across the index",
|
|
250
|
-
},
|
|
251
|
-
{
|
|
252
|
-
functionName: "search-images",
|
|
253
|
-
label: "Search Images",
|
|
254
|
-
description: "Searches images for use in content",
|
|
255
|
-
},
|
|
256
|
-
{
|
|
257
|
-
functionName: "google-search",
|
|
258
|
-
label: "Google Search",
|
|
259
|
-
description: "Performs a web search",
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
functionName: "scrape-webpage",
|
|
263
|
-
label: "Scrape Webpage",
|
|
264
|
-
description: "Fetches a webpage and extracts content",
|
|
265
|
-
},
|
|
266
|
-
{
|
|
267
|
-
functionName: "edit-image",
|
|
268
|
-
label: "Edit Image",
|
|
269
|
-
description: "Uses AI to modify an image",
|
|
270
|
-
},
|
|
271
|
-
{
|
|
272
|
-
functionName: "get-picture-description",
|
|
273
|
-
label: "Get Picture Description",
|
|
274
|
-
description: "Describes an image",
|
|
275
|
-
},
|
|
276
|
-
{
|
|
277
|
-
functionName: "add-comment",
|
|
278
|
-
label: "Add Comment",
|
|
279
|
-
description: "Adds a comment to the page",
|
|
280
|
-
},
|
|
281
|
-
{
|
|
282
|
-
functionName: "get-comments",
|
|
283
|
-
label: "Get Comments",
|
|
284
|
-
description: "Lists comments on the page",
|
|
285
|
-
},
|
|
286
|
-
{
|
|
287
|
-
functionName: "get-suggestions",
|
|
288
|
-
label: "Get Suggestions",
|
|
289
|
-
description: "Provides AI suggestions",
|
|
290
|
-
},
|
|
291
|
-
];
|
|
292
|
-
|
|
293
|
-
// Create or update tool items
|
|
294
|
-
for (const t of tools) {
|
|
295
|
-
let node = findChildByLabel(t.label);
|
|
296
|
-
if (!node) {
|
|
297
|
-
const created = await editContext.operations.createItem(
|
|
298
|
-
{
|
|
299
|
-
id: aiToolsParent.id,
|
|
300
|
-
language: userLang,
|
|
301
|
-
version: 0,
|
|
302
|
-
} as ItemDescriptor,
|
|
303
|
-
AI_TOOL_TEMPLATE_ID,
|
|
304
|
-
t.label,
|
|
305
|
-
);
|
|
306
|
-
if (!created) throw new Error(`Failed to create tool '${t.label}'`);
|
|
307
|
-
node = {
|
|
308
|
-
id: created.id,
|
|
309
|
-
name: t.label,
|
|
310
|
-
displayName: t.label,
|
|
311
|
-
thumbUrl: "",
|
|
312
|
-
previewUrl: "",
|
|
313
|
-
templateId: "",
|
|
314
|
-
icon: "",
|
|
315
|
-
hasChildren: false,
|
|
316
|
-
isComponent: false,
|
|
317
|
-
language: userLang,
|
|
318
|
-
version: 0,
|
|
319
|
-
hasLayout: false,
|
|
320
|
-
} as unknown as ItemTreeNodeData;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// Set Function Name
|
|
324
|
-
await editContext.operations.editField({
|
|
325
|
-
field: {
|
|
326
|
-
fieldId: FIELD_FUNCTION_NAME_ID,
|
|
327
|
-
item: { id: node.id, language: userLang, version: 0 },
|
|
328
|
-
},
|
|
329
|
-
value: t.functionName,
|
|
330
|
-
rawValue: t.functionName,
|
|
331
|
-
refresh: "delayed",
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
// Set Label
|
|
335
|
-
await editContext.operations.editField({
|
|
336
|
-
field: {
|
|
337
|
-
fieldId: FIELD_LABEL_ID,
|
|
338
|
-
item: { id: node.id, language: userLang, version: 0 },
|
|
339
|
-
},
|
|
340
|
-
value: t.label,
|
|
341
|
-
rawValue: t.label,
|
|
342
|
-
refresh: "delayed",
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
// Set Description
|
|
346
|
-
if (t.description) {
|
|
347
|
-
await editContext.operations.editField({
|
|
348
|
-
field: {
|
|
349
|
-
fieldId: FIELD_DESCRIPTION_ID,
|
|
350
|
-
item: { id: node.id, language: userLang, version: 0 },
|
|
351
|
-
},
|
|
352
|
-
value: t.description,
|
|
353
|
-
rawValue: t.description,
|
|
354
|
-
refresh: "delayed",
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
setAiState("success");
|
|
360
|
-
editContext.requestRefresh?.("immediate");
|
|
361
|
-
} catch (e: any) {
|
|
362
|
-
setToolsError(e?.message || "Failed to generate AI tools");
|
|
363
|
-
} finally {
|
|
364
|
-
setToolsBusy(false);
|
|
365
|
-
}
|
|
366
|
-
}, [editContext, resolvePathUnderContent, userLang]);
|
|
367
|
-
|
|
368
|
-
const createAiEndpoint = useCallback(async () => {
|
|
369
|
-
if (!aiProvider || !editContext) return;
|
|
370
|
-
try {
|
|
371
|
-
setAiBusy(true);
|
|
372
|
-
setAiError(null);
|
|
373
|
-
|
|
374
|
-
const settingsItem = await resolvePathUnderContent([
|
|
375
|
-
"Settings",
|
|
376
|
-
"Editor",
|
|
377
|
-
]);
|
|
378
|
-
if (!settingsItem)
|
|
379
|
-
throw new Error("Editor settings item not found. Create it first.");
|
|
380
|
-
|
|
381
|
-
const children = (await getChildren(
|
|
382
|
-
settingsItem.id,
|
|
383
|
-
editContext.sessionId!,
|
|
384
|
-
[],
|
|
385
|
-
false,
|
|
386
|
-
userLang,
|
|
387
|
-
"path",
|
|
388
|
-
)) as unknown as ItemTreeNodeData[];
|
|
389
|
-
let aiEndpointsParent = findByName(children, "Ai Endpoints");
|
|
390
|
-
if (!aiEndpointsParent) {
|
|
391
|
-
const aiEndpointsTemplateId = "4592f2e0-06e4-470e-9820-7fd4ea148e00";
|
|
392
|
-
const createdContainer = await editContext.operations.createItem(
|
|
393
|
-
settingsItem,
|
|
394
|
-
aiEndpointsTemplateId,
|
|
395
|
-
"Ai Endpoints",
|
|
396
|
-
);
|
|
397
|
-
if (!createdContainer)
|
|
398
|
-
throw new Error("Failed to create 'Ai Endpoints' container");
|
|
399
|
-
aiEndpointsParent = {
|
|
400
|
-
id: createdContainer.id,
|
|
401
|
-
name: "Ai Endpoints",
|
|
402
|
-
thumbUrl: "",
|
|
403
|
-
previewUrl: "",
|
|
404
|
-
templateId: "",
|
|
405
|
-
icon: "",
|
|
406
|
-
hasChildren: false,
|
|
407
|
-
isComponent: false,
|
|
408
|
-
displayName: "Ai Endpoints",
|
|
409
|
-
language: userLang,
|
|
410
|
-
version: 0,
|
|
411
|
-
hasLayout: false,
|
|
412
|
-
} as unknown as ItemTreeNodeData;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
const endpointTemplateId = "a6358b92-a9ea-4dd8-b4e1-7d6d3a3b9c40";
|
|
416
|
-
const endpointName =
|
|
417
|
-
aiProvider === "openai"
|
|
418
|
-
? "OpenAI"
|
|
419
|
-
: aiProvider === "azure-openai"
|
|
420
|
-
? "Azure OpenAI"
|
|
421
|
-
: "Open Router";
|
|
422
|
-
|
|
423
|
-
// Find or create endpoint
|
|
424
|
-
let endpointItem: ItemDescriptor | null = null;
|
|
425
|
-
const epChildren = (await getChildren(
|
|
426
|
-
aiEndpointsParent!.id,
|
|
427
|
-
editContext.sessionId!,
|
|
428
|
-
[],
|
|
429
|
-
false,
|
|
430
|
-
userLang,
|
|
431
|
-
"path",
|
|
432
|
-
)) as unknown as ItemTreeNodeData[];
|
|
433
|
-
const existingEndpoint = findByName(epChildren, endpointName);
|
|
434
|
-
if (existingEndpoint) {
|
|
435
|
-
endpointItem = {
|
|
436
|
-
id: existingEndpoint.id,
|
|
437
|
-
language: userLang,
|
|
438
|
-
version: 0,
|
|
439
|
-
} as ItemDescriptor;
|
|
440
|
-
} else {
|
|
441
|
-
const created = await editContext.operations.createItem(
|
|
442
|
-
{
|
|
443
|
-
id: aiEndpointsParent!.id,
|
|
444
|
-
language: userLang,
|
|
445
|
-
version: 0,
|
|
446
|
-
} as ItemDescriptor,
|
|
447
|
-
endpointTemplateId,
|
|
448
|
-
endpointName,
|
|
449
|
-
);
|
|
450
|
-
if (!created) throw new Error("Failed to create AI endpoint");
|
|
451
|
-
endpointItem = created;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
// Set API key if provided
|
|
455
|
-
if (apiKey && endpointItem) {
|
|
456
|
-
const apiKeyFieldId = "db07ae53-459a-4314-89b3-ab2721df2b4f";
|
|
457
|
-
await editContext.operations.editField({
|
|
458
|
-
field: {
|
|
459
|
-
fieldId: apiKeyFieldId,
|
|
460
|
-
item: {
|
|
461
|
-
id: endpointItem.id,
|
|
462
|
-
language: userLang,
|
|
463
|
-
version: 0,
|
|
464
|
-
},
|
|
465
|
-
},
|
|
466
|
-
value: apiKey,
|
|
467
|
-
rawValue: apiKey,
|
|
468
|
-
refresh: "delayed",
|
|
469
|
-
});
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
// Ensure Ai Models container exists
|
|
473
|
-
let aiModelsParent = findByName(children, "Ai Models");
|
|
474
|
-
if (!aiModelsParent) {
|
|
475
|
-
const aiModelsTemplateId = "e5f6a7b8-9c0d-1e2f-3a4b-5c6d7e8f9a0b";
|
|
476
|
-
const createdModels = await editContext.operations.createItem(
|
|
477
|
-
settingsItem,
|
|
478
|
-
aiModelsTemplateId,
|
|
479
|
-
"Ai Models",
|
|
480
|
-
);
|
|
481
|
-
if (!createdModels)
|
|
482
|
-
throw new Error("Failed to create 'Ai Models' container");
|
|
483
|
-
aiModelsParent = {
|
|
484
|
-
id: createdModels.id,
|
|
485
|
-
name: "Ai Models",
|
|
486
|
-
thumbUrl: "",
|
|
487
|
-
previewUrl: "",
|
|
488
|
-
templateId: "",
|
|
489
|
-
icon: "",
|
|
490
|
-
hasChildren: false,
|
|
491
|
-
isComponent: false,
|
|
492
|
-
displayName: "Ai Models",
|
|
493
|
-
language: userLang,
|
|
494
|
-
version: 0,
|
|
495
|
-
hasLayout: false,
|
|
496
|
-
} as unknown as ItemTreeNodeData;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
// Create default models if missing and link to endpoint
|
|
500
|
-
const modelsToEnsure = ["gpt-5", "gpt5-high", "image-1"];
|
|
501
|
-
const modelTemplateId = "d2e3f4a5-4b5c-5c6d-bf0b-3e4f5a6b7c8e";
|
|
502
|
-
const modelNameFieldId = "f1e2d3c4-5b6a-7980-8e9f-1a2b3c4d5e6f";
|
|
503
|
-
const modelEndpointFieldId = "cbade708-ce95-4f54-81b7-308ea61a76a6";
|
|
504
|
-
|
|
505
|
-
const modelChildren = (await getChildren(
|
|
506
|
-
aiModelsParent.id,
|
|
507
|
-
editContext.sessionId!,
|
|
508
|
-
[],
|
|
509
|
-
false,
|
|
510
|
-
userLang,
|
|
511
|
-
"path",
|
|
512
|
-
)) as unknown as ItemTreeNodeData[];
|
|
513
|
-
|
|
514
|
-
for (const modelName of modelsToEnsure) {
|
|
515
|
-
let modelNode = findByName(modelChildren, modelName);
|
|
516
|
-
if (!modelNode) {
|
|
517
|
-
const createdModel = await editContext.operations.createItem(
|
|
518
|
-
{
|
|
519
|
-
id: aiModelsParent.id,
|
|
520
|
-
language: userLang,
|
|
521
|
-
version: 0,
|
|
522
|
-
} as ItemDescriptor,
|
|
523
|
-
modelTemplateId,
|
|
524
|
-
modelName,
|
|
525
|
-
);
|
|
526
|
-
if (!createdModel)
|
|
527
|
-
throw new Error(`Failed to create model '${modelName}'`);
|
|
528
|
-
modelNode = {
|
|
529
|
-
id: createdModel.id,
|
|
530
|
-
name: modelName,
|
|
531
|
-
displayName: modelName,
|
|
532
|
-
thumbUrl: "",
|
|
533
|
-
previewUrl: "",
|
|
534
|
-
templateId: "",
|
|
535
|
-
icon: "",
|
|
536
|
-
hasChildren: false,
|
|
537
|
-
isComponent: false,
|
|
538
|
-
language: userLang,
|
|
539
|
-
version: 0,
|
|
540
|
-
hasLayout: false,
|
|
541
|
-
} as unknown as ItemTreeNodeData;
|
|
542
|
-
|
|
543
|
-
await editContext.operations.editField({
|
|
544
|
-
field: {
|
|
545
|
-
fieldId: modelNameFieldId,
|
|
546
|
-
item: { id: modelNode.id, language: userLang, version: 0 },
|
|
547
|
-
},
|
|
548
|
-
value: modelName,
|
|
549
|
-
rawValue: modelName,
|
|
550
|
-
refresh: "delayed",
|
|
551
|
-
});
|
|
552
|
-
|
|
553
|
-
const endpointGuid = `{${(endpointItem!.id as string)
|
|
554
|
-
.replace(/[{}()]/g, "")
|
|
555
|
-
.toUpperCase()}}`;
|
|
556
|
-
await editContext.operations.editField({
|
|
557
|
-
field: {
|
|
558
|
-
fieldId: modelEndpointFieldId,
|
|
559
|
-
item: { id: modelNode.id, language: userLang, version: 0 },
|
|
560
|
-
},
|
|
561
|
-
rawValue: endpointGuid,
|
|
562
|
-
refresh: "delayed",
|
|
563
|
-
});
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
setAiState("success");
|
|
568
|
-
editContext.requestRefresh?.("immediate");
|
|
569
|
-
} catch (e: any) {
|
|
570
|
-
setAiState("error");
|
|
571
|
-
setAiError(e?.message || "Failed to add AI endpoint");
|
|
572
|
-
} finally {
|
|
573
|
-
setAiBusy(false);
|
|
574
|
-
}
|
|
575
|
-
}, [aiProvider, editContext, userLang, resolvePathUnderContent, apiKey]);
|
|
576
|
-
|
|
577
|
-
const checkRequiredContainers = useCallback(async () => {
|
|
578
|
-
try {
|
|
579
|
-
setContainersError(null);
|
|
580
|
-
const initialStates: Record<string, StepState> = {};
|
|
581
|
-
for (const rc of requiredContainers) initialStates[rc.name] = "checking";
|
|
582
|
-
setContainerStates(initialStates);
|
|
583
|
-
|
|
584
|
-
const settingsItem = await resolvePathUnderContent([
|
|
585
|
-
"Settings",
|
|
586
|
-
"Editor",
|
|
587
|
-
]);
|
|
588
|
-
if (!settingsItem) {
|
|
589
|
-
setEditorSettingsItem(null);
|
|
590
|
-
const errorMsg = "Editor settings item not found. Create it first.";
|
|
591
|
-
setContainersError(errorMsg);
|
|
592
|
-
const errorStates: Record<string, StepState> = {};
|
|
593
|
-
for (const rc of requiredContainers) errorStates[rc.name] = "error";
|
|
594
|
-
setContainerStates(errorStates);
|
|
595
|
-
return;
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
setEditorSettingsItem(settingsItem);
|
|
599
|
-
const children = (await getChildren(
|
|
600
|
-
settingsItem.id,
|
|
601
|
-
editContext!.sessionId!,
|
|
602
|
-
[],
|
|
603
|
-
false,
|
|
604
|
-
userLang,
|
|
605
|
-
"path",
|
|
606
|
-
)) as unknown as ItemTreeNodeData[];
|
|
607
|
-
|
|
608
|
-
const states: Record<string, StepState> = {};
|
|
609
|
-
for (const rc of requiredContainers) {
|
|
610
|
-
const exists = !!findByName(children, rc.name);
|
|
611
|
-
states[rc.name] = exists ? "success" : "error";
|
|
612
|
-
}
|
|
613
|
-
setContainerStates(states);
|
|
614
|
-
} catch (e: any) {
|
|
615
|
-
setContainersError(e?.message || "Failed to check AI containers");
|
|
616
|
-
const errorStates: Record<string, StepState> = {};
|
|
617
|
-
for (const rc of requiredContainers) errorStates[rc.name] = "error";
|
|
618
|
-
setContainerStates(errorStates);
|
|
619
|
-
}
|
|
620
|
-
}, [editContext, requiredContainers, resolvePathUnderContent, userLang]);
|
|
621
|
-
|
|
622
|
-
React.useEffect(() => {
|
|
623
|
-
checkRequiredContainers();
|
|
624
|
-
}, [checkRequiredContainers]);
|
|
625
|
-
|
|
626
|
-
const createContainer = useCallback(
|
|
627
|
-
async (name: string, templateId: string) => {
|
|
628
|
-
if (!editorSettingsItem || !editContext) return;
|
|
629
|
-
try {
|
|
630
|
-
setBusyMap((s) => ({ ...s, [name]: true }));
|
|
631
|
-
setContainersError(null);
|
|
632
|
-
|
|
633
|
-
const created = await editContext.operations.createItem(
|
|
634
|
-
editorSettingsItem,
|
|
635
|
-
templateId,
|
|
636
|
-
name,
|
|
637
|
-
);
|
|
638
|
-
|
|
639
|
-
if (!created) throw new Error(`Failed to create '${name}'`);
|
|
640
|
-
setContainerStates((s) => ({ ...s, [name]: "success" }));
|
|
641
|
-
} catch (e: any) {
|
|
642
|
-
setContainersError(e?.message || `Failed to create '${name}'`);
|
|
643
|
-
setContainerStates((s) => ({ ...s, [name]: "error" }));
|
|
644
|
-
} finally {
|
|
645
|
-
setBusyMap((s) => ({ ...s, [name]: false }));
|
|
646
|
-
}
|
|
647
|
-
},
|
|
648
|
-
[editorSettingsItem, editContext],
|
|
649
|
-
);
|
|
650
|
-
|
|
651
22
|
return (
|
|
652
23
|
<Card
|
|
24
|
+
className="w-full"
|
|
653
25
|
icon={<SparklesIcon strokeWidth={1} className="h-5 w-5" />}
|
|
654
26
|
title="AI setup"
|
|
655
27
|
description="Add an AI endpoint (OpenAI, Azure OpenAI, or OpenRouter)."
|
|
656
28
|
>
|
|
657
|
-
<
|
|
658
|
-
requiredContainers={requiredContainers}
|
|
659
|
-
containerStates={containerStates}
|
|
660
|
-
busyMap={busyMap}
|
|
661
|
-
canFix={!!editorSettingsItem}
|
|
662
|
-
containersError={containersError}
|
|
663
|
-
onFixContainer={createContainer}
|
|
664
|
-
/>
|
|
665
|
-
|
|
666
|
-
<ProviderSection
|
|
667
|
-
aiProvider={aiProvider}
|
|
668
|
-
aiOptions={aiOptions}
|
|
669
|
-
onProviderChange={setAiProvider}
|
|
670
|
-
apiKey={apiKey}
|
|
671
|
-
onApiKeyChange={setApiKey}
|
|
672
|
-
aiBusy={aiBusy}
|
|
673
|
-
onAddEndpoint={createAiEndpoint}
|
|
674
|
-
/>
|
|
29
|
+
<RequiredContainersSection />
|
|
675
30
|
|
|
676
|
-
<
|
|
677
|
-
toolsBusy={toolsBusy}
|
|
678
|
-
toolsError={toolsError}
|
|
679
|
-
onGenerateTools={ensureAiToolsAndGenerate}
|
|
680
|
-
/>
|
|
31
|
+
<ProviderSection />
|
|
681
32
|
|
|
682
|
-
|
|
683
|
-
<div className="mt-2 rounded border border-red-200 bg-red-50 p-2 text-xs whitespace-pre-wrap text-red-700">
|
|
684
|
-
{aiError}
|
|
685
|
-
</div>
|
|
686
|
-
)}
|
|
33
|
+
<GenerateToolsSection />
|
|
687
34
|
</Card>
|
|
688
35
|
);
|
|
689
36
|
}
|