comisai 1.0.28 → 1.0.30

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 (241) hide show
  1. package/node_modules/@comis/agent/dist/bootstrap/sections/tool-descriptions.js +62 -8
  2. package/node_modules/@comis/agent/dist/bootstrap/sections/tooling-sections.js +3 -1
  3. package/node_modules/@comis/agent/dist/bridge/pi-event-bridge.d.ts +7 -0
  4. package/node_modules/@comis/agent/dist/bridge/pi-event-bridge.js +26 -0
  5. package/node_modules/@comis/agent/dist/context-engine/signature-replay-scrubber.d.ts +21 -0
  6. package/node_modules/@comis/agent/dist/context-engine/signature-replay-scrubber.js +29 -9
  7. package/node_modules/@comis/agent/dist/context-engine/signature-surrogate-guard.d.ts +10 -2
  8. package/node_modules/@comis/agent/dist/context-engine/signature-surrogate-guard.js +15 -9
  9. package/node_modules/@comis/agent/dist/context-engine/thinking-block-cleaner.d.ts +17 -2
  10. package/node_modules/@comis/agent/dist/context-engine/thinking-block-cleaner.js +19 -8
  11. package/node_modules/@comis/agent/dist/executor/executor-prompt-runner.js +28 -0
  12. package/node_modules/@comis/agent/dist/executor/executor-response-filter.js +3 -0
  13. package/node_modules/@comis/agent/dist/executor/executor-tool-assembly.js +3 -1
  14. package/node_modules/@comis/agent/dist/executor/phase-filter.d.ts +20 -4
  15. package/node_modules/@comis/agent/dist/executor/phase-filter.js +62 -19
  16. package/node_modules/@comis/agent/dist/executor/pi-executor.js +6 -0
  17. package/node_modules/@comis/agent/dist/executor/stream-wrappers/config-resolver.js +2 -3
  18. package/node_modules/@comis/agent/dist/executor/stream-wrappers/request-body-injector.js +2 -3
  19. package/node_modules/@comis/agent/dist/executor/ttl-guard.js +2 -3
  20. package/node_modules/@comis/agent/dist/index.d.ts +4 -2
  21. package/node_modules/@comis/agent/dist/index.js +3 -2
  22. package/node_modules/@comis/agent/dist/model/compaction-model-resolver.d.ts +41 -0
  23. package/node_modules/@comis/agent/dist/model/compaction-model-resolver.js +51 -0
  24. package/node_modules/@comis/agent/dist/model/model-registry-adapter.js +113 -26
  25. package/node_modules/@comis/agent/dist/model/model-scanner.d.ts +27 -0
  26. package/node_modules/@comis/agent/dist/model/model-scanner.js +64 -23
  27. package/node_modules/@comis/agent/dist/model/operation-model-defaults.d.ts +37 -15
  28. package/node_modules/@comis/agent/dist/model/operation-model-defaults.js +70 -25
  29. package/node_modules/@comis/agent/dist/model/operation-model-resolver.d.ts +2 -2
  30. package/node_modules/@comis/agent/dist/model/operation-model-resolver.js +12 -8
  31. package/node_modules/@comis/agent/dist/provider/capabilities.d.ts +21 -0
  32. package/node_modules/@comis/agent/dist/provider/capabilities.js +28 -0
  33. package/node_modules/@comis/agent/dist/session/orphaned-message-repair.js +61 -1
  34. package/node_modules/@comis/agent/dist/workspace/templates.js +1 -1
  35. package/node_modules/@comis/agent/package.json +1 -1
  36. package/node_modules/@comis/channels/dist/shared/channel-manager.d.ts +19 -1
  37. package/node_modules/@comis/channels/dist/shared/channel-manager.js +59 -3
  38. package/node_modules/@comis/channels/dist/shared/deliver-to-channel.d.ts +10 -0
  39. package/node_modules/@comis/channels/dist/shared/deliver-to-channel.js +25 -10
  40. package/node_modules/@comis/channels/dist/shared/execution-deliver.d.ts +1 -1
  41. package/node_modules/@comis/channels/dist/shared/execution-deliver.js +1 -1
  42. package/node_modules/@comis/channels/dist/shared/execution-pipeline.d.ts +8 -0
  43. package/node_modules/@comis/channels/dist/shared/inbound-pipeline.d.ts +8 -0
  44. package/node_modules/@comis/channels/dist/shared/inbound-route.d.ts +1 -1
  45. package/node_modules/@comis/channels/dist/shared/inbound-route.js +1 -0
  46. package/node_modules/@comis/channels/package.json +1 -1
  47. package/node_modules/@comis/cli/package.json +1 -1
  48. package/node_modules/@comis/core/dist/config/schema-agent.d.ts +15 -3
  49. package/node_modules/@comis/core/dist/config/schema-agent.js +6 -2
  50. package/node_modules/@comis/core/dist/config/schema-integrations.d.ts +4 -4
  51. package/node_modules/@comis/core/dist/config/schema-integrations.js +3 -3
  52. package/node_modules/@comis/core/dist/config/schema-models.d.ts +4 -2
  53. package/node_modules/@comis/core/dist/config/schema-models.js +4 -2
  54. package/node_modules/@comis/core/package.json +1 -1
  55. package/node_modules/@comis/daemon/dist/daemon.js +51 -8
  56. package/node_modules/@comis/daemon/dist/rpc/agent-handlers.js +40 -9
  57. package/node_modules/@comis/daemon/dist/rpc/builtin-provider-guard.d.ts +16 -0
  58. package/node_modules/@comis/daemon/dist/rpc/builtin-provider-guard.js +60 -0
  59. package/node_modules/@comis/daemon/dist/rpc/config-handlers.js +59 -0
  60. package/node_modules/@comis/daemon/dist/rpc/credential-resolver.d.ts +17 -0
  61. package/node_modules/@comis/daemon/dist/rpc/credential-resolver.js +99 -0
  62. package/node_modules/@comis/daemon/dist/rpc/message-handlers.d.ts +5 -0
  63. package/node_modules/@comis/daemon/dist/rpc/message-handlers.js +25 -4
  64. package/node_modules/@comis/daemon/dist/rpc/model-handlers.d.ts +4 -3
  65. package/node_modules/@comis/daemon/dist/rpc/model-handlers.js +21 -3
  66. package/node_modules/@comis/daemon/dist/rpc/provider-handlers.js +82 -6
  67. package/node_modules/@comis/daemon/dist/rpc/rpc-dispatch.d.ts +4 -0
  68. package/node_modules/@comis/daemon/dist/wiring/inbound-message-id-resolver.d.ts +48 -0
  69. package/node_modules/@comis/daemon/dist/wiring/inbound-message-id-resolver.js +58 -0
  70. package/node_modules/@comis/daemon/dist/wiring/setup-agents.d.ts +18 -6
  71. package/node_modules/@comis/daemon/dist/wiring/setup-agents.js +98 -46
  72. package/node_modules/@comis/daemon/dist/wiring/setup-channels.d.ts +13 -1
  73. package/node_modules/@comis/daemon/dist/wiring/setup-channels.js +2 -1
  74. package/node_modules/@comis/daemon/dist/wiring/setup-gateway-rpc.js +1 -1
  75. package/node_modules/@comis/daemon/package.json +2 -2
  76. package/node_modules/@comis/gateway/package.json +1 -1
  77. package/node_modules/@comis/infra/package.json +1 -1
  78. package/node_modules/@comis/memory/package.json +1 -1
  79. package/node_modules/@comis/scheduler/package.json +1 -1
  80. package/node_modules/@comis/shared/package.json +1 -1
  81. package/node_modules/@comis/skills/dist/bridge/mcp-tool-bridge.d.ts +1 -1
  82. package/node_modules/@comis/skills/dist/bridge/mcp-tool-bridge.js +1 -1
  83. package/node_modules/@comis/skills/dist/bridge/tool-audit.js +1 -1
  84. package/node_modules/@comis/skills/dist/builtin/exec-tool.d.ts +12 -11
  85. package/node_modules/@comis/skills/dist/builtin/exec-tool.js +1 -1
  86. package/node_modules/@comis/skills/dist/builtin/file/apply-patch-tool.d.ts +3 -2
  87. package/node_modules/@comis/skills/dist/builtin/file/apply-patch-tool.js +1 -1
  88. package/node_modules/@comis/skills/dist/builtin/file-tools/edit-tool.d.ts +7 -6
  89. package/node_modules/@comis/skills/dist/builtin/file-tools/edit-tool.js +1 -1
  90. package/node_modules/@comis/skills/dist/builtin/file-tools/find-tool.d.ts +6 -5
  91. package/node_modules/@comis/skills/dist/builtin/file-tools/find-tool.js +1 -1
  92. package/node_modules/@comis/skills/dist/builtin/file-tools/grep-tool.d.ts +16 -15
  93. package/node_modules/@comis/skills/dist/builtin/file-tools/grep-tool.js +1 -1
  94. package/node_modules/@comis/skills/dist/builtin/file-tools/ls-tool.d.ts +4 -3
  95. package/node_modules/@comis/skills/dist/builtin/file-tools/ls-tool.js +1 -1
  96. package/node_modules/@comis/skills/dist/builtin/file-tools/notebook-edit-tool.d.ts +7 -6
  97. package/node_modules/@comis/skills/dist/builtin/file-tools/notebook-edit-tool.js +1 -1
  98. package/node_modules/@comis/skills/dist/builtin/file-tools/read-tool.d.ts +6 -5
  99. package/node_modules/@comis/skills/dist/builtin/file-tools/read-tool.js +1 -1
  100. package/node_modules/@comis/skills/dist/builtin/file-tools/write-tool.d.ts +5 -4
  101. package/node_modules/@comis/skills/dist/builtin/file-tools/write-tool.js +1 -1
  102. package/node_modules/@comis/skills/dist/builtin/platform/admin-manage-factory.d.ts +1 -1
  103. package/node_modules/@comis/skills/dist/builtin/platform/agents-manage-tool.d.ts +28 -27
  104. package/node_modules/@comis/skills/dist/builtin/platform/agents-manage-tool.js +1 -1
  105. package/node_modules/@comis/skills/dist/builtin/platform/background-tasks-tool.d.ts +4 -3
  106. package/node_modules/@comis/skills/dist/builtin/platform/background-tasks-tool.js +1 -1
  107. package/node_modules/@comis/skills/dist/builtin/platform/browser-tool-schema.d.ts +67 -66
  108. package/node_modules/@comis/skills/dist/builtin/platform/browser-tool-schema.js +1 -1
  109. package/node_modules/@comis/skills/dist/builtin/platform/channels-manage-tool.d.ts +6 -5
  110. package/node_modules/@comis/skills/dist/builtin/platform/channels-manage-tool.js +1 -1
  111. package/node_modules/@comis/skills/dist/builtin/platform/cron-tool.d.ts +20 -19
  112. package/node_modules/@comis/skills/dist/builtin/platform/cron-tool.js +1 -1
  113. package/node_modules/@comis/skills/dist/builtin/platform/ctx-expand-tool.d.ts +4 -3
  114. package/node_modules/@comis/skills/dist/builtin/platform/ctx-expand-tool.js +1 -1
  115. package/node_modules/@comis/skills/dist/builtin/platform/ctx-inspect-tool.d.ts +3 -2
  116. package/node_modules/@comis/skills/dist/builtin/platform/ctx-inspect-tool.js +1 -1
  117. package/node_modules/@comis/skills/dist/builtin/platform/ctx-recall-tool.d.ts +6 -5
  118. package/node_modules/@comis/skills/dist/builtin/platform/ctx-recall-tool.js +1 -1
  119. package/node_modules/@comis/skills/dist/builtin/platform/ctx-search-tool.d.ts +6 -5
  120. package/node_modules/@comis/skills/dist/builtin/platform/ctx-search-tool.js +1 -1
  121. package/node_modules/@comis/skills/dist/builtin/platform/describe-video-tool.d.ts +4 -3
  122. package/node_modules/@comis/skills/dist/builtin/platform/describe-video-tool.js +1 -1
  123. package/node_modules/@comis/skills/dist/builtin/platform/discord-action-tool.d.ts +2 -1
  124. package/node_modules/@comis/skills/dist/builtin/platform/discord-action-tool.js +1 -1
  125. package/node_modules/@comis/skills/dist/builtin/platform/extract-document-tool.d.ts +4 -3
  126. package/node_modules/@comis/skills/dist/builtin/platform/extract-document-tool.js +1 -1
  127. package/node_modules/@comis/skills/dist/builtin/platform/gateway-tool.d.ts +12 -11
  128. package/node_modules/@comis/skills/dist/builtin/platform/gateway-tool.js +1 -1
  129. package/node_modules/@comis/skills/dist/builtin/platform/heartbeat-manage-tool.d.ts +23 -22
  130. package/node_modules/@comis/skills/dist/builtin/platform/heartbeat-manage-tool.js +1 -1
  131. package/node_modules/@comis/skills/dist/builtin/platform/image-generate-tool.d.ts +4 -3
  132. package/node_modules/@comis/skills/dist/builtin/platform/image-generate-tool.js +1 -1
  133. package/node_modules/@comis/skills/dist/builtin/platform/image-tool.d.ts +8 -7
  134. package/node_modules/@comis/skills/dist/builtin/platform/image-tool.js +1 -1
  135. package/node_modules/@comis/skills/dist/builtin/platform/mcp-manage-tool.d.ts +9 -8
  136. package/node_modules/@comis/skills/dist/builtin/platform/mcp-manage-tool.js +1 -1
  137. package/node_modules/@comis/skills/dist/builtin/platform/memory-get-tool.d.ts +5 -4
  138. package/node_modules/@comis/skills/dist/builtin/platform/memory-get-tool.js +1 -1
  139. package/node_modules/@comis/skills/dist/builtin/platform/memory-manage-tool.d.ts +12 -11
  140. package/node_modules/@comis/skills/dist/builtin/platform/memory-manage-tool.js +1 -1
  141. package/node_modules/@comis/skills/dist/builtin/platform/memory-search-tool.d.ts +4 -3
  142. package/node_modules/@comis/skills/dist/builtin/platform/memory-search-tool.js +1 -1
  143. package/node_modules/@comis/skills/dist/builtin/platform/memory-store-tool.d.ts +4 -3
  144. package/node_modules/@comis/skills/dist/builtin/platform/memory-store-tool.js +1 -1
  145. package/node_modules/@comis/skills/dist/builtin/platform/message-tool.d.ts +32 -31
  146. package/node_modules/@comis/skills/dist/builtin/platform/message-tool.js +1 -1
  147. package/node_modules/@comis/skills/dist/builtin/platform/messaging-factory.d.ts +1 -1
  148. package/node_modules/@comis/skills/dist/builtin/platform/models-manage-tool.d.ts +4 -3
  149. package/node_modules/@comis/skills/dist/builtin/platform/models-manage-tool.js +11 -4
  150. package/node_modules/@comis/skills/dist/builtin/platform/notify-tool.d.ts +6 -5
  151. package/node_modules/@comis/skills/dist/builtin/platform/notify-tool.js +1 -1
  152. package/node_modules/@comis/skills/dist/builtin/platform/obs-query-tool.d.ts +11 -10
  153. package/node_modules/@comis/skills/dist/builtin/platform/obs-query-tool.js +1 -1
  154. package/node_modules/@comis/skills/dist/builtin/platform/pipeline-tool.d.ts +37 -36
  155. package/node_modules/@comis/skills/dist/builtin/platform/pipeline-tool.js +1 -1
  156. package/node_modules/@comis/skills/dist/builtin/platform/platform-action-tool.d.ts +1 -1
  157. package/node_modules/@comis/skills/dist/builtin/platform/providers-manage-tool.d.ts +21 -20
  158. package/node_modules/@comis/skills/dist/builtin/platform/providers-manage-tool.js +1 -1
  159. package/node_modules/@comis/skills/dist/builtin/platform/session-search-tool.d.ts +6 -5
  160. package/node_modules/@comis/skills/dist/builtin/platform/session-search-tool.js +1 -1
  161. package/node_modules/@comis/skills/dist/builtin/platform/session-status-tool.d.ts +3 -2
  162. package/node_modules/@comis/skills/dist/builtin/platform/session-status-tool.js +1 -1
  163. package/node_modules/@comis/skills/dist/builtin/platform/sessions-history-tool.d.ts +5 -4
  164. package/node_modules/@comis/skills/dist/builtin/platform/sessions-history-tool.js +1 -1
  165. package/node_modules/@comis/skills/dist/builtin/platform/sessions-list-tool.d.ts +4 -3
  166. package/node_modules/@comis/skills/dist/builtin/platform/sessions-list-tool.js +1 -1
  167. package/node_modules/@comis/skills/dist/builtin/platform/sessions-manage-tool.d.ts +5 -4
  168. package/node_modules/@comis/skills/dist/builtin/platform/sessions-manage-tool.js +1 -1
  169. package/node_modules/@comis/skills/dist/builtin/platform/sessions-send-tool.d.ts +7 -6
  170. package/node_modules/@comis/skills/dist/builtin/platform/sessions-send-tool.js +1 -1
  171. package/node_modules/@comis/skills/dist/builtin/platform/sessions-spawn-tool.d.ts +15 -14
  172. package/node_modules/@comis/skills/dist/builtin/platform/sessions-spawn-tool.js +1 -1
  173. package/node_modules/@comis/skills/dist/builtin/platform/skills-manage-tool.d.ts +8 -7
  174. package/node_modules/@comis/skills/dist/builtin/platform/skills-manage-tool.js +1 -1
  175. package/node_modules/@comis/skills/dist/builtin/platform/slack-action-tool.d.ts +2 -1
  176. package/node_modules/@comis/skills/dist/builtin/platform/slack-action-tool.js +1 -1
  177. package/node_modules/@comis/skills/dist/builtin/platform/subagents-tool.d.ts +7 -6
  178. package/node_modules/@comis/skills/dist/builtin/platform/subagents-tool.js +1 -1
  179. package/node_modules/@comis/skills/dist/builtin/platform/telegram-action-tool.d.ts +2 -1
  180. package/node_modules/@comis/skills/dist/builtin/platform/telegram-action-tool.js +1 -1
  181. package/node_modules/@comis/skills/dist/builtin/platform/tokens-manage-tool.d.ts +5 -4
  182. package/node_modules/@comis/skills/dist/builtin/platform/tokens-manage-tool.js +1 -1
  183. package/node_modules/@comis/skills/dist/builtin/platform/transcribe-audio-tool.d.ts +4 -3
  184. package/node_modules/@comis/skills/dist/builtin/platform/transcribe-audio-tool.js +1 -1
  185. package/node_modules/@comis/skills/dist/builtin/platform/tts-tool.d.ts +6 -5
  186. package/node_modules/@comis/skills/dist/builtin/platform/tts-tool.js +1 -1
  187. package/node_modules/@comis/skills/dist/builtin/platform/unified-context-tool.d.ts +13 -12
  188. package/node_modules/@comis/skills/dist/builtin/platform/unified-context-tool.js +1 -1
  189. package/node_modules/@comis/skills/dist/builtin/platform/unified-memory-tool.d.ts +18 -17
  190. package/node_modules/@comis/skills/dist/builtin/platform/unified-memory-tool.js +1 -1
  191. package/node_modules/@comis/skills/dist/builtin/platform/unified-session-tool.d.ts +11 -10
  192. package/node_modules/@comis/skills/dist/builtin/platform/unified-session-tool.js +1 -1
  193. package/node_modules/@comis/skills/dist/builtin/platform/whatsapp-action-tool.d.ts +2 -1
  194. package/node_modules/@comis/skills/dist/builtin/platform/whatsapp-action-tool.js +1 -1
  195. package/node_modules/@comis/skills/dist/builtin/process-tool.d.ts +6 -5
  196. package/node_modules/@comis/skills/dist/builtin/process-tool.js +1 -1
  197. package/node_modules/@comis/skills/dist/builtin/web-fetch-tool.d.ts +5 -4
  198. package/node_modules/@comis/skills/dist/builtin/web-fetch-tool.js +1 -1
  199. package/node_modules/@comis/skills/dist/builtin/web-search-tool.d.ts +9 -8
  200. package/node_modules/@comis/skills/dist/builtin/web-search-tool.js +1 -1
  201. package/node_modules/@comis/skills/package.json +1 -1
  202. package/node_modules/@comis/web/dist/assets/{agent-detail-DqL6Artv.js → agent-detail-71BSbSfD.js} +1 -1
  203. package/node_modules/@comis/web/dist/assets/{agent-editor-CNM_h94Y.js → agent-editor-CTSDZhwT.js} +1 -1
  204. package/node_modules/@comis/web/dist/assets/{agent-list-Dbh-xD_F.js → agent-list-BEhni2ea.js} +1 -1
  205. package/node_modules/@comis/web/dist/assets/{billing-view-C1DmtyzK.js → billing-view-DVP1IvVs.js} +1 -1
  206. package/node_modules/@comis/web/dist/assets/{channel-detail-CtCH22N1.js → channel-detail-N_YK74xC.js} +1 -1
  207. package/node_modules/@comis/web/dist/assets/{channel-list-C7xXn-60.js → channel-list-DRk6ZJaF.js} +1 -1
  208. package/node_modules/@comis/web/dist/assets/{chat-console-C51pjFwk.js → chat-console-Dm-GtSf9.js} +1 -1
  209. package/node_modules/@comis/web/dist/assets/{config-editor-BLArYRB7.js → config-editor-CIferYX6.js} +1 -1
  210. package/node_modules/@comis/web/dist/assets/{context-dag-browser-fuyMinNI.js → context-dag-browser-CL84rXXM.js} +1 -1
  211. package/node_modules/@comis/web/dist/assets/{context-engine-Bngf2bH0.js → context-engine-B1HOTEZv.js} +1 -1
  212. package/node_modules/@comis/web/dist/assets/{delivery-view-C80hucxX.js → delivery-view-Y6JKYVFw.js} +1 -1
  213. package/node_modules/@comis/web/dist/assets/{diagnostics-view-Cl4VbHZ6.js → diagnostics-view-DWV1UQjz.js} +1 -1
  214. package/node_modules/@comis/web/dist/assets/{ic-chat-message-ByFUoMm6.js → ic-chat-message-DfSERzzg.js} +1 -1
  215. package/node_modules/@comis/web/dist/assets/{ic-connection-dot-C4nDHgY2.js → ic-connection-dot-CXyhlJup.js} +1 -1
  216. package/node_modules/@comis/web/dist/assets/{ic-tool-call-Bh5kq-yY.js → ic-tool-call-DNmwTjek.js} +1 -1
  217. package/node_modules/@comis/web/dist/assets/{index-BBkuC-EU.js → index-CBr0Tm9_.js} +2 -2
  218. package/node_modules/@comis/web/dist/assets/{mcp-management-DB-phOo7.js → mcp-management-BaH2-vox.js} +1 -1
  219. package/node_modules/@comis/web/dist/assets/{media-config-CRqZ1ZUH.js → media-config-CZLshJoN.js} +1 -1
  220. package/node_modules/@comis/web/dist/assets/{media-test-C9vE20Oy.js → media-test-C9NUWgo_.js} +1 -1
  221. package/node_modules/@comis/web/dist/assets/{memory-inspector-CeqfnxMZ.js → memory-inspector-D_fmTcRN.js} +1 -1
  222. package/node_modules/@comis/web/dist/assets/{message-center-Daup7Mof.js → message-center-BBFlNCZn.js} +1 -1
  223. package/node_modules/@comis/web/dist/assets/{models-DLYnEU8E.js → models-BytGLm99.js} +1 -1
  224. package/node_modules/@comis/web/dist/assets/{observe-view-BTSt_PO5.js → observe-view-VXtHqaqq.js} +1 -1
  225. package/node_modules/@comis/web/dist/assets/{pipeline-builder-DknfzyLt.js → pipeline-builder-CfXczlfJ.js} +1 -1
  226. package/node_modules/@comis/web/dist/assets/{pipeline-history-JnHZdeU_.js → pipeline-history-CPmXFnbe.js} +1 -1
  227. package/node_modules/@comis/web/dist/assets/{pipeline-history-detail-Dg4knsEb.js → pipeline-history-detail-DcueTMs9.js} +1 -1
  228. package/node_modules/@comis/web/dist/assets/{pipeline-list-AEnibjsp.js → pipeline-list-B-xG5WZh.js} +1 -1
  229. package/node_modules/@comis/web/dist/assets/{pipeline-monitor-DG7RbIOO.js → pipeline-monitor-pnIOYaSY.js} +1 -1
  230. package/node_modules/@comis/web/dist/assets/{scheduler-uL1fYKAT.js → scheduler-BtUIFHhA.js} +1 -1
  231. package/node_modules/@comis/web/dist/assets/{security-C3DywRLH.js → security-C8mWRq2y.js} +1 -1
  232. package/node_modules/@comis/web/dist/assets/{session-detail-BtqCNWXV.js → session-detail-DgdkO5ka.js} +1 -1
  233. package/node_modules/@comis/web/dist/assets/{session-list-CJXWa2XT.js → session-list-DcylcfTn.js} +1 -1
  234. package/node_modules/@comis/web/dist/assets/{setup-wizard-ywn7oJvu.js → setup-wizard-BP5yjsuL.js} +75 -39
  235. package/node_modules/@comis/web/dist/assets/{skills-DX0KYnWD.js → skills-DXt1bX8Z.js} +1 -1
  236. package/node_modules/@comis/web/dist/assets/{subagents-B8p5YJEB.js → subagents-C7YbUHXY.js} +1 -1
  237. package/node_modules/@comis/web/dist/assets/{workspace-manager-CgzNIrw1.js → workspace-manager-DP6pW4wa.js} +1 -1
  238. package/node_modules/@comis/web/dist/index.html +1 -1
  239. package/node_modules/@comis/web/package.json +1 -1
  240. package/npm-shrinkwrap.json +6126 -0
  241. package/package.json +74 -74
