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
|
@@ -16,8 +16,9 @@ import type { AgentSession } from "@mariozechner/pi-coding-agent";
|
|
|
16
16
|
import type { CacheRetention } from "@mariozechner/pi-ai";
|
|
17
17
|
import { type SessionKey, type NormalizedMessage, type PerAgentConfig, type TypedEventBus, type MemoryPort } from "@comis/core";
|
|
18
18
|
import type { ComisLogger } from "@comis/infra";
|
|
19
|
+
import { drainAt, markRead, markConsumed, formatDrainKey, type DrainKey, type DrainInflightState } from "./drain-helper.js";
|
|
19
20
|
import type { ActiveRunRegistry } from "./active-run-registry.js";
|
|
20
|
-
import type { ComisSessionManager } from "../session/comis-session-manager.js";
|
|
21
|
+
import type { ComisSessionManager, SessionMetadata } from "../session/comis-session-manager.js";
|
|
21
22
|
import type { ExecutionResult, ExecutionOverrides } from "./types.js";
|
|
22
23
|
import type { ExecutionPlan } from "../planner/types.js";
|
|
23
24
|
import type { ContextEngine } from "../context-engine/index.js";
|
|
@@ -53,11 +54,11 @@ export interface PostExecutionBridgeResult {
|
|
|
53
54
|
cacheWrite5mTokens?: number;
|
|
54
55
|
/** Estimated 1h TTL cache write tokens from TTL split data. */
|
|
55
56
|
cacheWrite1hTokens?: number;
|
|
56
|
-
/**
|
|
57
|
+
/** Session-cumulative total cost across all turns (USD). */
|
|
57
58
|
sessionCostUsd?: number;
|
|
58
|
-
/**
|
|
59
|
+
/** Session-cumulative cache savings across all turns (USD). */
|
|
59
60
|
sessionCacheSavedUsd?: number;
|
|
60
|
-
/**
|
|
61
|
+
/** Thinking tokens from SDK reasoningTokens field. */
|
|
61
62
|
thinkingTokens?: number;
|
|
62
63
|
/** Number of pre-LLM-call hash-assertion walks performed (one per turn_start). */
|
|
63
64
|
hashAssertionsRan?: number;
|
|
@@ -74,6 +75,19 @@ export interface PostExecutionBridgeResult {
|
|
|
74
75
|
/** Bridge interface used by post-execution. */
|
|
75
76
|
export interface PostExecutionBridge {
|
|
76
77
|
getResult(): PostExecutionBridgeResult;
|
|
78
|
+
/**
|
|
79
|
+
* Expose the bridge-owned drain inflight gate so postExecution can fire
|
|
80
|
+
* an end-of-turn backstop `drainAt(...)`. The bridge already drains on
|
|
81
|
+
* `tool_execution_end` for `message` actions (inline-consumption); the
|
|
82
|
+
* end-of-turn backstop closes the residual race for turns that never
|
|
83
|
+
* invoked the `message` tool but still need the inline-consumption
|
|
84
|
+
* queue flipped (NO_REPLY-only turns, sentinel passes, etc.).
|
|
85
|
+
*
|
|
86
|
+
* Both call sites share the SAME composite key gate map so concurrent
|
|
87
|
+
* drains for the same `(agentId, channelType, channelId)` triple
|
|
88
|
+
* collapse to a single in-flight Promise.
|
|
89
|
+
*/
|
|
90
|
+
getDrainState(): DrainInflightState;
|
|
77
91
|
}
|
|
78
92
|
/** Parameters for postExecution(). */
|
|
79
93
|
export interface PostExecutionParams {
|
|
@@ -86,6 +100,9 @@ export interface PostExecutionParams {
|
|
|
86
100
|
msg: NormalizedMessage;
|
|
87
101
|
sessionKey: SessionKey;
|
|
88
102
|
formattedKey: string;
|
|
103
|
+
/** Resolver-aligned key for activeRunRegistry.deregister. Must match the
|
|
104
|
+
* formula used at the corresponding register call site. */
|
|
105
|
+
resolverRegisterKey: string;
|
|
89
106
|
agentId: string | undefined;
|
|
90
107
|
executionStartMs: number;
|
|
91
108
|
executionId: string;
|
|
@@ -182,6 +199,33 @@ export declare function shouldStorePairedMemory(userText: string, agentResponse:
|
|
|
182
199
|
export declare function isDuplicatePairedMemory(content: string, agentId: string): boolean;
|
|
183
200
|
/** Reset the paired-memory dedup cache. Exported for unit tests. */
|
|
184
201
|
export declare function resetPairedMemoryDedupForTests(): void;
|
|
202
|
+
/**
|
|
203
|
+
* Build the SessionMetadata payload written to `_session-metadata.json` at the
|
|
204
|
+
* end of an execution.
|
|
205
|
+
*
|
|
206
|
+
* `traceId` and `runId` are deliberately distinct:
|
|
207
|
+
* - `traceId` is the request-scope AsyncLocalStorage value set by
|
|
208
|
+
* `runWithContext` at the channel boundary (execution-execute.ts) and injected
|
|
209
|
+
* into every daemon log line by the Pino tracing mixin. Operators grep
|
|
210
|
+
* daemon.log for this exact value. Pass `tryGetContext()?.traceId` here.
|
|
211
|
+
* - `runId` is the executor-scope UUID minted in pi-executor.ts per
|
|
212
|
+
* `executor.execute()` call. It keys cost-tracker / token_usage rows.
|
|
213
|
+
*
|
|
214
|
+
* They happen to be 1:1 in the steady-state interactive path (one inbound
|
|
215
|
+
* message → one execution), but the schema treats them as distinct because
|
|
216
|
+
* heartbeat / sub-agent paths can fan out one trace into multiple executions.
|
|
217
|
+
*
|
|
218
|
+
* Pure: no I/O, no side effects. The fire-and-forget try/catch around
|
|
219
|
+
* `writeSessionMetadata` lives at the call site.
|
|
220
|
+
*/
|
|
221
|
+
export declare function buildSessionEndMetadata(args: {
|
|
222
|
+
finishReason: string;
|
|
223
|
+
durationMs: number;
|
|
224
|
+
totalTokens: number;
|
|
225
|
+
executionId: string;
|
|
226
|
+
traceId: string | undefined;
|
|
227
|
+
}): SessionMetadata;
|
|
228
|
+
export { drainAt, markRead, markConsumed, formatDrainKey, type DrainKey, type DrainInflightState, };
|
|
185
229
|
/**
|
|
186
230
|
* Run post-execution cleanup for a PiExecutor turn.
|
|
187
231
|
*
|
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
*
|
|
14
14
|
* @module
|
|
15
15
|
*/
|
|
16
|
-
import {
|
|
16
|
+
import { tryGetContext, } from "@comis/core";
|
|
17
|
+
import { suppressError, isSilentResponse } from "@comis/shared";
|
|
18
|
+
import { drainAt, markRead, markConsumed, formatDrainKey, } from "./drain-helper.js";
|
|
17
19
|
import { setBreakpointIndex, deleteBreakpointIndex, getBreakpointIndexMapSize, } from "./executor-session-state.js";
|
|
18
20
|
import { mergeSessionStats } from "./pi-executor.js";
|
|
19
21
|
import { recordLastResponseTs } from "./ttl-guard.js";
|
|
@@ -124,6 +126,63 @@ export function isDuplicatePairedMemory(content, agentId) {
|
|
|
124
126
|
export function resetPairedMemoryDedupForTests() {
|
|
125
127
|
pairedMemoryDedup.clear();
|
|
126
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Map an SDK finishReason to the SessionMetadata.sessionEnd.endReason enum.
|
|
131
|
+
* Unknown reasons fall through to "error" — that's a defensive bucket for
|
|
132
|
+
* provider strings we haven't classified yet (rather than dropping the
|
|
133
|
+
* session_end entry entirely). Module-level so the post-execution path
|
|
134
|
+
* doesn't reallocate it on every turn.
|
|
135
|
+
*/
|
|
136
|
+
const END_REASON_MAP = {
|
|
137
|
+
stop: "success", end_turn: "success", error: "error",
|
|
138
|
+
budget_exceeded: "budget_exceeded", budget_exhausted: "budget_exhausted",
|
|
139
|
+
circuit_open: "circuit_open",
|
|
140
|
+
provider_degraded: "provider_degraded", max_steps: "error",
|
|
141
|
+
context_loop: "error", context_exhausted: "error",
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Build the SessionMetadata payload written to `_session-metadata.json` at the
|
|
145
|
+
* end of an execution.
|
|
146
|
+
*
|
|
147
|
+
* `traceId` and `runId` are deliberately distinct:
|
|
148
|
+
* - `traceId` is the request-scope AsyncLocalStorage value set by
|
|
149
|
+
* `runWithContext` at the channel boundary (execution-execute.ts) and injected
|
|
150
|
+
* into every daemon log line by the Pino tracing mixin. Operators grep
|
|
151
|
+
* daemon.log for this exact value. Pass `tryGetContext()?.traceId` here.
|
|
152
|
+
* - `runId` is the executor-scope UUID minted in pi-executor.ts per
|
|
153
|
+
* `executor.execute()` call. It keys cost-tracker / token_usage rows.
|
|
154
|
+
*
|
|
155
|
+
* They happen to be 1:1 in the steady-state interactive path (one inbound
|
|
156
|
+
* message → one execution), but the schema treats them as distinct because
|
|
157
|
+
* heartbeat / sub-agent paths can fan out one trace into multiple executions.
|
|
158
|
+
*
|
|
159
|
+
* Pure: no I/O, no side effects. The fire-and-forget try/catch around
|
|
160
|
+
* `writeSessionMetadata` lives at the call site.
|
|
161
|
+
*/
|
|
162
|
+
export function buildSessionEndMetadata(args) {
|
|
163
|
+
return {
|
|
164
|
+
...(args.traceId && { traceId: args.traceId }),
|
|
165
|
+
runId: args.executionId,
|
|
166
|
+
sessionEnd: {
|
|
167
|
+
type: "session_end",
|
|
168
|
+
timestamp: new Date().toISOString(),
|
|
169
|
+
endReason: END_REASON_MAP[args.finishReason] ?? "error",
|
|
170
|
+
durationMs: args.durationMs,
|
|
171
|
+
totalTokens: args.totalTokens,
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
// Drain-seam re-exports.
|
|
177
|
+
//
|
|
178
|
+
// Canonical implementations live in ./drain-helper.ts so the bridge
|
|
179
|
+
// (packages/agent/src/bridge/pi-event-bridge.ts) can import them without
|
|
180
|
+
// creating a cycle through pi-executor.js. The bridge owns the
|
|
181
|
+
// `drainInflightByKey: Map<string, Promise<void>>` gate state in
|
|
182
|
+
// `BridgeMetricsState` and threads it into drainAt at the
|
|
183
|
+
// `tool_execution_end` call site (inline-consumption + composite drain).
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
export { drainAt, markRead, markConsumed, formatDrainKey, };
|
|
127
186
|
// ---------------------------------------------------------------------------
|
|
128
187
|
// Implementation
|
|
129
188
|
// ---------------------------------------------------------------------------
|
|
@@ -139,7 +198,12 @@ export function resetPairedMemoryDedupForTests() {
|
|
|
139
198
|
* @param params - All inputs needed for post-execution cleanup
|
|
140
199
|
*/
|
|
141
200
|
export async function postExecution(params) {
|
|
142
|
-
const { result, session, sm, config, msg, sessionKey, formattedKey, agentId, executionStartMs, executionId, bridge, unsubscribe, contextEngineRef, ceSetup, streamSetup, getTruncationSummary, getTurnBudgetSummary, executionPlanRef, isOnboarding, geminiCacheHit, geminiCachedTokens, modelTier, provider, providerFamily, deferralResult, mergedCustomTools, deliveredGuides, deps, sessionAdapter, executionCacheRetentionClear, adaptiveRetentionClear, } = params;
|
|
201
|
+
const { result, session, sm, config, msg, sessionKey, formattedKey, resolverRegisterKey, agentId, executionStartMs, executionId, bridge, unsubscribe, contextEngineRef, ceSetup, streamSetup, getTruncationSummary, getTurnBudgetSummary, executionPlanRef, isOnboarding, geminiCacheHit, geminiCachedTokens, modelTier, provider, providerFamily, deferralResult, mergedCustomTools, deliveredGuides, deps, sessionAdapter, executionCacheRetentionClear, adaptiveRetentionClear, } = params;
|
|
202
|
+
// Hoist effectiveAgentId normalization to the TOP of the function so all
|
|
203
|
+
// downstream branches (silent-sentinel gate, memory-store path, drainAt
|
|
204
|
+
// call site, skip-log debug branches) share the same normalized value.
|
|
205
|
+
// Multi-agent isolation requires uniformity across all paths.
|
|
206
|
+
const effectiveAgentId = agentId ?? "default";
|
|
143
207
|
unsubscribe();
|
|
144
208
|
// Clear per-execution cache retention to prevent state leakage
|
|
145
209
|
executionCacheRetentionClear();
|
|
@@ -168,7 +232,7 @@ export async function postExecution(params) {
|
|
|
168
232
|
if (result.errorContext && bridgeResult.lastActiveToolName) {
|
|
169
233
|
result.errorContext.failingTool = bridgeResult.lastActiveToolName;
|
|
170
234
|
}
|
|
171
|
-
//
|
|
235
|
+
// Delegate token totals to SDK session stats (single source of truth).
|
|
172
236
|
// Cost stays from bridge for consistency with per-turn observability events.
|
|
173
237
|
// Per-turn event emission in bridge remains manual (SDK stats are cumulative only).
|
|
174
238
|
mergeSessionStats(result, () => session.getSessionStats());
|
|
@@ -184,7 +248,7 @@ export async function postExecution(params) {
|
|
|
184
248
|
// The context:pipeline event fires pre-LLM with zeros. This event patches actual data.
|
|
185
249
|
if (deps.eventBus) {
|
|
186
250
|
deps.eventBus.emit("context:pipeline:cache", {
|
|
187
|
-
agentId:
|
|
251
|
+
agentId: effectiveAgentId,
|
|
188
252
|
sessionKey: formattedKey,
|
|
189
253
|
cacheHitTokens: cacheReadTokens,
|
|
190
254
|
cacheWriteTokens,
|
|
@@ -207,7 +271,7 @@ export async function postExecution(params) {
|
|
|
207
271
|
planExtractionTurn: 1,
|
|
208
272
|
};
|
|
209
273
|
deps.eventBus.emit("sep:plan_completed", {
|
|
210
|
-
agentId:
|
|
274
|
+
agentId: effectiveAgentId,
|
|
211
275
|
sessionKey: formattedKey,
|
|
212
276
|
stepsPlanned: toolCalls,
|
|
213
277
|
stepsCompleted: toolCalls,
|
|
@@ -264,7 +328,7 @@ export async function postExecution(params) {
|
|
|
264
328
|
comisEstimatedTtlSplit: (bridgeResult.cacheWrite5mTokens ?? 0) > 0 || (bridgeResult.cacheWrite1hTokens ?? 0) > 0,
|
|
265
329
|
costUsd: result.cost.total,
|
|
266
330
|
cacheSavedUsd: result.cost.cacheSaved ?? 0,
|
|
267
|
-
//
|
|
331
|
+
// Session-cumulative cost fields (alongside per-turn costUsd/cacheSavedUsd)
|
|
268
332
|
sessionCostUsd: bridgeResult.sessionCostUsd ?? 0,
|
|
269
333
|
sessionCacheSavedUsd: bridgeResult.sessionCacheSavedUsd ?? 0,
|
|
270
334
|
// Session cache savings rate
|
|
@@ -312,7 +376,7 @@ export async function postExecution(params) {
|
|
|
312
376
|
postBatchContinuationAttempts: result.continuationMetrics.attempts,
|
|
313
377
|
postBatchContinuationOutcome: result.continuationMetrics.outcome,
|
|
314
378
|
}),
|
|
315
|
-
//
|
|
379
|
+
// Thinking token tracking (conditional -- only when thinking tokens detected)
|
|
316
380
|
...(bridgeResult.thinkingTokens != null && bridgeResult.thinkingTokens > 0 && {
|
|
317
381
|
thinkingTokens: bridgeResult.thinkingTokens,
|
|
318
382
|
totalOutputTokens: result.tokensUsed.output ?? 0,
|
|
@@ -339,27 +403,19 @@ export async function postExecution(params) {
|
|
|
339
403
|
errorKind: "resource",
|
|
340
404
|
}, "Turn budget truncation summary");
|
|
341
405
|
}
|
|
342
|
-
// Write session metadata companion file with trace correlation
|
|
343
|
-
//
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
circuit_open: "circuit_open",
|
|
348
|
-
provider_degraded: "provider_degraded", max_steps: "error",
|
|
349
|
-
context_loop: "error", context_exhausted: "error",
|
|
350
|
-
};
|
|
406
|
+
// Write session metadata companion file with trace correlation.
|
|
407
|
+
// traceId comes from the AsyncLocalStorage request scope so `_session-metadata.json`
|
|
408
|
+
// can be cross-correlated against daemon.log via grep; runId stays as the
|
|
409
|
+
// executor-scope UUID. See buildSessionEndMetadata for the contract.
|
|
410
|
+
// Fire-and-forget: metadata write failure must not affect execution.
|
|
351
411
|
try {
|
|
352
|
-
sessionAdapter.writeSessionMetadata(sessionKey, {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
durationMs,
|
|
360
|
-
totalTokens: result.tokensUsed.total,
|
|
361
|
-
},
|
|
362
|
-
});
|
|
412
|
+
sessionAdapter.writeSessionMetadata(sessionKey, buildSessionEndMetadata({
|
|
413
|
+
finishReason: result.finishReason,
|
|
414
|
+
durationMs,
|
|
415
|
+
totalTokens: result.tokensUsed.total,
|
|
416
|
+
executionId,
|
|
417
|
+
traceId: tryGetContext()?.traceId,
|
|
418
|
+
}));
|
|
363
419
|
}
|
|
364
420
|
catch { /* fire-and-forget */ }
|
|
365
421
|
// Check onboarding completion after execution
|
|
@@ -383,14 +439,23 @@ export async function postExecution(params) {
|
|
|
383
439
|
// Non-blocking, non-fatal -- execution never fails due to memory store errors.
|
|
384
440
|
const operationType = params.executionOverrides?.operationType;
|
|
385
441
|
const skipMemoryForOperation = operationType != null && MEMORY_SKIP_OPERATIONS.has(operationType);
|
|
386
|
-
|
|
442
|
+
// Layer 0: silent sentinels never enter memory. Idempotent under
|
|
443
|
+
// stripReplyTags + trim per @comis/shared silent-tokens.ts JSDoc
|
|
444
|
+
// contract. The check happens BEFORE the operationType + content-hash
|
|
445
|
+
// dedup gates so that even when the response would otherwise pass those
|
|
446
|
+
// gates, a `NO_REPLY` / `HEARTBEAT_OK` / `[SILENT]` sentinel is rejected
|
|
447
|
+
// from memory persistence.
|
|
448
|
+
const isSilent = !!(deps.memoryPort && result.response && msg.text && isSilentResponse(result.response));
|
|
449
|
+
if (isSilent) {
|
|
450
|
+
deps.logger.debug({ agentId: effectiveAgentId, sessionKey: formattedKey, hint: "Silent-sentinel response (NO_REPLY / HEARTBEAT_OK / [SILENT]) skipped from paired memory" }, "Paired memory skipped: silent-sentinel response");
|
|
451
|
+
}
|
|
452
|
+
else if (deps.memoryPort &&
|
|
387
453
|
result.response &&
|
|
388
454
|
msg.text &&
|
|
389
455
|
!skipMemoryForOperation &&
|
|
390
456
|
shouldStorePairedMemory(msg.text, result.response)) {
|
|
391
457
|
const now = Date.now();
|
|
392
458
|
const pairedContent = buildPairedMemoryContent(msg.text, result.response);
|
|
393
|
-
const effectiveAgentId = agentId ?? "default";
|
|
394
459
|
if (isDuplicatePairedMemory(pairedContent, effectiveAgentId)) {
|
|
395
460
|
deps.logger.debug({ agentId: effectiveAgentId, sessionKey: formattedKey }, "Paired memory skipped: duplicate content within dedup window");
|
|
396
461
|
}
|
|
@@ -433,9 +498,47 @@ export async function postExecution(params) {
|
|
|
433
498
|
deps.logger.debug({ userLen: msg.text.trim().length, minUserChars: PAIRED_MIN_USER_CHARS, minCombinedChars: PAIRED_MIN_COMBINED_CHARS }, "Paired memory skipped: content below quality threshold");
|
|
434
499
|
}
|
|
435
500
|
}
|
|
436
|
-
//
|
|
501
|
+
// End-of-turn backstop drain.
|
|
502
|
+
//
|
|
503
|
+
// The bridge fires `drainAt(...)` on `tool_execution_end` for successful
|
|
504
|
+
// `message(send|reply|attach)` calls (the primary inline-consumption
|
|
505
|
+
// call site). The end-of-turn call site below is the BACKSTOP for turns
|
|
506
|
+
// that produced a response WITHOUT invoking the message tool (NO_REPLY-
|
|
507
|
+
// only turns, sentinel-passthrough turns, error paths). Both call sites
|
|
508
|
+
// share the SAME composite-key inflight gate (`drainInflightByKey`) so a
|
|
509
|
+
// bridge-fired drain in flight collapses any backstop drain for the same
|
|
510
|
+
// composite key (single-tick gate).
|
|
511
|
+
//
|
|
512
|
+
// The drain key is composed from `effectiveAgentId` (multi-agent
|
|
513
|
+
// isolation) + `msg.channelType` + `msg.channelId`. markRead and
|
|
514
|
+
// markConsumed inside drainAt read tool context via tryGetContext();
|
|
515
|
+
// when the executor runs outside an AsyncLocalStorage scope (e.g.,
|
|
516
|
+
// tests with no runWithContext wrapper) the helpers fall through silently.
|
|
517
|
+
const drainKey = {
|
|
518
|
+
agentId: effectiveAgentId,
|
|
519
|
+
channelType: msg.channelType,
|
|
520
|
+
channelId: msg.channelId,
|
|
521
|
+
};
|
|
522
|
+
// tryGetContext() reads the AsyncLocalStorage scope; markRead/markConsumed
|
|
523
|
+
// do the same internally, but reading once here lets us correlate the
|
|
524
|
+
// backstop-drain log line with the request's traceId without re-deriving
|
|
525
|
+
// it inside the helper. Returns undefined outside any request scope --
|
|
526
|
+
// markRead/markConsumed handle that path silently.
|
|
527
|
+
const drainCtx = tryGetContext();
|
|
528
|
+
if (drainCtx) {
|
|
529
|
+
deps.logger.debug({
|
|
530
|
+
submodule: "drain.endOfTurn",
|
|
531
|
+
agentId: effectiveAgentId,
|
|
532
|
+
channelType: msg.channelType,
|
|
533
|
+
channelId: msg.channelId,
|
|
534
|
+
traceId: drainCtx.traceId,
|
|
535
|
+
}, "End-of-turn drain backstop firing");
|
|
536
|
+
}
|
|
537
|
+
drainAt({ agentId: effectiveAgentId, channelType: drainKey.channelType, channelId: drainKey.channelId }, bridge.getDrainState(), deps.logger);
|
|
538
|
+
// Deregister active run before dispose. Must use the same resolver-aligned
|
|
539
|
+
// key formula as the corresponding register call site.
|
|
437
540
|
if (deps.activeRunRegistry) {
|
|
438
|
-
deps.activeRunRegistry.deregister(
|
|
541
|
+
deps.activeRunRegistry.deregister(resolverRegisterKey);
|
|
439
542
|
}
|
|
440
543
|
// Strip verbose <functions> blocks from discover_tools results
|
|
441
544
|
// in session history. Runs post-execution so the current turn's model
|
|
@@ -26,6 +26,7 @@ import type { AuthRotationAdapter } from "../model/auth-rotation-adapter.js";
|
|
|
26
26
|
import type { ProviderHealthMonitor } from "../safety/provider-health-monitor.js";
|
|
27
27
|
import type { LastKnownModelTracker } from "../model/last-known-model.js";
|
|
28
28
|
import type { EnvelopeConfig } from "@comis/core";
|
|
29
|
+
import type { CapabilityIndexRenderResult } from "./capability-index-context.js";
|
|
29
30
|
/** Bridge interface used by the prompt runner (minimal getResult). */
|
|
30
31
|
export interface PromptRunnerBridge {
|
|
31
32
|
getResult(): {
|
|
@@ -60,6 +61,12 @@ export interface RunPromptParams {
|
|
|
60
61
|
bridge: PromptRunnerBridge;
|
|
61
62
|
dynamicPreamble: string | undefined;
|
|
62
63
|
deferredContext: string | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Per-turn capability-index render result. The .text field is concatenated
|
|
66
|
+
* into the dynamic preamble via `[...].filter(Boolean).join("\n\n")`; the
|
|
67
|
+
* count fields feed the Pino debug log below.
|
|
68
|
+
*/
|
|
69
|
+
capabilityIndexResult: CapabilityIndexRenderResult;
|
|
63
70
|
inlineMemory: string | undefined;
|
|
64
71
|
systemPrompt: string | undefined;
|
|
65
72
|
mergedCustomTools: Array<{
|
|
@@ -47,7 +47,7 @@ import { getCacheProviderInfo } from "../executor/cache-usage-helpers.js";
|
|
|
47
47
|
* @returns Prompt execution outcome (success, error, escalation state)
|
|
48
48
|
*/
|
|
49
49
|
export async function runPrompt(params) {
|
|
50
|
-
const { msg, session, config, sessionKey, formattedKey, agentId, result, executionStartMs, effectiveTimeout, executionId, bridge, dynamicPreamble, deferredContext, inlineMemory, systemPrompt, mergedCustomTools, cmdResult, sepEnabled, executionPlanRef, _directives, _prevTimestamp, resolvedModel, deps, onResetTimer, getLastCacheWriteTokens, budgetWarningRef, } = params;
|
|
50
|
+
const { msg, session, config, sessionKey, formattedKey, agentId, result, executionStartMs, effectiveTimeout, executionId, bridge, dynamicPreamble, deferredContext, capabilityIndexResult, inlineMemory, systemPrompt, mergedCustomTools, cmdResult, sepEnabled, executionPlanRef, _directives, _prevTimestamp, resolvedModel, deps, onResetTimer, getLastCacheWriteTokens, budgetWarningRef, } = params;
|
|
51
51
|
// Wrap message text with envelope
|
|
52
52
|
let messageText = deps.envelopeConfig
|
|
53
53
|
? wrapInEnvelope(msg, deps.envelopeConfig, _prevTimestamp)
|
|
@@ -55,12 +55,33 @@ export async function runPrompt(params) {
|
|
|
55
55
|
// Prepend dynamic preamble (date/time, inbound metadata)
|
|
56
56
|
// relocated from system prompt for cache stability.
|
|
57
57
|
// Also includes <deferred-tools> context block when deferred tools exist.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
//
|
|
59
|
+
// Array-concat shape. Each element either contributes a non-empty string
|
|
60
|
+
// or filters out cleanly. The renderer's EMPTY sentinel (gate-disabled OR
|
|
61
|
+
// all-zero counts) yields text === "" which .filter(Boolean) drops
|
|
62
|
+
// automatically.
|
|
63
|
+
const capabilityIndexContext = capabilityIndexResult.text;
|
|
64
|
+
const fullDynamicPreamble = [dynamicPreamble, capabilityIndexContext, deferredContext]
|
|
65
|
+
.filter(Boolean)
|
|
66
|
+
.join("\n\n");
|
|
61
67
|
if (fullDynamicPreamble) {
|
|
62
68
|
messageText = `[System context]\n${fullDynamicPreamble}\n[End system context]\n\n${messageText}`;
|
|
63
69
|
}
|
|
70
|
+
// Pino debug log. Submodule binding per AGENTS.md §2.7:
|
|
71
|
+
// deps.logger.child({ submodule }) attaches the label only at this call
|
|
72
|
+
// site, not module-scope.
|
|
73
|
+
const submoduleLogger = deps.logger.child({ submodule: "executor.capability-index" });
|
|
74
|
+
const fullPreambleTokens = Math.ceil((fullDynamicPreamble ?? "").length / CHARS_PER_TOKEN_RATIO);
|
|
75
|
+
const deferredContextTokens = Math.ceil((deferredContext ?? "").length / CHARS_PER_TOKEN_RATIO);
|
|
76
|
+
submoduleLogger.debug({
|
|
77
|
+
capabilityIndexTokens: capabilityIndexResult.capabilityIndexTokens,
|
|
78
|
+
deferredContextTokens,
|
|
79
|
+
fullPreambleTokens,
|
|
80
|
+
clusterCount: capabilityIndexResult.clusterCount,
|
|
81
|
+
activeToolCount: capabilityIndexResult.activeToolCount,
|
|
82
|
+
deferredToolCount: capabilityIndexResult.deferredToolCount,
|
|
83
|
+
promptSkillCount: capabilityIndexResult.promptSkillCount,
|
|
84
|
+
}, "Dynamic preamble assembled");
|
|
64
85
|
// Task 229: Inject top-1 RAG memory inline, adjacent to user message
|
|
65
86
|
// for maximum LLM attention. Placed AFTER [End system context] and
|
|
66
87
|
// BEFORE the user's actual question text.
|
|
@@ -15,9 +15,10 @@
|
|
|
15
15
|
import { SettingsManager, DefaultResourceLoader } from "@mariozechner/pi-coding-agent";
|
|
16
16
|
import type { ToolDefinition } from "@mariozechner/pi-coding-agent";
|
|
17
17
|
import type { AgentTool } from "@mariozechner/pi-agent-core";
|
|
18
|
-
import { type SessionKey, type NormalizedMessage, type PerAgentConfig, type TypedEventBus, type MemoryPort, type HookRunner, type SecretManager, type EnvelopeConfig, type SenderTrustDisplayConfig } from "@comis/core";
|
|
18
|
+
import { type SessionKey, type NormalizedMessage, type PerAgentConfig, type TypedEventBus, type MemoryPort, type HookRunner, type SecretManager, type EnvelopeConfig, type SenderTrustDisplayConfig, type ToolCapabilityPort } from "@comis/core";
|
|
19
19
|
import type { ComisLogger } from "@comis/infra";
|
|
20
20
|
import type { ExcludeDeferralResult } from "./tool-deferral.js";
|
|
21
|
+
import type { CapabilityIndexRenderResult } from "./capability-index-context.js";
|
|
21
22
|
import type { DiscoveryTracker } from "./discovery-tracker.js";
|
|
22
23
|
import type { ExecutionPromptResult } from "./prompt-assembly.js";
|
|
23
24
|
import type { ExecutionOverrides } from "./types.js";
|
|
@@ -48,6 +49,13 @@ export interface ToolAssemblyDeps {
|
|
|
48
49
|
maxCharsPerInjection: number;
|
|
49
50
|
};
|
|
50
51
|
embeddingPort?: EmbeddingPort;
|
|
52
|
+
/**
|
|
53
|
+
* Tool-capability port for the per-turn capability-index renderer.
|
|
54
|
+
* Daemon wiring injects createNoOpCapabilityPort() from @comis/core; the
|
|
55
|
+
* live adapter is swapped in elsewhere. The no-op is a real production
|
|
56
|
+
* code path — NOT a transitional shim.
|
|
57
|
+
*/
|
|
58
|
+
toolCapabilityPort: ToolCapabilityPort;
|
|
51
59
|
skillRegistry?: {
|
|
52
60
|
getEligibleSkillNames(): Set<string>;
|
|
53
61
|
initFromSdkSkills(sdkSkills: Array<{
|
|
@@ -70,6 +78,15 @@ export interface ToolAssemblyResult {
|
|
|
70
78
|
deferralResult: ExcludeDeferralResult;
|
|
71
79
|
/** Formatted deferred tools context for dynamic preamble injection. */
|
|
72
80
|
deferredContext: string;
|
|
81
|
+
/**
|
|
82
|
+
* Per-turn capability-index render result.
|
|
83
|
+
* `text` is concatenated into the dynamic preamble; the count fields feed
|
|
84
|
+
* the Pino debug log emitted in `executor-prompt-runner.ts`.
|
|
85
|
+
* When the port returns gate-disabled or all counts are zero, the renderer
|
|
86
|
+
* returns the EMPTY sentinel and `text === ""` filters out via
|
|
87
|
+
* `[...].filter(Boolean)` in the runner.
|
|
88
|
+
*/
|
|
89
|
+
capabilityIndexResult: CapabilityIndexRenderResult;
|
|
73
90
|
/** Session-scoped guide delivery tracking set. */
|
|
74
91
|
deliveredGuides: Set<string>;
|
|
75
92
|
/** Model tier derived from context window: "small" | "medium" | "large". */
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { SettingsManager, } from "@mariozechner/pi-coding-agent";
|
|
17
17
|
import { formatSessionKey, } from "@comis/core";
|
|
18
|
-
import { applyToolDeferral, buildDeferredToolsContext, createDiscoverTool, createAutoDiscoveryStubs, extractRecentlyUsedToolNames, resolveModelTier,
|
|
18
|
+
import { applyToolDeferral, buildDeferredToolsContext, createDiscoverTool, createAutoDiscoveryStubs, extractRecentlyUsedToolNames, resolveModelTier, CORE_TOOLS } from "./tool-deferral.js";
|
|
19
|
+
import { buildCapabilityIndexContext } from "./capability-index-context.js";
|
|
19
20
|
import { getOrCreateDiscoveryTracker } from "./discovery-tracker.js";
|
|
20
21
|
import { getOrCreateTracker, DEFAULT_LIFECYCLE_CONFIG } from "./tool-lifecycle.js";
|
|
21
22
|
import { isAnthropicFamily, isGoogleFamily } from "../provider/capabilities.js";
|
|
@@ -159,6 +160,9 @@ export async function assembleTools(params) {
|
|
|
159
160
|
deliveryMirror: deps.deliveryMirror,
|
|
160
161
|
deliveryMirrorConfig: deps.deliveryMirrorConfig,
|
|
161
162
|
channelMaxChars: deps.getChannelMaxChars?.(msg.channelType),
|
|
163
|
+
// Forward the tool-capability port so prompt-assembly.ts can read
|
|
164
|
+
// `port.isCapabilityIndexEnabled()` for the static-prompt swap gate.
|
|
165
|
+
toolCapabilityPort: deps.toolCapabilityPort,
|
|
162
166
|
},
|
|
163
167
|
msg,
|
|
164
168
|
sessionKey,
|
|
@@ -321,24 +325,22 @@ export async function assembleTools(params) {
|
|
|
321
325
|
const stubs = createAutoDiscoveryStubs(deferralResult.deferredEntries, discoveryTracker, deps.logger);
|
|
322
326
|
mergedCustomTools.push(...stubs);
|
|
323
327
|
}
|
|
324
|
-
// Build deferred context for dynamic preamble injection.
|
|
325
|
-
//
|
|
326
|
-
//
|
|
327
|
-
//
|
|
328
|
-
//
|
|
329
|
-
//
|
|
330
|
-
// deferred tools auto-load on first direct invocation, rather than telling
|
|
331
|
-
// it to call a tool the model can no longer see.
|
|
332
|
-
//
|
|
333
|
-
// resolvedModel is in scope here (param of assembleToolsForAgent, see
|
|
334
|
-
// function signature ~line 143). When undefined (test paths / fallback),
|
|
335
|
-
// useToolSearch defaults to false, preserving backward-compatible
|
|
336
|
-
// discover_tools wording.
|
|
328
|
+
// Build deferred-tools context for dynamic preamble injection (mechanism-neutral).
|
|
329
|
+
// Provider-specific payload reshaping (stripping the client-side discovery
|
|
330
|
+
// tool, appending the server-side tool-search regex tool for Anthropic
|
|
331
|
+
// Sonnet/Opus 4.x) lives entirely in `request-body-injector.ts` and is
|
|
332
|
+
// gated there by a model-id capability check. See tool-deferral.ts JSDoc
|
|
333
|
+
// on `buildDeferredToolsContext` for the rationale.
|
|
337
334
|
let deferredContext = "";
|
|
338
335
|
if (deferralResult.deferredEntries.length > 0) {
|
|
339
|
-
|
|
340
|
-
deferredContext = buildDeferredToolsContext(deferralResult.deferredEntries, { useToolSearch });
|
|
336
|
+
deferredContext = buildDeferredToolsContext(deferralResult.deferredEntries);
|
|
341
337
|
}
|
|
338
|
+
// Per-turn capability index.
|
|
339
|
+
// Lives AFTER applyToolDeferral so the renderer sees the post-partition
|
|
340
|
+
// state (active vs deferred entries). When the port is the no-op, the
|
|
341
|
+
// renderer's gate check still respects port.isCapabilityIndexEnabled();
|
|
342
|
+
// if false, returns EMPTY which the runner filters via .filter(Boolean).
|
|
343
|
+
const capabilityIndexResult = buildCapabilityIndexContext(deferralResult, deps.toolCapabilityPort);
|
|
342
344
|
// -------------------------------------------------------------------
|
|
343
345
|
// 8. JIT guide wrapping, schema pruning, snapshot, normalization, serializer
|
|
344
346
|
// -------------------------------------------------------------------
|
|
@@ -368,6 +370,7 @@ export async function assembleTools(params) {
|
|
|
368
370
|
mergedCustomTools,
|
|
369
371
|
deferralResult,
|
|
370
372
|
deferredContext,
|
|
373
|
+
capabilityIndexResult,
|
|
371
374
|
deliveredGuides,
|
|
372
375
|
modelTier,
|
|
373
376
|
discoveryTracker,
|
|
@@ -35,10 +35,19 @@ import type { AgentToolResult } from "@mariozechner/pi-agent-core";
|
|
|
35
35
|
*
|
|
36
36
|
* - If no guide exists for the tool, returns result unchanged.
|
|
37
37
|
* - If guide was already delivered in this session, returns result unchanged.
|
|
38
|
-
* -
|
|
39
|
-
*
|
|
38
|
+
* - Skips injection when result has isError: true and does NOT mark delivered
|
|
39
|
+
* (so a retry can fire — see regression coverage in `jit-guide-injector.test.ts`).
|
|
40
40
|
* - Logs at INFO level when guide is injected.
|
|
41
41
|
*
|
|
42
|
+
* **Re-injection de-dup contract.** The `deliveredGuides` Set is the single
|
|
43
|
+
* source of truth for which guide ids have been injected within the current
|
|
44
|
+
* scope (per-session by default; cleared on session reset by pi-executor).
|
|
45
|
+
* Within a single turn — even when the same tool fires multiple times via
|
|
46
|
+
* mid-turn discovery / retries — the same guide id is not re-injected
|
|
47
|
+
* because the early-return on `deliveredGuides.has(...)` fires on the
|
|
48
|
+
* second-and-later check. The existing Set IS the per-turn (and per-session)
|
|
49
|
+
* tracker; no second data structure is needed.
|
|
50
|
+
*
|
|
42
51
|
* Note: AgentToolResult does not formally include isError (it is set by
|
|
43
52
|
* the agent-loop on the message level), but some tools (MCP, discovery)
|
|
44
53
|
* include it at runtime. We check for it defensively.
|
|
@@ -42,10 +42,19 @@ const PRIVILEGED_SECTION_KEY = "section:privileged";
|
|
|
42
42
|
*
|
|
43
43
|
* - If no guide exists for the tool, returns result unchanged.
|
|
44
44
|
* - If guide was already delivered in this session, returns result unchanged.
|
|
45
|
-
* -
|
|
46
|
-
*
|
|
45
|
+
* - Skips injection when result has isError: true and does NOT mark delivered
|
|
46
|
+
* (so a retry can fire — see regression coverage in `jit-guide-injector.test.ts`).
|
|
47
47
|
* - Logs at INFO level when guide is injected.
|
|
48
48
|
*
|
|
49
|
+
* **Re-injection de-dup contract.** The `deliveredGuides` Set is the single
|
|
50
|
+
* source of truth for which guide ids have been injected within the current
|
|
51
|
+
* scope (per-session by default; cleared on session reset by pi-executor).
|
|
52
|
+
* Within a single turn — even when the same tool fires multiple times via
|
|
53
|
+
* mid-turn discovery / retries — the same guide id is not re-injected
|
|
54
|
+
* because the early-return on `deliveredGuides.has(...)` fires on the
|
|
55
|
+
* second-and-later check. The existing Set IS the per-turn (and per-session)
|
|
56
|
+
* tracker; no second data structure is needed.
|
|
57
|
+
*
|
|
49
58
|
* Note: AgentToolResult does not formally include isError (it is set by
|
|
50
59
|
* the agent-loop on the message level), but some tools (MCP, discovery)
|
|
51
60
|
* include it at runtime. We check for it defensively.
|
|
@@ -67,6 +76,11 @@ export function wrapToolResultWithGuide(toolName, result, deliveredGuides, logge
|
|
|
67
76
|
const wantsPrivileged = PRIVILEGED_TOOL_SET.has(toolName) &&
|
|
68
77
|
!deliveredGuides.has(PRIVILEGED_SECTION_KEY) &&
|
|
69
78
|
!!SYSTEM_PROMPT_GUIDES["__privileged_tools__"];
|
|
79
|
+
// Re-injection de-dup: when every candidate guide id is already in
|
|
80
|
+
// `deliveredGuides`, none of `wantsTool`/`wantsSection`/`wantsPrivileged`
|
|
81
|
+
// is true and we early-return without appending. This single check is the
|
|
82
|
+
// per-turn (and per-session) de-dup gate — the same `deliveredGuides` Set
|
|
83
|
+
// passed across calls within a turn IS the injectedGuideIds tracker.
|
|
70
84
|
if (!wantsTool && !wantsSection && !wantsPrivileged)
|
|
71
85
|
return result;
|
|
72
86
|
// Skip on error — but DO NOT consume delivery slots so a retry can fire.
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import type { ToolDefinition } from "@mariozechner/pi-coding-agent";
|
|
23
23
|
import type { AuthStorage, ModelRegistry } from "@mariozechner/pi-coding-agent";
|
|
24
|
-
import { type PerAgentConfig, type TypedEventBus, type MemoryPort, type HookRunner, type SecretManager, type EnvelopeConfig, type OutputGuardPort, type InputValidationResult, type InputSecurityGuard, type InjectionRateLimiter, type SenderTrustDisplayConfig } from "@comis/core";
|
|
24
|
+
import { type PerAgentConfig, type TypedEventBus, type MemoryPort, type HookRunner, type SecretManager, type EnvelopeConfig, type OutputGuardPort, type InputValidationResult, type InputSecurityGuard, type InjectionRateLimiter, type SenderTrustDisplayConfig, type ToolCapabilityPort } from "@comis/core";
|
|
25
25
|
import type { ComisLogger } from "@comis/infra";
|
|
26
26
|
import type { AgentTool } from "@mariozechner/pi-agent-core";
|
|
27
27
|
import type { BudgetGuard } from "../budget/budget-guard.js";
|
|
@@ -53,7 +53,7 @@ import type { AgentExecutor } from "./types.js";
|
|
|
53
53
|
*/
|
|
54
54
|
export declare function createBeforeToolCallGuard(stepCounter: StepCounter, budgetGuard: BudgetGuard, circuitBreaker: CircuitBreaker, toolRetryBreaker?: ToolRetryBreaker, messageSendLimiter?: MessageSendLimiter): (context: unknown, _signal?: AbortSignal) => Promise<import("../safety/message-send-limiter.js").MessageSendVerdict | undefined>;
|
|
55
55
|
/**
|
|
56
|
-
* Merge SDK session stats into execution result for token totals
|
|
56
|
+
* Merge SDK session stats into execution result for token totals.
|
|
57
57
|
*
|
|
58
58
|
* Token counts (input, output, cacheRead, cacheWrite, total) are sourced
|
|
59
59
|
* from the SDK's cumulative session stats -- single source of truth.
|
|
@@ -169,6 +169,12 @@ export interface PiExecutorDeps {
|
|
|
169
169
|
embeddingEnqueue?: (entryId: string, content: string) => void;
|
|
170
170
|
/** Optional embedding port for semantic search in discover_tools. */
|
|
171
171
|
embeddingPort?: import("@comis/core").EmbeddingPort;
|
|
172
|
+
/**
|
|
173
|
+
* Tool-capability port for the per-turn capability-index renderer.
|
|
174
|
+
* Daemon wiring injects createNoOpCapabilityPort() from @comis/core
|
|
175
|
+
* until the live adapter ships.
|
|
176
|
+
*/
|
|
177
|
+
toolCapabilityPort: ToolCapabilityPort;
|
|
172
178
|
/** Sender trust display config from AppConfig. */
|
|
173
179
|
senderTrustDisplayConfig?: SenderTrustDisplayConfig;
|
|
174
180
|
/** Documentation config from AppConfig. */
|