@agent-native/toolkit 0.216.0 → 0.218.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 (261) hide show
  1. package/agent-native.eject.json +26 -0
  2. package/dist/app/agent-page/AgentContextTab.d.ts.map +1 -1
  3. package/dist/app/agent-page/AgentContextTab.js +1 -0
  4. package/dist/app/agent-page/AgentContextTab.js.map +1 -1
  5. package/dist/app/agentkit/react/components.d.ts.map +1 -1
  6. package/dist/app/agentkit/react/components.js +1 -1
  7. package/dist/app/agentkit/react/components.js.map +1 -1
  8. package/dist/app/agentkit/react/context.d.ts +4 -1
  9. package/dist/app/agentkit/react/context.d.ts.map +1 -1
  10. package/dist/app/agentkit/react/context.js +3 -1
  11. package/dist/app/agentkit/react/context.js.map +1 -1
  12. package/dist/app/agentkit/react/data-chart-layout.d.ts +30 -0
  13. package/dist/app/agentkit/react/data-chart-layout.d.ts.map +1 -0
  14. package/dist/app/agentkit/react/data-chart-layout.js +2 -0
  15. package/dist/app/agentkit/react/data-chart-layout.js.map +1 -0
  16. package/dist/app/agentkit/react/index.d.ts +1 -0
  17. package/dist/app/agentkit/react/index.d.ts.map +1 -1
  18. package/dist/app/agentkit/react/index.js +1 -0
  19. package/dist/app/agentkit/react/index.js.map +1 -1
  20. package/dist/app/agentkit/react/root.d.ts +3 -1
  21. package/dist/app/agentkit/react/root.d.ts.map +1 -1
  22. package/dist/app/agentkit/react/root.js +2 -2
  23. package/dist/app/agentkit/react/root.js.map +1 -1
  24. package/dist/app/agentkit/react/styles.css +18 -0
  25. package/dist/app/agentkit/react/transcript-layout.d.ts +2 -0
  26. package/dist/app/agentkit/react/transcript-layout.d.ts.map +1 -1
  27. package/dist/app/agentkit/react/transcript-layout.js.map +1 -1
  28. package/dist/app/auth/AuthPage.d.ts.map +1 -1
  29. package/dist/app/auth/AuthPage.js +33 -44
  30. package/dist/app/auth/AuthPage.js.map +1 -1
  31. package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
  32. package/dist/app/chat/AgentKitAssistantChat.js +2 -2
  33. package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
  34. package/dist/app/chat/MultiTabAssistantChat.d.ts.map +1 -1
  35. package/dist/app/chat/MultiTabAssistantChat.js +51 -93
  36. package/dist/app/chat/MultiTabAssistantChat.js.map +1 -1
  37. package/dist/app/chat/agentkit-chat/action-widget.d.ts.map +1 -1
  38. package/dist/app/chat/agentkit-chat/action-widget.js +3 -1
  39. package/dist/app/chat/agentkit-chat/action-widget.js.map +1 -1
  40. package/dist/app/chat/agentkit-chat/rail.d.ts +1 -1
  41. package/dist/app/chat/agentkit-chat/rail.d.ts.map +1 -1
  42. package/dist/app/chat/agentkit-chat/rail.js +1 -1
  43. package/dist/app/chat/agentkit-chat/rail.js.map +1 -1
  44. package/dist/app/chat/chat/index.d.ts +2 -1
  45. package/dist/app/chat/chat/index.d.ts.map +1 -1
  46. package/dist/app/chat/chat/index.js +1 -1
  47. package/dist/app/chat/chat/index.js.map +1 -1
  48. package/dist/app/chat/chat/surface-types.d.ts +3 -0
  49. package/dist/app/chat/chat/surface-types.d.ts.map +1 -1
  50. package/dist/app/chat/chat/surface-types.js.map +1 -1
  51. package/dist/app/chat/chat/tool-call-display.d.ts +3 -1
  52. package/dist/app/chat/chat/tool-call-display.d.ts.map +1 -1
  53. package/dist/app/chat/chat/tool-call-display.js +4 -3
  54. package/dist/app/chat/chat/tool-call-display.js.map +1 -1
  55. package/dist/app/chat/chat/tool-render-registry.d.ts +2 -0
  56. package/dist/app/chat/chat/tool-render-registry.d.ts.map +1 -1
  57. package/dist/app/chat/chat/tool-render-registry.js.map +1 -1
  58. package/dist/app/chat/chat/widgets/DataChartRenderer.d.ts +3 -1
  59. package/dist/app/chat/chat/widgets/DataChartRenderer.d.ts.map +1 -1
  60. package/dist/app/chat/chat/widgets/DataChartRenderer.js +116 -26
  61. package/dist/app/chat/chat/widgets/DataChartRenderer.js.map +1 -1
  62. package/dist/app/chat/chat/widgets/DataChartWidget.d.ts +3 -1
  63. package/dist/app/chat/chat/widgets/DataChartWidget.d.ts.map +1 -1
  64. package/dist/app/chat/chat/widgets/DataChartWidget.js +21 -2
  65. package/dist/app/chat/chat/widgets/DataChartWidget.js.map +1 -1
  66. package/dist/app/chat/chat/widgets/DataInsightsWidget.d.ts +3 -1
  67. package/dist/app/chat/chat/widgets/DataInsightsWidget.d.ts.map +1 -1
  68. package/dist/app/chat/chat/widgets/DataInsightsWidget.js +2 -2
  69. package/dist/app/chat/chat/widgets/DataInsightsWidget.js.map +1 -1
  70. package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.d.ts +1 -1
  71. package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.d.ts.map +1 -1
  72. package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.js +3 -1
  73. package/dist/app/chat/chat/widgets/DataWidgetDisplayControls.js.map +1 -1
  74. package/dist/app/chat/chat/widgets/builtin-tool-renderers.d.ts.map +1 -1
  75. package/dist/app/chat/chat/widgets/builtin-tool-renderers.js +2 -2
  76. package/dist/app/chat/chat/widgets/builtin-tool-renderers.js.map +1 -1
  77. package/dist/app/chat/chat-first/chat-history.d.ts +13 -2
  78. package/dist/app/chat/chat-first/chat-history.d.ts.map +1 -1
  79. package/dist/app/chat/chat-first/chat-history.js +24 -3
  80. package/dist/app/chat/chat-first/chat-history.js.map +1 -1
  81. package/dist/app/chat/ownership-history/ChatOwnerAvatar.d.ts +6 -0
  82. package/dist/app/chat/ownership-history/ChatOwnerAvatar.d.ts.map +1 -0
  83. package/dist/app/chat/ownership-history/ChatOwnerAvatar.js +9 -0
  84. package/dist/app/chat/ownership-history/ChatOwnerAvatar.js.map +1 -0
  85. package/dist/app/chat/ownership-history/index.d.ts +11 -0
  86. package/dist/app/chat/ownership-history/index.d.ts.map +1 -0
  87. package/dist/app/chat/ownership-history/index.js +22 -0
  88. package/dist/app/chat/ownership-history/index.js.map +1 -0
  89. package/dist/app/chat/ownership-history/rows.d.ts +27 -0
  90. package/dist/app/chat/ownership-history/rows.d.ts.map +1 -0
  91. package/dist/app/chat/ownership-history/rows.js +101 -0
  92. package/dist/app/chat/ownership-history/rows.js.map +1 -0
  93. package/dist/app/chat/ownership-history/useOwnershipChatHistory.d.ts +52 -0
  94. package/dist/app/chat/ownership-history/useOwnershipChatHistory.d.ts.map +1 -0
  95. package/dist/app/chat/ownership-history/useOwnershipChatHistory.js +497 -0
  96. package/dist/app/chat/ownership-history/useOwnershipChatHistory.js.map +1 -0
  97. package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
  98. package/dist/app/i18n/catalogs/ar-SA.js +3 -0
  99. package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
  100. package/dist/app/i18n/catalogs/de-DE.d.ts.map +1 -1
  101. package/dist/app/i18n/catalogs/de-DE.js +3 -0
  102. package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
  103. package/dist/app/i18n/catalogs/en-US.d.ts +3 -0
  104. package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
  105. package/dist/app/i18n/catalogs/en-US.js +3 -0
  106. package/dist/app/i18n/catalogs/en-US.js.map +1 -1
  107. package/dist/app/i18n/catalogs/es-ES.d.ts.map +1 -1
  108. package/dist/app/i18n/catalogs/es-ES.js +3 -0
  109. package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
  110. package/dist/app/i18n/catalogs/fr-FR.d.ts.map +1 -1
  111. package/dist/app/i18n/catalogs/fr-FR.js +3 -0
  112. package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
  113. package/dist/app/i18n/catalogs/hi-IN.d.ts.map +1 -1
  114. package/dist/app/i18n/catalogs/hi-IN.js +3 -0
  115. package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
  116. package/dist/app/i18n/catalogs/ja-JP.d.ts.map +1 -1
  117. package/dist/app/i18n/catalogs/ja-JP.js +3 -0
  118. package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
  119. package/dist/app/i18n/catalogs/ko-KR.d.ts.map +1 -1
  120. package/dist/app/i18n/catalogs/ko-KR.js +3 -0
  121. package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
  122. package/dist/app/i18n/catalogs/pt-BR.d.ts.map +1 -1
  123. package/dist/app/i18n/catalogs/pt-BR.js +3 -0
  124. package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
  125. package/dist/app/i18n/catalogs/zh-CN.d.ts.map +1 -1
  126. package/dist/app/i18n/catalogs/zh-CN.js +3 -0
  127. package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
  128. package/dist/app/i18n/catalogs/zh-TW.d.ts.map +1 -1
  129. package/dist/app/i18n/catalogs/zh-TW.js +3 -0
  130. package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
  131. package/dist/app/onboarding/GettingStartedCard.d.ts +35 -0
  132. package/dist/app/onboarding/GettingStartedCard.d.ts.map +1 -0
  133. package/dist/app/onboarding/GettingStartedCard.js +38 -0
  134. package/dist/app/onboarding/GettingStartedCard.js.map +1 -0
  135. package/dist/app/onboarding/index.d.ts +1 -0
  136. package/dist/app/onboarding/index.d.ts.map +1 -1
  137. package/dist/app/onboarding/index.js +1 -0
  138. package/dist/app/onboarding/index.js.map +1 -1
  139. package/dist/app/providers/AppProviders.d.ts.map +1 -1
  140. package/dist/app/providers/AppProviders.js +3 -1
  141. package/dist/app/providers/AppProviders.js.map +1 -1
  142. package/dist/app/settings/AccountSettingsCard.d.ts.map +1 -1
  143. package/dist/app/settings/AccountSettingsCard.js +2 -1
  144. package/dist/app/settings/AccountSettingsCard.js.map +1 -1
  145. package/dist/app/settings/index.d.ts +1 -0
  146. package/dist/app/settings/index.d.ts.map +1 -1
  147. package/dist/app/settings/index.js +1 -0
  148. package/dist/app/settings/index.js.map +1 -1
  149. package/dist/app/settings/shell/SettingsShell.d.ts +40 -1
  150. package/dist/app/settings/shell/SettingsShell.d.ts.map +1 -1
  151. package/dist/app/settings/shell/SettingsShell.js +87 -20
  152. package/dist/app/settings/shell/SettingsShell.js.map +1 -1
  153. package/dist/app/settings/shell/bridge.d.ts +5 -3
  154. package/dist/app/settings/shell/bridge.d.ts.map +1 -1
  155. package/dist/app/settings/shell/bridge.js +8 -5
  156. package/dist/app/settings/shell/bridge.js.map +1 -1
  157. package/dist/app/settings/shell/index.d.ts +2 -2
  158. package/dist/app/settings/shell/index.d.ts.map +1 -1
  159. package/dist/app/settings/shell/index.js.map +1 -1
  160. package/dist/app/settings/shell/registry.d.ts +9 -1
  161. package/dist/app/settings/shell/registry.d.ts.map +1 -1
  162. package/dist/app/settings/shell/registry.js +16 -0
  163. package/dist/app/settings/shell/registry.js.map +1 -1
  164. package/dist/app/settings/shell/routing.d.ts +5 -4
  165. package/dist/app/settings/shell/routing.d.ts.map +1 -1
  166. package/dist/app/settings/shell/routing.js +38 -10
  167. package/dist/app/settings/shell/routing.js.map +1 -1
  168. package/dist/app/shared/CommandMenu.d.ts +86 -6
  169. package/dist/app/shared/CommandMenu.d.ts.map +1 -1
  170. package/dist/app/shared/CommandMenu.js +303 -41
  171. package/dist/app/shared/CommandMenu.js.map +1 -1
  172. package/dist/app/shared/ConsentBanner.d.ts +9 -0
  173. package/dist/app/shared/ConsentBanner.d.ts.map +1 -0
  174. package/dist/app/shared/ConsentBanner.js +35 -0
  175. package/dist/app/shared/ConsentBanner.js.map +1 -0
  176. package/dist/app/sharing/ShareButton.d.ts.map +1 -1
  177. package/dist/app/sharing/ShareButton.js +9 -8
  178. package/dist/app/sharing/ShareButton.js.map +1 -1
  179. package/dist/chat-history/ChatHistoryList.d.ts +16 -3
  180. package/dist/chat-history/ChatHistoryList.d.ts.map +1 -1
  181. package/dist/chat-history/ChatHistoryList.js +25 -15
  182. package/dist/chat-history/ChatHistoryList.js.map +1 -1
  183. package/dist/chat-history.css +109 -9
  184. package/dist/ui/sonner.d.ts +2 -2
  185. package/dist/ui/sonner.d.ts.map +1 -1
  186. package/dist/ui/sonner.js +2 -2
  187. package/dist/ui/sonner.js.map +1 -1
  188. package/package.json +10 -3
  189. package/src/app/agent-page/AgentContextTab.spec.ts +50 -2
  190. package/src/app/agent-page/AgentContextTab.tsx +1 -0
  191. package/src/app/agentkit/react/components.interaction.spec.tsx +2 -0
  192. package/src/app/agentkit/react/components.spec.tsx +4 -1
  193. package/src/app/agentkit/react/components.tsx +3 -0
  194. package/src/app/agentkit/react/context.tsx +6 -0
  195. package/src/app/agentkit/react/data-chart-layout.ts +25 -0
  196. package/src/app/agentkit/react/index.ts +1 -0
  197. package/src/app/agentkit/react/root.tsx +4 -0
  198. package/src/app/agentkit/react/styles.css +18 -0
  199. package/src/app/agentkit/react/transcript-layout.ts +2 -0
  200. package/src/app/auth/AuthPage.interaction.spec.tsx +74 -0
  201. package/src/app/auth/AuthPage.tsx +32 -39
  202. package/src/app/chat/AgentKitAssistantChat.tsx +2 -0
  203. package/src/app/chat/MultiTabAssistantChat.spec.tsx +270 -3
  204. package/src/app/chat/MultiTabAssistantChat.tsx +79 -156
  205. package/src/app/chat/agentkit-chat/action-widget.tsx +3 -0
  206. package/src/app/chat/agentkit-chat/rail.ts +11 -0
  207. package/src/app/chat/chat/index.ts +10 -0
  208. package/src/app/chat/chat/surface-types.ts +3 -0
  209. package/src/app/chat/chat/tool-call-display.spec.tsx +29 -0
  210. package/src/app/chat/chat/tool-call-display.tsx +7 -0
  211. package/src/app/chat/chat/tool-render-registry.tsx +3 -0
  212. package/src/app/chat/chat/widgets/DataChartRenderer.spec.tsx +377 -17
  213. package/src/app/chat/chat/widgets/DataChartRenderer.tsx +232 -63
  214. package/src/app/chat/chat/widgets/DataChartWidget.spec.tsx +67 -0
  215. package/src/app/chat/chat/widgets/DataChartWidget.tsx +39 -5
  216. package/src/app/chat/chat/widgets/DataInsightsWidget.tsx +13 -2
  217. package/src/app/chat/chat/widgets/DataWidgetDisplayControls.tsx +6 -4
  218. package/src/app/chat/chat/widgets/builtin-tool-renderers.tsx +5 -1
  219. package/src/app/chat/chat-first/chat-history.spec.tsx +79 -0
  220. package/src/app/chat/chat-first/chat-history.tsx +75 -22
  221. package/src/app/chat/ownership-history/ChatOwnerAvatar.tsx +27 -0
  222. package/src/app/chat/ownership-history/index.tsx +67 -0
  223. package/src/app/chat/ownership-history/ownership-history.spec.tsx +3146 -0
  224. package/src/app/chat/ownership-history/rows.ts +156 -0
  225. package/src/app/chat/ownership-history/useOwnershipChatHistory.ts +709 -0
  226. package/src/app/i18n/catalogs/ar-SA.ts +3 -0
  227. package/src/app/i18n/catalogs/de-DE.ts +3 -0
  228. package/src/app/i18n/catalogs/en-US.ts +3 -0
  229. package/src/app/i18n/catalogs/es-ES.ts +3 -0
  230. package/src/app/i18n/catalogs/fr-FR.ts +3 -0
  231. package/src/app/i18n/catalogs/hi-IN.ts +3 -0
  232. package/src/app/i18n/catalogs/ja-JP.ts +3 -0
  233. package/src/app/i18n/catalogs/ko-KR.ts +3 -0
  234. package/src/app/i18n/catalogs/pt-BR.ts +3 -0
  235. package/src/app/i18n/catalogs/zh-CN.ts +3 -0
  236. package/src/app/i18n/catalogs/zh-TW.ts +3 -0
  237. package/src/app/onboarding/GettingStartedCard.tsx +203 -0
  238. package/src/app/onboarding/index.ts +1 -0
  239. package/src/app/providers/AppProviders.tsx +7 -1
  240. package/src/app/settings/AccountSettingsCard.spec.tsx +31 -0
  241. package/src/app/settings/AccountSettingsCard.tsx +8 -0
  242. package/src/app/settings/index.ts +1 -0
  243. package/src/app/settings/shell/SettingsShell.spec.tsx +472 -1
  244. package/src/app/settings/shell/SettingsShell.tsx +245 -31
  245. package/src/app/settings/shell/bridge.spec.ts +12 -0
  246. package/src/app/settings/shell/bridge.ts +17 -4
  247. package/src/app/settings/shell/index.ts +6 -1
  248. package/src/app/settings/shell/registry.ts +33 -1
  249. package/src/app/settings/shell/routing.spec.ts +92 -1
  250. package/src/app/settings/shell/routing.ts +52 -9
  251. package/src/app/shared/CommandMenu.spec.tsx +1662 -1
  252. package/src/app/shared/CommandMenu.tsx +763 -164
  253. package/src/app/shared/ConsentBanner.spec.tsx +141 -0
  254. package/src/app/shared/ConsentBanner.tsx +141 -0
  255. package/src/app/sharing/ShareButton.tsx +12 -10
  256. package/src/chat-history/ChatHistoryList.spec.tsx +51 -0
  257. package/src/chat-history/ChatHistoryList.tsx +87 -26
  258. package/src/chat-history/ChatHistoryRailSections.spec.tsx +12 -4
  259. package/src/chat-history.css +109 -9
  260. package/src/ui/sonner.spec.ts +10 -0
  261. package/src/ui/sonner.tsx +2 -2
