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,234 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ /**
3
+ * Background completion runner: subscribes to background_task:completed and
4
+ * background_task:failed events from the TypedEventBus and re-enters the
5
+ * originating agent session with a formatted completion announcement.
6
+ *
7
+ * Per-session lock serialization is delegated to the existing session
8
+ * manager (ComisSessionManager.withSession in packages/agent/src/session/).
9
+ * The runner does NOT introduce its own queueing -- one turn per completion
10
+ * event, ordering follows the existing per-session lock.
11
+ *
12
+ * Recursion bound: per-task incoming hop count + 1 must stay below
13
+ * `maxBackgroundHops` (default 3). When the cap is hit, the runner emits
14
+ * the fallback notification instead of triggering executor.execute().
15
+ * The hop count is read from `task.origin.backgroundHopCount`
16
+ * (populated by the originResolver).
17
+ *
18
+ * Latency-instrumentation hook: emits `background_task:reentered`
19
+ * immediately before executor.execute(). Integration tests compute the delta
20
+ * from `background_task:completed.timestamp` to this event for SLO tracking.
21
+ *
22
+ * Failure isolation: each handler is wrapped in suppressError so a single
23
+ * completion's failure does not tear down the subscription (AGENTS §2.1).
24
+ *
25
+ * @module
26
+ */
27
+ import { randomUUID } from "node:crypto";
28
+ import { suppressError } from "@comis/shared";
29
+ import { parseFormattedSessionKey } from "@comis/core";
30
+ import { formatCompletionAnnouncement } from "./completion-formatter.js";
31
+ /**
32
+ * Wire the completion runner against an event bus + executor + session store.
33
+ * Subscriptions are installed synchronously; call shutdown() to remove them.
34
+ */
35
+ export function createBackgroundCompletionRunner(deps) {
36
+ const log = deps.logger.child({ submodule: "background-completion-runner" });
37
+ let stopped = false;
38
+ let inflight = Promise.resolve();
39
+ const onCompleted = (data) => {
40
+ if (stopped)
41
+ return;
42
+ const promise = handleEvent(data.taskId, "completed");
43
+ inflight = inflight.then(() => promise).catch(() => undefined);
44
+ suppressError(promise, "background completion handler (completed)");
45
+ };
46
+ const onFailed = (data) => {
47
+ if (stopped)
48
+ return;
49
+ const promise = handleEvent(data.taskId, "failed");
50
+ inflight = inflight.then(() => promise).catch(() => undefined);
51
+ suppressError(promise, "background completion handler (failed)");
52
+ };
53
+ deps.eventBus.on("background_task:completed", onCompleted);
54
+ deps.eventBus.on("background_task:failed", onFailed);
55
+ async function handleEvent(taskId, kind) {
56
+ const task = deps.taskManager.getTask(taskId);
57
+ if (!task) {
58
+ log.warn({ taskId, kind, hint: "Task disappeared from manager before runner could resolve it; no announcement injected", errorKind: "internal" }, "Background completion: task not in manager");
59
+ return;
60
+ }
61
+ // At-most-once: the dispatcher subscribed BEFORE this runner (see
62
+ // setup-background-completion-runner.ts) and already transitioned
63
+ // task.dispatchState. When state is "notified", the dispatcher fired
64
+ // the user-visible fallback; the runner stays out of the way to
65
+ // enforce single-owner notification routing (zero spurious outbound).
66
+ if (task.dispatchState === "notified") {
67
+ log.debug({
68
+ taskId,
69
+ dispatchState: task.dispatchState,
70
+ // Include originating traceId so operator log streams stay
71
+ // continuous across the dispatcher / runner boundary.
72
+ traceId: task.origin?.traceId ?? undefined,
73
+ hint: "Dispatcher already fired fallback notification (at-most-once)",
74
+ }, "Background completion runner: skipped (dispatcher fired fallback)");
75
+ return;
76
+ }
77
+ // origin is producer-required (background-task-manager promote()
78
+ // rejects missing-origin) so we read it directly.
79
+ const origin = task.origin;
80
+ // Hop cap. Read incoming hop count from origin (schema field populated
81
+ // by the originResolver).
82
+ const nextHopCount = (origin.backgroundHopCount ?? 0) + 1;
83
+ if (nextHopCount >= deps.maxBackgroundHops) {
84
+ log.info({
85
+ taskId,
86
+ toolName: task.toolName,
87
+ agentId: origin.agentId,
88
+ hopCount: nextHopCount,
89
+ max: deps.maxBackgroundHops,
90
+ // traceId from origin keeps operator logs threaded.
91
+ traceId: origin.traceId ?? undefined,
92
+ }, "Background completion: hop cap reached, falling back to user notification");
93
+ await fallbackForTask(task.id, origin.agentId, task.toolName, `Background task "${task.toolName}" completed but follow-up was skipped — recursion limit reached. Run again or check the result manually.`);
94
+ return;
95
+ }
96
+ // No active session for this sessionKey in the in-memory store. The
97
+ // originating session may have ended (user closed the channel) OR may live
98
+ // in JSONL but not be currently registered. Either way, there is no
99
+ // streaming channel to inject into, so skip fallback (which would only
100
+ // produce a WARN from notification-service).
101
+ const sessionExists = deps.sessionStore.loadByFormattedKey(origin.sessionKey) !== undefined;
102
+ if (!sessionExists) {
103
+ log.info({
104
+ taskId,
105
+ sessionKey: origin.sessionKey,
106
+ // traceId from origin so this INFO log line stays threaded with the
107
+ // originating request's trace stream even though the runner runs in a
108
+ // background context (the ALS traceId at this point may differ from
109
+ // origin.traceId).
110
+ traceId: origin.traceId ?? undefined,
111
+ hint: "No active in-memory session for this sessionKey; runner will skip re-entry. Task result remains in JSONL for offline review.",
112
+ }, "Background completion: no active session for re-entry");
113
+ return;
114
+ }
115
+ // Reconstruct the SessionKey object for executor.execute().
116
+ const parsedKey = parseFormattedSessionKey(origin.sessionKey);
117
+ if (!parsedKey) {
118
+ log.warn({
119
+ taskId,
120
+ sessionKey: origin.sessionKey,
121
+ // traceId from origin keeps operator logs threaded.
122
+ traceId: origin.traceId ?? undefined,
123
+ hint: "Persisted sessionKey is malformed; cannot route announcement",
124
+ errorKind: "internal",
125
+ }, "Background completion: invalid sessionKey");
126
+ await fallbackForTask(task.id, origin.agentId, task.toolName, `Background task "${task.toolName}" completed (routing failed).`);
127
+ return;
128
+ }
129
+ // Format the announcement (byte-identical trailing instruction).
130
+ const announcement = formatCompletionAnnouncement(task);
131
+ // Construct the synthetic NormalizedMessage (hop counter in metadata).
132
+ const syntheticMsg = {
133
+ id: randomUUID(),
134
+ channelId: origin.channelId,
135
+ channelType: "background_task",
136
+ senderId: "background-task-runner",
137
+ text: announcement,
138
+ timestamp: Date.now(),
139
+ attachments: [],
140
+ metadata: {
141
+ backgroundHopCount: nextHopCount,
142
+ backgroundTaskId: task.id,
143
+ toolName: task.toolName,
144
+ agentId: origin.agentId,
145
+ traceId: origin.traceId ?? undefined,
146
+ },
147
+ };
148
+ log.debug({
149
+ taskId,
150
+ sessionKey: origin.sessionKey,
151
+ agentId: origin.agentId,
152
+ toolName: task.toolName,
153
+ hopCount: nextHopCount,
154
+ // traceId from origin keeps debug logs threaded.
155
+ traceId: origin.traceId ?? undefined,
156
+ }, "Background completion runner: invoking executor");
157
+ // Emit background_task:reentered immediately before executor.execute().
158
+ // Integration tests compute p95 latency from
159
+ // background_task:completed.timestamp to this event's timestamp.
160
+ // Include traceId from origin so subscribers (and operator log streams)
161
+ // preserve the originating request's trace across the
162
+ // background_task:completed → :reentered boundary.
163
+ deps.eventBus.emit("background_task:reentered", {
164
+ taskId: task.id,
165
+ agentId: origin.agentId,
166
+ sessionKey: origin.sessionKey,
167
+ hopCount: nextHopCount,
168
+ traceId: origin.traceId ?? null,
169
+ timestamp: Date.now(),
170
+ });
171
+ // One turn per event. Existing session lock orders concurrent calls.
172
+ try {
173
+ await deps.getExecutor(origin.agentId).execute(syntheticMsg, parsedKey, undefined, undefined, origin.agentId);
174
+ }
175
+ catch (err) {
176
+ log.warn({
177
+ taskId,
178
+ err,
179
+ // traceId from origin keeps the WARN line threaded.
180
+ traceId: origin.traceId ?? undefined,
181
+ hint: "Executor failed mid-completion turn; subscription remains active",
182
+ errorKind: "internal",
183
+ }, "Background completion: executor.execute() rejected");
184
+ }
185
+ }
186
+ /**
187
+ * Two-phase commit:
188
+ *
189
+ * 1. transitionDispatchState(taskId, "notified") — synchronously persists
190
+ * `dispatchState = "notified"` to disk (via persistTaskSync inside the
191
+ * manager). This MUST run before fallbackNotifyFn so a SIGKILL between
192
+ * persist and fire does NOT leak a duplicate on recovery: the at-most-
193
+ * once gate at the top of handleEvent (which reads task.dispatchState)
194
+ * sees "notified" and skips re-firing. Without this ordering, the gate
195
+ * misses and the user receives the notification twice.
196
+ *
197
+ * 2. fallbackNotifyFn(...) — actually deliver the user-visible
198
+ * notification. May reject (channel offline, rate-limited, etc.); the
199
+ * failure is logged at WARN. The persisted state stays at "notified" —
200
+ * the user did not see the notification, but the at-most-once contract
201
+ * takes precedence over delivery completeness.
202
+ */
203
+ async function fallbackForTask(taskId, agentId, toolName, message) {
204
+ // Phase 1: persist state. transitionDispatchState may return false if
205
+ // the task disappeared from the manager between handler entry and this
206
+ // call (e.g., explicit cleanup). In that case there is nothing to gate
207
+ // on; we still fire so the user sees the completion. The persist is
208
+ // synchronous so the on-disk state is updated before phase 2.
209
+ deps.taskManager.transitionDispatchState(taskId, "notified");
210
+ // Phase 2: fire user-visible notification.
211
+ try {
212
+ await deps.fallbackNotifyFn({
213
+ agentId,
214
+ message,
215
+ priority: "normal",
216
+ origin: "background_task",
217
+ });
218
+ }
219
+ catch (err) {
220
+ log.warn({ taskId, toolName, agentId, err, hint: "fallbackNotifyFn rejected; user will not see the completion notification for this task. dispatchState already persisted as \"notified\" — no duplicate on recovery.", errorKind: "internal" }, "Background completion: fallbackNotifyFn rejected (post-persist)");
221
+ }
222
+ }
223
+ return {
224
+ async shutdown() {
225
+ if (stopped)
226
+ return;
227
+ stopped = true;
228
+ deps.eventBus.off("background_task:completed", onCompleted);
229
+ deps.eventBus.off("background_task:failed", onFailed);
230
+ // Wait for any in-flight handler to settle before returning.
231
+ await inflight;
232
+ },
233
+ };
234
+ }
@@ -3,9 +3,18 @@
3
3
  *
