@agent-native/core 0.119.2 → 0.119.4

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 (228) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +19 -0
  3. package/corpus/core/package.json +3 -3
  4. package/corpus/core/src/agent/production-agent.ts +107 -125
  5. package/corpus/core/src/agent/run-manager.ts +45 -2
  6. package/corpus/core/src/agent/thread-data-builder.ts +85 -8
  7. package/corpus/core/src/cli/create.ts +44 -5
  8. package/corpus/core/src/client/AssistantChat.tsx +37 -9
  9. package/corpus/core/src/client/chat/message-components.tsx +9 -1
  10. package/corpus/core/src/client/chat/repo-helpers.ts +77 -0
  11. package/corpus/core/src/client/chat/tool-call-display.tsx +51 -15
  12. package/corpus/core/src/server/agent-chat/framework-prompts.ts +3 -1
  13. package/corpus/core/src/server/agent-chat/plugin-options.ts +9 -0
  14. package/corpus/core/src/server/agent-chat-plugin.ts +12 -3
  15. package/corpus/core/src/templates/chat/.agents/skills/actions/SKILL.md +512 -0
  16. package/corpus/core/src/templates/chat/.agents/skills/adding-a-feature/SKILL.md +189 -0
  17. package/corpus/core/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +115 -0
  18. package/corpus/core/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +177 -0
  19. package/corpus/core/src/templates/chat/.agents/skills/capture-learnings/SKILL.md +89 -0
  20. package/corpus/core/src/templates/chat/.agents/skills/create-skill/SKILL.md +221 -0
  21. package/corpus/core/src/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +220 -0
  22. package/corpus/core/src/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +263 -0
  23. package/corpus/core/src/templates/chat/.agents/skills/feature-flags/SKILL.md +169 -0
  24. package/corpus/core/src/templates/chat/.agents/skills/frontend-design/SKILL.md +160 -0
  25. package/corpus/core/src/templates/chat/.agents/skills/real-time-sync/SKILL.md +232 -0
  26. package/corpus/core/src/templates/chat/.agents/skills/security/SKILL.md +280 -0
  27. package/corpus/core/src/templates/chat/.agents/skills/self-modifying-code/SKILL.md +118 -0
  28. package/corpus/core/src/templates/chat/.agents/skills/shadcn-ui/SKILL.md +119 -0
  29. package/corpus/core/src/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +100 -0
  30. package/corpus/core/src/templates/chat/.env.example +5 -0
  31. package/corpus/core/src/templates/chat/.ignore +0 -0
  32. package/corpus/core/src/templates/chat/.oxfmtrc.json +8 -0
  33. package/corpus/core/src/templates/chat/AGENTS.md +69 -0
  34. package/corpus/core/src/templates/chat/CHANGELOG.md +10 -0
  35. package/corpus/core/src/templates/chat/DEVELOPING.md +185 -0
  36. package/corpus/core/src/templates/chat/README.md +32 -0
  37. package/corpus/core/src/templates/chat/_gitignore +43 -0
  38. package/corpus/core/src/templates/chat/actions/hello.ts +13 -0
  39. package/corpus/core/src/templates/chat/actions/navigate.ts +41 -0
  40. package/corpus/core/src/templates/chat/actions/run.ts +2 -0
  41. package/corpus/core/src/templates/chat/actions/view-screen.ts +31 -0
  42. package/corpus/core/src/templates/chat/app/components/layout/Header.tsx +60 -0
  43. package/corpus/core/src/templates/chat/app/components/layout/Layout.tsx +185 -0
  44. package/corpus/core/src/templates/chat/app/components/layout/Sidebar.tsx +450 -0
  45. package/corpus/core/src/templates/chat/app/components/ui/button.tsx +1 -0
  46. package/corpus/core/src/templates/chat/app/components/ui/card.tsx +1 -0
  47. package/corpus/core/src/templates/chat/app/components/ui/dropdown-menu.tsx +1 -0
  48. package/corpus/core/src/templates/chat/app/components/ui/input.tsx +1 -0
  49. package/corpus/core/src/templates/chat/app/components/ui/label.tsx +1 -0
  50. package/corpus/core/src/templates/chat/app/components/ui/sheet.tsx +1 -0
  51. package/corpus/core/src/templates/chat/app/components/ui/toolkit-provider.tsx +17 -0
  52. package/corpus/core/src/templates/chat/app/components/ui/tooltip.tsx +1 -0
  53. package/corpus/core/src/templates/chat/app/design-system.ts +3 -0
  54. package/corpus/core/src/templates/chat/app/entry.client.tsx +19 -0
  55. package/corpus/core/src/templates/chat/app/entry.server.tsx +10 -0
  56. package/corpus/core/src/templates/chat/app/global.css +93 -0
  57. package/corpus/core/src/templates/chat/app/hooks/use-navigation-state.ts +93 -0
  58. package/corpus/core/src/templates/chat/app/i18n/ar-SA.ts +68 -0
  59. package/corpus/core/src/templates/chat/app/i18n/de-DE.ts +71 -0
  60. package/corpus/core/src/templates/chat/app/i18n/en-US.ts +70 -0
  61. package/corpus/core/src/templates/chat/app/i18n/es-ES.ts +71 -0
  62. package/corpus/core/src/templates/chat/app/i18n/fr-FR.ts +71 -0
  63. package/corpus/core/src/templates/chat/app/i18n/hi-IN.ts +69 -0
  64. package/corpus/core/src/templates/chat/app/i18n/index.ts +34 -0
  65. package/corpus/core/src/templates/chat/app/i18n/ja-JP.ts +70 -0
  66. package/corpus/core/src/templates/chat/app/i18n/ko-KR.ts +70 -0
  67. package/corpus/core/src/templates/chat/app/i18n/pt-BR.ts +71 -0
  68. package/corpus/core/src/templates/chat/app/i18n/zh-CN.ts +66 -0
  69. package/corpus/core/src/templates/chat/app/i18n/zh-TW.ts +66 -0
  70. package/corpus/core/src/templates/chat/app/i18n-data.ts +556 -0
  71. package/corpus/core/src/templates/chat/app/lib/agent-page.tsx +49 -0
  72. package/corpus/core/src/templates/chat/app/lib/app-config.ts +11 -0
  73. package/corpus/core/src/templates/chat/app/lib/tab-id.ts +1 -0
  74. package/corpus/core/src/templates/chat/app/lib/utils.ts +1 -0
  75. package/corpus/core/src/templates/chat/app/root.tsx +173 -0
  76. package/corpus/core/src/templates/chat/app/routes/_index.tsx +94 -0
  77. package/corpus/core/src/templates/chat/app/routes/agent.tsx +24 -0
  78. package/corpus/core/src/templates/chat/app/routes/chat.$threadId.tsx +1 -0
  79. package/corpus/core/src/templates/chat/app/routes/database.tsx +17 -0
  80. package/corpus/core/src/templates/chat/app/routes/extensions.$id.$slug.tsx +2 -0
  81. package/corpus/core/src/templates/chat/app/routes/extensions.$id.tsx +11 -0
  82. package/corpus/core/src/templates/chat/app/routes/extensions._index.tsx +11 -0
  83. package/corpus/core/src/templates/chat/app/routes/extensions.tsx +5 -0
  84. package/corpus/core/src/templates/chat/app/routes/observability.tsx +19 -0
  85. package/corpus/core/src/templates/chat/app/routes/settings.tsx +89 -0
  86. package/corpus/core/src/templates/chat/app/routes/team.tsx +11 -0
  87. package/corpus/core/src/templates/chat/app/routes.ts +4 -0
  88. package/corpus/core/src/templates/chat/app/vite-env.d.ts +6 -0
  89. package/corpus/core/src/templates/chat/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +6 -0
  90. package/corpus/core/src/templates/chat/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +6 -0
  91. package/corpus/core/src/templates/chat/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
  92. package/corpus/core/src/templates/chat/changelog/2026-06-28-left-sidebar-collapse-motion-and-footer-chrome-are-quieter.md +6 -0
  93. package/corpus/core/src/templates/chat/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  94. package/corpus/core/src/templates/chat/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  95. package/corpus/core/src/templates/chat/changelog/2026-07-10-chat-now-makes-ai-connection-setup-clear-without-shifting-th.md +6 -0
  96. package/corpus/core/src/templates/chat/changelog/2026-07-13-a-full-agent-page-now-brings-context-files-connections-jobs-.md +6 -0
  97. package/corpus/core/src/templates/chat/changelog/2026-07-14-chat-opens-reliably-on-hosted-deployments-instead-of-failing.md +6 -0
  98. package/corpus/core/src/templates/chat/changelog/2026-07-14-fixed-chat-template-startup-with-older-core-versions.md +6 -0
  99. package/corpus/core/src/templates/chat/changelog/2026-07-15-chat-navigation-focuses-on-chat-and-agent.md +6 -0
  100. package/corpus/core/src/templates/chat/changelog/2026-07-17-the-agent-chat-sidebar-stays-closed-until-you-open-it-or-sta.md +6 -0
  101. package/corpus/core/src/templates/chat/changelog/2026-07-22-compact-sidebar-footer.md +6 -0
  102. package/corpus/core/src/templates/chat/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +6 -0
  103. package/corpus/core/src/templates/chat/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  104. package/corpus/core/src/templates/chat/changelog/2026-07-22-recent-chats-are-easier-to-scan-and-expand.md +6 -0
  105. package/corpus/core/src/templates/chat/changelog/2026-07-23-full-page-chat-is-better-centered-with-quieter-chat-history-.md +6 -0
  106. package/corpus/core/src/templates/chat/components.json +20 -0
  107. package/corpus/core/src/templates/chat/learnings.defaults.md +5 -0
  108. package/corpus/core/src/templates/chat/netlify.toml +10 -0
  109. package/corpus/core/src/templates/chat/package.json +92 -0
  110. package/corpus/core/src/templates/chat/public/agent-native-icon-dark.svg +10 -0
  111. package/corpus/core/src/templates/chat/public/agent-native-icon-light.svg +10 -0
  112. package/corpus/core/src/templates/chat/public/agent-native-logo-dark.svg +21 -0
  113. package/corpus/core/src/templates/chat/public/agent-native-logo-light.svg +21 -0
  114. package/corpus/core/src/templates/chat/public/favicon.svg +1 -0
  115. package/corpus/core/src/templates/chat/public/icon-180.svg +1 -0
  116. package/corpus/core/src/templates/chat/public/icon-192.svg +1 -0
  117. package/corpus/core/src/templates/chat/public/icon-512.svg +1 -0
  118. package/corpus/core/src/templates/chat/public/manifest.json +21 -0
  119. package/corpus/core/src/templates/chat/react-router.config.ts +7 -0
  120. package/corpus/core/src/templates/chat/server/middleware/auth.ts +15 -0
  121. package/corpus/core/src/templates/chat/server/plugins/agent-chat.ts +21 -0
  122. package/corpus/core/src/templates/chat/server/plugins/auth.ts +17 -0
  123. package/corpus/core/src/templates/chat/server/routes/[...page].get.ts +5 -0
  124. package/corpus/core/src/templates/chat/ssr-entry.ts +15 -0
  125. package/corpus/core/src/templates/chat/tsconfig.json +21 -0
  126. package/corpus/core/src/templates/chat/vite.config.ts +19 -0
  127. package/corpus/templates/analytics/AGENTS.md +19 -11
  128. package/corpus/templates/analytics/actions/list-data-dictionary.ts +3 -1
  129. package/corpus/templates/analytics/actions/save-data-dictionary-entry.ts +14 -0
  130. package/corpus/templates/analytics/actions/search-analytics-query-catalog.ts +41 -0
  131. package/corpus/templates/analytics/app/components/dashboard/DashboardPanelSkeleton.tsx +13 -0
  132. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +12 -11
  133. package/corpus/templates/analytics/app/pages/adhoc/DashboardSkeleton.tsx +3 -3
  134. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +7 -1
  135. package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +8 -1
  136. package/corpus/templates/analytics/changelog/2026-07-22-fixed-dashboards-and-analyses-missing-a-copyable-share-link.md +6 -0
  137. package/corpus/templates/analytics/changelog/2026-07-23-dashboard-chart-loading-placeholders-are-easier-to-see-in-da.md +6 -0
  138. package/corpus/templates/analytics/changelog/2026-07-23-routine-analytics-lookups-reuse-existing-query-definitions.md +6 -0
  139. package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +1 -12
  140. package/corpus/templates/analytics/server/lib/analytics-query-catalog.ts +405 -0
  141. package/corpus/templates/analytics/server/plugins/agent-chat.ts +11 -16
  142. package/corpus/templates/content/changelog/2026-07-23-database-toolbar-sort-and-filter-controls-open-reliably.md +6 -0
  143. package/corpus/templates/forms/app/lib/public-form-link.ts +14 -0
  144. package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +6 -14
  145. package/corpus/templates/forms/changelog/2026-07-23-published-form-links-can-be-copied-without-being-asked-to-re.md +6 -0
  146. package/corpus/templates/mail/changelog/2026-07-23-scheduled-emails-now-send-only-once-when-multiple-requests-r.md +6 -0
  147. package/corpus/templates/mail/server/lib/jobs.ts +13 -4
  148. package/corpus/templates/mail/server/plugins/mail-jobs.ts +1 -1
  149. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +7 -18
  150. package/corpus/templates/slides/app/lib/agent-visible-message.ts +28 -0
  151. package/corpus/templates/slides/app/pages/Index.tsx +6 -34
  152. package/corpus/templates/slides/changelog/2026-07-23-full-prompts-stay-visible-in-chat-when-creating-decks-or-add.md +6 -0
  153. package/corpus/toolkit/CHANGELOG.md +13 -0
  154. package/corpus/toolkit/package.json +1 -1
  155. package/corpus/toolkit/src/editor/SharedRichEditor.tsx +23 -2
  156. package/corpus/toolkit/src/editor/SlashCommandMenu.tsx +68 -2
  157. package/corpus/toolkit/src/editor/index.ts +1 -0
  158. package/corpus/toolkit/src/editor.css +75 -0
  159. package/corpus/toolkit/src/ui/button.tsx +3 -2
  160. package/dist/agent/production-agent.d.ts.map +1 -1
  161. package/dist/agent/production-agent.js +96 -115
  162. package/dist/agent/production-agent.js.map +1 -1
  163. package/dist/agent/run-manager.d.ts +9 -1
  164. package/dist/agent/run-manager.d.ts.map +1 -1
  165. package/dist/agent/run-manager.js +26 -0
  166. package/dist/agent/run-manager.js.map +1 -1
  167. package/dist/agent/thread-data-builder.d.ts +2 -0
  168. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  169. package/dist/agent/thread-data-builder.js +69 -9
  170. package/dist/agent/thread-data-builder.js.map +1 -1
  171. package/dist/cli/create.d.ts +2 -1
  172. package/dist/cli/create.d.ts.map +1 -1
  173. package/dist/cli/create.js +43 -6
  174. package/dist/cli/create.js.map +1 -1
  175. package/dist/client/AssistantChat.d.ts.map +1 -1
  176. package/dist/client/AssistantChat.js +32 -10
  177. package/dist/client/AssistantChat.js.map +1 -1
  178. package/dist/client/chat/message-components.d.ts +2 -1
  179. package/dist/client/chat/message-components.d.ts.map +1 -1
  180. package/dist/client/chat/message-components.js +9 -3
  181. package/dist/client/chat/message-components.js.map +1 -1
  182. package/dist/client/chat/repo-helpers.d.ts +4 -0
  183. package/dist/client/chat/repo-helpers.d.ts.map +1 -1
  184. package/dist/client/chat/repo-helpers.js +61 -0
  185. package/dist/client/chat/repo-helpers.js.map +1 -1
  186. package/dist/client/chat/tool-call-display.d.ts +2 -1
  187. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  188. package/dist/client/chat/tool-call-display.js +10 -9
  189. package/dist/client/chat/tool-call-display.js.map +1 -1
  190. package/dist/collab/awareness.d.ts +2 -2
  191. package/dist/collab/awareness.d.ts.map +1 -1
  192. package/dist/collab/routes.d.ts +1 -1
  193. package/dist/collab/struct-routes.d.ts +1 -1
  194. package/dist/notifications/routes.d.ts +2 -2
  195. package/dist/observability/routes.d.ts +3 -3
  196. package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
  197. package/dist/provider-api/actions/provider-api.d.ts +7 -7
  198. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  199. package/dist/resources/handlers.d.ts +1 -1
  200. package/dist/secrets/routes.d.ts +9 -9
  201. package/dist/server/agent-chat/framework-prompts.d.ts.map +1 -1
  202. package/dist/server/agent-chat/framework-prompts.js +3 -1
  203. package/dist/server/agent-chat/framework-prompts.js.map +1 -1
  204. package/dist/server/agent-chat/plugin-options.d.ts +9 -0
  205. package/dist/server/agent-chat/plugin-options.d.ts.map +1 -1
  206. package/dist/server/agent-chat/plugin-options.js.map +1 -1
  207. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  208. package/dist/server/agent-chat-plugin.js +11 -2
  209. package/dist/server/agent-chat-plugin.js.map +1 -1
  210. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  211. package/dist/server/realtime-token.d.ts +1 -1
  212. package/dist/server/transcribe-voice.d.ts +1 -1
  213. package/package.json +4 -4
  214. package/src/agent/production-agent.ts +107 -125
  215. package/src/agent/run-manager.ts +45 -2
  216. package/src/agent/thread-data-builder.ts +85 -8
  217. package/src/cli/create.ts +44 -5
  218. package/src/client/AssistantChat.tsx +37 -9
  219. package/src/client/chat/message-components.tsx +9 -1
  220. package/src/client/chat/repo-helpers.ts +77 -0
  221. package/src/client/chat/tool-call-display.tsx +51 -15
  222. package/src/server/agent-chat/framework-prompts.ts +3 -1
  223. package/src/server/agent-chat/plugin-options.ts +9 -0
  224. package/src/server/agent-chat-plugin.ts +12 -3
  225. package/src/templates/chat/actions/hello.spec.ts +0 -23
  226. package/src/templates/chat/actions/navigate.spec.ts +0 -68
  227. package/src/templates/chat/actions/view-screen.spec.ts +0 -40
  228. package/src/templates/chat/app/lib/agent-page.spec.tsx +0 -61
