@mycadet/assistant 0.12.9 → 0.12.10

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 (651) hide show
  1. package/Dockerfile +0 -8
  2. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +1 -1
  3. package/openapi.yaml +62 -910
  4. package/package.json +3 -7
  5. package/scripts/build-test-fixtures.ts +1 -1
  6. package/scripts/generate-openapi.ts +22 -6
  7. package/scripts/postinstall.ts +4 -10
  8. package/scripts/run-tests.ts +0 -21
  9. package/src/__tests__/adaptive-thinking-repair.test.ts +19 -57
  10. package/src/__tests__/agent-loop.test.ts +0 -76
  11. package/src/__tests__/anthropic-provider.test.ts +6 -6
  12. package/src/__tests__/assert-not-live-db.ts +1 -1
  13. package/src/__tests__/assistant-id-boundary-guard.test.ts +3 -3
  14. package/src/__tests__/attachments-store-heic-normalize.test.ts +1 -1
  15. package/src/__tests__/attachments-store.test.ts +1 -1
  16. package/src/__tests__/audit-log-rotation.test.ts +1 -1
  17. package/src/__tests__/btw-routes.test.ts +1 -1
  18. package/src/__tests__/byok-default-profile-ensure.test.ts +21 -27
  19. package/src/__tests__/call-conversation-messages.test.ts +0 -5
  20. package/src/__tests__/call-recovery.test.ts +2 -7
  21. package/src/__tests__/call-routes-http.test.ts +0 -12
  22. package/src/__tests__/call-store.test.ts +2 -7
  23. package/src/__tests__/catalog-files.test.ts +7 -5
  24. package/src/__tests__/checker.test.ts +1 -1
  25. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +4 -4
  26. package/src/__tests__/cloud-client-verify-credential.test.ts +0 -4
  27. package/src/__tests__/cloud-credential-catalog-cli.test.ts +14 -14
  28. package/src/__tests__/cloud-profile-guard.test.ts +48 -401
  29. package/src/__tests__/compaction-events.test.ts +2 -2
  30. package/src/__tests__/config-loader-backfill.test.ts +74 -163
  31. package/src/__tests__/config-loader-cloud-defaults.test.ts +11 -11
  32. package/src/__tests__/config-loader-corrupt.test.ts +10 -10
  33. package/src/__tests__/config-loader-quarantine-notice.test.ts +7 -7
  34. package/src/__tests__/config-loader-validation-reset-notice.test.ts +11 -11
  35. package/src/__tests__/config-schema.test.ts +26 -27
  36. package/src/__tests__/config-set-route.test.ts +2 -6
  37. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +28 -300
  38. package/src/__tests__/conversation-agent-loop-overflow.test.ts +39 -246
  39. package/src/__tests__/conversation-agent-loop.test.ts +2 -58
  40. package/src/__tests__/conversation-clear-safety.test.ts +0 -30
  41. package/src/__tests__/conversation-inference-profile-route.test.ts +1 -1
  42. package/src/__tests__/conversation-queue.test.ts +1 -1
  43. package/src/__tests__/conversation-runtime-assembly.test.ts +1 -1
  44. package/src/__tests__/conversation-skill-tools.test.ts +4 -444
  45. package/src/__tests__/conversation-slash-commands.test.ts +1 -1
  46. package/src/__tests__/conversation-store.test.ts +1 -84
  47. package/src/__tests__/conversation-surface-state.test.ts +0 -16
  48. package/src/__tests__/credential-health-service.test.ts +14 -1
  49. package/src/__tests__/credential-record-retire.test.ts +1 -1
  50. package/src/__tests__/credential-record-write-through.test.ts +1 -1
  51. package/src/__tests__/credential-security-invariants.test.ts +0 -145
  52. package/src/__tests__/custom-profile-ensure.test.ts +1 -1
  53. package/src/__tests__/default-profile-catalog-fallback.test.ts +5 -15
  54. package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -2
  55. package/src/__tests__/dictation-profile-store.test.ts +6 -6
  56. package/src/__tests__/disk-usage.test.ts +28 -164
  57. package/src/__tests__/docker-signing-key-bootstrap.test.ts +1 -1
  58. package/src/__tests__/embedding-cloud-proxy-selection.test.ts +1 -1
  59. package/src/__tests__/emit-event-signal.test.ts +1 -1
  60. package/src/__tests__/gateway-client-cloud-outbound.test.ts +3 -3
  61. package/src/__tests__/gateway-only-enforcement.test.ts +1 -1
  62. package/src/__tests__/guardian-dispatch.test.ts +0 -13
  63. package/src/__tests__/helpers/seed-app.ts +1 -1
  64. package/src/__tests__/host-cu-routes-targeted.test.ts +1 -1
  65. package/src/__tests__/host-shell-tool.test.ts +1 -1
  66. package/src/__tests__/identity-routes.test.ts +1 -1
  67. package/src/__tests__/inference-profile-session-handler.test.ts +1 -1
  68. package/src/__tests__/inference-profile-session-ipc.test.ts +1 -1
  69. package/src/__tests__/injector-chain.test.ts +1 -1
  70. package/src/__tests__/injector-config-quarantine-notice.test.ts +1 -1
  71. package/src/__tests__/injector-config-validation-reset-notice.test.ts +1 -1
  72. package/src/__tests__/injector-pkb-v2-silenced.test.ts +1 -1
  73. package/src/__tests__/{platform.test.ts → layout.test.ts} +1 -1
  74. package/src/__tests__/list-all-apps.test.ts +1 -1
  75. package/src/__tests__/live-workspace-guard.test.ts +2 -2
  76. package/src/__tests__/llm-resolver-override-or-default.test.ts +5 -6
  77. package/src/__tests__/llm-resolver.test.ts +7 -7
  78. package/src/__tests__/llm-schema-fallback-profile.test.ts +9 -10
  79. package/src/__tests__/llm-usage-store.test.ts +0 -495
  80. package/src/__tests__/log-export-routes.test.ts +1 -1
  81. package/src/__tests__/mcp-config-secret-boundary.test.ts +12 -53
  82. package/src/__tests__/mcp-list-plugin-servers.test.ts +1 -1
  83. package/src/__tests__/memory-config-file-parity.test.ts +1 -1
  84. package/src/__tests__/memory-v2-static-injector.test.ts +1 -1
  85. package/src/__tests__/messages-read-boundary-guard.test.ts +0 -2
  86. package/src/__tests__/notification-guardian-path.test.ts +0 -7
  87. package/src/__tests__/onboarding-persona-write.test.ts +1 -1
  88. package/src/__tests__/openai-provider.test.ts +8 -8
  89. package/src/__tests__/path-policy.test.ts +1 -1
  90. package/src/__tests__/persona-resolver.test.ts +1 -1
  91. package/src/__tests__/plugin-app-serve-routes.test.ts +1 -1
  92. package/src/__tests__/plugin-effective-enabled-set.test.ts +1 -1
  93. package/src/__tests__/plugin-import-boundary-guard.test.ts +4 -6
  94. package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +0 -3
  95. package/src/__tests__/provider-cloud-proxy-integration.test.ts +1 -5
  96. package/src/__tests__/provider-connections-backfill.test.ts +10 -10
  97. package/src/__tests__/prune-old-conversations-job.test.ts +6 -31
  98. package/src/__tests__/resolve-app.test.ts +1 -1
  99. package/src/__tests__/run-due-schedules.test.ts +1 -1
  100. package/src/__tests__/scaffold-managed-skill-tool.test.ts +0 -53
  101. package/src/__tests__/schedule-routes.test.ts +1 -1
  102. package/src/__tests__/schedule-store.test.ts +1 -1
  103. package/src/__tests__/secret-routes-cloud-proxy.test.ts +1 -1
  104. package/src/__tests__/skill-load-plugin-scope.test.ts +1 -1
  105. package/src/__tests__/surface-completion-compaction-boundary.test.ts +1 -1
  106. package/src/__tests__/tool-approval-handler.test.ts +1 -1
  107. package/src/__tests__/tool-audit.test.ts +5 -235
  108. package/src/__tests__/tool-executor-lifecycle-events.test.ts +54 -114
  109. package/src/__tests__/tools-get-route.test.ts +1 -1
  110. package/src/__tests__/turn-outcome-read.test.ts +1 -1
  111. package/src/__tests__/twilio-routes.test.ts +0 -1
  112. package/src/__tests__/usage-attribution.test.ts +0 -31
  113. package/src/__tests__/verification-control-plane-policy.test.ts +3 -10
  114. package/src/__tests__/visible-app-context.test.ts +1 -1
  115. package/src/__tests__/voice-ingress-preflight.test.ts +1 -1
  116. package/src/__tests__/workspace-git-service.test.ts +1 -1
  117. package/src/__tests__/workspace-greetings.test.ts +1 -1
  118. package/src/acp/__tests__/helpers/acp-config-stub.ts +1 -1
  119. package/src/activation/progress-store.ts +1 -1
  120. package/src/activation/turn-hooks.ts +1 -1
  121. package/src/agent/loop.ts +0 -51
  122. package/src/apps/app-store.ts +1 -1
  123. package/src/avatar/__tests__/avatar-store.test.ts +2 -172
  124. package/src/avatar/accent-backfill.ts +1 -1
  125. package/src/avatar/avatar-manifest.ts +1 -1
  126. package/src/avatar/avatar-store.ts +10 -69
  127. package/src/avatar/ensure-raster.ts +1 -1
  128. package/src/avatar/identity-avatar.ts +1 -1
  129. package/src/avatar/sync-avatar.ts +1 -1
  130. package/src/avatar/traits-png-sync.ts +1 -1
  131. package/src/bundler/compiler-tools.ts +1 -1
  132. package/src/bundler/package-resolver.ts +1 -1
  133. package/src/calls/__tests__/call-controller.test.ts +25 -27
  134. package/src/calls/active-call-lease.ts +1 -1
  135. package/src/calls/call-controller.ts +3 -3
  136. package/src/calls/call-domain.ts +4 -8
  137. package/src/calls/call-store.ts +2 -76
  138. package/src/calls/resolve-call-tts-provider.ts +3 -3
  139. package/src/calls/twilio-config.ts +3 -3
  140. package/src/calls/twilio-rest.ts +2 -2
  141. package/src/calls/voice-ingress-preflight.ts +2 -2
  142. package/src/cli/bundled-modules.ts +0 -2
  143. package/src/cli/commands/__tests__/apps.test.ts +1 -1
  144. package/src/cli/commands/__tests__/plugins.test.ts +9 -66
  145. package/src/cli/commands/__tests__/ps.test.ts +67 -0
  146. package/src/cli/commands/auth.help.ts +2 -2
  147. package/src/cli/commands/avatar.ts +1 -1
  148. package/src/cli/commands/changelog.ts +1 -1
  149. package/src/cli/commands/cloud/__tests__/subscription.test.ts +2 -2
  150. package/src/cli/commands/cloud/index.help.ts +1 -1
  151. package/src/cli/commands/cloud/index.ts +2 -2
  152. package/src/cli/commands/db/refresh.ts +1 -1
  153. package/src/cli/commands/db/repair-step-conversation-backfill.ts +1 -1
  154. package/src/cli/commands/db/repair.ts +1 -1
  155. package/src/cli/commands/db/status.ts +1 -1
  156. package/src/cli/commands/inference-profiles.ts +1 -12
  157. package/src/cli/commands/memory/__tests__/memory-v3.test.ts +1 -116
  158. package/src/cli/commands/memory/index.help.ts +1 -43
  159. package/src/cli/commands/memory/memory-v3.ts +0 -64
  160. package/src/cli/commands/plugins.ts +54 -205
  161. package/src/cli/commands/ps.ts +5 -2
  162. package/src/cli/commands/status.ts +1 -1
  163. package/src/cli/index.help.ts +0 -2
  164. package/src/cli/lib/__tests__/inspect-plugin.test.ts +36 -66
  165. package/src/cli/lib/__tests__/install-from-cloud.test.ts +1 -1
  166. package/src/cli/lib/__tests__/install-from-github.test.ts +41 -117
  167. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +2 -185
  168. package/src/cli/lib/__tests__/plugin-catalog-resolve.test.ts +36 -66
  169. package/src/cli/lib/__tests__/plugin-catalog-visibility.test.ts +4 -6
  170. package/src/cli/lib/__tests__/plugin-details.test.ts +113 -96
  171. package/src/cli/lib/__tests__/search-plugins.test.ts +9 -16
  172. package/src/cli/lib/__tests__/uninstall-plugin.test.ts +1 -1
  173. package/src/cli/lib/__tests__/upgrade-plugin.test.ts +38 -15
  174. package/src/cli/lib/diff-plugin.ts +1 -1
  175. package/src/cli/lib/inspect-plugin.ts +13 -97
  176. package/src/cli/lib/install-from-cloud.ts +1 -1
  177. package/src/cli/lib/install-from-github.ts +75 -154
  178. package/src/cli/lib/install-plugin-dependencies.ts +1 -1
  179. package/src/cli/lib/list-installed-plugins.ts +1 -1
  180. package/src/cli/lib/open-browser.ts +1 -1
  181. package/src/cli/lib/plugin-catalog-cache.ts +8 -51
  182. package/src/cli/lib/plugin-catalog-resolve.ts +3 -22
  183. package/src/cli/lib/plugin-details.ts +5 -27
  184. package/src/cli/lib/plugin-marketplace.ts +18 -266
  185. package/src/cli/lib/search-plugins.ts +23 -43
  186. package/src/cli/lib/toggle-plugin.ts +1 -1
  187. package/src/cli/lib/uninstall-plugin.ts +1 -1
  188. package/src/cli/lib/upgrade-plugin.ts +3 -49
  189. package/src/cli/program.ts +1 -3
  190. package/src/cli.ts +1 -1
  191. package/src/cloud/client.ts +0 -6
  192. package/src/cloud/consent-cache.test.ts +22 -201
  193. package/src/cloud/consent-cache.ts +16 -111
  194. package/src/cloud/sync-identity.ts +1 -1
  195. package/src/config/__tests__/chat-settings.test.ts +1 -1
  196. package/src/config/__tests__/cloud-identity.test.ts +15 -2
  197. package/src/config/__tests__/default-plugin-skill-discovery.test.ts +1 -1
  198. package/src/config/__tests__/default-profile-catalog.test.ts +12 -51
  199. package/src/config/__tests__/deployment-context-defaults.test.ts +13 -13
  200. package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +4 -4
  201. package/src/config/__tests__/loader-last-known-good.test.ts +9 -9
  202. package/src/config/__tests__/loader-sparse-array-cleanup.test.ts +7 -7
  203. package/src/config/__tests__/plugin-resident-skill-discovery.test.ts +1 -1
  204. package/src/config/__tests__/profile-materialization.test.ts +2 -4
  205. package/src/config/__tests__/sync-gated-profiles.test.ts +1 -106
  206. package/src/config/acp-agent-write.ts +1 -1
  207. package/src/config/bundled-skills/settings/tools/open-system-settings.test.ts +1 -1
  208. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -1
  209. package/src/config/call-site-defaults.ts +0 -6
  210. package/src/config/cloud-identity.ts +12 -5
  211. package/src/config/composer-preferences.ts +1 -1
  212. package/src/config/default-profile-catalog.ts +8 -75
  213. package/src/config/default-profile-names.ts +2 -25
  214. package/src/config/env-registry.ts +1 -14
  215. package/src/config/env.ts +8 -6
  216. package/src/config/llm-resolver.ts +1 -2
  217. package/src/config/loader.ts +13 -17
  218. package/src/config/profile-materialization.ts +1 -1
  219. package/src/config/schema.ts +1 -7
  220. package/src/config/schemas/call-site-catalog.ts +0 -7
  221. package/src/config/schemas/llm.ts +22 -27
  222. package/src/config/seed-inference-profiles.ts +16 -17
  223. package/src/config/skills.ts +2 -2
  224. package/src/config/sync-gated-profiles.ts +6 -24
  225. package/src/credential-health/credential-health-service.ts +10 -3
  226. package/src/daemon/approval-generators.ts +3 -3
  227. package/src/daemon/config-watcher.ts +2 -2
  228. package/src/daemon/conversation-agent-loop-handlers.ts +0 -18
  229. package/src/daemon/conversation-agent-loop.ts +6 -97
  230. package/src/daemon/conversation-process.ts +1 -1
  231. package/src/daemon/conversation-skill-tools.ts +4 -72
  232. package/src/daemon/conversation-store.ts +1 -1
  233. package/src/daemon/conversation-surface-state.ts +0 -33
  234. package/src/daemon/conversation-surfaces.ts +1 -86
  235. package/src/daemon/conversation-tool-setup.test.ts +1 -1
  236. package/src/daemon/conversation-tool-setup.ts +0 -23
  237. package/src/daemon/conversation.ts +3 -5
  238. package/src/daemon/daemon-control.ts +3 -3
  239. package/src/daemon/dictation-profile-store.ts +3 -3
  240. package/src/daemon/event-loop-watchdog.test.ts +2 -198
  241. package/src/daemon/event-loop-watchdog.ts +0 -185
  242. package/src/daemon/external-plugins-bootstrap.ts +1 -1
  243. package/src/daemon/first-greeting.ts +1 -1
  244. package/src/daemon/handlers/skills.ts +1 -1
  245. package/src/daemon/host-app-control-proxy.ts +1 -1
  246. package/src/daemon/host-cu-proxy.ts +2 -2
  247. package/src/daemon/identity-helpers.ts +1 -1
  248. package/src/daemon/lifecycle.ts +11 -15
  249. package/src/daemon/main.ts +1 -1
  250. package/src/daemon/now-scratchpad.ts +1 -1
  251. package/src/daemon/process-message.ts +4 -4
  252. package/src/daemon/profiler-run-store.ts +2 -2
  253. package/src/daemon/providers-setup.ts +2 -2
  254. package/src/daemon/shutdown-handlers.ts +0 -10
  255. package/src/daemon/sqlite-corruption-watchdog.test.ts +2 -142
  256. package/src/daemon/sqlite-corruption-watchdog.ts +17 -81
  257. package/src/daemon/tool-side-effects.ts +1 -1
  258. package/src/desktop/desktop-session-manager.ts +1 -1
  259. package/src/desktop/desktop-wallpaper-renderer.ts +1 -1
  260. package/src/heartbeat/heartbeat-service.ts +1 -1
  261. package/src/home/feed-writer.ts +1 -1
  262. package/src/home/home-greeting-cache.ts +1 -1
  263. package/src/home/relationship-state-writer.ts +2 -2
  264. package/src/hooks/__tests__/hook-live-reload.test.ts +1 -1
  265. package/src/hooks/hook-loader.ts +2 -2
  266. package/src/inbound/__tests__/oauth-callback-url.test.ts +2 -2
  267. package/src/inbound/oauth-callback-url.ts +3 -3
  268. package/src/ipc/__tests__/attachment-ipc.test.ts +1 -1
  269. package/src/ipc/socket-path.ts +1 -1
  270. package/src/live-voice/__tests__/live-voice-archive.test.ts +1 -1
  271. package/src/live-voice/__tests__/live-voice-vad.test.ts +1 -1
  272. package/src/live-voice/live-voice-session.ts +3 -66
  273. package/src/mcp/__tests__/effective-config.test.ts +1 -1
  274. package/src/mcp/__tests__/mcp-oauth-client-registration.test.ts +2 -2
  275. package/src/mcp/__tests__/mcp-oauth-provider.test.ts +2 -3
  276. package/src/mcp/__tests__/reload-signal-emission.test.ts +1 -1
  277. package/src/mcp/__tests__/reload-signal.test.ts +1 -1
  278. package/src/mcp/__tests__/workspace-mcp-config.test.ts +19 -21
  279. package/src/mcp/reload-signal.ts +1 -1
  280. package/src/mcp/workspace-mcp-config.ts +1 -23
  281. package/src/messaging/draft-store.ts +1 -1
  282. package/src/monitoring/__tests__/active-conversations.test.ts +1 -1
  283. package/src/monitoring/__tests__/page-cache.test.ts +1 -1
  284. package/src/monitoring/__tests__/stall-capture.test.ts +1 -1
  285. package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +1 -1
  286. package/src/monitoring/active-conversations.ts +1 -1
  287. package/src/monitoring/control.ts +1 -1
  288. package/src/monitoring/daemon-boot-time.ts +1 -1
  289. package/src/monitoring/daemon-heartbeat.ts +1 -1
  290. package/src/monitoring/page-cache.ts +1 -1
  291. package/src/monitoring/plugin-auto-update.ts +1 -7
  292. package/src/monitoring/plugin-source-watch.ts +1 -1
  293. package/src/monitoring/recovery/db.ts +1 -1
  294. package/src/monitoring/recovery/inflight-content.ts +1 -1
  295. package/src/monitoring/resource-sampler.ts +3 -14
  296. package/src/monitoring/stall-capture.ts +1 -1
  297. package/src/monitoring/worker.ts +9 -76
  298. package/src/monitoring/workspace-git-heartbeat.ts +1 -1
  299. package/src/oauth/connect-orchestrator.ts +4 -4
  300. package/src/permissions/checker.ts +1 -1
  301. package/src/permissions/workspace-policy.ts +1 -1
  302. package/src/persistence/__tests__/main-db-readonly-probe.ts +27 -52
  303. package/src/persistence/__tests__/message-content-file.test.ts +1 -1
  304. package/src/persistence/__tests__/slow-sync-log.test.ts +0 -2
  305. package/src/persistence/attachments-store.ts +1 -1
  306. package/src/persistence/conversation-crud.ts +1 -38
  307. package/src/persistence/conversation-directories.ts +1 -1
  308. package/src/persistence/conversation-types.ts +0 -8
  309. package/src/persistence/db-async-query.ts +1 -1
  310. package/src/persistence/db-connection.ts +11 -1
  311. package/src/persistence/db-init.ts +1 -1
  312. package/src/persistence/db-maintenance.ts +1 -1
  313. package/src/persistence/embeddings/__tests__/embedding-local-lifecycle.test.ts +1 -1
  314. package/src/persistence/embeddings/embedding-local.ts +4 -4
  315. package/src/persistence/embeddings/embedding-runtime-manager.ts +1 -1
  316. package/src/persistence/embeddings/qdrant-client.ts +1 -1
  317. package/src/persistence/embeddings/qdrant-manager.ts +1 -1
  318. package/src/persistence/job-handlers/__tests__/message-lexical-backfill.test.ts +1 -1
  319. package/src/persistence/job-handlers/__tests__/message-lexical-enqueue.test.ts +1 -1
  320. package/src/persistence/job-handlers/cleanup.ts +8 -17
  321. package/src/persistence/llm-usage-store.ts +2 -229
  322. package/src/persistence/message-content-file.ts +1 -1
  323. package/src/persistence/migrations/209-strip-thinking-from-consolidated.ts +1 -1
  324. package/src/persistence/migrations/222-strip-placeholder-sentinels-from-messages.ts +1 -1
  325. package/src/persistence/migrations/296-rewrite-balanced-economy-profile-pins.test.ts +1 -1
  326. package/src/persistence/migrations/306-rewrite-frontier-profile-pins.test.ts +1 -1
  327. package/src/persistence/migrations/329-move-onboarding-events-to-telemetry-db.test.ts +13 -0
  328. package/src/persistence/migrations/330-move-auth-fallback-events-to-telemetry-db.test.ts +13 -0
  329. package/src/persistence/migrations/331-move-lifecycle-events-to-telemetry-db.test.ts +13 -0
  330. package/src/persistence/migrations/332-move-skill-loaded-events-to-telemetry-db.test.ts +13 -0
  331. package/src/persistence/migrations/333-create-telemetry-events-table.test.ts +7 -4
  332. package/src/persistence/migrations/334-backfill-telemetry-events-outbox.test.ts +13 -0
  333. package/src/persistence/migrations/387-drop-telemetry-tables.ts +51 -0
  334. package/src/persistence/migrations/__tests__/327-create-flush-checkpoints.test.ts +9 -1
  335. package/src/persistence/migrations/__tests__/387-drop-telemetry-tables.test.ts +79 -0
  336. package/src/persistence/migrations/helpers/relocation.ts +1 -1
  337. package/src/persistence/migrations/run-migrations.ts +1 -1
  338. package/src/persistence/migrations/validate-migration-state.ts +1 -1
  339. package/src/persistence/raw-query.ts +1 -29
  340. package/src/persistence/slow-sync-log.ts +0 -23
  341. package/src/persistence/steps.ts +2 -0
  342. package/src/{telemetry → persistence}/tool-audit.ts +6 -121
  343. package/src/plugin-api/index.ts +1 -1
  344. package/src/plugin-api/plugin-name-env.ts +1 -1
  345. package/src/plugins/__tests__/installed-plugin-dirs.test.ts +1 -1
  346. package/src/plugins/collect-source-versions.ts +1 -1
  347. package/src/plugins/defaults/channel/package.json +1 -1
  348. package/src/plugins/defaults/cloud-hosted/package.json +1 -1
  349. package/src/plugins/defaults/compaction/package.json +1 -1
  350. package/src/plugins/defaults/documents/package.json +1 -1
  351. package/src/plugins/defaults/empty-response/package.json +1 -1
  352. package/src/plugins/defaults/exploration-drift/package.json +1 -1
  353. package/src/plugins/defaults/image-fallback/package.json +1 -1
  354. package/src/plugins/defaults/image-recovery/package.json +1 -1
  355. package/src/plugins/defaults/max-tokens-continue/package.json +1 -1
  356. package/src/plugins/defaults/memory/__tests__/db-async-query.test.ts +1 -1
  357. package/src/plugins/defaults/memory/__tests__/db-maintenance.test.ts +1 -1
  358. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +0 -82
  359. package/src/plugins/defaults/memory/__tests__/memory-retrospective-skill-card.test.ts +0 -41
  360. package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +0 -2
  361. package/src/plugins/defaults/memory/memory-retrospective-job.ts +3 -52
  362. package/src/plugins/defaults/memory/memory-retrospective-skill-card.ts +0 -18
  363. package/src/plugins/defaults/memory/package.json +1 -1
  364. package/src/plugins/defaults/memory/paths.ts +4 -4
  365. package/src/plugins/defaults/memory/src/__tests__/memory-worker-routes.test.ts +1 -1
  366. package/src/plugins/defaults/memory/src/memory-v2-routes.ts +5 -5
  367. package/src/plugins/defaults/memory/src/memory-v3-routes.ts +0 -207
  368. package/src/plugins/defaults/memory/src/memory-worker-routes.ts +1 -1
  369. package/src/plugins/defaults/memory/startup.ts +1 -22
  370. package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +2 -253
  371. package/src/plugins/defaults/memory/v3/orchestrate.ts +5 -129
  372. package/src/plugins/defaults/memory/worker-control.ts +1 -1
  373. package/src/plugins/defaults/memory/worker.ts +2 -2
  374. package/src/plugins/defaults/session/package.json +1 -1
  375. package/src/plugins/defaults/surface-completion-nudge/package.json +1 -1
  376. package/src/plugins/defaults/task-progress/package.json +1 -1
  377. package/src/plugins/defaults/task-progress-nudge/package.json +1 -1
  378. package/src/plugins/defaults/title-generate/package.json +1 -1
  379. package/src/plugins/defaults/tool-error/package.json +1 -1
  380. package/src/plugins/defaults/tool-result-truncate/package.json +1 -1
  381. package/src/plugins/defaults/turn-context/package.json +1 -1
  382. package/src/plugins/defaults/workspace/injectors.ts +1 -1
  383. package/src/plugins/defaults/workspace/package.json +1 -1
  384. package/src/plugins/disabled-state.ts +1 -1
  385. package/src/plugins/ensure-plugin-api-shim.ts +1 -1
  386. package/src/plugins/ensure-shared-dep-links.ts +1 -1
  387. package/src/plugins/installed-plugin-dirs.ts +1 -1
  388. package/src/plugins/mcp-servers.ts +7 -9
  389. package/src/plugins/mtime-cache.ts +2 -2
  390. package/src/plugins/source-versions.ts +1 -1
  391. package/src/prompts/bootstrap-cleanup.ts +1 -1
  392. package/src/prompts/persona-resolver.ts +1 -1
  393. package/src/prompts/sections.ts +2 -2
  394. package/src/prompts/system-prompt.ts +10 -42
  395. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +0 -37
  396. package/src/providers/__tests__/cadet-connection-routing.test.ts +2 -2
  397. package/src/providers/cadet/client.ts +1 -1
  398. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +1 -1
  399. package/src/providers/inference/adapter-factory.ts +1 -1
  400. package/src/providers/inference/backfill.ts +3 -10
  401. package/src/providers/inference/profile-probe.ts +1 -1
  402. package/src/providers/retry.ts +0 -2
  403. package/src/providers/types.ts +0 -7
  404. package/src/providers/usage-tracking.ts +1 -1
  405. package/src/routes/__tests__/route-host.test.ts +1 -1
  406. package/src/routes/control.ts +1 -1
  407. package/src/routes/route-host-client.ts +1 -1
  408. package/src/routes/worker.ts +2 -2
  409. package/src/runtime/agent-wake.ts +1 -1
  410. package/src/runtime/assistant-stream-state.ts +1 -1
  411. package/src/runtime/auth/token-service.ts +1 -1
  412. package/src/runtime/background-job-runner.ts +1 -1
  413. package/src/runtime/middleware/twilio-validation.ts +2 -2
  414. package/src/runtime/routes/__tests__/app-pin-routes.test.ts +1 -1
  415. package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +1 -1
  416. package/src/runtime/routes/__tests__/avatar-state-routes.test.ts +3 -33
  417. package/src/runtime/routes/__tests__/cloud-credits-routes.test.ts +5 -4
  418. package/src/runtime/routes/__tests__/cloud-invoice-routes.test.ts +4 -3
  419. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +59 -287
  420. package/src/runtime/routes/__tests__/default-plugin-routes.test.ts +1 -1
  421. package/src/runtime/routes/__tests__/deprecated-route-context.test.ts +15 -62
  422. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +105 -12
  423. package/src/runtime/routes/__tests__/ingress-status-routes.test.ts +1 -1
  424. package/src/runtime/routes/__tests__/monitoring-routes.test.ts +1 -1
  425. package/src/runtime/routes/__tests__/plugins-routes.test.ts +47 -211
  426. package/src/runtime/routes/__tests__/route-host-worker-routes.test.ts +1 -1
  427. package/src/runtime/routes/__tests__/schedule-routes-disarm-reason.test.ts +1 -1
  428. package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +1 -1
  429. package/src/runtime/routes/__tests__/user-route-dispatcher-host.test.ts +1 -1
  430. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +1 -1
  431. package/src/runtime/routes/__tests__/user-routes-cli.test.ts +1 -1
  432. package/src/runtime/routes/__tests__/user-routes-notices.test.ts +1 -1
  433. package/src/runtime/routes/__tests__/user-routes-request.test.ts +1 -1
  434. package/src/runtime/routes/app-management-routes.ts +1 -1
  435. package/src/runtime/routes/attachment-routes.ts +1 -1
  436. package/src/runtime/routes/audit-routes.ts +1 -1
  437. package/src/runtime/routes/avatar-routes.ts +3 -10
  438. package/src/runtime/routes/cloud-routes.ts +3 -3
  439. package/src/runtime/routes/content-source-routes.ts +1 -1
  440. package/src/runtime/routes/conversation-query-routes.ts +60 -621
  441. package/src/runtime/routes/conversation-routes.ts +1 -38
  442. package/src/runtime/routes/debug-routes.ts +1 -1
  443. package/src/runtime/routes/deprecated-route-context.ts +5 -61
  444. package/src/runtime/routes/heartbeat-routes.ts +1 -1
  445. package/src/runtime/routes/identity-routes.ts +1 -1
  446. package/src/runtime/routes/index.ts +0 -6
  447. package/src/runtime/routes/inference-profile-session-handler.ts +3 -3
  448. package/src/runtime/routes/inference-profiles-routes.ts +48 -21
  449. package/src/runtime/routes/inference-provider-connection-routes.ts +0 -1
  450. package/src/runtime/routes/llm-call-sites-routes.ts +3 -3
  451. package/src/runtime/routes/log-export/__tests__/installed-inventory.test.ts +1 -1
  452. package/src/runtime/routes/log-export/__tests__/workspace-allowlist-error-contract.test.ts +1 -1
  453. package/src/runtime/routes/log-export/__tests__/workspace-allowlist.test.ts +1 -1
  454. package/src/runtime/routes/log-export/workspace-allowlist.ts +1 -1
  455. package/src/runtime/routes/log-export-routes.ts +17 -15
  456. package/src/runtime/routes/migration-rollback-routes.ts +1 -1
  457. package/src/runtime/routes/migration-routes.ts +2 -3
  458. package/src/runtime/routes/monitoring-routes.ts +2 -2
  459. package/src/runtime/routes/oauth-providers.ts +5 -5
  460. package/src/runtime/routes/plugins-routes.ts +38 -163
  461. package/src/runtime/routes/profiler-routes.ts +1 -1
  462. package/src/runtime/routes/route-host-worker-routes.ts +1 -1
  463. package/src/runtime/routes/sanity-routes.ts +1 -1
  464. package/src/runtime/routes/schedule-routes.ts +1 -1
  465. package/src/runtime/routes/schedule-worker-routes.ts +1 -1
  466. package/src/runtime/routes/settings-routes.ts +1 -1
  467. package/src/runtime/routes/sounds-config-routes.ts +1 -1
  468. package/src/runtime/routes/surface-conversation-resolver.ts +1 -7
  469. package/src/runtime/routes/user-route-dispatcher.ts +1 -3
  470. package/src/runtime/routes/user-route-import.ts +1 -1
  471. package/src/runtime/routes/user-route-resolution.ts +1 -1
  472. package/src/runtime/routes/user-routes-cli.ts +1 -1
  473. package/src/runtime/routes/workspace-commit-routes.ts +1 -1
  474. package/src/runtime/routes/workspace-greetings.ts +1 -1
  475. package/src/runtime/routes/workspace-routes.ts +1 -1
  476. package/src/runtime/routes/workspace-utils.ts +1 -1
  477. package/src/runtime/sync/resource-sync-events.ts +1 -1
  478. package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +1 -1
  479. package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +1 -1
  480. package/src/schedule/plugin-schedule-availability.ts +1 -1
  481. package/src/schedule/plugin-schedule-declarations.ts +1 -1
  482. package/src/schedule/run-script.ts +1 -1
  483. package/src/schedule/scheduler.ts +1 -11
  484. package/src/schedule/worker-control.ts +1 -1
  485. package/src/schedule/worker.ts +3 -3
  486. package/src/security/oauth2.ts +2 -2
  487. package/src/security/secret-allowlist.ts +1 -1
  488. package/src/signals/cancel.ts +1 -1
  489. package/src/signals/conversation-undo.ts +1 -1
  490. package/src/signals/emit-event.ts +1 -1
  491. package/src/signals/event-stream.ts +1 -1
  492. package/src/signals/user-message.ts +1 -1
  493. package/src/skills/catalog-install.ts +2 -1
  494. package/src/skills/clawhub.ts +1 -1
  495. package/src/skills/cloud-store.ts +1 -1
  496. package/src/skills/path-classifier.ts +1 -1
  497. package/src/skills/skill-history.ts +1 -1
  498. package/src/skills/skillssh-registry.ts +1 -1
  499. package/src/skills/uninstall.ts +1 -1
  500. package/src/skills/workspace-skill-md-signature.ts +1 -1
  501. package/src/subagent/manager.ts +1 -1
  502. package/src/theme/workspace-theme.ts +1 -1
  503. package/src/tools/browser/auth-cache.ts +1 -1
  504. package/src/tools/browser/browser-manager.ts +1 -1
  505. package/src/tools/browser/runtime-check.ts +1 -1
  506. package/src/tools/executor.ts +4 -4
  507. package/src/tools/filesystem/write.ts +1 -1
  508. package/src/tools/permission-checker.ts +2 -51
  509. package/src/tools/run-standalone.ts +1 -1
  510. package/src/tools/skills/format-input-schema.ts +1 -1
  511. package/src/tools/skills/load.ts +1 -1
  512. package/src/tools/skills/scaffold-cloud.ts +0 -32
  513. package/src/tools/terminal/safe-env.ts +1 -2
  514. package/src/tools/terminal/sanitized-bash.ts +1 -1
  515. package/src/tools/terminal/shell.ts +1 -1
  516. package/src/tools/tool-approval-handler.ts +4 -1
  517. package/src/tools/workflows/manage-workflows.ts +2 -2
  518. package/src/tools/workflows/run-workflow.test.ts +1 -1
  519. package/src/tools/workspace-tools/loader.ts +1 -1
  520. package/src/tts/synthesis-stream.ts +2 -2
  521. package/src/usage/attribution.ts +1 -11
  522. package/src/util/browser.ts +1 -1
  523. package/src/util/bun-runtime.ts +2 -1
  524. package/src/util/device-id.ts +1 -1
  525. package/src/util/disk-usage.ts +4 -139
  526. package/src/util/layout.ts +3 -3
  527. package/src/util/logger.ts +1 -1
  528. package/src/util/logs-db-path.ts +1 -1
  529. package/src/util/memory-db-path.ts +1 -1
  530. package/src/util/{platform.ts → os.ts} +5 -30
  531. package/src/util/process-tree.ts +19 -0
  532. package/src/util/sqlite3-runtime.ts +1 -1
  533. package/src/util/telemetry-db-path.ts +1 -1
  534. package/src/watcher/__tests__/engine.test.ts +0 -23
  535. package/src/watcher/engine.ts +0 -7
  536. package/src/windows-compiled-cli.ts +0 -4
  537. package/src/windows-compiled-worker-entry.ts +0 -6
  538. package/src/workflows/leaf-runner.test.ts +1 -1
  539. package/src/workflows/leaf-runner.ts +1 -1
  540. package/src/workflows/library.ts +1 -1
  541. package/src/workspace/adaptive-thinking-repair.ts +5 -24
  542. package/src/workspace/byok-default-profile-ensure.ts +24 -26
  543. package/src/workspace/custom-profile-ensure.ts +2 -2
  544. package/src/workspace/git-service.ts +1 -1
  545. package/src/workspace/hatched-date.ts +1 -1
  546. package/src/workspace/migrations/038-unify-llm-callsite-configs.ts +2 -2
  547. package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +1 -1
  548. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +1 -1
  549. package/src/workspace/migrations/077-seed-memory-router-callsite.ts +1 -1
  550. package/src/workspace/migrations/registry.ts +0 -4
  551. package/src/workspace/turn-commit.ts +1 -1
  552. package/docs/activation-funnel-telemetry.md +0 -324
  553. package/scripts/bundled-plugin-packages.ts +0 -154
  554. package/scripts/generate-bundled-plugin-packages.ts +0 -29
  555. package/src/__tests__/activation-early-marking.test.ts +0 -114
  556. package/src/__tests__/auth-fallback-events-store.test.ts +0 -99
  557. package/src/__tests__/config-get-vision-flag.test.ts +0 -139
  558. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +0 -400
  559. package/src/__tests__/internal-telemetry-routes.test.ts +0 -213
  560. package/src/__tests__/telemetry-routes.test.ts +0 -182
  561. package/src/__tests__/turn-events-store.test.ts +0 -376
  562. package/src/__tests__/ui-channel-variants.test.ts +0 -53
  563. package/src/avatar/__tests__/avatar-changed-telemetry.test.ts +0 -217
  564. package/src/avatar/avatar-changed-telemetry.ts +0 -128
  565. package/src/calls/__tests__/call-funnel-telemetry.test.ts +0 -204
  566. package/src/cli/commands/telemetry.help.ts +0 -27
  567. package/src/cli/commands/telemetry.ts +0 -83
  568. package/src/cli/lib/__tests__/local-plugin-upgrade.test.ts +0 -251
  569. package/src/cli/lib/__tests__/plugin-catalog-local.test.ts +0 -113
  570. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +0 -384
  571. package/src/cli/lib/__tests__/plugin-pin-history.test.ts +0 -164
  572. package/src/cli/lib/__tests__/plugins-install-offline.test.ts +0 -228
  573. package/src/cli/lib/bundled-marketplace.json +0 -1575
  574. package/src/cli/lib/bundled-plugin-packages.json +0 -827
  575. package/src/cli/lib/bundled-plugin-packages.ts +0 -87
  576. package/src/cli/lib/plugin-catalog-local.ts +0 -94
  577. package/src/cli/lib/plugin-pin-history.ts +0 -276
  578. package/src/cloud/feature-gate.ts +0 -8
  579. package/src/config/__tests__/cloud-rehydration.test.ts +0 -180
  580. package/src/config/cloud-rehydration.ts +0 -35
  581. package/src/daemon/__tests__/auto-profile-router.test.ts +0 -380
  582. package/src/daemon/auto-profile-router.ts +0 -428
  583. package/src/live-voice/__tests__/live-voice-session-telemetry.test.ts +0 -391
  584. package/src/monitoring/__tests__/db-integrity-sample.test.ts +0 -113
  585. package/src/monitoring/__tests__/oom-kill-reporter.test.ts +0 -374
  586. package/src/monitoring/db-integrity-check.ts +0 -163
  587. package/src/monitoring/db-integrity-sample.ts +0 -176
  588. package/src/monitoring/oom-kill-reporter.ts +0 -469
  589. package/src/onboarding/__tests__/onboarding-events-store.test.ts +0 -158
  590. package/src/onboarding/onboarding-events-store.ts +0 -296
  591. package/src/persistence/__tests__/raw-query-telemetry.test.ts +0 -76
  592. package/src/persistence/lifecycle-events-store.test.ts +0 -134
  593. package/src/persistence/lifecycle-events-store.ts +0 -110
  594. package/src/plugins/defaults/memory/__tests__/activation-session-store.test.ts +0 -76
  595. package/src/plugins/defaults/memory/activation-session-store.ts +0 -50
  596. package/src/plugins/defaults/memory/src/__tests__/memory-v3-gate-stats.test.ts +0 -281
  597. package/src/runtime/routes/auto-profile-routes.ts +0 -83
  598. package/src/runtime/routes/internal-telemetry-routes.ts +0 -142
  599. package/src/runtime/routes/telemetry-routes.ts +0 -274
  600. package/src/security/auth-fallback-events-store.ts +0 -57
  601. package/src/telemetry/__tests__/activation-funnel.test.ts +0 -95
  602. package/src/telemetry/__tests__/config-setting-events-store.test.ts +0 -63
  603. package/src/telemetry/__tests__/config-setting-snapshot.test.ts +0 -143
  604. package/src/telemetry/__tests__/flush-checkpoints.test.ts +0 -56
  605. package/src/telemetry/__tests__/live-voice-funnel.test.ts +0 -174
  606. package/src/telemetry/__tests__/outbox-test-harness.ts +0 -85
  607. package/src/telemetry/__tests__/phone-call-funnel.test.ts +0 -72
  608. package/src/telemetry/__tests__/telemetry-event-fixtures.ts +0 -282
  609. package/src/telemetry/__tests__/watchdog-events-store.test.ts +0 -71
  610. package/src/telemetry/activation-funnel.ts +0 -172
  611. package/src/telemetry/config-setting-events-store.ts +0 -40
  612. package/src/telemetry/config-setting-snapshot.ts +0 -170
  613. package/src/telemetry/flush-checkpoints.ts +0 -70
  614. package/src/telemetry/live-voice-funnel.ts +0 -185
  615. package/src/telemetry/memory-corpus-size.test.ts +0 -120
  616. package/src/telemetry/memory-corpus-size.ts +0 -184
  617. package/src/telemetry/memory-tier-reporter.test.ts +0 -195
  618. package/src/telemetry/memory-tier-reporter.ts +0 -130
  619. package/src/telemetry/phone-call-funnel.ts +0 -144
  620. package/src/telemetry/skill-loaded-events-store.test.ts +0 -93
  621. package/src/telemetry/skill-loaded-events-store.ts +0 -39
  622. package/src/telemetry/telemetry-event-sources.test.ts +0 -223
  623. package/src/telemetry/telemetry-event-sources.ts +0 -597
  624. package/src/telemetry/telemetry-events-outbox.test.ts +0 -375
  625. package/src/telemetry/telemetry-events-outbox.ts +0 -237
  626. package/src/telemetry/telemetry-main-db.ts +0 -48
  627. package/src/telemetry/telemetry-wire-source.json +0 -4
  628. package/src/telemetry/telemetry-wire-validation.test.ts +0 -157
  629. package/src/telemetry/telemetry-wire-validation.ts +0 -162
  630. package/src/telemetry/telemetry-wire.generated.ts +0 -483
  631. package/src/telemetry/tool-executed-events-store.test.ts +0 -210
  632. package/src/telemetry/tool-executed-events-store.ts +0 -102
  633. package/src/telemetry/trace-collection-policy.test.ts +0 -28
  634. package/src/telemetry/trace-collection-policy.ts +0 -30
  635. package/src/telemetry/turn-events-store.ts +0 -216
  636. package/src/telemetry/turn-trace-store.test.ts +0 -884
  637. package/src/telemetry/turn-trace-store.ts +0 -399
  638. package/src/telemetry/types.test.ts +0 -38
  639. package/src/telemetry/types.ts +0 -780
  640. package/src/telemetry/usage-telemetry-reporter.test.ts +0 -3445
  641. package/src/telemetry/usage-telemetry-reporter.ts +0 -566
  642. package/src/telemetry/watchdog-direct-emit.test.ts +0 -112
  643. package/src/telemetry/watchdog-direct-emit.ts +0 -104
  644. package/src/telemetry/watchdog-events-store.ts +0 -31
  645. package/src/tools/ui-surface/channel-variants.ts +0 -52
  646. package/src/watcher/__tests__/telemetry.test.ts +0 -178
  647. package/src/watcher/telemetry.ts +0 -93
  648. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +0 -165
  649. package/src/workspace/migrations/104-recheck-adaptive-thinking-model-implied-anthropic.ts +0 -151
  650. /package/src/{telemetry → persistence}/tool-usage-store.ts +0 -0
  651. /package/src/{telemetry → persistence}/turn-outcome.ts +0 -0
