@agent-native/toolkit 0.214.0 → 0.217.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 (203) hide show
  1. package/agent-native.eject.json +5 -0
  2. package/dist/app/agentkit/react/chat.d.ts.map +1 -1
  3. package/dist/app/agentkit/react/chat.js +2 -2
  4. package/dist/app/agentkit/react/chat.js.map +1 -1
  5. package/dist/app/agentkit/react/components.d.ts +4 -1
  6. package/dist/app/agentkit/react/components.d.ts.map +1 -1
  7. package/dist/app/agentkit/react/components.js +69 -15
  8. package/dist/app/agentkit/react/components.js.map +1 -1
  9. package/dist/app/agentkit/react/context.d.ts +7 -1
  10. package/dist/app/agentkit/react/context.d.ts.map +1 -1
  11. package/dist/app/agentkit/react/context.js +5 -1
  12. package/dist/app/agentkit/react/context.js.map +1 -1
  13. package/dist/app/agentkit/react/index.d.ts +1 -0
  14. package/dist/app/agentkit/react/index.d.ts.map +1 -1
  15. package/dist/app/agentkit/react/index.js +1 -0
  16. package/dist/app/agentkit/react/index.js.map +1 -1
  17. package/dist/app/agentkit/react/root.d.ts +4 -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 +43 -6
  22. package/dist/app/agentkit/react/transcript-layout.d.ts +51 -0
  23. package/dist/app/agentkit/react/transcript-layout.d.ts.map +1 -0
  24. package/dist/app/agentkit/react/transcript-layout.js +34 -0
  25. package/dist/app/agentkit/react/transcript-layout.js.map +1 -0
  26. package/dist/app/auth/AuthPage.d.ts.map +1 -1
  27. package/dist/app/auth/AuthPage.js +33 -44
  28. package/dist/app/auth/AuthPage.js.map +1 -1
  29. package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
  30. package/dist/app/chat/AgentKitAssistantChat.js +3 -3
  31. package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
  32. package/dist/app/chat/AgentPanel.d.ts +2 -0
  33. package/dist/app/chat/AgentPanel.d.ts.map +1 -1
  34. package/dist/app/chat/AgentPanel.js +6 -2
  35. package/dist/app/chat/AgentPanel.js.map +1 -1
  36. package/dist/app/chat/chat/index.d.ts +2 -0
  37. package/dist/app/chat/chat/index.d.ts.map +1 -1
  38. package/dist/app/chat/chat/index.js.map +1 -1
  39. package/dist/app/chat/chat/surface-types.d.ts +7 -0
  40. package/dist/app/chat/chat/surface-types.d.ts.map +1 -1
  41. package/dist/app/chat/chat/surface-types.js.map +1 -1
  42. package/dist/app/chat/chat/tool-call-display.d.ts +7 -2
  43. package/dist/app/chat/chat/tool-call-display.d.ts.map +1 -1
  44. package/dist/app/chat/chat/tool-call-display.js +10 -9
  45. package/dist/app/chat/chat/tool-call-display.js.map +1 -1
  46. package/dist/app/chat/chat/widgets/DataChartRenderer.d.ts.map +1 -1
  47. package/dist/app/chat/chat/widgets/DataChartRenderer.js +196 -26
  48. package/dist/app/chat/chat/widgets/DataChartRenderer.js.map +1 -1
  49. package/dist/app/chat/chat/widgets/DataChartWidget.d.ts.map +1 -1
  50. package/dist/app/chat/chat/widgets/DataChartWidget.js +5 -1
  51. package/dist/app/chat/chat/widgets/DataChartWidget.js.map +1 -1
  52. package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.d.ts +2 -2
  53. package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.d.ts.map +1 -1
  54. package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.js +6 -4
  55. package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.js.map +1 -1
  56. package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
  57. package/dist/app/i18n/catalogs/ar-SA.js +1 -0
  58. package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
  59. package/dist/app/i18n/catalogs/de-DE.d.ts.map +1 -1
  60. package/dist/app/i18n/catalogs/de-DE.js +1 -0
  61. package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
  62. package/dist/app/i18n/catalogs/en-US.d.ts +1 -0
  63. package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
  64. package/dist/app/i18n/catalogs/en-US.js +1 -0
  65. package/dist/app/i18n/catalogs/en-US.js.map +1 -1
  66. package/dist/app/i18n/catalogs/es-ES.d.ts.map +1 -1
  67. package/dist/app/i18n/catalogs/es-ES.js +1 -0
  68. package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
  69. package/dist/app/i18n/catalogs/fr-FR.d.ts.map +1 -1
  70. package/dist/app/i18n/catalogs/fr-FR.js +1 -0
  71. package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
  72. package/dist/app/i18n/catalogs/hi-IN.d.ts.map +1 -1
  73. package/dist/app/i18n/catalogs/hi-IN.js +1 -0
  74. package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
  75. package/dist/app/i18n/catalogs/ja-JP.d.ts.map +1 -1
  76. package/dist/app/i18n/catalogs/ja-JP.js +1 -0
  77. package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
  78. package/dist/app/i18n/catalogs/ko-KR.d.ts.map +1 -1
  79. package/dist/app/i18n/catalogs/ko-KR.js +1 -0
  80. package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
  81. package/dist/app/i18n/catalogs/pt-BR.d.ts.map +1 -1
  82. package/dist/app/i18n/catalogs/pt-BR.js +1 -0
  83. package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
  84. package/dist/app/i18n/catalogs/zh-CN.d.ts.map +1 -1
  85. package/dist/app/i18n/catalogs/zh-CN.js +1 -0
  86. package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
  87. package/dist/app/i18n/catalogs/zh-TW.d.ts.map +1 -1
  88. package/dist/app/i18n/catalogs/zh-TW.js +1 -0
  89. package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
  90. package/dist/app/onboarding/GettingStartedCard.d.ts +35 -0
  91. package/dist/app/onboarding/GettingStartedCard.d.ts.map +1 -0
  92. package/dist/app/onboarding/GettingStartedCard.js +38 -0
  93. package/dist/app/onboarding/GettingStartedCard.js.map +1 -0
  94. package/dist/app/onboarding/index.d.ts +1 -0
  95. package/dist/app/onboarding/index.d.ts.map +1 -1
  96. package/dist/app/onboarding/index.js +1 -0
  97. package/dist/app/onboarding/index.js.map +1 -1
  98. package/dist/app/providers/AppProviders.d.ts.map +1 -1
  99. package/dist/app/providers/AppProviders.js +3 -1
  100. package/dist/app/providers/AppProviders.js.map +1 -1
  101. package/dist/app/settings/AccountSettingsCard.d.ts.map +1 -1
  102. package/dist/app/settings/AccountSettingsCard.js +2 -1
  103. package/dist/app/settings/AccountSettingsCard.js.map +1 -1
  104. package/dist/app/settings/index.d.ts +1 -0
  105. package/dist/app/settings/index.d.ts.map +1 -1
  106. package/dist/app/settings/index.js +1 -0
  107. package/dist/app/settings/index.js.map +1 -1
  108. package/dist/app/settings/shell/SettingsShell.d.ts +40 -1
  109. package/dist/app/settings/shell/SettingsShell.d.ts.map +1 -1
  110. package/dist/app/settings/shell/SettingsShell.js +87 -20
  111. package/dist/app/settings/shell/SettingsShell.js.map +1 -1
  112. package/dist/app/settings/shell/bridge.d.ts +5 -3
  113. package/dist/app/settings/shell/bridge.d.ts.map +1 -1
  114. package/dist/app/settings/shell/bridge.js +8 -5
  115. package/dist/app/settings/shell/bridge.js.map +1 -1
  116. package/dist/app/settings/shell/index.d.ts +2 -2
  117. package/dist/app/settings/shell/index.d.ts.map +1 -1
  118. package/dist/app/settings/shell/index.js.map +1 -1
  119. package/dist/app/settings/shell/registry.d.ts +9 -1
  120. package/dist/app/settings/shell/registry.d.ts.map +1 -1
  121. package/dist/app/settings/shell/registry.js +16 -0
  122. package/dist/app/settings/shell/registry.js.map +1 -1
  123. package/dist/app/settings/shell/routing.d.ts +5 -4
  124. package/dist/app/settings/shell/routing.d.ts.map +1 -1
  125. package/dist/app/settings/shell/routing.js +38 -10
  126. package/dist/app/settings/shell/routing.js.map +1 -1
  127. package/dist/app/shared/CommandMenu.d.ts +86 -6
  128. package/dist/app/shared/CommandMenu.d.ts.map +1 -1
  129. package/dist/app/shared/CommandMenu.js +303 -41
  130. package/dist/app/shared/CommandMenu.js.map +1 -1
  131. package/dist/app/shared/ConsentBanner.d.ts +9 -0
  132. package/dist/app/shared/ConsentBanner.d.ts.map +1 -0
  133. package/dist/app/shared/ConsentBanner.js +35 -0
  134. package/dist/app/shared/ConsentBanner.js.map +1 -0
  135. package/dist/composer/ComposerContextBanner.d.ts +3 -1
  136. package/dist/composer/ComposerContextBanner.d.ts.map +1 -1
  137. package/dist/composer/ComposerContextBanner.js +2 -2
  138. package/dist/composer/ComposerContextBanner.js.map +1 -1
  139. package/dist/ui/sonner.d.ts +2 -2
  140. package/dist/ui/sonner.d.ts.map +1 -1
  141. package/dist/ui/sonner.js +2 -2
  142. package/dist/ui/sonner.js.map +1 -1
  143. package/package.json +3 -3
  144. package/src/app/agentkit/react/chat.tsx +2 -0
  145. package/src/app/agentkit/react/components.interaction.spec.tsx +107 -0
  146. package/src/app/agentkit/react/components.spec.tsx +28 -1
  147. package/src/app/agentkit/react/components.tsx +153 -17
  148. package/src/app/agentkit/react/context.tsx +12 -0
  149. package/src/app/agentkit/react/index.ts +1 -0
  150. package/src/app/agentkit/react/lifecycle.spec.tsx +186 -16
  151. package/src/app/agentkit/react/root.tsx +7 -0
  152. package/src/app/agentkit/react/styles.css +43 -6
  153. package/src/app/agentkit/react/transcript-layout.spec.ts +72 -0
  154. package/src/app/agentkit/react/transcript-layout.ts +97 -0
  155. package/src/app/auth/AuthPage.attribution.spec.tsx +6 -0
  156. package/src/app/auth/AuthPage.interaction.spec.tsx +74 -0
  157. package/src/app/auth/AuthPage.tsx +32 -39
  158. package/src/app/chat/AgentKitAssistantChat.spec.tsx +39 -0
  159. package/src/app/chat/AgentKitAssistantChat.tsx +5 -0
  160. package/src/app/chat/AgentPanel.page-header-share.spec.tsx +101 -0
  161. package/src/app/chat/AgentPanel.tsx +14 -2
  162. package/src/app/chat/chat/index.ts +2 -0
  163. package/src/app/chat/chat/surface-types.ts +10 -0
  164. package/src/app/chat/chat/tool-call-display.spec.tsx +83 -0
  165. package/src/app/chat/chat/tool-call-display.tsx +40 -8
  166. package/src/app/chat/chat/widgets/DataChartRenderer.spec.tsx +632 -0
  167. package/src/app/chat/chat/widgets/DataChartRenderer.tsx +308 -51
  168. package/src/app/chat/chat/widgets/DataChartWidget.spec.tsx +126 -23
  169. package/src/app/chat/chat/widgets/DataChartWidget.tsx +10 -0
  170. package/src/app/chat/chat/widgets/DataWidgetDisplayControls.tsx +26 -6
  171. package/src/app/i18n/catalogs/ar-SA.ts +1 -0
  172. package/src/app/i18n/catalogs/de-DE.ts +2 -0
  173. package/src/app/i18n/catalogs/en-US.ts +2 -0
  174. package/src/app/i18n/catalogs/es-ES.ts +2 -0
  175. package/src/app/i18n/catalogs/fr-FR.ts +2 -0
  176. package/src/app/i18n/catalogs/hi-IN.ts +1 -0
  177. package/src/app/i18n/catalogs/ja-JP.ts +2 -0
  178. package/src/app/i18n/catalogs/ko-KR.ts +1 -0
  179. package/src/app/i18n/catalogs/pt-BR.ts +2 -0
  180. package/src/app/i18n/catalogs/zh-CN.ts +1 -0
  181. package/src/app/i18n/catalogs/zh-TW.ts +1 -0
  182. package/src/app/onboarding/GettingStartedCard.tsx +203 -0
  183. package/src/app/onboarding/index.ts +1 -0
  184. package/src/app/providers/AppProviders.tsx +7 -1
  185. package/src/app/settings/AccountSettingsCard.spec.tsx +31 -0
  186. package/src/app/settings/AccountSettingsCard.tsx +8 -0
  187. package/src/app/settings/index.ts +1 -0
  188. package/src/app/settings/shell/SettingsShell.spec.tsx +472 -1
  189. package/src/app/settings/shell/SettingsShell.tsx +245 -31
  190. package/src/app/settings/shell/bridge.spec.ts +12 -0
  191. package/src/app/settings/shell/bridge.ts +17 -4
  192. package/src/app/settings/shell/index.ts +6 -1
  193. package/src/app/settings/shell/registry.ts +33 -1
  194. package/src/app/settings/shell/routing.spec.ts +92 -1
  195. package/src/app/settings/shell/routing.ts +52 -9
  196. package/src/app/shared/CommandMenu.spec.tsx +1662 -1
  197. package/src/app/shared/CommandMenu.tsx +763 -164
  198. package/src/app/shared/ConsentBanner.spec.tsx +141 -0
  199. package/src/app/shared/ConsentBanner.tsx +141 -0
  200. package/src/composer/ComposerContextBanner.spec.tsx +31 -5
  201. package/src/composer/ComposerContextBanner.tsx +7 -2
  202. package/src/ui/sonner.spec.ts +10 -0
  203. package/src/ui/sonner.tsx +2 -2
