@agent-native/core 0.91.0 → 0.91.2

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 (219) hide show
  1. package/blueprints/action/crud.md +1 -1
  2. package/blueprints/channel/discord.md +1 -1
  3. package/blueprints/provider/stripe.md +1 -1
  4. package/blueprints/sandbox/docker.md +1 -1
  5. package/corpus/README.md +1 -1
  6. package/corpus/core/CHANGELOG.md +26 -0
  7. package/corpus/core/blueprints/action/crud.md +1 -1
  8. package/corpus/core/blueprints/channel/discord.md +1 -1
  9. package/corpus/core/blueprints/provider/stripe.md +1 -1
  10. package/corpus/core/blueprints/sandbox/docker.md +1 -1
  11. package/corpus/core/package.json +6 -5
  12. package/corpus/core/src/agent/run-manager.ts +23 -2
  13. package/corpus/core/src/agent/run-store.ts +2 -2
  14. package/corpus/core/src/cli/add.ts +1 -1
  15. package/corpus/core/src/cli/create.ts +8 -3
  16. package/corpus/core/src/cli/design-connect.ts +53 -9
  17. package/corpus/core/src/cli/index.ts +5 -4
  18. package/corpus/core/src/client/extensions/ExtensionSlot.tsx +7 -0
  19. package/corpus/core/src/client/session-replay.ts +97 -3
  20. package/corpus/core/src/jobs/scheduler.ts +30 -1
  21. package/corpus/core/src/localization/default-messages.ts +21 -0
  22. package/corpus/core/src/templates/default/app/i18n/ar-SA.ts +21 -0
  23. package/corpus/core/src/templates/default/app/i18n/de-DE.ts +21 -0
  24. package/corpus/core/src/templates/default/app/i18n/en-US.ts +21 -0
  25. package/corpus/core/src/templates/default/app/i18n/es-ES.ts +21 -0
  26. package/corpus/core/src/templates/default/app/i18n/fr-FR.ts +21 -0
  27. package/corpus/core/src/templates/default/app/i18n/hi-IN.ts +20 -0
  28. package/corpus/core/src/templates/default/app/i18n/ja-JP.ts +21 -0
  29. package/corpus/core/src/templates/default/app/i18n/ko-KR.ts +20 -0
  30. package/corpus/core/src/templates/default/app/i18n/pt-BR.ts +21 -0
  31. package/corpus/core/src/templates/default/app/i18n/zh-CN.ts +20 -0
  32. package/corpus/core/src/templates/default/app/i18n/zh-TW.ts +19 -0
  33. package/corpus/core/src/templates/default/package.json +2 -2
  34. package/corpus/core/src/templates/headless/package.json +3 -3
  35. package/corpus/core/src/templates/workspace-core/package.json +6 -6
  36. package/corpus/core/src/templates/workspace-root/package.json +2 -2
  37. package/corpus/core/src/triggers/dispatcher.ts +30 -2
  38. package/corpus/core/src/vite/client.ts +96 -1
  39. package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +21 -2
  40. package/corpus/templates/analytics/app/global.css +26 -10
  41. package/corpus/templates/analytics/app/i18n/zh-TW.ts +2 -0
  42. package/corpus/templates/analytics/app/i18n-data.ts +25 -0
  43. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +548 -237
  44. package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +285 -294
  45. package/corpus/templates/analytics/changelog/2026-07-08-console-details-expand-inline-under-each-row-and-the-event-t.md +6 -0
  46. package/corpus/templates/analytics/changelog/2026-07-08-session-replay-clamps-ultra-wide-viewports-while-keeping-the.md +6 -0
  47. package/corpus/templates/analytics/changelog/2026-07-08-session-replay-keeps-a-usable-stage-when-dev-tools-is-open-a.md +6 -0
  48. package/corpus/templates/analytics/changelog/2026-07-08-session-replay-resumes-after-scrubbing-and-expands-console-r.md +6 -0
  49. package/corpus/templates/analytics/changelog/2026-07-08-session-replays-wait-for-full-load-keep-a-normal-viewport-an.md +6 -0
  50. package/corpus/templates/analytics/package.json +2 -2
  51. package/corpus/templates/assets/package.json +2 -2
  52. package/corpus/templates/brain/package.json +2 -2
  53. package/corpus/templates/calendar/AGENTS.md +10 -0
  54. package/corpus/templates/calendar/actions/create-event.ts +5 -1
  55. package/corpus/templates/calendar/actions/event-action-helpers.ts +41 -0
  56. package/corpus/templates/calendar/actions/get-attendee-timezones.ts +28 -0
  57. package/corpus/templates/calendar/actions/set-attendee-timezone.ts +68 -0
  58. package/corpus/templates/calendar/app/components/calendar/EventAttendeesSection.tsx +150 -11
  59. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +36 -1
  60. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +32 -0
  61. package/corpus/templates/calendar/app/hooks/use-attendee-timezones.ts +24 -0
  62. package/corpus/templates/calendar/app/i18n/zh-TW.ts +2 -0
  63. package/corpus/templates/calendar/app/i18n-data.ts +20 -0
  64. package/corpus/templates/calendar/app/lib/attendee-local-time.ts +122 -0
  65. package/corpus/templates/calendar/changelog/2026-07-08-event-details-now-support-extension-widgets-and-you-can-see-.md +6 -0
  66. package/corpus/templates/calendar/changelog/2026-07-08-when-you-invite-guests-to-a-new-event-you-now-appear-in.md +6 -0
  67. package/corpus/templates/calendar/package.json +2 -2
  68. package/corpus/templates/calendar/server/handlers/events.ts +5 -1
  69. package/corpus/templates/calendar/shared/api.ts +6 -0
  70. package/corpus/templates/chat/package.json +2 -2
  71. package/corpus/templates/clips/.agents/skills/meetings/SKILL.md +6 -2
  72. package/corpus/templates/clips/actions/create-meeting.ts +8 -3
  73. package/corpus/templates/clips/actions/list-meetings.ts +31 -3
  74. package/corpus/templates/clips/changelog/2026-07-08-after-finishing-a-desktop-recording-reopening-clips-restor.md +6 -0
  75. package/corpus/templates/clips/changelog/2026-07-08-clips-now-pops-up-to-take-notes-when-you-join-an-adhoc-zoom-.md +6 -0
  76. package/corpus/templates/clips/changelog/2026-07-08-desktop-clip-recordings-are-louder-after-capture-mic-only.md +6 -0
  77. package/corpus/templates/clips/changelog/2026-07-08-meeting-reminders-now-appear-1-minute-before-start-stay-unti.md +6 -0
  78. package/corpus/templates/clips/changelog/2026-07-08-the-desktop-meetings-panel-has-room-for-its-drop-shadow-and-.md +6 -0
  79. package/corpus/templates/clips/chrome-extension/package.json +2 -2
  80. package/corpus/templates/clips/desktop/package.json +2 -2
  81. package/corpus/templates/clips/desktop/src/app.tsx +91 -34
  82. package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +15 -5
  83. package/corpus/templates/clips/desktop/src/lib/meeting-notification-timing.ts +83 -0
  84. package/corpus/templates/clips/desktop/src/lib/native-recording-warm.ts +21 -0
  85. package/corpus/templates/clips/desktop/src/lib/recorder.ts +98 -20
  86. package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +174 -50
  87. package/corpus/templates/clips/desktop/src/styles.css +128 -53
  88. package/corpus/templates/clips/desktop/src-tauri/src/adhoc_meetings_watcher.rs +364 -0
  89. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +1 -1
  90. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +5 -0
  91. package/corpus/templates/clips/desktop/src-tauri/src/meetings_watcher.rs +91 -11
  92. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +69 -19
  93. package/corpus/templates/clips/desktop/src-tauri/src/native_speech.rs +36 -1
  94. package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +62 -10
  95. package/corpus/templates/clips/desktop/src-tauri/src/silence_detector.rs +1 -24
  96. package/corpus/templates/clips/desktop/src-tauri/src/util.rs +36 -1
  97. package/corpus/templates/clips/package.json +2 -2
  98. package/corpus/templates/content/actions/_content-database-personal-view.ts +80 -0
  99. package/corpus/templates/content/actions/get-content-database-personal-view.ts +27 -0
  100. package/corpus/templates/content/actions/update-content-database-personal-view.ts +31 -0
  101. package/corpus/templates/content/actions/update-content-database-view.ts +3 -0
  102. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +1 -1
  103. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +2584 -546
  104. package/corpus/templates/content/app/components/editor/database/filter-sort.ts +220 -18
  105. package/corpus/templates/content/app/hooks/use-content-database.ts +32 -0
  106. package/corpus/templates/content/app/i18n/zh-TW.ts +16 -0
  107. package/corpus/templates/content/app/i18n-data.ts +154 -0
  108. package/corpus/templates/content/changelog/2026-07-08-database-filters-now-support-notion-style-reset-save-for-eve.md +6 -0
  109. package/corpus/templates/content/changelog/2026-07-08-date-filters-can-now-target-a-between-range.md +6 -0
  110. package/corpus/templates/content/package.json +2 -2
  111. package/corpus/templates/content/parity/matrix.md +1 -1
  112. package/corpus/templates/content/parity/matrix.ts +2 -0
  113. package/corpus/templates/content/shared/api.ts +24 -0
  114. package/corpus/templates/design/AGENTS.md +9 -0
  115. package/corpus/templates/design/actions/request-localhost-write-consent.ts +141 -0
  116. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +13 -19
  117. package/corpus/templates/design/package.json +2 -2
  118. package/corpus/templates/design/server/lib/verify-write-grant.ts +4 -2
  119. package/corpus/templates/dispatch/app/i18n/zh-TW.ts +34 -1
  120. package/corpus/templates/dispatch/app/i18n-data.ts +387 -10
  121. package/corpus/templates/dispatch/app/routes/automations.tsx +1 -0
  122. package/corpus/templates/dispatch/changelog/2026-07-08-added-an-automations-page-to-review-pause-and-create.md +6 -0
  123. package/corpus/templates/dispatch/changelog/2026-07-08-destinations-now-shows-outbound-delivery-queue-health.md +6 -0
  124. package/corpus/templates/dispatch/package.json +2 -2
  125. package/corpus/templates/forms/package.json +2 -2
  126. package/corpus/templates/macros/package.json +2 -2
  127. package/corpus/templates/mail/app/hooks/use-emails.ts +56 -44
  128. package/corpus/templates/mail/app/lib/gmail-mutation-queue.ts +325 -0
  129. package/corpus/templates/mail/changelog/2026-07-08-rapid-archive-and-mark-read-now-batch-gmail-updates-so-the-i.md +6 -0
  130. package/corpus/templates/mail/package.json +2 -2
  131. package/corpus/templates/plan/package.json +2 -2
  132. package/corpus/templates/slides/app/components/editor/ImageDropPromptPopover.tsx +46 -29
  133. package/corpus/templates/slides/app/context/DeckContext.tsx +45 -18
  134. package/corpus/templates/slides/app/i18n/ar-SA.ts +4 -0
  135. package/corpus/templates/slides/app/i18n/de-DE.ts +4 -0
  136. package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
  137. package/corpus/templates/slides/app/i18n/es-ES.ts +4 -0
  138. package/corpus/templates/slides/app/i18n/fr-FR.ts +4 -0
  139. package/corpus/templates/slides/app/i18n/hi-IN.ts +4 -0
  140. package/corpus/templates/slides/app/i18n/ja-JP.ts +4 -0
  141. package/corpus/templates/slides/app/i18n/ko-KR.ts +4 -0
  142. package/corpus/templates/slides/app/i18n/pt-BR.ts +4 -0
  143. package/corpus/templates/slides/app/i18n/zh-CN.ts +4 -0
  144. package/corpus/templates/slides/app/i18n/zh-TW.ts +4 -0
  145. package/corpus/templates/slides/app/lib/image-drop-to-agent.ts +115 -0
  146. package/corpus/templates/slides/app/pages/DeckEditor.tsx +22 -13
  147. package/corpus/templates/slides/changelog/2026-07-08-dropping-an-image-onto-a-slide-and-sending-it-to-the-agent-w.md +6 -0
  148. package/corpus/templates/slides/changelog/2026-07-08-undo-works-after-the-agent-edits-a-slide-so-you-can-reverse.md +6 -0
  149. package/corpus/templates/slides/package.json +2 -2
  150. package/dist/agent/run-manager.d.ts.map +1 -1
  151. package/dist/agent/run-manager.js +23 -2
  152. package/dist/agent/run-manager.js.map +1 -1
  153. package/dist/agent/run-store.js +2 -2
  154. package/dist/agent/run-store.js.map +1 -1
  155. package/dist/catalog.json +2 -2
  156. package/dist/cli/add.js +1 -1
  157. package/dist/cli/add.js.map +1 -1
  158. package/dist/cli/create.d.ts.map +1 -1
  159. package/dist/cli/create.js +8 -3
  160. package/dist/cli/create.js.map +1 -1
  161. package/dist/cli/design-connect.d.ts.map +1 -1
  162. package/dist/cli/design-connect.js +40 -10
  163. package/dist/cli/design-connect.js.map +1 -1
  164. package/dist/cli/index.js +5 -4
  165. package/dist/cli/index.js.map +1 -1
  166. package/dist/client/extensions/ExtensionSlot.js +6 -0
  167. package/dist/client/extensions/ExtensionSlot.js.map +1 -1
  168. package/dist/client/session-replay.d.ts +8 -0
  169. package/dist/client/session-replay.d.ts.map +1 -1
  170. package/dist/client/session-replay.js +80 -3
  171. package/dist/client/session-replay.js.map +1 -1
  172. package/dist/collab/routes.d.ts +1 -1
  173. package/dist/jobs/scheduler.js +26 -1
  174. package/dist/jobs/scheduler.js.map +1 -1
  175. package/dist/localization/default-messages.d.ts +19 -0
  176. package/dist/localization/default-messages.d.ts.map +1 -1
  177. package/dist/localization/default-messages.js +19 -0
  178. package/dist/localization/default-messages.js.map +1 -1
  179. package/dist/notifications/routes.d.ts +1 -1
  180. package/dist/observability/routes.d.ts +1 -1
  181. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  182. package/dist/resources/handlers.d.ts +1 -1
  183. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  184. package/dist/templates/default/app/i18n/ar-SA.ts +21 -0
  185. package/dist/templates/default/app/i18n/de-DE.ts +21 -0
  186. package/dist/templates/default/app/i18n/en-US.ts +21 -0
  187. package/dist/templates/default/app/i18n/es-ES.ts +21 -0
  188. package/dist/templates/default/app/i18n/fr-FR.ts +21 -0
  189. package/dist/templates/default/app/i18n/hi-IN.ts +20 -0
  190. package/dist/templates/default/app/i18n/ja-JP.ts +21 -0
  191. package/dist/templates/default/app/i18n/ko-KR.ts +20 -0
  192. package/dist/templates/default/app/i18n/pt-BR.ts +21 -0
  193. package/dist/templates/default/app/i18n/zh-CN.ts +20 -0
  194. package/dist/templates/default/app/i18n/zh-TW.ts +19 -0
  195. package/dist/templates/default/package.json +2 -2
  196. package/dist/templates/headless/package.json +3 -3
  197. package/dist/templates/workspace-core/package.json +6 -6
  198. package/dist/templates/workspace-root/package.json +2 -2
  199. package/dist/triggers/dispatcher.js +27 -2
  200. package/dist/triggers/dispatcher.js.map +1 -1
  201. package/dist/vite/client.d.ts.map +1 -1
  202. package/dist/vite/client.js +70 -1
  203. package/dist/vite/client.js.map +1 -1
  204. package/package.json +7 -6
  205. package/src/templates/default/app/i18n/ar-SA.ts +21 -0
  206. package/src/templates/default/app/i18n/de-DE.ts +21 -0
  207. package/src/templates/default/app/i18n/en-US.ts +21 -0
  208. package/src/templates/default/app/i18n/es-ES.ts +21 -0
  209. package/src/templates/default/app/i18n/fr-FR.ts +21 -0
  210. package/src/templates/default/app/i18n/hi-IN.ts +20 -0
  211. package/src/templates/default/app/i18n/ja-JP.ts +21 -0
  212. package/src/templates/default/app/i18n/ko-KR.ts +20 -0
  213. package/src/templates/default/app/i18n/pt-BR.ts +21 -0
  214. package/src/templates/default/app/i18n/zh-CN.ts +20 -0
  215. package/src/templates/default/app/i18n/zh-TW.ts +19 -0
  216. package/src/templates/default/package.json +2 -2
  217. package/src/templates/headless/package.json +3 -3
  218. package/src/templates/workspace-core/package.json +6 -6
  219. package/src/templates/workspace-root/package.json +2 -2
