@agent-native/toolkit 0.213.1 → 0.214.0

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 (198) hide show
  1. package/agent-native.eject.json +9 -0
  2. package/dist/app/agentkit/react/components.d.ts.map +1 -1
  3. package/dist/app/agentkit/react/components.js +10 -4
  4. package/dist/app/agentkit/react/components.js.map +1 -1
  5. package/dist/app/agentkit/react/context.d.ts +13 -1
  6. package/dist/app/agentkit/react/context.d.ts.map +1 -1
  7. package/dist/app/agentkit/react/context.js +3 -1
  8. package/dist/app/agentkit/react/context.js.map +1 -1
  9. package/dist/app/agentkit/react/index.d.ts +1 -0
  10. package/dist/app/agentkit/react/index.d.ts.map +1 -1
  11. package/dist/app/agentkit/react/index.js +1 -0
  12. package/dist/app/agentkit/react/index.js.map +1 -1
  13. package/dist/app/agentkit/react/message-content-order.d.ts +21 -0
  14. package/dist/app/agentkit/react/message-content-order.d.ts.map +1 -0
  15. package/dist/app/agentkit/react/message-content-order.js +173 -0
  16. package/dist/app/agentkit/react/message-content-order.js.map +1 -0
  17. package/dist/app/agentkit/react/root.d.ts +3 -1
  18. package/dist/app/agentkit/react/root.d.ts.map +1 -1
  19. package/dist/app/agentkit/react/root.js +2 -2
  20. package/dist/app/agentkit/react/root.js.map +1 -1
  21. package/dist/app/agentkit/react/styles.css +2 -2
  22. package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
  23. package/dist/app/chat/AgentKitAssistantChat.js +7 -2
  24. package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
  25. package/dist/app/chat/AgentPanel.d.ts +14 -2
  26. package/dist/app/chat/AgentPanel.d.ts.map +1 -1
  27. package/dist/app/chat/AgentPanel.js +22 -5
  28. package/dist/app/chat/AgentPanel.js.map +1 -1
  29. package/dist/app/chat/chat/surface-types.d.ts +8 -0
  30. package/dist/app/chat/chat/surface-types.d.ts.map +1 -1
  31. package/dist/app/chat/chat/surface-types.js.map +1 -1
  32. package/dist/app/chat/chat/widgets/DataChartRenderer.d.ts.map +1 -1
  33. package/dist/app/chat/chat/widgets/DataChartRenderer.js +127 -30
  34. package/dist/app/chat/chat/widgets/DataChartRenderer.js.map +1 -1
  35. package/dist/app/chat/chat/widgets/DataChartWidget.d.ts +3 -2
  36. package/dist/app/chat/chat/widgets/DataChartWidget.d.ts.map +1 -1
  37. package/dist/app/chat/chat/widgets/DataChartWidget.js +14 -9
  38. package/dist/app/chat/chat/widgets/DataChartWidget.js.map +1 -1
  39. package/dist/app/chat/chat/widgets/DataInsightsWidget.js +1 -1
  40. package/dist/app/chat/chat/widgets/DataInsightsWidget.js.map +1 -1
  41. package/dist/app/chat/chat/widgets/DataTableWidget.d.ts +3 -2
  42. package/dist/app/chat/chat/widgets/DataTableWidget.d.ts.map +1 -1
  43. package/dist/app/chat/chat/widgets/DataTableWidget.js +10 -66
  44. package/dist/app/chat/chat/widgets/DataTableWidget.js.map +1 -1
  45. package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.d.ts +11 -0
  46. package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.d.ts.map +1 -0
  47. package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.js +131 -0
  48. package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.js.map +1 -0
  49. package/dist/app/chat/chat/widgets/builtin-tool-renderers.js +2 -2
  50. package/dist/app/chat/chat/widgets/builtin-tool-renderers.js.map +1 -1
  51. package/dist/app/chat/mcp-apps/McpAppRenderer.d.ts.map +1 -1
  52. package/dist/app/chat/mcp-apps/McpAppRenderer.js +6 -5
  53. package/dist/app/chat/mcp-apps/McpAppRenderer.js.map +1 -1
  54. package/dist/app/chat/mcp-apps/mcp-app-theme.d.ts +2 -0
  55. package/dist/app/chat/mcp-apps/mcp-app-theme.d.ts.map +1 -0
  56. package/dist/app/chat/mcp-apps/mcp-app-theme.js +11 -0
  57. package/dist/app/chat/mcp-apps/mcp-app-theme.js.map +1 -0
  58. package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
  59. package/dist/app/i18n/catalogs/ar-SA.js +8 -0
  60. package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
  61. package/dist/app/i18n/catalogs/de-DE.d.ts.map +1 -1
  62. package/dist/app/i18n/catalogs/de-DE.js +8 -0
  63. package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
  64. package/dist/app/i18n/catalogs/en-US.d.ts +8 -0
  65. package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
  66. package/dist/app/i18n/catalogs/en-US.js +8 -0
  67. package/dist/app/i18n/catalogs/en-US.js.map +1 -1
  68. package/dist/app/i18n/catalogs/es-ES.d.ts.map +1 -1
  69. package/dist/app/i18n/catalogs/es-ES.js +8 -0
  70. package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
  71. package/dist/app/i18n/catalogs/fr-FR.d.ts.map +1 -1
  72. package/dist/app/i18n/catalogs/fr-FR.js +8 -0
  73. package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
  74. package/dist/app/i18n/catalogs/hi-IN.d.ts.map +1 -1
  75. package/dist/app/i18n/catalogs/hi-IN.js +8 -0
  76. package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
  77. package/dist/app/i18n/catalogs/ja-JP.d.ts.map +1 -1
  78. package/dist/app/i18n/catalogs/ja-JP.js +8 -0
  79. package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
  80. package/dist/app/i18n/catalogs/ko-KR.d.ts.map +1 -1
  81. package/dist/app/i18n/catalogs/ko-KR.js +8 -0
  82. package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
  83. package/dist/app/i18n/catalogs/pt-BR.d.ts.map +1 -1
  84. package/dist/app/i18n/catalogs/pt-BR.js +8 -0
  85. package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
  86. package/dist/app/i18n/catalogs/zh-CN.d.ts.map +1 -1
  87. package/dist/app/i18n/catalogs/zh-CN.js +8 -0
  88. package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
  89. package/dist/app/i18n/catalogs/zh-TW.d.ts.map +1 -1
  90. package/dist/app/i18n/catalogs/zh-TW.js +8 -0
  91. package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
  92. package/dist/app/providers/AppProviders.d.ts +2 -1
  93. package/dist/app/providers/AppProviders.d.ts.map +1 -1
  94. package/dist/app/providers/AppProviders.js +4 -3
  95. package/dist/app/providers/AppProviders.js.map +1 -1
  96. package/dist/app/providers/ThemeFamilySync.d.ts +2 -0
  97. package/dist/app/providers/ThemeFamilySync.d.ts.map +1 -0
  98. package/dist/app/providers/ThemeFamilySync.js +6 -0
  99. package/dist/app/providers/ThemeFamilySync.js.map +1 -0
  100. package/dist/app/settings/account/PreferencesSettings.d.ts.map +1 -1
  101. package/dist/app/settings/account/PreferencesSettings.js +2 -1
  102. package/dist/app/settings/account/PreferencesSettings.js.map +1 -1
  103. package/dist/app/settings/account/ThemeFamilySettings.d.ts +2 -0
  104. package/dist/app/settings/account/ThemeFamilySettings.d.ts.map +1 -0
  105. package/dist/app/settings/account/ThemeFamilySettings.js +31 -0
  106. package/dist/app/settings/account/ThemeFamilySettings.js.map +1 -0
  107. package/dist/app/settings/account/search-entries.d.ts.map +1 -1
  108. package/dist/app/settings/account/search-entries.js +6 -0
  109. package/dist/app/settings/account/search-entries.js.map +1 -1
  110. package/dist/app/shared/DefaultSpinner.d.ts.map +1 -1
  111. package/dist/app/shared/DefaultSpinner.js +4 -5
  112. package/dist/app/shared/DefaultSpinner.js.map +1 -1
  113. package/dist/app/shared/ErrorBoundary.d.ts +1 -0
  114. package/dist/app/shared/ErrorBoundary.d.ts.map +1 -1
  115. package/dist/app/shared/ErrorBoundary.js +27 -12
  116. package/dist/app/shared/ErrorBoundary.js.map +1 -1
  117. package/dist/app/shared/PoweredByBadge.d.ts.map +1 -1
  118. package/dist/app/shared/PoweredByBadge.js +8 -49
  119. package/dist/app/shared/PoweredByBadge.js.map +1 -1
  120. package/dist/app/styles/agent-conversation.css +0 -23
  121. package/dist/app/styles/agent-native.css +1 -1
  122. package/dist/app/styles/theme-families.css +66 -0
  123. package/dist/composer/ComposerContextBanner.d.ts +22 -0
  124. package/dist/composer/ComposerContextBanner.d.ts.map +1 -0
  125. package/dist/composer/ComposerContextBanner.js +9 -0
  126. package/dist/composer/ComposerContextBanner.js.map +1 -0
  127. package/dist/composer/ComposerModePicker.d.ts +26 -0
  128. package/dist/composer/ComposerModePicker.d.ts.map +1 -0
  129. package/dist/composer/ComposerModePicker.js +14 -0
  130. package/dist/composer/ComposerModePicker.js.map +1 -0
  131. package/dist/composer/index.d.ts +2 -0
  132. package/dist/composer/index.d.ts.map +1 -1
  133. package/dist/composer/index.js +2 -0
  134. package/dist/composer/index.js.map +1 -1
  135. package/dist/styles.css +1 -0
  136. package/package.json +3 -3
  137. package/src/app/agentkit/react/components.spec.tsx +12 -0
  138. package/src/app/agentkit/react/components.tsx +41 -22
  139. package/src/app/agentkit/react/context.tsx +17 -0
  140. package/src/app/agentkit/react/index.ts +1 -0
  141. package/src/app/agentkit/react/lifecycle.spec.tsx +116 -1
  142. package/src/app/agentkit/react/message-content-order.spec.ts +190 -0
  143. package/src/app/agentkit/react/message-content-order.ts +246 -0
  144. package/src/app/agentkit/react/root.tsx +4 -0
  145. package/src/app/agentkit/react/styles.css +2 -2
  146. package/src/app/chat/AgentKitAssistantChat.spec.tsx +19 -0
  147. package/src/app/chat/AgentKitAssistantChat.tsx +10 -1
  148. package/src/app/chat/AgentPanel.header.spec.ts +72 -14
  149. package/src/app/chat/AgentPanel.tsx +97 -53
  150. package/src/app/chat/chat/surface-types.ts +8 -0
  151. package/src/app/chat/chat/widgets/DataChartRenderer.spec.tsx +217 -0
  152. package/src/app/chat/chat/widgets/DataChartRenderer.tsx +306 -68
  153. package/src/app/chat/chat/widgets/DataChartWidget.spec.tsx +329 -0
  154. package/src/app/chat/chat/widgets/DataChartWidget.ssr.spec.tsx +25 -0
  155. package/src/app/chat/chat/widgets/DataChartWidget.tsx +48 -33
  156. package/src/app/chat/chat/widgets/DataInsightsWidget.tsx +2 -2
  157. package/src/app/chat/chat/widgets/DataTableWidget.spec.tsx +37 -3
  158. package/src/app/chat/chat/widgets/DataTableWidget.tsx +22 -86
  159. package/src/app/chat/chat/widgets/DataWidgetDisplayControls.tsx +301 -0
  160. package/src/app/chat/chat/widgets/builtin-tool-renderers.tsx +5 -5
  161. package/src/app/chat/mcp-apps/McpAppRenderer.tsx +10 -5
  162. package/src/app/chat/mcp-apps/mcp-app-theme.spec.ts +30 -0
  163. package/src/app/chat/mcp-apps/mcp-app-theme.ts +11 -0
  164. package/src/app/i18n/catalogs/ar-SA.ts +9 -0
  165. package/src/app/i18n/catalogs/de-DE.ts +9 -0
  166. package/src/app/i18n/catalogs/en-US.ts +9 -0
  167. package/src/app/i18n/catalogs/es-ES.ts +10 -0
  168. package/src/app/i18n/catalogs/fr-FR.ts +10 -0
  169. package/src/app/i18n/catalogs/hi-IN.ts +9 -0
  170. package/src/app/i18n/catalogs/ja-JP.ts +9 -0
  171. package/src/app/i18n/catalogs/ko-KR.ts +9 -0
  172. package/src/app/i18n/catalogs/pt-BR.ts +9 -0
  173. package/src/app/i18n/catalogs/zh-CN.ts +8 -0
  174. package/src/app/i18n/catalogs/zh-TW.ts +9 -0
  175. package/src/app/providers/AppProviders.spec.tsx +71 -0
  176. package/src/app/providers/AppProviders.tsx +10 -0
  177. package/src/app/providers/ThemeFamilySync.tsx +6 -0
  178. package/src/app/settings/account/PreferencesSettings.spec.tsx +13 -2
  179. package/src/app/settings/account/PreferencesSettings.tsx +8 -0
  180. package/src/app/settings/account/ThemeFamilySettings.tsx +61 -0
  181. package/src/app/settings/account/search-entries.ts +6 -0
  182. package/src/app/shared/DefaultSpinner.spec.tsx +14 -0
  183. package/src/app/shared/DefaultSpinner.tsx +4 -5
  184. package/src/app/shared/ErrorBoundary.spec.tsx +45 -2
  185. package/src/app/shared/ErrorBoundary.tsx +37 -12
  186. package/src/app/shared/PoweredByBadge.spec.tsx +16 -0
  187. package/src/app/shared/PoweredByBadge.tsx +8 -50
  188. package/src/app/styles/agent-conversation.css +0 -23
  189. package/src/app/styles/agent-native.css +1 -1
  190. package/src/app/styles/agent-native.spec.ts +18 -0
  191. package/src/app/styles/theme-families.css +66 -0
  192. package/src/app/styles/theme-families.spec.ts +29 -0
  193. package/src/composer/ComposerContextBanner.spec.tsx +74 -0
  194. package/src/composer/ComposerContextBanner.tsx +72 -0
  195. package/src/composer/ComposerModePicker.spec.tsx +101 -0
  196. package/src/composer/ComposerModePicker.tsx +98 -0
  197. package/src/composer/index.ts +9 -0
  198. package/src/styles.css +1 -0