4
4
  * @module
5
5
  */
6
- export type { BackgroundTask, BackgroundTaskStatus, PersistedTaskState } from "./background-task-types.js";
6
+ export type { BackgroundTask, BackgroundTaskStatus, BackgroundSessionState, PersistedTaskState, } from "./background-task-types.js";
7
+ export type { BackgroundTaskNotificationPolicy as BackgroundTaskNotificationPolicyType } from "./background-task-types.js";
8
+ export type { BackgroundTaskOrigin } from "@comis/core";
7
9
  export { persistTaskSync, loadTask, recoverTasks, removeTaskFile, TASK_DIR_NAME, } from "./background-task-persistence.js";
8
10
  export { createBackgroundTaskManager, } from "./background-task-manager.js";
9
11
  export type { BackgroundTaskManager, BackgroundTaskManagerOpts, NotifyFn, } from "./background-task-manager.js";
10
12
  export { wrapToolForAutoBackground, } from "./auto-background-middleware.js";
11
13
  export type { ToolDefinition, } from "./auto-background-middleware.js";
14
+ export { formatCompletionAnnouncement, TRAILING_INSTRUCTION } from "./completion-formatter.js";
15
+ export { createBackgroundCompletionRunner } from "./completion-runner.js";
16
+ export type { BackgroundCompletionRunner, BackgroundCompletionRunnerDeps, RunnerSessionStore, } from "./completion-runner.js";
17
+ export { createCompletionDispatcher, STATES, BackgroundTaskNotificationPolicy, } from "./completion-dispatcher.js";
18
+ export type { CompletionDispatcher, CompletionDispatcherDeps, DispatcherSessionStore, DispatcherTaskManager, } from "./completion-dispatcher.js";
19
+ export { createBackgroundSessionResolver } from "./session-resolver.js";
20
+ export type { ActiveSessionKey, BackgroundSessionResolver, BackgroundSessionResolverDeps, } from "./session-resolver.js";
@@ -7,3 +7,7 @@
7
7
  export { persistTaskSync, loadTask, recoverTasks, removeTaskFile, TASK_DIR_NAME, } from "./background-task-persistence.js";