@@ -1,38 +1,83 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  /**
3
- * Operation model defaults: static maps for provider-family model tiering.
3
+ * Operation model defaults: catalog-derived per-provider model tiering.
4
4
  *
5
- * These maps define the zero-config smart defaults for non-interactive
6
- * operations. When no explicit operationModels config is set, the resolver
7
- * uses these to select cost-appropriate models per provider family.
5
+ * Replaces the previous hardcoded `OPERATION_MODEL_DEFAULTS` table (which
6
+ * pinned `mid`/`fast` model IDs per provider family) with a pure function
7
+ * that reads the live pi-ai catalog at call time. Two design properties:
8
8
  *
9
- * Default model IDs are verified against pi-ai SDK registry v0.65.0.
10
- * Do NOT call normalizeModelId() on these -- they are already valid
11
- * registry IDs that bypass normalization.
9
+ * 1. Pi-ai SDK upgrades automatically light up new providers/models — no
10
+ * per-release source edits to bump `OPERATION_MODEL_DEFAULTS` literals.
11
+ * 2. Closes the latent bug where switching primary to a non-Anthropic
12
+ * provider left cron/heartbeat/compaction routed to Claude Sonnet
13
+ * (because the old map was Anthropic/OpenAI/Google only).
14
+ *
15
+ * Tier picking: filter to text-capable models with non-zero cost, sort
16
+ * ascending by total cost (input + output), pick 10th-percentile = `fast`,
17
+ * 50th-percentile = `mid`. All-free-models providers (e.g. local Ollama,
18
+ * Z.AI most models) fall back to "first text-capable id" for both slots.
12
19
  *
13
20
  * @module
14
21
  */
