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.
- package/node_modules/@comis/agent/dist/background/auto-background-middleware.js +9 -0
- package/node_modules/@comis/agent/dist/background/background-task-manager.d.ts +22 -2
- package/node_modules/@comis/agent/dist/background/background-task-manager.js +48 -41
- package/node_modules/@comis/agent/dist/background/background-task-persistence.js +28 -5
- package/node_modules/@comis/agent/dist/background/background-task-types.d.ts +49 -0
- package/node_modules/@comis/agent/dist/background/completion-dispatcher.d.ts +130 -0
- package/node_modules/@comis/agent/dist/background/completion-dispatcher.js +215 -0
- package/node_modules/@comis/agent/dist/background/completion-runner.d.ts +10 -1
- package/node_modules/@comis/agent/dist/background/completion-runner.js +98 -15
- package/node_modules/@comis/agent/dist/background/index.d.ts +6 -1
- package/node_modules/@comis/agent/dist/background/index.js +2 -0
- package/node_modules/@comis/agent/dist/background/session-resolver.d.ts +85 -0
- package/node_modules/@comis/agent/dist/background/session-resolver.js +78 -0
- package/node_modules/@comis/agent/dist/bootstrap/sections/messaging-sections.js +1 -0
- package/node_modules/@comis/agent/dist/bootstrap/sections/tool-descriptions.js +3 -3
- package/node_modules/@comis/agent/dist/bootstrap/sections/tooling-sections.d.ts +30 -2
- package/node_modules/@comis/agent/dist/bootstrap/sections/tooling-sections.js +51 -2
- package/node_modules/@comis/agent/dist/bootstrap/system-prompt-assembler.d.ts +22 -0
- package/node_modules/@comis/agent/dist/bootstrap/system-prompt-assembler.js +2 -2
- package/node_modules/@comis/agent/dist/bridge/bridge-event-handlers.d.ts +1 -5
- package/node_modules/@comis/agent/dist/bridge/bridge-event-handlers.js +2 -14
- package/node_modules/@comis/agent/dist/bridge/bridge-metrics.d.ts +26 -0
- package/node_modules/@comis/agent/dist/bridge/bridge-metrics.js +3 -0
- package/node_modules/@comis/agent/dist/bridge/pi-event-bridge.d.ts +9 -0
- package/node_modules/@comis/agent/dist/bridge/pi-event-bridge.js +73 -2
- package/node_modules/@comis/agent/dist/context-engine/signature-surrogate-guard.d.ts +10 -10
- package/node_modules/@comis/agent/dist/context-engine/signature-surrogate-guard.js +14 -14
- package/node_modules/@comis/agent/dist/context-engine/thinking-block-cleaner.d.ts +11 -13
- package/node_modules/@comis/agent/dist/context-engine/thinking-block-cleaner.js +14 -15
- package/node_modules/@comis/agent/dist/executor/capability-index-context.d.ts +72 -0
- package/node_modules/@comis/agent/dist/executor/capability-index-context.js +329 -0
- package/node_modules/@comis/agent/dist/executor/drain-helper.d.ts +122 -0
- package/node_modules/@comis/agent/dist/executor/drain-helper.js +173 -0
- package/node_modules/@comis/agent/dist/executor/error-classifier.js +2 -2
- package/node_modules/@comis/agent/dist/executor/executor-post-execution.d.ts +48 -4
- package/node_modules/@comis/agent/dist/executor/executor-post-execution.js +134 -31
- package/node_modules/@comis/agent/dist/executor/executor-prompt-runner.d.ts +7 -0
- package/node_modules/@comis/agent/dist/executor/executor-prompt-runner.js +25 -4
- package/node_modules/@comis/agent/dist/executor/executor-tool-assembly.d.ts +18 -1
- package/node_modules/@comis/agent/dist/executor/executor-tool-assembly.js +19 -16
- package/node_modules/@comis/agent/dist/executor/jit-guide-injector.d.ts +11 -2
- package/node_modules/@comis/agent/dist/executor/jit-guide-injector.js +16 -2
- package/node_modules/@comis/agent/dist/executor/pi-executor.d.ts +8 -2
- package/node_modules/@comis/agent/dist/executor/pi-executor.js +25 -12
- package/node_modules/@comis/agent/dist/executor/prompt-assembly.d.ts +9 -1
- package/node_modules/@comis/agent/dist/executor/prompt-assembly.js +15 -1
- package/node_modules/@comis/agent/dist/executor/tool-deferral.d.ts +18 -27
- package/node_modules/@comis/agent/dist/executor/tool-deferral.js +29 -38
- package/node_modules/@comis/agent/dist/model/model-registry-adapter.js +1 -1
- package/node_modules/@comis/agent/dist/model/model-scanner.js +1 -1
- package/node_modules/@comis/agent/dist/safety/tool-retry-breaker.d.ts +11 -1
- package/node_modules/@comis/agent/dist/safety/tool-retry-breaker.js +19 -22
- package/node_modules/@comis/agent/dist/session/comis-session-manager.d.ts +16 -2
- package/node_modules/@comis/agent/dist/spawn/pi-mono-adapters.d.ts +1 -1
- package/node_modules/@comis/agent/dist/spawn/pi-mono-adapters.js +5 -5
- package/node_modules/@comis/agent/dist/workspace/data-env.d.ts +38 -0
- package/node_modules/@comis/agent/dist/workspace/data-env.js +56 -0
- package/node_modules/@comis/agent/dist/workspace/index.d.ts +1 -0
- package/node_modules/@comis/agent/dist/workspace/index.js +1 -0
- package/node_modules/@comis/agent/dist/workspace/templates.js +5 -1
- package/node_modules/@comis/agent/package.json +1 -1
- package/node_modules/@comis/channels/dist/index.d.ts +1 -1
- package/node_modules/@comis/channels/dist/index.js +1 -1
- package/node_modules/@comis/channels/dist/shared/channel-manager.d.ts +9 -3
- package/node_modules/@comis/channels/dist/shared/inbound-gate.d.ts +1 -1
- package/node_modules/@comis/channels/dist/shared/inbound-gate.js +22 -7
- package/node_modules/@comis/channels/dist/shared/inbound-pipeline.d.ts +10 -3
- package/node_modules/@comis/channels/dist/shared/inbound-route.d.ts +1 -1
- package/node_modules/@comis/channels/dist/shared/inbound-route.js +13 -2
- package/node_modules/@comis/channels/dist/shared/response-filter.d.ts +11 -24
- package/node_modules/@comis/channels/dist/shared/response-filter.js +25 -53
- package/node_modules/@comis/channels/package.json +1 -1
- package/node_modules/@comis/cli/dist/commands/providers.d.ts +1 -2
- package/node_modules/@comis/cli/dist/commands/providers.js +5 -6
- package/node_modules/@comis/cli/package.json +1 -1
- package/node_modules/@comis/core/dist/config/field-metadata.js +2 -0
- package/node_modules/@comis/core/dist/config/immutable-keys.js +4 -1
- package/node_modules/@comis/core/dist/config/index.d.ts +4 -0
- package/node_modules/@comis/core/dist/config/index.js +2 -0
- package/node_modules/@comis/core/dist/config/schema-agent.d.ts +0 -792
- package/node_modules/@comis/core/dist/config/schema-approvals.d.ts +0 -14
- package/node_modules/@comis/core/dist/config/schema-auto-reply-engine.d.ts +0 -6
- package/node_modules/@comis/core/dist/config/schema-background-tasks.d.ts +0 -12
- package/node_modules/@comis/core/dist/config/schema-browser.d.ts +0 -18
- package/node_modules/@comis/core/dist/config/schema-channel.d.ts +0 -158
- package/node_modules/@comis/core/dist/config/schema-coalescer.d.ts +0 -5
- package/node_modules/@comis/core/dist/config/schema-daemon.d.ts +0 -32
- package/node_modules/@comis/core/dist/config/schema-delivery.d.ts +0 -18
- package/node_modules/@comis/core/dist/config/schema-documentation.d.ts +0 -12
- package/node_modules/@comis/core/dist/config/schema-embedding.d.ts +0 -20
- package/node_modules/@comis/core/dist/config/schema-envelope.d.ts +0 -15
- package/node_modules/@comis/core/dist/config/schema-gateway.d.ts +0 -37
- package/node_modules/@comis/core/dist/config/schema-gemini-cache.d.ts +0 -2
- package/node_modules/@comis/core/dist/config/schema-integrations.d.ts +0 -318
- package/node_modules/@comis/core/dist/config/schema-lifecycle-reactions.d.ts +0 -18
- package/node_modules/@comis/core/dist/config/schema-memory-review.d.ts +0 -7
- package/node_modules/@comis/core/dist/config/schema-memory.d.ts +0 -16
- package/node_modules/@comis/core/dist/config/schema-messages.d.ts +0 -8
- package/node_modules/@comis/core/dist/config/schema-models.d.ts +0 -15
- package/node_modules/@comis/core/dist/config/schema-notification.d.ts +0 -5
- package/node_modules/@comis/core/dist/config/schema-oauth.d.ts +0 -5
- package/node_modules/@comis/core/dist/config/schema-observability.d.ts +0 -38
- package/node_modules/@comis/core/dist/config/schema-output-retention.d.ts +34 -0
- package/node_modules/@comis/core/dist/config/schema-output-retention.js +48 -0
- package/node_modules/@comis/core/dist/config/schema-plugins.d.ts +0 -8
- package/node_modules/@comis/core/dist/config/schema-providers.d.ts +0 -64
- package/node_modules/@comis/core/dist/config/schema-queue.d.ts +0 -58
- package/node_modules/@comis/core/dist/config/schema-response-prefix.d.ts +0 -2
- package/node_modules/@comis/core/dist/config/schema-retry.d.ts +0 -6
- package/node_modules/@comis/core/dist/config/schema-scheduler.d.ts +0 -39
- package/node_modules/@comis/core/dist/config/schema-secrets.d.ts +0 -3
- package/node_modules/@comis/core/dist/config/schema-security.d.ts +0 -18
- package/node_modules/@comis/core/dist/config/schema-send-policy.d.ts +0 -13
- package/node_modules/@comis/core/dist/config/schema-sender-trust-display.d.ts +0 -5
- package/node_modules/@comis/core/dist/config/schema-serializer.js +2 -0
- package/node_modules/@comis/core/dist/config/schema-skills.d.ts +0 -61
- package/node_modules/@comis/core/dist/config/schema-streaming.d.ts +0 -38
- package/node_modules/@comis/core/dist/config/schema-telegram-file-guard.d.ts +0 -3
- package/node_modules/@comis/core/dist/config/schema-tooling.d.ts +87 -0
- package/node_modules/@comis/core/dist/config/schema-tooling.js +152 -0
- package/node_modules/@comis/core/dist/config/schema-verbosity.d.ts +0 -12
- package/node_modules/@comis/core/dist/config/schema-webhooks.d.ts +0 -40
- package/node_modules/@comis/core/dist/config/schema.d.ts +41 -38
- package/node_modules/@comis/core/dist/config/schema.js +6 -0
- package/node_modules/@comis/core/dist/context/context.d.ts +0 -4
- package/node_modules/@comis/core/dist/domain/approval-request.d.ts +0 -17
- package/node_modules/@comis/core/dist/domain/background-task-origin.d.ts +0 -10
- package/node_modules/@comis/core/dist/domain/delivery-origin.d.ts +0 -5
- package/node_modules/@comis/core/dist/domain/execution-graph.d.ts +0 -48
- package/node_modules/@comis/core/dist/domain/memory-entry.d.ts +0 -3
- package/node_modules/@comis/core/dist/domain/model-compat.d.ts +0 -4
- package/node_modules/@comis/core/dist/domain/normalized-message.d.ts +0 -15
- package/node_modules/@comis/core/dist/domain/provider-capabilities.d.ts +0 -6
- package/node_modules/@comis/core/dist/domain/rich-message.d.ts +0 -14
- package/node_modules/@comis/core/dist/domain/subagent-context-config.d.ts +0 -22
- package/node_modules/@comis/core/dist/domain/subagent-context-types.d.ts +0 -8
- package/node_modules/@comis/core/dist/event-bus/events-agent.d.ts +31 -0
- package/node_modules/@comis/core/dist/event-bus/events-infra.d.ts +5 -0
- package/node_modules/@comis/core/dist/exports/config.d.ts +2 -2
- package/node_modules/@comis/core/dist/exports/config.js +3 -1
- package/node_modules/@comis/core/dist/exports/hooks.d.ts +1 -1
- package/node_modules/@comis/core/dist/exports/ports.d.ts +2 -2
- package/node_modules/@comis/core/dist/exports/ports.js +1 -1
- package/node_modules/@comis/core/dist/ports/channel-plugin.d.ts +0 -13
- package/node_modules/@comis/core/dist/ports/index.d.ts +2 -0
- package/node_modules/@comis/core/dist/ports/index.js +4 -0
- package/node_modules/@comis/core/dist/ports/no-op-tool-capability.d.ts +30 -0
- package/node_modules/@comis/core/dist/ports/no-op-tool-capability.js +47 -0
- package/node_modules/@comis/core/dist/ports/tool-capability.d.ts +165 -0
- package/node_modules/@comis/core/dist/ports/tool-capability.js +15 -0
- package/node_modules/@comis/core/dist/security/audit.d.ts +0 -11
- package/node_modules/@comis/core/dist/tool-metadata.d.ts +21 -1
- package/node_modules/@comis/core/dist/tool-metadata.js +1 -1
- package/node_modules/@comis/core/package.json +1 -1
- package/node_modules/@comis/daemon/bundled-skills/skill-creator/scripts/validate-skill.py +1 -1
- package/node_modules/@comis/daemon/dist/daemon.js +89 -14
- package/node_modules/@comis/daemon/dist/rpc/agent-inline-workspace.d.ts +1 -1
- package/node_modules/@comis/daemon/dist/rpc/agent-inline-workspace.js +1 -1
- package/node_modules/@comis/daemon/dist/rpc/builtin-provider-guard.js +2 -2
- package/node_modules/@comis/daemon/dist/rpc/credential-resolver.js +1 -1
- package/node_modules/@comis/daemon/dist/rpc/model-handlers.d.ts +1 -1
- package/node_modules/@comis/daemon/dist/rpc/model-handlers.js +2 -2
- package/node_modules/@comis/daemon/dist/sub-agent-runner.d.ts +18 -0
- package/node_modules/@comis/daemon/dist/sub-agent-runner.js +41 -9
- package/node_modules/@comis/daemon/dist/wiring/index.d.ts +2 -0
- package/node_modules/@comis/daemon/dist/wiring/index.js +1 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-agents.d.ts +36 -2
- package/node_modules/@comis/daemon/dist/wiring/setup-agents.js +45 -8
- package/node_modules/@comis/daemon/dist/wiring/setup-background-completion-runner.d.ts +28 -9
- package/node_modules/@comis/daemon/dist/wiring/setup-background-completion-runner.js +36 -9
- package/node_modules/@comis/daemon/dist/wiring/setup-background-tasks.js +2 -2
- package/node_modules/@comis/daemon/dist/wiring/setup-channels.d.ts +9 -2
- package/node_modules/@comis/daemon/dist/wiring/setup-channels.js +15 -9
- package/node_modules/@comis/daemon/dist/wiring/setup-cross-session.d.ts +20 -5
- package/node_modules/@comis/daemon/dist/wiring/setup-cross-session.js +20 -15
- package/node_modules/@comis/daemon/dist/wiring/setup-delivery.js +14 -2
- package/node_modules/@comis/daemon/dist/wiring/setup-gateway.d.ts +4 -6
- package/node_modules/@comis/daemon/dist/wiring/setup-gateway.js +3 -5
- package/node_modules/@comis/daemon/dist/wiring/setup-heartbeat.d.ts +20 -5
- package/node_modules/@comis/daemon/dist/wiring/setup-heartbeat.js +11 -2
- package/node_modules/@comis/daemon/dist/wiring/setup-output-retention.d.ts +89 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-output-retention.js +212 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-tools.d.ts +18 -4
- package/node_modules/@comis/daemon/dist/wiring/setup-tools.js +29 -10
- package/node_modules/@comis/daemon/dist/wiring/tool-capability-adapter.d.ts +75 -0
- package/node_modules/@comis/daemon/dist/wiring/tool-capability-adapter.js +253 -0
- package/node_modules/@comis/daemon/package.json +1 -1
- package/node_modules/@comis/gateway/dist/webhook/webhook-endpoint.d.ts +0 -4
- package/node_modules/@comis/gateway/package.json +1 -1
- package/node_modules/@comis/infra/package.json +1 -1
- package/node_modules/@comis/memory/package.json +1 -1
- package/node_modules/@comis/scheduler/dist/cron/cron-types.d.ts +0 -42
- package/node_modules/@comis/scheduler/dist/heartbeat/agent-heartbeat-source.d.ts +29 -8
- package/node_modules/@comis/scheduler/dist/heartbeat/agent-heartbeat-source.js +19 -7
- package/node_modules/@comis/scheduler/dist/system-events/system-event-types.d.ts +0 -3
- package/node_modules/@comis/scheduler/dist/tasks/task-types.d.ts +0 -17
- package/node_modules/@comis/scheduler/package.json +1 -1
- package/node_modules/@comis/shared/dist/index.d.ts +3 -0
- package/node_modules/@comis/shared/dist/index.js +4 -0
- package/node_modules/@comis/shared/dist/mcp-tool-name.d.ts +78 -0
- package/node_modules/@comis/shared/dist/mcp-tool-name.js +92 -0
- package/node_modules/@comis/shared/dist/silent-tokens.d.ts +38 -0
- package/node_modules/@comis/shared/dist/silent-tokens.js +51 -0
- package/node_modules/@comis/shared/dist/visible-delivery.d.ts +28 -0
- package/node_modules/@comis/shared/dist/visible-delivery.js +16 -0
- package/node_modules/@comis/shared/package.json +1 -1
- package/node_modules/@comis/skills/dist/bridge/mcp-tool-bridge.d.ts +2 -13
- package/node_modules/@comis/skills/dist/bridge/mcp-tool-bridge.js +3 -21
- package/node_modules/@comis/skills/dist/bridge/tool-metadata-enforcement.js +1 -1
- package/node_modules/@comis/skills/dist/bridge/tool-metadata-registry.js +4 -4
- package/node_modules/@comis/skills/dist/builtin/exec-tool.d.ts +55 -9
- package/node_modules/@comis/skills/dist/builtin/exec-tool.js +383 -19
- package/node_modules/@comis/skills/dist/builtin/install-detour.d.ts +67 -0
- package/node_modules/@comis/skills/dist/builtin/install-detour.js +342 -0
- package/node_modules/@comis/skills/dist/builtin/platform/admin-manage-factory.js +5 -5
- package/node_modules/@comis/skills/dist/builtin/platform/agents-manage-tool.d.ts +2 -2
- package/node_modules/@comis/skills/dist/builtin/platform/agents-manage-tool.js +2 -2
- package/node_modules/@comis/skills/dist/builtin/platform/message-tool.js +18 -0
- package/node_modules/@comis/skills/dist/builtin/platform/messaging-factory.d.ts +18 -1
- package/node_modules/@comis/skills/dist/builtin/platform/messaging-factory.js +18 -2
- package/node_modules/@comis/skills/dist/builtin/platform/models-manage-tool.js +3 -3
- package/node_modules/@comis/skills/dist/builtin/process-registry.d.ts +14 -0
- package/node_modules/@comis/skills/dist/builtin/process-tool.d.ts +24 -4
- package/node_modules/@comis/skills/dist/builtin/process-tool.js +25 -7
- package/node_modules/@comis/skills/dist/builtin/sandbox/bwrap-provider.d.ts +1 -1
- package/node_modules/@comis/skills/dist/builtin/sandbox/bwrap-provider.js +9 -0
- package/node_modules/@comis/skills/dist/index.d.ts +4 -1
- package/node_modules/@comis/skills/dist/index.js +3 -1
- package/node_modules/@comis/skills/dist/manifest/capability-parser.d.ts +44 -0
- package/node_modules/@comis/skills/dist/manifest/capability-parser.js +68 -0
- package/node_modules/@comis/skills/dist/manifest/schema.d.ts +44 -37
- package/node_modules/@comis/skills/dist/manifest/schema.js +35 -0
- package/node_modules/@comis/skills/dist/registry/discovery.d.ts +8 -0
- package/node_modules/@comis/skills/dist/registry/discovery.js +10 -3
- package/node_modules/@comis/skills/dist/registry/skill-registry.d.ts +45 -1
- package/node_modules/@comis/skills/dist/registry/skill-registry.js +70 -7
- package/node_modules/@comis/skills/package.json +1 -1
- package/node_modules/@comis/web/package.json +1 -1
- 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
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
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: "
|
|
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
|
|
430
|
-
// - Downstream nodes (depth >= 1): "long" -- may be consumed by further
|
|
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
|
-
//
|
|
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
|
|
476
|
-
// Downstream nodes (depth>=1): "long" -- may be consumed
|
|
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
|
-
//
|
|
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
|
-
|
|
576
|
-
|
|
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
|
-
//
|
|
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
|
|
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({
|
|
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
|
-
*
|
|
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
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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
|
-
/**
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
/**
|
|
33
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
*
|
|
4
|
-
*
|
|
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. */
|