@agent-native/core 0.21.0 → 0.22.1

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 (160) hide show
  1. package/dist/action-change-marker.d.ts +11 -0
  2. package/dist/action-change-marker.d.ts.map +1 -0
  3. package/dist/action-change-marker.js +52 -0
  4. package/dist/action-change-marker.js.map +1 -0
  5. package/dist/action.d.ts +2 -2
  6. package/dist/action.js +1 -1
  7. package/dist/action.js.map +1 -1
  8. package/dist/agent/production-agent.d.ts +1 -1
  9. package/dist/agent/production-agent.d.ts.map +1 -1
  10. package/dist/agent/production-agent.js +4 -6
  11. package/dist/agent/production-agent.js.map +1 -1
  12. package/dist/cli/connect.d.ts +5 -3
  13. package/dist/cli/connect.d.ts.map +1 -1
  14. package/dist/cli/connect.js +127 -15
  15. package/dist/cli/connect.js.map +1 -1
  16. package/dist/client/AgentPanel.d.ts.map +1 -1
  17. package/dist/client/AgentPanel.js +6 -2
  18. package/dist/client/AgentPanel.js.map +1 -1
  19. package/dist/client/AssistantChat.d.ts.map +1 -1
  20. package/dist/client/AssistantChat.js +7 -1
  21. package/dist/client/AssistantChat.js.map +1 -1
  22. package/dist/client/NewWorkspaceAppFlow.js +1 -1
  23. package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
  24. package/dist/client/agent-chat.d.ts.map +1 -1
  25. package/dist/client/agent-chat.js +13 -8
  26. package/dist/client/agent-chat.js.map +1 -1
  27. package/dist/client/agent-sidebar-state.d.ts +2 -0
  28. package/dist/client/agent-sidebar-state.d.ts.map +1 -1
  29. package/dist/client/agent-sidebar-state.js +40 -7
  30. package/dist/client/agent-sidebar-state.js.map +1 -1
  31. package/dist/client/mcp-apps/McpAppRenderer.d.ts.map +1 -1
  32. package/dist/client/mcp-apps/McpAppRenderer.js +9 -4
  33. package/dist/client/mcp-apps/McpAppRenderer.js.map +1 -1
  34. package/dist/client/use-db-sync.d.ts +5 -5
  35. package/dist/client/use-db-sync.d.ts.map +1 -1
  36. package/dist/client/use-db-sync.js +15 -5
  37. package/dist/client/use-db-sync.js.map +1 -1
  38. package/dist/client/use-db-sync.spec.d.ts +2 -0
  39. package/dist/client/use-db-sync.spec.d.ts.map +1 -0
  40. package/dist/client/use-db-sync.spec.js +80 -0
  41. package/dist/client/use-db-sync.spec.js.map +1 -0
  42. package/dist/db/client.d.ts.map +1 -1
  43. package/dist/db/client.js +14 -8
  44. package/dist/db/client.js.map +1 -1
  45. package/dist/extensions/actions.d.ts.map +1 -1
  46. package/dist/extensions/actions.js +62 -3
  47. package/dist/extensions/actions.js.map +1 -1
  48. package/dist/extensions/content-patch.d.ts +71 -0
  49. package/dist/extensions/content-patch.d.ts.map +1 -0
  50. package/dist/extensions/content-patch.js +251 -0
  51. package/dist/extensions/content-patch.js.map +1 -0
  52. package/dist/extensions/routes.js +6 -1
  53. package/dist/extensions/routes.js.map +1 -1
  54. package/dist/extensions/store.d.ts +4 -4
  55. package/dist/extensions/store.d.ts.map +1 -1
  56. package/dist/extensions/store.js +14 -18
  57. package/dist/extensions/store.js.map +1 -1
  58. package/dist/mcp/build-server.d.ts +3 -0
  59. package/dist/mcp/build-server.d.ts.map +1 -1
  60. package/dist/mcp/build-server.js +55 -6
  61. package/dist/mcp/build-server.js.map +1 -1
  62. package/dist/mcp/oauth-route.d.ts +22 -0
  63. package/dist/mcp/oauth-route.d.ts.map +1 -0
  64. package/dist/mcp/oauth-route.js +618 -0
  65. package/dist/mcp/oauth-route.js.map +1 -0
  66. package/dist/mcp/oauth-store.d.ts +89 -0
  67. package/dist/mcp/oauth-store.d.ts.map +1 -0
  68. package/dist/mcp/oauth-store.js +391 -0
  69. package/dist/mcp/oauth-store.js.map +1 -0
  70. package/dist/mcp/oauth-token.d.ts +28 -0
  71. package/dist/mcp/oauth-token.d.ts.map +1 -0
  72. package/dist/mcp/oauth-token.js +83 -0
  73. package/dist/mcp/oauth-token.js.map +1 -0
  74. package/dist/mcp/server.d.ts.map +1 -1
  75. package/dist/mcp/server.js +5 -2
  76. package/dist/mcp/server.js.map +1 -1
  77. package/dist/mcp-client/index.d.ts.map +1 -1
  78. package/dist/mcp-client/index.js +16 -2
  79. package/dist/mcp-client/index.js.map +1 -1
  80. package/dist/mcp-client/routes.js +18 -5
  81. package/dist/mcp-client/routes.js.map +1 -1
  82. package/dist/scripts/dev/shell.d.ts.map +1 -1
  83. package/dist/scripts/dev/shell.js +24 -1
  84. package/dist/scripts/dev/shell.js.map +1 -1
  85. package/dist/scripts/runner.d.ts.map +1 -1
  86. package/dist/scripts/runner.js +7 -0
  87. package/dist/scripts/runner.js.map +1 -1
  88. package/dist/server/action-change.d.ts +8 -0
  89. package/dist/server/action-change.d.ts.map +1 -0
  90. package/dist/server/action-change.js +38 -0
  91. package/dist/server/action-change.js.map +1 -0
  92. package/dist/server/action-routes.d.ts.map +1 -1
  93. package/dist/server/action-routes.js +4 -6
  94. package/dist/server/action-routes.js.map +1 -1
  95. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  96. package/dist/server/agent-chat-plugin.js +3 -2
  97. package/dist/server/agent-chat-plugin.js.map +1 -1
  98. package/dist/server/auth.d.ts.map +1 -1
  99. package/dist/server/auth.js +14 -8
  100. package/dist/server/auth.js.map +1 -1
  101. package/dist/server/builder-browser.d.ts +6 -0
  102. package/dist/server/builder-browser.d.ts.map +1 -1
  103. package/dist/server/builder-browser.js +15 -0
  104. package/dist/server/builder-browser.js.map +1 -1
  105. package/dist/server/core-routes-plugin.d.ts +5 -4
  106. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  107. package/dist/server/core-routes-plugin.js +17 -2
  108. package/dist/server/core-routes-plugin.js.map +1 -1
  109. package/dist/server/poll.d.ts.map +1 -1
  110. package/dist/server/poll.js +55 -3
  111. package/dist/server/poll.js.map +1 -1
  112. package/dist/templates/default/.agents/skills/actions/SKILL.md +193 -72
  113. package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +88 -38
  114. package/dist/templates/default/AGENTS.md +3 -3
  115. package/dist/templates/default/actions/hello.ts +13 -20
  116. package/dist/templates/default/actions/navigate.ts +19 -51
  117. package/dist/templates/default/actions/view-screen.ts +16 -33
  118. package/dist/templates/default/app/hooks/use-navigation-state.ts +13 -3
  119. package/dist/templates/default/app/lib/tab-id.ts +1 -0
  120. package/dist/templates/default/app/root.tsx +2 -1
  121. package/dist/templates/default/app/routes/_index.tsx +11 -0
  122. package/dist/templates/default/package.json +2 -1
  123. package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +1 -1
  124. package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +9 -1
  125. package/dist/templates/workspace-core/AGENTS.md +8 -0
  126. package/dist/templates/workspace-root/AGENTS.md +7 -0
  127. package/dist/vite/client.d.ts.map +1 -1
  128. package/dist/vite/client.js +2 -2
  129. package/dist/vite/client.js.map +1 -1
  130. package/docs/content/actions.md +1 -1
  131. package/docs/content/authentication.md +16 -1
  132. package/docs/content/client.md +11 -8
  133. package/docs/content/context-awareness.md +2 -3
  134. package/docs/content/creating-templates.md +2 -2
  135. package/docs/content/external-agents.md +48 -15
  136. package/docs/content/faq.md +2 -2
  137. package/docs/content/key-concepts.md +31 -23
  138. package/docs/content/mcp-protocol.md +50 -17
  139. package/docs/content/template-starter.md +3 -3
  140. package/docs/content/what-is-agent-native.md +5 -3
  141. package/package.json +2 -1
  142. package/src/templates/default/.agents/skills/actions/SKILL.md +193 -72
  143. package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +88 -38
  144. package/src/templates/default/AGENTS.md +3 -3
  145. package/src/templates/default/actions/hello.ts +13 -20
  146. package/src/templates/default/actions/navigate.ts +19 -51
  147. package/src/templates/default/actions/view-screen.ts +16 -33
  148. package/src/templates/default/app/hooks/use-navigation-state.ts +13 -3
  149. package/src/templates/default/app/lib/tab-id.ts +1 -0
  150. package/src/templates/default/app/root.tsx +2 -1
  151. package/src/templates/default/app/routes/_index.tsx +11 -0
  152. package/src/templates/default/package.json +2 -1
  153. package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +1 -1
  154. package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +9 -1
  155. package/src/templates/workspace-core/AGENTS.md +8 -0
  156. package/src/templates/workspace-root/AGENTS.md +7 -0
  157. package/dist/templates/default/server/routes/api/hello.get.ts +0 -5
  158. package/dist/templates/default/shared/api.ts +0 -6
  159. package/src/templates/default/server/routes/api/hello.get.ts +0 -5
  160. package/src/templates/default/shared/api.ts +0 -6
