@agent-native/core 0.12.30 → 0.12.32
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/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +21 -5
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +10 -3
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +234 -23
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +9 -8
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +23 -4
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/components/ui/hover-card.d.ts +7 -0
- package/dist/client/components/ui/hover-card.d.ts.map +1 -0
- package/dist/client/components/ui/hover-card.js +10 -0
- package/dist/client/components/ui/hover-card.js.map +1 -0
- package/dist/client/composer/TiptapComposer.js +1 -1
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/dev-overlay/DevOverlay.d.ts.map +1 -1
- package/dist/client/dev-overlay/DevOverlay.js +5 -1
- package/dist/client/dev-overlay/DevOverlay.js.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.js +3 -2
- package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
- package/dist/client/guided-questions.d.ts +77 -0
- package/dist/client/guided-questions.d.ts.map +1 -0
- package/dist/client/guided-questions.js +295 -0
- package/dist/client/guided-questions.js.map +1 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +8 -1
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts +3 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +78 -12
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/SettingsSection.d.ts +2 -1
- package/dist/client/settings/SettingsSection.d.ts.map +1 -1
- package/dist/client/settings/SettingsSection.js +2 -2
- package/dist/client/settings/SettingsSection.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts +4 -0
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +76 -32
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/sharing/ShareButton.spec.js +54 -7
- package/dist/client/sharing/ShareButton.spec.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +42 -5
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/use-db-sync.d.ts +12 -2
- package/dist/client/use-db-sync.d.ts.map +1 -1
- package/dist/client/use-db-sync.js +195 -53
- package/dist/client/use-db-sync.js.map +1 -1
- package/dist/server/core-routes-plugin.js +2 -2
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/google-auth-plugin.d.ts.map +1 -1
- package/dist/server/google-auth-plugin.js +18 -2
- package/dist/server/google-auth-plugin.js.map +1 -1
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +2 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +18 -2
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/poll-events.d.ts +12 -0
- package/dist/server/poll-events.d.ts.map +1 -0
- package/dist/server/poll-events.js +41 -0
- package/dist/server/poll-events.js.map +1 -0
- package/dist/server/poll.d.ts +4 -0
- package/dist/server/poll.d.ts.map +1 -1
- package/dist/server/poll.js +19 -12
- package/dist/server/poll.js.map +1 -1
- package/dist/templates/default/react-router.config.ts +1 -0
- package/package.json +2 -1
- package/src/templates/default/react-router.config.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/AssistantChat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAQN,MAAM,OAAO,CAAC;AA4Bf,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"AssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/AssistantChat.tsx"],"names":[],"mappings":"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"}
|
|
@@ -23,7 +23,7 @@ import { ThumbsFeedback } from "./observability/ThumbsFeedback.js";
|
|
|
23
23
|
import { TiptapComposer, } from "./composer/TiptapComposer.js";
|
|
24
24
|
import { isPastedTextAttachmentName } from "./composer/pasted-text.js";
|
|
25
25
|
import { PastedTextChip } from "./composer/PastedTextChip.js";
|
|
26
|
-
import { IconMessage, IconX, IconPlayerStop, IconCheck, IconChevronDown, IconCopy, IconTerminal, IconLoader2, IconCircleX, IconSquareFilled, IconClock, IconFile, IconFolder, IconFileText, IconCheckbox, IconMail, IconUser, IconPresentation, IconStack2, IconMessageChatbot, IconLock, IconArrowBackUp, IconExternalLink, IconDots, IconGitFork, IconId, IconQuote, IconGauge, IconArrowRight, IconSettings, IconAlertTriangle, IconRefresh, IconPlayerPlay, IconClipboardList, } from "@tabler/icons-react";
|
|
26
|
+
import { IconMessage, IconX, IconPlayerStop, IconCheck, IconChevronDown, IconCopy, IconTerminal, IconLoader2, IconCircleX, IconSquareFilled, IconClock, IconFile, IconFolder, IconFileText, IconCheckbox, IconMail, IconUser, IconPresentation, IconStack2, IconMessageChatbot, IconLock, IconArrowBackUp, IconExternalLink, IconDots, IconGitFork, IconId, IconQuote, IconGauge, IconArrowRight, IconSettings, IconAlertTriangle, IconRefresh, IconPlayerPlay, IconClipboardList, IconSearch, IconArrowsMaximize, IconArrowsMinimize, } from "@tabler/icons-react";
|
|
27
27
|
class BinaryDocumentAttachmentAdapter {
|
|
28
28
|
accept = "application/pdf,.pdf";
|
|
29
29
|
async add(state) {
|
|
@@ -207,6 +207,11 @@ const markdownStyles = `
|
|
|
207
207
|
.dark .agent-markdown-shiki pre { background: var(--shiki-dark-bg); color: var(--shiki-dark); }
|
|
208
208
|
.dark .agent-markdown-shiki pre span { color: var(--shiki-dark); background: var(--shiki-dark-bg); }
|
|
209
209
|
@media (prefers-color-scheme: dark) { :root:not(.light) .agent-markdown-shiki pre { background: var(--shiki-dark-bg); color: var(--shiki-dark); } :root:not(.light) .agent-markdown-shiki pre span { color: var(--shiki-dark); background: var(--shiki-dark-bg); } }
|
|
210
|
+
.agent-tool-code .agent-markdown-shiki { margin: 0; border-radius: 0; min-width: max-content; }
|
|
211
|
+
.agent-tool-code .agent-markdown-shiki pre { padding: 0.75rem; border: 0; background: transparent; }
|
|
212
|
+
.agent-tool-code .agent-markdown-shiki pre span { background: transparent; }
|
|
213
|
+
.agent-tool-code pre { margin: 0; min-width: max-content; padding: 0.75rem; background: transparent; color: inherit; }
|
|
214
|
+
.agent-tool-code mark { border-radius: 0.1875rem; background: rgba(245, 158, 11, 0.25); color: inherit; }
|
|
210
215
|
.agent-markdown hr { border: none; border-top: 1px solid hsl(var(--border, 0 0% 20%)); margin: 0.75em 0; }
|
|
211
216
|
.agent-markdown a { text-decoration: underline; text-underline-offset: 2px; }
|
|
212
217
|
.agent-markdown a.agent-markdown-cta { text-decoration: none; }
|
|
@@ -406,6 +411,7 @@ function loadHighlighter() {
|
|
|
406
411
|
import("shiki/langs/shellscript.mjs"),
|
|
407
412
|
import("shiki/langs/python.mjs"),
|
|
408
413
|
import("shiki/langs/yaml.mjs"),
|
|
414
|
+
import("shiki/langs/sql.mjs"),
|
|
409
415
|
],
|
|
410
416
|
engine: createOnigurumaEngine(import("shiki/wasm")),
|
|
411
417
|
});
|
|
@@ -430,6 +436,8 @@ const LANG_ALIASES = {
|
|
|
430
436
|
py: "python",
|
|
431
437
|
yml: "yaml",
|
|
432
438
|
md: "markdown",
|
|
439
|
+
bq: "sql",
|
|
440
|
+
bigquery: "sql",
|
|
433
441
|
};
|
|
434
442
|
function HighlightedCodeBlock({ code, lang }) {
|
|
435
443
|
const [html, setHtml] = useState(null);
|
|
@@ -563,11 +571,190 @@ function ComposerAttachmentPreviewStrip() {
|
|
|
563
571
|
// can stop spinning when the user clicks stop. `thread.isRunning` alone misses
|
|
564
572
|
// the force-stopped case; `part.result === undefined` alone ignores stop.
|
|
565
573
|
const ChatRunningContext = React.createContext(false);
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
574
|
+
function stringifyToolValue(value, pretty = false) {
|
|
575
|
+
if (typeof value === "string")
|
|
576
|
+
return value;
|
|
577
|
+
try {
|
|
578
|
+
return JSON.stringify(value, null, pretty ? 2 : 0);
|
|
579
|
+
}
|
|
580
|
+
catch {
|
|
581
|
+
return String(value ?? "");
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
function toolArgsPreview(args) {
|
|
585
|
+
return Object.entries(args)
|
|
586
|
+
.map(([key, value]) => {
|
|
587
|
+
const singleLine = stringifyToolValue(value).replace(/\s+/g, " ").trim();
|
|
588
|
+
const preview = singleLine.length > 96 ? `${singleLine.slice(0, 96)}...` : singleLine;
|
|
589
|
+
return `${key}=${preview}`;
|
|
590
|
+
})
|
|
591
|
+
.join(", ");
|
|
592
|
+
}
|
|
593
|
+
function looksLikeSql(text) {
|
|
594
|
+
return /^\s*(select|with|insert|update|delete|merge|create|alter|drop|explain|declare|begin)\b/i.test(text);
|
|
595
|
+
}
|
|
596
|
+
function parseJsonText(text) {
|
|
597
|
+
const trimmed = text.trim();
|
|
598
|
+
if (!trimmed || !/^[{[]/.test(trimmed))
|
|
599
|
+
return null;
|
|
600
|
+
try {
|
|
601
|
+
return JSON.parse(trimmed);
|
|
602
|
+
}
|
|
603
|
+
catch {
|
|
604
|
+
return null;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
function inferToolTextLanguage(text, key, toolName) {
|
|
608
|
+
const keyName = (key ?? "").toLowerCase();
|
|
609
|
+
const tool = (toolName ?? "").toLowerCase();
|
|
610
|
+
if (keyName === "sql" ||
|
|
611
|
+
keyName.endsWith("sql") ||
|
|
612
|
+
keyName === "query" ||
|
|
613
|
+
tool.includes("bigquery") ||
|
|
614
|
+
tool.includes("db-query") ||
|
|
615
|
+
looksLikeSql(text)) {
|
|
616
|
+
return "sql";
|
|
617
|
+
}
|
|
618
|
+
return parseJsonText(text) ? "json" : "text";
|
|
619
|
+
}
|
|
620
|
+
function formatToolTextValue(value, key, toolName) {
|
|
621
|
+
if (typeof value === "string") {
|
|
622
|
+
const parsed = parseJsonText(value);
|
|
623
|
+
if (parsed) {
|
|
624
|
+
return { text: JSON.stringify(parsed, null, 2), lang: "json" };
|
|
625
|
+
}
|
|
626
|
+
return {
|
|
627
|
+
text: value,
|
|
628
|
+
lang: inferToolTextLanguage(value, key, toolName),
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
return { text: stringifyToolValue(value, true), lang: "json" };
|
|
632
|
+
}
|
|
633
|
+
function toolInputPayload(toolName, args) {
|
|
634
|
+
const entries = Object.entries(args);
|
|
635
|
+
if (entries.length === 0)
|
|
636
|
+
return null;
|
|
637
|
+
if (entries.length === 1) {
|
|
638
|
+
const [key, value] = entries[0];
|
|
639
|
+
const formatted = formatToolTextValue(value, key, toolName);
|
|
640
|
+
const normalizedKey = key.toLowerCase();
|
|
641
|
+
const keyLabel = normalizedKey === "sql" || normalizedKey.endsWith("sql") ? "SQL" : key;
|
|
642
|
+
return {
|
|
643
|
+
section: "input",
|
|
644
|
+
title: `Input - ${keyLabel}`,
|
|
645
|
+
text: formatted.text,
|
|
646
|
+
copyText: typeof value === "string" ? value : stringifyToolValue(value, true),
|
|
647
|
+
lang: formatted.lang,
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
return {
|
|
651
|
+
section: "input",
|
|
652
|
+
title: "Input",
|
|
653
|
+
text: JSON.stringify(args, null, 2),
|
|
654
|
+
copyText: JSON.stringify(args, null, 2),
|
|
655
|
+
lang: "json",
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
function toolResultPayload(result) {
|
|
659
|
+
if (result === undefined)
|
|
660
|
+
return null;
|
|
661
|
+
const formatted = formatToolTextValue(result);
|
|
662
|
+
return {
|
|
663
|
+
section: "result",
|
|
664
|
+
title: "Result",
|
|
665
|
+
text: formatted.text,
|
|
666
|
+
copyText: result,
|
|
667
|
+
lang: formatted.lang,
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
function escapeRegExp(value) {
|
|
671
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
672
|
+
}
|
|
673
|
+
function countTextMatches(text, query) {
|
|
674
|
+
const needle = query.trim();
|
|
675
|
+
if (!needle)
|
|
676
|
+
return 0;
|
|
677
|
+
return Array.from(text.matchAll(new RegExp(escapeRegExp(needle), "gi")))
|
|
678
|
+
.length;
|
|
679
|
+
}
|
|
680
|
+
function renderHighlightedSearchText(text, query) {
|
|
681
|
+
const needle = query.trim();
|
|
682
|
+
if (!needle)
|
|
683
|
+
return text;
|
|
684
|
+
const regex = new RegExp(escapeRegExp(needle), "gi");
|
|
685
|
+
const parts = [];
|
|
686
|
+
let lastIndex = 0;
|
|
687
|
+
let match;
|
|
688
|
+
while ((match = regex.exec(text))) {
|
|
689
|
+
if (match.index > lastIndex) {
|
|
690
|
+
parts.push(text.slice(lastIndex, match.index));
|
|
691
|
+
}
|
|
692
|
+
parts.push(_jsx("mark", { children: match[0] }, `${match.index}-${match[0]}`));
|
|
693
|
+
lastIndex = match.index + match[0].length;
|
|
694
|
+
if (match[0].length === 0)
|
|
695
|
+
regex.lastIndex += 1;
|
|
696
|
+
}
|
|
697
|
+
if (lastIndex < text.length)
|
|
698
|
+
parts.push(text.slice(lastIndex));
|
|
699
|
+
return parts;
|
|
700
|
+
}
|
|
701
|
+
function ToolDetailViewer({ payload }) {
|
|
702
|
+
const [expanded, setExpanded] = useState(false);
|
|
703
|
+
const [searchOpen, setSearchOpen] = useState(false);
|
|
704
|
+
const [search, setSearch] = useState("");
|
|
705
|
+
const [copied, setCopied] = useState(false);
|
|
706
|
+
const copyResetRef = useRef(null);
|
|
707
|
+
const matchCount = useMemo(() => countTextMatches(payload.text, search), [payload.text, search]);
|
|
708
|
+
useEffect(() => {
|
|
709
|
+
return () => {
|
|
710
|
+
if (copyResetRef.current)
|
|
711
|
+
clearTimeout(copyResetRef.current);
|
|
712
|
+
};
|
|
713
|
+
}, []);
|
|
714
|
+
const copyValue = useCallback(async () => {
|
|
715
|
+
try {
|
|
716
|
+
await navigator.clipboard.writeText(payload.copyText);
|
|
717
|
+
setCopied(true);
|
|
718
|
+
if (copyResetRef.current)
|
|
719
|
+
clearTimeout(copyResetRef.current);
|
|
720
|
+
copyResetRef.current = setTimeout(() => setCopied(false), 1200);
|
|
721
|
+
}
|
|
722
|
+
catch {
|
|
723
|
+
// Clipboard failures should not interrupt chat rendering.
|
|
724
|
+
}
|
|
725
|
+
}, [payload.copyText]);
|
|
726
|
+
return (_jsxs("div", { className: "rounded-md border border-border/50 bg-background/60", children: [_jsxs("div", { className: "flex min-h-9 flex-wrap items-center gap-2 border-b border-border/50 px-2.5 py-1.5", children: [_jsx("div", { className: "min-w-0 flex-1", children: _jsxs("div", { className: "flex min-w-0 items-center gap-1.5", children: [_jsx("span", { className: "truncate text-[11px] font-medium text-foreground/85", children: payload.title }), payload.lang !== "text" && (_jsx("span", { className: "shrink-0 rounded border border-border/60 px-1 py-0.5 font-mono text-[9px] uppercase leading-none text-muted-foreground", children: payload.lang }))] }) }), _jsx("button", { type: "button", onClick: () => setSearchOpen((v) => !v), "aria-label": `Search ${payload.title.toLowerCase()}`, "aria-pressed": searchOpen, className: cn("inline-flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground", searchOpen && "bg-accent text-foreground"), children: _jsx(IconSearch, { size: 12 }) }), _jsx("button", { type: "button", onClick: () => setExpanded((v) => !v), "aria-label": expanded ? "Shrink code viewer" : "Expand code viewer", "aria-pressed": expanded, className: "inline-flex h-6 w-6 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground", children: expanded ? (_jsx(IconArrowsMinimize, { size: 12 })) : (_jsx(IconArrowsMaximize, { size: 12 })) }), _jsxs("button", { type: "button", onClick: copyValue, className: "inline-flex h-6 items-center gap-1 rounded-md px-1.5 font-sans text-[11px] text-muted-foreground hover:bg-accent hover:text-foreground", children: [copied ? _jsx(IconCheck, { size: 12 }) : _jsx(IconCopy, { size: 12 }), copied ? "Copied" : "Copy"] })] }), searchOpen && (_jsxs("div", { className: "flex items-center gap-2 border-b border-border/50 px-2.5 py-2", children: [_jsx("input", { value: search, onChange: (e) => setSearch(e.target.value), placeholder: "Find", className: "h-7 min-w-0 flex-1 rounded-md border border-border bg-background px-2 text-xs text-foreground outline-none placeholder:text-muted-foreground focus:ring-1 focus:ring-ring" }), _jsx("span", { className: "shrink-0 text-[11px] text-muted-foreground", children: search.trim() ? matchCount : "" })] })), _jsx("div", { className: cn("agent-tool-code overflow-auto font-mono text-[11px] leading-relaxed text-foreground", expanded ? "max-h-[70vh]" : "max-h-72"), children: search.trim() ? (_jsx("pre", { children: _jsx("code", { children: renderHighlightedSearchText(payload.text, search) }) })) : (_jsx(HighlightedCodeBlock, { code: payload.text, lang: payload.lang })) })] }));
|
|
727
|
+
}
|
|
728
|
+
function activityTrailFromMetadata(message) {
|
|
729
|
+
const meta = message?.metadata;
|
|
730
|
+
const raw = meta?.custom?.activityTrail ?? meta?.activityTrail;
|
|
731
|
+
if (!Array.isArray(raw))
|
|
732
|
+
return [];
|
|
733
|
+
return raw
|
|
734
|
+
.map((item, index) => {
|
|
735
|
+
if (!item || typeof item !== "object")
|
|
736
|
+
return null;
|
|
737
|
+
const label = item.label;
|
|
738
|
+
const tool = item.tool;
|
|
739
|
+
if (typeof label !== "string" || !label.trim())
|
|
740
|
+
return null;
|
|
741
|
+
return {
|
|
742
|
+
id: `trail-${index}-${label}`,
|
|
743
|
+
label: label.trim(),
|
|
744
|
+
...(typeof tool === "string" && tool.trim()
|
|
745
|
+
? { tool: tool.trim() }
|
|
746
|
+
: {}),
|
|
747
|
+
};
|
|
748
|
+
})
|
|
749
|
+
.filter((item) => item !== null);
|
|
750
|
+
}
|
|
751
|
+
function RunActivityTrail({ steps }) {
|
|
752
|
+
const [open, setOpen] = useState(false);
|
|
753
|
+
if (steps.length === 0)
|
|
754
|
+
return null;
|
|
755
|
+
const visibleSteps = steps.slice(-6);
|
|
756
|
+
return (_jsxs("div", { className: "mt-1.5", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), "aria-expanded": open, className: "inline-flex items-center gap-1 text-[11px] font-medium text-muted-foreground hover:text-foreground", children: [_jsx(IconChevronDown, { size: 12, className: cn("transition-transform", open && "rotate-180") }), "Steps"] }), open && (_jsx("div", { className: "mt-1 rounded-md border border-border/60 bg-muted/25 px-2.5 py-2 text-[11px] text-muted-foreground", children: _jsx("div", { className: "space-y-1", children: visibleSteps.map((step) => (_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx(IconCheck, { className: "h-3 w-3 shrink-0 text-emerald-500" }), _jsx("span", { className: "truncate", children: step.label })] }, step.id))) }) }))] }));
|
|
757
|
+
}
|
|
571
758
|
function ToolCallDisplay({ toolName, argsText, args, result, isRunning, }) {
|
|
572
759
|
const streamRef = useRef(null);
|
|
573
760
|
const isAgentCall = toolName.startsWith("agent:");
|
|
@@ -576,6 +763,7 @@ function ToolCallDisplay({ toolName, argsText, args, result, isRunning, }) {
|
|
|
576
763
|
const isAgentError = isAgentCall && result === "Error calling agent";
|
|
577
764
|
const agentStreamText = isAgentCall ? (argsText ?? "") : "";
|
|
578
765
|
const hasStreamText = agentStreamText.length > 0;
|
|
766
|
+
const hasArgs = !isAgentCall && Object.keys(args).length > 0;
|
|
579
767
|
// NOTE: All hooks must be above any conditional returns
|
|
580
768
|
useEffect(() => {
|
|
581
769
|
if (isAgentCall && isRunning && streamRef.current) {
|
|
@@ -620,11 +808,9 @@ function ToolCallDisplay({ toolName, argsText, args, result, isRunning, }) {
|
|
|
620
808
|
// Fall through to default pill rendering
|
|
621
809
|
}
|
|
622
810
|
}
|
|
623
|
-
const argsStr = isAgentCall
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
.map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`)
|
|
627
|
-
.join(", ");
|
|
811
|
+
const argsStr = isAgentCall ? "" : toolArgsPreview(args);
|
|
812
|
+
const inputPayload = hasArgs ? toolInputPayload(toolName, args) : null;
|
|
813
|
+
const resultPayload = toolResultPayload(result);
|
|
628
814
|
const displayName = isAgentCall
|
|
629
815
|
? isRunning
|
|
630
816
|
? `Asking ${agentName}...`
|
|
@@ -632,13 +818,13 @@ function ToolCallDisplay({ toolName, argsText, args, result, isRunning, }) {
|
|
|
632
818
|
? `Error asking ${agentName}`
|
|
633
819
|
: `Asked ${agentName}`
|
|
634
820
|
: toolName;
|
|
635
|
-
const canExpand = isAgentCall
|
|
821
|
+
const canExpand = isAgentCall
|
|
822
|
+
? hasStreamText
|
|
823
|
+
: hasArgs || result !== undefined;
|
|
636
824
|
const isExpanded = isAgentCall ? hasStreamText && expanded : expanded;
|
|
637
|
-
return (_jsxs("div", { className: "my-1 overflow-hidden", children: [_jsxs("button", { onClick: () => canExpand && setExpanded(!isExpanded), className: cn("flex items-center gap-2 rounded-md px-2.5 py-1.5 text-xs font-mono w-full text-left overflow-hidden", isRunning
|
|
825
|
+
return (_jsxs("div", { className: "my-1 overflow-hidden", children: [_jsxs("button", { onClick: () => canExpand && setExpanded(!isExpanded), "aria-expanded": canExpand ? isExpanded : undefined, className: cn("flex items-center gap-2 rounded-md px-2.5 py-1.5 text-xs font-mono w-full text-left overflow-hidden", isRunning
|
|
638
826
|
? "bg-muted text-muted-foreground"
|
|
639
|
-
: "bg-muted text-muted-foreground hover:bg-accent"), children: [_jsx("span", { className: "shrink-0", children: isRunning ? (_jsx(IconLoader2, { className: "h-3 w-3 animate-spin" })) : isAgentError ? (_jsx(IconCircleX, { className: "h-3 w-3 text-destructive" })) : result !== undefined ? (_jsx(IconCheck, { className: "h-3 w-3 text-emerald-500" })) : (_jsx(IconSquareFilled, { className: "h-3 w-3 text-muted-foreground" })) }), _jsxs("span", { className: "truncate min-w-0", children: [_jsx("span", { className: "font-medium", children: displayName }), argsStr && _jsxs("span", { className: "opacity-60 ml-1", children: ["(", argsStr, ")"] })] }), canExpand &&
|
|
640
|
-
? result
|
|
641
|
-
: JSON.stringify(result, null, 2) }))] }));
|
|
827
|
+
: "bg-muted text-muted-foreground hover:bg-accent"), children: [_jsx("span", { className: "shrink-0", children: isRunning ? (_jsx(IconLoader2, { className: "h-3 w-3 animate-spin" })) : isAgentError ? (_jsx(IconCircleX, { className: "h-3 w-3 text-destructive" })) : result !== undefined ? (_jsx(IconCheck, { className: "h-3 w-3 text-emerald-500" })) : (_jsx(IconSquareFilled, { className: "h-3 w-3 text-muted-foreground" })) }), _jsxs("span", { className: "truncate min-w-0", children: [_jsx("span", { className: "font-medium", children: displayName }), argsStr && _jsxs("span", { className: "opacity-60 ml-1", children: ["(", argsStr, ")"] })] }), canExpand && (_jsx(IconChevronDown, { className: cn("ml-auto h-3 w-3 shrink-0 opacity-40", isExpanded && "rotate-180") }))] }), isExpanded && isAgentCall && hasStreamText && (_jsx("div", { ref: streamRef, className: "mt-1 rounded-md bg-muted/50 px-3 py-2 text-xs text-muted-foreground break-words max-h-48 overflow-y-auto agent-markdown prose prose-sm prose-invert max-w-none", children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components: markdownComponents, children: agentStreamText }) })), isExpanded && !isAgentCall && (hasArgs || result !== undefined) && (_jsxs("div", { className: "mt-1 space-y-2 rounded-md bg-muted/50 px-3 py-2 text-xs text-muted-foreground", children: [inputPayload && _jsx(ToolDetailViewer, { payload: inputPayload }), resultPayload && _jsx(ToolDetailViewer, { payload: resultPayload })] }))] }));
|
|
642
828
|
}
|
|
643
829
|
function ToolCallFallback({ toolName, args, argsText, result, }) {
|
|
644
830
|
const chatRunning = React.useContext(ChatRunningContext);
|
|
@@ -866,6 +1052,7 @@ function AssistantMessage() {
|
|
|
866
1052
|
const chatRunning = React.useContext(ChatRunningContext);
|
|
867
1053
|
const msg = messageRuntime.getState();
|
|
868
1054
|
const timestamp = formatMessageTimestamp(msg.createdAt);
|
|
1055
|
+
const activityTrail = activityTrailFromMetadata(msg);
|
|
869
1056
|
const isLast = thread.messages.length > 0 &&
|
|
870
1057
|
thread.messages[thread.messages.length - 1].id === msg.id;
|
|
871
1058
|
const isComplete = !isLast || !chatRunning;
|
|
@@ -921,7 +1108,7 @@ function AssistantMessage() {
|
|
|
921
1108
|
tools: {
|
|
922
1109
|
Fallback: ToolCallFallback,
|
|
923
1110
|
},
|
|
924
|
-
} }) }), isComplete && (_jsxs("div", { className: "mt-1 flex items-center justify-between", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx(MessageActionsMenu, { showRevert: showRestore && restoreState === "idle", onRevert: handleRestore }), timestamp && (_jsx(MessageTimestamp, { timestamp: timestamp, className: "opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100" }))] }), showRestore && restoreState === "confirming" ? (_jsxs("div", { className: "flex items-center gap-1 text-xs", children: [_jsx("button", { onClick: handleRestore, className: "rounded-md bg-destructive px-1.5 py-0.5 text-destructive-foreground hover:bg-destructive/90", children: "Restore to here?" }), _jsx("button", { onClick: cancelRestore, className: "rounded-md px-1.5 py-0.5 text-muted-foreground hover:bg-accent", children: "Cancel" })] })) : showRestore && restoreState === "restoring" ? (_jsxs("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [_jsx(IconLoader2, { className: "h-3 w-3 animate-spin" }), "Restoring..."] })) : (_jsx(ThumbsFeedback, { threadId: cpCtx?.threadId ?? "", runId: (() => {
|
|
1111
|
+
} }) }), isComplete && activityTrail.length > 0 && (_jsx(RunActivityTrail, { steps: activityTrail })), isComplete && (_jsxs("div", { className: "mt-1 flex items-center justify-between", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx(MessageActionsMenu, { showRevert: showRestore && restoreState === "idle", onRevert: handleRestore }), timestamp && (_jsx(MessageTimestamp, { timestamp: timestamp, className: "opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100" }))] }), showRestore && restoreState === "confirming" ? (_jsxs("div", { className: "flex items-center gap-1 text-xs", children: [_jsx("button", { onClick: handleRestore, className: "rounded-md bg-destructive px-1.5 py-0.5 text-destructive-foreground hover:bg-destructive/90", children: "Restore to here?" }), _jsx("button", { onClick: cancelRestore, className: "rounded-md px-1.5 py-0.5 text-muted-foreground hover:bg-accent", children: "Cancel" })] })) : showRestore && restoreState === "restoring" ? (_jsxs("span", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [_jsx(IconLoader2, { className: "h-3 w-3 animate-spin" }), "Restoring..."] })) : (_jsx(ThumbsFeedback, { threadId: cpCtx?.threadId ?? "", runId: (() => {
|
|
925
1112
|
const meta = messageRuntime.getState().metadata;
|
|
926
1113
|
return ((typeof meta?.custom?.runId === "string" &&
|
|
927
1114
|
meta.custom.runId) ||
|
|
@@ -1036,6 +1223,11 @@ function getRunErrorMetadata(message) {
|
|
|
1036
1223
|
...(runError.recoverable ? { recoverable: true } : {}),
|
|
1037
1224
|
};
|
|
1038
1225
|
}
|
|
1226
|
+
function getRequestModeMetadata(message) {
|
|
1227
|
+
const meta = message?.metadata;
|
|
1228
|
+
const requestMode = meta?.custom?.requestMode ?? meta?.requestMode;
|
|
1229
|
+
return requestMode === "act" || requestMode === "plan" ? requestMode : null;
|
|
1230
|
+
}
|
|
1039
1231
|
function isBuilderReconnectRunError(info) {
|
|
1040
1232
|
const code = (info.errorCode ?? "").toLowerCase();
|
|
1041
1233
|
const message = info.message.toLowerCase();
|
|
@@ -1047,6 +1239,20 @@ function isBuilderReconnectRunError(info) {
|
|
|
1047
1239
|
message.includes("builder authentication failed") ||
|
|
1048
1240
|
(isAuthCode && message.includes("invalid token")));
|
|
1049
1241
|
}
|
|
1242
|
+
function isProviderQueryRunError(info) {
|
|
1243
|
+
const text = [info.errorCode, info.message, info.details]
|
|
1244
|
+
.filter(Boolean)
|
|
1245
|
+
.join("\n")
|
|
1246
|
+
.toLowerCase();
|
|
1247
|
+
return (text.includes("bigquery") ||
|
|
1248
|
+
text.includes("sql") ||
|
|
1249
|
+
text.includes("query") ||
|
|
1250
|
+
text.includes("schema") ||
|
|
1251
|
+
text.includes("syntax") ||
|
|
1252
|
+
text.includes("unknown column") ||
|
|
1253
|
+
text.includes("unknown table") ||
|
|
1254
|
+
text.includes("type mismatch"));
|
|
1255
|
+
}
|
|
1050
1256
|
function getMessageText(message) {
|
|
1051
1257
|
const msg = message?.message ?? message;
|
|
1052
1258
|
const content = msg?.content;
|
|
@@ -1064,6 +1270,8 @@ function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDismiss, })
|
|
|
1064
1270
|
const [copied, setCopied] = useState(false);
|
|
1065
1271
|
const canRecover = info.recoverable === true;
|
|
1066
1272
|
const shouldShowBuilderReconnect = isBuilderReconnectRunError(info);
|
|
1273
|
+
const isQueryError = isProviderQueryRunError(info);
|
|
1274
|
+
const copyLabel = info.runId || info.errorCode || info.details ? "Copy debug" : "Copy";
|
|
1067
1275
|
const copyDetails = useCallback(() => {
|
|
1068
1276
|
const text = [
|
|
1069
1277
|
info.message,
|
|
@@ -1079,7 +1287,7 @@ function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDismiss, })
|
|
|
1079
1287
|
}, [info]);
|
|
1080
1288
|
return (_jsxs("div", { className: "rounded-lg border border-amber-500/25 bg-amber-500/[0.06] p-3 text-sm", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-amber-500/10 text-amber-700 dark:text-amber-300", children: _jsx(IconAlertTriangle, { size: 14 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-medium text-foreground", children: canRecover
|
|
1081
1289
|
? "The agent stopped before finishing"
|
|
1082
|
-
: "The agent hit an error" }), _jsx("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: info.message }), shouldShowBuilderReconnect && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-muted-foreground", children: "The current Builder.io or model-provider credential was rejected. Reconnect Builder.io, then retry this message." })), (info.runId || info.errorCode || info.details) && (_jsxs("button", { type: "button", onClick: () => setDetailsOpen((v) => !v), className: "mt-2 inline-flex items-center gap-1 text-[11px] font-medium text-muted-foreground hover:text-foreground", children: [_jsx(IconChevronDown, { size: 12, className: cn("transition-transform", detailsOpen && "rotate-180") }), "Details"] })), detailsOpen && (_jsxs("div", { className: "mt-2 rounded-md border border-border/60 bg-background/70 p-2 font-mono text-[11px] leading-relaxed text-muted-foreground", children: [info.runId && _jsxs("div", { children: ["run: ", info.runId] }), info.errorCode && _jsxs("div", { children: ["code: ", info.errorCode] }), info.details && (_jsx("pre", { className: "mt-2 max-h-28 overflow-auto whitespace-pre-wrap break-words font-mono", children: info.details }))] }))] }), _jsx("button", { type: "button", onClick: onDismiss, "aria-label": "Dismiss", className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-background/80 hover:text-foreground", children: _jsx(IconX, { size: 14 }) })] }), _jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [shouldShowBuilderReconnect && (_jsxs("a", { href: agentNativePath("/_agent-native/builder/connect"), target: "_blank", rel: "noreferrer", className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90", children: [_jsx(IconExternalLink, { size: 13 }), "Reconnect Builder.io"] })), canRecover && (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", onClick: onContinue, className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90", children: [_jsx(IconPlayerPlay, { size: 13 }), "Continue"] }), _jsxs("button", { type: "button", onClick: onRetry, className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent", children: [_jsx(IconRefresh, { size: 13 }), "Retry"] })] })), canRecover && onFork && (_jsxs("button", { type: "button", onClick: onFork, title: "Fork this conversation into a separate chat thread.", "aria-label": "Fork this conversation into a separate chat thread", className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent", children: [_jsx(IconGitFork, { size: 13 }), "Fork chat"] })), _jsxs("button", { type: "button", onClick: copyDetails, className: "ml-auto inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs font-medium text-muted-foreground hover:bg-background/80 hover:text-foreground", children: [copied ? _jsx(IconCheck, { size: 13 }) : _jsx(IconCopy, { size: 13 }), copied ? "Copied" :
|
|
1290
|
+
: "The agent hit an error" }), _jsx("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: info.message }), shouldShowBuilderReconnect && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-muted-foreground", children: "The current Builder.io or model-provider credential was rejected. Reconnect Builder.io, then retry this message." })), (info.runId || info.errorCode || info.details) && (_jsxs("button", { type: "button", onClick: () => setDetailsOpen((v) => !v), className: "mt-2 inline-flex items-center gap-1 text-[11px] font-medium text-muted-foreground hover:text-foreground", children: [_jsx(IconChevronDown, { size: 12, className: cn("transition-transform", detailsOpen && "rotate-180") }), "Details"] })), detailsOpen && (_jsxs("div", { className: "mt-2 rounded-md border border-border/60 bg-background/70 p-2 font-mono text-[11px] leading-relaxed text-muted-foreground", children: [info.runId && _jsxs("div", { children: ["run: ", info.runId] }), info.errorCode && _jsxs("div", { children: ["code: ", info.errorCode] }), info.details && (_jsx("pre", { className: "mt-2 max-h-28 overflow-auto whitespace-pre-wrap break-words font-mono", children: info.details }))] }))] }), _jsx("button", { type: "button", onClick: onDismiss, "aria-label": "Dismiss", className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-background/80 hover:text-foreground", children: _jsx(IconX, { size: 14 }) })] }), _jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [shouldShowBuilderReconnect && (_jsxs("a", { href: agentNativePath("/_agent-native/builder/connect"), target: "_blank", rel: "noreferrer", className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90", children: [_jsx(IconExternalLink, { size: 13 }), "Reconnect Builder.io"] })), canRecover && (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", onClick: onContinue, className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90", children: [_jsx(IconPlayerPlay, { size: 13 }), "Continue"] }), _jsxs("button", { type: "button", onClick: onRetry, className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent", children: [_jsx(IconRefresh, { size: 13 }), isQueryError ? "Diagnose and retry" : "Retry"] })] })), canRecover && onFork && (_jsxs("button", { type: "button", onClick: onFork, title: "Fork this conversation into a separate chat thread.", "aria-label": "Fork this conversation into a separate chat thread", className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent", children: [_jsx(IconGitFork, { size: 13 }), "Fork chat"] })), _jsxs("button", { type: "button", onClick: copyDetails, className: "ml-auto inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs font-medium text-muted-foreground hover:bg-background/80 hover:text-foreground", children: [copied ? _jsx(IconCheck, { size: 13 }) : _jsx(IconCopy, { size: 13 }), copied ? "Copied" : copyLabel] })] })] }));
|
|
1083
1291
|
}
|
|
1084
1292
|
function LoopLimitContinueCard({ info, onContinue, }) {
|
|
1085
1293
|
const [settings, setSettings] = useState(null);
|
|
@@ -2093,12 +2301,15 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2093
2301
|
}
|
|
2094
2302
|
return "";
|
|
2095
2303
|
}, [messages]);
|
|
2096
|
-
const
|
|
2304
|
+
const latestMessage = messages[messages.length - 1];
|
|
2305
|
+
const latestMessageRole = latestMessage?.role;
|
|
2306
|
+
const latestAssistantWasPlan = latestMessageRole === "assistant" &&
|
|
2307
|
+
getRequestModeMetadata(latestMessage) === "plan";
|
|
2097
2308
|
const showPlanModeCallout = execMode === "plan" &&
|
|
2098
2309
|
!planModeDisabled &&
|
|
2099
2310
|
!isComposerDisabled &&
|
|
2100
2311
|
!showRunningInUI;
|
|
2101
|
-
const canImplementPlan = showPlanModeCallout &&
|
|
2312
|
+
const canImplementPlan = showPlanModeCallout && latestAssistantWasPlan;
|
|
2102
2313
|
const handleImplementPlan = useCallback(() => {
|
|
2103
2314
|
onExecModeChange?.("build");
|
|
2104
2315
|
void addToQueue("Implement the plan.", undefined, undefined, undefined, "act");
|
|
@@ -2161,12 +2372,12 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
2161
2372
|
addToQueue("Continue from where you left off.");
|
|
2162
2373
|
} })), shouldShowRunError && visibleRunError && (_jsx(RunErrorRecoveryCard, { info: visibleRunError, onContinue: () => {
|
|
2163
2374
|
setRunErrorInfo(null);
|
|
2164
|
-
addToQueue("Continue from where you stopped. Use the partial work above, verify what succeeded, and finish the original request. Prefer dedicated app actions over raw database edits when they exist.");
|
|
2375
|
+
addToQueue("Continue from where you stopped. Use the partial work above, verify what succeeded, and finish the original request. Do not rerun the exact same failed tool input unless the failure was transient or the user explicitly asked for an exact rerun. Prefer dedicated app actions over raw database edits when they exist.");
|
|
2165
2376
|
}, onRetry: () => {
|
|
2166
2377
|
setRunErrorInfo(null);
|
|
2167
2378
|
addToQueue(lastUserText
|
|
2168
|
-
? `Retry the previous request from a clean approach.
|
|
2169
|
-
: "Retry the previous request from a clean approach.");
|
|
2379
|
+
? `Retry the previous request from a clean approach. Do not rerun the exact same failed tool input unless the failure was transient or the user explicitly asked for an exact rerun. If a provider query failed because of schema, syntax, or type mismatch, diagnose the error and adjust the query first.\n\nOriginal request:\n\n${lastUserText}`
|
|
2380
|
+
: "Retry the previous request from a clean approach. Do not rerun the exact same failed tool input unless the failure was transient or the user explicitly asked for an exact rerun. If a provider query failed because of schema, syntax, or type mismatch, diagnose the error and adjust the query first.");
|
|
2170
2381
|
}, onFork: onForkChat, onDismiss: () => {
|
|
2171
2382
|
if (visibleRunErrorKey) {
|
|
2172
2383
|
setDismissedRunErrorKey(visibleRunErrorKey);
|