@agent-native/core 0.30.6 → 0.31.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 (255) hide show
  1. package/dist/a2a/client.d.ts +2 -0
  2. package/dist/a2a/client.d.ts.map +1 -1
  3. package/dist/a2a/client.js +6 -4
  4. package/dist/a2a/client.js.map +1 -1
  5. package/dist/a2a/handlers.d.ts.map +1 -1
  6. package/dist/a2a/handlers.js +3 -0
  7. package/dist/a2a/handlers.js.map +1 -1
  8. package/dist/a2a/server.d.ts.map +1 -1
  9. package/dist/a2a/server.js.map +1 -1
  10. package/dist/a2a/task-store.js.map +1 -1
  11. package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
  12. package/dist/agent/engine/anthropic-engine.js +0 -7
  13. package/dist/agent/engine/anthropic-engine.js.map +1 -1
  14. package/dist/agent/engine/registry.d.ts.map +1 -1
  15. package/dist/agent/engine/registry.js.map +1 -1
  16. package/dist/agent/engine/translate-ai-sdk.d.ts.map +1 -1
  17. package/dist/agent/engine/translate-ai-sdk.js +5 -3
  18. package/dist/agent/engine/translate-ai-sdk.js.map +1 -1
  19. package/dist/agent/production-agent.js +7 -3
  20. package/dist/agent/production-agent.js.map +1 -1
  21. package/dist/agent/run-manager.d.ts.map +1 -1
  22. package/dist/agent/run-manager.js +14 -6
  23. package/dist/agent/run-manager.js.map +1 -1
  24. package/dist/application-state/store.d.ts.map +1 -1
  25. package/dist/application-state/store.js.map +1 -1
  26. package/dist/brand-kit/brand-signals.d.ts +31 -0
  27. package/dist/brand-kit/brand-signals.d.ts.map +1 -0
  28. package/dist/brand-kit/brand-signals.js +101 -0
  29. package/dist/brand-kit/brand-signals.js.map +1 -0
  30. package/dist/brand-kit/index.d.ts +21 -0
  31. package/dist/brand-kit/index.d.ts.map +1 -0
  32. package/dist/brand-kit/index.js +34 -0
  33. package/dist/brand-kit/index.js.map +1 -0
  34. package/dist/brand-kit/types.d.ts +103 -0
  35. package/dist/brand-kit/types.d.ts.map +1 -0
  36. package/dist/brand-kit/types.js +17 -0
  37. package/dist/brand-kit/types.js.map +1 -0
  38. package/dist/cli/code-agent-executor.d.ts.map +1 -1
  39. package/dist/cli/code-agent-executor.js.map +1 -1
  40. package/dist/cli/create.d.ts.map +1 -1
  41. package/dist/cli/create.js +0 -1
  42. package/dist/cli/create.js.map +1 -1
  43. package/dist/client/AgentNative.js.map +1 -1
  44. package/dist/client/AgentPanel.d.ts.map +1 -1
  45. package/dist/client/AgentPanel.js +0 -2
  46. package/dist/client/AgentPanel.js.map +1 -1
  47. package/dist/client/AssistantChat.d.ts.map +1 -1
  48. package/dist/client/AssistantChat.js +69 -17
  49. package/dist/client/AssistantChat.js.map +1 -1
  50. package/dist/client/IframeEmbed.d.ts.map +1 -1
  51. package/dist/client/IframeEmbed.js.map +1 -1
  52. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  53. package/dist/client/MultiTabAssistantChat.js +1 -1
  54. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  55. package/dist/client/RunStuckBanner.js.map +1 -1
  56. package/dist/client/agent-chat.d.ts.map +1 -1
  57. package/dist/client/agent-chat.js.map +1 -1
  58. package/dist/client/builder-mark.d.ts.map +1 -1
  59. package/dist/client/builder-mark.js.map +1 -1
  60. package/dist/client/components/MissingKeyCard.d.ts.map +1 -1
  61. package/dist/client/components/MissingKeyCard.js.map +1 -1
  62. package/dist/client/composer/PromptComposer.d.ts.map +1 -1
  63. package/dist/client/composer/PromptComposer.js +6 -3
  64. package/dist/client/composer/PromptComposer.js.map +1 -1
  65. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  66. package/dist/client/composer/TiptapComposer.js +5 -0
  67. package/dist/client/composer/TiptapComposer.js.map +1 -1
  68. package/dist/client/composer/VoiceButton.d.ts.map +1 -1
  69. package/dist/client/composer/VoiceButton.js +9 -0
  70. package/dist/client/composer/VoiceButton.js.map +1 -1
  71. package/dist/client/composer/extensions/FileReference.d.ts.map +1 -1
  72. package/dist/client/composer/extensions/FileReference.js.map +1 -1
  73. package/dist/client/composer/extensions/MentionReference.d.ts.map +1 -1
  74. package/dist/client/composer/extensions/MentionReference.js.map +1 -1
  75. package/dist/client/composer/extensions/SkillReference.d.ts.map +1 -1
  76. package/dist/client/composer/extensions/SkillReference.js.map +1 -1
  77. package/dist/client/conversation/AgentConversation.js +8 -6
  78. package/dist/client/conversation/AgentConversation.js.map +1 -1
  79. package/dist/client/conversation/use-near-bottom-autoscroll.d.ts.map +1 -1
  80. package/dist/client/conversation/use-near-bottom-autoscroll.js +133 -35
  81. package/dist/client/conversation/use-near-bottom-autoscroll.js.map +1 -1
  82. package/dist/client/db-admin/DbAdminPage.js.map +1 -1
  83. package/dist/client/dev-overlay/DevOverlay.d.ts.map +1 -1
  84. package/dist/client/dev-overlay/DevOverlay.js +0 -1
  85. package/dist/client/dev-overlay/DevOverlay.js.map +1 -1
  86. package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
  87. package/dist/client/extensions/EmbeddedExtension.js +19 -0
  88. package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
  89. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  90. package/dist/client/extensions/ExtensionViewer.js +11 -3
  91. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  92. package/dist/client/integrations/IntegrationsPanel.d.ts.map +1 -1
  93. package/dist/client/integrations/IntegrationsPanel.js.map +1 -1
  94. package/dist/client/mcp-app-host.d.ts.map +1 -1
  95. package/dist/client/mcp-app-host.js +6 -1
  96. package/dist/client/mcp-app-host.js.map +1 -1
  97. package/dist/client/mcp-apps/McpAppRenderer.d.ts.map +1 -1
  98. package/dist/client/mcp-apps/McpAppRenderer.js +1 -1
  99. package/dist/client/mcp-apps/McpAppRenderer.js.map +1 -1
  100. package/dist/client/notifications/NotificationsBell.js.map +1 -1
  101. package/dist/client/onboarding/SetupButton.d.ts.map +1 -1
  102. package/dist/client/onboarding/SetupButton.js +6 -0
  103. package/dist/client/onboarding/SetupButton.js.map +1 -1
  104. package/dist/client/progress/RunsTray.js.map +1 -1
  105. package/dist/client/resources/McpServerDetail.d.ts.map +1 -1
  106. package/dist/client/resources/McpServerDetail.js.map +1 -1
  107. package/dist/client/settings/AgentsSection.d.ts.map +1 -1
  108. package/dist/client/settings/AgentsSection.js +1 -1
  109. package/dist/client/settings/AgentsSection.js.map +1 -1
  110. package/dist/client/settings/AutomationsSection.js.map +1 -1
  111. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  112. package/dist/client/sharing/ShareButton.js +0 -4
  113. package/dist/client/sharing/ShareButton.js.map +1 -1
  114. package/dist/client/terminal/AgentTerminal.d.ts.map +1 -1
  115. package/dist/client/terminal/AgentTerminal.js +1 -1
  116. package/dist/client/terminal/AgentTerminal.js.map +1 -1
  117. package/dist/client/use-agent-chat.d.ts.map +1 -1
  118. package/dist/client/use-agent-chat.js +20 -4
  119. package/dist/client/use-agent-chat.js.map +1 -1
  120. package/dist/client/use-chat-threads.d.ts.map +1 -1
  121. package/dist/client/use-chat-threads.js +39 -25
  122. package/dist/client/use-chat-threads.js.map +1 -1
  123. package/dist/client/use-db-sync.d.ts.map +1 -1
  124. package/dist/client/use-db-sync.js +8 -0
  125. package/dist/client/use-db-sync.js.map +1 -1
  126. package/dist/client/use-dev-mode.d.ts.map +1 -1
  127. package/dist/client/use-dev-mode.js +25 -9
  128. package/dist/client/use-dev-mode.js.map +1 -1
  129. package/dist/client/useProductionAgent.d.ts.map +1 -1
  130. package/dist/client/useProductionAgent.js +6 -2
  131. package/dist/client/useProductionAgent.js.map +1 -1
  132. package/dist/collab/agent-presence.d.ts.map +1 -1
  133. package/dist/collab/agent-presence.js +1 -1
  134. package/dist/collab/agent-presence.js.map +1 -1
  135. package/dist/collab/awareness.d.ts.map +1 -1
  136. package/dist/collab/awareness.js +8 -0
  137. package/dist/collab/awareness.js.map +1 -1
  138. package/dist/collab/client-struct.js.map +1 -1
  139. package/dist/deploy/build.js +0 -5
  140. package/dist/deploy/build.js.map +1 -1
  141. package/dist/extensions/fetch-tool.d.ts.map +1 -1
  142. package/dist/extensions/fetch-tool.js +4 -1
  143. package/dist/extensions/fetch-tool.js.map +1 -1
  144. package/dist/file-upload/actions/upload-image.d.ts.map +1 -1
  145. package/dist/file-upload/actions/upload-image.js +39 -4
  146. package/dist/file-upload/actions/upload-image.js.map +1 -1
  147. package/dist/integrations/adapters/slack.d.ts.map +1 -1
  148. package/dist/integrations/adapters/slack.js.map +1 -1
  149. package/dist/integrations/google-docs-poller.d.ts.map +1 -1
  150. package/dist/integrations/google-docs-poller.js +14 -1
  151. package/dist/integrations/google-docs-poller.js.map +1 -1
  152. package/dist/integrations/plugin.d.ts.map +1 -1
  153. package/dist/integrations/plugin.js.map +1 -1
  154. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  155. package/dist/integrations/webhook-handler.js +10 -1
  156. package/dist/integrations/webhook-handler.js.map +1 -1
  157. package/dist/jobs/scheduler.d.ts.map +1 -1
  158. package/dist/jobs/scheduler.js.map +1 -1
  159. package/dist/mcp/build-server.d.ts.map +1 -1
  160. package/dist/mcp/build-server.js +20 -8
  161. package/dist/mcp/build-server.js.map +1 -1
  162. package/dist/mcp/connect-store.d.ts.map +1 -1
  163. package/dist/mcp/connect-store.js +1 -1
  164. package/dist/mcp/connect-store.js.map +1 -1
  165. package/dist/notifications/channels.d.ts.map +1 -1
  166. package/dist/notifications/channels.js +3 -2
  167. package/dist/notifications/channels.js.map +1 -1
  168. package/dist/oauth-tokens/store.js.map +1 -1
  169. package/dist/observability/evals.d.ts.map +1 -1
  170. package/dist/observability/evals.js +7 -7
  171. package/dist/observability/evals.js.map +1 -1
  172. package/dist/observability/traces.d.ts.map +1 -1
  173. package/dist/observability/traces.js +15 -5
  174. package/dist/observability/traces.js.map +1 -1
  175. package/dist/org/handlers.d.ts.map +1 -1
  176. package/dist/org/handlers.js +3 -2
  177. package/dist/org/handlers.js.map +1 -1
  178. package/dist/resources/handlers.d.ts +5 -5
  179. package/dist/resources/handlers.d.ts.map +1 -1
  180. package/dist/resources/handlers.js.map +1 -1
  181. package/dist/scripts/db/schema.js.map +1 -1
  182. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  183. package/dist/server/agent-chat-plugin.js +0 -6
  184. package/dist/server/agent-chat-plugin.js.map +1 -1
  185. package/dist/server/auth.d.ts.map +1 -1
  186. package/dist/server/auth.js.map +1 -1
  187. package/dist/server/better-auth-instance.d.ts.map +1 -1
  188. package/dist/server/better-auth-instance.js +0 -3
  189. package/dist/server/better-auth-instance.js.map +1 -1
  190. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  191. package/dist/server/core-routes-plugin.js +1 -2
  192. package/dist/server/core-routes-plugin.js.map +1 -1
  193. package/dist/server/create-server.d.ts.map +1 -1
  194. package/dist/server/create-server.js +0 -23
  195. package/dist/server/create-server.js.map +1 -1
  196. package/dist/server/google-oauth.d.ts.map +1 -1
  197. package/dist/server/google-oauth.js +0 -3
  198. package/dist/server/google-oauth.js.map +1 -1
  199. package/dist/server/poll.d.ts.map +1 -1
  200. package/dist/server/poll.js +49 -18
  201. package/dist/server/poll.js.map +1 -1
  202. package/dist/settings/store.js.map +1 -1
  203. package/dist/sharing/access.d.ts.map +1 -1
  204. package/dist/sharing/access.js +25 -4
  205. package/dist/sharing/access.js.map +1 -1
  206. package/dist/triggers/dispatcher.d.ts.map +1 -1
  207. package/dist/triggers/dispatcher.js.map +1 -1
  208. package/dist/vite/client.d.ts.map +1 -1
  209. package/dist/vite/client.js +2 -0
  210. package/dist/vite/client.js.map +1 -1
  211. package/package.json +3 -2
  212. package/dist/client/conversation/AgentConversation.spec.d.ts +0 -2
  213. package/dist/client/conversation/AgentConversation.spec.d.ts.map +0 -1
  214. package/dist/client/conversation/AgentConversation.spec.js +0 -69
  215. package/dist/client/conversation/AgentConversation.spec.js.map +0 -1
  216. package/dist/client/extensions/AgentNativeExtensionFrame.e2e-host.d.ts +0 -2
  217. package/dist/client/extensions/AgentNativeExtensionFrame.e2e-host.d.ts.map +0 -1
  218. package/dist/client/extensions/AgentNativeExtensionFrame.e2e-host.js +0 -110
  219. package/dist/client/extensions/AgentNativeExtensionFrame.e2e-host.js.map +0 -1
  220. package/dist/client/extensions/AgentNativeExtensionFrame.spec.d.ts +0 -2
  221. package/dist/client/extensions/AgentNativeExtensionFrame.spec.d.ts.map +0 -1
  222. package/dist/client/extensions/AgentNativeExtensionFrame.spec.js +0 -68
  223. package/dist/client/extensions/AgentNativeExtensionFrame.spec.js.map +0 -1
  224. package/dist/client/extensions/ExtensionViewer.spec.d.ts +0 -2
  225. package/dist/client/extensions/ExtensionViewer.spec.d.ts.map +0 -1
  226. package/dist/client/extensions/ExtensionViewer.spec.js +0 -94
  227. package/dist/client/extensions/ExtensionViewer.spec.js.map +0 -1
  228. package/dist/client/guided-questions.flow.spec.d.ts +0 -2
  229. package/dist/client/guided-questions.flow.spec.d.ts.map +0 -1
  230. package/dist/client/guided-questions.flow.spec.js +0 -147
  231. package/dist/client/guided-questions.flow.spec.js.map +0 -1
  232. package/dist/client/settings/useBuilderStatus.spec.d.ts +0 -2
  233. package/dist/client/settings/useBuilderStatus.spec.d.ts.map +0 -1
  234. package/dist/client/settings/useBuilderStatus.spec.js +0 -487
  235. package/dist/client/settings/useBuilderStatus.spec.js.map +0 -1
  236. package/dist/client/sharing/ShareButton.spec.d.ts +0 -2
  237. package/dist/client/sharing/ShareButton.spec.d.ts.map +0 -1
  238. package/dist/client/sharing/ShareButton.spec.js +0 -196
  239. package/dist/client/sharing/ShareButton.spec.js.map +0 -1
  240. package/dist/client/use-chat-models.spec.d.ts +0 -2
  241. package/dist/client/use-chat-models.spec.d.ts.map +0 -1
  242. package/dist/client/use-chat-models.spec.js +0 -39
  243. package/dist/client/use-chat-models.spec.js.map +0 -1
  244. package/dist/client/use-chat-threads.spec.d.ts +0 -2
  245. package/dist/client/use-chat-threads.spec.d.ts.map +0 -1
  246. package/dist/client/use-chat-threads.spec.js +0 -760
  247. package/dist/client/use-chat-threads.spec.js.map +0 -1
  248. package/dist/client/use-db-sync.spec.d.ts +0 -2
  249. package/dist/client/use-db-sync.spec.d.ts.map +0 -1
  250. package/dist/client/use-db-sync.spec.js +0 -107
  251. package/dist/client/use-db-sync.spec.js.map +0 -1
  252. package/dist/server/script-discovery.d.ts +0 -6
  253. package/dist/server/script-discovery.d.ts.map +0 -1
  254. package/dist/server/script-discovery.js +0 -6
  255. package/dist/server/script-discovery.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"use-db-sync.js","sourceRoot":"","sources":["../../src/client/use-db-sync.ts"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { agentNativePath } from \"./api-path.js\";\nimport { bumpChangeVersion } from \"./use-change-version.js\";\nimport { ensureDemoModeFetchInterceptor } from \"../demo/fetch-interceptor.js\";\nimport {\n ensureEmbedAuthFetchInterceptor,\n isEmbedAuthActive,\n} from \"./embed-auth.js\";\n\ninterface QueryClient {\n invalidateQueries(opts?: { queryKey?: string[] }): void;\n}\n\nconst POLL_ABORT_MIN_MS = 10_000;\nconst SSE_FALLBACK_INTERVAL_MS = 15_000;\nconst POLL_AUTH_FAILURE_COOLDOWN_MS = 60_000;\n\nclass HttpStatusError extends Error {\n status: number;\n\n constructor(status: number) {\n super(\"HTTP \" + status);\n this.status = status;\n }\n}\n\ntype SyncEvent = {\n version?: number;\n source?: string;\n type?: string;\n key?: string;\n requestSource?: string;\n [k: string]: unknown;\n};\n\ntype PollResponse = {\n version: number;\n events: SyncEvent[];\n};\n\nfunction getPollAbortMs(interval: number): number {\n return Math.max(POLL_ABORT_MIN_MS, interval * 4);\n}\n\nfunction isDocumentHidden(): boolean {\n return (\n typeof document !== \"undefined\" && document.visibilityState === \"hidden\"\n );\n}\n\nfunction resolveSseUrl(sseUrl: string | false | undefined): string | false {\n if (sseUrl === false) return false;\n if (isEmbedAuthActive()) return false;\n return agentNativePath(sseUrl ?? \"/_agent-native/events\");\n}\n\nfunction normalizeEventPayload(payload: unknown): SyncEvent[] {\n if (!payload || typeof payload !== \"object\") return [];\n const record = payload as { type?: unknown; events?: unknown };\n if (record.type === \"batch\" && Array.isArray(record.events)) {\n return record.events.filter(\n (event): event is SyncEvent => !!event && typeof event === \"object\",\n );\n }\n if (Array.isArray(record.events)) {\n return record.events.filter(\n (event): event is SyncEvent => !!event && typeof event === \"object\",\n );\n }\n return [payload as SyncEvent];\n}\n\nfunction eventVersion(event: SyncEvent): number {\n return typeof event.version === \"number\" ? event.version : 0;\n}\n\nfunction hasAppStateEvent(events: SyncEvent[], key: string): boolean {\n return events.some(\n (event) =>\n event.source === \"app-state\" &&\n (event.key === key ||\n event.key === \"*\" ||\n (typeof event.key === \"string\" && event.key.startsWith(`${key}:`))),\n );\n}\n\nfunction isAuthFailure(error: unknown): boolean {\n return (\n !!error &&\n typeof error === \"object\" &&\n \"status\" in error &&\n ((error as { status?: unknown }).status === 401 ||\n (error as { status?: unknown }).status === 403)\n );\n}\n\nasync function fetchPollJson<T>(\n pollUrl: string,\n since: number,\n interval: number,\n): Promise<T> {\n const controller =\n typeof AbortController === \"undefined\" ? null : new AbortController();\n const timeout = controller\n ? setTimeout(() => controller.abort(), getPollAbortMs(interval))\n : null;\n\n try {\n const res = await fetch(\n `${pollUrl}?since=${since}`,\n controller ? { signal: controller.signal } : undefined,\n );\n if (!res.ok) throw new HttpStatusError(res.status);\n // Await the json before the finally so a body-stream abort doesn't\n // produce a dangling promise that escapes as an unhandled rejection.\n return await res.json();\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n}\n\n/**\n * Hook that listens to /_agent-native/events for DB change events and\n * invalidates react-query caches when changes are detected. Falls back to\n * /_agent-native/poll so cross-process/serverless writes still show up.\n *\n * Works in all deployment environments (serverless, edge, long-lived server).\n * SSE is the fast path; polling is the safety net.\n *\n * @param options.queryClient - The react-query QueryClient instance\n * @param options.queryKeys - **Deprecated and ignored.** The hook uses\n * framework-owned fixed prefixes plus per-source change counters instead of\n * caller-supplied key lists. Kept in the type signature for backward\n * compatibility — existing call sites that still pass this option keep\n * working but the value has no effect.\n * @param options.pollUrl - Poll endpoint URL. Default: \"/_agent-native/poll\"\n * @param options.sseUrl - SSE endpoint URL. Default: \"/_agent-native/events\".\n * Pass false to disable SSE and use polling only.\n * @param options.onEvent - Optional callback for each change event\n * @param options.interval - Poll interval in ms. Default: 2000\n * @param options.fallbackInterval - Poll interval while SSE is connected.\n * Default: 15000\n * @param options.pauseWhenHidden - Pause polling while the tab is hidden.\n * Default: true\n * @param options.ignoreSource - Skip events whose `requestSource` matches this\n * value. Use a per-tab ID so the UI ignores its own writes while still\n * picking up changes from other tabs, agents, and scripts.\n */\nexport function useDbSync(\n options: {\n queryClient?: QueryClient;\n queryKeys?: string[];\n pollUrl?: string;\n sseUrl?: string | false;\n /** @deprecated Use pollUrl instead */\n eventsUrl?: string;\n onEvent?: (data: any) => void;\n interval?: number;\n fallbackInterval?: number;\n pauseWhenHidden?: boolean;\n ignoreSource?: string;\n } = {},\n): void {\n const {\n queryClient,\n pollUrl = agentNativePath(options.eventsUrl ?? \"/_agent-native/poll\"),\n sseUrl = resolveSseUrl(options.sseUrl),\n interval = 2000,\n fallbackInterval = Math.max(\n options.fallbackInterval ?? SSE_FALLBACK_INTERVAL_MS,\n interval,\n ),\n pauseWhenHidden = true,\n } = options;\n\n const onEventRef = useRef(options.onEvent);\n onEventRef.current = options.onEvent;\n\n const ignoreSourceRef = useRef(options.ignoreSource);\n ignoreSourceRef.current = options.ignoreSource;\n\n useEffect(() => {\n // Universal demo-mode redaction for the UI. Idempotent + browser-only +\n // a no-op until demo mode is on. Lives here because every template root\n // already mounts useDbSync, so this needs zero per-template wiring.\n ensureEmbedAuthFetchInterceptor();\n ensureDemoModeFetchInterceptor();\n\n let versionRef = 0;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let stopped = false;\n let inFlight = false;\n let eventSource: EventSource | null = null;\n let sseConnected = false;\n let authFailureUntil = 0;\n\n function authFailureDelayMs(): number {\n return Math.max(0, authFailureUntil - Date.now());\n }\n\n function schedulePoll() {\n if (stopped) return;\n if (pauseWhenHidden && isDocumentHidden()) return;\n if (timer) clearTimeout(timer);\n const authDelay = authFailureDelayMs();\n if (authDelay > 0) {\n timer = setTimeout(() => {\n timer = null;\n void poll();\n }, authDelay);\n return;\n }\n timer = setTimeout(\n () => {\n timer = null;\n void poll();\n },\n sseConnected ? fallbackInterval : interval,\n );\n }\n\n function invalidateForEvents(events: SyncEvent[]) {\n const ignore = ignoreSourceRef.current;\n const relevant = ignore\n ? events.filter((e) => e.requestSource !== ignore)\n : events;\n\n // Bump per-source change counters. Components that read these via\n // `useChangeVersion(source)` and fold the value into a React Query\n // queryKey get a targeted refetch — no whole-cache invalidate, no\n // request storm. See `use-change-version.ts` for the contract.\n for (const evt of relevant) {\n const src = typeof evt.source === \"string\" ? evt.source : \"\";\n const ver = typeof evt.version === \"number\" ? evt.version : 0;\n if (src && ver > 0) bumpChangeVersion(src, ver);\n }\n\n if (relevant.length > 0 && queryClient) {\n const hasActionEvent = relevant.some((evt) => evt.source === \"action\");\n if (hasActionEvent) {\n // Custom apps frequently start with raw `useQuery` calls before\n // graduating to `useActionQuery` or source-versioned query keys.\n // A successful mutating action is the core \"agent changed app data\"\n // signal, so refresh active queries broadly as a compatibility\n // safety net. Other event sources stay targeted to avoid request\n // storms from noisy domain-specific writes.\n queryClient.invalidateQueries();\n }\n\n // Framework-level invalidate: a small, fixed list of query-key\n // prefixes the framework's own hooks/components use (action results,\n // extension state, application-state, the agent's `set-url` channel,\n // etc.). Templates' own data queries do NOT live here — they react\n // through `useChangeVersion(source)` in their query keys instead, so\n // a single change event doesn't fan out into \"refetch everything\".\n queryClient.invalidateQueries({ queryKey: [\"action\"] });\n queryClient.invalidateQueries({ queryKey: [\"extension\"] });\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n queryClient.invalidateQueries({ queryKey: [\"extension-slots\"] });\n queryClient.invalidateQueries({ queryKey: [\"slot-installs\"] });\n queryClient.invalidateQueries({ queryKey: [\"slot-available\"] });\n queryClient.invalidateQueries({ queryKey: [\"tool\"] });\n queryClient.invalidateQueries({ queryKey: [\"tools\"] });\n queryClient.invalidateQueries({ queryKey: [\"app-state\"] });\n if (hasAppStateEvent(relevant, \"navigate\")) {\n queryClient.invalidateQueries({ queryKey: [\"navigate-command\"] });\n }\n if (hasAppStateEvent(relevant, \"show-questions\")) {\n queryClient.invalidateQueries({ queryKey: [\"show-questions\"] });\n }\n if (hasAppStateEvent(relevant, \"__set_url__\")) {\n queryClient.invalidateQueries({ queryKey: [\"__set_url__\"] });\n }\n }\n\n // Always forward all events to onEvent — templates can layer surgical\n // logic on top (e.g. ignore their own writes via requestSource, or\n // invalidate inactive queries for a specific source).\n for (const evt of events) {\n onEventRef.current?.(evt);\n }\n }\n\n function applyEvents(events: SyncEvent[], version?: number) {\n const freshEvents = events.filter((event) => {\n const version = eventVersion(event);\n return version === 0 || version > versionRef;\n });\n\n if (freshEvents.length > 0) {\n invalidateForEvents(freshEvents);\n }\n\n const maxEventVersion = freshEvents.reduce(\n (max, event) => Math.max(max, eventVersion(event)),\n 0,\n );\n versionRef = Math.max(versionRef, version ?? 0, maxEventVersion);\n }\n\n function closeEvents() {\n if (!eventSource) return;\n eventSource.close();\n eventSource = null;\n sseConnected = false;\n }\n\n function connectEvents() {\n if (\n stopped ||\n !sseUrl ||\n eventSource ||\n typeof EventSource === \"undefined\" ||\n (pauseWhenHidden && isDocumentHidden())\n ) {\n return;\n }\n\n const source = new EventSource(sseUrl);\n eventSource = source;\n source.onopen = () => {\n sseConnected = true;\n schedulePoll();\n };\n source.onerror = () => {\n sseConnected = false;\n schedulePoll();\n };\n source.onmessage = (message) => {\n try {\n const payload = JSON.parse(message.data);\n const events = normalizeEventPayload(payload);\n const version =\n typeof payload?.version === \"number\" ? payload.version : undefined;\n applyEvents(events, version);\n } catch {\n // Ignore malformed SSE frames; polling is the safety net.\n }\n };\n }\n\n async function poll() {\n if (stopped || inFlight) return;\n inFlight = true;\n try {\n const data = await fetchPollJson<PollResponse>(\n pollUrl,\n versionRef,\n interval,\n );\n applyEvents(data.events ?? [], data.version);\n } catch (err) {\n if (isAuthFailure(err)) {\n authFailureUntil = Date.now() + POLL_AUTH_FAILURE_COOLDOWN_MS;\n closeEvents();\n }\n // Network error — will retry on next interval\n } finally {\n inFlight = false;\n schedulePoll();\n }\n }\n\n function pollNow() {\n if (pauseWhenHidden && isDocumentHidden()) {\n return;\n }\n if (authFailureDelayMs() > 0) {\n schedulePoll();\n return;\n }\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n connectEvents();\n void poll();\n }\n\n function handleVisibilityChange() {\n if (document.visibilityState === \"visible\") {\n connectEvents();\n pollNow();\n } else if (pauseWhenHidden) {\n closeEvents();\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n }\n }\n\n // Initial poll immediately when visible. Hidden tabs catch up on focus.\n if (!pauseWhenHidden || !isDocumentHidden()) {\n connectEvents();\n void poll();\n }\n window.addEventListener(\"focus\", pollNow);\n document.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n return () => {\n stopped = true;\n closeEvents();\n if (timer) clearTimeout(timer);\n window.removeEventListener(\"focus\", pollNow);\n document.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n };\n }, [\n pollUrl,\n sseUrl,\n queryClient,\n interval,\n fallbackInterval,\n pauseWhenHidden,\n ]);\n}\n\n/** @deprecated Use useDbSync instead */\nexport const useFileWatcher = useDbSync;\n\n/**\n * Subscribe to `refresh-screen` events from the agent. Returns an integer\n * that increments every time the agent invokes the framework's `refresh-screen`\n * tool. Apply it as a React `key` on the main content wrapper (the part\n * OUTSIDE the agent chat sidebar) so that region remounts and re-fetches its\n * data while the chat, sidebar, and any other persistent chrome keep their\n * in-flight state.\n *\n * Usage in a template's root:\n *\n * const screenKey = useScreenRefreshKey();\n * return (\n * <AppLayout>\n * <div key={screenKey}>\n * <Outlet />\n * </div>\n * </AppLayout>\n * );\n */\nexport function useScreenRefreshKey(\n options: {\n pollUrl?: string;\n sseUrl?: string | false;\n interval?: number;\n fallbackInterval?: number;\n pauseWhenHidden?: boolean;\n } = {},\n): number {\n const {\n pollUrl = agentNativePath(options.pollUrl ?? \"/_agent-native/poll\"),\n sseUrl = resolveSseUrl(options.sseUrl),\n interval = 2000,\n fallbackInterval = Math.max(\n options.fallbackInterval ?? SSE_FALLBACK_INTERVAL_MS,\n interval,\n ),\n pauseWhenHidden = true,\n } = options;\n const [key, setKey] = useState(0);\n\n useEffect(() => {\n let versionRef = 0;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let stopped = false;\n let inFlight = false;\n let eventSource: EventSource | null = null;\n let sseConnected = false;\n let authFailureUntil = 0;\n\n function authFailureDelayMs(): number {\n return Math.max(0, authFailureUntil - Date.now());\n }\n\n function schedulePoll() {\n if (stopped) return;\n if (pauseWhenHidden && isDocumentHidden()) return;\n if (timer) clearTimeout(timer);\n const authDelay = authFailureDelayMs();\n if (authDelay > 0) {\n timer = setTimeout(() => {\n timer = null;\n void poll();\n }, authDelay);\n return;\n }\n timer = setTimeout(\n () => {\n timer = null;\n void poll();\n },\n sseConnected ? fallbackInterval : interval,\n );\n }\n\n function applyEvents(events: SyncEvent[], version?: number) {\n const freshEvents = events.filter((event) => {\n const version = eventVersion(event);\n return version === 0 || version > versionRef;\n });\n if (freshEvents.some((e) => e.source === \"screen-refresh\")) {\n setKey((k) => k + 1);\n }\n const maxEventVersion = freshEvents.reduce(\n (max, event) => Math.max(max, eventVersion(event)),\n 0,\n );\n versionRef = Math.max(versionRef, version ?? 0, maxEventVersion);\n }\n\n function closeEvents() {\n if (!eventSource) return;\n eventSource.close();\n eventSource = null;\n sseConnected = false;\n }\n\n function connectEvents() {\n if (\n stopped ||\n !sseUrl ||\n eventSource ||\n typeof EventSource === \"undefined\" ||\n (pauseWhenHidden && isDocumentHidden())\n ) {\n return;\n }\n\n const source = new EventSource(sseUrl);\n eventSource = source;\n source.onopen = () => {\n sseConnected = true;\n schedulePoll();\n };\n source.onerror = () => {\n sseConnected = false;\n schedulePoll();\n };\n source.onmessage = (message) => {\n try {\n const payload = JSON.parse(message.data);\n const events = normalizeEventPayload(payload);\n const version =\n typeof payload?.version === \"number\" ? payload.version : undefined;\n applyEvents(events, version);\n } catch {\n // Polling will catch missed screen-refresh events.\n }\n };\n }\n\n async function poll() {\n if (stopped || inFlight) return;\n inFlight = true;\n try {\n const data = await fetchPollJson<PollResponse>(\n pollUrl,\n versionRef,\n interval,\n );\n applyEvents(data.events ?? [], data.version);\n } catch (err) {\n if (isAuthFailure(err)) {\n authFailureUntil = Date.now() + POLL_AUTH_FAILURE_COOLDOWN_MS;\n closeEvents();\n }\n // Network error — retry on next interval.\n } finally {\n inFlight = false;\n schedulePoll();\n }\n }\n\n function pollNow() {\n if (pauseWhenHidden && isDocumentHidden()) {\n return;\n }\n if (authFailureDelayMs() > 0) {\n schedulePoll();\n return;\n }\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n connectEvents();\n void poll();\n }\n\n function handleVisibilityChange() {\n if (document.visibilityState === \"visible\") {\n connectEvents();\n pollNow();\n } else if (pauseWhenHidden) {\n closeEvents();\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n }\n }\n\n if (!pauseWhenHidden || !isDocumentHidden()) {\n connectEvents();\n void poll();\n }\n window.addEventListener(\"focus\", pollNow);\n document.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n return () => {\n stopped = true;\n closeEvents();\n if (timer) clearTimeout(timer);\n window.removeEventListener(\"focus\", pollNow);\n document.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n };\n }, [pollUrl, sseUrl, interval, fallbackInterval, pauseWhenHidden]);\n\n return key;\n}\n"]}