@@ -554,6 +554,16 @@ export function applyUndoOpToDecks(decks: Deck[], op: DeckUndoOp): Deck[] {
554
554
  }
555
555
  }
556
556
 
557
+ /**
558
+ * Compare deck content for remote-sync undo. Ignores `updatedAt` so a
559
+ * metadata-only refresh does not create a no-op undo entry.
560
+ */
561
+ export function deckContentSignature(deck: Deck): string {
562
+ const { updatedAt: _updatedAt, ...rest } = deck;
563
+ void _updatedAt;
564
+ return JSON.stringify(rest);
565
+ }
566
+
557
567
  /**
558
568
  * Build the inverse of a granular op given the deck state BEFORE the op was
559
569
  * applied. Returns an array of ops to apply (usually one, occasionally two) or
@@ -939,6 +949,37 @@ export function DeckProvider({ children }: { children: ReactNode }) {
939
949
  [],
940
950
  );
941
951
 
952
+ /**
953
+ * Apply a remote deck snapshot (agent / collaborator via SSE or poll) and
954
+ * record a replace-deck undo entry when content actually changed. Without
955
+ * this, chat-driven edits land in the editor with Undo disabled.
956
+ */
957
+ const applyRemoteDeckUpdate = useCallback(
958
+ (updated: Deck, label = "Agent edit") => {
959
+ const before = decksRef.current.find((d) => d.id === updated.id);
960
+ if (
961
+ before &&
962
+ deckContentSignature(before) !== deckContentSignature(updated)
963
+ ) {
964
+ undoControllerRef.current?.push({
965
+ undo: [{ op: "replace-deck", deckId: updated.id, deck: before }],
966
+ redo: [{ op: "replace-deck", deckId: updated.id, deck: updated }],
967
+ label,
968
+ });
969
+ }
970
+ setDecks((prev) => {
971
+ const idx = prev.findIndex((d) => d.id === updated.id);
972
+ if (idx >= 0) {
973
+ const next = [...prev];
974
+ next[idx] = updated;
975
+ return next;
976
+ }
977
+ return [...prev, updated];
978
+ });
979
+ },
980
+ [],
981
+ );
982
+
942
983
  const resetDeckBaseline = useCallback((nextDecks: Deck[]) => {
943
984
  setDecks(nextDecks);
944
985
  // A baseline reset (initial mount, route change, or access reload) starts a
@@ -1082,13 +1123,7 @@ export function DeckProvider({ children }: { children: ReactNode }) {
1082
1123
  clientDeck.slides.length !== serverDeck.slides.length;
1083
1124
  if (changed) {
1084
1125
  lastExternalUpdateRef.current = Date.now();
1085
- setDecks((prev) => {
1086
- const idx = prev.findIndex((d) => d.id === currentOpenId);
1087
- if (idx < 0) return [...prev, serverDeck];
1088
- const next = [...prev];
1089
- next[idx] = serverDeck;
1090
- return next;
1091
- });
1126
+ applyRemoteDeckUpdate(serverDeck);
1092
1127
  }
1093
1128
  }
1094
1129
  } catch {}
@@ -1125,7 +1160,7 @@ export function DeckProvider({ children }: { children: ReactNode }) {
1125
1160
  window.removeEventListener("focus", pollNow);
1126
1161
  document.removeEventListener("visibilitychange", handleVisibilityChange);
1127
1162
  };
1128
- }, [loading]);
1163
+ }, [applyRemoteDeckUpdate, loading]);
1129
1164
 