@@ -38,7 +38,15 @@ function resolve(
38
38
  rest: Partial<SettingsLocation> = {},
39
39
  pages: readonly SettingsPageDefinition[] = CORE_SETTINGS_PAGES,
40
40
  ) {
41
- return resolveSettingsRoute({ pathname, hash, ...rest }, pages);
41
+ return resolveSettingsRoute({ pathname, hash, ...rest }, pages, {
42
+ templateTabPageIds: new Map(
43
+ pages.flatMap((page) =>
44
+ page.group === "app"
45
+ ? (page.legacyTabIds ?? []).map((tabId) => [tabId, page.id] as const)
46
+ : [],
47
+ ),
48
+ ),
49
+ });
42
50
  }
43
51
 
44
52
  describe("settings shell routing", () => {
@@ -244,6 +252,27 @@ describe("legacy settings links", () => {
244
252
  "recordings",
245
253
  ]),
246
254
  ).toMatchObject({ page: "app", sub: "recordings" });
255
+ const collidingPages = [...CORE_SETTINGS_PAGES, appPage("alerts")];
256
+ expect(
257
+ resolveSettingsTabValue("alerts", collidingPages, ["alerts"]),
258
+ ).toMatchObject({ page: "alerts", sub: null, legacy: false });
259
+ expect(
260
+ resolveSettingsRoute(
261
+ { pathname: "/settings", hash: "" },
262
+ collidingPages,
263
+ {
264
+ appAreaIds: ["alerts"],
265
+ tabValue: "alerts",
266
+ },
267
+ ),
268
+ ).toMatchObject({ page: "alerts", sub: null, legacy: false });
269
+ expect(
270
+ resolveSettingsRoute(
271
+ { pathname: "/settings/alerts", hash: "" },
272
+ collidingPages,
273
+ { appAreaIds: ["alerts"] },
274
+ ),
275
+ ).toMatchObject({ page: "alerts", sub: null, legacy: false });
247
276
  // Today's tab path for an area (Analytics' Alerts tab).
248
277
  expect(
249
278
  resolveSettingsRoute(
@@ -267,6 +296,67 @@ describe("legacy settings links", () => {
267
296
  ).toMatchObject({ page: "usage", legacy: false });
268
297
  });
269
298
 
299
+ it("keeps app and derived template pages addressable when ids collide", () => {
300
+ const pages = [
301
+ ...CORE_SETTINGS_PAGES,
302
+ appPage("app-drafting", "drafting"),
303
+ appPage("drafting"),
304
+ ];
305
+ expect(
306
+ resolveSettingsRoute(
307
+ { pathname: "/settings/drafting", hash: "" },
308
+ pages,
309
+ { templateTabPageIds: new Map([["drafting", "app-drafting"]]) },
310
+ ),
311
+ ).toEqual({
312
+ page: "drafting",
313
+ sub: null,
314
+ anchor: null,
315
+ legacy: false,
316
+ });
317
+ expect(
318
+ resolveSettingsRoute(
319
+ { pathname: "/settings/app-drafting", hash: "" },
320
+ pages,
321
+ { templateTabPageIds: new Map([["drafting", "app-drafting"]]) },
322
+ ),
323
+ ).toMatchObject({ page: "app-drafting", legacy: false });
324
+ expect(
325
+ resolveSettingsTabValue(
326
+ "drafting",
327
+ pages,
328
+ [],
329
+ new Map([["drafting", "app-drafting"]]),
330
+ ),
331
+ ).toMatchObject({ page: "app-drafting", legacy: true });
332
+ expect(
333
+ resolveSettingsRoute(
334
+ {
335
+ pathname: "/settings",
336
+ hash: "",
337
+ search: "?section=drafting",
338
+ },
339
+ pages,
340
+ { templateTabPageIds: new Map([["drafting", "app-drafting"]]) },
341
+ ),
342
+ ).toMatchObject({ page: "app-drafting", legacy: true });
343
+ });
344
+
345
+ it("preserves nested routes for app-owned page ids that match legacy patterns", () => {
346
+ const pages = [...CORE_SETTINGS_PAGES, appPage("secrets")];
347
+ expect(
348
+ resolveSettingsRoute(
349
+ { pathname: "/settings/secrets/credentials", hash: "" },
350
+ pages,
351
+ ),
352
+ ).toEqual({
353
+ page: "secrets",
354
+ sub: "credentials",
355
+ anchor: null,
356
+ legacy: false,
357
+ });
358
+ });
359
+
270
360
  it("prefers the agent panel's section over the hash it navigated to", () => {
271
361
  // The panel sends `secrets` to #integrations for today's Settings.
272
362
  expect(
@@ -284,6 +374,7 @@ describe("legacy settings links", () => {
284
374
  expect(
285
375
  resolveSettingsRoute({ pathname: "/settings", hash: "" }, MAIL_PAGES, {
286
376
  tabValue: "drafting",
377
+ templateTabPageIds: new Map([["drafting", "drafting"]]),
287
378
  }),
288
379
  ).toMatchObject({ page: "drafting", legacy: true });
289
380
  });
@@ -43,6 +43,8 @@ export interface ResolvedSettingsRoute extends SettingsRoute {
43
43
  export interface ResolveSettingsRouteOptions {
44
44
  /** Tabs on the app's General page, routed `/settings/app/<id>`. */
45
45
  appAreaIds?: readonly string[];
46
+ /** Legacy template tab ids map unless a direct page claims that path. */
47
+ templateTabPageIds?: ReadonlyMap<string, string>;
46
48
  /**
47
49
  * The tab a controlled template chose. A bare `/settings` opens it, which
48
50
  * covers the moment between a template stripping `?section=` from the URL
@@ -159,17 +161,30 @@ function pageForTabIds(
159
161
  }
160
162
 
161
163
  /**
162
- * The page a template's tab id opens. The template's own tabs win, because
163
- * its id space is its own: Mail's inbox `automations` tab is not the core
164
- * Automations page.
164
+ * The page a template's tab id opens. Direct page ids are canonical paths;
165
+ * template aliases still win over legacy redirects and core tab aliases.
165
166
  */
166
167
  export function resolveSettingsTabValue(
167
168
  value: string,
168
169
  pages: readonly SettingsPageDefinition[],
169
170
  appAreaIds: readonly string[] = [],
171
+ templateTabPageIds?: ReadonlyMap<string, string>,
170
172
  ): ResolvedSettingsRoute {
171
173
  const tab = value.trim();
172
174
  if (!tab) return NO_ROUTE;
175
+ const templatePage = templateTabPageIds?.get(tab);
176
+ if (templatePage && pages.some((page) => page.id === templatePage)) {
177
+ return { page: templatePage, sub: null, anchor: null, legacy: true };
178
+ }
179
+ const directAppPage = pages.find(
180
+ (page) => isAppPage(page) && page.id === tab,
181
+ );
182
+ if (directAppPage) {
183
+ return { page: directAppPage.id, sub: null, anchor: null, legacy: false };
184
+ }
185
+ if (appAreaIds.includes(tab)) {
186
+ return { page: "app", sub: tab, anchor: null, legacy: true };
187
+ }
173
188
  const appPage = pages.find(
174
189
  (page) =>
175
190
  isAppPage(page) && (page.id === tab || page.legacyTabIds?.includes(tab)),
@@ -177,9 +192,6 @@ export function resolveSettingsTabValue(
177
192
  if (appPage) {
178
193
  return { page: appPage.id, sub: null, anchor: null, legacy: true };
179
194
  }
180
- if (appAreaIds.includes(tab)) {
181
- return { page: "app", sub: tab, anchor: null, legacy: true };
182
- }
183
195
  const redirect = resolveLegacySettingsId(tab, "tab");
184
196
  if (redirect) return redirectRoute(redirect, pages, null);
185
197
  const page =
@@ -206,7 +218,8 @@ export function resolveSettingsRoute(
206
218
  if (segments.length > 0) {
207
219
  const joined = segments.join(":");
208
220
  const pageId = segments[0]!;
209
- if (pages.some((page) => page.id === pageId)) {
221
+ const directPage = pages.find((page) => page.id === pageId);
222
+ if (directPage && isCoreSettingsPageId(pageId)) {
210
223
  const pattern = segments.length > 1 && resolveSettingsIdPattern(joined);
211
224
  if (pattern) return redirectRoute(pattern, pages, hash || null);
212
225
  return {
@@ -216,6 +229,26 @@ export function resolveSettingsRoute(
216
229
  legacy: segments.length > 2,
217
230
  };
218
231
  }
232
+ if (directPage) {
233
+ return {
234
+ page: pageId,
235
+ sub: segments[1] ?? null,
236
+ anchor: hash || null,
237
+ legacy: segments.length > 2,
238
+ };
239
+ }
240
+ const templatePageId = options.templateTabPageIds?.get(pageId);
241
+ const templatePage = templatePageId
242
+ ? pages.find((page) => page.id === templatePageId)
243
+ : undefined;
244
+ if (templatePage) {
245
+ return {
246
+ page: templatePage.id,
247
+ sub: null,
248
+ anchor: hash || null,
249
+ legacy: true,
250
+ };
251
+ }
219
252
  // Today's tab link to an area that moved onto the app's General page
220
253
  // (`/settings/alerts`). Checked before the redirect table, like
221
254
  // `resolveSettingsTabValue`, because the area id is the template's own.
@@ -266,11 +299,21 @@ export function resolveSettingsRoute(
266
299
  }
267
300
  const section = settingsSectionParam(location.search);
268
301
  if (section) {
269
- const route = resolveSettingsTabValue(section, pages, options.appAreaIds);
302
+ const route = resolveSettingsTabValue(
303
+ section,
304
+ pages,
305
+ options.appAreaIds,
306
+ options.templateTabPageIds,
307
+ );
270
308
  if (route.page) return route;
271
309
  }
272
310
  if (options.tabValue) {
273
- return resolveSettingsTabValue(options.tabValue, pages, options.appAreaIds);
311
+ return resolveSettingsTabValue(
312
+ options.tabValue,
313
+ pages,
314
+ options.appAreaIds,
315
+ options.templateTabPageIds,
316
+ );
274
317
  }
275
318
  return NO_ROUTE;
276
319
  }