22
+ import { getModels, getProviders } from "@mariozechner/pi-ai";
23
+ // ---------------------------------------------------------------------------
24
+ // Tier resolution
25
+ // ---------------------------------------------------------------------------
26
+ /** Cached set of native pi-ai providers for O(1) membership check. */
27
+ const _nativeProviderSet = new Set(getProviders());
28
+ /** Sum of input + output cost (per-million-tokens). Treats undefined as 0. */
29
+ function totalCost(m) {
30
+ return (m.cost?.input ?? 0) + (m.cost?.output ?? 0);
31
+ }
15
32
  /**
16
- * Per-provider-family default models for mid-tier and fast-tier operations.
33
+ * Resolve cost-tier model defaults for a given native pi-ai provider.
34
+ *
35
+ * Returns `{ fast, mid }` model IDs (without provider prefix) selected from
36
+ * the catalog by ascending total cost. Both undefined fields when the
37
+ * provider is unknown to pi-ai (e.g. custom YAML providers like Ollama).
38
+ *
39
+ * Algorithm:
40
+ * 1. Fetch `getModels(provider)` -> all models for that provider.
41
+ * 2. Filter to models supporting text input (`m.input.includes("text")`).
42
+ * 3. Filter to non-zero cost (eliminates free/local-only models from
43
+ * ranking — they won't be reachable in production).
44
+ * 4. Sort ascending by total cost.
45
+ * 5. `fast` = 10th percentile, `mid` = 50th percentile.
46
+ * 6. If post-filter set is empty (all-free provider), use the first
47
+ * text-capable model id for both slots.
17
48
  *
18
- * - anthropic: Sonnet 4.6 (mid) for tool-using ops, Haiku 4.5 (fast) for classification
19
- * - google: Gemini 3 Flash (mid) for tool-using ops, Gemini 2.5 Flash Lite (fast) for classification
20
- * - openai: GPT-5.4-mini (mid) for tool-using ops, GPT-5.4-nano (fast) for classification
49
+ * Pure function no async, no side effects. Re-callable per request.
50
+ *
51
+ * @param provider - Provider name to resolve (e.g. "anthropic", "openrouter")
52
+ * @returns `{ fast?: string, mid?: string }` — empty object for unknown providers
21
53
  */
