@agent-native/core 0.76.9 → 0.76.11

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 (137) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +39 -0
  3. package/corpus/core/docs/content/locales/ar-SA/actions.md +7 -7
  4. package/corpus/core/docs/content/locales/ar-SA/template-plan.md +6 -4
  5. package/corpus/core/docs/content/locales/de-DE/actions.md +9 -9
  6. package/corpus/core/docs/content/locales/de-DE/template-plan.md +6 -4
  7. package/corpus/core/docs/content/locales/es-ES/actions.md +9 -9
  8. package/corpus/core/docs/content/locales/es-ES/template-plan.md +6 -4
  9. package/corpus/core/docs/content/locales/fr-FR/actions.md +9 -9
  10. package/corpus/core/docs/content/locales/fr-FR/template-plan.md +6 -4
  11. package/corpus/core/docs/content/locales/hi-IN/actions.md +9 -9
  12. package/corpus/core/docs/content/locales/hi-IN/template-plan.md +4 -4
  13. package/corpus/core/docs/content/locales/ja-JP/actions.md +9 -9
  14. package/corpus/core/docs/content/locales/ja-JP/template-plan.md +4 -4
  15. package/corpus/core/docs/content/locales/ko-KR/actions.md +9 -9
  16. package/corpus/core/docs/content/locales/ko-KR/template-plan.md +4 -4
  17. package/corpus/core/docs/content/locales/pt-BR/actions.md +9 -9
  18. package/corpus/core/docs/content/locales/pt-BR/template-plan.md +6 -4
  19. package/corpus/core/docs/content/locales/zh-CN/actions.md +9 -9
  20. package/corpus/core/docs/content/locales/zh-CN/template-plan.md +4 -4
  21. package/corpus/core/package.json +1 -1
  22. package/corpus/core/scripts/generate-og-font-data.mjs +9 -5
  23. package/corpus/core/src/client/AgentPanel.tsx +70 -1
  24. package/corpus/core/src/client/AssistantChat.tsx +1 -3
  25. package/corpus/core/src/client/ErrorBoundary.tsx +151 -10
  26. package/corpus/core/src/client/MultiTabAssistantChat.tsx +0 -62
  27. package/corpus/core/src/client/composer/TiptapComposer.tsx +6 -13
  28. package/corpus/core/src/server/og-fonts-data.ts +7 -4
  29. package/corpus/core/src/server/og-fonts.ts +10 -3
  30. package/corpus/core/src/server/social-og-image.ts +45 -6
  31. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +199 -19
  32. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +51 -31
  33. package/corpus/templates/analytics/app/components/layout/DashboardHeader.tsx +26 -16
  34. package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -2
  35. package/corpus/templates/analytics/app/components/layout/HeaderActions.tsx +8 -1
  36. package/corpus/templates/analytics/app/components/layout/Layout.tsx +2 -5
  37. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +172 -107
  38. package/corpus/templates/analytics/app/i18n-data.ts +1076 -5
  39. package/corpus/templates/analytics/app/pages/Settings.tsx +2 -2
  40. package/corpus/templates/analytics/app/pages/adhoc/AdhocRouter.tsx +1 -21
  41. package/corpus/templates/analytics/app/pages/adhoc/DashboardSkeleton.tsx +35 -0
  42. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +3 -23
  43. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +3 -26
  44. package/corpus/templates/analytics/changelog/2026-06-24-analytics-navigation-command-palette-and-settings-now-honor-.md +6 -0
  45. package/corpus/templates/analytics/changelog/2026-06-24-daily-dashboard-charts-now-use-local-day-buckets-and-show-th.md +6 -0
  46. package/corpus/templates/analytics/changelog/2026-06-24-dashboard-loading-placeholders-now-span-the-available-page-w.md +6 -0
  47. package/corpus/templates/analytics/changelog/2026-06-24-first-party-dashboard-dates-now-align-to-pacific-time-for-da.md +6 -0
  48. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +19 -7
  49. package/corpus/templates/assets/app/components/layout/Header.tsx +0 -2
  50. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +0 -2
  51. package/corpus/templates/calendar/app/pages/CalendarView.tsx +0 -2
  52. package/corpus/templates/chat/app/components/layout/Header.tsx +1 -6
  53. package/corpus/templates/clips/app/components/layout/Header.tsx +1 -6
  54. package/corpus/templates/clips/app/hooks/use-library.ts +2 -0
  55. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +3 -1
  56. package/corpus/templates/clips/changelog/2026-06-24-archive-and-spaces-navigation-is-more-resilient-when-sidebar.md +6 -0
  57. package/corpus/templates/content/app/components/layout/Header.tsx +0 -2
  58. package/corpus/templates/design/app/components/layout/Header.tsx +1 -6
  59. package/corpus/templates/forms/app/components/layout/Header.tsx +1 -6
  60. package/corpus/templates/macros/app/components/layout/Header.tsx +1 -6
  61. package/corpus/templates/mail/app/components/email/CodeBlockLangPicker.tsx +4 -2
  62. package/corpus/templates/mail/app/components/email/ComposeBubbleToolbar.tsx +18 -12
  63. package/corpus/templates/mail/app/components/email/ComposeEditor.tsx +9 -5
  64. package/corpus/templates/mail/app/components/email/ComposeModal.tsx +36 -19
  65. package/corpus/templates/mail/app/components/email/EmailList.tsx +59 -55
  66. package/corpus/templates/mail/app/components/email/EmailListItem.tsx +7 -3
  67. package/corpus/templates/mail/app/components/email/EmailThread.tsx +25 -16
  68. package/corpus/templates/mail/app/components/email/InlineReplyComposer.tsx +25 -19
  69. package/corpus/templates/mail/app/components/email/IntegrationsSidebar.tsx +32 -17
  70. package/corpus/templates/mail/app/components/email/RecipientInput.tsx +26 -10
  71. package/corpus/templates/mail/app/components/email/SendLaterButton.tsx +5 -3
  72. package/corpus/templates/mail/app/components/email/SnoozeModal.tsx +4 -2
  73. package/corpus/templates/mail/app/components/email/SnoozePopover.tsx +9 -5
  74. package/corpus/templates/mail/app/components/email/extensions/ComposeImageBlock.tsx +4 -2
  75. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +168 -86
  76. package/corpus/templates/mail/app/components/layout/SearchBar.tsx +4 -2
  77. package/corpus/templates/mail/app/i18n/ar-SA.ts +212 -0
  78. package/corpus/templates/mail/app/i18n/de-DE.ts +212 -0
  79. package/corpus/templates/mail/app/i18n/en-US.ts +212 -0
  80. package/corpus/templates/mail/app/i18n/es-ES.ts +212 -0
  81. package/corpus/templates/mail/app/i18n/fr-FR.ts +212 -0
  82. package/corpus/templates/mail/app/i18n/hi-IN.ts +212 -0
  83. package/corpus/templates/mail/app/i18n/ja-JP.ts +212 -0
  84. package/corpus/templates/mail/app/i18n/ko-KR.ts +212 -0
  85. package/corpus/templates/mail/app/i18n/pt-BR.ts +212 -0
  86. package/corpus/templates/mail/app/i18n/zh-CN.ts +211 -0
  87. package/corpus/templates/mail/changelog/2026-06-24-interface-language-support-now-covers-more-mail-controls-and.md +6 -0
  88. package/corpus/templates/plan/app/components/layout/Header.tsx +1 -6
  89. package/corpus/templates/slides/app/components/layout/Header.tsx +1 -6
  90. package/corpus/templates/videos/app/components/layout/Header.tsx +1 -6
  91. package/dist/client/AgentPanel.d.ts +5 -1
  92. package/dist/client/AgentPanel.d.ts.map +1 -1
  93. package/dist/client/AgentPanel.js +23 -4
  94. package/dist/client/AgentPanel.js.map +1 -1
  95. package/dist/client/AssistantChat.d.ts +1 -3
  96. package/dist/client/AssistantChat.d.ts.map +1 -1
  97. package/dist/client/AssistantChat.js.map +1 -1
  98. package/dist/client/ErrorBoundary.d.ts.map +1 -1
  99. package/dist/client/ErrorBoundary.js +128 -7
  100. package/dist/client/ErrorBoundary.js.map +1 -1
  101. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  102. package/dist/client/MultiTabAssistantChat.js +1 -17
  103. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  104. package/dist/client/composer/TiptapComposer.d.ts +4 -0
  105. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  106. package/dist/client/composer/TiptapComposer.js +5 -9
  107. package/dist/client/composer/TiptapComposer.js.map +1 -1
  108. package/dist/server/og-fonts-data.d.ts +1 -0
  109. package/dist/server/og-fonts-data.d.ts.map +1 -1
  110. package/dist/server/og-fonts-data.js +5 -4
  111. package/dist/server/og-fonts-data.js.map +1 -1
  112. package/dist/server/og-fonts.d.ts +1 -0
  113. package/dist/server/og-fonts.d.ts.map +1 -1
  114. package/dist/server/og-fonts.js +10 -4
  115. package/dist/server/og-fonts.js.map +1 -1
  116. package/dist/server/social-og-image.d.ts.map +1 -1
  117. package/dist/server/social-og-image.js +33 -6
  118. package/dist/server/social-og-image.js.map +1 -1
  119. package/docs/content/locales/ar-SA/actions.md +7 -7
  120. package/docs/content/locales/ar-SA/template-plan.md +6 -4
  121. package/docs/content/locales/de-DE/actions.md +9 -9
  122. package/docs/content/locales/de-DE/template-plan.md +6 -4
  123. package/docs/content/locales/es-ES/actions.md +9 -9
  124. package/docs/content/locales/es-ES/template-plan.md +6 -4
  125. package/docs/content/locales/fr-FR/actions.md +9 -9
  126. package/docs/content/locales/fr-FR/template-plan.md +6 -4
  127. package/docs/content/locales/hi-IN/actions.md +9 -9
  128. package/docs/content/locales/hi-IN/template-plan.md +4 -4
  129. package/docs/content/locales/ja-JP/actions.md +9 -9
  130. package/docs/content/locales/ja-JP/template-plan.md +4 -4
  131. package/docs/content/locales/ko-KR/actions.md +9 -9
  132. package/docs/content/locales/ko-KR/template-plan.md +4 -4
  133. package/docs/content/locales/pt-BR/actions.md +9 -9
  134. package/docs/content/locales/pt-BR/template-plan.md +6 -4
  135. package/docs/content/locales/zh-CN/actions.md +9 -9
  136. package/docs/content/locales/zh-CN/template-plan.md +4 -4
  137. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ErrorBoundary.d.ts","sourceRoot":"","sources":["../../src/client/ErrorBoundary.tsx"],"names":[],"mappings":"AAmJA,wBAAgB,aAAa,4CAI5B"}
