@alpaca-editor/core 1.0.4172 → 1.0.4174

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/dist/agents-view/AgentsView.d.ts +5 -0
  2. package/dist/agents-view/AgentsView.js +213 -0
  3. package/dist/agents-view/AgentsView.js.map +1 -0
  4. package/dist/components/ui/context-menu.js +4 -4
  5. package/dist/components/ui/context-menu.js.map +1 -1
  6. package/dist/config/config.js +56 -1
  7. package/dist/config/config.js.map +1 -1
  8. package/dist/editor/ConfirmationDialog.js +2 -1
  9. package/dist/editor/ConfirmationDialog.js.map +1 -1
  10. package/dist/editor/ContentTree.d.ts +2 -1
  11. package/dist/editor/ContentTree.js +18 -3
  12. package/dist/editor/ContentTree.js.map +1 -1
  13. package/dist/editor/ContextMenu.js +1 -1
  14. package/dist/editor/ContextMenu.js.map +1 -1
  15. package/dist/editor/FieldList.js +7 -3
  16. package/dist/editor/FieldList.js.map +1 -1
  17. package/dist/editor/FieldListField.d.ts +3 -2
  18. package/dist/editor/FieldListField.js +4 -4
  19. package/dist/editor/FieldListField.js.map +1 -1
  20. package/dist/editor/FieldListFieldWithFallbacks.d.ts +2 -1
  21. package/dist/editor/FieldListFieldWithFallbacks.js +5 -2
  22. package/dist/editor/FieldListFieldWithFallbacks.js.map +1 -1
  23. package/dist/editor/MainLayout.js +1 -1
  24. package/dist/editor/QuickItemSwitcher.d.ts +9 -0
  25. package/dist/editor/QuickItemSwitcher.js +74 -0
  26. package/dist/editor/QuickItemSwitcher.js.map +1 -0
  27. package/dist/editor/ai/AgentCostDisplay.js +7 -11
  28. package/dist/editor/ai/AgentCostDisplay.js.map +1 -1
  29. package/dist/editor/ai/AgentProfilesOverview.d.ts +9 -0
  30. package/dist/editor/ai/AgentProfilesOverview.js +16 -0
  31. package/dist/editor/ai/AgentProfilesOverview.js.map +1 -0
  32. package/dist/editor/ai/AgentTerminal.js +285 -748
  33. package/dist/editor/ai/AgentTerminal.js.map +1 -1
  34. package/dist/editor/ai/Agents.js +112 -54
  35. package/dist/editor/ai/Agents.js.map +1 -1
  36. package/dist/editor/ai/AiResponseMessage.d.ts +2 -1
  37. package/dist/editor/ai/AiResponseMessage.js +4 -2
  38. package/dist/editor/ai/AiResponseMessage.js.map +1 -1
  39. package/dist/editor/ai/ContextInfoBar.js +17 -17
  40. package/dist/editor/ai/useAgentStatus.js +7 -0
  41. package/dist/editor/ai/useAgentStatus.js.map +1 -1
  42. package/dist/editor/client/EditorShell.js +230 -4
  43. package/dist/editor/client/EditorShell.js.map +1 -1
  44. package/dist/editor/client/hooks/useSocketMessageHandler.js +0 -12
  45. package/dist/editor/client/hooks/useSocketMessageHandler.js.map +1 -1
  46. package/dist/editor/client/ui/EditorChrome.js +1 -1
  47. package/dist/editor/client/ui/EditorChrome.js.map +1 -1
  48. package/dist/editor/commands/itemCommands.js +1 -0
  49. package/dist/editor/commands/itemCommands.js.map +1 -1
  50. package/dist/editor/control-center/parhelia-setup/Overview.d.ts +1 -0
  51. package/dist/editor/control-center/parhelia-setup/Overview.js +91 -0
  52. package/dist/editor/control-center/parhelia-setup/Overview.js.map +1 -0
  53. package/dist/editor/field-types/AttachmentEditor.js +3 -6
  54. package/dist/editor/field-types/AttachmentEditor.js.map +1 -1
  55. package/dist/editor/field-types/DropLinkEditor.js +2 -2
  56. package/dist/editor/field-types/DropLinkEditor.js.map +1 -1
  57. package/dist/editor/field-types/DropListEditor.js +2 -1
  58. package/dist/editor/field-types/DropListEditor.js.map +1 -1
  59. package/dist/editor/field-types/InternalLinkFieldEditor.js +3 -3
  60. package/dist/editor/field-types/InternalLinkFieldEditor.js.map +1 -1
  61. package/dist/editor/field-types/MultiLineText.d.ts +2 -1
  62. package/dist/editor/field-types/MultiLineText.js +2 -2
  63. package/dist/editor/field-types/MultiLineText.js.map +1 -1
  64. package/dist/editor/field-types/RawEditor.d.ts +2 -1
  65. package/dist/editor/field-types/RawEditor.js +2 -2
  66. package/dist/editor/field-types/RawEditor.js.map +1 -1
  67. package/dist/editor/field-types/SingleLineText.d.ts +2 -1
  68. package/dist/editor/field-types/SingleLineText.js +2 -2
  69. package/dist/editor/field-types/SingleLineText.js.map +1 -1
  70. package/dist/editor/field-types/TreeListEditor.js +9 -7
  71. package/dist/editor/field-types/TreeListEditor.js.map +1 -1
  72. package/dist/editor/media-selector/MediaFolderBrowser.js +68 -7
  73. package/dist/editor/media-selector/MediaFolderBrowser.js.map +1 -1
  74. package/dist/editor/media-selector/TreeSelector.js +1 -1
  75. package/dist/editor/media-selector/TreeSelector.js.map +1 -1
  76. package/dist/editor/menubar/ActiveUsers.js +2 -2
  77. package/dist/editor/menubar/FavoritesControls.js +2 -2
  78. package/dist/editor/menubar/FavoritesControls.js.map +1 -1
  79. package/dist/editor/page-editor-chrome/FrameMenu.js +10 -1
  80. package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
  81. package/dist/editor/page-viewer/pageModelSkeletonBuilder.js +14 -0
  82. package/dist/editor/page-viewer/pageModelSkeletonBuilder.js.map +1 -1
  83. package/dist/editor/services/agentService.d.ts +21 -3
  84. package/dist/editor/services/agentService.js +24 -8
  85. package/dist/editor/services/agentService.js.map +1 -1
  86. package/dist/editor/services/aiService.d.ts +6 -1
  87. package/dist/editor/services/aiService.js +36 -5
  88. package/dist/editor/services/aiService.js.map +1 -1
  89. package/dist/editor/services/contentService.d.ts +1 -1
  90. package/dist/editor/services/contentService.js +4 -2
  91. package/dist/editor/services/contentService.js.map +1 -1
  92. package/dist/editor/services/editService.d.ts +5 -1
  93. package/dist/editor/services/editService.js +1 -1
  94. package/dist/editor/services/editService.js.map +1 -1
  95. package/dist/editor/services/setupService.d.ts +21 -0
  96. package/dist/editor/services/setupService.js +10 -0
  97. package/dist/editor/services/setupService.js.map +1 -0
  98. package/dist/editor/sidebar/ComponentTree.js +15 -1
  99. package/dist/editor/sidebar/ComponentTree.js.map +1 -1
  100. package/dist/editor/sidebar/SidebarView.js +1 -1
  101. package/dist/editor/sidebar/SidebarView.js.map +1 -1
  102. package/dist/editor/ui/ItemSearch.d.ts +1 -0
  103. package/dist/editor/ui/ItemSearch.js +2 -2
  104. package/dist/editor/ui/ItemSearch.js.map +1 -1
  105. package/dist/editor/ui/PerfectTree.d.ts +5 -1
  106. package/dist/editor/ui/PerfectTree.js +308 -29
  107. package/dist/editor/ui/PerfectTree.js.map +1 -1
  108. package/dist/editor/utils/keyboardNavigation.d.ts +2 -0
  109. package/dist/editor/utils/keyboardNavigation.js +80 -2
  110. package/dist/editor/utils/keyboardNavigation.js.map +1 -1
  111. package/dist/editor/views/SingleEditView.js +6 -4
  112. package/dist/editor/views/SingleEditView.js.map +1 -1
  113. package/dist/revision.d.ts +2 -2
  114. package/dist/revision.js +2 -2
  115. package/dist/splash-screen/SplashScreen.js +78 -4
  116. package/dist/splash-screen/SplashScreen.js.map +1 -1
  117. package/dist/styles.css +157 -23
  118. package/dist/types.d.ts +13 -0
  119. package/package.json +1 -1
  120. package/src/agents-view/AgentsView.tsx +431 -0
  121. package/src/components/ui/context-menu.tsx +4 -4
  122. package/src/config/config.tsx +61 -0
  123. package/src/editor/ConfirmationDialog.tsx +42 -10
  124. package/src/editor/ContentTree.tsx +20 -1
  125. package/src/editor/ContextMenu.tsx +4 -1
  126. package/src/editor/FieldList.tsx +10 -4
  127. package/src/editor/FieldListField.tsx +7 -0
  128. package/src/editor/FieldListFieldWithFallbacks.tsx +10 -0
  129. package/src/editor/MainLayout.tsx +1 -1
  130. package/src/editor/QuickItemSwitcher.tsx +217 -0
  131. package/src/editor/ai/AgentCostDisplay.tsx +59 -60
  132. package/src/editor/ai/AgentProfilesOverview.tsx +81 -0
  133. package/src/editor/ai/AgentTerminal.tsx +321 -775
  134. package/src/editor/ai/Agents.tsx +157 -91
  135. package/src/editor/ai/AiResponseMessage.tsx +12 -1
  136. package/src/editor/ai/ContextInfoBar.tsx +17 -17
  137. package/src/editor/ai/useAgentStatus.ts +6 -0
  138. package/src/editor/client/EditorShell.tsx +288 -3
  139. package/src/editor/client/hooks/useSocketMessageHandler.ts +0 -15
  140. package/src/editor/client/ui/EditorChrome.tsx +1 -1
  141. package/src/editor/commands/itemCommands.tsx +1 -0
  142. package/src/editor/control-center/parhelia-setup/Overview.tsx +184 -0
  143. package/src/editor/field-types/AttachmentEditor.tsx +13 -50
  144. package/src/editor/field-types/DropLinkEditor.tsx +2 -2
  145. package/src/editor/field-types/DropListEditor.tsx +2 -1
  146. package/src/editor/field-types/InternalLinkFieldEditor.tsx +3 -3
  147. package/src/editor/field-types/MultiLineText.tsx +3 -0
  148. package/src/editor/field-types/RawEditor.tsx +3 -0
  149. package/src/editor/field-types/SingleLineText.tsx +3 -0
  150. package/src/editor/field-types/TreeListEditor.tsx +32 -24
  151. package/src/editor/media-selector/MediaFolderBrowser.tsx +93 -9
  152. package/src/editor/media-selector/TreeSelector.tsx +1 -0
  153. package/src/editor/menubar/ActiveUsers.tsx +2 -2
  154. package/src/editor/menubar/FavoritesControls.tsx +5 -5
  155. package/src/editor/page-editor-chrome/FrameMenu.tsx +10 -1
  156. package/src/editor/page-viewer/pageModelSkeletonBuilder.ts +17 -0
  157. package/src/editor/services/agentService.ts +46 -11
  158. package/src/editor/services/aiService.ts +48 -7
  159. package/src/editor/services/contentService.ts +4 -1
  160. package/src/editor/services/editService.ts +8 -3
  161. package/src/editor/services/setupService.ts +35 -0
  162. package/src/editor/sidebar/ComponentTree.tsx +16 -1
  163. package/src/editor/sidebar/SidebarView.tsx +1 -1
  164. package/src/editor/ui/ItemSearch.tsx +3 -1
  165. package/src/editor/ui/PerfectTree.tsx +393 -42
  166. package/src/editor/utils/keyboardNavigation.ts +97 -1
  167. package/src/editor/views/SingleEditView.tsx +27 -13
  168. package/src/revision.ts +2 -2
  169. package/src/splash-screen/SplashScreen.tsx +134 -2
  170. package/src/types.ts +15 -0