1130
1165
  // The dirty-deck set is now only used as a sentinel that "something changed
1131
1166
  // for this deck". Ops are enqueued directly in each mutation handler below;
@@ -1172,20 +1207,12 @@ export function DeckProvider({ children }: { children: ReactNode }) {
1172
1207
  const updated = await fetchDeckFromAPI(data.deckId);
1173
1208
  if (!updated) return;
1174
1209
  lastExternalUpdateRef.current = Date.now(); // Suppress save-back
1175
- setDecks((prev) => {
1176
- const idx = prev.findIndex((d) => d.id === data.deckId);
1177
- if (idx >= 0) {
1178
- const next = [...prev];
1179
- next[idx] = updated;
1180
- return next;
1181
- }
1182
- return [...prev, updated];
1183
- });
1210
+ applyRemoteDeckUpdate(updated);
1184
1211
  }
1185
1212
  } catch {}
1186
1213
  };
1187
1214
  return () => evtSource.close();
1188
- }, []);
1215
+ }, [applyRemoteDeckUpdate]);
1189
1216
 
1190
1217
  // Flush pending (debounced) saves before the tab is hidden or unloaded so the
1191
1218
  // last ~500ms of edits aren't lost on close/navigation. `pagehide` is the
@@ -91,6 +91,8 @@ const messages = {
91
91
  googlePickerNeedsKeys:
92
92
  "Google Picker precisa de GOOGLE_PICKER_API_KEY e GOOGLE_PICKER_APP_ID.",
93
93
  imageUploadFailed: "Falha ao enviar imagem",
94
+ imageUploadNeedsBuilder:
95
+ "وصّل Builder.io من قائمة النموذج في مؤلف الوكيل لتحميل الصور إلى الشرائح. لا يزال بإمكانك إفلات صورة على اللوحة الفارغة لإرسالها إلى الوكيل بدون مزود.",
94
96
  sentToAgent: "Enviado ao agente",
95
97
  imageUploadGenericError: "Algo deu errado ao enviar esta imagem.",
96
98
  uploading: "Enviando…",
@@ -489,6 +491,8 @@ const messages = {
489
491
  backToDecks: "Volver a decks",
490
492
  tryAgain: "Intentar de nuevo",
491
493
  imageUploadFailed: "Error al subir imagen",
494
+ imageUploadNeedsBuilder:
495
+ "وصّل Builder.io من قائمة النموذج في مؤلف الوكيل لتحميل الصور إلى الشرائح. لا يزال بإمكانك إفلات صورة على اللوحة الفارغة لإرسالها إلى الوكيل بدون مزود.",
492
496
  imageAdded: "Imagen añadida",
493
497
  imageUploadError: "Algo salió mal al subir esta imagen.",
494
498
  exportFailed: "Error al exportar",
@@ -93,6 +93,8 @@ const messages = {
93
93
  googlePickerNeedsKeys:
94
94
  "Google Picker benötigt GOOGLE_PICKER_API_KEY und GOOGLE_PICKER_APP_ID.",
95
95
  imageUploadFailed: "Bildupload fehlgeschlagen",
96
+ imageUploadNeedsBuilder:
97
+ "Verbinde Builder.io im Modellmenü des Agent-Composers, um Bilder auf Folien hochzuladen. Wenn du ein Bild auf die leere Arbeitsfläche ziehst, kann es auch ohne Anbieter an den Agenten gesendet werden.",
96
98
  sentToAgent: "An Agent gesendet",
97
99
  imageUploadGenericError:
98
100
  "Beim Hochladen dieses Bildes ist etwas schiefgelaufen.",
@@ -484,6 +486,8 @@ const messages = {
484
486
  backToDecks: "Volver a decks",
485
487
  tryAgain: "Intentar de nuevo",
486
488
  imageUploadFailed: "Error al subir imagen",
489
+ imageUploadNeedsBuilder:
490
+ "Verbinde Builder.io im Modellmenü des Agent-Composers, um Bilder auf Folien hochzuladen. Wenn du ein Bild auf die leere Arbeitsfläche ziehst, kann es auch ohne Anbieter an den Agenten gesendet werden.",
487
491
  imageAdded: "Imagen añadida",
488
492
  imageUploadError: "Algo salió mal al subir esta imagen.",
489
493
  exportFailed: "Error al exportar",
@@ -92,6 +92,8 @@ const messages = {
92
92
  googlePickerNeedsKeys:
93
93
  "Google Picker needs GOOGLE_PICKER_API_KEY and GOOGLE_PICKER_APP_ID.",
94
94
  imageUploadFailed: "Image upload failed",
95
+ imageUploadNeedsBuilder:
96
+ "Connect Builder.io from the agent composer model menu to upload images onto slides. Dropping an image onto empty canvas can still send it to the agent without a provider.",
95
97
  sentToAgent: "Sent to agent",
96
98
  imageUploadGenericError: "Something went wrong uploading this image.",
97
99
  uploading: "Uploading…",
@@ -477,6 +479,8 @@ const messages = {
477
479
  backToDecks: "Back to Decks",
478
480
  tryAgain: "Try again",
479
481
  imageUploadFailed: "Image upload failed",
482
+ imageUploadNeedsBuilder:
483
+ "Connect Builder.io from the agent composer model menu to upload images onto slides. Dropping an image onto empty canvas can still send it to the agent without a provider.",
480
484
  imageAdded: "Image added",
481
485
  imageUploadError: "Something went wrong uploading this image.",
482
486
  exportFailed: "Export failed",
@@ -93,6 +93,8 @@ const messages = {
93
93
  googlePickerNeedsKeys:
94
94
  "Google Picker necesita GOOGLE_PICKER_API_KEY y GOOGLE_PICKER_APP_ID.",
95
95
  imageUploadFailed: "Error al subir la imagen",
96
+ imageUploadNeedsBuilder:
97
+ "Conecta Builder.io desde el menú de modelos del compositor del agente para subir imágenes a las diapositivas. Soltar una imagen en el lienzo vacío aún puede enviarla al agente sin proveedor.",
96
98
  sentToAgent: "Enviado al agente",
97
99
  imageUploadGenericError: "Algo salió mal al subir esta imagen.",
98
100
  uploading: "Subiendo…",
@@ -488,6 +490,8 @@ const messages = {
488
490
  backToDecks: "Volver a decks",
489
491
  tryAgain: "Intentar de nuevo",
490
492
  imageUploadFailed: "Error al subir imagen",
493
+ imageUploadNeedsBuilder:
494
+ "Conecta Builder.io desde el menú de modelos del compositor del agente para subir imágenes a las diapositivas. Soltar una imagen en el lienzo vacío aún puede enviarla al agente sin proveedor.",
491
495
  imageAdded: "Imagen añadida",
492
496
  imageUploadError: "Algo salió mal al subir esta imagen.",
493
497
  exportFailed: "Error al exportar",
@@ -93,6 +93,8 @@ const messages = {
93
93
  googlePickerNeedsKeys:
94
94
  "Google Picker nécessite GOOGLE_PICKER_API_KEY et GOOGLE_PICKER_APP_ID.",
95
95
  imageUploadFailed: "Échec de l’envoi de l’image",
96
+ imageUploadNeedsBuilder:
97
+ "Connectez Builder.io depuis le menu de modèle du composeur d’agent pour téléverser des images sur les diapositives. Déposer une image sur le canevas vide peut toujours l’envoyer à l’agent sans fournisseur.",
96
98
  sentToAgent: "Envoyé à l’agent",
97
99
  imageUploadGenericError:
98
100
  "Une erreur est survenue lors de l’envoi de cette image.",
@@ -492,6 +494,8 @@ const messages = {
492
494
  backToDecks: "Volver a decks",
493
495
  tryAgain: "Intentar de nuevo",
494
496
  imageUploadFailed: "Error al subir imagen",
497
+ imageUploadNeedsBuilder:
498
+ "Connectez Builder.io depuis le menu de modèle du composeur d’agent pour téléverser des images sur les diapositives. Déposer une image sur le canevas vide peut toujours l’envoyer à l’agent sans fournisseur.",
495
499
  imageAdded: "Imagen añadida",
496
500
  imageUploadError: "Algo salió mal al subir esta imagen.",
497
501
  exportFailed: "Error al exportar",
@@ -91,6 +91,8 @@ const messages = {
91
91
  googlePickerNeedsKeys:
92
92
  "Google Picker precisa de GOOGLE_PICKER_API_KEY e GOOGLE_PICKER_APP_ID.",
93
93
  imageUploadFailed: "Falha ao enviar imagem",
94
+ imageUploadNeedsBuilder:
95
+ "स्लाइड पर चित्र अपलोड करने के लिए एजेंट composer के मॉडल मेनू से Builder.io कनेक्ट करें। खाली कैनवास पर चित्र छोड़ने से वह बिना provider के भी एजेंट को भेजा जा सकता है।",
94
96
  sentToAgent: "Enviado ao agente",
95
97
  imageUploadGenericError: "Algo deu errado ao enviar esta imagem.",
96
98
  uploading: "Enviando…",
@@ -472,6 +474,8 @@ const messages = {
472
474
  backToDecks: "डेक पर वापस जाएं",
473
475
  tryAgain: "फिर कोशिश करें",
474
476
  imageUploadFailed: "चित्र अपलोड विफल",
477
+ imageUploadNeedsBuilder:
478
+ "स्लाइड पर चित्र अपलोड करने के लिए एजेंट composer के मॉडल मेनू से Builder.io कनेक्ट करें। खाली कैनवास पर चित्र छोड़ने से वह बिना provider के भी एजेंट को भेजा जा सकता है।",
475
479
  imageAdded: "चित्र जोड़ा गया",
476
480
  imageUploadError: "यह चित्र अपलोड करते समय कुछ गलत हुआ।",
477
481
  exportFailed: "निर्यात विफल",
@@ -92,6 +92,8 @@ const messages = {
92
92
  googlePickerNeedsKeys:
93
93
  "Google PickerにはGOOGLE_PICKER_API_KEYとGOOGLE_PICKER_APP_IDが必要です。",
94
94
  imageUploadFailed: "画像のアップロードに失敗しました",
95
+ imageUploadNeedsBuilder:
96
+ "スライドに画像をアップロードするには、エージェント作成欄のモデルメニューから Builder.io に接続してください。空のキャンバスに画像をドロップすると、プロバイダーなしでもエージェントに送信できます。",
95
97
  sentToAgent: "エージェントに送信しました",
96
98
  imageUploadGenericError: "この画像のアップロード中に問題が発生しました。",
97
99
  uploading: "アップロード中…",
@@ -471,6 +473,8 @@ const messages = {
471
473
  backToDecks: "返回幻灯片",
472
474
  tryAgain: "重试",
473
475
  imageUploadFailed: "图片上传失败",
476
+ imageUploadNeedsBuilder:
477
+ "スライドに画像をアップロードするには、エージェント作成欄のモデルメニューから Builder.io に接続してください。空のキャンバスに画像をドロップすると、プロバイダーなしでもエージェントに送信できます。",
474
478
  imageAdded: "图片已添加",
475
479
  imageUploadError: "上传此图片时出了点问题。",
476
480
  exportFailed: "导出失败",
@@ -92,6 +92,8 @@ const messages = {
92
92
  googlePickerNeedsKeys:
93
93
  "Google PickerにはGOOGLE_PICKER_API_KEYとGOOGLE_PICKER_APP_IDが必要です。",
94
94
  imageUploadFailed: "画像のアップロードに失敗しました",
95
+ imageUploadNeedsBuilder:
96
+ "슬라이드에 이미지를 업로드하려면 에이전트 작성기의 모델 메뉴에서 Builder.io를 연결하세요. 빈 캔버스에 이미지를 놓으면 제공자 없이도 에이전트로 보낼 수 있습니다.",
95
97
  sentToAgent: "エージェントに送信しました",
96
98
  imageUploadGenericError: "この画像のアップロード中に問題が発生しました。",
97
99
  uploading: "アップロード中…",
@@ -469,6 +471,8 @@ const messages = {
469
471
  backToDecks: "返回幻灯片",
470
472
  tryAgain: "重试",
471
473
  imageUploadFailed: "图片上传失败",
474
+ imageUploadNeedsBuilder:
475
+ "슬라이드에 이미지를 업로드하려면 에이전트 작성기의 모델 메뉴에서 Builder.io를 연결하세요. 빈 캔버스에 이미지를 놓으면 제공자 없이도 에이전트로 보낼 수 있습니다.",
472
476
  imageAdded: "图片已添加",
473
477
  imageUploadError: "上传此图片时出了点问题。",
474
478
  exportFailed: "导出失败",
@@ -92,6 +92,8 @@ const messages = {
92
92
  googlePickerNeedsKeys:
93
93
  "Google Picker precisa de GOOGLE_PICKER_API_KEY e GOOGLE_PICKER_APP_ID.",
94
94
  imageUploadFailed: "Falha ao enviar imagem",
95
+ imageUploadNeedsBuilder:
96
+ "Conecte o Builder.io no menu de modelo do compositor do agente para enviar imagens aos slides. Soltar uma imagem na tela vazia ainda pode enviá-la ao agente sem provedor.",
95
97
  sentToAgent: "Enviado ao agente",
96
98
  imageUploadGenericError: "Algo deu errado ao enviar esta imagem.",
97
99
  uploading: "Enviando…",
@@ -483,6 +485,8 @@ const messages = {
483
485
  backToDecks: "Volver a decks",
484
486
  tryAgain: "Intentar de nuevo",
485
487
  imageUploadFailed: "Error al subir imagen",
488
+ imageUploadNeedsBuilder:
489
+ "Conecte o Builder.io no menu de modelo do compositor do agente para enviar imagens aos slides. Soltar uma imagem na tela vazia ainda pode enviá-la ao agente sem provedor.",
486
490
  imageAdded: "Imagen añadida",
487
491
  imageUploadError: "Algo salió mal al subir esta imagen.",
488
492
  exportFailed: "Error al exportar",
@@ -90,6 +90,8 @@ const messages = {
90
90
  googlePickerNeedsKeys:
91
91
  "Google PickerにはGOOGLE_PICKER_API_KEYとGOOGLE_PICKER_APP_IDが必要です。",
92
92
  imageUploadFailed: "画像のアップロードに失敗しました",
93
+ imageUploadNeedsBuilder:
94
+ "请从代理编写器的模型菜单连接 Builder.io,以便将图片上传到幻灯片。即使没有提供方,把图片拖到空白画布上仍可发送给代理。",
93
95
  sentToAgent: "エージェントに送信しました",
94
96
  imageUploadGenericError: "この画像のアップロード中に問題が発生しました。",
95
97
  uploading: "アップロード中…",
@@ -465,6 +467,8 @@ const messages = {
465
467
  backToDecks: "返回幻灯片",
466
468
  tryAgain: "重试",
467
469
  imageUploadFailed: "图片上传失败",
470
+ imageUploadNeedsBuilder:
471
+ "请从代理编写器的模型菜单连接 Builder.io,以便将图片上传到幻灯片。即使没有提供方,把图片拖到空白画布上仍可发送给代理。",
468
472
  imageAdded: "图片已添加",
469
473
  imageUploadError: "上传此图片时出了点问题。",
470
474
  exportFailed: "导出失败",
@@ -88,6 +88,8 @@ const messages = {
88
88
  googlePickerNeedsKeys:
89
89
  "Google Picker 需要 GOOGLE_PICKER_API_KEY 和 GOOGLE_PICKER_APP_ID。",
90
90
  imageUploadFailed: "圖片上傳失敗",
91
+ imageUploadNeedsBuilder:
92
+ "請從代理編寫器的模型選單連接 Builder.io,以便將圖片上傳到投影片。即使沒有提供者,將圖片拖到空白畫布上仍可傳送給代理。",
91
93
  sentToAgent: "已傳送給代理",
92
94
  imageUploadGenericError: "上傳這張圖片時發生問題。",
93
95
  uploading: "正在上傳…",
@@ -460,6 +462,8 @@ const messages = {
460
462
  backToDecks: "返回幻燈片",
461
463
  tryAgain: "重試",
462
464
  imageUploadFailed: "圖片上傳失敗",
465
+ imageUploadNeedsBuilder:
466
+ "請從代理編寫器的模型選單連接 Builder.io,以便將圖片上傳到投影片。即使沒有提供者,將圖片拖到空白畫布上仍可傳送給代理。",
463
467
  imageAdded: "圖片已新增",
464
468
  imageUploadError: "上傳此圖片時出了點問題。",
465
469
  exportFailed: "匯出失敗",
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Resolve how to hand a dropped image to the agent chat.
3
+ *
4
+ * Prefer a hosted CDN URL from `/api/assets/upload` when a file-upload
5
+ * provider is configured. When nothing is configured (or the upload fails),
6
+ * fall back to an inline data URL so the agent can still see the image —
7
+ * chat already accepts `images: string[]` data URLs without a storage
8
+ * provider. The agent can call `upload-image` later if the slide needs a
9
+ * durable hosted URL.
10
+ */
11
+
12
+ export interface HostedImageUploadResult {
13
+ ok: boolean;
14
+ status: number;
15
+ url?: string;
16
+ error?: string;
17
+ }
18
+
19
+ export type ImageDropAgentPayload =
20
+ | {
21
+ kind: "hosted";
22
+ message: string;
23
+ referenceImagePaths: string[];
24
+ }
25
+ | {
26
+ kind: "inline";
27
+ message: string;
28
+ images: string[];
29
+ };
30
+
31
+ export function isMissingUploadProviderError(
32
+ status: number,
33
+ error: string | undefined,
34
+ ): boolean {
35
+ if (status === 503) return true;
36
+ const lower = (error ?? "").toLowerCase();
37
+ return (
38
+ lower.includes("no file upload provider") ||
39
+ lower.includes("registerfileuploadprovider") ||
40
+ lower.includes("connect builder.io")
41
+ );
42
+ }
43
+
44
+ export function buildImageDropAgentPayload(args: {
45
+ intent: string;
46
+ contextHint?: string;
47
+ filename: string;
48
+ upload: HostedImageUploadResult;
49
+ dataUrl?: string;
50
+ }): ImageDropAgentPayload {
51
+ const intentLine =
52
+ args.intent.trim().length > 0
53
+ ? args.intent.trim()
54
+ : "Use this image on the current slide.";
55
+ const lines = [intentLine];
56
+ if (args.contextHint && args.contextHint.trim().length > 0) {
57
+ lines.push(args.contextHint.trim());
58
+ }
59
+ lines.push(`Filename: ${args.filename}`);
60
+
61
+ if (args.upload.ok && args.upload.url) {
62
+ lines.splice(
63
+ lines.length - 1,
64
+ 0,
65
+ `Image URL (already uploaded): ${args.upload.url}`,
66
+ );
67
+ return {
68
+ kind: "hosted",
69
+ message: lines.join("\n\n"),
70
+ referenceImagePaths: [args.upload.url],
71
+ };
72
+ }
73
+
74
+ if (!args.dataUrl) {
75
+ throw new Error(
76
+ args.upload.error ||
77
+ "Image upload failed. Connect Builder.io from the agent composer model menu, or register a custom provider via registerFileUploadProvider().",
78
+ );
79
+ }
80
+
81
+ if (!isMissingUploadProviderError(args.upload.status, args.upload.error)) {
82
+ // Unexpected upload failure — still try the inline path so the user can
83
+ // keep working, but tell the agent the hosted upload didn't land.
84
+ lines.push(
85
+ "Hosted upload failed; the image is attached inline as a data URL. Call upload-image on it before placing it on the slide if a durable URL is required.",
86
+ );
87
+ } else {
88
+ lines.push(
89
+ "No file upload provider is configured, so the image is attached inline as a data URL. Call upload-image to obtain a hosted URL before inserting it into slide HTML.",
90
+ );
91
+ }
92
+
93
+ return {
94
+ kind: "inline",
95
+ message: lines.join("\n\n"),
96
+ images: [args.dataUrl],
97
+ };
98
+ }
99
+
100
+ export function readFileAsDataUrl(file: File): Promise<string> {
101
+ return new Promise((resolve, reject) => {
102
+ const reader = new FileReader();
103
+ reader.onload = () => {
104
+ const result = reader.result;
105
+ if (typeof result === "string" && result.startsWith("data:")) {
106
+ resolve(result);
107
+ } else {
108
+ reject(new Error("Failed to read image file."));
109
+ }
110
+ };
111
+ reader.onerror = () =>
112
+ reject(reader.error ?? new Error("Failed to read image file."));
113
+ reader.readAsDataURL(file);
114
+ });
115
+ }
@@ -70,6 +70,7 @@ import {
70
70
  shouldClearNewDeckGeneratingState,
71
71
  shouldShowNewDeckGeneratingOverlay,
72
72
  } from "@/lib/generation-state";
73
+ import { isMissingUploadProviderError } from "@/lib/image-drop-to-agent";
73
74
  import { imageFileLooksSupported } from "@/lib/slide-image-replacement";
74
75
  import { replaceImageTargetInSlideHtml } from "@/lib/slide-image-replacement";
75
76
  import { TAB_ID } from "@/lib/tab-id";
@@ -323,19 +324,27 @@ export default function DeckEditor() {
323
324
  [deck, id, reorderSlides],
324
325
  );
325
326
 
326
- const uploadImageAsset = useCallback(async (file: File): Promise<string> => {
327
- const form = new FormData();
328
- form.append("file", file);
329
- const res = await fetch(`${appBasePath()}/api/assets/upload`, {
330
- method: "POST",
331
- body: form,
332
- });
333
- const data = await res.json().catch(() => null);
334
- if (!res.ok || !data?.url) {
335
- throw new Error(data?.error || t("deckEditor.imageUploadFailed"));
336
- }
337
- return data.url as string;
338
- }, []);
327
+ const uploadImageAsset = useCallback(
328
+ async (file: File): Promise<string> => {
329
+ const form = new FormData();
330
+ form.append("file", file);
331
+ const res = await fetch(`${appBasePath()}/api/assets/upload`, {
332
+ method: "POST",
333
+ body: form,
334
+ });
335
+ const data = await res.json().catch(() => null);
336
+ if (!res.ok || !data?.url) {
337
+ const serverError =
338
+ typeof data?.error === "string" ? data.error : undefined;
339
+ if (isMissingUploadProviderError(res.status, serverError)) {
340
+ throw new Error(t("deckEditor.imageUploadNeedsBuilder"));
341
+ }
342
+ throw new Error(serverError || t("deckEditor.imageUploadFailed"));
343
+ }
344
+ return data.url as string;
345
+ },
346
+ [t],
347
+ );
339
348
 
340
349
  // Replace an image or placeholder in the current slide's HTML content.
341
350
  const replaceImageInSlide = useCallback(
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-08
4
+ ---
5
+
6
+ Dropping an image onto a slide and sending it to the agent works even when Builder.io storage isn't connected yet
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-08
4
+ ---
5
+
6
+ Undo works after the agent edits a slide, so you can reverse chat-driven changes from the toolbar
@@ -103,7 +103,6 @@
103
103
  "@types/react": "catalog:",
104
104
  "@types/react-dom": "catalog:",
105
105
  "@types/three": "^0.176.0",
106
- "@typescript/native-preview": "catalog:",
107
106
  "@vitejs/plugin-react-swc": "^4.0.0",
108
107
  "class-variance-authority": "^0.7.1",
109
108
  "clsx": "^2.1.1",
@@ -129,7 +128,8 @@
129
128
  "tailwindcss": "catalog:",
130
129
  "three": "^0.176.0",
131
130
  "tsx": "^4.20.3",
132
- "typescript": "^6.0.3",
131
+ "typescript": "catalog:",
132
+ "typescript-7": "catalog:",
133
133
  "vaul": "^1.1.2",
134
134
  "vite": "catalog:",
135
135
  "vitest": "catalog:"
@@ -1 +1 @@
1
- {"version":3,"file":"run-manager.d.ts","sourceRoot":"","sources":["../../src/agent/run-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run-manager.d.ts","sourceRoot":"","sources":["../../src/agent/run-manager.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEtE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,MAAM,EAAE,SAAS,CAAC;IAClB,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC,CAAC;IAC5C,KAAK,EAAE,eAAe,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAQD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,kCAAkC,QAAS,CAAC;AAEzD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,8BAA8B,QAAS,CAAC;AAErD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,kCAAkC,QAAc,CAAC;AAE9D;;;;;GAKG;AACH,eAAO,MAAM,sCAAsC,QACf,CAAC;AAErC;;;;;;;GAOG;AACH,eAAO,MAAM,yCAAyC,QACT,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,+BAA+B,SAAU,CAAC;AAEvD,qEAAqE;AACrE,eAAO,MAAM,kCAAkC,QAAsB,CAAC;AAEtE;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,QAA0B,CAAC;AAExE;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,QAAiB,CAAC;AAE/D,wFAAwF;AACxF,eAAO,MAAM,+BAA+B,MAAM,CAAC;AAEnD,iEAAiE;AACjE,eAAO,MAAM,6BAA6B,MAAM,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,gCAAgC,OAAQ,CAAC;AAEtD,8EAA8E;AAC9E,eAAO,MAAM,+BAA+B,MAAM,CAAC;AAEnD,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,MAAM,GACtB,MAAM,CAIR;AAmDD,MAAM,WAAW,eAAe;IAC9B;;2CAEuC;IACvC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;4DACwD;IACxD,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC;;;+EAG2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,YAAY,CAAC,EAAE,YAAY,GAAG,uBAAuB,CAAC;CACvD;AAED,MAAM,WAAW,4BAA4B;IAC3C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AA0BD,wBAAgB,uBAAuB,CACrC,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,4BAA4B,GACrC,MAAM,CAkCR;AAED,wBAAgB,8BAA8B,IAAI,MAAM,CAOvD;AAED,wBAAgB,4BAA4B,IAAI,MAAM,CAOrD;AAiDD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,CACL,IAAI,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,EACrC,MAAM,EAAE,WAAW,KAChB,OAAO,CAAC,IAAI,CAAC,EAClB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EACrD,OAAO,CAAC,EAAE,eAAe,GACxB,SAAS,CAynBX;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GACd,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAOnC;AAwRD,wEAAwE;AACxE,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAOxE;AAED;;;;;;;;;GASG;AACH,wBAAsB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,+FAA+F;IAC/F,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,0EAA0E;IAC1E,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,GAAG,IAAI,CAAC,CA4GR;AAgBD,sBAAsB;AACtB,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAEtD;AAED,gDAAgD;AAChD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,MAAe,GAAG,OAAO,CAQxE;AAGD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
@@ -516,10 +516,31 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
516
516
  };
517
517
  // Heartbeat: bump heartbeat_at every 1.5s so watchers can detect a dead
518
518
  // producer (process crash, HMR restart, isolate eviction) quickly and
519
- // reap the row. Paired with RUN_STALE_MS (6s) — 4x the interval to
519
+ // reap the row. Paired with RUN_STALE_MS (15s) — 10x the interval to
520
520
  // tolerate transient DB slowness without false positives.
521
+ let consecutiveHeartbeatFailures = 0;
521
522
  const heartbeatTimer = setInterval(() => {
522
- updateRunHeartbeat(runId).catch(() => { });
523
+ updateRunHeartbeat(runId)
524
+ .then(() => {
525
+ consecutiveHeartbeatFailures = 0;
526
+ })
527
+ .catch((error) => {
528
+ consecutiveHeartbeatFailures += 1;
529
+ // Swallow routine single-tick blips; escalate once failures approach
530
+ // the stale window so false-positive stale_run from silent write
531
+ // failures is diagnosable.
532
+ if (consecutiveHeartbeatFailures >= 3) {
533
+ captureError(error, {
534
+ route: "/_agent-native/agent-chat",
535
+ tags: {
536
+ source: "agent-run-manager",
537
+ phase: "heartbeat",
538
+ consecutiveFailures: String(consecutiveHeartbeatFailures),
539
+ },
540
+ extra: { runId, threadId },
541
+ });
542
+ }
543
+ });
523
544
  checkSqlAbort();
524
545
  checkNoProgressBackstop();
525
546
  }, 1500);