comisai 1.0.36 → 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 (239) hide show
  1. package/node_modules/@comis/agent/dist/background/auto-background-middleware.js +9 -0
  2. package/node_modules/@comis/agent/dist/background/background-task-manager.d.ts +22 -2
  3. package/node_modules/@comis/agent/dist/background/background-task-manager.js +48 -41
  4. package/node_modules/@comis/agent/dist/background/background-task-persistence.js +28 -5
  5. package/node_modules/@comis/agent/dist/background/background-task-types.d.ts +49 -0
  6. package/node_modules/@comis/agent/dist/background/completion-dispatcher.d.ts +130 -0
  7. package/node_modules/@comis/agent/dist/background/completion-dispatcher.js +215 -0
  8. package/node_modules/@comis/agent/dist/background/completion-runner.d.ts +10 -1
  9. package/node_modules/@comis/agent/dist/background/completion-runner.js +98 -15
  10. package/node_modules/@comis/agent/dist/background/index.d.ts +6 -1
  11. package/node_modules/@comis/agent/dist/background/index.js +2 -0
  12. package/node_modules/@comis/agent/dist/background/session-resolver.d.ts +85 -0
  13. package/node_modules/@comis/agent/dist/background/session-resolver.js +78 -0
  14. package/node_modules/@comis/agent/dist/bootstrap/sections/messaging-sections.js +1 -0
  15. package/node_modules/@comis/agent/dist/bootstrap/sections/tool-descriptions.js +3 -3
  16. package/node_modules/@comis/agent/dist/bootstrap/sections/tooling-sections.d.ts +30 -2
  17. package/node_modules/@comis/agent/dist/bootstrap/sections/tooling-sections.js +51 -2
  18. package/node_modules/@comis/agent/dist/bootstrap/system-prompt-assembler.d.ts +22 -0
  19. package/node_modules/@comis/agent/dist/bootstrap/system-prompt-assembler.js +2 -2
  20. package/node_modules/@comis/agent/dist/bridge/bridge-event-handlers.d.ts +1 -5
  21. package/node_modules/@comis/agent/dist/bridge/bridge-event-handlers.js +2 -14
  22. package/node_modules/@comis/agent/dist/bridge/bridge-metrics.d.ts +26 -0
  23. package/node_modules/@comis/agent/dist/bridge/bridge-metrics.js +3 -0
  24. package/node_modules/@comis/agent/dist/bridge/pi-event-bridge.d.ts +9 -0
  25. package/node_modules/@comis/agent/dist/bridge/pi-event-bridge.js +73 -2
  26. package/node_modules/@comis/agent/dist/context-engine/signature-surrogate-guard.d.ts +10 -10
  27. package/node_modules/@comis/agent/dist/context-engine/signature-surrogate-guard.js +14 -14
  28. package/node_modules/@comis/agent/dist/context-engine/thinking-block-cleaner.d.ts +11 -13
  29. package/node_modules/@comis/agent/dist/context-engine/thinking-block-cleaner.js +14 -15
  30. package/node_modules/@comis/agent/dist/executor/capability-index-context.d.ts +72 -0
  31. package/node_modules/@comis/agent/dist/executor/capability-index-context.js +329 -0
  32. package/node_modules/@comis/agent/dist/executor/drain-helper.d.ts +122 -0
  33. package/node_modules/@comis/agent/dist/executor/drain-helper.js +173 -0
  34. package/node_modules/@comis/agent/dist/executor/error-classifier.js +2 -2
  35. package/node_modules/@comis/agent/dist/executor/executor-post-execution.d.ts +48 -4
  36. package/node_modules/@comis/agent/dist/executor/executor-post-execution.js +134 -31
  37. package/node_modules/@comis/agent/dist/executor/executor-prompt-runner.d.ts +7 -0
  38. package/node_modules/@comis/agent/dist/executor/executor-prompt-runner.js +25 -4
  39. package/node_modules/@comis/agent/dist/executor/executor-tool-assembly.d.ts +18 -1
  40. package/node_modules/@comis/agent/dist/executor/executor-tool-assembly.js +19 -16
  41. package/node_modules/@comis/agent/dist/executor/jit-guide-injector.d.ts +11 -2
  42. package/node_modules/@comis/agent/dist/executor/jit-guide-injector.js +16 -2
  43. package/node_modules/@comis/agent/dist/executor/pi-executor.d.ts +8 -2
  44. package/node_modules/@comis/agent/dist/executor/pi-executor.js +25 -12
  45. package/node_modules/@comis/agent/dist/executor/prompt-assembly.d.ts +9 -1
  46. package/node_modules/@comis/agent/dist/executor/prompt-assembly.js +15 -1
  47. package/node_modules/@comis/agent/dist/executor/tool-deferral.d.ts +18 -27
  48. package/node_modules/@comis/agent/dist/executor/tool-deferral.js +29 -38
  49. package/node_modules/@comis/agent/dist/model/model-registry-adapter.js +1 -1
  50. package/node_modules/@comis/agent/dist/model/model-scanner.js +1 -1
  51. package/node_modules/@comis/agent/dist/safety/tool-retry-breaker.d.ts +11 -1
  52. package/node_modules/@comis/agent/dist/safety/tool-retry-breaker.js +19 -22
  53. package/node_modules/@comis/agent/dist/session/comis-session-manager.d.ts +16 -2
  54. package/node_modules/@comis/agent/dist/spawn/pi-mono-adapters.d.ts +1 -1
  55. package/node_modules/@comis/agent/dist/spawn/pi-mono-adapters.js +5 -5
  56. package/node_modules/@comis/agent/dist/workspace/data-env.d.ts +38 -0
  57. package/node_modules/@comis/agent/dist/workspace/data-env.js +56 -0
  58. package/node_modules/@comis/agent/dist/workspace/index.d.ts +1 -0
  59. package/node_modules/@comis/agent/dist/workspace/index.js +1 -0
  60. package/node_modules/@comis/agent/dist/workspace/templates.js +5 -1
  61. package/node_modules/@comis/agent/package.json +1 -1
  62. package/node_modules/@comis/channels/dist/index.d.ts +1 -1
  63. package/node_modules/@comis/channels/dist/index.js +1 -1
  64. package/node_modules/@comis/channels/dist/shared/channel-manager.d.ts +9 -3
  65. package/node_modules/@comis/channels/dist/shared/inbound-gate.d.ts +1 -1
  66. package/node_modules/@comis/channels/dist/shared/inbound-gate.js +22 -7
  67. package/node_modules/@comis/channels/dist/shared/inbound-pipeline.d.ts +10 -3
  68. package/node_modules/@comis/channels/dist/shared/inbound-route.d.ts +1 -1
  69. package/node_modules/@comis/channels/dist/shared/inbound-route.js +13 -2
  70. package/node_modules/@comis/channels/dist/shared/response-filter.d.ts +11 -24
  71. package/node_modules/@comis/channels/dist/shared/response-filter.js +25 -53
  72. package/node_modules/@comis/channels/package.json +1 -1
  73. package/node_modules/@comis/cli/dist/commands/providers.d.ts +1 -2
  74. package/node_modules/@comis/cli/dist/commands/providers.js +5 -6
  75. package/node_modules/@comis/cli/package.json +1 -1
  76. package/node_modules/@comis/core/dist/config/field-metadata.js +2 -0
  77. package/node_modules/@comis/core/dist/config/immutable-keys.js +4 -1
  78. package/node_modules/@comis/core/dist/config/index.d.ts +4 -0
  79. package/node_modules/@comis/core/dist/config/index.js +2 -0
  80. package/node_modules/@comis/core/dist/config/schema-agent.d.ts +0 -792
  81. package/node_modules/@comis/core/dist/config/schema-approvals.d.ts +0 -14
  82. package/node_modules/@comis/core/dist/config/schema-auto-reply-engine.d.ts +0 -6
  83. package/node_modules/@comis/core/dist/config/schema-background-tasks.d.ts +0 -12
  84. package/node_modules/@comis/core/dist/config/schema-browser.d.ts +0 -18
  85. package/node_modules/@comis/core/dist/config/schema-channel.d.ts +0 -158
  86. package/node_modules/@comis/core/dist/config/schema-coalescer.d.ts +0 -5
  87. package/node_modules/@comis/core/dist/config/schema-daemon.d.ts +0 -32
  88. package/node_modules/@comis/core/dist/config/schema-delivery.d.ts +0 -18
  89. package/node_modules/@comis/core/dist/config/schema-documentation.d.ts +0 -12
  90. package/node_modules/@comis/core/dist/config/schema-embedding.d.ts +0 -20
  91. package/node_modules/@comis/core/dist/config/schema-envelope.d.ts +0 -15
  92. package/node_modules/@comis/core/dist/config/schema-gateway.d.ts +0 -37
  93. package/node_modules/@comis/core/dist/config/schema-gemini-cache.d.ts +0 -2
  94. package/node_modules/@comis/core/dist/config/schema-integrations.d.ts +0 -318
  95. package/node_modules/@comis/core/dist/config/schema-lifecycle-reactions.d.ts +0 -18
  96. package/node_modules/@comis/core/dist/config/schema-memory-review.d.ts +0 -7
  97. package/node_modules/@comis/core/dist/config/schema-memory.d.ts +0 -16
  98. package/node_modules/@comis/core/dist/config/schema-messages.d.ts +0 -8
  99. package/node_modules/@comis/core/dist/config/schema-models.d.ts +0 -15
  100. package/node_modules/@comis/core/dist/config/schema-notification.d.ts +0 -5
  101. package/node_modules/@comis/core/dist/config/schema-oauth.d.ts +0 -5
  102. package/node_modules/@comis/core/dist/config/schema-observability.d.ts +0 -38
  103. package/node_modules/@comis/core/dist/config/schema-output-retention.d.ts +34 -0
  104. package/node_modules/@comis/core/dist/config/schema-output-retention.js +48 -0
  105. package/node_modules/@comis/core/dist/config/schema-plugins.d.ts +0 -8
  106. package/node_modules/@comis/core/dist/config/schema-providers.d.ts +0 -64
  107. package/node_modules/@comis/core/dist/config/schema-queue.d.ts +0 -58
  108. package/node_modules/@comis/core/dist/config/schema-response-prefix.d.ts +0 -2
  109. package/node_modules/@comis/core/dist/config/schema-retry.d.ts +0 -6
  110. package/node_modules/@comis/core/dist/config/schema-scheduler.d.ts +0 -39
  111. package/node_modules/@comis/core/dist/config/schema-secrets.d.ts +0 -3
  112. package/node_modules/@comis/core/dist/config/schema-security.d.ts +0 -18
  113. package/node_modules/@comis/core/dist/config/schema-send-policy.d.ts +0 -13
  114. package/node_modules/@comis/core/dist/config/schema-sender-trust-display.d.ts +0 -5
  115. package/node_modules/@comis/core/dist/config/schema-serializer.js +2 -0
  116. package/node_modules/@comis/core/dist/config/schema-skills.d.ts +0 -61
  117. package/node_modules/@comis/core/dist/config/schema-streaming.d.ts +0 -38
  118. package/node_modules/@comis/core/dist/config/schema-telegram-file-guard.d.ts +0 -3
  119. package/node_modules/@comis/core/dist/config/schema-tooling.d.ts +87 -0
  120. package/node_modules/@comis/core/dist/config/schema-tooling.js +152 -0
  121. package/node_modules/@comis/core/dist/config/schema-verbosity.d.ts +0 -12
  122. package/node_modules/@comis/core/dist/config/schema-webhooks.d.ts +0 -40
  123. package/node_modules/@comis/core/dist/config/schema.d.ts +41 -38
  124. package/node_modules/@comis/core/dist/config/schema.js +6 -0
  125. package/node_modules/@comis/core/dist/context/context.d.ts +0 -4
  126. package/node_modules/@comis/core/dist/domain/approval-request.d.ts +0 -17
  127. package/node_modules/@comis/core/dist/domain/background-task-origin.d.ts +0 -10
  128. package/node_modules/@comis/core/dist/domain/delivery-origin.d.ts +0 -5
  129. package/node_modules/@comis/core/dist/domain/execution-graph.d.ts +0 -48
  130. package/node_modules/@comis/core/dist/domain/memory-entry.d.ts +0 -3
  131. package/node_modules/@comis/core/dist/domain/model-compat.d.ts +0 -4
  132. package/node_modules/@comis/core/dist/domain/normalized-message.d.ts +0 -15
  133. package/node_modules/@comis/core/dist/domain/provider-capabilities.d.ts +0 -6
  134. package/node_modules/@comis/core/dist/domain/rich-message.d.ts +0 -14
  135. package/node_modules/@comis/core/dist/domain/subagent-context-config.d.ts +0 -22
  136. package/node_modules/@comis/core/dist/domain/subagent-context-types.d.ts +0 -8
  137. package/node_modules/@comis/core/dist/event-bus/events-agent.d.ts +31 -0
  138. package/node_modules/@comis/core/dist/event-bus/events-infra.d.ts +5 -0
  139. package/node_modules/@comis/core/dist/exports/config.d.ts +2 -2
  140. package/node_modules/@comis/core/dist/exports/config.js +3 -1
  141. package/node_modules/@comis/core/dist/exports/hooks.d.ts +1 -1
  142. package/node_modules/@comis/core/dist/exports/ports.d.ts +2 -2
  143. package/node_modules/@comis/core/dist/exports/ports.js +1 -1
  144. package/node_modules/@comis/core/dist/ports/channel-plugin.d.ts +0 -13
  145. package/node_modules/@comis/core/dist/ports/index.d.ts +2 -0
  146. package/node_modules/@comis/core/dist/ports/index.js +4 -0
  147. package/node_modules/@comis/core/dist/ports/no-op-tool-capability.d.ts +30 -0
  148. package/node_modules/@comis/core/dist/ports/no-op-tool-capability.js +47 -0
  149. package/node_modules/@comis/core/dist/ports/tool-capability.d.ts +165 -0
  150. package/node_modules/@comis/core/dist/ports/tool-capability.js +15 -0
  151. package/node_modules/@comis/core/dist/security/audit.d.ts +0 -11
  152. package/node_modules/@comis/core/dist/tool-metadata.d.ts +21 -1
  153. package/node_modules/@comis/core/dist/tool-metadata.js +1 -1
  154. package/node_modules/@comis/core/package.json +1 -1
  155. package/node_modules/@comis/daemon/bundled-skills/skill-creator/scripts/validate-skill.py +1 -1
  156. package/node_modules/@comis/daemon/dist/daemon.js +89 -14
  157. package/node_modules/@comis/daemon/dist/rpc/agent-inline-workspace.d.ts +1 -1
  158. package/node_modules/@comis/daemon/dist/rpc/agent-inline-workspace.js +1 -1
  159. package/node_modules/@comis/daemon/dist/rpc/builtin-provider-guard.js +2 -2
  160. package/node_modules/@comis/daemon/dist/rpc/credential-resolver.js +1 -1
  161. package/node_modules/@comis/daemon/dist/rpc/model-handlers.d.ts +1 -1
  162. package/node_modules/@comis/daemon/dist/rpc/model-handlers.js +2 -2
  163. package/node_modules/@comis/daemon/dist/sub-agent-runner.d.ts +18 -0
  164. package/node_modules/@comis/daemon/dist/sub-agent-runner.js +41 -9
  165. package/node_modules/@comis/daemon/dist/wiring/index.d.ts +2 -0
  166. package/node_modules/@comis/daemon/dist/wiring/index.js +1 -0
  167. package/node_modules/@comis/daemon/dist/wiring/setup-agents.d.ts +36 -2
  168. package/node_modules/@comis/daemon/dist/wiring/setup-agents.js +45 -8
  169. package/node_modules/@comis/daemon/dist/wiring/setup-background-completion-runner.d.ts +28 -9
  170. package/node_modules/@comis/daemon/dist/wiring/setup-background-completion-runner.js +36 -9
  171. package/node_modules/@comis/daemon/dist/wiring/setup-background-tasks.js +2 -2
  172. package/node_modules/@comis/daemon/dist/wiring/setup-channels.d.ts +9 -2
  173. package/node_modules/@comis/daemon/dist/wiring/setup-channels.js +15 -9
  174. package/node_modules/@comis/daemon/dist/wiring/setup-cross-session.d.ts +20 -5
  175. package/node_modules/@comis/daemon/dist/wiring/setup-cross-session.js +20 -15
  176. package/node_modules/@comis/daemon/dist/wiring/setup-delivery.js +14 -2
  177. package/node_modules/@comis/daemon/dist/wiring/setup-gateway.d.ts +4 -6
  178. package/node_modules/@comis/daemon/dist/wiring/setup-gateway.js +3 -5
  179. package/node_modules/@comis/daemon/dist/wiring/setup-heartbeat.d.ts +20 -5
  180. package/node_modules/@comis/daemon/dist/wiring/setup-heartbeat.js +11 -2
  181. package/node_modules/@comis/daemon/dist/wiring/setup-output-retention.d.ts +89 -0
  182. package/node_modules/@comis/daemon/dist/wiring/setup-output-retention.js +212 -0
  183. package/node_modules/@comis/daemon/dist/wiring/setup-tools.d.ts +18 -4
  184. package/node_modules/@comis/daemon/dist/wiring/setup-tools.js +29 -10
  185. package/node_modules/@comis/daemon/dist/wiring/tool-capability-adapter.d.ts +75 -0
  186. package/node_modules/@comis/daemon/dist/wiring/tool-capability-adapter.js +253 -0
  187. package/node_modules/@comis/daemon/package.json +1 -1
  188. package/node_modules/@comis/gateway/dist/webhook/webhook-endpoint.d.ts +0 -4
  189. package/node_modules/@comis/gateway/package.json +1 -1
  190. package/node_modules/@comis/infra/package.json +1 -1
  191. package/node_modules/@comis/memory/package.json +1 -1
  192. package/node_modules/@comis/scheduler/dist/cron/cron-types.d.ts +0 -42
  193. package/node_modules/@comis/scheduler/dist/heartbeat/agent-heartbeat-source.d.ts +29 -8
  194. package/node_modules/@comis/scheduler/dist/heartbeat/agent-heartbeat-source.js +19 -7
  195. package/node_modules/@comis/scheduler/dist/system-events/system-event-types.d.ts +0 -3
  196. package/node_modules/@comis/scheduler/dist/tasks/task-types.d.ts +0 -17
  197. package/node_modules/@comis/scheduler/package.json +1 -1
  198. package/node_modules/@comis/shared/dist/index.d.ts +3 -0
  199. package/node_modules/@comis/shared/dist/index.js +4 -0
  200. package/node_modules/@comis/shared/dist/mcp-tool-name.d.ts +78 -0
  201. package/node_modules/@comis/shared/dist/mcp-tool-name.js +92 -0
  202. package/node_modules/@comis/shared/dist/silent-tokens.d.ts +38 -0
  203. package/node_modules/@comis/shared/dist/silent-tokens.js +51 -0
  204. package/node_modules/@comis/shared/dist/visible-delivery.d.ts +28 -0
  205. package/node_modules/@comis/shared/dist/visible-delivery.js +16 -0
  206. package/node_modules/@comis/shared/package.json +1 -1
  207. package/node_modules/@comis/skills/dist/bridge/mcp-tool-bridge.d.ts +2 -13
  208. package/node_modules/@comis/skills/dist/bridge/mcp-tool-bridge.js +3 -21
  209. package/node_modules/@comis/skills/dist/bridge/tool-metadata-enforcement.js +1 -1
  210. package/node_modules/@comis/skills/dist/bridge/tool-metadata-registry.js +4 -4
  211. package/node_modules/@comis/skills/dist/builtin/exec-tool.d.ts +55 -9
  212. package/node_modules/@comis/skills/dist/builtin/exec-tool.js +383 -19
  213. package/node_modules/@comis/skills/dist/builtin/install-detour.d.ts +67 -0
  214. package/node_modules/@comis/skills/dist/builtin/install-detour.js +342 -0
  215. package/node_modules/@comis/skills/dist/builtin/platform/admin-manage-factory.js +5 -5
  216. package/node_modules/@comis/skills/dist/builtin/platform/agents-manage-tool.d.ts +2 -2
  217. package/node_modules/@comis/skills/dist/builtin/platform/agents-manage-tool.js +2 -2
  218. package/node_modules/@comis/skills/dist/builtin/platform/message-tool.js +18 -0
  219. package/node_modules/@comis/skills/dist/builtin/platform/messaging-factory.d.ts +18 -1
  220. package/node_modules/@comis/skills/dist/builtin/platform/messaging-factory.js +18 -2
  221. package/node_modules/@comis/skills/dist/builtin/platform/models-manage-tool.js +3 -3
  222. package/node_modules/@comis/skills/dist/builtin/process-registry.d.ts +14 -0
  223. package/node_modules/@comis/skills/dist/builtin/process-tool.d.ts +24 -4
  224. package/node_modules/@comis/skills/dist/builtin/process-tool.js +25 -7
  225. package/node_modules/@comis/skills/dist/builtin/sandbox/bwrap-provider.d.ts +1 -1
  226. package/node_modules/@comis/skills/dist/builtin/sandbox/bwrap-provider.js +9 -0
  227. package/node_modules/@comis/skills/dist/index.d.ts +4 -1
  228. package/node_modules/@comis/skills/dist/index.js +3 -1
  229. package/node_modules/@comis/skills/dist/manifest/capability-parser.d.ts +44 -0
  230. package/node_modules/@comis/skills/dist/manifest/capability-parser.js +68 -0
  231. package/node_modules/@comis/skills/dist/manifest/schema.d.ts +44 -37
  232. package/node_modules/@comis/skills/dist/manifest/schema.js +35 -0
  233. package/node_modules/@comis/skills/dist/registry/discovery.d.ts +8 -0
  234. package/node_modules/@comis/skills/dist/registry/discovery.js +10 -3
  235. package/node_modules/@comis/skills/dist/registry/skill-registry.d.ts +45 -1
  236. package/node_modules/@comis/skills/dist/registry/skill-registry.js +70 -7
  237. package/node_modules/@comis/skills/package.json +1 -1
  238. package/node_modules/@comis/web/package.json +1 -1
  239. package/package.json +21 -21
