@agent-native/core 0.114.12 → 0.114.15

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 (241) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +21 -0
  3. package/corpus/core/docs/content/deployment.mdx +1 -1
  4. package/corpus/core/docs/content/frames.mdx +1 -1
  5. package/corpus/core/docs/content/integrations.mdx +27 -27
  6. package/corpus/core/docs/content/pr-visual-recap.mdx +17 -13
  7. package/corpus/core/docs/content/workspace-management.mdx +1 -1
  8. package/corpus/core/package.json +2 -1
  9. package/corpus/core/src/agent/engine/builder-engine.ts +4 -0
  10. package/corpus/core/src/application-state/index.ts +3 -0
  11. package/corpus/core/src/application-state/script-helpers.ts +12 -1
  12. package/corpus/core/src/application-state/store.ts +216 -15
  13. package/corpus/core/src/client/AgentPanel.tsx +10 -4
  14. package/corpus/core/src/client/ConnectBuilderCard.tsx +5 -1
  15. package/corpus/core/src/client/chat/markdown-renderer.tsx +3 -5
  16. package/corpus/core/src/client/error-format.ts +2 -1
  17. package/corpus/core/src/client/index.ts +1 -0
  18. package/corpus/core/src/client/integrations/IntegrationsPanel.tsx +2 -18
  19. package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +43 -32
  20. package/corpus/core/src/client/resources/mcp-integration-catalog.ts +4 -2
  21. package/corpus/core/src/client/settings/BackgroundAgentSection.tsx +5 -1
  22. package/corpus/core/src/client/settings/SettingsPanel.tsx +4 -4
  23. package/corpus/core/src/client/settings/useBuilderStatus.ts +3 -0
  24. package/corpus/core/src/db/client.ts +44 -1
  25. package/corpus/core/src/localization/default-messages.ts +1 -7
  26. package/corpus/core/src/server/builder-browser.ts +4 -0
  27. package/corpus/core/src/server/builder-design-systems.ts +6 -1
  28. package/corpus/core/src/server/fusion-app.ts +5 -1
  29. package/corpus/core/src/shared/builder-link-tracking.ts +41 -0
  30. package/corpus/core/src/shared/index.ts +1 -0
  31. package/corpus/templates/analytics/AGENTS.md +10 -1
  32. package/corpus/templates/analytics/actions/save-dashboard-report-subscription.ts +10 -2
  33. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +5 -4
  34. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +20 -32
  35. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/report-panel-window.ts +62 -0
  36. package/corpus/templates/analytics/changelog/2026-07-21-chart-series-controls-stay-open-while-moving-from-the-legend.md +6 -0
  37. package/corpus/templates/analytics/changelog/2026-07-21-dashboard-email-captures-complete-large-dashboards-in-chunks.md +6 -0
  38. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +4 -4
  39. package/corpus/templates/analytics/server/jobs/dashboard-report.ts +1 -8
  40. package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +39 -7
  41. package/corpus/templates/analytics/server/lib/dashboard-report.ts +341 -251
  42. package/corpus/templates/analytics/server/lib/first-party-dashboard-repair.ts +114 -0
  43. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +84 -6
  44. package/corpus/templates/analytics/server/plugins/db.ts +13 -0
  45. package/corpus/templates/clips/app/components/player/video-player.tsx +10 -4
  46. package/corpus/templates/clips/changelog/2026-07-21-choose-which-whisper-model-to-use-in-settings.md +6 -0
  47. package/corpus/templates/clips/changelog/2026-07-21-fixed-organization-recording-visibility-default.md +6 -0
  48. package/corpus/templates/clips/changelog/2026-07-21-live-dictation-text-now-appears-above-the-desktop-recording-.md +6 -0
  49. package/corpus/templates/clips/changelog/2026-07-21-meeting-notes-stop-when-calls-end.md +6 -0
  50. package/corpus/templates/clips/desktop/src/app.tsx +66 -75
  51. package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +2 -0
  52. package/corpus/templates/clips/desktop/src/hooks/useWhisperSettings.ts +172 -0
  53. package/corpus/templates/clips/desktop/src/lib/meeting-call-app.ts +41 -0
  54. package/corpus/templates/clips/desktop/src/lib/silence-events.ts +1 -0
  55. package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +14 -3
  56. package/corpus/templates/clips/desktop/src/overlays/flow-bar.tsx +25 -0
  57. package/corpus/templates/clips/desktop/src/shared/config.ts +1 -0
  58. package/corpus/templates/clips/desktop/src/styles.css +100 -7
  59. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +3 -4
  60. package/corpus/templates/clips/desktop/src-tauri/src/config.rs +32 -0
  61. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +3 -0
  62. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +11 -4
  63. package/corpus/templates/clips/desktop/src-tauri/src/silence_detector.rs +268 -20
  64. package/corpus/templates/clips/desktop/src-tauri/src/whisper_model.rs +285 -164
  65. package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +18 -7
  66. package/corpus/templates/clips/learnings.defaults.md +1 -1
  67. package/corpus/templates/clips/server/plugins/db.ts +11 -0
  68. package/corpus/templates/clips/shared/builder-credits.ts +1 -1
  69. package/corpus/templates/design/AGENTS.md +7 -3
  70. package/corpus/templates/design/actions/begin-node-rewrite-request.ts +78 -0
  71. package/corpus/templates/design/actions/cancel-node-rewrite-request.ts +17 -7
  72. package/corpus/templates/design/actions/propose-node-rewrite.ts +26 -18
  73. package/corpus/templates/design/actions/resolve-node-rewrite.ts +67 -19
  74. package/corpus/templates/design/app/components/design/FusionAppBanner.tsx +9 -1
  75. package/corpus/templates/design/app/components/design/edit-panel/component-section.tsx +5 -1
  76. package/corpus/templates/design/app/components/visual-editor/NodeRewriteProposal.tsx +1 -4
  77. package/corpus/templates/design/app/components/visual-editor/ReviewCanvasPins.tsx +2 -6
  78. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +9 -1
  79. package/corpus/templates/design/shared/node-rewrite.ts +32 -0
  80. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +6 -3
  81. package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +11 -18
  82. package/corpus/templates/forms/app/pages/FormsListPage.tsx +9 -5
  83. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +9 -1
  84. package/corpus/templates/slides/app/context/DeckContext.tsx +18 -0
  85. package/corpus/templates/slides/changelog/2026-07-21-decks-list-now-refreshes-when-you-switch-organizations.md +6 -0
  86. package/corpus/templates/tasks/app/components/custom-fields/FieldCreateBar.tsx +13 -19
  87. package/corpus/templates/tasks/app/components/custom-fields/FieldListRow.tsx +27 -22
  88. package/corpus/templates/tasks/app/components/custom-fields/FieldsList.tsx +26 -22
  89. package/corpus/templates/tasks/app/components/custom-fields/FieldsListSkeleton.tsx +4 -1
  90. package/corpus/templates/tasks/app/components/custom-fields/FieldsPage.tsx +4 -2
  91. package/corpus/templates/tasks/app/components/custom-fields/editor/FieldEditorSidebar.tsx +12 -3
  92. package/corpus/templates/tasks/app/components/custom-fields/editor/FieldTitleSection.tsx +6 -3
  93. package/corpus/templates/tasks/app/components/custom-fields/editor/config/CurrencyConfigControl.tsx +5 -2
  94. package/corpus/templates/tasks/app/components/custom-fields/editor/config/NumberConfigControl.tsx +5 -2
  95. package/corpus/templates/tasks/app/components/custom-fields/editor/config/PercentConfigControl.tsx +4 -1
  96. package/corpus/templates/tasks/app/components/custom-fields/editor/config/SelectConfigControl.tsx +17 -7
  97. package/corpus/templates/tasks/app/components/custom-fields/editor/config/select-colors.ts +37 -9
  98. package/corpus/templates/tasks/app/components/custom-fields/field-types.ts +23 -0
  99. package/corpus/templates/tasks/app/components/inbox/InboxList.tsx +24 -16
  100. package/corpus/templates/tasks/app/components/inbox/InboxListPage.tsx +5 -3
  101. package/corpus/templates/tasks/app/components/inbox/InboxListRow.tsx +7 -5
  102. package/corpus/templates/tasks/app/components/layout/Header.tsx +10 -10
  103. package/corpus/templates/tasks/app/components/layout/Layout.tsx +11 -7
  104. package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +17 -10
  105. package/corpus/templates/tasks/app/components/shared/AddListItemInput.tsx +14 -8
  106. package/corpus/templates/tasks/app/components/shared/AlertDialog.tsx +6 -2
  107. package/corpus/templates/tasks/app/components/shared/BulkDeleteDialog.tsx +13 -6
  108. package/corpus/templates/tasks/app/components/shared/ChipSelect.tsx +12 -5
  109. package/corpus/templates/tasks/app/components/shared/DeleteItemDialog.tsx +6 -6
  110. package/corpus/templates/tasks/app/components/shared/ListViewHeader.tsx +3 -1
  111. package/corpus/templates/tasks/app/components/shared/SidePanel.tsx +5 -2
  112. package/corpus/templates/tasks/app/components/shared/list/ListRowDragHandle.tsx +3 -1
  113. package/corpus/templates/tasks/app/components/shared/selection/ListSelectionBar.tsx +46 -20
  114. package/corpus/templates/tasks/app/components/shared/selection/ListSelectionHeaderToggle.tsx +3 -1
  115. package/corpus/templates/tasks/app/components/shared/selection/ListSelectionToolbar.tsx +10 -6
  116. package/corpus/templates/tasks/app/components/tasks/TaskList.tsx +24 -13
  117. package/corpus/templates/tasks/app/components/tasks/TaskListHeaderRow.tsx +4 -1
  118. package/corpus/templates/tasks/app/components/tasks/TaskListPage.tsx +5 -3
  119. package/corpus/templates/tasks/app/components/tasks/TaskListRow.tsx +15 -6
  120. package/corpus/templates/tasks/app/components/tasks/fields/TaskFieldsSidebar.tsx +11 -6
  121. package/corpus/templates/tasks/app/components/tasks/fields/TaskTitleSection.tsx +8 -3
  122. package/corpus/templates/tasks/app/components/tasks/fields/controls/RichTextValueControl.tsx +12 -6
  123. package/corpus/templates/tasks/app/components/tasks/fields/controls/SingleSelectValueControl.tsx +6 -1
  124. package/corpus/templates/tasks/app/i18n/en-US.ts +209 -0
  125. package/corpus/templates/tasks/app/i18n/index.ts +34 -0
  126. package/corpus/templates/tasks/app/root.tsx +34 -2
  127. package/corpus/templates/tasks/app/routes/extensions.$id.tsx +2 -1
  128. package/corpus/templates/tasks/app/routes/extensions._index.tsx +2 -1
  129. package/corpus/templates/tasks/app/routes/fields.tsx +2 -1
  130. package/corpus/templates/tasks/app/routes/inbox.tsx +2 -1
  131. package/corpus/templates/tasks/app/routes/tasks.tsx +2 -1
  132. package/corpus/templates/tasks/app/routes/team.tsx +6 -3
  133. package/corpus/templates/tasks/changelog/2026-07-20-tasks-is-now-available-in-10-additional-languages.md +6 -0
  134. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  135. package/dist/agent/engine/builder-engine.js +4 -0
  136. package/dist/agent/engine/builder-engine.js.map +1 -1
  137. package/dist/application-state/index.d.ts +2 -2
  138. package/dist/application-state/index.d.ts.map +1 -1
  139. package/dist/application-state/index.js +2 -2
  140. package/dist/application-state/index.js.map +1 -1
  141. package/dist/application-state/script-helpers.d.ts +3 -1
  142. package/dist/application-state/script-helpers.d.ts.map +1 -1
  143. package/dist/application-state/script-helpers.js +7 -1
  144. package/dist/application-state/script-helpers.js.map +1 -1
  145. package/dist/application-state/store.d.ts +7 -1
  146. package/dist/application-state/store.d.ts.map +1 -1
  147. package/dist/application-state/store.js +143 -17
  148. package/dist/application-state/store.js.map +1 -1
  149. package/dist/client/AgentPanel.d.ts.map +1 -1
  150. package/dist/client/AgentPanel.js +10 -3
  151. package/dist/client/AgentPanel.js.map +1 -1
  152. package/dist/client/ConnectBuilderCard.d.ts.map +1 -1
  153. package/dist/client/ConnectBuilderCard.js +5 -1
  154. package/dist/client/ConnectBuilderCard.js.map +1 -1
  155. package/dist/client/chat/markdown-renderer.d.ts.map +1 -1
  156. package/dist/client/chat/markdown-renderer.js +3 -2
  157. package/dist/client/chat/markdown-renderer.js.map +1 -1
  158. package/dist/client/error-format.d.ts +1 -1
  159. package/dist/client/error-format.d.ts.map +1 -1
  160. package/dist/client/error-format.js +1 -1
  161. package/dist/client/error-format.js.map +1 -1
  162. package/dist/client/index.d.ts +1 -0
  163. package/dist/client/index.d.ts.map +1 -1
  164. package/dist/client/index.js +1 -0
  165. package/dist/client/index.js.map +1 -1
  166. package/dist/client/integrations/IntegrationsPanel.d.ts.map +1 -1
  167. package/dist/client/integrations/IntegrationsPanel.js +3 -4
  168. package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
  169. package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
  170. package/dist/client/resources/McpIntegrationDialog.js +21 -7
  171. package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
  172. package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
  173. package/dist/client/resources/mcp-integration-catalog.js +2 -2
  174. package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
  175. package/dist/client/settings/BackgroundAgentSection.d.ts.map +1 -1
  176. package/dist/client/settings/BackgroundAgentSection.js +5 -1
  177. package/dist/client/settings/BackgroundAgentSection.js.map +1 -1
  178. package/dist/client/settings/SettingsPanel.js +1 -1
  179. package/dist/client/settings/SettingsPanel.js.map +1 -1
  180. package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
  181. package/dist/client/settings/useBuilderStatus.js +2 -0
  182. package/dist/client/settings/useBuilderStatus.js.map +1 -1
  183. package/dist/collab/routes.d.ts +1 -1
  184. package/dist/db/client.d.ts +7 -0
  185. package/dist/db/client.d.ts.map +1 -1
  186. package/dist/db/client.js +39 -1
  187. package/dist/db/client.js.map +1 -1
  188. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  189. package/dist/localization/default-messages.d.ts +0 -6
  190. package/dist/localization/default-messages.d.ts.map +1 -1
  191. package/dist/localization/default-messages.js +1 -7
  192. package/dist/localization/default-messages.js.map +1 -1
  193. package/dist/notifications/routes.d.ts +2 -2
  194. package/dist/observability/routes.d.ts +3 -3
  195. package/dist/resources/handlers.d.ts +1 -1
  196. package/dist/server/builder-browser.d.ts.map +1 -1
  197. package/dist/server/builder-browser.js +4 -0
  198. package/dist/server/builder-browser.js.map +1 -1
  199. package/dist/server/builder-design-systems.d.ts.map +1 -1
  200. package/dist/server/builder-design-systems.js +6 -1
  201. package/dist/server/builder-design-systems.js.map +1 -1
  202. package/dist/server/fusion-app.d.ts.map +1 -1
  203. package/dist/server/fusion-app.js +2 -1
  204. package/dist/server/fusion-app.js.map +1 -1
  205. package/dist/server/transcribe-voice.d.ts +1 -1
  206. package/dist/shared/builder-link-tracking.d.ts +14 -0
  207. package/dist/shared/builder-link-tracking.d.ts.map +1 -0
  208. package/dist/shared/builder-link-tracking.js +26 -0
  209. package/dist/shared/builder-link-tracking.js.map +1 -0
  210. package/dist/shared/index.d.ts +1 -0
  211. package/dist/shared/index.d.ts.map +1 -1
  212. package/dist/shared/index.js +1 -0
  213. package/dist/shared/index.js.map +1 -1
  214. package/docs/content/deployment.mdx +1 -1
  215. package/docs/content/frames.mdx +1 -1
  216. package/docs/content/integrations.mdx +27 -27
  217. package/docs/content/pr-visual-recap.mdx +17 -13
  218. package/docs/content/workspace-management.mdx +1 -1
  219. package/package.json +3 -2
  220. package/src/agent/engine/builder-engine.ts +4 -0
  221. package/src/application-state/index.ts +3 -0
  222. package/src/application-state/script-helpers.ts +12 -1
  223. package/src/application-state/store.ts +216 -15
  224. package/src/client/AgentPanel.tsx +10 -4
  225. package/src/client/ConnectBuilderCard.tsx +5 -1
  226. package/src/client/chat/markdown-renderer.tsx +3 -5
  227. package/src/client/error-format.ts +2 -1
  228. package/src/client/index.ts +1 -0
  229. package/src/client/integrations/IntegrationsPanel.tsx +2 -18
  230. package/src/client/resources/McpIntegrationDialog.tsx +43 -32
  231. package/src/client/resources/mcp-integration-catalog.ts +4 -2
  232. package/src/client/settings/BackgroundAgentSection.tsx +5 -1
  233. package/src/client/settings/SettingsPanel.tsx +4 -4
  234. package/src/client/settings/useBuilderStatus.ts +3 -0
  235. package/src/db/client.ts +44 -1
  236. package/src/localization/default-messages.ts +1 -7
  237. package/src/server/builder-browser.ts +4 -0
  238. package/src/server/builder-design-systems.ts +6 -1
  239. package/src/server/fusion-app.ts +5 -1
  240. package/src/shared/builder-link-tracking.ts +41 -0
  241. package/src/shared/index.ts +1 -0