8
8
  export { createBackgroundTaskManager, } from "./background-task-manager.js";
9
9
  export { wrapToolForAutoBackground, } from "./auto-background-middleware.js";
10
+ export { formatCompletionAnnouncement, TRAILING_INSTRUCTION } from "./completion-formatter.js";
11
+ export { createBackgroundCompletionRunner } from "./completion-runner.js";
12
+ export { createCompletionDispatcher, STATES, BackgroundTaskNotificationPolicy, } from "./completion-dispatcher.js";
13
+ export { createBackgroundSessionResolver } from "./session-resolver.js";
@@ -0,0 +1,85 @@
1
+ /**
2
+ * BackgroundSessionResolver: composite-key wrapper around ActiveRunRegistry.
3
+ *
4
+ * The underlying `activeRunRegistry.has(sessionKey)` and `.get(sessionKey)`
5
+ * take a single formatted-key string. That string would collapse two
6
+ * distinct sessions for the same `channelId` across different agents (or
7
+ * different channelTypes) into one bucket — a latent multi-agent /
8
+ * multi-channel correctness bug.
9
+ *
10
+ * This resolver makes the composite key explicit at every public call site:
11
+ * `(agentId, channelType, channelId)`. It internally composes the formatted
12
+ * key via `formatSessionKey` from `@comis/core` and delegates to the
13
+ * underlying registry.
14
+ *
15
+ * Runtime semantics do not change at the registry layer — what changes is
16
+ * the lookup-key signature surfaced to production callers. No production
17
+ * code outside *.test.ts should retain a single-arg `.has(...)` or
18
+ * `.get(...)` on `activeRunRegistry`.
19
+ *
20
+ * @module
21
+ */
22
+ import type { ActiveRunRegistry, RunHandle } from "../executor/active-run-registry.js";
23
+ /**
24
+ * Composite key for active-session lookup.
25
+ *
26
+ * The three fields uniquely identify a session at the inbound-routing layer:
27
+ * - `agentId` — distinguishes per-agent isolation (multi-agent safety)
28
+ * - `channelType` — distinguishes platform (telegram vs discord vs slack)
29
+ * - `channelId` — platform-specific chat / peer / group identifier
30
+ *
31
+ * The resolver internally composes a `SessionKey` and formats it via
32
+ * `formatSessionKey` so the underlying registry's string-keyed Map is
33
+ * addressed deterministically.
34
+ */
35
+ export interface ActiveSessionKey {
36
+ agentId: string;
37
+ channelType: string;
38
+ channelId: string;
39
+ }
40
+ /**
41
+ * Public-facing resolver returned by `createBackgroundSessionResolver`.
42
+ *
43
+ * The resolver exposes ONLY composite-key methods. There is no single-arg
44
+ * fallback — production callers MUST thread `(agentId, channelType,
45
+ * channelId)` end-to-end.
46
+ */
47
+ export interface BackgroundSessionResolver {
48
+ /**
49
+ * Look up the RunHandle for an active session.
50
+ *
51
+ * @param key - Composite key (agentId, channelType, channelId).
52
+ * @returns The RunHandle if a session is registered, otherwise undefined.
53
+ * @throws Error when any composite-key field is empty / falsy
54
+ * (programming error, parity with manager.promote's
55
+ * empty-string guards in background-task-manager.ts:96-107).
56
+ */
57
+ resolveActiveSession(key: ActiveSessionKey): RunHandle | undefined;
58
+ /**
59
+ * Check whether a session is registered for the composite key.
60
+ *
61
+ * @param key - Composite key (agentId, channelType, channelId).
62
+ * @returns true iff a RunHandle is registered, false otherwise.
63
+ * @throws Error when any composite-key field is empty / falsy.
64
+ */
65
+ hasActiveSession(key: ActiveSessionKey): boolean;
66
+ }
67
+ /**
68
+ * Dependencies required by the resolver.
69
+ *
70
+ * Only the registry is needed today — the resolver is a pure-function
71
+ * wrapper. No logger / event-bus injection (CLAUDE.md: NO logging in
72
+ * pure-function helpers).
73
+ */
74
+ export interface BackgroundSessionResolverDeps {
75
+ activeRunRegistry: ActiveRunRegistry;
76
+ }
77
+ /**
78
+ * Create a BackgroundSessionResolver wrapping an ActiveRunRegistry.
79
+ *
80
+ * Public-facing methods accept ONLY the composite key (agentId,
81
+ * channelType, channelId) — no single-arg fallback. Production callers
82
+ * no longer reach into `activeRunRegistry.has(...)` / `.get(...)`
83
+ * directly.
84
+ */
85
+ export declare function createBackgroundSessionResolver(deps: BackgroundSessionResolverDeps): BackgroundSessionResolver;
@@ -0,0 +1,78 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ /**
3
+ * BackgroundSessionResolver: composite-key wrapper around ActiveRunRegistry.
4
+ *
5
+ * The underlying `activeRunRegistry.has(sessionKey)` and `.get(sessionKey)`
6
+ * take a single formatted-key string. That string would collapse two
7
+ * distinct sessions for the same `channelId` across different agents (or
8
+ * different channelTypes) into one bucket — a latent multi-agent /
9
+ * multi-channel correctness bug.
10
+ *
11
+ * This resolver makes the composite key explicit at every public call site:
12
+ * `(agentId, channelType, channelId)`. It internally composes the formatted
13
+ * key via `formatSessionKey` from `@comis/core` and delegates to the
14
+ * underlying registry.
15
+ *
16
+ * Runtime semantics do not change at the registry layer — what changes is
17
+ * the lookup-key signature surfaced to production callers. No production
18
+ * code outside *.test.ts should retain a single-arg `.has(...)` or
19
+ * `.get(...)` on `activeRunRegistry`.
20
+ *
21
+ * @module
22
+ */
23
+ import { formatSessionKey } from "@comis/core";
24
+ // ---------------------------------------------------------------------------
25
+ // Factory
26
+ // ---------------------------------------------------------------------------
27
+ /**
28
+ * Compose the formatted session-key string from a composite key.
29
+ *
30
+ * Mirrors the shape that production session-managers use when registering
31
+ * handles: `formatSessionKey({tenantId: agentId, channelId:
32
+ * "${channelType}:${channelId}", userId: channelId})`. The output is a
33
+ * deterministic colon-delimited string that round-trips through
34
+ * `parseFormattedSessionKey` (the channelType prefix on channelId is
35
+ * stable across format/parse).
36
+ *
37
+ * The triple is REQUIRED — empty fields are a programming error
38
+ * (parity with the empty-string guard in
39
+ * `background-task-manager.ts:promote()`).
40
+ */
41
+ function formatComposite(key) {
42
+ if (!key.agentId || !key.channelType || !key.channelId) {
43
+ throw new Error(`BackgroundSessionResolver: composite key requires non-empty agentId, channelType, channelId; got ${JSON.stringify(key)}`);
44
+ }
45
+ return formatSessionKey({
46
+ tenantId: key.agentId,
47
+ channelId: `${key.channelType}:${key.channelId}`,
48
+ userId: key.channelId,
49
+ });
50
+ }
51
+ /**
52
+ * Create a BackgroundSessionResolver wrapping an ActiveRunRegistry.
53
+ *
54
+ * Public-facing methods accept ONLY the composite key (agentId,
55
+ * channelType, channelId) — no single-arg fallback. Production callers
56
+ * no longer reach into `activeRunRegistry.has(...)` / `.get(...)`
57
+ * directly.
58
+ */
59
+ export function createBackgroundSessionResolver(deps) {
60
+ // Local alias: the resolver IS the abstraction over the underlying
61
+ // single-arg registry. We rename to `registry` so source-grep tooling
62
+ // (`activeRunRegistry.has|get(`) does not flag this file as a callsite
63
+ // to migrate -- the resolver IS the migration target. Invariant:
64
+ // *production callers* of `activeRunRegistry` go through this resolver;
65
+ // the resolver itself remains the sole consumer of the underlying
66
+ // single-arg surface.
67
+ const registry = deps.activeRunRegistry;
68
+ return {
69
+ resolveActiveSession(key) {
70
+ const formatted = formatComposite(key);
71
+ return registry.get(formatted);
72
+ },
73
+ hasActiveSession(key) {
74
+ const formatted = formatComposite(key);
75
+ return registry.has(formatted);
76
+ },
77
+ };
78
+ }
@@ -34,6 +34,7 @@ export function buildMessagingSection(toolNames, isMinimal, channelContext) {
34
34
  '- `[System Message]` blocks are internal context. If one reports completed work and asks for a user update, rewrite it in your normal assistant voice. Never forward raw system message text to users.',
35
35
  "- Never use shell execution, code execution, or file tools to send messages. Use only the messaging tools.",
36
36
  "- Do NOT use message(action=send) for progress updates, debug output, or placeholder text. The user sees every send as a phone notification. Work silently; deliver the result.",
37
+ "- Do NOT narrate intent before calling a tool. Avoid prefacing tool calls with phrases like \"I'll do X now…\" or \"Let me run Y…\" — invoke the tool directly. Pre-tool-text creates user-visible promises the agent may not be able to fulfill if the tool gets backgrounded.",
37
38
  "- Use `fetch` to read recent messages from a channel before responding to context you missed.",
38
39
  "- The `delete` action requires confirmation and cannot be undone.",
39
40
  ];
