comisai 1.0.33 → 1.0.36

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 (285) hide show
  1. package/node_modules/@comis/agent/dist/background/auto-background-middleware.d.ts +11 -1
  2. package/node_modules/@comis/agent/dist/background/auto-background-middleware.js +21 -4
  3. package/node_modules/@comis/agent/dist/background/background-task-manager.d.ts +2 -2
  4. package/node_modules/@comis/agent/dist/background/background-task-manager.js +61 -20
  5. package/node_modules/@comis/agent/dist/background/background-task-persistence.js +10 -3
  6. package/node_modules/@comis/agent/dist/background/background-task-types.d.ts +10 -3
  7. package/node_modules/@comis/agent/dist/background/background-task-types.js +1 -1
  8. package/node_modules/@comis/agent/dist/background/completion-formatter.d.ts +39 -0
  9. package/node_modules/@comis/agent/dist/background/completion-formatter.js +77 -0
  10. package/node_modules/@comis/agent/dist/background/completion-runner.d.ts +53 -0
  11. package/node_modules/@comis/agent/dist/background/completion-runner.js +151 -0
  12. package/node_modules/@comis/agent/dist/background/index.d.ts +4 -0
  13. package/node_modules/@comis/agent/dist/background/index.js +2 -0
  14. package/node_modules/@comis/agent/dist/bridge/bridge-metrics.d.ts +17 -2
  15. package/node_modules/@comis/agent/dist/bridge/bridge-metrics.js +14 -2
  16. package/node_modules/@comis/agent/dist/bridge/pi-event-bridge.d.ts +23 -23
  17. package/node_modules/@comis/agent/dist/bridge/pi-event-bridge.js +72 -60
  18. package/node_modules/@comis/agent/dist/bridge/thinking-block-hash-invariant.d.ts +6 -7
  19. package/node_modules/@comis/agent/dist/bridge/thinking-block-hash-invariant.js +24 -25
  20. package/node_modules/@comis/agent/dist/budget/cost-tracker.d.ts +1 -1
  21. package/node_modules/@comis/agent/dist/context-engine/constants.d.ts +5 -5
  22. package/node_modules/@comis/agent/dist/context-engine/constants.js +12 -12
  23. package/node_modules/@comis/agent/dist/context-engine/context-engine.js +13 -4
  24. package/node_modules/@comis/agent/dist/context-engine/dag-annotator.d.ts +1 -2
  25. package/node_modules/@comis/agent/dist/context-engine/dag-annotator.js +1 -2
  26. package/node_modules/@comis/agent/dist/context-engine/llm-compaction.js +20 -16
  27. package/node_modules/@comis/agent/dist/context-engine/rehydration.js +6 -6
  28. package/node_modules/@comis/agent/dist/context-engine/signature-replay-scrubber.d.ts +12 -12
  29. package/node_modules/@comis/agent/dist/context-engine/signature-replay-scrubber.js +36 -22
  30. package/node_modules/@comis/agent/dist/context-engine/types-core.d.ts +15 -0
  31. package/node_modules/@comis/agent/dist/executor/cache-break-detection.d.ts +6 -6
  32. package/node_modules/@comis/agent/dist/executor/cache-break-detection.js +8 -8
  33. package/node_modules/@comis/agent/dist/executor/executor-context-engine-setup.d.ts +16 -0
  34. package/node_modules/@comis/agent/dist/executor/executor-context-engine-setup.js +46 -5
  35. package/node_modules/@comis/agent/dist/executor/executor-post-execution.d.ts +30 -0
  36. package/node_modules/@comis/agent/dist/executor/executor-post-execution.js +17 -1
  37. package/node_modules/@comis/agent/dist/executor/executor-prompt-runner.js +1 -1
  38. package/node_modules/@comis/agent/dist/executor/executor-response-filter.d.ts +7 -6
  39. package/node_modules/@comis/agent/dist/executor/executor-response-filter.js +9 -42
  40. package/node_modules/@comis/agent/dist/executor/executor-tool-assembly.js +2 -3
  41. package/node_modules/@comis/agent/dist/executor/gemini-cache-injector.d.ts +2 -2
  42. package/node_modules/@comis/agent/dist/executor/gemini-cache-injector.js +4 -4
  43. package/node_modules/@comis/agent/dist/executor/phase-filter.d.ts +2 -2
  44. package/node_modules/@comis/agent/dist/executor/phase-filter.js +5 -7
  45. package/node_modules/@comis/agent/dist/executor/pi-executor.d.ts +13 -0
  46. package/node_modules/@comis/agent/dist/executor/pi-executor.js +71 -6
  47. package/node_modules/@comis/agent/dist/executor/post-batch-continuation.js +7 -7
  48. package/node_modules/@comis/agent/dist/executor/stream-wrappers/request-body-injector.d.ts +1 -1
  49. package/node_modules/@comis/agent/dist/executor/stream-wrappers/request-body-injector.js +1 -1
  50. package/node_modules/@comis/agent/dist/executor/tool-deferral.d.ts +2 -2
  51. package/node_modules/@comis/agent/dist/executor/tool-deferral.js +7 -7
  52. package/node_modules/@comis/agent/dist/index.d.ts +17 -0
  53. package/node_modules/@comis/agent/dist/index.js +32 -11
  54. package/node_modules/@comis/agent/dist/model/auth-provider.d.ts +25 -2
  55. package/node_modules/@comis/agent/dist/model/auth-provider.js +6 -0
  56. package/node_modules/@comis/agent/dist/model/compaction-model-resolver.d.ts +3 -3
  57. package/node_modules/@comis/agent/dist/model/compaction-model-resolver.js +3 -3
  58. package/node_modules/@comis/agent/dist/model/oauth-credential-store-file.d.ts +37 -0
  59. package/node_modules/@comis/agent/dist/model/oauth-credential-store-file.js +279 -0
  60. package/node_modules/@comis/agent/dist/model/oauth-credential-store-selector.d.ts +49 -0
  61. package/node_modules/@comis/agent/dist/model/oauth-credential-store-selector.js +50 -0
  62. package/node_modules/@comis/agent/dist/model/oauth-device-code.d.ts +57 -0
  63. package/node_modules/@comis/agent/dist/model/oauth-device-code.js +302 -0
  64. package/node_modules/@comis/agent/dist/model/oauth-env.d.ts +33 -0
  65. package/node_modules/@comis/agent/dist/model/oauth-env.js +38 -0
  66. package/node_modules/@comis/agent/dist/model/oauth-errors.d.ts +41 -0
  67. package/node_modules/@comis/agent/dist/model/oauth-errors.js +88 -0
  68. package/node_modules/@comis/agent/dist/model/oauth-identity.d.ts +53 -0
  69. package/node_modules/@comis/agent/dist/model/oauth-identity.js +141 -0
  70. package/node_modules/@comis/agent/dist/model/oauth-login-runner.d.ts +99 -0
  71. package/node_modules/@comis/agent/dist/model/oauth-login-runner.js +374 -0
  72. package/node_modules/@comis/agent/dist/model/oauth-tls-preflight.d.ts +58 -0
  73. package/node_modules/@comis/agent/dist/model/oauth-tls-preflight.js +82 -0
  74. package/node_modules/@comis/agent/dist/model/oauth-token-manager.d.ts +86 -16
  75. package/node_modules/@comis/agent/dist/model/oauth-token-manager.js +961 -66
  76. package/node_modules/@comis/agent/dist/model/operation-model-defaults.d.ts +9 -4
  77. package/node_modules/@comis/agent/dist/model/operation-model-defaults.js +36 -9
  78. package/node_modules/@comis/agent/dist/model/resolve-provider-api-key.d.ts +48 -0
  79. package/node_modules/@comis/agent/dist/model/resolve-provider-api-key.js +66 -0
  80. package/node_modules/@comis/agent/dist/provider/capabilities.d.ts +5 -5
  81. package/node_modules/@comis/agent/dist/provider/capabilities.js +10 -23
  82. package/node_modules/@comis/agent/dist/safety/tool-output-safety.js +3 -3
  83. package/node_modules/@comis/agent/dist/session/comis-session-manager.d.ts +1 -1
  84. package/node_modules/@comis/agent/dist/session/comis-session-manager.js +1 -1
  85. package/node_modules/@comis/agent/dist/spawn/narrative-caster.d.ts +10 -0
  86. package/node_modules/@comis/agent/dist/spawn/narrative-caster.js +5 -1
  87. package/node_modules/@comis/agent/package.json +1 -1
  88. package/node_modules/@comis/channels/dist/email/email-adapter.js +6 -6
  89. package/node_modules/@comis/channels/dist/email/imap-lifecycle.js +7 -7
  90. package/node_modules/@comis/channels/dist/shared/deliver-to-channel.js +12 -10
  91. package/node_modules/@comis/channels/dist/telegram/telegram-adapter.js +1 -1
  92. package/node_modules/@comis/channels/package.json +1 -1
  93. package/node_modules/@comis/cli/dist/cli.js +2 -0
  94. package/node_modules/@comis/cli/dist/commands/agent.d.ts +3 -3
  95. package/node_modules/@comis/cli/dist/commands/agent.js +46 -3
  96. package/node_modules/@comis/cli/dist/commands/auth.d.ts +37 -0
  97. package/node_modules/@comis/cli/dist/commands/auth.js +433 -0
  98. package/node_modules/@comis/cli/dist/commands/doctor.d.ts +4 -1
  99. package/node_modules/@comis/cli/dist/commands/doctor.js +20 -5
  100. package/node_modules/@comis/cli/dist/doctor/checks/oauth-health.d.ts +39 -0
  101. package/node_modules/@comis/cli/dist/doctor/checks/oauth-health.js +399 -0
  102. package/node_modules/@comis/cli/dist/doctor/types.d.ts +19 -0
  103. package/node_modules/@comis/cli/dist/index.d.ts +1 -0
  104. package/node_modules/@comis/cli/dist/index.js +10 -4
  105. package/node_modules/@comis/cli/dist/output/relative-time.d.ts +23 -0
  106. package/node_modules/@comis/cli/dist/output/relative-time.js +36 -0
  107. package/node_modules/@comis/cli/dist/wizard/non-interactive.js +17 -8
  108. package/node_modules/@comis/cli/dist/wizard/steps/03-provider.js +2 -1
  109. package/node_modules/@comis/cli/dist/wizard/steps/04-credentials.js +223 -34
  110. package/node_modules/@comis/cli/dist/wizard/steps/10-write-config.js +14 -0
  111. package/node_modules/@comis/cli/dist/wizard/steps/11-daemon-start.js +3 -3
  112. package/node_modules/@comis/cli/dist/wizard/types.d.ts +7 -0
  113. package/node_modules/@comis/cli/package.json +1 -1
  114. package/node_modules/@comis/core/dist/bootstrap.d.ts +1 -1
  115. package/node_modules/@comis/core/dist/config/env-substitution.d.ts +66 -0
  116. package/node_modules/@comis/core/dist/config/env-substitution.js +115 -0
  117. package/node_modules/@comis/core/dist/config/index.d.ts +3 -1
  118. package/node_modules/@comis/core/dist/config/index.js +2 -1
  119. package/node_modules/@comis/core/dist/config/loader.js +61 -0
  120. package/node_modules/@comis/core/dist/config/managed-sections.d.ts +3 -3
  121. package/node_modules/@comis/core/dist/config/managed-sections.js +10 -5
  122. package/node_modules/@comis/core/dist/config/schema-agent.d.ts +4 -0
  123. package/node_modules/@comis/core/dist/config/schema-agent.js +16 -1
  124. package/node_modules/@comis/core/dist/config/schema-background-tasks.d.ts +7 -0
  125. package/node_modules/@comis/core/dist/config/schema-background-tasks.js +7 -0
  126. package/node_modules/@comis/core/dist/config/schema-delivery.d.ts +2 -0
  127. package/node_modules/@comis/core/dist/config/schema-delivery.js +2 -0
  128. package/node_modules/@comis/core/dist/config/schema-gemini-cache.d.ts +0 -2
  129. package/node_modules/@comis/core/dist/config/schema-gemini-cache.js +0 -2
  130. package/node_modules/@comis/core/dist/config/schema-oauth.d.ts +23 -0
  131. package/node_modules/@comis/core/dist/config/schema-oauth.js +19 -0
  132. package/node_modules/@comis/core/dist/config/schema-skills.d.ts +6 -8
  133. package/node_modules/@comis/core/dist/config/schema-skills.js +3 -4
  134. package/node_modules/@comis/core/dist/config/schema.d.ts +10 -0
  135. package/node_modules/@comis/core/dist/config/schema.js +3 -0
  136. package/node_modules/@comis/core/dist/domain/background-task-origin.d.ts +39 -0
  137. package/node_modules/@comis/core/dist/domain/background-task-origin.js +39 -0
  138. package/node_modules/@comis/core/dist/event-bus/events-infra.d.ts +71 -2
  139. package/node_modules/@comis/core/dist/exports/config.d.ts +2 -2
  140. package/node_modules/@comis/core/dist/exports/config.js +1 -1
  141. package/node_modules/@comis/core/dist/exports/domain.d.ts +2 -0
  142. package/node_modules/@comis/core/dist/exports/domain.js +1 -0
  143. package/node_modules/@comis/core/dist/exports/ports.d.ts +2 -2
  144. package/node_modules/@comis/core/dist/exports/ports.js +1 -1
  145. package/node_modules/@comis/core/dist/ports/delivery-queue.d.ts +23 -0
  146. package/node_modules/@comis/core/dist/ports/delivery-queue.js +2 -0
  147. package/node_modules/@comis/core/dist/ports/index.d.ts +2 -0
  148. package/node_modules/@comis/core/dist/ports/index.js +1 -0
  149. package/node_modules/@comis/core/dist/ports/oauth-credential-store.d.ts +64 -0
  150. package/node_modules/@comis/core/dist/ports/oauth-credential-store.js +37 -0
  151. package/node_modules/@comis/core/dist/tool-metadata.d.ts +20 -0
  152. package/node_modules/@comis/core/package.json +1 -1
  153. package/node_modules/@comis/daemon/dist/daemon-types.d.ts +23 -3
  154. package/node_modules/@comis/daemon/dist/daemon.js +82 -19
  155. package/node_modules/@comis/daemon/dist/health/watchdog.js +18 -3
  156. package/node_modules/@comis/daemon/dist/index.d.ts +2 -0
  157. package/node_modules/@comis/daemon/dist/index.js +5 -0
  158. package/node_modules/@comis/daemon/dist/observability/channel-health-logger.js +3 -3
  159. package/node_modules/@comis/daemon/dist/observability/delivery-queue-logger.js +1 -1
  160. package/node_modules/@comis/daemon/dist/rpc/agent-handlers.d.ts +22 -1
  161. package/node_modules/@comis/daemon/dist/rpc/agent-handlers.js +84 -21
  162. package/node_modules/@comis/daemon/dist/rpc/agent-inline-workspace.js +2 -2
  163. package/node_modules/@comis/daemon/dist/rpc/config-handlers.d.ts +9 -1
  164. package/node_modules/@comis/daemon/dist/rpc/config-handlers.js +104 -23
  165. package/node_modules/@comis/daemon/dist/rpc/credential-resolver.d.ts +30 -1
  166. package/node_modules/@comis/daemon/dist/rpc/credential-resolver.js +74 -11
  167. package/node_modules/@comis/daemon/dist/rpc/mcp-handlers.d.ts +8 -0
  168. package/node_modules/@comis/daemon/dist/rpc/mcp-handlers.js +22 -8
  169. package/node_modules/@comis/daemon/dist/rpc/provider-handlers.js +9 -12
  170. package/node_modules/@comis/daemon/dist/rpc/rpc-dispatch.d.ts +1 -0
  171. package/node_modules/@comis/daemon/dist/rpc/rpc-dispatch.js +27 -2
  172. package/node_modules/@comis/daemon/dist/setup-docker-restart-warn.js +0 -1
  173. package/node_modules/@comis/daemon/dist/wiring/index.d.ts +2 -0
  174. package/node_modules/@comis/daemon/dist/wiring/index.js +1 -0
  175. package/node_modules/@comis/daemon/dist/wiring/oauth-preflight.d.ts +21 -0
  176. package/node_modules/@comis/daemon/dist/wiring/oauth-preflight.js +134 -0
  177. package/node_modules/@comis/daemon/dist/wiring/setup-agents.d.ts +46 -1
  178. package/node_modules/@comis/daemon/dist/wiring/setup-agents.js +127 -3
  179. package/node_modules/@comis/daemon/dist/wiring/setup-background-completion-runner.d.ts +39 -0
  180. package/node_modules/@comis/daemon/dist/wiring/setup-background-completion-runner.js +32 -0
  181. package/node_modules/@comis/daemon/dist/wiring/setup-background-tasks.d.ts +10 -3
  182. package/node_modules/@comis/daemon/dist/wiring/setup-background-tasks.js +11 -5
  183. package/node_modules/@comis/daemon/dist/wiring/setup-channels.js +20 -1
  184. package/node_modules/@comis/daemon/dist/wiring/setup-cross-session.js +1 -1
  185. package/node_modules/@comis/daemon/dist/wiring/setup-delivery.d.ts +14 -5
  186. package/node_modules/@comis/daemon/dist/wiring/setup-delivery.js +52 -19
  187. package/node_modules/@comis/daemon/dist/wiring/setup-schedulers.js +4 -0
  188. package/node_modules/@comis/daemon/package.json +1 -1
  189. package/node_modules/@comis/gateway/dist/index.d.ts +2 -0
  190. package/node_modules/@comis/gateway/dist/index.js +2 -0
  191. package/node_modules/@comis/gateway/dist/oauth/oauth-callback-route.d.ts +66 -0
  192. package/node_modules/@comis/gateway/dist/oauth/oauth-callback-route.js +212 -0
  193. package/node_modules/@comis/gateway/dist/server/hono-server.d.ts +14 -0
  194. package/node_modules/@comis/gateway/dist/server/hono-server.js +10 -0
  195. package/node_modules/@comis/gateway/package.json +1 -1
  196. package/node_modules/@comis/infra/dist/logging/log-fields.d.ts +23 -0
  197. package/node_modules/@comis/infra/package.json +1 -1
  198. package/node_modules/@comis/memory/dist/compaction.d.ts +3 -5
  199. package/node_modules/@comis/memory/dist/compaction.js +2 -3
  200. package/node_modules/@comis/memory/dist/delivery-queue-adapter.d.ts +2 -2
  201. package/node_modules/@comis/memory/dist/delivery-queue-adapter.js +49 -1
  202. package/node_modules/@comis/memory/dist/index.d.ts +2 -0
  203. package/node_modules/@comis/memory/dist/index.js +3 -0
  204. package/node_modules/@comis/memory/dist/memory-api.d.ts +1 -1
  205. package/node_modules/@comis/memory/dist/memory-api.js +1 -1
  206. package/node_modules/@comis/memory/dist/oauth-profile-schema.d.ts +17 -0
  207. package/node_modules/@comis/memory/dist/oauth-profile-schema.js +33 -0
  208. package/node_modules/@comis/memory/dist/oauth-profile-store-encrypted.d.ts +27 -0
  209. package/node_modules/@comis/memory/dist/oauth-profile-store-encrypted.js +144 -0
  210. package/node_modules/@comis/memory/dist/session-store.d.ts +1 -1
  211. package/node_modules/@comis/memory/dist/session-store.js +1 -1
  212. package/node_modules/@comis/memory/dist/sqlite-secret-store.d.ts +29 -3
  213. package/node_modules/@comis/memory/dist/sqlite-secret-store.js +11 -3
  214. package/node_modules/@comis/memory/package.json +1 -1
  215. package/node_modules/@comis/scheduler/dist/execution/execution-lock.d.ts +13 -0
  216. package/node_modules/@comis/scheduler/dist/execution/execution-lock.js +1 -1
  217. package/node_modules/@comis/scheduler/dist/execution/index.d.ts +2 -0
  218. package/node_modules/@comis/scheduler/dist/execution/index.js +2 -0
  219. package/node_modules/@comis/scheduler/dist/heartbeat/agent-heartbeat-source.js +1 -1
  220. package/node_modules/@comis/scheduler/dist/index.d.ts +2 -0
  221. package/node_modules/@comis/scheduler/dist/index.js +2 -0
  222. package/node_modules/@comis/scheduler/package.json +1 -1
  223. package/node_modules/@comis/shared/package.json +1 -1
  224. package/node_modules/@comis/skills/dist/bridge/schema-validator.d.ts +38 -0
  225. package/node_modules/@comis/skills/dist/bridge/schema-validator.js +169 -0
  226. package/node_modules/@comis/skills/dist/bridge/tool-metadata-enforcement.js +12 -0
  227. package/node_modules/@comis/skills/dist/bridge/tool-metadata-registry.js +130 -0
  228. package/node_modules/@comis/skills/dist/builtin/exec-diagnostics.d.ts +32 -0
  229. package/node_modules/@comis/skills/dist/builtin/exec-diagnostics.js +127 -0
  230. package/node_modules/@comis/skills/dist/builtin/exec-security.js +38 -0
  231. package/node_modules/@comis/skills/dist/builtin/exec-tool.js +9 -0
  232. package/node_modules/@comis/skills/dist/builtin/file-tools/grep-tool.js +6 -6
  233. package/node_modules/@comis/skills/dist/builtin/platform/agents-manage-tool.d.ts +5 -4
  234. package/node_modules/@comis/skills/dist/builtin/platform/agents-manage-tool.js +38 -27
  235. package/node_modules/@comis/skills/dist/builtin/platform/background-tasks-tool.d.ts +4 -1
  236. package/node_modules/@comis/skills/dist/builtin/platform/background-tasks-tool.js +3 -3
  237. package/node_modules/@comis/skills/dist/builtin/platform/cron-tool.js +1 -1
  238. package/node_modules/@comis/skills/dist/builtin/platform/gateway-tool.js +6 -6
  239. package/node_modules/@comis/skills/dist/builtin/platform/mcp-manage-tool.d.ts +1 -1
  240. package/node_modules/@comis/skills/dist/builtin/platform/mcp-manage-tool.js +9 -9
  241. package/node_modules/@comis/skills/dist/builtin/sandbox/bwrap-provider.d.ts +11 -0
  242. package/node_modules/@comis/skills/dist/builtin/sandbox/bwrap-provider.js +114 -1
  243. package/node_modules/@comis/skills/dist/builtin/sandbox/detect-provider.js +40 -15
  244. package/node_modules/@comis/skills/dist/media/ssrf-fetcher.d.ts +7 -0
  245. package/node_modules/@comis/skills/dist/media/ssrf-fetcher.js +9 -2
  246. package/node_modules/@comis/skills/package.json +1 -1
  247. package/node_modules/@comis/web/dist/assets/{agent-detail-71BSbSfD.js → agent-detail-q8t1NB7w.js} +1 -1
  248. package/node_modules/@comis/web/dist/assets/{agent-editor-CTSDZhwT.js → agent-editor-B46io5gv.js} +1 -1
  249. package/node_modules/@comis/web/dist/assets/{agent-list-BEhni2ea.js → agent-list-DQ6g2Rcx.js} +1 -1
  250. package/node_modules/@comis/web/dist/assets/{billing-view-DVP1IvVs.js → billing-view-IWPR8LgF.js} +1 -1
  251. package/node_modules/@comis/web/dist/assets/{channel-detail-N_YK74xC.js → channel-detail-DlNNZuuC.js} +1 -1
  252. package/node_modules/@comis/web/dist/assets/{channel-list-DRk6ZJaF.js → channel-list-DhGwxiMc.js} +1 -1
  253. package/node_modules/@comis/web/dist/assets/{chat-console-Dm-GtSf9.js → chat-console-Nv6fM3Rc.js} +1 -1
  254. package/node_modules/@comis/web/dist/assets/{config-editor-CIferYX6.js → config-editor-BYKuJF76.js} +1 -1
  255. package/node_modules/@comis/web/dist/assets/{context-dag-browser-CL84rXXM.js → context-dag-browser-ClNEtzYE.js} +1 -1
  256. package/node_modules/@comis/web/dist/assets/{context-engine-B1HOTEZv.js → context-engine-BZJ6HChd.js} +1 -1
  257. package/node_modules/@comis/web/dist/assets/{delivery-view-Y6JKYVFw.js → delivery-view-Cb7I3vGu.js} +1 -1
  258. package/node_modules/@comis/web/dist/assets/{diagnostics-view-DWV1UQjz.js → diagnostics-view-9u9Lyu5a.js} +1 -1
  259. package/node_modules/@comis/web/dist/assets/{ic-chat-message-DfSERzzg.js → ic-chat-message-BFt3cVpx.js} +1 -1
  260. package/node_modules/@comis/web/dist/assets/{ic-connection-dot-CXyhlJup.js → ic-connection-dot-y77LZ3Gu.js} +1 -1
  261. package/node_modules/@comis/web/dist/assets/{ic-tool-call-DNmwTjek.js → ic-tool-call-qt6w1NQl.js} +1 -1
  262. package/node_modules/@comis/web/dist/assets/{index-CBr0Tm9_.js → index-8Tg9oc-C.js} +2 -2
  263. package/node_modules/@comis/web/dist/assets/{mcp-management-BaH2-vox.js → mcp-management-69dtH_kY.js} +2 -2
  264. package/node_modules/@comis/web/dist/assets/{media-config-CZLshJoN.js → media-config-BdjLj5c1.js} +1 -1
  265. package/node_modules/@comis/web/dist/assets/{media-test-C9NUWgo_.js → media-test-DuPqrixi.js} +1 -1
  266. package/node_modules/@comis/web/dist/assets/{memory-inspector-D_fmTcRN.js → memory-inspector-B-Pepbq-.js} +1 -1
  267. package/node_modules/@comis/web/dist/assets/{message-center-BBFlNCZn.js → message-center-B7l0yNYY.js} +1 -1
  268. package/node_modules/@comis/web/dist/assets/{models-BytGLm99.js → models-JHFHuv5S.js} +1 -1
  269. package/node_modules/@comis/web/dist/assets/{observe-view-VXtHqaqq.js → observe-view-r8mqhy4O.js} +1 -1
  270. package/node_modules/@comis/web/dist/assets/{pipeline-builder-CfXczlfJ.js → pipeline-builder-XjkiZRcR.js} +1 -1
  271. package/node_modules/@comis/web/dist/assets/{pipeline-history-CPmXFnbe.js → pipeline-history-CZqJv_Hj.js} +1 -1
  272. package/node_modules/@comis/web/dist/assets/{pipeline-history-detail-DcueTMs9.js → pipeline-history-detail-BEFGMoDy.js} +1 -1
  273. package/node_modules/@comis/web/dist/assets/{pipeline-list-B-xG5WZh.js → pipeline-list-B6q5LvO1.js} +1 -1
  274. package/node_modules/@comis/web/dist/assets/{pipeline-monitor-pnIOYaSY.js → pipeline-monitor-BNomXjVL.js} +1 -1
  275. package/node_modules/@comis/web/dist/assets/{scheduler-BtUIFHhA.js → scheduler-BJEjcGKA.js} +1 -1
  276. package/node_modules/@comis/web/dist/assets/{security-C8mWRq2y.js → security-2G1jhBfV.js} +1 -1
  277. package/node_modules/@comis/web/dist/assets/{session-detail-DgdkO5ka.js → session-detail-DmVPzFBR.js} +1 -1
  278. package/node_modules/@comis/web/dist/assets/{session-list-DcylcfTn.js → session-list-CsqMQoHs.js} +1 -1
  279. package/node_modules/@comis/web/dist/assets/{setup-wizard-BP5yjsuL.js → setup-wizard-CAdM-gSP.js} +1 -1
  280. package/node_modules/@comis/web/dist/assets/{skills-DXt1bX8Z.js → skills-2ODqKaWr.js} +1 -1
  281. package/node_modules/@comis/web/dist/assets/{subagents-C7YbUHXY.js → subagents-BFlwfTbD.js} +1 -1
  282. package/node_modules/@comis/web/dist/assets/{workspace-manager-DP6pW4wa.js → workspace-manager--CbOx_dI.js} +1 -1
  283. package/node_modules/@comis/web/dist/index.html +1 -1
  284. package/node_modules/@comis/web/package.json +1 -1
  285. package/package.json +17 -16