22
- export const OPERATION_MODEL_DEFAULTS = {
23
- anthropic: {
24
- mid: "claude-sonnet-4-6",
25
- fast: "claude-haiku-4-5",
26
- },
27
- google: {
28
- mid: "gemini-3-flash",
29
- fast: "gemini-2.5-flash-lite",
30
- },
31
- openai: {
32
- mid: "gpt-5.4-mini",
33
- fast: "gpt-5.4-nano",
34
- },
35
- };
54
+ export function resolveOperationDefaults(provider) {
55
+ if (!_nativeProviderSet.has(provider))
56
+ return {};
57
+ const all = getModels(provider);
58
+ const textCapable = all.filter((m) => m.input?.includes("text"));
59
+ // Non-free models, sorted ascending by total cost.
60
+ const priced = textCapable
61
+ .filter((m) => totalCost(m) > 0)
62
+ .sort((a, b) => totalCost(a) - totalCost(b));
63
+ if (priced.length === 0) {
64
+ // All-free-models provider (e.g. Z.AI's predominantly-free catalog,
65
+ // Github Copilot, Kimi Coding). Use first text-capable id for both
66
+ // slots — no division by zero, graceful degradation.
67
+ const fallback = textCapable[0]?.id;
68
+ return { fast: fallback, mid: fallback };
69
+ }
70
+ // Math.min clamp guards single-element arrays (10% of 1 -> 0).
71
+ const fastIdx = Math.min(priced.length - 1, Math.floor(priced.length * 0.1));
72
+ const midIdx = Math.min(priced.length - 1, Math.floor(priced.length * 0.5));
73
+ return {
74
+ fast: priced[fastIdx].id,
75
+ mid: priced[midIdx].id,
76
+ };
77
+ }
78
+ // ---------------------------------------------------------------------------
79
+ // Operation -> tier mapping (provider-agnostic semantics)
80
+ // ---------------------------------------------------------------------------
36
81
  /**
37
82
  * Maps each operation type to its cost tier.
38
83
  *
@@ -9,7 +9,7 @@
9
9
  * Level 1: invocationOverride (e.g., CronPayload.model)
10
10
  * Level 2: operationModels[operationType] from agent config
11
11
  * Level 3: parentModel (sub-agent only)
12
- * Level 4: OPERATION_MODEL_DEFAULTS[providerFamily] + OPERATION_TIER_MAP
12
+ * Level 4: catalog-derived tier (resolveOperationDefaults + OPERATION_TIER_MAP)
13
13
  * Level 5: Agent primary model (ultimate fallback)
14
14
  *
15
15
  * @module
@@ -47,7 +47,7 @@ export declare function resolveProviderFamily(provider: string): string;
47
47
  * 1. invocationOverride -- per-call override (e.g., CronPayload.model)
48
48
  * 2. operationModels[op] -- explicit agent config
49
49
  * 3. parentModel -- inherited from parent agent (subagent only)
50
- * 4. OPERATION_MODEL_DEFAULTS -- provider-family smart defaults
50
+ * 4. resolveOperationDefaults -- pi-ai catalog-derived per-provider tier
51
51
  * 5. agent primary -- ultimate fallback
52
52
  *
53
53
  * @param params - Resolution context (all inputs needed for the decision)
@@ -10,13 +10,13 @@
10
10
  * Level 1: invocationOverride (e.g., CronPayload.model)
11
11
  * Level 2: operationModels[operationType] from agent config
12
12
  * Level 3: parentModel (sub-agent only)
13
- * Level 4: OPERATION_MODEL_DEFAULTS[providerFamily] + OPERATION_TIER_MAP
13
+ * Level 4: catalog-derived tier (resolveOperationDefaults + OPERATION_TIER_MAP)
14
14
  * Level 5: Agent primary model (ultimate fallback)
15
15
  *
16
16
  * @module
17
17
  */