@@ -12,11 +12,11 @@ interface QueryClient {
12
12
  * SSE is the fast path; polling is the safety net.
13
13
  *
14
14
  * @param options.queryClient - The react-query QueryClient instance
15
- * @param options.queryKeys - **Deprecated and ignored.** The hook now
16
- * invalidates every active query on any non-own change event, so templates
17
- * no longer need to enumerate their keys. Kept in the type signature for
18
- * backward compatibility — existing call sites that still pass this option
19
- * keep working but the value has no effect.
15
+ * @param options.queryKeys - **Deprecated and ignored.** The hook uses
16
+ * framework-owned fixed prefixes plus per-source change counters instead of
17
+ * caller-supplied key lists. Kept in the type signature for backward
18
+ * compatibility — existing call sites that still pass this option keep
19
+ * working but the value has no effect.
20
20
  * @param options.pollUrl - Poll endpoint URL. Default: "/_agent-native/poll"
21
21
  * @param options.sseUrl - SSE endpoint URL. Default: "/_agent-native/events".
22
22
  * Pass false to disable SSE and use polling only.
@@ -1 +1 @@
1
- {"version":3,"file":"use-db-sync.d.ts","sourceRoot":"","sources":["../../src/client/use-db-sync.ts"],"names":[],"mappings":"AAKA,UAAU,WAAW;IACnB,iBAAiB,CAAC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;CACzD;AAyFD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,SAAS,CACvB,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACxB,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;CAClB,GACL,IAAI,CA4NN;AAED,wCAAwC;AACxC,eAAO,MAAM,cAAc,kBAAY,CAAC;AAExC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;CACtB,GACL,MAAM,CAsJR"}
1
+ {"version":3,"file":"use-db-sync.d.ts","sourceRoot":"","sources":["../../src/client/use-db-sync.ts"],"names":[],"mappings":"AAKA,UAAU,WAAW;IACnB,iBAAiB,CAAC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;CACzD;AAyFD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,SAAS,CACvB,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACxB,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;CAClB,GACL,IAAI,CAuON;AAED,wCAAwC;AACxC,eAAO,MAAM,cAAc,kBAAY,CAAC;AAExC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;CACtB,GACL,MAAM,CAsJR"}
@@ -63,11 +63,11 @@ async function fetchPollJson(pollUrl, since, interval) {
63
63
  * SSE is the fast path; polling is the safety net.
64
64
  *
65
65
  * @param options.queryClient - The react-query QueryClient instance
66
- * @param options.queryKeys - **Deprecated and ignored.** The hook now
67
- * invalidates every active query on any non-own change event, so templates
68
- * no longer need to enumerate their keys. Kept in the type signature for
69
- * backward compatibility — existing call sites that still pass this option
70
- * keep working but the value has no effect.
66
+ * @param options.queryKeys - **Deprecated and ignored.** The hook uses
67
+ * framework-owned fixed prefixes plus per-source change counters instead of
68
+ * caller-supplied key lists. Kept in the type signature for backward
69
+ * compatibility — existing call sites that still pass this option keep
70
+ * working but the value has no effect.
71
71
  * @param options.pollUrl - Poll endpoint URL. Default: "/_agent-native/poll"
72
72
  * @param options.sseUrl - SSE endpoint URL. Default: "/_agent-native/events".
73
73
  * Pass false to disable SSE and use polling only.
@@ -126,6 +126,16 @@ export function useDbSync(options = {}) {
126
126
  bumpChangeVersion(src, ver);
127
127
  }
128
128
  if (relevant.length > 0 && queryClient) {
129
+ const hasActionEvent = relevant.some((evt) => evt.source === "action");
130
+ if (hasActionEvent) {
131
+ // Custom apps frequently start with raw `useQuery` calls before
132
+ // graduating to `useActionQuery` or source-versioned query keys.
133
+ // A successful mutating action is the core "agent changed app data"
134
+ // signal, so refresh active queries broadly as a compatibility
135
+ // safety net. Other event sources stay targeted to avoid request
136
+ // storms from noisy domain-specific writes.
137
+ queryClient.invalidateQueries();
138
+ }
129
139
  // Framework-level invalidate: a small, fixed list of query-key
130
140
  // prefixes the framework's own hooks/components use (action results,
131
141
  // extension state, application-state, the agent's `set-url` channel,
@@ -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\";\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;\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 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\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 Error(\"HTTP \" + 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 now\n * invalidates every active query on any non-own change event, so templates\n * no longer need to enumerate their keys. Kept in the type signature for\n * backward compatibility — existing call sites that still pass this option\n * keep 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 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\n function schedulePoll() {\n if (stopped) return;\n if (pauseWhenHidden && isDocumentHidden()) return;\n if (timer) clearTimeout(timer);\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 // 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 {\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 (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\n function schedulePoll() {\n if (stopped) return;\n if (pauseWhenHidden && isDocumentHidden()) return;\n if (timer) clearTimeout(timer);\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 {\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 (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":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAM9E,MAAM,iBAAiB,GAAG,MAAM,CAAC;AACjC,MAAM,wBAAwB,GAAG,MAAM,CAAC;AAgBxC,SAAS,cAAc,CAAC,QAAgB;IACtC,OAAO,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,gBAAgB;IACvB,OAAO,CACL,OAAO,QAAQ,KAAK,WAAW,IAAI,QAAQ,CAAC,eAAe,KAAK,QAAQ,CACzE,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,MAAkC;IACvD,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IACnC,OAAO,eAAe,CAAC,MAAM,IAAI,uBAAuB,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,qBAAqB,CAAC,OAAgB;IAC7C,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IACvD,MAAM,MAAM,GAAG,OAA+C,CAAC;IAC/D,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5D,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CACzB,CAAC,KAAK,EAAsB,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,CACpE,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACjC,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CACzB,CAAC,KAAK,EAAsB,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,CACpE,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,OAAoB,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,YAAY,CAAC,KAAgB;IACpC,OAAO,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAmB,EAAE,GAAW;IACxD,OAAO,MAAM,CAAC,IAAI,CAChB,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,MAAM,KAAK,WAAW;QAC5B,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG;YAChB,KAAK,CAAC,GAAG,KAAK,GAAG;YACjB,CAAC,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CACxE,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,OAAe,EACf,KAAa,EACb,QAAgB;IAEhB,MAAM,UAAU,GACd,OAAO,eAAe,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,eAAe,EAAE,CAAC;IACxE,MAAM,OAAO,GAAG,UAAU;QACxB,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;QAChE,CAAC,CAAC,IAAI,CAAC;IAET,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,GAAG,OAAO,UAAU,KAAK,EAAE,EAC3B,UAAU,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CACvD,CAAC;QACF,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;QACnD,mEAAmE;QACnE,qEAAqE;QACrE,OAAO,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC1B,CAAC;YAAS,CAAC;QACT,IAAI,OAAO;YAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,SAAS,CACvB,UAYI,EAAE;IAEN,MAAM,EACJ,WAAW,EACX,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,SAAS,IAAI,qBAAqB,CAAC,EACrE,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,EACtC,QAAQ,GAAG,IAAI,EACf,gBAAgB,GAAG,IAAI,CAAC,GAAG,CACzB,OAAO,CAAC,gBAAgB,IAAI,wBAAwB,EACpD,QAAQ,CACT,EACD,eAAe,GAAG,IAAI,GACvB,GAAG,OAAO,CAAC;IAEZ,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3C,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAErC,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACrD,eAAe,CAAC,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC;IAE/C,SAAS,CAAC,GAAG,EAAE;QACb,wEAAwE;QACxE,wEAAwE;QACxE,oEAAoE;QACpE,8BAA8B,EAAE,CAAC;QAEjC,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,KAAK,GAAyC,IAAI,CAAC;QACvD,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,IAAI,WAAW,GAAuB,IAAI,CAAC;QAC3C,IAAI,YAAY,GAAG,KAAK,CAAC;QAEzB,SAAS,YAAY;YACnB,IAAI,OAAO;gBAAE,OAAO;YACpB,IAAI,eAAe,IAAI,gBAAgB,EAAE;gBAAE,OAAO;YAClD,IAAI,KAAK;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;YAC/B,KAAK,GAAG,UAAU,CAChB,GAAG,EAAE;gBACH,KAAK,GAAG,IAAI,CAAC;gBACb,KAAK,IAAI,EAAE,CAAC;YACd,CAAC,EACD,YAAY,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAC3C,CAAC;QACJ,CAAC;QAED,SAAS,mBAAmB,CAAC,MAAmB;YAC9C,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC;YACvC,MAAM,QAAQ,GAAG,MAAM;gBACrB,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,KAAK,MAAM,CAAC;gBAClD,CAAC,CAAC,MAAM,CAAC;YAEX,kEAAkE;YAClE,mEAAmE;YACnE,kEAAkE;YAClE,+DAA+D;YAC/D,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;gBAC3B,MAAM,GAAG,GAAG,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7D,MAAM,GAAG,GAAG,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC9D,IAAI,GAAG,IAAI,GAAG,GAAG,CAAC;oBAAE,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAClD,CAAC;YAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,EAAE,CAAC;gBACvC,MAAM,cAAc,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;gBACvE,IAAI,cAAc,EAAE,CAAC;oBACnB,gEAAgE;oBAChE,iEAAiE;oBACjE,oEAAoE;oBACpE,+DAA+D;oBAC/D,iEAAiE;oBACjE,4CAA4C;oBAC5C,WAAW,CAAC,iBAAiB,EAAE,CAAC;gBAClC,CAAC;gBAED,+DAA+D;gBAC/D,qEAAqE;gBACrE,qEAAqE;gBACrE,mEAAmE;gBACnE,qEAAqE;gBACrE,mEAAmE;gBACnE,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBACxD,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;gBAC3D,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;gBAC5D,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;gBACjE,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;gBAC/D,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;gBAChE,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACtD,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBACvD,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;gBAC3D,IAAI,gBAAgB,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,CAAC;oBAC3C,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;gBACpE,CAAC;gBACD,IAAI,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,CAAC,EAAE,CAAC;oBACjD,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;gBAClE,CAAC;gBACD,IAAI,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,CAAC;oBAC9C,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;gBAC/D,CAAC;YACH,CAAC;YAED,sEAAsE;YACtE,mEAAmE;YACnE,sDAAsD;YACtD,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;gBACzB,UAAU,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,SAAS,WAAW,CAAC,MAAmB,EAAE,OAAgB;YACxD,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBAC1C,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpC,OAAO,OAAO,KAAK,CAAC,IAAI,OAAO,GAAG,UAAU,CAAC;YAC/C,CAAC,CAAC,CAAC;YAEH,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3B,mBAAmB,CAAC,WAAW,CAAC,CAAC;YACnC,CAAC;YAED,MAAM,eAAe,GAAG,WAAW,CAAC,MAAM,CACxC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,EAClD,CAAC,CACF,CAAC;YACF,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,IAAI,CAAC,EAAE,eAAe,CAAC,CAAC;QACnE,CAAC;QAED,SAAS,WAAW;YAClB,IAAI,CAAC,WAAW;gBAAE,OAAO;YACzB,WAAW,CAAC,KAAK,EAAE,CAAC;YACpB,WAAW,GAAG,IAAI,CAAC;YACnB,YAAY,GAAG,KAAK,CAAC;QACvB,CAAC;QAED,SAAS,aAAa;YACpB,IACE,OAAO;gBACP,CAAC,MAAM;gBACP,WAAW;gBACX,OAAO,WAAW,KAAK,WAAW;gBAClC,CAAC,eAAe,IAAI,gBAAgB,EAAE,CAAC,EACvC,CAAC;gBACD,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;YACvC,WAAW,GAAG,MAAM,CAAC;YACrB,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE;gBACnB,YAAY,GAAG,IAAI,CAAC;gBACpB,YAAY,EAAE,CAAC;YACjB,CAAC,CAAC;YACF,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE;gBACpB,YAAY,GAAG,KAAK,CAAC;gBACrB,YAAY,EAAE,CAAC;YACjB,CAAC,CAAC;YACF,MAAM,CAAC,SAAS,GAAG,CAAC,OAAO,EAAE,EAAE;gBAC7B,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;oBACzC,MAAM,MAAM,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;oBAC9C,MAAM,OAAO,GACX,OAAO,OAAO,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;oBACrE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAC/B,CAAC;gBAAC,MAAM,CAAC;oBACP,0DAA0D;gBAC5D,CAAC;YACH,CAAC,CAAC;QACJ,CAAC;QAED,KAAK,UAAU,IAAI;YACjB,IAAI,OAAO,IAAI,QAAQ;gBAAE,OAAO;YAChC,QAAQ,GAAG,IAAI,CAAC;YAChB,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,aAAa,CAC9B,OAAO,EACP,UAAU,EACV,QAAQ,CACT,CAAC;gBACF,WAAW,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YAC/C,CAAC;YAAC,MAAM,CAAC;gBACP,8CAA8C;YAChD,CAAC;oBAAS,CAAC;gBACT,QAAQ,GAAG,KAAK,CAAC;gBACjB,YAAY,EAAE,CAAC;YACjB,CAAC;QACH,CAAC;QAED,SAAS,OAAO;YACd,IAAI,eAAe,IAAI,gBAAgB,EAAE,EAAE,CAAC;gBAC1C,OAAO;YACT,CAAC;YACD,IAAI,KAAK,EAAE,CAAC;gBACV,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;YACD,aAAa,EAAE,CAAC;YAChB,KAAK,IAAI,EAAE,CAAC;QACd,CAAC;QAED,SAAS,sBAAsB;YAC7B,IAAI,QAAQ,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;gBAC3C,aAAa,EAAE,CAAC;gBAChB,OAAO,EAAE,CAAC;YACZ,CAAC;iBAAM,IAAI,eAAe,EAAE,CAAC;gBAC3B,WAAW,EAAE,CAAC;gBACd,IAAI,KAAK,EAAE,CAAC;oBACV,YAAY,CAAC,KAAK,CAAC,CAAC;oBACpB,KAAK,GAAG,IAAI,CAAC;gBACf,CAAC;YACH,CAAC;QACH,CAAC;QAED,wEAAwE;QACxE,IAAI,CAAC,eAAe,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC;YAC5C,aAAa,EAAE,CAAC;YAChB,KAAK,IAAI,EAAE,CAAC;QACd,CAAC;QACD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1C,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,sBAAsB,CAAC,CAAC;QAEtE,OAAO,GAAG,EAAE;YACV,OAAO,GAAG,IAAI,CAAC;YACf,WAAW,EAAE,CAAC;YACd,IAAI,KAAK;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;YAC/B,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7C,QAAQ,CAAC,mBAAmB,CAAC,kBAAkB,EAAE,sBAAsB,CAAC,CAAC;QAC3E,CAAC,CAAC;IACJ,CAAC,EAAE;QACD,OAAO;QACP,MAAM;QACN,WAAW;QACX,QAAQ;QACR,gBAAgB;QAChB,eAAe;KAChB,CAAC,CAAC;AACL,CAAC;AAED,wCAAwC;AACxC,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAC;AAExC;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,mBAAmB,CACjC,UAMI,EAAE;IAEN,MAAM,EACJ,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,OAAO,IAAI,qBAAqB,CAAC,EACnE,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,EACtC,QAAQ,GAAG,IAAI,EACf,gBAAgB,GAAG,IAAI,CAAC,GAAG,CACzB,OAAO,CAAC,gBAAgB,IAAI,wBAAwB,EACpD,QAAQ,CACT,EACD,eAAe,GAAG,IAAI,GACvB,GAAG,OAAO,CAAC;IACZ,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAElC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,KAAK,GAAyC,IAAI,CAAC;QACvD,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,IAAI,WAAW,GAAuB,IAAI,CAAC;QAC3C,IAAI,YAAY,GAAG,KAAK,CAAC;QAEzB,SAAS,YAAY;YACnB,IAAI,OAAO;gBAAE,OAAO;YACpB,IAAI,eAAe,IAAI,gBAAgB,EAAE;gBAAE,OAAO;YAClD,IAAI,KAAK;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;YAC/B,KAAK,GAAG,UAAU,CAChB,GAAG,EAAE;gBACH,KAAK,GAAG,IAAI,CAAC;gBACb,KAAK,IAAI,EAAE,CAAC;YACd,CAAC,EACD,YAAY,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAC3C,CAAC;QACJ,CAAC;QAED,SAAS,WAAW,CAAC,MAAmB,EAAE,OAAgB;YACxD,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;gBAC1C,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpC,OAAO,OAAO,KAAK,CAAC,IAAI,OAAO,GAAG,UAAU,CAAC;YAC/C,CAAC,CAAC,CAAC;YACH,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,gBAAgB,CAAC,EAAE,CAAC;gBAC3D,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACvB,CAAC;YACD,MAAM,eAAe,GAAG,WAAW,CAAC,MAAM,CACxC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,EAClD,CAAC,CACF,CAAC;YACF,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,IAAI,CAAC,EAAE,eAAe,CAAC,CAAC;QACnE,CAAC;QAED,SAAS,WAAW;YAClB,IAAI,CAAC,WAAW;gBAAE,OAAO;YACzB,WAAW,CAAC,KAAK,EAAE,CAAC;YACpB,WAAW,GAAG,IAAI,CAAC;YACnB,YAAY,GAAG,KAAK,CAAC;QACvB,CAAC;QAED,SAAS,aAAa;YACpB,IACE,OAAO;gBACP,CAAC,MAAM;gBACP,WAAW;gBACX,OAAO,WAAW,KAAK,WAAW;gBAClC,CAAC,eAAe,IAAI,gBAAgB,EAAE,CAAC,EACvC,CAAC;gBACD,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;YACvC,WAAW,GAAG,MAAM,CAAC;YACrB,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE;gBACnB,YAAY,GAAG,IAAI,CAAC;gBACpB,YAAY,EAAE,CAAC;YACjB,CAAC,CAAC;YACF,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE;gBACpB,YAAY,GAAG,KAAK,CAAC;gBACrB,YAAY,EAAE,CAAC;YACjB,CAAC,CAAC;YACF,MAAM,CAAC,SAAS,GAAG,CAAC,OAAO,EAAE,EAAE;gBAC7B,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;oBACzC,MAAM,MAAM,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;oBAC9C,MAAM,OAAO,GACX,OAAO,OAAO,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;oBACrE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAC/B,CAAC;gBAAC,MAAM,CAAC;oBACP,mDAAmD;gBACrD,CAAC;YACH,CAAC,CAAC;QACJ,CAAC;QAED,KAAK,UAAU,IAAI;YACjB,IAAI,OAAO,IAAI,QAAQ;gBAAE,OAAO;YAChC,QAAQ,GAAG,IAAI,CAAC;YAChB,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,aAAa,CAC9B,OAAO,EACP,UAAU,EACV,QAAQ,CACT,CAAC;gBACF,WAAW,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YAC/C,CAAC;YAAC,MAAM,CAAC;gBACP,0CAA0C;YAC5C,CAAC;oBAAS,CAAC;gBACT,QAAQ,GAAG,KAAK,CAAC;gBACjB,YAAY,EAAE,CAAC;YACjB,CAAC;QACH,CAAC;QAED,SAAS,OAAO;YACd,IAAI,eAAe,IAAI,gBAAgB,EAAE,EAAE,CAAC;gBAC1C,OAAO;YACT,CAAC;YACD,IAAI,KAAK,EAAE,CAAC;gBACV,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;YACD,aAAa,EAAE,CAAC;YAChB,KAAK,IAAI,EAAE,CAAC;QACd,CAAC;QAED,SAAS,sBAAsB;YAC7B,IAAI,QAAQ,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;gBAC3C,aAAa,EAAE,CAAC;gBAChB,OAAO,EAAE,CAAC;YACZ,CAAC;iBAAM,IAAI,eAAe,EAAE,CAAC;gBAC3B,WAAW,EAAE,CAAC;gBACd,IAAI,KAAK,EAAE,CAAC;oBACV,YAAY,CAAC,KAAK,CAAC,CAAC;oBACpB,KAAK,GAAG,IAAI,CAAC;gBACf,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,CAAC,eAAe,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC;YAC5C,aAAa,EAAE,CAAC;YAChB,KAAK,IAAI,EAAE,CAAC;QACd,CAAC;QACD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1C,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,sBAAsB,CAAC,CAAC;QAEtE,OAAO,GAAG,EAAE;YACV,OAAO,GAAG,IAAI,CAAC;YACf,WAAW,EAAE,CAAC;YACd,IAAI,KAAK;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;YAC/B,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7C,QAAQ,CAAC,mBAAmB,CAAC,kBAAkB,EAAE,sBAAsB,CAAC,CAAC;QAC3E,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,eAAe,CAAC,CAAC,CAAC;IAEnE,OAAO,GAAG,CAAC;AACb,CAAC","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\";\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;\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 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\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 Error(\"HTTP \" + 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 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\n function schedulePoll() {\n if (stopped) return;\n if (pauseWhenHidden && isDocumentHidden()) return;\n if (timer) clearTimeout(timer);\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 {\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 (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\n function schedulePoll() {\n if (stopped) return;\n if (pauseWhenHidden && isDocumentHidden()) return;\n if (timer) clearTimeout(timer);\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 {\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 (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"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=use-db-sync.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-db-sync.spec.d.ts","sourceRoot":"","sources":["../../src/client/use-db-sync.spec.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,80 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // @vitest-environment happy-dom
3
+ import { act } from "react";
4
+ import { createRoot } from "react-dom/client";
5
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
6
+ import { useDbSync } from "./use-db-sync.js";
7
+ class QueryClientProbe {
8
+ calls = [];
9
+ invalidateQueries(opts) {
10
+ this.calls.push(opts);
11
+ }
12
+ }
13
+ function SyncProbe({ queryClient }) {
14
+ useDbSync({
15
+ queryClient,
16
+ sseUrl: false,
17
+ interval: 50,
18
+ pauseWhenHidden: false,
19
+ });
20
+ return null;
21
+ }
22
+ async function renderWithEvent(event) {
23
+ const queryClient = new QueryClientProbe();
24
+ const fetchMock = vi.fn(async () => new Response(JSON.stringify({ version: event.version ?? 1, events: [event] })));
25
+ vi.stubGlobal("fetch", fetchMock);
26
+ const container = document.createElement("div");
27
+ document.body.appendChild(container);
28
+ const root = createRoot(container);
29
+ await act(async () => {
30
+ root.render(_jsx(SyncProbe, { queryClient: queryClient }));
31
+ await Promise.resolve();
32
+ await Promise.resolve();
33
+ });
34
+ return { container, fetchMock, queryClient, root };
35
+ }
36
+ describe("useDbSync", () => {
37
+ let roots = [];
38
+ let containers = [];
39
+ beforeEach(() => {
40
+ vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
41
+ });
42
+ afterEach(() => {
43
+ for (const root of roots) {
44
+ act(() => root.unmount());
45
+ }
46
+ for (const container of containers) {
47
+ container.remove();
48
+ }
49
+ roots = [];
50
+ containers = [];
51
+ vi.unstubAllGlobals();
52
+ });
53
+ it("broadly invalidates active queries for action events", async () => {
54
+ const result = await renderWithEvent({
55
+ version: 1,
56
+ source: "action",
57
+ type: "change",
58
+ key: "create-project",
59
+ });
60
+ roots.push(result.root);
61
+ containers.push(result.container);
62
+ expect(result.fetchMock).toHaveBeenCalled();
63
+ expect(result.queryClient.calls).toContainEqual(undefined);
64
+ expect(result.queryClient.calls).toContainEqual({ queryKey: ["action"] });
65
+ });
66
+ it("keeps non-action events on targeted framework invalidations", async () => {
67
+ const result = await renderWithEvent({
68
+ version: 1,
69
+ source: "settings",
70
+ type: "change",
71
+ key: "*",
72
+ });
73
+ roots.push(result.root);
74
+ containers.push(result.container);
75
+ expect(result.fetchMock).toHaveBeenCalled();
76
+ expect(result.queryClient.calls).not.toContainEqual(undefined);
77
+ expect(result.queryClient.calls).toContainEqual({ queryKey: ["action"] });
78
+ });
79
+ });
80
+ //# sourceMappingURL=use-db-sync.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-db-sync.spec.js","sourceRoot":"","sources":["../../src/client/use-db-sync.spec.tsx"],"names":[],"mappings":"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","sourcesContent":["// @vitest-environment happy-dom\n\nimport React, { act } from \"react\";\nimport { createRoot, type Root } from \"react-dom/client\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { useDbSync } from \"./use-db-sync.js\";\n\nclass QueryClientProbe {\n calls: Array<{ queryKey?: string[] } | undefined> = [];\n\n invalidateQueries(opts?: { queryKey?: string[] }) {\n this.calls.push(opts);\n }\n}\n\nfunction SyncProbe({ queryClient }: { queryClient: QueryClientProbe }) {\n useDbSync({\n queryClient,\n sseUrl: false,\n interval: 50,\n pauseWhenHidden: false,\n });\n return null;\n}\n\nasync function renderWithEvent(event: Record<string, unknown>) {\n const queryClient = new QueryClientProbe();\n const fetchMock = vi.fn(\n async () =>\n new Response(\n JSON.stringify({ version: event.version ?? 1, events: [event] }),\n ),\n );\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const container = document.createElement(\"div\");\n document.body.appendChild(container);\n const root = createRoot(container);\n\n await act(async () => {\n root.render(<SyncProbe queryClient={queryClient} />);\n await Promise.resolve();\n await Promise.resolve();\n });\n\n return { container, fetchMock, queryClient, root };\n}\n\ndescribe(\"useDbSync\", () => {\n let roots: Root[] = [];\n let containers: HTMLDivElement[] = [];\n\n beforeEach(() => {\n vi.stubGlobal(\"IS_REACT_ACT_ENVIRONMENT\", true);\n });\n\n afterEach(() => {\n for (const root of roots) {\n act(() => root.unmount());\n }\n for (const container of containers) {\n container.remove();\n }\n roots = [];\n containers = [];\n vi.unstubAllGlobals();\n });\n\n it(\"broadly invalidates active queries for action events\", async () => {\n const result = await renderWithEvent({\n version: 1,\n source: \"action\",\n type: \"change\",\n key: \"create-project\",\n });\n roots.push(result.root);\n containers.push(result.container);\n\n expect(result.fetchMock).toHaveBeenCalled();\n expect(result.queryClient.calls).toContainEqual(undefined);\n expect(result.queryClient.calls).toContainEqual({ queryKey: [\"action\"] });\n });\n\n it(\"keeps non-action events on targeted framework invalidations\", async () => {\n const result = await renderWithEvent({\n version: 1,\n source: \"settings\",\n type: \"change\",\n key: \"*\",\n });\n roots.push(result.root);\n containers.push(result.container);\n\n expect(result.fetchMock).toHaveBeenCalled();\n expect(result.queryClient.calls).not.toContainEqual(undefined);\n expect(result.queryClient.calls).toContainEqual({ queryKey: [\"action\"] });\n });\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/db/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/db/client.ts"],"names":[],"mappings":"AAkBA,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,IAAI,CAAC;AAEnD,MAAM,WAAW,MAAM;IACrB,OAAO,CACL,GAAG,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,GAAG,EAAE,CAAA;KAAE,GACzC,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,EAAE,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,GAAG,CAAC;CACjB;AAMD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,QAAQ,SAAK,GAAG,MAAM,CAOpD;AAED,8EAA8E;AAC9E,wBAAgB,oBAAoB,IAAI,MAAM,GAAG,SAAS,CAOzD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBxE;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAQzD;AAMD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAO/D;AAMD;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAC3E,OAAO,CAAC,CAAC,CAAC,CAkBZ;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAOxE;AAiBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,GAAG,GAAG,OAAO,CAejD;AAQD,wBAAgB,UAAU,IAAI,OAAO,CAyBpC;AAED,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAgBD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAIzC;AAED,iFAAiF;AACjF,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AA2BD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAoBnD;AAED,wBAAsB,sBAAsB,CAAC,CAAC,EAC5C,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,WAAW,SAAI,GACd,OAAO,CAAC,CAAC,CAAC,CAYZ;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAItC;AAgBD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,CAAC,EACnC,EAAE,EAAE,MAAM,EACV,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACrB,EAAE,SAAkB,EACpB,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACrC,OAAO,CAAC,CAAC,CAAC,CAmDZ;AAMD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAQ7C;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAYlE;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAsQD,wBAAsB,YAAY,CAAC,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAE7E;AAiBD;;;GAGG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAoClC;AAED,qEAAqE;AACrE,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAejD"}
package/dist/db/client.js CHANGED
@@ -9,6 +9,7 @@
9
9
  * Cloudflare Workers, edge) without failing on missing native deps.
10
10
  */
11
11
  import path from "path";
12
+ const recyclingPostgresPools = new WeakSet();
12
13
  // ---------------------------------------------------------------------------
13
14
  // Per-app DATABASE_URL resolution
14
15
  // ---------------------------------------------------------------------------
@@ -566,12 +567,16 @@ async function createDbExecInternal(config = {}, trackSingletonResources = false
566
567
  let pool = createPool();
567
568
  if (trackSingletonResources)
568
569
  _pgPool = pool;
569
- const recyclePool = async () => {
570
- const oldPool = pool;
571
- pool = createPool();
572
- if (trackSingletonResources)
573
- _pgPool = pool;
574
- await oldPool.end({ timeout: 1 });
570
+ const recyclePool = async (timedOutPool) => {
571
+ if (recyclingPostgresPools.has(timedOutPool))
572
+ return;
573
+ recyclingPostgresPools.add(timedOutPool);
574
+ if (pool === timedOutPool) {
575
+ pool = createPool();
576
+ if (trackSingletonResources)
577
+ _pgPool = pool;
578
+ }
579
+ await timedOutPool.end({ timeout: 1 });
575
580
  };
576
581
  return {
577
582
  async execute(sql) {
@@ -579,8 +584,9 @@ async function createDbExecInternal(config = {}, trackSingletonResources = false
579
584
  const args = typeof sql === "string" ? [] : sql.args || [];
580
585
  const pgSql = sqliteToPostgresParams(rawSql);
581
586
  const result = await retryOnConnectionError(() => {
582
- const query = pool.unsafe(pgSql, args);
583
- return withDbTimeout("query", () => query, dbOpTimeoutMs(), recyclePool);
587
+ const queryPool = pool;
588
+ const query = queryPool.unsafe(pgSql, args);
589
+ return withDbTimeout("query", () => query, dbOpTimeoutMs(), () => recyclePool(queryPool));
584
590
  });
585
591
  return {
586
592
  rows: Array.from(result),