@@ -13,8 +13,15 @@ import { homedir } from "node:os";
13
13
  import { existsSync, mkdirSync } from "node:fs";
14
14
  import { isAbsolute, resolve } from "node:path";
15
15
  import { getModels, getProviders } from "@mariozechner/pi-ai";
16
- import { createCircuitBreaker, createBudgetGuard, createCostTracker, createStepCounter, createSessionLifecycle, ensureWorkspace, resolveWorkspaceDir, createPiExecutor, createComisSessionManager, cleanupStaleLocks, createAuthStorageAdapter, createModelRegistryAdapter, registerCustomProviders, createProviderHealthMonitor, createLastKnownModelTracker, createAuthProfileManager, createAuthRotationAdapter, setSanitizeLogger, setToolNormalizationLogger, resolveOperationDefaults, resolveCompactionModel, LEAN_TOOL_DESCRIPTIONS, resolveDescription, } from "@comis/agent";
16
+ import { createCircuitBreaker, createBudgetGuard, createCostTracker, createStepCounter, createSessionLifecycle, ensureWorkspace, resolveWorkspaceDir, createPiExecutor, createComisSessionManager, cleanupStaleLocks, createAuthStorageAdapter, createAuthProvider, selectOAuthCredentialStore, createModelRegistryAdapter, registerCustomProviders, createProviderHealthMonitor, createLastKnownModelTracker, createAuthProfileManager, createAuthRotationAdapter, setSanitizeLogger, setToolNormalizationLogger, resolveOperationDefaults, resolveCompactionModel, LEAN_TOOL_DESCRIPTIONS, resolveDescription, } from "@comis/agent";
17
17
  import { agentToolsToToolDefinitions, createSkillRegistry, createRuntimeEligibilityContext, TOOL_PROFILES, } from "@comis/skills";