@@ -441,6 +441,30 @@ export function shouldShowAgentPanelPageHeader(
441
441
  );
442
442
  }
443
443
 
444
+ export function resolveAgentPanelPageHeaderActions({
445
+ showPageTitleMenu = true,
446
+ canShareActiveTab,
447
+ }: {
448
+ showPageTitleMenu?: boolean;
449
+ canShareActiveTab: boolean;
450
+ }) {
451
+ return { showPageTitleMenu, showShareAction: canShareActiveTab };
452
+ }
453
+
454
+ export type AgentPanelPageToolbarActions = Pick<
455
+ MultiTabAssistantChatHeaderCallbackProps,
456
+ "activeTabMessageCount" | "clearActiveTab" | "showHistory" | "toggleHistory"
457
+ >;
458
+
459
+ export function resolveAgentPanelPageToolbarSlot(
460
+ slot:
461
+ | React.ReactNode
462
+ | ((actions: AgentPanelPageToolbarActions) => React.ReactNode),
463
+ actions: AgentPanelPageToolbarActions,
464
+ ) {
465
+ return typeof slot === "function" ? slot(actions) : slot;
466
+ }
467
+
444
468
  export function shouldShowAgentPanelCliTabBar(cliTabs: string[]) {
445
469
  return cliTabs.length > 1;
446
470
  }