@@ -18,20 +18,61 @@ export type AiProfile = {
18
18
  prompts: { prompt: string; title: string }[];
19
19
  includeEditorContextOnCreate?: boolean;
20
20
  greetingMessage?: string;
21
+ displayTitle?: string;
22
+ description?: string;
23
+ svgIcon?: string;
24
+ hiddenFromOverview?: boolean;
25
+ // Optional cost limit configured on the profile (USD)
26
+ costLimit?: number | null;
21
27
  };
22
28
 
29
+ // In-flight de-duplication and short TTL cache for AI profiles to avoid
30
+ // duplicate network requests in React StrictMode and across multiple callers.
31
+ const aiProfilesInFlight = new Map<string, Promise<AiProfile[]>>();
32
+ const aiProfilesCache = new Map<
33
+ string,
34
+ { timestamp: number; data: AiProfile[] }
35
+ >();
36
+ const AI_PROFILES_TTL_MS = 60_000; // 1 minute
37
+
38
+ function makeProfilesCacheKey(item?: ItemDescriptor): string {
39
+ if (!item) return "global";
40
+ const id = (item as any)?.id || "";
41
+ const language = (item as any)?.language ?? "";
42
+ const version = (item as any)?.version ?? "";
43
+ return `${id}:${language}:${version}`;
44
+ }
45
+
23
46
  export async function loadAiProfiles(
24
- item: ItemDescriptor,
47
+ item?: ItemDescriptor,
25
48
  ): Promise<AiProfile[]> {
26
- let url = "/alpaca/editor/agent/profiles";
27
-
28
- const response = await post<AiProfile[]>(url, item);
49
+ const url = "/alpaca/editor/agent/profiles";
50
+ const cacheKey = makeProfilesCacheKey(item);
29
51
 
30
- if (response.type !== "success") {
31
- throw new Error("Error loading AI profiles");
52
+ // Serve from cache if fresh
53
+ const cached = aiProfilesCache.get(cacheKey);
54
+ if (cached && Date.now() - cached.timestamp < AI_PROFILES_TTL_MS) {
55
+ return cached.data;
32
56
  }
33
57
 
34
- return response.data || [];
58
+ // Reuse in-flight request for the same key
59
+ const inFlight = aiProfilesInFlight.get(cacheKey);
60
+ if (inFlight) return inFlight;
61
+
62
+ const requestPromise = (async () => {
63
+ const response = await post<AiProfile[]>(url, item ?? {});
64
+ if (response.type !== "success") {
65
+ throw new Error("Error loading AI profiles");
66
+ }
67
+ const data = response.data || [];
68
+ aiProfilesCache.set(cacheKey, { timestamp: Date.now(), data });
69
+ return data;
70
+ })().finally(() => {
71
+ aiProfilesInFlight.delete(cacheKey);
72
+ });
73
+
74
+ aiProfilesInFlight.set(cacheKey, requestPromise);
75
+ return requestPromise;
35
76
  }
36
77
 
37
78
  type Message = {
@@ -49,6 +49,7 @@ export async function getChildren(
49
49
  includeEmbeddedItems: boolean,
50
50
  language: string,
51
51
  include?: string,
52
+ database: string = "master",
52
53
  ): Promise<ItemTreeNodeData[]> {
53
54
  let url =
54
55
  // configuration.services.editorService.baseUrl +
@@ -61,7 +62,9 @@ export async function getChildren(
61
62
  "&language=" +
62
63
  language +
63
64
  "&include=" +
64
- include;
65
+ include +
66
+ "&database=" +
67
+ database;
65
68
 
66
69
  url = templateIds.reduce((u, t) => u + "&templateIds=" + t, url);
67
70
 
@@ -387,20 +387,25 @@ export async function loadFieldButtons(
387
387
  return await response.json();
388
388
  }
389
389
 
390
+ export type LookupSourcesResponse = {
391
+ items: ItemIdAndName[];
392
+ database: string;
393
+ };
394
+
390
395
  export async function getLookupSources(
391
396
  field: Field,
392
397
  sessionId: string,
393
- ): Promise<ItemIdAndName[]> {
398
+ ): Promise<LookupSourcesResponse> {
394
399
  let url = "/alpaca/editor/getlookupsources";
395
400
  const fieldItem = field.descriptor.item;
396
401
 
397
- const response = await post<ItemIdAndName[]>(
402
+ const response = await post<LookupSourcesResponse>(
398
403
  url,
399
404
  { item: fieldItem, fieldId: field.id },
400
405
  sessionId,
401
406
  );
402
407
 
403
- return (await response.data) || [];
408
+ return (await response.data) || { items: [], database: "master" };
404
409
  }
405
410
 
406
411
  export async function executeCreateItem(
@@ -0,0 +1,35 @@
1
+ import { get, post } from "./serviceHelper";
2
+
3
+ export interface SetupItemDto {
4
+ key: string;
5
+ sourcePath: string;
6
+ targetPath: string;
7
+ status: "Missing" | "UpToDate" | "Outdated" | "Modified" | "Blocked";
8
+ sourceRevision?: string;
9
+ installedRevision?: string;
10
+ }
11
+
12
+ export interface SetupCategoryDto {
13
+ name: string;
14
+ items: SetupItemDto[];
15
+ }
16
+
17
+ export interface SetupStatusDto {
18
+ categories: SetupCategoryDto[];
19
+ }
20
+
21
+ export async function getSetupStatus(includeDiff: boolean = false) {
22
+ const result = await get<SetupStatusDto>(
23
+ `/alpaca/editor/setup/status?includeDiff=${includeDiff ? "true" : "false"}`,
24
+ );
25
+ return result.data as SetupStatusDto;
26
+ }
27
+
28
+ export async function applySetup(keys: string[], includeDependencies: boolean) {
29
+ const result = await post<{
30
+ createdCount: number;
31
+ updatedCount: number;
32
+ appliedKeys: string[];
33
+ }>("/alpaca/editor/setup/apply", { keys, includeDependencies });
34
+ return result.data;
35
+ }
@@ -59,6 +59,7 @@ export function ComponentTree({}) {
59
59
 
60
60
  const treeRef = useRef<HTMLDivElement>(null);
61
61
  const confirmDialogRef = useRef<ConfirmationDialogHandle>(null);
62
+ const pendingDragStartTimeoutRef = useRef<NodeJS.Timeout | null>(null);
62
63
 
63
64
  // Helper function to clean placeholder labels by removing _{guid} pattern
64
65
  function cleanPlaceholderLabel(label: string): string {
@@ -820,7 +821,7 @@ export function ComponentTree({}) {
820
821
 
821
822
  // Only create drag object for components with datasourceItem
822
823
  if (!component?.datasourceItem) return;
823
- setTimeout(() => {
824
+ pendingDragStartTimeoutRef.current = setTimeout(() => {
824
825
  const language = editContext!.page!.item.language;
825
826
  const version = editContext!.page!.item.version;
826
827
  const selectedIds =
@@ -851,11 +852,25 @@ export function ComponentTree({}) {
851
852
  // Memoize onDragEnd callback
852
853
  const handleDragEnd = useCallback(
853
854
  (event: React.DragEvent | null) => {
855
+ if (pendingDragStartTimeoutRef.current) {
856
+ clearTimeout(pendingDragStartTimeoutRef.current);
857
+ pendingDragStartTimeoutRef.current = null;
858
+ }
854
859
  editContext!.dragEnd();
855
860
  },
856
861
  [editContext],
857
862
  );
858
863
 
864
+ // Cleanup pending drag start timeout on unmount
865
+ useEffect(() => {
866
+ return () => {
867
+ if (pendingDragStartTimeoutRef.current) {
868
+ clearTimeout(pendingDragStartTimeoutRef.current);
869
+ pendingDragStartTimeoutRef.current = null;
870
+ }
871
+ };
872
+ }, []);
873
+
859
874
  if (!page) {
860
875
  if (editContext?.contentEditorItem?.hasLayout) {
861
876
  return (
@@ -38,7 +38,7 @@ export function SidebarView({
38
38
  ) : (
39
39
  <div className="mr-2">{panel.icon}</div>
40
40
  ))}
41
- <div className="mr-auto">{panel.title}</div>
41
+ <div className="mr-auto truncate">{panel.title}</div>
42
42
 
43
43
  {/* Close button - only show on the first panel */}
44
44
  {index === 0 && (
@@ -26,6 +26,7 @@ interface SearchProps {
26
26
  resultClassName?: string;
27
27
  autoFocus?: boolean;
28
28
  disabled?: boolean;
29
+ database?: string; // Database to search in (defaults to "master")
29
30
  }
30
31
 
31
32
  export const ItemSearch: React.FC<SearchProps> = ({
@@ -36,6 +37,7 @@ export const ItemSearch: React.FC<SearchProps> = ({
36
37
  resultClassName,
37
38
  autoFocus = false,
38
39
  disabled = false,
40
+ database = "master",
39
41
  }) => {
40
42
  const [query, setQuery] = useState("");
41
43
  const [results, setResults] = useState<ResultItem[]>([]);
@@ -85,7 +87,7 @@ export const ItemSearch: React.FC<SearchProps> = ({
85
87
 
86
88
  // If it looks like a path, search with skipValidation to allow exact path matching
87
89
  const result = await executeSearch({
88
- index: "master",
90
+ index: database,
89
91
  query: trimmedPrompt,
90
92
  editContext,
91
93
  rootItemIds,