18
18
  import { normalizeModelId } from "../provider/model-id-normalize.js";
19
- import { OPERATION_MODEL_DEFAULTS, OPERATION_TIER_MAP, OPERATION_TIMEOUT_DEFAULTS, OPERATION_CACHE_DEFAULTS, } from "./operation-model-defaults.js";
19
+ import { resolveOperationDefaults, OPERATION_TIER_MAP, OPERATION_TIMEOUT_DEFAULTS, OPERATION_CACHE_DEFAULTS, } from "./operation-model-defaults.js";
20
20
  // ---------------------------------------------------------------------------
21
21
  // Helpers
22
22
  // ---------------------------------------------------------------------------
@@ -80,7 +80,7 @@ export function resolveProviderFamily(provider) {
80
80
  * 1. invocationOverride -- per-call override (e.g., CronPayload.model)
81
81
  * 2. operationModels[op] -- explicit agent config
82
82
  * 3. parentModel -- inherited from parent agent (subagent only)
83
- * 4. OPERATION_MODEL_DEFAULTS -- provider-family smart defaults
83
+ * 4. resolveOperationDefaults -- pi-ai catalog-derived per-provider tier
84
84
  * 5. agent primary -- ultimate fallback
85
85
  *
86
86
  * @param params - Resolution context (all inputs needed for the decision)
@@ -120,13 +120,17 @@ export function resolveOperationModel(params) {
120
120
  const parsed = parseModelString(parentModel, agentProvider);
121
121
  return buildResult(parsed.provider, parsed.modelId, "parent_inherited", operationType, timeoutMs, cacheRetention);
122
122
  }
123
- // -- Level 4: family default --
123
+ // -- Level 4: catalog-derived tier --
124
+ // Reads pi-ai catalog at call time (no hardcoded family map). Picks the
125
+ // 10th-percentile cost text-capable model for `fast`, 50th for `mid`.
126
+ // Returns {} for unknown providers (custom YAML providers like Ollama).
124
127
  const tier = OPERATION_TIER_MAP[operationType];
125
128
  if (tier !== "primary") {
126
- const familyDefaults = OPERATION_MODEL_DEFAULTS[providerFamily];
127
- if (familyDefaults) {
128
- const modelId = familyDefaults[tier];
129
- // Do NOT call normalizeModelId on defaults -- they are already registry-validated
129
+ const defaults = resolveOperationDefaults(providerFamily);
130
+ const modelId = defaults[tier];
131
+ if (modelId) {
132
+ // Do NOT call normalizeModelId on catalog ids they are already
133
+ // canonical pi-ai registry entries.
130
134
  return buildResult(agentProvider, modelId, "family_default", operationType, timeoutMs, cacheRetention);
131
135
  }
132
136
  }
@@ -70,3 +70,24 @@ export declare function shouldDropThinkingBlocks(provider: string, modelId: stri
70
70
  * Otherwise returns "default".
71
71
  */
72
72
  export declare function resolveToolCallIdMode(provider: string, modelId: string): "default" | "strict9";
73
+ /**
74
+ * Minimal Pino-compatible logger surface for `validateProviderOverrides`.
75
+ * Object-first warn signature matches the project convention (object + msg).
76
+ */
77
+ export interface ProviderOverridesValidatorLogger {
78
+ warn(obj: object, msg: string): void;
79
+ }
80
+ /**
81
+ * Validate that every key in `PROVIDER_OVERRIDES` exists in the live pi-ai
82
+ * catalog. Orphaned keys (override entries for providers pi-ai no longer
83
+ * ships) are emitted as structured WARNs so operators notice on the next
84
+ * pi-ai bump. Does NOT throw -- the daemon continues to boot. Orphaned
85
+ * overrides are dead-code, not active failures.
86
+ *
87
+ * @param logger - Pino-compatible logger (object-first warn signature)
88
+ * @returns Inventory: orphan keys + total count of override keys checked
89
+ */
90
+ export declare function validateProviderOverrides(logger: ProviderOverridesValidatorLogger): {
91
+ orphans: string[];
92
+ checked: number;
93
+ };
@@ -13,6 +13,7 @@
13
13
  *
14
14
  * @module
15
15
  */
16
+ import { getProviders } from "@mariozechner/pi-ai";
16
17
  /**
17
18
  * Default provider capabilities. Matches ProviderCapabilitiesSchema defaults.
18
19
  * All fields present -- serves as the base layer in the 3-layer cascade.
@@ -161,3 +162,30 @@ export function resolveToolCallIdMode(provider, modelId) {
161
162
  }
162
163
  return caps.transcriptToolCallIdMode;
163
164
  }
165
+ /**
166
+ * Validate that every key in `PROVIDER_OVERRIDES` exists in the live pi-ai
167
+ * catalog. Orphaned keys (override entries for providers pi-ai no longer
168
+ * ships) are emitted as structured WARNs so operators notice on the next
169
+ * pi-ai bump. Does NOT throw -- the daemon continues to boot. Orphaned
170
+ * overrides are dead-code, not active failures.
171
+ *
172
+ * @param logger - Pino-compatible logger (object-first warn signature)
173
+ * @returns Inventory: orphan keys + total count of override keys checked
174
+ */
175
+ export function validateProviderOverrides(logger) {
176
+ const liveProviders = new Set(getProviders());
177
+ const overrideKeys = Object.keys(PROVIDER_OVERRIDES);
178
+ const orphans = [];
179
+ for (const key of overrideKeys) {
180
+ if (!liveProviders.has(key)) {
181
+ orphans.push(key);
182
+ logger.warn({
183
+ provider: key,
184
+ hint: "Provider override exists for unknown pi-ai provider; remove from PROVIDER_OVERRIDES on next bump",
185
+ errorKind: "config",
186
+ module: "agent.capabilities",
187
+ }, "Capability override has no matching pi-ai provider");
188
+ }
189
+ }
190
+ return { orphans, checked: overrideKeys.length };
191
+ }
@@ -74,11 +74,27 @@ export function repairOrphanedMessages(sessionManager) {
74
74
  }
75
75
  // Case 2: Tool-result tail -- session ends with tool/toolResult after
76
76
  // an assistant toolUse, but execution was interrupted by a restart.
77
+ // Content-aware (CONTEXT.md §Change 1A): the synthetic assistant text
78
+ // reflects the actual trailing toolResult body so the model is not given
79
+ // a prompt that contradicts the real successful result already on disk.
77
80
  /* eslint-disable @typescript-eslint/no-explicit-any -- role "tool"/"toolResult" not in SDK AgentMessage union */
78
81
  const isToolResult = lastMsg.role === "tool" || lastMsg.role === "toolResult";
79
82
  /* eslint-enable @typescript-eslint/no-explicit-any */
80
83
  if (isToolResult) {
81
- appendSyntheticAssistant(sessionManager, "(previous tool execution was interrupted by a system restart)");
84
+ let text;
85
+ if (isErroredToolResult(lastMsg)) {
86
+ text = "(previous tool errored before I could react)";
87
+ }
88
+ else {
89
+ const body = parseToolResultBody(lastMsg);
90
+ if (body && body.restarting === true) {
91
+ text = "(daemon restarted to apply the change — continuing)";
92
+ }
93
+ else {
94
+ text = "(continuing after daemon restart)";
95
+ }
96
+ }
97
+ appendSyntheticAssistant(sessionManager, text);
82
98
  return {
83
99
  repaired: true,
84
100
  reason: "trailing tool result without assistant reply (interrupted by restart)",
@@ -153,6 +169,50 @@ function createSyntheticMessage(role, text) {
153
169
  function appendSyntheticAssistant(sessionManager, text) {
154
170
  sessionManager.appendMessage(createSyntheticMessage("assistant", text));
155
171
  }
172
+ /**
173
+ * Best-effort parse of a trailing toolResult message into its tool-body
174
+ * shape. The SDK wire format stores the body as one or more text content
175
+ * blocks containing JSON. Returns null when the content isn't parseable
176
+ * JSON (e.g., raw string output from a non-structured tool). Per CONTEXT.md
177
+ * §Change 1A, parsing is best-effort, not a domain operation, so Result<T,E>
178
+ * is intentionally not used here.
179
+ */
180
+ function parseToolResultBody(msg) {
181
+ const m = msg;
182
+ if (!m || !Array.isArray(m.content))
183
+ return null;
184
+ const first = m.content[0];
185
+ if (!first || first.type !== "text" || typeof first.text !== "string")
186
+ return null;
187
+ const trimmed = first.text.trim();
188
+ if (!trimmed.startsWith("{") && !trimmed.startsWith("["))
189
+ return null;
190
+ try {
191
+ const parsed = JSON.parse(trimmed);
192
+ return typeof parsed === "object" && parsed !== null ? parsed : null;
193
+ }
194
+ catch {
195
+ return null;
196
+ }
197
+ }
198
+ /**
199
+ * Best-effort detection of an errored toolResult. The SDK and various tool
200
+ * adapters surface errors either via `isError: true` on the message envelope
201
+ * or on the first content block. Inspect both.
202
+ */
203
+ function isErroredToolResult(msg) {
204
+ const m = msg;
205
+ if (!m)
206
+ return false;
207
+ if (m.isError === true)
208
+ return true;
209
+ if (Array.isArray(m.content) && m.content.length > 0) {
210
+ const first = m.content[0];
211
+ if (first && first.isError === true)
212
+ return true;
213
+ }
214
+ return false;
215
+ }
156
216
  // ---------------------------------------------------------------------------
157
217
  // Case 4: Mid-session full-scan repair
158
218
  // ---------------------------------------------------------------------------
@@ -31,7 +31,7 @@ That's the default you start from. Kind without being soft. Witty without being
31
31
 
32
32
  ## About Comis
33
33
 
34
- Comis is an open-source, security-first AI agent platform. You're one of its agents. You live in your human's messaging apps -- Discord, Telegram, Slack, WhatsApp, Signal, iMessage, IRC, LINE -- and help them with real tools, persistent memory, and proactive scheduling. You're part of a fleet: multiple agents with different skills, models, and personalities, working together. MIT licensed. No cloud dependency. Self-hosted.
34
+ Comis is an open-source, security-first AI agent platform. You're one of its agents. You live in your human's messaging apps -- Discord, Telegram, Slack, WhatsApp, Signal, iMessage, IRC, LINE -- and help them with real tools, persistent memory, and proactive scheduling. You're part of a fleet: multiple agents with different skills, models, and personalities, working together. Apache-2.0 licensed. No cloud dependency. Self-hosted.
35
35
 
36
36
  Friendly by nature. Powerful by design.
37
37
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@comis/agent",
3
3
  "private": true,
4
- "version": "1.0.28",
4
+ "version": "1.0.30",
5
5
  "author": "Moshe Anconina",
6
6
  "license": "Apache-2.0",
7
7
  "description": "AI agent executor, budget control, and session management for Comis",
@@ -130,7 +130,15 @@ export interface ChannelManagerDeps {
130
130
  handleConfigCommand?: (args: string[], channelType: string) => Promise<string | undefined>;
131
131
  /** Optional callback for task extraction after successful agent execution. */
132
132
  onTaskExtraction?: (conversationText: string, sessionKey: string, agentId: string) => Promise<void>;
133
- /** Optional callback fired after each successful inbound message processing. Used by restart continuation tracker. */
133
+ /**
134
+ * Optional hook fired BEFORE the inbound message is dispatched to the executor.
135
+ * Use this for state that must be visible during processing (e.g. continuation
136
+ * tracker for SIGUSR2 capture). Fires for both real adapter inbounds and
137
+ * synthetic injected messages. Does NOT fire for early-return paths
138
+ * (no-adapter warning, graph-report intercept).
139
+ */
140
+ onMessageReceived?: (msg: NormalizedMessage, channelType: string) => void;
141
+ /** Optional callback fired AFTER each successful inbound message processing. Used by post-processing state (e.g. notification session activity recording). */
134
142
  onMessageProcessed?: (msg: NormalizedMessage, channelType: string) => void;
135
143
  /** When true, lifecycle reactor handles queued/thinking reactions -- skip ack reaction in inbound pipeline. */
136
144
  lifecycleReactionsEnabled?: boolean;
@@ -149,6 +157,16 @@ export interface ChannelManagerDeps {
149
157
  handleSlashCommand?: InboundPipelineDeps["handleSlashCommand"];
150
158
  /** Per-agent enforceFinalTag config lookup. */
151
159
  getEnforceFinalTag?: InboundPipelineDeps["getEnforceFinalTag"];
160
+ /**
161
+ * Optional in-flight outbound sendMessage promise tracker. PRODUCTION
162
+ * callers (daemon) MUST NOT pass this -- the factory creates its own
163
+ * per-instance Set. Exposed via deps strictly to allow unit tests to
164
+ * inject a controllable Set for drain-ordering and deadline assertions.
165
+ * Drained in stopAll() with a 5s deadline so SIGUSR2 cannot tear down
166
+ * adapters mid-send (which would orphan the SQLite delivery-queue ack
167
+ * and trigger a duplicate retry on the next instance).
168
+ */
169
+ inFlightSends?: Set<Promise<unknown>>;
152
170
  /** Optional allowFrom sender filter lookup. Returns allowed sender IDs for a channel type. Empty array = allow all. */
153
171
  getAllowFrom?: (channelType: string) => string[];
154
172
  }
@@ -33,6 +33,27 @@ export function createChannelManager(deps) {
33
33
  const sendOverrides = createSendOverrideStore();
34
34
  /** Adapter lookup map: channelType -> ChannelPort. Populated in startAll(). */
35
35
  const adaptersByType = new Map();
36
+ /**
37
+ * Per-instance in-flight outbound sendMessage promises. Used by
38
+ * deliver-to-channel.ts to register active sends; drained in stopAll() with
39
+ * a 5s deadline so SIGUSR2 cannot tear down adapters mid-send (which would
40
+ * orphan the SQLite delivery-queue ack and trigger a duplicate retry on the
41
+ * next instance).
42
+ *
43
+ * Tests may inject a Set via deps.inFlightSends to seed controllable
44
+ * promises for drain-ordering and deadline assertions; production callers
45
+ * (daemon) must NOT pass this -- the factory creates its own.
46
+ */
47
+ const inFlightSends = deps.inFlightSends ?? new Set();
48
+ /**
49
+ * Pipeline deps with inFlightSends threaded in. Spread once so the Set is
50
+ * visible to processInboundMessage at all three call sites (debounce flush
51
+ * handler, normal onMessage handler, injectMessage). The original deps
52
+ * object is left untouched -- callbacks like onMessageProcessed and
53
+ * onGraphReportRequest live on the same reference (spread copies the
54
+ * function references, not the underlying behavior).
55
+ */
56
+ const pipelineDeps = { ...deps, inFlightSends };
36
57
  // Clean up stale overrides, debounce entries, and group history when sessions expire
37
58
  deps.eventBus.on("session:expired", (ev) => {
38
59
  sendOverrides.delete(formatSessionKey(ev.sessionKey));
@@ -65,7 +86,7 @@ export function createChannelManager(deps) {
65
86
  };
66
87
  // Fire-and-forget: processInboundMessage is async but the flush callback is sync.
67
88
  // Errors are caught by the onMessage error handler.
68
- void processInboundMessage(deps, adapter, syntheticMsg, activePacers, sendOverrides).catch((error) => {
89
+ void processInboundMessage(pipelineDeps, adapter, syntheticMsg, activePacers, sendOverrides).catch((error) => {
69
90
  deps.logger.error({
70
91
  err: error instanceof Error ? error : new Error(String(error)),
71
92
  channelType,
@@ -90,7 +111,12 @@ export function createChannelManager(deps) {
90
111
  return; // Handled -- do not forward to agent
91
112
  }
92
113
  }
93
- await processInboundMessage(deps, adapter, msg, activePacers, sendOverrides);
114
+ // Fire onMessageReceived BEFORE await processInboundMessage so any
115
+ // mid-processing SIGUSR2 still sees the session in continuation
116
+ // tracker state. The graph-report intercept above must remain BEFORE
117
+ // this call so control-plane callbacks bypass both hooks.
118
+ deps.onMessageReceived?.(msg, adapter.channelType);
119
+ await processInboundMessage(pipelineDeps, adapter, msg, activePacers, sendOverrides);
94
120
  deps.onMessageProcessed?.(msg, adapter.channelType);
95
121
  }
96
122
  catch (error) {
@@ -130,6 +156,25 @@ export function createChannelManager(deps) {
130
156
  for (const pacer of activePacers) {
131
157
  pacer.cancel();
132
158
  }
159
+ // Await in-flight outbound sends with a 5s deadline so SIGUSR2 cannot
160
+ // tear down adapters mid-HTTP-response (which would orphan the SQLite
161
+ // delivery-queue ack and trigger a duplicate retry on the next instance).
162
+ // Empty-Set fast path takes no log line, no setTimeout, no Promise.race --
163
+ // existing shutdown latency is preserved when nothing is in flight.
164
+ if (inFlightSends.size > 0) {
165
+ const drainStart = Date.now();
166
+ const inFlightCount = inFlightSends.size;
167
+ await Promise.race([
168
+ Promise.allSettled([...inFlightSends]),
169
+ new Promise((resolve) => setTimeout(resolve, 5000)),
170
+ ]);
171
+ deps.logger.info({
172
+ inFlightCount,
173
+ drainMs: Date.now() - drainStart,
174
+ remaining: inFlightSends.size,
175
+ hint: "Outbound sends drained before adapter teardown to avoid duplicate-message risk on SIGUSR2 hot-reload",
176
+ }, "Channel manager: in-flight outbound sends drained");
177
+ }
133
178
  // Build combined adapter list: direct adapters + plugin-registered adapters
134
179
  const registryAdapters = deps.channelRegistry
135
180
  ? deps.channelRegistry.getChannelPlugins().map((p) => p.adapter)
@@ -168,7 +213,18 @@ export function createChannelManager(deps) {
168
213
  return;
169
214
  }
170
215
  }
171
- await processInboundMessage(deps, adapter, msg, activePacers, sendOverrides);
216
+ // Two-callback contract (symmetric with the normal inbound path):
217
+ // onMessageReceived fires BEFORE processInboundMessage so any
218
+ // mid-execution SIGUSR2 sees the session in continuation tracker
219
+ // state. Daemon wires this to continuationTracker.track(...).
220
+ // onMessageProcessed fires AFTER processing for post-processing state
221
+ // that depends on deferred refs (e.g. sessionTrackerRef.recordActivity).
222
+ // Both early-return branches above (no-adapter warn, graph-report intercept)
223
+ // intentionally bypass both callbacks because they represent control-plane
224
+ // events, not real session activity.
225
+ deps.onMessageReceived?.(msg, channelType);
226
+ await processInboundMessage(pipelineDeps, adapter, msg, activePacers, sendOverrides);
227
+ deps.onMessageProcessed?.(msg, channelType);
172
228
  },
173
229
  };
174
230
  }
@@ -118,6 +118,16 @@ export interface DeliverToChannelDeps {
118
118
  * Aborted deliveries emit delivery:aborted (not delivery:complete).
119
119
  */
120
120
  abortSignal?: AbortSignal;
121
+ /**
122
+ * Per-instance set of in-flight outbound sendMessage promises. When provided,
123
+ * each chunk send is added to the set BEFORE the await (so a throwing send
124
+ * is still tracked) and removed via .finally() on settle. Drained in
125
+ * channel-manager.stopAll() with a 5s deadline so SIGUSR2 cannot tear down
126
+ * adapters mid-send (which would orphan the SQLite delivery-queue ack and
127
+ * trigger a duplicate retry on the next instance). Created by the
128
+ * channel-manager factory; do not pass externally.
129
+ */
130
+ inFlightSends?: Set<Promise<unknown>>;
121
131
  }
122
132
  /**
123
133
  * Resolve the effective chunk limit for a delivery.
@@ -334,18 +334,33 @@ export async function deliverToChannel(adapter, channelId, text, options, deps)
334
334
  // If enqueue fails, log and continue -- queue failure should not block delivery
335
335
  }
336
336
  // Send with or without retry
337
- let result;
338
- let retried = false;
337
+ const retried = Boolean(deps?.retryEngine);
339
338
  const chunkSendStart = Date.now();
340
- if (deps?.retryEngine) {
341
- // RetryEngine expects a ChannelPort-like adapter -- our DeliveryAdapter
342
- // has the same sendMessage signature, so cast through unknown
343
- result = await deps.retryEngine.sendWithRetry(adapter, channelId, chunk, sendOpts);
344
- retried = true;
345
- }
346
- else {
347
- result = await adapter.sendMessage(channelId, chunk, sendOpts);
339
+ // Build the send promise WITHOUT awaiting yet, so we can register it
340
+ // in deps.inFlightSends synchronously before the underlying HTTPS POST
341
+ // is observable as in-flight. This guarantees that a SIGUSR2 hitting
342
+ // mid-send will see the promise in the Set and drain it before tearing
343
+ // down adapters (avoids orphaned SQLite delivery-queue acks and the
344
+ // resulting duplicate-message retry on the next instance).
345
+ const sendPromise = deps?.retryEngine
346
+ ? deps.retryEngine.sendWithRetry(
347
+ // RetryEngine expects a ChannelPort-like adapter -- our
348
+ // DeliveryAdapter has the same sendMessage signature, so cast
349
+ // through unknown
350
+ adapter, channelId, chunk, sendOpts)
351
+ : adapter.sendMessage(channelId, chunk, sendOpts);
352
+ if (deps?.inFlightSends) {
353
+ const tracked = sendPromise;
354
+ deps.inFlightSends.add(tracked);
355
+ // .finally fires on both fulfillment and rejection -- guarantees
356
+ // Set cleanup even if sendPromise rejects. We intentionally do
357
+ // not await this side-effect; the void keeps no-floating-promise
358
+ // lint quiet without altering the awaited value below.
359
+ void sendPromise.finally(() => {
360
+ deps.inFlightSends?.delete(tracked);
361
+ });
348
362
  }
363
+ const result = await sendPromise;
349
364
  const chunkResult = {
350
365
  ok: result.ok,
351
366
  charCount: chunk.length,
@@ -11,7 +11,7 @@ import type { ExecutionPipelineDeps } from "./execution-pipeline.js";
11
11
  import type { BlockPacer } from "./block-pacer.js";
12
12
  import type { TypingLifecycleController } from "./typing-lifecycle-controller.js";
13
13
  /** Minimal deps needed for the delivery phase. */
14
- export type DeliverDeps = Pick<ExecutionPipelineDeps, "eventBus" | "logger" | "streamingConfig" | "channelRegistry" | "retryEngine" | "deliveryQueue">;
14
+ export type DeliverDeps = Pick<ExecutionPipelineDeps, "eventBus" | "logger" | "streamingConfig" | "channelRegistry" | "retryEngine" | "deliveryQueue" | "inFlightSends">;
15
15
  /**
16
16
  * Chunk, coalesce, pace, and deliver the response text to the channel.
17
17
  *
@@ -101,7 +101,7 @@ export async function deliverExecutionResponse(deps, adapter, effectiveMsg, fina
101
101
  skipChunking: true,
102
102
  origin: "agent",
103
103
  }, deps.deliveryQueue
104
- ? { retryEngine: deps.retryEngine, eventBus: deps.eventBus, deliveryQueue: deps.deliveryQueue, replyMode: resolvedReplyMode, abortSignal: deliverySignal }
104
+ ? { retryEngine: deps.retryEngine, eventBus: deps.eventBus, deliveryQueue: deps.deliveryQueue, replyMode: resolvedReplyMode, abortSignal: deliverySignal, inFlightSends: deps.inFlightSends }
105
105
  : undefined);
106
106
  if (!deliveryResult.ok || !deliveryResult.value.ok) {
107
107
  failedChunks++;
@@ -78,6 +78,14 @@ export interface ExecutionPipelineDeps {
78
78
  executionTimeoutMs?: number;
79
79
  /** Delivery queue for crash-safe persistence. */
80
80
  deliveryQueue?: DeliveryQueuePort;
81
+ /**
82
+ * Per-instance set of in-flight outbound sendMessage promises. Threaded
83
+ * through DeliverToChannelDeps so deliver-to-channel can register active
84
+ * sends. Drained in stopAll() with a 5s deadline so SIGUSR2 cannot tear
85
+ * down adapters mid-send. Created by the channel-manager factory; do not
86
+ * pass externally.
87
+ */
88
+ inFlightSends?: Set<Promise<unknown>>;
81
89
  /** When true, only content inside <final> blocks reaches users. */
82
90
  enforceFinalTag?: boolean;
83
91
  }
@@ -89,6 +89,14 @@ export interface InboundPipelineDeps {
89
89
  retryEngine?: RetryEngine;
90
90
  /** Delivery queue for crash-safe message persistence. When present, agent responses are enqueued before send. */
91
91
  deliveryQueue?: DeliveryQueuePort;
92
+ /**
93
+ * Per-instance set of in-flight outbound sendMessage promises. Threaded
94
+ * through ExecutionPipelineDeps -> DeliverToChannelDeps so deliver-to-channel
95
+ * can register active sends. Drained in stopAll() with a 5s deadline so
96
+ * SIGUSR2 cannot tear down adapters mid-send. Created by the channel-manager
97
+ * factory; do not pass externally.
98
+ */
99
+ inFlightSends?: Set<Promise<unknown>>;
92
100
  /** Optional active run registry for SDK-native steer+followup. */
93
101
  activeRunRegistry?: ActiveRunRegistry;
94
102
  /** Handle /config command. Returns response text or undefined if not a config command. */
@@ -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" | "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" | "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.
@@ -104,6 +104,7 @@ export async function routeInboundMessage(deps, adapter, processedMsg, originalM
104
104
  channelRegistry: deps.channelRegistry,
105
105
  retryEngine: deps.retryEngine,
106
106
  deliveryQueue: deps.deliveryQueue,
107
+ inFlightSends: deps.inFlightSends,
107
108
  followupTrigger: deps.followupTrigger,
108
109
  followupConfig: deps.followupConfig,
109
110
  commandQueue: deps.commandQueue,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@comis/channels",
3
3
  "private": true,
4
- "version": "1.0.28",
4
+ "version": "1.0.30",
5
5
  "author": "Moshe Anconina",
6
6
  "license": "Apache-2.0",
7
7
  "description": "Chat platform adapters — Discord, Telegram, Slack, WhatsApp, Signal, iMessage, IRC, LINE",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@comis/cli",
3
3
  "private": true,
4
- "version": "1.0.28",
4
+ "version": "1.0.30",
5
5
  "author": "Moshe Anconina",
6
6
  "license": "Apache-2.0",
7
7
  "description": "Command-line interface for the Comis AI agent platform",