@@ -1,4 +1,5 @@
1
1
  import { useT } from "@agent-native/core/client/i18n";
2
+ import { DATA_WIDGET_MAX_CHART_POINTS } from "@agent-native/core/data-widgets";
2
3
  import { lazy, Suspense, useEffect, useState } from "react";
3
4
 
4
5
  import type {
@@ -27,6 +28,10 @@ export function DataChartWidget({
27
28
  const [mounted, setMounted] = useState(false);
28
29
  const contentHeight = chart.contentHeight;
29
30
  const contentPadding = chart.contentPadding ?? 0;
31
+ const hasOmittedRows =
32
+ chart.sampled === true ||
33
+ chart.truncated === true ||
34
+ chart.data.length > DATA_WIDGET_MAX_CHART_POINTS;
30
35
 
31
36
  useEffect(() => {
32
37
  setMounted(true);
@@ -69,6 +74,11 @@ export function DataChartWidget({
69
74
  <LazyDataChartRenderer chart={chart} />
70
75
  </Suspense>
71
76
  )}
77
+ {hasOmittedRows ? (
78
+ <p className="px-3 pb-3 text-xs text-muted-foreground" role="status">
79
+ {t("agentChat.widget.chartRowsOmitted")}
80
+ </p>
81
+ ) : null}
72
82
  <DataWidgetSourceChips sources={display?.sources ?? []} />
73
83
  </div>
74
84
  );
@@ -23,7 +23,7 @@ import { forwardRef } from "react";
23
23
 
24
24
  import { toast } from "../../../../hooks/use-toast.js";
25
25
  import type {
26
- DataWidgetAction,
26
+ DataWidgetChartAction,
27
27
  DataWidgetActionIcon,
28
28
  DataWidgetDataSource,
29
29
  DataWidgetDisplay,
@@ -82,12 +82,15 @@ const WidgetActionLink = forwardRef<
82
82
  label: string;
83
83
  className: string;
84
84
  icon?: DataWidgetActionIcon;
85
+ iconOnly?: boolean;
85
86
  }
86
- >(function WidgetActionLink({ href, label, className, icon }, ref) {
87
+ >(function WidgetActionLink({ href, label, className, icon, iconOnly }, ref) {
87
88
  return (
88
89
  <a
89
90
  ref={ref}
90
91
  href={href}
92
+ aria-label={iconOnly ? label : undefined}
93
+ title={iconOnly ? label : undefined}
91
94
  onClick={(event) => {
92
95
  if (
93
96
  event.defaultPrevented ||
@@ -109,7 +112,7 @@ const WidgetActionLink = forwardRef<
109
112
  }}
110
113
  className={className}
111
114
  >
112
- <span className="truncate">{label}</span>
115
+ <span className={iconOnly ? "sr-only" : "truncate"}>{label}</span>
113
116
  {icon === "explore" ? (
114
117
  <IconCompass aria-hidden="true" className="size-3.5 shrink-0" />
115
118
  ) : icon === "camera" ? (
@@ -144,7 +147,7 @@ export function DataWidgetDisplayControls({
144
147
  kind = "chart",
145
148
  }: {
146
149
  display?: DataWidgetDisplay;
147
- chartActions?: DataWidgetAction[];
150
+ chartActions?: DataWidgetChartAction[];
148
151
  variant?: "primary" | "secondary";
149
152
  kind?: "chart" | "table";
150
153
  }) {
@@ -194,6 +197,13 @@ export function DataWidgetDisplayControls({
194
197
  key: action.id ?? `copy-${index}`,
195
198
  });
196
199
  }
200
+ const directActions = actions.filter(
201
+ (item): item is Extract<PreparedDisplayAction, { type: "link" }> =>
202
+ item.type === "link" && item.action.presentation === "icon",
203
+ );
204
+ const overflowActions = actions.filter(
205
+ (item) => item.type !== "link" || item.action.presentation !== "icon",
206
+ );
197
207
  const actionsLabel =
198
208
  kind === "table"
199
209
  ? t("agentChat.widget.tableActions", { defaultValue: "Table actions" })
@@ -213,7 +223,17 @@ export function DataWidgetDisplayControls({
213
223
  }
214
224
  />
215
225
  ) : null}
216
- {actions.length > 0 ? (
226
+ {directActions.map((item) => (
227
+ <WidgetActionLink
228
+ key={item.key}
229
+ href={item.href}
230
+ label={item.action.label}
231
+ icon={item.action.icon}
232
+ iconOnly
233
+ className="inline-flex size-8 shrink-0 items-center justify-center rounded-md border border-border text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
234
+ />
235
+ ))}
236
+ {overflowActions.length > 0 ? (
217
237
  <DropdownMenu>
218
238
  <DropdownMenuTrigger asChild>
219
239
  <button
@@ -226,7 +246,7 @@ export function DataWidgetDisplayControls({
226
246
  </button>
227
247
  </DropdownMenuTrigger>
228
248
  <DropdownMenuContent align="end">
229
- {actions.map((item) =>
249
+ {overflowActions.map((item) =>
230
250
  item.type === "copy" ? (
231
251
  <DropdownMenuItem
232
252
  key={item.key}
@@ -1523,6 +1523,7 @@ const messages: ToolkitAgentChatTranslation = {
1523
1523
  "tool.workedFor": "عمل لمدة {{duration}}",
1524
1524
  "widget.chart": "مخطط",
1525
1525
  "widget.chartActions": "إجراءات المخطط",
1526
+ "widget.chartRowsOmitted": "يعرض هذا المخطط بعض الصفوف المتاحة فقط.",
1526
1527
  "widget.dataSources": "مصادر البيانات",
1527
1528
  "widget.tableActions": "إجراءات الجدول",
1528
1529
  "widget.dataChart": "مخطط بيانات",
@@ -1069,6 +1069,8 @@ const messages: ToolkitAgentChatTranslation = {
1069
1069
  "tool.workedFor": "{{duration}} verarbeitet",
1070
1070
  "widget.chart": "Diagramm",
1071
1071
  "widget.chartActions": "Diagrammaktionen",
1072
+ "widget.chartRowsOmitted":
1073
+ "Dieses Diagramm zeigt nur einen Teil der verfügbaren Zeilen.",
1072
1074
  "widget.dataSources": "Datenquellen",
1073
1075
  "widget.tableActions": "Tabellenaktionen",
1074
1076
  "widget.dataChart": "Datendiagramm",
@@ -1514,6 +1514,8 @@ const messages = {
1514
1514
  "tool.workedFor": "Worked for {{duration}}",
1515
1515
  "widget.chart": "Chart",
1516
1516
  "widget.chartActions": "Chart actions",
1517
+ "widget.chartRowsOmitted":
1518
+ "This chart shows only some of the available rows.",
1517
1519
  "widget.dataSources": "Data sources",
1518
1520
  "widget.tableActions": "Table actions",
1519
1521
  "widget.dataChart": "Data chart",
@@ -1064,6 +1064,8 @@ const messages: ToolkitAgentChatTranslation = {
1064
1064
  "tool.workedFor": "Trabajó durante {{duration}}",
1065
1065
  "widget.chart": "Gráfico",
1066
1066
  "widget.chartActions": "Acciones del gráfico",
1067
+ "widget.chartRowsOmitted":
1068
+ "Este gráfico muestra solo algunas de las filas disponibles.",
1067
1069
  "widget.dataSources": "Fuentes de datos",
1068
1070
  "widget.tableActions": "Acciones de la tabla",
1069
1071
  "widget.dataChart": "Gráfico de datos",
@@ -1069,6 +1069,8 @@ const messages: ToolkitAgentChatTranslation = {
1069
1069
  "tool.workedFor": "A travaillé pendant {{duration}}",
1070
1070
  "widget.chart": "Graphique",
1071
1071
  "widget.chartActions": "Actions du graphique",
1072
+ "widget.chartRowsOmitted":
1073
+ "Ce graphique n’affiche qu’une partie des lignes disponibles.",
1072
1074
  "widget.dataSources": "Sources de données",
1073
1075
  "widget.tableActions": "Actions du tableau",
1074
1076
  "widget.dataChart": "Graphique de données",
@@ -1492,6 +1492,7 @@ const messages: ToolkitAgentChatTranslation = {
1492
1492
  "tool.workedFor": "{{duration}} तक काम किया",
1493
1493
  "widget.chart": "चार्ट",
1494
1494
  "widget.chartActions": "चार्ट कार्रवाइयाँ",
1495
+ "widget.chartRowsOmitted": "यह चार्ट उपलब्ध पंक्तियों में से केवल कुछ दिखाता है।",
1495
1496
  "widget.dataSources": "डेटा स्रोत",
1496
1497
  "widget.tableActions": "टेबल कार्रवाइयाँ",
1497
1498
  "widget.dataChart": "डेटा चार्ट",
@@ -1537,6 +1537,8 @@ const messages: ToolkitAgentChatTranslation = {
1537
1537
  "tool.workedFor": "{{duration}} 作業しました",
1538
1538
  "widget.chart": "チャート",
1539
1539
  "widget.chartActions": "チャート操作",
1540
+ "widget.chartRowsOmitted":
1541
+ "このグラフには、利用可能な行の一部のみが表示されます。",
1540
1542
  "widget.dataSources": "データソース",
1541
1543
  "widget.tableActions": "テーブル操作",
1542
1544
  "widget.dataChart": "データチャート",
@@ -1511,6 +1511,7 @@ const messages: ToolkitAgentChatTranslation = {
1511
1511
  "tool.workedFor": "{{duration}} 동안 작업함",
1512
1512
  "widget.chart": "차트",
1513
1513
  "widget.chartActions": "차트 작업",
1514
+ "widget.chartRowsOmitted": "이 차트에는 사용 가능한 행 중 일부만 표시됩니다.",
1514
1515
  "widget.dataSources": "데이터 소스",
1515
1516
  "widget.tableActions": "표 작업",
1516
1517
  "widget.dataChart": "데이터 차트",
@@ -1056,6 +1056,8 @@ const messages: ToolkitAgentChatTranslation = {
1056
1056
  "tool.workedFor": "Trabalhou por {{duration}}",
1057
1057
  "widget.chart": "Gráfico",
1058
1058
  "widget.chartActions": "Ações do gráfico",
1059
+ "widget.chartRowsOmitted":
1060
+ "Este gráfico mostra apenas algumas das linhas disponíveis.",
1059
1061
  "widget.dataSources": "Fontes de dados",
1060
1062
  "widget.tableActions": "Ações da tabela",
1061
1063
  "widget.dataChart": "Gráfico de dados",
@@ -1420,6 +1420,7 @@ const messages: ToolkitAgentChatTranslation = {
1420
1420
  "tool.workedFor": "处理了 {{duration}}",
1421
1421
  "widget.chart": "图表",
1422
1422
  "widget.chartActions": "图表操作",
1423
+ "widget.chartRowsOmitted": "此图表仅显示部分可用行。",
1423
1424
  "widget.dataSources": "数据来源",
1424
1425
  "widget.tableActions": "表格操作",
1425
1426
  "widget.dataChart": "数据图表",
@@ -1425,6 +1425,7 @@ const messages: ToolkitAgentChatTranslation = {
1425
1425
  "tool.workedFor": "處理了 {{duration}}",
1426
1426
  "widget.chart": "圖表",
1427
1427
  "widget.chartActions": "圖表操作",
1428
+ "widget.chartRowsOmitted": "此圖表僅顯示部分可用資料列。",
1428
1429
  "widget.dataSources": "資料來源",
1429
1430
  "widget.tableActions": "表格操作",
1430
1431
  "widget.dataChart": "資料圖表",
@@ -0,0 +1,203 @@
1
+ import { useOnboardingChecklist } from "@agent-native/core/client/onboarding/use-onboarding-checklist";
2
+ import { IconCheck, IconChevronDown, IconChevronUp } from "@tabler/icons-react";
3
+ import type { ComponentType, ReactNode } from "react";
4
+
5
+ import { Button } from "../../ui/button.js";
6
+ import { Progress } from "../../ui/progress.js";
7
+ import { Skeleton } from "../../ui/skeleton.js";
8
+ import { cn } from "../../utils.js";
9
+
10
+ export interface GettingStartedLabels {
11
+ title: string;
12
+ progress: (completeCount: number, totalCount: number) => string;
13
+ /** Read by screen readers on a finished row; the check mark is decorative. */
14
+ completed: string;
15
+ collapse: string;
16
+ expand: string;
17
+ loadError: string;
18
+ retry: string;
19
+ }
20
+
21
+ export interface GettingStartedLinkProps {
22
+ to: string;
23
+ className?: string;
24
+ children: ReactNode;
25
+ }
26
+
27
+ function NativeLink({ to, className, children }: GettingStartedLinkProps) {
28
+ return (
29
+ <a href={to} className={className}>
30
+ {children}
31
+ </a>
32
+ );
33
+ }
34
+
35
+ export interface GettingStartedCardProps {
36
+ /** Name the steps were registered under with `registerOnboardingStep({ checklist })`. */
37
+ checklist: string;
38
+ labels: GettingStartedLabels;
39
+ /** Localized row titles by step id; a step without one shows its registered title. */
40
+ stepTitles?: Record<string, string>;
41
+ /** Router link for in-app rows so a click keeps the SPA and Cmd/Ctrl-click opens a tab. */
42
+ LinkComponent?: ComponentType<GettingStartedLinkProps>;
43
+ /** Number of rows to reserve while the first answer loads. */
44
+ expectedSteps?: number;
45
+ className?: string;
46
+ }
47
+
48
+ /**
49
+ * Progress checklist pinned to the app sidebar. Each app registers its own
50
+ * steps on the onboarding registry; the card only renders what the server
51
+ * derived. It renders nothing once every step is done.
52
+ */
53
+ export function GettingStartedCard({
54
+ checklist,
55
+ labels,
56
+ stepTitles,
57
+ LinkComponent = NativeLink,
58
+ expectedSteps = 6,
59
+ className,
60
+ }: GettingStartedCardProps) {
61
+ const {
62
+ steps,
63
+ completeCount,
64
+ totalCount,
65
+ dismissed,
66
+ collapsed,
67
+ status,
68
+ refresh,
69
+ setCollapsed,
70
+ } = useOnboardingChecklist(checklist);
71
+
72
+ const frame = cn(
73
+ "overflow-hidden rounded-[14px] border border-border bg-card text-card-foreground shadow-sm",
74
+ className,
75
+ );
76
+
77
+ if (status === "loading") {
78
+ return (
79
+ <div className={frame} aria-hidden>
80
+ <div className="space-y-3 px-4 py-3">
81
+ <Skeleton className="h-5 w-32" />
82
+ <Skeleton className="h-1.5 w-full rounded-full" />
83
+ </div>
84
+ <div className="border-t border-border">
85
+ {Array.from({ length: expectedSteps }, (_, index) => (
86
+ <div key={index} className="flex min-h-12 items-center gap-3 px-4">
87
+ <Skeleton className="size-4 rounded-full" />
88
+ <Skeleton className="h-3.5 w-28" />
89
+ </div>
90
+ ))}
91
+ </div>
92
+ </div>
93
+ );
94
+ }
95
+
96
+ if (status === "error") {
97
+ return (
98
+ <div
99
+ role="alert"
100
+ className={cn(
101
+ frame,
102
+ "flex items-center justify-between gap-2 px-4 py-3",
103
+ )}
104
+ >
105
+ <span className="text-[13px] text-muted-foreground">
106
+ {labels.loadError}
107
+ </span>
108
+ <Button
109
+ type="button"
110
+ variant="outline"
111
+ size="xs"
112
+ onClick={() => void refresh()}
113
+ >
114
+ {labels.retry}
115
+ </Button>
116
+ </div>
117
+ );
118
+ }
119
+
120
+ if (dismissed || totalCount === 0 || completeCount === totalCount) {
121
+ return null;
122
+ }
123
+
124
+ const progressText = labels.progress(completeCount, totalCount);
125
+ const ToggleIcon = collapsed ? IconChevronUp : IconChevronDown;
126
+
127
+ return (
128
+ <section className={frame} aria-label={labels.title}>
129
+ <div className="space-y-3 px-4 py-3">
130
+ <div className="flex items-center justify-between gap-2">
131
+ <h2 className="text-base font-semibold leading-5">{labels.title}</h2>
132
+ <Button
133
+ type="button"
134
+ variant="ghost"
135
+ size="icon"
136
+ className="size-6"
137
+ aria-label={collapsed ? labels.expand : labels.collapse}
138
+ aria-expanded={!collapsed}
139
+ onClick={() => void setCollapsed(!collapsed)}
140
+ >
141
+ <ToggleIcon className="size-4" />
142
+ </Button>
143
+ </div>
144
+ <Progress
145
+ value={(completeCount / totalCount) * 100}
146
+ className="h-1.5 bg-muted"
147
+ aria-label={progressText}
148
+ />
149
+ </div>
150
+ {collapsed ? null : (
151
+ <ul className="border-t border-border">
152
+ {steps.map((step) => {
153
+ const rowClass =
154
+ "flex min-h-12 items-center gap-3 px-4 text-[13px]";
155
+ const content = (
156
+ <>
157
+ <span
158
+ aria-hidden
159
+ className={cn(
160
+ "flex size-4 shrink-0 items-center justify-center rounded-full border",
161
+ step.complete
162
+ ? "border-primary bg-primary text-primary-foreground"
163
+ : "border-muted-foreground/60",
164
+ )}
165
+ >
166
+ {step.complete ? <IconCheck className="size-3" /> : null}
167
+ </span>
168
+ <span
169
+ className={cn(
170
+ "min-w-0 flex-1 truncate",
171
+ step.complete && "text-muted-foreground",
172
+ )}
173
+ >
174
+ {stepTitles?.[step.id] ?? step.title}
175
+ </span>
176
+ {step.complete ? (
177
+ <span className="sr-only">{labels.completed}</span>
178
+ ) : null}
179
+ </>
180
+ );
181
+ return (
182
+ <li key={step.id}>
183
+ {step.href ? (
184
+ <LinkComponent
185
+ to={step.href}
186
+ className={cn(
187
+ rowClass,
188
+ "hover:bg-accent/60 focus-visible:bg-accent/60 focus-visible:outline-none",
189
+ )}
190
+ >
191
+ {content}
192
+ </LinkComponent>
193
+ ) : (
194
+ <div className={rowClass}>{content}</div>
195
+ )}
196
+ </li>
197
+ );
198
+ })}
199
+ </ul>
200
+ )}
201
+ </section>
202
+ );
203
+ }
@@ -1,4 +1,5 @@
1
1
  export * from "./FirstRunOnboarding.js";
2
+ export * from "./GettingStartedCard.js";
2
3
  export * from "./NewWorkspaceAppFlow.js";
3
4
  export * from "./OnboardingBanner.js";
4
5
  export * from "./OnboardingPanel.js";
@@ -39,6 +39,7 @@ import {
39
39
  type AppShellSkeletonLayout,
40
40
  } from "../shared/AppShellSkeleton.js";
41
41
  import { ClientOnly } from "../shared/ClientOnly.js";
42
+ import { ConsentBanner } from "../shared/ConsentBanner.js";
42
43
  import { EnvironmentBadge } from "../shared/EnvironmentBadge.js";
43
44
  import { RouteTransitionIndicator } from "../shared/RouteTransitionIndicator.js";
44
45
  import { RuntimeConfigNotice } from "../shared/RuntimeConfigNotice.js";
@@ -436,12 +437,17 @@ function ProvidersInner({
436
437
  settingsShortcut: boolean;
437
438
  children: React.ReactNode;
438
439
  }) {
440
+ // The banner reads the app's locale, so it sits inside the same provider.
439
441
  const localizedChildren =
440
442
  i18n === false ? (
441
- children
443
+ <>
444
+ {children}
445
+ {ownsDocument ? <ConsentBanner /> : null}
446
+ </>
442
447
  ) : (
443
448
  <AgentNativeI18nProvider {...(i18n ?? {})}>
444
449
  {children}
450
+ {ownsDocument ? <ConsentBanner /> : null}
445
451
  </AgentNativeI18nProvider>
446
452
  );
447
453
 
@@ -148,6 +148,7 @@ vi.mock("@agent-native/core/client/i18n", () => ({
148
148
  "settings.privacyDeletionDescription":
149
149
  "This records a deletion request; it does not delete data immediately. An administrator will verify your identity and complete the request under the deployment's retention and legal obligations.",
150
150
  "settings.privacyDocsLink": "Read privacy and data rights",
151
+ "consentBanner.cookieSettings": "Cookie settings",
151
152
  "common.cancel": "Cancel",
152
153
  "agentChat.auth.logOut": "Log out",
153
154
  }[key] ??
@@ -155,6 +156,11 @@ vi.mock("@agent-native/core/client/i18n", () => ({
155
156
  key,
156
157
  }));
157
158
 
159
+ const openConsentSettingsMock = vi.hoisted(() => vi.fn());
160
+ vi.mock("@agent-native/core/client/consent", () => ({
161
+ openConsentSettings: openConsentSettingsMock,
162
+ }));
163
+
158
164
  vi.mock("./SchedulingTimezoneField.js", () => ({
159
165
  SchedulingTimezoneField: () => <div data-testid="timezone" />,
160
166
  }));
@@ -454,4 +460,29 @@ describe("AccountSettingsForm name editing", () => {
454
460
  requestType: "deletion",
455
461
  });
456
462
  });
463
+
464
+ it("reopens the cookie banner from Privacy & data", async () => {
465
+ await act(async () => {
466
+ root.render(
467
+ <TooltipProvider>
468
+ <AccountSettingsForm />
469
+ </TooltipProvider>,
470
+ );
471
+ });
472
+ act(() => {
473
+ Array.from(
474
+ container.querySelectorAll<HTMLButtonElement>("#privacy-data button"),
475
+ )
476
+ .find((button) => button.textContent?.trim() === "Manage")
477
+ ?.click();
478
+ });
479
+
480
+ act(() => {
481
+ Array.from(document.querySelectorAll<HTMLButtonElement>("button"))
482
+ .find((button) => button.textContent?.trim() === "Cookie settings")
483
+ ?.click();
484
+ });
485
+
486
+ expect(openConsentSettingsMock).toHaveBeenCalledTimes(1);
487
+ });
457
488
  });
@@ -1,3 +1,4 @@
1
+ import { openConsentSettings } from "@agent-native/core/client/consent";
1
2
  import {
2
3
  useActionMutation,
3
4
  useActionQuery,
@@ -579,6 +580,13 @@ function PrivacySettings() {
579
580
  {t("settings.privacyRequestError")}
580
581
  </p>
581
582
  )}
583
+ <button
584
+ type="button"
585
+ onClick={openConsentSettings}
586
+ className="block text-xs font-medium text-muted-foreground underline-offset-4 hover:text-foreground hover:underline"
587
+ >
588
+ {t("consentBanner.cookieSettings")}
589
+ </button>
582
590
  <a
583
591
  href={docsUrl("privacy-and-data-rights")}
584
592
  target="_blank"
@@ -73,6 +73,7 @@ export {
73
73
  type SettingsGroupProps,
74
74
  type SettingsRowProps,
75
75
  } from "./SettingsRow.js";
76
+ export { ThemeFamilySettings } from "./account/ThemeFamilySettings.js";
76
77
  export {
77
78
  SettingsSection,
78
79
  SettingsSurfaceProvider,