@@ -1,10 +1,71 @@
1
1
  // Owns: typed helpers for reading/comparing the assistant-ui message repository shape.
2
+ // The assistant-ui ExportedMessageRepository type is structurally complex and
3
+ // the normalised internal form diverges slightly. We define a structural
4
+ // interface covering the shapes both `threadRuntime.export()` and
5
+ // `normalizeThreadRepository()` produce, and use it everywhere instead of `any`.
6
+ import { ASSISTANT_RUN_DURATION_METADATA_KEY } from "../../agent/thread-data-builder.js";
2
7
  export function getRepoMessages(repo) {
3
8
  return Array.isArray(repo?.messages) ? repo.messages : [];
4
9
  }
5
10
  export function getRepoMessage(entry) {
6
11
  return (entry?.message ?? entry);
7
12
  }
13
+ export function getAssistantRunDurationMs(message) {
14
+ const metadata = message?.metadata && typeof message.metadata === "object"
15
+ ? message.metadata
16
+ : null;
17
+ const custom = metadata?.custom && typeof metadata.custom === "object"
18
+ ? metadata.custom
19
+ : null;
20
+ const durationMs = custom?.[ASSISTANT_RUN_DURATION_METADATA_KEY];
21
+ return typeof durationMs === "number" &&
22
+ Number.isFinite(durationMs) &&
23
+ durationMs >= 0
24
+ ? durationMs
25
+ : null;
26
+ }
27
+ export function withLastAssistantRunDuration(repo, durationMs) {
28
+ if (!Array.isArray(repo.messages) ||
29
+ typeof durationMs !== "number" ||
30
+ !Number.isFinite(durationMs) ||
31
+ durationMs < 0) {
32
+ return repo;
33
+ }
34
+ let messageIndex = -1;
35
+ for (let index = repo.messages.length - 1; index >= 0; index -= 1) {
36
+ if (getRepoMessage(repo.messages[index])?.role === "assistant") {
37
+ messageIndex = index;
38
+ break;
39
+ }
40
+ }
41
+ if (messageIndex < 0)
42
+ return repo;
43
+ const entry = repo.messages[messageIndex];
44
+ const message = getRepoMessage(entry);
45
+ if (!message || getAssistantRunDurationMs(message) === durationMs) {
46
+ return repo;
47
+ }
48
+ const metadata = message.metadata ?? {};
49
+ const custom = metadata.custom && typeof metadata.custom === "object"
50
+ ? metadata.custom
51
+ : {};
52
+ const nextMessage = {
53
+ ...message,
54
+ metadata: {
55
+ ...metadata,
56
+ custom: {
57
+ ...custom,
58
+ [ASSISTANT_RUN_DURATION_METADATA_KEY]: durationMs,
59
+ },
60
+ },
61
+ };
62
+ const messages = repo.messages.slice();
63
+ messages[messageIndex] =
64
+ entry.message === undefined
65
+ ? nextMessage
66
+ : { ...entry, message: nextMessage };
67
+ return { ...repo, messages };
68
+ }
8
69
  /**
9
70
  * Collapse duplicate message ids before a repository is handed to
10
71
  * `threadRuntime.import()`. assistant-ui's `MessageRepository` throws
@@ -1 +1 @@
1
- {"version":3,"file":"repo-helpers.js","sourceRoot":"","sources":["../../../src/client/chat/repo-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Owns: typed helpers for reading/comparing the assistant-ui message repository shape.\n\n// The assistant-ui ExportedMessageRepository type is structurally complex and\n// the normalised internal form diverges slightly. We define a structural\n// interface covering the shapes both `threadRuntime.export()` and\n// `normalizeThreadRepository()` produce, and use it everywhere instead of `any`.\n\nexport interface RepoMessageStatus {\n type?: string;\n reason?: string;\n}\n\nexport interface RepoMessageContent {\n type: string;\n text?: string;\n [key: string]: unknown;\n}\n\nexport interface RepoMessage {\n id?: string;\n role?: string;\n status?: RepoMessageStatus;\n content?: string | RepoMessageContent[];\n metadata?: Record<string, unknown>;\n createdAt?: Date | string | number;\n [key: string]: unknown;\n}\n\n/** Entry in `repo.messages` — may be flat or wrapped `{ message: RepoMessage }`. */\nexport interface RepoEntry {\n parentId?: string | null;\n message?: RepoMessage;\n // Flat (unwrapped) fields are also legal:\n id?: string;\n role?: string;\n status?: RepoMessageStatus;\n content?: string | RepoMessageContent[];\n [key: string]: unknown;\n}\n\n/** Minimal structure of the normalised thread repository used by AssistantChat. */\nexport interface NormalizedRepo {\n messages?: RepoEntry[];\n headId?: string;\n queuedMessages?: unknown[];\n [key: string]: unknown;\n}\n\nexport function getRepoMessages(\n repo: NormalizedRepo | null | undefined,\n): RepoEntry[] {\n return Array.isArray(repo?.messages) ? repo.messages : [];\n}\n\nexport function getRepoMessage(entry: RepoEntry): RepoMessage | null {\n return (entry?.message ?? entry) as RepoMessage | null;\n}\n\n/**\n * Collapse duplicate message ids before a repository is handed to\n * `threadRuntime.import()`. assistant-ui's `MessageRepository` throws\n * \"MessageRepository(performOp/link): A message with the same id already exists\n * in the parent tree\" when the imported messages contain the same id more than\n * once (Sentry AGENT-NATIVE-BROWSER-2Q). Duplicate ids are never valid thread\n * data — they come from optimistic+echo races, streaming reconnect replays, or\n * multi-tab merges — so keep only the LAST occurrence of each id (the most\n * recent, most complete copy). parentId references stay valid because the\n * surviving entry keeps the same id.\n *\n * Returns the input unchanged (same reference) when there are no duplicates, so\n * the overwhelmingly common no-dupe case is a cheap no-op with zero behavioural\n * change for normal threads.\n */\nexport function dedupeRepoMessagesById<T extends NormalizedRepo>(\n repo: T | null | undefined,\n): T | null | undefined {\n if (!repo || !Array.isArray(repo.messages)) return repo;\n const entries = repo.messages;\n const lastIndexById = new Map<string, number>();\n let hasDuplicate = false;\n entries.forEach((entry, index) => {\n const id = getRepoMessage(entry)?.id;\n if (typeof id !== \"string\" || !id) return;\n if (lastIndexById.has(id)) hasDuplicate = true;\n lastIndexById.set(id, index);\n });\n if (!hasDuplicate) return repo;\n const deduped = entries.filter((entry, index) => {\n const id = getRepoMessage(entry)?.id;\n // Keep id-less entries untouched; for duplicated ids keep only the last.\n if (typeof id !== \"string\" || !id) return true;\n return lastIndexById.get(id) === index;\n });\n return { ...repo, messages: deduped };\n}\n\nfunction repoMessageContentIsEmpty(content: unknown): boolean {\n if (typeof content === \"string\") return content.trim().length === 0;\n if (!Array.isArray(content)) return true;\n return !content.some((part) => {\n if (!part || typeof part !== \"object\") return false;\n const type = (part as { type?: unknown }).type;\n if (type === \"text\") {\n const text = (part as { text?: unknown }).text;\n return typeof text === \"string\" && text.trim().length > 0;\n }\n return true;\n });\n}\n\nfunction entryWithParentId(\n entry: RepoEntry,\n parentId: string | null,\n): RepoEntry {\n return { ...entry, parentId };\n}\n\nfunction repairRepoLinks<T extends NormalizedRepo>(\n repo: T,\n entries: RepoEntry[],\n): T {\n const seenIds = new Set<string>();\n let previousId: string | null = null;\n const repaired: RepoEntry[] = [];\n\n for (const entry of entries) {\n const id = getRepoMessage(entry)?.id;\n if (typeof id !== \"string\" || !id) continue;\n const requestedParentId = entry.parentId;\n const parentId =\n requestedParentId === null\n ? null\n : typeof requestedParentId === \"string\" &&\n seenIds.has(requestedParentId)\n ? requestedParentId\n : previousId;\n repaired.push(entryWithParentId(entry, parentId));\n seenIds.add(id);\n previousId = id;\n }\n\n const headId =\n typeof repo.headId === \"string\" && seenIds.has(repo.headId)\n ? repo.headId\n : previousId;\n return { ...repo, messages: repaired, headId: headId ?? undefined };\n}\n\nexport function dropEmptyAssistantMessages<T extends NormalizedRepo>(\n repo: T | null | undefined,\n): T | null | undefined {\n if (!repo || !Array.isArray(repo.messages)) return repo;\n\n let changed = false;\n const messages = repo.messages.filter((entry) => {\n const message = getRepoMessage(entry);\n const drop =\n message?.role === \"assistant\" &&\n repoMessageContentIsEmpty(message.content);\n if (drop) changed = true;\n return !drop;\n });\n\n if (!changed) return repo;\n return repairRepoLinks(repo, messages);\n}\n\nexport function isAssistantMessageTerminal(\n message: RepoMessage | null,\n): boolean {\n const statusType = message?.status?.type;\n return statusType === \"complete\" || statusType === \"incomplete\";\n}\n\nexport function repoHasAssistantMessage(\n repo: NormalizedRepo | null | undefined,\n): boolean {\n return getRepoMessages(repo).some(\n (m) => getRepoMessage(m)?.role === \"assistant\",\n );\n}\n\nfunction repoTextLength(repo: NormalizedRepo | null | undefined): number {\n let length = 0;\n for (const entry of getRepoMessages(repo)) {\n const message = getRepoMessage(entry);\n const content = message?.content;\n if (typeof content === \"string\") {\n length += content.length;\n } else if (Array.isArray(content)) {\n for (const part of content) {\n if (part?.type === \"text\" && typeof part.text === \"string\") {\n length += part.text.length;\n }\n }\n }\n }\n return length;\n}\n\nfunction repoTerminalAssistantCount(\n repo: NormalizedRepo | null | undefined,\n): number {\n return getRepoMessages(repo).filter((entry) => {\n const message = getRepoMessage(entry);\n return message?.role === \"assistant\" && isAssistantMessageTerminal(message);\n }).length;\n}\n\nfunction toolCallProgressScore(part: RepoMessageContent): number {\n if (part.type !== \"tool-call\") return 0;\n let score = 1;\n if (part.activity !== true) score += 1;\n if (\"result\" in part) score += 4;\n return score;\n}\n\nfunction repoToolCallProgress(repo: NormalizedRepo | null | undefined): {\n total: number;\n materialized: number;\n completed: number;\n score: number;\n} {\n const progress = {\n total: 0,\n materialized: 0,\n completed: 0,\n score: 0,\n };\n for (const entry of getRepoMessages(repo)) {\n const message = getRepoMessage(entry);\n const content = message?.content;\n if (!Array.isArray(content)) continue;\n for (const part of content) {\n if (part?.type !== \"tool-call\") continue;\n progress.total += 1;\n if (part.activity !== true) progress.materialized += 1;\n if (\"result\" in part) progress.completed += 1;\n progress.score += toolCallProgressScore(part);\n }\n }\n return progress;\n}\n\nexport function shouldImportServerThreadData(\n currentRepo: NormalizedRepo | null | undefined,\n incomingRepo: NormalizedRepo | null | undefined,\n): boolean {\n const incomingCount = getRepoMessages(incomingRepo).length;\n if (incomingCount === 0) return false;\n\n const currentCount = getRepoMessages(currentRepo).length;\n if (currentCount === 0) return true;\n if (incomingCount < currentCount) return false;\n\n if (incomingCount === currentCount) {\n const currentTerminalAssistants = repoTerminalAssistantCount(currentRepo);\n const incomingTerminalAssistants = repoTerminalAssistantCount(incomingRepo);\n if (incomingTerminalAssistants < currentTerminalAssistants) {\n return false;\n }\n if (\n incomingTerminalAssistants <= currentTerminalAssistants &&\n repoTextLength(incomingRepo) < repoTextLength(currentRepo)\n ) {\n return false;\n }\n const currentTools = repoToolCallProgress(currentRepo);\n const incomingTools = repoToolCallProgress(incomingRepo);\n if (\n incomingTools.total < currentTools.total ||\n incomingTools.materialized < currentTools.materialized ||\n incomingTools.completed < currentTools.completed ||\n incomingTools.score < currentTools.score\n ) {\n return false;\n }\n }\n\n return true;\n}\n"]}
1
+ {"version":3,"file":"repo-helpers.js","sourceRoot":"","sources":["../../../src/client/chat/repo-helpers.ts"],"names":[],"mappings":"AAAA,uFAAuF;AAEvF,8EAA8E;AAC9E,yEAAyE;AACzE,kEAAkE;AAClE,iFAAiF;AAEjF,OAAO,EAAE,mCAAmC,EAAE,MAAM,oCAAoC,CAAC;AA2CzF,MAAM,UAAU,eAAe,CAC7B,IAAuC;IAEvC,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAgB;IAC7C,OAAO,CAAC,KAAK,EAAE,OAAO,IAAI,KAAK,CAAuB,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,OAKa;IAEb,MAAM,QAAQ,GACZ,OAAO,EAAE,QAAQ,IAAI,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ;QACvD,CAAC,CAAE,OAAO,CAAC,QAAoC;QAC/C,CAAC,CAAC,IAAI,CAAC;IACX,MAAM,MAAM,GACV,QAAQ,EAAE,MAAM,IAAI,OAAO,QAAQ,CAAC,MAAM,KAAK,QAAQ;QACrD,CAAC,CAAE,QAAQ,CAAC,MAAkC;QAC9C,CAAC,CAAC,IAAI,CAAC;IACX,MAAM,UAAU,GAAG,MAAM,EAAE,CAAC,mCAAmC,CAAC,CAAC;IACjE,OAAO,OAAO,UAAU,KAAK,QAAQ;QACnC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC3B,UAAU,IAAI,CAAC;QACf,CAAC,CAAC,UAAU;QACZ,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,IAAO,EACP,UAAqC;IAErC,IACE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;QAC7B,OAAO,UAAU,KAAK,QAAQ;QAC9B,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC5B,UAAU,GAAG,CAAC,EACd,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,YAAY,GAAG,CAAC,CAAC,CAAC;IACtB,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAClE,IAAI,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAE,CAAC,EAAE,IAAI,KAAK,WAAW,EAAE,CAAC;YAChE,YAAY,GAAG,KAAK,CAAC;YACrB,MAAM;QACR,CAAC;IACH,CAAC;IACD,IAAI,YAAY,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAElC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAE,CAAC;IAC3C,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACtC,IAAI,CAAC,OAAO,IAAI,yBAAyB,CAAC,OAAO,CAAC,KAAK,UAAU,EAAE,CAAC;QAClE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;IACxC,MAAM,MAAM,GACV,QAAQ,CAAC,MAAM,IAAI,OAAO,QAAQ,CAAC,MAAM,KAAK,QAAQ;QACpD,CAAC,CAAE,QAAQ,CAAC,MAAkC;QAC9C,CAAC,CAAC,EAAE,CAAC;IACT,MAAM,WAAW,GAAgB;QAC/B,GAAG,OAAO;QACV,QAAQ,EAAE;YACR,GAAG,QAAQ;YACX,MAAM,EAAE;gBACN,GAAG,MAAM;gBACT,CAAC,mCAAmC,CAAC,EAAE,UAAU;aAClD;SACF;KACF,CAAC;IACF,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACvC,QAAQ,CAAC,YAAY,CAAC;QACpB,KAAK,CAAC,OAAO,KAAK,SAAS;YACzB,CAAC,CAAE,WAAyB;YAC5B,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IACzC,OAAO,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAC;AAC/B,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAA0B;IAE1B,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IACxD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC9B,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;IAChD,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QAC/B,MAAM,EAAE,GAAG,cAAc,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,CAAC,EAAE;YAAE,OAAO;QAC1C,IAAI,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,YAAY,GAAG,IAAI,CAAC;QAC/C,aAAa,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,YAAY;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QAC9C,MAAM,EAAE,GAAG,cAAc,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QACrC,yEAAyE;QACzE,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QAC/C,OAAO,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,KAAK,CAAC;IACzC,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AACxC,CAAC;AAED,SAAS,yBAAyB,CAAC,OAAgB;IACjD,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC;IACpE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;QAC5B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QACpD,MAAM,IAAI,GAAI,IAA2B,CAAC,IAAI,CAAC;QAC/C,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,MAAM,IAAI,GAAI,IAA2B,CAAC,IAAI,CAAC;YAC/C,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,iBAAiB,CACxB,KAAgB,EAChB,QAAuB;IAEvB,OAAO,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,CAAC;AAChC,CAAC;AAED,SAAS,eAAe,CACtB,IAAO,EACP,OAAoB;IAEpB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,IAAI,UAAU,GAAkB,IAAI,CAAC;IACrC,MAAM,QAAQ,GAAgB,EAAE,CAAC;IAEjC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,EAAE,GAAG,cAAc,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,CAAC,EAAE;YAAE,SAAS;QAC5C,MAAM,iBAAiB,GAAG,KAAK,CAAC,QAAQ,CAAC;QACzC,MAAM,QAAQ,GACZ,iBAAiB,KAAK,IAAI;YACxB,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,OAAO,iBAAiB,KAAK,QAAQ;gBACnC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;gBAChC,CAAC,CAAC,iBAAiB;gBACnB,CAAC,CAAC,UAAU,CAAC;QACnB,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,UAAU,GAAG,EAAE,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GACV,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;QACzD,CAAC,CAAC,IAAI,CAAC,MAAM;QACb,CAAC,CAAC,UAAU,CAAC;IACjB,OAAO,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,IAAI,SAAS,EAAE,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,IAA0B;IAE1B,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAExD,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QAC9C,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,IAAI,GACR,OAAO,EAAE,IAAI,KAAK,WAAW;YAC7B,yBAAyB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC7C,IAAI,IAAI;YAAE,OAAO,GAAG,IAAI,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC;IACf,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,OAAO,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,OAA2B;IAE3B,MAAM,UAAU,GAAG,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC;IACzC,OAAO,UAAU,KAAK,UAAU,IAAI,UAAU,KAAK,YAAY,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,IAAuC;IAEvC,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,CAC/B,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,WAAW,CAC/C,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,IAAuC;IAC7D,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,KAAK,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,CAAC;QACjC,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;QAC3B,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAClC,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;gBAC3B,IAAI,IAAI,EAAE,IAAI,KAAK,MAAM,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC3D,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;gBAC7B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,0BAA0B,CACjC,IAAuC;IAEvC,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QAC5C,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACtC,OAAO,OAAO,EAAE,IAAI,KAAK,WAAW,IAAI,0BAA0B,CAAC,OAAO,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC,MAAM,CAAC;AACZ,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAwB;IACrD,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,CAAC,CAAC;IACxC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI;QAAE,KAAK,IAAI,CAAC,CAAC;IACvC,IAAI,QAAQ,IAAI,IAAI;QAAE,KAAK,IAAI,CAAC,CAAC;IACjC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAuC;IAMnE,MAAM,QAAQ,GAAG;QACf,KAAK,EAAE,CAAC;QACR,YAAY,EAAE,CAAC;QACf,SAAS,EAAE,CAAC;QACZ,KAAK,EAAE,CAAC;KACT,CAAC;IACF,KAAK,MAAM,KAAK,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,CAAC;QACjC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;YAAE,SAAS;QACtC,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,IAAI,IAAI,EAAE,IAAI,KAAK,WAAW;gBAAE,SAAS;YACzC,QAAQ,CAAC,KAAK,IAAI,CAAC,CAAC;YACpB,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI;gBAAE,QAAQ,CAAC,YAAY,IAAI,CAAC,CAAC;YACvD,IAAI,QAAQ,IAAI,IAAI;gBAAE,QAAQ,CAAC,SAAS,IAAI,CAAC,CAAC;YAC9C,QAAQ,CAAC,KAAK,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,WAA8C,EAC9C,YAA+C;IAE/C,MAAM,aAAa,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC;IAC3D,IAAI,aAAa,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEtC,MAAM,YAAY,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC;IACzD,IAAI,YAAY,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,aAAa,GAAG,YAAY;QAAE,OAAO,KAAK,CAAC;IAE/C,IAAI,aAAa,KAAK,YAAY,EAAE,CAAC;QACnC,MAAM,yBAAyB,GAAG,0BAA0B,CAAC,WAAW,CAAC,CAAC;QAC1E,MAAM,0BAA0B,GAAG,0BAA0B,CAAC,YAAY,CAAC,CAAC;QAC5E,IAAI,0BAA0B,GAAG,yBAAyB,EAAE,CAAC;YAC3D,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IACE,0BAA0B,IAAI,yBAAyB;YACvD,cAAc,CAAC,YAAY,CAAC,GAAG,cAAc,CAAC,WAAW,CAAC,EAC1D,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,YAAY,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;QACvD,MAAM,aAAa,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;QACzD,IACE,aAAa,CAAC,KAAK,GAAG,YAAY,CAAC,KAAK;YACxC,aAAa,CAAC,YAAY,GAAG,YAAY,CAAC,YAAY;YACtD,aAAa,CAAC,SAAS,GAAG,YAAY,CAAC,SAAS;YAChD,aAAa,CAAC,KAAK,GAAG,YAAY,CAAC,KAAK,EACxC,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["// Owns: typed helpers for reading/comparing the assistant-ui message repository shape.\n\n// The assistant-ui ExportedMessageRepository type is structurally complex and\n// the normalised internal form diverges slightly. We define a structural\n// interface covering the shapes both `threadRuntime.export()` and\n// `normalizeThreadRepository()` produce, and use it everywhere instead of `any`.\n\nimport { ASSISTANT_RUN_DURATION_METADATA_KEY } from \"../../agent/thread-data-builder.js\";\n\nexport interface RepoMessageStatus {\n type?: string;\n reason?: string;\n}\n\nexport interface RepoMessageContent {\n type: string;\n text?: string;\n [key: string]: unknown;\n}\n\nexport interface RepoMessage {\n id?: string;\n role?: string;\n status?: RepoMessageStatus;\n content?: string | RepoMessageContent[];\n metadata?: Record<string, unknown>;\n createdAt?: Date | string | number;\n [key: string]: unknown;\n}\n\n/** Entry in `repo.messages` — may be flat or wrapped `{ message: RepoMessage }`. */\nexport interface RepoEntry {\n parentId?: string | null;\n message?: RepoMessage;\n // Flat (unwrapped) fields are also legal:\n id?: string;\n role?: string;\n status?: RepoMessageStatus;\n content?: string | RepoMessageContent[];\n [key: string]: unknown;\n}\n\n/** Minimal structure of the normalised thread repository used by AssistantChat. */\nexport interface NormalizedRepo {\n messages?: RepoEntry[];\n headId?: string;\n queuedMessages?: unknown[];\n [key: string]: unknown;\n}\n\nexport function getRepoMessages(\n repo: NormalizedRepo | null | undefined,\n): RepoEntry[] {\n return Array.isArray(repo?.messages) ? repo.messages : [];\n}\n\nexport function getRepoMessage(entry: RepoEntry): RepoMessage | null {\n return (entry?.message ?? entry) as RepoMessage | null;\n}\n\nexport function getAssistantRunDurationMs(\n message:\n | {\n metadata?: unknown;\n }\n | null\n | undefined,\n): number | null {\n const metadata =\n message?.metadata && typeof message.metadata === \"object\"\n ? (message.metadata as Record<string, unknown>)\n : null;\n const custom =\n metadata?.custom && typeof metadata.custom === \"object\"\n ? (metadata.custom as Record<string, unknown>)\n : null;\n const durationMs = custom?.[ASSISTANT_RUN_DURATION_METADATA_KEY];\n return typeof durationMs === \"number\" &&\n Number.isFinite(durationMs) &&\n durationMs >= 0\n ? durationMs\n : null;\n}\n\nexport function withLastAssistantRunDuration<T extends NormalizedRepo>(\n repo: T,\n durationMs: number | null | undefined,\n): T {\n if (\n !Array.isArray(repo.messages) ||\n typeof durationMs !== \"number\" ||\n !Number.isFinite(durationMs) ||\n durationMs < 0\n ) {\n return repo;\n }\n\n let messageIndex = -1;\n for (let index = repo.messages.length - 1; index >= 0; index -= 1) {\n if (getRepoMessage(repo.messages[index]!)?.role === \"assistant\") {\n messageIndex = index;\n break;\n }\n }\n if (messageIndex < 0) return repo;\n\n const entry = repo.messages[messageIndex]!;\n const message = getRepoMessage(entry);\n if (!message || getAssistantRunDurationMs(message) === durationMs) {\n return repo;\n }\n\n const metadata = message.metadata ?? {};\n const custom =\n metadata.custom && typeof metadata.custom === \"object\"\n ? (metadata.custom as Record<string, unknown>)\n : {};\n const nextMessage: RepoMessage = {\n ...message,\n metadata: {\n ...metadata,\n custom: {\n ...custom,\n [ASSISTANT_RUN_DURATION_METADATA_KEY]: durationMs,\n },\n },\n };\n const messages = repo.messages.slice();\n messages[messageIndex] =\n entry.message === undefined\n ? (nextMessage as RepoEntry)\n : { ...entry, message: nextMessage };\n return { ...repo, messages };\n}\n\n/**\n * Collapse duplicate message ids before a repository is handed to\n * `threadRuntime.import()`. assistant-ui's `MessageRepository` throws\n * \"MessageRepository(performOp/link): A message with the same id already exists\n * in the parent tree\" when the imported messages contain the same id more than\n * once (Sentry AGENT-NATIVE-BROWSER-2Q). Duplicate ids are never valid thread\n * data — they come from optimistic+echo races, streaming reconnect replays, or\n * multi-tab merges — so keep only the LAST occurrence of each id (the most\n * recent, most complete copy). parentId references stay valid because the\n * surviving entry keeps the same id.\n *\n * Returns the input unchanged (same reference) when there are no duplicates, so\n * the overwhelmingly common no-dupe case is a cheap no-op with zero behavioural\n * change for normal threads.\n */\nexport function dedupeRepoMessagesById<T extends NormalizedRepo>(\n repo: T | null | undefined,\n): T | null | undefined {\n if (!repo || !Array.isArray(repo.messages)) return repo;\n const entries = repo.messages;\n const lastIndexById = new Map<string, number>();\n let hasDuplicate = false;\n entries.forEach((entry, index) => {\n const id = getRepoMessage(entry)?.id;\n if (typeof id !== \"string\" || !id) return;\n if (lastIndexById.has(id)) hasDuplicate = true;\n lastIndexById.set(id, index);\n });\n if (!hasDuplicate) return repo;\n const deduped = entries.filter((entry, index) => {\n const id = getRepoMessage(entry)?.id;\n // Keep id-less entries untouched; for duplicated ids keep only the last.\n if (typeof id !== \"string\" || !id) return true;\n return lastIndexById.get(id) === index;\n });\n return { ...repo, messages: deduped };\n}\n\nfunction repoMessageContentIsEmpty(content: unknown): boolean {\n if (typeof content === \"string\") return content.trim().length === 0;\n if (!Array.isArray(content)) return true;\n return !content.some((part) => {\n if (!part || typeof part !== \"object\") return false;\n const type = (part as { type?: unknown }).type;\n if (type === \"text\") {\n const text = (part as { text?: unknown }).text;\n return typeof text === \"string\" && text.trim().length > 0;\n }\n return true;\n });\n}\n\nfunction entryWithParentId(\n entry: RepoEntry,\n parentId: string | null,\n): RepoEntry {\n return { ...entry, parentId };\n}\n\nfunction repairRepoLinks<T extends NormalizedRepo>(\n repo: T,\n entries: RepoEntry[],\n): T {\n const seenIds = new Set<string>();\n let previousId: string | null = null;\n const repaired: RepoEntry[] = [];\n\n for (const entry of entries) {\n const id = getRepoMessage(entry)?.id;\n if (typeof id !== \"string\" || !id) continue;\n const requestedParentId = entry.parentId;\n const parentId =\n requestedParentId === null\n ? null\n : typeof requestedParentId === \"string\" &&\n seenIds.has(requestedParentId)\n ? requestedParentId\n : previousId;\n repaired.push(entryWithParentId(entry, parentId));\n seenIds.add(id);\n previousId = id;\n }\n\n const headId =\n typeof repo.headId === \"string\" && seenIds.has(repo.headId)\n ? repo.headId\n : previousId;\n return { ...repo, messages: repaired, headId: headId ?? undefined };\n}\n\nexport function dropEmptyAssistantMessages<T extends NormalizedRepo>(\n repo: T | null | undefined,\n): T | null | undefined {\n if (!repo || !Array.isArray(repo.messages)) return repo;\n\n let changed = false;\n const messages = repo.messages.filter((entry) => {\n const message = getRepoMessage(entry);\n const drop =\n message?.role === \"assistant\" &&\n repoMessageContentIsEmpty(message.content);\n if (drop) changed = true;\n return !drop;\n });\n\n if (!changed) return repo;\n return repairRepoLinks(repo, messages);\n}\n\nexport function isAssistantMessageTerminal(\n message: RepoMessage | null,\n): boolean {\n const statusType = message?.status?.type;\n return statusType === \"complete\" || statusType === \"incomplete\";\n}\n\nexport function repoHasAssistantMessage(\n repo: NormalizedRepo | null | undefined,\n): boolean {\n return getRepoMessages(repo).some(\n (m) => getRepoMessage(m)?.role === \"assistant\",\n );\n}\n\nfunction repoTextLength(repo: NormalizedRepo | null | undefined): number {\n let length = 0;\n for (const entry of getRepoMessages(repo)) {\n const message = getRepoMessage(entry);\n const content = message?.content;\n if (typeof content === \"string\") {\n length += content.length;\n } else if (Array.isArray(content)) {\n for (const part of content) {\n if (part?.type === \"text\" && typeof part.text === \"string\") {\n length += part.text.length;\n }\n }\n }\n }\n return length;\n}\n\nfunction repoTerminalAssistantCount(\n repo: NormalizedRepo | null | undefined,\n): number {\n return getRepoMessages(repo).filter((entry) => {\n const message = getRepoMessage(entry);\n return message?.role === \"assistant\" && isAssistantMessageTerminal(message);\n }).length;\n}\n\nfunction toolCallProgressScore(part: RepoMessageContent): number {\n if (part.type !== \"tool-call\") return 0;\n let score = 1;\n if (part.activity !== true) score += 1;\n if (\"result\" in part) score += 4;\n return score;\n}\n\nfunction repoToolCallProgress(repo: NormalizedRepo | null | undefined): {\n total: number;\n materialized: number;\n completed: number;\n score: number;\n} {\n const progress = {\n total: 0,\n materialized: 0,\n completed: 0,\n score: 0,\n };\n for (const entry of getRepoMessages(repo)) {\n const message = getRepoMessage(entry);\n const content = message?.content;\n if (!Array.isArray(content)) continue;\n for (const part of content) {\n if (part?.type !== \"tool-call\") continue;\n progress.total += 1;\n if (part.activity !== true) progress.materialized += 1;\n if (\"result\" in part) progress.completed += 1;\n progress.score += toolCallProgressScore(part);\n }\n }\n return progress;\n}\n\nexport function shouldImportServerThreadData(\n currentRepo: NormalizedRepo | null | undefined,\n incomingRepo: NormalizedRepo | null | undefined,\n): boolean {\n const incomingCount = getRepoMessages(incomingRepo).length;\n if (incomingCount === 0) return false;\n\n const currentCount = getRepoMessages(currentRepo).length;\n if (currentCount === 0) return true;\n if (incomingCount < currentCount) return false;\n\n if (incomingCount === currentCount) {\n const currentTerminalAssistants = repoTerminalAssistantCount(currentRepo);\n const incomingTerminalAssistants = repoTerminalAssistantCount(incomingRepo);\n if (incomingTerminalAssistants < currentTerminalAssistants) {\n return false;\n }\n if (\n incomingTerminalAssistants <= currentTerminalAssistants &&\n repoTextLength(incomingRepo) < repoTextLength(currentRepo)\n ) {\n return false;\n }\n const currentTools = repoToolCallProgress(currentRepo);\n const incomingTools = repoToolCallProgress(incomingRepo);\n if (\n incomingTools.total < currentTools.total ||\n incomingTools.materialized < currentTools.materialized ||\n incomingTools.completed < currentTools.completed ||\n incomingTools.score < currentTools.score\n ) {\n return false;\n }\n }\n\n return true;\n}\n"]}
@@ -31,10 +31,11 @@ export type ApprovalContextValue = {
31
31
  };
32
32
  export declare const ApprovalContext: React.Context<ApprovalContextValue | null>;
33
33
  export declare const TOOL_LONG_RUNNING_HINT_DELAY_MS = 45000;
34
- export declare function ToolActivityPresentation({ toolName, isRunning, isActiveTail, children, }: {
34
+ export declare function ToolActivityPresentation({ toolName, isRunning, isActiveTail, suppressLongRunningHint, children, }: {
35
35
  toolName: string;
36
36
  isRunning: boolean;
37
37
  isActiveTail: boolean;
38
+ suppressLongRunningHint?: boolean;
38
39
  children: React.ReactNode;
39
40
  }): React.JSX.Element;
40
41
  type ToolDetailSection = "input" | "result";
@@ -1 +1 @@
1
- {"version":3,"file":"tool-call-display.d.ts","sourceRoot":"","sources":["../../../src/client/chat/tool-call-display.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tool-call-display.d.ts","sourceRoot":"","sources":["../../../src/client/chat/tool-call-display.tsx"],"names":[],"mappings":"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"}
@@ -20,14 +20,14 @@ export const ChatRunDurationContext = React.createContext(null);
20
20
  export const ASSISTANT_VISIBLE_TOOL_CALL_LIMIT = 3;
21
21
  export const ApprovalContext = React.createContext(null);
22
22
  export const TOOL_LONG_RUNNING_HINT_DELAY_MS = 45_000;
23
- export function ToolActivityPresentation({ toolName, isRunning, isActiveTail, children, }) {
23
+ export function ToolActivityPresentation({ toolName, isRunning, isActiveTail, suppressLongRunningHint = false, children, }) {
24
24
  const [showLongRunningHint, setShowLongRunningHint] = useState(false);
25
25
  // A batched update can first reveal a tool with its result already attached.
26
26
  // Presentation follows the active chat tail rather than execution state so
27
27
  // that newly revealed completed tools still get their entrance motion.
28
28
  const [animateEntry] = useState(isActiveTail);
29
29
  useEffect(() => {
30
- if (!isRunning) {
30
+ if (!isRunning || suppressLongRunningHint) {
31
31
  setShowLongRunningHint(false);
32
32
  return;
33
33
  }
@@ -36,7 +36,7 @@ export function ToolActivityPresentation({ toolName, isRunning, isActiveTail, ch
36
36
  setShowLongRunningHint(true);
37
37
  }, TOOL_LONG_RUNNING_HINT_DELAY_MS);
38
38
  return () => window.clearTimeout(timeout);
39
- }, [isRunning, toolName]);
39
+ }, [isRunning, suppressLongRunningHint, toolName]);
40
40
  return (_jsxs("div", { className: cn("agent-tool-call", animateEntry && "agent-tool-call--entering"), "data-running": isRunning ? "true" : undefined, children: [children, isRunning && showLongRunningHint && (_jsx("div", { className: "mt-0.5 px-2.5 pb-2 text-[11px] leading-snug text-muted-foreground/80", children: "Still working. Large updates can take a minute or two." }))] }));
41
41
  }
42
42
  function stringifyToolValue(value, pretty = false) {
@@ -243,7 +243,7 @@ export function ToolCallDisplay({ toolName, argsText, args, result, mcpApp, chat
243
243
  // These must be separate components so hook order in ToolCallDisplayGeneric
244
244
  // is always stable (no conditional hook calls).
245
245
  const toolKind = structuredMeta?.toolKind;
246
- const wrapToolDisplay = (children) => (_jsx(ToolActivityPresentation, { toolName: toolName, isRunning: isRunning, isActiveTail: showActiveTail, children: children }));
246
+ const wrapToolDisplay = (children) => (_jsx(ToolActivityPresentation, { toolName: toolName, isRunning: isRunning, isActiveTail: showActiveTail, suppressLongRunningHint: toolName === "call-agent" || toolName.startsWith("agent:"), children: children }));
247
247
  if (toolKind === "bash") {
248
248
  return wrapToolDisplay(_jsx(BashCell, { meta: structuredMeta, output: result, isRunning: isRunning }));
249
249
  }
@@ -376,11 +376,7 @@ function AgentCallCell({ agentName, activity, progress, responseText, isRunning,
376
376
  const tool = activity?.toolCalls?.[index];
377
377
  return (_jsxs(React.Fragment, { children: [reasoningText && (_jsx(ReasoningCell, { text: reasoningText, isStreaming: isRunning &&
378
378
  activity.activePhase === "reasoning" &&
379
- index === activity.reasoning.length - 1, defaultOpen: index === activity.reasoning.length - 1, collapseWhenReplaced: index < activity.toolCalls.length })), tool && (_jsx(ToolCallDisplay, { toolName: tool.name, args: {}, argsText: "", isRunning: tool.status === "running", result: tool.status === "failed"
380
- ? "Failed"
381
- : tool.status === "completed"
382
- ? "Done"
383
- : undefined, isActiveTail: isRunning && index === activity.toolCalls.length - 1 }))] }, `activity-${index}`));
379
+ index === activity.reasoning.length - 1, defaultOpen: index === activity.reasoning.length - 1, collapseWhenReplaced: index < activity.toolCalls.length })), tool && (_jsx(AgentActivityToolCallRow, { tool: tool, isActiveTail: isRunning && index === activity.toolCalls.length - 1 }))] }, `activity-${index}`));
384
380
  }) })) : null;