1
+ {"version":3,"file":"use-db-sync.js","sourceRoot":"","sources":["../../src/client/use-db-sync.ts"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { agentNativePath } from \"./api-path.js\";\nimport { bumpChangeVersion } from \"./use-change-version.js\";\nimport { ensureDemoModeFetchInterceptor } from \"../demo/fetch-interceptor.js\";\nimport {\n ensureEmbedAuthFetchInterceptor,\n isEmbedAuthActive,\n} from \"./embed-auth.js\";\n\ninterface QueryClient {\n invalidateQueries(opts?: { queryKey?: string[] }): void;\n}\n\nconst POLL_ABORT_MIN_MS = 10_000;\nconst SSE_FALLBACK_INTERVAL_MS = 15_000;\nconst POLL_AUTH_FAILURE_COOLDOWN_MS = 60_000;\n\nclass HttpStatusError extends Error {\n status: number;\n\n constructor(status: number) {\n super(\"HTTP \" + status);\n this.status = status;\n }\n}\n\ntype SyncEvent = {\n version?: number;\n source?: string;\n type?: string;\n key?: string;\n requestSource?: string;\n [k: string]: unknown;\n};\n\ntype PollResponse = {\n version: number;\n events: SyncEvent[];\n};\n\nfunction getPollAbortMs(interval: number): number {\n return Math.max(POLL_ABORT_MIN_MS, interval * 4);\n}\n\nfunction isDocumentHidden(): boolean {\n return (\n typeof document !== \"undefined\" && document.visibilityState === \"hidden\"\n );\n}\n\nfunction resolveSseUrl(sseUrl: string | false | undefined): string | false {\n if (sseUrl === false) return false;\n if (isEmbedAuthActive()) return false;\n return agentNativePath(sseUrl ?? \"/_agent-native/events\");\n}\n\nfunction normalizeEventPayload(payload: unknown): SyncEvent[] {\n if (!payload || typeof payload !== \"object\") return [];\n const record = payload as { type?: unknown; events?: unknown };\n if (record.type === \"batch\" && Array.isArray(record.events)) {\n return record.events.filter(\n (event): event is SyncEvent => !!event && typeof event === \"object\",\n );\n }\n if (Array.isArray(record.events)) {\n return record.events.filter(\n (event): event is SyncEvent => !!event && typeof event === \"object\",\n );\n }\n return [payload as SyncEvent];\n}\n\nfunction eventVersion(event: SyncEvent): number {\n return typeof event.version === \"number\" ? event.version : 0;\n}\n\nfunction hasAppStateEvent(events: SyncEvent[], key: string): boolean {\n return events.some(\n (event) =>\n event.source === \"app-state\" &&\n (event.key === key ||\n event.key === \"*\" ||\n (typeof event.key === \"string\" && event.key.startsWith(`${key}:`))),\n );\n}\n\nfunction isAuthFailure(error: unknown): boolean {\n return (\n !!error &&\n typeof error === \"object\" &&\n \"status\" in error &&\n ((error as { status?: unknown }).status === 401 ||\n (error as { status?: unknown }).status === 403)\n );\n}\n\nasync function fetchPollJson<T>(\n pollUrl: string,\n since: number,\n interval: number,\n): Promise<T> {\n const controller =\n typeof AbortController === \"undefined\" ? null : new AbortController();\n const timeout = controller\n ? setTimeout(() => controller.abort(), getPollAbortMs(interval))\n : null;\n\n try {\n const res = await fetch(\n `${pollUrl}?since=${since}`,\n controller ? { signal: controller.signal } : undefined,\n );\n if (!res.ok) throw new HttpStatusError(res.status);\n // Await the json before the finally so a body-stream abort doesn't\n // produce a dangling promise that escapes as an unhandled rejection.\n return await res.json();\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n}\n\n/**\n * Hook that listens to /_agent-native/events for DB change events and\n * invalidates react-query caches when changes are detected. Falls back to\n * /_agent-native/poll so cross-process/serverless writes still show up.\n *\n * Works in all deployment environments (serverless, edge, long-lived server).\n * SSE is the fast path; polling is the safety net.\n *\n * @param options.queryClient - The react-query QueryClient instance\n * @param options.queryKeys - **Deprecated and ignored.** The hook uses\n * framework-owned fixed prefixes plus per-source change counters instead of\n * caller-supplied key lists. Kept in the type signature for backward\n * compatibility — existing call sites that still pass this option keep\n * working but the value has no effect.\n * @param options.pollUrl - Poll endpoint URL. Default: \"/_agent-native/poll\"\n * @param options.sseUrl - SSE endpoint URL. Default: \"/_agent-native/events\".\n * Pass false to disable SSE and use polling only.\n * @param options.onEvent - Optional callback for each change event\n * @param options.interval - Poll interval in ms. Default: 2000\n * @param options.fallbackInterval - Poll interval while SSE is connected.\n * Default: 15000\n * @param options.pauseWhenHidden - Pause polling while the tab is hidden.\n * Default: true\n * @param options.ignoreSource - Skip events whose `requestSource` matches this\n * value. Use a per-tab ID so the UI ignores its own writes while still\n * picking up changes from other tabs, agents, and scripts.\n */\nexport function useDbSync(\n options: {\n queryClient?: QueryClient;\n queryKeys?: string[];\n pollUrl?: string;\n sseUrl?: string | false;\n /** @deprecated Use pollUrl instead */\n eventsUrl?: string;\n onEvent?: (data: any) => void;\n interval?: number;\n fallbackInterval?: number;\n pauseWhenHidden?: boolean;\n ignoreSource?: string;\n } = {},\n): void {\n const {\n queryClient,\n pollUrl = agentNativePath(options.eventsUrl ?? \"/_agent-native/poll\"),\n sseUrl = resolveSseUrl(options.sseUrl),\n interval = 2000,\n fallbackInterval = Math.max(\n options.fallbackInterval ?? SSE_FALLBACK_INTERVAL_MS,\n interval,\n ),\n pauseWhenHidden = true,\n } = options;\n\n const onEventRef = useRef(options.onEvent);\n onEventRef.current = options.onEvent;\n\n const ignoreSourceRef = useRef(options.ignoreSource);\n ignoreSourceRef.current = options.ignoreSource;\n\n useEffect(() => {\n // Universal demo-mode redaction for the UI. Idempotent + browser-only +\n // a no-op until demo mode is on. Lives here because every template root\n // already mounts useDbSync, so this needs zero per-template wiring.\n ensureEmbedAuthFetchInterceptor();\n ensureDemoModeFetchInterceptor();\n\n let versionRef = 0;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let stopped = false;\n let inFlight = false;\n let eventSource: EventSource | null = null;\n let sseConnected = false;\n let authFailureUntil = 0;\n\n function authFailureDelayMs(): number {\n return Math.max(0, authFailureUntil - Date.now());\n }\n\n function schedulePoll() {\n if (stopped) return;\n if (pauseWhenHidden && isDocumentHidden()) return;\n if (timer) clearTimeout(timer);\n const authDelay = authFailureDelayMs();\n if (authDelay > 0) {\n timer = setTimeout(() => {\n timer = null;\n void poll();\n }, authDelay);\n return;\n }\n timer = setTimeout(\n () => {\n timer = null;\n void poll();\n },\n sseConnected ? fallbackInterval : interval,\n );\n }\n\n function invalidateForEvents(events: SyncEvent[]) {\n const ignore = ignoreSourceRef.current;\n const relevant = ignore\n ? events.filter((e) => e.requestSource !== ignore)\n : events;\n\n // Bump per-source change counters. Components that read these via\n // `useChangeVersion(source)` and fold the value into a React Query\n // queryKey get a targeted refetch — no whole-cache invalidate, no\n // request storm. See `use-change-version.ts` for the contract.\n for (const evt of relevant) {\n const src = typeof evt.source === \"string\" ? evt.source : \"\";\n const ver = typeof evt.version === \"number\" ? evt.version : 0;\n if (src && ver > 0) bumpChangeVersion(src, ver);\n }\n\n if (relevant.length > 0 && queryClient) {\n const hasActionEvent = relevant.some((evt) => evt.source === \"action\");\n if (hasActionEvent) {\n // Custom apps frequently start with raw `useQuery` calls before\n // graduating to `useActionQuery` or source-versioned query keys.\n // A successful mutating action is the core \"agent changed app data\"\n // signal, so refresh active queries broadly as a compatibility\n // safety net. Other event sources stay targeted to avoid request\n // storms from noisy domain-specific writes.\n queryClient.invalidateQueries();\n }\n\n // Framework-level invalidate: a small, fixed list of query-key\n // prefixes the framework's own hooks/components use (action results,\n // extension state, application-state, the agent's `set-url` channel,\n // etc.). Templates' own data queries do NOT live here — they react\n // through `useChangeVersion(source)` in their query keys instead, so\n // a single change event doesn't fan out into \"refetch everything\".\n queryClient.invalidateQueries({ queryKey: [\"action\"] });\n queryClient.invalidateQueries({ queryKey: [\"extension\"] });\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n queryClient.invalidateQueries({ queryKey: [\"extension-slots\"] });\n queryClient.invalidateQueries({ queryKey: [\"slot-installs\"] });\n queryClient.invalidateQueries({ queryKey: [\"slot-available\"] });\n queryClient.invalidateQueries({ queryKey: [\"tool\"] });\n queryClient.invalidateQueries({ queryKey: [\"tools\"] });\n queryClient.invalidateQueries({ queryKey: [\"app-state\"] });\n if (hasAppStateEvent(relevant, \"navigate\")) {\n queryClient.invalidateQueries({ queryKey: [\"navigate-command\"] });\n }\n if (hasAppStateEvent(relevant, \"show-questions\")) {\n queryClient.invalidateQueries({ queryKey: [\"show-questions\"] });\n }\n if (hasAppStateEvent(relevant, \"__set_url__\")) {\n queryClient.invalidateQueries({ queryKey: [\"__set_url__\"] });\n }\n }\n\n // Always forward all events to onEvent — templates can layer surgical\n // logic on top (e.g. ignore their own writes via requestSource, or\n // invalidate inactive queries for a specific source).\n for (const evt of events) {\n onEventRef.current?.(evt);\n }\n }\n\n function applyEvents(events: SyncEvent[], version?: number) {\n const freshEvents = events.filter((event) => {\n const version = eventVersion(event);\n return version === 0 || version > versionRef;\n });\n\n if (freshEvents.length > 0) {\n invalidateForEvents(freshEvents);\n }\n\n const maxEventVersion = freshEvents.reduce(\n (max, event) => Math.max(max, eventVersion(event)),\n 0,\n );\n versionRef = Math.max(versionRef, version ?? 0, maxEventVersion);\n }\n\n function closeEvents() {\n if (!eventSource) return;\n eventSource.close();\n eventSource = null;\n sseConnected = false;\n }\n\n function connectEvents() {\n if (\n stopped ||\n !sseUrl ||\n eventSource ||\n typeof EventSource === \"undefined\" ||\n (pauseWhenHidden && isDocumentHidden())\n ) {\n return;\n }\n\n const source = new EventSource(sseUrl);\n eventSource = source;\n source.onopen = () => {\n sseConnected = true;\n schedulePoll();\n };\n source.onerror = () => {\n sseConnected = false;\n schedulePoll();\n };\n source.onmessage = (message) => {\n try {\n const payload = JSON.parse(message.data);\n const events = normalizeEventPayload(payload);\n const version =\n typeof payload?.version === \"number\" ? payload.version : undefined;\n applyEvents(events, version);\n } catch {\n // Ignore malformed SSE frames; polling is the safety net.\n }\n };\n }\n\n async function poll() {\n if (stopped || inFlight) return;\n inFlight = true;\n try {\n const data = await fetchPollJson<PollResponse>(\n pollUrl,\n versionRef,\n interval,\n );\n if (stopped) return;\n applyEvents(data.events ?? [], data.version);\n } catch (err) {\n if (stopped) return;\n if (isAuthFailure(err)) {\n authFailureUntil = Date.now() + POLL_AUTH_FAILURE_COOLDOWN_MS;\n closeEvents();\n }\n // Network error — will retry on next interval\n } finally {\n inFlight = false;\n schedulePoll();\n }\n }\n\n function pollNow() {\n if (pauseWhenHidden && isDocumentHidden()) {\n return;\n }\n if (authFailureDelayMs() > 0) {\n schedulePoll();\n return;\n }\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n connectEvents();\n void poll();\n }\n\n function handleVisibilityChange() {\n if (document.visibilityState === \"visible\") {\n connectEvents();\n pollNow();\n } else if (pauseWhenHidden) {\n closeEvents();\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n }\n }\n\n // Initial poll immediately when visible. Hidden tabs catch up on focus.\n if (!pauseWhenHidden || !isDocumentHidden()) {\n connectEvents();\n void poll();\n }\n window.addEventListener(\"focus\", pollNow);\n document.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n return () => {\n stopped = true;\n closeEvents();\n if (timer) clearTimeout(timer);\n window.removeEventListener(\"focus\", pollNow);\n document.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n };\n }, [\n pollUrl,\n sseUrl,\n queryClient,\n interval,\n fallbackInterval,\n pauseWhenHidden,\n ]);\n}\n\n/** @deprecated Use useDbSync instead */\nexport const useFileWatcher = useDbSync;\n\n/**\n * Subscribe to `refresh-screen` events from the agent. Returns an integer\n * that increments every time the agent invokes the framework's `refresh-screen`\n * tool. Apply it as a React `key` on the main content wrapper (the part\n * OUTSIDE the agent chat sidebar) so that region remounts and re-fetches its\n * data while the chat, sidebar, and any other persistent chrome keep their\n * in-flight state.\n *\n * Usage in a template's root:\n *\n * const screenKey = useScreenRefreshKey();\n * return (\n * <AppLayout>\n * <div key={screenKey}>\n * <Outlet />\n * </div>\n * </AppLayout>\n * );\n */\nexport function useScreenRefreshKey(\n options: {\n pollUrl?: string;\n sseUrl?: string | false;\n interval?: number;\n fallbackInterval?: number;\n pauseWhenHidden?: boolean;\n } = {},\n): number {\n const {\n pollUrl = agentNativePath(options.pollUrl ?? \"/_agent-native/poll\"),\n sseUrl = resolveSseUrl(options.sseUrl),\n interval = 2000,\n fallbackInterval = Math.max(\n options.fallbackInterval ?? SSE_FALLBACK_INTERVAL_MS,\n interval,\n ),\n pauseWhenHidden = true,\n } = options;\n const [key, setKey] = useState(0);\n\n useEffect(() => {\n let versionRef = 0;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let stopped = false;\n let inFlight = false;\n let eventSource: EventSource | null = null;\n let sseConnected = false;\n let authFailureUntil = 0;\n\n function authFailureDelayMs(): number {\n return Math.max(0, authFailureUntil - Date.now());\n }\n\n function schedulePoll() {\n if (stopped) return;\n if (pauseWhenHidden && isDocumentHidden()) return;\n if (timer) clearTimeout(timer);\n const authDelay = authFailureDelayMs();\n if (authDelay > 0) {\n timer = setTimeout(() => {\n timer = null;\n void poll();\n }, authDelay);\n return;\n }\n timer = setTimeout(\n () => {\n timer = null;\n void poll();\n },\n sseConnected ? fallbackInterval : interval,\n );\n }\n\n function applyEvents(events: SyncEvent[], version?: number) {\n const freshEvents = events.filter((event) => {\n const version = eventVersion(event);\n return version === 0 || version > versionRef;\n });\n if (freshEvents.some((e) => e.source === \"screen-refresh\")) {\n setKey((k) => k + 1);\n }\n const maxEventVersion = freshEvents.reduce(\n (max, event) => Math.max(max, eventVersion(event)),\n 0,\n );\n versionRef = Math.max(versionRef, version ?? 0, maxEventVersion);\n }\n\n function closeEvents() {\n if (!eventSource) return;\n eventSource.close();\n eventSource = null;\n sseConnected = false;\n }\n\n function connectEvents() {\n if (\n stopped ||\n !sseUrl ||\n eventSource ||\n typeof EventSource === \"undefined\" ||\n (pauseWhenHidden && isDocumentHidden())\n ) {\n return;\n }\n\n const source = new EventSource(sseUrl);\n eventSource = source;\n source.onopen = () => {\n sseConnected = true;\n schedulePoll();\n };\n source.onerror = () => {\n sseConnected = false;\n schedulePoll();\n };\n source.onmessage = (message) => {\n try {\n const payload = JSON.parse(message.data);\n const events = normalizeEventPayload(payload);\n const version =\n typeof payload?.version === \"number\" ? payload.version : undefined;\n applyEvents(events, version);\n } catch {\n // Polling will catch missed screen-refresh events.\n }\n };\n }\n\n async function poll() {\n if (stopped || inFlight) return;\n inFlight = true;\n try {\n const data = await fetchPollJson<PollResponse>(\n pollUrl,\n versionRef,\n interval,\n );\n if (stopped) return;\n applyEvents(data.events ?? [], data.version);\n } catch (err) {\n if (stopped) return;\n if (isAuthFailure(err)) {\n authFailureUntil = Date.now() + POLL_AUTH_FAILURE_COOLDOWN_MS;\n closeEvents();\n }\n // Network error — retry on next interval.\n } finally {\n inFlight = false;\n schedulePoll();\n }\n }\n\n function pollNow() {\n if (pauseWhenHidden && isDocumentHidden()) {\n return;\n }\n if (authFailureDelayMs() > 0) {\n schedulePoll();\n return;\n }\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n connectEvents();\n void poll();\n }\n\n function handleVisibilityChange() {\n if (document.visibilityState === \"visible\") {\n connectEvents();\n pollNow();\n } else if (pauseWhenHidden) {\n closeEvents();\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n }\n }\n\n if (!pauseWhenHidden || !isDocumentHidden()) {\n connectEvents();\n void poll();\n }\n window.addEventListener(\"focus\", pollNow);\n document.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n return () => {\n stopped = true;\n closeEvents();\n if (timer) clearTimeout(timer);\n window.removeEventListener(\"focus\", pollNow);\n document.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n };\n }, [pollUrl, sseUrl, interval, fallbackInterval, pauseWhenHidden]);\n\n return key;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"use-dev-mode.d.ts","sourceRoot":"","sources":["../../src/client/use-dev-mode.ts"],"names":[],"mappings":"AAqHA;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CACzB,OAAO,SAA+C,GACrD;IACD,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD,CAIA;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,OAAO,SAA+C,GACrD;IACD,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD,CASA"}
1
+ {"version":3,"file":"use-dev-mode.d.ts","sourceRoot":"","sources":["../../src/client/use-dev-mode.ts"],"names":[],"mappings":"AAkIA;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CACzB,OAAO,SAA+C,GACrD;IACD,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD,CAIA;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,OAAO,SAA+C,GACrD;IACD,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD,CASA"}
@@ -73,16 +73,32 @@ function useCodeModeInternal(apiBase) {
73
73
  }, [apiBase]);
74
74
  const setCodeMode = useCallback(async (codeMode) => {
75
75
  // Optimistic update — apply immediately, then confirm with server.
76
- // The endpoint still speaks `devMode` for back-compat.
77
- notifyListeners({ devMode: codeMode, canToggle: true });
78
- const res = await fetch(`${apiBase}/mode`, {
79
- method: "POST",
80
- headers: { "Content-Type": "application/json" },
81
- body: JSON.stringify({ devMode: codeMode }),
76
+ // The endpoint still speaks `devMode` for back-compat. Snapshot the
77
+ // prior state so we can roll back if the server rejects or the request
78
+ // throws; otherwise a failed toggle would leave every subscriber stuck
79
+ // showing the wrong mode until a full reload re-fetches `/mode`.
80
+ const prev = cached;
81
+ notifyListeners({
82
+ devMode: codeMode,
83
+ canToggle: prev?.canToggle ?? true,
82
84
  });
83
- if (res.ok) {
84
- const data = await res.json();
85
- notifyListeners(data);
85
+ try {
86
+ const res = await fetch(`${apiBase}/mode`, {
87
+ method: "POST",
88
+ headers: { "Content-Type": "application/json" },
89
+ body: JSON.stringify({ devMode: codeMode }),
90
+ });
91
+ if (res.ok) {
92
+ const data = await res.json();
93
+ notifyListeners(data);
94
+ }
95
+ else if (prev) {
96
+ notifyListeners(prev);
97
+ }
98
+ }
99
+ catch {
100
+ if (prev)
101
+ notifyListeners(prev);
86
102
  }
87
103
  }, [apiBase]);
88
104
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"use-dev-mode.js","sourceRoot":"","sources":["../../src/client/use-dev-mode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAOhD,IAAI,MAAM,GAAyB,IAAI,CAAC;AACxC,IAAI,YAAY,GAAkC,IAAI,CAAC;AACvD,IAAI,SAAS,GAAwC,IAAI,GAAG,EAAE,CAAC;AAE/D,SAAS,eAAe,CAAC,KAAoB;IAC3C,MAAM,GAAG,KAAK,CAAC;IACf,SAAS,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,mBAAmB;IAC1B,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,KAAK,CAAC;IAChD,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;IACnC,OAAO,CAAC,KAAK,WAAW,IAAI,CAAC,KAAK,WAAW,IAAI,CAAC,KAAK,KAAK,CAAC;AAC/D,CAAC;AAED,SAAS,aAAa,CAAC,OAAe;IACpC,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,YAAY,GAAG,KAAK,CAAC,GAAG,OAAO,OAAO,CAAC;aACpC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YACZ,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;YAC9C,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;QACpB,CAAC,CAAC;aACD,IAAI,CAAC,CAAC,IAAmB,EAAE,EAAE;YAC5B,MAAM,GAAG,IAAI,CAAC;YACd,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE;YACV,sEAAsE;YACtE,sEAAsE;YACtE,qEAAqE;YACrE,kEAAkE;YAClE,MAAM,GAAG,mBAAmB,EAAE;gBAC5B,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;gBACpC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;YACzC,gEAAgE;YAChE,8DAA8D;YAC9D,YAAY,GAAG,IAAI,CAAC;YACpB,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC,CAAC;IACP,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,mBAAmB,CAAC,OAAe;IAM1C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAChC,MAAM,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAC/C,CAAC;IACF,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;IAE5D,SAAS,CAAC,GAAG,EAAE;QACb,iDAAiD;QACjD,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACxB,OAAO,GAAG,EAAE;YACV,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC7B,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,QAAQ,CAAC,MAAM,CAAC,CAAC;YACjB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO;QACT,CAAC;QACD,aAAa,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YAClC,QAAQ,CAAC,GAAG,CAAC,CAAC;YACd,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,MAAM,WAAW,GAAG,WAAW,CAC7B,KAAK,EAAE,QAAiB,EAAE,EAAE;QAC1B,mEAAmE;QACnE,uDAAuD;QACvD,eAAe,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,OAAO,EAAE;YACzC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;SAC5C,CAAC,CAAC;QACH,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;YACX,MAAM,IAAI,GAAkB,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC7C,eAAe,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,EACD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO;QACL,QAAQ,EAAE,KAAK,CAAC,OAAO;QACvB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,SAAS;QACT,WAAW;KACZ,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CACzB,OAAO,GAAG,eAAe,CAAC,2BAA2B,CAAC;IAOtD,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,GACnD,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC/B,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC;AACrE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CACxB,OAAO,GAAG,eAAe,CAAC,2BAA2B,CAAC;IAOtD,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,GACnD,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC/B,OAAO;QACL,SAAS,EAAE,QAAQ;QACnB,SAAS;QACT,SAAS;QACT,UAAU,EAAE,WAAW;KACxB,CAAC;AACJ,CAAC","sourcesContent":["import { useState, useEffect, useCallback } from \"react\";\nimport { agentNativePath } from \"./api-path.js\";\n\ninterface CodeModeState {\n devMode: boolean;\n canToggle: boolean;\n}\n\nlet cached: CodeModeState | null = null;\nlet fetchPromise: Promise<CodeModeState> | null = null;\nlet listeners: Set<(state: CodeModeState) => void> = new Set();\n\nfunction notifyListeners(state: CodeModeState) {\n cached = state;\n listeners.forEach((fn) => fn(state));\n}\n\nfunction isLocalhostHostname(): boolean {\n if (typeof window === \"undefined\") return false;\n const h = window.location.hostname;\n return h === \"localhost\" || h === \"127.0.0.1\" || h === \"::1\";\n}\n\nfunction fetchCodeMode(apiBase: string): Promise<CodeModeState> {\n if (!fetchPromise) {\n fetchPromise = fetch(`${apiBase}/mode`)\n .then((res) => {\n if (!res.ok) throw new Error(`${res.status}`);\n return res.json();\n })\n .then((data: CodeModeState) => {\n cached = data;\n return cached;\n })\n .catch(() => {\n // If the server isn't reachable (503 during boot, connection refused,\n // etc.) but we're clearly on localhost, assume Code mode is on so the\n // CLI tab and Code mode toggle still work. Without this, a transient\n // server error permanently disables code features in the sidebar.\n cached = isLocalhostHostname()\n ? { devMode: true, canToggle: true }\n : { devMode: false, canToggle: false };\n // Null the in-flight promise so the next call retries the fetch\n // and we can pick up the real answer once the server is back.\n fetchPromise = null;\n return cached;\n });\n }\n return fetchPromise;\n}\n\n/**\n * Shared internal state machine backing both `useCodeMode` (primary) and the\n * deprecated `useDevMode` alias. Returns the raw `{ codeMode, canToggle,\n * isLoading, setCodeMode }` shape; the public hooks adapt the field names.\n *\n * The `/mode` endpoint and its `devMode` payload key are unchanged for\n * back-compat — only the user-facing concept name moved from \"dev mode\" to\n * \"Code mode\".\n */\nfunction useCodeModeInternal(apiBase: string): {\n codeMode: boolean;\n canToggle: boolean;\n isLoading: boolean;\n setCodeMode: (codeMode: boolean) => Promise<void>;\n} {\n const [state, setState] = useState<CodeModeState>(\n cached ?? { devMode: false, canToggle: false },\n );\n const [isLoading, setIsLoading] = useState(cached === null);\n\n useEffect(() => {\n // Subscribe to changes from other hook instances\n listeners.add(setState);\n return () => {\n listeners.delete(setState);\n };\n }, []);\n\n useEffect(() => {\n if (cached !== null) {\n setState(cached);\n setIsLoading(false);\n return;\n }\n fetchCodeMode(apiBase).then((val) => {\n setState(val);\n setIsLoading(false);\n });\n }, [apiBase]);\n\n const setCodeMode = useCallback(\n async (codeMode: boolean) => {\n // Optimistic update — apply immediately, then confirm with server.\n // The endpoint still speaks `devMode` for back-compat.\n notifyListeners({ devMode: codeMode, canToggle: true });\n const res = await fetch(`${apiBase}/mode`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ devMode: codeMode }),\n });\n if (res.ok) {\n const data: CodeModeState = await res.json();\n notifyListeners(data);\n }\n },\n [apiBase],\n );\n\n return {\n codeMode: state.devMode,\n canToggle: state.canToggle,\n isLoading,\n setCodeMode,\n };\n}\n\n/**\n * Whether the agent is in \"Code mode\" — the capability toggle that lets the\n * agent run shell/file/raw-DB tools and edit the app's own source code. This is\n * distinct from environment dev mode (NODE_ENV / Vite).\n *\n * Fetches `/_agent-native/agent-chat/mode` on first call, then stays in sync via\n * `setCodeMode`. The endpoint, its `devMode` payload key, the `AGENT_MODE` env\n * var, and the `agent-chat.mode` settings key are unchanged for back-compat.\n */\nexport function useCodeMode(\n apiBase = agentNativePath(\"/_agent-native/agent-chat\"),\n): {\n isCodeMode: boolean;\n canToggle: boolean;\n isLoading: boolean;\n setCodeMode: (codeMode: boolean) => Promise<void>;\n} {\n const { codeMode, canToggle, isLoading, setCodeMode } =\n useCodeModeInternal(apiBase);\n return { isCodeMode: codeMode, canToggle, isLoading, setCodeMode };\n}\n\n/**\n * @deprecated Use {@link useCodeMode} instead. The agent-capability \"dev mode\"\n * was renamed to \"Code mode\" to disambiguate it from environment/NODE_ENV dev\n * mode. This alias preserves the old `{ isDevMode, canToggle, isLoading,\n * setDevMode }` shape so existing callers keep working; it delegates to the same\n * shared internal state as `useCodeMode`.\n */\nexport function useDevMode(\n apiBase = agentNativePath(\"/_agent-native/agent-chat\"),\n): {\n isDevMode: boolean;\n canToggle: boolean;\n isLoading: boolean;\n setDevMode: (devMode: boolean) => Promise<void>;\n} {\n const { codeMode, canToggle, isLoading, setCodeMode } =\n useCodeModeInternal(apiBase);\n return {\n isDevMode: codeMode,\n canToggle,\n isLoading,\n setDevMode: setCodeMode,\n };\n}\n"]}
1
+ {"version":3,"file":"use-dev-mode.js","sourceRoot":"","sources":["../../src/client/use-dev-mode.ts"],"names":[],"mappings":"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","sourcesContent":["import { useState, useEffect, useCallback } from \"react\";\nimport { agentNativePath } from \"./api-path.js\";\n\ninterface CodeModeState {\n devMode: boolean;\n canToggle: boolean;\n}\n\nlet cached: CodeModeState | null = null;\nlet fetchPromise: Promise<CodeModeState> | null = null;\nlet listeners: Set<(state: CodeModeState) => void> = new Set();\n\nfunction notifyListeners(state: CodeModeState) {\n cached = state;\n listeners.forEach((fn) => fn(state));\n}\n\nfunction isLocalhostHostname(): boolean {\n if (typeof window === \"undefined\") return false;\n const h = window.location.hostname;\n return h === \"localhost\" || h === \"127.0.0.1\" || h === \"::1\";\n}\n\nfunction fetchCodeMode(apiBase: string): Promise<CodeModeState> {\n if (!fetchPromise) {\n fetchPromise = fetch(`${apiBase}/mode`)\n .then((res) => {\n if (!res.ok) throw new Error(`${res.status}`);\n return res.json();\n })\n .then((data: CodeModeState) => {\n cached = data;\n return cached;\n })\n .catch(() => {\n // If the server isn't reachable (503 during boot, connection refused,\n // etc.) but we're clearly on localhost, assume Code mode is on so the\n // CLI tab and Code mode toggle still work. Without this, a transient\n // server error permanently disables code features in the sidebar.\n cached = isLocalhostHostname()\n ? { devMode: true, canToggle: true }\n : { devMode: false, canToggle: false };\n // Null the in-flight promise so the next call retries the fetch\n // and we can pick up the real answer once the server is back.\n fetchPromise = null;\n return cached;\n });\n }\n return fetchPromise;\n}\n\n/**\n * Shared internal state machine backing both `useCodeMode` (primary) and the\n * deprecated `useDevMode` alias. Returns the raw `{ codeMode, canToggle,\n * isLoading, setCodeMode }` shape; the public hooks adapt the field names.\n *\n * The `/mode` endpoint and its `devMode` payload key are unchanged for\n * back-compat — only the user-facing concept name moved from \"dev mode\" to\n * \"Code mode\".\n */\nfunction useCodeModeInternal(apiBase: string): {\n codeMode: boolean;\n canToggle: boolean;\n isLoading: boolean;\n setCodeMode: (codeMode: boolean) => Promise<void>;\n} {\n const [state, setState] = useState<CodeModeState>(\n cached ?? { devMode: false, canToggle: false },\n );\n const [isLoading, setIsLoading] = useState(cached === null);\n\n useEffect(() => {\n // Subscribe to changes from other hook instances\n listeners.add(setState);\n return () => {\n listeners.delete(setState);\n };\n }, []);\n\n useEffect(() => {\n if (cached !== null) {\n setState(cached);\n setIsLoading(false);\n return;\n }\n fetchCodeMode(apiBase).then((val) => {\n setState(val);\n setIsLoading(false);\n });\n }, [apiBase]);\n\n const setCodeMode = useCallback(\n async (codeMode: boolean) => {\n // Optimistic update — apply immediately, then confirm with server.\n // The endpoint still speaks `devMode` for back-compat. Snapshot the\n // prior state so we can roll back if the server rejects or the request\n // throws; otherwise a failed toggle would leave every subscriber stuck\n // showing the wrong mode until a full reload re-fetches `/mode`.\n const prev = cached;\n notifyListeners({\n devMode: codeMode,\n canToggle: prev?.canToggle ?? true,\n });\n try {\n const res = await fetch(`${apiBase}/mode`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ devMode: codeMode }),\n });\n if (res.ok) {\n const data: CodeModeState = await res.json();\n notifyListeners(data);\n } else if (prev) {\n notifyListeners(prev);\n }\n } catch {\n if (prev) notifyListeners(prev);\n }\n },\n [apiBase],\n );\n\n return {\n codeMode: state.devMode,\n canToggle: state.canToggle,\n isLoading,\n setCodeMode,\n };\n}\n\n/**\n * Whether the agent is in \"Code mode\" — the capability toggle that lets the\n * agent run shell/file/raw-DB tools and edit the app's own source code. This is\n * distinct from environment dev mode (NODE_ENV / Vite).\n *\n * Fetches `/_agent-native/agent-chat/mode` on first call, then stays in sync via\n * `setCodeMode`. The endpoint, its `devMode` payload key, the `AGENT_MODE` env\n * var, and the `agent-chat.mode` settings key are unchanged for back-compat.\n */\nexport function useCodeMode(\n apiBase = agentNativePath(\"/_agent-native/agent-chat\"),\n): {\n isCodeMode: boolean;\n canToggle: boolean;\n isLoading: boolean;\n setCodeMode: (codeMode: boolean) => Promise<void>;\n} {\n const { codeMode, canToggle, isLoading, setCodeMode } =\n useCodeModeInternal(apiBase);\n return { isCodeMode: codeMode, canToggle, isLoading, setCodeMode };\n}\n\n/**\n * @deprecated Use {@link useCodeMode} instead. The agent-capability \"dev mode\"\n * was renamed to \"Code mode\" to disambiguate it from environment/NODE_ENV dev\n * mode. This alias preserves the old `{ isDevMode, canToggle, isLoading,\n * setDevMode }` shape so existing callers keep working; it delegates to the same\n * shared internal state as `useCodeMode`.\n */\nexport function useDevMode(\n apiBase = agentNativePath(\"/_agent-native/agent-chat\"),\n): {\n isDevMode: boolean;\n canToggle: boolean;\n isLoading: boolean;\n setDevMode: (devMode: boolean) => Promise<void>;\n} {\n const { codeMode, canToggle, isLoading, setCodeMode } =\n useCodeModeInternal(apiBase);\n return {\n isDevMode: codeMode,\n canToggle,\n isLoading,\n setDevMode: setCodeMode,\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"useProductionAgent.d.ts","sourceRoot":"","sources":["../../src/client/useProductionAgent.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,KAAK,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,yBAAyB;IACxC,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IACnC,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,wDAAwD;AACxD,wBAAgB,kBAAkB,CAChC,OAAO,CAAC,EAAE,yBAAyB,GAClC,wBAAwB,CAkN1B"}
1
+ {"version":3,"file":"useProductionAgent.d.ts","sourceRoot":"","sources":["../../src/client/useProductionAgent.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,KAAK,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,yBAAyB;IACxC,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IACnC,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,wDAAwD;AACxD,wBAAgB,kBAAkB,CAChC,OAAO,CAAC,EAAE,yBAAyB,GAClC,wBAAwB,CAwN1B"}
@@ -93,8 +93,12 @@ export function useProductionAgent(options) {
93
93
  if (m.id !== assistantId)
94
94
  return m;
95
95
  const calls = [...(m.toolCalls ?? [])];
96
- // Update last tool call with result
97
- const idx = calls.map((c) => c.tool).lastIndexOf(ev.tool);
96
+ // Results can arrive out of order for concurrent same-named
97
+ // calls, so attach to the first not-yet-resolved match
98
+ // (FIFO) rather than the most recent same-named call.
99
+ let idx = calls.findIndex((c) => c.tool === ev.tool && c.result === undefined);
100
+ if (idx < 0)
101
+ idx = calls.map((c) => c.tool).lastIndexOf(ev.tool);
98
102
  if (idx >= 0)
99
103
  calls[idx] = { ...calls[idx], result: ev.result };
100
104
  return { ...m, toolCalls: calls };
@@ -1 +1 @@
1
- {"version":3,"file":"useProductionAgent.js","sourceRoot":"","sources":["../../src/client/useProductionAgent.ts"],"names":[],"mappings":"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","sourcesContent":["import { useState, useCallback, useRef } from \"react\";\nimport type { AgentMessage, AgentChatEvent } from \"../agent/types.js\";\nimport { formatChatErrorText } from \"./error-format.js\";\nimport { agentNativePath } from \"./api-path.js\";\n\nexport interface ProductionAgentMessage {\n id: string;\n role: \"user\" | \"assistant\";\n content: string;\n toolCalls?: Array<{\n tool: string;\n input: Record<string, string>;\n result?: string;\n }>;\n}\n\nexport interface UseProductionAgentOptions {\n /** API endpoint URL. Default: \"/_agent-native/agent-chat\" */\n apiUrl?: string;\n}\n\nexport interface UseProductionAgentResult {\n messages: ProductionAgentMessage[];\n isGenerating: boolean;\n sendMessage: (text: string) => void;\n clearHistory: () => void;\n}\n\n/** @deprecated Use `AssistantChat` component instead */\nexport function useProductionAgent(\n options?: UseProductionAgentOptions,\n): UseProductionAgentResult {\n const apiUrl =\n options?.apiUrl ?? agentNativePath(\"/_agent-native/agent-chat\");\n const [messages, setMessages] = useState<ProductionAgentMessage[]>([]);\n const [isGenerating, setIsGenerating] = useState(false);\n const abortRef = useRef<AbortController | null>(null);\n\n const sendMessage = useCallback(\n async (text: string) => {\n if (!text.trim() || isGenerating) return;\n\n const userMsg: ProductionAgentMessage = {\n id: `user-${Date.now()}`,\n role: \"user\",\n content: text.trim(),\n };\n\n setMessages((prev) => [...prev, userMsg]);\n setIsGenerating(true);\n\n // Notify any listeners that generation is running\n window.dispatchEvent(\n new CustomEvent(\"agentNative.chatRunning\", {\n detail: { isRunning: true, running: true },\n }),\n );\n\n // Build history for this request — skip empty-content messages\n // (assistant turns with only tool calls have no text content to send)\n const history: AgentMessage[] = messages\n .filter((m) => m.content.trim())\n .map((m) => ({\n role: m.role,\n content: m.content,\n }));\n\n const assistantId = `assistant-${Date.now()}`;\n const assistantMsg: ProductionAgentMessage = {\n id: assistantId,\n role: \"assistant\",\n content: \"\",\n toolCalls: [],\n };\n setMessages((prev) => [...prev, assistantMsg]);\n\n const abort = new AbortController();\n abortRef.current = abort;\n\n try {\n const res = await fetch(apiUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ message: text.trim(), history }),\n signal: abort.signal,\n });\n\n if (!res.ok || !res.body) {\n throw new Error(`Server error: ${res.status}`);\n }\n\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n let buf = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buf += decoder.decode(value, { stream: true });\n const lines = buf.split(\"\\n\");\n buf = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) continue;\n const raw = line.slice(6).trim();\n if (!raw) continue;\n\n let ev: AgentChatEvent;\n try {\n ev = JSON.parse(raw);\n } catch {\n continue;\n }\n\n if (ev.type === \"text\") {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantId\n ? { ...m, content: m.content + ev.text }\n : m,\n ),\n );\n } else if (ev.type === \"tool_start\") {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantId\n ? {\n ...m,\n toolCalls: [\n ...(m.toolCalls ?? []),\n { tool: ev.tool, input: ev.input },\n ],\n }\n : m,\n ),\n );\n } else if (ev.type === \"tool_done\") {\n setMessages((prev) =>\n prev.map((m) => {\n if (m.id !== assistantId) return m;\n const calls = [...(m.toolCalls ?? [])];\n // Update last tool call with result\n const idx = calls.map((c) => c.tool).lastIndexOf(ev.tool);\n if (idx >= 0)\n calls[idx] = { ...calls[idx], result: ev.result };\n return { ...m, toolCalls: calls };\n }),\n );\n } else if (ev.type === \"agent_call\") {\n const agentName = ev.agent;\n if (ev.status === \"start\") {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantId\n ? {\n ...m,\n toolCalls: [\n ...(m.toolCalls ?? []),\n {\n tool: `agent:${agentName}`,\n input: {},\n },\n ],\n }\n : m,\n ),\n );\n } else if (ev.status === \"done\" || ev.status === \"error\") {\n setMessages((prev) =>\n prev.map((m) => {\n if (m.id !== assistantId) return m;\n const calls = [...(m.toolCalls ?? [])];\n const idx = calls\n .map((c) => c.tool)\n .lastIndexOf(`agent:${agentName}`);\n if (idx >= 0)\n calls[idx] = {\n ...calls[idx],\n result:\n ev.status === \"error\"\n ? \"Error calling agent\"\n : \"Done\",\n };\n return { ...m, toolCalls: calls };\n }),\n );\n }\n } else if (ev.type === \"done\" || ev.type === \"error\") {\n if (ev.type === \"error\") {\n const fallbackContent = formatChatErrorText(\n ev.error ?? \"Unknown error\",\n ev.upgradeUrl,\n ev.errorCode,\n );\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantId\n ? { ...m, content: m.content || fallbackContent }\n : m,\n ),\n );\n }\n break;\n }\n }\n }\n } catch (err: any) {\n if (err?.name !== \"AbortError\") {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantId\n ? {\n ...m,\n content:\n m.content || \"Something went wrong. Please try again.\",\n }\n : m,\n ),\n );\n }\n } finally {\n setIsGenerating(false);\n window.dispatchEvent(\n new CustomEvent(\"agentNative.chatRunning\", {\n detail: { isRunning: false, running: false },\n }),\n );\n abortRef.current = null;\n }\n },\n [messages, isGenerating],\n );\n\n const clearHistory = useCallback(() => {\n abortRef.current?.abort();\n setMessages([]);\n setIsGenerating(false);\n }, []);\n\n return { messages, isGenerating, sendMessage, clearHistory };\n}\n"]}
1
+ {"version":3,"file":"useProductionAgent.js","sourceRoot":"","sources":["../../src/client/useProductionAgent.ts"],"names":[],"mappings":"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","sourcesContent":["import { useState, useCallback, useRef } from \"react\";\nimport type { AgentMessage, AgentChatEvent } from \"../agent/types.js\";\nimport { formatChatErrorText } from \"./error-format.js\";\nimport { agentNativePath } from \"./api-path.js\";\n\nexport interface ProductionAgentMessage {\n id: string;\n role: \"user\" | \"assistant\";\n content: string;\n toolCalls?: Array<{\n tool: string;\n input: Record<string, string>;\n result?: string;\n }>;\n}\n\nexport interface UseProductionAgentOptions {\n /** API endpoint URL. Default: \"/_agent-native/agent-chat\" */\n apiUrl?: string;\n}\n\nexport interface UseProductionAgentResult {\n messages: ProductionAgentMessage[];\n isGenerating: boolean;\n sendMessage: (text: string) => void;\n clearHistory: () => void;\n}\n\n/** @deprecated Use `AssistantChat` component instead */\nexport function useProductionAgent(\n options?: UseProductionAgentOptions,\n): UseProductionAgentResult {\n const apiUrl =\n options?.apiUrl ?? agentNativePath(\"/_agent-native/agent-chat\");\n const [messages, setMessages] = useState<ProductionAgentMessage[]>([]);\n const [isGenerating, setIsGenerating] = useState(false);\n const abortRef = useRef<AbortController | null>(null);\n\n const sendMessage = useCallback(\n async (text: string) => {\n if (!text.trim() || isGenerating) return;\n\n const userMsg: ProductionAgentMessage = {\n id: `user-${Date.now()}`,\n role: \"user\",\n content: text.trim(),\n };\n\n setMessages((prev) => [...prev, userMsg]);\n setIsGenerating(true);\n\n // Notify any listeners that generation is running\n window.dispatchEvent(\n new CustomEvent(\"agentNative.chatRunning\", {\n detail: { isRunning: true, running: true },\n }),\n );\n\n // Build history for this request — skip empty-content messages\n // (assistant turns with only tool calls have no text content to send)\n const history: AgentMessage[] = messages\n .filter((m) => m.content.trim())\n .map((m) => ({\n role: m.role,\n content: m.content,\n }));\n\n const assistantId = `assistant-${Date.now()}`;\n const assistantMsg: ProductionAgentMessage = {\n id: assistantId,\n role: \"assistant\",\n content: \"\",\n toolCalls: [],\n };\n setMessages((prev) => [...prev, assistantMsg]);\n\n const abort = new AbortController();\n abortRef.current = abort;\n\n try {\n const res = await fetch(apiUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ message: text.trim(), history }),\n signal: abort.signal,\n });\n\n if (!res.ok || !res.body) {\n throw new Error(`Server error: ${res.status}`);\n }\n\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n let buf = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buf += decoder.decode(value, { stream: true });\n const lines = buf.split(\"\\n\");\n buf = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) continue;\n const raw = line.slice(6).trim();\n if (!raw) continue;\n\n let ev: AgentChatEvent;\n try {\n ev = JSON.parse(raw);\n } catch {\n continue;\n }\n\n if (ev.type === \"text\") {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantId\n ? { ...m, content: m.content + ev.text }\n : m,\n ),\n );\n } else if (ev.type === \"tool_start\") {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantId\n ? {\n ...m,\n toolCalls: [\n ...(m.toolCalls ?? []),\n { tool: ev.tool, input: ev.input },\n ],\n }\n : m,\n ),\n );\n } else if (ev.type === \"tool_done\") {\n setMessages((prev) =>\n prev.map((m) => {\n if (m.id !== assistantId) return m;\n const calls = [...(m.toolCalls ?? [])];\n // Results can arrive out of order for concurrent same-named\n // calls, so attach to the first not-yet-resolved match\n // (FIFO) rather than the most recent same-named call.\n let idx = calls.findIndex(\n (c) => c.tool === ev.tool && c.result === undefined,\n );\n if (idx < 0)\n idx = calls.map((c) => c.tool).lastIndexOf(ev.tool);\n if (idx >= 0)\n calls[idx] = { ...calls[idx], result: ev.result };\n return { ...m, toolCalls: calls };\n }),\n );\n } else if (ev.type === \"agent_call\") {\n const agentName = ev.agent;\n if (ev.status === \"start\") {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantId\n ? {\n ...m,\n toolCalls: [\n ...(m.toolCalls ?? []),\n {\n tool: `agent:${agentName}`,\n input: {},\n },\n ],\n }\n : m,\n ),\n );\n } else if (ev.status === \"done\" || ev.status === \"error\") {\n setMessages((prev) =>\n prev.map((m) => {\n if (m.id !== assistantId) return m;\n const calls = [...(m.toolCalls ?? [])];\n const idx = calls\n .map((c) => c.tool)\n .lastIndexOf(`agent:${agentName}`);\n if (idx >= 0)\n calls[idx] = {\n ...calls[idx],\n result:\n ev.status === \"error\"\n ? \"Error calling agent\"\n : \"Done\",\n };\n return { ...m, toolCalls: calls };\n }),\n );\n }\n } else if (ev.type === \"done\" || ev.type === \"error\") {\n if (ev.type === \"error\") {\n const fallbackContent = formatChatErrorText(\n ev.error ?? \"Unknown error\",\n ev.upgradeUrl,\n ev.errorCode,\n );\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantId\n ? { ...m, content: m.content || fallbackContent }\n : m,\n ),\n );\n }\n break;\n }\n }\n }\n } catch (err: any) {\n if (err?.name !== \"AbortError\") {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === assistantId\n ? {\n ...m,\n content:\n m.content || \"Something went wrong. Please try again.\",\n }\n : m,\n ),\n );\n }\n } finally {\n setIsGenerating(false);\n window.dispatchEvent(\n new CustomEvent(\"agentNative.chatRunning\", {\n detail: { isRunning: false, running: false },\n }),\n );\n abortRef.current = null;\n }\n },\n [messages, isGenerating],\n );\n\n const clearHistory = useCallback(() => {\n abortRef.current?.abort();\n setMessages([]);\n setIsGenerating(false);\n }, []);\n\n return { messages, isGenerating, sendMessage, clearHistory };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"agent-presence.d.ts","sourceRoot":"","sources":["../../src/collab/agent-presence.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiBH;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,IAAI,CAuCN;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAgBtD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,IAAI,CA0BN;AAED;;;;;GAKG;AACH,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,EAC/C,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7B,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;;;;;GAQG;AACH,wBAAsB,8BAA8B,CAClD,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,KAAK,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC,EACF,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7B,OAAO,CAAC,IAAI,CAAC,CAgCf"}
1
+ {"version":3,"file":"agent-presence.d.ts","sourceRoot":"","sources":["../../src/collab/agent-presence.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAaH;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,IAAI,CAuCN;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAgBtD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,IAAI,CA0BN;AAED;;;;;GAKG;AACH,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,EAC/C,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7B,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;;;;;GAQG;AACH,wBAAsB,8BAA8B,CAClD,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,KAAK,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC,EACF,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7B,OAAO,CAAC,IAAI,CAAC,CAgCf"}
@@ -7,7 +7,7 @@
7
7
  * instead of hand-rolling HTTP awareness calls.
8
8
  */
9
9
  import { getDocAwareness } from "./awareness.js";
10
- import { AGENT_CLIENT_ID, DEFAULT_AGENT_IDENTITY, } from "./agent-identity.js";
10
+ import { AGENT_CLIENT_ID, DEFAULT_AGENT_IDENTITY } from "./agent-identity.js";
11
11
  import { searchAndReplace } from "./ydoc-manager.js";
12
12
  const HEARTBEAT_INTERVAL = 10_000; // 10 seconds
13
13
  // docId → heartbeat interval handle
@@ -1 +1 @@
1
- {"version":3,"file":"agent-presence.js","sourceRoot":"","sources":["../../src/collab/agent-presence.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Server-side agent presence lifecycle for collaborative editing.\n *\n * Provides enter/leave semantics so the agent behaves like a real\n * collaborator — it \"enters\" a document, its edits are visible with\n * durable presence, and it \"leaves\" when done. Actions call these\n * instead of hand-rolling HTTP awareness calls.\n */\n\nimport { getDocAwareness, type AwarenessEntry } from \"./awareness.js\";\nimport {\n AGENT_CLIENT_ID,\n DEFAULT_AGENT_IDENTITY,\n type AgentIdentity,\n} from \"./agent-identity.js\";\nimport { searchAndReplace } from \"./ydoc-manager.js\";\n\nconst HEARTBEAT_INTERVAL = 10_000; // 10 seconds\n\n// docId → heartbeat interval handle\nconst _heartbeats = new Map<string, NodeJS.Timeout>();\n// docId → reference count (how many concurrent operations are using this doc)\nconst _refCounts = new Map<string, number>();\n\n/**\n * Mark the agent as present on a document.\n *\n * Sets an awareness entry for the agent and starts a heartbeat that\n * keeps it alive. If the agent is already present on this doc, just\n * refreshes `lastSeen` without creating a second interval.\n */\nexport function agentEnterDocument(\n docId: string,\n metadata?: Record<string, unknown>,\n): void {\n const map = getDocAwareness(docId);\n\n const state = JSON.stringify({\n user: {\n name: DEFAULT_AGENT_IDENTITY.name,\n email: DEFAULT_AGENT_IDENTITY.email,\n color: DEFAULT_AGENT_IDENTITY.color,\n },\n ...metadata,\n });\n\n const entry: AwarenessEntry = {\n clientId: AGENT_CLIENT_ID,\n state,\n lastSeen: Date.now(),\n };\n map.set(AGENT_CLIENT_ID, entry);\n\n // Increment reference count\n _refCounts.set(docId, (_refCounts.get(docId) ?? 0) + 1);\n\n // Don't create another interval if one already exists\n if (_heartbeats.has(docId)) return;\n\n const interval = setInterval(() => {\n const m = getDocAwareness(docId);\n const existing = m.get(AGENT_CLIENT_ID);\n if (existing) {\n existing.lastSeen = Date.now();\n }\n }, HEARTBEAT_INTERVAL);\n\n // Don't block Node from exiting if this is the only timer left\n if (typeof interval === \"object\" && \"unref\" in interval) {\n interval.unref();\n }\n\n _heartbeats.set(docId, interval);\n}\n\n/**\n * Remove the agent's presence from a document.\n *\n * Clears the awareness entry and stops the heartbeat.\n */\nexport function agentLeaveDocument(docId: string): void {\n const count = (_refCounts.get(docId) ?? 1) - 1;\n if (count > 0) {\n _refCounts.set(docId, count);\n return;\n }\n _refCounts.delete(docId);\n\n const map = getDocAwareness(docId);\n map.delete(AGENT_CLIENT_ID);\n\n const interval = _heartbeats.get(docId);\n if (interval) {\n clearInterval(interval);\n _heartbeats.delete(docId);\n }\n}\n\n/**\n * Update the agent's awareness state to include selection info\n * (e.g., which track, panel, or element the agent is working on).\n */\nexport function agentUpdateSelection(\n docId: string,\n selection: Record<string, unknown>,\n): void {\n const map = getDocAwareness(docId);\n const existing = map.get(AGENT_CLIENT_ID);\n\n let parsed: Record<string, unknown> = {\n user: {\n name: DEFAULT_AGENT_IDENTITY.name,\n email: DEFAULT_AGENT_IDENTITY.email,\n color: DEFAULT_AGENT_IDENTITY.color,\n },\n };\n\n if (existing) {\n try {\n parsed = JSON.parse(existing.state) as Record<string, unknown>;\n } catch {\n // Invalid state — use defaults\n }\n }\n\n const state = JSON.stringify({ ...parsed, ...selection });\n map.set(AGENT_CLIENT_ID, {\n clientId: AGENT_CLIENT_ID,\n state,\n lastSeen: Date.now(),\n });\n}\n\n/**\n * Apply search-and-replace edits incrementally so each one appears\n * as a separate poll event to connected clients.\n *\n * Enters the document before editing and leaves in a finally block.\n */\nexport async function agentApplyEditsIncrementally(\n docId: string,\n edits: Array<{ find: string; replace: string }>,\n options?: { delayMs?: number },\n): Promise<void> {\n const delayMs = options?.delayMs ?? 150;\n agentEnterDocument(docId);\n\n try {\n for (const edit of edits) {\n await searchAndReplace(docId, edit.find, edit.replace, \"agent\");\n if (delayMs > 0) {\n await new Promise((r) => setTimeout(r, delayMs));\n }\n }\n } finally {\n agentLeaveDocument(docId);\n }\n}\n\n/**\n * Apply structured data patches incrementally so each one appears\n * as a separate poll event to connected clients.\n *\n * Enters the document before patching and leaves in a finally block.\n *\n * NOTE: `applyPatchOps` may not exist yet (Phase 1 creates it).\n * This will compile once Phase 1 finishes.\n */\nexport async function agentApplyPatchesIncrementally(\n docId: string,\n fieldName: string,\n patches: Array<{\n op: string;\n path: string;\n value?: unknown;\n index?: number;\n from?: number;\n to?: number;\n }>,\n options?: { delayMs?: number },\n): Promise<void> {\n const delayMs = options?.delayMs ?? 150;\n agentEnterDocument(docId);\n\n try {\n // Dynamic import — applyPatchOps is being added by Phase 1.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let applyPatchOps: any;\n try {\n const mod = await import(\"./ydoc-manager.js\");\n applyPatchOps = (mod as Record<string, unknown>).applyPatchOps;\n } catch {\n throw new Error(\n \"applyPatchOps is not available yet — Phase 1 must complete first\",\n );\n }\n\n if (typeof applyPatchOps !== \"function\") {\n throw new Error(\n \"applyPatchOps is not available yet — Phase 1 must complete first\",\n );\n }\n\n for (const patch of patches) {\n await applyPatchOps(docId, [patch], fieldName, \"agent\");\n if (delayMs > 0) {\n await new Promise((r) => setTimeout(r, delayMs));\n }\n }\n } finally {\n agentLeaveDocument(docId);\n }\n}\n"]}
1
+ {"version":3,"file":"agent-presence.js","sourceRoot":"","sources":["../../src/collab/agent-presence.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Server-side agent presence lifecycle for collaborative editing.\n *\n * Provides enter/leave semantics so the agent behaves like a real\n * collaborator — it \"enters\" a document, its edits are visible with\n * durable presence, and it \"leaves\" when done. Actions call these\n * instead of hand-rolling HTTP awareness calls.\n */\n\nimport { getDocAwareness, type AwarenessEntry } from \"./awareness.js\";\nimport { AGENT_CLIENT_ID, DEFAULT_AGENT_IDENTITY } from \"./agent-identity.js\";\nimport { searchAndReplace } from \"./ydoc-manager.js\";\n\nconst HEARTBEAT_INTERVAL = 10_000; // 10 seconds\n\n// docId → heartbeat interval handle\nconst _heartbeats = new Map<string, NodeJS.Timeout>();\n// docId → reference count (how many concurrent operations are using this doc)\nconst _refCounts = new Map<string, number>();\n\n/**\n * Mark the agent as present on a document.\n *\n * Sets an awareness entry for the agent and starts a heartbeat that\n * keeps it alive. If the agent is already present on this doc, just\n * refreshes `lastSeen` without creating a second interval.\n */\nexport function agentEnterDocument(\n docId: string,\n metadata?: Record<string, unknown>,\n): void {\n const map = getDocAwareness(docId);\n\n const state = JSON.stringify({\n user: {\n name: DEFAULT_AGENT_IDENTITY.name,\n email: DEFAULT_AGENT_IDENTITY.email,\n color: DEFAULT_AGENT_IDENTITY.color,\n },\n ...metadata,\n });\n\n const entry: AwarenessEntry = {\n clientId: AGENT_CLIENT_ID,\n state,\n lastSeen: Date.now(),\n };\n map.set(AGENT_CLIENT_ID, entry);\n\n // Increment reference count\n _refCounts.set(docId, (_refCounts.get(docId) ?? 0) + 1);\n\n // Don't create another interval if one already exists\n if (_heartbeats.has(docId)) return;\n\n const interval = setInterval(() => {\n const m = getDocAwareness(docId);\n const existing = m.get(AGENT_CLIENT_ID);\n if (existing) {\n existing.lastSeen = Date.now();\n }\n }, HEARTBEAT_INTERVAL);\n\n // Don't block Node from exiting if this is the only timer left\n if (typeof interval === \"object\" && \"unref\" in interval) {\n interval.unref();\n }\n\n _heartbeats.set(docId, interval);\n}\n\n/**\n * Remove the agent's presence from a document.\n *\n * Clears the awareness entry and stops the heartbeat.\n */\nexport function agentLeaveDocument(docId: string): void {\n const count = (_refCounts.get(docId) ?? 1) - 1;\n if (count > 0) {\n _refCounts.set(docId, count);\n return;\n }\n _refCounts.delete(docId);\n\n const map = getDocAwareness(docId);\n map.delete(AGENT_CLIENT_ID);\n\n const interval = _heartbeats.get(docId);\n if (interval) {\n clearInterval(interval);\n _heartbeats.delete(docId);\n }\n}\n\n/**\n * Update the agent's awareness state to include selection info\n * (e.g., which track, panel, or element the agent is working on).\n */\nexport function agentUpdateSelection(\n docId: string,\n selection: Record<string, unknown>,\n): void {\n const map = getDocAwareness(docId);\n const existing = map.get(AGENT_CLIENT_ID);\n\n let parsed: Record<string, unknown> = {\n user: {\n name: DEFAULT_AGENT_IDENTITY.name,\n email: DEFAULT_AGENT_IDENTITY.email,\n color: DEFAULT_AGENT_IDENTITY.color,\n },\n };\n\n if (existing) {\n try {\n parsed = JSON.parse(existing.state) as Record<string, unknown>;\n } catch {\n // Invalid state — use defaults\n }\n }\n\n const state = JSON.stringify({ ...parsed, ...selection });\n map.set(AGENT_CLIENT_ID, {\n clientId: AGENT_CLIENT_ID,\n state,\n lastSeen: Date.now(),\n });\n}\n\n/**\n * Apply search-and-replace edits incrementally so each one appears\n * as a separate poll event to connected clients.\n *\n * Enters the document before editing and leaves in a finally block.\n */\nexport async function agentApplyEditsIncrementally(\n docId: string,\n edits: Array<{ find: string; replace: string }>,\n options?: { delayMs?: number },\n): Promise<void> {\n const delayMs = options?.delayMs ?? 150;\n agentEnterDocument(docId);\n\n try {\n for (const edit of edits) {\n await searchAndReplace(docId, edit.find, edit.replace, \"agent\");\n if (delayMs > 0) {\n await new Promise((r) => setTimeout(r, delayMs));\n }\n }\n } finally {\n agentLeaveDocument(docId);\n }\n}\n\n/**\n * Apply structured data patches incrementally so each one appears\n * as a separate poll event to connected clients.\n *\n * Enters the document before patching and leaves in a finally block.\n *\n * NOTE: `applyPatchOps` may not exist yet (Phase 1 creates it).\n * This will compile once Phase 1 finishes.\n */\nexport async function agentApplyPatchesIncrementally(\n docId: string,\n fieldName: string,\n patches: Array<{\n op: string;\n path: string;\n value?: unknown;\n index?: number;\n from?: number;\n to?: number;\n }>,\n options?: { delayMs?: number },\n): Promise<void> {\n const delayMs = options?.delayMs ?? 150;\n agentEnterDocument(docId);\n\n try {\n // Dynamic import — applyPatchOps is being added by Phase 1.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let applyPatchOps: any;\n try {\n const mod = await import(\"./ydoc-manager.js\");\n applyPatchOps = (mod as Record<string, unknown>).applyPatchOps;\n } catch {\n throw new Error(\n \"applyPatchOps is not available yet — Phase 1 must complete first\",\n );\n }\n\n if (typeof applyPatchOps !== \"function\") {\n throw new Error(\n \"applyPatchOps is not available yet — Phase 1 must complete first\",\n );\n }\n\n for (const patch of patches) {\n await applyPatchOps(docId, [patch], fieldName, \"agent\");\n if (delayMs > 0) {\n await new Promise((r) => setTimeout(r, delayMs));\n }\n }\n } finally {\n agentLeaveDocument(docId);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"awareness.d.ts","sourceRoot":"","sources":["../../src/collab/awareness.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAKD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAO1E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,IAAI,CAOnE;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa;;;;;kBA2BQ,MAAM;eAAS,MAAM;;;GAQrD,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,cAAc;;;;;kBAUM,MAAM;kBAAY,MAAM;;;GAMvD,CAAC"}
1
+ {"version":3,"file":"awareness.d.ts","sourceRoot":"","sources":["../../src/collab/awareness.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAKD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAO1E;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,IAAI,CAOnE;AAUD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa;;;;;kBA2BQ,MAAM;eAAS,MAAM;;;GAQrD,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,cAAc;;;;;kBAWM,MAAM;kBAAY,MAAM;;;GAMvD,CAAC"}
@@ -26,6 +26,13 @@ export function cleanExpired(map) {
26
26
  }
27
27
  }
28
28
  }
29
+ // Drop the per-document map from the registry once it has no entries left,
30
+ // so the outer map does not grow unbounded with every docId ever touched.
31
+ function pruneIfEmpty(docId, map) {
32
+ if (map.size === 0) {
33
+ _awarenessMap.delete(docId);
34
+ }
35
+ }
29
36
  /**
30
37
  * POST /_agent-native/collab/:docId/awareness
31
38
  *
@@ -73,6 +80,7 @@ export const getActiveUsers = defineEventHandler(async (event) => {
73
80
  }
74
81
  const map = getDocAwareness(docId);
75
82
  cleanExpired(map);
83
+ pruneIfEmpty(docId, map);
76
84
  const users = [];
77
85
  for (const [, entry] of map) {
78
86
  users.push({ clientId: entry.clientId, lastSeen: entry.lastSeen });
@@ -1 +1 @@
1
- {"version":3,"file":"awareness.js","sourceRoot":"","sources":["../../src/collab/awareness.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Server-side awareness state management for collaborative editing.\n *\n * Stores per-client awareness state (cursor positions, user info) in memory.\n * Clients POST their state and receive other clients' states via polling.\n * States expire after 30 seconds of no updates.\n */\n\nimport { defineEventHandler, setResponseStatus, getRouterParam } from \"h3\";\nimport type { H3Event } from \"h3\";\nimport { readBody } from \"../server/h3-helpers.js\";\n\nconst AWARENESS_TIMEOUT = 30_000; // 30 seconds\n\nexport interface AwarenessEntry {\n clientId: number;\n state: string; // base64-encoded awareness update\n lastSeen: number;\n}\n\n// docId → Map<clientId, AwarenessEntry>\nconst _awarenessMap = new Map<string, Map<number, AwarenessEntry>>();\n\nexport function getDocAwareness(docId: string): Map<number, AwarenessEntry> {\n let map = _awarenessMap.get(docId);\n if (!map) {\n map = new Map();\n _awarenessMap.set(docId, map);\n }\n return map;\n}\n\nexport function cleanExpired(map: Map<number, AwarenessEntry>): void {\n const now = Date.now();\n for (const [clientId, entry] of map) {\n if (now - entry.lastSeen > AWARENESS_TIMEOUT) {\n map.delete(clientId);\n }\n }\n}\n\n/**\n * POST /_agent-native/collab/:docId/awareness\n *\n * Client sends its awareness state and receives other clients' states.\n *\n * Body: { clientId: number, state: string (base64) }\n * Response: { states: Array<{ clientId: number, state: string }> }\n */\nexport const postAwareness = defineEventHandler(async (event: H3Event) => {\n const docId = getRouterParam(event, \"docId\");\n if (!docId) {\n setResponseStatus(event, 400);\n return { error: \"docId required\" };\n }\n\n const body = await readBody(event);\n const { clientId, state } = body as {\n clientId?: number;\n state?: string;\n };\n\n if (!clientId || !state) {\n setResponseStatus(event, 400);\n return { error: \"clientId and state required\" };\n }\n\n const map = getDocAwareness(docId);\n\n // Store this client's state\n map.set(clientId, { clientId, state, lastSeen: Date.now() });\n\n // Clean expired entries\n cleanExpired(map);\n\n // Return other clients' states (exclude the sender)\n const states: Array<{ clientId: number; state: string }> = [];\n for (const [id, entry] of map) {\n if (id !== clientId) {\n states.push({ clientId: id, state: entry.state });\n }\n }\n\n return { states };\n});\n\n/**\n * GET /_agent-native/collab/:docId/users\n *\n * Returns the list of active users for a document (for presence bar).\n */\nexport const getActiveUsers = defineEventHandler(async (event: H3Event) => {\n const docId = getRouterParam(event, \"docId\");\n if (!docId) {\n setResponseStatus(event, 400);\n return { error: \"docId required\" };\n }\n\n const map = getDocAwareness(docId);\n cleanExpired(map);\n\n const users: Array<{ clientId: number; lastSeen: number }> = [];\n for (const [, entry] of map) {\n users.push({ clientId: entry.clientId, lastSeen: entry.lastSeen });\n }\n\n return { users };\n});\n"]}
1
+ {"version":3,"file":"awareness.js","sourceRoot":"","sources":["../../src/collab/awareness.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Server-side awareness state management for collaborative editing.\n *\n * Stores per-client awareness state (cursor positions, user info) in memory.\n * Clients POST their state and receive other clients' states via polling.\n * States expire after 30 seconds of no updates.\n */\n\nimport { defineEventHandler, setResponseStatus, getRouterParam } from \"h3\";\nimport type { H3Event } from \"h3\";\nimport { readBody } from \"../server/h3-helpers.js\";\n\nconst AWARENESS_TIMEOUT = 30_000; // 30 seconds\n\nexport interface AwarenessEntry {\n clientId: number;\n state: string; // base64-encoded awareness update\n lastSeen: number;\n}\n\n// docId → Map<clientId, AwarenessEntry>\nconst _awarenessMap = new Map<string, Map<number, AwarenessEntry>>();\n\nexport function getDocAwareness(docId: string): Map<number, AwarenessEntry> {\n let map = _awarenessMap.get(docId);\n if (!map) {\n map = new Map();\n _awarenessMap.set(docId, map);\n }\n return map;\n}\n\nexport function cleanExpired(map: Map<number, AwarenessEntry>): void {\n const now = Date.now();\n for (const [clientId, entry] of map) {\n if (now - entry.lastSeen > AWARENESS_TIMEOUT) {\n map.delete(clientId);\n }\n }\n}\n\n// Drop the per-document map from the registry once it has no entries left,\n// so the outer map does not grow unbounded with every docId ever touched.\nfunction pruneIfEmpty(docId: string, map: Map<number, AwarenessEntry>): void {\n if (map.size === 0) {\n _awarenessMap.delete(docId);\n }\n}\n\n/**\n * POST /_agent-native/collab/:docId/awareness\n *\n * Client sends its awareness state and receives other clients' states.\n *\n * Body: { clientId: number, state: string (base64) }\n * Response: { states: Array<{ clientId: number, state: string }> }\n */\nexport const postAwareness = defineEventHandler(async (event: H3Event) => {\n const docId = getRouterParam(event, \"docId\");\n if (!docId) {\n setResponseStatus(event, 400);\n return { error: \"docId required\" };\n }\n\n const body = await readBody(event);\n const { clientId, state } = body as {\n clientId?: number;\n state?: string;\n };\n\n if (!clientId || !state) {\n setResponseStatus(event, 400);\n return { error: \"clientId and state required\" };\n }\n\n const map = getDocAwareness(docId);\n\n // Store this client's state\n map.set(clientId, { clientId, state, lastSeen: Date.now() });\n\n // Clean expired entries\n cleanExpired(map);\n\n // Return other clients' states (exclude the sender)\n const states: Array<{ clientId: number; state: string }> = [];\n for (const [id, entry] of map) {\n if (id !== clientId) {\n states.push({ clientId: id, state: entry.state });\n }\n }\n\n return { states };\n});\n\n/**\n * GET /_agent-native/collab/:docId/users\n *\n * Returns the list of active users for a document (for presence bar).\n */\nexport const getActiveUsers = defineEventHandler(async (event: H3Event) => {\n const docId = getRouterParam(event, \"docId\");\n if (!docId) {\n setResponseStatus(event, 400);\n return { error: \"docId required\" };\n }\n\n const map = getDocAwareness(docId);\n cleanExpired(map);\n pruneIfEmpty(docId, map);\n\n const users: Array<{ clientId: number; lastSeen: number }> = [];\n for (const [, entry] of map) {\n users.push({ clientId: entry.clientId, lastSeen: entry.lastSeen });\n }\n\n return { users };\n});\n"]}