@agent-native/toolkit 0.221.0-same-host-mcp-20261027-20261027081850 → 0.221.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 (259) hide show
  1. package/agent-native.eject.json +16 -1
  2. package/dist/app/agentkit/react/components.d.ts +5 -3
  3. package/dist/app/agentkit/react/components.d.ts.map +1 -1
  4. package/dist/app/agentkit/react/components.js +103 -42
  5. package/dist/app/agentkit/react/components.js.map +1 -1
  6. package/dist/app/agentkit/react/styles.css +93 -65
  7. package/dist/app/agentkit/react/voice-transcripts.d.ts +22 -1
  8. package/dist/app/agentkit/react/voice-transcripts.d.ts.map +1 -1
  9. package/dist/app/agentkit/react/voice-transcripts.js +209 -8
  10. package/dist/app/agentkit/react/voice-transcripts.js.map +1 -1
  11. package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
  12. package/dist/app/chat/AgentKitAssistantChat.js +55 -40
  13. package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
  14. package/dist/app/chat/agentkit-chat/guided-questions.d.ts +1 -0
  15. package/dist/app/chat/agentkit-chat/guided-questions.d.ts.map +1 -1
  16. package/dist/app/chat/agentkit-chat/guided-questions.js +18 -6
  17. package/dist/app/chat/agentkit-chat/guided-questions.js.map +1 -1
  18. package/dist/app/chat/agentkit-chat/index.d.ts +1 -1
  19. package/dist/app/chat/agentkit-chat/index.d.ts.map +1 -1
  20. package/dist/app/chat/agentkit-chat/index.js +1 -1
  21. package/dist/app/chat/agentkit-chat/index.js.map +1 -1
  22. package/dist/app/chat/chat/run-recovery.d.ts.map +1 -1
  23. package/dist/app/chat/chat/run-recovery.js +5 -1
  24. package/dist/app/chat/chat/run-recovery.js.map +1 -1
  25. package/dist/app/chat/composer/runtime-adapters.d.ts.map +1 -1
  26. package/dist/app/chat/composer/runtime-adapters.js +2 -0
  27. package/dist/app/chat/composer/runtime-adapters.js.map +1 -1
  28. package/dist/app/chat/reply-connection-suggestion.d.ts +29 -0
  29. package/dist/app/chat/reply-connection-suggestion.d.ts.map +1 -0
  30. package/dist/app/chat/reply-connection-suggestion.js +42 -0
  31. package/dist/app/chat/reply-connection-suggestion.js.map +1 -0
  32. package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
  33. package/dist/app/i18n/catalogs/ar-SA.js +7 -0
  34. package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
  35. package/dist/app/i18n/catalogs/de-DE.d.ts.map +1 -1
  36. package/dist/app/i18n/catalogs/de-DE.js +7 -0
  37. package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
  38. package/dist/app/i18n/catalogs/en-US.d.ts +7 -0
  39. package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
  40. package/dist/app/i18n/catalogs/en-US.js +7 -0
  41. package/dist/app/i18n/catalogs/en-US.js.map +1 -1
  42. package/dist/app/i18n/catalogs/es-ES.d.ts.map +1 -1
  43. package/dist/app/i18n/catalogs/es-ES.js +7 -0
  44. package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
  45. package/dist/app/i18n/catalogs/fr-FR.d.ts.map +1 -1
  46. package/dist/app/i18n/catalogs/fr-FR.js +7 -0
  47. package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
  48. package/dist/app/i18n/catalogs/hi-IN.d.ts.map +1 -1
  49. package/dist/app/i18n/catalogs/hi-IN.js +7 -0
  50. package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
  51. package/dist/app/i18n/catalogs/ja-JP.d.ts.map +1 -1
  52. package/dist/app/i18n/catalogs/ja-JP.js +7 -0
  53. package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
  54. package/dist/app/i18n/catalogs/ko-KR.d.ts.map +1 -1
  55. package/dist/app/i18n/catalogs/ko-KR.js +7 -0
  56. package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
  57. package/dist/app/i18n/catalogs/pt-BR.d.ts.map +1 -1
  58. package/dist/app/i18n/catalogs/pt-BR.js +7 -0
  59. package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
  60. package/dist/app/i18n/catalogs/zh-CN.d.ts.map +1 -1
  61. package/dist/app/i18n/catalogs/zh-CN.js +7 -0
  62. package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
  63. package/dist/app/i18n/catalogs/zh-TW.d.ts.map +1 -1
  64. package/dist/app/i18n/catalogs/zh-TW.js +7 -0
  65. package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
  66. package/dist/app/mcp-approval/McpApprovalReview.d.ts +25 -0
  67. package/dist/app/mcp-approval/McpApprovalReview.d.ts.map +1 -0
  68. package/dist/app/mcp-approval/McpApprovalReview.js +342 -0
  69. package/dist/app/mcp-approval/McpApprovalReview.js.map +1 -0
  70. package/dist/app/onboarding/FirstRunOnboarding.d.ts.map +1 -1
  71. package/dist/app/onboarding/FirstRunOnboarding.js +299 -71
  72. package/dist/app/onboarding/FirstRunOnboarding.js.map +1 -1
  73. package/dist/app/onboarding/GettingStartedCard.js +1 -1
  74. package/dist/app/onboarding/GettingStartedCard.js.map +1 -1
  75. package/dist/app/onboarding/first-run-builder-credits-flag.d.ts +2 -0
  76. package/dist/app/onboarding/first-run-builder-credits-flag.d.ts.map +1 -0
  77. package/dist/app/onboarding/first-run-builder-credits-flag.js +8 -0
  78. package/dist/app/onboarding/first-run-builder-credits-flag.js.map +1 -0
  79. package/dist/app/providers/AppProviders.d.ts.map +1 -1
  80. package/dist/app/providers/AppProviders.js +14 -1
  81. package/dist/app/providers/AppProviders.js.map +1 -1
  82. package/dist/app/resources/McpConnectionSuggestion.d.ts +2 -4
  83. package/dist/app/resources/McpConnectionSuggestion.d.ts.map +1 -1
  84. package/dist/app/resources/McpConnectionSuggestion.js +59 -36
  85. package/dist/app/resources/McpConnectionSuggestion.js.map +1 -1
  86. package/dist/app/settings/account/PreferencesSettings.d.ts.map +1 -1
  87. package/dist/app/settings/account/PreferencesSettings.js +14 -1
  88. package/dist/app/settings/account/PreferencesSettings.js.map +1 -1
  89. package/dist/app/settings/account/ThemeFamilySettings.js +2 -2
  90. package/dist/app/settings/account/ThemeFamilySettings.js.map +1 -1
  91. package/dist/app/settings/account/search-entries.d.ts +1 -0
  92. package/dist/app/settings/account/search-entries.d.ts.map +1 -1
  93. package/dist/app/settings/account/search-entries.js +5 -0
  94. package/dist/app/settings/account/search-entries.js.map +1 -1
  95. package/dist/app/settings/shell/SettingsShell.d.ts.map +1 -1
  96. package/dist/app/settings/shell/SettingsShell.js +26 -2
  97. package/dist/app/settings/shell/SettingsShell.js.map +1 -1
  98. package/dist/app/shared/AppShellSkeleton.d.ts.map +1 -1
  99. package/dist/app/shared/AppShellSkeleton.js +4 -10
  100. package/dist/app/shared/AppShellSkeleton.js.map +1 -1
  101. package/dist/app/shared/EnvironmentBadge.d.ts +2 -1
  102. package/dist/app/shared/EnvironmentBadge.d.ts.map +1 -1
  103. package/dist/app/shared/EnvironmentBadge.js +2 -3
  104. package/dist/app/shared/EnvironmentBadge.js.map +1 -1
  105. package/dist/app/shared/is-builder-io-employee.d.ts +8 -0
  106. package/dist/app/shared/is-builder-io-employee.d.ts.map +1 -0
  107. package/dist/app/shared/is-builder-io-employee.js +10 -0
  108. package/dist/app/shared/is-builder-io-employee.js.map +1 -0
  109. package/dist/app/styles/agent-conversation.css +30 -17
  110. package/dist/app/styles/theme-families.css +22 -5
  111. package/dist/app/styles/tokens/agent-kit.css +3 -3
  112. package/dist/composer/PromptComposer.d.ts +15 -3
  113. package/dist/composer/PromptComposer.d.ts.map +1 -1
  114. package/dist/composer/PromptComposer.js +74 -16
  115. package/dist/composer/PromptComposer.js.map +1 -1
  116. package/dist/composer/RealtimeVoiceMode.d.ts +7 -0
  117. package/dist/composer/RealtimeVoiceMode.d.ts.map +1 -1
  118. package/dist/composer/RealtimeVoiceMode.js +9 -2
  119. package/dist/composer/RealtimeVoiceMode.js.map +1 -1
  120. package/dist/composer/TiptapComposer.d.ts +7 -0
  121. package/dist/composer/TiptapComposer.d.ts.map +1 -1
  122. package/dist/composer/TiptapComposer.js +12 -4
  123. package/dist/composer/TiptapComposer.js.map +1 -1
  124. package/dist/composer/VoiceButton.d.ts +2 -0
  125. package/dist/composer/VoiceButton.d.ts.map +1 -1
  126. package/dist/composer/VoiceButton.js +5 -4
  127. package/dist/composer/VoiceButton.js.map +1 -1
  128. package/dist/composer/index.d.ts +2 -2
  129. package/dist/composer/index.d.ts.map +1 -1
  130. package/dist/composer/index.js +1 -1
  131. package/dist/composer/index.js.map +1 -1
  132. package/dist/composer/prompt-attachments.d.ts +20 -0
  133. package/dist/composer/prompt-attachments.d.ts.map +1 -1
  134. package/dist/composer/prompt-attachments.js +188 -11
  135. package/dist/composer/prompt-attachments.js.map +1 -1
  136. package/dist/composer/realtime-voice-transcript.d.ts +27 -0
  137. package/dist/composer/realtime-voice-transcript.d.ts.map +1 -1
  138. package/dist/composer/realtime-voice-transcript.js +34 -1
  139. package/dist/composer/realtime-voice-transcript.js.map +1 -1
  140. package/dist/composer/realtime-voice-turn-metrics.d.ts +43 -0
  141. package/dist/composer/realtime-voice-turn-metrics.d.ts.map +1 -0
  142. package/dist/composer/realtime-voice-turn-metrics.js +132 -0
  143. package/dist/composer/realtime-voice-turn-metrics.js.map +1 -0
  144. package/dist/composer/runtime-adapters.d.ts +4 -1
  145. package/dist/composer/runtime-adapters.d.ts.map +1 -1
  146. package/dist/composer/runtime-adapters.js +2 -1
  147. package/dist/composer/runtime-adapters.js.map +1 -1
  148. package/dist/composer/useRealtimeVoiceMode.d.ts +61 -9
  149. package/dist/composer/useRealtimeVoiceMode.d.ts.map +1 -1
  150. package/dist/composer/useRealtimeVoiceMode.js +536 -99
  151. package/dist/composer/useRealtimeVoiceMode.js.map +1 -1
  152. package/dist/composer/voice-chat-icon.d.ts +7 -0
  153. package/dist/composer/voice-chat-icon.d.ts.map +1 -0
  154. package/dist/composer/voice-chat-icon.js +14 -0
  155. package/dist/composer/voice-chat-icon.js.map +1 -0
  156. package/dist/editor/DragHandle.d.ts +12 -1
  157. package/dist/editor/DragHandle.d.ts.map +1 -1
  158. package/dist/editor/DragHandle.js +165 -41
  159. package/dist/editor/DragHandle.js.map +1 -1
  160. package/dist/editor/RegistryBlockNode.d.ts +20 -0
  161. package/dist/editor/RegistryBlockNode.d.ts.map +1 -1
  162. package/dist/editor/RegistryBlockNode.js +58 -13
  163. package/dist/editor/RegistryBlockNode.js.map +1 -1
  164. package/dist/editor/index.d.ts +2 -2
  165. package/dist/editor/index.d.ts.map +1 -1
  166. package/dist/editor/index.js +1 -1
  167. package/dist/editor/index.js.map +1 -1
  168. package/dist/styles.css +2 -0
  169. package/dist/ui/dropdown-menu.d.ts.map +1 -1
  170. package/dist/ui/dropdown-menu.js +5 -1
  171. package/dist/ui/dropdown-menu.js.map +1 -1
  172. package/package.json +14 -4
  173. package/src/app/agentkit/react/components.regenerate-readiness.spec.tsx +3 -1
  174. package/src/app/agentkit/react/components.spec.tsx +24 -4
  175. package/src/app/agentkit/react/components.tsx +174 -44
  176. package/src/app/agentkit/react/composer-context.spec.tsx +3 -0
  177. package/src/app/agentkit/react/disclosures.spec.tsx +124 -0
  178. package/src/app/agentkit/react/lifecycle.spec.tsx +8 -2
  179. package/src/app/agentkit/react/message-actions.spec.tsx +161 -5
  180. package/src/app/agentkit/react/saved-reply-reload.spec.tsx +206 -0
  181. package/src/app/agentkit/react/styles.css +93 -65
  182. package/src/app/agentkit/react/voice-transcripts.spec.tsx +239 -4
  183. package/src/app/agentkit/react/voice-transcripts.ts +245 -8
  184. package/src/app/chat/AgentKitAssistantChat.spec.tsx +59 -11
  185. package/src/app/chat/AgentKitAssistantChat.tsx +74 -62
  186. package/src/app/chat/agentkit-chat/guided-answers-context.spec.ts +9 -0
  187. package/src/app/chat/agentkit-chat/guided-questions.tsx +17 -7
  188. package/src/app/chat/agentkit-chat/index.ts +1 -0
  189. package/src/app/chat/chat/run-recovery.spec.tsx +45 -0
  190. package/src/app/chat/chat/run-recovery.tsx +6 -1
  191. package/src/app/chat/composer/runtime-adapters.tsx +2 -0
  192. package/src/app/chat/reply-connection-suggestion.spec.ts +121 -0
  193. package/src/app/chat/reply-connection-suggestion.ts +76 -0
  194. package/src/app/i18n/catalogs/ar-SA.ts +10 -0
  195. package/src/app/i18n/catalogs/de-DE.ts +10 -0
  196. package/src/app/i18n/catalogs/en-US.ts +10 -0
  197. package/src/app/i18n/catalogs/es-ES.ts +10 -0
  198. package/src/app/i18n/catalogs/fr-FR.ts +10 -0
  199. package/src/app/i18n/catalogs/hi-IN.ts +10 -0
  200. package/src/app/i18n/catalogs/ja-JP.ts +10 -0
  201. package/src/app/i18n/catalogs/ko-KR.ts +10 -0
  202. package/src/app/i18n/catalogs/pt-BR.ts +10 -0
  203. package/src/app/i18n/catalogs/zh-CN.ts +10 -0
  204. package/src/app/i18n/catalogs/zh-TW.ts +10 -0
  205. package/src/app/mcp-approval/McpApprovalReview.spec.tsx +687 -0
  206. package/src/app/mcp-approval/McpApprovalReview.tsx +913 -0
  207. package/src/app/onboarding/FirstRunOnboarding.spec.tsx +736 -26
  208. package/src/app/onboarding/FirstRunOnboarding.tsx +473 -145
  209. package/src/app/onboarding/GettingStartedCard.tsx +1 -1
  210. package/src/app/onboarding/first-run-builder-credits-flag.spec.ts +13 -0
  211. package/src/app/onboarding/first-run-builder-credits-flag.ts +9 -0
  212. package/src/app/providers/AppProviders.spec.tsx +109 -0
  213. package/src/app/providers/AppProviders.tsx +53 -1
  214. package/src/app/resources/McpConnectionSuggestion.spec.ts +77 -12
  215. package/src/app/resources/McpConnectionSuggestion.tsx +69 -51
  216. package/src/app/settings/VoiceChatSettings.spec.tsx +6 -1
  217. package/src/app/settings/account/PreferencesSettings.spec.tsx +73 -0
  218. package/src/app/settings/account/PreferencesSettings.tsx +24 -7
  219. package/src/app/settings/account/ThemeFamilySettings.tsx +2 -2
  220. package/src/app/settings/account/search-entries.spec.ts +14 -0
  221. package/src/app/settings/account/search-entries.ts +9 -0
  222. package/src/app/settings/shell/SettingsShell.tsx +29 -2
  223. package/src/app/shared/AppShellSkeleton.spec.tsx +2 -2
  224. package/src/app/shared/AppShellSkeleton.tsx +3 -16
  225. package/src/app/shared/EnvironmentBadge.tsx +3 -4
  226. package/src/app/shared/is-builder-io-employee.ts +17 -0
  227. package/src/app/styles/agent-conversation.css +30 -17
  228. package/src/app/styles/theme-families.css +22 -5
  229. package/src/app/styles/theme-families.spec.ts +73 -0
  230. package/src/app/styles/tokens/agent-kit.css +3 -3
  231. package/src/composer/AgentSuggestionBar.overflow.spec.tsx +1 -1
  232. package/src/composer/AttachmentChip.spec.tsx +87 -0
  233. package/src/composer/PromptComposer.context.spec.tsx +8 -4
  234. package/src/composer/PromptComposer.setup-card.spec.tsx +170 -0
  235. package/src/composer/PromptComposer.tsx +125 -14
  236. package/src/composer/RealtimeVoiceMode.spec.tsx +48 -0
  237. package/src/composer/RealtimeVoiceMode.tsx +45 -2
  238. package/src/composer/TiptapComposer.tsx +25 -0
  239. package/src/composer/TiptapComposer.voice-toolbar.spec.tsx +4 -1
  240. package/src/composer/VoiceButton.tsx +8 -3
  241. package/src/composer/index.ts +4 -0
  242. package/src/composer/prompt-attachments.spec.ts +160 -8
  243. package/src/composer/prompt-attachments.ts +221 -12
  244. package/src/composer/realtime-voice-transcript.spec.ts +36 -0
  245. package/src/composer/realtime-voice-transcript.ts +56 -1
  246. package/src/composer/realtime-voice-turn-metrics.spec.ts +175 -0
  247. package/src/composer/realtime-voice-turn-metrics.ts +192 -0
  248. package/src/composer/runtime-adapters.tsx +5 -1
  249. package/src/composer/useRealtimeVoiceMode.session.spec.tsx +487 -2
  250. package/src/composer/useRealtimeVoiceMode.spec.ts +267 -65
  251. package/src/composer/useRealtimeVoiceMode.tsx +716 -139
  252. package/src/composer/voice-chat-icon.tsx +19 -0
  253. package/src/editor/DragHandle.spec.ts +217 -0
  254. package/src/editor/DragHandle.ts +214 -55
  255. package/src/editor/RegistryBlockNode.spec.ts +172 -2
  256. package/src/editor/RegistryBlockNode.tsx +91 -13
  257. package/src/editor/index.ts +4 -0
  258. package/src/styles.css +2 -0
  259. package/src/ui/dropdown-menu.tsx +4 -0