@@ -1,566 +0,0 @@
1
- /**
2
- * Usage telemetry reporter.
3
- *
4
- * Periodically flushes unreported telemetry events (LLM usage, turns,
5
- * lifecycle, ...) from the local SQLite databases and POSTs them to the
6
- * platform telemetry endpoint. Each event type is a
7
- * {@link TelemetryEventSource}; the reporter is a generic engine over the
8
- * source list it is constructed with, acknowledging each source after a
9
- * successful upload in one of two modes: watermark-mode sources advance a
10
- * compound `(createdAt, id)` cursor in the telemetry DB's
11
- * `flush_checkpoints` table, and ack-mode sources (those defining `ack`)
12
- * delete their shipped rows instead.
13
- *
14
- * Flushing is split across two processes, each running its own reporter
15
- * instance over a disjoint source partition: the daemon flushes turn events
16
- * (their completeness barrier and consented traces read live in-memory
17
- * conversation state), and the resource monitor process flushes everything
18
- * else off the daemon's event loop — see `monitoring/worker.ts`. The
19
- * per-source watermark cursors live in the telemetry DB, which both
20
- * processes open read-write; each instance only touches its own sources'
21
- * cursors, so the split shares no flush state.
22
- *
23
- * Authenticated-only: events are sent via the cloud proxy context
24
- * (Api-Key header). When no cloud credentials are available, or when
25
- * platform features are disabled (CADET_DISABLE_CLOUD in local mode), the
26
- * flush is skipped and retried next cycle.
27
- */
28
-
29
- import { CadetCloudClient } from "../cloud/client.js";
30
- import { getRawShareAnalytics } from "../cloud/consent-cache.js";
31
- import { areCloudFeaturesEnabled } from "../cloud/feature-gate.js";
32
- import { getCloudOrganizationId, getCloudUserId } from "../config/env.js";
33
- import { getDeviceId } from "../util/device-id.js";
34
- import { getLogger } from "../util/logger.js";
35
- import { APP_VERSION } from "../version.js";
36
- import {
37
- type FlushCheckpointStore,
38
- telemetryDbFlushCheckpointStore,
39
- } from "./flush-checkpoints.js";
40
- import {
41
- DAEMON_TELEMETRY_EVENT_SOURCES,
42
- MONITOR_TELEMETRY_EVENT_SOURCES,
43
- type TelemetryEventSource,
44
- type TelemetryEventSourceBatch,
45
- TOOL_EXECUTED_SOURCE_ID,
46
- watermarkKeysForSource,
47
- } from "./telemetry-event-sources.js";
48
- import {
49
- deleteTelemetryOutboxEventsBefore,
50
- OUTBOX_MAX_ROW_AGE_MS,
51
- } from "./telemetry-events-outbox.js";
52
- import { useReadOnlyMainDbForTelemetry } from "./telemetry-main-db.js";
53
- import { validateWireEvents } from "./telemetry-wire-validation.js";
54
-
55
- const log = getLogger("usage-telemetry");
56
-
57
- // ---------------------------------------------------------------------------
58
- // Constants
59
- // ---------------------------------------------------------------------------
60
-
61
- // Written into the `*_id` watermark checkpoints by the opt-out flush branch.
62
- // Sorts lexicographically above every real row ID (all event stores generate
63
- // lowercase v4 UUIDs), so the compound cursor's same-millisecond arm
64
- // (`createdAt == watermark AND id > afterId`) can never match an opt-out row.
65
- const OPT_OUT_WATERMARK_ID_SENTINEL = "ffffffff-ffff-ffff-ffff-ffffffffffff";
66
- const REPORT_INTERVAL_MS = 5 * 60 * 1000;
67
- const INITIAL_FLUSH_DELAY_MS = 30_000; // Delay first flush to let CES handshake complete
68
- const BATCH_SIZE = 500;
69
- const MAX_CONSECUTIVE_BATCHES = 10;
70
- const TELEMETRY_PATH = "/v1/telemetry/ingest/";
71
-
72
- /**
73
- * Outcome of a {@link UsageTelemetryReporter.flush} call. `flushed: true` means
74
- * at least one batch reached the cloud (2xx). `sent` is the count the daemon
75
- * POSTed; `persisted` is the count the cloud confirmed written; `dropped` is
76
- * `sent - persisted` — folding server-side drops (opt-out, unauthenticated) and
77
- * events silently skipped at ingest validation (unknown/invalid type) into one
78
- * "did not land" number. `flushed: false` carries a kebab-case skip reason.
79
- */
80
- export type TelemetryFlushSummary =
81
- | { flushed: true; sent: number; persisted: number; dropped: number }
82
- | { flushed: false; reason: string };
83
-
84
- interface FlushAccumulator {
85
- sent: number;
86
- persisted: number;
87
- }
88
-
89
- /**
90
- * Read `persisted` from an ingest response body. Falls back to `fallback`
91
- * (the POSTed count — assume all landed) on a malformed body or an older
92
- * platform that omits the field. Never throws.
93
- */
94
- function parsePersistedCount(body: string, fallback: number): number {
95
- try {
96
- const parsed: unknown = JSON.parse(body);
97
- if (parsed && typeof parsed === "object") {
98
- const p = (parsed as { persisted?: unknown }).persisted;
99
- if (typeof p === "number" && Number.isFinite(p) && p >= 0) {
100
- return p;
101
- }
102
- }
103
- } catch {
104
- // Malformed/empty body — assume everything persisted.
105
- }
106
- return fallback;
107
- }
108
-
109
- // ---------------------------------------------------------------------------
110
- // Singleton access
111
- // ---------------------------------------------------------------------------
112
-
113
- let _instance: UsageTelemetryReporter | null = null;
114
-
115
- export function getUsageTelemetryReporter(): UsageTelemetryReporter | null {
116
- return _instance;
117
- }
118
-
119
- function startReporterWithSources(
120
- sources: readonly TelemetryEventSource[],
121
- label: string,
122
- ): void {
123
- if (process.env.CADET_DEV === "1") {
124
- return;
125
- }
126
- if (_instance) {
127
- return;
128
- }
129
- _instance = new UsageTelemetryReporter(sources);
130
- _instance.start();
131
- log.info(`${label} telemetry reporter started`);
132
- }
133
-
134
- /**
135
- * Construct and start the daemon's singleton telemetry reporter, flushing
136
- * the daemon-owned sources (turn events). No-op in dev mode (CADET_DEV=1)
137
- * and idempotent if already started.
138
- *
139
- * Started even when share_analytics consent is opted out: flush() re-checks
140
- * consent each cycle and, when opted out, sends nothing but advances its
141
- * sources' watermarks (including the final flush in stop()). Not gated on DB
142
- * readiness: getDb() can still work when initializeDb() failed mid-migration,
143
- * in which case message writes keep producing rows the opt-out branch must
144
- * keep covered. The reporter is degraded-mode safe — flush() treats DB errors
145
- * as non-fatal.
146
- *
147
- * Also initializes the tool_executed absent-watermark epoch even though that
148
- * source is flushed by the monitor process: the "no flush has ever advanced
149
- * it" guard needs the before-any-tool-runs ordering only daemon startup can
150
- * provide (the monitor boots concurrently with the daemon serving turns).
151
- */
152
- export function startUsageTelemetryReporter(): void {
153
- if (process.env.CADET_DEV === "1") {
154
- return;
155
- }
156
- initToolExecutedWatermarkIfAbsent(telemetryDbFlushCheckpointStore);
157
- startReporterWithSources(DAEMON_TELEMETRY_EVENT_SOURCES, "Daemon");
158
- }
159
-
160
- /**
161
- * Construct and start the resource monitor process's singleton telemetry
162
- * reporter, flushing every non-turn source off the daemon's event loop.
163
- * No-op in dev mode (CADET_DEV=1) and idempotent if already started.
164
- *
165
- * Switches this process's telemetry main-DB reads to the dedicated
166
- * read-only connection first: the monitor observes the daemon's main DB
167
- * (WAL permits cross-process readers) and must never write to it or create
168
- * it. The caller (monitoring/worker.ts) is responsible for the consent
169
- * refresh loop the share_analytics gate reads.
170
- */
171
- export function startMonitorUsageTelemetryReporter(): void {
172
- if (process.env.CADET_DEV === "1") {
173
- return;
174
- }
175
- useReadOnlyMainDbForTelemetry();
176
- startReporterWithSources(MONITOR_TELEMETRY_EVENT_SOURCES, "Monitor");
177
- }
178
-
179
- /**
180
- * Stop the singleton usage telemetry reporter (final flush + timer teardown)
181
- * and clear it. No-op when the reporter was never started (e.g. dev mode).
182
- */
183
- export async function stopUsageTelemetryReporter(): Promise<void> {
184
- if (!_instance) {
185
- return;
186
- }
187
- try {
188
- await _instance.stop();
189
- } finally {
190
- _instance = null;
191
- }
192
- }
193
-
194
- /**
195
- * Initialize the tool_executed flush watermark to "now" when absent.
196
- *
197
- * `tool_invocations` is an always-on audit table that predates the reporter
198
- * shipping its rows: an absent watermark means no flush (opted in or out) has
199
- * ever advanced it, so rows recorded before this build — including any
200
- * opted-out period under older builds that gated the reporter on the
201
- * usage-data opt-out — would otherwise ship retroactively. Runs at daemon
202
- * startup, before any tool can run, so no legitimate row falls behind the
203
- * epoch; the checkpoint persists immediately so a crash can't leave it absent
204
- * and re-initialize later. An EXISTING watermark is never touched: opted-out
205
- * sessions keep it advancing via the opt-out flush branch, and overwriting it
206
- * would drop a legitimate unshipped backlog. The other sources need no init:
207
- * their recording is either consent-gated at write time (opt-out rows never
208
- * exist) or covered by the same watermark discipline from first boot.
209
- *
210
- * Best-effort: DB init failures are tolerated at daemon startup (degraded
211
- * mode), so this never throws — matching flush(), which treats DB errors as
212
- * non-fatal.
213
- */
214
- export function initToolExecutedWatermarkIfAbsent(
215
- checkpoints: FlushCheckpointStore,
216
- ): void {
217
- try {
218
- const key = watermarkKeysForSource(TOOL_EXECUTED_SOURCE_ID).at;
219
- if (checkpoints.get(key) == null) {
220
- checkpoints.set(key, String(Date.now()));
221
- }
222
- } catch (err) {
223
- log.warn(
224
- { err },
225
- "tool_executed watermark init failed — non-fatal; a later run with a working DB re-runs the absent-checkpoint init",
226
- );
227
- }
228
- }
229
-
230
- // ---------------------------------------------------------------------------
231
- // Reporter
232
- // ---------------------------------------------------------------------------
233
-
234
- export class UsageTelemetryReporter {
235
- private initialFlushTimer: ReturnType<typeof setTimeout> | null = null;
236
- private timer: ReturnType<typeof setInterval> | null = null;
237
- private activeFlush: Promise<TelemetryFlushSummary> | null = null;
238
- private readonly sources: readonly TelemetryEventSource[];
239
- private readonly checkpoints: FlushCheckpointStore;
240
-
241
- constructor(
242
- sources: readonly TelemetryEventSource[],
243
- checkpoints: FlushCheckpointStore = telemetryDbFlushCheckpointStore,
244
- ) {
245
- this.sources = sources;
246
- this.checkpoints = checkpoints;
247
- // Backstop for the tool_executed absent-watermark epoch (see
248
- // initToolExecutedWatermarkIfAbsent) — the authoritative init runs at
249
- // daemon startup, which alone guarantees the before-any-tool-runs
250
- // ordering; constructing an instance that flushes the source re-runs the
251
- // guarded init in case that never happened (e.g. a standalone monitor
252
- // started out of band).
253
- if (this.sources.some((s) => s.id === TOOL_EXECUTED_SOURCE_ID)) {
254
- initToolExecutedWatermarkIfAbsent(this.checkpoints);
255
- }
256
- }
257
-
258
- start(): void {
259
- // Delay the first flush to allow the credential infrastructure (CES
260
- // handshake) to complete. Without this delay, CadetCloudClient.create()
261
- // returns null because the credential backend hasn't resolved yet, causing
262
- // the initial flush to be skipped (we send authenticated-only); the
263
- // delay lets credentials resolve so the first flush can actually ship.
264
- this.initialFlushTimer = setTimeout(() => {
265
- this.initialFlushTimer = null;
266
- this.flush().catch((err) => {
267
- log.warn({ err }, "Initial usage telemetry flush failed");
268
- });
269
- }, INITIAL_FLUSH_DELAY_MS);
270
- this.timer = setInterval(() => {
271
- this.flush().catch((err) => {
272
- log.warn({ err }, "Scheduled usage telemetry flush failed");
273
- });
274
- }, REPORT_INTERVAL_MS);
275
- }
276
-
277
- async stop(): Promise<void> {
278
- if (this.initialFlushTimer) {
279
- clearTimeout(this.initialFlushTimer);
280
- this.initialFlushTimer = null;
281
- }
282
- if (this.timer) {
283
- clearInterval(this.timer);
284
- this.timer = null;
285
- }
286
- if (this.activeFlush) {
287
- await this.activeFlush;
288
- }
289
- await this.flush();
290
- }
291
-
292
- async flush(): Promise<TelemetryFlushSummary> {
293
- if (this.activeFlush) {
294
- return this.activeFlush; // overlap guard — share the in-flight result
295
- }
296
- this.activeFlush = this._doFlush();
297
- try {
298
- return await this.activeFlush;
299
- } finally {
300
- this.activeFlush = null;
301
- }
302
- }
303
-
304
- private async _doFlush(
305
- batchCount = 0,
306
- acc: FlushAccumulator = { sent: 0, persisted: 0 },
307
- ): Promise<TelemetryFlushSummary> {
308
- // Once any batch has shipped (acc.sent > 0), a later skip/defer/error is
309
- // just the natural end of the flush — report what landed, not a failure.
310
- const flushed = (): TelemetryFlushSummary => ({
311
- flushed: true,
312
- sent: acc.sent,
313
- persisted: acc.persisted,
314
- dropped: Math.max(0, acc.sent - acc.persisted),
315
- });
316
- const settle = (reason: string): TelemetryFlushSummary =>
317
- acc.sent > 0 ? flushed() : { flushed: false, reason };
318
-
319
- try {
320
- if (batchCount >= MAX_CONSECUTIVE_BATCHES) {
321
- return flushed();
322
- }
323
-
324
- // Age-bound the ack-mode outbox before any skip gate (platform,
325
- // checkpoint store, consent three-way), so the bound holds in every
326
- // state — including the unknown-consent deferral below. Only the
327
- // reporter partition that flushes the outbox (ack-mode sources)
328
- // prunes it.
329
- if (batchCount === 0 && this.sources.some((source) => source.ack)) {
330
- const prunedCount = deleteTelemetryOutboxEventsBefore(
331
- Date.now() - OUTBOX_MAX_ROW_AGE_MS,
332
- );
333
- if (prunedCount > 0) {
334
- log.debug(
335
- { prunedCount },
336
- "Telemetry flush: pruned expired outbox rows",
337
- );
338
- }
339
- }
340
-
341
- // Skip when platform features are disabled (CADET_DISABLE_CLOUD in
342
- // local mode; the flag is ignored when IS_CLOUD is set, matching
343
- // CadetCloudClient.create()). Watermarks are NOT advanced here: this
344
- // is a deployment/local-mode toggle, not a privacy opt-out, so the unsent
345
- // backlog ships once the flag is cleared.
346
- if (!areCloudFeaturesEnabled()) {
347
- return settle("disabled");
348
- }
349
-
350
- // Skip when the flush-checkpoint store (telemetry DB) is unreachable.
351
- // An unreadable watermark must not be mistaken for cursor 0 — that
352
- // would requery and re-ship history from the beginning. Nothing is
353
- // advanced or sent; the cycle retries once the store is back.
354
- if (!this.checkpoints.isAvailable()) {
355
- log.warn(
356
- "Telemetry flush: flush-checkpoint store unavailable — skipping, will retry next cycle",
357
- );
358
- return settle("checkpoint-unavailable");
359
- }
360
-
361
- // Tri-state consent gate: `true` ships, `false` purges, `"unknown"`
362
- // defers.
363
- const shareAnalytics = getRawShareAnalytics();
364
-
365
- // `"unknown"` (boot before the first successful consent refresh, no
366
- // platform session, no resolvable owner) is not an opt-out: nothing is
367
- // sent, acked, discarded, or advanced — the same shape as the
368
- // checkpoint-unavailable skip above. Purging here would silently
369
- // destroy events recorded before the cache warmed up; instead the
370
- // backlog ships (or is purged) on a later cycle once the 5-minute
371
- // refresh loop resolves the cache to a confirmed value. Bounded by
372
- // the age prune above.
373
- if (shareAnalytics === "unknown") {
374
- log.debug(
375
- "Telemetry flush: share_analytics consent unknown — skipping, will retry next cycle",
376
- );
377
- return settle("unknown-consent");
378
- }
379
-
380
- // Respect a confirmed opt-out: if the cloud owner declined
381
- // `share_analytics` consent, skip the flush and advance watermarks so
382
- // events recorded during the opt-out window are never sent
383
- // retroactively. The daemon runs the reporter even when opted out
384
- // specifically so this branch keeps executing — every cycle plus the
385
- // final flush in stop() — which is what lets a later opt-in (runtime or
386
- // via restart) resume from a watermark that already covers the opt-out
387
- // window. One caveat: a RUNTIME false→true flip can still ship up to one
388
- // flush interval (≤5 min) of pre-toggle rows recorded since the last
389
- // opted-out flush;
390
- // the restart path is fully covered by the final flush in stop(). The
391
- // caveat applies to the always-on tables without a write-time opt-out
392
- // gate (llm_usage, turn events) and to tool_invocations rows recorded
393
- // under builds predating the audit listener's write-time gate — new
394
- // opted-out tool_invocations rows persist NULL telemetry columns and
395
- // are unreportable by construction regardless of watermark timing.
396
- if (shareAnalytics === false) {
397
- // Ack-mode sources drop their pending rows outright. Watermark-mode
398
- // sources advance the timestamp watermarks and pin the ID watermarks
399
- // to a sentinel that sorts above any real UUID. The sentinel (rather
400
- // than "") keeps the compound-cursor branch active — a falsy ID would
401
- // downgrade the query to a timestamp-only `gt(createdAt, watermark)`
402
- // — while making its same-millisecond arm unsatisfiable, so a row
403
- // written in the same millisecond as this flush's Date.now() can
404
- // never ship after a later opt-in. The next opted-in flush that
405
- // ships events overwrites the sentinel with a real row ID.
406
- const now = String(Date.now());
407
- for (const source of this.sources) {
408
- if (source.ack) {
409
- source.ack.discardPending();
410
- continue;
411
- }
412
- const keys = watermarkKeysForSource(source.id);
413
- this.checkpoints.set(keys.at, now);
414
- this.checkpoints.set(keys.id, OPT_OUT_WATERMARK_ID_SENTINEL);
415
- }
416
- return settle("opted-out");
417
- }
418
-
419
- // Read each source's watermark (compound cursor: createdAt + id) and
420
- // collect its reportable batch. Absent checkpoints default to cursor 0
421
- // — safe for the consent-gated tables (opted-out rows never exist) and
422
- // for tool_executed, whose absent watermark was initialized at
423
- // construction (see the constructor).
424
- const batches: Array<{
425
- source: TelemetryEventSource;
426
- batch: TelemetryEventSourceBatch;
427
- }> = this.sources.map((source) => {
428
- const keys = watermarkKeysForSource(source.id);
429
- const afterCreatedAt = Number(this.checkpoints.get(keys.at) ?? "0");
430
- const afterId = this.checkpoints.get(keys.id) ?? undefined;
431
- return {
432
- source,
433
- batch: source.collect(afterCreatedAt, afterId, BATCH_SIZE),
434
- };
435
- });
436
-
437
- // Ack-mode batches must carry a row id per event: without them nothing
438
- // can be acknowledged post-2xx, so shipping would re-send the same rows
439
- // on every flush. Exclude such a batch from the POST instead.
440
- for (const entry of batches) {
441
- const { source, batch } = entry;
442
- if (
443
- source.ack &&
444
- batch.events.length > 0 &&
445
- (batch.rowIds ?? []).length !== batch.events.length
446
- ) {
447
- log.warn(
448
- {
449
- sourceId: source.id,
450
- eventCount: batch.events.length,
451
- rowIdCount: batch.rowIds?.length ?? 0,
452
- },
453
- "Telemetry flush: ack-mode batch missing/mismatched rowIds — excluding from POST",
454
- );
455
- entry.batch = {
456
- events: [],
457
- rowIds: [],
458
- lastCursor: null,
459
- fullBatch: false,
460
- };
461
- }
462
- }
463
-
464
- if (batches.every(({ batch }) => batch.events.length === 0)) {
465
- return settle("nothing-pending");
466
- }
467
-
468
- // Resolve auth context. We send authenticated-only: if no platform
469
- // credentials are available yet, skip without advancing watermarks so the
470
- // backlog ships on a later cycle once credentials resolve.
471
- const client = await CadetCloudClient.create();
472
- if (!client) {
473
- log.debug(
474
- {
475
- pendingEventCount: batches.reduce(
476
- (total, { batch }) => total + batch.events.length,
477
- 0,
478
- ),
479
- },
480
- "Telemetry flush: no cloud credentials — skipping, will retry next cycle",
481
- );
482
- return settle("no-credentials");
483
- }
484
- log.debug(
485
- {
486
- counts: Object.fromEntries(
487
- batches.map(({ source, batch }) => [
488
- source.id,
489
- batch.events.length,
490
- ]),
491
- ),
492
- },
493
- "Telemetry flush: resolved auth context",
494
- );
495
-
496
- // Build payload — sources in construction order, each source's events
497
- // in cursor order.
498
- const typedEvents = batches.flatMap(({ batch }) => batch.events);
499
-
500
- // Pre-flush wire validation — observability only: warns about events
501
- // the server would silently drop; the batch is POSTed unchanged.
502
- validateWireEvents(typedEvents, log);
503
-
504
- const organizationId = getCloudOrganizationId() || undefined;
505
- const userId = getCloudUserId() || undefined;
506
- const payload = {
507
- device_id: getDeviceId(),
508
- assistant_version: APP_VERSION,
509
- ...(organizationId ? { organization_id: organizationId } : {}),
510
- ...(userId ? { user_id: userId } : {}),
511
- events: typedEvents,
512
- };
513
-
514
- // Send
515
- const fetchInit: RequestInit = {
516
- method: "POST",
517
- headers: {
518
- "Content-Type": "application/json",
519
- },
520
- body: JSON.stringify(payload),
521
- };
522
-
523
- const resp = await client.fetch(TELEMETRY_PATH, fetchInit);
524
-
525
- if (!resp.ok) {
526
- const body = await resp.text();
527
- log.warn(
528
- { status: resp.status, body },
529
- "Usage telemetry POST failed — will retry next cycle",
530
- );
531
- return settle("post-failed");
532
- }
533
-
534
- // Read the ingest response so `persisted` reflects what actually landed;
535
- // consuming the body also releases the connection.
536
- const body = await resp.text();
537
- acc.sent += typedEvents.length;
538
- acc.persisted += parsePersistedCount(body, typedEvents.length);
539
-
540
- // Acknowledge each source's shipped rows: ack-mode sources delete them
541
- // (never touching flush_checkpoints), watermark-mode sources advance
542
- // their compound cursor to the last reported row.
543
- for (const { source, batch } of batches) {
544
- if (source.ack) {
545
- if (batch.events.length > 0) {
546
- source.ack.acknowledge(batch.rowIds ?? []);
547
- }
548
- } else if (batch.lastCursor) {
549
- const keys = watermarkKeysForSource(source.id);
550
- this.checkpoints.set(keys.at, String(batch.lastCursor.createdAt));
551
- this.checkpoints.set(keys.id, batch.lastCursor.id);
552
- }
553
- }
554
-
555
- // If any source produced a full batch, there may be more — recurse,
556
- // threading the accumulator so counts span every batch in this flush.
557
- if (batches.some(({ batch }) => batch.fullBatch)) {
558
- return this._doFlush(batchCount + 1, acc);
559
- }
560
- return flushed();
561
- } catch (err) {
562
- log.warn({ err }, "Usage telemetry flush error — non-fatal, will retry");
563
- return settle("error");
564
- }
565
- }
566
- }
@@ -1,112 +0,0 @@
1
- /**
2
- * Tests for the direct (unbuffered) watchdog telemetry emit.
3
- *
4
- * Unlike the batched reporter, this POSTs a single event straight to the
5
- * platform ingest. It must honor the `share_analytics` opt-out and the
6
- * platform-features gate, skip cleanly when credentials aren't resolved yet,
7
- * and otherwise send a well-formed single-event payload.
8
- */
9
- import { beforeEach, describe, expect, mock, test } from "bun:test";
10
-
11
- import type { ConsentState } from "../cloud/consent-cache.js";
12
-
13
- let shareAnalytics: ConsentState = true;
14
- mock.module("../cloud/consent-cache.js", () => ({
15
- getRawShareAnalytics: () => shareAnalytics,
16
- }));
17
-
18
- let platformEnabled = true;
19
- mock.module("../cloud/feature-gate.js", () => ({
20
- areCloudFeaturesEnabled: () => platformEnabled,
21
- }));
22
-
23
- const fetchCalls: Array<{ path: string; body: string }> = [];
24
- let clientAvailable = true;
25
- mock.module("../cloud/client.js", () => ({
26
- CadetCloudClient: {
27
- create: async () =>
28
- clientAvailable
29
- ? {
30
- fetch: async (path: string, init: { body: string }) => {
31
- fetchCalls.push({ path, body: init.body });
32
- return new Response("", { status: 200 });
33
- },
34
- }
35
- : null,
36
- },
37
- }));
38
-
39
- import { setCloudOrganizationId, setCloudUserId } from "../config/env.js";
40
- setCloudOrganizationId("org-1");
41
- setCloudUserId("user-1");
42
-
43
- mock.module("../util/device-id.js", () => ({
44
- getDeviceId: () => "device-xyz",
45
- }));
46
- mock.module("../version.js", () => ({ APP_VERSION: "9.9.9" }));
47
-
48
- import { emitWatchdogEventDirect } from "./watchdog-direct-emit.js";
49
-
50
- describe("emitWatchdogEventDirect", () => {
51
- beforeEach(() => {
52
- fetchCalls.length = 0;
53
- shareAnalytics = true;
54
- platformEnabled = true;
55
- clientAvailable = true;
56
- });
57
-
58
- test("POSTs a single well-formed watchdog event when opted in", async () => {
59
- await emitWatchdogEventDirect("sqlite_corrupted", {
60
- database: "main",
61
- error: "database disk image is malformed",
62
- });
63
-
64
- expect(fetchCalls).toHaveLength(1);
65
- expect(fetchCalls[0].path).toBe("/v1/telemetry/ingest/");
66
- const payload = JSON.parse(fetchCalls[0].body) as {
67
- device_id: string;
68
- assistant_version: string;
69
- organization_id?: string;
70
- user_id?: string;
71
- events: Array<Record<string, unknown>>;
72
- };
73
- expect(payload.device_id).toBe("device-xyz");
74
- expect(payload.assistant_version).toBe("9.9.9");
75
- expect(payload.organization_id).toBe("org-1");
76
- expect(payload.user_id).toBe("user-1");
77
- expect(payload.events).toHaveLength(1);
78
- const event = payload.events[0];
79
- expect(event.type).toBe("watchdog");
80
- expect(event.check_name).toBe("sqlite_corrupted");
81
- expect(event.value).toBeNull();
82
- expect(event.daemon_event_id).toBeString();
83
- expect(event.detail).toMatchObject({
84
- database: "main",
85
- error: "database disk image is malformed",
86
- });
87
- });
88
-
89
- test("sends nothing when share_analytics is a confirmed opt-out", async () => {
90
- shareAnalytics = false;
91
- await emitWatchdogEventDirect("sqlite_corrupted", { database: "main" });
92
- expect(fetchCalls).toHaveLength(0);
93
- });
94
-
95
- test("emits while consent is unknown (no buffer to defer into)", async () => {
96
- shareAnalytics = "unknown";
97
- await emitWatchdogEventDirect("sqlite_corrupted", { database: "main" });
98
- expect(fetchCalls).toHaveLength(1);
99
- });
100
-
101
- test("sends nothing when platform features are disabled", async () => {
102
- platformEnabled = false;
103
- await emitWatchdogEventDirect("sqlite_corrupted", { database: "main" });
104
- expect(fetchCalls).toHaveLength(0);
105
- });
106
-
107
- test("sends nothing (no throw) when credentials aren't resolved yet", async () => {
108
- clientAvailable = false;
109
- await emitWatchdogEventDirect("sqlite_corrupted", { database: "main" });
110
- expect(fetchCalls).toHaveLength(0);
111
- });
112
- });