1
+ {"version":3,"file":"ErrorBoundary.d.ts","sourceRoot":"","sources":["../../src/client/ErrorBoundary.tsx"],"names":[],"mappings":"AAgSA,wBAAgB,aAAa,4CAI5B"}
@@ -3,7 +3,126 @@ import { useEffect, useState } from "react";
3
3
  import { isRouteErrorResponse, useInRouterContext, useRouteError, } from "react-router";
4
4
  import { appPath } from "./api-path.js";
5
5
  import { isDynamicImportFailureMessage, recoverFromStaleChunkError, } from "./route-chunk-recovery.js";
6
+ import { DEFAULT_LOCALE, LOCALE_HYDRATION_GLOBAL, LOCALE_STORAGE_KEY, normalizeLocaleCode, } from "../localization/shared.js";
6
7
  const homeLinkClassName = "mt-6 inline-flex items-center gap-1.5 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm hover:bg-primary/90 cursor-pointer";
8
+ const errorCopy = {
9
+ "en-US": {
10
+ loadingLatest: "Loading the latest version...",
11
+ genericTitle: "Something went wrong",
12
+ genericDetails: "An unexpected error occurred.",
13
+ notFoundTitle: "Page not found",
14
+ notFoundDetails: "We couldn't find this page.",
15
+ statusTitle: (status) => `${status} Error`,
16
+ goHome: "Go home",
17
+ reload: "Reload",
18
+ },
19
+ "zh-CN": {
20
+ loadingLatest: "正在加载最新版本...",
21
+ genericTitle: "出错了",
22
+ genericDetails: "发生了意外错误。",
23
+ notFoundTitle: "页面未找到",
24
+ notFoundDetails: "我们找不到这个页面。",
25
+ statusTitle: (status) => `${status} 错误`,
26
+ goHome: "回到首页",
27
+ reload: "重新加载",
28
+ },
29
+ "es-ES": {
30
+ loadingLatest: "Cargando la versión más reciente...",
31
+ genericTitle: "Algo salió mal",
32
+ genericDetails: "Se produjo un error inesperado.",
33
+ notFoundTitle: "Página no encontrada",
34
+ notFoundDetails: "No pudimos encontrar esta página.",
35
+ statusTitle: (status) => `Error ${status}`,
36
+ goHome: "Ir al inicio",
37
+ reload: "Recargar",
38
+ },
39
+ "fr-FR": {
40
+ loadingLatest: "Chargement de la dernière version...",
41
+ genericTitle: "Un problème est survenu",
42
+ genericDetails: "Une erreur inattendue s'est produite.",
43
+ notFoundTitle: "Page introuvable",
44
+ notFoundDetails: "Nous n'avons pas trouvé cette page.",
45
+ statusTitle: (status) => `Erreur ${status}`,
46
+ goHome: "Accueil",
47
+ reload: "Recharger",
48
+ },
49
+ "de-DE": {
50
+ loadingLatest: "Neueste Version wird geladen...",
51
+ genericTitle: "Etwas ist schiefgelaufen",
52
+ genericDetails: "Ein unerwarteter Fehler ist aufgetreten.",
53
+ notFoundTitle: "Seite nicht gefunden",
54
+ notFoundDetails: "Wir konnten diese Seite nicht finden.",
55
+ statusTitle: (status) => `Fehler ${status}`,
56
+ goHome: "Zur Startseite",
57
+ reload: "Neu laden",
58
+ },
59
+ "ja-JP": {
60
+ loadingLatest: "最新バージョンを読み込み中...",
61
+ genericTitle: "問題が発生しました",
62
+ genericDetails: "予期しないエラーが発生しました。",
63
+ notFoundTitle: "ページが見つかりません",
64
+ notFoundDetails: "このページは見つかりませんでした。",
65
+ statusTitle: (status) => `${status} エラー`,
66
+ goHome: "ホームへ",
67
+ reload: "再読み込み",
68
+ },
69
+ "ko-KR": {
70
+ loadingLatest: "최신 버전을 불러오는 중...",
71
+ genericTitle: "문제가 발생했습니다",
72
+ genericDetails: "예기치 않은 오류가 발생했습니다.",
73
+ notFoundTitle: "페이지를 찾을 수 없음",
74
+ notFoundDetails: "이 페이지를 찾을 수 없습니다.",
75
+ statusTitle: (status) => `${status} 오류`,
76
+ goHome: "홈으로 이동",
77
+ reload: "새로고침",
78
+ },
79
+ "pt-BR": {
80
+ loadingLatest: "Carregando a versão mais recente...",
81
+ genericTitle: "Algo deu errado",
82
+ genericDetails: "Ocorreu um erro inesperado.",
83
+ notFoundTitle: "Página não encontrada",
84
+ notFoundDetails: "Não encontramos esta página.",
85
+ statusTitle: (status) => `Erro ${status}`,
86
+ goHome: "Ir para início",
87
+ reload: "Recarregar",
88
+ },
89
+ "hi-IN": {
90
+ loadingLatest: "नवीनतम संस्करण लोड हो रहा है...",
91
+ genericTitle: "कुछ गलत हो गया",
92
+ genericDetails: "एक अनपेक्षित त्रुटि हुई।",
93
+ notFoundTitle: "पेज नहीं मिला",
94
+ notFoundDetails: "हमें यह पेज नहीं मिला।",
95
+ statusTitle: (status) => `${status} त्रुटि`,
96
+ goHome: "होम पर जाएं",
97
+ reload: "रीलोड करें",
98
+ },
99
+ "ar-SA": {
100
+ loadingLatest: "جار تحميل أحدث إصدار...",
101
+ genericTitle: "حدث خطأ ما",
102
+ genericDetails: "حدث خطأ غير متوقع.",
103
+ notFoundTitle: "الصفحة غير موجودة",
104
+ notFoundDetails: "تعذر العثور على هذه الصفحة.",
105
+ statusTitle: (status) => `خطأ ${status}`,
106
+ goHome: "العودة للرئيسية",
107
+ reload: "إعادة التحميل",
108
+ },
109
+ };
110
+ function readErrorLocale() {
111
+ if (typeof window === "undefined")
112
+ return DEFAULT_LOCALE;
113
+ const hydrated = window[LOCALE_HYDRATION_GLOBAL]?.locale;
114
+ const stored = window.localStorage?.getItem(LOCALE_STORAGE_KEY);
115
+ return (normalizeLocaleCode(hydrated) ??
116
+ normalizeLocaleCode(stored) ??
117
+ DEFAULT_LOCALE);
118
+ }
119
+ function useErrorCopy() {
120
+ const [locale, setLocale] = useState(readErrorLocale);
121
+ useEffect(() => {
122
+ setLocale(readErrorLocale());
123
+ }, []);
124
+ return errorCopy[locale] ?? errorCopy[DEFAULT_LOCALE];
125
+ }
7
126
  function useApplyThemeClass() {
8
127
  useEffect(() => {
9
128
  const root = document.documentElement;
@@ -48,9 +167,11 @@ function useStaleChunkRecovery(error) {
48
167
  return recovering;
49
168
  }
50
169
  function UpdatingScreen() {
51
- return (_jsx("main", { className: "flex items-center justify-center min-h-screen p-4 bg-background text-foreground", children: _jsx("p", { className: "text-muted-foreground text-sm", children: "Loading the latest version\u2026" }) }));
170
+ const copy = useErrorCopy();
171
+ return (_jsx("main", { className: "flex items-center justify-center min-h-screen p-4 bg-background text-foreground", children: _jsx("p", { className: "text-muted-foreground text-sm", children: copy.loadingLatest }) }));
52
172
  }
53
173
  function ErrorScreen({ error }) {
174
+ const copy = useErrorCopy();
54
175
  const recovering = useStaleChunkRecovery(error);
55
176
  // While auto-recovering a stale chunk, show a neutral state and skip the
56
177
  // console.error below so the transient, self-healing failure does not get
@@ -58,17 +179,17 @@ function ErrorScreen({ error }) {
58
179
  if (recovering)
59
180
  return _jsx(UpdatingScreen, {});
60
181
  let status = null;
61
- let title = "Something went wrong";
62
- let details = "An unexpected error occurred.";
182
+ let title = copy.genericTitle;
183
+ let details = copy.genericDetails;
63
184
  let stack;
64
185
  if (isRouteErrorResponse(error)) {
65
186
  status = error.status;
66
187
  if (error.status === 404) {
67
- title = "Page not found";
68
- details = "We couldn't find this page.";
188
+ title = copy.notFoundTitle;
189
+ details = copy.notFoundDetails;
69
190
  }
70
191
  else {
71
- title = `${error.status} Error`;
192
+ title = copy.statusTitle(error.status);
72
193
  details = error.statusText || details;
73
194
  }
74
195
  }
@@ -93,7 +214,7 @@ function ErrorScreen({ error }) {
93
214
  if (typeof console !== "undefined" && error) {
94
215
  console.error("[ErrorBoundary]", error);
95
216
  }
96
- return (_jsx("main", { className: "flex items-center justify-center min-h-screen p-4 bg-background text-foreground", children: _jsxs("div", { className: "flex flex-col items-center text-center max-w-md", children: [status && (_jsx("span", { className: "text-7xl font-bold tracking-tight text-muted-foreground/40", children: status })), _jsx("h1", { className: "mt-3 text-2xl font-semibold", children: title }), _jsx("p", { className: "mt-2 text-muted-foreground text-sm", children: details }), _jsx("a", { href: appPath("/"), className: homeLinkClassName, children: "Go home" }), _jsx("button", { type: "button", onClick: () => window.location.reload(), className: "mt-3 inline-flex cursor-pointer items-center gap-1.5 rounded-md border border-border bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm hover:bg-accent", children: "Reload" }), stack && (_jsx("pre", { className: "mt-6 w-full text-start text-xs overflow-auto p-4 bg-muted rounded", children: _jsx("code", { children: stack }) }))] }) }));
217
+ return (_jsx("main", { className: "flex items-center justify-center min-h-screen p-4 bg-background text-foreground", children: _jsxs("div", { className: "flex flex-col items-center text-center max-w-md", children: [status && (_jsx("span", { className: "text-7xl font-bold tracking-tight text-muted-foreground/40", children: status })), _jsx("h1", { className: "mt-3 text-2xl font-semibold", children: title }), _jsx("p", { className: "mt-2 text-muted-foreground text-sm", children: details }), _jsx("a", { href: appPath("/"), className: homeLinkClassName, children: copy.goHome }), _jsx("button", { type: "button", onClick: () => window.location.reload(), className: "mt-3 inline-flex cursor-pointer items-center gap-1.5 rounded-md border border-border bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm hover:bg-accent", children: copy.reload }), stack && (_jsx("pre", { className: "mt-6 w-full text-start text-xs overflow-auto p-4 bg-muted rounded", children: _jsx("code", { children: stack }) }))] }) }));
97
218
  }
98
219
  function RoutedErrorScreen() {
99
220
  return _jsx(ErrorScreen, { error: useRouteError() });
@@ -1 +1 @@
1
- {"version":3,"file":"ErrorBoundary.js","sourceRoot":"","sources":["../../src/client/ErrorBoundary.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useState } from \"react\";\nimport {\n isRouteErrorResponse,\n useInRouterContext,\n useRouteError,\n} from \"react-router\";\nimport { appPath } from \"./api-path.js\";\nimport {\n isDynamicImportFailureMessage,\n recoverFromStaleChunkError,\n} from \"./route-chunk-recovery.js\";\n\nconst homeLinkClassName =\n \"mt-6 inline-flex items-center gap-1.5 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm hover:bg-primary/90 cursor-pointer\";\n\nfunction useApplyThemeClass() {\n useEffect(() => {\n const root = document.documentElement;\n if (root.classList.contains(\"dark\") || root.classList.contains(\"light\"))\n return;\n try {\n const stored = localStorage.getItem(\"theme\");\n if (stored === \"dark\") {\n root.classList.add(\"dark\");\n } else if (stored === \"light\") {\n root.classList.add(\"light\");\n } else if (window.matchMedia(\"(prefers-color-scheme: dark)\").matches) {\n root.classList.add(\"dark\");\n }\n } catch {}\n }, []);\n}\n\nfunction errorMessageOf(error: unknown): string {\n if (error instanceof Error) return error.message;\n return typeof error === \"string\" ? error : \"\";\n}\n\n/**\n * When a route renders against a stale lazy chunk after a deploy (the chunk's\n * hashed filename no longer exists), the import rejection surfaces here. Reload\n * once to fetch fresh assets instead of stranding the user on an error screen.\n * The reload is loop-guarded; if it cannot recover, fall back to the screen.\n */\nfunction useStaleChunkRecovery(error: unknown): boolean {\n const [recovering, setRecovering] = useState(() =>\n isDynamicImportFailureMessage(errorMessageOf(error)),\n );\n useEffect(() => {\n if (!isDynamicImportFailureMessage(errorMessageOf(error))) {\n setRecovering(false);\n return;\n }\n if (!recoverFromStaleChunkError(error)) setRecovering(false);\n }, [error]);\n return recovering;\n}\n\nfunction UpdatingScreen() {\n return (\n <main className=\"flex items-center justify-center min-h-screen p-4 bg-background text-foreground\">\n <p className=\"text-muted-foreground text-sm\">\n Loading the latest version…\n </p>\n </main>\n );\n}\n\nfunction ErrorScreen({ error }: { error: unknown }) {\n const recovering = useStaleChunkRecovery(error);\n // While auto-recovering a stale chunk, show a neutral state and skip the\n // console.error below so the transient, self-healing failure does not get\n // reported as a hard error.\n if (recovering) return <UpdatingScreen />;\n\n let status: number | null = null;\n let title = \"Something went wrong\";\n let details = \"An unexpected error occurred.\";\n let stack: string | undefined;\n\n if (isRouteErrorResponse(error)) {\n status = error.status;\n if (error.status === 404) {\n title = \"Page not found\";\n details = \"We couldn't find this page.\";\n } else {\n title = `${error.status} Error`;\n details = error.statusText || details;\n }\n } else if (error instanceof Error) {\n // Always surface the underlying error message — a generic\n // \"An unexpected error occurred.\" in production tells users (and us)\n // nothing. The stack trace is still gated to dev so we don't leak\n // internals to end users.\n if (error.message) {\n details = error.message;\n }\n if (\n typeof process !== \"undefined\" &&\n process.env.NODE_ENV !== \"production\"\n ) {\n stack = error.stack;\n }\n } else if (typeof error === \"string\" && error) {\n details = error;\n }\n\n // Log to the console so the underlying failure is recoverable from\n // browser devtools / Sentry even when the UI hides the stack.\n if (typeof console !== \"undefined\" && error) {\n console.error(\"[ErrorBoundary]\", error);\n }\n\n return (\n <main className=\"flex items-center justify-center min-h-screen p-4 bg-background text-foreground\">\n <div className=\"flex flex-col items-center text-center max-w-md\">\n {status && (\n <span className=\"text-7xl font-bold tracking-tight text-muted-foreground/40\">\n {status}\n </span>\n )}\n <h1 className=\"mt-3 text-2xl font-semibold\">{title}</h1>\n <p className=\"mt-2 text-muted-foreground text-sm\">{details}</p>\n <a href={appPath(\"/\")} className={homeLinkClassName}>\n Go home\n </a>\n <button\n type=\"button\"\n onClick={() => window.location.reload()}\n className=\"mt-3 inline-flex cursor-pointer items-center gap-1.5 rounded-md border border-border bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm hover:bg-accent\"\n >\n Reload\n </button>\n {stack && (\n <pre className=\"mt-6 w-full text-start text-xs overflow-auto p-4 bg-muted rounded\">\n <code>{stack}</code>\n </pre>\n )}\n </div>\n </main>\n );\n}\n\nfunction RoutedErrorScreen() {\n return <ErrorScreen error={useRouteError()} />;\n}\n\nexport function ErrorBoundary() {\n useApplyThemeClass();\n if (!useInRouterContext()) return <ErrorScreen error={undefined} />;\n return <RoutedErrorScreen />;\n}\n"]}
1
+ {"version":3,"file":"ErrorBoundary.js","sourceRoot":"","sources":["../../src/client/ErrorBoundary.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useState } from \"react\";\nimport {\n isRouteErrorResponse,\n useInRouterContext,\n useRouteError,\n} from \"react-router\";\nimport { appPath } from \"./api-path.js\";\nimport {\n isDynamicImportFailureMessage,\n recoverFromStaleChunkError,\n} from \"./route-chunk-recovery.js\";\nimport {\n DEFAULT_LOCALE,\n LOCALE_HYDRATION_GLOBAL,\n LOCALE_STORAGE_KEY,\n normalizeLocaleCode,\n type LocaleCode,\n} from \"../localization/shared.js\";\n\nconst homeLinkClassName =\n \"mt-6 inline-flex items-center gap-1.5 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm hover:bg-primary/90 cursor-pointer\";\n\nconst errorCopy: Record<\n LocaleCode,\n {\n loadingLatest: string;\n genericTitle: string;\n genericDetails: string;\n notFoundTitle: string;\n notFoundDetails: string;\n statusTitle: (status: number) => string;\n goHome: string;\n reload: string;\n }\n> = {\n \"en-US\": {\n loadingLatest: \"Loading the latest version...\",\n genericTitle: \"Something went wrong\",\n genericDetails: \"An unexpected error occurred.\",\n notFoundTitle: \"Page not found\",\n notFoundDetails: \"We couldn't find this page.\",\n statusTitle: (status) => `${status} Error`,\n goHome: \"Go home\",\n reload: \"Reload\",\n },\n \"zh-CN\": {\n loadingLatest: \"正在加载最新版本...\",\n genericTitle: \"出错了\",\n genericDetails: \"发生了意外错误。\",\n notFoundTitle: \"页面未找到\",\n notFoundDetails: \"我们找不到这个页面。\",\n statusTitle: (status) => `${status} 错误`,\n goHome: \"回到首页\",\n reload: \"重新加载\",\n },\n \"es-ES\": {\n loadingLatest: \"Cargando la versión más reciente...\",\n genericTitle: \"Algo salió mal\",\n genericDetails: \"Se produjo un error inesperado.\",\n notFoundTitle: \"Página no encontrada\",\n notFoundDetails: \"No pudimos encontrar esta página.\",\n statusTitle: (status) => `Error ${status}`,\n goHome: \"Ir al inicio\",\n reload: \"Recargar\",\n },\n \"fr-FR\": {\n loadingLatest: \"Chargement de la dernière version...\",\n genericTitle: \"Un problème est survenu\",\n genericDetails: \"Une erreur inattendue s'est produite.\",\n notFoundTitle: \"Page introuvable\",\n notFoundDetails: \"Nous n'avons pas trouvé cette page.\",\n statusTitle: (status) => `Erreur ${status}`,\n goHome: \"Accueil\",\n reload: \"Recharger\",\n },\n \"de-DE\": {\n loadingLatest: \"Neueste Version wird geladen...\",\n genericTitle: \"Etwas ist schiefgelaufen\",\n genericDetails: \"Ein unerwarteter Fehler ist aufgetreten.\",\n notFoundTitle: \"Seite nicht gefunden\",\n notFoundDetails: \"Wir konnten diese Seite nicht finden.\",\n statusTitle: (status) => `Fehler ${status}`,\n goHome: \"Zur Startseite\",\n reload: \"Neu laden\",\n },\n \"ja-JP\": {\n loadingLatest: \"最新バージョンを読み込み中...\",\n genericTitle: \"問題が発生しました\",\n genericDetails: \"予期しないエラーが発生しました。\",\n notFoundTitle: \"ページが見つかりません\",\n notFoundDetails: \"このページは見つかりませんでした。\",\n statusTitle: (status) => `${status} エラー`,\n goHome: \"ホームへ\",\n reload: \"再読み込み\",\n },\n \"ko-KR\": {\n loadingLatest: \"최신 버전을 불러오는 중...\",\n genericTitle: \"문제가 발생했습니다\",\n genericDetails: \"예기치 않은 오류가 발생했습니다.\",\n notFoundTitle: \"페이지를 찾을 수 없음\",\n notFoundDetails: \"이 페이지를 찾을 수 없습니다.\",\n statusTitle: (status) => `${status} 오류`,\n goHome: \"홈으로 이동\",\n reload: \"새로고침\",\n },\n \"pt-BR\": {\n loadingLatest: \"Carregando a versão mais recente...\",\n genericTitle: \"Algo deu errado\",\n genericDetails: \"Ocorreu um erro inesperado.\",\n notFoundTitle: \"Página não encontrada\",\n notFoundDetails: \"Não encontramos esta página.\",\n statusTitle: (status) => `Erro ${status}`,\n goHome: \"Ir para início\",\n reload: \"Recarregar\",\n },\n \"hi-IN\": {\n loadingLatest: \"नवीनतम संस्करण लोड हो रहा है...\",\n genericTitle: \"कुछ गलत हो गया\",\n genericDetails: \"एक अनपेक्षित त्रुटि हुई।\",\n notFoundTitle: \"पेज नहीं मिला\",\n notFoundDetails: \"हमें यह पेज नहीं मिला।\",\n statusTitle: (status) => `${status} त्रुटि`,\n goHome: \"होम पर जाएं\",\n reload: \"रीलोड करें\",\n },\n \"ar-SA\": {\n loadingLatest: \"جار تحميل أحدث إصدار...\",\n genericTitle: \"حدث خطأ ما\",\n genericDetails: \"حدث خطأ غير متوقع.\",\n notFoundTitle: \"الصفحة غير موجودة\",\n notFoundDetails: \"تعذر العثور على هذه الصفحة.\",\n statusTitle: (status) => `خطأ ${status}`,\n goHome: \"العودة للرئيسية\",\n reload: \"إعادة التحميل\",\n },\n};\n\nfunction readErrorLocale(): LocaleCode {\n if (typeof window === \"undefined\") return DEFAULT_LOCALE;\n const hydrated = (window as any)[LOCALE_HYDRATION_GLOBAL]?.locale;\n const stored = window.localStorage?.getItem(LOCALE_STORAGE_KEY);\n return (\n normalizeLocaleCode(hydrated) ??\n normalizeLocaleCode(stored) ??\n DEFAULT_LOCALE\n );\n}\n\nfunction useErrorCopy() {\n const [locale, setLocale] = useState<LocaleCode>(readErrorLocale);\n useEffect(() => {\n setLocale(readErrorLocale());\n }, []);\n return errorCopy[locale] ?? errorCopy[DEFAULT_LOCALE];\n}\n\nfunction useApplyThemeClass() {\n useEffect(() => {\n const root = document.documentElement;\n if (root.classList.contains(\"dark\") || root.classList.contains(\"light\"))\n return;\n try {\n const stored = localStorage.getItem(\"theme\");\n if (stored === \"dark\") {\n root.classList.add(\"dark\");\n } else if (stored === \"light\") {\n root.classList.add(\"light\");\n } else if (window.matchMedia(\"(prefers-color-scheme: dark)\").matches) {\n root.classList.add(\"dark\");\n }\n } catch {}\n }, []);\n}\n\nfunction errorMessageOf(error: unknown): string {\n if (error instanceof Error) return error.message;\n return typeof error === \"string\" ? error : \"\";\n}\n\n/**\n * When a route renders against a stale lazy chunk after a deploy (the chunk's\n * hashed filename no longer exists), the import rejection surfaces here. Reload\n * once to fetch fresh assets instead of stranding the user on an error screen.\n * The reload is loop-guarded; if it cannot recover, fall back to the screen.\n */\nfunction useStaleChunkRecovery(error: unknown): boolean {\n const [recovering, setRecovering] = useState(() =>\n isDynamicImportFailureMessage(errorMessageOf(error)),\n );\n useEffect(() => {\n if (!isDynamicImportFailureMessage(errorMessageOf(error))) {\n setRecovering(false);\n return;\n }\n if (!recoverFromStaleChunkError(error)) setRecovering(false);\n }, [error]);\n return recovering;\n}\n\nfunction UpdatingScreen() {\n const copy = useErrorCopy();\n return (\n <main className=\"flex items-center justify-center min-h-screen p-4 bg-background text-foreground\">\n <p className=\"text-muted-foreground text-sm\">{copy.loadingLatest}</p>\n </main>\n );\n}\n\nfunction ErrorScreen({ error }: { error: unknown }) {\n const copy = useErrorCopy();\n const recovering = useStaleChunkRecovery(error);\n // While auto-recovering a stale chunk, show a neutral state and skip the\n // console.error below so the transient, self-healing failure does not get\n // reported as a hard error.\n if (recovering) return <UpdatingScreen />;\n\n let status: number | null = null;\n let title = copy.genericTitle;\n let details = copy.genericDetails;\n let stack: string | undefined;\n\n if (isRouteErrorResponse(error)) {\n status = error.status;\n if (error.status === 404) {\n title = copy.notFoundTitle;\n details = copy.notFoundDetails;\n } else {\n title = copy.statusTitle(error.status);\n details = error.statusText || details;\n }\n } else if (error instanceof Error) {\n // Always surface the underlying error message — a generic\n // \"An unexpected error occurred.\" in production tells users (and us)\n // nothing. The stack trace is still gated to dev so we don't leak\n // internals to end users.\n if (error.message) {\n details = error.message;\n }\n if (\n typeof process !== \"undefined\" &&\n process.env.NODE_ENV !== \"production\"\n ) {\n stack = error.stack;\n }\n } else if (typeof error === \"string\" && error) {\n details = error;\n }\n\n // Log to the console so the underlying failure is recoverable from\n // browser devtools / Sentry even when the UI hides the stack.\n if (typeof console !== \"undefined\" && error) {\n console.error(\"[ErrorBoundary]\", error);\n }\n\n return (\n <main className=\"flex items-center justify-center min-h-screen p-4 bg-background text-foreground\">\n <div className=\"flex flex-col items-center text-center max-w-md\">\n {status && (\n <span className=\"text-7xl font-bold tracking-tight text-muted-foreground/40\">\n {status}\n </span>\n )}\n <h1 className=\"mt-3 text-2xl font-semibold\">{title}</h1>\n <p className=\"mt-2 text-muted-foreground text-sm\">{details}</p>\n <a href={appPath(\"/\")} className={homeLinkClassName}>\n {copy.goHome}\n </a>\n <button\n type=\"button\"\n onClick={() => window.location.reload()}\n className=\"mt-3 inline-flex cursor-pointer items-center gap-1.5 rounded-md border border-border bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm hover:bg-accent\"\n >\n {copy.reload}\n </button>\n {stack && (\n <pre className=\"mt-6 w-full text-start text-xs overflow-auto p-4 bg-muted rounded\">\n <code>{stack}</code>\n </pre>\n )}\n </div>\n </main>\n );\n}\n\nfunction RoutedErrorScreen() {\n return <ErrorScreen error={useRouteError()} />;\n}\n\nexport function ErrorBoundary() {\n useApplyThemeClass();\n if (!useInRouterContext()) return <ErrorScreen error={undefined} />;\n return <RoutedErrorScreen />;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"MultiTabAssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/MultiTabAssistantChat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AAUf,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,oBAAoB,CAAC;AAe5B,OAAO,EAEL,KAAK,eAAe,EAErB,MAAM,uBAAuB,CAAC;AAqqB/B,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAAC;IACzC,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAsGD,MAAM,WAAW,wBAAwB;IACvC,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,8EAA8E;IAC9E,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,MAAM,CAAC;IAC9C,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;CACpE;AAyED,MAAM,WAAW,gCAAgC;IAC/C,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,+BAA+B;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAC3C,kBAAkB,EAClB,OAAO,GAAG,UAAU,CACrB,GAAG;IACF,sCAAsC;IACtC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iDAAiD;IACjD,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,gCAAgC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC5E,2DAA2D;IAC3D,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,gCAAgC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC7E,sGAAsG;IACtG,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,wBAAwB,CAAC;IACnD;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,EACpC,UAAiB,EACjB,YAAY,EACZ,aAAa,EACb,aAAqB,EACrB,MAAqD,EACrD,UAAU,EACV,mBAA0B,EAC1B,YAAY,EACZ,aAAqB,EACrB,KAAY,EACZ,GAAG,KAAK,EACT,EAAE,0BAA0B,2CA00D5B"}
1
+ {"version":3,"file":"MultiTabAssistantChat.d.ts","sourceRoot":"","sources":["../../src/client/MultiTabAssistantChat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AAUf,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,oBAAoB,CAAC;AAe5B,OAAO,EAEL,KAAK,eAAe,EAErB,MAAM,uBAAuB,CAAC;AAknB/B,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAAC;IACzC,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAsGD,MAAM,WAAW,wBAAwB;IACvC,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,8EAA8E;IAC9E,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,MAAM,CAAC;IAC9C,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;CACpE;AAyED,MAAM,WAAW,gCAAgC;IAC/C,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,+BAA+B;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAC3C,kBAAkB,EAClB,OAAO,GAAG,UAAU,CACrB,GAAG;IACF,sCAAsC;IACtC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iDAAiD;IACjD,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,gCAAgC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC5E,2DAA2D;IAC3D,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,gCAAgC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC7E,sGAAsG;IACtG,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,wBAAwB,CAAC;IACnD;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,EACpC,UAAiB,EACjB,YAAY,EACZ,aAAa,EACb,aAAqB,EACrB,MAAqD,EACrD,UAAU,EACV,mBAA0B,EAC1B,YAAY,EACZ,aAAqB,EACrB,KAAY,EACZ,GAAG,KAAK,EACT,EAAE,0BAA0B,2CA+zD5B"}
@@ -139,20 +139,6 @@ function ScopeBadge({ scope, currentScope, onDetach, otherScopedThreads, activeT
139
139
  onDetach();
140
140
  }, className: "flex w-full items-center gap-2 rounded px-2 py-1.5 text-xs text-foreground hover:bg-accent cursor-pointer", children: [_jsx(IconLinkOff, { size: 13 }), _jsx("span", { children: "Remove context" })] }) })] })] }) }));
