comisai 1.0.34 → 1.0.37

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 (448) 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 +30 -4
  3. package/node_modules/@comis/agent/dist/background/background-task-manager.d.ts +22 -2
  4. package/node_modules/@comis/agent/dist/background/background-task-manager.js +88 -40
  5. package/node_modules/@comis/agent/dist/background/background-task-persistence.js +34 -4
  6. package/node_modules/@comis/agent/dist/background/background-task-types.d.ts +59 -3
  7. package/node_modules/@comis/agent/dist/background/background-task-types.js +1 -1
  8. package/node_modules/@comis/agent/dist/background/completion-dispatcher.d.ts +130 -0
  9. package/node_modules/@comis/agent/dist/background/completion-dispatcher.js +215 -0
  10. package/node_modules/@comis/agent/dist/background/completion-formatter.d.ts +39 -0
  11. package/node_modules/@comis/agent/dist/background/completion-formatter.js +77 -0
  12. package/node_modules/@comis/agent/dist/background/completion-runner.d.ts +62 -0
  13. package/node_modules/@comis/agent/dist/background/completion-runner.js +234 -0
  14. package/node_modules/@comis/agent/dist/background/index.d.ts +10 -1
  15. package/node_modules/@comis/agent/dist/background/index.js +4 -0
  16. package/node_modules/@comis/agent/dist/background/session-resolver.d.ts +85 -0
  17. package/node_modules/@comis/agent/dist/background/session-resolver.js +78 -0
  18. package/node_modules/@comis/agent/dist/bootstrap/sections/messaging-sections.js +1 -0
  19. package/node_modules/@comis/agent/dist/bootstrap/sections/tool-descriptions.js +3 -3
  20. package/node_modules/@comis/agent/dist/bootstrap/sections/tooling-sections.d.ts +30 -2
  21. package/node_modules/@comis/agent/dist/bootstrap/sections/tooling-sections.js +51 -2
  22. package/node_modules/@comis/agent/dist/bootstrap/system-prompt-assembler.d.ts +22 -0
  23. package/node_modules/@comis/agent/dist/bootstrap/system-prompt-assembler.js +2 -2
  24. package/node_modules/@comis/agent/dist/bridge/bridge-event-handlers.d.ts +1 -5
  25. package/node_modules/@comis/agent/dist/bridge/bridge-event-handlers.js +2 -14
  26. package/node_modules/@comis/agent/dist/bridge/bridge-metrics.d.ts +43 -2
  27. package/node_modules/@comis/agent/dist/bridge/bridge-metrics.js +17 -2
  28. package/node_modules/@comis/agent/dist/bridge/pi-event-bridge.d.ts +32 -23
  29. package/node_modules/@comis/agent/dist/bridge/pi-event-bridge.js +145 -62
  30. package/node_modules/@comis/agent/dist/bridge/thinking-block-hash-invariant.d.ts +6 -7
  31. package/node_modules/@comis/agent/dist/bridge/thinking-block-hash-invariant.js +24 -25
  32. package/node_modules/@comis/agent/dist/budget/cost-tracker.d.ts +1 -1
  33. package/node_modules/@comis/agent/dist/context-engine/constants.d.ts +5 -5
  34. package/node_modules/@comis/agent/dist/context-engine/constants.js +12 -12
  35. package/node_modules/@comis/agent/dist/context-engine/context-engine.js +13 -4
  36. package/node_modules/@comis/agent/dist/context-engine/dag-annotator.d.ts +1 -2
  37. package/node_modules/@comis/agent/dist/context-engine/dag-annotator.js +1 -2
  38. package/node_modules/@comis/agent/dist/context-engine/llm-compaction.js +20 -16
  39. package/node_modules/@comis/agent/dist/context-engine/rehydration.js +6 -6
  40. package/node_modules/@comis/agent/dist/context-engine/signature-replay-scrubber.d.ts +12 -12
  41. package/node_modules/@comis/agent/dist/context-engine/signature-replay-scrubber.js +36 -22
  42. package/node_modules/@comis/agent/dist/context-engine/signature-surrogate-guard.d.ts +10 -10
  43. package/node_modules/@comis/agent/dist/context-engine/signature-surrogate-guard.js +14 -14
  44. package/node_modules/@comis/agent/dist/context-engine/thinking-block-cleaner.d.ts +11 -13
  45. package/node_modules/@comis/agent/dist/context-engine/thinking-block-cleaner.js +14 -15
  46. package/node_modules/@comis/agent/dist/context-engine/types-core.d.ts +15 -0
  47. package/node_modules/@comis/agent/dist/executor/cache-break-detection.d.ts +6 -6
  48. package/node_modules/@comis/agent/dist/executor/cache-break-detection.js +8 -8
  49. package/node_modules/@comis/agent/dist/executor/capability-index-context.d.ts +72 -0
  50. package/node_modules/@comis/agent/dist/executor/capability-index-context.js +329 -0
  51. package/node_modules/@comis/agent/dist/executor/drain-helper.d.ts +122 -0
  52. package/node_modules/@comis/agent/dist/executor/drain-helper.js +173 -0
  53. package/node_modules/@comis/agent/dist/executor/error-classifier.js +2 -2
  54. package/node_modules/@comis/agent/dist/executor/executor-context-engine-setup.d.ts +16 -0
  55. package/node_modules/@comis/agent/dist/executor/executor-context-engine-setup.js +46 -5
  56. package/node_modules/@comis/agent/dist/executor/executor-post-execution.d.ts +78 -4
  57. package/node_modules/@comis/agent/dist/executor/executor-post-execution.js +150 -31
  58. package/node_modules/@comis/agent/dist/executor/executor-prompt-runner.d.ts +7 -0
  59. package/node_modules/@comis/agent/dist/executor/executor-prompt-runner.js +26 -5
  60. package/node_modules/@comis/agent/dist/executor/executor-response-filter.d.ts +7 -6
  61. package/node_modules/@comis/agent/dist/executor/executor-response-filter.js +9 -42
  62. package/node_modules/@comis/agent/dist/executor/executor-tool-assembly.d.ts +18 -1
  63. package/node_modules/@comis/agent/dist/executor/executor-tool-assembly.js +20 -18
  64. package/node_modules/@comis/agent/dist/executor/gemini-cache-injector.d.ts +2 -2
  65. package/node_modules/@comis/agent/dist/executor/gemini-cache-injector.js +4 -4
  66. package/node_modules/@comis/agent/dist/executor/jit-guide-injector.d.ts +11 -2
  67. package/node_modules/@comis/agent/dist/executor/jit-guide-injector.js +16 -2
  68. package/node_modules/@comis/agent/dist/executor/phase-filter.d.ts +2 -2
  69. package/node_modules/@comis/agent/dist/executor/phase-filter.js +5 -7
  70. package/node_modules/@comis/agent/dist/executor/pi-executor.d.ts +21 -2
  71. package/node_modules/@comis/agent/dist/executor/pi-executor.js +96 -18
  72. package/node_modules/@comis/agent/dist/executor/post-batch-continuation.js +7 -7
  73. package/node_modules/@comis/agent/dist/executor/prompt-assembly.d.ts +9 -1
  74. package/node_modules/@comis/agent/dist/executor/prompt-assembly.js +15 -1
  75. package/node_modules/@comis/agent/dist/executor/stream-wrappers/request-body-injector.d.ts +1 -1
  76. package/node_modules/@comis/agent/dist/executor/stream-wrappers/request-body-injector.js +1 -1
  77. package/node_modules/@comis/agent/dist/executor/tool-deferral.d.ts +18 -27
  78. package/node_modules/@comis/agent/dist/executor/tool-deferral.js +34 -43
  79. package/node_modules/@comis/agent/dist/index.d.ts +17 -0
  80. package/node_modules/@comis/agent/dist/index.js +32 -11
  81. package/node_modules/@comis/agent/dist/model/auth-provider.d.ts +25 -2
  82. package/node_modules/@comis/agent/dist/model/auth-provider.js +6 -0
  83. package/node_modules/@comis/agent/dist/model/compaction-model-resolver.d.ts +3 -3
  84. package/node_modules/@comis/agent/dist/model/compaction-model-resolver.js +3 -3
  85. package/node_modules/@comis/agent/dist/model/model-registry-adapter.js +1 -1
  86. package/node_modules/@comis/agent/dist/model/model-scanner.js +1 -1
  87. package/node_modules/@comis/agent/dist/model/oauth-credential-store-file.d.ts +37 -0
  88. package/node_modules/@comis/agent/dist/model/oauth-credential-store-file.js +279 -0
  89. package/node_modules/@comis/agent/dist/model/oauth-credential-store-selector.d.ts +49 -0
  90. package/node_modules/@comis/agent/dist/model/oauth-credential-store-selector.js +50 -0
  91. package/node_modules/@comis/agent/dist/model/oauth-device-code.d.ts +57 -0
  92. package/node_modules/@comis/agent/dist/model/oauth-device-code.js +302 -0
  93. package/node_modules/@comis/agent/dist/model/oauth-env.d.ts +33 -0
  94. package/node_modules/@comis/agent/dist/model/oauth-env.js +38 -0
  95. package/node_modules/@comis/agent/dist/model/oauth-errors.d.ts +41 -0
  96. package/node_modules/@comis/agent/dist/model/oauth-errors.js +88 -0
  97. package/node_modules/@comis/agent/dist/model/oauth-identity.d.ts +53 -0
  98. package/node_modules/@comis/agent/dist/model/oauth-identity.js +141 -0
  99. package/node_modules/@comis/agent/dist/model/oauth-login-runner.d.ts +99 -0
  100. package/node_modules/@comis/agent/dist/model/oauth-login-runner.js +374 -0
  101. package/node_modules/@comis/agent/dist/model/oauth-tls-preflight.d.ts +58 -0
  102. package/node_modules/@comis/agent/dist/model/oauth-tls-preflight.js +82 -0
  103. package/node_modules/@comis/agent/dist/model/oauth-token-manager.d.ts +86 -16
  104. package/node_modules/@comis/agent/dist/model/oauth-token-manager.js +961 -66
  105. package/node_modules/@comis/agent/dist/model/operation-model-defaults.d.ts +9 -4
  106. package/node_modules/@comis/agent/dist/model/operation-model-defaults.js +36 -9
  107. package/node_modules/@comis/agent/dist/model/resolve-provider-api-key.d.ts +48 -0
  108. package/node_modules/@comis/agent/dist/model/resolve-provider-api-key.js +66 -0
  109. package/node_modules/@comis/agent/dist/provider/capabilities.d.ts +5 -5
  110. package/node_modules/@comis/agent/dist/provider/capabilities.js +10 -23
  111. package/node_modules/@comis/agent/dist/safety/tool-output-safety.js +3 -3
  112. package/node_modules/@comis/agent/dist/safety/tool-retry-breaker.d.ts +11 -1
  113. package/node_modules/@comis/agent/dist/safety/tool-retry-breaker.js +19 -22
  114. package/node_modules/@comis/agent/dist/session/comis-session-manager.d.ts +17 -3
  115. package/node_modules/@comis/agent/dist/session/comis-session-manager.js +1 -1
  116. package/node_modules/@comis/agent/dist/spawn/narrative-caster.d.ts +10 -0
  117. package/node_modules/@comis/agent/dist/spawn/narrative-caster.js +5 -1
  118. package/node_modules/@comis/agent/dist/spawn/pi-mono-adapters.d.ts +1 -1
  119. package/node_modules/@comis/agent/dist/spawn/pi-mono-adapters.js +5 -5
  120. package/node_modules/@comis/agent/dist/workspace/data-env.d.ts +38 -0
  121. package/node_modules/@comis/agent/dist/workspace/data-env.js +56 -0
  122. package/node_modules/@comis/agent/dist/workspace/index.d.ts +1 -0
  123. package/node_modules/@comis/agent/dist/workspace/index.js +1 -0
  124. package/node_modules/@comis/agent/dist/workspace/templates.js +5 -1
  125. package/node_modules/@comis/agent/package.json +1 -1
  126. package/node_modules/@comis/channels/dist/email/email-adapter.js +6 -6
  127. package/node_modules/@comis/channels/dist/email/imap-lifecycle.js +7 -7
  128. package/node_modules/@comis/channels/dist/index.d.ts +1 -1
  129. package/node_modules/@comis/channels/dist/index.js +1 -1
  130. package/node_modules/@comis/channels/dist/shared/channel-manager.d.ts +9 -3
  131. package/node_modules/@comis/channels/dist/shared/deliver-to-channel.js +12 -10
  132. package/node_modules/@comis/channels/dist/shared/inbound-gate.d.ts +1 -1
  133. package/node_modules/@comis/channels/dist/shared/inbound-gate.js +22 -7
  134. package/node_modules/@comis/channels/dist/shared/inbound-pipeline.d.ts +10 -3
  135. package/node_modules/@comis/channels/dist/shared/inbound-route.d.ts +1 -1
  136. package/node_modules/@comis/channels/dist/shared/inbound-route.js +13 -2
  137. package/node_modules/@comis/channels/dist/shared/response-filter.d.ts +11 -24
  138. package/node_modules/@comis/channels/dist/shared/response-filter.js +25 -53
  139. package/node_modules/@comis/channels/dist/telegram/telegram-adapter.js +1 -1
  140. package/node_modules/@comis/channels/package.json +1 -1
  141. package/node_modules/@comis/cli/dist/cli.js +2 -0
  142. package/node_modules/@comis/cli/dist/commands/agent.d.ts +3 -3
  143. package/node_modules/@comis/cli/dist/commands/agent.js +46 -3
  144. package/node_modules/@comis/cli/dist/commands/auth.d.ts +37 -0
  145. package/node_modules/@comis/cli/dist/commands/auth.js +433 -0
  146. package/node_modules/@comis/cli/dist/commands/doctor.d.ts +4 -1
  147. package/node_modules/@comis/cli/dist/commands/doctor.js +20 -5
  148. package/node_modules/@comis/cli/dist/commands/providers.d.ts +1 -2
  149. package/node_modules/@comis/cli/dist/commands/providers.js +5 -6
  150. package/node_modules/@comis/cli/dist/doctor/checks/oauth-health.d.ts +39 -0
  151. package/node_modules/@comis/cli/dist/doctor/checks/oauth-health.js +399 -0
  152. package/node_modules/@comis/cli/dist/doctor/types.d.ts +19 -0
  153. package/node_modules/@comis/cli/dist/index.d.ts +1 -0
  154. package/node_modules/@comis/cli/dist/index.js +10 -4
  155. package/node_modules/@comis/cli/dist/output/relative-time.d.ts +23 -0
  156. package/node_modules/@comis/cli/dist/output/relative-time.js +36 -0
  157. package/node_modules/@comis/cli/dist/wizard/non-interactive.js +17 -8
  158. package/node_modules/@comis/cli/dist/wizard/steps/03-provider.js +2 -1
  159. package/node_modules/@comis/cli/dist/wizard/steps/04-credentials.js +223 -34
  160. package/node_modules/@comis/cli/dist/wizard/steps/10-write-config.js +14 -0
  161. package/node_modules/@comis/cli/dist/wizard/steps/11-daemon-start.js +3 -3
  162. package/node_modules/@comis/cli/dist/wizard/types.d.ts +7 -0
  163. package/node_modules/@comis/cli/package.json +1 -1
  164. package/node_modules/@comis/core/dist/bootstrap.d.ts +1 -1
  165. package/node_modules/@comis/core/dist/config/env-substitution.d.ts +66 -0
  166. package/node_modules/@comis/core/dist/config/env-substitution.js +115 -0
  167. package/node_modules/@comis/core/dist/config/field-metadata.js +2 -0
  168. package/node_modules/@comis/core/dist/config/immutable-keys.js +4 -1
  169. package/node_modules/@comis/core/dist/config/index.d.ts +7 -1
  170. package/node_modules/@comis/core/dist/config/index.js +4 -1
  171. package/node_modules/@comis/core/dist/config/loader.js +61 -0
  172. package/node_modules/@comis/core/dist/config/managed-sections.d.ts +3 -3
  173. package/node_modules/@comis/core/dist/config/managed-sections.js +10 -5
  174. package/node_modules/@comis/core/dist/config/schema-agent.d.ts +4 -792
  175. package/node_modules/@comis/core/dist/config/schema-agent.js +16 -1
  176. package/node_modules/@comis/core/dist/config/schema-approvals.d.ts +0 -14
  177. package/node_modules/@comis/core/dist/config/schema-auto-reply-engine.d.ts +0 -6
  178. package/node_modules/@comis/core/dist/config/schema-background-tasks.d.ts +1 -6
  179. package/node_modules/@comis/core/dist/config/schema-background-tasks.js +7 -0
  180. package/node_modules/@comis/core/dist/config/schema-browser.d.ts +0 -18
  181. package/node_modules/@comis/core/dist/config/schema-channel.d.ts +0 -158
  182. package/node_modules/@comis/core/dist/config/schema-coalescer.d.ts +0 -5
  183. package/node_modules/@comis/core/dist/config/schema-daemon.d.ts +0 -32
  184. package/node_modules/@comis/core/dist/config/schema-delivery.d.ts +1 -17
  185. package/node_modules/@comis/core/dist/config/schema-delivery.js +2 -0
  186. package/node_modules/@comis/core/dist/config/schema-documentation.d.ts +0 -12
  187. package/node_modules/@comis/core/dist/config/schema-embedding.d.ts +0 -20
  188. package/node_modules/@comis/core/dist/config/schema-envelope.d.ts +0 -15
  189. package/node_modules/@comis/core/dist/config/schema-gateway.d.ts +0 -37
  190. package/node_modules/@comis/core/dist/config/schema-gemini-cache.d.ts +0 -4
  191. package/node_modules/@comis/core/dist/config/schema-gemini-cache.js +0 -2
  192. package/node_modules/@comis/core/dist/config/schema-integrations.d.ts +0 -318
  193. package/node_modules/@comis/core/dist/config/schema-lifecycle-reactions.d.ts +0 -18
  194. package/node_modules/@comis/core/dist/config/schema-memory-review.d.ts +0 -7
  195. package/node_modules/@comis/core/dist/config/schema-memory.d.ts +0 -16
  196. package/node_modules/@comis/core/dist/config/schema-messages.d.ts +0 -8
  197. package/node_modules/@comis/core/dist/config/schema-models.d.ts +0 -15
  198. package/node_modules/@comis/core/dist/config/schema-notification.d.ts +0 -5
  199. package/node_modules/@comis/core/dist/config/schema-oauth.d.ts +18 -0
  200. package/node_modules/@comis/core/dist/config/schema-oauth.js +19 -0
  201. package/node_modules/@comis/core/dist/config/schema-observability.d.ts +0 -38
  202. package/node_modules/@comis/core/dist/config/schema-output-retention.d.ts +34 -0
  203. package/node_modules/@comis/core/dist/config/schema-output-retention.js +48 -0
  204. package/node_modules/@comis/core/dist/config/schema-plugins.d.ts +0 -8
  205. package/node_modules/@comis/core/dist/config/schema-providers.d.ts +0 -64
  206. package/node_modules/@comis/core/dist/config/schema-queue.d.ts +0 -58
  207. package/node_modules/@comis/core/dist/config/schema-response-prefix.d.ts +0 -2
  208. package/node_modules/@comis/core/dist/config/schema-retry.d.ts +0 -6
  209. package/node_modules/@comis/core/dist/config/schema-scheduler.d.ts +0 -39
  210. package/node_modules/@comis/core/dist/config/schema-secrets.d.ts +0 -3
  211. package/node_modules/@comis/core/dist/config/schema-security.d.ts +0 -18
  212. package/node_modules/@comis/core/dist/config/schema-send-policy.d.ts +0 -13
  213. package/node_modules/@comis/core/dist/config/schema-sender-trust-display.d.ts +0 -5
  214. package/node_modules/@comis/core/dist/config/schema-serializer.js +2 -0
  215. package/node_modules/@comis/core/dist/config/schema-skills.d.ts +0 -63
  216. package/node_modules/@comis/core/dist/config/schema-skills.js +3 -4
  217. package/node_modules/@comis/core/dist/config/schema-streaming.d.ts +0 -38
  218. package/node_modules/@comis/core/dist/config/schema-telegram-file-guard.d.ts +0 -3
  219. package/node_modules/@comis/core/dist/config/schema-tooling.d.ts +87 -0
  220. package/node_modules/@comis/core/dist/config/schema-tooling.js +152 -0
  221. package/node_modules/@comis/core/dist/config/schema-verbosity.d.ts +0 -12
  222. package/node_modules/@comis/core/dist/config/schema-webhooks.d.ts +0 -40
  223. package/node_modules/@comis/core/dist/config/schema.d.ts +50 -37
  224. package/node_modules/@comis/core/dist/config/schema.js +9 -0
  225. package/node_modules/@comis/core/dist/context/context.d.ts +0 -4
  226. package/node_modules/@comis/core/dist/domain/approval-request.d.ts +0 -17
  227. package/node_modules/@comis/core/dist/domain/background-task-origin.d.ts +29 -0
  228. package/node_modules/@comis/core/dist/domain/background-task-origin.js +39 -0
  229. package/node_modules/@comis/core/dist/domain/delivery-origin.d.ts +0 -5
  230. package/node_modules/@comis/core/dist/domain/execution-graph.d.ts +0 -48
  231. package/node_modules/@comis/core/dist/domain/memory-entry.d.ts +0 -3
  232. package/node_modules/@comis/core/dist/domain/model-compat.d.ts +0 -4
  233. package/node_modules/@comis/core/dist/domain/normalized-message.d.ts +0 -15
  234. package/node_modules/@comis/core/dist/domain/provider-capabilities.d.ts +0 -6
  235. package/node_modules/@comis/core/dist/domain/rich-message.d.ts +0 -14
  236. package/node_modules/@comis/core/dist/domain/subagent-context-config.d.ts +0 -22
  237. package/node_modules/@comis/core/dist/domain/subagent-context-types.d.ts +0 -8
  238. package/node_modules/@comis/core/dist/event-bus/events-agent.d.ts +31 -0
  239. package/node_modules/@comis/core/dist/event-bus/events-infra.d.ts +76 -2
  240. package/node_modules/@comis/core/dist/exports/config.d.ts +2 -2
  241. package/node_modules/@comis/core/dist/exports/config.js +3 -1
  242. package/node_modules/@comis/core/dist/exports/domain.d.ts +2 -0
  243. package/node_modules/@comis/core/dist/exports/domain.js +1 -0
  244. package/node_modules/@comis/core/dist/exports/hooks.d.ts +1 -1
  245. package/node_modules/@comis/core/dist/exports/ports.d.ts +2 -2
  246. package/node_modules/@comis/core/dist/exports/ports.js +1 -1
  247. package/node_modules/@comis/core/dist/ports/channel-plugin.d.ts +0 -13
  248. package/node_modules/@comis/core/dist/ports/delivery-queue.d.ts +23 -0
  249. package/node_modules/@comis/core/dist/ports/delivery-queue.js +2 -0
  250. package/node_modules/@comis/core/dist/ports/index.d.ts +4 -0
  251. package/node_modules/@comis/core/dist/ports/index.js +5 -0
  252. package/node_modules/@comis/core/dist/ports/no-op-tool-capability.d.ts +30 -0
  253. package/node_modules/@comis/core/dist/ports/no-op-tool-capability.js +47 -0
  254. package/node_modules/@comis/core/dist/ports/oauth-credential-store.d.ts +64 -0
  255. package/node_modules/@comis/core/dist/ports/oauth-credential-store.js +37 -0
  256. package/node_modules/@comis/core/dist/ports/tool-capability.d.ts +165 -0
  257. package/node_modules/@comis/core/dist/ports/tool-capability.js +15 -0
  258. package/node_modules/@comis/core/dist/security/audit.d.ts +0 -11
  259. package/node_modules/@comis/core/dist/tool-metadata.d.ts +41 -1
  260. package/node_modules/@comis/core/dist/tool-metadata.js +1 -1
  261. package/node_modules/@comis/core/package.json +1 -1
  262. package/node_modules/@comis/daemon/bundled-skills/skill-creator/scripts/validate-skill.py +1 -1
  263. package/node_modules/@comis/daemon/dist/daemon-types.d.ts +23 -3
  264. package/node_modules/@comis/daemon/dist/daemon.js +168 -30
  265. package/node_modules/@comis/daemon/dist/index.d.ts +2 -0
  266. package/node_modules/@comis/daemon/dist/index.js +5 -0
  267. package/node_modules/@comis/daemon/dist/observability/channel-health-logger.js +3 -3
  268. package/node_modules/@comis/daemon/dist/observability/delivery-queue-logger.js +1 -1
  269. package/node_modules/@comis/daemon/dist/rpc/agent-handlers.d.ts +22 -1
  270. package/node_modules/@comis/daemon/dist/rpc/agent-handlers.js +84 -21
  271. package/node_modules/@comis/daemon/dist/rpc/agent-inline-workspace.d.ts +1 -1
  272. package/node_modules/@comis/daemon/dist/rpc/agent-inline-workspace.js +3 -3
  273. package/node_modules/@comis/daemon/dist/rpc/builtin-provider-guard.js +2 -2
  274. package/node_modules/@comis/daemon/dist/rpc/config-handlers.d.ts +9 -1
  275. package/node_modules/@comis/daemon/dist/rpc/config-handlers.js +104 -23
  276. package/node_modules/@comis/daemon/dist/rpc/credential-resolver.d.ts +30 -1
  277. package/node_modules/@comis/daemon/dist/rpc/credential-resolver.js +74 -11
  278. package/node_modules/@comis/daemon/dist/rpc/mcp-handlers.d.ts +8 -0
  279. package/node_modules/@comis/daemon/dist/rpc/mcp-handlers.js +22 -8
  280. package/node_modules/@comis/daemon/dist/rpc/model-handlers.d.ts +1 -1
  281. package/node_modules/@comis/daemon/dist/rpc/model-handlers.js +2 -2
  282. package/node_modules/@comis/daemon/dist/rpc/provider-handlers.js +9 -12
  283. package/node_modules/@comis/daemon/dist/rpc/rpc-dispatch.d.ts +1 -0
  284. package/node_modules/@comis/daemon/dist/rpc/rpc-dispatch.js +27 -2
  285. package/node_modules/@comis/daemon/dist/setup-docker-restart-warn.js +0 -1
  286. package/node_modules/@comis/daemon/dist/sub-agent-runner.d.ts +18 -0
  287. package/node_modules/@comis/daemon/dist/sub-agent-runner.js +41 -9
  288. package/node_modules/@comis/daemon/dist/wiring/index.d.ts +4 -0
  289. package/node_modules/@comis/daemon/dist/wiring/index.js +2 -0
  290. package/node_modules/@comis/daemon/dist/wiring/oauth-preflight.d.ts +21 -0
  291. package/node_modules/@comis/daemon/dist/wiring/oauth-preflight.js +134 -0
  292. package/node_modules/@comis/daemon/dist/wiring/setup-agents.d.ts +81 -2
  293. package/node_modules/@comis/daemon/dist/wiring/setup-agents.js +164 -3
  294. package/node_modules/@comis/daemon/dist/wiring/setup-background-completion-runner.d.ts +58 -0
  295. package/node_modules/@comis/daemon/dist/wiring/setup-background-completion-runner.js +59 -0
  296. package/node_modules/@comis/daemon/dist/wiring/setup-background-tasks.d.ts +10 -3
  297. package/node_modules/@comis/daemon/dist/wiring/setup-background-tasks.js +13 -7
  298. package/node_modules/@comis/daemon/dist/wiring/setup-channels.d.ts +9 -2
  299. package/node_modules/@comis/daemon/dist/wiring/setup-channels.js +35 -10
  300. package/node_modules/@comis/daemon/dist/wiring/setup-cross-session.d.ts +20 -5
  301. package/node_modules/@comis/daemon/dist/wiring/setup-cross-session.js +21 -16
  302. package/node_modules/@comis/daemon/dist/wiring/setup-delivery.d.ts +14 -5
  303. package/node_modules/@comis/daemon/dist/wiring/setup-delivery.js +65 -20
  304. package/node_modules/@comis/daemon/dist/wiring/setup-gateway.d.ts +4 -6
  305. package/node_modules/@comis/daemon/dist/wiring/setup-gateway.js +3 -5
  306. package/node_modules/@comis/daemon/dist/wiring/setup-heartbeat.d.ts +20 -5
  307. package/node_modules/@comis/daemon/dist/wiring/setup-heartbeat.js +11 -2
  308. package/node_modules/@comis/daemon/dist/wiring/setup-output-retention.d.ts +89 -0
  309. package/node_modules/@comis/daemon/dist/wiring/setup-output-retention.js +212 -0
  310. package/node_modules/@comis/daemon/dist/wiring/setup-schedulers.js +4 -0
  311. package/node_modules/@comis/daemon/dist/wiring/setup-tools.d.ts +18 -4
  312. package/node_modules/@comis/daemon/dist/wiring/setup-tools.js +29 -10
  313. package/node_modules/@comis/daemon/dist/wiring/tool-capability-adapter.d.ts +75 -0
  314. package/node_modules/@comis/daemon/dist/wiring/tool-capability-adapter.js +253 -0
  315. package/node_modules/@comis/daemon/package.json +1 -1
  316. package/node_modules/@comis/gateway/dist/index.d.ts +2 -0
  317. package/node_modules/@comis/gateway/dist/index.js +2 -0
  318. package/node_modules/@comis/gateway/dist/oauth/oauth-callback-route.d.ts +66 -0
  319. package/node_modules/@comis/gateway/dist/oauth/oauth-callback-route.js +212 -0
  320. package/node_modules/@comis/gateway/dist/server/hono-server.d.ts +14 -0
  321. package/node_modules/@comis/gateway/dist/server/hono-server.js +10 -0
  322. package/node_modules/@comis/gateway/dist/webhook/webhook-endpoint.d.ts +0 -4
  323. package/node_modules/@comis/gateway/package.json +1 -1
  324. package/node_modules/@comis/infra/dist/logging/log-fields.d.ts +23 -0
  325. package/node_modules/@comis/infra/package.json +1 -1
  326. package/node_modules/@comis/memory/dist/compaction.d.ts +3 -5
  327. package/node_modules/@comis/memory/dist/compaction.js +2 -3
  328. package/node_modules/@comis/memory/dist/delivery-queue-adapter.d.ts +2 -2
  329. package/node_modules/@comis/memory/dist/delivery-queue-adapter.js +49 -1
  330. package/node_modules/@comis/memory/dist/index.d.ts +2 -0
  331. package/node_modules/@comis/memory/dist/index.js +3 -0
  332. package/node_modules/@comis/memory/dist/memory-api.d.ts +1 -1
  333. package/node_modules/@comis/memory/dist/memory-api.js +1 -1
  334. package/node_modules/@comis/memory/dist/oauth-profile-schema.d.ts +17 -0
  335. package/node_modules/@comis/memory/dist/oauth-profile-schema.js +33 -0
  336. package/node_modules/@comis/memory/dist/oauth-profile-store-encrypted.d.ts +27 -0
  337. package/node_modules/@comis/memory/dist/oauth-profile-store-encrypted.js +144 -0
  338. package/node_modules/@comis/memory/dist/session-store.d.ts +1 -1
  339. package/node_modules/@comis/memory/dist/session-store.js +1 -1
  340. package/node_modules/@comis/memory/dist/sqlite-secret-store.d.ts +29 -3
  341. package/node_modules/@comis/memory/dist/sqlite-secret-store.js +11 -3
  342. package/node_modules/@comis/memory/package.json +1 -1
  343. package/node_modules/@comis/scheduler/dist/cron/cron-types.d.ts +0 -42
  344. package/node_modules/@comis/scheduler/dist/execution/execution-lock.d.ts +13 -0
  345. package/node_modules/@comis/scheduler/dist/execution/execution-lock.js +1 -1
  346. package/node_modules/@comis/scheduler/dist/execution/index.d.ts +2 -0
  347. package/node_modules/@comis/scheduler/dist/execution/index.js +2 -0
  348. package/node_modules/@comis/scheduler/dist/heartbeat/agent-heartbeat-source.d.ts +29 -8
  349. package/node_modules/@comis/scheduler/dist/heartbeat/agent-heartbeat-source.js +20 -8
  350. package/node_modules/@comis/scheduler/dist/index.d.ts +2 -0
  351. package/node_modules/@comis/scheduler/dist/index.js +2 -0
  352. package/node_modules/@comis/scheduler/dist/system-events/system-event-types.d.ts +0 -3
  353. package/node_modules/@comis/scheduler/dist/tasks/task-types.d.ts +0 -17
  354. package/node_modules/@comis/scheduler/package.json +1 -1
  355. package/node_modules/@comis/shared/dist/index.d.ts +3 -0
  356. package/node_modules/@comis/shared/dist/index.js +4 -0
  357. package/node_modules/@comis/shared/dist/mcp-tool-name.d.ts +78 -0
  358. package/node_modules/@comis/shared/dist/mcp-tool-name.js +92 -0
  359. package/node_modules/@comis/shared/dist/silent-tokens.d.ts +38 -0
  360. package/node_modules/@comis/shared/dist/silent-tokens.js +51 -0
  361. package/node_modules/@comis/shared/dist/visible-delivery.d.ts +28 -0
  362. package/node_modules/@comis/shared/dist/visible-delivery.js +16 -0
  363. package/node_modules/@comis/shared/package.json +1 -1
  364. package/node_modules/@comis/skills/dist/bridge/mcp-tool-bridge.d.ts +2 -13
  365. package/node_modules/@comis/skills/dist/bridge/mcp-tool-bridge.js +3 -21
  366. package/node_modules/@comis/skills/dist/bridge/schema-validator.d.ts +38 -0
  367. package/node_modules/@comis/skills/dist/bridge/schema-validator.js +169 -0
  368. package/node_modules/@comis/skills/dist/bridge/tool-metadata-enforcement.js +12 -0
  369. package/node_modules/@comis/skills/dist/bridge/tool-metadata-registry.js +133 -3
  370. package/node_modules/@comis/skills/dist/builtin/exec-diagnostics.d.ts +32 -0
  371. package/node_modules/@comis/skills/dist/builtin/exec-diagnostics.js +127 -0
  372. package/node_modules/@comis/skills/dist/builtin/exec-security.js +38 -0
  373. package/node_modules/@comis/skills/dist/builtin/exec-tool.d.ts +55 -9
  374. package/node_modules/@comis/skills/dist/builtin/exec-tool.js +392 -19
  375. package/node_modules/@comis/skills/dist/builtin/file-tools/grep-tool.js +6 -6
  376. package/node_modules/@comis/skills/dist/builtin/install-detour.d.ts +67 -0
  377. package/node_modules/@comis/skills/dist/builtin/install-detour.js +342 -0
  378. package/node_modules/@comis/skills/dist/builtin/platform/admin-manage-factory.js +5 -5
  379. package/node_modules/@comis/skills/dist/builtin/platform/agents-manage-tool.d.ts +7 -6
  380. package/node_modules/@comis/skills/dist/builtin/platform/agents-manage-tool.js +40 -29
  381. package/node_modules/@comis/skills/dist/builtin/platform/background-tasks-tool.d.ts +4 -1
  382. package/node_modules/@comis/skills/dist/builtin/platform/background-tasks-tool.js +3 -3
  383. package/node_modules/@comis/skills/dist/builtin/platform/cron-tool.js +1 -1
  384. package/node_modules/@comis/skills/dist/builtin/platform/gateway-tool.js +6 -6
  385. package/node_modules/@comis/skills/dist/builtin/platform/mcp-manage-tool.d.ts +1 -1
  386. package/node_modules/@comis/skills/dist/builtin/platform/mcp-manage-tool.js +9 -9
  387. package/node_modules/@comis/skills/dist/builtin/platform/message-tool.js +18 -0
  388. package/node_modules/@comis/skills/dist/builtin/platform/messaging-factory.d.ts +18 -1
  389. package/node_modules/@comis/skills/dist/builtin/platform/messaging-factory.js +18 -2
  390. package/node_modules/@comis/skills/dist/builtin/platform/models-manage-tool.js +3 -3
  391. package/node_modules/@comis/skills/dist/builtin/process-registry.d.ts +14 -0
  392. package/node_modules/@comis/skills/dist/builtin/process-tool.d.ts +24 -4
  393. package/node_modules/@comis/skills/dist/builtin/process-tool.js +25 -7
  394. package/node_modules/@comis/skills/dist/builtin/sandbox/bwrap-provider.d.ts +11 -0
  395. package/node_modules/@comis/skills/dist/builtin/sandbox/bwrap-provider.js +123 -1
  396. package/node_modules/@comis/skills/dist/builtin/sandbox/detect-provider.js +40 -15
  397. package/node_modules/@comis/skills/dist/index.d.ts +4 -1
  398. package/node_modules/@comis/skills/dist/index.js +3 -1
  399. package/node_modules/@comis/skills/dist/manifest/capability-parser.d.ts +44 -0
  400. package/node_modules/@comis/skills/dist/manifest/capability-parser.js +68 -0
  401. package/node_modules/@comis/skills/dist/manifest/schema.d.ts +44 -37
  402. package/node_modules/@comis/skills/dist/manifest/schema.js +35 -0
  403. package/node_modules/@comis/skills/dist/media/ssrf-fetcher.d.ts +7 -0
  404. package/node_modules/@comis/skills/dist/media/ssrf-fetcher.js +9 -2
  405. package/node_modules/@comis/skills/dist/registry/discovery.d.ts +8 -0
  406. package/node_modules/@comis/skills/dist/registry/discovery.js +10 -3
  407. package/node_modules/@comis/skills/dist/registry/skill-registry.d.ts +45 -1
  408. package/node_modules/@comis/skills/dist/registry/skill-registry.js +70 -7
  409. package/node_modules/@comis/skills/package.json +1 -1
  410. package/node_modules/@comis/web/dist/assets/{agent-detail-71BSbSfD.js → agent-detail-q8t1NB7w.js} +1 -1
  411. package/node_modules/@comis/web/dist/assets/{agent-editor-CTSDZhwT.js → agent-editor-B46io5gv.js} +1 -1
  412. package/node_modules/@comis/web/dist/assets/{agent-list-BEhni2ea.js → agent-list-DQ6g2Rcx.js} +1 -1
  413. package/node_modules/@comis/web/dist/assets/{billing-view-DVP1IvVs.js → billing-view-IWPR8LgF.js} +1 -1
  414. package/node_modules/@comis/web/dist/assets/{channel-detail-N_YK74xC.js → channel-detail-DlNNZuuC.js} +1 -1
  415. package/node_modules/@comis/web/dist/assets/{channel-list-DRk6ZJaF.js → channel-list-DhGwxiMc.js} +1 -1
  416. package/node_modules/@comis/web/dist/assets/{chat-console-Dm-GtSf9.js → chat-console-Nv6fM3Rc.js} +1 -1
  417. package/node_modules/@comis/web/dist/assets/{config-editor-CIferYX6.js → config-editor-BYKuJF76.js} +1 -1
  418. package/node_modules/@comis/web/dist/assets/{context-dag-browser-CL84rXXM.js → context-dag-browser-ClNEtzYE.js} +1 -1
  419. package/node_modules/@comis/web/dist/assets/{context-engine-B1HOTEZv.js → context-engine-BZJ6HChd.js} +1 -1
  420. package/node_modules/@comis/web/dist/assets/{delivery-view-Y6JKYVFw.js → delivery-view-Cb7I3vGu.js} +1 -1
  421. package/node_modules/@comis/web/dist/assets/{diagnostics-view-DWV1UQjz.js → diagnostics-view-9u9Lyu5a.js} +1 -1
  422. package/node_modules/@comis/web/dist/assets/{ic-chat-message-DfSERzzg.js → ic-chat-message-BFt3cVpx.js} +1 -1
  423. package/node_modules/@comis/web/dist/assets/{ic-connection-dot-CXyhlJup.js → ic-connection-dot-y77LZ3Gu.js} +1 -1
  424. package/node_modules/@comis/web/dist/assets/{ic-tool-call-DNmwTjek.js → ic-tool-call-qt6w1NQl.js} +1 -1
  425. package/node_modules/@comis/web/dist/assets/{index-CBr0Tm9_.js → index-8Tg9oc-C.js} +2 -2
  426. package/node_modules/@comis/web/dist/assets/{mcp-management-BaH2-vox.js → mcp-management-69dtH_kY.js} +2 -2
  427. package/node_modules/@comis/web/dist/assets/{media-config-CZLshJoN.js → media-config-BdjLj5c1.js} +1 -1
  428. package/node_modules/@comis/web/dist/assets/{media-test-C9NUWgo_.js → media-test-DuPqrixi.js} +1 -1
  429. package/node_modules/@comis/web/dist/assets/{memory-inspector-D_fmTcRN.js → memory-inspector-B-Pepbq-.js} +1 -1
  430. package/node_modules/@comis/web/dist/assets/{message-center-BBFlNCZn.js → message-center-B7l0yNYY.js} +1 -1
  431. package/node_modules/@comis/web/dist/assets/{models-BytGLm99.js → models-JHFHuv5S.js} +1 -1
  432. package/node_modules/@comis/web/dist/assets/{observe-view-VXtHqaqq.js → observe-view-r8mqhy4O.js} +1 -1
  433. package/node_modules/@comis/web/dist/assets/{pipeline-builder-CfXczlfJ.js → pipeline-builder-XjkiZRcR.js} +1 -1
  434. package/node_modules/@comis/web/dist/assets/{pipeline-history-CPmXFnbe.js → pipeline-history-CZqJv_Hj.js} +1 -1
  435. package/node_modules/@comis/web/dist/assets/{pipeline-history-detail-DcueTMs9.js → pipeline-history-detail-BEFGMoDy.js} +1 -1
  436. package/node_modules/@comis/web/dist/assets/{pipeline-list-B-xG5WZh.js → pipeline-list-B6q5LvO1.js} +1 -1
  437. package/node_modules/@comis/web/dist/assets/{pipeline-monitor-pnIOYaSY.js → pipeline-monitor-BNomXjVL.js} +1 -1
  438. package/node_modules/@comis/web/dist/assets/{scheduler-BtUIFHhA.js → scheduler-BJEjcGKA.js} +1 -1
  439. package/node_modules/@comis/web/dist/assets/{security-C8mWRq2y.js → security-2G1jhBfV.js} +1 -1
  440. package/node_modules/@comis/web/dist/assets/{session-detail-DgdkO5ka.js → session-detail-DmVPzFBR.js} +1 -1
  441. package/node_modules/@comis/web/dist/assets/{session-list-DcylcfTn.js → session-list-CsqMQoHs.js} +1 -1
  442. package/node_modules/@comis/web/dist/assets/{setup-wizard-BP5yjsuL.js → setup-wizard-CAdM-gSP.js} +1 -1
  443. package/node_modules/@comis/web/dist/assets/{skills-DXt1bX8Z.js → skills-2ODqKaWr.js} +1 -1
  444. package/node_modules/@comis/web/dist/assets/{subagents-C7YbUHXY.js → subagents-BFlwfTbD.js} +1 -1
  445. package/node_modules/@comis/web/dist/assets/{workspace-manager-DP6pW4wa.js → workspace-manager--CbOx_dI.js} +1 -1
  446. package/node_modules/@comis/web/dist/index.html +1 -1
  447. package/node_modules/@comis/web/package.json +1 -1
  448. package/package.json +25 -24
