@parhelia/core 0.1.12844 → 0.1.12868
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 +1 -2
- package/dist/agents-view/AgentCard.js +10 -15
- package/dist/agents-view/AgentCard.js.map +1 -1
- package/dist/agents-view/AgentsSidebar.d.ts +1 -3
- package/dist/agents-view/AgentsSidebar.js +2 -3
- package/dist/agents-view/AgentsSidebar.js.map +1 -1
- package/dist/agents-view/AgentsView.js +19 -39
- package/dist/agents-view/AgentsView.js.map +1 -1
- package/dist/agents-view/AgentsWorkspaceView.js +6 -16
- package/dist/agents-view/AgentsWorkspaceView.js.map +1 -1
- package/dist/agents-view/DateAgentsGroup.d.ts +1 -2
- package/dist/agents-view/DateAgentsGroup.js +2 -2
- package/dist/agents-view/DateAgentsGroup.js.map +1 -1
- package/dist/agents-view/ProfileAgentsGroup.d.ts +1 -2
- package/dist/agents-view/ProfileAgentsGroup.js +4 -4
- package/dist/agents-view/ProfileAgentsGroup.js.map +1 -1
- package/dist/components/MarkdownDisplay.js +6 -6
- package/dist/components/MarkdownDisplay.js.map +1 -1
- package/dist/components/ui/LanguageSelectionGrid.d.ts +3 -1
- package/dist/components/ui/LanguageSelectionGrid.js +2 -2
- package/dist/components/ui/LanguageSelectionGrid.js.map +1 -1
- package/dist/components/ui/avatar.d.ts +1 -1
- package/dist/components/ui/avatar.js +1 -1
- package/dist/components/ui/avatar.js.map +1 -1
- package/dist/components/ui/sonner.js +27 -1
- package/dist/components/ui/sonner.js.map +1 -1
- package/dist/config/config.js +8 -4
- package/dist/config/config.js.map +1 -1
- package/dist/config/types/sidebar.d.ts +2 -0
- package/dist/config/types.d.ts +2 -0
- package/dist/config/types.js.map +1 -1
- package/dist/editor/ConfirmationDialog.js +2 -2
- package/dist/editor/ConfirmationDialog.js.map +1 -1
- package/dist/editor/Editor.js +19 -3
- package/dist/editor/Editor.js.map +1 -1
- package/dist/editor/ai/AgentProfileSelector.d.ts +1 -0
- package/dist/editor/ai/AgentProfileSelector.js +4 -4
- package/dist/editor/ai/AgentProfileSelector.js.map +1 -1
- package/dist/editor/ai/Agents.js +103 -390
- package/dist/editor/ai/Agents.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentGreeting.js +2 -5
- package/dist/editor/ai/terminal/components/AgentGreeting.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentSummaryAssistantResponse.d.ts +1 -1
- package/dist/editor/ai/terminal/components/AgentSummaryAssistantResponse.js +1 -1
- package/dist/editor/ai/terminal/components/AgentSummaryAssistantResponse.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentTerminalFullUpperContent.js +1 -1
- package/dist/editor/ai/terminal/components/AgentTerminalFullUpperContent.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentTerminalMessageGroups.d.ts +1 -1
- package/dist/editor/ai/terminal/components/AgentTerminalMessageGroups.js +4 -2
- package/dist/editor/ai/terminal/components/AgentTerminalMessageGroups.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentTerminalSummaryLayout.js +1 -1
- package/dist/editor/ai/terminal/components/AgentTerminalSummaryLayout.js.map +1 -1
- package/dist/editor/ai/terminal/components/AgentThinkingDots.d.ts +1 -1
- package/dist/editor/ai/terminal/components/AgentThinkingDots.js +4 -8
- package/dist/editor/ai/terminal/components/AgentThinkingDots.js.map +1 -1
- package/dist/editor/ai/terminal/components/AiResponseMessage.d.ts +2 -2
- package/dist/editor/ai/terminal/components/AiResponseMessage.js +366 -196
- package/dist/editor/ai/terminal/components/AiResponseMessage.js.map +1 -1
- package/dist/editor/ai/terminal/components/InitialThinkingSplash.d.ts +1 -3
- package/dist/editor/ai/terminal/components/InitialThinkingSplash.js +2 -6
- package/dist/editor/ai/terminal/components/InitialThinkingSplash.js.map +1 -1
- package/dist/editor/ai/terminal/components/ToolCallDisplay.js +26 -52
- package/dist/editor/ai/terminal/components/ToolCallDisplay.js.map +1 -1
- package/dist/editor/ai/terminal/components/UserMessage.d.ts +2 -1
- package/dist/editor/ai/terminal/components/UserMessage.js +25 -6
- package/dist/editor/ai/terminal/components/UserMessage.js.map +1 -1
- package/dist/editor/client/AboutDialog.js +3 -3
- package/dist/editor/client/AboutDialog.js.map +1 -1
- package/dist/editor/client/EditorShell.d.ts +2 -1
- package/dist/editor/client/EditorShell.js +7 -5
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/client/hooks/useEditorWebSocket.d.ts +1 -0
- package/dist/editor/client/hooks/useEditorWebSocket.js +5 -2
- package/dist/editor/client/hooks/useEditorWebSocket.js.map +1 -1
- package/dist/editor/client/pageModelBuilder.d.ts +1 -0
- package/dist/editor/client/pageModelBuilder.js +54 -11
- package/dist/editor/client/pageModelBuilder.js.map +1 -1
- package/dist/editor/client/ui/EditorChrome.js +1 -1
- package/dist/editor/client/ui/EditorChrome.js.map +1 -1
- package/dist/editor/context-menu/InsertMenu.js +2 -2
- package/dist/editor/context-menu/InsertMenu.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/ManualBrowser.d.ts +7 -0
- package/dist/editor/menubar/toolbar-sections/ManualBrowser.js +160 -15
- package/dist/editor/menubar/toolbar-sections/ManualBrowser.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/UtilityControls.js +2 -2
- package/dist/editor/menubar/toolbar-sections/UtilityControls.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/ViewportControls.js +2 -1
- package/dist/editor/menubar/toolbar-sections/ViewportControls.js.map +1 -1
- package/dist/editor/page-editor-chrome/CommentHighlightings.js +108 -94
- package/dist/editor/page-editor-chrome/CommentHighlightings.js.map +1 -1
- package/dist/editor/page-editor-chrome/FeedbackHighlightBadge.d.ts +17 -0
- package/dist/editor/page-editor-chrome/FeedbackHighlightBadge.js +33 -0
- package/dist/editor/page-editor-chrome/FeedbackHighlightBadge.js.map +1 -0
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js +5 -12
- package/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -1
- package/dist/editor/page-editor-chrome/SuggestionHighlightings.js +50 -17
- package/dist/editor/page-editor-chrome/SuggestionHighlightings.js.map +1 -1
- package/dist/editor/page-viewer/PageViewer.js +43 -4
- package/dist/editor/page-viewer/PageViewer.js.map +1 -1
- package/dist/editor/page-viewer/PageViewerFrame.js +84 -13
- package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
- package/dist/editor/page-viewer/pageModelSkeletonBuilder.js +377 -21
- package/dist/editor/page-viewer/pageModelSkeletonBuilder.js.map +1 -1
- package/dist/editor/pageModel.d.ts +3 -0
- package/dist/editor/pageModel.js +12 -1
- package/dist/editor/pageModel.js.map +1 -1
- package/dist/editor/reviews/CommentDisplayPopover.js +3 -2
- package/dist/editor/reviews/CommentDisplayPopover.js.map +1 -1
- package/dist/editor/reviews/CommentEditor.d.ts +3 -1
- package/dist/editor/reviews/CommentEditor.js +36 -8
- package/dist/editor/reviews/CommentEditor.js.map +1 -1
- package/dist/editor/reviews/CommentPopover.js +3 -2
- package/dist/editor/reviews/CommentPopover.js.map +1 -1
- package/dist/editor/reviews/CommentView.js +7 -9
- package/dist/editor/reviews/CommentView.js.map +1 -1
- package/dist/editor/reviews/Comments.js +6 -5
- package/dist/editor/reviews/Comments.js.map +1 -1
- package/dist/editor/reviews/FeedbackCard.d.ts +2 -1
- package/dist/editor/reviews/FeedbackCard.js +8 -4
- package/dist/editor/reviews/FeedbackCard.js.map +1 -1
- package/dist/editor/reviews/LatestFeedback.js +2 -3
- package/dist/editor/reviews/LatestFeedback.js.map +1 -1
- package/dist/editor/reviews/MentionText.js +2 -1
- package/dist/editor/reviews/MentionText.js.map +1 -1
- package/dist/editor/reviews/SuggestedEdit.js +47 -27
- package/dist/editor/reviews/SuggestedEdit.js.map +1 -1
- package/dist/editor/reviews/SuggestionCommentThread.js +3 -3
- package/dist/editor/reviews/SuggestionCommentThread.js.map +1 -1
- package/dist/editor/reviews/SuggestionDisplayPopover.js +7 -16
- package/dist/editor/reviews/SuggestionDisplayPopover.js.map +1 -1
- package/dist/editor/reviews/feedbackAvatar.d.ts +7 -0
- package/dist/editor/reviews/feedbackAvatar.js +41 -0
- package/dist/editor/reviews/feedbackAvatar.js.map +1 -1
- package/dist/editor/reviews/feedbackSidebarText.d.ts +2 -0
- package/dist/editor/reviews/feedbackSidebarText.js +3 -0
- package/dist/editor/reviews/feedbackSidebarText.js.map +1 -0
- package/dist/editor/services/contentService.js +5 -18
- package/dist/editor/services/contentService.js.map +1 -1
- package/dist/editor/settings/SettingsView.js +1 -1
- package/dist/editor/settings/SettingsView.js.map +1 -1
- package/dist/editor/settings/panels/AgentsPanel.js +3 -3
- package/dist/editor/settings/panels/AgentsPanel.js.map +1 -1
- package/dist/editor/settings/panels/NotificationSubscriptionsPanel.js +2 -2
- package/dist/editor/settings/panels/NotificationSubscriptionsPanel.js.map +1 -1
- package/dist/editor/settings/panels/ProjectTemplateAgentPanel.d.ts +2 -1
- package/dist/editor/settings/panels/ProjectTemplateAgentPanel.js +3 -2
- package/dist/editor/settings/panels/ProjectTemplateAgentPanel.js.map +1 -1
- package/dist/editor/settings/panels/ProjectTemplateSelectorList.js +4 -4
- package/dist/editor/settings/panels/ProjectTemplateSelectorList.js.map +1 -1
- package/dist/editor/settings/panels/ProjectTemplatesPanel.js +9 -1
- package/dist/editor/settings/panels/ProjectTemplatesPanel.js.map +1 -1
- package/dist/editor/settings/status/coreStatusChecks.js +52 -2
- package/dist/editor/settings/status/coreStatusChecks.js.map +1 -1
- package/dist/editor/sidebar/SidebarPanel.js +2 -2
- package/dist/editor/sidebar/SidebarPanel.js.map +1 -1
- package/dist/editor/sidebar/SidebarStack.js +1 -0
- package/dist/editor/sidebar/SidebarStack.js.map +1 -1
- package/dist/editor/ui/Icons.d.ts +1 -1
- package/dist/editor/ui/Icons.js +2 -2
- package/dist/editor/ui/Icons.js.map +1 -1
- package/dist/editor/ui/PublishItemDialog.js +36 -71
- package/dist/editor/ui/PublishItemDialog.js.map +1 -1
- package/dist/editor/ui/SimpleIconButton.d.ts +1 -0
- package/dist/editor/ui/SimpleIconButton.js +2 -2
- package/dist/editor/ui/SimpleIconButton.js.map +1 -1
- package/dist/editor/ui/SimpleMenu.js +1 -1
- package/dist/editor/ui/SimpleMenu.js.map +1 -1
- package/dist/editor/ui/SimpleTabs.d.ts +2 -1
- package/dist/editor/ui/SimpleTabs.js +2 -2
- package/dist/editor/ui/SimpleTabs.js.map +1 -1
- package/dist/editor/ui/Splitter.d.ts +1 -0
- package/dist/editor/ui/Splitter.js +4 -3
- package/dist/editor/ui/Splitter.js.map +1 -1
- package/dist/editor/utils.d.ts +8 -2
- package/dist/editor/utils.js +46 -35
- package/dist/editor/utils.js.map +1 -1
- package/dist/editor/version-diff/versionDiffTargets.js +8 -15
- package/dist/editor/version-diff/versionDiffTargets.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/splash-screen/DialogWrappers.js +2 -2
- package/dist/splash-screen/DialogWrappers.js.map +1 -1
- package/dist/splash-screen/RecentPages.js +7 -7
- package/dist/splash-screen/RecentPages.js.map +1 -1
- package/dist/task-board/TaskBoardWorkspace.js +1 -1
- package/dist/task-board/TaskBoardWorkspace.js.map +1 -1
- package/dist/tour/Tour.js +1 -1
- package/dist/tour/Tour.js.map +1 -1
- package/package.json +1 -1
- package/styles.css +5 -0
|
@@ -8,15 +8,19 @@ import { X, Brain, ChevronDown, ChevronRight, Loader2, Undo2, Check, } from "luc
|
|
|
8
8
|
import { Button } from "../../../../components/ui/button";
|
|
9
9
|
import { Checkbox } from "../../../../components/ui/checkbox";
|
|
10
10
|
import { Tooltip, TooltipTrigger, TooltipContent, } from "../../../../components/ui/tooltip";
|
|
11
|
-
import { SecretAgentIcon } from "../../../ui/Icons";
|
|
12
11
|
import { CopyButton } from "../../../../components/ui/copy-button";
|
|
13
|
-
import { sanitizeHtml
|
|
12
|
+
import { sanitizeHtml } from "../../../../lib/sanitize";
|
|
14
13
|
// Helper to extract partial quick actions from potentially incomplete JSON during streaming
|
|
15
14
|
const extractPartialQuickActions = (jsonText) => {
|
|
16
15
|
const actions = [];
|
|
16
|
+
let headline;
|
|
17
17
|
// First try to parse complete JSON
|
|
18
18
|
try {
|
|
19
19
|
const parsed = JSON.parse(jsonText);
|
|
20
|
+
headline =
|
|
21
|
+
!Array.isArray(parsed) && typeof parsed?.headline === "string"
|
|
22
|
+
? parsed.headline.trim() || undefined
|
|
23
|
+
: undefined;
|
|
20
24
|
const rawActions = Array.isArray(parsed)
|
|
21
25
|
? parsed
|
|
22
26
|
: parsed?.actions || parsed?.buttons || parsed?.choices || [];
|
|
@@ -46,11 +50,20 @@ const extractPartialQuickActions = (jsonText) => {
|
|
|
46
50
|
}
|
|
47
51
|
});
|
|
48
52
|
}
|
|
49
|
-
return actions;
|
|
53
|
+
return { headline, actions };
|
|
50
54
|
}
|
|
51
55
|
catch (e) {
|
|
52
56
|
// JSON is incomplete, try to extract whatever complete action objects we can find
|
|
53
57
|
}
|
|
58
|
+
const headlineMatch = jsonText.match(/"(?:headline|title)"\s*:\s*"([^"\\]*(\\.[^"\\]*)*)"/);
|
|
59
|
+
if (headlineMatch?.[1]) {
|
|
60
|
+
try {
|
|
61
|
+
headline = JSON.parse(`"${headlineMatch[1]}"`).trim() || undefined;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
headline = headlineMatch[1].trim() || undefined;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
54
67
|
// Look for individual action objects in the partial JSON
|
|
55
68
|
// Match patterns like: { "label": "...", ... }
|
|
56
69
|
const labelPattern = /"(?:label|text)"\s*:\s*"([^"\\]*(\\.[^"\\]*)*)"/g;
|
|
@@ -123,7 +136,7 @@ const extractPartialQuickActions = (jsonText) => {
|
|
|
123
136
|
// Skip malformed objects
|
|
124
137
|
}
|
|
125
138
|
}
|
|
126
|
-
return actions;
|
|
139
|
+
return { headline, actions };
|
|
127
140
|
};
|
|
128
141
|
function parseContentSegments(content, hideIncomplete) {
|
|
129
142
|
if (!content)
|
|
@@ -255,9 +268,9 @@ function parseContentSegments(content, hideIncomplete) {
|
|
|
255
268
|
// Incomplete fenced block during streaming
|
|
256
269
|
if (hideIncomplete && pick.type === "quick") {
|
|
257
270
|
// Try to parse partial quick actions and show what we have so far
|
|
258
|
-
const
|
|
259
|
-
if (
|
|
260
|
-
segments.push({ kind: "actions",
|
|
271
|
+
const partialActionGroup = extractPartialQuickActions(jsonText);
|
|
272
|
+
if (partialActionGroup.actions.length > 0) {
|
|
273
|
+
segments.push({ kind: "actions", ...partialActionGroup });
|
|
261
274
|
}
|
|
262
275
|
break;
|
|
263
276
|
}
|
|
@@ -380,7 +393,10 @@ function parseContentSegments(content, hideIncomplete) {
|
|
|
380
393
|
});
|
|
381
394
|
}
|
|
382
395
|
if (actions.length > 0) {
|
|
383
|
-
|
|
396
|
+
const headline = typeof parsed?.headline === "string"
|
|
397
|
+
? parsed.headline.trim() || undefined
|
|
398
|
+
: undefined;
|
|
399
|
+
segments.push({ kind: "actions", headline, actions });
|
|
384
400
|
}
|
|
385
401
|
}
|
|
386
402
|
else if (pick.type === "todo") {
|
|
@@ -448,9 +464,9 @@ function parseContentSegments(content, hideIncomplete) {
|
|
|
448
464
|
// Incomplete plain JSON block during streaming
|
|
449
465
|
if (hideIncomplete && pick.type === "quick") {
|
|
450
466
|
// Try to parse partial quick actions and show what we have so far
|
|
451
|
-
const
|
|
452
|
-
if (
|
|
453
|
-
segments.push({ kind: "actions",
|
|
467
|
+
const partialActionGroup = extractPartialQuickActions(jsonText);
|
|
468
|
+
if (partialActionGroup.actions.length > 0) {
|
|
469
|
+
segments.push({ kind: "actions", ...partialActionGroup });
|
|
454
470
|
}
|
|
455
471
|
break;
|
|
456
472
|
}
|
|
@@ -498,7 +514,10 @@ function parseContentSegments(content, hideIncomplete) {
|
|
|
498
514
|
});
|
|
499
515
|
}
|
|
500
516
|
if (actions.length > 0) {
|
|
501
|
-
|
|
517
|
+
const headline = typeof parsed?.headline === "string"
|
|
518
|
+
? parsed.headline.trim() || undefined
|
|
519
|
+
: undefined;
|
|
520
|
+
segments.push({ kind: "actions", headline, actions });
|
|
502
521
|
}
|
|
503
522
|
}
|
|
504
523
|
else {
|
|
@@ -618,17 +637,21 @@ function JsonBlockDisplay({ data, raw, className, defaultCollapsed = false, }) {
|
|
|
618
637
|
return (_jsxs("div", { className: `border-border-default bg-neutral-grey-5 my-2 overflow-hidden rounded-lg border ${className || ""}`, children: [_jsxs("div", { className: "border-border-default bg-neutral-grey-5 flex items-center justify-between border-b px-3 py-2", children: [_jsxs("button", { onClick: () => setIsExpanded(!isExpanded), className: "text-neutral-grey-100 hover:text-neutral-grey-100 flex items-center gap-2 text-xs font-medium", children: [isExpanded ? _jsx(ChevronDown, { size: 14 }) : _jsx(ChevronRight, { size: 14 }), _jsx("span", { children: getTitle() })] }), _jsx("button", { onClick: handleCopy, className: "badge-pad text-neutral-grey-50 hover:bg-neutral-grey-10 hover:text-neutral-grey-100 rounded text-xs transition-colors", children: isCopied ? "Copied!" : "Copy" })] }), isExpanded && (_jsx("div", { className: "overflow-x-auto p-3", children: data ? (_jsx("pre", { className: "font-mono text-[11px] leading-relaxed", children: renderJsonValue(data) })) : (_jsx("pre", { className: "text-neutral-grey-50 font-mono text-[11px] leading-relaxed whitespace-pre-wrap", children: raw })) }))] }));
|
|
619
638
|
}
|
|
620
639
|
function simpleFormatToHtml(text) {
|
|
640
|
+
const stripLegacyFontTags = (value) => value
|
|
641
|
+
.replace(/<\/?font\b[^>]*>/gi, "")
|
|
642
|
+
.replace(/<\/?font\b(?:(?!>)[\s\S])*?>/gi, "");
|
|
643
|
+
const normalizedText = stripLegacyFontTags(text);
|
|
621
644
|
//Inline formatting
|
|
622
645
|
const format = (s) => s
|
|
623
|
-
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, text, url) => `<a href="${url}"
|
|
624
|
-
.replace(/^######\s+(.+)$/,
|
|
625
|
-
.replace(/^#####\s+(.+)$/,
|
|
626
|
-
.replace(/^####\s+(.+)$/,
|
|
627
|
-
.replace(/^###\s+(.+)$/,
|
|
628
|
-
.replace(/^##\s+(.+)$/,
|
|
629
|
-
.replace(/^#\s+(.+)$/,
|
|
646
|
+
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, text, url) => `<a href="${url}" target="_blank" rel="noopener noreferrer">${text.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>")}</a>`)
|
|
647
|
+
.replace(/^######\s+(.+)$/, "<h6>$1</h6>")
|
|
648
|
+
.replace(/^#####\s+(.+)$/, "<h5>$1</h5>")
|
|
649
|
+
.replace(/^####\s+(.+)$/, "<h4>$1</h4>")
|
|
650
|
+
.replace(/^###\s+(.+)$/, "<h3>$1</h3>")
|
|
651
|
+
.replace(/^##\s+(.+)$/, "<h2>$1</h2>")
|
|
652
|
+
.replace(/^#\s+(.+)$/, "<h1>$1</h1>")
|
|
630
653
|
.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>");
|
|
631
|
-
const lines =
|
|
654
|
+
const lines = normalizedText.split(/\r?\n/);
|
|
632
655
|
const blocks = [];
|
|
633
656
|
let i = 0;
|
|
634
657
|
while (i < lines.length) {
|
|
@@ -640,7 +663,7 @@ function simpleFormatToHtml(text) {
|
|
|
640
663
|
const t = line.trim();
|
|
641
664
|
// Sepperator Lines
|
|
642
665
|
if (/^[\-\*\_]{3,}$/.test(t)) {
|
|
643
|
-
blocks.push(
|
|
666
|
+
blocks.push("<hr />");
|
|
644
667
|
i++;
|
|
645
668
|
continue;
|
|
646
669
|
}
|
|
@@ -668,15 +691,14 @@ function simpleFormatToHtml(text) {
|
|
|
668
691
|
break;
|
|
669
692
|
}
|
|
670
693
|
if (rows.length > 0 && rows[0]) {
|
|
671
|
-
let html =
|
|
672
|
-
rows[0].forEach((c) => (html += `<th
|
|
694
|
+
let html = "<table><thead><tr>";
|
|
695
|
+
rows[0].forEach((c) => (html += `<th>${format(c)}</th>`));
|
|
673
696
|
html += "</tr></thead>";
|
|
674
697
|
if (rows.length > 1) {
|
|
675
698
|
html += "<tbody>";
|
|
676
699
|
for (let k = 1; k < rows.length; k++) {
|
|
677
|
-
html +=
|
|
678
|
-
|
|
679
|
-
rows[k]?.forEach((c) => (html += `<td style="padding: 0.375rem 0.5rem; color: var(--color-neutral-grey-50);">${format(c)}</td>`));
|
|
700
|
+
html += "<tr>";
|
|
701
|
+
rows[k]?.forEach((c) => (html += `<td>${format(c)}</td>`));
|
|
680
702
|
html += "</tr>";
|
|
681
703
|
}
|
|
682
704
|
html += "</tbody>";
|
|
@@ -706,16 +728,12 @@ function simpleFormatToHtml(text) {
|
|
|
706
728
|
j++;
|
|
707
729
|
}
|
|
708
730
|
if (listLines.length > 0) {
|
|
709
|
-
const listStyleByTag = {
|
|
710
|
-
ul: "list-style: disc;",
|
|
711
|
-
ol: "list-style: decimal;",
|
|
712
|
-
};
|
|
713
731
|
const indentStack = [];
|
|
714
732
|
const tagStack = [];
|
|
715
733
|
let html = "";
|
|
716
734
|
let itemOpen = false;
|
|
717
735
|
const openList = (tag, indent) => {
|
|
718
|
-
html += `<${tag}
|
|
736
|
+
html += `<${tag}>`;
|
|
719
737
|
tagStack.push(tag);
|
|
720
738
|
indentStack.push(indent);
|
|
721
739
|
};
|
|
@@ -748,8 +766,7 @@ function simpleFormatToHtml(text) {
|
|
|
748
766
|
if (currentIndent === undefined ||
|
|
749
767
|
(entry.indent !== currentIndent && entry.indent > currentIndent)) {
|
|
750
768
|
if (!itemOpen) {
|
|
751
|
-
html +=
|
|
752
|
-
'<li style="margin: 0.25rem 0; color: var(--color-neutral-grey-50);">';
|
|
769
|
+
html += "<li>";
|
|
753
770
|
itemOpen = true;
|
|
754
771
|
}
|
|
755
772
|
openList(tag, entry.indent);
|
|
@@ -766,7 +783,7 @@ function simpleFormatToHtml(text) {
|
|
|
766
783
|
}
|
|
767
784
|
}
|
|
768
785
|
closeItem();
|
|
769
|
-
html += `<li
|
|
786
|
+
html += `<li>${format(entry.content)}`;
|
|
770
787
|
itemOpen = true;
|
|
771
788
|
}
|
|
772
789
|
while (tagStack.length > 0)
|
|
@@ -801,6 +818,154 @@ function simpleFormatToHtml(text) {
|
|
|
801
818
|
}
|
|
802
819
|
return sanitizeHtml(result.replace(/<\/(h[1-6])><br\/>/g, "</$1>"));
|
|
803
820
|
}
|
|
821
|
+
const assistantMessageTextClassName = [
|
|
822
|
+
"max-w-none text-xs leading-5 text-neutral-grey-100 select-text",
|
|
823
|
+
"[&_a]:text-neutral-grey-100 [&_a]:underline [&_a]:underline-offset-2",
|
|
824
|
+
"[&_strong]:font-semibold [&_strong]:text-neutral-grey-100",
|
|
825
|
+
"[&_h1]:mt-0 [&_h1]:mb-3 [&_h1]:text-[16px] [&_h1]:leading-6 [&_h1]:font-semibold [&_h1]:text-neutral-grey-100",
|
|
826
|
+
"[&_h2]:mt-3 [&_h2]:mb-1.5 [&_h2]:text-[15px] [&_h2]:leading-5 [&_h2]:font-semibold [&_h2]:text-neutral-grey-100",
|
|
827
|
+
"[&_h3]:mt-2.5 [&_h3]:mb-1 [&_h3]:text-[13px] [&_h3]:leading-5 [&_h3]:font-semibold [&_h3]:text-neutral-grey-100",
|
|
828
|
+
"[&_h4]:mt-2 [&_h4]:mb-1 [&_h4]:text-[12px] [&_h4]:leading-5 [&_h4]:font-semibold [&_h4]:text-neutral-grey-100",
|
|
829
|
+
"[&_h5]:mt-2 [&_h5]:mb-1 [&_h5]:text-[12px] [&_h5]:leading-5 [&_h5]:font-semibold [&_h5]:text-neutral-grey-100",
|
|
830
|
+
"[&_h6]:mt-2 [&_h6]:mb-1 [&_h6]:text-[12px] [&_h6]:leading-5 [&_h6]:font-semibold [&_h6]:text-neutral-grey-100",
|
|
831
|
+
"[&_ul]:my-1.5 [&_ul]:list-disc [&_ul]:pl-5",
|
|
832
|
+
"[&_ol]:my-1.5 [&_ol]:list-decimal [&_ol]:pl-5",
|
|
833
|
+
"[&_li]:my-0.5 [&_li]:pl-1 [&_li]:leading-5 [&_li]:text-neutral-grey-100",
|
|
834
|
+
"[&_li::marker]:text-neutral-grey-100",
|
|
835
|
+
"[&_table]:my-2 [&_table]:text-neutral-grey-100",
|
|
836
|
+
"[&_th]:px-2 [&_th]:py-1.5 [&_th]:text-neutral-grey-100",
|
|
837
|
+
"[&_td]:px-2 [&_td]:py-1.5 [&_td]:text-neutral-grey-100",
|
|
838
|
+
].join(" ");
|
|
839
|
+
const cleanToolFunctionName = (name) => {
|
|
840
|
+
return (name || "")
|
|
841
|
+
.replace(" (approved)", "")
|
|
842
|
+
.replace(" (rejected)", "")
|
|
843
|
+
.replace(" (pending approval)", "")
|
|
844
|
+
.trim();
|
|
845
|
+
};
|
|
846
|
+
const getToolFunctionName = (toolCall) => {
|
|
847
|
+
return cleanToolFunctionName(toolCall.function?.name || toolCall.displayName || "");
|
|
848
|
+
};
|
|
849
|
+
const isActivityItem = (item) => {
|
|
850
|
+
if (item.type === "toolcalls") {
|
|
851
|
+
return item.toolCalls.length > 0;
|
|
852
|
+
}
|
|
853
|
+
return (item.segment.kind === "reasoning" && item.segment.text.trim().length > 0);
|
|
854
|
+
};
|
|
855
|
+
const isVisibleUserDirectedItem = (item) => {
|
|
856
|
+
if (item.type !== "segment" || item.segment.kind === "reasoning") {
|
|
857
|
+
return false;
|
|
858
|
+
}
|
|
859
|
+
const segment = item.segment;
|
|
860
|
+
if (segment.kind === "text") {
|
|
861
|
+
return segment.text.trim().length > 0;
|
|
862
|
+
}
|
|
863
|
+
if (segment.kind === "actions") {
|
|
864
|
+
return segment.actions.length > 0;
|
|
865
|
+
}
|
|
866
|
+
if (segment.kind === "todo") {
|
|
867
|
+
return segment.items.length > 0 || !!segment.title?.trim();
|
|
868
|
+
}
|
|
869
|
+
if (segment.kind === "media") {
|
|
870
|
+
return segment.items.length > 0;
|
|
871
|
+
}
|
|
872
|
+
if (segment.kind === "json") {
|
|
873
|
+
return (!!segment.raw.trim() ||
|
|
874
|
+
(segment.data !== null && segment.data !== undefined));
|
|
875
|
+
}
|
|
876
|
+
return false;
|
|
877
|
+
};
|
|
878
|
+
const groupActivityItems = (flatItems) => {
|
|
879
|
+
const displayItems = [];
|
|
880
|
+
const activityEntries = [];
|
|
881
|
+
const flushActivityEntries = () => {
|
|
882
|
+
const entries = activityEntries;
|
|
883
|
+
if (entries.length === 0) {
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
const first = entries[0];
|
|
887
|
+
if (entries.length === 1) {
|
|
888
|
+
displayItems.push({
|
|
889
|
+
type: "single",
|
|
890
|
+
entry: first,
|
|
891
|
+
key: `item-${first.index}`,
|
|
892
|
+
});
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
const last = entries[entries.length - 1];
|
|
896
|
+
displayItems.push({
|
|
897
|
+
type: "activity-group",
|
|
898
|
+
entries,
|
|
899
|
+
key: `activity-${first.index}-${last.index}`,
|
|
900
|
+
});
|
|
901
|
+
};
|
|
902
|
+
flatItems.forEach((item, index) => {
|
|
903
|
+
if (isActivityItem(item)) {
|
|
904
|
+
activityEntries.push({ item, index });
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
if (isVisibleUserDirectedItem(item)) {
|
|
908
|
+
flushActivityEntries();
|
|
909
|
+
displayItems.push({
|
|
910
|
+
type: "single",
|
|
911
|
+
entry: { item, index },
|
|
912
|
+
key: `item-${index}`,
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
});
|
|
916
|
+
flushActivityEntries();
|
|
917
|
+
return displayItems;
|
|
918
|
+
};
|
|
919
|
+
function ActivityBlockGroup({ entries, isLive, renderEntry, }) {
|
|
920
|
+
const toolCalls = entries.flatMap((entry) => entry.item.type === "toolcalls" ? entry.item.toolCalls : []);
|
|
921
|
+
const thinkingCount = entries.filter((entry) => entry.item.type === "segment" && entry.item.segment.kind === "reasoning").length;
|
|
922
|
+
const toolCallCount = toolCalls.length;
|
|
923
|
+
const toolNames = [
|
|
924
|
+
...new Set(toolCalls.map(getToolFunctionName).filter(Boolean)),
|
|
925
|
+
];
|
|
926
|
+
const errorCount = toolCalls.filter((toolCall) => {
|
|
927
|
+
const rawName = toolCall.function?.name || toolCall.displayName || "";
|
|
928
|
+
const isRejected = rawName.toLowerCase().includes("(rejected)");
|
|
929
|
+
return !!toolCall.function?.error || isRejected;
|
|
930
|
+
}).length;
|
|
931
|
+
const hasPendingApproval = toolCalls.some((toolCall) => {
|
|
932
|
+
const rawName = toolCall.function?.name || toolCall.displayName || "";
|
|
933
|
+
return (!!toolCall.requiresApproval &&
|
|
934
|
+
!rawName.includes("(approved)") &&
|
|
935
|
+
!rawName.includes("(rejected)"));
|
|
936
|
+
});
|
|
937
|
+
const hasIncompleteToolCall = toolCalls.some((toolCall) => {
|
|
938
|
+
return (!toolCall.isCompleted &&
|
|
939
|
+
!toolCall.function?.result &&
|
|
940
|
+
!toolCall.function?.error);
|
|
941
|
+
});
|
|
942
|
+
const [isExpanded, setIsExpanded] = useState(hasPendingApproval);
|
|
943
|
+
const summaryParts = [
|
|
944
|
+
toolCallCount > 0
|
|
945
|
+
? `${toolCallCount} tool call${toolCallCount !== 1 ? "s" : ""}`
|
|
946
|
+
: null,
|
|
947
|
+
thinkingCount > 0
|
|
948
|
+
? `${thinkingCount} thinking block${thinkingCount !== 1 ? "s" : ""}`
|
|
949
|
+
: null,
|
|
950
|
+
].filter(Boolean);
|
|
951
|
+
const detailsText = toolNames.length <= 3
|
|
952
|
+
? toolNames.join(", ")
|
|
953
|
+
: `${toolNames.slice(0, 2).join(", ")} +${toolNames.length - 2} more`;
|
|
954
|
+
const isActive = !errorCount && (isLive || hasIncompleteToolCall);
|
|
955
|
+
useEffect(() => {
|
|
956
|
+
if (hasPendingApproval) {
|
|
957
|
+
setIsExpanded(true);
|
|
958
|
+
}
|
|
959
|
+
}, [hasPendingApproval]);
|
|
960
|
+
return (_jsxs("div", { className: "border-border-default my-2 overflow-hidden rounded-lg border", "data-testid": "agent-activity-group", children: [_jsxs("button", { type: "button", className: "group text-neutral-grey-50 hover:bg-neutral-grey-5/60 hover:text-neutral-grey-100 flex w-full cursor-pointer items-center gap-1.5 px-2 py-1.5 text-left text-xs transition-all", onClick: () => {
|
|
961
|
+
setIsExpanded(!isExpanded);
|
|
962
|
+
}, "aria-expanded": isExpanded, "data-testid": "agent-activity-group-toggle", children: [_jsx("div", { className: "flex h-4 w-4 shrink-0 items-center justify-center transition-transform group-hover:scale-110", children: isExpanded ? (_jsx(ChevronDown, { size: 14, strokeWidth: 1.5, className: "text-neutral-grey-50" })) : (_jsx(ChevronRight, { size: 14, strokeWidth: 1.5, className: "text-neutral-grey-50" })) }), _jsx("span", { className: `shrink-0 leading-4 font-medium ${isActive ? "animate-text-shimmer" : ""}`, children: summaryParts.join(", ") }), detailsText && (_jsx("span", { className: "text-neutral-grey-50 min-w-0 flex-1 truncate text-[10px] leading-4", children: detailsText })), errorCount > 0 && (_jsxs("span", { className: "text-feedback-red shrink-0 text-[10px] leading-4", children: ["(", errorCount, " error", errorCount !== 1 ? "s" : "", ")"] })), _jsx("div", { className: "ml-auto flex h-4 w-4 shrink-0 items-center justify-center", children: errorCount > 0 ? (_jsx(XCircleLike, {})) : isActive ? (_jsx(Loader2, { className: "text-neutral-grey-50 h-3.5 w-3.5 animate-spin", strokeWidth: 1.5 })) : (_jsx(Check, { className: "text-feedback-green h-3.5 w-3.5", strokeWidth: 2 })) })] }), _jsx("div", { className: "grid transition-[grid-template-rows] duration-200 ease-out motion-reduce:transition-none", style: {
|
|
963
|
+
gridTemplateRows: isExpanded ? "1fr" : "0fr",
|
|
964
|
+
}, "aria-hidden": !isExpanded, "data-testid": "agent-activity-group-content", children: _jsx("div", { className: "min-h-0 overflow-hidden", children: _jsx("div", { className: "border-border-default/60 border-t px-2 py-1", children: entries.map((entry) => renderEntry(entry)) }) }) })] }));
|
|
965
|
+
}
|
|
966
|
+
function XCircleLike() {
|
|
967
|
+
return (_jsx("span", { className: "border-feedback-red text-feedback-red flex h-3.5 w-3.5 items-center justify-center rounded-full border", children: _jsx(X, { className: "h-2.5 w-2.5", strokeWidth: 2 }) }));
|
|
968
|
+
}
|
|
804
969
|
// Thinking block component with auto-scroll
|
|
805
970
|
function ThinkingBlock({ text, isStreaming, isCollapsed, thinkingKey, onToggleCollapse, }) {
|
|
806
971
|
const contentRef = useRef(null);
|
|
@@ -810,13 +975,9 @@ function ThinkingBlock({ text, isStreaming, isCollapsed, thinkingKey, onToggleCo
|
|
|
810
975
|
contentRef.current.scrollTop = contentRef.current.scrollHeight;
|
|
811
976
|
}
|
|
812
977
|
}, [text, isStreaming, isCollapsed]);
|
|
813
|
-
return (_jsxs("div", { className: `my-2 flex flex-col gap-1
|
|
814
|
-
? "border-border-default bg-neutral-grey-5/50 text-neutral-grey-100"
|
|
815
|
-
: "border-border-default bg-neutral-grey-5/50 text-neutral-grey-50"}`, children: [_jsxs("div", { className: `flex cursor-pointer items-center gap-1.5 p-2 text-[10px] font-medium tracking-wider transition-colors ${isStreaming
|
|
816
|
-
? "text-neutral-grey-50 hover:bg-neutral-grey-5/50"
|
|
817
|
-
: "text-neutral-grey-50 hover:bg-neutral-grey-5/50"}`, onClick: onToggleCollapse, children: [isCollapsed ? _jsx(ChevronRight, { size: 12 }) : _jsx(ChevronDown, { size: 12 }), _jsx(Brain, { size: 12, className: isStreaming ? "animate-pulse" : "" }), _jsx("span", { children: "Thinking" }), isStreaming && (_jsx(Loader2, { className: "text-neutral-grey-50 ml-1 h-3 w-3 animate-spin", strokeWidth: 1.5 }))] }), !isCollapsed && (_jsxs("div", { ref: contentRef, className: `prose-sm max-h-[6rem] overflow-y-auto px-2 pb-2 leading-relaxed whitespace-pre-wrap italic ${isStreaming ? "text-neutral-grey-50" : ""}`, children: [text, isStreaming && (_jsx("span", { className: "bg-neutral-grey-50 ml-0.5 inline-block h-3 w-0.5 animate-pulse" }))] }))] }));
|
|
978
|
+
return (_jsxs("div", { className: `my-2 flex flex-col gap-1 text-[11px] transition-colors duration-200 ${isStreaming ? "text-neutral-grey-100" : "text-neutral-grey-50"}`, children: [_jsxs("div", { className: "text-neutral-grey-50 hover:text-neutral-grey-100 flex cursor-pointer items-center gap-1.5 p-2 text-[10px] font-medium tracking-wider transition-colors", onClick: onToggleCollapse, children: [isCollapsed ? _jsx(ChevronRight, { size: 12 }) : _jsx(ChevronDown, { size: 12 }), _jsx(Brain, { size: 12, className: isStreaming ? "animate-pulse" : "" }), _jsx("span", { children: "Thinking" }), isStreaming && (_jsx(Loader2, { className: "text-neutral-grey-50 ml-1 h-3 w-3 animate-spin", strokeWidth: 1.5 }))] }), !isCollapsed && (_jsxs("div", { ref: contentRef, className: `prose-sm max-h-[6rem] overflow-y-auto px-2 pb-2 leading-relaxed whitespace-pre-wrap italic ${isStreaming ? "text-neutral-grey-50" : ""}`, children: [text, isStreaming && (_jsx("span", { className: "bg-neutral-grey-50 ml-0.5 inline-block h-3 w-0.5 animate-pulse" }))] }))] }));
|
|
818
979
|
}
|
|
819
|
-
export function AiResponseMessage({ messages, finished, editOperations, error, onQuickAction, defaultCollapseJson = false,
|
|
980
|
+
export function AiResponseMessage({ messages, finished, editOperations, error, onQuickAction, defaultCollapseJson = false, agentId, agentName, allPendingApprovals, onSwitchToAutonomous, browserCaptureInlinePrompt, readOnly = false, followsUserMessage = false, }) {
|
|
820
981
|
const editContext = useEditContext();
|
|
821
982
|
// const [showFunctions, setShowFunctions] = useState(false);
|
|
822
983
|
const [changesRejected, setChangesRejected] = useState(undefined);
|
|
@@ -917,6 +1078,7 @@ export function AiResponseMessage({ messages, finished, editOperations, error, o
|
|
|
917
1078
|
const lastMessage = messages[messages.length - 1];
|
|
918
1079
|
// Memoize filtered messages and their parsed content segments to avoid hooks inside loops
|
|
919
1080
|
const nonToolAssistantMessages = useMemo(() => messages.filter((x) => x.role !== "tool" && x.role !== "user"), [messages]);
|
|
1081
|
+
// Create a flat structure of content items: text, tool calls, text, tool calls, etc.
|
|
920
1082
|
const flatItems = useMemo(() => {
|
|
921
1083
|
const items = [];
|
|
922
1084
|
// Collect all unique tool call IDs and their latest versions across all messages in this group
|
|
@@ -1032,6 +1194,7 @@ export function AiResponseMessage({ messages, finished, editOperations, error, o
|
|
|
1032
1194
|
preservedToolCalls,
|
|
1033
1195
|
getToolArgumentsScore,
|
|
1034
1196
|
]);
|
|
1197
|
+
const displayItems = useMemo(() => groupActivityItems(flatItems), [flatItems]);
|
|
1035
1198
|
// Check if any reasoning block is currently showing a spinner
|
|
1036
1199
|
const isAnyReasoningStreaming = useMemo(() => {
|
|
1037
1200
|
if (!isStreaming || allPendingApprovals?.length)
|
|
@@ -1076,165 +1239,172 @@ export function AiResponseMessage({ messages, finished, editOperations, error, o
|
|
|
1076
1239
|
});
|
|
1077
1240
|
return textParts.join("\n\n");
|
|
1078
1241
|
}, [flatItems]);
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
if (html) {
|
|
1132
|
-
parts.push(_jsx("span", { dangerouslySetInnerHTML: { __html: html } }, `text-${itemIndex}-${linkIdx}`));
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
// Add the button
|
|
1136
|
-
// Calculate the actual text that will be submitted (same logic as in AgentTerminal.tsx)
|
|
1137
|
-
// For command links: prompt=command, value=command, so submitted text is link.command
|
|
1138
|
-
const submittedText = (link.command ||
|
|
1139
|
-
link.label ||
|
|
1140
|
-
"").trim();
|
|
1141
|
-
parts.push(_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { size: "sm", variant: "outline", className: "mx-1 inline-flex", onClick: () => onQuickAction?.({
|
|
1142
|
-
label: link.label,
|
|
1143
|
-
value: link.command,
|
|
1144
|
-
prompt: link.command,
|
|
1145
|
-
}, message), children: link.label }) }), submittedText && (_jsx(TooltipContent, { children: _jsx("p", { className: "max-w-xs break-words", children: submittedText }) }))] }, `btn-${itemIndex}-${linkIdx}`));
|
|
1146
|
-
// Find the end of this match in the original text
|
|
1147
|
-
const matchEnd = link.index +
|
|
1148
|
-
`[${link.label}](command:${link.command})`.length;
|
|
1149
|
-
lastIndex = matchEnd;
|
|
1150
|
-
});
|
|
1151
|
-
// Add any remaining text after the last link
|
|
1152
|
-
if (lastIndex < text.length) {
|
|
1153
|
-
const textAfter = text.substring(lastIndex);
|
|
1154
|
-
const html = simpleFormatToHtml(textAfter);
|
|
1155
|
-
if (html) {
|
|
1156
|
-
parts.push(_jsx("span", { dangerouslySetInnerHTML: { __html: html } }, `text-${itemIndex}-end`));
|
|
1157
|
-
}
|
|
1158
|
-
}
|
|
1159
|
-
return (_jsxs("div", { className: `prose prose-sm text-neutral-grey-100 max-w-none text-xs select-text ${shouldAddSpacing ? "mt-2" : ""}`, children: [parts, isStreaming && isLastItem && (_jsx("span", { className: "bg-neutral-grey-50 ml-0.5 inline-block h-3 w-0.5 animate-pulse" }))] }, `item-${itemIndex}`));
|
|
1160
|
-
}
|
|
1161
|
-
const html = simpleFormatToHtml(trimmedText);
|
|
1162
|
-
if (!html)
|
|
1163
|
-
return null;
|
|
1164
|
-
return (_jsxs("div", { className: `prose prose-sm text-neutral-grey-100 max-w-none text-xs select-text ${shouldAddSpacing ? "mt-2" : ""}`, children: [_jsx("span", { dangerouslySetInnerHTML: { __html: html } }), isStreaming && isLastItem && (_jsx("span", { className: "bg-neutral-grey-50 ml-0.5 inline-block h-3 w-0.5 animate-pulse" }))] }, `item-${itemIndex}`));
|
|
1165
|
-
}
|
|
1166
|
-
if (segment.kind === "todo") {
|
|
1167
|
-
const todo = segment;
|
|
1168
|
-
return (_jsxs("div", { className: `my-1 ${shouldAddSpacing ? "mt-2" : ""}`, children: [todo.title && (_jsx("div", { className: "text-neutral-grey-100 mb-1 text-xs font-medium", children: todo.title })), _jsx("div", { className: "flex flex-col gap-1", children: todo.items.map((todoItem, iIdx) => (_jsxs("label", { className: "text-neutral-grey-100 flex items-start gap-2 text-xs", children: [_jsx(Checkbox, { checked: todoItem.status === "completed", onCheckedChange: () => { }, "aria-readonly": true, className: "mt-0.5" }), _jsxs("div", { children: [_jsx("div", { className: todoItem.status === "completed" ||
|
|
1169
|
-
todoItem.status === "cancelled"
|
|
1170
|
-
? "line-through opacity-70"
|
|
1171
|
-
: todoItem.status === "in_progress"
|
|
1172
|
-
? "text-feedback-blue font-medium"
|
|
1173
|
-
: "", children: todoItem.title }), todoItem.instructions && (_jsx("div", { className: "text-neutral-grey-100 text-xs", children: todoItem.instructions }))] })] }, (todoItem.id || todoItem.title || "todo") + "-" + iIdx))) })] }, `item-${itemIndex}`));
|
|
1174
|
-
}
|
|
1175
|
-
if (segment.kind === "media") {
|
|
1176
|
-
const media = segment;
|
|
1177
|
-
return (_jsx("div", { className: `my-2 flex flex-col gap-3 ${shouldAddSpacing ? "mt-2" : ""}`, children: media.items.map((mediaItem, mIdx) => (_jsx(MediaImage, { itemId: mediaItem.itemId, label: mediaItem.label }, mediaItem.itemId || `media-${itemIndex}-${mIdx}`))) }, `item-${itemIndex}`));
|
|
1178
|
-
}
|
|
1179
|
-
if (segment.kind === "json") {
|
|
1180
|
-
return (_jsx(JsonBlockDisplay, { data: segment.data, raw: segment.raw, defaultCollapsed: defaultCollapseJson, className: shouldAddSpacing ? "mt-2" : "" }, `item-${itemIndex}`));
|
|
1242
|
+
const renderFlatItem = (item, itemIndex) => {
|
|
1243
|
+
const prevItem = itemIndex > 0 ? flatItems[itemIndex - 1] : null;
|
|
1244
|
+
const isLastItem = itemIndex === flatItems.length - 1;
|
|
1245
|
+
const shouldAddSpacing = prevItem?.type === "toolcalls" && item.type === "segment";
|
|
1246
|
+
if (item.type === "segment") {
|
|
1247
|
+
const segment = item.segment;
|
|
1248
|
+
const message = item.message;
|
|
1249
|
+
if (segment.kind === "reasoning") {
|
|
1250
|
+
const thinkingKey = `thinking-${message.id}-${itemIndex}`;
|
|
1251
|
+
// Only show the "Thinking" spinner while we're still in the pre-output phase.
|
|
1252
|
+
// Once any actual response content starts appearing, thinking has effectively finished,
|
|
1253
|
+
// even if the overall response is still streaming.
|
|
1254
|
+
const contentString = (message.content ||
|
|
1255
|
+
message.formattedContent ||
|
|
1256
|
+
"");
|
|
1257
|
+
const hasToolCalls = (message.tool_calls && message.tool_calls.length > 0) ||
|
|
1258
|
+
(preservedToolCalls[message.id] &&
|
|
1259
|
+
preservedToolCalls[message.id].length > 0);
|
|
1260
|
+
const hasStartedOutput = contentString.trim().length > 0 || hasToolCalls;
|
|
1261
|
+
// Check if this reasoning block is still actively streaming
|
|
1262
|
+
const isReasoningStreaming = !!(isStreaming &&
|
|
1263
|
+
item.isLastMessage &&
|
|
1264
|
+
!hasStartedOutput &&
|
|
1265
|
+
!allPendingApprovals?.length);
|
|
1266
|
+
// During streaming, default to expanded; after streaming, default to collapsed
|
|
1267
|
+
const isCollapsed = collapsedThinking[thinkingKey] !== undefined
|
|
1268
|
+
? collapsedThinking[thinkingKey]
|
|
1269
|
+
: !isReasoningStreaming; // Expanded during streaming, collapsed after
|
|
1270
|
+
return (_jsx(ThinkingBlock, { text: segment.text, isStreaming: isReasoningStreaming, isCollapsed: isCollapsed, thinkingKey: thinkingKey, onToggleCollapse: () => {
|
|
1271
|
+
setCollapsedThinking((prev) => ({
|
|
1272
|
+
...prev,
|
|
1273
|
+
[thinkingKey]: !isCollapsed,
|
|
1274
|
+
}));
|
|
1275
|
+
} }, `item-${itemIndex}`));
|
|
1276
|
+
}
|
|
1277
|
+
if (segment.kind === "text") {
|
|
1278
|
+
const trimmedText = segment.text.trim();
|
|
1279
|
+
if (!trimmedText)
|
|
1280
|
+
return null;
|
|
1281
|
+
// Check for command links in the text
|
|
1282
|
+
const { text, links } = extractCommandLinks(trimmedText);
|
|
1283
|
+
if (links.length > 0) {
|
|
1284
|
+
// Split text around command links and render buttons
|
|
1285
|
+
const parts = [];
|
|
1286
|
+
let lastIndex = 0;
|
|
1287
|
+
links.forEach((link, linkIdx) => {
|
|
1288
|
+
// Add text before the link
|
|
1289
|
+
if (link.index > lastIndex) {
|
|
1290
|
+
const textBefore = text.substring(lastIndex, link.index);
|
|
1291
|
+
const html = simpleFormatToHtml(textBefore);
|
|
1292
|
+
if (html) {
|
|
1293
|
+
parts.push(_jsx("span", { dangerouslySetInnerHTML: { __html: html } }, `text-${itemIndex}-${linkIdx}`));
|
|
1181
1294
|
}
|
|
1182
|
-
// segment.kind === "actions"
|
|
1183
|
-
const actions = segment.actions;
|
|
1184
|
-
return (_jsx("div", { className: `my-3 flex flex-wrap gap-2 ${shouldAddSpacing ? "mt-2" : ""}`, children: actions.map((a, aIdx) => {
|
|
1185
|
-
const variant = a.style === "destructive"
|
|
1186
|
-
? "destructive"
|
|
1187
|
-
: a.style === "outline"
|
|
1188
|
-
? "outline"
|
|
1189
|
-
: a.style === "secondary"
|
|
1190
|
-
? "secondary"
|
|
1191
|
-
: "default"; // primary
|
|
1192
|
-
// Calculate the actual text that will be submitted (same logic as in AgentTerminal.tsx)
|
|
1193
|
-
const submittedText = (a.prompt ||
|
|
1194
|
-
a.value ||
|
|
1195
|
-
a.label ||
|
|
1196
|
-
"").trim();
|
|
1197
|
-
return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { size: "xs", variant: variant, onClick: () => onQuickAction?.({
|
|
1198
|
-
label: a.label,
|
|
1199
|
-
prompt: a.prompt,
|
|
1200
|
-
value: a.value,
|
|
1201
|
-
behavior: a.behavior,
|
|
1202
|
-
placeholder: a.placeholder,
|
|
1203
|
-
}, message), children: a.label }) }), submittedText && (_jsx(TooltipContent, { children: _jsx("p", { className: "max-w-xs break-words", children: submittedText }) }))] }, (a.id || a.label || "btn") + "-" + aIdx));
|
|
1204
|
-
}) }, `item-${itemIndex}`));
|
|
1205
1295
|
}
|
|
1206
|
-
//
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
},
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1296
|
+
// Add the button
|
|
1297
|
+
// Calculate the actual text that will be submitted (same logic as in AgentTerminal.tsx)
|
|
1298
|
+
// For command links: prompt=command, value=command, so submitted text is link.command
|
|
1299
|
+
const submittedText = (link.command || link.label || "").trim();
|
|
1300
|
+
parts.push(_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { size: "sm", variant: "outline", className: "mx-1 inline-flex", onClick: () => onQuickAction?.({
|
|
1301
|
+
label: link.label,
|
|
1302
|
+
value: link.command,
|
|
1303
|
+
prompt: link.command,
|
|
1304
|
+
}, message), children: link.label }) }), submittedText && (_jsx(TooltipContent, { children: _jsx("p", { className: "max-w-xs break-words", children: submittedText }) }))] }, `btn-${itemIndex}-${linkIdx}`));
|
|
1305
|
+
// Find the end of this match in the original text
|
|
1306
|
+
const matchEnd = link.index + `[${link.label}](command:${link.command})`.length;
|
|
1307
|
+
lastIndex = matchEnd;
|
|
1308
|
+
});
|
|
1309
|
+
// Add any remaining text after the last link
|
|
1310
|
+
if (lastIndex < text.length) {
|
|
1311
|
+
const textAfter = text.substring(lastIndex);
|
|
1312
|
+
const html = simpleFormatToHtml(textAfter);
|
|
1313
|
+
if (html) {
|
|
1314
|
+
parts.push(_jsx("span", { dangerouslySetInnerHTML: { __html: html } }, `text-${itemIndex}-end`));
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
return (_jsxs("div", { className: `${assistantMessageTextClassName} ${shouldAddSpacing ? "mt-2" : ""}`, children: [parts, isStreaming && isLastItem && (_jsx("span", { className: "bg-neutral-grey-50 ml-0.5 inline-block h-3 w-0.5 animate-pulse" }))] }, `item-${itemIndex}`));
|
|
1318
|
+
}
|
|
1319
|
+
const html = simpleFormatToHtml(trimmedText);
|
|
1320
|
+
if (!html)
|
|
1321
|
+
return null;
|
|
1322
|
+
return (_jsxs("div", { className: `${assistantMessageTextClassName} ${shouldAddSpacing ? "mt-2" : ""}`, children: [_jsx("span", { dangerouslySetInnerHTML: { __html: html } }), isStreaming && isLastItem && (_jsx("span", { className: "bg-neutral-grey-50 ml-0.5 inline-block h-3 w-0.5 animate-pulse" }))] }, `item-${itemIndex}`));
|
|
1323
|
+
}
|
|
1324
|
+
if (segment.kind === "todo") {
|
|
1325
|
+
const todo = segment;
|
|
1326
|
+
return (_jsxs("div", { className: `my-1 ${shouldAddSpacing ? "mt-2" : ""}`, children: [todo.title && (_jsx("div", { className: "text-neutral-grey-100 mb-1 text-xs font-medium", children: todo.title })), _jsx("div", { className: "flex flex-col gap-1", children: todo.items.map((todoItem, iIdx) => (_jsxs("label", { className: "text-neutral-grey-100 flex items-start gap-2 text-xs", children: [_jsx(Checkbox, { checked: todoItem.status === "completed", onCheckedChange: () => { }, "aria-readonly": true, className: "mt-0.5" }), _jsxs("div", { children: [_jsx("div", { className: todoItem.status === "completed" ||
|
|
1327
|
+
todoItem.status === "cancelled"
|
|
1328
|
+
? "line-through opacity-70"
|
|
1329
|
+
: todoItem.status === "in_progress"
|
|
1330
|
+
? "text-feedback-blue font-medium"
|
|
1331
|
+
: "", children: todoItem.title }), todoItem.instructions && (_jsx("div", { className: "text-neutral-grey-100 text-xs", children: todoItem.instructions }))] })] }, (todoItem.id || todoItem.title || "todo") + "-" + iIdx))) })] }, `item-${itemIndex}`));
|
|
1332
|
+
}
|
|
1333
|
+
if (segment.kind === "media") {
|
|
1334
|
+
const media = segment;
|
|
1335
|
+
return (_jsx("div", { className: `my-2 flex flex-col gap-3 ${shouldAddSpacing ? "mt-2" : ""}`, children: media.items.map((mediaItem, mIdx) => (_jsx(MediaImage, { itemId: mediaItem.itemId, label: mediaItem.label }, mediaItem.itemId || `media-${itemIndex}-${mIdx}`))) }, `item-${itemIndex}`));
|
|
1336
|
+
}
|
|
1337
|
+
if (segment.kind === "json") {
|
|
1338
|
+
return (_jsx(JsonBlockDisplay, { data: segment.data, raw: segment.raw, defaultCollapsed: defaultCollapseJson, className: shouldAddSpacing ? "mt-2" : "" }, `item-${itemIndex}`));
|
|
1339
|
+
}
|
|
1340
|
+
// segment.kind === "actions"
|
|
1341
|
+
const actions = segment.actions;
|
|
1342
|
+
const headline = segment.headline?.trim();
|
|
1343
|
+
return (_jsxs("div", { className: `border-neutral-grey-10 my-3 rounded-xl border bg-white px-3 py-2.5 ${shouldAddSpacing ? "mt-2" : ""}`, children: [headline && (_jsx("div", { className: "text-neutral-grey-100 mb-2.5 text-[13px] leading-4 font-semibold", children: headline })), _jsx("div", { className: "flex flex-wrap gap-2", children: actions.map((a, aIdx) => {
|
|
1344
|
+
const variant = a.style === "destructive"
|
|
1345
|
+
? "destructive"
|
|
1346
|
+
: a.style === "outline"
|
|
1347
|
+
? "outline"
|
|
1348
|
+
: a.style === "secondary"
|
|
1349
|
+
? "secondary"
|
|
1350
|
+
: "default"; // primary
|
|
1351
|
+
const buttonClassName = variant === "outline"
|
|
1352
|
+
? "h-7 rounded-full border-neutral-grey-10 bg-white px-3 text-xs font-medium text-neutral-grey-100 shadow-none hover:bg-neutral-grey-5"
|
|
1353
|
+
: "h-7 rounded-full border border-transparent bg-neutral-grey-10 px-3 text-xs font-medium text-neutral-grey-100 shadow-none hover:bg-neutral-grey-5";
|
|
1354
|
+
// Calculate the actual text that will be submitted (same logic as in AgentTerminal.tsx)
|
|
1355
|
+
const submittedText = (a.prompt ||
|
|
1356
|
+
a.value ||
|
|
1357
|
+
a.label ||
|
|
1358
|
+
"").trim();
|
|
1359
|
+
return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { size: "xs", variant: variant, className: buttonClassName, onClick: () => onQuickAction?.({
|
|
1360
|
+
label: a.label,
|
|
1361
|
+
prompt: a.prompt,
|
|
1362
|
+
value: a.value,
|
|
1363
|
+
behavior: a.behavior,
|
|
1364
|
+
placeholder: a.placeholder,
|
|
1365
|
+
}, message), children: a.label }) }), submittedText && (_jsx(TooltipContent, { children: _jsx("p", { className: "max-w-xs break-words", children: submittedText }) }))] }, (a.id || a.label || "btn") + "-" + aIdx));
|
|
1366
|
+
}) })] }, `item-${itemIndex}`));
|
|
1367
|
+
}
|
|
1368
|
+
// item.type === "toolcalls"
|
|
1369
|
+
return (_jsx("div", { className: shouldAddSpacing ? "mt-2" : "", children: _jsx(ToolCallDisplay, { toolCalls: item.toolCalls, finished: finished, openPopovers: openPopovers, setOpenPopovers: setOpenPopovers, messageId: item.messageId, agentId: agentId, allPendingApprovals: allPendingApprovals, onSwitchToAutonomous: onSwitchToAutonomous, browserCaptureInlinePrompt: browserCaptureInlinePrompt, readOnly: readOnly }) }, `item-${itemIndex}`));
|
|
1370
|
+
};
|
|
1371
|
+
return (_jsx("div", { className: `px-4 pb-3 ${followsUserMessage ? "pt-6" : "pt-3"}`, "data-testid": "agent-message", children: _jsxs("div", { className: "min-w-0 flex-1 select-text", children: [_jsxs("div", { className: "mb-1 flex items-center gap-2", children: [_jsx("span", { className: "text-neutral-grey-100 text-xs font-medium", children: agentName || "Agent" }), lastMessage && lastMessage.createdDate && (_jsx(TimeWithTooltip, { date: new Date(lastMessage.createdDate), className: "text-neutral-grey-50 text-xs", testId: "agent-message-timestamp", timestampAttr: lastMessage.createdDate }))] }), error && (_jsx("div", { className: "border-feedback-red bg-feedback-red-light mb-2 rounded-lg border-l-4 p-2.5", "data-testid": "agent-error", children: _jsxs("div", { className: "flex items-start", children: [_jsx("div", { className: "flex-shrink-0", children: _jsx(X, { className: "text-feedback-red h-5 w-5", strokeWidth: 1 }) }), _jsxs("div", { className: "ml-3", children: [_jsx("p", { className: "text-feedback-red text-sm font-medium", children: "Agent Error" }), _jsx("p", { className: "text-feedback-red mt-1 text-sm", children: error })] })] }) })), displayItems.map((displayItem) => {
|
|
1372
|
+
if (displayItem.type === "activity-group") {
|
|
1373
|
+
const isLive = !finished &&
|
|
1374
|
+
displayItem.entries.some((entry) => entry.item.isLastMessage);
|
|
1375
|
+
return (_jsx(ActivityBlockGroup, { entries: displayItem.entries, isLive: isLive, renderEntry: (entry) => renderFlatItem(entry.item, entry.index) }, displayItem.key));
|
|
1376
|
+
}
|
|
1377
|
+
return renderFlatItem(displayItem.entry.item, displayItem.entry.index);
|
|
1378
|
+
}), isStreaming &&
|
|
1379
|
+
!error &&
|
|
1380
|
+
!allPendingApprovals?.length &&
|
|
1381
|
+
!isAnyReasoningStreaming && (_jsxs("div", { className: "flex items-center gap-1 pt-2", "data-testid": "agent-streaming-dots", children: [_jsx("div", { className: "bg-neutral-grey-50 h-1 w-1 animate-bounce rounded-full [animation-delay:-0.3s]" }), _jsx("div", { className: "bg-neutral-grey-50 h-1 w-1 animate-bounce rounded-full [animation-delay:-0.15s]" }), _jsx("div", { className: "bg-neutral-grey-50 h-1 w-1 animate-bounce rounded-full" })] })), (copyableText || (finished && editOperations.length > 0)) && (_jsxs("div", { className: "mt-3 flex items-center justify-end gap-2", children: [copyableText && (_jsx(CopyButton, { textToCopy: copyableText, iconOnly: false, className: "text-neutral-grey-50 hover:text-neutral-grey-50 flex cursor-pointer items-center gap-1 p-0 text-xs" })), finished && editOperations.length > 0 && (_jsxs(_Fragment, { children: [canUndo && !changesRejected && !confirmingUndo && (_jsxs("button", { type: "button", title: `Undo ${editOperations.length} change${editOperations.length !== 1 ? "s" : ""}`, className: "tour-ai-response-message-changes text-neutral-grey-50 hover:text-neutral-grey-50 flex cursor-pointer items-center gap-1 text-xs", onClick: (e) => {
|
|
1382
|
+
e.stopPropagation();
|
|
1383
|
+
setConfirmingUndo(true);
|
|
1384
|
+
}, children: [_jsx(Undo2, { strokeWidth: 1.5, size: 12 }), " Undo"] })), canUndo && !changesRejected && confirmingUndo && (_jsxs("div", { className: "flex items-center gap-2 text-xs", children: [_jsxs("span", { className: "text-neutral-grey-50", children: ["Undo ", editOperations.length, " change", editOperations.length !== 1 ? "s" : "", "?"] }), _jsx("button", { type: "button", className: "text-feedback-red hover:text-feedback-red cursor-pointer", onClick: async (e) => {
|
|
1385
|
+
e.stopPropagation();
|
|
1386
|
+
const operationIds = undoableOperations.map((op) => op.id);
|
|
1387
|
+
if (!editContext?.operations?.undoOperations) {
|
|
1234
1388
|
setConfirmingUndo(false);
|
|
1235
|
-
|
|
1236
|
-
|
|
1389
|
+
return;
|
|
1390
|
+
}
|
|
1391
|
+
if (operationIds.length === 0) {
|
|
1237
1392
|
setConfirmingUndo(false);
|
|
1238
|
-
|
|
1393
|
+
return;
|
|
1394
|
+
}
|
|
1395
|
+
try {
|
|
1396
|
+
const success = await editContext.operations.undoOperations(operationIds);
|
|
1397
|
+
if (success) {
|
|
1398
|
+
setChangesRejected(true);
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
catch (error) {
|
|
1402
|
+
// Undo operation failed
|
|
1403
|
+
}
|
|
1404
|
+
setConfirmingUndo(false);
|
|
1405
|
+
}, children: "Yes" }), _jsx("button", { type: "button", className: "text-neutral-grey-50 hover:text-neutral-grey-50 cursor-pointer", onClick: (e) => {
|
|
1406
|
+
e.stopPropagation();
|
|
1407
|
+
setConfirmingUndo(false);
|
|
1408
|
+
}, children: "No" })] })), (changesRejected || allOperationsUndone) && (_jsxs("span", { className: "text-neutral-grey-50 inline-flex items-center gap-1 text-xs", children: [_jsx(Check, { strokeWidth: 2, size: 12 }), " Undone"] }))] }))] }))] }) }));
|
|
1239
1409
|
}
|
|
1240
1410
|
//# sourceMappingURL=AiResponseMessage.js.map
|