@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.
Files changed (82) hide show
  1. package/dist/agent/run-manager.d.ts.map +1 -1
  2. package/dist/agent/run-manager.js +21 -5
  3. package/dist/agent/run-manager.js.map +1 -1
  4. package/dist/client/AgentPanel.d.ts.map +1 -1
  5. package/dist/client/AgentPanel.js +10 -3
  6. package/dist/client/AgentPanel.js.map +1 -1
  7. package/dist/client/AssistantChat.d.ts.map +1 -1
  8. package/dist/client/AssistantChat.js +234 -23
  9. package/dist/client/AssistantChat.js.map +1 -1
  10. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  11. package/dist/client/MultiTabAssistantChat.js +9 -8
  12. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  13. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  14. package/dist/client/agent-chat-adapter.js +23 -4
  15. package/dist/client/agent-chat-adapter.js.map +1 -1
  16. package/dist/client/components/ui/hover-card.d.ts +7 -0
  17. package/dist/client/components/ui/hover-card.d.ts.map +1 -0
  18. package/dist/client/components/ui/hover-card.js +10 -0
  19. package/dist/client/components/ui/hover-card.js.map +1 -0
  20. package/dist/client/composer/TiptapComposer.js +1 -1
  21. package/dist/client/composer/TiptapComposer.js.map +1 -1
  22. package/dist/client/dev-overlay/DevOverlay.d.ts.map +1 -1
  23. package/dist/client/dev-overlay/DevOverlay.js +5 -1
  24. package/dist/client/dev-overlay/DevOverlay.js.map +1 -1
  25. package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
  26. package/dist/client/extensions/ExtensionsSidebarSection.js +3 -2
  27. package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
  28. package/dist/client/guided-questions.d.ts +77 -0
  29. package/dist/client/guided-questions.d.ts.map +1 -0
  30. package/dist/client/guided-questions.js +295 -0
  31. package/dist/client/guided-questions.js.map +1 -0
  32. package/dist/client/index.d.ts +1 -0
  33. package/dist/client/index.d.ts.map +1 -1
  34. package/dist/client/index.js +1 -0
  35. package/dist/client/index.js.map +1 -1
  36. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  37. package/dist/client/org/OrgSwitcher.js +8 -1
  38. package/dist/client/org/OrgSwitcher.js.map +1 -1
  39. package/dist/client/settings/SettingsPanel.d.ts +3 -1
  40. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  41. package/dist/client/settings/SettingsPanel.js +78 -12
  42. package/dist/client/settings/SettingsPanel.js.map +1 -1
  43. package/dist/client/settings/SettingsSection.d.ts +2 -1
  44. package/dist/client/settings/SettingsSection.d.ts.map +1 -1
  45. package/dist/client/settings/SettingsSection.js +2 -2
  46. package/dist/client/settings/SettingsSection.js.map +1 -1
  47. package/dist/client/sharing/ShareButton.d.ts +4 -0
  48. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  49. package/dist/client/sharing/ShareButton.js +76 -32
  50. package/dist/client/sharing/ShareButton.js.map +1 -1
  51. package/dist/client/sharing/ShareButton.spec.js +54 -7
  52. package/dist/client/sharing/ShareButton.spec.js.map +1 -1
  53. package/dist/client/sse-event-processor.d.ts.map +1 -1
  54. package/dist/client/sse-event-processor.js +42 -5
  55. package/dist/client/sse-event-processor.js.map +1 -1
  56. package/dist/client/use-db-sync.d.ts +12 -2
  57. package/dist/client/use-db-sync.d.ts.map +1 -1
  58. package/dist/client/use-db-sync.js +195 -53
  59. package/dist/client/use-db-sync.js.map +1 -1
  60. package/dist/server/core-routes-plugin.js +2 -2
  61. package/dist/server/core-routes-plugin.js.map +1 -1
  62. package/dist/server/google-auth-plugin.d.ts.map +1 -1
  63. package/dist/server/google-auth-plugin.js +18 -2
  64. package/dist/server/google-auth-plugin.js.map +1 -1
  65. package/dist/server/index.d.ts +2 -1
  66. package/dist/server/index.d.ts.map +1 -1
  67. package/dist/server/index.js +2 -1
  68. package/dist/server/index.js.map +1 -1
  69. package/dist/server/onboarding-html.d.ts.map +1 -1
  70. package/dist/server/onboarding-html.js +18 -2
  71. package/dist/server/onboarding-html.js.map +1 -1
  72. package/dist/server/poll-events.d.ts +12 -0
  73. package/dist/server/poll-events.d.ts.map +1 -0
  74. package/dist/server/poll-events.js +41 -0
  75. package/dist/server/poll-events.js.map +1 -0
  76. package/dist/server/poll.d.ts +4 -0
  77. package/dist/server/poll.d.ts.map +1 -1
  78. package/dist/server/poll.js +19 -12
  79. package/dist/server/poll.js.map +1 -1
  80. package/dist/templates/default/react-router.config.ts +1 -0
  81. package/package.json +2 -1
  82. 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":"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"}
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
- // ─── Tool Call Display ──────────────────────────────────────────────────────
567
- // Shared presentational component for rendering a tool call pill + result.
568
- // Used by both the normal message path (ToolCallFallback) and the reconnect
569
- // stream path (ReconnectStreamMessage). All state is passed as props — no
570
- // assistant-ui hooks here.
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
- : Object.entries(args)
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 ? hasStreamText : result !== undefined;
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 && !isRunning && (_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 && result !== undefined && (_jsx("div", { className: "mt-1 rounded-md bg-muted/50 px-3 py-2 text-xs font-mono text-muted-foreground whitespace-pre-wrap break-all max-h-48 overflow-y-auto", children: typeof result === "string"
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" : "Copy"] })] })] }));
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 latestMessageRole = messages[messages.length - 1]?.role;
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 && latestMessageRole === "assistant";
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. Original request:\n\n${lastUserText}`
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);