@aitne/daemon 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1386) hide show
  1. package/LICENSE +21 -0
  2. package/dist/adapters/composite-dashboard-stream.d.ts +42 -0
  3. package/dist/adapters/composite-dashboard-stream.d.ts.map +1 -0
  4. package/dist/adapters/composite-dashboard-stream.js +49 -0
  5. package/dist/adapters/composite-dashboard-stream.js.map +1 -0
  6. package/dist/adapters/dashboard-adapter.d.ts +104 -0
  7. package/dist/adapters/dashboard-adapter.d.ts.map +1 -0
  8. package/dist/adapters/dashboard-adapter.js +216 -0
  9. package/dist/adapters/dashboard-adapter.js.map +1 -0
  10. package/dist/adapters/discord.d.ts +77 -0
  11. package/dist/adapters/discord.d.ts.map +1 -0
  12. package/dist/adapters/discord.js +339 -0
  13. package/dist/adapters/discord.js.map +1 -0
  14. package/dist/adapters/docs-qa-adapter.d.ts +123 -0
  15. package/dist/adapters/docs-qa-adapter.d.ts.map +1 -0
  16. package/dist/adapters/docs-qa-adapter.js +218 -0
  17. package/dist/adapters/docs-qa-adapter.js.map +1 -0
  18. package/dist/adapters/message-hub.d.ts +70 -0
  19. package/dist/adapters/message-hub.d.ts.map +1 -0
  20. package/dist/adapters/message-hub.js +359 -0
  21. package/dist/adapters/message-hub.js.map +1 -0
  22. package/dist/adapters/notification-manager.d.ts +99 -0
  23. package/dist/adapters/notification-manager.d.ts.map +1 -0
  24. package/dist/adapters/notification-manager.js +498 -0
  25. package/dist/adapters/notification-manager.js.map +1 -0
  26. package/dist/adapters/outbound-text.d.ts +28 -0
  27. package/dist/adapters/outbound-text.d.ts.map +1 -0
  28. package/dist/adapters/outbound-text.js +58 -0
  29. package/dist/adapters/outbound-text.js.map +1 -0
  30. package/dist/adapters/slack-adapter.d.ts +82 -0
  31. package/dist/adapters/slack-adapter.d.ts.map +1 -0
  32. package/dist/adapters/slack-adapter.js +359 -0
  33. package/dist/adapters/slack-adapter.js.map +1 -0
  34. package/dist/adapters/telegram-adapter.d.ts +107 -0
  35. package/dist/adapters/telegram-adapter.d.ts.map +1 -0
  36. package/dist/adapters/telegram-adapter.js +477 -0
  37. package/dist/adapters/telegram-adapter.js.map +1 -0
  38. package/dist/adapters/types.d.ts +92 -0
  39. package/dist/adapters/types.d.ts.map +1 -0
  40. package/dist/adapters/types.js +2 -0
  41. package/dist/adapters/types.js.map +1 -0
  42. package/dist/adapters/whatsapp-adapter.d.ts +213 -0
  43. package/dist/adapters/whatsapp-adapter.d.ts.map +1 -0
  44. package/dist/adapters/whatsapp-adapter.js +1216 -0
  45. package/dist/adapters/whatsapp-adapter.js.map +1 -0
  46. package/dist/api/chat-binding-query.d.ts +36 -0
  47. package/dist/api/chat-binding-query.d.ts.map +1 -0
  48. package/dist/api/chat-binding-query.js +63 -0
  49. package/dist/api/chat-binding-query.js.map +1 -0
  50. package/dist/api/chat-session-resume.d.ts +12 -0
  51. package/dist/api/chat-session-resume.d.ts.map +1 -0
  52. package/dist/api/chat-session-resume.js +21 -0
  53. package/dist/api/chat-session-resume.js.map +1 -0
  54. package/dist/api/delegated-proxy-helper.d.ts +33 -0
  55. package/dist/api/delegated-proxy-helper.d.ts.map +1 -0
  56. package/dist/api/delegated-proxy-helper.js +54 -0
  57. package/dist/api/delegated-proxy-helper.js.map +1 -0
  58. package/dist/api/directory-picker.d.ts +38 -0
  59. package/dist/api/directory-picker.d.ts.map +1 -0
  60. package/dist/api/directory-picker.js +278 -0
  61. package/dist/api/directory-picker.js.map +1 -0
  62. package/dist/api/env-writer.d.ts +25 -0
  63. package/dist/api/env-writer.d.ts.map +1 -0
  64. package/dist/api/env-writer.js +421 -0
  65. package/dist/api/env-writer.js.map +1 -0
  66. package/dist/api/integration-route-gate.d.ts +60 -0
  67. package/dist/api/integration-route-gate.d.ts.map +1 -0
  68. package/dist/api/integration-route-gate.js +83 -0
  69. package/dist/api/integration-route-gate.js.map +1 -0
  70. package/dist/api/json-body.d.ts +29 -0
  71. package/dist/api/json-body.d.ts.map +1 -0
  72. package/dist/api/json-body.js +87 -0
  73. package/dist/api/json-body.js.map +1 -0
  74. package/dist/api/routes/activity-sources.d.ts +20 -0
  75. package/dist/api/routes/activity-sources.d.ts.map +1 -0
  76. package/dist/api/routes/activity-sources.js +18 -0
  77. package/dist/api/routes/activity-sources.js.map +1 -0
  78. package/dist/api/routes/agent.d.ts +4 -0
  79. package/dist/api/routes/agent.d.ts.map +1 -0
  80. package/dist/api/routes/agent.js +619 -0
  81. package/dist/api/routes/agent.js.map +1 -0
  82. package/dist/api/routes/apple-calendar.d.ts +31 -0
  83. package/dist/api/routes/apple-calendar.d.ts.map +1 -0
  84. package/dist/api/routes/apple-calendar.js +310 -0
  85. package/dist/api/routes/apple-calendar.js.map +1 -0
  86. package/dist/api/routes/attachments.d.ts +36 -0
  87. package/dist/api/routes/attachments.d.ts.map +1 -0
  88. package/dist/api/routes/attachments.js +305 -0
  89. package/dist/api/routes/attachments.js.map +1 -0
  90. package/dist/api/routes/backends.d.ts +4 -0
  91. package/dist/api/routes/backends.d.ts.map +1 -0
  92. package/dist/api/routes/backends.js +1132 -0
  93. package/dist/api/routes/backends.js.map +1 -0
  94. package/dist/api/routes/books.d.ts +63 -0
  95. package/dist/api/routes/books.d.ts.map +1 -0
  96. package/dist/api/routes/books.js +467 -0
  97. package/dist/api/routes/books.js.map +1 -0
  98. package/dist/api/routes/calendar.d.ts +36 -0
  99. package/dist/api/routes/calendar.d.ts.map +1 -0
  100. package/dist/api/routes/calendar.js +351 -0
  101. package/dist/api/routes/calendar.js.map +1 -0
  102. package/dist/api/routes/commands.d.ts +4 -0
  103. package/dist/api/routes/commands.d.ts.map +1 -0
  104. package/dist/api/routes/commands.js +251 -0
  105. package/dist/api/routes/commands.js.map +1 -0
  106. package/dist/api/routes/context.d.ts +57 -0
  107. package/dist/api/routes/context.d.ts.map +1 -0
  108. package/dist/api/routes/context.js +1765 -0
  109. package/dist/api/routes/context.js.map +1 -0
  110. package/dist/api/routes/dashboard.d.ts +29 -0
  111. package/dist/api/routes/dashboard.d.ts.map +1 -0
  112. package/dist/api/routes/dashboard.js +2062 -0
  113. package/dist/api/routes/dashboard.js.map +1 -0
  114. package/dist/api/routes/delegated-sync.d.ts +4 -0
  115. package/dist/api/routes/delegated-sync.d.ts.map +1 -0
  116. package/dist/api/routes/delegated-sync.js +192 -0
  117. package/dist/api/routes/delegated-sync.js.map +1 -0
  118. package/dist/api/routes/delegated.d.ts +42 -0
  119. package/dist/api/routes/delegated.d.ts.map +1 -0
  120. package/dist/api/routes/delegated.js +250 -0
  121. package/dist/api/routes/delegated.js.map +1 -0
  122. package/dist/api/routes/docs.d.ts +34 -0
  123. package/dist/api/routes/docs.d.ts.map +1 -0
  124. package/dist/api/routes/docs.js +580 -0
  125. package/dist/api/routes/docs.js.map +1 -0
  126. package/dist/api/routes/entities.d.ts +9 -0
  127. package/dist/api/routes/entities.d.ts.map +1 -0
  128. package/dist/api/routes/entities.js +176 -0
  129. package/dist/api/routes/entities.js.map +1 -0
  130. package/dist/api/routes/git-accounts.d.ts +23 -0
  131. package/dist/api/routes/git-accounts.d.ts.map +1 -0
  132. package/dist/api/routes/git-accounts.js +227 -0
  133. package/dist/api/routes/git-accounts.js.map +1 -0
  134. package/dist/api/routes/git-templates.d.ts +50 -0
  135. package/dist/api/routes/git-templates.d.ts.map +1 -0
  136. package/dist/api/routes/git-templates.js +276 -0
  137. package/dist/api/routes/git-templates.js.map +1 -0
  138. package/dist/api/routes/git.d.ts +34 -0
  139. package/dist/api/routes/git.d.ts.map +1 -0
  140. package/dist/api/routes/git.js +126 -0
  141. package/dist/api/routes/git.js.map +1 -0
  142. package/dist/api/routes/github.d.ts +34 -0
  143. package/dist/api/routes/github.d.ts.map +1 -0
  144. package/dist/api/routes/github.js +465 -0
  145. package/dist/api/routes/github.js.map +1 -0
  146. package/dist/api/routes/health.d.ts +4 -0
  147. package/dist/api/routes/health.d.ts.map +1 -0
  148. package/dist/api/routes/health.js +257 -0
  149. package/dist/api/routes/health.js.map +1 -0
  150. package/dist/api/routes/integrations-reconcile.d.ts +33 -0
  151. package/dist/api/routes/integrations-reconcile.d.ts.map +1 -0
  152. package/dist/api/routes/integrations-reconcile.js +463 -0
  153. package/dist/api/routes/integrations-reconcile.js.map +1 -0
  154. package/dist/api/routes/integrations.d.ts +19 -0
  155. package/dist/api/routes/integrations.d.ts.map +1 -0
  156. package/dist/api/routes/integrations.js +1384 -0
  157. package/dist/api/routes/integrations.js.map +1 -0
  158. package/dist/api/routes/knowledge.d.ts +4 -0
  159. package/dist/api/routes/knowledge.d.ts.map +1 -0
  160. package/dist/api/routes/knowledge.js +224 -0
  161. package/dist/api/routes/knowledge.js.map +1 -0
  162. package/dist/api/routes/mail.d.ts +39 -0
  163. package/dist/api/routes/mail.d.ts.map +1 -0
  164. package/dist/api/routes/mail.js +1406 -0
  165. package/dist/api/routes/mail.js.map +1 -0
  166. package/dist/api/routes/managed-tasks.d.ts +48 -0
  167. package/dist/api/routes/managed-tasks.d.ts.map +1 -0
  168. package/dist/api/routes/managed-tasks.js +844 -0
  169. package/dist/api/routes/managed-tasks.js.map +1 -0
  170. package/dist/api/routes/mcp.d.ts +50 -0
  171. package/dist/api/routes/mcp.d.ts.map +1 -0
  172. package/dist/api/routes/mcp.js +470 -0
  173. package/dist/api/routes/mcp.js.map +1 -0
  174. package/dist/api/routes/metrics.d.ts +13 -0
  175. package/dist/api/routes/metrics.d.ts.map +1 -0
  176. package/dist/api/routes/metrics.js +117 -0
  177. package/dist/api/routes/metrics.js.map +1 -0
  178. package/dist/api/routes/notion.d.ts +35 -0
  179. package/dist/api/routes/notion.d.ts.map +1 -0
  180. package/dist/api/routes/notion.js +442 -0
  181. package/dist/api/routes/notion.js.map +1 -0
  182. package/dist/api/routes/observations.d.ts +4 -0
  183. package/dist/api/routes/observations.d.ts.map +1 -0
  184. package/dist/api/routes/observations.js +177 -0
  185. package/dist/api/routes/observations.js.map +1 -0
  186. package/dist/api/routes/obsidian.d.ts +16 -0
  187. package/dist/api/routes/obsidian.d.ts.map +1 -0
  188. package/dist/api/routes/obsidian.js +321 -0
  189. package/dist/api/routes/obsidian.js.map +1 -0
  190. package/dist/api/routes/profile-questions.d.ts +17 -0
  191. package/dist/api/routes/profile-questions.d.ts.map +1 -0
  192. package/dist/api/routes/profile-questions.js +115 -0
  193. package/dist/api/routes/profile-questions.js.map +1 -0
  194. package/dist/api/routes/receipts.d.ts +4 -0
  195. package/dist/api/routes/receipts.d.ts.map +1 -0
  196. package/dist/api/routes/receipts.js +155 -0
  197. package/dist/api/routes/receipts.js.map +1 -0
  198. package/dist/api/routes/recurring-schedules.d.ts +4 -0
  199. package/dist/api/routes/recurring-schedules.d.ts.map +1 -0
  200. package/dist/api/routes/recurring-schedules.js +137 -0
  201. package/dist/api/routes/recurring-schedules.js.map +1 -0
  202. package/dist/api/routes/repositories.d.ts +40 -0
  203. package/dist/api/routes/repositories.d.ts.map +1 -0
  204. package/dist/api/routes/repositories.js +857 -0
  205. package/dist/api/routes/repositories.js.map +1 -0
  206. package/dist/api/routes/setup-migrate.d.ts +74 -0
  207. package/dist/api/routes/setup-migrate.d.ts.map +1 -0
  208. package/dist/api/routes/setup-migrate.js +944 -0
  209. package/dist/api/routes/setup-migrate.js.map +1 -0
  210. package/dist/api/routes/setup.d.ts +4 -0
  211. package/dist/api/routes/setup.d.ts.map +1 -0
  212. package/dist/api/routes/setup.js +443 -0
  213. package/dist/api/routes/setup.js.map +1 -0
  214. package/dist/api/routes/skill-curation.d.ts +5 -0
  215. package/dist/api/routes/skill-curation.d.ts.map +1 -0
  216. package/dist/api/routes/skill-curation.js +728 -0
  217. package/dist/api/routes/skill-curation.js.map +1 -0
  218. package/dist/api/routes/skills.d.ts +52 -0
  219. package/dist/api/routes/skills.d.ts.map +1 -0
  220. package/dist/api/routes/skills.js +429 -0
  221. package/dist/api/routes/skills.js.map +1 -0
  222. package/dist/api/routes/sot-bindings.d.ts +20 -0
  223. package/dist/api/routes/sot-bindings.d.ts.map +1 -0
  224. package/dist/api/routes/sot-bindings.js +163 -0
  225. package/dist/api/routes/sot-bindings.js.map +1 -0
  226. package/dist/api/routes/sse.d.ts +86 -0
  227. package/dist/api/routes/sse.d.ts.map +1 -0
  228. package/dist/api/routes/sse.js +378 -0
  229. package/dist/api/routes/sse.js.map +1 -0
  230. package/dist/api/routes/system.d.ts +4 -0
  231. package/dist/api/routes/system.d.ts.map +1 -0
  232. package/dist/api/routes/system.js +207 -0
  233. package/dist/api/routes/system.js.map +1 -0
  234. package/dist/api/routes/task-flows.d.ts +30 -0
  235. package/dist/api/routes/task-flows.d.ts.map +1 -0
  236. package/dist/api/routes/task-flows.js +155 -0
  237. package/dist/api/routes/task-flows.js.map +1 -0
  238. package/dist/api/routes/travel-bookings.d.ts +4 -0
  239. package/dist/api/routes/travel-bookings.d.ts.map +1 -0
  240. package/dist/api/routes/travel-bookings.js +142 -0
  241. package/dist/api/routes/travel-bookings.js.map +1 -0
  242. package/dist/api/routes/travel-time.d.ts +8 -0
  243. package/dist/api/routes/travel-time.d.ts.map +1 -0
  244. package/dist/api/routes/travel-time.js +87 -0
  245. package/dist/api/routes/travel-time.js.map +1 -0
  246. package/dist/api/routes/triggers.d.ts +4 -0
  247. package/dist/api/routes/triggers.d.ts.map +1 -0
  248. package/dist/api/routes/triggers.js +101 -0
  249. package/dist/api/routes/triggers.js.map +1 -0
  250. package/dist/api/routes/voice.d.ts +48 -0
  251. package/dist/api/routes/voice.d.ts.map +1 -0
  252. package/dist/api/routes/voice.js +232 -0
  253. package/dist/api/routes/voice.js.map +1 -0
  254. package/dist/api/server.d.ts +428 -0
  255. package/dist/api/server.d.ts.map +1 -0
  256. package/dist/api/server.js +558 -0
  257. package/dist/api/server.js.map +1 -0
  258. package/dist/config.d.ts +136 -0
  259. package/dist/config.d.ts.map +1 -0
  260. package/dist/config.js +699 -0
  261. package/dist/config.js.map +1 -0
  262. package/dist/core/agent-core.d.ts +517 -0
  263. package/dist/core/agent-core.d.ts.map +1 -0
  264. package/dist/core/agent-core.js +102 -0
  265. package/dist/core/agent-core.js.map +1 -0
  266. package/dist/core/alerts.d.ts +86 -0
  267. package/dist/core/alerts.d.ts.map +1 -0
  268. package/dist/core/alerts.js +304 -0
  269. package/dist/core/alerts.js.map +1 -0
  270. package/dist/core/atomic-write.d.ts +51 -0
  271. package/dist/core/atomic-write.d.ts.map +1 -0
  272. package/dist/core/atomic-write.js +135 -0
  273. package/dist/core/atomic-write.js.map +1 -0
  274. package/dist/core/backends/api-key-probe.d.ts +40 -0
  275. package/dist/core/backends/api-key-probe.d.ts.map +1 -0
  276. package/dist/core/backends/api-key-probe.js +116 -0
  277. package/dist/core/backends/api-key-probe.js.map +1 -0
  278. package/dist/core/backends/auth-health-monitor.d.ts +373 -0
  279. package/dist/core/backends/auth-health-monitor.d.ts.map +1 -0
  280. package/dist/core/backends/auth-health-monitor.js +950 -0
  281. package/dist/core/backends/auth-health-monitor.js.map +1 -0
  282. package/dist/core/backends/auth-recovery.d.ts +263 -0
  283. package/dist/core/backends/auth-recovery.d.ts.map +1 -0
  284. package/dist/core/backends/auth-recovery.js +1086 -0
  285. package/dist/core/backends/auth-recovery.js.map +1 -0
  286. package/dist/core/backends/auth-telemetry.d.ts +81 -0
  287. package/dist/core/backends/auth-telemetry.d.ts.map +1 -0
  288. package/dist/core/backends/auth-telemetry.js +108 -0
  289. package/dist/core/backends/auth-telemetry.js.map +1 -0
  290. package/dist/core/backends/backend-router.d.ts +272 -0
  291. package/dist/core/backends/backend-router.d.ts.map +1 -0
  292. package/dist/core/backends/backend-router.js +759 -0
  293. package/dist/core/backends/backend-router.js.map +1 -0
  294. package/dist/core/backends/claude-code-core.d.ts +299 -0
  295. package/dist/core/backends/claude-code-core.d.ts.map +1 -0
  296. package/dist/core/backends/claude-code-core.js +2541 -0
  297. package/dist/core/backends/claude-code-core.js.map +1 -0
  298. package/dist/core/backends/claude-credentials-store.d.ts +83 -0
  299. package/dist/core/backends/claude-credentials-store.d.ts.map +1 -0
  300. package/dist/core/backends/claude-credentials-store.js +243 -0
  301. package/dist/core/backends/claude-credentials-store.js.map +1 -0
  302. package/dist/core/backends/cli-utils.d.ts +95 -0
  303. package/dist/core/backends/cli-utils.d.ts.map +1 -0
  304. package/dist/core/backends/cli-utils.js +464 -0
  305. package/dist/core/backends/cli-utils.js.map +1 -0
  306. package/dist/core/backends/codex-core.d.ts +127 -0
  307. package/dist/core/backends/codex-core.d.ts.map +1 -0
  308. package/dist/core/backends/codex-core.js +1693 -0
  309. package/dist/core/backends/codex-core.js.map +1 -0
  310. package/dist/core/backends/gemini-cli-core.d.ts +367 -0
  311. package/dist/core/backends/gemini-cli-core.d.ts.map +1 -0
  312. package/dist/core/backends/gemini-cli-core.js +2331 -0
  313. package/dist/core/backends/gemini-cli-core.js.map +1 -0
  314. package/dist/core/backends/idle-watchdog.d.ts +77 -0
  315. package/dist/core/backends/idle-watchdog.d.ts.map +1 -0
  316. package/dist/core/backends/idle-watchdog.js +94 -0
  317. package/dist/core/backends/idle-watchdog.js.map +1 -0
  318. package/dist/core/backends/install-methods.d.ts +93 -0
  319. package/dist/core/backends/install-methods.d.ts.map +1 -0
  320. package/dist/core/backends/install-methods.js +267 -0
  321. package/dist/core/backends/install-methods.js.map +1 -0
  322. package/dist/core/backends/model-registry.d.ts +58 -0
  323. package/dist/core/backends/model-registry.d.ts.map +1 -0
  324. package/dist/core/backends/model-registry.js +539 -0
  325. package/dist/core/backends/model-registry.js.map +1 -0
  326. package/dist/core/backends/plan-presets.d.ts +123 -0
  327. package/dist/core/backends/plan-presets.d.ts.map +1 -0
  328. package/dist/core/backends/plan-presets.js +235 -0
  329. package/dist/core/backends/plan-presets.js.map +1 -0
  330. package/dist/core/backends/price-fetcher.d.ts +48 -0
  331. package/dist/core/backends/price-fetcher.d.ts.map +1 -0
  332. package/dist/core/backends/price-fetcher.js +248 -0
  333. package/dist/core/backends/price-fetcher.js.map +1 -0
  334. package/dist/core/backends/process-config-cascade.d.ts +68 -0
  335. package/dist/core/backends/process-config-cascade.d.ts.map +1 -0
  336. package/dist/core/backends/process-config-cascade.js +173 -0
  337. package/dist/core/backends/process-config-cascade.js.map +1 -0
  338. package/dist/core/backends/prompt-utils.d.ts +6 -0
  339. package/dist/core/backends/prompt-utils.d.ts.map +1 -0
  340. package/dist/core/backends/prompt-utils.js +80 -0
  341. package/dist/core/backends/prompt-utils.js.map +1 -0
  342. package/dist/core/backends/proxy-model-registry.d.ts +110 -0
  343. package/dist/core/backends/proxy-model-registry.d.ts.map +1 -0
  344. package/dist/core/backends/proxy-model-registry.js +195 -0
  345. package/dist/core/backends/proxy-model-registry.js.map +1 -0
  346. package/dist/core/backends/silent-api-error-detector.d.ts +31 -0
  347. package/dist/core/backends/silent-api-error-detector.d.ts.map +1 -0
  348. package/dist/core/backends/silent-api-error-detector.js +44 -0
  349. package/dist/core/backends/silent-api-error-detector.js.map +1 -0
  350. package/dist/core/bang-commands/commands-cost.d.ts +13 -0
  351. package/dist/core/bang-commands/commands-cost.d.ts.map +1 -0
  352. package/dist/core/bang-commands/commands-cost.js +91 -0
  353. package/dist/core/bang-commands/commands-cost.js.map +1 -0
  354. package/dist/core/bang-commands/commands-report.d.ts +18 -0
  355. package/dist/core/bang-commands/commands-report.d.ts.map +1 -0
  356. package/dist/core/bang-commands/commands-report.js +105 -0
  357. package/dist/core/bang-commands/commands-report.js.map +1 -0
  358. package/dist/core/bang-commands/commands-stop-start.d.ts +4 -0
  359. package/dist/core/bang-commands/commands-stop-start.d.ts.map +1 -0
  360. package/dist/core/bang-commands/commands-stop-start.js +88 -0
  361. package/dist/core/bang-commands/commands-stop-start.js.map +1 -0
  362. package/dist/core/bang-commands/format-utils.d.ts +34 -0
  363. package/dist/core/bang-commands/format-utils.d.ts.map +1 -0
  364. package/dist/core/bang-commands/format-utils.js +118 -0
  365. package/dist/core/bang-commands/format-utils.js.map +1 -0
  366. package/dist/core/bang-commands/index.d.ts +20 -0
  367. package/dist/core/bang-commands/index.d.ts.map +1 -0
  368. package/dist/core/bang-commands/index.js +31 -0
  369. package/dist/core/bang-commands/index.js.map +1 -0
  370. package/dist/core/bang-commands/registry.d.ts +72 -0
  371. package/dist/core/bang-commands/registry.d.ts.map +1 -0
  372. package/dist/core/bang-commands/registry.js +174 -0
  373. package/dist/core/bang-commands/registry.js.map +1 -0
  374. package/dist/core/bang-commands/user-commands.d.ts +86 -0
  375. package/dist/core/bang-commands/user-commands.d.ts.map +1 -0
  376. package/dist/core/bang-commands/user-commands.js +212 -0
  377. package/dist/core/bang-commands/user-commands.js.map +1 -0
  378. package/dist/core/channel-timeline.d.ts +28 -0
  379. package/dist/core/channel-timeline.d.ts.map +1 -0
  380. package/dist/core/channel-timeline.js +117 -0
  381. package/dist/core/channel-timeline.js.map +1 -0
  382. package/dist/core/character-block.d.ts +37 -0
  383. package/dist/core/character-block.d.ts.map +1 -0
  384. package/dist/core/character-block.js +162 -0
  385. package/dist/core/character-block.js.map +1 -0
  386. package/dist/core/context/activity-sources.d.ts +37 -0
  387. package/dist/core/context/activity-sources.d.ts.map +1 -0
  388. package/dist/core/context/activity-sources.js +69 -0
  389. package/dist/core/context/activity-sources.js.map +1 -0
  390. package/dist/core/context/activity-view-reconciler.d.ts +110 -0
  391. package/dist/core/context/activity-view-reconciler.d.ts.map +1 -0
  392. package/dist/core/context/activity-view-reconciler.js +252 -0
  393. package/dist/core/context/activity-view-reconciler.js.map +1 -0
  394. package/dist/core/context/activity-view-runner.d.ts +38 -0
  395. package/dist/core/context/activity-view-runner.d.ts.map +1 -0
  396. package/dist/core/context/activity-view-runner.js +402 -0
  397. package/dist/core/context/activity-view-runner.js.map +1 -0
  398. package/dist/core/context/default-schedules-reconciler.d.ts +85 -0
  399. package/dist/core/context/default-schedules-reconciler.d.ts.map +1 -0
  400. package/dist/core/context/default-schedules-reconciler.js +153 -0
  401. package/dist/core/context/default-schedules-reconciler.js.map +1 -0
  402. package/dist/core/context/default-schedules-runner.d.ts +40 -0
  403. package/dist/core/context/default-schedules-runner.d.ts.map +1 -0
  404. package/dist/core/context/default-schedules-runner.js +233 -0
  405. package/dist/core/context/default-schedules-runner.js.map +1 -0
  406. package/dist/core/context/domain-index-reconciler.d.ts +81 -0
  407. package/dist/core/context/domain-index-reconciler.d.ts.map +1 -0
  408. package/dist/core/context/domain-index-reconciler.js +199 -0
  409. package/dist/core/context/domain-index-reconciler.js.map +1 -0
  410. package/dist/core/context/domain-index-runner.d.ts +35 -0
  411. package/dist/core/context/domain-index-runner.d.ts.map +1 -0
  412. package/dist/core/context/domain-index-runner.js +223 -0
  413. package/dist/core/context/domain-index-runner.js.map +1 -0
  414. package/dist/core/context/entity-mirror.d.ts +227 -0
  415. package/dist/core/context/entity-mirror.d.ts.map +1 -0
  416. package/dist/core/context/entity-mirror.js +629 -0
  417. package/dist/core/context/entity-mirror.js.map +1 -0
  418. package/dist/core/context/entity-source-rename.d.ts +61 -0
  419. package/dist/core/context/entity-source-rename.d.ts.map +1 -0
  420. package/dist/core/context/entity-source-rename.js +237 -0
  421. package/dist/core/context/entity-source-rename.js.map +1 -0
  422. package/dist/core/context/index-reconciler.d.ts +61 -0
  423. package/dist/core/context/index-reconciler.d.ts.map +1 -0
  424. package/dist/core/context/index-reconciler.js +329 -0
  425. package/dist/core/context/index-reconciler.js.map +1 -0
  426. package/dist/core/context/policy-index-reconciler.d.ts +102 -0
  427. package/dist/core/context/policy-index-reconciler.d.ts.map +1 -0
  428. package/dist/core/context/policy-index-reconciler.js +202 -0
  429. package/dist/core/context/policy-index-reconciler.js.map +1 -0
  430. package/dist/core/context/policy-index-runner.d.ts +66 -0
  431. package/dist/core/context/policy-index-runner.d.ts.map +1 -0
  432. package/dist/core/context/policy-index-runner.js +406 -0
  433. package/dist/core/context/policy-index-runner.js.map +1 -0
  434. package/dist/core/context/reconciler-runner.d.ts +44 -0
  435. package/dist/core/context/reconciler-runner.d.ts.map +1 -0
  436. package/dist/core/context/reconciler-runner.js +273 -0
  437. package/dist/core/context/reconciler-runner.js.map +1 -0
  438. package/dist/core/context-builder.d.ts +115 -0
  439. package/dist/core/context-builder.d.ts.map +1 -0
  440. package/dist/core/context-builder.js +1148 -0
  441. package/dist/core/context-builder.js.map +1 -0
  442. package/dist/core/context-frontmatter-backfill.d.ts +33 -0
  443. package/dist/core/context-frontmatter-backfill.d.ts.map +1 -0
  444. package/dist/core/context-frontmatter-backfill.js +111 -0
  445. package/dist/core/context-frontmatter-backfill.js.map +1 -0
  446. package/dist/core/context-frontmatter.d.ts +13 -0
  447. package/dist/core/context-frontmatter.d.ts.map +1 -0
  448. package/dist/core/context-frontmatter.js +325 -0
  449. package/dist/core/context-frontmatter.js.map +1 -0
  450. package/dist/core/context-health.d.ts +51 -0
  451. package/dist/core/context-health.d.ts.map +1 -0
  452. package/dist/core/context-health.js +304 -0
  453. package/dist/core/context-health.js.map +1 -0
  454. package/dist/core/context-paths.d.ts +183 -0
  455. package/dist/core/context-paths.d.ts.map +1 -0
  456. package/dist/core/context-paths.js +241 -0
  457. package/dist/core/context-paths.js.map +1 -0
  458. package/dist/core/context-staleness.d.ts +45 -0
  459. package/dist/core/context-staleness.d.ts.map +1 -0
  460. package/dist/core/context-staleness.js +88 -0
  461. package/dist/core/context-staleness.js.map +1 -0
  462. package/dist/core/custom-routine-scheduler.d.ts +151 -0
  463. package/dist/core/custom-routine-scheduler.d.ts.map +1 -0
  464. package/dist/core/custom-routine-scheduler.js +335 -0
  465. package/dist/core/custom-routine-scheduler.js.map +1 -0
  466. package/dist/core/daemon-api-cli.d.ts +33 -0
  467. package/dist/core/daemon-api-cli.d.ts.map +1 -0
  468. package/dist/core/daemon-api-cli.js +614 -0
  469. package/dist/core/daemon-api-cli.js.map +1 -0
  470. package/dist/core/dashboard-session-cleanup.d.ts +39 -0
  471. package/dist/core/dashboard-session-cleanup.d.ts.map +1 -0
  472. package/dist/core/dashboard-session-cleanup.js +108 -0
  473. package/dist/core/dashboard-session-cleanup.js.map +1 -0
  474. package/dist/core/dashboard-session-controls.d.ts +41 -0
  475. package/dist/core/dashboard-session-controls.d.ts.map +1 -0
  476. package/dist/core/dashboard-session-controls.js +154 -0
  477. package/dist/core/dashboard-session-controls.js.map +1 -0
  478. package/dist/core/delegated-connector-health.d.ts +63 -0
  479. package/dist/core/delegated-connector-health.d.ts.map +1 -0
  480. package/dist/core/delegated-connector-health.js +157 -0
  481. package/dist/core/delegated-connector-health.js.map +1 -0
  482. package/dist/core/dispatcher.d.ts +999 -0
  483. package/dist/core/dispatcher.d.ts.map +1 -0
  484. package/dist/core/dispatcher.js +4378 -0
  485. package/dist/core/dispatcher.js.map +1 -0
  486. package/dist/core/dm-freshness-metrics.d.ts +73 -0
  487. package/dist/core/dm-freshness-metrics.d.ts.map +1 -0
  488. package/dist/core/dm-freshness-metrics.js +138 -0
  489. package/dist/core/dm-freshness-metrics.js.map +1 -0
  490. package/dist/core/docs/citation-validator.d.ts +73 -0
  491. package/dist/core/docs/citation-validator.d.ts.map +1 -0
  492. package/dist/core/docs/citation-validator.js +195 -0
  493. package/dist/core/docs/citation-validator.js.map +1 -0
  494. package/dist/core/docs/extract-terms.d.ts +78 -0
  495. package/dist/core/docs/extract-terms.d.ts.map +1 -0
  496. package/dist/core/docs/extract-terms.js +147 -0
  497. package/dist/core/docs/extract-terms.js.map +1 -0
  498. package/dist/core/docs/indexer.d.ts +104 -0
  499. package/dist/core/docs/indexer.d.ts.map +1 -0
  500. package/dist/core/docs/indexer.js +340 -0
  501. package/dist/core/docs/indexer.js.map +1 -0
  502. package/dist/core/drift-effects.d.ts +30 -0
  503. package/dist/core/drift-effects.d.ts.map +1 -0
  504. package/dist/core/drift-effects.js +384 -0
  505. package/dist/core/drift-effects.js.map +1 -0
  506. package/dist/core/event-bus.d.ts +56 -0
  507. package/dist/core/event-bus.d.ts.map +1 -0
  508. package/dist/core/event-bus.js +135 -0
  509. package/dist/core/event-bus.js.map +1 -0
  510. package/dist/core/git-project-docs.d.ts +77 -0
  511. package/dist/core/git-project-docs.d.ts.map +1 -0
  512. package/dist/core/git-project-docs.js +439 -0
  513. package/dist/core/git-project-docs.js.map +1 -0
  514. package/dist/core/health-monitor.d.ts +57 -0
  515. package/dist/core/health-monitor.d.ts.map +1 -0
  516. package/dist/core/health-monitor.js +137 -0
  517. package/dist/core/health-monitor.js.map +1 -0
  518. package/dist/core/heartbeat.d.ts +26 -0
  519. package/dist/core/heartbeat.d.ts.map +1 -0
  520. package/dist/core/heartbeat.js +48 -0
  521. package/dist/core/heartbeat.js.map +1 -0
  522. package/dist/core/integration-health.d.ts +49 -0
  523. package/dist/core/integration-health.d.ts.map +1 -0
  524. package/dist/core/integration-health.js +89 -0
  525. package/dist/core/integration-health.js.map +1 -0
  526. package/dist/core/integration-lifecycle.d.ts +79 -0
  527. package/dist/core/integration-lifecycle.d.ts.map +1 -0
  528. package/dist/core/integration-lifecycle.js +153 -0
  529. package/dist/core/integration-lifecycle.js.map +1 -0
  530. package/dist/core/integration-main-backend.d.ts +36 -0
  531. package/dist/core/integration-main-backend.d.ts.map +1 -0
  532. package/dist/core/integration-main-backend.js +59 -0
  533. package/dist/core/integration-main-backend.js.map +1 -0
  534. package/dist/core/integration-probe.d.ts +98 -0
  535. package/dist/core/integration-probe.d.ts.map +1 -0
  536. package/dist/core/integration-probe.js +152 -0
  537. package/dist/core/integration-probe.js.map +1 -0
  538. package/dist/core/management-md-write-lock.d.ts +68 -0
  539. package/dist/core/management-md-write-lock.d.ts.map +1 -0
  540. package/dist/core/management-md-write-lock.js +93 -0
  541. package/dist/core/management-md-write-lock.js.map +1 -0
  542. package/dist/core/management-md.d.ts +186 -0
  543. package/dist/core/management-md.d.ts.map +1 -0
  544. package/dist/core/management-md.js +652 -0
  545. package/dist/core/management-md.js.map +1 -0
  546. package/dist/core/management-registry.d.ts +245 -0
  547. package/dist/core/management-registry.d.ts.map +1 -0
  548. package/dist/core/management-registry.js +906 -0
  549. package/dist/core/management-registry.js.map +1 -0
  550. package/dist/core/management-telemetry.d.ts +100 -0
  551. package/dist/core/management-telemetry.d.ts.map +1 -0
  552. package/dist/core/management-telemetry.js +156 -0
  553. package/dist/core/management-telemetry.js.map +1 -0
  554. package/dist/core/message-recorder.d.ts +38 -0
  555. package/dist/core/message-recorder.d.ts.map +1 -0
  556. package/dist/core/message-recorder.js +88 -0
  557. package/dist/core/message-recorder.js.map +1 -0
  558. package/dist/core/metrics.d.ts +338 -0
  559. package/dist/core/metrics.d.ts.map +1 -0
  560. package/dist/core/metrics.js +747 -0
  561. package/dist/core/metrics.js.map +1 -0
  562. package/dist/core/migration-backup.d.ts +218 -0
  563. package/dist/core/migration-backup.d.ts.map +1 -0
  564. package/dist/core/migration-backup.js +934 -0
  565. package/dist/core/migration-backup.js.map +1 -0
  566. package/dist/core/overview-write-lock.d.ts +48 -0
  567. package/dist/core/overview-write-lock.d.ts.map +1 -0
  568. package/dist/core/overview-write-lock.js +56 -0
  569. package/dist/core/overview-write-lock.js.map +1 -0
  570. package/dist/core/path-compat.d.ts +22 -0
  571. package/dist/core/path-compat.d.ts.map +1 -0
  572. package/dist/core/path-compat.js +67 -0
  573. package/dist/core/path-compat.js.map +1 -0
  574. package/dist/core/path-rewrite.d.ts +58 -0
  575. package/dist/core/path-rewrite.d.ts.map +1 -0
  576. package/dist/core/path-rewrite.js +141 -0
  577. package/dist/core/path-rewrite.js.map +1 -0
  578. package/dist/core/policy-files.d.ts +108 -0
  579. package/dist/core/policy-files.d.ts.map +1 -0
  580. package/dist/core/policy-files.js +198 -0
  581. package/dist/core/policy-files.js.map +1 -0
  582. package/dist/core/profile-questions/seed.d.ts +44 -0
  583. package/dist/core/profile-questions/seed.d.ts.map +1 -0
  584. package/dist/core/profile-questions/seed.js +173 -0
  585. package/dist/core/profile-questions/seed.js.map +1 -0
  586. package/dist/core/profile-questions/slot-filled.d.ts +51 -0
  587. package/dist/core/profile-questions/slot-filled.d.ts.map +1 -0
  588. package/dist/core/profile-questions/slot-filled.js +118 -0
  589. package/dist/core/profile-questions/slot-filled.js.map +1 -0
  590. package/dist/core/prompts.d.ts +111 -0
  591. package/dist/core/prompts.d.ts.map +1 -0
  592. package/dist/core/prompts.js +267 -0
  593. package/dist/core/prompts.js.map +1 -0
  594. package/dist/core/quiet-hours-sync.d.ts +15 -0
  595. package/dist/core/quiet-hours-sync.d.ts.map +1 -0
  596. package/dist/core/quiet-hours-sync.js +51 -0
  597. package/dist/core/quiet-hours-sync.js.map +1 -0
  598. package/dist/core/read-sensitive-token-manager.d.ts +19 -0
  599. package/dist/core/read-sensitive-token-manager.d.ts.map +1 -0
  600. package/dist/core/read-sensitive-token-manager.js +29 -0
  601. package/dist/core/read-sensitive-token-manager.js.map +1 -0
  602. package/dist/core/recurrence.d.ts +24 -0
  603. package/dist/core/recurrence.d.ts.map +1 -0
  604. package/dist/core/recurrence.js +162 -0
  605. package/dist/core/recurrence.js.map +1 -0
  606. package/dist/core/reinstall.d.ts +107 -0
  607. package/dist/core/reinstall.d.ts.map +1 -0
  608. package/dist/core/reinstall.js +163 -0
  609. package/dist/core/reinstall.js.map +1 -0
  610. package/dist/core/release-assets.d.ts +106 -0
  611. package/dist/core/release-assets.d.ts.map +1 -0
  612. package/dist/core/release-assets.js +434 -0
  613. package/dist/core/release-assets.js.map +1 -0
  614. package/dist/core/repository-management-docs.d.ts +216 -0
  615. package/dist/core/repository-management-docs.d.ts.map +1 -0
  616. package/dist/core/repository-management-docs.js +855 -0
  617. package/dist/core/repository-management-docs.js.map +1 -0
  618. package/dist/core/retention.d.ts +164 -0
  619. package/dist/core/retention.d.ts.map +1 -0
  620. package/dist/core/retention.js +1008 -0
  621. package/dist/core/retention.js.map +1 -0
  622. package/dist/core/review-context.d.ts +48 -0
  623. package/dist/core/review-context.d.ts.map +1 -0
  624. package/dist/core/review-context.js +282 -0
  625. package/dist/core/review-context.js.map +1 -0
  626. package/dist/core/roadmap-horizon.d.ts +48 -0
  627. package/dist/core/roadmap-horizon.d.ts.map +1 -0
  628. package/dist/core/roadmap-horizon.js +213 -0
  629. package/dist/core/roadmap-horizon.js.map +1 -0
  630. package/dist/core/roadmap-ids.d.ts +57 -0
  631. package/dist/core/roadmap-ids.d.ts.map +1 -0
  632. package/dist/core/roadmap-ids.js +118 -0
  633. package/dist/core/roadmap-ids.js.map +1 -0
  634. package/dist/core/roadmap-merge.d.ts +7 -0
  635. package/dist/core/roadmap-merge.d.ts.map +1 -0
  636. package/dist/core/roadmap-merge.js +187 -0
  637. package/dist/core/roadmap-merge.js.map +1 -0
  638. package/dist/core/roadmap-refresh-triggers.d.ts +32 -0
  639. package/dist/core/roadmap-refresh-triggers.d.ts.map +1 -0
  640. package/dist/core/roadmap-refresh-triggers.js +51 -0
  641. package/dist/core/roadmap-refresh-triggers.js.map +1 -0
  642. package/dist/core/roadmap-truncate.d.ts +49 -0
  643. package/dist/core/roadmap-truncate.d.ts.map +1 -0
  644. package/dist/core/roadmap-truncate.js +152 -0
  645. package/dist/core/roadmap-truncate.js.map +1 -0
  646. package/dist/core/roadmap-validate.d.ts +31 -0
  647. package/dist/core/roadmap-validate.d.ts.map +1 -0
  648. package/dist/core/roadmap-validate.js +403 -0
  649. package/dist/core/roadmap-validate.js.map +1 -0
  650. package/dist/core/roadmap-write-lock.d.ts +53 -0
  651. package/dist/core/roadmap-write-lock.d.ts.map +1 -0
  652. package/dist/core/roadmap-write-lock.js +59 -0
  653. package/dist/core/roadmap-write-lock.js.map +1 -0
  654. package/dist/core/schedule-insert-helper.d.ts +46 -0
  655. package/dist/core/schedule-insert-helper.d.ts.map +1 -0
  656. package/dist/core/schedule-insert-helper.js +52 -0
  657. package/dist/core/schedule-insert-helper.js.map +1 -0
  658. package/dist/core/schedule-maintenance.d.ts +22 -0
  659. package/dist/core/schedule-maintenance.d.ts.map +1 -0
  660. package/dist/core/schedule-maintenance.js +57 -0
  661. package/dist/core/schedule-maintenance.js.map +1 -0
  662. package/dist/core/scheduler.d.ts +208 -0
  663. package/dist/core/scheduler.d.ts.map +1 -0
  664. package/dist/core/scheduler.js +896 -0
  665. package/dist/core/scheduler.js.map +1 -0
  666. package/dist/core/semaphore.d.ts +13 -0
  667. package/dist/core/semaphore.d.ts.map +1 -0
  668. package/dist/core/semaphore.js +31 -0
  669. package/dist/core/semaphore.js.map +1 -0
  670. package/dist/core/session-gate.d.ts +37 -0
  671. package/dist/core/session-gate.d.ts.map +1 -0
  672. package/dist/core/session-gate.js +69 -0
  673. package/dist/core/session-gate.js.map +1 -0
  674. package/dist/core/session-manager.d.ts +252 -0
  675. package/dist/core/session-manager.d.ts.map +1 -0
  676. package/dist/core/session-manager.js +716 -0
  677. package/dist/core/session-manager.js.map +1 -0
  678. package/dist/core/signal-detector.d.ts +97 -0
  679. package/dist/core/signal-detector.d.ts.map +1 -0
  680. package/dist/core/signal-detector.js +215 -0
  681. package/dist/core/signal-detector.js.map +1 -0
  682. package/dist/core/skeleton.d.ts +83 -0
  683. package/dist/core/skeleton.d.ts.map +1 -0
  684. package/dist/core/skeleton.js +255 -0
  685. package/dist/core/skeleton.js.map +1 -0
  686. package/dist/core/skill-curation/apply-proposal.d.ts +71 -0
  687. package/dist/core/skill-curation/apply-proposal.d.ts.map +1 -0
  688. package/dist/core/skill-curation/apply-proposal.js +175 -0
  689. package/dist/core/skill-curation/apply-proposal.js.map +1 -0
  690. package/dist/core/skill-curation/auto-revert.d.ts +43 -0
  691. package/dist/core/skill-curation/auto-revert.d.ts.map +1 -0
  692. package/dist/core/skill-curation/auto-revert.js +155 -0
  693. package/dist/core/skill-curation/auto-revert.js.map +1 -0
  694. package/dist/core/skill-curation/classify-diff.d.ts +27 -0
  695. package/dist/core/skill-curation/classify-diff.d.ts.map +1 -0
  696. package/dist/core/skill-curation/classify-diff.js +0 -0
  697. package/dist/core/skill-curation/classify-diff.js.map +1 -0
  698. package/dist/core/skill-curation/declarations.d.ts +32 -0
  699. package/dist/core/skill-curation/declarations.d.ts.map +1 -0
  700. package/dist/core/skill-curation/declarations.js +171 -0
  701. package/dist/core/skill-curation/declarations.js.map +1 -0
  702. package/dist/core/skill-curation/knowledge-map.d.ts +26 -0
  703. package/dist/core/skill-curation/knowledge-map.d.ts.map +1 -0
  704. package/dist/core/skill-curation/knowledge-map.js +154 -0
  705. package/dist/core/skill-curation/knowledge-map.js.map +1 -0
  706. package/dist/core/skill-curation/orphan-overlay.d.ts +35 -0
  707. package/dist/core/skill-curation/orphan-overlay.d.ts.map +1 -0
  708. package/dist/core/skill-curation/orphan-overlay.js +167 -0
  709. package/dist/core/skill-curation/orphan-overlay.js.map +1 -0
  710. package/dist/core/skill-curation/overlay-store.d.ts +41 -0
  711. package/dist/core/skill-curation/overlay-store.d.ts.map +1 -0
  712. package/dist/core/skill-curation/overlay-store.js +143 -0
  713. package/dist/core/skill-curation/overlay-store.js.map +1 -0
  714. package/dist/core/skill-curation/render/convention-notes.d.ts +4 -0
  715. package/dist/core/skill-curation/render/convention-notes.d.ts.map +1 -0
  716. package/dist/core/skill-curation/render/convention-notes.js +13 -0
  717. package/dist/core/skill-curation/render/convention-notes.js.map +1 -0
  718. package/dist/core/skill-curation/render/cross-references.d.ts +4 -0
  719. package/dist/core/skill-curation/render/cross-references.d.ts.map +1 -0
  720. package/dist/core/skill-curation/render/cross-references.js +10 -0
  721. package/dist/core/skill-curation/render/cross-references.js.map +1 -0
  722. package/dist/core/skill-curation/render/frontmatter-schema.d.ts +4 -0
  723. package/dist/core/skill-curation/render/frontmatter-schema.d.ts.map +1 -0
  724. package/dist/core/skill-curation/render/frontmatter-schema.js +25 -0
  725. package/dist/core/skill-curation/render/frontmatter-schema.js.map +1 -0
  726. package/dist/core/skill-curation/render/index.d.ts +5 -0
  727. package/dist/core/skill-curation/render/index.d.ts.map +1 -0
  728. package/dist/core/skill-curation/render/index.js +42 -0
  729. package/dist/core/skill-curation/render/index.js.map +1 -0
  730. package/dist/core/skill-curation/render/knowledge-layout.d.ts +4 -0
  731. package/dist/core/skill-curation/render/knowledge-layout.d.ts.map +1 -0
  732. package/dist/core/skill-curation/render/knowledge-layout.js +36 -0
  733. package/dist/core/skill-curation/render/knowledge-layout.js.map +1 -0
  734. package/dist/core/skill-curation/render/routing-table.d.ts +4 -0
  735. package/dist/core/skill-curation/render/routing-table.d.ts.map +1 -0
  736. package/dist/core/skill-curation/render/routing-table.js +37 -0
  737. package/dist/core/skill-curation/render/routing-table.js.map +1 -0
  738. package/dist/core/skill-curation/render/search-recipes.d.ts +4 -0
  739. package/dist/core/skill-curation/render/search-recipes.d.ts.map +1 -0
  740. package/dist/core/skill-curation/render/search-recipes.js +39 -0
  741. package/dist/core/skill-curation/render/search-recipes.js.map +1 -0
  742. package/dist/core/skill-curation/run-token.d.ts +27 -0
  743. package/dist/core/skill-curation/run-token.d.ts.map +1 -0
  744. package/dist/core/skill-curation/run-token.js +81 -0
  745. package/dist/core/skill-curation/run-token.js.map +1 -0
  746. package/dist/core/skill-curation/signals.d.ts +49 -0
  747. package/dist/core/skill-curation/signals.d.ts.map +1 -0
  748. package/dist/core/skill-curation/signals.js +149 -0
  749. package/dist/core/skill-curation/signals.js.map +1 -0
  750. package/dist/core/skill-curation/smoke-test.d.ts +39 -0
  751. package/dist/core/skill-curation/smoke-test.d.ts.map +1 -0
  752. package/dist/core/skill-curation/smoke-test.js +313 -0
  753. package/dist/core/skill-curation/smoke-test.js.map +1 -0
  754. package/dist/core/skill-curation/splicer.d.ts +16 -0
  755. package/dist/core/skill-curation/splicer.d.ts.map +1 -0
  756. package/dist/core/skill-curation/splicer.js +78 -0
  757. package/dist/core/skill-curation/splicer.js.map +1 -0
  758. package/dist/core/skill-curation/workdir.d.ts +40 -0
  759. package/dist/core/skill-curation/workdir.d.ts.map +1 -0
  760. package/dist/core/skill-curation/workdir.js +242 -0
  761. package/dist/core/skill-curation/workdir.js.map +1 -0
  762. package/dist/core/skills-compiler.d.ts +391 -0
  763. package/dist/core/skills-compiler.d.ts.map +1 -0
  764. package/dist/core/skills-compiler.js +1271 -0
  765. package/dist/core/skills-compiler.js.map +1 -0
  766. package/dist/core/skills-manifest.d.ts +8 -0
  767. package/dist/core/skills-manifest.d.ts.map +1 -0
  768. package/dist/core/skills-manifest.js +408 -0
  769. package/dist/core/skills-manifest.js.map +1 -0
  770. package/dist/core/system-reset.d.ts +268 -0
  771. package/dist/core/system-reset.d.ts.map +1 -0
  772. package/dist/core/system-reset.js +816 -0
  773. package/dist/core/system-reset.js.map +1 -0
  774. package/dist/core/template-store.d.ts +170 -0
  775. package/dist/core/template-store.d.ts.map +1 -0
  776. package/dist/core/template-store.js +388 -0
  777. package/dist/core/template-store.js.map +1 -0
  778. package/dist/core/template-versions.d.ts +95 -0
  779. package/dist/core/template-versions.d.ts.map +1 -0
  780. package/dist/core/template-versions.js +175 -0
  781. package/dist/core/template-versions.js.map +1 -0
  782. package/dist/core/today-agent-plan.d.ts +33 -0
  783. package/dist/core/today-agent-plan.d.ts.map +1 -0
  784. package/dist/core/today-agent-plan.js +120 -0
  785. package/dist/core/today-agent-plan.js.map +1 -0
  786. package/dist/core/today-direct-writer.d.ts +62 -0
  787. package/dist/core/today-direct-writer.d.ts.map +1 -0
  788. package/dist/core/today-direct-writer.js +132 -0
  789. package/dist/core/today-direct-writer.js.map +1 -0
  790. package/dist/core/today-write-lock.d.ts +89 -0
  791. package/dist/core/today-write-lock.d.ts.map +1 -0
  792. package/dist/core/today-write-lock.js +154 -0
  793. package/dist/core/today-write-lock.js.map +1 -0
  794. package/dist/core/trigger-dispatch.d.ts +31 -0
  795. package/dist/core/trigger-dispatch.d.ts.map +1 -0
  796. package/dist/core/trigger-dispatch.js +100 -0
  797. package/dist/core/trigger-dispatch.js.map +1 -0
  798. package/dist/core/trigger-evaluator.d.ts +59 -0
  799. package/dist/core/trigger-evaluator.d.ts.map +1 -0
  800. package/dist/core/trigger-evaluator.js +243 -0
  801. package/dist/core/trigger-evaluator.js.map +1 -0
  802. package/dist/core/workdir.d.ts +241 -0
  803. package/dist/core/workdir.d.ts.map +1 -0
  804. package/dist/core/workdir.js +565 -0
  805. package/dist/core/workdir.js.map +1 -0
  806. package/dist/db/automation-triggers.d.ts +90 -0
  807. package/dist/db/automation-triggers.d.ts.map +1 -0
  808. package/dist/db/automation-triggers.js +199 -0
  809. package/dist/db/automation-triggers.js.map +1 -0
  810. package/dist/db/client.d.ts +6 -0
  811. package/dist/db/client.d.ts.map +1 -0
  812. package/dist/db/client.js +47 -0
  813. package/dist/db/client.js.map +1 -0
  814. package/dist/db/entities-store.d.ts +92 -0
  815. package/dist/db/entities-store.d.ts.map +1 -0
  816. package/dist/db/entities-store.js +180 -0
  817. package/dist/db/entities-store.js.map +1 -0
  818. package/dist/db/hourly-check-signals.d.ts +78 -0
  819. package/dist/db/hourly-check-signals.d.ts.map +1 -0
  820. package/dist/db/hourly-check-signals.js +289 -0
  821. package/dist/db/hourly-check-signals.js.map +1 -0
  822. package/dist/db/integration-probe-store.d.ts +27 -0
  823. package/dist/db/integration-probe-store.d.ts.map +1 -0
  824. package/dist/db/integration-probe-store.js +75 -0
  825. package/dist/db/integration-probe-store.js.map +1 -0
  826. package/dist/db/integrations-store.d.ts +19 -0
  827. package/dist/db/integrations-store.d.ts.map +1 -0
  828. package/dist/db/integrations-store.js +85 -0
  829. package/dist/db/integrations-store.js.map +1 -0
  830. package/dist/db/managed-tasks-store.d.ts +130 -0
  831. package/dist/db/managed-tasks-store.d.ts.map +1 -0
  832. package/dist/db/managed-tasks-store.js +238 -0
  833. package/dist/db/managed-tasks-store.js.map +1 -0
  834. package/dist/db/management-parse-failures-store.d.ts +45 -0
  835. package/dist/db/management-parse-failures-store.d.ts.map +1 -0
  836. package/dist/db/management-parse-failures-store.js +36 -0
  837. package/dist/db/management-parse-failures-store.js.map +1 -0
  838. package/dist/db/observations.d.ts +145 -0
  839. package/dist/db/observations.d.ts.map +1 -0
  840. package/dist/db/observations.js +287 -0
  841. package/dist/db/observations.js.map +1 -0
  842. package/dist/db/recurring-schedules.d.ts +70 -0
  843. package/dist/db/recurring-schedules.d.ts.map +1 -0
  844. package/dist/db/recurring-schedules.js +213 -0
  845. package/dist/db/recurring-schedules.js.map +1 -0
  846. package/dist/db/repositories-store.d.ts +296 -0
  847. package/dist/db/repositories-store.d.ts.map +1 -0
  848. package/dist/db/repositories-store.js +754 -0
  849. package/dist/db/repositories-store.js.map +1 -0
  850. package/dist/db/runtime-state.d.ts +61 -0
  851. package/dist/db/runtime-state.d.ts.map +1 -0
  852. package/dist/db/runtime-state.js +104 -0
  853. package/dist/db/runtime-state.js.map +1 -0
  854. package/dist/db/schema.d.ts +4 -0
  855. package/dist/db/schema.d.ts.map +1 -0
  856. package/dist/db/schema.js +1338 -0
  857. package/dist/db/schema.js.map +1 -0
  858. package/dist/db/sot-bindings-store.d.ts +41 -0
  859. package/dist/db/sot-bindings-store.d.ts.map +1 -0
  860. package/dist/db/sot-bindings-store.js +64 -0
  861. package/dist/db/sot-bindings-store.js.map +1 -0
  862. package/dist/db/test-schemas.d.ts +23 -0
  863. package/dist/db/test-schemas.d.ts.map +1 -0
  864. package/dist/db/test-schemas.js +111 -0
  865. package/dist/db/test-schemas.js.map +1 -0
  866. package/dist/db/voice-transcripts-store.d.ts +28 -0
  867. package/dist/db/voice-transcripts-store.d.ts.map +1 -0
  868. package/dist/db/voice-transcripts-store.js +43 -0
  869. package/dist/db/voice-transcripts-store.js.map +1 -0
  870. package/dist/index.d.ts +2 -0
  871. package/dist/index.d.ts.map +1 -0
  872. package/dist/index.js +2913 -0
  873. package/dist/index.js.map +1 -0
  874. package/dist/init.d.ts +7 -0
  875. package/dist/init.d.ts.map +1 -0
  876. package/dist/init.js +32 -0
  877. package/dist/init.js.map +1 -0
  878. package/dist/log-buffer.d.ts +71 -0
  879. package/dist/log-buffer.d.ts.map +1 -0
  880. package/dist/log-buffer.js +201 -0
  881. package/dist/log-buffer.js.map +1 -0
  882. package/dist/logging.d.ts +5 -0
  883. package/dist/logging.d.ts.map +1 -0
  884. package/dist/logging.js +130 -0
  885. package/dist/logging.js.map +1 -0
  886. package/dist/management-rules.d.ts +2 -0
  887. package/dist/management-rules.d.ts.map +1 -0
  888. package/dist/management-rules.js +62 -0
  889. package/dist/management-rules.js.map +1 -0
  890. package/dist/messaging/constants.d.ts +33 -0
  891. package/dist/messaging/constants.d.ts.map +1 -0
  892. package/dist/messaging/constants.js +52 -0
  893. package/dist/messaging/constants.js.map +1 -0
  894. package/dist/messaging/magic-phrase.d.ts +16 -0
  895. package/dist/messaging/magic-phrase.d.ts.map +1 -0
  896. package/dist/messaging/magic-phrase.js +103 -0
  897. package/dist/messaging/magic-phrase.js.map +1 -0
  898. package/dist/messaging/owner-channels.d.ts +20 -0
  899. package/dist/messaging/owner-channels.d.ts.map +1 -0
  900. package/dist/messaging/owner-channels.js +41 -0
  901. package/dist/messaging/owner-channels.js.map +1 -0
  902. package/dist/observers/calendar-poller.d.ts +51 -0
  903. package/dist/observers/calendar-poller.d.ts.map +1 -0
  904. package/dist/observers/calendar-poller.js +128 -0
  905. package/dist/observers/calendar-poller.js.map +1 -0
  906. package/dist/observers/context-index-reconciler-observer.d.ts +72 -0
  907. package/dist/observers/context-index-reconciler-observer.d.ts.map +1 -0
  908. package/dist/observers/context-index-reconciler-observer.js +253 -0
  909. package/dist/observers/context-index-reconciler-observer.js.map +1 -0
  910. package/dist/observers/delegated-probe-observer.d.ts +83 -0
  911. package/dist/observers/delegated-probe-observer.d.ts.map +1 -0
  912. package/dist/observers/delegated-probe-observer.js +237 -0
  913. package/dist/observers/delegated-probe-observer.js.map +1 -0
  914. package/dist/observers/delegated-sync-worker.d.ts +375 -0
  915. package/dist/observers/delegated-sync-worker.d.ts.map +1 -0
  916. package/dist/observers/delegated-sync-worker.js +1087 -0
  917. package/dist/observers/delegated-sync-worker.js.map +1 -0
  918. package/dist/observers/entity-mirror-observer.d.ts +55 -0
  919. package/dist/observers/entity-mirror-observer.d.ts.map +1 -0
  920. package/dist/observers/entity-mirror-observer.js +73 -0
  921. package/dist/observers/entity-mirror-observer.js.map +1 -0
  922. package/dist/observers/git-delegated-cron.d.ts +41 -0
  923. package/dist/observers/git-delegated-cron.d.ts.map +1 -0
  924. package/dist/observers/git-delegated-cron.js +159 -0
  925. package/dist/observers/git-delegated-cron.js.map +1 -0
  926. package/dist/observers/git-event-classifier.d.ts +52 -0
  927. package/dist/observers/git-event-classifier.d.ts.map +1 -0
  928. package/dist/observers/git-event-classifier.js +70 -0
  929. package/dist/observers/git-event-classifier.js.map +1 -0
  930. package/dist/observers/git-watcher.d.ts +162 -0
  931. package/dist/observers/git-watcher.d.ts.map +1 -0
  932. package/dist/observers/git-watcher.js +768 -0
  933. package/dist/observers/git-watcher.js.map +1 -0
  934. package/dist/observers/github-poller-classifier.d.ts +101 -0
  935. package/dist/observers/github-poller-classifier.d.ts.map +1 -0
  936. package/dist/observers/github-poller-classifier.js +199 -0
  937. package/dist/observers/github-poller-classifier.js.map +1 -0
  938. package/dist/observers/github-poller.d.ts +291 -0
  939. package/dist/observers/github-poller.d.ts.map +1 -0
  940. package/dist/observers/github-poller.js +609 -0
  941. package/dist/observers/github-poller.js.map +1 -0
  942. package/dist/observers/imminent-event-scheduler.d.ts +34 -0
  943. package/dist/observers/imminent-event-scheduler.d.ts.map +1 -0
  944. package/dist/observers/imminent-event-scheduler.js +125 -0
  945. package/dist/observers/imminent-event-scheduler.js.map +1 -0
  946. package/dist/observers/mail-poller.d.ts +133 -0
  947. package/dist/observers/mail-poller.d.ts.map +1 -0
  948. package/dist/observers/mail-poller.js +563 -0
  949. package/dist/observers/mail-poller.js.map +1 -0
  950. package/dist/observers/mail-reconciliation.d.ts +87 -0
  951. package/dist/observers/mail-reconciliation.d.ts.map +1 -0
  952. package/dist/observers/mail-reconciliation.js +241 -0
  953. package/dist/observers/mail-reconciliation.js.map +1 -0
  954. package/dist/observers/manager.d.ts +67 -0
  955. package/dist/observers/manager.d.ts.map +1 -0
  956. package/dist/observers/manager.js +136 -0
  957. package/dist/observers/manager.js.map +1 -0
  958. package/dist/observers/notion-poller.d.ts +43 -0
  959. package/dist/observers/notion-poller.d.ts.map +1 -0
  960. package/dist/observers/notion-poller.js +184 -0
  961. package/dist/observers/notion-poller.js.map +1 -0
  962. package/dist/observers/observation-summarizer/index.d.ts +13 -0
  963. package/dist/observers/observation-summarizer/index.d.ts.map +1 -0
  964. package/dist/observers/observation-summarizer/index.js +13 -0
  965. package/dist/observers/observation-summarizer/index.js.map +1 -0
  966. package/dist/observers/observation-summarizer/pre-filter.d.ts +62 -0
  967. package/dist/observers/observation-summarizer/pre-filter.d.ts.map +1 -0
  968. package/dist/observers/observation-summarizer/pre-filter.js +189 -0
  969. package/dist/observers/observation-summarizer/pre-filter.js.map +1 -0
  970. package/dist/observers/observation-summarizer/response-parser.d.ts +30 -0
  971. package/dist/observers/observation-summarizer/response-parser.d.ts.map +1 -0
  972. package/dist/observers/observation-summarizer/response-parser.js +106 -0
  973. package/dist/observers/observation-summarizer/response-parser.js.map +1 -0
  974. package/dist/observers/observation-summarizer/summarizer-client.d.ts +83 -0
  975. package/dist/observers/observation-summarizer/summarizer-client.d.ts.map +1 -0
  976. package/dist/observers/observation-summarizer/summarizer-client.js +185 -0
  977. package/dist/observers/observation-summarizer/summarizer-client.js.map +1 -0
  978. package/dist/observers/observation-summarizer/summarizer-prompts.d.ts +51 -0
  979. package/dist/observers/observation-summarizer/summarizer-prompts.d.ts.map +1 -0
  980. package/dist/observers/observation-summarizer/summarizer-prompts.js +286 -0
  981. package/dist/observers/observation-summarizer/summarizer-prompts.js.map +1 -0
  982. package/dist/observers/observation-summarizer/worker.d.ts +106 -0
  983. package/dist/observers/observation-summarizer/worker.d.ts.map +1 -0
  984. package/dist/observers/observation-summarizer/worker.js +311 -0
  985. package/dist/observers/observation-summarizer/worker.js.map +1 -0
  986. package/dist/observers/obsidian-watcher.d.ts +90 -0
  987. package/dist/observers/obsidian-watcher.d.ts.map +1 -0
  988. package/dist/observers/obsidian-watcher.js +166 -0
  989. package/dist/observers/obsidian-watcher.js.map +1 -0
  990. package/dist/observers/primary-vault-watcher.d.ts +73 -0
  991. package/dist/observers/primary-vault-watcher.d.ts.map +1 -0
  992. package/dist/observers/primary-vault-watcher.js +115 -0
  993. package/dist/observers/primary-vault-watcher.js.map +1 -0
  994. package/dist/observers/repository-management-cron.d.ts +70 -0
  995. package/dist/observers/repository-management-cron.d.ts.map +1 -0
  996. package/dist/observers/repository-management-cron.js +166 -0
  997. package/dist/observers/repository-management-cron.js.map +1 -0
  998. package/dist/observers/skill-curation-walker.d.ts +33 -0
  999. package/dist/observers/skill-curation-walker.d.ts.map +1 -0
  1000. package/dist/observers/skill-curation-walker.js +216 -0
  1001. package/dist/observers/skill-curation-walker.js.map +1 -0
  1002. package/dist/safety/absolute-block-audit.d.ts +22 -0
  1003. package/dist/safety/absolute-block-audit.d.ts.map +1 -0
  1004. package/dist/safety/absolute-block-audit.js +32 -0
  1005. package/dist/safety/absolute-block-audit.js.map +1 -0
  1006. package/dist/safety/agent-write-tracker.d.ts +42 -0
  1007. package/dist/safety/agent-write-tracker.d.ts.map +1 -0
  1008. package/dist/safety/agent-write-tracker.js +82 -0
  1009. package/dist/safety/agent-write-tracker.js.map +1 -0
  1010. package/dist/safety/always-disallowed.d.ts +66 -0
  1011. package/dist/safety/always-disallowed.d.ts.map +1 -0
  1012. package/dist/safety/always-disallowed.js +347 -0
  1013. package/dist/safety/always-disallowed.js.map +1 -0
  1014. package/dist/safety/audit.d.ts +118 -0
  1015. package/dist/safety/audit.d.ts.map +1 -0
  1016. package/dist/safety/audit.js +324 -0
  1017. package/dist/safety/audit.js.map +1 -0
  1018. package/dist/safety/integration-write-tracker.d.ts +58 -0
  1019. package/dist/safety/integration-write-tracker.d.ts.map +1 -0
  1020. package/dist/safety/integration-write-tracker.js +41 -0
  1021. package/dist/safety/integration-write-tracker.js.map +1 -0
  1022. package/dist/safety/risk-classifier.d.ts +65 -0
  1023. package/dist/safety/risk-classifier.d.ts.map +1 -0
  1024. package/dist/safety/risk-classifier.js +763 -0
  1025. package/dist/safety/risk-classifier.js.map +1 -0
  1026. package/dist/scheduler/hourly-check-gate.d.ts +73 -0
  1027. package/dist/scheduler/hourly-check-gate.d.ts.map +1 -0
  1028. package/dist/scheduler/hourly-check-gate.js +128 -0
  1029. package/dist/scheduler/hourly-check-gate.js.map +1 -0
  1030. package/dist/secrets/backend-api-key-env.d.ts +104 -0
  1031. package/dist/secrets/backend-api-key-env.d.ts.map +1 -0
  1032. package/dist/secrets/backend-api-key-env.js +197 -0
  1033. package/dist/secrets/backend-api-key-env.js.map +1 -0
  1034. package/dist/secrets/codex-home-materializer.d.ts +35 -0
  1035. package/dist/secrets/codex-home-materializer.d.ts.map +1 -0
  1036. package/dist/secrets/codex-home-materializer.js +76 -0
  1037. package/dist/secrets/codex-home-materializer.js.map +1 -0
  1038. package/dist/secrets/encrypted-blob-store.d.ts +20 -0
  1039. package/dist/secrets/encrypted-blob-store.d.ts.map +1 -0
  1040. package/dist/secrets/encrypted-blob-store.js +80 -0
  1041. package/dist/secrets/encrypted-blob-store.js.map +1 -0
  1042. package/dist/secrets/platform-secret-store.d.ts +17 -0
  1043. package/dist/secrets/platform-secret-store.d.ts.map +1 -0
  1044. package/dist/secrets/platform-secret-store.js +37 -0
  1045. package/dist/secrets/platform-secret-store.js.map +1 -0
  1046. package/dist/secrets/redaction.d.ts +2 -0
  1047. package/dist/secrets/redaction.d.ts.map +1 -0
  1048. package/dist/secrets/redaction.js +2 -0
  1049. package/dist/secrets/redaction.js.map +1 -0
  1050. package/dist/secrets/secret-broker.d.ts +61 -0
  1051. package/dist/secrets/secret-broker.d.ts.map +1 -0
  1052. package/dist/secrets/secret-broker.js +160 -0
  1053. package/dist/secrets/secret-broker.js.map +1 -0
  1054. package/dist/secrets/secret-names.d.ts +34 -0
  1055. package/dist/secrets/secret-names.d.ts.map +1 -0
  1056. package/dist/secrets/secret-names.js +39 -0
  1057. package/dist/secrets/secret-names.js.map +1 -0
  1058. package/dist/secrets/secret-store.d.ts +8 -0
  1059. package/dist/secrets/secret-store.d.ts.map +1 -0
  1060. package/dist/secrets/secret-store.js +2 -0
  1061. package/dist/secrets/secret-store.js.map +1 -0
  1062. package/dist/secrets/types.d.ts +7 -0
  1063. package/dist/secrets/types.d.ts.map +1 -0
  1064. package/dist/secrets/types.js +2 -0
  1065. package/dist/secrets/types.js.map +1 -0
  1066. package/dist/services/apple-calendar/caldav-client.d.ts +48 -0
  1067. package/dist/services/apple-calendar/caldav-client.d.ts.map +1 -0
  1068. package/dist/services/apple-calendar/caldav-client.js +86 -0
  1069. package/dist/services/apple-calendar/caldav-client.js.map +1 -0
  1070. package/dist/services/apple-calendar/caldav-codec.d.ts +67 -0
  1071. package/dist/services/apple-calendar/caldav-codec.d.ts.map +1 -0
  1072. package/dist/services/apple-calendar/caldav-codec.js +341 -0
  1073. package/dist/services/apple-calendar/caldav-codec.js.map +1 -0
  1074. package/dist/services/apple-calendar/index.d.ts +3 -0
  1075. package/dist/services/apple-calendar/index.d.ts.map +1 -0
  1076. package/dist/services/apple-calendar/index.js +2 -0
  1077. package/dist/services/apple-calendar/index.js.map +1 -0
  1078. package/dist/services/apple-calendar/service.d.ts +75 -0
  1079. package/dist/services/apple-calendar/service.d.ts.map +1 -0
  1080. package/dist/services/apple-calendar/service.js +374 -0
  1081. package/dist/services/apple-calendar/service.js.map +1 -0
  1082. package/dist/services/apple-calendar/types.d.ts +78 -0
  1083. package/dist/services/apple-calendar/types.d.ts.map +1 -0
  1084. package/dist/services/apple-calendar/types.js +17 -0
  1085. package/dist/services/apple-calendar/types.js.map +1 -0
  1086. package/dist/services/attachments/hardlink.d.ts +11 -0
  1087. package/dist/services/attachments/hardlink.d.ts.map +1 -0
  1088. package/dist/services/attachments/hardlink.js +56 -0
  1089. package/dist/services/attachments/hardlink.js.map +1 -0
  1090. package/dist/services/attachments/sanitize.d.ts +21 -0
  1091. package/dist/services/attachments/sanitize.d.ts.map +1 -0
  1092. package/dist/services/attachments/sanitize.js +128 -0
  1093. package/dist/services/attachments/sanitize.js.map +1 -0
  1094. package/dist/services/attachments/store.d.ts +146 -0
  1095. package/dist/services/attachments/store.d.ts.map +1 -0
  1096. package/dist/services/attachments/store.js +477 -0
  1097. package/dist/services/attachments/store.js.map +1 -0
  1098. package/dist/services/calendar/outlook/graph-calendar-client.d.ts +114 -0
  1099. package/dist/services/calendar/outlook/graph-calendar-client.d.ts.map +1 -0
  1100. package/dist/services/calendar/outlook/graph-calendar-client.js +146 -0
  1101. package/dist/services/calendar/outlook/graph-calendar-client.js.map +1 -0
  1102. package/dist/services/calendar.d.ts +115 -0
  1103. package/dist/services/calendar.d.ts.map +1 -0
  1104. package/dist/services/calendar.js +281 -0
  1105. package/dist/services/calendar.js.map +1 -0
  1106. package/dist/services/delegated-backend-invoker.d.ts +414 -0
  1107. package/dist/services/delegated-backend-invoker.d.ts.map +1 -0
  1108. package/dist/services/delegated-backend-invoker.js +2372 -0
  1109. package/dist/services/delegated-backend-invoker.js.map +1 -0
  1110. package/dist/services/delegated-proxy-config.d.ts +93 -0
  1111. package/dist/services/delegated-proxy-config.d.ts.map +1 -0
  1112. package/dist/services/delegated-proxy-config.js +98 -0
  1113. package/dist/services/delegated-proxy-config.js.map +1 -0
  1114. package/dist/services/delegated-task-result-cache.d.ts +176 -0
  1115. package/dist/services/delegated-task-result-cache.d.ts.map +1 -0
  1116. package/dist/services/delegated-task-result-cache.js +0 -0
  1117. package/dist/services/delegated-task-result-cache.js.map +1 -0
  1118. package/dist/services/delegated-task-runtime.d.ts +346 -0
  1119. package/dist/services/delegated-task-runtime.d.ts.map +1 -0
  1120. package/dist/services/delegated-task-runtime.js +589 -0
  1121. package/dist/services/delegated-task-runtime.js.map +1 -0
  1122. package/dist/services/delegated-task-session-pool.d.ts +182 -0
  1123. package/dist/services/delegated-task-session-pool.d.ts.map +1 -0
  1124. package/dist/services/delegated-task-session-pool.js +292 -0
  1125. package/dist/services/delegated-task-session-pool.js.map +1 -0
  1126. package/dist/services/delegated-tool-runtime.d.ts +50 -0
  1127. package/dist/services/delegated-tool-runtime.d.ts.map +1 -0
  1128. package/dist/services/delegated-tool-runtime.js +120 -0
  1129. package/dist/services/delegated-tool-runtime.js.map +1 -0
  1130. package/dist/services/fts5.d.ts +40 -0
  1131. package/dist/services/fts5.d.ts.map +1 -0
  1132. package/dist/services/fts5.js +54 -0
  1133. package/dist/services/fts5.js.map +1 -0
  1134. package/dist/services/git-account-registry.d.ts +164 -0
  1135. package/dist/services/git-account-registry.d.ts.map +1 -0
  1136. package/dist/services/git-account-registry.js +297 -0
  1137. package/dist/services/git-account-registry.js.map +1 -0
  1138. package/dist/services/github.d.ts +49 -0
  1139. package/dist/services/github.d.ts.map +1 -0
  1140. package/dist/services/github.js +123 -0
  1141. package/dist/services/github.js.map +1 -0
  1142. package/dist/services/gmail-classifier.d.ts +62 -0
  1143. package/dist/services/gmail-classifier.d.ts.map +1 -0
  1144. package/dist/services/gmail-classifier.js +221 -0
  1145. package/dist/services/gmail-classifier.js.map +1 -0
  1146. package/dist/services/gmail.d.ts +192 -0
  1147. package/dist/services/gmail.d.ts.map +1 -0
  1148. package/dist/services/gmail.js +678 -0
  1149. package/dist/services/gmail.js.map +1 -0
  1150. package/dist/services/google-auth.d.ts +16 -0
  1151. package/dist/services/google-auth.d.ts.map +1 -0
  1152. package/dist/services/google-auth.js +37 -0
  1153. package/dist/services/google-auth.js.map +1 -0
  1154. package/dist/services/google-maps.d.ts +35 -0
  1155. package/dist/services/google-maps.d.ts.map +1 -0
  1156. package/dist/services/google-maps.js +82 -0
  1157. package/dist/services/google-maps.js.map +1 -0
  1158. package/dist/services/integrations/extract-write-item-id.d.ts +64 -0
  1159. package/dist/services/integrations/extract-write-item-id.d.ts.map +1 -0
  1160. package/dist/services/integrations/extract-write-item-id.js +188 -0
  1161. package/dist/services/integrations/extract-write-item-id.js.map +1 -0
  1162. package/dist/services/integrations/reconcile.d.ts +136 -0
  1163. package/dist/services/integrations/reconcile.d.ts.map +1 -0
  1164. package/dist/services/integrations/reconcile.js +218 -0
  1165. package/dist/services/integrations/reconcile.js.map +1 -0
  1166. package/dist/services/integrations/snapshot-partitions.d.ts +40 -0
  1167. package/dist/services/integrations/snapshot-partitions.d.ts.map +1 -0
  1168. package/dist/services/integrations/snapshot-partitions.js +113 -0
  1169. package/dist/services/integrations/snapshot-partitions.js.map +1 -0
  1170. package/dist/services/journal/render.d.ts +15 -0
  1171. package/dist/services/journal/render.d.ts.map +1 -0
  1172. package/dist/services/journal/render.js +17 -0
  1173. package/dist/services/journal/render.js.map +1 -0
  1174. package/dist/services/journal/writer.d.ts +26 -0
  1175. package/dist/services/journal/writer.d.ts.map +1 -0
  1176. package/dist/services/journal/writer.js +50 -0
  1177. package/dist/services/journal/writer.js.map +1 -0
  1178. package/dist/services/mail/account-registry.d.ts +208 -0
  1179. package/dist/services/mail/account-registry.d.ts.map +1 -0
  1180. package/dist/services/mail/account-registry.js +554 -0
  1181. package/dist/services/mail/account-registry.js.map +1 -0
  1182. package/dist/services/mail/gmail/auth-failure-classifier.d.ts +24 -0
  1183. package/dist/services/mail/gmail/auth-failure-classifier.d.ts.map +1 -0
  1184. package/dist/services/mail/gmail/auth-failure-classifier.js +67 -0
  1185. package/dist/services/mail/gmail/auth-failure-classifier.js.map +1 -0
  1186. package/dist/services/mail/gmail/gmail-provider.d.ts +58 -0
  1187. package/dist/services/mail/gmail/gmail-provider.d.ts.map +1 -0
  1188. package/dist/services/mail/gmail/gmail-provider.js +434 -0
  1189. package/dist/services/mail/gmail/gmail-provider.js.map +1 -0
  1190. package/dist/services/mail/gmail/legacy-row.d.ts +24 -0
  1191. package/dist/services/mail/gmail/legacy-row.d.ts.map +1 -0
  1192. package/dist/services/mail/gmail/legacy-row.js +71 -0
  1193. package/dist/services/mail/gmail/legacy-row.js.map +1 -0
  1194. package/dist/services/mail/gmail/poll-cursor.d.ts +12 -0
  1195. package/dist/services/mail/gmail/poll-cursor.d.ts.map +1 -0
  1196. package/dist/services/mail/gmail/poll-cursor.js +32 -0
  1197. package/dist/services/mail/gmail/poll-cursor.js.map +1 -0
  1198. package/dist/services/mail/html-to-plaintext.d.ts +27 -0
  1199. package/dist/services/mail/html-to-plaintext.d.ts.map +1 -0
  1200. package/dist/services/mail/html-to-plaintext.js +163 -0
  1201. package/dist/services/mail/html-to-plaintext.js.map +1 -0
  1202. package/dist/services/mail/imap/app-password.d.ts +27 -0
  1203. package/dist/services/mail/imap/app-password.d.ts.map +1 -0
  1204. package/dist/services/mail/imap/app-password.js +86 -0
  1205. package/dist/services/mail/imap/app-password.js.map +1 -0
  1206. package/dist/services/mail/imap/auth-failure-classifier.d.ts +21 -0
  1207. package/dist/services/mail/imap/auth-failure-classifier.d.ts.map +1 -0
  1208. package/dist/services/mail/imap/auth-failure-classifier.js +54 -0
  1209. package/dist/services/mail/imap/auth-failure-classifier.js.map +1 -0
  1210. package/dist/services/mail/imap/capabilities.d.ts +30 -0
  1211. package/dist/services/mail/imap/capabilities.d.ts.map +1 -0
  1212. package/dist/services/mail/imap/capabilities.js +70 -0
  1213. package/dist/services/mail/imap/capabilities.js.map +1 -0
  1214. package/dist/services/mail/imap/client.d.ts +15 -0
  1215. package/dist/services/mail/imap/client.d.ts.map +1 -0
  1216. package/dist/services/mail/imap/client.js +60 -0
  1217. package/dist/services/mail/imap/client.js.map +1 -0
  1218. package/dist/services/mail/imap/cursor.d.ts +19 -0
  1219. package/dist/services/mail/imap/cursor.d.ts.map +1 -0
  1220. package/dist/services/mail/imap/cursor.js +47 -0
  1221. package/dist/services/mail/imap/cursor.js.map +1 -0
  1222. package/dist/services/mail/imap/folder-resolver.d.ts +24 -0
  1223. package/dist/services/mail/imap/folder-resolver.d.ts.map +1 -0
  1224. package/dist/services/mail/imap/folder-resolver.js +58 -0
  1225. package/dist/services/mail/imap/folder-resolver.js.map +1 -0
  1226. package/dist/services/mail/imap/icloud-provider.d.ts +5 -0
  1227. package/dist/services/mail/imap/icloud-provider.d.ts.map +1 -0
  1228. package/dist/services/mail/imap/icloud-provider.js +5 -0
  1229. package/dist/services/mail/imap/icloud-provider.js.map +1 -0
  1230. package/dist/services/mail/imap/imap-provider-base.d.ts +173 -0
  1231. package/dist/services/mail/imap/imap-provider-base.d.ts.map +1 -0
  1232. package/dist/services/mail/imap/imap-provider-base.js +1004 -0
  1233. package/dist/services/mail/imap/imap-provider-base.js.map +1 -0
  1234. package/dist/services/mail/imap/query-translator.d.ts +13 -0
  1235. package/dist/services/mail/imap/query-translator.d.ts.map +1 -0
  1236. package/dist/services/mail/imap/query-translator.js +114 -0
  1237. package/dist/services/mail/imap/query-translator.js.map +1 -0
  1238. package/dist/services/mail/imap/reconcile-planner.d.ts +56 -0
  1239. package/dist/services/mail/imap/reconcile-planner.d.ts.map +1 -0
  1240. package/dist/services/mail/imap/reconcile-planner.js +52 -0
  1241. package/dist/services/mail/imap/reconcile-planner.js.map +1 -0
  1242. package/dist/services/mail/imap/reply-mime.d.ts +24 -0
  1243. package/dist/services/mail/imap/reply-mime.d.ts.map +1 -0
  1244. package/dist/services/mail/imap/reply-mime.js +77 -0
  1245. package/dist/services/mail/imap/reply-mime.js.map +1 -0
  1246. package/dist/services/mail/imap/yahoo-provider.d.ts +5 -0
  1247. package/dist/services/mail/imap/yahoo-provider.d.ts.map +1 -0
  1248. package/dist/services/mail/imap/yahoo-provider.js +5 -0
  1249. package/dist/services/mail/imap/yahoo-provider.js.map +1 -0
  1250. package/dist/services/mail/mail-search.d.ts +35 -0
  1251. package/dist/services/mail/mail-search.d.ts.map +1 -0
  1252. package/dist/services/mail/mail-search.js +59 -0
  1253. package/dist/services/mail/mail-search.js.map +1 -0
  1254. package/dist/services/mail/outlook/auth-failure-classifier.d.ts +38 -0
  1255. package/dist/services/mail/outlook/auth-failure-classifier.d.ts.map +1 -0
  1256. package/dist/services/mail/outlook/auth-failure-classifier.js +91 -0
  1257. package/dist/services/mail/outlook/auth-failure-classifier.js.map +1 -0
  1258. package/dist/services/mail/outlook/client-config.d.ts +34 -0
  1259. package/dist/services/mail/outlook/client-config.d.ts.map +1 -0
  1260. package/dist/services/mail/outlook/client-config.js +58 -0
  1261. package/dist/services/mail/outlook/client-config.js.map +1 -0
  1262. package/dist/services/mail/outlook/delta-cursor.d.ts +66 -0
  1263. package/dist/services/mail/outlook/delta-cursor.d.ts.map +1 -0
  1264. package/dist/services/mail/outlook/delta-cursor.js +85 -0
  1265. package/dist/services/mail/outlook/delta-cursor.js.map +1 -0
  1266. package/dist/services/mail/outlook/graph-client.d.ts +98 -0
  1267. package/dist/services/mail/outlook/graph-client.d.ts.map +1 -0
  1268. package/dist/services/mail/outlook/graph-client.js +198 -0
  1269. package/dist/services/mail/outlook/graph-client.js.map +1 -0
  1270. package/dist/services/mail/outlook/msal-app-factory.d.ts +20 -0
  1271. package/dist/services/mail/outlook/msal-app-factory.d.ts.map +1 -0
  1272. package/dist/services/mail/outlook/msal-app-factory.js +62 -0
  1273. package/dist/services/mail/outlook/msal-app-factory.js.map +1 -0
  1274. package/dist/services/mail/outlook/msal-cache-plugin.d.ts +19 -0
  1275. package/dist/services/mail/outlook/msal-cache-plugin.d.ts.map +1 -0
  1276. package/dist/services/mail/outlook/msal-cache-plugin.js +30 -0
  1277. package/dist/services/mail/outlook/msal-cache-plugin.js.map +1 -0
  1278. package/dist/services/mail/outlook/oauth-device-code.d.ts +26 -0
  1279. package/dist/services/mail/outlook/oauth-device-code.d.ts.map +1 -0
  1280. package/dist/services/mail/outlook/oauth-device-code.js +32 -0
  1281. package/dist/services/mail/outlook/oauth-device-code.js.map +1 -0
  1282. package/dist/services/mail/outlook/oauth-loopback.d.ts +41 -0
  1283. package/dist/services/mail/outlook/oauth-loopback.d.ts.map +1 -0
  1284. package/dist/services/mail/outlook/oauth-loopback.js +223 -0
  1285. package/dist/services/mail/outlook/oauth-loopback.js.map +1 -0
  1286. package/dist/services/mail/outlook/outlook-provider.d.ts +100 -0
  1287. package/dist/services/mail/outlook/outlook-provider.d.ts.map +1 -0
  1288. package/dist/services/mail/outlook/outlook-provider.js +619 -0
  1289. package/dist/services/mail/outlook/outlook-provider.js.map +1 -0
  1290. package/dist/services/mail/outlook/query-translator.d.ts +10 -0
  1291. package/dist/services/mail/outlook/query-translator.d.ts.map +1 -0
  1292. package/dist/services/mail/outlook/query-translator.js +103 -0
  1293. package/dist/services/mail/outlook/query-translator.js.map +1 -0
  1294. package/dist/services/mail/provider.d.ts +267 -0
  1295. package/dist/services/mail/provider.d.ts.map +1 -0
  1296. package/dist/services/mail/provider.js +34 -0
  1297. package/dist/services/mail/provider.js.map +1 -0
  1298. package/dist/services/mail/query-utils.d.ts +13 -0
  1299. package/dist/services/mail/query-utils.d.ts.map +1 -0
  1300. package/dist/services/mail/query-utils.js +18 -0
  1301. package/dist/services/mail/query-utils.js.map +1 -0
  1302. package/dist/services/mail-classifier.d.ts +25 -0
  1303. package/dist/services/mail-classifier.d.ts.map +1 -0
  1304. package/dist/services/mail-classifier.js +52 -0
  1305. package/dist/services/mail-classifier.js.map +1 -0
  1306. package/dist/services/mail-ingestion.d.ts +139 -0
  1307. package/dist/services/mail-ingestion.d.ts.map +1 -0
  1308. package/dist/services/mail-ingestion.js +223 -0
  1309. package/dist/services/mail-ingestion.js.map +1 -0
  1310. package/dist/services/mcp/auto-probe.d.ts +76 -0
  1311. package/dist/services/mcp/auto-probe.d.ts.map +1 -0
  1312. package/dist/services/mcp/auto-probe.js +147 -0
  1313. package/dist/services/mcp/auto-probe.js.map +1 -0
  1314. package/dist/services/mcp/generators/claude.d.ts +18 -0
  1315. package/dist/services/mcp/generators/claude.d.ts.map +1 -0
  1316. package/dist/services/mcp/generators/claude.js +90 -0
  1317. package/dist/services/mcp/generators/claude.js.map +1 -0
  1318. package/dist/services/mcp/generators/codex.d.ts +22 -0
  1319. package/dist/services/mcp/generators/codex.d.ts.map +1 -0
  1320. package/dist/services/mcp/generators/codex.js +102 -0
  1321. package/dist/services/mcp/generators/codex.js.map +1 -0
  1322. package/dist/services/mcp/generators/gemini.d.ts +20 -0
  1323. package/dist/services/mcp/generators/gemini.d.ts.map +1 -0
  1324. package/dist/services/mcp/generators/gemini.js +97 -0
  1325. package/dist/services/mcp/generators/gemini.js.map +1 -0
  1326. package/dist/services/mcp/generators/index.d.ts +20 -0
  1327. package/dist/services/mcp/generators/index.d.ts.map +1 -0
  1328. package/dist/services/mcp/generators/index.js +29 -0
  1329. package/dist/services/mcp/generators/index.js.map +1 -0
  1330. package/dist/services/mcp/generators/types.d.ts +47 -0
  1331. package/dist/services/mcp/generators/types.d.ts.map +1 -0
  1332. package/dist/services/mcp/generators/types.js +40 -0
  1333. package/dist/services/mcp/generators/types.js.map +1 -0
  1334. package/dist/services/mcp/probe.d.ts +31 -0
  1335. package/dist/services/mcp/probe.d.ts.map +1 -0
  1336. package/dist/services/mcp/probe.js +437 -0
  1337. package/dist/services/mcp/probe.js.map +1 -0
  1338. package/dist/services/mcp/registry.d.ts +84 -0
  1339. package/dist/services/mcp/registry.d.ts.map +1 -0
  1340. package/dist/services/mcp/registry.js +387 -0
  1341. package/dist/services/mcp/registry.js.map +1 -0
  1342. package/dist/services/mcp/risk.d.ts +82 -0
  1343. package/dist/services/mcp/risk.d.ts.map +1 -0
  1344. package/dist/services/mcp/risk.js +126 -0
  1345. package/dist/services/mcp/risk.js.map +1 -0
  1346. package/dist/services/mcp/session-materializer.d.ts +123 -0
  1347. package/dist/services/mcp/session-materializer.d.ts.map +1 -0
  1348. package/dist/services/mcp/session-materializer.js +361 -0
  1349. package/dist/services/mcp/session-materializer.js.map +1 -0
  1350. package/dist/services/mcp/tool-audit.d.ts +53 -0
  1351. package/dist/services/mcp/tool-audit.d.ts.map +1 -0
  1352. package/dist/services/mcp/tool-audit.js +74 -0
  1353. package/dist/services/mcp/tool-audit.js.map +1 -0
  1354. package/dist/services/mcp/types.d.ts +88 -0
  1355. package/dist/services/mcp/types.d.ts.map +1 -0
  1356. package/dist/services/mcp/types.js +94 -0
  1357. package/dist/services/mcp/types.js.map +1 -0
  1358. package/dist/services/notion.d.ts +134 -0
  1359. package/dist/services/notion.d.ts.map +1 -0
  1360. package/dist/services/notion.js +350 -0
  1361. package/dist/services/notion.js.map +1 -0
  1362. package/dist/services/obsidian.d.ts +116 -0
  1363. package/dist/services/obsidian.d.ts.map +1 -0
  1364. package/dist/services/obsidian.js +305 -0
  1365. package/dist/services/obsidian.js.map +1 -0
  1366. package/dist/services/service-registry.d.ts +31 -0
  1367. package/dist/services/service-registry.d.ts.map +1 -0
  1368. package/dist/services/service-registry.js +15 -0
  1369. package/dist/services/service-registry.js.map +1 -0
  1370. package/dist/services/voice/transcriber-impl.d.ts +15 -0
  1371. package/dist/services/voice/transcriber-impl.d.ts.map +1 -0
  1372. package/dist/services/voice/transcriber-impl.js +129 -0
  1373. package/dist/services/voice/transcriber-impl.js.map +1 -0
  1374. package/dist/services/voice/transcriber.d.ts +117 -0
  1375. package/dist/services/voice/transcriber.d.ts.map +1 -0
  1376. package/dist/services/voice/transcriber.js +201 -0
  1377. package/dist/services/voice/transcriber.js.map +1 -0
  1378. package/dist/settings/runtime-settings.d.ts +232 -0
  1379. package/dist/settings/runtime-settings.d.ts.map +1 -0
  1380. package/dist/settings/runtime-settings.js +769 -0
  1381. package/dist/settings/runtime-settings.js.map +1 -0
  1382. package/dist/settings/settings-store.d.ts +13 -0
  1383. package/dist/settings/settings-store.d.ts.map +1 -0
  1384. package/dist/settings/settings-store.js +87 -0
  1385. package/dist/settings/settings-store.js.map +1 -0
  1386. package/package.json +85 -0