@@ -20,7 +20,7 @@
20
20
  import { getToolMetadata } from "@comis/core";
21
21
  import { getProviders } from "@mariozechner/pi-ai";
22
22
  // ---------------------------------------------------------------------------
23
- // Layer 1D (260430-vwt) -- live native-catalog provider list
23
+ // Live native-catalog provider list
24
24
  //
25
25
  // Computed once at module load time. Used by the providers_manage TOOL_GUIDE
26
26
  // "Built-in vs Custom Provider Check" block below so the text reflects
@@ -325,7 +325,7 @@ If the model IS built-in: skip provider creation. After credential pre-check pas
325
325
  If the model is NOT built-in: you need a custom provider. Proceed to the steps below, but first gather ALL required configuration.
326
326
 
327
327
  ### Choosing the \`type\` Field (POST AUTO-PROMOTE FLOW)
328
- After Layer 1C of the catalog-driven providers redesign, the \`type\` field follows two distinct rules depending on the provider name:
328
+ For catalog-driven providers, the \`type\` field follows two distinct rules depending on the provider name:
329
329
  - **If \`provider_id\` matches a built-in name** (use models_manage list_providers to verify): OMIT \`type\` entirely from the create config. The daemon auto-promotes \`type\` to the native catalog name when \`provider_id\` matches a native entry AND no custom \`baseUrl\` is supplied. Setting \`type:"openai"\` for a built-in name still works (auto-promoted), but omitting it is cleaner.
330
330
  - **If \`provider_id\` is a custom OpenAI-compatible proxy** (NVIDIA NIM, Together, Fireworks, etc.) NOT in the native catalog: set \`type:"openai"\` (or whatever wire-format API matches). Auto-promotion does not fire for non-catalog names.
331
331
  - **If \`baseUrl\` differs from the native catalog URL** for a built-in name: this signals you want the OpenAI-passthrough shape (custom proxy that masquerades as the built-in). Auto-promotion is suppressed; the entry stays as \`type:"openai"\`.
@@ -357,7 +357,7 @@ To switch an agent to a different provider/model, call agents_manage update with
357
357
  **Three preconditions the LLM MUST verify before issuing the update:**
358
358
  1. The target provider exists as a \`providers.entries.<provider_id>\` key. If it does not, call providers_manage create FIRST (and gateway env_set for the API key if needed). Patching an agent to a provider that has no entry resolves under the wrong provider family at the next session — the original bug.
359
359
  2. The model id matches a \`models[].id\` in that provider entry (or is a built-in known to the pi-ai catalog for that provider type). Otherwise \`registry.find(provider, model)\` returns undefined and the next session falls back with a "Model not found" message.
360
- 3. **Credential pre-check passed** (see top of this guide). The target provider's apiKeyName is non-empty AND \`gateway env_list filter:"<PROVIDER>*"\` confirmed the named secret exists in env. Skipping this step is the bug that causes "No API key found" failures at the next chat turn — verified production repro on 2026-05-01.
360
+ 3. **Credential pre-check passed** (see top of this guide). The target provider's apiKeyName is non-empty AND \`gateway env_list filter:"<PROVIDER>*"\` confirmed the named secret exists in env. Skipping this step is the bug that causes "No API key found" failures at the next chat turn.
361
361
 
362
362
  **Timing — the change is NOT hot-applied to the active session.**
363
363
  agents_manage update writes through persistToConfig WITHOUT a hot-update callback, which triggers a SIGUSR2 daemon restart (2-second debounce). The new provider/model takes effect on the next session, not the currently-running prompt. Tell the user the switch is queued and will take effect after the daemon settles.
@@ -4,8 +4,36 @@
4
4
  */
5
5
  /** Model size tier — determines prompt verbosity for tool descriptions. */
6
6
  export type ModelTier = "small" | "medium" | "large";
7
- export declare function buildToolingSection(toolNames: string[], _modelTier: ModelTier, toolSummaries?: Record<string, string>): string[];
8
- export declare function buildToolCallStyleSection(isMinimal: boolean, toolNames?: string[]): string[];
7
+ /**
8
+ * Build the static `## Available Tools` block (legacy path, gate-off) OR a
9
+ * single residual one-liner pointing the model at the per-turn `## Capabilities`
10
+ * block (gate-on path).
11
+ *
12
+ * @param capabilityIndexEnabled - When `true`, emits ONLY the residual
13
+ * one-liner. When `false` or undefined, emits the legacy flat block
14
+ * BYTE-IDENTICALLY to the pre-feature baseline. The two paths are MUTUALLY
15
+ * EXCLUSIVE.
16
+ *
17
+ * Restart-required: this gate selects between two cached system-prompt
18
+ * shapes; toggling at runtime is forbidden. Operator-facing constraint is
19
+ * documented in config docs.
20
+ */
21
+ export declare function buildToolingSection(toolNames: string[], _modelTier: ModelTier, toolSummaries?: Record<string, string>, capabilityIndexEnabled?: boolean): string[];
22
+ /**
23
+ * Build the static "## Tool Call Style" section with conditional coding guidelines.
24
+ *
25
+ * @param capabilityIndexEnabled - When `true`, AND when `exec` is in
26
+ * `toolNames`, the rendered output includes the dual-gated "Tool-first
27
+ * principle" bullet immediately before the existing Python-virtualenv rule.
28
+ * When `false` or `undefined`, the bullet is omitted; the existing venv
29
+ * rule emits unchanged when `exec` is present.
30
+ *
31
+ * Restart-required: the gate value flows from `tooling.capabilityIndex.enabled`
32
+ * via `AssemblerParams.capabilityIndexEnabled`, populated at the prompt
33
+ * assembly site from `port.isCapabilityIndexEnabled()`. The value is
34
+ * config-derived and stable per session — SAFE inside the cache fence.
35
+ */
36
+ export declare function buildToolCallStyleSection(isMinimal: boolean, toolNames?: string[], capabilityIndexEnabled?: boolean): string[];
9
37
  /** Tool names that trigger the confirmation flow / self-update gating section. */
