@alpaca-editor/core 1.0.4184 → 1.0.4186
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/agents-view/AgentCard.d.ts +12 -0
- package/dist/agents-view/AgentCard.js +30 -0
- package/dist/agents-view/AgentCard.js.map +1 -0
- package/dist/agents-view/AgentsView.d.ts +2 -2
- package/dist/agents-view/AgentsView.js +102 -85
- package/dist/agents-view/AgentsView.js.map +1 -1
- package/dist/agents-view/ProfileAgentsGroup.d.ts +17 -0
- package/dist/agents-view/ProfileAgentsGroup.js +13 -0
- package/dist/agents-view/ProfileAgentsGroup.js.map +1 -0
- package/dist/components/ui/popover.d.ts +3 -3
- package/dist/config/config.js +8 -1
- package/dist/config/config.js.map +1 -1
- package/dist/editor/ConfirmationDialog.js.map +1 -1
- package/dist/editor/ImageEditButton.js.map +1 -1
- package/dist/editor/ai/AgentProfilesOverview.js +1 -1
- package/dist/editor/ai/AgentProfilesOverview.js.map +1 -1
- package/dist/editor/ai/Agents.js +6 -2
- package/dist/editor/ai/Agents.js.map +1 -1
- package/dist/editor/client/EditorShell.js +17 -0
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/client/ui/EditorChrome.js +1 -0
- package/dist/editor/client/ui/EditorChrome.js.map +1 -1
- package/dist/editor/commands/componentCommands.js +19 -1
- package/dist/editor/commands/componentCommands.js.map +1 -1
- package/dist/editor/field-types/DateTimeFieldEditor.js +1 -1
- package/dist/editor/field-types/DateTimeFieldEditor.js.map +1 -1
- package/dist/editor/page-editor-chrome/FrameMenu.js +7 -3
- package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
- package/dist/editor/page-viewer/PageViewerFrame.js +7 -28
- package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
- package/dist/editor/reviews/Comment.js +56 -4
- package/dist/editor/reviews/Comment.js.map +1 -1
- package/dist/editor/reviews/CommentDisplayPopover.js.map +1 -1
- package/dist/editor/reviews/CommentPopover.js +1 -1
- package/dist/editor/reviews/CommentPopover.js.map +1 -1
- package/dist/editor/reviews/SuggestionDisplayPopover.js.map +1 -1
- package/dist/editor/services/agentService.d.ts +19 -0
- package/dist/editor/services/agentService.js +39 -0
- package/dist/editor/services/agentService.js.map +1 -1
- package/dist/editor/services/aiService.d.ts +2 -0
- package/dist/editor/services/aiService.js.map +1 -1
- package/dist/editor/services/serviceHelper.d.ts +1 -0
- package/dist/editor/services/serviceHelper.js +58 -4
- package/dist/editor/services/serviceHelper.js.map +1 -1
- package/dist/editor/views/ParheliaView.d.ts +5 -0
- package/dist/editor/views/ParheliaView.js +136 -0
- package/dist/editor/views/ParheliaView.js.map +1 -0
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/styles.css +8 -6
- package/dist/tour/default-tour.js +24 -9
- package/dist/tour/default-tour.js.map +1 -1
- package/package.json +12 -8
- package/src/agents-view/AgentCard.tsx +162 -0
- package/src/agents-view/AgentsView.tsx +218 -253
- package/src/agents-view/ProfileAgentsGroup.tsx +123 -0
- package/src/config/config.tsx +10 -1
- package/src/editor/ConfirmationDialog.tsx +1 -1
- package/src/editor/ImageEditButton.tsx +4 -2
- package/src/editor/ai/AgentProfilesOverview.tsx +1 -2
- package/src/editor/ai/Agents.tsx +7 -2
- package/src/editor/client/EditorShell.tsx +18 -0
- package/src/editor/client/ui/EditorChrome.tsx +1 -0
- package/src/editor/commands/componentCommands.tsx +19 -1
- package/src/editor/field-types/DateTimeFieldEditor.tsx +5 -4
- package/src/editor/page-editor-chrome/FrameMenu.tsx +9 -3
- package/src/editor/page-viewer/PageViewerFrame.tsx +7 -36
- package/src/editor/reviews/Comment.tsx +85 -4
- package/src/editor/reviews/CommentDisplayPopover.tsx +2 -2
- package/src/editor/reviews/CommentPopover.tsx +2 -2
- package/src/editor/reviews/SuggestionDisplayPopover.tsx +1 -1
- package/src/editor/services/agentService.ts +77 -0
- package/src/editor/services/aiService.ts +4 -0
- package/src/editor/services/serviceHelper.ts +92 -28
- package/src/editor/views/ParheliaView.tsx +207 -0
- package/src/revision.ts +2 -2
- package/src/tour/default-tour.tsx +63 -48
|
@@ -517,6 +517,19 @@ export interface GetAgentsResponse {
|
|
|
517
517
|
hasMore: boolean;
|
|
518
518
|
}
|
|
519
519
|
|
|
520
|
+
export interface ProfileAgentsGroup {
|
|
521
|
+
profileId: string | null;
|
|
522
|
+
profileName: string;
|
|
523
|
+
profileSvgIcon?: string;
|
|
524
|
+
totalClosedCount: number;
|
|
525
|
+
agents: Agent[];
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
export interface GetAgentsGroupedResponse {
|
|
529
|
+
activeAgents: Agent[];
|
|
530
|
+
closedAgentsByProfile: ProfileAgentsGroup[];
|
|
531
|
+
}
|
|
532
|
+
|
|
520
533
|
/**
|
|
521
534
|
* Gets all agents for the current user with pagination and search support
|
|
522
535
|
*/
|
|
@@ -550,6 +563,70 @@ export async function getActiveAgents(
|
|
|
550
563
|
return result.data || { agents: [], totalCount: 0, hasMore: false };
|
|
551
564
|
}
|
|
552
565
|
|
|
566
|
+
/**
|
|
567
|
+
* Gets all active agents and closed agents grouped by profile for the current user
|
|
568
|
+
*/
|
|
569
|
+
export async function getAgentsGrouped(
|
|
570
|
+
searchTerm?: string,
|
|
571
|
+
includeShared: boolean = true,
|
|
572
|
+
includeOwned: boolean = true,
|
|
573
|
+
): Promise<GetAgentsGroupedResponse> {
|
|
574
|
+
const queryParams = new URLSearchParams();
|
|
575
|
+
|
|
576
|
+
if (searchTerm) queryParams.append("searchTerm", searchTerm);
|
|
577
|
+
queryParams.append("includeShared", includeShared.toString());
|
|
578
|
+
queryParams.append("includeOwned", includeOwned.toString());
|
|
579
|
+
|
|
580
|
+
const queryString = queryParams.toString();
|
|
581
|
+
const url =
|
|
582
|
+
AGENT_BASE_URL +
|
|
583
|
+
"/getAgentsGroupedByProfile" +
|
|
584
|
+
(queryString ? `?${queryString}` : "");
|
|
585
|
+
|
|
586
|
+
const result = await get<GetAgentsGroupedResponse>(url);
|
|
587
|
+
|
|
588
|
+
if (result.type !== "success") {
|
|
589
|
+
throw new Error(
|
|
590
|
+
`Failed to get grouped agents: ${result.summary || "Unknown error"} ${result.details || ""}`,
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
return result.data || { activeAgents: [], closedAgentsByProfile: [] };
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* Gets more closed agents for a specific profile
|
|
599
|
+
*/
|
|
600
|
+
export async function getClosedAgentsByProfile(
|
|
601
|
+
profileId: string,
|
|
602
|
+
skip: number,
|
|
603
|
+
limit: number,
|
|
604
|
+
searchTerm?: string,
|
|
605
|
+
): Promise<GetAgentsResponse> {
|
|
606
|
+
const queryParams = new URLSearchParams();
|
|
607
|
+
|
|
608
|
+
queryParams.append("profileId", profileId);
|
|
609
|
+
queryParams.append("skip", skip.toString());
|
|
610
|
+
queryParams.append("limit", limit.toString());
|
|
611
|
+
if (searchTerm) queryParams.append("searchTerm", searchTerm);
|
|
612
|
+
|
|
613
|
+
const queryString = queryParams.toString();
|
|
614
|
+
const url =
|
|
615
|
+
AGENT_BASE_URL +
|
|
616
|
+
"/getClosedAgentsByProfile" +
|
|
617
|
+
(queryString ? `?${queryString}` : "");
|
|
618
|
+
|
|
619
|
+
const result = await get<GetAgentsResponse>(url);
|
|
620
|
+
|
|
621
|
+
if (result.type !== "success") {
|
|
622
|
+
throw new Error(
|
|
623
|
+
`Failed to get closed agents by profile: ${result.summary || "Unknown error"} ${result.details || ""}`,
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
return result.data || { agents: [], totalCount: 0, hasMore: false };
|
|
628
|
+
}
|
|
629
|
+
|
|
553
630
|
/**
|
|
554
631
|
* Gets all closed agents for the current user
|
|
555
632
|
* @deprecated Use getActiveAgents() instead - the backend now returns all agents (including closed) by default
|
|
@@ -24,6 +24,10 @@ export type AiProfile = {
|
|
|
24
24
|
hiddenFromOverview?: boolean;
|
|
25
25
|
// Optional cost limit configured on the profile (USD)
|
|
26
26
|
costLimit?: number | null;
|
|
27
|
+
// Number of user browse history items to include (0 = disabled)
|
|
28
|
+
includeUserBrowseHistory?: number;
|
|
29
|
+
// Whether to include user favorites
|
|
30
|
+
includeUserFavorites?: boolean;
|
|
27
31
|
};
|
|
28
32
|
|
|
29
33
|
// In-flight de-duplication and short TTL cache for AI profiles to avoid
|
|
@@ -2,47 +2,102 @@ export type ExecutionResult<T> = {
|
|
|
2
2
|
type: "success" | "error" | "unauthorized";
|
|
3
3
|
summary?: string;
|
|
4
4
|
details?: string;
|
|
5
|
+
rawDetails?: string; // Original unprocessed error details (for logging/debugging)
|
|
5
6
|
response: Response;
|
|
6
7
|
data?: T;
|
|
7
8
|
};
|
|
8
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Extracts a user-friendly error message from the response.
|
|
12
|
+
* Handles HTML error pages by extracting the title or exception details.
|
|
13
|
+
* Also extracts source file information if available.
|
|
14
|
+
*/
|
|
15
|
+
function extractErrorMessage(message: string): string {
|
|
16
|
+
// Check if it's an HTML error page
|
|
17
|
+
if (message.includes("<!DOCTYPE html>") || message.includes("<html>")) {
|
|
18
|
+
let errorMessage = "";
|
|
19
|
+
|
|
20
|
+
// Try to extract the title (which usually contains the error message)
|
|
21
|
+
const titleMatch = message.match(/<title>(.*?)<\/title>/i);
|
|
22
|
+
if (titleMatch && titleMatch[1]) {
|
|
23
|
+
// Remove "Server Error" prefix if present
|
|
24
|
+
errorMessage = titleMatch[1].replace(
|
|
25
|
+
/^Server Error in '.*?' Application\.\s*/i,
|
|
26
|
+
"",
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// If no title, try h2 tag (exception message)
|
|
31
|
+
if (!errorMessage) {
|
|
32
|
+
const h2Match = message.match(/<h2>\s*<i>(.*?)<\/i>\s*<\/h2>/i);
|
|
33
|
+
if (h2Match && h2Match[1]) {
|
|
34
|
+
errorMessage = h2Match[1];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// If no h2, try Exception Details
|
|
39
|
+
if (!errorMessage) {
|
|
40
|
+
const exceptionMatch = message.match(
|
|
41
|
+
/<b>\s*Exception Details:\s*<\/b>(.*?)(?:<br>|<\/)/i,
|
|
42
|
+
);
|
|
43
|
+
if (exceptionMatch && exceptionMatch[1]) {
|
|
44
|
+
errorMessage = exceptionMatch[1].replace(/<[^>]*>/g, "").trim();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Try to extract source file and line information
|
|
49
|
+
const sourceMatch = message.match(
|
|
50
|
+
/<b>\s*Source File:\s*<\/b>\s*([^<]+)<b>\s* \s*Line:\s*<\/b>\s*(\d+)/i,
|
|
51
|
+
);
|
|
52
|
+
if (sourceMatch && sourceMatch[1] && sourceMatch[2]) {
|
|
53
|
+
const fileName = sourceMatch[1].trim().split("\\").pop();
|
|
54
|
+
errorMessage += ` (${fileName}:${sourceMatch[2]})`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (errorMessage) {
|
|
58
|
+
return errorMessage;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// If we can't parse it, just strip all HTML tags
|
|
62
|
+
const cleaned = message.replace(/<[^>]*>/g, "").trim();
|
|
63
|
+
// Limit length for toast display
|
|
64
|
+
return cleaned.length > 200 ? cleaned.substring(0, 200) + "..." : cleaned;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return message;
|
|
68
|
+
}
|
|
69
|
+
|
|
9
70
|
export async function post<T>(
|
|
10
71
|
url: string,
|
|
11
72
|
body: any,
|
|
12
|
-
session?: string
|
|
73
|
+
session?: string,
|
|
13
74
|
): Promise<ExecutionResult<T>> {
|
|
14
75
|
if (session) url += "?sessionId=" + session;
|
|
15
76
|
|
|
16
|
-
const response = await fetch(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
},
|
|
25
|
-
}
|
|
26
|
-
);
|
|
77
|
+
const response = await fetch(url, {
|
|
78
|
+
method: "POST",
|
|
79
|
+
body: JSON.stringify(body),
|
|
80
|
+
credentials: "include",
|
|
81
|
+
headers: {
|
|
82
|
+
"Content-Type": "application/json",
|
|
83
|
+
},
|
|
84
|
+
});
|
|
27
85
|
|
|
28
86
|
return handleResponse<T>(response);
|
|
29
87
|
}
|
|
30
88
|
|
|
31
89
|
export async function get<T>(
|
|
32
90
|
url: string,
|
|
33
|
-
session?: string
|
|
91
|
+
session?: string,
|
|
34
92
|
): Promise<ExecutionResult<T>> {
|
|
35
93
|
if (session) url += "?sessionId=" + session;
|
|
36
|
-
const response = await fetch(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
},
|
|
44
|
-
}
|
|
45
|
-
);
|
|
94
|
+
const response = await fetch(url, {
|
|
95
|
+
method: "GET",
|
|
96
|
+
credentials: "include",
|
|
97
|
+
headers: {
|
|
98
|
+
"Content-Type": "application/json",
|
|
99
|
+
},
|
|
100
|
+
});
|
|
46
101
|
|
|
47
102
|
return handleResponse<T>(response);
|
|
48
103
|
}
|
|
@@ -54,17 +109,20 @@ async function handleResponse<T>(
|
|
|
54
109
|
const data = await response.json();
|
|
55
110
|
return {
|
|
56
111
|
type: "error",
|
|
57
|
-
summary: data.summary,
|
|
58
|
-
details: data.details,
|
|
112
|
+
summary: data.summary ? extractErrorMessage(data.summary) : data.summary,
|
|
113
|
+
details: data.details ? extractErrorMessage(data.details) : data.details,
|
|
114
|
+
rawDetails: data.details || data.summary, // Preserve original for logging
|
|
59
115
|
response,
|
|
60
116
|
};
|
|
61
117
|
}
|
|
62
118
|
|
|
63
119
|
if (response.status === 500 || response.redirected) {
|
|
120
|
+
const rawText = await response.text();
|
|
64
121
|
return {
|
|
65
122
|
type: "error",
|
|
66
123
|
summary: "Error",
|
|
67
|
-
details:
|
|
124
|
+
details: extractErrorMessage(rawText),
|
|
125
|
+
rawDetails: rawText, // Preserve full HTML error with stack trace
|
|
68
126
|
response,
|
|
69
127
|
};
|
|
70
128
|
}
|
|
@@ -77,9 +135,15 @@ async function handleResponse<T>(
|
|
|
77
135
|
response,
|
|
78
136
|
};
|
|
79
137
|
}
|
|
80
|
-
|
|
138
|
+
|
|
81
139
|
if (response.status !== 200) {
|
|
82
|
-
|
|
140
|
+
const rawText = await response.text();
|
|
141
|
+
return {
|
|
142
|
+
type: "error",
|
|
143
|
+
response,
|
|
144
|
+
details: extractErrorMessage(rawText),
|
|
145
|
+
rawDetails: rawText, // Preserve original for logging
|
|
146
|
+
};
|
|
83
147
|
}
|
|
84
148
|
|
|
85
149
|
if (!response.headers.get("content-type")?.includes("application/json")) {
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import React, { useState, useEffect } from "react";
|
|
2
|
+
import { AgentTerminal } from "../ai/AgentTerminal";
|
|
3
|
+
import { Agent, AgentMetadata } from "../services/agentService";
|
|
4
|
+
import { useEditContext } from "../client/editContext";
|
|
5
|
+
import { AiProfile, loadAiProfiles } from "../services/aiService";
|
|
6
|
+
import { AgentProfilesOverview } from "../ai/AgentProfilesOverview";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* ParheliaView - A minimalistic, focused view for a single agent terminal
|
|
10
|
+
* This view provides a distraction-free interface with just the agent terminal centered on screen
|
|
11
|
+
*/
|
|
12
|
+
export function ParheliaView() {
|
|
13
|
+
const editContext = useEditContext();
|
|
14
|
+
const [agent, setAgent] = useState<Agent | null>(null);
|
|
15
|
+
const [initialMetadata, setInitialMetadata] = useState<
|
|
16
|
+
AgentMetadata | undefined
|
|
17
|
+
>(undefined);
|
|
18
|
+
const [availableProfiles, setAvailableProfiles] = useState<AiProfile[]>([]);
|
|
19
|
+
const [loadingProfiles, setLoadingProfiles] = useState(false);
|
|
20
|
+
|
|
21
|
+
// Load available profiles
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
let cancelled = false;
|
|
24
|
+
(async () => {
|
|
25
|
+
try {
|
|
26
|
+
setLoadingProfiles(true);
|
|
27
|
+
const profiles = await loadAiProfiles(
|
|
28
|
+
editContext?.currentItemDescriptor,
|
|
29
|
+
);
|
|
30
|
+
if (cancelled) return;
|
|
31
|
+
setAvailableProfiles(profiles || []);
|
|
32
|
+
} catch (e) {
|
|
33
|
+
console.error("Failed to load AI profiles", e);
|
|
34
|
+
} finally {
|
|
35
|
+
if (!cancelled) setLoadingProfiles(false);
|
|
36
|
+
}
|
|
37
|
+
})();
|
|
38
|
+
return () => {
|
|
39
|
+
cancelled = true;
|
|
40
|
+
};
|
|
41
|
+
}, [editContext?.currentItemDescriptor?.id]);
|
|
42
|
+
|
|
43
|
+
// Listen for external requests to add a new agent
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
const handleAddNewAgent = (ev: Event) => {
|
|
46
|
+
let metadata: AgentMetadata | undefined = undefined;
|
|
47
|
+
try {
|
|
48
|
+
const ce = ev as unknown as CustomEvent;
|
|
49
|
+
metadata = (ce.detail && (ce.detail as any).metadata) as
|
|
50
|
+
| AgentMetadata
|
|
51
|
+
| undefined;
|
|
52
|
+
} catch {}
|
|
53
|
+
|
|
54
|
+
// Create a new agent
|
|
55
|
+
const newAgent: Agent = {
|
|
56
|
+
status: "new",
|
|
57
|
+
id: crypto.randomUUID(),
|
|
58
|
+
name: `New Agent`,
|
|
59
|
+
updatedDate: new Date().toISOString(),
|
|
60
|
+
userId: "",
|
|
61
|
+
};
|
|
62
|
+
setAgent(newAgent);
|
|
63
|
+
setInitialMetadata(metadata);
|
|
64
|
+
|
|
65
|
+
// Focus the prompt after the agent mounts
|
|
66
|
+
setTimeout(() => {
|
|
67
|
+
try {
|
|
68
|
+
window.dispatchEvent(new CustomEvent("editor:focusAgentPrompt"));
|
|
69
|
+
} catch {}
|
|
70
|
+
}, 60);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
window.addEventListener(
|
|
74
|
+
"editor:addNewAgent",
|
|
75
|
+
handleAddNewAgent as EventListener,
|
|
76
|
+
);
|
|
77
|
+
return () =>
|
|
78
|
+
window.removeEventListener(
|
|
79
|
+
"editor:addNewAgent",
|
|
80
|
+
handleAddNewAgent as EventListener,
|
|
81
|
+
);
|
|
82
|
+
}, []);
|
|
83
|
+
|
|
84
|
+
// Listen for external requests to open an existing agent
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
const handleOpenAgent = (ev: Event) => {
|
|
87
|
+
try {
|
|
88
|
+
const ce = ev as unknown as CustomEvent;
|
|
89
|
+
const agentId = (ce.detail && (ce.detail as any).agentId) as
|
|
90
|
+
| string
|
|
91
|
+
| undefined;
|
|
92
|
+
|
|
93
|
+
if (!agentId) return;
|
|
94
|
+
|
|
95
|
+
// Load the agent
|
|
96
|
+
const loadedAgent: Agent = {
|
|
97
|
+
id: agentId,
|
|
98
|
+
name: "Loading...",
|
|
99
|
+
status: "running",
|
|
100
|
+
userId: "",
|
|
101
|
+
updatedDate: new Date().toISOString(),
|
|
102
|
+
};
|
|
103
|
+
setAgent(loadedAgent);
|
|
104
|
+
} catch (error) {
|
|
105
|
+
console.error("Error opening agent:", error);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
window.addEventListener(
|
|
110
|
+
"editor:openAgent",
|
|
111
|
+
handleOpenAgent as EventListener,
|
|
112
|
+
);
|
|
113
|
+
return () =>
|
|
114
|
+
window.removeEventListener(
|
|
115
|
+
"editor:openAgent",
|
|
116
|
+
handleOpenAgent as EventListener,
|
|
117
|
+
);
|
|
118
|
+
}, []);
|
|
119
|
+
|
|
120
|
+
const handleSelectProfile = (profileId: string) => {
|
|
121
|
+
try {
|
|
122
|
+
const selected = availableProfiles.find((p) => p.id === profileId);
|
|
123
|
+
const metadata = selected
|
|
124
|
+
? {
|
|
125
|
+
profile: selected.name,
|
|
126
|
+
additionalData: {
|
|
127
|
+
profileId: selected.id,
|
|
128
|
+
profileName: selected.name,
|
|
129
|
+
},
|
|
130
|
+
}
|
|
131
|
+
: undefined;
|
|
132
|
+
|
|
133
|
+
// Create a new agent with the selected profile
|
|
134
|
+
const newAgent: Agent = {
|
|
135
|
+
status: "new",
|
|
136
|
+
id: crypto.randomUUID(),
|
|
137
|
+
name: `New Agent`,
|
|
138
|
+
updatedDate: new Date().toISOString(),
|
|
139
|
+
userId: "",
|
|
140
|
+
};
|
|
141
|
+
setAgent(newAgent);
|
|
142
|
+
setInitialMetadata(metadata);
|
|
143
|
+
|
|
144
|
+
// Focus the prompt after the agent mounts
|
|
145
|
+
setTimeout(() => {
|
|
146
|
+
try {
|
|
147
|
+
window.dispatchEvent(new CustomEvent("editor:focusAgentPrompt"));
|
|
148
|
+
} catch {}
|
|
149
|
+
}, 60);
|
|
150
|
+
} catch (error) {
|
|
151
|
+
console.error("Error creating agent with profile:", error);
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// Empty state when no agent is active
|
|
156
|
+
if (!agent) {
|
|
157
|
+
return (
|
|
158
|
+
<div className="flex h-full items-center justify-center bg-gray-50 p-8">
|
|
159
|
+
<div className="w-full max-w-4xl">
|
|
160
|
+
{loadingProfiles ? (
|
|
161
|
+
<div className="text-center text-sm text-gray-500">
|
|
162
|
+
Loading profiles...
|
|
163
|
+
</div>
|
|
164
|
+
) : availableProfiles.length > 0 ? (
|
|
165
|
+
<div className="flex flex-col gap-6">
|
|
166
|
+
<div className="text-center">
|
|
167
|
+
<h2 className="text-2xl font-light tracking-wide text-gray-900">
|
|
168
|
+
parhelia
|
|
169
|
+
</h2>
|
|
170
|
+
<p className="mt-2 text-sm text-gray-500">
|
|
171
|
+
Select an AI agent profile to begin
|
|
172
|
+
</p>
|
|
173
|
+
</div>
|
|
174
|
+
<AgentProfilesOverview
|
|
175
|
+
profiles={availableProfiles}
|
|
176
|
+
onSelectProfile={handleSelectProfile}
|
|
177
|
+
/>
|
|
178
|
+
</div>
|
|
179
|
+
) : (
|
|
180
|
+
<div className="text-center">
|
|
181
|
+
<h2 className="text-2xl font-light tracking-wide text-gray-900">
|
|
182
|
+
parhelia
|
|
183
|
+
</h2>
|
|
184
|
+
<p className="mt-2 text-sm text-gray-500">
|
|
185
|
+
No agent profiles available
|
|
186
|
+
</p>
|
|
187
|
+
</div>
|
|
188
|
+
)}
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Active agent terminal view
|
|
195
|
+
return (
|
|
196
|
+
<div className="flex h-full items-center justify-center bg-gray-50">
|
|
197
|
+
<div className="h-full w-full max-w-6xl">
|
|
198
|
+
<AgentTerminal
|
|
199
|
+
agentStub={agent}
|
|
200
|
+
initialMetadata={initialMetadata}
|
|
201
|
+
profiles={availableProfiles}
|
|
202
|
+
isActive={true}
|
|
203
|
+
/>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
);
|
|
207
|
+
}
|
package/src/revision.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const version = "1.0.
|
|
2
|
-
export const buildDate = "2025-10-
|
|
1
|
+
export const version = "1.0.4186";
|
|
2
|
+
export const buildDate = "2025-10-24 01:52:39";
|
|
@@ -63,7 +63,7 @@ export function getDefaultTourSteps(
|
|
|
63
63
|
</>
|
|
64
64
|
),
|
|
65
65
|
focusElement: '#create-new-page-button, [data-testid="create-new-page-button"]',
|
|
66
|
-
bubblePosition: "
|
|
66
|
+
bubblePosition: "right",
|
|
67
67
|
waitForUserInput: async () => {
|
|
68
68
|
await waitForElement(".tour-pick-location");
|
|
69
69
|
},
|
|
@@ -261,63 +261,78 @@ export function getDefaultTourSteps(
|
|
|
261
261
|
<>
|
|
262
262
|
<ArrowRight className="inline h-4 w-4" /> Great, show me!
|
|
263
263
|
</>
|
|
264
|
-
|
|
265
|
-
|
|
264
|
+
),
|
|
265
|
+
onClick: () => nextStep("open-agents-panel"),
|
|
266
|
+
},
|
|
267
|
+
],
|
|
266
268
|
},
|
|
267
|
-
],
|
|
268
|
-
},
|
|
269
269
|
"open-agents-panel": {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
await new Promise<void>((resolve) => {
|
|
270
|
+
title: "Open AI Agents",
|
|
271
|
+
description: "Open the Agents panel to start an AI chat.",
|
|
272
|
+
focusElement: "#agents-panel-button, [data-testid='agents-panel-button']",
|
|
273
|
+
bubblePosition: "left",
|
|
274
|
+
waitForUserInput: async () => {
|
|
275
|
+
const btn = document.querySelector(
|
|
276
|
+
"#agents-panel-button, [data-testid='agents-panel-button']"
|
|
277
|
+
);
|
|
278
|
+
if (btn) {
|
|
279
|
+
await new Promise<void>((resolve) => {
|
|
281
280
|
btn.addEventListener("click", () => resolve(), { once: true });
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
await delay(500);
|
|
284
|
+
await waitForElement("[data-testid='agent-profile-card']");
|
|
285
|
+
},
|
|
286
|
+
nextStep: "choose-agent",
|
|
287
|
+
},
|
|
288
|
+
"choose-agent": {
|
|
289
|
+
title: "Choose an AI Agent",
|
|
290
|
+
description: "Choose an AI agent to assist you with your tasks.",
|
|
291
|
+
focusElement: "#agent-profile-card, [data-testid='agent-profile-card']",
|
|
292
|
+
bubblePosition: "left",
|
|
293
|
+
waitForUserInput: async () => {
|
|
294
|
+
const btn = document.querySelector(
|
|
295
|
+
"#agent-profile-card, [data-testid='agent-profile-card']"
|
|
296
|
+
);
|
|
297
|
+
if (btn) {
|
|
298
|
+
await new Promise<void>((resolve) => {
|
|
299
|
+
btn.addEventListener("click", () => resolve(), { once: true });
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
await delay(500);
|
|
303
|
+
await waitForElement("[data-testid='agent-terminal-prompt']");
|
|
304
|
+
},
|
|
305
|
+
nextStep: "start-agent-chat",
|
|
306
|
+
},
|
|
290
307
|
"start-agent-chat": {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
308
|
+
title: "Start a chat",
|
|
309
|
+
description:
|
|
310
|
+
"Type a prompt for the agent - Let AI create your whole webpage or just parts and press Enter.",
|
|
311
|
+
focusElement: "[data-testid='agent-terminal-prompt']",
|
|
312
|
+
bubblePosition: "top-left",
|
|
313
|
+
buttons: [
|
|
314
|
+
{
|
|
315
|
+
label: (
|
|
298
316
|
<>
|
|
299
317
|
<Check className="inline h-4 w-4" /> Got it
|
|
300
318
|
</>
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
319
|
+
),
|
|
320
|
+
onClick: () => nextStep("congratulations"),
|
|
321
|
+
className: "button button-primary mt-2",
|
|
322
|
+
},
|
|
323
|
+
],
|
|
324
|
+
waitForUserInput: async () => {
|
|
325
|
+
await waitForInput("[data-testid='agent-terminal-prompt'] textarea", 5);
|
|
326
|
+
},
|
|
327
|
+
nextStep: "congratulations",
|
|
304
328
|
},
|
|
305
|
-
],
|
|
306
|
-
waitForUserInput: async () => {
|
|
307
|
-
await waitForInput(
|
|
308
|
-
`[data-testid="agent-terminal-prompt"] textarea`,
|
|
309
|
-
5,
|
|
310
|
-
);
|
|
311
|
-
},
|
|
312
|
-
nextStep: "congratulations",
|
|
313
|
-
},
|
|
314
329
|
|
|
315
330
|
congratulations: {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
331
|
+
title: "Congratulations!",
|
|
332
|
+
description: "You have completed the tour and are now an AI Editor Pro!",
|
|
333
|
+
buttons: [
|
|
334
|
+
{
|
|
335
|
+
label: (
|
|
321
336
|
<>
|
|
322
337
|
<Check className="inline h-4 w-4" /> Finish Tour
|
|
323
338
|
</>
|