@@ -0,0 +1,56 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ /**
3
+ * Workspace-internal data env resolver.
4
+ *
5
+ * Returns environment variables for python/matplotlib subprocesses that
6
+ * derive ALL paths from `workspaceDir`. Avoids slow pip installs in the
7
+ * chart hot path and matplotlib Fontconfig errors from a non-writable
8
+ * default cache dir.
9
+ *
10
+ * This file contains no host-env reads. Subprocesses inheriting the
11
+ * daemon's full environment can pick up host paths (e.g.
12
+ * `/root/.cache/matplotlib`) that fail under read-only systemd hardening
13
+ * (`ProtectSystem=strict`) and leak host PATH into the agent's tool
14
+ * execution.
15
+ *
16
+ * matplotlib + python deps install into the agent workspace's `venv/`.
17
+ * The Dockerfile pre-warms the default workspace's venv at image build
18
+ * time so first-chart latency drops; subsequent chart calls reuse the
19
+ * venv. Full Docker image size goes up (acceptable trade-off).
20
+ *
21
+ * Mirrors workspace-resolver.ts's safePath + workspaceDir precedent
22
+ * (no path.join, no host-env reads).
23
+ *
24
+ * @module
25
+ */
26
+ import { safePath } from "@comis/core";
27
+ /**
28
+ * Resolve workspace-internal env vars for python/matplotlib subprocesses.
29
+ *
30
+ * The returned record is intended to be MERGED over an existing subprocess
31
+ * env at the call site (e.g. exec-tool's `{ ...baseEnv, ...resolveDataEnv(...) }`),
32
+ * so the workspace-internal values win on collision and the host PATH /
33
+ * cache dirs are not surfaced inside the subprocess.
34
+ *
35
+ * @param opts.workspaceDir - Absolute path to the agent workspace.
36
+ * @returns env-var record suitable for `child_process.spawn(..., { env })`.
37
+ */
38
+ export function resolveDataEnv(opts) {
39
+ const venvBin = safePath(opts.workspaceDir, "venv", "bin");
40
+ const cacheDir = safePath(opts.workspaceDir, ".cache");
41
+ const mplDir = safePath(cacheDir, "matplotlib");
42
+ return {
43
+ // Python venv binaries on PATH (no host-PATH pollution).
44
+ PATH: venvBin,
45
+ // matplotlib config + cache dir (writable, workspace-internal).
46
+ MPLCONFIGDIR: mplDir,
47
+ // XDG cache spec -- fontconfig + other libs honor this.
48
+ XDG_CACHE_HOME: cacheDir,
49
+ // Force matplotlib to use a non-interactive backend (avoids
50
+ // Tkinter / X11 dependencies that would bloat the container image
51
+ // and otherwise crash on headless containers).
52
+ MPLBACKEND: "Agg",
53
+ // Disable pip's distrust of the (workspace-internal) venv path.
54
+ PIP_DISABLE_PIP_VERSION_CHECK: "1",
55
+ };
56
+ }
@@ -1,6 +1,7 @@
1
1
  export { ensureWorkspace, getWorkspaceStatus, registerWorkspaceFilesInTracker, WORKSPACE_SUBDIRS, } from "./workspace-manager.js";