18
+ // Once-per-daemon-process WARN flag for the encrypted-store hot-reload
19
+ // limitation. Lifted to module scope so the flag survives across per-agent
20
+ // setupSingleAgent calls AND any future re-invocations of setupAgents within
21
+ // the same process. Operator-friendly notice — fires exactly once per daemon
22
+ // process so the operator sees it in startup logs without N-times-per-agent
23
+ // noise.
24
+ let encryptedModeWarnFired = false;
18
25
  // ---------------------------------------------------------------------------
19
26
  // Single-agent setup (extracted for hot-add reuse)
20
27
  // ---------------------------------------------------------------------------
@@ -104,6 +111,75 @@ export async function setupSingleAgent(agentId, rawAgentConfig, deps) {
104
111
  secretManager: scopedManager,
105
112
  customProviderEntries,
106
113
  });
114
+ // -------------------------------------------------------------------------
115
+ // FIRST daemon-side OAuth wiring.
116
+ //
117
+ // Closes the unwired-OAuth gap — the createAuthProvider symbol was exported
118
+ // by @comis/agent but never called by the daemon, so refreshed OAuth tokens
119
+ // lived only in the in-memory cache and silently disappeared on restart.
120
+ // AuthProviderConfig.oauth credentialStore + logger + dataDir are REQUIRED
121
+ // so this wiring is type-checked at compile time — future regressions
122
+ // surface as TS errors, not silent runtime failures.
123
+ //
124
+ // All path constructions in this block use safePath from @comis/core (NOT
125
+ // path.join — AGENTS.md §2.2 ESLint security rule).
126
+ // When storage === "encrypted", the OAuth profile adapter SHARES the
127
+ // existing secretsDb handle from createSqliteSecretStore (no dual-handle).
128
+ // -------------------------------------------------------------------------
129
+ const oauthStorageMode = container.config.oauth.storage;
130
+ const dataDirAbs = container.config.dataDir && container.config.dataDir.length > 0
131
+ ? container.config.dataDir
132
+ : safePath(homedir(), ".comis");
133
+ // Use the daemon-level OAuthCredentialStore handle that setupAgents()
134
+ // constructed once and threaded through SingleAgentDeps. Same store
135
+ // reference is also exposed on AgentsResult so daemon.ts can plumb it into
136
+ // RpcDispatchDeps for the agents.update oauthProfiles existence check.
137
+ const oauthCredentialStore = deps.oauthCredentialStore;
138
+ const authProvider = createAuthProvider({
139
+ secretManager: scopedManager,
140
+ additionalProviderKeys: undefined,
141
+ oauth: {
142
+ eventBus: container.eventBus,
143
+ credentialStore: oauthCredentialStore,
144
+ logger: agentLogger.child({ submodule: "oauth-token-manager" }),
145
+ dataDir: dataDirAbs,
146
+ keyPrefix: "OAUTH_",
147
+ // Pass auth-profiles.json path when file adapter active so
148
+ // OAuthTokenManager can register the chokidar watcher and pick up
149
+ // CLI-written profiles within ~250ms without a daemon restart.
150
+ // Encrypted-mode: undefined -> no watcher; documented limitation.
151
+ watchPath: oauthStorageMode === "file"
152
+ ? safePath(dataDirAbs, "auth-profiles.json")
153
+ : undefined,
154
+ // Closure-stability: the closure dereferences
155
+ // container.config.agents[agentId]?.oauthProfiles on every call.
156
+ // This is the only correct shape because:
157
+ // 1. Line ~222 above writes effectiveConfig (a NEW object built
158
+ // from { ...agentConfig, model, provider }) into
159
+ // container.config.agents[agentId]. The local `agentConfig`
160
+ // parameter diverges from the daemon's map immediately at
161
+ // startup — capturing it would observe the wrong value.
162
+ // 2. agents.update at agent-handlers.ts:341 executes
163
+ // `deps.agents[agentId] = parsedConfig`, REPLACING the
164
+ // reference at that key with a new validated object. Capturing
165
+ // the local agentConfig parameter would miss this hot-update.
166
+ // 3. daemon.ts:594, 634 confirm `deps.agents` and
167
+ // `container.config.agents` are THE SAME map object — the
168
+ // daemon's single per-process Container.config instance.
169
+ // The map identity is stable; only the value at the agent key
170
+ // changes. The closure-evaluated dereference observes (1) at
171
+ // startup AND (2) on every agents.update without an event-bus
172
+ // invalidation or daemon restart, allowing the agents_manage tool to
173
+ // update without a daemon restart.
174
+ getAgentOauthProfiles: () => container.config.agents?.[agentId]?.oauthProfiles,
175
+ },
176
+ });
177
+ agentLogger.debug({
178
+ agentId,
179
+ oauthStorage: oauthStorageMode,
180
+ dataDir: dataDirAbs,
181
+ submodule: "setup-agents",
182
+ }, "OAuth credential store + auth provider + per-LLM-call dispatch wired");
107
183
  const piModelRegistry = createModelRegistryAdapter(piAuthStorage);