@@ -1,3 +1,4 @@
1
+ import { useT } from "@agent-native/core/client/i18n";
1
2
  import { type ReactNode } from "react";
2
3
 
3
4
  import {
@@ -20,19 +21,18 @@ export function DeleteItemDialog({
20
21
  pending,
21
22
  onConfirm,
22
23
  }: DeleteItemDialogProps) {
24
+ const t = useT();
23
25
  return (
24
26
  <AlertDialog
25
27
  open={open}
26
28
  onOpenChange={onOpenChange}
27
29
  pending={pending}
28
- title={`Delete ${entityLabel}?`}
30
+ title={t("dialogs.deleteEntityTitle", { entity: entityLabel })}
29
31
  description={
30
32
  description ??
31
- (itemTitle ? (
32
- <>This removes &quot;{itemTitle}&quot; permanently.</>
33
- ) : (
34
- `This removes the ${entityLabel} permanently.`
35
- ))
33
+ (itemTitle
34
+ ? t("dialogs.deleteItemDescriptionWithTitle", { title: itemTitle })
35
+ : t("dialogs.deleteItemDescription", { entity: entityLabel }))
36
36
  }
37
37
  onConfirm={onConfirm}
38
38
  />
@@ -1,4 +1,5 @@
1
1
  import { AgentToggleButton } from "@agent-native/core/client/agent-chat";
2
+ import { useT } from "@agent-native/core/client/i18n";
2
3
 
3
4
  import { PageHeader } from "@/components/shared/PageHeader";
4
5
  import { ListSelectionHeaderToggle } from "@/components/shared/selection/ListSelectionHeaderToggle";
@@ -29,6 +30,7 @@ export function ListViewHeader<T extends { id: string }>({
29
30
  onIncludeDoneChange,
30
31
  showAgentToggle = false,
31
32
  }: ListViewHeaderProps<T>) {
33
+ const t = useT();
32
34
  const showIncludeDone =
33
35
  includeDone !== undefined && onIncludeDoneChange !== undefined;
34
36
  const hasActions =
@@ -62,7 +64,7 @@ export function ListViewHeader<T extends { id: string }>({
62
64
  htmlFor="include-done"
63
65
  className="text-sm whitespace-nowrap"
64
66
  >
65
- Show all
67
+ {t("common.showAll")}
66
68
  </Label>
67
69
  </div>
68
70
  ) : null}
@@ -1,3 +1,4 @@
1
+ import { useT } from "@agent-native/core/client/i18n";
1
2
  import { IconX } from "@tabler/icons-react";
2
3
  import { useEffect, useState, type ReactNode } from "react";
3
4
 
@@ -32,7 +33,7 @@ export function SidePanel({
32
33
  className,
33
34
  title,
34
35
  subtitle,
35
- closeLabel = "Close panel",
36
+ closeLabel,
36
37
  onClose,
37
38
  }: {
38
39
  children: ReactNode;
@@ -42,6 +43,8 @@ export function SidePanel({
42
43
  closeLabel?: string;
43
44
  onClose?: () => void;
44
45
  }) {
46
+ const t = useT();
47
+ const resolvedCloseLabel = closeLabel ?? t("common.closePanel");
45
48
  const width = useAgentSidebarWidth();
46
49
 
47
50
  useEffect(() => {
@@ -85,7 +88,7 @@ export function SidePanel({
85
88
  variant="ghost"
86
89
  size="icon"
87
90
  onClick={onClose}
88
- aria-label={closeLabel}
91
+ aria-label={resolvedCloseLabel}
89
92
  className="size-8"
90
93
  >
91
94
  <IconX className="size-4" />
@@ -1,3 +1,4 @@
1
+ import { useT } from "@agent-native/core/client/i18n";
1
2
  import { IconGripVertical } from "@tabler/icons-react";
2
3
 
3
4
  import type {
@@ -19,6 +20,7 @@ export function ListRowDragHandle({
19
20
  displayTitle,
20
21
  disabled = false,
21
22
  }: ListRowDragHandleProps) {
23
+ const t = useT();
22
24
  const { dragHandleProps, isDragging } = rowDrag;
23
25
  const { selectionMode } = rowSelection;
24
26
 
@@ -29,7 +31,7 @@ export function ListRowDragHandle({
29
31
  type="button"
30
32
  {...dragHandleProps}
31
33
  disabled={disabled}
32
- aria-label={`Reorder ${displayTitle}`}
34
+ aria-label={t("common.reorderAriaLabel", { title: displayTitle })}
33
35
  onClick={(event) => {
34
36
  if (selectionMode) {
35
37
  event.stopPropagation();
@@ -1,3 +1,4 @@
1
+ import { useT } from "@agent-native/core/client/i18n";
1
2
  import { IconCircleCheck, IconCircle } from "@tabler/icons-react";
2
3
  import { toast } from "sonner";
3
4
 
@@ -26,6 +27,7 @@ export function ListSelectionBar<
26
27
  toolbarBusy,
27
28
  onOpenBulkDelete,
28
29
  }: ListSelectionBarProps<T>) {
30
+ const t = useT();
29
31
  const bulkUpdateTasks = useBulkUpdateTasks();
30
32
  const bulkMarkInboxItemsReady = useBulkMarkInboxItemsReady();
31
33
 
@@ -35,8 +37,6 @@ export function ListSelectionBar<
35
37
  const allVisibleSelected =
36
38
  items.length > 0 && items.every((item) => selectedIdSet.has(item.id));
37
39
 
38
- const entityLabel = promotedToTask ? "task" : "item";
39
-
40
40
  async function markSelectedReady() {
41
41
  if (selectedCount === 0) return;
42
42
 
@@ -45,11 +45,13 @@ export function ListSelectionBar<
45
45
  inboxItemIds: selectedItems.map((item) => item.id),
46
46
  });
47
47
  toast.success(
48
- `Marked ${selectedCount} ${selectedCount === 1 ? "item" : "items"} ready`,
48
+ selectedCount === 1
49
+ ? t("selection.markedReadyOne", { count: selectedCount })
50
+ : t("selection.markedReadyOther", { count: selectedCount }),
49
51
  );
50
52
  selection.actions.clearSelection();
51
53
  } catch {
52
- toast.error("Could not mark selected items ready.");
54
+ toast.error(t("selection.couldNotMarkReady"));
53
55
  }
54
56
  }
55
57
 
@@ -59,8 +61,8 @@ export function ListSelectionBar<
59
61
  if (applicableTasks.length === 0) {
60
62
  toast.info(
61
63
  done
62
- ? "All selected tasks are already complete."
63
- : "All selected tasks are already incomplete.",
64
+ ? t("selection.allTasksAlreadyComplete")
65
+ : t("selection.allTasksAlreadyIncomplete"),
64
66
  );
65
67
  return;
66
68
  }
@@ -70,19 +72,33 @@ export function ListSelectionBar<
70
72
  try {
71
73
  await bulkUpdateTasks.mutateAsync({ taskIds, done });
72
74
 
73
- const countLabel = applicableTasks.length === 1 ? "task" : "tasks";
75
+ const unit =
76
+ applicableTasks.length === 1
77
+ ? t("tasks.entitySingular")
78
+ : t("tasks.entityPlural");
74
79
  toast.success(
75
80
  done
76
81
  ? skippedCount > 0
77
- ? `Marked ${applicableTasks.length} ${countLabel} complete (${skippedCount} already complete)`
78
- : `Marked ${applicableTasks.length} ${countLabel} complete`
82
+ ? t("selection.markedDoneWithSkipped", {
83
+ count: applicableTasks.length,
84
+ unit,
85
+ skipped: skippedCount,
86
+ })
87
+ : t("selection.markedDone", { count: applicableTasks.length, unit })
79
88
  : skippedCount > 0
80
- ? `Marked ${applicableTasks.length} ${countLabel} incomplete (${skippedCount} already incomplete)`
81
- : `Marked ${applicableTasks.length} ${countLabel} incomplete`,
89
+ ? t("selection.markedNotDoneWithSkipped", {
90
+ count: applicableTasks.length,
91
+ unit,
92
+ skipped: skippedCount,
93
+ })
94
+ : t("selection.markedNotDone", {
95
+ count: applicableTasks.length,
96
+ unit,
97
+ }),
82
98
  );
83
99
  selection.actions.clearSelection();
84
100
  } catch {
85
- toast.error("Could not update selected tasks.");
101
+ toast.error(t("selection.couldNotUpdateTasks"));
86
102
  }
87
103
  }
88
104
 
@@ -101,9 +117,15 @@ export function ListSelectionBar<
101
117
  return (
102
118
  <ListSelectionToolbar
103
119
  ariaLabel={
104
- promotedToTask ? "Task selection actions" : "Inbox selection actions"
120
+ promotedToTask
121
+ ? t("selection.taskSelectionActionsAriaLabel")
122
+ : t("selection.inboxSelectionActionsAriaLabel")
123
+ }
124
+ emptySelectionHint={
125
+ promotedToTask
126
+ ? t("selection.tapToSelectTasks")
127
+ : t("selection.tapToSelectItems")
105
128
  }
106
- emptySelectionHint={`Tap ${entityLabel}s to select them.`}
107
129
  visibleCount={items.length}
108
130
  selectedCount={selectedCount}
109
131
  allVisibleSelected={allVisibleSelected}
@@ -120,11 +142,13 @@ export function ListSelectionBar<
120
142
  disabled={
121
143
  selectedCount === 0 || toolbarDisabled || allSelectedComplete
122
144
  }
123
- aria-label="Mark complete"
145
+ aria-label={t("selection.markComplete")}
124
146
  onClick={() => void markSelectedDone(true)}
125
147
  >
126
148
  <IconCircleCheck className="h-3.5 w-3.5" />
127
- <span className="hidden sm:inline">Complete</span>
149
+ <span className="hidden sm:inline">
150
+ {t("selection.completeLabel")}
151
+ </span>
128
152
  </Button>
129
153
  <Button
130
154
  variant="ghost"
@@ -133,11 +157,13 @@ export function ListSelectionBar<
133
157
  disabled={
134
158
  selectedCount === 0 || toolbarDisabled || allSelectedIncomplete
135
159
  }
136
- aria-label="Mark incomplete"
160
+ aria-label={t("selection.markIncomplete")}
137
161
  onClick={() => void markSelectedDone(false)}
138
162
  >
139
163
  <IconCircle className="h-3.5 w-3.5" />
140
- <span className="hidden sm:inline">Incomplete</span>
164
+ <span className="hidden sm:inline">
165
+ {t("selection.incompleteLabel")}
166
+ </span>
141
167
  </Button>
142
168
  </>
143
169
  ) : (
@@ -146,11 +172,11 @@ export function ListSelectionBar<
146
172
  size="sm"
147
173
  className="h-8 shrink-0 gap-1 px-2 text-xs"
148
174
  disabled={selectedCount === 0 || toolbarDisabled}
149
- aria-label="Mark ready"
175
+ aria-label={t("common.markReady")}
150
176
  onClick={() => void markSelectedReady()}
151
177
  >
152
178
  <IconCircleCheck className="h-3.5 w-3.5" />
153
- <span className="hidden sm:inline">Mark ready</span>
179
+ <span className="hidden sm:inline">{t("common.markReady")}</span>
154
180
  </Button>
155
181
  )}
156
182
  </ListSelectionToolbar>
@@ -1,3 +1,4 @@
1
+ import { useT } from "@agent-native/core/client/i18n";
1
2
  import { IconChecks } from "@tabler/icons-react";
2
3
 
3
4
  import { Button } from "@/components/ui/button";
@@ -13,6 +14,7 @@ export function ListSelectionHeaderToggle({
13
14
  disabled,
14
15
  onSelectionModeChange,
15
16
  }: ListSelectionHeaderToggleProps) {
17
+ const t = useT();
16
18
  return (
17
19
  <Button
18
20
  variant={selectionMode ? "secondary" : "ghost"}
@@ -22,7 +24,7 @@ export function ListSelectionHeaderToggle({
22
24
  onClick={() => onSelectionModeChange(!selectionMode)}
23
25
  >
24
26
  <IconChecks className="h-3.5 w-3.5" />
25
- {selectionMode ? "Done selecting" : "Select"}
27
+ {selectionMode ? t("selection.doneSelecting") : t("selection.select")}
26
28
  </Button>
27
29
  );
28
30
  }
@@ -1,3 +1,4 @@
1
+ import { useT } from "@agent-native/core/client/i18n";
1
2
  import { IconTrash, IconX } from "@tabler/icons-react";
2
3
  import { type ReactNode } from "react";
3
4
 
@@ -27,12 +28,13 @@ export function ListSelectionToolbar({
27
28
  onOpenBulkDelete,
28
29
  children,
29
30
  }: ListSelectionToolbarProps) {
31
+ const t = useT();
30
32
  const statusText =
31
33
  selectedCount === 0
32
34
  ? emptySelectionHint
33
35
  : selectedCount > 1
34
- ? `${selectedCount} selected · drag to reorder`
35
- : `${selectedCount} selected`;
36
+ ? t("selection.selectedCountReorder", { count: selectedCount })
37
+ : t("selection.selectedCount", { count: selectedCount });
36
38
 
37
39
  return (
38
40
  <div
@@ -51,7 +53,9 @@ export function ListSelectionToolbar({
51
53
  disabled={toolbarDisabled || visibleCount === 0}
52
54
  onClick={selectionActions.selectAll}
53
55
  >
54
- {allVisibleSelected ? "Clear all" : "Select all"}
56
+ {allVisibleSelected
57
+ ? t("selection.clearAll")
58
+ : t("selection.selectAll")}
55
59
  </Button>
56
60
  {children}
57
61
  <Button
@@ -59,11 +63,11 @@ export function ListSelectionToolbar({
59
63
  size="sm"
60
64
  className="h-8 shrink-0 gap-1 px-2 text-xs text-destructive hover:text-destructive"
61
65
  disabled={selectedCount === 0 || toolbarDisabled}
62
- aria-label="Delete"
66
+ aria-label={t("common.delete")}
63
67
  onClick={onOpenBulkDelete}
64
68
  >
65
69
  <IconTrash className="h-3.5 w-3.5" />
66
- <span className="hidden sm:inline">Delete</span>
70
+ <span className="hidden sm:inline">{t("common.delete")}</span>
67
71
  </Button>
68
72
  <Button
69
73
  variant="ghost"
@@ -71,7 +75,7 @@ export function ListSelectionToolbar({
71
75
  className="h-8 w-8 shrink-0"
72
76
  disabled={toolbarDisabled}
73
77
  onClick={selectionActions.clearSelection}
74
- aria-label="Exit selection mode"
78
+ aria-label={t("selection.exitSelectionMode")}
75
79
  >
76
80
  <IconX className="h-3.5 w-3.5" />
77
81
  </Button>
@@ -1,4 +1,5 @@
1
1
  import { focusAgentChat } from "@agent-native/core/client/agent-chat";
2
+ import { useT } from "@agent-native/core/client/i18n";
2
3
  import { useEffect, useMemo, useRef, useState } from "react";
3
4
  import { toast } from "sonner";
4
5
 
@@ -41,19 +42,20 @@ function NoTasksMessage({
41
42
  }: {
42
43
  hasHiddenCompletedTasks: boolean;
43
44
  }) {
45
+ const t = useT();
44
46
  if (hasHiddenCompletedTasks) {
45
47
  return (
46
48
  <ListEmptyState
47
- heading="All tasks complete"
48
- description="Toggle Show all to review completed tasks."
49
+ heading={t("tasks.allCompleteHeading")}
50
+ description={t("tasks.allCompleteDescription")}
49
51
  />
50
52
  );
51
53
  }
52
54
 
53
55
  return (
54
56
  <ListEmptyState
55
- heading="No tasks yet"
56
- description="Add one above or ask chat to create a task for you."
57
+ heading={t("tasks.emptyHeading")}
58
+ description={t("tasks.emptyDescription")}
57
59
  />
58
60
  );
59
61
  }
@@ -67,6 +69,7 @@ export function TaskList({
67
69
  activeTaskId,
68
70
  setActiveTaskId,
69
71
  }: TaskListProps) {
72
+ const t = useT();
70
73
  const createTask = useCreateTask();
71
74
  const updateTask = useUpdateTask();
72
75
  const deleteTask = useDeleteTask();
@@ -162,12 +165,18 @@ export function TaskList({
162
165
  try {
163
166
  await handleBulkDelete(ids);
164
167
  toast.success(
165
- `Deleted ${ids.length} ${ids.length === 1 ? "task" : "tasks"}`,
168
+ t("dialogs.deletedCount", {
169
+ count: ids.length,
170
+ entity:
171
+ ids.length === 1
172
+ ? t("tasks.entitySingular")
173
+ : t("tasks.entityPlural"),
174
+ }),
166
175
  );
167
176
  selection.actions.clearSelection();
168
177
  setBulkDeleteOpen(false);
169
178
  } catch {
170
- toast.error("Could not delete selected tasks.");
179
+ toast.error(t("tasks.bulkDeleteError"));
171
180
  }
172
181
  }
173
182
 
@@ -176,8 +185,8 @@ export function TaskList({
176
185
  <div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
177
186
  <div className="flex min-h-0 flex-col gap-6 overflow-hidden">
178
187
  <ListViewHeader
179
- title="Tasks"
180
- description="Manage your task list, drag to reorder, or ask chat to add reminders."
188
+ title={t("tasks.pageTitle")}
189
+ description={t("tasks.pageDescription")}
181
190
  isPending={isPending}
182
191
  showSelectToggle={hasTasks}
183
192
  selection={selection}
@@ -215,7 +224,9 @@ export function TaskList({
215
224
 
216
225
  <div
217
226
  aria-label={
218
- isPending || tasks.length === 0 ? "Tasks list" : undefined
227
+ isPending || tasks.length === 0
228
+ ? t("tasks.listAriaLabel")
229
+ : undefined
219
230
  }
220
231
  className="min-h-0 flex-1 overflow-y-auto overscroll-contain pr-1 outline-none"
221
232
  >
@@ -229,7 +240,7 @@ export function TaskList({
229
240
  <List
230
241
  items={orderedTasks}
231
242
  selection={selection}
232
- ariaLabel="Tasks list"
243
+ ariaLabel={t("tasks.listAriaLabel")}
233
244
  onReorder={handleReorder}
234
245
  renderItem={({ item, sortable }) => (
235
246
  <TaskListRow
@@ -300,7 +311,7 @@ export function TaskList({
300
311
  onOpenChange={(open) => {
301
312
  if (!open) setPendingDeleteId(null);
302
313
  }}
303
- entityLabel="task"
314
+ entityLabel={t("tasks.entitySingular")}
304
315
  itemTitle={pendingDeleteTask?.title ?? null}
305
316
  pending={deleteTask.isPending}
306
317
  onConfirm={async () => {
@@ -315,8 +326,8 @@ export function TaskList({
315
326
  open={bulkDeleteOpen}
316
327
  onOpenChange={setBulkDeleteOpen}
317
328
  selectedItems={selection.state.selectedItems}
318
- entitySingular="task"
319
- entityPlural="tasks"
329
+ entitySingular={t("tasks.entitySingular")}
330
+ entityPlural={t("tasks.entityPlural")}
320
331
  pending={bulkDeleteTasks.isPending}
321
332
  onConfirm={() => void confirmBulkDelete()}
322
333
  />
@@ -1,3 +1,5 @@
1
+ import { useT } from "@agent-native/core/client/i18n";
2
+
1
3
  import type { TaskFieldValue } from "@/hooks/use-custom-fields";
2
4
  import type { TaskWithFields } from "@/hooks/use-tasks";
3
5
  import {
@@ -34,11 +36,12 @@ export function TaskListHeaderRow({
34
36
  }: {
35
37
  task: TaskWithFields | undefined;
36
38
  }) {
39
+ const t = useT();
37
40
  return (
38
41
  <div className="hidden items-center gap-3 px-3 mb-2 text-xs font-medium text-muted-foreground md:flex">
39
42
  <div className="size-8 shrink-0" />
40
43
  <div className="size-4 shrink-0" />
41
- <div className="min-w-0 flex-1 px-3">Task</div>
44
+ <div className="min-w-0 flex-1 px-3">{t("tasks.taskColumnHeader")}</div>
42
45
  <TaskListFieldStripHeader fields={task?.fields} />
43
46
  <div className="size-8 shrink-0" />
44
47
  </div>
@@ -1,3 +1,4 @@
1
+ import { useT } from "@agent-native/core/client/i18n";
1
2
  import {
2
3
  INCLUDE_DONE_QUERY_VALUE,
3
4
  parseIncludeDoneParam,
@@ -11,6 +12,7 @@ import { TaskList } from "@/components/tasks/TaskList";
11
12
  import { useTasks } from "@/hooks/use-tasks";
12
13
 
13
14
  export function TaskListPage() {
15
+ const t = useT();
14
16
  const [searchParams, setSearchParams] = useSearchParams();
15
17
  const includeDone = parseIncludeDoneParam(searchParams.get("includeDone"));
16
18
  const activeTaskId = searchParams.get("task");
@@ -84,8 +86,8 @@ export function TaskListPage() {
84
86
  {isError ? (
85
87
  <>
86
88
  <ListViewHeader
87
- title="Tasks"
88
- description="Manage your task list, drag to reorder, or ask chat to add reminders."
89
+ title={t("tasks.pageTitle")}
90
+ description={t("tasks.pageDescription")}
89
91
  isPending={false}
90
92
  showSelectToggle={false}
91
93
  selection={null}
@@ -96,7 +98,7 @@ export function TaskListPage() {
96
98
  />
97
99
  <ListErrorMessage
98
100
  error={error}
99
- fallbackMessage="Failed to load tasks."
101
+ fallbackMessage={t("tasks.loadError")}
100
102
  />
101
103
  </>
102
104
  ) : (
@@ -1,3 +1,4 @@
1
+ import { useT } from "@agent-native/core/client/i18n";
1
2
  import { IconChecks, IconTrash } from "@tabler/icons-react";
2
3
  import { useState } from "react";
3
4
 
@@ -55,6 +56,7 @@ export function TaskListRow({
55
56
  onBeginExit,
56
57
  onExitAfterComplete,
57
58
  }: TaskListRowProps) {
59
+ const t = useT();
58
60
  const selected = selection.state.selectedItems.some(
59
61
  (entry) => entry.id === item.id,
60
62
  );
@@ -122,7 +124,11 @@ export function TaskListRow({
122
124
  onClick={
123
125
  rowSelection.selectionMode ? rowSelection.selectRow : undefined
124
126
  }
125
- aria-label={`Mark ${displayTitle} ${displayDone ? "incomplete" : "complete"}`}
127
+ aria-label={
128
+ displayDone
129
+ ? t("tasks.markIncompleteAriaLabel", { title: displayTitle })
130
+ : t("tasks.markCompleteAriaLabel", { title: displayTitle })
131
+ }
126
132
  />
127
133
 
128
134
  <div className="min-w-0 flex-1">
@@ -133,7 +139,7 @@ export function TaskListRow({
133
139
  value={item.title}
134
140
  onSave={onUpdateTitle}
135
141
  onDisplayTitleChange={setDisplayTitle}
136
- ariaLabel="Edit title"
142
+ ariaLabel={t("common.editTitleAriaLabel")}
137
143
  disabled={busy}
138
144
  titleDragProps={rowDrag.titleDragProps}
139
145
  displayDone={displayDone}
@@ -149,7 +155,9 @@ export function TaskListRow({
149
155
  </div>
150
156
 
151
157
  <RowActionsMenu
152
- ariaLabel={`Actions for ${displayTitle}`}
158
+ ariaLabel={t("common.rowActionsAriaLabel", {
159
+ title: displayTitle,
160
+ })}
153
161
  disabled={busy || rowSelection.selectionMode}
154
162
  >
155
163
  <DropdownMenuItem
@@ -157,14 +165,14 @@ export function TaskListRow({
157
165
  onSelect={() => selection.actions.startSelection(item.id)}
158
166
  >
159
167
  <IconChecks className="size-4" />
160
- Select
168
+ {t("selection.select")}
161
169
  </DropdownMenuItem>
162
170
  <DropdownMenuItem
163
171
  className="gap-2 text-destructive focus:bg-destructive focus:text-destructive-foreground"
164
172
  onSelect={onRequestDelete}
165
173
  >
166
174
  <IconTrash className="size-4" />
167
- Delete
175
+ {t("common.delete")}
168
176
  </DropdownMenuItem>
169
177
  </RowActionsMenu>
170
178
  </>
@@ -203,6 +211,7 @@ function TaskListRowFieldBadges({ fields }: { fields?: TaskFieldValue[] }) {
203
211
  }
204
212
 
205
213
  function TaskListRowFieldStrip({ fields }: { fields?: TaskFieldValue[] }) {
214
+ const t = useT();
206
215
  const { fieldIds } = useVisibleTaskFieldIds();
207
216
  const items = taskCardDisplayFields(fieldIds, fields);
208
217
  const columnCount = Math.min(fieldIds.length, TASK_CARD_FIELD_LIMIT);
@@ -213,7 +222,7 @@ function TaskListRowFieldStrip({ fields }: { fields?: TaskFieldValue[] }) {
213
222
  style={{
214
223
  gridTemplateColumns: `repeat(${columnCount}, minmax(6.5rem, 8rem))`,
215
224
  }}
216
- aria-label="Visible task fields"
225
+ aria-label={t("tasks.visibleTaskFieldsAriaLabel")}
217
226
  >
218
227
  {items.map((item) => (
219
228
  <div
@@ -1,3 +1,4 @@
1
+ import { useT } from "@agent-native/core/client/i18n";
1
2
  import { useCallback } from "react";
2
3
  import { toast } from "sonner";
3
4
 
@@ -16,13 +17,14 @@ export function TaskFieldsSidebar({
16
17
  task: TaskWithFields | null;
17
18
  onClose: () => void;
18
19
  }) {
20
+ const t = useT();
19
21
  if (!task) return null;
20
22
 
21
23
  return (
22
24
  <SidePanel
23
- title="Fields"
24
- subtitle="Task details"
25
- closeLabel="Close fields panel"
25
+ title={t("taskFields.panelTitle")}
26
+ subtitle={t("taskFields.panelSubtitle")}
27
+ closeLabel={t("taskFields.closeLabel")}
26
28
  onClose={onClose}
27
29
  >
28
30
  <TaskFieldsSidebarPanel task={task} />
@@ -31,6 +33,7 @@ export function TaskFieldsSidebar({
31
33
  }
32
34
 
33
35
  function TaskFieldsSidebarPanel({ task }: { task: TaskWithFields }) {
36
+ const t = useT();
34
37
  const fields = task.fields ?? [];
35
38
  const updateTask = useUpdateTask();
36
39
 
@@ -42,10 +45,12 @@ function TaskFieldsSidebarPanel({ task }: { task: TaskWithFields }) {
42
45
  void updateTask
43
46
  .mutateAsync({ taskId: task.id, ...payload })
44
47
  .catch((caught) => {
45
- toast.error((caught as Error)?.message ?? "Could not update task.");
48
+ toast.error(
49
+ (caught as Error)?.message ?? t("taskFields.updateError"),
50
+ );
46
51
  });
47
52
  },
48
- [task.id, updateTask],
53
+ [task.id, updateTask, t],
49
54
  );
50
55
 
51
56
  return (
@@ -57,7 +62,7 @@ function TaskFieldsSidebarPanel({ task }: { task: TaskWithFields }) {
57
62
 
58
63
  {fields.length === 0 ? (
59
64
  <div className="m-3 rounded-lg border border-dashed border-border p-6 text-center text-[13px] text-muted-foreground">
60
- No fields defined.
65
+ {t("taskFields.noFieldsDefined")}
61
66
  </div>
62
67
  ) : (
63
68
  fields.map((field) => (
@@ -1,3 +1,5 @@
1
+ import { useT } from "@agent-native/core/client/i18n";
2
+
1
3
  import { Input } from "@/components/ui/input";
2
4
  import { Label } from "@/components/ui/label";
3
5
 
@@ -8,18 +10,21 @@ export function TaskTitleSection({
8
10
  title: string;
9
11
  onChange: (title: string) => void;
10
12
  }) {
13
+ const t = useT();
11
14
  return (
12
15
  <section className="grid gap-2 border-b border-border/70 px-3 py-3">
13
16
  <div className="flex min-w-0 items-center justify-between gap-2">
14
17
  <Label className="min-w-0 truncate text-[13px] font-medium">
15
- Title
18
+ {t("taskFields.titleLabel")}
16
19
  </Label>
17
- <span className="shrink-0 text-[11px] text-muted-foreground">Task</span>
20
+ <span className="shrink-0 text-[11px] text-muted-foreground">
21
+ {t("taskFields.taskBadge")}
22
+ </span>
18
23
  </div>
19
24
  <Input
20
25
  value={title}
21
26
  onChange={(event) => onChange(event.currentTarget.value)}
22
- aria-label="Edit task title"
27
+ aria-label={t("taskFields.editTaskTitleAriaLabel")}
23
28
  className="h-9 text-[13px]"
24
29
  />
25
30
  </section>