@@ -583,8 +607,13 @@ export interface AgentPanelProps extends Omit<
583
607
  showPageNewChatButton?: boolean;
584
608
  showPageHeader?: boolean;
585
609
  showPageHeaderWhenEmpty?: boolean;
610
+ /** Hide the default page title menu while keeping the shared page actions. */
611
+ showPageTitleMenu?: boolean;
586
612
  pageHeaderLeadingSlot?: React.ReactNode;
587
- pageToolbarSlot?: React.ReactNode;
613
+ /** Render host page actions alongside Share, with the active chat controls. */
614
+ pageToolbarSlot?:
615
+ | React.ReactNode
616
+ | ((actions: AgentPanelPageToolbarActions) => React.ReactNode);
588
617
  onPageHeaderVisibilityChange?: (visible: boolean) => void;
589
618
  chatOnly?: boolean;
590
619
  agentPageHref?: string;
@@ -778,6 +807,7 @@ function AgentPanelInner({
778
807
  showPageNewChatButton = false,
779
808
  showPageHeader = false,
780
809
  showPageHeaderWhenEmpty = false,
810
+ showPageTitleMenu = true,
781
811
  pageHeaderLeadingSlot,
782
812
  pageToolbarSlot,
783
813
  onPageHeaderVisibilityChange,
@@ -1694,11 +1724,16 @@ function AgentPanelInner({
1694
1724
  showPageHeaderWhenEmpty,
1695
1725
  activeTabIsPersisted,
1696
1726
  );
1697
- const canShareActiveTab =
1727
+ const canShareActiveTab = Boolean(
1698
1728
  activeTab &&
1699
1729
  (activeTabIsPersisted ||
1700
1730
  activeTabMessageCount > 0 ||
1701
- activeTab.status !== "idle");
1731
+ activeTab.status !== "idle"),
1732
+ );
1733
+ const pageHeaderActions = resolveAgentPanelPageHeaderActions({
1734
+ showPageTitleMenu,
1735
+ canShareActiveTab,
1736
+ });
1702
1737
  const showNewChatAction =
1703
1738
  showPageNewChatButton &&
1704
1739
  shouldShowAgentPanelPageNewChatButton(
@@ -1707,6 +1742,12 @@ function AgentPanelInner({
1707
1742
  activeTabMessageCount,
1708
1743
  activeTabIsPersisted,
1709
1744
  );
1745
+ const toolbarSlot = resolveAgentPanelPageToolbarSlot(pageToolbarSlot, {
1746
+ activeTabMessageCount,
1747
+ clearActiveTab,
1748
+ showHistory,
1749
+ toggleHistory,
1750
+ });
1710
1751
 
1711
1752
  return (
1712
1753
  <>
@@ -1730,62 +1771,64 @@ function AgentPanelInner({
1730
1771
  <h1 className="truncate text-xs font-medium text-foreground">
1731
1772
  {activeTab?.label || t("agentPanel.newChat")}
1732
1773
  </h1>
1733
- <DropdownMenu
1734
- open={headerMenuOpen}
1735
- onOpenChange={setHeaderMenuOpen}
1736
- >
1737
- <DropdownMenuTrigger asChild>
1738
- <button
1739
- type="button"
1740
- data-agent-page-title-menu=""
1741
- aria-label={t("agentPanel.panelOptions")}
1742
- className="flex size-7 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent/60 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring data-[state=open]:bg-accent data-[state=open]:text-foreground"
1743
- >
1744
- <IconDotsVertical size={14} />
1745
- </button>
1746
- </DropdownMenuTrigger>
1747
- <DropdownMenuContent
1748
- align="start"
1749
- sideOffset={5}
1750
- className="w-44"
1751
- onCloseAutoFocus={(event) => {
1752
- consumeAgentPanelOverlayFocusRestore(
1753
- pendingHeaderOverlayRef,
1754
- event,
1755
- );
1756
- }}
1774
+ {pageHeaderActions.showPageTitleMenu ? (
1775
+ <DropdownMenu
1776
+ open={headerMenuOpen}
1777
+ onOpenChange={setHeaderMenuOpen}
1757
1778
  >
1758
- {toggleHistory ? (
1759
- <DropdownMenuItem
1760
- onSelect={(event) =>
1761
- deferAgentPanelOverlayOpen(
1762
- event,
1763
- closeHeaderMenuForOverlay,
1764
- toggleHistory,
1765
- pendingHeaderOverlayRef,
1766
- )
1767
- }
1779
+ <DropdownMenuTrigger asChild>
1780
+ <button
1781
+ type="button"
1782
+ data-agent-page-title-menu=""
1783
+ aria-label={t("agentPanel.panelOptions")}
1784
+ className="flex size-7 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent/60 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring data-[state=open]:bg-accent data-[state=open]:text-foreground"
1768
1785
  >
1769
- <IconHistory size={14} className="shrink-0" />
1770
- {showHistory
1771
- ? t("agentPanel.hideChats")
1772
- : t("agentPanel.allChats")}
1773
- </DropdownMenuItem>
1774
- ) : null}
1775
- {activeTabMessageCount > 0 ? (
1776
- <DropdownMenuItem onSelect={clearActiveTab}>
1777
- <IconX size={14} className="shrink-0" />
1778
- {t("agentPanel.clearChat")}
1779
- </DropdownMenuItem>
1780
- ) : null}
1781
- </DropdownMenuContent>
1782
- </DropdownMenu>
1786
+ <IconDotsVertical size={14} />
1787
+ </button>
1788
+ </DropdownMenuTrigger>
1789
+ <DropdownMenuContent
1790
+ align="start"
1791
+ sideOffset={5}
1792
+ className="w-44"
1793
+ onCloseAutoFocus={(event) => {
1794
+ consumeAgentPanelOverlayFocusRestore(
1795
+ pendingHeaderOverlayRef,
1796
+ event,
1797
+ );
1798
+ }}
1799
+ >
1800
+ {toggleHistory ? (
1801
+ <DropdownMenuItem
1802
+ onSelect={(event) =>
1803
+ deferAgentPanelOverlayOpen(
1804
+ event,
1805
+ closeHeaderMenuForOverlay,
1806
+ toggleHistory,
1807
+ pendingHeaderOverlayRef,
1808
+ )
1809
+ }
1810
+ >
1811
+ <IconHistory size={14} className="shrink-0" />
1812
+ {showHistory
1813
+ ? t("agentPanel.hideChats")
1814
+ : t("agentPanel.allChats")}
1815
+ </DropdownMenuItem>
1816
+ ) : null}
1817
+ {activeTabMessageCount > 0 ? (
1818
+ <DropdownMenuItem onSelect={clearActiveTab}>
1819
+ <IconX size={14} className="shrink-0" />
1820
+ {t("agentPanel.clearChat")}
1821
+ </DropdownMenuItem>
1822
+ ) : null}
1823
+ </DropdownMenuContent>
1824
+ </DropdownMenu>
1825
+ ) : null}
1783
1826
  {activeTab?.status === "running" ? (
1784
1827
  <span className="size-1.5 shrink-0 rounded-full bg-muted-foreground/55 animate-pulse motion-reduce:animate-none" />
1785
1828
  ) : null}
1786
1829
  </div>
1787
1830
  <div className="flex shrink-0 items-center gap-1">
1788
- {canShareActiveTab ? (
1831
+ {pageHeaderActions.showShareAction && activeTab ? (
1789
1832
  <ShareButton
1790
1833
  resourceType="chat_thread"
1791
1834
  resourceId={activeTab.id}
@@ -1798,7 +1841,7 @@ function AgentPanelInner({
1798
1841
  triggerClassName="size-8 p-0 border-0 bg-transparent shadow-none hover:bg-accent/60"
1799
1842
  />
1800
1843
  ) : null}
1801
- {pageToolbarSlot}
1844
+ {toolbarSlot}
1802
1845
  {showNewChatAction ? (
1803
1846
  <button
1804
1847
  type="button"
@@ -1829,6 +1872,7 @@ function AgentPanelInner({
1829
1872
  pageToolbarSlot,
1830
1873
  pendingHeaderOverlayRef,
1831
1874
  setHeaderMenuOpen,
1875
+ showPageTitleMenu,
1832
1876
  showPageNewChatButton,
1833
1877
  t,
1834
1878
  ],
@@ -26,6 +26,8 @@ import type {
26
26
  import type { ExportedMessageRepository } from "@assistant-ui/react";
27
27
  import type * as React from "react";
28
28
 
29
+ import type { AgentKitWorkedForSummaryRenderProps } from "../../agentkit/react/context.js";
30
+ import type { AgentMessageContentOrderResolver } from "../../agentkit/react/message-content-order.js";
29
31
  import type { AssistantChatHistoryConfig } from "./history-types.js";
30
32
  import type { BuilderSetupCardLayout } from "./run-recovery.js";
31
33
 
@@ -267,6 +269,12 @@ export interface AssistantChatProps {
267
269
  ) => void;
268
270
  /** Optional content rendered just above the composer input */
269
271
  composerSlot?: React.ReactNode;
272
+ /** Optional shared context banner rendered above the composer input. */
273
+ composerContextBannerSlot?: React.ReactNode;
274
+ /** Optional renderer for the shared work-summary disclosure row. */
275
+ workedForSummarySlot?: React.ComponentType<AgentKitWorkedForSummaryRenderProps>;
276
+ /** Optional ordering policy for assistant message text and attached widgets. */
277
+ resolveMessageContentOrder?: AgentMessageContentOrderResolver;
270
278
  /** App-owned context controller, mounted separately for each chat thread. */
271
279
  composerContextProvider?: React.ComponentType<AssistantChatComposerContextProviderProps>;
272
280
  /** Optional home content rendered above the composer on an empty chat. */
@@ -0,0 +1,217 @@
1
+ import React from "react";
2
+ import { renderToStaticMarkup } from "react-dom/server";
3
+ import { describe, expect, it, vi } from "vitest";
4
+
5
+ import type { DataChartWidget as DataChartWidgetData } from "./data-widget-types.js";
6
+
7
+ vi.mock("@agent-native/core/client/i18n", () => ({
8
+ useT: () => (key: string) => key,
9
+ }));
10
+
11
+ import { DataChartRenderer } from "./DataChartRenderer.js";
12
+
13
+ const chart: DataChartWidgetData = {
14
+ type: "bar",
15
+ xKey: "day",
16
+ series: [
17
+ { key: "first", label: "First" },
18
+ { key: "second", label: "Second" },
19
+ { key: "third", label: "Third" },
20
+ { key: "fourth", label: "Fourth" },
21
+ ],
22
+ data: [{ day: "Monday", first: 1, second: 2, third: 3, fourth: 4 }],
23
+ };
24
+
25
+ describe("DataChartRenderer theme colors", () => {
26
+ it("resolves its series colors through app chart tokens with legacy fallbacks", () => {
27
+ const markup = renderToStaticMarkup(<DataChartRenderer chart={chart} />);
28
+
29
+ expect(markup).toContain('viewBox="0 0 640 360"');
30
+ expect(markup).toContain("block w-full h-auto");
31
+ expect(markup).not.toContain("style=");
32
+ expect(markup).not.toContain("preserveAspectRatio");
33
+ expect(markup).not.toContain("h-60");
34
+ expect(markup).toContain('fill="hsl(var(--chart-1, var(--primary)))"');
35
+ expect(markup).toContain('fill="hsl(var(--chart-2, 199 89% 48%))"');
36
+ expect(markup).toContain('fill="hsl(var(--chart-3, 151 55% 42%))"');
37
+ expect(markup).toContain('fill="hsl(var(--chart-4, 35 92% 50%))"');
38
+ });
39
+
40
+ it("uses the requested chart content height", () => {
41
+ const markup = renderToStaticMarkup(
42
+ <DataChartRenderer chart={{ ...chart, contentHeight: 400 }} />,
43
+ );
44
+
45
+ expect(markup).toContain('style="height:400px;padding:0px"');
46
+ expect(markup).toContain(
47
+ 'class="agent-data-chart-renderer block w-full h-full"',
48
+ );
49
+ expect(markup).toContain('viewBox="0 0 640 360"');
50
+ expect(markup).toContain('preserveAspectRatio="none"');
51
+ });
52
+
53
+ it("fits labels and the chart canvas inside a padded body box", () => {
54
+ const markup = renderToStaticMarkup(
55
+ <DataChartRenderer
56
+ chart={{
57
+ ...chart,
58
+ contentHeight: 400,
59
+ contentPadding: 16,
60
+ labelFontFamily: "sans",
61
+ labelFontSize: 14,
62
+ }}
63
+ />,
64
+ );
65
+
66
+ expect(markup).toContain('style="height:400px;padding:16px"');
67
+ expect(markup).toContain(
68
+ 'font-family="var(--font-sans, ui-sans-serif, system-ui, sans-serif)"',
69
+ );
70
+ expect(markup).toContain('font-size="14"');
71
+ });
72
+
73
+ it("renders optional horizontal titles and value labels with their font roles", () => {
74
+ const markup = renderToStaticMarkup(
75
+ <DataChartRenderer
76
+ chart={{
77
+ ...chart,
78
+ layout: "horizontal",
79
+ xAxisTitle: "Value",
80
+ yAxisTitle: "Category",
81
+ showValueLabels: true,
82
+ labelFontSize: 10,
83
+ axisTitleFontSize: 11,
84
+ axisTitleFontWeight: 500,
85
+ valueLabelFontSize: 11,
86
+ valueLabelFontWeight: 400,
87
+ }}
88
+ />,
89
+ );
90
+
91
+ expect(markup).toContain(">Value</text>");
92
+ expect(markup).toContain(">Category</text>");
93
+ expect(markup).toContain('font-size="10"');
94
+ expect(markup).toContain('font-size="11"');
95
+ expect(markup).toContain('font-weight="500"');
96
+ expect(markup).toContain('font-weight="400"');
97
+ expect(markup).toContain('text-anchor="start"');
98
+ expect(markup).toContain('viewBox="0 0 640 360"');
99
+ });
100
+
101
+ it("reserves space for long horizontal category and value labels", () => {
102
+ const markup = renderToStaticMarkup(
103
+ <DataChartRenderer
104
+ chart={{
105
+ ...chart,
106
+ layout: "horizontal",
107
+ showValueLabels: true,
108
+ labelFontSize: 10,
109
+ valueLabelFontSize: 11,
110
+ data: [
111
+ {
112
+ day: "A very long category label",
113
+ first: 123456,
114
+ second: 2,
115
+ third: 3,
116
+ fourth: 4,
117
+ },
118
+ ],
119
+ }}
120
+ />,
121
+ );
122
+ const categoryLabel = markup.match(
123
+ /<text x="([\d.]+)" y="[^"]+" fill="hsl\(var\(--muted-foreground\)\)" font-size="10" text-anchor="end">A very long c\.\.\.<\/text>/,
124
+ );
125
+ const largestValueLabel = markup.match(
126
+ /<text x="([\d.]+)" y="[^"]+" fill="hsl\(var\(--muted-foreground\)\)" font-size="11" font-weight="400" text-anchor="start">123,456<\/text>/,
127
+ );
128
+
129
+ expect(categoryLabel).not.toBeNull();
130
+ expect(Number(categoryLabel?.[1])).toBeGreaterThan(100);
131
+ expect(largestValueLabel).not.toBeNull();
132
+ expect(Number(largestValueLabel?.[1])).toBeLessThan(590);
133
+ });
134
+
135
+ it("places negative horizontal value labels outside the bar's left edge", () => {
136
+ const markup = renderToStaticMarkup(
137
+ <DataChartRenderer
138
+ chart={{
139
+ type: "bar",
140
+ layout: "horizontal",
141
+ xKey: "day",
142
+ series: [{ key: "value", label: "Value" }],
143
+ data: [{ day: "Monday", value: -123456 }],
144
+ showValueLabels: true,
145
+ }}
146
+ />,
147
+ );
148
+ const negativeBarX = markup.match(/<rect x="([\d.]+)"/);
149
+ const negativeBarLabel = markup.match(
150
+ /<text x="([\d.]+)"[^>]*text-anchor="end">-123,456<\/text>/,
151
+ );
152
+ const categoryLabel = markup.match(
153
+ /<text x="([\d.]+)" y="[^"]+" fill="hsl\(var\(--muted-foreground\)\)" font-size="11" text-anchor="end">Monday<\/text>/,
154
+ );
155
+
156
+ expect(negativeBarX).not.toBeNull();
157
+ expect(negativeBarLabel).not.toBeNull();
158
+ expect(Number(negativeBarLabel?.[1])).toBeLessThan(
159
+ Number(negativeBarX?.[1]),
160
+ );
161
+ expect(categoryLabel).not.toBeNull();
162
+ expect(
163
+ Number(negativeBarLabel?.[1]) - Number(categoryLabel?.[1]),
164
+ ).toBeGreaterThan(60);
165
+ });
166
+
167
+ it.each(["line", "area"] as const)(
168
+ "renders requested value labels for %s charts",
169
+ (type) => {
170
+ const markup = renderToStaticMarkup(
171
+ <DataChartRenderer
172
+ chart={{
173
+ type,
174
+ xKey: "day",
175
+ series: [{ key: "value", label: "Value" }],
176
+ data: [
177
+ { day: "Monday", value: 4 },
178
+ { day: "Tuesday", value: 11 },
179
+ { day: "Wednesday", value: 7 },
180
+ ],
181
+ showValueLabels: true,
182
+ }}
183
+ />,
184
+ );
185
+
186
+ expect(markup).toContain(">7</text>");
187
+ expect(markup).toContain('font-weight="400"');
188
+ },
189
+ );
190
+
191
+ it.each(["line", "area"] as const)(
192
+ "keeps the final %s value label inside the chart bounds",
193
+ (type) => {
194
+ const markup = renderToStaticMarkup(
195
+ <DataChartRenderer
196
+ chart={{
197
+ type,
198
+ xKey: "day",
199
+ series: [{ key: "value", label: "Value" }],
200
+ data: [
201
+ { day: "Monday", value: 4 },
202
+ { day: "Tuesday", value: 11 },
203
+ { day: "Wednesday", value: 123456789 },
204
+ ],
205
+ showValueLabels: true,
206
+ }}
207
+ />,
208
+ );
209
+ const finalValueLabel = markup.match(
210
+ /<text x="([\d.]+)" y="[\d.]+" fill="hsl\(var\(--muted-foreground\)\)" font-size="11" font-weight="400" text-anchor="end">123,456,789<\/text>/,
211
+ );
212
+
213
+ expect(finalValueLabel).not.toBeNull();
214
+ expect(Number(finalValueLabel?.[1])).toBeLessThan(640);
215
+ },
216
+ );
217
+ });