@@ -1,10 +1,10 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  /**
3
3
  * Cross-session messaging setup: cross-session sender and sub-agent runner.
4
- * Extracted from daemon.ts step 6.6.9 to isolate cross-session service
5
- * creation from the main wiring sequence. The three callback closures
6
- * (executeInSession, sendToChannel, executeSubAgent) are built internally
7
- * from injected dependencies (assembleToolsForAgent, getExecutor, adaptersByType).
4
+ * Isolates cross-session service creation from the main wiring sequence.
5
+ * The three callback closures (executeInSession, sendToChannel,
6
+ * executeSubAgent) are built internally from injected dependencies
7
+ * (assembleToolsForAgent, getExecutor, adaptersByType).
8
8
  * @module
9
9
  */
10
10
  import { tryGetContext, runWithContext, formatSessionKey, safePath } from "@comis/core";
@@ -15,7 +15,6 @@ import { createSubAgentRunner } from "../sub-agent-runner.js";
15
15
  import { createAnnouncementBatcher } from "../announcement-batcher.js";
16
16
  import { createAnnouncementDeadLetterQueue } from "../announcement-dead-letter.js";
17
17
  import { randomUUID } from "node:crypto";
18
- import { resolve } from "node:path";
19
18
  // ---------------------------------------------------------------------------
