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
@@ -13,7 +13,9 @@
13
13
  *
14
14
  * @module
15
15
  */
16
- import { suppressError } from "@comis/shared";
16
+ import { tryGetContext, } from "@comis/core";
17
+ import { suppressError, isSilentResponse } from "@comis/shared";
18
+ import { drainAt, markRead, markConsumed, formatDrainKey, } from "./drain-helper.js";
17
19
  import { setBreakpointIndex, deleteBreakpointIndex, getBreakpointIndexMapSize, } from "./executor-session-state.js";
18
20
  import { mergeSessionStats } from "./pi-executor.js";
19
21
  import { recordLastResponseTs } from "./ttl-guard.js";
@@ -124,6 +126,63 @@ export function isDuplicatePairedMemory(content, agentId) {
124
126
  export function resetPairedMemoryDedupForTests() {
125
127
  pairedMemoryDedup.clear();
126
128
  }
129
+ /**
130
+ * Map an SDK finishReason to the SessionMetadata.sessionEnd.endReason enum.
131
+ * Unknown reasons fall through to "error" — that's a defensive bucket for
132
+ * provider strings we haven't classified yet (rather than dropping the
133
+ * session_end entry entirely). Module-level so the post-execution path
134
+ * doesn't reallocate it on every turn.
135
+ */
136
+ const END_REASON_MAP = {
137
+ stop: "success", end_turn: "success", error: "error",
138
+ budget_exceeded: "budget_exceeded", budget_exhausted: "budget_exhausted",
139
+ circuit_open: "circuit_open",
140
+ provider_degraded: "provider_degraded", max_steps: "error",
141
+ context_loop: "error", context_exhausted: "error",
142
+ };
143
+ /**
144
+ * Build the SessionMetadata payload written to `_session-metadata.json` at the
145
+ * end of an execution.
146
+ *
147
+ * `traceId` and `runId` are deliberately distinct:
148
+ * - `traceId` is the request-scope AsyncLocalStorage value set by
149
+ * `runWithContext` at the channel boundary (execution-execute.ts) and injected
150
+ * into every daemon log line by the Pino tracing mixin. Operators grep
151
+ * daemon.log for this exact value. Pass `tryGetContext()?.traceId` here.
152
+ * - `runId` is the executor-scope UUID minted in pi-executor.ts per
153
+ * `executor.execute()` call. It keys cost-tracker / token_usage rows.
154
+ *
155
+ * They happen to be 1:1 in the steady-state interactive path (one inbound
156
+ * message → one execution), but the schema treats them as distinct because
157
+ * heartbeat / sub-agent paths can fan out one trace into multiple executions.
158
+ *
159
+ * Pure: no I/O, no side effects. The fire-and-forget try/catch around
160
+ * `writeSessionMetadata` lives at the call site.
161
+ */
162
+ export function buildSessionEndMetadata(args) {
163
+ return {
164
+ ...(args.traceId && { traceId: args.traceId }),
165
+ runId: args.executionId,
166
+ sessionEnd: {
167
+ type: "session_end",
168
+ timestamp: new Date().toISOString(),
169
+ endReason: END_REASON_MAP[args.finishReason] ?? "error",
170
+ durationMs: args.durationMs,
171
+ totalTokens: args.totalTokens,
172
+ },
173
+ };
174
+ }
175
+ // ---------------------------------------------------------------------------
176
+ // Drain-seam re-exports.
177
+ //
178
+ // Canonical implementations live in ./drain-helper.ts so the bridge
179
+ // (packages/agent/src/bridge/pi-event-bridge.ts) can import them without
180
+ // creating a cycle through pi-executor.js. The bridge owns the
181
+ // `drainInflightByKey: Map<string, Promise<void>>` gate state in
182
+ // `BridgeMetricsState` and threads it into drainAt at the
183
+ // `tool_execution_end` call site (inline-consumption + composite drain).
184
+ // ---------------------------------------------------------------------------
185
+ export { drainAt, markRead, markConsumed, formatDrainKey, };
127
186
  // ---------------------------------------------------------------------------
128
187
  // Implementation
129
188
  // ---------------------------------------------------------------------------
@@ -139,7 +198,12 @@ export function resetPairedMemoryDedupForTests() {
139
198
  * @param params - All inputs needed for post-execution cleanup
140
199
  */
141
200
  export async function postExecution(params) {
142
- const { result, session, sm, config, msg, sessionKey, formattedKey, agentId, executionStartMs, executionId, bridge, unsubscribe, contextEngineRef, ceSetup, streamSetup, getTruncationSummary, getTurnBudgetSummary, executionPlanRef, isOnboarding, geminiCacheHit, geminiCachedTokens, modelTier, deferralResult, mergedCustomTools, deliveredGuides, deps, sessionAdapter, executionCacheRetentionClear, adaptiveRetentionClear, } = params;
201
+ const { result, session, sm, config, msg, sessionKey, formattedKey, resolverRegisterKey, agentId, executionStartMs, executionId, bridge, unsubscribe, contextEngineRef, ceSetup, streamSetup, getTruncationSummary, getTurnBudgetSummary, executionPlanRef, isOnboarding, geminiCacheHit, geminiCachedTokens, modelTier, provider, providerFamily, deferralResult, mergedCustomTools, deliveredGuides, deps, sessionAdapter, executionCacheRetentionClear, adaptiveRetentionClear, } = params;
202
+ // Hoist effectiveAgentId normalization to the TOP of the function so all
203
+ // downstream branches (silent-sentinel gate, memory-store path, drainAt
204
+ // call site, skip-log debug branches) share the same normalized value.
205
+ // Multi-agent isolation requires uniformity across all paths.
206
+ const effectiveAgentId = agentId ?? "default";
143
207
  unsubscribe();
144
208
  // Clear per-execution cache retention to prevent state leakage
145
209
  executionCacheRetentionClear();
@@ -168,7 +232,7 @@ export async function postExecution(params) {
168
232
  if (result.errorContext && bridgeResult.lastActiveToolName) {
169
233
  result.errorContext.failingTool = bridgeResult.lastActiveToolName;
170
234
  }
171
- // R-13: Delegate token totals to SDK session stats (single source of truth).
235
+ // Delegate token totals to SDK session stats (single source of truth).
172
236
  // Cost stays from bridge for consistency with per-turn observability events.
173
237
  // Per-turn event emission in bridge remains manual (SDK stats are cumulative only).
174
238
  mergeSessionStats(result, () => session.getSessionStats());
@@ -184,7 +248,7 @@ export async function postExecution(params) {
184
248
  // The context:pipeline event fires pre-LLM with zeros. This event patches actual data.
185
249
  if (deps.eventBus) {
186
250
  deps.eventBus.emit("context:pipeline:cache", {
187
- agentId: agentId ?? "unknown",
251
+ agentId: effectiveAgentId,
188
252
  sessionKey: formattedKey,
189
253
  cacheHitTokens: cacheReadTokens,
190
254
  cacheWriteTokens,
@@ -207,7 +271,7 @@ export async function postExecution(params) {
207
271
  planExtractionTurn: 1,
208
272
  };
209
273
  deps.eventBus.emit("sep:plan_completed", {
210
- agentId: agentId ?? "default",
274
+ agentId: effectiveAgentId,
211
275
  sessionKey: formattedKey,
212
276
  stepsPlanned: toolCalls,
213
277
  stepsCompleted: toolCalls,
@@ -235,6 +299,10 @@ export async function postExecution(params) {
235
299
  // Truncation summary from bouncer + turn budget summary
236
300
  const truncSummary = getTruncationSummary();
237
301
  const turnBudgetSummary = getTurnBudgetSummary();
302
+ // Snapshot the scrub counters once before composing the bookend log so both
303
+ // fields read from the same observation (the getter is cheap but the
304
+ // read-twice pattern would still be a micro-divergence risk).
305
+ const scrubCounters = ceSetup.getSignatureScrubCounters();
238
306
  deps.logger.info({
239
307
  sessionKey: formattedKey,
240
308
  durationMs,
@@ -260,7 +328,7 @@ export async function postExecution(params) {
260
328
  comisEstimatedTtlSplit: (bridgeResult.cacheWrite5mTokens ?? 0) > 0 || (bridgeResult.cacheWrite1hTokens ?? 0) > 0,
261
329
  costUsd: result.cost.total,
262
330
  cacheSavedUsd: result.cost.cacheSaved ?? 0,
263
- // 1.3: Session-cumulative cost fields (alongside per-turn costUsd/cacheSavedUsd)
331
+ // Session-cumulative cost fields (alongside per-turn costUsd/cacheSavedUsd)
264
332
  sessionCostUsd: bridgeResult.sessionCostUsd ?? 0,
265
333
  sessionCacheSavedUsd: bridgeResult.sessionCacheSavedUsd ?? 0,
266
334
  // Session cache savings rate
@@ -274,6 +342,8 @@ export async function postExecution(params) {
274
342
  geminiCacheHit,
275
343
  geminiCachedTokens,
276
344
  modelTier,
345
+ provider,
346
+ providerFamily,
277
347
  deferredCount: deferralResult.deferredCount,
278
348
  activeToolCount: mergedCustomTools.length,
279
349
  guidesDelivered: deliveredGuides.size,
@@ -282,6 +352,16 @@ export async function postExecution(params) {
282
352
  toolFailureRate: (result.stepsExecuted ?? 0) > 0
283
353
  ? Math.round(((bridgeResult.failedToolCalls ?? 0) / (result.stepsExecuted ?? 0)) * 100)
284
354
  : 0,
355
+ // Per-execute diagnostic counters rolled up from the two demoted log
356
+ // sites. Always populated (no `> 0` gate) — `0` is itself meaningful
357
+ // ("no scrubs/assertions this execute") and gating would lose that
358
+ // signal. hashAssertions* come from the bridge metrics path;
359
+ // signatureScrubs* come from ceSetup since the scrubber doesn't write
360
+ // to bridge state.
361
+ hashAssertionsRan: bridgeResult.hashAssertionsRan ?? 0,
362
+ hashAssertionMismatches: bridgeResult.hashAssertionMismatches ?? 0,
363
+ signatureScrubs: scrubCounters.signatureScrubs,
364
+ signatureScrubsToolCallsAffected: scrubCounters.signatureScrubsToolCallsAffected,
285
365
  ...(bridgeResult.failedTools && bridgeResult.failedTools.length > 0 && { failedTools: bridgeResult.failedTools }),
286
366
  truncatedTools: truncSummary.truncatedTools,
287
367
  totalTruncatedChars: truncSummary.totalTruncatedChars,
@@ -296,7 +376,7 @@ export async function postExecution(params) {
296
376
  postBatchContinuationAttempts: result.continuationMetrics.attempts,
297
377
  postBatchContinuationOutcome: result.continuationMetrics.outcome,
298
378
  }),
299
- // 1.5 + 3.2: Thinking token tracking (conditional -- only when thinking tokens detected)
379
+ // Thinking token tracking (conditional -- only when thinking tokens detected)
300
380
  ...(bridgeResult.thinkingTokens != null && bridgeResult.thinkingTokens > 0 && {
301
381
  thinkingTokens: bridgeResult.thinkingTokens,
302
382
  totalOutputTokens: result.tokensUsed.output ?? 0,
@@ -323,27 +403,19 @@ export async function postExecution(params) {
323
403
  errorKind: "resource",
324
404
  }, "Turn budget truncation summary");
325
405
  }
326
- // Write session metadata companion file with trace correlation
327
- // Fire-and-forget: metadata write failure must not affect execution
328
- const endReasonMap = {
329
- stop: "success", end_turn: "success", error: "error",
330
- budget_exceeded: "budget_exceeded", budget_exhausted: "budget_exhausted",
331
- circuit_open: "circuit_open",
332
- provider_degraded: "provider_degraded", max_steps: "error",
333
- context_loop: "error", context_exhausted: "error",
334
- };
406
+ // Write session metadata companion file with trace correlation.
407
+ // traceId comes from the AsyncLocalStorage request scope so `_session-metadata.json`
408
+ // can be cross-correlated against daemon.log via grep; runId stays as the
409
+ // executor-scope UUID. See buildSessionEndMetadata for the contract.
410
+ // Fire-and-forget: metadata write failure must not affect execution.
335
411
  try {
336
- sessionAdapter.writeSessionMetadata(sessionKey, {
337
- traceId: executionId,
338
- runId: executionId,
339
- sessionEnd: {
340
- type: "session_end",
341
- timestamp: new Date().toISOString(),
342
- endReason: endReasonMap[result.finishReason] ?? "error",
343
- durationMs,
344
- totalTokens: result.tokensUsed.total,
345
- },
346
- });
412
+ sessionAdapter.writeSessionMetadata(sessionKey, buildSessionEndMetadata({
413
+ finishReason: result.finishReason,
414
+ durationMs,
415
+ totalTokens: result.tokensUsed.total,
416
+ executionId,
417
+ traceId: tryGetContext()?.traceId,
418
+ }));
347
419
  }
348
420
  catch { /* fire-and-forget */ }
349
421
  // Check onboarding completion after execution
@@ -367,14 +439,23 @@ export async function postExecution(params) {
367
439
  // Non-blocking, non-fatal -- execution never fails due to memory store errors.
368
440
  const operationType = params.executionOverrides?.operationType;
369
441
  const skipMemoryForOperation = operationType != null && MEMORY_SKIP_OPERATIONS.has(operationType);
370
- if (deps.memoryPort &&
442
+ // Layer 0: silent sentinels never enter memory. Idempotent under
443
+ // stripReplyTags + trim per @comis/shared silent-tokens.ts JSDoc
444
+ // contract. The check happens BEFORE the operationType + content-hash
445
+ // dedup gates so that even when the response would otherwise pass those
446
+ // gates, a `NO_REPLY` / `HEARTBEAT_OK` / `[SILENT]` sentinel is rejected
447
+ // from memory persistence.
448
+ const isSilent = !!(deps.memoryPort && result.response && msg.text && isSilentResponse(result.response));
449
+ if (isSilent) {
450
+ deps.logger.debug({ agentId: effectiveAgentId, sessionKey: formattedKey, hint: "Silent-sentinel response (NO_REPLY / HEARTBEAT_OK / [SILENT]) skipped from paired memory" }, "Paired memory skipped: silent-sentinel response");
451
+ }
452
+ else if (deps.memoryPort &&
371
453
  result.response &&
372
454
  msg.text &&
373
455
  !skipMemoryForOperation &&
374
456
  shouldStorePairedMemory(msg.text, result.response)) {
375
457
  const now = Date.now();
376
458
  const pairedContent = buildPairedMemoryContent(msg.text, result.response);
377
- const effectiveAgentId = agentId ?? "default";
378
459
  if (isDuplicatePairedMemory(pairedContent, effectiveAgentId)) {
379
460
  deps.logger.debug({ agentId: effectiveAgentId, sessionKey: formattedKey }, "Paired memory skipped: duplicate content within dedup window");
380
461
  }
@@ -417,9 +498,47 @@ export async function postExecution(params) {
417
498
  deps.logger.debug({ userLen: msg.text.trim().length, minUserChars: PAIRED_MIN_USER_CHARS, minCombinedChars: PAIRED_MIN_COMBINED_CHARS }, "Paired memory skipped: content below quality threshold");
418
499
  }
419
500
  }
420
- // Deregister active run before dispose
501
+ // End-of-turn backstop drain.
502
+ //
503
+ // The bridge fires `drainAt(...)` on `tool_execution_end` for successful
504
+ // `message(send|reply|attach)` calls (the primary inline-consumption
505
+ // call site). The end-of-turn call site below is the BACKSTOP for turns
506
+ // that produced a response WITHOUT invoking the message tool (NO_REPLY-
507
+ // only turns, sentinel-passthrough turns, error paths). Both call sites
508
+ // share the SAME composite-key inflight gate (`drainInflightByKey`) so a
509
+ // bridge-fired drain in flight collapses any backstop drain for the same
510
+ // composite key (single-tick gate).
511
+ //
512
+ // The drain key is composed from `effectiveAgentId` (multi-agent
513
+ // isolation) + `msg.channelType` + `msg.channelId`. markRead and
514
+ // markConsumed inside drainAt read tool context via tryGetContext();
515
+ // when the executor runs outside an AsyncLocalStorage scope (e.g.,
516
+ // tests with no runWithContext wrapper) the helpers fall through silently.
517
+ const drainKey = {
518
+ agentId: effectiveAgentId,
519
+ channelType: msg.channelType,
520
+ channelId: msg.channelId,
521
+ };
522
+ // tryGetContext() reads the AsyncLocalStorage scope; markRead/markConsumed
523
+ // do the same internally, but reading once here lets us correlate the
524
+ // backstop-drain log line with the request's traceId without re-deriving
525
+ // it inside the helper. Returns undefined outside any request scope --
526
+ // markRead/markConsumed handle that path silently.
527
+ const drainCtx = tryGetContext();
528
+ if (drainCtx) {
529
+ deps.logger.debug({
530
+ submodule: "drain.endOfTurn",
531
+ agentId: effectiveAgentId,
532
+ channelType: msg.channelType,
533
+ channelId: msg.channelId,
534
+ traceId: drainCtx.traceId,
535
+ }, "End-of-turn drain backstop firing");
536
+ }
537
+ drainAt({ agentId: effectiveAgentId, channelType: drainKey.channelType, channelId: drainKey.channelId }, bridge.getDrainState(), deps.logger);
538
+ // Deregister active run before dispose. Must use the same resolver-aligned
539
+ // key formula as the corresponding register call site.
421
540
  if (deps.activeRunRegistry) {
422
- deps.activeRunRegistry.deregister(formattedKey);
541
+ deps.activeRunRegistry.deregister(resolverRegisterKey);
423
542
  }
424
543
  // Strip verbose <functions> blocks from discover_tools results
425
544
  // in session history. Runs post-execution so the current turn's model
@@ -26,6 +26,7 @@ import type { AuthRotationAdapter } from "../model/auth-rotation-adapter.js";
26
26
  import type { ProviderHealthMonitor } from "../safety/provider-health-monitor.js";
27
27
  import type { LastKnownModelTracker } from "../model/last-known-model.js";
28
28
  import type { EnvelopeConfig } from "@comis/core";
29
+ import type { CapabilityIndexRenderResult } from "./capability-index-context.js";
29
30
  /** Bridge interface used by the prompt runner (minimal getResult). */
30
31
  export interface PromptRunnerBridge {
31
32
  getResult(): {
@@ -60,6 +61,12 @@ export interface RunPromptParams {
60
61
  bridge: PromptRunnerBridge;
61
62
  dynamicPreamble: string | undefined;
62
63
  deferredContext: string | undefined;
64
+ /**
65
+ * Per-turn capability-index render result. The .text field is concatenated
66
+ * into the dynamic preamble via `[...].filter(Boolean).join("\n\n")`; the
67
+ * count fields feed the Pino debug log below.
68
+ */
69
+ capabilityIndexResult: CapabilityIndexRenderResult;
63
70
  inlineMemory: string | undefined;
64
71
  systemPrompt: string | undefined;
65
72
  mergedCustomTools: Array<{
@@ -47,7 +47,7 @@ import { getCacheProviderInfo } from "../executor/cache-usage-helpers.js";
47
47
  * @returns Prompt execution outcome (success, error, escalation state)
48
48
  */
49
49
  export async function runPrompt(params) {
50
- const { msg, session, config, sessionKey, formattedKey, agentId, result, executionStartMs, effectiveTimeout, executionId, bridge, dynamicPreamble, deferredContext, inlineMemory, systemPrompt, mergedCustomTools, cmdResult, sepEnabled, executionPlanRef, _directives, _prevTimestamp, resolvedModel, deps, onResetTimer, getLastCacheWriteTokens, budgetWarningRef, } = params;
50
+ const { msg, session, config, sessionKey, formattedKey, agentId, result, executionStartMs, effectiveTimeout, executionId, bridge, dynamicPreamble, deferredContext, capabilityIndexResult, inlineMemory, systemPrompt, mergedCustomTools, cmdResult, sepEnabled, executionPlanRef, _directives, _prevTimestamp, resolvedModel, deps, onResetTimer, getLastCacheWriteTokens, budgetWarningRef, } = params;
51
51
  // Wrap message text with envelope
52
52
  let messageText = deps.envelopeConfig
53
53
  ? wrapInEnvelope(msg, deps.envelopeConfig, _prevTimestamp)
@@ -55,12 +55,33 @@ export async function runPrompt(params) {
55
55
  // Prepend dynamic preamble (date/time, inbound metadata)
56
56
  // relocated from system prompt for cache stability.
57
57
  // Also includes <deferred-tools> context block when deferred tools exist.
58
- const fullDynamicPreamble = deferredContext
59
- ? (dynamicPreamble ? dynamicPreamble + "\n\n" + deferredContext : deferredContext)
60
- : dynamicPreamble;
58
+ //
59
+ // Array-concat shape. Each element either contributes a non-empty string
60
+ // or filters out cleanly. The renderer's EMPTY sentinel (gate-disabled OR
61
+ // all-zero counts) yields text === "" which .filter(Boolean) drops
62
+ // automatically.
63
+ const capabilityIndexContext = capabilityIndexResult.text;
64
+ const fullDynamicPreamble = [dynamicPreamble, capabilityIndexContext, deferredContext]
65
+ .filter(Boolean)
66
+ .join("\n\n");
61
67
  if (fullDynamicPreamble) {
62
68
  messageText = `[System context]\n${fullDynamicPreamble}\n[End system context]\n\n${messageText}`;
63
69
  }
70
+ // Pino debug log. Submodule binding per AGENTS.md §2.7:
71
+ // deps.logger.child({ submodule }) attaches the label only at this call
72
+ // site, not module-scope.
73
+ const submoduleLogger = deps.logger.child({ submodule: "executor.capability-index" });
74
+ const fullPreambleTokens = Math.ceil((fullDynamicPreamble ?? "").length / CHARS_PER_TOKEN_RATIO);
75
+ const deferredContextTokens = Math.ceil((deferredContext ?? "").length / CHARS_PER_TOKEN_RATIO);
76
+ submoduleLogger.debug({
77
+ capabilityIndexTokens: capabilityIndexResult.capabilityIndexTokens,
78
+ deferredContextTokens,
79
+ fullPreambleTokens,
80
+ clusterCount: capabilityIndexResult.clusterCount,
81
+ activeToolCount: capabilityIndexResult.activeToolCount,
82
+ deferredToolCount: capabilityIndexResult.deferredToolCount,
83
+ promptSkillCount: capabilityIndexResult.promptSkillCount,
84
+ }, "Dynamic preamble assembled");
64
85
  // Task 229: Inject top-1 RAG memory inline, adjacent to user message
65
86
  // for maximum LLM attention. Placed AFTER [End system context] and
66
87
  // BEFORE the user's actual question text.
@@ -644,7 +665,7 @@ export async function runPrompt(params) {
644
665
  // NOTE: Only evaluate bridge.getResult().textEmitted when needed to avoid
645
666
  // incrementing mock call counters (budget tests use callCount on getResult).
646
667
  const rawResponse = getVisibleAssistantText(session);
647
- const needsRecovery = rawResponse === "" || ["NO_REPLY", "HEARTBEAT_OK"].includes(rawResponse.trim());
668
+ const needsRecovery = rawResponse === "";
648
669
  // Find the last user message index to bound empty-response recovery
649
670
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
650
671
  const sessionMessages = session.messages ?? [];
@@ -42,10 +42,15 @@ export declare function scanWithOutputGuard(params: {
42
42
  logger: ComisLogger;
43
43
  }): OutputGuardScanResult;
44
44
  /**
45
- * When the final assistant message is thinking-only or a
46
- * silent token (NO_REPLY, HEARTBEAT_OK) but text was emitted in earlier
45
+ * When the final assistant message is empty but text was emitted in earlier
47
46
  * turns, recover a meaningful user-visible response.
48
47
  *
48
+ * Recovery fires only when `extractedResponse === ""`. Silent tokens
49
+ * (`NO_REPLY`, `HEARTBEAT_OK`) are explicit suppression signals and pass
50
+ * through unchanged — the channel-layer filter
51
+ * (`packages/channels/src/shared/response-filter.ts`) detects and suppresses
52
+ * them downstream.
53
+ *
49
54
  * Two-pass strategy (gated):
50
55
  * 1. **Tool-call synthesis** (primary) — if ≥1 prior assistant turn within the
51
56
  * current execution window contains tool-call blocks, synthesize a
@@ -62,10 +67,6 @@ export declare function scanWithOutputGuard(params: {
62
67
  * comment below) ensures the standalone walk only fires when no tool calls
63
68
  * were observed; this keeps the pass selection mutually exclusive.
64
69
  *
65
- * Suppressed when a delivery tool (`message`, `notify`) was used — the agent
66
- * already delivered content via side-channel and the silent final token is
67
- * intentional.
68
- *
69
70
  * Returns the recovered text, or the original response if no recovery needed.
70
71
  */
71
72
  export declare function recoverEmptyFinalResponse(params: {
@@ -84,16 +84,16 @@ export function scanWithOutputGuard(params) {
84
84
  // ---------------------------------------------------------------------------
85
85
  /** Silent tokens that indicate the final message has no visible content. */
86
86
  const SILENT_FINAL_TOKENS = ["NO_REPLY", "HEARTBEAT_OK"];
87
- /** Tool names whose successful invocation means the agent already delivered
88
- * content to the user through a side-channel. When one of these tools was
89
- * called during the execution, a silent final token (NO_REPLY) is intentional
90
- * and recovery must be suppressed to avoid leaking internal narration. */
91
- const DELIVERY_TOOL_NAMES = ["message", "notify"];
92
87
  /**
93
- * When the final assistant message is thinking-only or a
94
- * silent token (NO_REPLY, HEARTBEAT_OK) but text was emitted in earlier
88
+ * When the final assistant message is empty but text was emitted in earlier
95
89
  * turns, recover a meaningful user-visible response.
96
90
  *
91
+ * Recovery fires only when `extractedResponse === ""`. Silent tokens
92
+ * (`NO_REPLY`, `HEARTBEAT_OK`) are explicit suppression signals and pass
93
+ * through unchanged — the channel-layer filter
94
+ * (`packages/channels/src/shared/response-filter.ts`) detects and suppresses
95
+ * them downstream.
96
+ *
97
97
  * Two-pass strategy (gated):
98
98
  * 1. **Tool-call synthesis** (primary) — if ≥1 prior assistant turn within the
99
99
  * current execution window contains tool-call blocks, synthesize a
@@ -110,29 +110,13 @@ const DELIVERY_TOOL_NAMES = ["message", "notify"];
110
110
  * comment below) ensures the standalone walk only fires when no tool calls
111
111
  * were observed; this keeps the pass selection mutually exclusive.
112
112
  *
113
- * Suppressed when a delivery tool (`message`, `notify`) was used — the agent
114
- * already delivered content via side-channel and the silent final token is
115
- * intentional.
116
- *
117
113
  * Returns the recovered text, or the original response if no recovery needed.
118
114
  */
119
115
  export function recoverEmptyFinalResponse(params) {
120
116
  const { extractedResponse, textEmitted, messages, logger, userMessageIndex } = params;
121
117
  const lowerBound = userMessageIndex ?? 0;
122
- const isSilentFinalToken = SILENT_FINAL_TOKENS.includes(extractedResponse.trim());
123
- if ((extractedResponse === "" || isSilentFinalToken) && textEmitted) {
118
+ if (extractedResponse === "" && textEmitted) {
124
119
  if (Array.isArray(messages)) {
125
- // Guard: if the agent already delivered content via a delivery tool
126
- // (message, notify), the silent final token is intentional — skip
127
- // recovery to avoid leaking internal narration (e.g. "Now let me
128
- // generate the chart:" surfaced as a user-visible message).
129
- if (isSilentFinalToken && hasDeliveryToolCall(messages, lowerBound)) {
130
- logger.debug({
131
- hint: "Silent final token after delivery tool call — recovery suppressed",
132
- extractedResponse,
133
- }, "Skipping empty-response recovery (delivery tool used)");
134
- return extractedResponse;
135
- }
136
120
  /* eslint-disable @typescript-eslint/no-explicit-any */
137
121
  // Collect tool-call summaries from prior assistant turns within the
138
122
  // current execution window (lowerBound .. messages.length).
@@ -170,7 +154,7 @@ export function recoverEmptyFinalResponse(params) {
170
154
  `${bullets}\n` +
171
155
  `The work was done; the assistant did not summarize. Please ask "what did you do?" if details are needed.`;
172
156
  logger.info({
173
- module: "agent.executor.empty-turn-recovery",
157
+ submodule: "executor.empty-turn-recovery",
174
158
  recoveryPass: "tool-call-synthesis",
175
159
  toolCallCount: toolCallSummaries.length,
176
160
  toolNames: [...toolNamesSet],
@@ -226,23 +210,6 @@ function extractVisibleText(content) {
226
210
  return undefined;
227
211
  }
228
212
  /* eslint-enable @typescript-eslint/no-explicit-any */
229
- /** Check whether any assistant turn (from lowerBound onward) contains a tool
230
- * call to a delivery tool (message, notify). These tools send content to the
231
- * user through a side-channel, so a subsequent NO_REPLY is intentional. */
232
- /* eslint-disable @typescript-eslint/no-explicit-any */
233
- function hasDeliveryToolCall(messages, lowerBound) {
234
- for (let i = lowerBound; i < messages.length; i++) {
235
- const msg = messages[i]; // eslint-disable-line security/detect-object-injection
236
- if (msg?.role === "assistant" && Array.isArray(msg.content)) {
237
- const hasDelivery = msg.content.some((b) => (b?.type === "toolCall" || b?.type === "tool_use") &&
238
- DELIVERY_TOOL_NAMES.includes(b?.name));
239
- if (hasDelivery)
240
- return true;
241
- }
242
- }
243
- return false;
244
- }
245
- /* eslint-enable @typescript-eslint/no-explicit-any */
246
213
  /** Summarize a single tool-call content block as `toolName({primary_arg: "value"})`.
247
214
  * Reads `name` from the block, and `input` (Anthropic native) or `arguments`
248
215
  * (internal mapped convention) for args. Returns bare tool name on malformed
@@ -15,9 +15,10 @@
15
15
  import { SettingsManager, DefaultResourceLoader } from "@mariozechner/pi-coding-agent";
16
16
  import type { ToolDefinition } from "@mariozechner/pi-coding-agent";
17
17
  import type { AgentTool } from "@mariozechner/pi-agent-core";
18
- import { type SessionKey, type NormalizedMessage, type PerAgentConfig, type TypedEventBus, type MemoryPort, type HookRunner, type SecretManager, type EnvelopeConfig, type SenderTrustDisplayConfig } from "@comis/core";
18
+ import { type SessionKey, type NormalizedMessage, type PerAgentConfig, type TypedEventBus, type MemoryPort, type HookRunner, type SecretManager, type EnvelopeConfig, type SenderTrustDisplayConfig, type ToolCapabilityPort } from "@comis/core";
19
19
  import type { ComisLogger } from "@comis/infra";
20
20
  import type { ExcludeDeferralResult } from "./tool-deferral.js";
21
+ import type { CapabilityIndexRenderResult } from "./capability-index-context.js";
21
22
  import type { DiscoveryTracker } from "./discovery-tracker.js";
22
23
  import type { ExecutionPromptResult } from "./prompt-assembly.js";
23
24
  import type { ExecutionOverrides } from "./types.js";
@@ -48,6 +49,13 @@ export interface ToolAssemblyDeps {
48
49
  maxCharsPerInjection: number;
49
50
  };
50
51
  embeddingPort?: EmbeddingPort;
52
+ /**
53
+ * Tool-capability port for the per-turn capability-index renderer.
54
+ * Daemon wiring injects createNoOpCapabilityPort() from @comis/core; the
55
+ * live adapter is swapped in elsewhere. The no-op is a real production
56
+ * code path — NOT a transitional shim.
57
+ */
58
+ toolCapabilityPort: ToolCapabilityPort;
51
59
  skillRegistry?: {
52
60
  getEligibleSkillNames(): Set<string>;
53
61
  initFromSdkSkills(sdkSkills: Array<{
@@ -70,6 +78,15 @@ export interface ToolAssemblyResult {
70
78
  deferralResult: ExcludeDeferralResult;
71
79
  /** Formatted deferred tools context for dynamic preamble injection. */
72
80
  deferredContext: string;
81
+ /**
82
+ * Per-turn capability-index render result.
83
+ * `text` is concatenated into the dynamic preamble; the count fields feed
84
+ * the Pino debug log emitted in `executor-prompt-runner.ts`.
85
+ * When the port returns gate-disabled or all counts are zero, the renderer
86
+ * returns the EMPTY sentinel and `text === ""` filters out via
87
+ * `[...].filter(Boolean)` in the runner.
88
+ */
89
+ capabilityIndexResult: CapabilityIndexRenderResult;
73
90
  /** Session-scoped guide delivery tracking set. */
74
91
  deliveredGuides: Set<string>;
75
92
  /** Model tier derived from context window: "small" | "medium" | "large". */
@@ -15,7 +15,8 @@
15
15
  */
16
16
  import { SettingsManager, } from "@mariozechner/pi-coding-agent";
17
17
  import { formatSessionKey, } from "@comis/core";
18
- import { applyToolDeferral, buildDeferredToolsContext, createDiscoverTool, createAutoDiscoveryStubs, extractRecentlyUsedToolNames, resolveModelTier, supportsToolSearch, CORE_TOOLS } from "./tool-deferral.js";
18
+ import { applyToolDeferral, buildDeferredToolsContext, createDiscoverTool, createAutoDiscoveryStubs, extractRecentlyUsedToolNames, resolveModelTier, CORE_TOOLS } from "./tool-deferral.js";
19
+ import { buildCapabilityIndexContext } from "./capability-index-context.js";
19
20
  import { getOrCreateDiscoveryTracker } from "./discovery-tracker.js";
20
21
  import { getOrCreateTracker, DEFAULT_LIFECYCLE_CONFIG } from "./tool-lifecycle.js";
21
22
  import { isAnthropicFamily, isGoogleFamily } from "../provider/capabilities.js";
@@ -159,6 +160,9 @@ export async function assembleTools(params) {
159
160
  deliveryMirror: deps.deliveryMirror,
160
161
  deliveryMirrorConfig: deps.deliveryMirrorConfig,
161
162
  channelMaxChars: deps.getChannelMaxChars?.(msg.channelType),
163
+ // Forward the tool-capability port so prompt-assembly.ts can read
164
+ // `port.isCapabilityIndexEnabled()` for the static-prompt swap gate.
165
+ toolCapabilityPort: deps.toolCapabilityPort,
162
166
  },
163
167
  msg,
164
168
  sessionKey,
@@ -297,8 +301,7 @@ export async function assembleTools(params) {
297
301
  // discovered) is the only factually-accurate set -- using mergedCustomTools
298
302
  // (pre-deferral) would false-positive on currently-deferred tools and tell
299
303
  // the agent "call directly, no discovery needed" for tools that aren't
300
- // actually loaded. See design §4.2, §5.5, decision log row 4:
301
- // .planning/design/discover-tools-bm25-fallback-fix.md
304
+ // actually loaded.
302
305
  if (deferralResult.discoverTool) {
303
306
  const activeAfterDeferral = new Set([
304
307
  ...deferralResult.activeTools.map(t => t.name),
@@ -322,24 +325,22 @@ export async function assembleTools(params) {
322
325
  const stubs = createAutoDiscoveryStubs(deferralResult.deferredEntries, discoveryTracker, deps.logger);
323
326
  mergedCustomTools.push(...stubs);
324
327
  }
325
- // Build deferred context for dynamic preamble injection.
326
- //
327
- // 260428-oyc: under Anthropic Sonnet/Opus 4.x, request-body-injector.ts
328
- // strips client-side `discover_tools` from the API payload and replaces it
329
- // with the server-side `tool_search_tool_regex` + per-tool `defer_loading`
330
- // flag. Pass `useToolSearch=true` so the preamble teaches the model that
331
- // deferred tools auto-load on first direct invocation, rather than telling
332
- // it to call a tool the model can no longer see.
333
- //
334
- // resolvedModel is in scope here (param of assembleToolsForAgent, see
335
- // function signature ~line 143). When undefined (test paths / fallback),
336
- // useToolSearch defaults to false, preserving backward-compatible
337
- // discover_tools wording.
328
+ // Build deferred-tools context for dynamic preamble injection (mechanism-neutral).
329
+ // Provider-specific payload reshaping (stripping the client-side discovery
330
+ // tool, appending the server-side tool-search regex tool for Anthropic
331
+ // Sonnet/Opus 4.x) lives entirely in `request-body-injector.ts` and is
332
+ // gated there by a model-id capability check. See tool-deferral.ts JSDoc
333
+ // on `buildDeferredToolsContext` for the rationale.
338
334
  let deferredContext = "";
339
335
  if (deferralResult.deferredEntries.length > 0) {
340
- const useToolSearch = supportsToolSearch(resolvedModel?.id ?? "");
341
- deferredContext = buildDeferredToolsContext(deferralResult.deferredEntries, { useToolSearch });
336
+ deferredContext = buildDeferredToolsContext(deferralResult.deferredEntries);
342
337
  }
338
+ // Per-turn capability index.
339
+ // Lives AFTER applyToolDeferral so the renderer sees the post-partition
340
+ // state (active vs deferred entries). When the port is the no-op, the
341
+ // renderer's gate check still respects port.isCapabilityIndexEnabled();
342
+ // if false, returns EMPTY which the runner filters via .filter(Boolean).
343
+ const capabilityIndexResult = buildCapabilityIndexContext(deferralResult, deps.toolCapabilityPort);
343
344
  // -------------------------------------------------------------------
344
345
  // 8. JIT guide wrapping, schema pruning, snapshot, normalization, serializer
345
346
  // -------------------------------------------------------------------
@@ -369,6 +370,7 @@ export async function assembleTools(params) {
369
370
  mergedCustomTools,
370
371
  deferralResult,
371
372
  deferredContext,
373
+ capabilityIndexResult,
372
374
  deliveredGuides,
373
375
  modelTier,
374
376
  discoveryTracker,
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Injects CachedContent name into Gemini API payloads and atomically strips
5
5
  * the three inherited fields (systemInstruction, tools, toolConfig) to avoid
6
- * double-billing. Operates inside the onPayload hook (post-buildParams) per D-04.
6
+ * double-billing. Operates inside the onPayload hook (post-buildParams).
7
7
  *
8
8
  * Handles cache injection, inherited field stripping, and staleness recovery.
9
9
  *
@@ -24,7 +24,7 @@ export interface GeminiCacheInjectorConfig {
24
24
  /** Callback when a Gemini CachedContent entry is successfully injected.
25
25
  * Called with the CacheEntry so the caller can capture cache hit stats for logging. */
26
26
  onCacheHit?: (entry: CacheEntry) => void;
27
- /** Callback for cache break detection Phase 1.
27
+ /** Callback for cache break detection.
28
28
  * Called with the API-ready payload AFTER any cache injection. */
29
29
  onPayloadForCacheDetection?: (params: Record<string, unknown>, model: {
30
30
  id: string;