108
184
  const { registered: customProviderCount, providerAliases } = registerCustomProviders(piModelRegistry, customProviderEntries, scopedManager, agentLogger);
109
185
  if (customProviderCount > 0) {
@@ -235,6 +311,11 @@ export async function setupSingleAgent(agentId, rawAgentConfig, deps) {
235
311
  eventBus: container.eventBus,
236
312
  logger: perAgentLogger,
237
313
  authStorage: piAuthStorage,
314
+ // Thread OAuthTokenManager into the executor so the per-LLM-call
315
+ // dispatch hook (PiExecutor.execute pre-hook + the two compaction
316
+ // getApiKey callbacks in executor-context-engine-setup.ts) can resolve
317
+ // OAuth tokens via resolveProviderApiKey.
318
+ oauthManager: authProvider.oauth,
238
319
  modelRegistry: piModelRegistry,
239
320
  providerAliases,
240
321
  fallbackModels: fallbackModelStrings.length > 0 ? fallbackModelStrings : undefined,
@@ -312,9 +393,23 @@ export async function setupSingleAgent(agentId, rawAgentConfig, deps) {
312
393
  export async function setupAgents(deps) {
313
394
  const { container, memoryAdapter, sessionStore, agentLogger } = deps;
314
395
  // Inject module-level logger for response sanitization pipeline
315
- setSanitizeLogger(agentLogger.child({ module: "response-sanitize" }));
396
+ setSanitizeLogger(agentLogger.child({ submodule: "response-sanitize" }));
316
397
  // Inject module-level logger for tool schema normalization pipeline
317
- setToolNormalizationLogger(agentLogger.child({ module: "tool-normalize" }));
398
+ setToolNormalizationLogger(agentLogger.child({ submodule: "tool-normalize" }));
399
+ // Once-per-daemon WARN for the encrypted-store hot-reload limitation.
400
+ // Placed in setupAgents() body (NOT setupSingleAgent) so the notice fires
401
+ // exactly once per daemon process — not N times for N agents. Operator
402
+ // sees this in startup logs without surprise; daemon restart is required
403
+ // to pick up CLI-written OAuth profiles in encrypted-store mode.
404
+ const overallStorageMode = container.config.oauth.storage;
405
+ if (overallStorageMode === "encrypted" && !encryptedModeWarnFired) {
406
+ encryptedModeWarnFired = true;
407
+ agentLogger.warn({
408
+ hint: "CLI auth login changes require daemon restart in encrypted mode (file-watch unsupported on encrypted SQLite WAL)",
409
+ errorKind: "limitation_known",
410
+ submodule: "setup-agents",
411
+ }, "OAuth hot-reload disabled in encrypted-store mode");
412
+ }
318
413
  const agents = container.config.agents; // Always populated after schema transform
319
414
  const routingConfig = container.config.routing;
320
415
  // Daemon-level tracing defaults
@@ -368,6 +463,19 @@ export async function setupAgents(deps) {
368
463
  });
369
464
  // Global last-known-working model tracker (shared across all agents)
370
465
  const lastKnownModel = createLastKnownModelTracker();
466
+ // Construct the daemon-level OAuthCredentialStore handle ONCE (instead of
467
+ // per-agent inside setupSingleAgent). Same handle is reused across every
468
+ // agent setup AND surfaced on AgentsResult so daemon.ts can plumb it into
469
+ // RpcDispatchDeps for the agents.update oauthProfiles existence check.
470
+ const dataDirAbsForOauth = container.config.dataDir && container.config.dataDir.length > 0
471
+ ? container.config.dataDir
472
+ : safePath(homedir(), ".comis");
473
+ const oauthCredentialStore = selectOAuthCredentialStore({
474
+ storage: container.config.oauth.storage,
475
+ dataDir: dataDirAbsForOauth,
476
+ secretsCrypto: deps.secretsCrypto,
477
+ secretsDb: deps.secretsDb,
478
+ });
371
479
  // Construct shared deps struct once before the loop (for hot-add reuse)
372
480
  const singleAgentDeps = {
373
481
  container,
@@ -395,6 +503,12 @@ export async function setupAgents(deps) {
395
503
  getChannelMaxChars: deps.getChannelMaxChars,
396
504
  backgroundTaskManager: deps.backgroundTaskManager,
397
505
  backgroundNotifyFn: deps.backgroundNotifyFn,
506
+ // Secrets bootstrap output for OAuth wiring.
507
+ secretsCrypto: deps.secretsCrypto,
508
+ secretsDb: deps.secretsDb,
509
+ // Daemon-level OAuth credential store handle (constructed once above,
510
+ // reused per-agent + threaded into RPC deps).
511
+ oauthCredentialStore,
398
512
  };
399
513
  for (const [agentId, agentConfig] of Object.entries(agents)) {
400
514
  const result = await setupSingleAgent(agentId, agentConfig, singleAgentDeps);
@@ -451,6 +565,10 @@ export async function setupAgents(deps) {
451
565
  lockCleanupTimer,
452
566
  singleAgentDeps,
453
567
  providerHealth,
568
+ // Daemon-level OAuth credential store, plumbed by daemon.ts into
569
+ // RpcDispatchDeps.oauthCredentialStore so agents.update can validate
570
+ // oauthProfiles patches via has().
571
+ oauthCredentialStore,
454
572
  };
455
573
  }
456
574
  // ---------------------------------------------------------------------------
@@ -543,3 +661,9 @@ function deriveCanaryFallback(baseSecret, agentId) {
543
661
  .update(`canary-fallback:${agentId}`)
544
662
  .digest("hex");
545
663
  }
664
+ // ---------------------------------------------------------------------------
665
+ // OAuth credential store selection lives in @comis/agent (CLI cannot import
666
+ // from @comis/daemon, so the helper must live where both daemon and CLI
667
+ // consume it).
668
+ // See: packages/agent/src/model/oauth-credential-store-selector.ts
669
+ // ---------------------------------------------------------------------------
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Background completion runner wiring for daemon startup.
3
+ *
4
+ * Subscribes the runner to background_task:{completed,failed} events after
5
+ * the notification service has been wired (so fallbackNotifyFn is live),
6
+ * and returns a shutdown handle for the daemon's system:shutdown sequence
7
+ * to await before tearing down the executor.
8
+ *
9
+ * Per AGENTS §2.4: composition root + factories. This wiring lives in
10
+ * @comis/daemon (composition root); the actual factory body is in
11
+ * @comis/agent.
12
+ *
13
+ * @module
14
+ */
15
+ import { type BackgroundCompletionRunner, type BackgroundTaskManager, type NotifyFn } from "@comis/agent";
16
+ import type { TypedEventBus } from "@comis/core";
17
+ import type { ComisLogger } from "@comis/infra";
18
+ import type { AgentExecutor } from "@comis/agent";
19
+ import type { RunnerSessionStore } from "@comis/agent";
20
+ /** Result of setupBackgroundCompletionRunner -- exposed to the daemon for shutdown. */
21
+ export interface BackgroundCompletionRunnerContext {
22
+ runner: BackgroundCompletionRunner;
23
+ }
24
+ export interface SetupBackgroundCompletionRunnerDeps {
25
+ eventBus: TypedEventBus;
26
+ getExecutor: (agentId: string) => AgentExecutor;
27
+ sessionStore: RunnerSessionStore;
28
+ taskManager: Pick<BackgroundTaskManager, "getTask">;
29
+ /** bgNotifyFn closure used when the originating session is gone. */
30
+ fallbackNotifyFn: NotifyFn;
31
+ /** From config.backgroundTasks.maxBackgroundHops (default 3). NOT config.workflow.*. */
32
+ maxBackgroundHops: number;
33
+ logger: ComisLogger;
34
+ }
35
+ /**
36
+ * Wire the background completion runner from daemon-level dependencies.
37
+ * Call this AFTER setupNotifications so fallbackNotifyFn is wired.
38
+ */
39
+ export declare function setupBackgroundCompletionRunner(deps: SetupBackgroundCompletionRunnerDeps): BackgroundCompletionRunnerContext;
@@ -0,0 +1,32 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ /**
3
+ * Background completion runner wiring for daemon startup.
4
+ *
5
+ * Subscribes the runner to background_task:{completed,failed} events after
6
+ * the notification service has been wired (so fallbackNotifyFn is live),
7
+ * and returns a shutdown handle for the daemon's system:shutdown sequence
8
+ * to await before tearing down the executor.
9
+ *
10
+ * Per AGENTS §2.4: composition root + factories. This wiring lives in
11
+ * @comis/daemon (composition root); the actual factory body is in
12
+ * @comis/agent.
13
+ *
14
+ * @module
15
+ */
16
+ import { createBackgroundCompletionRunner, } from "@comis/agent";
17
+ /**
18
+ * Wire the background completion runner from daemon-level dependencies.
19
+ * Call this AFTER setupNotifications so fallbackNotifyFn is wired.
20
+ */
21
+ export function setupBackgroundCompletionRunner(deps) {
22
+ const runner = createBackgroundCompletionRunner({
23
+ eventBus: deps.eventBus,
24
+ getExecutor: deps.getExecutor,
25
+ sessionStore: deps.sessionStore,
26
+ taskManager: deps.taskManager,
27
+ fallbackNotifyFn: deps.fallbackNotifyFn,
28
+ maxBackgroundHops: deps.maxBackgroundHops,
29
+ logger: deps.logger,
30
+ });
31
+ return { runner };
32
+ }
@@ -19,9 +19,16 @@ export interface SetupBackgroundTasksDeps {
19
19
  }
20
20
  /**
21
21
  * Wire the background task subsystem from daemon-level dependencies.
22
- * Creates BackgroundTaskManager with file-based persistence, recovers
23
- * incomplete tasks from the previous daemon run (marking them failed),
24
- * and starts an hourly cleanup timer for stale completed/failed tasks.
22
+ * Creates BackgroundTaskManager with file-based persistence and starts
23
+ * an hourly cleanup timer for stale completed/failed tasks.
24
+ *
25
+ * Note: startup recovery (marking interrupted tasks as failed) is
26
+ * INTENTIONALLY deferred to daemon.ts. The daemon calls it AFTER
27
+ * `setupBackgroundCompletionRunner` has subscribed to
28
+ * background_task:{completed,failed}. If recovery fires before the runner
29
+ * subscribes, the synthesized failure events for restart-interrupted tasks
30
+ * land in an empty handler set and the user never sees the recovery
31
+ * announcement.
25
32
  * @param deps - Daemon-level dependencies
26
33
  * @returns BackgroundTasksContext with manager instance
27
34
  */
@@ -9,9 +9,16 @@ import { createBackgroundTaskManager } from "@comis/agent";
9
9
  import { safePath } from "@comis/core";
10
10
  /**
11
11
  * Wire the background task subsystem from daemon-level dependencies.
12
- * Creates BackgroundTaskManager with file-based persistence, recovers
13
- * incomplete tasks from the previous daemon run (marking them failed),
14
- * and starts an hourly cleanup timer for stale completed/failed tasks.
12
+ * Creates BackgroundTaskManager with file-based persistence and starts
13
+ * an hourly cleanup timer for stale completed/failed tasks.
14
+ *
15
+ * Note: startup recovery (marking interrupted tasks as failed) is
16
+ * INTENTIONALLY deferred to daemon.ts. The daemon calls it AFTER
17
+ * `setupBackgroundCompletionRunner` has subscribed to
18
+ * background_task:{completed,failed}. If recovery fires before the runner
19
+ * subscribes, the synthesized failure events for restart-interrupted tasks
20
+ * land in an empty handler set and the user never sees the recovery
21
+ * announcement.
15
22
  * @param deps - Daemon-level dependencies
16
23
  * @returns BackgroundTasksContext with manager instance
17
24
  */
@@ -21,8 +28,7 @@ export function setupBackgroundTasks(deps) {
21
28
  eventBus: deps.eventBus,
22
29
  logger: deps.logger,
23
30
  });
24
- // Mark incomplete tasks from previous daemon run as failed
25
- manager.recoverOnStartup();
31
+ // Startup recovery is deferred to daemon.ts (after the completion runner subscribes).
26
32
  // Periodic cleanup of stale completed/failed tasks (24h TTL)
27
33
  const cleanupInterval = setInterval(() => manager.cleanup(), 3_600_000); // every hour
28
34
  cleanupInterval.unref(); // don't keep daemon alive for cleanup
@@ -96,7 +96,7 @@ export async function setupChannels(deps) {
96
96
  return;
97
97
  }
98
98
  const workspacePath = deps.workspaceDirs?.get(agentId) ?? "";
99
- const reviewLogger = logger.child({ agentId, module: "memory-review" });
99
+ const reviewLogger = logger.child({ agentId, submodule: "memory-review" });
100
100
  const reviewResult = await runMemoryReview({
101
101
  agentId,
102
102
  tenantId: deps.tenantId ?? container.config.tenantId ?? "default",
@@ -142,6 +142,25 @@ export async function setupChannels(deps) {
142
142
  // Extract session strategy from event payload (defaults: fresh, 3 turns)
143
143
  const sessionStrategy = payload.sessionStrategy ?? "fresh";
144
144
  const maxHistoryTurns = payload.maxHistoryTurns ?? 3;
145
+ // Cadence-aware cache-waste guard: rolling/accumulate strategies on long cadences
146
+ // guarantee cache-write waste because the prompt cache TTL is short (5 min for "cron"
147
+ // operations — see OPERATION_CACHE_DEFAULTS.cron in @comis/agent). Threshold = 2x TTL
148
+ // so we don't warn on borderline-useful 6-9 min cadences. Operator intent is preserved
149
+ // (no auto-downgrade) — this is informational only. Scoped to schedule.kind === "every"
150
+ // because cron-expression cadence is not threaded through the event payload.
151
+ const CRON_CACHE_TTL_2X_MS = 600_000;
152
+ if (sessionStrategy !== "fresh" &&
153
+ payload.cadenceMs !== undefined &&
154
+ payload.cadenceMs > CRON_CACHE_TTL_2X_MS) {
155
+ logger.warn({
156
+ jobName,
157
+ agentId: payload.agentId,
158
+ sessionStrategy,
159
+ cadenceMs: payload.cadenceMs,
160
+ hint: "Cadence exceeds cache TTL by 2x; rolling/accumulate guarantees per-tick cache-write waste. Set sessionStrategy:'fresh' unless cross-tick session memory is essential.",
161
+ errorKind: "config",
162
+ }, "Cron sessionStrategy may waste cache writes at this cadence");
163
+ }
145
164
  // Resolve cron operation model via 5-level priority chain
146
165
  const agentConfig = agents[payload.agentId];
147
166
  let cronOverrides;
@@ -581,7 +581,7 @@ export function setupCrossSession(deps) {
581
581
  maxAgeMs: 3_600_000,
582
582
  maxEntries: 100,
583
583
  eventBus: container.eventBus,
584
- logger: deps.logger?.child({ module: "dead-letter-queue" }),
584
+ logger: deps.logger?.child({ submodule: "dead-letter-queue" }),
585
585
  });
586
586
  // Create announcement batcher for coalescing near-simultaneous sub-agent completions
587
587
  const announcementBatcher = createAnnouncementBatcher({
@@ -5,8 +5,9 @@
5
5
  * Queue two-phase lifecycle resolves the circular dependency between the
6
6
  * queue and channel adapters:
7
7
  * 1. setupDeliveryQueue() creates the adapter immediately (before setupChannels).
8
- * 2. drainAndStartPrune() runs drain + starts prune timer AFTER setupChannels
9
- * populates channelAdapters.
8
+ * 2. drainAndStart() recovers in_flight rows, runs startup drain, then starts
9
+ * both the recurring drain timer and the prune timer AFTER
10
+ * setupChannels populates channelAdapters.
10
11
  * Crash-Safe Delivery Queue.
11
12
  * Session Mirroring.
12
13
  * @module setup-delivery — Delivery subsystem wiring (queue + mirror)
@@ -18,9 +19,9 @@ import type { PluginRegistry } from "@comis/core";
18
19
  export interface DeliveryQueueResult {
19
20
  /** The delivery queue adapter (real or no-op), available immediately. */
20
21
  deliveryQueue: DeliveryQueuePort;
21
- /** Runs startup drain then starts periodic prune timer. Call AFTER setupChannels. */
22
- drainAndStartPrune: () => Promise<void>;
23
- /** Clears the prune interval timer (call on shutdown). */
22
+ /** Recovers in_flight rows, runs startup drain, then starts the recurring drain + prune timers. Call AFTER setupChannels. */
23
+ drainAndStart: () => Promise<void>;
24
+ /** Clears the recurring drain interval AND the prune interval (call on shutdown). */
24
25
  shutdown: () => void;
25
26
  }
26
27
  export declare function setupDeliveryQueue(deps: {
@@ -31,6 +32,14 @@ export declare function setupDeliveryQueue(deps: {
31
32
  logger: ComisLogger;
32
33
  channelAdapters: Map<string, DeliveryAdapter>;
33
34
  }): Promise<DeliveryQueueResult>;
35
+ export declare function drainDeliveryQueue(deps: {
36
+ deliveryQueue: DeliveryQueuePort;
37
+ channelAdapters: Map<string, DeliveryAdapter>;
38
+ eventBus: TypedEventBus;
39
+ logger: ComisLogger;
40
+ drainBudgetMs: number;
41
+ defaultMaxAttempts: number;
42
+ }): Promise<void>;
34
43
  export interface DeliveryMirrorResult {
35
44
  /** The delivery mirror adapter (real or no-op), available immediately. */
36
45
  deliveryMirror: DeliveryMirrorPort;
@@ -6,8 +6,9 @@
6
6
  * Queue two-phase lifecycle resolves the circular dependency between the
7
7
  * queue and channel adapters:
8
8
  * 1. setupDeliveryQueue() creates the adapter immediately (before setupChannels).
9
- * 2. drainAndStartPrune() runs drain + starts prune timer AFTER setupChannels
10
- * populates channelAdapters.
9
+ * 2. drainAndStart() recovers in_flight rows, runs startup drain, then starts
10
+ * both the recurring drain timer and the prune timer AFTER
11
+ * setupChannels populates channelAdapters.
11
12
  * Crash-Safe Delivery Queue.
12
13
  * Session Mirroring.
13
14
  * @module setup-delivery — Delivery subsystem wiring (queue + mirror)
@@ -15,7 +16,7 @@
15
16
  import { createNoOpDeliveryQueue, createNoOpDeliveryMirror } from "@comis/core";
16
17
  import { createSqliteDeliveryQueue, createSqliteDeliveryMirror } from "@comis/memory";
17
18
  import { isPermanentError, computeQueueBackoff } from "@comis/channels";
18
- import { ok } from "@comis/shared";
19
+ import { ok, suppressError } from "@comis/shared";
19
20
  import { createHash } from "node:crypto";
20
21
  // ---------------------------------------------------------------------------
21
22
  // Setup function
@@ -28,28 +29,56 @@ export async function setupDeliveryQueue(deps) {
28
29
  logger.debug("Delivery queue disabled by config");
29
30
  return {
30
31
  deliveryQueue: createNoOpDeliveryQueue(),
31
- drainAndStartPrune: async () => { },
32
+ drainAndStart: async () => { },
32
33
  shutdown: () => { },
33
34
  };
34
35
  }
35
36
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- db is better-sqlite3 Database; typed as unknown to avoid cross-package type dependency
36
- const deliveryQueue = createSqliteDeliveryQueue(db);
37
+ const deliveryQueue = createSqliteDeliveryQueue(db, eventBus);
37
38
  logger.info({ maxQueueDepth: queueConfig.maxQueueDepth, defaultMaxAttempts: queueConfig.defaultMaxAttempts }, "Delivery queue enabled");
38
39
  let pruneInterval;
39
- // 2. Startup drain + 3. Periodic prune (deferred until channelAdapters populated)
40
- const drainAndStartPrune = async () => {
41
- // --- Drain ---
40
+ let drainInterval;
41
+ // Single-tick gate: in-flight Promise prevents overlapping ticks.
42
+ let draining = null;
43
+ // Inner helper: one drain pass. Reused by startup drain AND each recurring tick.
44
+ const runOneDrainPass = async () => {
45
+ await drainDeliveryQueue({
46
+ deliveryQueue,
47
+ channelAdapters,
48
+ eventBus,
49
+ logger,
50
+ drainBudgetMs: queueConfig.drainBudgetMs,
51
+ defaultMaxAttempts: queueConfig.defaultMaxAttempts,
52
+ });
53
+ };
54
+ // 2. Startup drain + recurring drain timer + prune timer (deferred until channelAdapters populated)
55
+ const drainAndStart = async () => {
56
+ // --- Step 1: Recover in_flight rows. ---
57
+ // Runs UNCONDITIONALLY -- independent of drainOnStartup policy. An 'in_flight'
58
+ // row from a prior crash is a correctness bug regardless of the drain policy.
59
+ const recoverResult = await deliveryQueue.recoverInFlight();
60
+ if (!recoverResult.ok) {
61
+ logger.warn({ err: recoverResult.error, hint: "Could not recover in_flight rows on startup; messages may stall until next restart", errorKind: "internal" }, "Delivery queue: recoverInFlight failed");
62
+ }
63
+ else if (recoverResult.value > 0) {
64
+ logger.info({ recovered: recoverResult.value }, "Delivery queue: recovered in_flight rows to pending");
65
+ }
66
+ // --- Step 2: Startup drain (existing behavior, unchanged). ---
42
67
  if (queueConfig.drainOnStartup) {
43
- await drainDeliveryQueue({
44
- deliveryQueue,
45
- channelAdapters,
46
- eventBus,
47
- logger,
48
- drainBudgetMs: queueConfig.drainBudgetMs,
49
- defaultMaxAttempts: queueConfig.defaultMaxAttempts,
50
- });
68
+ await runOneDrainPass();
51
69
  }
52
- // --- Prune timer ---
70
+ // --- Step 3: Recurring drain timer. ---
71
+ drainInterval = setInterval(() => {
72
+ if (draining)
73
+ return; // single-tick gate
74
+ draining = runOneDrainPass().finally(() => { draining = null; });
75
+ // Fire-and-forget: failures inside drainDeliveryQueue are already logged
76
+ // and do not propagate (it never throws). suppressError satisfies the
77
+ // no-floating-promise lint without altering semantics.
78
+ suppressError(draining, "delivery queue recurring drain tick");
79
+ }, queueConfig.drainIntervalMs);
80
+ drainInterval.unref();
81
+ // --- Step 4: Prune timer (existing behavior, unchanged). ---
53
82
  pruneInterval = setInterval(async () => {
54
83
  const result = await deliveryQueue.pruneExpired();
55
84
  if (result.ok && result.value > 0) {
@@ -59,17 +88,21 @@ export async function setupDeliveryQueue(deps) {
59
88
  pruneInterval.unref();
60
89
  };
61
90
  const shutdown = () => {
91
+ if (drainInterval) {
92
+ clearInterval(drainInterval);
93
+ drainInterval = undefined;
94
+ }
62
95
  if (pruneInterval) {
63
96
  clearInterval(pruneInterval);
64
97
  pruneInterval = undefined;
65
98
  }
66
99
  };
67
- return { deliveryQueue, drainAndStartPrune, shutdown };
100
+ return { deliveryQueue, drainAndStart, shutdown };
68
101
  }
69
102
  // ---------------------------------------------------------------------------
70
103
  // Drain implementation
71
104
  // ---------------------------------------------------------------------------
72
- async function drainDeliveryQueue(deps) {
105
+ export async function drainDeliveryQueue(deps) {
73
106
  const { deliveryQueue, channelAdapters, eventBus, logger, drainBudgetMs, defaultMaxAttempts } = deps;
74
107
  const drainStart = Date.now();
75
108
  const deadline = drainStart + drainBudgetMs;
@@ -108,6 +108,10 @@ export async function setupSchedulers(deps) {
108
108
  payloadKind: job.payload.kind,
109
109
  sessionStrategy: job.sessionStrategy,
110
110
  maxHistoryTurns: job.maxHistoryTurns,
111
+ // Cadence is a literal number only for kind === "every"; cron-expression
112
+ // schedules would require parsing the expression to estimate a cadence,
113
+ // which is out of scope. Consumers must treat undefined as "unknown".
114
+ cadenceMs: job.schedule.kind === "every" ? job.schedule.everyMs : undefined,
111
115
  cronJobModel: job.payload.kind === "agent_turn" ? job.payload.model : undefined,
112
116
  cacheRetention: job.cacheRetention,
113
117
  toolPolicy: job.toolPolicy,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@comis/daemon",
3
3
  "private": true,
4
- "version": "1.0.33",
4
+ "version": "1.0.36",
5
5
  "author": "Moshe Anconina",
6
6
  "license": "Apache-2.0",
7
7
  "description": "Background daemon and orchestrator for the Comis platform",
@@ -9,6 +9,8 @@ export type { RpcAdapterDeps } from "./rpc/rpc-adapters.js";
9
9
  export { WsConnectionManager } from "./rpc/ws-handler.js";
10
10
  export { createMappedWebhookEndpoint } from "./webhook/webhook-endpoint.js";
11
11
  export { getPresetMappings } from "./webhook/webhook-presets.js";
12
+ export { createOAuthCallbackRoute, insertPendingFlow, PENDING_FLOW_TIMEOUT_MS, } from "./oauth/oauth-callback-route.js";
13
+ export type { OAuthCallbackDeps, PendingFlow, } from "./oauth/oauth-callback-route.js";
12
14
  export { createMediaRoutes } from "./web/index.js";
13
15
  export { createOpenaiCompletionsRoute } from "./openai/index.js";
14
16
  export { createOpenaiModelsRoute } from "./openai/index.js";
@@ -16,6 +16,8 @@ export { WsConnectionManager } from "./rpc/ws-handler.js";
16
16
  // Webhook
17
17
  export { createMappedWebhookEndpoint } from "./webhook/webhook-endpoint.js";
18
18
  export { getPresetMappings } from "./webhook/webhook-presets.js";
19
+ // OAuth callback route exports
20
+ export { createOAuthCallbackRoute, insertPendingFlow, PENDING_FLOW_TIMEOUT_MS, } from "./oauth/oauth-callback-route.js";
19
21
  // Web -- media routes
20
22
  export { createMediaRoutes } from "./web/index.js";
21
23
  // OpenAI compatibility endpoints
@@ -0,0 +1,66 @@
1
+ /**
2
+ * OAuth callback route for the Comis gateway.
3
+ *
4
+ * Mounted at `GET /callback/:provider` via `app.route("/oauth", subApp)`. The
5
+ * handler validates code+state, looks up the state in the in-memory pending-
6
+ * flow map, verifies path-vs-flow provider match, deletes the entry BEFORE
7
+ * the token exchange (one-time-use invariant), exchanges the code at
8
+ * auth.openai.com/oauth/token, resolves identity via
9
+ * resolveCodexAuthIdentity, persists via OAuthCredentialStorePort.set, emits
10
+ * auth:profile_bootstrapped, and returns a static "Login Successful" HTML
11
+ * page (200) on success or a "Login Failed" HTML page (400/500) on failure.
12
+ *
13
+ * HTTP method is GET, NOT POST (OAuth servers always redirect with GET).
14
+ * Logging discipline (CLAUDE.md): submodule: "oauth-callback"
15
+ * on every line; NEVER log code/state/verifier/access/refresh values.
16
+ *
17
+ * @module
18
+ */
19
+ import { Hono } from "hono";
20
+ import type { OAuthCredentialStorePort, TypedEventBus } from "@comis/core";
21
+ import type { GatewayLogger } from "../server/hono-server.js";
22
+ /** 5-minute pending-flow expiry. Exported for test parity. */
23
+ export declare const PENDING_FLOW_TIMEOUT_MS: number;
24
+ /**
25
+ * Pending-flow entry stored in the in-memory map keyed by `state`.
26
+ * Created by insertPendingFlow at flow-initiation time; consumed by the
27
+ * /callback/:provider handler on a successful state-match.
28
+ */
29
+ export interface PendingFlow {
30
+ /** PKCE code_verifier generated at flow initiation. */
31
+ verifier: string;
32
+ /** "openai-codex" — used for path-vs-flow provider validation. */
33
+ provider: string;
34
+ /** Date.now() at insertion time. */
35
+ createdAt: number;
36
+ /**
37
+ * Cleanup timer reference. The handler clearTimeout(timer) on consume;
38
+ * the auto-expiry path (PENDING_FLOW_TIMEOUT_MS) deletes the entry.
39
+ */
40
+ timer: ReturnType<typeof setTimeout>;
41
+ }
42
+ /** Dependencies for createOAuthCallbackRoute. */
43
+ export interface OAuthCallbackDeps {
44
+ readonly credentialStore: OAuthCredentialStorePort;
45
+ readonly eventBus: TypedEventBus;
46
+ readonly logger: GatewayLogger;
47
+ /** State -> PendingFlow map; mutated by handler + insertPendingFlow. */
48
+ readonly pendingFlows: Map<string, PendingFlow>;
49
+ }
50
+ /**
51
+ * Seed the pending-flow map with a new state -> PendingFlow entry, scheduling
52
+ * a 5-minute auto-delete cleanup timer.
53
+ *
54
+ * The caller is responsible for generating `state` via crypto.randomBytes(16)
55
+ * — never hand-roll a PRNG.
56
+ */
57
+ export declare function insertPendingFlow(map: Map<string, PendingFlow>, state: string, flow: Omit<PendingFlow, "timer">, logger: GatewayLogger): void;
58
+ /**
59
+ * Create the OAuth callback Hono sub-app.
60
+ *
61
+ * Mount via:
62
+ * const app = new Hono();
63
+ * app.route("/oauth", createOAuthCallbackRoute(deps));
64
+ * Resulting URL: GET /oauth/callback/:provider
65
+ */
66
+ export declare function createOAuthCallbackRoute(deps: OAuthCallbackDeps): Hono;