385
381
  const progressState = progress?.state.replaceAll(/[-_]+/g, " ");
386
382
  const progressText = isRunning && !activity && progress && progressState
@@ -397,6 +393,11 @@ function AgentCallCell({ agentName, activity, progress, responseText, isRunning,
397
393
  return (_jsxs("div", { className: "group/tool my-0.5 w-full", children: [_jsxs("button", { type: "button", onClick: () => setOpen((value) => !value), "aria-expanded": open, className: "flex w-full items-center gap-1.5 rounded-md py-0.5 text-left text-[13px] text-muted-foreground transition-colors hover:text-foreground", children: [isRunning ? (_jsx(IconLoader2, { className: "size-3.5 animate-spin" })) : isError ? (_jsx(IconCircleX, { className: "size-3.5 text-destructive" })) : (_jsx(IconChevronRight, { className: cn("size-3.5 transition-transform", open && "rotate-90") })), _jsx("span", { className: cn("min-w-0 truncate font-normal", isRunning && "agent-running-shimmer"), children: label })] }), _jsx(AnimatedCollapse, { open: open, children: _jsxs("div", { className: "ms-1 border-s border-border/50 ps-2 pt-1", children: [workContent &&
398
394
  (isRunning ? (workContent) : (_jsx(WorkedForSummary, { durationMs: durationMs, children: workContent }))), progressText && (_jsx("p", { className: "ps-5 pb-1 text-xs text-muted-foreground", "data-testid": "agent-call-progress", "aria-live": "polite", children: progressText })), finalText && (_jsx("div", { className: "ps-5 pb-1", children: _jsx(SmoothMarkdownText, { text: finalText, streaming: isRunning, resetKey: `agent-response-${agentName}`, statusType: isRunning ? "running" : "complete" }) }))] }) })] }));
399
395
  }
396
+ function AgentActivityToolCallRow({ tool, isActiveTail, }) {
397
+ const isRunning = tool.status === "running";
398
+ const ToolIcon = resolveToolIcon(tool.name);
399
+ return (_jsx(ToolActivityPresentation, { toolName: tool.name, isRunning: isRunning, isActiveTail: isActiveTail, suppressLongRunningHint: true, children: _jsxs("div", { className: "my-0.5 flex w-full items-center gap-1.5 rounded-md py-0.5 text-left text-[13px] text-muted-foreground", children: [_jsx("span", { className: "flex size-4 shrink-0 items-center justify-center", children: isRunning ? (_jsx(IconLoader2, { className: "size-3.5 animate-spin" })) : (_jsx(ToolIcon, { className: "size-3.5" })) }), _jsx("span", { className: cn("min-w-0 truncate font-normal", isActiveTail && "agent-running-shimmer"), children: humanizeToolName(tool.name) })] }) }));
400
+ }
400
401
  // ─── ToolCallFallback ──────────────────────────────────────────────────────────
401
402
  export function ToolCallFallback({ toolName, args, argsText, result, ...rest }) {
402
403
  const chatRunning = React.useContext(ChatRunningContext);