2
2
  export type { WorkspaceFiles, EnsureWorkspaceOptions, WorkspaceStatus, WorkspaceSeedTracker, RegisterWorkspaceResult, } from "./workspace-manager.js";
3
3
  export { resolveWorkspaceDir } from "./workspace-resolver.js";
4
+ export { resolveDataEnv } from "./data-env.js";
4
5
  export { WORKSPACE_FILE_NAMES, DEFAULT_TEMPLATES } from "./templates.js";
5
6
  export type { WorkspaceFileName } from "./templates.js";
6
7
  export { isHeartbeatContentEffectivelyEmpty } from "./heartbeat-file.js";
@@ -1,6 +1,7 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  export { ensureWorkspace, getWorkspaceStatus, registerWorkspaceFilesInTracker, WORKSPACE_SUBDIRS, } from "./workspace-manager.js";
3
3
  export { resolveWorkspaceDir } from "./workspace-resolver.js";
4
+ export { resolveDataEnv } from "./data-env.js";
4
5
  export { WORKSPACE_FILE_NAMES, DEFAULT_TEMPLATES } from "./templates.js";
5
6
  export { isHeartbeatContentEffectivelyEmpty } from "./heartbeat-file.js";
6
7
  export { isBootContentEffectivelyEmpty, BOOT_FILE_NAME } from "./boot-file.js";