141
141
  }
142
- /**
143
- * Empty-state addon shown when the user starts a fresh chat inside a
144
- * scoped surface that already has other threads. Surfaces those threads
145
- * inline so chats don't feel "lost" after the user navigates away and
146
- * back — the chip popover lists them too, but this nudge is visible
147
- * without any extra clicks.
148
- */
149
- function PreviousScopedChatsHint({ scope, threads, onSelectThread, }) {
150
- const MAX_INLINE = 3;
151
- const shown = threads.slice(0, MAX_INLINE);
152
- const remaining = threads.length - shown.length;
153
- const scopeLabel = scope.label || `this ${formatScopeType(scope.type)}`;
154
- return (_jsxs("div", { className: "flex w-full max-w-[280px] flex-col gap-1.5", children: [_jsxs("div", { className: "text-[10px] uppercase tracking-wider text-muted-foreground/70 text-center", children: ["Previous chats for ", scopeLabel] }), _jsx("div", { className: "flex flex-col gap-1", children: shown.map((thread) => (_jsxs("button", { type: "button", onClick: () => onSelectThread(thread.id), className: "flex items-baseline justify-between gap-2 rounded-md border border-border px-2.5 py-1.5 text-start hover:bg-accent cursor-pointer", children: [_jsx("span", { className: "truncate text-[12px] text-foreground", children: thread.title || thread.preview || "Chat" }), _jsx("span", { className: "shrink-0 text-[10px] text-muted-foreground", children: formatThreadTime(thread.updatedAt) })] }, thread.id))) }), remaining > 0 && (_jsxs("div", { className: "text-[10px] text-muted-foreground/70 text-center", children: ["+", remaining, " more"] }))] }));
155
- }
156
142
  /**
157
143
  * Thin confirmation banner shown briefly after detach. The chip itself
158
144
  * unmounts the moment scope clears on the active thread, so this banner
@@ -1796,9 +1782,7 @@ export function MultiTabAssistantChat({ showTabBar = true, renderHeader, renderO
1796
1782
  handle?.sendRecoveryMessage("Continue from where you left off and finish my last request. Do not repeat completed work.", "continue");
1797
1783
  } }), _jsx(AssistantChat, { ...props, dynamicSuggestions: tabDynamicSuggestions, emptyStateText: tabScope?.label && tabId === activeThreadId
1798
1784
  ? `Ask about ${tabScope.label}`
1799
- : props.emptyStateText, emptyStateAddon: tabId === activeThreadId &&
1800
- tabScope &&
1801
- otherScopedThreads.length > 0 ? (_jsx(PreviousScopedChatsHint, { scope: tabScope, threads: otherScopedThreads, onSelectThread: openFromHistory })) : undefined, ref: (handle) => {
1785
+ : props.emptyStateText, ref: (handle) => {
1802
1786
  if (handle) {
1803
1787
  chatRefs.current.set(tabId, handle);
1804
1788
  }