10
38
  export declare const CONFIRMATION_TOOL_NAMES: string[];
11
39
  /**
@@ -5,9 +5,36 @@
5
5
  */
6
6
  import { TOOL_SUMMARIES, TOOL_ORDER } from "./tool-descriptions.js";
7
7
  import { getProviders } from "@mariozechner/pi-ai";
8
- export function buildToolingSection(toolNames, _modelTier, toolSummaries) {
8
+ /**
9
+ * Build the static `## Available Tools` block (legacy path, gate-off) OR a
10
+ * single residual one-liner pointing the model at the per-turn `## Capabilities`
11
+ * block (gate-on path).
12
+ *
13
+ * @param capabilityIndexEnabled - When `true`, emits ONLY the residual
14
+ * one-liner. When `false` or undefined, emits the legacy flat block
15
+ * BYTE-IDENTICALLY to the pre-feature baseline. The two paths are MUTUALLY
16
+ * EXCLUSIVE.
17
+ *
18
+ * Restart-required: this gate selects between two cached system-prompt
19
+ * shapes; toggling at runtime is forbidden. Operator-facing constraint is
20
+ * documented in config docs.
21
+ */
22
+ export function buildToolingSection(toolNames, _modelTier, toolSummaries, capabilityIndexEnabled) {
9
23
  if (toolNames.length === 0)
10
24
  return [];
25
+ // Gate-on path: residual one-liner only. The per-turn `## Capabilities`
26
+ // block is rendered into the dynamic preamble by `executor-prompt-runner.ts`.
27
+ // The wording below is normative.
28
+ if (capabilityIndexEnabled === true) {
29
+ return [
30
+ "When this turn includes a `Capabilities` context, refer to it for grouped tool guidance " +
31
+ "before invoking tools or running installs. Tool schemas in your active toolspace are " +
32
+ "authoritative for parameter shapes.",
33
+ ];
34
+ }
35
+ // Gate-off path: legacy flat block BYTE-IDENTICAL to pre-feature baseline.
36
+ // DO NOT modify the body below — the byte-identity assertion in
37
+ // tooling-sections.test.ts depends on this shape staying exact.
11
38
  const summaries = { ...TOOL_SUMMARIES, ...toolSummaries };
12
39
  const ordered = TOOL_ORDER.filter((t) => toolNames.includes(t));
13
40
  const extras = toolNames.filter((t) => !TOOL_ORDER.includes(t)).sort();
@@ -23,7 +50,21 @@ export function buildToolingSection(toolNames, _modelTier, toolSummaries) {
23
50
  // ---------------------------------------------------------------------------
24
51
  // 4. Tool Call Style (skip if minimal)
25
52
  // ---------------------------------------------------------------------------
26
- export function buildToolCallStyleSection(isMinimal, toolNames = []) {
53
+ /**
54
+ * Build the static "## Tool Call Style" section with conditional coding guidelines.
55
+ *
56
+ * @param capabilityIndexEnabled - When `true`, AND when `exec` is in
57
+ * `toolNames`, the rendered output includes the dual-gated "Tool-first
58
+ * principle" bullet immediately before the existing Python-virtualenv rule.
59
+ * When `false` or `undefined`, the bullet is omitted; the existing venv
60
+ * rule emits unchanged when `exec` is present.
61
+ *
62
+ * Restart-required: the gate value flows from `tooling.capabilityIndex.enabled`
63
+ * via `AssemblerParams.capabilityIndexEnabled`, populated at the prompt
64
+ * assembly site from `port.isCapabilityIndexEnabled()`. The value is
65
+ * config-derived and stable per session — SAFE inside the cache fence.
66
+ */
67
+ export function buildToolCallStyleSection(isMinimal, toolNames = [], capabilityIndexEnabled) {
27
68
  if (isMinimal)
28
69
  return [];
29
70
  const lines = [
@@ -64,6 +105,14 @@ export function buildToolCallStyleSection(isMinimal, toolNames = []) {
64
105
  guidelines.push("- Show file paths clearly when working with files.");
65
106
  }
66
107
  if (has("exec")) {
108
+ // Dual-gated counterweight to the venv rule below. The bullet precedes
109
+ // the venv rule because the first read sets the default; the second is
110
+ // the install fallback. Restart-required: capabilityIndexEnabled flows
111
+ // from `tooling.capabilityIndex.enabled` via AssemblerParams →
112
+ // SECTIONS["tool-call-style"].
113
+ if (capabilityIndexEnabled === true) {
114
+ guidelines.push("- **Tool-first principle.** When this turn includes a `Capabilities` context and the task can be satisfied by a connected tool or available skill, prefer that capability over installing a Python or Node package. Use installs only for capabilities not covered by active tools, deferred tools, or visible prompt skills.");
115
+ }
67
116
  guidelines.push("- **Python projects:** Always create a virtualenv per project (`python3 -m venv .venv`). "
68
117
  + "Install packages into the project venv (`source .venv/bin/activate && pip install ...`). "
69
118
  + "Never use `--break-system-packages` — it pollutes the system Python. "
@@ -79,6 +79,28 @@ export interface AssemblerParams {
79
79
  excludeBootstrapFromContext?: boolean;
80
80
  /** Workspace profile controlling platform instruction verbosity ('full' or 'specialist'). */
81
81
  workspaceProfile?: "full" | "specialist";
82
+ /**
83
+ * Capability index gate.
84
+ *
85
+ * When `true`, `buildToolingSection` emits the residual one-liner instead
86
+ * of the legacy `## Available Tools` flat block; the per-turn
87
+ * `## Capabilities` block is rendered into the dynamic preamble in
88
+ * `executor-prompt-runner.ts`.
89
+ * When `false` or `undefined`, the static prompt is byte-identical to
90
+ * the pre-feature baseline.
91
+ *
92
+ * RESTART-REQUIRED: this flag selects between two cached system-prompt
93
+ * shapes. Daemon wiring documents the operator-facing constraint.
94
+ *
95
+ * SAFE INSIDE THE CACHE FENCE: this value is config-derived
96
+ * (operator-only, restart-required) and stable across all turns of a
97
+ * session. Plumbing it through `assemblerParams` does NOT create a
98
+ * cache-thrash regression. Live-runtime accessors
99
+ * (getPromptSkillCapabilities, getConnectedMcpServers) are forbidden
100
+ * inside this interface and enforced by an architecture-grep test.
101
+ * Adding a config-derived flag to the cache fence is safe.
102
+ */
103
+ capabilityIndexEnabled?: boolean;
82
104
  /** Whether Silent Execution Planner (SEP) is enabled for this agent. */
83
105
  sepEnabled?: boolean;
84
106
  }
@@ -82,8 +82,8 @@ export const SECTIONS = [
82
82
  { id: "safety", includeIn: MODES_ALL, build: (p, m) => buildSafetySection(m === "minimal") },
83
83
  { id: "language", includeIn: MODES_ALL, build: (p) => buildLanguageSection(p.userLanguage) },
84
84
  // --- Semi-stable body: operational-kept sections (MODES_ALL -- builders self-filter for minimal) ---
85
- { id: "tooling", includeIn: MODES_ALL, build: (p, m) => buildToolingSection(p.toolNames ?? [], m === "minimal" ? "small" : "large", p.toolSummaries) },
86
- { id: "tool-call-style", includeIn: MODES_ALL, build: (p, m) => buildToolCallStyleSection(m === "minimal", p.toolNames ?? []) },
85
+ { id: "tooling", includeIn: MODES_ALL, build: (p, m) => buildToolingSection(p.toolNames ?? [], m === "minimal" ? "small" : "large", p.toolSummaries, p.capabilityIndexEnabled) },
86
+ { id: "tool-call-style", includeIn: MODES_ALL, build: (p, m) => buildToolCallStyleSection(m === "minimal", p.toolNames ?? [], p.capabilityIndexEnabled) },
87
87
  // --- Operational-stripped sections (MODES_FULL_MIN -- dropped in "operational") ---
88
88
  { id: "self-update", includeIn: MODES_FULL_MIN, build: (p, m) => buildSelfUpdateGatingSection(p.toolNames ?? [], m === "minimal", true) },
89
89
  { id: "config-secret", includeIn: MODES_FULL_MIN, build: (p, m) => buildConfigSecretIntegritySection(p.toolNames ?? [], m === "minimal") },
@@ -10,11 +10,7 @@
10
10
  *
11
11
  * @module
12
12
  */
13
- /**
14
- * Extract the MCP server name from a sanitized tool name.
15
- * Format: `mcp__serverName--toolName`. Returns undefined for non-MCP tools.
16
- */
17
- export declare function extractMcpServerName(toolName: string): string | undefined;
13
+ export { extractMcpServerName } from "@comis/shared";
18
14
  /**
19
15
  * Classify an MCP error message into a category for observability.
20
16
  */