@@ -1,8 +1,10 @@
1
1
  import { hasActiveAgentRuns, } from "@agent-native/agentkit/client";
2
+ import { inferAgentActivityKind, } from "@agent-native/agentkit/protocol";
2
3
  import { useEffect } from "react";
3
- import { realtimeVoiceTranscriptRegistry, } from "../../../composer/realtime-voice-transcript.js";
4
+ import { realtimeVoiceToolLabel, realtimeVoiceTranscriptRegistry, } from "../../../composer/realtime-voice-transcript.js";
4
5
  import { isChatThreadViewed } from "./viewed-threads.js";
5
6
  const REALTIME_VOICE_MESSAGE_SOURCE = "realtime-voice";
7
+ const VOICE_RUN_PREFIX = "voice:";
6
8
  function realtimeVoiceTranscriptMessage(transcript) {
7
9
  const createdAt = new Date(transcript.createdAt);
8
10
  return {
@@ -16,6 +18,146 @@ function realtimeVoiceTranscriptMessage(transcript) {
16
18
  metadata: { custom: { source: REALTIME_VOICE_MESSAGE_SOURCE } },
17
19
  };
18
20
  }
21
+ /**
22
+ * The events a voice reply's work still needs in its thread, as one local
23
+ * run. The run never starts on the server, so it never counts as an active
24
+ * run that would hold the composer or the transcript. `existingIds` and
25
+ * `lastSequence` describe the run as the thread already has it.
26
+ */
27
+ export function realtimeVoiceWorkEvents(update, existingIds = new Set(), lastSequence = 0) {
28
+ const runId = `${VOICE_RUN_PREFIX}${update.id}`;
29
+ const base = (id, occurredAt) => ({
30
+ id: `${runId}:${id}`,
31
+ threadId: update.threadId,
32
+ runId,
33
+ // Numbered below, once the events this run already has are left out.
34
+ sequence: 0,
35
+ occurredAt,
36
+ });
37
+ const steps = [];
38
+ for (const call of update.calls) {
39
+ const toolCall = {
40
+ id: call.id,
41
+ name: call.name,
42
+ status: "running",
43
+ runId,
44
+ ...(call.input ? { input: call.input } : {}),
45
+ };
46
+ const activity = {
47
+ id: call.id,
48
+ kind: inferAgentActivityKind(call.name),
49
+ label: realtimeVoiceToolLabel(call.name),
50
+ status: "running",
51
+ runId,
52
+ startedAt: call.startedAt,
53
+ };
54
+ steps.push({
55
+ at: call.startedAt,
56
+ event: {
57
+ ...base(`${call.id}:tool-started`, call.startedAt),
58
+ type: "tool.started",
59
+ toolCall,
60
+ },
61
+ }, {
62
+ at: call.startedAt,
63
+ event: {
64
+ ...base(`${call.id}:activity-started`, call.startedAt),
65
+ type: "activity.started",
66
+ activity,
67
+ },
68
+ });
69
+ const { completedAt } = call;
70
+ if (!completedAt || call.status === "running")
71
+ continue;
72
+ steps.push({
73
+ at: completedAt,
74
+ event: {
75
+ ...base(`${call.id}:tool-ended`, completedAt),
76
+ type: "tool.updated",
77
+ toolCall: {
78
+ ...toolCall,
79
+ status: call.status,
80
+ ...(call.output !== undefined ? { output: call.output } : {}),
81
+ },
82
+ },
83
+ }, {
84
+ at: completedAt,
85
+ event: {
86
+ ...base(`${call.id}:activity-ended`, completedAt),
87
+ type: "activity.completed",
88
+ activity: { ...activity, status: call.status, completedAt },
89
+ },
90
+ });
91
+ }
92
+ // Stable: a call's start keeps its place before its end at the same time.
93
+ steps.sort((left, right) => Date.parse(left.at) - Date.parse(right.at));
94
+ if (update.completedAt) {
95
+ steps.push({
96
+ at: update.completedAt,
97
+ event: {
98
+ ...base("completed", update.completedAt),
99
+ type: "run.completed",
100
+ },
101
+ });
102
+ }
103
+ let sequence = lastSequence;
104
+ return steps
105
+ .filter(({ event }) => !existingIds.has(event.id))
106
+ .map(({ event }) => ({ ...event, sequence: ++sequence }));
107
+ }
108
+ /**
109
+ * Voice work this page is still running, by thread. Saved work that is not
110
+ * here can never finish, so it is closed instead of waited on.
111
+ */
112
+ const runningVoiceWork = new Map();
113
+ function voiceRunPosition(thread, runId) {
114
+ return {
115
+ existingIds: new Set(thread.events
116
+ .filter((event) => event.runId === runId)
117
+ .map((event) => event.id)),
118
+ lastSequence: new Map(Object.entries(thread.runs)).get(runId)?.lastSequence ?? 0,
119
+ };
120
+ }
121
+ /**
122
+ * The events that end, as cancelled, every voice run in `thread` with no
123
+ * terminal event. A snapshot saved while a call ran keeps such a run after a
124
+ * reload, and nothing is left to finish it.
125
+ */
126
+ export function orphanedVoiceWorkEvents(thread, threadId, completedAt = new Date().toISOString()) {
127
+ const runs = new Map();
128
+ for (const event of thread.events) {
129
+ if (!event.runId.startsWith(VOICE_RUN_PREFIX))
130
+ continue;
131
+ const run = runs.get(event.runId) ?? { calls: [], completed: false };
132
+ runs.set(event.runId, run);
133
+ if (event.type === "run.completed")
134
+ run.completed = true;
135
+ if (event.type !== "tool.started")
136
+ continue;
137
+ const { input } = event.toolCall;
138
+ run.calls.push({
139
+ id: event.toolCall.id,
140
+ name: event.toolCall.name,
141
+ status: "cancelled",
142
+ startedAt: event.occurredAt,
143
+ completedAt,
144
+ ...(input && typeof input === "object" && !Array.isArray(input)
145
+ ? { input: input }
146
+ : {}),
147
+ });
148
+ }
149
+ return [...runs]
150
+ .filter(([, run]) => !run.completed)
151
+ .flatMap(([runId, run]) => {
152
+ const { existingIds, lastSequence } = voiceRunPosition(thread, runId);
153
+ return realtimeVoiceWorkEvents({
154
+ id: runId.slice(VOICE_RUN_PREFIX.length),
155
+ threadId,
156
+ calls: run.calls,
157
+ completedAt,
158
+ }, existingIds, lastSequence);
159
+ });
160
+ }
19
161
  /** A voice chat turn still being spoken; hosts must not save it. */
20
162
  export function isStreamingVoiceMessage(message) {
21
163
  const custom = message.metadata?.custom;
@@ -32,9 +174,69 @@ export function useRealtimeVoiceTranscripts(controller, threadId, running) {
32
174
  if (!threadId || !controller.upsertLocalMessages)
33
175
  return;
34
176
  const upsert = controller.upsertLocalMessages.bind(controller);
35
- return realtimeVoiceTranscriptRegistry.register({
177
+ const appendEvents = controller.appendLocalEvents?.bind(controller);
178
+ /** False when the thread could not be checked yet. */
179
+ const closeOrphanedWork = () => {
180
+ if (!appendEvents || runningVoiceWork.get(threadId)?.size)
181
+ return false;
182
+ const thread = controller.getThread(threadId);
183
+ if (hasActiveAgentRuns(thread))
184
+ return false;
185
+ const events = orphanedVoiceWorkEvents(thread, threadId);
186
+ if (events.length > 0)
187
+ appendEvents(threadId, events);
188
+ return true;
189
+ };
190
+ const persist = () => {
191
+ // The work's completion saves the thread, this turn included.
192
+ if (runningVoiceWork.get(threadId)?.size)
193
+ return;
194
+ closeOrphanedWork();
195
+ const messages = controller
196
+ .getThread(threadId)
197
+ .messages.filter((message) => !isStreamingVoiceMessage(message));
198
+ // A failed save surfaces through the controller's connection error;
199
+ // a host without transport persistence saves the thread itself.
200
+ void controller.persistThreadSnapshotWithResult?.(threadId, messages);
201
+ };
202
+ // The thread's snapshot can land after this mounts, so check each time
203
+ // its events change rather than once.
204
+ let checkedEventCount = -1;
205
+ const closeOrphanedWorkOnChange = () => {
206
+ const { length } = controller.getThread(threadId).events;
207
+ if (length === checkedEventCount)
208
+ return;
209
+ if (closeOrphanedWork())
210
+ checkedEventCount = length;
211
+ };
212
+ closeOrphanedWorkOnChange();
213
+ const unsubscribe = controller.subscribe(closeOrphanedWorkOnChange);
214
+ const unregister = realtimeVoiceTranscriptRegistry.register({
36
215
  threadId,
37
216
  active: () => isChatThreadViewed(threadId),
217
+ ...(appendEvents
218
+ ? {
219
+ appendWork: (update) => {
220
+ if (hasActiveAgentRuns(controller.getThread(threadId))) {
221
+ return false;
222
+ }
223
+ const runId = `${VOICE_RUN_PREFIX}${update.id}`;
224
+ const { existingIds, lastSequence } = voiceRunPosition(controller.getThread(threadId), runId);
225
+ const running = runningVoiceWork.get(threadId) ?? new Set();
226
+ runningVoiceWork.set(threadId, running);
227
+ // Marked before the append notifies, so its own events never
228
+ // read as orphaned.
229
+ if (!update.completedAt)
230
+ running.add(runId);
231
+ appendEvents(threadId, realtimeVoiceWorkEvents(update, existingIds, lastSequence));
232
+ if (update.completedAt) {
233
+ running.delete(runId);
234
+ persist();
235
+ }
236
+ return true;
237
+ },
238
+ }
239
+ : {}),
38
240
  append: (transcript) => {
39
241
  // A run owns the thread snapshot while it streams; the turn waits in
40
242
  // the registry and lands when this sink re-registers after the run.
@@ -43,15 +245,14 @@ export function useRealtimeVoiceTranscripts(controller, threadId, running) {
43
245
  upsert(threadId, [realtimeVoiceTranscriptMessage(transcript)]);
44
246
  if (transcript.status === "streaming")
45
247
  return true;
46
- const messages = controller
47
- .getThread(threadId)
48
- .messages.filter((message) => !isStreamingVoiceMessage(message));
49
- // A failed save surfaces through the controller's connection error;
50
- // a host without transport persistence saves the thread itself.
51
- void controller.persistThreadSnapshotWithResult?.(threadId, messages);
248
+ persist();
52
249
  return true;
53
250
  },
54
251
  });
252
+ return () => {
253
+ unsubscribe();
254
+ unregister();
255
+ };
55
256
  }, [controller, threadId, running]);
56
257
  }
57
258
  //# sourceMappingURL=voice-transcripts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"voice-transcripts.js","sourceRoot":"","sources":["../../../../src/app/agentkit/react/voice-transcripts.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,GAEnB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,OAAO,EACL,+BAA+B,GAEhC,MAAM,gDAAgD,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,6BAA6B,GAAG,gBAAgB,CAAC;AAEvD,SAAS,8BAA8B,CACrC,UAA0C;IAE1C,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACjD,OAAO;QACL,EAAE,EAAE,UAAU,CAAC,EAAE;QACjB,IAAI,EAAE,UAAU,CAAC,IAAI;QACrB,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,CAAC;QAChD,MAAM,EAAE,UAAU,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU;QACpE,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;YAC1C,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC1B,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE;QAC3B,QAAQ,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,6BAA6B,EAAE,EAAE;KAChE,CAAC;AACJ,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,uBAAuB,CAAC,OAAqB;IAC3D,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,MAA0C,CAAC;IAC5E,OAAO,CACL,OAAO,CAAC,MAAM,KAAK,WAAW;QAC9B,MAAM,EAAE,MAAM,KAAK,6BAA6B,CACjD,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CACzC,UAA8B,EAC9B,QAA4B,EAC5B,OAAgB;IAEhB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,QAAQ,IAAI,CAAC,UAAU,CAAC,mBAAmB;YAAE,OAAO;QACzD,MAAM,MAAM,GAAG,UAAU,CAAC,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC/D,OAAO,+BAA+B,CAAC,QAAQ,CAAC;YAC9C,QAAQ;YACR,MAAM,EAAE,GAAG,EAAE,CAAC,kBAAkB,CAAC,QAAQ,CAAC;YAC1C,MAAM,EAAE,CAAC,UAAU,EAAE,EAAE;gBACrB,qEAAqE;gBACrE,oEAAoE;gBACpE,IAAI,kBAAkB,CAAC,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;oBAAE,OAAO,KAAK,CAAC;gBACrE,MAAM,CAAC,QAAQ,EAAE,CAAC,8BAA8B,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;gBAC/D,IAAI,UAAU,CAAC,MAAM,KAAK,WAAW;oBAAE,OAAO,IAAI,CAAC;gBACnD,MAAM,QAAQ,GAAG,UAAU;qBACxB,SAAS,CAAC,QAAQ,CAAC;qBACnB,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,uBAAuB,CAAC,OAAO,CAAC,CAAC,CAAC;gBACnE,oEAAoE;gBACpE,gEAAgE;gBAChE,KAAK,UAAU,CAAC,+BAA+B,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;gBACtE,OAAO,IAAI,CAAC;YACd,CAAC;SACF,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AACtC,CAAC"}
1
+ {"version":3,"file":"voice-transcripts.js","sourceRoot":"","sources":["../../../../src/app/agentkit/react/voice-transcripts.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"AgentKitAssistantChat.d.ts","sourceRoot":"","sources":["../../../src/app/chat/AgentKitAssistantChat.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AgentKitAssistantChat.d.ts","sourceRoot":"","sources":["../../../src/app/chat/AgentKitAssistantChat.tsx"],"names":[],"mappings":"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"}
@@ -56,6 +56,7 @@ import { fallbackChatTitle } from "./fallback-chat-title.js";
56
56
  import { formatFeedbackReport } from "./feedback-report.js";
57
57
  import { FileStorageSetupPopover } from "./FileStorageSetupPopover.js";
58
58
  import { isWaitingOnApprovalRequest, isWaitingOnConnectionRequest, reconcileSettledRun, } from "./reconcile-settled-run.js";
59
+ import { pickReplyConnectionSuggestion, latestReplyContext, } from "./reply-connection-suggestion.js";
59
60
  import { RunStuckBanner } from "./RunStuckBanner.js";
60
61
  import { SESSION_REPLAY_MASK_PROPS } from "./session-replay-privacy.js";
61
62
  import { ThinkingDisplayProvider } from "./thinking-display.js";
@@ -1522,7 +1523,19 @@ const AgentKitAssistantChatBody = forwardRef(function AgentKitAssistantChatBody(
1522
1523
  const modelListUnavailable = props.showModelSelector !== false && props.modelListError === true;
1523
1524
  const effectiveReadiness = readiness.state;
1524
1525
  const canChat = !providerChecksEnabled || effectiveReadiness === "configured";
1525
- const setupMissing = providerChecksEnabled && effectiveReadiness === "missing";
1526
+ const [composerSetupRequired, setComposerSetupRequired] = useState(false);
1527
+ const setupConfirmedMissing = providerChecksEnabled && effectiveReadiness === "missing";
1528
+ // The composer's model list knows nothing is connected well before the
1529
+ // readiness check answers; an answer of "configured" still wins. Only this
1530
+ // chat's own card can show on that guess: a host-owned card waits for the
1531
+ // server, and acting on the guess without it closes the prompt with nothing
1532
+ // on screen to explain why.
1533
+ const ownsSetupCard = props.showMissingApiKeySetup !== false && props.setupCardOwner !== "host";
1534
+ const setupMissing = setupConfirmedMissing ||
1535
+ (providerChecksEnabled &&
1536
+ ownsSetupCard &&
1537
+ effectiveReadiness !== "configured" &&
1538
+ composerSetupRequired);
1526
1539
  const providerStatus = setupMissing
1527
1540
  ? "missing"
1528
1541
  : modelListUnavailable
@@ -3518,6 +3531,7 @@ const AgentKitAssistantChatBody = forwardRef(function AgentKitAssistantChatBody(
3518
3531
  hasRenderedMessages,
3519
3532
  canChat,
3520
3533
  setupMissing,
3534
+ setupConfirmedMissing,
3521
3535
  providerStatus,
3522
3536
  modelListUnavailable,
3523
3537
  retryProviderStatus,
@@ -3538,6 +3552,7 @@ const AgentKitAssistantChatBody = forwardRef(function AgentKitAssistantChatBody(
3538
3552
  authSessionAvailable,
3539
3553
  setupBouncePulse,
3540
3554
  bounceSetupCard,
3555
+ onComposerSetupRequiredChange: setComposerSetupRequired,
3541
3556
  isSubmissionInFlight,
3542
3557
  composerSubmissionPending,
3543
3558
  onComposerSubmissionPendingChange: setComposerSubmissionPending,
@@ -3793,7 +3808,7 @@ class AgentKitComposerContextError extends Error {
3793
3808
  this.name = "AgentKitComposerContextError";
3794
3809
  }
3795
3810
  }
3796
- function AgentKitComposerSurface({ threadId, props, composerContext, canChat, setupMissing, providerStatus, modelListUnavailable, retryProviderStatus, retryModelList, fileStorageConfigured, fileStorageMissing, retryFileStorageStatus, deferredSubmissionFailed, deferredSubmissionRequiresAttachment, retryDeferredSubmission, dismissDeferredSubmission, isRunning, isRestoring, isSubmissionInFlight, composerSubmissionPending, onComposerSubmissionPendingChange, isThinkingVisibleInTranscript, hasRenderedMessages, threadRestore, suggestions, showSuggestions, setupBouncePulse, bounceSetupCard, contextItems, providerContextItems, selectionLength, prefillRevision, text, onTextChange, onRemoveContextItem, onClearSelection, onSubmit, submitSuggestion, suggestionSubmitRef, onImplementPlan, }) {
3811
+ function AgentKitComposerSurface({ threadId, props, composerContext, canChat, setupMissing, providerStatus, modelListUnavailable, retryProviderStatus, retryModelList, fileStorageConfigured, fileStorageMissing, retryFileStorageStatus, deferredSubmissionFailed, deferredSubmissionRequiresAttachment, retryDeferredSubmission, dismissDeferredSubmission, isRunning, isRestoring, isSubmissionInFlight, composerSubmissionPending, onComposerSubmissionPendingChange, isThinkingVisibleInTranscript, hasRenderedMessages, threadRestore, suggestions, showSuggestions, setupBouncePulse, bounceSetupCard, onComposerSetupRequiredChange, contextItems, providerContextItems, selectionLength, prefillRevision, text, onTextChange, onRemoveContextItem, onClearSelection, onSubmit, submitSuggestion, suggestionSubmitRef, onImplementPlan, }) {
3797
3812
  const t = useT();
3798
3813
  const [composerError, setComposerError] = useState(null);
3799
3814
  useEffect(() => setComposerError(null), [threadId]);
@@ -3964,12 +3979,6 @@ function AgentKitComposerSurface({ threadId, props, composerContext, canChat, se
3964
3979
  },
3965
3980
  onError: (error) => setComposerError(error.message),
3966
3981
  });
3967
- const integration = findMcpConnectionSuggestionIntegration({
3968
- text,
3969
- variant: "composer",
3970
- requestedByUser: true,
3971
- excludedIntegrationIds: props.mcpSuggestionExcludedIntegrationIds,
3972
- });
3973
3982
  const showHomeIntro = props.homeIntroSlot &&
3974
3983
  !hasRenderedMessages &&
3975
3984
  threadRestore.status === "ready";
@@ -4007,7 +4016,7 @@ function AgentKitComposerSurface({ threadId, props, composerContext, canChat, se
4007
4016
  props.showMissingApiKeySetup !== false &&
4008
4017
  props.setupCardOwner !== "host" ? (_jsx(BuilderSetupCard, { fullWidth: true, attached: true, bouncePulse: setupBouncePulse, layout: props.missingApiKeySetupLayout ?? "default", onConnected: () => window.dispatchEvent(new Event("agent-engine:configured-changed")) })) : null, !setupMissing &&
4009
4018
  (modelListUnavailable ||
4010
- (!canChat && providerStatus !== "configured")) ? (_jsx(GuidedQuestionProviderGate, { providerStatus: providerStatus, modelListUnavailable: modelListUnavailable, onRetry: modelListUnavailable ? retryModelList : retryProviderStatus })) : null, integration ? (_jsx(McpConnectionSuggestion, { text: text, variant: "composer", requestedByUser: true, excludedIntegrationIds: props.mcpSuggestionExcludedIntegrationIds, integrationId: integration.id })) : null, selectionLength !== null && selectionLength > 0 ? (_jsx(AgentKitSelectionPill, { length: selectionLength, onClear: onClearSelection })) : null, showSuggestionsSlot ? (_jsx("div", { className: "agentkit-host-suggestions-slot", "data-agentkit-host-suggestions-slot": "true", children: showSuggestions && suggestions.length > 0 ? (_jsx(AgentKitSuggestedPrompts, { suggestions: suggestions, disabled: !canChat ||
4019
+ (!canChat && providerStatus !== "configured")) ? (_jsx(GuidedQuestionProviderGate, { providerStatus: providerStatus, modelListUnavailable: modelListUnavailable, onRetry: modelListUnavailable ? retryModelList : retryProviderStatus })) : null, selectionLength !== null && selectionLength > 0 ? (_jsx(AgentKitSelectionPill, { length: selectionLength, onClear: onClearSelection })) : null, showSuggestionsSlot ? (_jsx("div", { className: "agentkit-host-suggestions-slot", "data-agentkit-host-suggestions-slot": "true", children: showSuggestions && suggestions.length > 0 ? (_jsx(AgentKitSuggestedPrompts, { suggestions: suggestions, disabled: !canChat ||
4011
4020
  props.composerDisabled ||
4012
4021
  props.composerSubmissionDisabled ||
4013
4022
  isSubmissionInFlight ||
@@ -4022,7 +4031,7 @@ function AgentKitComposerSurface({ threadId, props, composerContext, canChat, se
4022
4031
  window.dispatchEvent(new CustomEvent("agent-chat:missing-api-key", {
4023
4032
  detail: { tabId: props.tabId, threadId },
4024
4033
  }));
4025
- }, initialText: text, initialTextKey: `${props.tabId ?? threadId}:${prefillRevision}`, showMissingApiKeySetup: false, setupCardVisible: composerShowsSetupCard({ setupMissing, props }), onTextChange: onTextChange, announcePendingSubmission: !isThinkingVisibleInTranscript, onSubmissionPendingChange: onComposerSubmissionPendingChange, contextItems: visibleContextItems, contextMenuItems: composerContext?.menuItems, onRemoveContextItem: (key) => {
4034
+ }, initialText: text, initialTextKey: `${props.tabId ?? threadId}:${prefillRevision}`, showMissingApiKeySetup: false, setupCardVisible: composerShowsSetupCard({ setupMissing, props }), onModelConnectionRequiredChange: onComposerSetupRequiredChange, onTextChange: onTextChange, announcePendingSubmission: !isThinkingVisibleInTranscript, onSubmissionPendingChange: onComposerSubmissionPendingChange, contextItems: visibleContextItems, contextMenuItems: composerContext?.menuItems, onRemoveContextItem: (key) => {
4026
4035
  if (providerContextKeys.has(key))
4027
4036
  composerContext?.onRemoveContextItem(key);
4028
4037
  else
@@ -4069,50 +4078,54 @@ function AgentKitUserMessage(props) {
4069
4078
  };
4070
4079
  return _jsx(AgentMessageView, { ...props, value: visible });
4071
4080
  }
4072
- const NO_SUGGESTION_CONTEXT = { runsActive: true };
4073
- function latestUserMessageBefore(messages, messageId) {
4074
- const index = messages.findIndex((message) => message.id === messageId);
4075
- return messages
4076
- .slice(0, Math.max(0, index))
4077
- .findLast((message) => message.role === "user");
4078
- }
4081
+ const NO_SUGGESTION_CONTEXT = {
4082
+ isLatest: false,
4083
+ userText: "",
4084
+ agentRequestedProviders: "",
4085
+ runsActive: true,
4086
+ };
4079
4087
  function AgentKitMessageSupplement(props) {
4080
4088
  const value = props.value;
4081
4089
  const t = useT();
4082
4090
  const surface = useAgentKitSurface();
4083
- const offersSuggestion = value.role === "assistant" && value.status === "complete";
4091
+ const isAssistant = value.role === "assistant";
4084
4092
  // Every row renders this, so it reads only what it shows; a whole-thread
4085
4093
  // subscription would re-render every row on every streamed delta.
4086
- const { latestUser, runsActive } = useAgentThreadSelector((thread) => offersSuggestion
4087
- ? {
4088
- latestUser: latestUserMessageBefore(thread.messages, value.id),
4089
- runsActive: hasActiveAgentRuns(thread),
4090
- }
4091
- : NO_SUGGESTION_CONTEXT, (previous, next) => previous.latestUser === next.latestUser &&
4094
+ const suggestion = useAgentThreadSelector((thread) => {
4095
+ const context = isAssistant
4096
+ ? latestReplyContext(thread, value.id)
4097
+ : undefined;
4098
+ return context?.isLatest
4099
+ ? { ...context, runsActive: hasActiveAgentRuns(thread) }
4100
+ : NO_SUGGESTION_CONTEXT;
4101
+ }, (previous, next) => previous.isLatest === next.isLatest &&
4102
+ previous.userText === next.userText &&
4103
+ previous.agentRequestedProviders === next.agentRequestedProviders &&
4092
4104
  previous.runsActive === next.runsActive, props.threadId);
4093
- const contextText = latestUser?.parts
4094
- .filter((part) => part.type === "text")
4095
- .map((part) => part.type === "text"
4096
- ? splitAgentChatContextFromMessage(part.text).message
4097
- : "")
4098
- .join("\n") ?? "";
4099
4105
  const text = value.parts
4100
4106
  .filter((part) => part.type === "text")
4101
4107
  .map((part) => (part.type === "text" ? part.text : ""))
4102
4108
  .join("\n");
4103
- const integration = offersSuggestion && !runsActive
4104
- ? findMcpConnectionSuggestionIntegration({
4105
- text,
4106
- contextText,
4107
- variant: "response",
4108
- requestedByAgent: true,
4109
- excludedIntegrationIds: surface.props.mcpSuggestionExcludedIntegrationIds,
4109
+ const excludedIntegrationIds = surface.props.mcpSuggestionExcludedIntegrationIds;
4110
+ const replyFinished = value.status === "complete" && !suggestion.runsActive;
4111
+ // The streaming row re-renders on every delta; its ask is read once done.
4112
+ const replyText = replyFinished ? text : "";
4113
+ const integration = useMemo(() => isAssistant
4114
+ ? pickReplyConnectionSuggestion({
4115
+ context: suggestion,
4116
+ replyText,
4117
+ replyFinished,
4118
+ find: (message) => findMcpConnectionSuggestionIntegration({
4119
+ text: message,
4120
+ variant: "response",
4121
+ ...(excludedIntegrationIds ? { excludedIntegrationIds } : {}),
4122
+ }),
4110
4123
  })
4111
- : null;
4124
+ : null, [excludedIntegrationIds, isAssistant, replyFinished, replyText, suggestion]);
4112
4125
  const runWarning = asRecord(asRecord(value.metadata?.custom)?.runWarning);
4113
4126
  const missingFinalResponse = runWarning?.errorCode === "final_response_missing_after_tool";
4114
4127
  const loopBreakerStopped = runWarning?.errorCode === "tool_loop_stopped";
4115
- return (_jsxs(_Fragment, { children: [missingFinalResponse ? (_jsx("div", { className: "rounded-md border border-amber-500/25 bg-amber-500/[0.06] px-3 py-2 text-xs text-muted-foreground", role: "status", children: t("agentChat.message.missingFinal") })) : null, loopBreakerStopped ? (_jsx("div", { className: "rounded-md border border-amber-500/25 bg-amber-500/[0.06] px-3 py-2 text-xs text-muted-foreground", role: "status", children: _jsx("span", { children: t("agentChat.error.stopped") }) })) : null, value.role === "assistant" && value.status === "complete" ? (_jsxs(_Fragment, { children: [_jsx(AgentKitFilesChangedSummary, { ...props }), _jsx(AgentKitDevCheckpointRestore, { message: value })] })) : null, integration ? (_jsx(McpConnectionSuggestion, { text: text, contextText: contextText, variant: "response", requestedByAgent: true, excludedIntegrationIds: surface.props.mcpSuggestionExcludedIntegrationIds, integrationId: integration.id })) : null] }));
4128
+ return (_jsxs(_Fragment, { children: [missingFinalResponse ? (_jsx("div", { className: "rounded-md border border-amber-500/25 bg-amber-500/[0.06] px-3 py-2 text-xs text-muted-foreground", role: "status", children: t("agentChat.message.missingFinal") })) : null, loopBreakerStopped ? (_jsx("div", { className: "rounded-md border border-amber-500/25 bg-amber-500/[0.06] px-3 py-2 text-xs text-muted-foreground", role: "status", children: _jsx("span", { children: t("agentChat.error.stopped") }) })) : null, value.role === "assistant" && value.status === "complete" ? (_jsxs(_Fragment, { children: [_jsx(AgentKitFilesChangedSummary, { ...props }), _jsx(AgentKitDevCheckpointRestore, { message: value })] })) : null, integration ? (_jsx(McpConnectionSuggestion, { text: text, contextText: suggestion.userText, variant: "response", requestedByAgent: true, excludedIntegrationIds: surface.props.mcpSuggestionExcludedIntegrationIds, integrationId: integration.id })) : null] }));
4116
4129
  }
4117
4130
  function AgentKitTool({ value, active }) {
4118
4131
  const surface = useAgentKitSurface();
@@ -4362,7 +4375,9 @@ function AgentKitRunFailure({ error, runId, threadId, }) {
4362
4375
  function useResumeAfterAiSetup(resendKey, enabled, resend) {
4363
4376
  const surface = useAgentKitSurface();
4364
4377
  const sawSetupMissingRef = useRef(false);
4365
- if (surface.setupMissing)
4378
+ // A resend fires without a fresh user action, so only the server's answer
4379
+ // arms it; the model list's early guess can be briefly wrong.
4380
+ if (surface.setupConfirmedMissing)
4366
4381
  sawSetupMissingRef.current = true;
4367
4382
  const latestRef = useRef({ resendKey, enabled, resend });
4368
4383
  latestRef.current = { resendKey, enabled, resend };