20
19
  // Depth-aware graph cache retention
21
20
  // ---------------------------------------------------------------------------
@@ -348,7 +347,7 @@ export function setupCrossSession(deps) {
348
347
  deps.logger?.warn({
349
348
  err,
350
349
  hint: "Parent summary generation failed; proceeding without summary",
351
- errorKind: "upstream",
350
+ errorKind: "dependency",
352
351
  }, "generateParentSummary failed for parent context");
353
352
  }
354
353
  }
@@ -426,13 +425,13 @@ export function setupCrossSession(deps) {
426
425
  const GRAPH_PROMPT_TIMEOUT_MS = 600_000;
427
426
  // Base subagent retention is "short" (5m TTL).
428
427
  // Graph sub-agents with graphSharedDir get depth-aware retention:
429
- // - Root nodes (depth=0): "short" -- complete in <3min, consumed by Wave 2 within 3-4min
430
- // - Downstream nodes (depth >= 1): "long" -- may be consumed by further waves
428
+ // - Root nodes (depth=0): "short" -- complete fast, consumed by downstream nodes within 5m
429
+ // - Downstream nodes (depth >= 1): "long" -- may be consumed by further descendants
431
430
  // Non-graph sub-agents always get "short".
432
431
  const subAgentCacheRetention = graphSharedDir
433
432
  ? resolveGraphCacheRetention(graphNodeDepth, isLeafNode)
434
433
  : "short";
435
- // R-11: Session adapter for sub-agents.
434
+ // Session adapter for sub-agents.
436
435
  // When subAgentSessionPersistence is true, sub-agents get disk-backed JSONL sessions
437
436
  // for debugging/auditing. Default (false): ephemeral in-memory, garbage-collected.
438
437
  const subAgentPersistence = container.config.security?.agentToAgent?.subAgentSessionPersistence ?? false;
@@ -472,8 +471,8 @@ export function setupCrossSession(deps) {
472
471
  // Reuse sessions need their own cache entries (skipCacheWrite will be false
473
472
  // because spawnPacket is undefined). Force "long" retention for multi-round persistence.
474
473
  // Graph sub-agents use depth-aware retention:
475
- // Root nodes (depth=0): "short" -- complete fast, consumed within 5m by Wave 2.
476
- // Downstream nodes (depth>=1): "long" -- may be consumed by later waves beyond 5m.
474
+ // Root nodes (depth=0): "short" -- complete fast, consumed within 5m by downstream nodes.
475
+ // Downstream nodes (depth>=1): "long" -- may be consumed beyond 5m.
477
476
  // Model resolution's cacheRetention must NOT override graph-aware default.
478
477
  cacheRetention: isReuseSession
479
478
  ? "long"
@@ -508,7 +507,7 @@ export function setupCrossSession(deps) {
508
507
  toolCallHistory: result.toolCallHistory,
509
508
  };
510
509
  };
511
- // 6.6.9a. Cross-session sender — fire-and-forget, wait, or ping-pong messaging
510
+ // Cross-session sender — fire-and-forget, wait, or ping-pong messaging
512
511
  const crossSessionSender = createCrossSessionSender({
513
512
  sessionStore: {
514
513
  loadByFormattedKey: (key) => sessionStore.loadByFormattedKey(key),
@@ -572,8 +571,13 @@ export function setupCrossSession(deps) {
572
571
  }
573
572
  };
574
573
  // Create dead-letter queue for failed announcement persistence (before batcher, so batcher can reference it)
575
- const dlqBaseDir = resolve(container.config.dataDir || ".");
576
- const deadLetterFilePath = safePath(dlqBaseDir, "dead-letters.jsonl");
574
+ // Direct safePath composition. AGENTS §2.2: all paths via safePath. safePath
575
+ // requires an absolute base (see PathTraversalError contract in
576
+ // packages/core/src/security/safe-path.ts), so when container.config.dataDir
577
+ // is unset we fall back to process.cwd(). process.cwd() is not banned by
578
+ // AGENTS §2.2 (only process.env and node:path's path.join/path.resolve are
579
+ // restricted).
580
+ const deadLetterFilePath = safePath(container.config.dataDir || process.cwd(), "dead-letters.jsonl");
577
581
  const deadLetterQueue = createAnnouncementDeadLetterQueue({
578
582
  filePath: deadLetterFilePath,
579
583
  maxRetries: 5,
@@ -628,7 +632,7 @@ export function setupCrossSession(deps) {
628
632
  : { info: () => { }, warn: () => { }, debug: () => { } },
629
633
  eventBus: container.eventBus,
630
634
  });
631
- // 6.6.9b. Sub-agent runner — async sub-agent spawning with allowlist + auto-archive
635
+ // Sub-agent runner — async sub-agent spawning with allowlist + auto-archive
632
636
  const subAgentRunner = createSubAgentRunner({
633
637
  sessionStore: {
634
638
  save: (key, messages, metadata) => sessionStore.save(key, messages, metadata),
@@ -645,6 +649,7 @@ export function setupCrossSession(deps) {
645
649
  memoryAdapter: deps.memoryAdapter,
646
650
  batcher: announcementBatcher,
647
651
  activeRunRegistry: deps.activeRunRegistry,
652
+ sessionResolver: deps.sessionResolver,
648
653
  resultCondenser,
649
654
  condenserModel: condenserApiKey ? { id: condensationResolution.modelId, provider: condensationResolution.provider } : undefined,
650
655
  condenserApiKey: condenserApiKey || undefined,
@@ -78,11 +78,23 @@ export async function setupDeliveryQueue(deps) {
78
78
  suppressError(draining, "delivery queue recurring drain tick");
79
79
  }, queueConfig.drainIntervalMs);
80
80
  drainInterval.unref();
81
- // --- Step 4: Prune timer (existing behavior, unchanged). ---
81
+ // --- Step 4: Prune timer. ---
82
+ // Emit a per-class drain log line with structured fields
83
+ // (`pruned`, `class`, `durationMs`) so operators can correlate prune
84
+ // activity by retention class across subsystems (delivery_queue,
85
+ // delivery_mirror, output retention housekeeper, etc.). The `class`
86
+ // field is a placeholder until the underlying pruneExpired() is
87
+ // extended with per-class breakdown. Canonical Pino object-first;
88
+ // durationMs is the canonical name (CLAUDE.md logging conventions).
82
89
  pruneInterval = setInterval(async () => {
90
+ const startMs = Date.now();
83
91
  const result = await deliveryQueue.pruneExpired();
84
92
  if (result.ok && result.value > 0) {
85
- logger.debug({ pruned: result.value }, "Delivery queue pruned");
93
+ logger.debug({
94
+ pruned: result.value,
95
+ class: "delivery_queue",
96
+ durationMs: Date.now() - startMs,
97
+ }, "Delivery queue pruned");
86
98
  }
87
99
  }, queueConfig.pruneIntervalMs);
88
100
  pruneInterval.unref();
@@ -1,10 +1,8 @@
1
1
  /**
2
2
  * Gateway setup: RPC bridge (deferred dispatch), RPC adapter wiring, dynamic
3
3
  * method registration, webhook mounting, OpenAI-compatible route mounting,
4
- * and gateway server creation/start.
5
- * Extracted from daemon.ts to isolate the single
6
- * largest inline block from the main wiring sequence. Covers the full
7
- * gateway lifecycle from RPC bridge creation through server start.
4
+ * and gateway server creation/start. Covers the full gateway lifecycle from
5
+ * RPC bridge creation through server start.
8
6
  * @module
9
7
  */
10
8
  import type { SessionKey, AppContainer, AppConfig } from "@comis/core";
@@ -36,7 +34,7 @@ export declare function buildExecutionRequestedLogFields(input: {
36
34
  messageHash?: string;
37
35
  connectionId?: string;
38
36
  };
39
- /** All services produced by the RPC bridge setup phase. */
37
+ /** All services produced by the RPC bridge setup. */
40
38
  export interface RpcBridgeResult {
41
39
  /** The rpcCall function usable immediately (delegates to inner dispatch once wired). */
42
40
  rpcCall: RpcCall;
@@ -145,7 +143,7 @@ export interface GatewayDeps {
145
143
  /** Set of suspended agent IDs for REST API status reporting. */
146
144
  suspendedAgents?: ReadonlySet<string>;
147
145
  }
148
- /** All services produced by the gateway setup phase. */
146
+ /** All services produced by the gateway setup. */
149
147
  export interface GatewayResult {
150
148
  /** Gateway server handle (undefined when gateway is disabled). */
151
149
  gatewayHandle?: GatewayServerHandle;
@@ -2,10 +2,8 @@
2
2
  /**
3
3
  * Gateway setup: RPC bridge (deferred dispatch), RPC adapter wiring, dynamic
4
4
  * method registration, webhook mounting, OpenAI-compatible route mounting,
5
- * and gateway server creation/start.
6
- * Extracted from daemon.ts to isolate the single
7
- * largest inline block from the main wiring sequence. Covers the full
8
- * gateway lifecycle from RPC bridge creation through server start.
5
+ * and gateway server creation/start. Covers the full gateway lifecycle from
6
+ * RPC bridge creation through server start.
9
7
  * @module
10
8
  */
11
9
  import { registerRpcMethods } from "./setup-gateway-rpc.js";
@@ -417,7 +415,7 @@ export async function setupGateway(deps) {
417
415
  catch {
418
416
  // Session history bridging is non-fatal
419
417
  }
420
- // Token usage now captured by tokenTracker's bus subscription (quick-138):
418
+ // Token usage captured by tokenTracker's bus subscription:
421
419
  // PiEventBridge emits observability:token_usage at turn_end -> tokenTracker
422
420
  // bus handler stores it. No direct record() call needed here.
423
421
  // Conversation memory persistence now handled by PiExecutor
@@ -9,9 +9,19 @@
9
9
  import type { AppContainer, ChannelPort } from "@comis/core";
10
10
  import type { ComisLogger } from "@comis/infra";
11
11
  import { type PerAgentHeartbeatRunner, type DuplicateDetector, type SystemEventQueue } from "@comis/scheduler";
12
- /** Minimal ActiveRunRegistry -- only needs has() for queue-busy check. */
13
- interface HeartbeatActiveRunRegistry {
14
- has(sessionKey: string): boolean;
12
+ /**
13
+ * Minimal BackgroundSessionResolver shape -- only needs hasActiveSession()
14
+ * for the queue-busy check. Locally re-declared to avoid the
15
+ * cycle from importing @comis/agent here; the daemon constructs the
16
+ * resolver as `createBackgroundSessionResolver({activeRunRegistry})` and
17
+ * the resulting object is structurally assignable to this shape.
18
+ */
19
+ interface HeartbeatSessionResolver {
20
+ hasActiveSession(key: {
21
+ agentId: string;
22
+ channelType: string;
23
+ channelId: string;
24
+ }): boolean;
15
25
  }
16
26
  /** 8-param executor interface matching AgentExecutor.execute (used in deps map). */
17
27
  interface InnerExecutor {
@@ -29,8 +39,13 @@ export interface HeartbeatSetupDeps {
29
39
  assembleToolsForAgent: (agentId: string) => Promise<unknown[]>;
30
40
  /** Per-agent workspace directories. */
31
41
  workspaceDirs: Map<string, string>;
32
- /** Active run registry for queue-busy detection (optional). */
33
- activeRunRegistry?: HeartbeatActiveRunRegistry;
42
+ /**
43
+ * Composite-key resolver for queue-busy detection (optional).
44
+ * The daemon wires this via `createBackgroundSessionResolver`; it
45
+ * supersedes the previous `.has(sessionKey)` lookup so multi-agent /
46
+ * multi-channel collisions are distinguishable.
47
+ */
48
+ sessionResolver?: HeartbeatSessionResolver;
34
49
  /** Duplicate detector shared between global and per-agent heartbeat delivery. */
35
50
  duplicateDetector?: DuplicateDetector;
36
51
  /** Channel adapters for heartbeat delivery (optional). */
@@ -23,7 +23,7 @@ import { applyToolPolicy } from "@comis/skills";
23
23
  * @param deps - Per-agent heartbeat dependencies
24
24
  */
25
25
  export function setupHeartbeat(deps) {
26
- const { container, executors, assembleToolsForAgent, workspaceDirs, activeRunRegistry, duplicateDetector, adaptersByType, systemEventQueue, memoryApi, schedulerLogger, } = deps;
26
+ const { container, executors, assembleToolsForAgent, workspaceDirs, sessionResolver, duplicateDetector, adaptersByType, systemEventQueue, memoryApi, schedulerLogger, } = deps;
27
27
  const agents = container.config.agents;
28
28
  const globalHeartbeat = container.config.scheduler.heartbeat;
29
29
  // 1. Build per-agent state map (only heartbeat-enabled agents)
@@ -76,7 +76,16 @@ export function setupHeartbeat(deps) {
76
76
  // 4. Build AgentHeartbeatSource dependencies
77
77
  const source = createAgentHeartbeatSource({
78
78
  getExecutor: (agentId) => {
79
+ // Explicit boundary throw replaces a non-null-assertion lookup. The
80
+ // assertion was unsafe — if executor wiring missed an agent that's
81
+ // still in the heartbeat config, `inner.execute(...)` would surface
82
+ // as a runtime TypeError inside a timer callback (uncaught). The
83
+ // explicit Error gives operators a clean stack at the wiring
84
+ // boundary instead.
79
85
  const inner = executors.get(agentId);
86
+ if (!inner) {
87
+ throw new Error(`No executor found for heartbeat agent ${agentId}`);
88
+ }
80
89
  return {
81
90
  execute: (msg, sessionKey, tools, hbAgentId, overrides) => inner.execute(msg, sessionKey, tools, undefined, hbAgentId, undefined, undefined, overrides),
82
91
  };
@@ -96,7 +105,7 @@ export function setupHeartbeat(deps) {
96
105
  eventBus: container.eventBus,
97
106
  logger: schedulerLogger,
98
107
  },
99
- activeRunRegistry,
108
+ sessionResolver,
100
109
  getMemoryStats,
101
110
  // Inject applyToolPolicy so scheduler can filter without taking a direct
102
111
  // dependency on @comis/skills. Type-erased `unknown[]` at the boundary is
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Output retention housekeeper: scans the agent's output/ directory,
3
+ * deletes files whose age exceeds the per-class retentionMs.
4
+ *
5
+ * Mirrors setup-delivery.ts drain+prune timer pattern (single-tick gate +
6
+ * unref() + structured DEBUG log per pass).
7
+ *
8
+ * Consumes JSONL details.visibleDelivery for offline analysis (the
9
+ * housekeeper does NOT delete JSONL itself; it only manages output/
10
+ * files referenced by it).
11
+ *
12
+ * Per AGENTS §2.2: NO `path.join`, NO `process.env`. All paths via
13
+ * `safePath(workspaceDir, ...)`. Per AGENTS §2.4: factory + Deps with
14
+ * ComisLogger injected. Per AGENTS §2.1: error paths log WARN/DEBUG with
15
+ * hint+errorKind; never throws. Per AGENTS §2.3 KISS: in-place file
16
+ * deletion. No "trash dir", no "soft delete". Per AGENTS §6.6
17
+ * (security/daemon): file deletion is destructive — operator can
18
+ * disable via `enabled: false` config.
19
+ *
20
+ * Test contract: `validateOutputRetentionConfig({ classes:
21
+ * [{classId, retentionMs}] })` returns `{ ok, value | error }`.
22
+ *
23
+ * @module setup-output-retention
24
+ */
25
+ import type { OutputRetentionConfig } from "@comis/core";
26
+ import type { ComisLogger } from "@comis/infra";
27
+ import { type Result } from "@comis/shared";
28
+ export interface SetupOutputRetentionDeps {
29
+ /**
30
+ * Validated config (from AppConfig.outputRetention). May be undefined
31
+ * in legacy test mocks where AppConfig is hand-constructed via
32
+ * `as unknown as`; the factory degrades to no-op in that case (mirrors
33
+ * `setupDeliveryMirror`'s `if (!mirrorConfig?.enabled)` pattern).
34
+ */
35
+ config: OutputRetentionConfig | undefined;
36
+ /** Absolute path to the workspace dir. The housekeeper scans `<workspaceDir>/output/`. */
37
+ workspaceDir: string;
38
+ /** Injected logger (per AGENTS §2.4 — never import @comis/infra at runtime). */
39
+ logger: ComisLogger;
40
+ }
41
+ export interface SetupOutputRetentionHandle {
42
+ /** Stop the recurring housekeeper interval. Idempotent. */
43
+ shutdown(): void;
44
+ /** Manual trigger for tests; runs one full pass synchronously. */
45
+ runOnePass(): Promise<{
46
+ deleted: number;
47
+ bytesFreed: number;
48
+ }>;
49
+ }
50
+ /**
51
+ * Legacy array-of-objects shape preserved as the input to
52
+ * `validateOutputRetentionConfig`. The housekeeper itself uses the
53
+ * schema-derived `OutputRetentionConfig` (Record-of-classes shape); this
54
+ * validator acts as the test's binding gate that retentionMs <= 0 is
55
+ * rejected.
56
+ */
57
+ export interface RetentionClassConfigInput {
58
+ classId: string;
59
+ retentionMs: number;
60
+ }
61
+ export interface ValidatedRetentionConfig {
62
+ classes: RetentionClassConfigInput[];
63
+ }
64
+ /**
65
+ * Validate an output-retention config supplied as the legacy
66
+ * `{ classes: [{classId, retentionMs}] }` shape. Returns a Result-shaped
67
+ * `{ ok: true, value }` on success, `{ ok: false, error }` on failure.
68
+ *
69
+ * Validator contract:
70
+ * - retentionMs = -1 → rejected
71
+ * - retentionMs = 0 → rejected
72
+ * - retentionMs = 1 → accepted
73
+ *
74
+ * Production wiring uses the Zod schema in
75
+ * @comis/core/config/schema-output-retention.ts directly; this
76
+ * validator is a thin compatibility surface for the test contract.
77
+ */
78
+ export declare function validateOutputRetentionConfig(config: unknown): Result<ValidatedRetentionConfig, Error>;
79
+ /**
80
+ * Wire the per-class output-retention housekeeper.
81
+ *
82
+ * Mirrors setup-delivery.ts (drain + prune timer): single-tick gate, .unref(),
83
+ * structured per-pass log. The factory starts the recurring interval
84
+ * immediately on construction; call shutdown() on system:shutdown.
85
+ *
86
+ * Returns a handle exposing `shutdown()` (idempotent) and `runOnePass()`
87
+ * (manual trigger for tests).
88
+ */
89
+ export declare function setupOutputRetention(deps: SetupOutputRetentionDeps): SetupOutputRetentionHandle;
@@ -0,0 +1,212 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ /**
3
+ * Output retention housekeeper: scans the agent's output/ directory,
4
+ * deletes files whose age exceeds the per-class retentionMs.
5
+ *
6
+ * Mirrors setup-delivery.ts drain+prune timer pattern (single-tick gate +
7
+ * unref() + structured DEBUG log per pass).
8
+ *
9
+ * Consumes JSONL details.visibleDelivery for offline analysis (the
10
+ * housekeeper does NOT delete JSONL itself; it only manages output/
11
+ * files referenced by it).
12
+ *
13
+ * Per AGENTS §2.2: NO `path.join`, NO `process.env`. All paths via
14
+ * `safePath(workspaceDir, ...)`. Per AGENTS §2.4: factory + Deps with
15
+ * ComisLogger injected. Per AGENTS §2.1: error paths log WARN/DEBUG with
16
+ * hint+errorKind; never throws. Per AGENTS §2.3 KISS: in-place file
17
+ * deletion. No "trash dir", no "soft delete". Per AGENTS §6.6
18
+ * (security/daemon): file deletion is destructive — operator can
19
+ * disable via `enabled: false` config.
20
+ *
21
+ * Test contract: `validateOutputRetentionConfig({ classes:
22
+ * [{classId, retentionMs}] })` returns `{ ok, value | error }`.
23
+ *
24
+ * @module setup-output-retention
25
+ */
26
+ import { readdirSync, statSync, unlinkSync } from "node:fs";
27
+ import { safePath } from "@comis/core";
28
+ import { ok, err, suppressError } from "@comis/shared";
29
+ // ---------------------------------------------------------------------------
30
+ // Validator (test contract gate)
31
+ // ---------------------------------------------------------------------------
32
+ /**
33
+ * Validate an output-retention config supplied as the legacy
34
+ * `{ classes: [{classId, retentionMs}] }` shape. Returns a Result-shaped
35
+ * `{ ok: true, value }` on success, `{ ok: false, error }` on failure.
36
+ *
37
+ * Validator contract:
38
+ * - retentionMs = -1 → rejected
39
+ * - retentionMs = 0 → rejected
40
+ * - retentionMs = 1 → accepted
41
+ *
42
+ * Production wiring uses the Zod schema in
43
+ * @comis/core/config/schema-output-retention.ts directly; this
44
+ * validator is a thin compatibility surface for the test contract.
45
+ */
46
+ export function validateOutputRetentionConfig(config) {
47
+ if (typeof config !== "object" || config === null) {
48
+ return err(new Error("output retention config must be an object"));
49
+ }
50
+ const obj = config;
51
+ if (!Array.isArray(obj.classes)) {
52
+ return err(new Error("output retention config: 'classes' must be an array"));
53
+ }
54
+ const out = [];
55
+ for (let i = 0; i < obj.classes.length; i++) {
56
+ const entry = obj.classes[i];
57
+ if (typeof entry !== "object" || entry === null) {
58
+ return err(new Error(`output retention config: classes[${i}] must be an object`));
59
+ }
60
+ const e = entry;
61
+ if (typeof e.classId !== "string" || e.classId.length === 0) {
62
+ return err(new Error(`output retention config: classes[${i}].classId must be a non-empty string`));
63
+ }
64
+ if (typeof e.retentionMs !== "number" ||
65
+ !Number.isInteger(e.retentionMs) ||
66
+ e.retentionMs <= 0) {
67
+ return err(new Error(`output retention config: classes[${i}].retentionMs must be a positive integer (got ${String(e.retentionMs)})`));
68
+ }
69
+ out.push({ classId: e.classId, retentionMs: e.retentionMs });
70
+ }
71
+ return ok({ classes: out });
72
+ }
73
+ // ---------------------------------------------------------------------------
74
+ // Housekeeper factory
75
+ // ---------------------------------------------------------------------------
76
+ /**
77
+ * Wire the per-class output-retention housekeeper.
78
+ *
79
+ * Mirrors setup-delivery.ts (drain + prune timer): single-tick gate, .unref(),
80
+ * structured per-pass log. The factory starts the recurring interval
81
+ * immediately on construction; call shutdown() on system:shutdown.
82
+ *
83
+ * Returns a handle exposing `shutdown()` (idempotent) and `runOnePass()`
84
+ * (manual trigger for tests).
85
+ */
86
+ export function setupOutputRetention(deps) {
87
+ const log = deps.logger.child({ submodule: "output-retention-housekeeper" });
88
+ // Defensive degradation: when config is undefined (legacy test mocks
89
+ // bypassing the AppConfig schema via `as unknown as`), behave as if
90
+ // disabled. Mirrors setupDeliveryMirror's optional-chain pattern.
91
+ // Production paths get a fully-defaulted config from
92
+ // AppConfigSchema.outputRetention, so this branch only triggers in
93
+ // tests with hand-constructed config objects.
94
+ if (!deps.config) {
95
+ log.debug({
96
+ hint: "Output retention config not present; housekeeper inactive (likely a hand-constructed test mock)",
97
+ }, "Output retention: no config");
98
+ return {
99
+ shutdown: () => { },
100
+ runOnePass: async () => ({ deleted: 0, bytesFreed: 0 }),
101
+ };
102
+ }
103
+ const config = deps.config;
104
+ let interval;
105
+ let running = null;
106
+ async function runOnePass() {
107
+ const outputDir = safePath(deps.workspaceDir, "output");
108
+ const now = Date.now();
109
+ let deleted = 0;
110
+ let bytesFreed = 0;
111
+ // Read class subdirectories under output/. Missing dir = nothing to do.
112
+ let classDirs;
113
+ try {
114
+ classDirs = readdirSync(outputDir);
115
+ }
116
+ catch {
117
+ log.debug({ outputDir, hint: "Output dir missing — nothing to retain yet" }, "Output retention: output dir not present");
118
+ return { deleted, bytesFreed };
119
+ }
120
+ for (const className of classDirs) {
121
+ // Resolve class config: explicit class, else fall back to "default".
122
+ const classConfig = config.classes[className] ?? config.classes.default;
123
+ if (!classConfig)
124
+ continue;
125
+ const classDir = safePath(outputDir, className);
126
+ let entries;
127
+ try {
128
+ entries = readdirSync(classDir);
129
+ }
130
+ catch (entryErr) {
131
+ log.debug({
132
+ err: entryErr,
133
+ classDir,
134
+ hint: "Could not read class dir; will retry next pass",
135
+ errorKind: "internal",
136
+ }, "Output retention: class dir read failed");
137
+ continue;
138
+ }
139
+ for (const entry of entries) {
140
+ const filePath = safePath(classDir, entry);
141
+ try {
142
+ const stats = statSync(filePath);
143
+ // Skip subdirectories — only retain leaf files. Per KISS, no
144
+ // recursion: each retention class is a single flat directory.
145
+ if (!stats.isFile())
146
+ continue;
147
+ const ageMs = now - stats.mtimeMs;
148
+ if (ageMs > classConfig.retentionMs) {
149
+ bytesFreed += stats.size;
150
+ unlinkSync(filePath);
151
+ deleted++;
152
+ }
153
+ }
154
+ catch (fileErr) {
155
+ log.debug({
156
+ err: fileErr,
157
+ filePath,
158
+ hint: "Failed to inspect/delete file in housekeeper pass; will retry next pass",
159
+ errorKind: "internal",
160
+ }, "Output retention: file inspect/delete failed");
161
+ }
162
+ }
163
+ }
164
+ if (deleted > 0) {
165
+ log.info({
166
+ deleted,
167
+ bytesFreed,
168
+ class: "output_retention",
169
+ hint: "Per-class output retention completed; files older than configured retentionMs removed",
170
+ }, "Output retention: housekeeper pass completed");
171
+ }
172
+ else {
173
+ log.debug({ class: "output_retention", hint: "No files exceeded retentionMs this pass" }, "Output retention: nothing to delete");
174
+ }
175
+ return { deleted, bytesFreed };
176
+ }
177
+ function startInterval() {
178
+ if (!config.enabled) {
179
+ log.info({ hint: "Output retention disabled by config; not starting housekeeper" }, "Output retention: disabled");
180
+ return;
181
+ }
182
+ interval = setInterval(() => {
183
+ // Single-tick gate: in-flight Promise prevents overlapping ticks.
184
+ if (running)
185
+ return;
186
+ running = runOnePass()
187
+ .then(() => undefined)
188
+ .finally(() => {
189
+ running = null;
190
+ });
191
+ // Fire-and-forget: failures inside runOnePass are already logged
192
+ // and do not propagate (it never throws). suppressError satisfies
193
+ // the no-floating-promise lint without altering semantics.
194
+ suppressError(running, "output retention recurring tick");
195
+ }, config.intervalMs);
196
+ interval.unref();
197
+ log.info({
198
+ intervalMs: config.intervalMs,
199
+ classes: Object.keys(config.classes),
200
+ hint: "Output retention housekeeper started",
201
+ }, "Output retention: started");
202
+ }
203
+ function shutdown() {
204
+ if (interval) {
205
+ clearInterval(interval);
206
+ interval = undefined;
207
+ }
208
+ }
209
+ // Start immediately on construction (mirrors setup-delivery's startup pattern).
210
+ startInterval();
211
+ return { shutdown, runOnePass };
212
+ }
@@ -1,11 +1,10 @@
1
1
  /**
2
2
  * Tool assembly setup: assembleToolsForAgent and preprocessMessageText.
3
- * Extracted from daemon.ts steps 6.6.8.5 (tool pipeline assembly) to isolate
4
- * per-agent tool creation and message preprocessing from the main wiring
5
- * sequence.
3
+ * Isolates per-agent tool creation and message preprocessing from the
4
+ * main wiring sequence.
6
5
  * @module
7
6
  */
8
- import type { AppContainer, ApprovalGate, CredentialMappingPort, WrapExternalContentOptions, SessionKey } from "@comis/core";
7
+ import type { AppContainer, ApprovalGate, CredentialMappingPort, WrapExternalContentOptions, SessionKey, ToolCapabilityPort } from "@comis/core";
9
8
  import type { ComisLogger } from "@comis/infra";
10
9
  import type { SessionTrackerRegistry } from "@comis/agent";
11
10
  import type { PerAgentConfig } from "@comis/core";
@@ -54,6 +53,21 @@ export interface ToolsDeps {
54
53
  * without requiring a daemon restart.
55
54
  */
56
55
  mcpClientManager: McpClientManager;
56
+ /**
57
+ * Per-agent ToolCapabilityPort resolver. Populated by daemon.ts from the
58
+ * AgentsResult.toolCapabilityPorts map (one adapter per agent constructed
59
+ * inside setupSingleAgent). Used by exec / process tools to consult the
60
+ * live install-detour mode + connected MCP servers + visible skills, and
61
+ * to read operator-supplied cluster hints. The closure may throw or fall
62
+ * back to the default agent's port for unknown agentIds -- daemon.ts
63
+ * decides the contract.
64
+ *
65
+ * Consumed via the single mandated form `deps.getCapabilityPortForAgent(agentId)`
66
+ * inside assembleToolsForAgent (mirrors the deps.<field> direct-access
67
+ * convention used for nearby fields like deps.eventBus, deps.skillsLogger,
68
+ * deps.linkRunner, deps.subprocessEnv).
69
+ */
70
+ getCapabilityPortForAgent: (agentId: string) => ToolCapabilityPort;
57
71
  /** Image generation provider (undefined when API key missing -- tool not registered). */
58
72
  imageGenProvider?: ImageGenerationPort;
59
73
  /** OS-level sandbox provider detected once at daemon startup. */