@@ -0,0 +1,2062 @@
1
+ import { Hono } from "hono";
2
+ import { readFileSync, writeFileSync, existsSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { randomUUID } from "node:crypto";
5
+ import { APP_NAME, EDITABLE_RUNTIME_KEY_TUPLE, getAgentDayBoundsUtc, normalizeAgentDisplayName, } from "@aitne/shared";
6
+ import { applyConfigUpdates } from "../env-writer.js";
7
+ import { runDefaultSchedulesReconciler } from "../../core/context/default-schedules-runner.js";
8
+ import { syncDmSessionTimesToQuietHours } from "../../core/quiet-hours-sync.js";
9
+ import { detectGoogleCredentialType, getGoogleOAuthClientConfig, parseGoogleCredentialsJson, } from "../../services/google-auth.js";
10
+ import { getContextDir } from "../../config.js";
11
+ import { CONTEXT_RELATIVE_PATHS } from "../../core/context-paths.js";
12
+ import { createLogger, toSafeErrorMessage } from "../../logging.js";
13
+ import { upsertManagementRulesAgentIdentity } from "../../management-rules.js";
14
+ import { DEFAULT_DISALLOWED_TOOLS, runtimeSettingsSchema } from "../../settings/runtime-settings.js";
15
+ import { createSettingsStore } from "../../settings/settings-store.js";
16
+ import { getSessionWorkdirPath } from "../../core/workdir.js";
17
+ import { rewriteCharacterBlock } from "../../core/skills-compiler.js";
18
+ import { DASHBOARD_CHAT_SCOPE, DOCS_QA_SCOPE } from "../../messaging/constants.js";
19
+ import { deleteAllChatSidebarSessions, deleteChatSession, } from "../../core/dashboard-session-cleanup.js";
20
+ import { readJsonBody } from "../json-body.js";
21
+ import { computeDmFreshnessAggregate } from "../../core/dm-freshness-metrics.js";
22
+ const MAX_UPLOAD_SIZE = 100 * 1024; // 100 KB — credential files are small
23
+ const MAX_OAUTH_STATE_AGE_MS = 10 * 60 * 1000;
24
+ const PUBLIC_CONFIG_RUNTIME_KEYS = [
25
+ "maxConcurrentSessions",
26
+ "maxReactiveSessions",
27
+ "delegatedProxyMaxConcurrent",
28
+ "delegatedTaskModeEnabled",
29
+ "delegatedTaskMaxPerDay",
30
+ "delegatedTaskDefaultMaxToolCalls",
31
+ "delegatedTaskDefaultMaxBudgetUsd",
32
+ "delegatedTaskDefaultTimeoutMs",
33
+ "delegatedTaskHeavyEnabled",
34
+ "executeTimeoutMinutes",
35
+ "agentDisplayName",
36
+ "sessionTimeoutDmMinutes",
37
+ "sessionTimeoutChannelMinutes",
38
+ "sessionTimeoutDashboardMinutes",
39
+ "timezone",
40
+ "dayBoundaryHour",
41
+ "hourlyCheckEnabled",
42
+ "hourlyCheckIntervalMinutes",
43
+ "hourlyCheckActiveStartHour",
44
+ "hourlyCheckActiveEndHour",
45
+ "hourlyCheckMinObservations",
46
+ "authProbeDisabled",
47
+ "authPreflightFreshnessMs",
48
+ "maxNotificationsPerHour",
49
+ "maxNotificationsPerDay",
50
+ "quietHoursStart",
51
+ "quietHoursEnd",
52
+ "batchIntervalMinutes",
53
+ "primaryPlatform",
54
+ "defaultNotificationPlatforms",
55
+ "whatsappEnabled",
56
+ "whatsappAuthDir",
57
+ "disallowedTools",
58
+ "claudeExecutionPermissionMode",
59
+ "codexExecutionPermissionMode",
60
+ "geminiExecutionPermissionMode",
61
+ "externalObsidianVaultPath",
62
+ "externalObsidianVaultName",
63
+ // SETUP-FLOW-REDESIGN-PLAN §6.3 — kill switch for the external-vault
64
+ // file watcher. Surfaced so the Note step's "Watch for changes"
65
+ // checkbox round-trips through the dashboard.
66
+ "externalObsidianWatch",
67
+ "primaryVaultPath",
68
+ "primaryVaultName",
69
+ // gitRepos / gitWatchedRepos / githubRepos removed at the unified-
70
+ // repositories cutover (docs/design/appendices/unified-repositories.md);
71
+ // dashboard reads the rows from /api/repositories instead.
72
+ "googleCalendarId",
73
+ "notionDatabaseIds",
74
+ "character",
75
+ "historyInjectionMaxMessages",
76
+ "historyInjectionMaxTokens",
77
+ "dmStalenessStrict",
78
+ "obsidianDebounceSeconds",
79
+ "schedulePollIntervalSeconds",
80
+ "gitPollIntervalSeconds",
81
+ "gitPushOverdueMinutes",
82
+ "gitProjectUpdateDebounceMinutes",
83
+ "notionPollIntervalSeconds",
84
+ "calendarPollIntervalSeconds",
85
+ "gmailPollIntervalSeconds",
86
+ "mcpAutoProbeIntervalMinutes",
87
+ "delegatedProbeIntervalMinutes",
88
+ "autonomousDailyCostCapUsd",
89
+ "autonomousMonthlyCostCapUsd",
90
+ "primaryLanguage",
91
+ "vaultMode",
92
+ ];
93
+ const PUBLIC_CONFIG_NULLABLE_STRING_KEYS = new Set([
94
+ "whatsappAuthDir",
95
+ "externalObsidianVaultPath",
96
+ "externalObsidianVaultName",
97
+ "primaryVaultPath",
98
+ "primaryVaultName",
99
+ ]);
100
+ /**
101
+ * Pre-defined static cost queries — no string interpolation of user input.
102
+ * `byModel` is computed in JS via `aggregateByBilledModel` because the SDK
103
+ * can route a request for one model to a sibling (e.g. opus-4-7 →
104
+ * opus-4-6[1m]); SQL `GROUP BY model_used` would lump cost under the
105
+ * requested model and produce a chart that disagrees with the per-row
106
+ * billed-model badge on the same page.
107
+ */
108
+ const COST_QUERIES = {
109
+ daily: {
110
+ byPeriod: `SELECT date(started_at) as period,
111
+ SUM(cost_usd) as total_cost, COUNT(*) as session_count,
112
+ SUM(tokens_input) as total_input_tokens, SUM(tokens_output) as total_output_tokens
113
+ FROM agent_actions WHERE started_at > datetime('now', '-30 days') AND cost_usd IS NOT NULL
114
+ GROUP BY date(started_at) ORDER BY period DESC`,
115
+ byModelRows: `SELECT model_used, model_usage_json, cost_usd
116
+ FROM agent_actions
117
+ WHERE started_at > datetime('now', '-30 days')
118
+ AND cost_usd IS NOT NULL
119
+ AND (model_used IS NOT NULL OR model_usage_json IS NOT NULL)`,
120
+ byEventType: `SELECT action_type as event_type, SUM(cost_usd) as total_cost, COUNT(*) as session_count
121
+ FROM agent_actions WHERE started_at > datetime('now', '-30 days') AND cost_usd IS NOT NULL
122
+ GROUP BY action_type ORDER BY total_cost DESC`,
123
+ },
124
+ weekly: {
125
+ byPeriod: `SELECT strftime('%Y-W%W', started_at) as period,
126
+ SUM(cost_usd) as total_cost, COUNT(*) as session_count,
127
+ SUM(tokens_input) as total_input_tokens, SUM(tokens_output) as total_output_tokens
128
+ FROM agent_actions WHERE started_at > datetime('now', '-90 days') AND cost_usd IS NOT NULL
129
+ GROUP BY strftime('%Y-W%W', started_at) ORDER BY period DESC`,
130
+ byModelRows: `SELECT model_used, model_usage_json, cost_usd
131
+ FROM agent_actions
132
+ WHERE started_at > datetime('now', '-90 days')
133
+ AND cost_usd IS NOT NULL
134
+ AND (model_used IS NOT NULL OR model_usage_json IS NOT NULL)`,
135
+ byEventType: `SELECT action_type as event_type, SUM(cost_usd) as total_cost, COUNT(*) as session_count
136
+ FROM agent_actions WHERE started_at > datetime('now', '-90 days') AND cost_usd IS NOT NULL
137
+ GROUP BY action_type ORDER BY total_cost DESC`,
138
+ },
139
+ monthly: {
140
+ byPeriod: `SELECT strftime('%Y-%m', started_at) as period,
141
+ SUM(cost_usd) as total_cost, COUNT(*) as session_count,
142
+ SUM(tokens_input) as total_input_tokens, SUM(tokens_output) as total_output_tokens
143
+ FROM agent_actions WHERE started_at > datetime('now', '-365 days') AND cost_usd IS NOT NULL
144
+ GROUP BY strftime('%Y-%m', started_at) ORDER BY period DESC`,
145
+ byModelRows: `SELECT model_used, model_usage_json, cost_usd
146
+ FROM agent_actions
147
+ WHERE started_at > datetime('now', '-365 days')
148
+ AND cost_usd IS NOT NULL
149
+ AND (model_used IS NOT NULL OR model_usage_json IS NOT NULL)`,
150
+ byEventType: `SELECT action_type as event_type, SUM(cost_usd) as total_cost, COUNT(*) as session_count
151
+ FROM agent_actions WHERE started_at > datetime('now', '-365 days') AND cost_usd IS NOT NULL
152
+ GROUP BY action_type ORDER BY total_cost DESC`,
153
+ },
154
+ };
155
+ /**
156
+ * Aggregate raw `byModelRows` into the `{ model, total_cost, session_count }`
157
+ * shape the dashboard expects, attributing cost to the actually-billed model
158
+ * from `model_usage_json` rather than the requested `model_used`. When a row
159
+ * has no usage breakdown we fall back to `model_used`. A row that touches
160
+ * multiple billed models contributes its split cost to each bucket and is
161
+ * counted once toward each model's `session_count`.
162
+ *
163
+ * Cost reconciliation: the SDK's `r.modelUsage[*].costUSD` covers LLM
164
+ * inference only — server-side tools (web_search, code_execution) appear in
165
+ * `r.total_cost_usd` (= row.cost_usd) but not in any per-model entry. If
166
+ * `Σ per-model cost < row.cost_usd`, the residual is credited to
167
+ * `model_used` (the requested model) so per-model totals add up to the
168
+ * dashboard's overall cost. Without this, a chart row's "billed total"
169
+ * silently drops tool-use spend.
170
+ */
171
+ export function aggregateByBilledModel(rows) {
172
+ const map = new Map();
173
+ // Per-row scratch; a single row counts toward `session_count` exactly once
174
+ // per model it touched, even when residual handling credits the same model
175
+ // twice (once from per-model breakdown, once from tool-use residual).
176
+ const addCost = (model, cost) => {
177
+ const bucket = map.get(model) ?? { total_cost: 0, session_count: 0 };
178
+ bucket.total_cost += cost;
179
+ map.set(model, bucket);
180
+ };
181
+ const incSession = (rowSeen, model) => {
182
+ if (rowSeen.has(model))
183
+ return;
184
+ rowSeen.add(model);
185
+ const bucket = map.get(model) ?? { total_cost: 0, session_count: 0 };
186
+ bucket.session_count += 1;
187
+ map.set(model, bucket);
188
+ };
189
+ // 0.0001¢ — below this, treat the residual as float-arithmetic noise and
190
+ // skip the bookkeeping. Real tool-use costs are always orders of magnitude
191
+ // above this.
192
+ const RESIDUAL_EPSILON_USD = 0.000001;
193
+ for (const row of rows) {
194
+ const seenForRow = new Set();
195
+ let parsed = null;
196
+ if (row.model_usage_json) {
197
+ try {
198
+ parsed = JSON.parse(row.model_usage_json);
199
+ }
200
+ catch {
201
+ parsed = null;
202
+ }
203
+ }
204
+ let perModelTotal = 0;
205
+ let touchedAny = false;
206
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
207
+ for (const [modelId, entry] of Object.entries(parsed)) {
208
+ if (!entry || typeof entry !== "object")
209
+ continue;
210
+ const v = entry;
211
+ const cost = typeof v.costUsd === "number" ? v.costUsd : 0;
212
+ addCost(modelId, cost);
213
+ incSession(seenForRow, modelId);
214
+ perModelTotal += cost;
215
+ touchedAny = true;
216
+ }
217
+ }
218
+ if (!touchedAny) {
219
+ if (row.model_used) {
220
+ addCost(row.model_used, row.cost_usd);
221
+ incSession(seenForRow, row.model_used);
222
+ }
223
+ continue;
224
+ }
225
+ // Residual handles server-side tool cost (web_search, code execution)
226
+ // that the SDK adds to total_cost_usd but not to any per-model bucket.
227
+ const residual = row.cost_usd - perModelTotal;
228
+ if (residual > RESIDUAL_EPSILON_USD && row.model_used) {
229
+ addCost(row.model_used, residual);
230
+ incSession(seenForRow, row.model_used);
231
+ }
232
+ }
233
+ return [...map.entries()]
234
+ .map(([model, v]) => ({ model, ...v }))
235
+ .sort((a, b) => b.total_cost - a.total_cost);
236
+ }
237
+ const COST_PERIOD_SPECS = {
238
+ daily: {
239
+ bucketExpr: "date(started_at)",
240
+ sinceExpr: "-30 days",
241
+ },
242
+ weekly: {
243
+ bucketExpr: "strftime('%Y-W%W', started_at)",
244
+ sinceExpr: "-90 days",
245
+ },
246
+ monthly: {
247
+ bucketExpr: "strftime('%Y-%m', started_at)",
248
+ sinceExpr: "-365 days",
249
+ },
250
+ };
251
+ /** Escape HTML special characters to prevent XSS */
252
+ function escapeHtml(s) {
253
+ return s
254
+ .replace(/&/g, "&amp;")
255
+ .replace(/</g, "&lt;")
256
+ .replace(/>/g, "&gt;")
257
+ .replace(/"/g, "&quot;")
258
+ .replace(/'/g, "&#039;");
259
+ }
260
+ function getLocalHourMinute(date, timeZone) {
261
+ const formatter = new Intl.DateTimeFormat("en-US", {
262
+ hour: "2-digit",
263
+ minute: "2-digit",
264
+ hour12: false,
265
+ timeZone,
266
+ });
267
+ const parts = formatter.formatToParts(date);
268
+ const hour = Number(parts.find((part) => part.type === "hour")?.value ?? "0");
269
+ const minute = Number(parts.find((part) => part.type === "minute")?.value ?? "0");
270
+ return { hour, minute };
271
+ }
272
+ function isHourlyCheckSlot(date, config) {
273
+ if (!config.hourlyCheckEnabled)
274
+ return false;
275
+ const { hour, minute } = getLocalHourMinute(date, config.timezone || undefined);
276
+ if (hour === config.dayBoundaryHour)
277
+ return false;
278
+ if (hour < config.hourlyCheckActiveStartHour || hour >= config.hourlyCheckActiveEndHour) {
279
+ return false;
280
+ }
281
+ return minute % config.hourlyCheckIntervalMinutes === 0;
282
+ }
283
+ function getNextHourlyCheck(config) {
284
+ if (!config.hourlyCheckEnabled) {
285
+ return { active: false, nextRunAt: null };
286
+ }
287
+ const now = new Date();
288
+ const active = isHourlyCheckSlot(now, config);
289
+ const start = new Date(now.getTime() + 60_000);
290
+ start.setSeconds(0, 0);
291
+ for (let offset = 0; offset < 48 * 60; offset++) {
292
+ const candidate = new Date(start.getTime() + offset * 60_000);
293
+ if (isHourlyCheckSlot(candidate, config)) {
294
+ return { active, nextRunAt: candidate.toISOString() };
295
+ }
296
+ }
297
+ return { active, nextRunAt: null };
298
+ }
299
+ function isStringRecord(value) {
300
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
301
+ return false;
302
+ }
303
+ return Object.entries(value).every(([key, entryValue]) => typeof key === "string" && typeof entryValue === "string");
304
+ }
305
+ function sameStringRecord(a, b) {
306
+ const aEntries = Object.entries(a);
307
+ const bEntries = Object.entries(b);
308
+ if (aEntries.length !== bEntries.length) {
309
+ return false;
310
+ }
311
+ return aEntries.every(([key, value]) => b[key] === value);
312
+ }
313
+ function buildSafeConfig(config, secretSummary) {
314
+ const safeConfig = {};
315
+ for (const key of PUBLIC_CONFIG_RUNTIME_KEYS) {
316
+ const value = config[key];
317
+ safeConfig[key] = PUBLIC_CONFIG_NULLABLE_STRING_KEYS.has(key)
318
+ ? value ?? ""
319
+ : value;
320
+ }
321
+ safeConfig.apiPort = config.apiPort;
322
+ safeConfig.allowedTools = config.allowedToolsOverride ?? [];
323
+ // Derived — the actual directory `getContextDir(config)` resolves to.
324
+ // Surfaces the mode/path → disk outcome to the dashboard so the
325
+ // Management Mode section can show the effective location without
326
+ // reimplementing the resolution logic. Always an absolute path.
327
+ safeConfig.contextDir = getContextDir(config);
328
+ safeConfig.slackConfigured = secretSummary.slackConfigured;
329
+ safeConfig.slackOwnerUserConfigured = !!config.slackOwnerUserId;
330
+ safeConfig.telegramConfigured = secretSummary.telegramConfigured;
331
+ safeConfig.telegramOwnerChatConfigured = !!config.telegramOwnerChatId;
332
+ safeConfig.discordConfigured = secretSummary.discordConfigured;
333
+ safeConfig.discordOwnerUserConfigured = !!config.discordOwnerUserId;
334
+ safeConfig.notionConfigured = secretSummary.notionConfigured;
335
+ safeConfig.githubConfigured = secretSummary.githubConfigured;
336
+ safeConfig.githubWebhookSecretConfigured = secretSummary.githubWebhookSecretConfigured;
337
+ safeConfig.apiTokenConfigured = secretSummary.apiTokenConfigured;
338
+ safeConfig.whatsappOwnerPhoneConfigured = !!config.whatsappOwnerPhone;
339
+ safeConfig.googleCalendarCredentialsConfigured = secretSummary.googleCalendarCredentialsConfigured;
340
+ safeConfig.googleCalendarTokenConfigured = secretSummary.googleCalendarTokenConfigured;
341
+ // SETUP-FLOW-REDESIGN-PLAN §6.1 — surface Outlook BYOA presence so
342
+ // dashboards can decide when direct-mode Outlook integrations are
343
+ // resumable.
344
+ safeConfig.outlookClientConfigConfigured = secretSummary.outlookClientConfigConfigured;
345
+ safeConfig.googleCredentialType = secretSummary.googleCredentialType;
346
+ return safeConfig;
347
+ }
348
+ /**
349
+ * Dashboard API routes — REST endpoints for the Dashboard UI.
350
+ *
351
+ * Provides:
352
+ * - Config management (GET/PATCH /api/config)
353
+ * - Event/action logs (GET /api/events)
354
+ * - Conversation history (GET /api/conversations)
355
+ * - Cost analytics (GET /api/cost)
356
+ * - Approval queue (GET/POST /api/approvals)
357
+ */
358
+ const logger = createLogger("dashboard-api");
359
+ export function createDashboardRoutes(deps) {
360
+ const app = new Hono();
361
+ const { db, config, services, secretBroker } = deps;
362
+ const settingsStore = createSettingsStore(db);
363
+ const oauthStates = new Map();
364
+ const agentActionColumns = new Set(db.pragma("table_info(agent_actions)").map((column) => column.name));
365
+ const backendExpr = agentActionColumns.has("backend")
366
+ ? "COALESCE(backend, 'claude')"
367
+ : "'claude'";
368
+ function pruneOauthStates(now = Date.now()) {
369
+ for (const [state, data] of oauthStates.entries()) {
370
+ if (now - data.createdAt > MAX_OAUTH_STATE_AGE_MS) {
371
+ oauthStates.delete(state);
372
+ }
373
+ }
374
+ }
375
+ async function getSecretConfigSummary() {
376
+ const [slackBotToken, slackAppToken, telegramBotToken, discordBotToken, notionApiKey, githubToken, githubWebhookSecret, apiToken, googleCredentialsJson, googleTokenJson,] = await Promise.all([
377
+ secretBroker.getSlackBotToken(),
378
+ secretBroker.getSlackAppToken(),
379
+ secretBroker.getTelegramBotToken(),
380
+ secretBroker.getDiscordBotToken(),
381
+ secretBroker.getNotionApiKey(),
382
+ secretBroker.getGitHubToken(),
383
+ secretBroker.getGitHubWebhookSecret(),
384
+ secretBroker.getApiToken(),
385
+ secretBroker.getGoogleCredentialsJson(),
386
+ secretBroker.getGoogleTokenJson(),
387
+ ]);
388
+ // SETUP-FLOW-REDESIGN-PLAN §6.1 — surface BYOA Outlook client config
389
+ // presence so the connections page knows when direct-mode Outlook
390
+ // integrations are resumable. Best-effort: if no blob store is
391
+ // wired (test harness), report `false` rather than crashing.
392
+ let outlookClientConfigConfigured = false;
393
+ try {
394
+ outlookClientConfigConfigured = deps.blobStore
395
+ ? await deps.blobStore.exists("mail:outlook:client-config")
396
+ : false;
397
+ }
398
+ catch {
399
+ outlookClientConfigConfigured = false;
400
+ }
401
+ return {
402
+ slackConfigured: !!(slackBotToken && slackAppToken),
403
+ telegramConfigured: !!telegramBotToken,
404
+ discordConfigured: !!discordBotToken,
405
+ notionConfigured: !!notionApiKey,
406
+ githubConfigured: !!githubToken,
407
+ githubWebhookSecretConfigured: !!githubWebhookSecret,
408
+ apiTokenConfigured: !!apiToken,
409
+ googleCalendarCredentialsConfigured: !!googleCredentialsJson,
410
+ googleCalendarTokenConfigured: !!googleTokenJson,
411
+ outlookClientConfigConfigured,
412
+ googleCredentialType: detectGoogleCredentialType(googleCredentialsJson),
413
+ };
414
+ }
415
+ async function notifySecretChange(scope) {
416
+ await deps.onSecretChanged?.(scope);
417
+ }
418
+ /**
419
+ * design/15-character.md §15.6.1 live-overwrite: when character changes,
420
+ * rewrite the `## Character` block inside every active session's
421
+ * instruction files (CLAUDE.md / AGENTS.md / GEMINI.md) so the next turn
422
+ * in the session picks up the new value without waiting for a session
423
+ * spawn. Per-workdir errors are counted and logged but never thrown —
424
+ * the DB write is already durable at the caller.
425
+ *
426
+ * Shared by PATCH /config (dashboard path, Approve tier) and
427
+ * PATCH /config/character (agent path, Notify tier).
428
+ */
429
+ function fanOutCharacterToActiveSessions() {
430
+ const sessions = db
431
+ .prepare(`SELECT id FROM conversation_sessions WHERE status = 'active'`)
432
+ .all();
433
+ const totals = { rewritten: 0, skipped: 0, failed: 0, missing: 0 };
434
+ for (const row of sessions) {
435
+ const sessionId = typeof row.id === "bigint" ? Number(row.id) : row.id;
436
+ const workdir = getSessionWorkdirPath(config.dataDir, sessionId);
437
+ if (!existsSync(workdir)) {
438
+ totals.missing++;
439
+ continue;
440
+ }
441
+ try {
442
+ const summary = rewriteCharacterBlock(workdir, config.character);
443
+ totals.rewritten += summary.rewritten;
444
+ totals.skipped += summary.skipped;
445
+ totals.failed += summary.failed;
446
+ }
447
+ catch (err) {
448
+ totals.failed++;
449
+ logger.warn({ err, sessionId, workdir }, "rewriteCharacterBlock threw on character live-overwrite");
450
+ }
451
+ }
452
+ logger.info({ ...totals, activeSessions: sessions.length }, "Character block fanned out to active session workdirs");
453
+ }
454
+ // ── Config API ──
455
+ /** GET /config — return current configuration */
456
+ app.get("/config", async (c) => {
457
+ const secretSummary = await getSecretConfigSummary();
458
+ const safeConfig = buildSafeConfig({ ...config, agentDisplayName: normalizeAgentDisplayName(config.agentDisplayName) }, secretSummary);
459
+ return c.json(safeConfig);
460
+ });
461
+ /** GET /config/defaults — return Zod schema defaults for all editable keys */
462
+ app.get("/config/defaults", (c) => {
463
+ const zodDefaults = runtimeSettingsSchema.parse({});
464
+ const defaults = {};
465
+ for (const key of EDITABLE_RUNTIME_KEY_TUPLE) {
466
+ const val = zodDefaults[key];
467
+ // Mirror GET /config shape: allowedToolsOverride null → empty array
468
+ if (key === "allowedToolsOverride") {
469
+ defaults.allowedTools = val ?? [];
470
+ }
471
+ else {
472
+ defaults[key] = val;
473
+ }
474
+ }
475
+ // Bootstrap keys not in runtimeSettingsSchema
476
+ defaults.apiPort = 8321;
477
+ return c.json(defaults);
478
+ });
479
+ /** PATCH /config — update one or more config fields */
480
+ app.patch("/config", async (c) => {
481
+ const parsedBody = await readJsonBody(c);
482
+ if (!parsedBody.ok)
483
+ return parsedBody.response;
484
+ const body = parsedBody.body;
485
+ if (!body || typeof body !== "object" || Array.isArray(body)) {
486
+ return c.json({ error: "Body must be a JSON object" }, 400);
487
+ }
488
+ const bodyRecord = { ...body };
489
+ if (Object.hasOwn(bodyRecord, "notionDatabaseIdsBase")) {
490
+ if (!Object.hasOwn(bodyRecord, "notionDatabaseIds")) {
491
+ return c.json({
492
+ error: "validation_failed",
493
+ details: {
494
+ notionDatabaseIdsBase: "notionDatabaseIdsBase requires notionDatabaseIds in the same request",
495
+ },
496
+ }, 400);
497
+ }
498
+ if (!isStringRecord(bodyRecord.notionDatabaseIdsBase)) {
499
+ return c.json({
500
+ error: "validation_failed",
501
+ details: {
502
+ notionDatabaseIdsBase: "notionDatabaseIdsBase must be an object mapping labels to database IDs",
503
+ },
504
+ }, 400);
505
+ }
506
+ if (!sameStringRecord(config.notionDatabaseIds, bodyRecord.notionDatabaseIdsBase)) {
507
+ return c.json({
508
+ error: "conflict",
509
+ message: "Notion database mappings changed on another tab. Reload and try again.",
510
+ }, 409);
511
+ }
512
+ delete bodyRecord.notionDatabaseIdsBase;
513
+ }
514
+ // Snapshot WhatsApp state BEFORE applying so we can detect a transition
515
+ // and trigger live enable/disable of the adapter (no daemon restart).
516
+ const prevWhatsappEnabled = config.whatsappEnabled;
517
+ const prevWhatsappOwnerPhone = config.whatsappOwnerPhone;
518
+ const prevWhatsappAuthDir = config.whatsappAuthDir;
519
+ // EXECUTION-MODE-DESIGN.md §5.2 / §6.3 — snapshot pre-apply execution mode
520
+ // so audit rows below can capture before → after per backend. The
521
+ // dedicated `POST /api/setup/mode` is the usual path (it emits its own
522
+ // audit row); this PATCH covers the power-user / env-style API caller
523
+ // who edits the key directly without going through the settings UI.
524
+ const prevExecMode = {
525
+ claude: config.claudeExecutionPermissionMode,
526
+ codex: config.codexExecutionPermissionMode,
527
+ gemini: config.geminiExecutionPermissionMode,
528
+ };
529
+ // design/15-character.md §15.6.1 — snapshot character pre-apply so the
530
+ // live-overwrite pass below has a stable "after" value to fan out to
531
+ // every active session workdir.
532
+ const prevCharacter = config.character;
533
+ // gitRepos / gitWatchedRepos no longer live in config — repository
534
+ // changes go through /api/repositories and trigger
535
+ // `onGitReposChanged` directly from that route.
536
+ // §6.2 Note Sources regeneration is centralized inside
537
+ // applyConfigUpdates (via the db option) — no inline hook in this
538
+ // handler. Any future caller of applyConfigUpdates that carries
539
+ // externalObsidianVaultPath / externalObsidianWatch automatically
540
+ // gets the same regeneration without copy-paste.
541
+ const result = await applyConfigUpdates(config, settingsStore, bodyRecord, {
542
+ db: deps.db,
543
+ });
544
+ if (Object.keys(result.errors).length > 0 && result.updated.length === 0) {
545
+ return c.json({ error: "validation_failed", details: result.errors }, 400);
546
+ }
547
+ // Hot-reload cron schedules when schedule-related config changes
548
+ const SCHEDULE_KEYS = [
549
+ "dayBoundaryHour",
550
+ "timezone",
551
+ "hourlyCheckEnabled",
552
+ "hourlyCheckIntervalMinutes",
553
+ "hourlyCheckActiveStartHour",
554
+ "hourlyCheckActiveEndHour",
555
+ ];
556
+ if (result.updated.some((k) => SCHEDULE_KEYS.includes(k))) {
557
+ deps.onScheduleConfigChanged?.();
558
+ }
559
+ // git repository changes route through POST/PATCH /api/repositories
560
+ // (unified-repositories cutover); they trigger onGitReposChanged
561
+ // from there, not from the dashboard config PATCH path.
562
+ // SCHEDULED-DM-IMPLEMENTATION-PLAN §6.7 — when quietHoursEnd
563
+ // changes, retime every enabled `dm_session` recurring row whose
564
+ // `task_context.pin_to_quiet_hours_end === true` so the briefing
565
+ // tracks the user's quiet-hours edge by default. Rows with the
566
+ // pin flag false (user-pinned a custom time) are left alone.
567
+ if (result.updated.includes("quietHoursEnd")
568
+ && typeof config.quietHoursEnd === "string"
569
+ && /^\d{2}:\d{2}$/.test(config.quietHoursEnd)) {
570
+ try {
571
+ syncDmSessionTimesToQuietHours(db, config.quietHoursEnd);
572
+ runDefaultSchedulesReconciler({
573
+ db,
574
+ contextDir: getContextDir(config, db),
575
+ writeTracker: deps.writeTracker,
576
+ onPromptContextChanged: deps.onPromptContextChanged,
577
+ trigger: "manual",
578
+ }).catch((err) => {
579
+ logger.warn({ err }, "Default-schedules reconciler failed after quietHoursEnd change");
580
+ });
581
+ }
582
+ catch (err) {
583
+ logger.warn({ err }, "syncDmSessionTimesToQuietHours threw after dashboard config PATCH");
584
+ }
585
+ }
586
+ // Hot-refresh DM session skill dirs when enabledMailProviders changes
587
+ // through the generic config PATCH. The per-endpoint `PATCH /mail/providers`
588
+ // handler already drives this through MailAccountRegistry.onScopeChanged,
589
+ // but the dashboard's catch-all config PATCH bypasses that route, so
590
+ // without this dispatch the scope toggle wouldn't reach active workdirs.
591
+ if (result.updated.includes("enabledMailProviders")) {
592
+ try {
593
+ deps.services.mail?.onProviderSelectionChanged(config.enabledMailProviders);
594
+ }
595
+ catch (err) {
596
+ logger.warn({ err }, "onProviderSelectionChanged threw after dashboard config PATCH");
597
+ }
598
+ }
599
+ // Hot-reload WhatsApp adapter when whatsappEnabled / phone / auth dir change.
600
+ // This eliminates the daemon-restart requirement that previously made
601
+ // pairing impossible from the dashboard.
602
+ const whatsappKeysTouched = result.updated.some((k) => ["whatsappEnabled", "whatsappOwnerPhone", "whatsappAuthDir"].includes(k));
603
+ if (whatsappKeysTouched && deps.whatsappControls) {
604
+ const phoneChanged = config.whatsappOwnerPhone !== prevWhatsappOwnerPhone;
605
+ const authDirChanged = config.whatsappAuthDir !== prevWhatsappAuthDir;
606
+ try {
607
+ if (!config.whatsappEnabled && prevWhatsappEnabled) {
608
+ // disabled — tear down
609
+ await deps.whatsappControls.disable();
610
+ }
611
+ else if (config.whatsappEnabled) {
612
+ if (!prevWhatsappEnabled) {
613
+ // newly enabled — build and start
614
+ await deps.whatsappControls.enable();
615
+ }
616
+ else if (phoneChanged || authDirChanged) {
617
+ // settings changed while enabled — bounce
618
+ await deps.whatsappControls.disable();
619
+ await deps.whatsappControls.enable();
620
+ }
621
+ }
622
+ // Drop "whatsappEnabled" / phone / auth dir from requiresRestart since
623
+ // we just hot-reloaded them. Other restart-required keys (like Slack
624
+ // tokens) still report restart.
625
+ result.requiresRestart = result.requiresRestart.filter((k) => !["whatsappEnabled", "whatsappOwnerPhone", "whatsappAuthDir"].includes(k));
626
+ }
627
+ catch (err) {
628
+ const message = toSafeErrorMessage(err, "unknown WhatsApp error");
629
+ result.errors.whatsapp = `WhatsApp hot-reload failed: ${message}`;
630
+ }
631
+ }
632
+ // EXECUTION-MODE-DESIGN.md §6.3 — emit one `execution_mode_changed`
633
+ // audit row per backend whose mode moved through this PATCH, matching
634
+ // the row shape that `POST /api/setup/mode` writes. Without this the
635
+ // PATCH path would silently bypass audit coverage for a power-user
636
+ // API caller.
637
+ for (const [backend, key] of [
638
+ ["claude", "claudeExecutionPermissionMode"],
639
+ ["codex", "codexExecutionPermissionMode"],
640
+ ["gemini", "geminiExecutionPermissionMode"],
641
+ ]) {
642
+ if (!result.updated.includes(key))
643
+ continue;
644
+ const before = prevExecMode[backend];
645
+ const after = config[key];
646
+ if (before === after)
647
+ continue;
648
+ try {
649
+ db.prepare(`INSERT INTO agent_actions (action_type, trigger, result, detail, backend)
650
+ VALUES (?, ?, ?, ?, ?)`).run("execution_mode_changed", "dashboard_config_patch", "success", JSON.stringify({ before, after }), backend);
651
+ }
652
+ catch (err) {
653
+ logger.warn({ err, backend }, "failed to record execution_mode_changed audit row (PATCH path)");
654
+ }
655
+ }
656
+ if (result.updated.includes("agentDisplayName")) {
657
+ try {
658
+ const rulesRelPath = CONTEXT_RELATIVE_PATHS.rules.management;
659
+ const rulesSnapshotKey = rulesRelPath.replace(/\.md$/, "");
660
+ const rulesPath = join(getContextDir(config, db), rulesRelPath);
661
+ if (existsSync(rulesPath)) {
662
+ const currentRules = readFileSync(rulesPath, "utf-8");
663
+ const nextRules = upsertManagementRulesAgentIdentity(currentRules, normalizeAgentDisplayName(config.agentDisplayName));
664
+ if (nextRules !== currentRules) {
665
+ db.prepare("INSERT INTO md_file_snapshots (file_path, content, trigger) VALUES (?, ?, ?)").run(rulesSnapshotKey, currentRules, "agent_name_update");
666
+ writeFileSync(rulesPath, nextRules, "utf-8");
667
+ }
668
+ }
669
+ }
670
+ catch (err) {
671
+ const message = toSafeErrorMessage(err, `unknown ${CONTEXT_RELATIVE_PATHS.rules.management} error`);
672
+ result.errors.agentDisplayName = `Saved config, but failed to sync ${CONTEXT_RELATIVE_PATHS.rules.management}: ${message}`;
673
+ }
674
+ deps.onPromptContextChanged?.("agentDisplayName", "config_update:agentDisplayName", "loud", { tierReason: "config_agent_display_name" });
675
+ }
676
+ // design/15-character.md §15.6.1 — character changed; fan the new value
677
+ // out to every active session's instruction files.
678
+ if (result.updated.includes("character") && config.character !== prevCharacter) {
679
+ fanOutCharacterToActiveSessions();
680
+ }
681
+ return c.json({
682
+ status: "updated",
683
+ updated: result.updated,
684
+ requiresRestart: result.requiresRestart,
685
+ errors: result.errors,
686
+ });
687
+ });
688
+ /**
689
+ * GET /config/character — agent-callable read of the persona string.
690
+ *
691
+ * design/15-character.md §15.6 — the general /api/config surface is
692
+ * Approve-tier (contains secret summaries, OAuth state, schedule keys),
693
+ * so bearer-less callers (the agent's curl from a session workdir) need
694
+ * a narrowly scoped read. Returns the single field shape `{character}`
695
+ * so `jq .character` in skills keeps working.
696
+ */
697
+ app.get("/config/character", (c) => {
698
+ return c.json({ character: config.character });
699
+ });
700
+ /**
701
+ * PATCH /config/character — agent-callable write of the persona string.
702
+ *
703
+ * Notify tier: audit-logged by the auth middleware, no Bearer required.
704
+ * Accepts only `{character: string}` — extra keys are rejected so this
705
+ * route cannot be used as a side channel into other config fields.
706
+ * Zod validation (max 1000 chars, no marker substring, non-blank-or-empty)
707
+ * runs inside `applyConfigUpdates` as usual.
708
+ */
709
+ app.patch("/config/character", async (c) => {
710
+ const parsedBody = await readJsonBody(c);
711
+ if (!parsedBody.ok)
712
+ return parsedBody.response;
713
+ const body = parsedBody.body;
714
+ if (!body || typeof body !== "object" || Array.isArray(body)) {
715
+ return c.json({ error: "Body must be a JSON object" }, 400);
716
+ }
717
+ const bodyRecord = body;
718
+ const extraKeys = Object.keys(bodyRecord).filter((k) => k !== "character");
719
+ if (extraKeys.length > 0) {
720
+ return c.json({
721
+ error: "validation_failed",
722
+ details: {
723
+ _extraKeys: `Only "character" is accepted on this endpoint; got: ${extraKeys.join(", ")}`,
724
+ },
725
+ }, 400);
726
+ }
727
+ if (!Object.hasOwn(bodyRecord, "character")) {
728
+ return c.json({
729
+ error: "validation_failed",
730
+ details: { character: "character field is required" },
731
+ }, 400);
732
+ }
733
+ const prevCharacter = config.character;
734
+ const result = await applyConfigUpdates(config, settingsStore, {
735
+ character: bodyRecord.character,
736
+ });
737
+ if (Object.keys(result.errors).length > 0 && result.updated.length === 0) {
738
+ return c.json({ error: "validation_failed", details: result.errors }, 400);
739
+ }
740
+ if (result.updated.includes("character") && config.character !== prevCharacter) {
741
+ fanOutCharacterToActiveSessions();
742
+ }
743
+ return c.json({
744
+ status: "updated",
745
+ character: config.character,
746
+ updated: result.updated,
747
+ errors: result.errors,
748
+ });
749
+ });
750
+ app.put("/secrets/slack", async (c) => {
751
+ const parsedBody = await readJsonBody(c);
752
+ if (!parsedBody.ok)
753
+ return parsedBody.response;
754
+ const body = parsedBody.body;
755
+ const botToken = typeof body?.botToken === "string" ? body.botToken.trim() : "";
756
+ const appToken = typeof body?.appToken === "string" ? body.appToken.trim() : "";
757
+ const validationErrors = {};
758
+ if (!botToken && !appToken) {
759
+ return c.json({
760
+ status: "validation_failed",
761
+ configured: false,
762
+ requiresRestart: false,
763
+ validationErrors: {
764
+ botToken: "Provide at least one Slack token to save.",
765
+ appToken: "Provide at least one Slack token to save.",
766
+ },
767
+ }, 400);
768
+ }
769
+ if (botToken)
770
+ await secretBroker.set("slackBotToken", botToken);
771
+ if (appToken)
772
+ await secretBroker.set("slackAppToken", appToken);
773
+ await notifySecretChange("slack");
774
+ return c.json({
775
+ status: "updated",
776
+ configured: (await getSecretConfigSummary()).slackConfigured,
777
+ requiresRestart: false,
778
+ validationErrors,
779
+ });
780
+ });
781
+ app.put("/secrets/telegram", async (c) => {
782
+ const parsedBody = await readJsonBody(c);
783
+ if (!parsedBody.ok)
784
+ return parsedBody.response;
785
+ const body = parsedBody.body;
786
+ const botToken = typeof body?.botToken === "string" ? body.botToken.trim() : "";
787
+ if (!botToken) {
788
+ return c.json({
789
+ status: "validation_failed",
790
+ configured: false,
791
+ requiresRestart: false,
792
+ validationErrors: { botToken: "Telegram bot token is required." },
793
+ }, 400);
794
+ }
795
+ await secretBroker.set("telegramBotToken", botToken);
796
+ await notifySecretChange("telegram");
797
+ return c.json({
798
+ status: "updated",
799
+ configured: (await getSecretConfigSummary()).telegramConfigured,
800
+ requiresRestart: false,
801
+ validationErrors: {},
802
+ });
803
+ });
804
+ app.put("/secrets/discord", async (c) => {
805
+ const parsedBody = await readJsonBody(c);
806
+ if (!parsedBody.ok)
807
+ return parsedBody.response;
808
+ const body = parsedBody.body;
809
+ const botToken = typeof body?.botToken === "string" ? body.botToken.trim() : "";
810
+ if (!botToken) {
811
+ return c.json({
812
+ status: "validation_failed",
813
+ configured: false,
814
+ requiresRestart: false,
815
+ validationErrors: { botToken: "Discord bot token is required." },
816
+ }, 400);
817
+ }
818
+ await secretBroker.set("discordBotToken", botToken);
819
+ await notifySecretChange("discord");
820
+ return c.json({
821
+ status: "updated",
822
+ configured: (await getSecretConfigSummary()).discordConfigured,
823
+ requiresRestart: false,
824
+ validationErrors: {},
825
+ });
826
+ });
827
+ app.put("/secrets/notion", async (c) => {
828
+ const parsedBody = await readJsonBody(c);
829
+ if (!parsedBody.ok)
830
+ return parsedBody.response;
831
+ const body = parsedBody.body;
832
+ const apiKey = typeof body?.apiKey === "string" ? body.apiKey.trim() : "";
833
+ if (!apiKey) {
834
+ return c.json({
835
+ status: "validation_failed",
836
+ configured: false,
837
+ requiresRestart: false,
838
+ validationErrors: { apiKey: "Notion API key is required." },
839
+ }, 400);
840
+ }
841
+ await secretBroker.set("notionApiKey", apiKey);
842
+ await notifySecretChange("notion");
843
+ return c.json({
844
+ status: "updated",
845
+ configured: (await getSecretConfigSummary()).notionConfigured,
846
+ requiresRestart: false,
847
+ validationErrors: {},
848
+ });
849
+ });
850
+ app.put("/secrets/github", async (c) => {
851
+ const parsedBody = await readJsonBody(c);
852
+ if (!parsedBody.ok)
853
+ return parsedBody.response;
854
+ const body = parsedBody.body;
855
+ const token = typeof body?.token === "string" ? body.token.trim() : "";
856
+ const webhookSecret = typeof body?.webhookSecret === "string" ? body.webhookSecret.trim() : "";
857
+ if (!token && !webhookSecret) {
858
+ return c.json({
859
+ status: "validation_failed",
860
+ configured: false,
861
+ requiresRestart: false,
862
+ validationErrors: {
863
+ token: "Provide a GitHub token and/or webhook secret.",
864
+ webhookSecret: "Provide a GitHub token and/or webhook secret.",
865
+ },
866
+ }, 400);
867
+ }
868
+ if (token)
869
+ await secretBroker.set("githubToken", token);
870
+ if (webhookSecret)
871
+ await secretBroker.set("githubWebhookSecret", webhookSecret);
872
+ await notifySecretChange("github");
873
+ const summary = await getSecretConfigSummary();
874
+ return c.json({
875
+ status: "updated",
876
+ configured: summary.githubConfigured || summary.githubWebhookSecretConfigured,
877
+ requiresRestart: false,
878
+ validationErrors: {},
879
+ });
880
+ });
881
+ app.put("/secrets/google/credentials", async (c) => {
882
+ const parsedBody = await readJsonBody(c);
883
+ if (!parsedBody.ok)
884
+ return parsedBody.response;
885
+ const body = parsedBody.body;
886
+ const raw = typeof body?.json === "string" ? body.json : "";
887
+ if (!raw) {
888
+ return c.json({
889
+ status: "validation_failed",
890
+ configured: false,
891
+ requiresRestart: false,
892
+ validationErrors: { json: "Credentials JSON is required." },
893
+ }, 400);
894
+ }
895
+ let parsed;
896
+ try {
897
+ parsed = JSON.parse(raw);
898
+ }
899
+ catch {
900
+ return c.json({
901
+ status: "validation_failed",
902
+ configured: false,
903
+ requiresRestart: false,
904
+ validationErrors: { json: "Invalid JSON file" },
905
+ }, 400);
906
+ }
907
+ if (!parsed.installed && !parsed.web && parsed.type !== "service_account") {
908
+ return c.json({
909
+ status: "validation_failed",
910
+ configured: false,
911
+ requiresRestart: false,
912
+ validationErrors: {
913
+ json: "Invalid credentials format. Expected OAuth2 credentials JSON or a service account JSON.",
914
+ },
915
+ }, 400);
916
+ }
917
+ await secretBroker.set("googleCredentialsJson", raw);
918
+ if (parsed.type === "service_account") {
919
+ await secretBroker.delete("googleTokenJson");
920
+ }
921
+ await notifySecretChange("google");
922
+ deps.onGoogleServicesReady?.();
923
+ const summary = await getSecretConfigSummary();
924
+ return c.json({
925
+ status: "updated",
926
+ configured: summary.googleCalendarCredentialsConfigured,
927
+ requiresRestart: false,
928
+ validationErrors: {},
929
+ });
930
+ });
931
+ app.put("/secrets/google/token", async (c) => {
932
+ const parsedBody = await readJsonBody(c);
933
+ if (!parsedBody.ok)
934
+ return parsedBody.response;
935
+ const body = parsedBody.body;
936
+ const raw = typeof body?.json === "string" ? body.json : "";
937
+ if (!raw) {
938
+ return c.json({
939
+ status: "validation_failed",
940
+ configured: false,
941
+ requiresRestart: false,
942
+ validationErrors: { json: "Token JSON is required." },
943
+ }, 400);
944
+ }
945
+ try {
946
+ JSON.parse(raw);
947
+ }
948
+ catch {
949
+ return c.json({
950
+ status: "validation_failed",
951
+ configured: false,
952
+ requiresRestart: false,
953
+ validationErrors: { json: "Invalid JSON file" },
954
+ }, 400);
955
+ }
956
+ await secretBroker.saveGoogleTokenJson(raw);
957
+ await notifySecretChange("google");
958
+ deps.onGoogleServicesReady?.();
959
+ const summary = await getSecretConfigSummary();
960
+ return c.json({
961
+ status: "updated",
962
+ configured: summary.googleCalendarTokenConfigured,
963
+ requiresRestart: false,
964
+ validationErrors: {},
965
+ });
966
+ });
967
+ app.delete("/secrets/:name", async (c) => {
968
+ const name = c.req.param("name");
969
+ if (name === "apiToken") {
970
+ return c.json({
971
+ error: "api_token_not_deletable",
972
+ message: "The daemon API token cannot be deleted from the API. Rotate it explicitly instead.",
973
+ }, 400);
974
+ }
975
+ const secretNameByParam = {
976
+ slackBotToken: "slackBotToken",
977
+ slackAppToken: "slackAppToken",
978
+ telegramBotToken: "telegramBotToken",
979
+ discordBotToken: "discordBotToken",
980
+ notionApiKey: "notionApiKey",
981
+ githubToken: "githubToken",
982
+ githubWebhookSecret: "githubWebhookSecret",
983
+ googleCredentialsJson: "googleCredentialsJson",
984
+ googleTokenJson: "googleTokenJson",
985
+ };
986
+ const secretName = secretNameByParam[name];
987
+ if (!secretName) {
988
+ return c.json({ error: "unknown_secret" }, 404);
989
+ }
990
+ await secretBroker.delete(secretName);
991
+ const scopeBySecret = {
992
+ slackBotToken: "slack",
993
+ slackAppToken: "slack",
994
+ telegramBotToken: "telegram",
995
+ discordBotToken: "discord",
996
+ notionApiKey: "notion",
997
+ githubToken: "github",
998
+ githubWebhookSecret: "github",
999
+ googleCredentialsJson: "google",
1000
+ googleTokenJson: "google",
1001
+ };
1002
+ await notifySecretChange(scopeBySecret[secretName]);
1003
+ return c.json({
1004
+ status: "deleted",
1005
+ configured: false,
1006
+ requiresRestart: false,
1007
+ validationErrors: {},
1008
+ });
1009
+ });
1010
+ app.get("/dashboard/next-check", (c) => {
1011
+ return c.json(getNextHourlyCheck(config));
1012
+ });
1013
+ // STAGE-C-DM-FRESHNESS-PLAN §Task 4 — DM freshness aggregate. Powered
1014
+ // by `agent_actions.detail.dm_freshness.*` rows the DM dispatch path
1015
+ // writes via AuditLogger.logAction. Window defaults to 7 days; query
1016
+ // param `days` overrides for ad-hoc inspection (clamped to 1..90).
1017
+ app.get("/dashboard/dm-freshness", (c) => {
1018
+ const daysParam = c.req.query("days");
1019
+ let windowDays = 7;
1020
+ if (daysParam !== undefined) {
1021
+ const parsed = Number(daysParam);
1022
+ if (!Number.isFinite(parsed) || parsed < 1 || parsed > 90) {
1023
+ return c.json({
1024
+ error: "invalid_window",
1025
+ message: "days must be a number between 1 and 90",
1026
+ }, 400);
1027
+ }
1028
+ windowDays = Math.round(parsed);
1029
+ }
1030
+ const aggregate = computeDmFreshnessAggregate(deps.db, windowDays);
1031
+ return c.json(aggregate);
1032
+ });
1033
+ /**
1034
+ * POST /messaging/whatsapp/pair
1035
+ *
1036
+ * Triggers Baileys pairing and waits up to ~10s for the first scannable QR.
1037
+ * If WhatsApp isn't enabled yet, returns 409 with a clear hint instead of
1038
+ * silently 404'ing — this surfaces the original setup-flow bug where users
1039
+ * clicked Pair without first enabling.
1040
+ */
1041
+ app.post("/messaging/whatsapp/pair", async (c) => {
1042
+ if (!deps.whatsappControls) {
1043
+ return c.json({ error: "whatsapp_not_available" }, 404);
1044
+ }
1045
+ if (!config.whatsappEnabled) {
1046
+ return c.json({
1047
+ error: "whatsapp_not_enabled",
1048
+ message: "Enable WhatsApp first (toggle the Enable button), then click Pair.",
1049
+ }, 409);
1050
+ }
1051
+ if (!config.whatsappOwnerPhone) {
1052
+ return c.json({
1053
+ error: "whatsapp_phone_missing",
1054
+ message: "Set the owner phone (E.164, e.g. +818012345678) and save before pairing.",
1055
+ }, 409);
1056
+ }
1057
+ try {
1058
+ const response = await deps.whatsappControls.waitForQr(10_000);
1059
+ return c.json(response);
1060
+ }
1061
+ catch (err) {
1062
+ const message = toSafeErrorMessage(err, "Unknown WhatsApp error");
1063
+ return c.json({
1064
+ error: "whatsapp_pair_failed",
1065
+ message,
1066
+ state: deps.whatsappControls.getQrResponse().state,
1067
+ }, 500);
1068
+ }
1069
+ });
1070
+ /**
1071
+ * GET /messaging/whatsapp/qr
1072
+ *
1073
+ * Returns the current QR snapshot WITHOUT triggering a fresh pair flow.
1074
+ * Dashboard polls this every ~3s while pairing is in progress so the user
1075
+ * always sees the latest QR (Baileys rotates them every ~20s).
1076
+ */
1077
+ app.get("/messaging/whatsapp/qr", (c) => {
1078
+ if (!deps.whatsappControls) {
1079
+ return c.json({ error: "whatsapp_not_available" }, 404);
1080
+ }
1081
+ const response = deps.whatsappControls.getQrResponse();
1082
+ return c.json({
1083
+ ...response,
1084
+ error: response.error ? toSafeErrorMessage(response.error) : null,
1085
+ });
1086
+ });
1087
+ /**
1088
+ * GET /messaging/whatsapp/status
1089
+ *
1090
+ * Lightweight health probe — connection state + last error, no QR fetch.
1091
+ */
1092
+ app.get("/messaging/whatsapp/status", (c) => {
1093
+ if (!deps.whatsappControls) {
1094
+ return c.json({ error: "whatsapp_not_available" }, 404);
1095
+ }
1096
+ const response = deps.whatsappControls.getQrResponse();
1097
+ return c.json({
1098
+ enabled: config.whatsappEnabled,
1099
+ initialized: deps.whatsappControls.isInitialized(),
1100
+ state: response.state,
1101
+ error: response.error ? toSafeErrorMessage(response.error) : null,
1102
+ });
1103
+ });
1104
+ // ── Telegram pairing ──────────────────────────────────────────────────
1105
+ //
1106
+ // Three endpoints support the dashboard's QR-deep-link pairing flow:
1107
+ // POST /messaging/telegram/test-token — getMe (validate token)
1108
+ // POST /messaging/telegram/start-pairing — generate token + QR + deep link
1109
+ // GET /messaging/telegram/pairing-status — poll until paired
1110
+ //
1111
+ // The QR encodes `https://t.me/<bot>?start=<token>`. When the user scans
1112
+ // it, Telegram opens the bot and sends `/start <token>`; the adapter
1113
+ // matches the token, captures the chat ID via discovery mode, and the
1114
+ // daemon writes the ID into .env via the onOwnerDetected callback.
1115
+ app.post("/messaging/telegram/test-token", async (c) => {
1116
+ if (!deps.messagingControls?.telegram) {
1117
+ return c.json({ error: "telegram_not_configured" }, 404);
1118
+ }
1119
+ // Accept an optional candidate token in the request body so the
1120
+ // dashboard can validate an UNSAVED draft before persisting it.
1121
+ const body = await c.req.json().catch(() => ({}));
1122
+ const candidate = typeof body?.token === "string" && body.token.length > 0
1123
+ ? body.token
1124
+ : undefined;
1125
+ try {
1126
+ const info = await deps.messagingControls.telegram.testToken(candidate);
1127
+ return c.json(info);
1128
+ }
1129
+ catch (err) {
1130
+ return c.json({
1131
+ error: "telegram_test_failed",
1132
+ message: toSafeErrorMessage(err, "Telegram token validation failed"),
1133
+ }, 400);
1134
+ }
1135
+ });
1136
+ app.post("/messaging/telegram/start-pairing", async (c) => {
1137
+ if (!deps.messagingControls?.telegram) {
1138
+ return c.json({ error: "telegram_not_configured" }, 404);
1139
+ }
1140
+ try {
1141
+ const result = await deps.messagingControls.telegram.startPairing();
1142
+ return c.json(result);
1143
+ }
1144
+ catch (err) {
1145
+ return c.json({
1146
+ error: "telegram_pair_start_failed",
1147
+ message: toSafeErrorMessage(err, "Telegram pairing could not start"),
1148
+ }, 500);
1149
+ }
1150
+ });
1151
+ app.get("/messaging/telegram/pairing-status", (c) => {
1152
+ if (!deps.messagingControls?.telegram) {
1153
+ return c.json({ error: "telegram_not_configured" }, 404);
1154
+ }
1155
+ return c.json(deps.messagingControls.telegram.getPairingStatus());
1156
+ });
1157
+ app.post("/messaging/telegram/cancel-pairing", (c) => {
1158
+ if (!deps.messagingControls?.telegram) {
1159
+ return c.json({ error: "telegram_not_configured" }, 404);
1160
+ }
1161
+ deps.messagingControls.telegram.cancelPairing();
1162
+ return c.json({ status: "cancelled" });
1163
+ });
1164
+ // ── Slack pairing ─────────────────────────────────────────────────────
1165
+ //
1166
+ // Slack has no QR/deep-link mechanism, so we offer two helpers:
1167
+ // 1. Token validation via auth.test
1168
+ // 2. A pre-built app manifest (one-click app creation at api.slack.com)
1169
+ // 3. Discovery mode for owner user ID — user DMs the bot, daemon captures
1170
+ //
1171
+ // The manifest uses Aitne's required scopes (im:history,
1172
+ // chat:write, app_mentions:read) + Socket Mode + bot scopes. We do NOT
1173
+ // include any oauth_redirect_url since Socket Mode bots don't need one.
1174
+ app.post("/messaging/slack/test-token", async (c) => {
1175
+ if (!deps.messagingControls?.slack) {
1176
+ return c.json({ error: "slack_not_configured" }, 404);
1177
+ }
1178
+ const body = await c.req.json().catch(() => ({}));
1179
+ const candidate = typeof body?.token === "string" && body.token.length > 0
1180
+ ? body.token
1181
+ : undefined;
1182
+ try {
1183
+ const info = await deps.messagingControls.slack.testToken(candidate);
1184
+ return c.json(info);
1185
+ }
1186
+ catch (err) {
1187
+ return c.json({
1188
+ error: "slack_test_failed",
1189
+ message: toSafeErrorMessage(err, "Slack token validation failed"),
1190
+ }, 400);
1191
+ }
1192
+ });
1193
+ app.get("/messaging/slack/manifest", (c) => {
1194
+ // App manifest in JSON form. Slack supports both YAML and JSON in the
1195
+ // `?manifest_json=` and `?manifest_yaml=` query params on the new-app
1196
+ // create page (https://docs.slack.dev/app-manifests/...).
1197
+ //
1198
+ // Scope minimization (intentional, do not re-broaden):
1199
+ // - app_mentions:read — for @mentions in channels the user invited the bot to
1200
+ // - chat:write — required to send messages
1201
+ // - files:read — required to download user-uploaded files
1202
+ // - im:history — required to receive `message.im` events
1203
+ // - im:read — list/inspect direct-message channels
1204
+ // - im:write — open a DM channel with the owner
1205
+ //
1206
+ // We DELIBERATELY OMIT:
1207
+ // - channels:history — would let the bot read every message in every
1208
+ // channel it's added to. Aitne only DMs,
1209
+ // so this scope is pure attack surface.
1210
+ // - users:read — not needed; resolveUserChannel() uses
1211
+ // conversations.open with the configured user ID.
1212
+ const manifest = {
1213
+ display_information: {
1214
+ name: APP_NAME,
1215
+ description: "Local-first proactive assistant",
1216
+ background_color: "#1a1a2e",
1217
+ },
1218
+ features: {
1219
+ bot_user: {
1220
+ display_name: APP_NAME,
1221
+ always_online: true,
1222
+ },
1223
+ },
1224
+ oauth_config: {
1225
+ scopes: {
1226
+ bot: [
1227
+ "app_mentions:read",
1228
+ "chat:write",
1229
+ "files:read",
1230
+ "im:history",
1231
+ "im:read",
1232
+ "im:write",
1233
+ ],
1234
+ },
1235
+ },
1236
+ settings: {
1237
+ event_subscriptions: {
1238
+ bot_events: ["app_mention", "message.im"],
1239
+ },
1240
+ interactivity: { is_enabled: false },
1241
+ org_deploy_enabled: false,
1242
+ socket_mode_enabled: true,
1243
+ token_rotation_enabled: false,
1244
+ },
1245
+ };
1246
+ const manifestJson = JSON.stringify(manifest);
1247
+ // Slack's "create app from manifest" deep link.
1248
+ const createAppUrl = `https://api.slack.com/apps?new_app=1&manifest_json=${encodeURIComponent(manifestJson)}`;
1249
+ return c.json({
1250
+ manifest,
1251
+ manifestJson,
1252
+ createAppUrl,
1253
+ instructions: [
1254
+ "1. Click 'Open Slack app builder' below — Slack will pre-fill the manifest.",
1255
+ "2. On the app page, scroll to 'Install App' and click Install to your workspace.",
1256
+ "3. Copy the Bot User OAuth Token (xoxb-…) from 'OAuth & Permissions' into the field below.",
1257
+ "4. Generate an App-Level Token (xapp-…) under 'Basic Information' → 'App-Level Tokens' with `connections:write` scope, paste it below.",
1258
+ "5. Click Save Slack Config, then 'Generate pairing phrase' and DM the bot with the phrase.",
1259
+ ],
1260
+ });
1261
+ });
1262
+ /**
1263
+ * POST /messaging/slack/start-pairing
1264
+ *
1265
+ * Generates a fresh magic phrase, registers it as the Slack adapter's
1266
+ * pairing challenge, and returns it to the dashboard. The user must
1267
+ * include this phrase in the next DM they send to the bot — only that
1268
+ * matching DM captures the owner role. The previous "enable-discovery"
1269
+ * endpoint was vulnerable to a 5-minute race where any DM could
1270
+ * hijack ownership; the magic phrase closes that.
1271
+ */
1272
+ app.post("/messaging/slack/start-pairing", async (c) => {
1273
+ if (!deps.messagingControls?.slack) {
1274
+ return c.json({ error: "slack_not_configured" }, 404);
1275
+ }
1276
+ try {
1277
+ const result = await deps.messagingControls.slack.startPairing();
1278
+ return c.json(result);
1279
+ }
1280
+ catch (err) {
1281
+ return c.json({
1282
+ error: "slack_pair_start_failed",
1283
+ message: toSafeErrorMessage(err, "Slack pairing could not start"),
1284
+ }, 400);
1285
+ }
1286
+ });
1287
+ app.post("/messaging/slack/cancel-pairing", (c) => {
1288
+ if (!deps.messagingControls?.slack) {
1289
+ return c.json({ error: "slack_not_configured" }, 404);
1290
+ }
1291
+ deps.messagingControls.slack.cancelPairing();
1292
+ return c.json({ status: "cancelled" });
1293
+ });
1294
+ app.get("/messaging/slack/pairing-status", (c) => {
1295
+ if (!deps.messagingControls?.slack) {
1296
+ return c.json({ error: "slack_not_configured" }, 404);
1297
+ }
1298
+ return c.json(deps.messagingControls.slack.getPairingStatus());
1299
+ });
1300
+ // ── Discord pairing ───────────────────────────────────────────────────
1301
+ //
1302
+ // Discord parity: token validation + magic-phrase pairing for owner user ID.
1303
+ app.post("/messaging/discord/test-token", async (c) => {
1304
+ if (!deps.messagingControls?.discord) {
1305
+ return c.json({ error: "discord_not_configured" }, 404);
1306
+ }
1307
+ const body = await c.req.json().catch(() => ({}));
1308
+ const candidate = typeof body?.token === "string" && body.token.length > 0
1309
+ ? body.token
1310
+ : undefined;
1311
+ try {
1312
+ const info = await deps.messagingControls.discord.testToken(candidate);
1313
+ return c.json(info);
1314
+ }
1315
+ catch (err) {
1316
+ return c.json({
1317
+ error: "discord_test_failed",
1318
+ message: toSafeErrorMessage(err, "Discord token validation failed"),
1319
+ }, 400);
1320
+ }
1321
+ });
1322
+ app.post("/messaging/discord/start-pairing", async (c) => {
1323
+ if (!deps.messagingControls?.discord) {
1324
+ return c.json({ error: "discord_not_configured" }, 404);
1325
+ }
1326
+ try {
1327
+ const result = await deps.messagingControls.discord.startPairing();
1328
+ return c.json(result);
1329
+ }
1330
+ catch (err) {
1331
+ return c.json({
1332
+ error: "discord_pair_start_failed",
1333
+ message: toSafeErrorMessage(err, "Discord pairing could not start"),
1334
+ }, 400);
1335
+ }
1336
+ });
1337
+ app.post("/messaging/discord/cancel-pairing", (c) => {
1338
+ if (!deps.messagingControls?.discord) {
1339
+ return c.json({ error: "discord_not_configured" }, 404);
1340
+ }
1341
+ deps.messagingControls.discord.cancelPairing();
1342
+ return c.json({ status: "cancelled" });
1343
+ });
1344
+ app.get("/messaging/discord/pairing-status", (c) => {
1345
+ if (!deps.messagingControls?.discord) {
1346
+ return c.json({ error: "discord_not_configured" }, 404);
1347
+ }
1348
+ return c.json(deps.messagingControls.discord.getPairingStatus());
1349
+ });
1350
+ /** POST /config/upload/google-credentials — upload Google Calendar credentials JSON */
1351
+ app.post("/config/upload/google-credentials", async (c) => {
1352
+ const body = await c.req.parseBody();
1353
+ const file = body["file"];
1354
+ if (!file || !(file instanceof File)) {
1355
+ return c.json({ error: "No file uploaded. Send as multipart with field name 'file'" }, 400);
1356
+ }
1357
+ if (file.size > MAX_UPLOAD_SIZE) {
1358
+ return c.json({ error: `File too large (max ${MAX_UPLOAD_SIZE / 1024} KB)` }, 400);
1359
+ }
1360
+ const content = await file.text();
1361
+ let parsed;
1362
+ try {
1363
+ parsed = JSON.parse(content);
1364
+ }
1365
+ catch {
1366
+ return c.json({ error: "Invalid JSON file" }, 400);
1367
+ }
1368
+ // Basic validation: must be OAuth2 (installed/web) or service account
1369
+ const obj = parsed;
1370
+ if (!obj.installed && !obj.web && obj.type !== "service_account") {
1371
+ return c.json({ error: "Invalid credentials format. Expected OAuth2 credentials JSON (with 'installed' or 'web' key) or a service account JSON." }, 400);
1372
+ }
1373
+ await secretBroker.set("googleCredentialsJson", content);
1374
+ if (parsed.type === "service_account") {
1375
+ await secretBroker.delete("googleTokenJson");
1376
+ }
1377
+ await notifySecretChange("google");
1378
+ deps.onGoogleServicesReady?.();
1379
+ return c.json({
1380
+ status: "uploaded",
1381
+ path: "keychain://google-credentials",
1382
+ requiresRestart: false,
1383
+ message: "Credentials saved.",
1384
+ });
1385
+ });
1386
+ /** POST /config/upload/google-token — upload Google Calendar OAuth token JSON */
1387
+ app.post("/config/upload/google-token", async (c) => {
1388
+ const body = await c.req.parseBody();
1389
+ const file = body["file"];
1390
+ if (!file || !(file instanceof File)) {
1391
+ return c.json({ error: "No file uploaded. Send as multipart with field name 'file'" }, 400);
1392
+ }
1393
+ if (file.size > MAX_UPLOAD_SIZE) {
1394
+ return c.json({ error: `File too large (max ${MAX_UPLOAD_SIZE / 1024} KB)` }, 400);
1395
+ }
1396
+ const content = await file.text();
1397
+ // Validate JSON
1398
+ try {
1399
+ JSON.parse(content);
1400
+ }
1401
+ catch {
1402
+ return c.json({ error: "Invalid JSON file" }, 400);
1403
+ }
1404
+ await secretBroker.saveGoogleTokenJson(content);
1405
+ await notifySecretChange("google");
1406
+ deps.onGoogleServicesReady?.();
1407
+ return c.json({
1408
+ status: "uploaded",
1409
+ path: "keychain://google-token",
1410
+ requiresRestart: false,
1411
+ message: "Token saved.",
1412
+ });
1413
+ });
1414
+ // ── Google OAuth2 Authorization Flow ──
1415
+ // Allows users to authenticate with just credentials.json — the daemon
1416
+ // handles the full OAuth2 flow and saves the token automatically.
1417
+ /** POST /config/google-auth/start — begin OAuth2 authorization */
1418
+ app.post("/config/google-auth/start", async (c) => {
1419
+ const credRaw = await secretBroker.getGoogleCredentialsJson();
1420
+ if (!credRaw) {
1421
+ return c.json({ error: "Upload credentials.json first" }, 400);
1422
+ }
1423
+ let cred;
1424
+ try {
1425
+ cred = parseGoogleCredentialsJson(credRaw);
1426
+ }
1427
+ catch {
1428
+ return c.json({ error: "Credentials JSON is invalid. Upload it again." }, 400);
1429
+ }
1430
+ // Service accounts don't need OAuth2 authorization
1431
+ if (cred.type === "service_account") {
1432
+ return c.json({ error: "Service account credentials don't require OAuth authorization. Restart the daemon to activate." }, 400);
1433
+ }
1434
+ const clientConfig = getGoogleOAuthClientConfig(cred);
1435
+ if (!clientConfig) {
1436
+ return c.json({ error: "Invalid credentials format" }, 400);
1437
+ }
1438
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1439
+ let google;
1440
+ try {
1441
+ const mod = await import("googleapis");
1442
+ google = mod.google;
1443
+ }
1444
+ catch {
1445
+ return c.json({ error: "googleapis package not installed" }, 500);
1446
+ }
1447
+ // Use daemon's own port for the OAuth callback
1448
+ const redirectUri = `http://localhost:${config.apiPort}/api/config/google-auth/callback`;
1449
+ const oauth2Client = new google.auth.OAuth2(clientConfig.client_id, clientConfig.client_secret, redirectUri);
1450
+ // Request scopes for Calendar + Gmail
1451
+ const scopes = [
1452
+ "https://www.googleapis.com/auth/calendar",
1453
+ "https://www.googleapis.com/auth/gmail.modify",
1454
+ "https://www.googleapis.com/auth/gmail.send",
1455
+ ];
1456
+ pruneOauthStates();
1457
+ const state = randomUUID();
1458
+ // Capture the dashboard origin so the callback can postMessage to the correct window
1459
+ const origin = c.req.header("origin");
1460
+ const referer = c.req.header("referer");
1461
+ const dashboardOrigin = origin
1462
+ || (referer ? new URL(referer).origin : `http://localhost:3000`);
1463
+ oauthStates.set(state, { createdAt: Date.now(), dashboardOrigin });
1464
+ const authUrl = oauth2Client.generateAuthUrl({
1465
+ access_type: "offline",
1466
+ scope: scopes,
1467
+ prompt: "consent", // Force consent to always get a refresh_token
1468
+ state,
1469
+ });
1470
+ return c.json({ authUrl, redirectUri, scopes });
1471
+ });
1472
+ /** GET /config/google-auth/callback — OAuth2 redirect handler */
1473
+ app.get("/config/google-auth/callback", async (c) => {
1474
+ const code = c.req.query("code");
1475
+ const error = c.req.query("error");
1476
+ const state = c.req.query("state");
1477
+ if (error) {
1478
+ return c.html(`<!DOCTYPE html><html><body style="font-family:system-ui;text-align:center;padding:60px">
1479
+ <h2 style="color:#dc2626">Authorization Failed</h2>
1480
+ <p>${escapeHtml(error)}</p>
1481
+ <p style="color:#666;font-size:14px">You can close this window.</p>
1482
+ </body></html>`);
1483
+ }
1484
+ pruneOauthStates();
1485
+ const stateData = state ? oauthStates.get(state) : undefined;
1486
+ if (!state || !stateData) {
1487
+ return c.html(`<!DOCTYPE html><html><body style="font-family:system-ui;text-align:center;padding:60px">
1488
+ <h2 style="color:#dc2626">Authorization Failed</h2>
1489
+ <p>Invalid or expired OAuth state.</p>
1490
+ <p style="color:#666;font-size:14px">Start the authorization flow again from the dashboard.</p>
1491
+ </body></html>`);
1492
+ }
1493
+ const { dashboardOrigin } = stateData;
1494
+ oauthStates.delete(state);
1495
+ if (!code) {
1496
+ return c.html(`<!DOCTYPE html><html><body style="font-family:system-ui;text-align:center;padding:60px">
1497
+ <h2 style="color:#dc2626">Error</h2>
1498
+ <p>No authorization code received.</p>
1499
+ </body></html>`);
1500
+ }
1501
+ // Re-create OAuth2 client from stored credentials
1502
+ const credRaw = await secretBroker.getGoogleCredentialsJson();
1503
+ if (!credRaw) {
1504
+ return c.html(`<!DOCTYPE html><html><body style="font-family:system-ui;text-align:center;padding:60px">
1505
+ <h2 style="color:#dc2626">Error</h2>
1506
+ <p>Credentials not configured.</p>
1507
+ </body></html>`);
1508
+ }
1509
+ try {
1510
+ const cred = parseGoogleCredentialsJson(credRaw);
1511
+ const clientConfig = getGoogleOAuthClientConfig(cred);
1512
+ if (!clientConfig)
1513
+ throw new Error("Invalid credentials");
1514
+ const mod = await import("googleapis");
1515
+ const google = mod.google;
1516
+ const redirectUri = `http://localhost:${config.apiPort}/api/config/google-auth/callback`;
1517
+ const oauth2Client = new google.auth.OAuth2(clientConfig.client_id, clientConfig.client_secret, redirectUri);
1518
+ // Exchange authorization code for tokens
1519
+ const { tokens } = await oauth2Client.getToken(code);
1520
+ await secretBroker.saveGoogleTokenJson(JSON.stringify(tokens));
1521
+ await notifySecretChange("google");
1522
+ deps.onGoogleServicesReady?.();
1523
+ const statusMsg = services.calendar || services.gmail
1524
+ ? "Services activated."
1525
+ : "Token saved.";
1526
+ return c.html(`<!DOCTYPE html><html><body style="font-family:system-ui;text-align:center;padding:60px">
1527
+ <h2 style="color:#059669">Authorization Successful</h2>
1528
+ <p>${escapeHtml(statusMsg)}</p>
1529
+ <p style="color:#666;font-size:14px">You can close this window.</p>
1530
+ <script>
1531
+ if (window.opener) {
1532
+ window.opener.postMessage({ type: "google-auth-success" }, ${JSON.stringify(dashboardOrigin)});
1533
+ }
1534
+ </script>
1535
+ </body></html>`);
1536
+ }
1537
+ catch (err) {
1538
+ const msg = toSafeErrorMessage(err, "Unknown error");
1539
+ return c.html(`<!DOCTYPE html><html><body style="font-family:system-ui;text-align:center;padding:60px">
1540
+ <h2 style="color:#dc2626">Token Exchange Failed</h2>
1541
+ <p>${escapeHtml(msg)}</p>
1542
+ <p style="color:#666;font-size:14px">You can close this window and try again.</p>
1543
+ </body></html>`);
1544
+ }
1545
+ });
1546
+ /** POST /config/reset-safety — reset disallowedTools to defaults */
1547
+ app.post("/config/reset-safety", async (c) => {
1548
+ const defaults = [...DEFAULT_DISALLOWED_TOOLS];
1549
+ // Actually persist the reset — update in-memory config and .env
1550
+ // Use null for allowedToolsOverride to match the Zod default (null = "no override")
1551
+ const result = await applyConfigUpdates(config, settingsStore, {
1552
+ disallowedTools: defaults,
1553
+ allowedToolsOverride: null,
1554
+ });
1555
+ return c.json({ status: "reset", disallowedTools: defaults, ...result });
1556
+ });
1557
+ // ── Events/Logs API ──
1558
+ /** GET /events — paginated event/action log */
1559
+ app.get("/events", (c) => {
1560
+ const page = Math.max(1, Number(c.req.query("page") ?? "1"));
1561
+ const limit = Math.min(Number(c.req.query("limit") ?? "50"), 100);
1562
+ const offset = (page - 1) * limit;
1563
+ const type = c.req.query("type");
1564
+ const result = c.req.query("result");
1565
+ const days = c.req.query("days"); // "1" (today), "7", "30"
1566
+ let whereClause = "WHERE 1=1";
1567
+ const params = [];
1568
+ if (type) {
1569
+ whereClause += " AND action_type = ?";
1570
+ params.push(type);
1571
+ }
1572
+ if (result) {
1573
+ whereClause += " AND result = ?";
1574
+ params.push(result);
1575
+ }
1576
+ if (days) {
1577
+ const d = Number(days);
1578
+ if (d > 0 && d <= 365) {
1579
+ // datetime(started_at) normalizes mixed ISO-8601 / SQL formats — the
1580
+ // delegated_proxy.invoke writer historically inserted ISO-with-T-and-Z
1581
+ // strings, which sort lexicographically above same-day SQL strings.
1582
+ whereClause += " AND datetime(started_at) > datetime('now', '-' || ? || ' days')";
1583
+ params.push(d);
1584
+ }
1585
+ }
1586
+ const total = db
1587
+ .prepare(`SELECT COUNT(*) as cnt FROM agent_actions ${whereClause}`)
1588
+ .get(...params);
1589
+ params.push(limit, offset);
1590
+ const rows = db
1591
+ .prepare(`SELECT id, event_id, action_type, trigger, model_used, model_usage_json, cost_usd,
1592
+ tokens_input, tokens_output,
1593
+ cache_creation_tokens, cache_read_tokens,
1594
+ duration_ms, num_turns,
1595
+ result, detail, started_at, completed_at, error
1596
+ FROM agent_actions ${whereClause}
1597
+ ORDER BY datetime(started_at) DESC, id DESC
1598
+ LIMIT ? OFFSET ?`)
1599
+ .all(...params);
1600
+ return c.json({
1601
+ events: rows,
1602
+ pagination: {
1603
+ page,
1604
+ limit,
1605
+ total: total.cnt,
1606
+ totalPages: Math.ceil(total.cnt / limit),
1607
+ },
1608
+ });
1609
+ });
1610
+ // ── Conversations API ──
1611
+ /** GET /conversations — paginated conversation sessions */
1612
+ app.get("/conversations", (c) => {
1613
+ const page = Number(c.req.query("page") ?? "1");
1614
+ const limit = Math.min(Number(c.req.query("limit") ?? "20"), 50);
1615
+ const offset = (page - 1) * limit;
1616
+ const platform = c.req.query("platform");
1617
+ const status = c.req.query("status");
1618
+ const scope = c.req.query("scope");
1619
+ const scopes = scope
1620
+ ?.split(",")
1621
+ .map((value) => value.trim())
1622
+ .filter((value) => value.length > 0);
1623
+ let whereClause = "WHERE 1=1";
1624
+ const params = [];
1625
+ if (platform) {
1626
+ whereClause += " AND platform = ?";
1627
+ params.push(platform);
1628
+ }
1629
+ if (status) {
1630
+ whereClause += " AND status = ?";
1631
+ params.push(status);
1632
+ }
1633
+ if (scopes && scopes.length > 0) {
1634
+ if (scopes.length === 1) {
1635
+ whereClause += " AND scope = ?";
1636
+ params.push(scopes[0]);
1637
+ }
1638
+ else {
1639
+ whereClause += ` AND scope IN (${scopes.map(() => "?").join(", ")})`;
1640
+ params.push(...scopes);
1641
+ }
1642
+ }
1643
+ else {
1644
+ // Default view excludes docs_qa: QA transcripts are short lookups
1645
+ // and would drown out chat in /activity. Operators opt in with the
1646
+ // explicit `?scope=docs_qa` filter chip.
1647
+ whereClause += " AND scope != ?";
1648
+ params.push(DOCS_QA_SCOPE);
1649
+ }
1650
+ const total = db
1651
+ .prepare(`SELECT COUNT(*) as cnt FROM conversation_sessions ${whereClause}`)
1652
+ .get(...params);
1653
+ params.push(limit, offset);
1654
+ const rows = db
1655
+ .prepare(`SELECT id, platform, channel_id, thread_id, scope, model, status,
1656
+ message_count, started_at, last_message_at, is_dm, backend_session_id
1657
+ FROM conversation_sessions ${whereClause}
1658
+ ORDER BY last_message_at DESC
1659
+ LIMIT ? OFFSET ?`)
1660
+ .all(...params);
1661
+ const sourcePlatformsStmt = db.prepare(`SELECT DISTINCT platform
1662
+ FROM messages
1663
+ WHERE session_id = ?
1664
+ ORDER BY CASE platform
1665
+ WHEN 'dashboard' THEN 0
1666
+ WHEN 'whatsapp' THEN 1
1667
+ WHEN 'telegram' THEN 2
1668
+ WHEN 'slack' THEN 3
1669
+ WHEN 'discord' THEN 4
1670
+ ELSE 99
1671
+ END, platform`);
1672
+ const conversations = rows.map((row) => {
1673
+ const sourcePlatforms = sourcePlatformsStmt.all(row.id).map((platformRow) => platformRow.platform);
1674
+ const normalizedSourcePlatforms = sourcePlatforms.length > 0
1675
+ ? sourcePlatforms
1676
+ : row.platform !== "owner"
1677
+ ? [row.platform]
1678
+ : [];
1679
+ const browserOnly = normalizedSourcePlatforms.length > 0
1680
+ && normalizedSourcePlatforms.every((platform) => platform === "dashboard");
1681
+ return {
1682
+ id: row.id,
1683
+ platform: row.platform,
1684
+ channel_id: row.channel_id,
1685
+ thread_id: row.thread_id,
1686
+ model: row.model,
1687
+ status: row.status,
1688
+ message_count: row.message_count,
1689
+ started_at: row.started_at,
1690
+ last_message_at: row.last_message_at,
1691
+ summary: null,
1692
+ source_platforms: normalizedSourcePlatforms,
1693
+ read_only_from_dashboard: normalizedSourcePlatforms.length === 0 ||
1694
+ normalizedSourcePlatforms.some((platform) => platform !== "dashboard"),
1695
+ // A session is continuable when the dispatcher can actually
1696
+ // execute against it — not when its stored SDK session id is
1697
+ // non-null. `continueDashboardSession` legitimately writes
1698
+ // `backend_session_id = NULL` on the `shouldInvalidateSdkSession`
1699
+ // path, and the dispatcher falls back to fresh-execute + history
1700
+ // injection for NULL backends. The real gates are: scope,
1701
+ // browser-only provenance, and the workdir surviving on disk.
1702
+ continue_available: row.scope === DASHBOARD_CHAT_SCOPE
1703
+ && browserOnly
1704
+ && existsSync(getSessionWorkdirPath(config.dataDir, row.id)),
1705
+ };
1706
+ });
1707
+ return c.json({
1708
+ conversations,
1709
+ pagination: {
1710
+ page,
1711
+ limit,
1712
+ total: total.cnt,
1713
+ totalPages: Math.ceil(total.cnt / limit),
1714
+ },
1715
+ });
1716
+ });
1717
+ /**
1718
+ * DELETE /conversations — bulk-delete every non-active sidebar session.
1719
+ * Scope is hard-coded to `dashboard_chat` + `owner_dm` (what the chat
1720
+ * sidebar shows); the live active session is filtered out so deleting
1721
+ * "all past sessions" never kills the current chat.
1722
+ */
1723
+ app.delete("/conversations", (c) => {
1724
+ const result = deleteAllChatSidebarSessions({ db, dataDir: config.dataDir });
1725
+ return c.json({ status: "deleted", deleted: result.deleted });
1726
+ });
1727
+ /** DELETE /conversations/:id — delete one non-active sidebar session. */
1728
+ app.delete("/conversations/:id", (c) => {
1729
+ const sessionId = Number(c.req.param("id"));
1730
+ if (!Number.isFinite(sessionId) || sessionId <= 0) {
1731
+ return c.json({ error: "invalid_session_id" }, 400);
1732
+ }
1733
+ const result = deleteChatSession({
1734
+ db,
1735
+ dataDir: config.dataDir,
1736
+ sessionId,
1737
+ });
1738
+ if (!result.ok) {
1739
+ return c.json({ error: "delete_failed", message: result.message }, result.status);
1740
+ }
1741
+ return c.json({ status: "deleted", deleted: result.deleted });
1742
+ });
1743
+ /** GET /conversations/:id/messages — messages for a specific conversation */
1744
+ app.get("/conversations/:id/messages", (c) => {
1745
+ const sessionId = Number(c.req.param("id"));
1746
+ const limit = Math.min(Number(c.req.query("limit") ?? "50"), 200);
1747
+ const before = c.req.query("before"); // cursor-based pagination
1748
+ let whereClause = "WHERE session_id = ?";
1749
+ const params = [sessionId];
1750
+ if (before) {
1751
+ whereClause += " AND id < ?";
1752
+ params.push(Number(before));
1753
+ }
1754
+ params.push(limit);
1755
+ const rows = db
1756
+ .prepare(`SELECT id, role, content, platform, sender_id, timestamp
1757
+ FROM messages ${whereClause}
1758
+ ORDER BY id DESC
1759
+ LIMIT ?`)
1760
+ .all(...params);
1761
+ // Chat-attachments Phase 1 — inline attachment refs per message so
1762
+ // the dashboard transcript can render thumbnails/download chips
1763
+ // alongside past messages without an extra round-trip per row.
1764
+ // Skipped when the chat_attachments table doesn't exist (older DB
1765
+ // snapshots / tests that don't run migrations).
1766
+ const hasAttachments = (() => {
1767
+ try {
1768
+ const row = db
1769
+ .prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='chat_attachments'`)
1770
+ .get();
1771
+ return row !== undefined;
1772
+ }
1773
+ catch {
1774
+ return false;
1775
+ }
1776
+ })();
1777
+ const attachmentsByMessage = new Map();
1778
+ if (hasAttachments && rows.length > 0) {
1779
+ const ids = rows.map((r) => r.id);
1780
+ const placeholders = ids.map(() => "?").join(",");
1781
+ const attachmentRows = db
1782
+ .prepare(`SELECT message_id, id, direction, original_filename, mime_type, size_bytes, caption
1783
+ FROM chat_attachments
1784
+ WHERE message_id IN (${placeholders})
1785
+ ORDER BY created_at ASC`)
1786
+ .all(...ids);
1787
+ for (const a of attachmentRows) {
1788
+ let bucket = attachmentsByMessage.get(a.message_id);
1789
+ if (!bucket) {
1790
+ bucket = [];
1791
+ attachmentsByMessage.set(a.message_id, bucket);
1792
+ }
1793
+ bucket.push({
1794
+ id: a.id,
1795
+ direction: a.direction,
1796
+ originalFilename: a.original_filename,
1797
+ mimeType: a.mime_type,
1798
+ sizeBytes: a.size_bytes,
1799
+ caption: a.caption,
1800
+ });
1801
+ }
1802
+ }
1803
+ const enriched = rows.map((row) => {
1804
+ const attachments = attachmentsByMessage.get(row.id);
1805
+ return attachments && attachments.length > 0
1806
+ ? { ...row, attachments }
1807
+ : row;
1808
+ });
1809
+ return c.json({
1810
+ messages: enriched.reverse(), // Return in chronological order
1811
+ hasMore: rows.length === limit,
1812
+ });
1813
+ });
1814
+ // ── Cost API ──
1815
+ /** GET /cost — cost analytics */
1816
+ app.get("/cost", (c) => {
1817
+ const period = c.req.query("period") ?? "daily"; // daily, weekly, monthly
1818
+ const periodKey = period in COST_QUERIES
1819
+ ? period
1820
+ : "daily";
1821
+ const queries = COST_QUERIES[periodKey];
1822
+ const spec = COST_PERIOD_SPECS[periodKey];
1823
+ const byPeriod = db.prepare(queries.byPeriod).all();
1824
+ const byModelRaw = db.prepare(queries.byModelRows).all();
1825
+ const byModel = aggregateByBilledModel(byModelRaw);
1826
+ const byEventType = db.prepare(queries.byEventType).all();
1827
+ const byBackend = db
1828
+ .prepare(`SELECT ${backendExpr} as backend,
1829
+ SUM(cost_usd) as total_cost,
1830
+ COUNT(*) as session_count
1831
+ FROM agent_actions
1832
+ WHERE started_at > datetime('now', ?)
1833
+ AND cost_usd IS NOT NULL
1834
+ GROUP BY 1
1835
+ ORDER BY total_cost DESC`)
1836
+ .all(spec.sinceExpr);
1837
+ const byBackendPeriod = db
1838
+ .prepare(`SELECT ${spec.bucketExpr} as period,
1839
+ ${backendExpr} as backend,
1840
+ SUM(cost_usd) as total_cost,
1841
+ COUNT(*) as session_count
1842
+ FROM agent_actions
1843
+ WHERE started_at > datetime('now', ?)
1844
+ AND cost_usd IS NOT NULL
1845
+ GROUP BY 1, 2
1846
+ ORDER BY period DESC, backend ASC`)
1847
+ .all(spec.sinceExpr);
1848
+ // Today's total (timezone-aware agent day, executed sessions only).
1849
+ // datetime(started_at) normalizes mixed ISO-8601 / SQL formats — same
1850
+ // rationale as the /events ORDER BY fix above.
1851
+ const bounds = getAgentDayBoundsUtc(config.timezone, config.dayBoundaryHour);
1852
+ const today = db
1853
+ .prepare(`SELECT COALESCE(SUM(cost_usd), 0) as cost,
1854
+ COUNT(*) as sessions
1855
+ FROM agent_actions
1856
+ WHERE datetime(started_at) >= ? AND datetime(started_at) < ?
1857
+ AND cost_usd IS NOT NULL`)
1858
+ .get(bounds.start, bounds.end);
1859
+ return c.json({
1860
+ period,
1861
+ today: { costUsd: today.cost, sessions: today.sessions },
1862
+ byPeriod,
1863
+ byModel,
1864
+ byEventType,
1865
+ byBackend,
1866
+ byBackendPeriod,
1867
+ });
1868
+ });
1869
+ // ── Approvals API ──
1870
+ /** GET /approvals — list pending approval requests */
1871
+ app.get("/approvals", (c) => {
1872
+ const rows = db
1873
+ .prepare(`SELECT id, scheduled_for, task_type, task_description,
1874
+ task_context, model, status, created_at
1875
+ FROM agent_schedule
1876
+ WHERE status = 'pending' AND task_type = 'approval'
1877
+ ORDER BY created_at DESC`)
1878
+ .all();
1879
+ return c.json({ approvals: rows });
1880
+ });
1881
+ /** POST /approvals/:id/approve — approve a pending request */
1882
+ app.post("/approvals/:id/approve", (c) => {
1883
+ const id = Number(c.req.param("id"));
1884
+ const result = db
1885
+ .prepare("UPDATE agent_schedule SET status = 'pending', task_type = 'approved_task' WHERE id = ? AND status = 'pending' AND task_type = 'approval'")
1886
+ .run(id);
1887
+ if (result.changes === 0) {
1888
+ return c.json({ error: "approval not found or already processed" }, 404);
1889
+ }
1890
+ return c.json({ status: "approved", id });
1891
+ });
1892
+ /** POST /approvals/:id/deny — deny a pending request */
1893
+ app.post("/approvals/:id/deny", (c) => {
1894
+ const id = Number(c.req.param("id"));
1895
+ const result = db
1896
+ .prepare("UPDATE agent_schedule SET status = 'skipped' WHERE id = ? AND status = 'pending' AND task_type = 'approval'")
1897
+ .run(id);
1898
+ if (result.changes === 0) {
1899
+ return c.json({ error: "approval not found or already processed" }, 404);
1900
+ }
1901
+ return c.json({ status: "denied", id });
1902
+ });
1903
+ // ── Schedule API ──
1904
+ /** GET /schedule/next — next pending scheduled task */
1905
+ app.get("/schedule/next", (c) => {
1906
+ const row = db
1907
+ .prepare(`SELECT id, scheduled_for, task_type, task_description
1908
+ FROM agent_schedule
1909
+ WHERE status = 'pending' AND scheduled_for > datetime('now')
1910
+ ORDER BY scheduled_for ASC LIMIT 1`)
1911
+ .get();
1912
+ return c.json({ next: row ?? null });
1913
+ });
1914
+ /** GET /schedule/list — all scheduled tasks (paginated) */
1915
+ app.get("/schedule/list", (c) => {
1916
+ const page = Math.max(1, Number(c.req.query("page") ?? "1"));
1917
+ const limit = Math.min(Number(c.req.query("limit") ?? "20"), 50);
1918
+ const status = c.req.query("status");
1919
+ const type = c.req.query("type");
1920
+ const offset = (page - 1) * limit;
1921
+ let where = "1=1";
1922
+ const params = [];
1923
+ if (status) {
1924
+ where += " AND status = ?";
1925
+ params.push(status);
1926
+ }
1927
+ if (type) {
1928
+ where += " AND task_type = ?";
1929
+ params.push(type);
1930
+ }
1931
+ const total = db
1932
+ .prepare(`SELECT COUNT(*) as count FROM agent_schedule WHERE ${where}`)
1933
+ .get(...params).count;
1934
+ params.push(limit, offset);
1935
+ const schedules = db
1936
+ .prepare(`SELECT id, scheduled_for, task_type, task_description, task_prompt, model, status, task_context, created_at
1937
+ FROM agent_schedule WHERE ${where}
1938
+ ORDER BY scheduled_for DESC LIMIT ? OFFSET ?`)
1939
+ .all(...params);
1940
+ return c.json({
1941
+ schedules,
1942
+ pagination: { page, limit, total, totalPages: Math.ceil(total / limit) },
1943
+ });
1944
+ });
1945
+ // ── Search API ──
1946
+ /** GET /search?q= — full-text search via FTS5 */
1947
+ app.get("/search", (c) => {
1948
+ const q = c.req.query("q");
1949
+ if (!q || q.length < 2)
1950
+ return c.json({ error: "query too short" }, 400);
1951
+ if (q.length > 200)
1952
+ return c.json({ error: "query too long" }, 400);
1953
+ const limit = Math.min(Number(c.req.query("limit") ?? "20"), 50);
1954
+ // Sanitize: wrap each word in double-quotes to disable FTS5 operators (NEAR, NOT, OR, etc.)
1955
+ const safeQuery = q
1956
+ .replace(/[^\w\s\u3000-\u9FFF\uF900-\uFAFF]/g, " ") // strip punctuation except CJK
1957
+ .split(/\s+/)
1958
+ .filter(Boolean)
1959
+ .map((w) => `"${w}"`)
1960
+ .join(" ");
1961
+ if (!safeQuery)
1962
+ return c.json({ actions: [], messages: [] });
1963
+ let actions = [];
1964
+ let messages = [];
1965
+ try {
1966
+ actions = db
1967
+ .prepare(`SELECT a.id, a.action_type, a.started_at,
1968
+ highlight(fts_actions, 1, '<mark>', '</mark>') as snippet
1969
+ FROM fts_actions JOIN agent_actions a ON a.id = fts_actions.rowid
1970
+ WHERE fts_actions MATCH ? ORDER BY rank LIMIT ?`)
1971
+ .all(safeQuery, limit);
1972
+ }
1973
+ catch {
1974
+ // FTS table may not exist yet
1975
+ }
1976
+ try {
1977
+ messages = db
1978
+ .prepare(`SELECT m.id, m.role, m.timestamp, m.session_id,
1979
+ highlight(fts_messages, 0, '<mark>', '</mark>') as snippet
1980
+ FROM fts_messages JOIN messages m ON m.id = fts_messages.rowid
1981
+ WHERE fts_messages MATCH ? ORDER BY rank LIMIT ?`)
1982
+ .all(safeQuery, limit);
1983
+ }
1984
+ catch {
1985
+ // FTS table may not exist yet
1986
+ }
1987
+ return c.json({ actions, messages });
1988
+ });
1989
+ // ── Snapshots API ──
1990
+ /** GET /snapshots/content/:id — single snapshot content */
1991
+ app.get("/snapshots/content/:id", (c) => {
1992
+ const id = Number(c.req.param("id"));
1993
+ if (!Number.isSafeInteger(id) || id <= 0) {
1994
+ return c.json({ error: "invalid id" }, 400);
1995
+ }
1996
+ const row = db
1997
+ .prepare("SELECT id, file_path, content, trigger, created_at FROM md_file_snapshots WHERE id = ?")
1998
+ .get(id);
1999
+ if (!row)
2000
+ return c.json({ error: "not_found" }, 404);
2001
+ return c.json(row);
2002
+ });
2003
+ /** GET /snapshots/* — snapshot history for a context file */
2004
+ app.get("/snapshots/*", (c) => {
2005
+ const filePath = c.req.path.replace("/api/snapshots/", "");
2006
+ // Validate: reject path traversal and unsafe characters
2007
+ if (!filePath || /\.\./.test(filePath) || !/^[\w./-]+$/.test(filePath)) {
2008
+ return c.json({ error: "invalid file path" }, 400);
2009
+ }
2010
+ const limit = Math.min(Number(c.req.query("limit") ?? "20"), 50);
2011
+ const rows = db
2012
+ .prepare(`SELECT id, file_path, trigger, session_id, created_at
2013
+ FROM md_file_snapshots WHERE file_path = ?
2014
+ ORDER BY created_at DESC LIMIT ?`)
2015
+ .all(filePath, limit);
2016
+ return c.json({ snapshots: rows });
2017
+ });
2018
+ // ── Notifications API ──
2019
+ /** GET /notifications — notification history (paginated) */
2020
+ app.get("/notifications", (c) => {
2021
+ const page = Math.max(1, Number(c.req.query("page") ?? "1"));
2022
+ const limit = Math.min(Number(c.req.query("limit") ?? "50"), 100);
2023
+ const status = c.req.query("status");
2024
+ const priority = c.req.query("priority");
2025
+ const offset = (page - 1) * limit;
2026
+ let where = "1=1";
2027
+ const params = [];
2028
+ if (status) {
2029
+ where += " AND status = ?";
2030
+ params.push(status);
2031
+ }
2032
+ if (priority) {
2033
+ where += " AND priority = ?";
2034
+ params.push(priority);
2035
+ }
2036
+ const total = db
2037
+ .prepare(`SELECT COUNT(*) as count FROM notification_log WHERE ${where}`)
2038
+ .get(...params).count;
2039
+ params.push(limit, offset);
2040
+ const notifications = db
2041
+ .prepare(`SELECT
2042
+ id,
2043
+ dispatch_id,
2044
+ content_summary AS message,
2045
+ platform,
2046
+ delivery_channel,
2047
+ priority,
2048
+ status,
2049
+ user_reaction,
2050
+ reacted_at,
2051
+ created_at
2052
+ FROM notification_log WHERE ${where}
2053
+ ORDER BY created_at DESC LIMIT ? OFFSET ?`)
2054
+ .all(...params);
2055
+ return c.json({
2056
+ notifications,
2057
+ pagination: { page, limit, total, totalPages: Math.ceil(total / limit) },
2058
+ });
2059
+ });
2060
+ return app;
2061
+ }
2062
+ //# sourceMappingURL=dashboard.js.map