@@ -203,7 +203,11 @@ Capture what matters. The system persists it automatically.
203
203
  ## Workspace Organization
204
204
 
205
205
  \`\`\`
206
- projects/ -- Code repos (each in its own subfolder, venvs inside as .venv)
206
+ projects/ -- Code repos (each in its own subfolder, .venv per repo)
207
+ venv/ -- Pre-warmed Python env (matplotlib, numpy, pandas on PATH).
208
+ Use venv/bin/python for chart/data work; venv/bin/pip
209
+ install <pkg> for extras. Per-project venvs go inside
210
+ projects/<name>/.venv (separate lifecycle).
207
211
  scripts/ -- Standalone reusable scripts
208
212
  documents/ -- Text docs, PDFs, spreadsheets, markdown
209
213
  media/ -- User-provided images, audio, video
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@comis/agent",
3
3
  "private": true,
4
- "version": "1.0.34",
4
+ "version": "1.0.37",
5
5
  "author": "Moshe Anconina",
6
6
  "license": "Apache-2.0",
7
7
  "description": "AI agent executor, budget control, and session management for Comis",
@@ -81,12 +81,12 @@ export function createEmailAdapter(deps) {
81
81
  const fromAddress = parsed.from?.value[0]?.address ?? "";
82
82
  // Skip automated senders
83
83
  if (isAutomatedSender(headers, fromAddress)) {
84
- deps.logger.debug({ channelType, module: "email", fromAddress }, "Skipping automated sender");
84
+ deps.logger.debug({ channelType, submodule: "email", fromAddress }, "Skipping automated sender");
85
85
  return;
86
86
  }
87
87
  // Sender allowlist
88
88
  if (!isAllowedSender(fromAddress, deps.allowFrom, deps.allowMode)) {
89
- deps.logger.debug({ channelType, module: "email", fromAddress }, "Sender not in allowlist, skipping");
89
+ deps.logger.debug({ channelType, submodule: "email", fromAddress }, "Sender not in allowlist, skipping");
90
90
  return;
91
91
  }
92
92
  // Map to NormalizedMessage — adapt mailparser's ParsedMail to our structural type
@@ -108,7 +108,7 @@ export function createEmailAdapter(deps) {
108
108
  }
109
109
  }
110
110
  catch (e) {
111
- deps.logger.warn({ err: e, channelType, module: "email", hint: "Failed to process inbound email", errorKind: "parse" }, "Inbound email processing failed");
111
+ deps.logger.warn({ err: e, channelType, submodule: "email", hint: "Failed to process inbound email", errorKind: "parse" }, "Inbound email processing failed");
112
112
  }
113
113
  });
114
114
  // -----------------------------------------------------------------------
@@ -126,7 +126,7 @@ export function createEmailAdapter(deps) {
126
126
  const result = await imapLifecycle.start();
127
127
  if (result.ok) {
128
128
  connected = true;
129
- deps.logger.info({ channelType, module: "email", channelId }, "Email adapter started");
129
+ deps.logger.info({ channelType, submodule: "email", channelId }, "Email adapter started");
130
130
  }
131
131
  return result;
132
132
  }
@@ -139,7 +139,7 @@ export function createEmailAdapter(deps) {
139
139
  transport.close();
140
140
  transport = undefined;
141
141
  }
142
- deps.logger.info({ channelType, module: "email", channelId }, "Email adapter stopped");
142
+ deps.logger.info({ channelType, submodule: "email", channelId }, "Email adapter stopped");
143
143
  return imapResult;
144
144
  }
145
145
  async function sendMessage(recipient, text, options) {
@@ -172,7 +172,7 @@ export function createEmailAdapter(deps) {
172
172
  const error = mailResult.error instanceof Error
173
173
  ? mailResult.error
174
174
  : new Error(String(mailResult.error));
175
- deps.logger.error({ err: error, channelType, module: "email", hint: "Check SMTP credentials and host", errorKind: "network" }, "Failed to send email");
175
+ deps.logger.error({ err: error, channelType, submodule: "email", hint: "Check SMTP credentials and host", errorKind: "network" }, "Failed to send email");
176
176
  return err(error);
177
177
  }
178
178
  const messageId = mailResult.value.messageId ?? "";
@@ -80,7 +80,7 @@ export function createImapLifecycle(opts) {
80
80
  }
81
81
  }
82
82
  catch (e) {
83
- opts.logger.warn({ err: e, channelType: "email", module: "imap", hint: "Fetch failed, will retry on next event", errorKind: "network" }, "Failed to fetch new messages");
83
+ opts.logger.warn({ err: e, channelType: "email", submodule: "imap", hint: "Fetch failed, will retry on next event", errorKind: "network" }, "Failed to fetch new messages");
84
84
  }
85
85
  }
86
86
  function scheduleReconnect() {
@@ -89,7 +89,7 @@ export function createImapLifecycle(opts) {
89
89
  // Add jitter: random 0-500ms
90
90
  const jitter = Math.floor(Math.random() * 500);
91
91
  const delay = reconnectDelay + jitter;
92
- opts.logger.info({ channelType: "email", module: "imap", delayMs: delay }, "Scheduling IMAP reconnect");
92
+ opts.logger.info({ channelType: "email", submodule: "imap", delayMs: delay }, "Scheduling IMAP reconnect");
93
93
  reconnectTimer = setTimeout(() => {
94
94
  if (stopped)
95
95
  return;
@@ -109,20 +109,20 @@ export function createImapLifecycle(opts) {
109
109
  });
110
110
  client.on("close", () => {
111
111
  if (!stopped) {
112
- opts.logger.info({ channelType: "email", module: "imap" }, "IMAP connection closed, scheduling reconnect");
112
+ opts.logger.info({ channelType: "email", submodule: "imap" }, "IMAP connection closed, scheduling reconnect");
113
113
  scheduleReconnect();
114
114
  }
115
115
  });
116
116
  client.on("error", (e) => {
117
117
  // Check if this is an IDLE-related error for polling fallback
118
118
  if (e.message && /idle/i.test(e.message)) {
119
- opts.logger.warn({ channelType: "email", module: "imap", hint: "Falling back to polling", errorKind: "capability" }, "IDLE not supported, switching to polling fallback");
119
+ opts.logger.warn({ channelType: "email", submodule: "imap", hint: "Falling back to polling", errorKind: "capability" }, "IDLE not supported, switching to polling fallback");
120
120
  startPolling();
121
121
  }
122
122
  });
123
123
  const connectResult = await fromPromise(client.connect());
124
124
  if (!connectResult.ok) {
125
- opts.logger.error({ err: connectResult.error, channelType: "email", module: "imap", hint: "Check IMAP credentials and host", errorKind: "network" }, "IMAP connection failed");
125
+ opts.logger.error({ err: connectResult.error, channelType: "email", submodule: "imap", hint: "Check IMAP credentials and host", errorKind: "network" }, "IMAP connection failed");
126
126
  scheduleReconnect();
127
127
  return err(connectResult.error instanceof Error ? connectResult.error : new Error(String(connectResult.error)));
128
128
  }
@@ -135,11 +135,11 @@ export function createImapLifecycle(opts) {
135
135
  }, STABLE_CONNECTION_MS + 1000);
136
136
  const lockResult = await fromPromise(client.getMailboxLock("INBOX"));
137
137
  if (!lockResult.ok) {
138
- opts.logger.error({ err: lockResult.error, channelType: "email", module: "imap", hint: "Could not lock INBOX", errorKind: "network" }, "Failed to get INBOX lock");
138
+ opts.logger.error({ err: lockResult.error, channelType: "email", submodule: "imap", hint: "Could not lock INBOX", errorKind: "network" }, "Failed to get INBOX lock");
139
139
  return err(lockResult.error instanceof Error ? lockResult.error : new Error(String(lockResult.error)));
140
140
  }
141
141
  lock = lockResult.value;
142
- opts.logger.info({ channelType: "email", module: "imap", host: opts.host }, "IMAP connected and listening");
142
+ opts.logger.info({ channelType: "email", submodule: "imap", host: opts.host }, "IMAP connected and listening");
143
143
  return ok(undefined);
144
144
  }
145
145
  function startPolling() {
@@ -99,7 +99,7 @@ export { evaluateAutoReply, isGroupMessage, isBotMentioned } from "./shared/auto
99
99
  export type { AutoReplyDecision } from "./shared/auto-reply-engine.js";
100
100
  export { audioPreflight } from "./shared/audio-preflight.js";
101
101
  export type { PreflightResult, PreflightDeps } from "./shared/audio-preflight.js";
102
- export { filterResponse, NO_REPLY_TOKEN } from "./shared/response-filter.js";
102
+ export { filterResponse, NO_REPLY_TOKEN, HEARTBEAT_OK_TOKEN } from "./shared/response-filter.js";
103
103
  export type { FilterResult } from "./shared/response-filter.js";
104
104
  export { mimeToAttachmentType } from "./shared/media-utils.js";
105
105
  export { normalizeTelegramPollResult, normalizeDiscordPollResult, normalizeWhatsAppPollResult, } from "./shared/poll-normalizer.js";
@@ -91,7 +91,7 @@ export { evaluateAutoReply, isGroupMessage, isBotMentioned } from "./shared/auto
91
91
  // Audio preflight
92
92
  export { audioPreflight } from "./shared/audio-preflight.js";
93
93
  // Response filter (NO_REPLY + HEARTBEAT_OK token suppression)
94
- export { filterResponse, NO_REPLY_TOKEN } from "./shared/response-filter.js";
94
+ export { filterResponse, NO_REPLY_TOKEN, HEARTBEAT_OK_TOKEN } from "./shared/response-filter.js";
95
95
  // Media utilities (shared attachment type resolution)
96
96
  export { mimeToAttachmentType } from "./shared/media-utils.js";
97
97
  // Poll result normalizers (cross-platform)
@@ -22,7 +22,7 @@ import type { DebounceBuffer } from "@comis/agent";
22
22
  import type { FollowupTrigger } from "@comis/agent";
23
23
  import type { PriorityScheduler } from "@comis/agent";
24
24
  import type { SessionLabelStore } from "@comis/agent";
25
- import type { ActiveRunRegistry } from "@comis/agent";
25
+ import type { ActiveRunRegistry, BackgroundSessionResolver } from "@comis/agent";
26
26
  import type { ChannelPort, DeliveryQueuePort, NormalizedMessage, SessionKey, TypedEventBus } from "@comis/core";
27
27
  import type { StreamingConfig } from "@comis/core";
28
28
  import type { AutoReplyEngineConfig, SendPolicyConfig, QueueConfig, ElevatedReplyConfig, AckReactionConfig } from "@comis/core";
@@ -126,6 +126,12 @@ export interface ChannelManagerDeps {
126
126
  }, Error>>;
127
127
  /** Optional active run registry for SDK-native steer+followup message routing. When absent, all messages route through CommandQueue. */
128
128
  activeRunRegistry?: ActiveRunRegistry;
129
+ /**
130
+ * Optional composite-key resolver. When present, supersedes
131
+ * `activeRunRegistry.has/.get` for production lookups in the inbound
132
+ * pipeline.
133
+ */
134
+ sessionResolver?: BackgroundSessionResolver;
129
135
  /** Handle /config command. Returns response text or undefined if not a config command. */
130
136
  handleConfigCommand?: (args: string[], channelType: string) => Promise<string | undefined>;
131
137
  /** Optional callback for task extraction after successful agent execution. */
@@ -151,9 +157,9 @@ export interface ChannelManagerDeps {
151
157
  };
152
158
  /** Template context builder for response prefix variables. */
153
159
  buildTemplateContext?: (agentId: string, channelType: string, msg: NormalizedMessage) => Record<string, string>;
154
- /** Optional approval gate for /approve and /deny chat commands (APPR-CHAT). When absent, approval commands pass through as plain text. */
160
+ /** Optional approval gate for /approve and /deny chat commands. When absent, approval commands pass through as plain text. */
155
161
  approvalGate?: InboundPipelineDeps["approvalGate"];
156
- /** Handle general slash commands via command handler (CMD-WIRE). */
162
+ /** Handle general slash commands via command handler. */
157
163
  handleSlashCommand?: InboundPipelineDeps["handleSlashCommand"];
158
164
  /** Per-agent enforceFinalTag config lookup. */
159
165
  getEnforceFinalTag?: InboundPipelineDeps["getEnforceFinalTag"];
@@ -302,10 +302,17 @@ export async function deliverToChannel(adapter, channelId, text, options, deps)
302
302
  if (Object.keys(rest).length > 0)
303
303
  sendOpts.extra = rest;
304
304
  }
305
- // --- Queue: enqueue before send ---
305
+ // --- Queue: enqueue (in_flight lease) before send ---
306
+ // We insert with status='in_flight' so the recurring drainer's
307
+ // `WHERE status='pending'` filter does NOT race-pick this row mid-send.
308
+ // On successful send, ack flips
309
+ // 'in_flight' -> 'delivered'; on permanent failure, fail flips
310
+ // 'in_flight' -> 'failed'; on transient failure, nack flips
311
+ // 'in_flight' -> 'pending' for the drainer to retry. All ack/nack/fail
312
+ // statements are status-agnostic UPDATE-by-id, so no SQL change is needed.
306
313
  let entryId = null;
307
314
  if (deps?.deliveryQueue) {
308
- const enqueueResult = await deps.deliveryQueue.enqueue({
315
+ const enqueueResult = await deps.deliveryQueue.enqueueInFlight({
309
316
  text: chunk,
310
317
  channelType: adapter.channelType,
311
318
  channelId,
@@ -322,14 +329,9 @@ export async function deliverToChannel(adapter, channelId, text, options, deps)
322
329
  });
323
330
  if (enqueueResult.ok) {
324
331
  entryId = enqueueResult.value;
325
- // Emit delivery:enqueued event
326
- deps.eventBus?.emit("delivery:enqueued", {
327
- entryId,
328
- channelId,
329
- channelType: adapter.channelType,
330
- origin: options?.origin ?? "unknown",
331
- timestamp: Date.now(),
332
- });
332
+ // delivery:enqueued is now emitted by the adapter (SqliteDeliveryQueueAdapter
333
+ // emits inside enqueueInFlight after the INSERT succeeds -- single source of
334
+ // truth). No-op here.
333
335
  }
334
336
  // If enqueue fails, log and continue -- queue failure should not block delivery
335
337
  }
@@ -12,7 +12,7 @@ import type { ChannelPort, NormalizedMessage, SessionKey } from "@comis/core";
12
12
  import type { InboundPipelineDeps } from "./inbound-pipeline.js";
13
13
  import type { SendOverrideStore } from "./send-policy.js";
14
14
  /** Minimal deps needed for the gate phase. */
15
- export type GateDeps = Pick<InboundPipelineDeps, "logger" | "eventBus" | "sessionManager" | "autoReplyEngineConfig" | "groupHistoryBuffer" | "commandQueue" | "sessionLabelStore" | "getResetTriggers" | "greetingGenerator" | "loadPromptSkill" | "getUserInvocableSkillNames" | "approvalGate" | "handleConfigCommand" | "handleSlashCommand" | "activeRunRegistry">;
15
+ export type GateDeps = Pick<InboundPipelineDeps, "logger" | "eventBus" | "sessionManager" | "autoReplyEngineConfig" | "groupHistoryBuffer" | "commandQueue" | "sessionLabelStore" | "getResetTriggers" | "greetingGenerator" | "loadPromptSkill" | "getUserInvocableSkillNames" | "approvalGate" | "handleConfigCommand" | "handleSlashCommand" | "activeRunRegistry" | "sessionResolver">;
16
16
  /** Gate decision: what should happen with this message. */
17
17
  export type GateDecision = {
18
18
  action: "process";
@@ -152,7 +152,7 @@ export async function evaluateInboundGate(deps, adapter, processedMsg, sessionKe
152
152
  }
153
153
  }
154
154
  // -------------------------------------------------------------------
155
- // /approve and /deny COMMAND INTERCEPTION (APPR-CHAT)
155
+ // /approve and /deny COMMAND INTERCEPTION
156
156
  // -------------------------------------------------------------------
157
157
  if (msg.text && deps.approvalGate) {
158
158
  const result = await handleApprovalCommand(deps, adapter, msg, sessionKey);
@@ -178,8 +178,15 @@ export async function evaluateInboundGate(deps, adapter, processedMsg, sessionKe
178
178
  if (msg.text) {
179
179
  const stopParsed = parseSlashCommand(msg.text);
180
180
  if (stopParsed.found && stopParsed.command === "stop") {
181
+ // Active-session lookup goes through the composite-key resolver.
182
+ // `formattedKey` is retained as a diagnostic log field so
183
+ // operators can correlate /stop-aborts with session traces.
181
184
  const formattedKey = formatSessionKey(sessionKey);
182
- const runHandle = deps.activeRunRegistry?.get(formattedKey);
185
+ const runHandle = deps.sessionResolver?.resolveActiveSession({
186
+ agentId,
187
+ channelType: adapter.channelType,
188
+ channelId: msg.channelId,
189
+ });
183
190
  if (runHandle) {
184
191
  try {
185
192
  await runHandle.abort();
@@ -209,7 +216,7 @@ export async function evaluateInboundGate(deps, adapter, processedMsg, sessionKe
209
216
  }
210
217
  }
211
218
  // -------------------------------------------------------------------
212
- // GENERAL SLASH COMMAND INTERCEPTION (CMD-WIRE)
219
+ // GENERAL SLASH COMMAND INTERCEPTION
213
220
  // -------------------------------------------------------------------
214
221
  if (msg.text && deps.handleSlashCommand) {
215
222
  const cmdResult = await deps.handleSlashCommand(msg.text, sessionKey, agentId);
@@ -294,7 +301,7 @@ export async function evaluateInboundGate(deps, adapter, processedMsg, sessionKe
294
301
  }
295
302
  }
296
303
  }
297
- // Extract command directives from metadata (set by CMD-WIRE interception above)
304
+ // Extract command directives from metadata (set by general slash command interception above)
298
305
  const directives = msg.metadata?._commandDirectives;
299
306
  return { action: "process", processedMsg: msg, directives };
300
307
  }
@@ -353,13 +360,21 @@ async function handleApprovalCommand(deps, adapter, msg, sessionKey) {
353
360
  }
354
361
  }
355
362
  else {
356
- // Single: resolve by request ID prefix match
363
+ // Single: resolve by request ID prefix match.
364
+ // Use filter+length check instead of first-match lookup — when the
365
+ // prefix is short and two pending requests share it, the operator
366
+ // must NOT silently get the first match. Warn and bail; the
367
+ // operator can re-issue with a longer prefix.
357
368
  const pending = gate.pending();
358
- const match = pending.find((r) => r.requestId.startsWith(arg));
359
- if (!match) {
369
+ const matches = pending.filter((r) => r.requestId.startsWith(arg));
370
+ if (matches.length === 0) {
360
371
  await deliverToChannel(adapter, msg.channelId, `No pending approval found for ID: ${arg} (may have already been resolved or timed out).`, { skipChunking: true });
361
372
  }
373
+ else if (matches.length > 1) {
374
+ await deliverToChannel(adapter, msg.channelId, `Ambiguous prefix "${arg}" matches ${matches.length} pending approvals. Use a longer prefix.`, { skipChunking: true });
375
+ }
362
376
  else {
377
+ const match = matches[0];
363
378
  gate.resolveApproval(match.requestId, isApprove, approvedBy);
364
379
  const verb = isApprove ? "Approved" : "Denied";
365
380
  await deliverToChannel(adapter, msg.channelId, `${verb}: ${match.toolName ?? match.action} (${match.requestId.slice(0, 8)})`, { skipChunking: true });
@@ -18,7 +18,7 @@ import type { DebounceBuffer } from "@comis/agent";
18
18
  import type { FollowupTrigger } from "@comis/agent";
19
19
  import type { PriorityScheduler } from "@comis/agent";
20
20
  import type { SessionLabelStore } from "@comis/agent";
21
- import type { ActiveRunRegistry } from "@comis/agent";
21
+ import type { ActiveRunRegistry, BackgroundSessionResolver } from "@comis/agent";
22
22
  import type { ChannelPort, DeliveryQueuePort, NormalizedMessage, SessionKey, TypedEventBus } from "@comis/core";
23
23
  import type { StreamingConfig } from "@comis/core";
24
24
  import type { AutoReplyEngineConfig, SendPolicyConfig, QueueConfig, ElevatedReplyConfig, AckReactionConfig } from "@comis/core";
@@ -99,6 +99,13 @@ export interface InboundPipelineDeps {
99
99
  inFlightSends?: Set<Promise<unknown>>;
100
100
  /** Optional active run registry for SDK-native steer+followup. */
101
101
  activeRunRegistry?: ActiveRunRegistry;
102
+ /**
103
+ * Optional composite-key resolver for active-session lookup. When
104
+ * present, supersedes `activeRunRegistry.has/.get` for production
105
+ * lookups. Wired by the daemon as
106
+ * `createBackgroundSessionResolver({ activeRunRegistry })`.
107
+ */
108
+ sessionResolver?: BackgroundSessionResolver;
102
109
  /** Handle /config command. Returns response text or undefined if not a config command. */
103
110
  handleConfigCommand?: (args: string[], channelType: string) => Promise<string | undefined>;
104
111
  /** Optional callback for task extraction after successful agent execution. */
@@ -112,7 +119,7 @@ export interface InboundPipelineDeps {
112
119
  };
113
120
  /** Template context builder for response prefix variables. */
114
121
  buildTemplateContext?: (agentId: string, channelType: string, msg: NormalizedMessage) => Record<string, string>;
115
- /** Optional approval gate for resolving /approve and /deny chat commands (APPR-CHAT). When absent, approval commands pass through as plain text. */
122
+ /** Optional approval gate for resolving /approve and /deny chat commands. When absent, approval commands pass through as plain text. */
116
123
  approvalGate?: {
117
124
  resolveApproval(requestId: string, approved: boolean, approvedBy: string, reason?: string): void;
118
125
  pending(): Array<{
@@ -126,7 +133,7 @@ export interface InboundPipelineDeps {
126
133
  sessionKey: string;
127
134
  } | undefined;
128
135
  };
129
- /** Handle general slash commands via command handler (CMD-WIRE). Returns CommandResult or undefined if not a command. */
136
+ /** Handle general slash commands via command handler. Returns CommandResult or undefined if not a command. */
130
137
  handleSlashCommand?: (text: string, sessionKey: SessionKey, agentId: string) => Promise<{
131
138
  handled: boolean;
132
139
  response?: string;
@@ -15,7 +15,7 @@ import type { BlockPacer } from "./block-pacer.js";
15
15
  import type { TypingLifecycleController } from "./typing-lifecycle-controller.js";
16
16
  import type { SendOverrideStore } from "./send-policy.js";
17
17
  /** Minimal deps needed for the routing phase. */
18
- export type RouteDeps = Pick<InboundPipelineDeps, "logger" | "eventBus" | "debounceBuffer" | "groupHistoryBuffer" | "sessionLabelStore" | "commandQueue" | "priorityScheduler" | "queueConfig" | "activeRunRegistry" | "streamingConfig" | "sendPolicyConfig" | "getElevatedReplyConfig" | "channelRegistry" | "retryEngine" | "deliveryQueue" | "inFlightSends" | "followupTrigger" | "followupConfig" | "assembleToolsForAgent" | "voiceResponsePipeline" | "parseOutboundMedia" | "outboundMediaFetch" | "onTaskExtraction" | "responsePrefixConfig" | "buildTemplateContext" | "getEnforceFinalTag">;
18
+ export type RouteDeps = Pick<InboundPipelineDeps, "logger" | "eventBus" | "debounceBuffer" | "groupHistoryBuffer" | "sessionLabelStore" | "commandQueue" | "priorityScheduler" | "queueConfig" | "activeRunRegistry" | "sessionResolver" | "streamingConfig" | "sendPolicyConfig" | "getElevatedReplyConfig" | "channelRegistry" | "retryEngine" | "deliveryQueue" | "inFlightSends" | "followupTrigger" | "followupConfig" | "assembleToolsForAgent" | "voiceResponsePipeline" | "parseOutboundMedia" | "outboundMediaFetch" | "onTaskExtraction" | "responsePrefixConfig" | "buildTemplateContext" | "getEnforceFinalTag">;
19
19
  /**
20
20
  * Route an inbound message through debounce, group history, steer+followup,
21
21
  * or command queue. Falls back to direct execution when no queue is present.
@@ -120,12 +120,23 @@ export async function routeInboundMessage(deps, adapter, processedMsg, originalM
120
120
  // -------------------------------------------------------------------
121
121
  // STEER+FOLLOWUP ROUTING
122
122
  // -------------------------------------------------------------------
123
- if (deps.activeRunRegistry && deps.queueConfig) {
123
+ // Active-session lookup goes through BackgroundSessionResolver:
124
+ // composite (agentId, channelType, channelId) supersedes the single-arg
125
+ // formatted-key lookup so multi-agent / multi-channel sessions are
126
+ // distinguishable. The original
127
+ // `formattedKey = formatSessionKey(sessionKey)` is retained ONLY for
128
+ // diagnostic log fields (the SessionKey may itself be richer than the
129
+ // resolver's composite triple).
130
+ if (deps.sessionResolver && deps.queueConfig) {
124
131
  const channelQueueConfig = deps.queueConfig.perChannel[adapter.channelType];
125
132
  const effectiveMode = channelQueueConfig?.mode ?? deps.queueConfig.defaultMode;
126
133
  if (effectiveMode === "steer+followup") {
127
134
  const formattedKey = formatSessionKey(sessionKey);
128
- const runHandle = deps.activeRunRegistry.get(formattedKey);
135
+ const runHandle = deps.sessionResolver.resolveActiveSession({
136
+ agentId,
137
+ channelType: adapter.channelType,
138
+ channelId: msg.channelId,
139
+ });
129
140
  if (runHandle) {
130
141
  const messageText = msg.text ?? "";
131
142
  if (runHandle.isStreaming() && !runHandle.isCompacting()) {
@@ -2,40 +2,27 @@
2
2
  * Response Filter: Suppresses silent tokens and strips reply tags from
3
3
  * channel delivery.
4
4
  *
5
- * Detects NO_REPLY and HEARTBEAT_OK tokens in agent responses and
6
- * determines whether the response should be delivered to the user.
7
- * Only suppresses when the token is the ENTIRE response (after trimming
8
- * and stripping reply tags) or when the response is empty/whitespace.
9
- *
10
- * Also strips `<reply>` / `<reply to="...">` XML tags that the LLM uses
11
- * for channel routing, since these are not valid HTML for platform delivery.
12
- *
13
- * This filter operates in the channel-manager delivery path (outbound
14
- * to users), NOT in the scheduler's internal heartbeat classification
15
- * which uses HEARTBEAT_OK_TOKEN for a different purpose.
5
+ * Delegates the silent-token check to `isSilentResponse` from `@comis/shared`
6
+ * the helper is documented as idempotent under `stripReplyTags + trim` (see
7
+ * `packages/shared/src/silent-tokens.ts` JSDoc contract).
16
8
  *
17
9
  * @module
18
10
  */
19
- /** Token that suppresses delivery for silent operations (e.g., memory flush) */
20
- export declare const NO_REPLY_TOKEN = "NO_REPLY";
21
- /** Result of filtering an agent response */
11
+ import { NO_REPLY_TOKEN, HEARTBEAT_OK_TOKEN } from "@comis/shared";
12
+ export { NO_REPLY_TOKEN, HEARTBEAT_OK_TOKEN };
13
+ /** Regex retained for backward compatibility with downstream re-exports. */
14
+ export declare const REPLY_TAG_RE: RegExp;
22
15
  export interface FilterResult {
23
- /** Whether the response should be delivered to the user */
24
16
  shouldDeliver: boolean;
25
- /** The cleaned response text (reply tags stripped, trimmed) */
26
17
  cleanedText: string;
27
- /** Which token caused suppression (for observability) */
28
18
  suppressedBy?: "NO_REPLY" | "HEARTBEAT_OK" | "SILENT" | "empty";
29
19
  }
30
20
  /**
31
21
  * Check if an agent response should be delivered to the user.
32
22
  *
33
- * Processing order:
34
- * 1. Strip `<reply>` / `<reply to="...">` XML tags
35
- * 2. Trim whitespace
36
- * 3. Suppress if empty or exact silent token match
37
- *
38
- * Does NOT suppress when the token appears mid-sentence in
39
- * substantive content (e.g., "I used NO_REPLY in my example").
23
+ * The silent-token check delegates to `isSilentResponse(trimmed)` for
24
+ * self-documentation at the call site. The helper is idempotent under
25
+ * `stripReplyTags + trim`, so passing the already-stripped value is safe
26
+ * and explicit.
40
27
  */
41
28
  export declare function filterResponse(response: string): FilterResult;
@@ -3,73 +3,45 @@
3
3
  * Response Filter: Suppresses silent tokens and strips reply tags from
4
4
  * channel delivery.
5
5
  *
6
- * Detects NO_REPLY and HEARTBEAT_OK tokens in agent responses and
7
- * determines whether the response should be delivered to the user.
8
- * Only suppresses when the token is the ENTIRE response (after trimming
9
- * and stripping reply tags) or when the response is empty/whitespace.
10
- *
11
- * Also strips `<reply>` / `<reply to="...">` XML tags that the LLM uses
12
- * for channel routing, since these are not valid HTML for platform delivery.
13
- *
14
- * This filter operates in the channel-manager delivery path (outbound
15
- * to users), NOT in the scheduler's internal heartbeat classification
16
- * which uses HEARTBEAT_OK_TOKEN for a different purpose.
6
+ * Delegates the silent-token check to `isSilentResponse` from `@comis/shared`
7
+ * the helper is documented as idempotent under `stripReplyTags + trim` (see
8
+ * `packages/shared/src/silent-tokens.ts` JSDoc contract).
17
9
  *
18
10
  * @module
19
11
  */
20
- /** Token that suppresses delivery for silent operations (e.g., memory flush) */
21
- export const NO_REPLY_TOKEN = "NO_REPLY";
22
- /**
23
- * HEARTBEAT_OK token value. Defined as a string literal here (not imported
24
- * from @comis/scheduler) to avoid circular package dependencies.
25
- * Must match HEARTBEAT_OK_TOKEN in packages/scheduler/src/heartbeat/relevance-filter.ts.
26
- */
27
- const HEARTBEAT_OK_VALUE = "HEARTBEAT_OK";
28
- /** Tokens that suppress response delivery when they ARE the entire response */
29
- const SILENT_TOKENS = [NO_REPLY_TOKEN, HEARTBEAT_OK_VALUE];
30
- /** Regex to match `<reply>` or `<reply to="...">` opening tags and `</reply>` closing tags */
31
- const REPLY_TAG_RE = /<\/?reply(?:\s[^>]*)?>|<reply>/gi;
12
+ import { isSilentResponse, stripReplyTags, NO_REPLY_TOKEN, HEARTBEAT_OK_TOKEN, } from "@comis/shared";
13
+ // Preserve existing public exports for downstream @comis/channels consumers.
14
+ export { NO_REPLY_TOKEN, HEARTBEAT_OK_TOKEN };
15
+ /** Regex retained for backward compatibility with downstream re-exports. */
16
+ export const REPLY_TAG_RE = /<\/?reply(?:\s[^>]*)?>|<reply>/gi;
32
17
  /**
33
18
  * Check if an agent response should be delivered to the user.
34
19
  *
35
- * Processing order:
36
- * 1. Strip `<reply>` / `<reply to="...">` XML tags
37
- * 2. Trim whitespace
38
- * 3. Suppress if empty or exact silent token match
39
- *
40
- * Does NOT suppress when the token appears mid-sentence in
41
- * substantive content (e.g., "I used NO_REPLY in my example").
20
+ * The silent-token check delegates to `isSilentResponse(trimmed)` for
21
+ * self-documentation at the call site. The helper is idempotent under
22
+ * `stripReplyTags + trim`, so passing the already-stripped value is safe
23
+ * and explicit.
42
24
  */
43
25
  export function filterResponse(response) {
44
- // Empty or whitespace
45
26
  if (!response || !response.trim()) {
46
27
  return { shouldDeliver: false, cleanedText: "", suppressedBy: "empty" };
47
28
  }
48
- // Strip <reply> / <reply to="..."> / </reply> tags
49
- const stripped = response.replace(REPLY_TAG_RE, "");
50
- const trimmed = stripped.trim();
51
- // Empty after stripping tags
52
- if (!trimmed) {
29
+ const trimmed = stripReplyTags(response);
30
+ if (!trimmed)
53
31
  return { shouldDeliver: false, cleanedText: "", suppressedBy: "empty" };
54
- }
55
- // [SILENT] prefix: suppress delivery when response starts with [SILENT] marker
32
+ // [SILENT] prefix branch — preserved verbatim from existing behavior.
33
+ // Resolves before the helper so we can return suppressedBy: "SILENT" cleanly.
56
34
  if (trimmed.toUpperCase().startsWith("[SILENT]")) {
57
- return {
58
- shouldDeliver: false,
59
- cleanedText: "",
60
- suppressedBy: "SILENT",
61
- };
35
+ return { shouldDeliver: false, cleanedText: "", suppressedBy: "SILENT" };
62
36
  }
63
- // Exact token match (entire response is the token)
64
- for (const token of SILENT_TOKENS) {
65
- if (trimmed === token) {
66
- return {
67
- shouldDeliver: false,
68
- cleanedText: "",
69
- suppressedBy: token === NO_REPLY_TOKEN ? "NO_REPLY" : "HEARTBEAT_OK",
70
- };
71
- }
37
+ // Pass the already-stripped value. isSilentResponse is documented as
38
+ // idempotent under stripReplyTags + trim (see silent-tokens.ts JSDoc).
39
+ // Self-documenting at the call site.
40
+ if (isSilentResponse(trimmed)) {
41
+ const tokenMatch = trimmed === NO_REPLY_TOKEN ? "NO_REPLY"
42
+ : trimmed === HEARTBEAT_OK_TOKEN ? "HEARTBEAT_OK"
43
+ : "SILENT";
44
+ return { shouldDeliver: false, cleanedText: "", suppressedBy: tokenMatch };
72
45
  }
73
- // Substantive response -- deliver cleaned text
74
46
  return { shouldDeliver: true, cleanedText: trimmed };
75
47
  }
@@ -318,7 +318,7 @@ export function createTelegramAdapter(deps) {
318
318
  }, "Callback query failed");
319
319
  }
320
320
  });
321
- // Start polling (webhook mode deferred to Phase 6/9)
321
+ // Start polling (webhook mode deferred)
322
322
  if (!deps.webhookUrl) {
323
323
  runnerHandle = run(bot);
324
324
  }