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
|
@@ -67,7 +67,7 @@ import { randomUUID } from "node:crypto";
|
|
|
67
67
|
/** Number of turns to restrict breakpoints after server eviction. */
|
|
68
68
|
const EVICTION_COOLDOWN_TURNS = 2;
|
|
69
69
|
// ---------------------------------------------------------------------------
|
|
70
|
-
//
|
|
70
|
+
// Proactive tool-call safety guard
|
|
71
71
|
// ---------------------------------------------------------------------------
|
|
72
72
|
/**
|
|
73
73
|
* Create a beforeToolCall guard that proactively blocks tool execution when
|
|
@@ -124,10 +124,10 @@ export function createBeforeToolCallGuard(stepCounter, budgetGuard, circuitBreak
|
|
|
124
124
|
};
|
|
125
125
|
}
|
|
126
126
|
// ---------------------------------------------------------------------------
|
|
127
|
-
//
|
|
127
|
+
// Session stats delegation helper
|
|
128
128
|
// ---------------------------------------------------------------------------
|
|
129
129
|
/**
|
|
130
|
-
* Merge SDK session stats into execution result for token totals
|
|
130
|
+
* Merge SDK session stats into execution result for token totals.
|
|
131
131
|
*
|
|
132
132
|
* Token counts (input, output, cacheRead, cacheWrite, total) are sourced
|
|
133
133
|
* from the SDK's cumulative session stats -- single source of truth.
|
|
@@ -400,7 +400,7 @@ export function createPiExecutor(config, deps) {
|
|
|
400
400
|
provider: resolvedModel.provider,
|
|
401
401
|
id: resolvedModel.id,
|
|
402
402
|
}) : undefined;
|
|
403
|
-
// f. Execute within session adapter (
|
|
403
|
+
// f. Execute within session adapter (use ephemeral adapter if provided)
|
|
404
404
|
const sessionAdapter = overrides?.ephemeralSessionAdapter ?? deps.sessionAdapter;
|
|
405
405
|
const lockResult = await sessionAdapter.withSession(sessionKey, async (sm) => {
|
|
406
406
|
// Repair orphaned messages
|
|
@@ -450,6 +450,7 @@ export function createPiExecutor(config, deps) {
|
|
|
450
450
|
const stableGetPromptSkillsXml = frozenPromptSkillsXml !== undefined
|
|
451
451
|
? () => frozenPromptSkillsXml
|
|
452
452
|
: deps.getPromptSkillsXml;
|
|
453
|
+
// toolCapabilityPort flows through frozenDeps spread — no explicit re-assignment.
|
|
453
454
|
const frozenDeps = { ...deps, getPromptSkillsXml: stableGetPromptSkillsXml };
|
|
454
455
|
// Tool assembly pipeline: merge, settings, prompt, deferral, JIT, pruning, snapshot, normalization, serializer
|
|
455
456
|
// Extracted to executor-tool-assembly.ts
|
|
@@ -459,7 +460,7 @@ export function createPiExecutor(config, deps) {
|
|
|
459
460
|
resolvedModel, modelCompat, agentId, safetyReinforcement, _directives,
|
|
460
461
|
});
|
|
461
462
|
const { mergedCustomTools, } = toolAssembly;
|
|
462
|
-
const { deferralResult, deferredContext, modelTier, discoveryTracker, settingsManager, resourceLoaderOptions, promptResult, cachedSystemTokensEstimate, } = toolAssembly;
|
|
463
|
+
const { deferralResult, deferredContext, capabilityIndexResult, modelTier, discoveryTracker, settingsManager, resourceLoaderOptions, promptResult, cachedSystemTokensEstimate, } = toolAssembly;
|
|
463
464
|
const currentDiscoveryTracker = toolAssembly.currentDiscoveryTracker;
|
|
464
465
|
const { systemPrompt, systemPromptBlocks, dynamicPreamble, inlineMemory } = promptResult;
|
|
465
466
|
// DAG ingestion hook -- install BEFORE microcompaction
|
|
@@ -537,8 +538,8 @@ export function createPiExecutor(config, deps) {
|
|
|
537
538
|
const messageSendLimiter = createMessageSendLimiter({
|
|
538
539
|
maxSendsPerExecution: deps.maxSendsPerExecution ?? 3,
|
|
539
540
|
});
|
|
540
|
-
//
|
|
541
|
-
//
|
|
541
|
+
// Proactive safety -- block tool execution before it starts when
|
|
542
|
+
// safety limits are already reached. Existing reactive checks in
|
|
542
543
|
// pi-event-bridge remain as fallback for limits crossed during execution.
|
|
543
544
|
// NOTE: beforeToolCall replaces the extension runner's hook. Comis does
|
|
544
545
|
// not load pi-mono extensions, so this override is safe.
|
|
@@ -663,6 +664,18 @@ export function createPiExecutor(config, deps) {
|
|
|
663
664
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
664
665
|
session.agent.transformContext = ceSetup.contextEngine.transformContext;
|
|
665
666
|
}
|
|
667
|
+
// Align register/deregister key shape with
|
|
668
|
+
// BackgroundSessionResolver.formatComposite so production lookups via
|
|
669
|
+
// resolveActiveSession({agentId, channelType, channelId}) find the
|
|
670
|
+
// handle this execute() call registers. session-resolver.test.ts
|
|
671
|
+
// locks the formula — drift on either side breaks that test.
|
|
672
|
+
// NormalizedMessageSchema enforces channelType / channelId are
|
|
673
|
+
// non-empty (z.string().min(1)), so this composition is unconditional.
|
|
674
|
+
const resolverRegisterKey = formatSessionKey({
|
|
675
|
+
tenantId: agentId ?? "default",
|
|
676
|
+
channelId: `${msg.channelType}:${msg.channelId}`,
|
|
677
|
+
userId: msg.channelId,
|
|
678
|
+
});
|
|
666
679
|
// Register active run for mid-execution steering
|
|
667
680
|
if (deps.activeRunRegistry) {
|
|
668
681
|
const handle = {
|
|
@@ -672,9 +685,9 @@ export function createPiExecutor(config, deps) {
|
|
|
672
685
|
isStreaming: () => session.isStreaming,
|
|
673
686
|
isCompacting: () => session.isCompacting,
|
|
674
687
|
};
|
|
675
|
-
const registered = deps.activeRunRegistry.register(
|
|
688
|
+
const registered = deps.activeRunRegistry.register(resolverRegisterKey, handle);
|
|
676
689
|
if (!registered) {
|
|
677
|
-
deps.logger.warn({ sessionKey:
|
|
690
|
+
deps.logger.warn({ sessionKey: resolverRegisterKey, hint: "Session already has an active run; concurrent execution may cause issues", errorKind: "resource" }, "Active run already registered");
|
|
678
691
|
}
|
|
679
692
|
}
|
|
680
693
|
// SDK tool management validation and introspection.
|
|
@@ -748,7 +761,7 @@ export function createPiExecutor(config, deps) {
|
|
|
748
761
|
deps.logger.debug({ err: sdkSkillError, hint: "SDK skill population failed, Comis discovery still active", errorKind: "dependency" }, "SDK skill population non-fatal error");
|
|
749
762
|
}
|
|
750
763
|
// session.sendCustomMessage() is available for operator annotations.
|
|
751
|
-
//
|
|
764
|
+
// Note: appendCustomEntry() is the SessionManager-level API;
|
|
752
765
|
// the AgentSession wrapper exposes this as sendCustomMessage({ customType, content, display, details }).
|
|
753
766
|
// Future commands or hooks can call this to inject custom entries into the JSONL session.
|
|
754
767
|
// Apply command directives (thinking, compact, model, export, fork, branch)
|
|
@@ -1067,7 +1080,7 @@ export function createPiExecutor(config, deps) {
|
|
|
1067
1080
|
const promptRunResult = await runPrompt({
|
|
1068
1081
|
msg, session, config, sessionKey, formattedKey, agentId, result,
|
|
1069
1082
|
executionOverrides, executionStartMs, effectiveTimeout, executionId,
|
|
1070
|
-
bridge, dynamicPreamble, deferredContext, inlineMemory,
|
|
1083
|
+
bridge, dynamicPreamble, deferredContext, capabilityIndexResult, inlineMemory,
|
|
1071
1084
|
systemPrompt,
|
|
1072
1085
|
mergedCustomTools,
|
|
1073
1086
|
cmdResult, sepEnabled, executionPlanRef,
|
|
@@ -1144,7 +1157,7 @@ export function createPiExecutor(config, deps) {
|
|
|
1144
1157
|
// Post-execution cleanup: stats merge, cache metrics, memory persist, session cleanup
|
|
1145
1158
|
// Extracted to executor-post-execution.ts
|
|
1146
1159
|
await postExecution({
|
|
1147
|
-
result, session, sm, config, msg, sessionKey, formattedKey, agentId,
|
|
1160
|
+
result, session, sm, config, msg, sessionKey, formattedKey, resolverRegisterKey, agentId,
|
|
1148
1161
|
executionStartMs, executionId, executionOverrides,
|
|
1149
1162
|
bridge, unsubscribe,
|
|
1150
1163
|
contextEngineRef, ceSetup, streamSetup,
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @module
|
|
10
10
|
*/
|
|
11
|
-
import type { SessionKey, NormalizedMessage, PerAgentConfig, MemoryPort, HookRunner, SecretManager, EnvelopeConfig, WrapExternalContentOptions, TypedEventBus, SenderTrustDisplayConfig, SpawnPacket, DeliveryMirrorPort, ModelOperationType } from "@comis/core";
|
|
11
|
+
import type { SessionKey, NormalizedMessage, PerAgentConfig, MemoryPort, HookRunner, SecretManager, EnvelopeConfig, WrapExternalContentOptions, TypedEventBus, SenderTrustDisplayConfig, SpawnPacket, DeliveryMirrorPort, ModelOperationType, ToolCapabilityPort } from "@comis/core";
|
|
12
12
|
import type { ComisLogger } from "@comis/infra";
|
|
13
13
|
import type { ToolDefinition } from "@mariozechner/pi-coding-agent";
|
|
14
14
|
import type { BootstrapContextFile } from "../bootstrap/types.js";
|
|
@@ -130,6 +130,14 @@ export interface PromptAssemblyParams {
|
|
|
130
130
|
}>;
|
|
131
131
|
/** Platform message character limit for auto verbosity mode. Resolved by caller from channelRegistry. */
|
|
132
132
|
channelMaxChars?: number;
|
|
133
|
+
/**
|
|
134
|
+
* Tool-capability port for the gate flag.
|
|
135
|
+
* Only `port.isCapabilityIndexEnabled()` is read from this file — live-runtime
|
|
136
|
+
* port accessors (skill catalog, connected MCP servers, deferred-tool state)
|
|
137
|
+
* are FORBIDDEN here per the cache-fence invariant. Architecture-grep tests
|
|
138
|
+
* statically enforce this restriction.
|
|
139
|
+
*/
|
|
140
|
+
toolCapabilityPort: ToolCapabilityPort;
|
|
133
141
|
};
|
|
134
142
|
msg: NormalizedMessage;
|
|
135
143
|
sessionKey: SessionKey;
|
|
@@ -331,7 +331,7 @@ export async function assembleExecutionPrompt(params) {
|
|
|
331
331
|
// Consolidated lightContext flag: heartbeat implies light-context regardless
|
|
332
332
|
// of the explicit msg.metadata.lightContext flag. Callers that only set the
|
|
333
333
|
// metadata flag OR only set operationType="heartbeat" produce identical
|
|
334
|
-
// prompt output
|
|
334
|
+
// prompt output.
|
|
335
335
|
const effectiveLightContext = msg.metadata?.lightContext === true || params.operationType === "heartbeat";
|
|
336
336
|
// 2. Load workspace bootstrap files (skip for "none" mode)
|
|
337
337
|
let bootstrapContextFiles = [];
|
|
@@ -522,6 +522,13 @@ export async function assembleExecutionPrompt(params) {
|
|
|
522
522
|
const isOnboarding = await detectOnboardingState(deps.workspaceDir);
|
|
523
523
|
// Shared params for both assembleRichSystemPrompt and assembleRichSystemPromptBlocks.
|
|
524
524
|
// Using a single variable guarantees identity by construction.
|
|
525
|
+
//
|
|
526
|
+
// Hot-flip safety: the capability-index gate value is read once per
|
|
527
|
+
// assembleExecutionPrompt call via
|
|
528
|
+
// `deps.toolCapabilityPort.isCapabilityIndexEnabled()`. The flag is
|
|
529
|
+
// restart-required and stable across the session by config contract, so the
|
|
530
|
+
// cached system-prompt prefix is NOT retroactively rewritten when the
|
|
531
|
+
// underlying YAML changes mid-session.
|
|
525
532
|
const assemblerParams = {
|
|
526
533
|
agentName: config.name,
|
|
527
534
|
promptMode,
|
|
@@ -554,6 +561,13 @@ export async function assembleExecutionPrompt(params) {
|
|
|
554
561
|
subagentRole: undefined, // relocated to dynamic preamble for sub-agent cache sharing
|
|
555
562
|
excludeBootstrapFromContext: true, // BOOTSTRAP.md is either elevated (onboarding) or dead weight (post-onboarding); never useful in Project Context
|
|
556
563
|
workspaceProfile: config.workspace?.profile,
|
|
564
|
+
/**
|
|
565
|
+
* Read once per call. The value is config-derived / restart-required,
|
|
566
|
+
* so it's stable across all turns in this session. Reading it via the
|
|
567
|
+
* port (rather than from config directly) isolates this code from the
|
|
568
|
+
* config-schema shape and matches the live adapter contract.
|
|
569
|
+
*/
|
|
570
|
+
capabilityIndexEnabled: deps.toolCapabilityPort.isCapabilityIndexEnabled(),
|
|
557
571
|
sepEnabled: params.sepEnabled,
|
|
558
572
|
};
|
|
559
573
|
let systemPrompt = assembleRichSystemPrompt(assemblerParams);
|
|
@@ -101,13 +101,16 @@ export declare function resolveModelTier(contextWindow: number): ModelTier;
|
|
|
101
101
|
*/
|
|
102
102
|
export declare function resolveToolCallingTemperature(modelTier: ModelTier): number;
|
|
103
103
|
/**
|
|
104
|
-
* Anthropic models that support server-side
|
|
105
|
-
*
|
|
104
|
+
* Anthropic models that support server-side tool-search via defer_loading.
|
|
105
|
+
* Sonnet 4.x+, Opus 4.x+; NOT Haiku.
|
|
106
106
|
*
|
|
107
|
-
*
|
|
108
|
-
* `
|
|
109
|
-
*
|
|
110
|
-
*
|
|
107
|
+
* **Surviving caller:** `request-body-injector.ts` (the
|
|
108
|
+
* `if (supportsToolSearch(model.id)) {...}` gate inside the Anthropic
|
|
109
|
+
* `onPayload` handler). Used to gate the API-payload reshape that strips
|
|
110
|
+
* the client-side discovery tool, appends the server-side tool-search
|
|
111
|
+
* regex tool, and marks deferred tools `defer_loading: true`. This is a
|
|
112
|
+
* runtime API-payload concern, distinct from the deferred-tool prompt
|
|
113
|
+
* teaching emitted by `buildDeferredToolsContext`.
|
|
111
114
|
*
|
|
112
115
|
* Lowercase-normalize so provider-prefixed model ids
|
|
113
116
|
* (`anthropic/claude-sonnet-4`, `bedrock/anthropic.claude-opus-4`) resolve
|
|
@@ -135,31 +138,19 @@ export declare function resolveToolDescription(tool: ToolDefinition): string;
|
|
|
135
138
|
* Lists deferred tool names and descriptions so the LLM knows what's
|
|
136
139
|
* available behind a discovery mechanism.
|
|
137
140
|
*
|
|
138
|
-
* The
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
* request-body-injector replaces it with the server-side
|
|
147
|
-
* `tool_search_tool_regex` and marks deferred tools `defer_loading: true`,
|
|
148
|
-
* meaning Anthropic auto-loads them on first direct invocation. The
|
|
149
|
-
* teaching string therefore points at direct invocation + tool-search by
|
|
150
|
-
* regex, never at `discover_tools`. Without this conditional, the model
|
|
151
|
-
* reads its own preamble ("call discover_tools") against a tool list that
|
|
152
|
-
* doesn't contain that tool and gives up (production repro).
|
|
141
|
+
* The instruction line is mechanism-neutral: it tells the model these
|
|
142
|
+
* tools are available but not loaded, and points it at "the discovery
|
|
143
|
+
* mechanism available in your active toolspace" without naming a specific
|
|
144
|
+
* tool. Provider-specific payload reshaping (stripping the client-side
|
|
145
|
+
* discovery tool and appending the server-side tool-search regex tool for
|
|
146
|
+
* Anthropic Sonnet/Opus 4.x) lives entirely in `request-body-injector.ts`
|
|
147
|
+
* and is gated by `supportsToolSearch(modelId)`. This separation is
|
|
148
|
+
* enforced by architecture-grep tests.
|
|
153
149
|
*
|
|
154
150
|
* @param entries - Deferred tool entries (remaining after discovery re-inclusion)
|
|
155
|
-
* @param options - Optional flags. `useToolSearch=true` switches the third
|
|
156
|
-
* line to the tool-search-aware variant. Defaults to false (backward-
|
|
157
|
-
* compatible with the discover_tools teaching).
|
|
158
151
|
* @returns XML block string, or empty string when no entries
|
|
159
152
|
*/
|
|
160
|
-
export declare function buildDeferredToolsContext(entries: DeferredToolEntry[]
|
|
161
|
-
useToolSearch?: boolean;
|
|
162
|
-
}): string;
|
|
153
|
+
export declare function buildDeferredToolsContext(entries: DeferredToolEntry[]): string;
|
|
163
154
|
/**
|
|
164
155
|
* Apply unified tool deferral: rule-based, budget-based, small-model,
|
|
165
156
|
* lifecycle merge, and operator overrides.
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* @module
|
|
16
16
|
*/
|
|
17
17
|
import { getToolMetadata } from "@comis/core";
|
|
18
|
-
import { extractMcpServerName } from "
|
|
18
|
+
import { extractMcpServerName } from "@comis/shared";
|
|
19
19
|
import { PRIVILEGED_TOOL_NAMES } from "../bootstrap/sections/tooling-sections.js";
|
|
20
20
|
import { LEAN_TOOL_DESCRIPTIONS } from "../bootstrap/sections/tool-descriptions.js";
|
|
21
21
|
// ---------------------------------------------------------------------------
|
|
@@ -96,13 +96,16 @@ export function resolveToolCallingTemperature(modelTier) {
|
|
|
96
96
|
return modelTier === "small" ? 0.0 : 0.1;
|
|
97
97
|
}
|
|
98
98
|
/**
|
|
99
|
-
* Anthropic models that support server-side
|
|
100
|
-
*
|
|
99
|
+
* Anthropic models that support server-side tool-search via defer_loading.
|
|
100
|
+
* Sonnet 4.x+, Opus 4.x+; NOT Haiku.
|
|
101
101
|
*
|
|
102
|
-
*
|
|
103
|
-
* `
|
|
104
|
-
*
|
|
105
|
-
*
|
|
102
|
+
* **Surviving caller:** `request-body-injector.ts` (the
|
|
103
|
+
* `if (supportsToolSearch(model.id)) {...}` gate inside the Anthropic
|
|
104
|
+
* `onPayload` handler). Used to gate the API-payload reshape that strips
|
|
105
|
+
* the client-side discovery tool, appends the server-side tool-search
|
|
106
|
+
* regex tool, and marks deferred tools `defer_loading: true`. This is a
|
|
107
|
+
* runtime API-payload concern, distinct from the deferred-tool prompt
|
|
108
|
+
* teaching emitted by `buildDeferredToolsContext`.
|
|
106
109
|
*
|
|
107
110
|
* Lowercase-normalize so provider-prefixed model ids
|
|
108
111
|
* (`anthropic/claude-sonnet-4`, `bedrock/anthropic.claude-opus-4`) resolve
|
|
@@ -169,32 +172,21 @@ export function resolveToolDescription(tool) {
|
|
|
169
172
|
* Lists deferred tool names and descriptions so the LLM knows what's
|
|
170
173
|
* available behind a discovery mechanism.
|
|
171
174
|
*
|
|
172
|
-
* The
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
* request-body-injector replaces it with the server-side
|
|
181
|
-
* `tool_search_tool_regex` and marks deferred tools `defer_loading: true`,
|
|
182
|
-
* meaning Anthropic auto-loads them on first direct invocation. The
|
|
183
|
-
* teaching string therefore points at direct invocation + tool-search by
|
|
184
|
-
* regex, never at `discover_tools`. Without this conditional, the model
|
|
185
|
-
* reads its own preamble ("call discover_tools") against a tool list that
|
|
186
|
-
* doesn't contain that tool and gives up (production repro).
|
|
175
|
+
* The instruction line is mechanism-neutral: it tells the model these
|
|
176
|
+
* tools are available but not loaded, and points it at "the discovery
|
|
177
|
+
* mechanism available in your active toolspace" without naming a specific
|
|
178
|
+
* tool. Provider-specific payload reshaping (stripping the client-side
|
|
179
|
+
* discovery tool and appending the server-side tool-search regex tool for
|
|
180
|
+
* Anthropic Sonnet/Opus 4.x) lives entirely in `request-body-injector.ts`
|
|
181
|
+
* and is gated by `supportsToolSearch(modelId)`. This separation is
|
|
182
|
+
* enforced by architecture-grep tests.
|
|
187
183
|
*
|
|
188
184
|
* @param entries - Deferred tool entries (remaining after discovery re-inclusion)
|
|
189
|
-
* @param options - Optional flags. `useToolSearch=true` switches the third
|
|
190
|
-
* line to the tool-search-aware variant. Defaults to false (backward-
|
|
191
|
-
* compatible with the discover_tools teaching).
|
|
192
185
|
* @returns XML block string, or empty string when no entries
|
|
193
186
|
*/
|
|
194
|
-
export function buildDeferredToolsContext(entries
|
|
187
|
+
export function buildDeferredToolsContext(entries) {
|
|
195
188
|
if (entries.length === 0)
|
|
196
189
|
return "";
|
|
197
|
-
const useToolSearch = options?.useToolSearch === true;
|
|
198
190
|
// Separate MCP tools (group by server) from non-MCP tools (individual listing)
|
|
199
191
|
const mcpByServer = new Map();
|
|
200
192
|
const nonMcpEntries = [];
|
|
@@ -220,9 +212,9 @@ export function buildDeferredToolsContext(entries, options) {
|
|
|
220
212
|
const shortNames = tools.map(t => t.name.startsWith(prefix) ? t.name.slice(prefix.length) : t.name);
|
|
221
213
|
lines.push(`[${server}] (${tools.length} tools): ${shortNames.join(", ")}`);
|
|
222
214
|
}
|
|
223
|
-
const instruction =
|
|
224
|
-
|
|
225
|
-
|
|
215
|
+
const instruction = "These tools are connected but not currently loaded into your active context. " +
|
|
216
|
+
"To use one, invoke the discovery mechanism available in your active toolspace, " +
|
|
217
|
+
"then call the loaded tool with the appropriate arguments.";
|
|
226
218
|
return [
|
|
227
219
|
"<deferred-tools>",
|
|
228
220
|
"The following tools are available but not loaded.",
|
|
@@ -428,7 +420,7 @@ function structuredSearch(deferredTools, query, maxResults) {
|
|
|
428
420
|
if (prefixMatches.length > 0)
|
|
429
421
|
return prefixMatches;
|
|
430
422
|
}
|
|
431
|
-
// Mode 4: Server name match (e.g.,
|
|
423
|
+
// Mode 4: Server name match (e.g., bare server token -> all mcp__<server>--* tools)
|
|
432
424
|
const serverPrefix = `mcp__${q}--`;
|
|
433
425
|
const serverMatches = deferredTools.filter(t => t.name.toLowerCase().startsWith(serverPrefix));
|
|
434
426
|
if (serverMatches.length > 0)
|
|
@@ -622,7 +614,7 @@ export function createDiscoverTool(deferredEntries, logger, embeddingPort, score
|
|
|
622
614
|
return {
|
|
623
615
|
content: [{
|
|
624
616
|
type: "text",
|
|
625
|
-
text: "No matching tools found. Try an exact tool name, MCP server name
|
|
617
|
+
text: "No matching tools found. Try an exact tool name, MCP server name, or select:tool1,tool2 syntax.",
|
|
626
618
|
}],
|
|
627
619
|
isError: false,
|
|
628
620
|
details: undefined,
|
|
@@ -648,12 +640,11 @@ export function createDiscoverTool(deferredEntries, logger, embeddingPort, score
|
|
|
648
640
|
* Match modes (checked in order, first non-empty wins):
|
|
649
641
|
* 1. Exact name match (case-insensitive) against the full query.
|
|
650
642
|
* 2. `mcp__` / `mcp:` prefix match against the full query.
|
|
651
|
-
* 3. Bare server-name match on full query (
|
|
643
|
+
* 3. Bare server-name match on full query (e.g., bare server token -> all `mcp__<server>--*`).
|
|
652
644
|
* 4. Per-token server-name fallback: for multi-word queries like
|
|
653
|
-
* `"
|
|
654
|
-
* potential MCP server name. Catches the
|
|
655
|
-
*
|
|
656
|
-
* `{query: "yfinance"}`.
|
|
645
|
+
* `"<server> <verb>"`, check each whitespace-separated token as a
|
|
646
|
+
* potential MCP server name. Catches the case where the agent emits
|
|
647
|
+
* `{query: "<server> <verb>"}` rather than just `{query: "<server>"}`.
|
|
657
648
|
*/
|
|
658
649
|
function findActiveToolMatches(query, activeToolNames) {
|
|
659
650
|
const q = query.toLowerCase().trim();
|
|
@@ -679,7 +670,7 @@ function findActiveToolMatches(query, activeToolNames) {
|
|
|
679
670
|
// Mode 4: per-token server fallback for multi-word queries.
|
|
680
671
|
// Each whitespace-separated token is probed as a server name. The first
|
|
681
672
|
// token that resolves to >= 1 active tool wins. This handles the common
|
|
682
|
-
// "
|
|
673
|
+
// "<server> <verb>" pattern like "<bare-server-token> <verb>".
|
|
683
674
|
const tokens = q.split(/\s+/).filter(t => /^[a-z0-9_-]+$/.test(t));
|
|
684
675
|
for (const token of tokens) {
|
|
685
676
|
const tokenServerPrefix = `mcp__${token}--`;
|
|
@@ -113,7 +113,7 @@ export function registerCustomProviders(registry, entries, secretManager, logger
|
|
|
113
113
|
if (isBuiltInType && providerName !== entry.type) {
|
|
114
114
|
providerAliases.set(providerName, entry.type);
|
|
115
115
|
}
|
|
116
|
-
//
|
|
116
|
+
// Catalog-aware model enrichment.
|
|
117
117
|
//
|
|
118
118
|
// Before computing customModels, decide whether to inherit the full
|
|
119
119
|
// pi-ai catalog or to enrich the user's sparse list with catalog
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { getModels, getProviders } from "@mariozechner/pi-ai";
|
|
16
16
|
// ---------------------------------------------------------------------------
|
|
17
|
-
// Catalog-driven endpoint resolution
|
|
17
|
+
// Catalog-driven endpoint resolution
|
|
18
18
|
// ---------------------------------------------------------------------------
|
|
19
19
|
/**
|
|
20
20
|
* Native pi-ai providers from the live catalog. Used to source baseUrls
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tool retry circuit breaker: per-tool-signature consecutive failure tracking.
|
|
3
3
|
*
|
|
4
|
-
* Prevents infinite retry loops (
|
|
4
|
+
* Prevents infinite retry loops (the original repro: 48-call MCP-server retry incident) by blocking
|
|
5
5
|
* tool calls after repeated failures and providing actionable LLM guidance with
|
|
6
6
|
* alternative tool suggestions.
|
|
7
7
|
*
|
|
@@ -29,6 +29,16 @@ export interface ToolRetryBreakerConfig {
|
|
|
29
29
|
/** Max consecutive same-error-class failures (any args) before blocking.
|
|
30
30
|
* Stricter than args-based because same error + different args = stronger stuck signal. */
|
|
31
31
|
maxConsecutiveErrorPatterns?: number;
|
|
32
|
+
/**
|
|
33
|
+
* Operator-supplied tool-alternative map. Keys are tool-name prefixes
|
|
34
|
+
* (e.g., `"mcp__finance-data"`); values are arrays of suggested alternative
|
|
35
|
+
* tool names. Used in block reasons to guide the LLM toward working tools.
|
|
36
|
+
*
|
|
37
|
+
* Defaults to an empty map (no alternatives suggested). The codebase MUST
|
|
38
|
+
* NOT ship hardcoded MCP server names — operators opt in by populating
|
|
39
|
+
* this map in their breaker config.
|
|
40
|
+
*/
|
|
41
|
+
toolAlternatives?: Record<string, readonly string[]>;
|
|
32
42
|
}
|
|
33
43
|
/** Tool retry breaker interface -- tracks per-tool-signature failures. */
|
|
34
44
|
export interface ToolRetryBreaker {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Tool retry circuit breaker: per-tool-signature consecutive failure tracking.
|
|
4
4
|
*
|
|
5
|
-
* Prevents infinite retry loops (
|
|
5
|
+
* Prevents infinite retry loops (the original repro: 48-call MCP-server retry incident) by blocking
|
|
6
6
|
* tool calls after repeated failures and providing actionable LLM guidance with
|
|
7
7
|
* alternative tool suggestions.
|
|
8
8
|
*
|
|
@@ -17,16 +17,6 @@
|
|
|
17
17
|
* @module
|
|
18
18
|
*/
|
|
19
19
|
// ---------------------------------------------------------------------------
|
|
20
|
-
// Alternative tool mapping (hardcoded v1)
|
|
21
|
-
// ---------------------------------------------------------------------------
|
|
22
|
-
/**
|
|
23
|
-
* Maps tool name prefixes to alternative tools that can serve similar purposes.
|
|
24
|
-
* Used in block reasons to guide the LLM toward working alternatives.
|
|
25
|
-
*/
|
|
26
|
-
const TOOL_ALTERNATIVES = {
|
|
27
|
-
"mcp__yfinance": ["web_search", "mcp__tavily--tavily-search", "web_fetch"],
|
|
28
|
-
};
|
|
29
|
-
// ---------------------------------------------------------------------------
|
|
30
20
|
// Error tag extraction
|
|
31
21
|
// ---------------------------------------------------------------------------
|
|
32
22
|
/**
|
|
@@ -154,17 +144,6 @@ function fingerprint(toolName, args) {
|
|
|
154
144
|
const sortedArgs = JSON.stringify(Object.fromEntries(Object.entries(args).sort()));
|
|
155
145
|
return `${toolName}::${sortedArgs}`;
|
|
156
146
|
}
|
|
157
|
-
/**
|
|
158
|
-
* Find alternative tools for a given tool name by prefix matching.
|
|
159
|
-
* @returns Array of alternative tool names, empty if none known.
|
|
160
|
-
*/
|
|
161
|
-
function findAlternatives(toolName) {
|
|
162
|
-
for (const [prefix, alts] of Object.entries(TOOL_ALTERNATIVES)) {
|
|
163
|
-
if (toolName.startsWith(prefix))
|
|
164
|
-
return alts;
|
|
165
|
-
}
|
|
166
|
-
return [];
|
|
167
|
-
}
|
|
168
147
|
/**
|
|
169
148
|
* When tool failures are caused by the macOS sandbox-exec profile denying writes
|
|
170
149
|
* to protected paths (~/.comis/skills/, global node_modules, ~/.gitconfig,
|
|
@@ -246,6 +225,7 @@ function buildBlockReason(toolName, count, lastError, alternatives, isToolLevel)
|
|
|
246
225
|
export function createToolRetryBreaker(config) {
|
|
247
226
|
const { maxConsecutiveFailures, maxToolFailures, suggestAlternatives } = config;
|
|
248
227
|
const maxErrorPatterns = config.maxConsecutiveErrorPatterns ?? 2;
|
|
228
|
+
const toolAlternatives = config.toolAlternatives ?? {};
|
|
249
229
|
// Per-fingerprint (tool+args) consecutive failure tracking
|
|
250
230
|
const signatureFailures = new Map();
|
|
251
231
|
// Per-tool-name total failure count (across all args)
|
|
@@ -254,6 +234,23 @@ export function createToolRetryBreaker(config) {
|
|
|
254
234
|
const blockedTools = new Set();
|
|
255
235
|
// Per-error-pattern consecutive failure tracking (keyed by `${toolName}::err::${errorTag}`)
|
|
256
236
|
const errorPatternFailures = new Map();
|
|
237
|
+
/**
|
|
238
|
+
* Find alternative tools for a given tool name by prefix matching against
|
|
239
|
+
* `config.toolAlternatives`. Closed-over the factory's `toolAlternatives`
|
|
240
|
+
* local; defaults to no alternatives when the config field is omitted.
|
|
241
|
+
* Spread to a fresh mutable array so the readonly-input / mutable-output
|
|
242
|
+
* contract documented in `ToolRetryVerdict.alternatives?: string[]` is
|
|
243
|
+
* preserved.
|
|
244
|
+
*
|
|
245
|
+
* @returns Array of alternative tool names, empty if no prefix match.
|
|
246
|
+
*/
|
|
247
|
+
function findAlternatives(toolName) {
|
|
248
|
+
for (const [prefix, alts] of Object.entries(toolAlternatives)) {
|
|
249
|
+
if (toolName.startsWith(prefix))
|
|
250
|
+
return [...alts];
|
|
251
|
+
}
|
|
252
|
+
return [];
|
|
253
|
+
}
|
|
257
254
|
return {
|
|
258
255
|
beforeToolCall(toolName, args) {
|
|
259
256
|
// Check tool-level block first (all args blocked)
|
|
@@ -30,11 +30,25 @@ export interface ComisSessionManagerDeps {
|
|
|
30
30
|
* Session metadata written as a companion file alongside the JSONL.
|
|
31
31
|
* The SDK controls the JSONL format, so enrichment data (traceId, runId, session_end)
|
|
32
32
|
* is stored in `_session-metadata.json` next to the `.jsonl` file.
|
|
33
|
+
*
|
|
34
|
+
* `traceId` and `runId` are deliberately distinct identifiers:
|
|
35
|
+
* - `traceId` is the request-scope AsyncLocalStorage value set by
|
|
36
|
+
* `runWithContext` at the channel boundary (channels/.../execution-execute.ts).
|
|
37
|
+
* The Pino tracing mixin (infra/.../log-fields.ts) injects it into every
|
|
38
|
+
* daemon log line, so an operator can grep daemon.log for this exact value
|
|
39
|
+
* to find every log entry produced while handling this turn.
|
|
40
|
+
* - `runId` is the executor-scope UUID minted per `executor.execute()` call
|
|
41
|
+
* in pi-executor.ts. It keys cost-tracker / token_usage rows in the
|
|
42
|
+
* observability store.
|
|
43
|
+
*
|
|
44
|
+
* They are 1:1 in the steady-state interactive path (one inbound message →
|
|
45
|
+
* one execution), but heartbeat and sub-agent paths can fan out a single
|
|
46
|
+
* trace into multiple executions.
|
|
33
47
|
*/
|
|
34
48
|
export interface SessionMetadata {
|
|
35
|
-
/**
|
|
49
|
+
/** Request-scope trace ID from runWithContext; matches traceId in daemon.log. */
|
|
36
50
|
traceId?: string;
|
|
37
|
-
/**
|
|
51
|
+
/** Executor-scope run ID; keys cost-tracker / token_usage rows. */
|
|
38
52
|
runId?: string;
|
|
39
53
|
/** Session end marker with completion details */
|
|
40
54
|
sessionEnd?: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pi-mono adapter wrappers for sub-agent ephemeral sessions
|
|
2
|
+
* Pi-mono adapter wrappers for sub-agent ephemeral sessions.
|
|
3
3
|
*
|
|
4
4
|
* Provides `createEphemeralComisSessionManager()` — a zero-persistence
|
|
5
5
|
* ComisSessionManager whose `withSession` uses `SessionManager.inMemory()`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
/**
|
|
3
|
-
* Pi-mono adapter wrappers for sub-agent ephemeral sessions
|
|
3
|
+
* Pi-mono adapter wrappers for sub-agent ephemeral sessions.
|
|
4
4
|
*
|
|
5
5
|
* Provides `createEphemeralComisSessionManager()` — a zero-persistence
|
|
6
6
|
* ComisSessionManager whose `withSession` uses `SessionManager.inMemory()`
|
|
@@ -51,10 +51,10 @@ export function createEphemeralComisSessionManager(cwd) {
|
|
|
51
51
|
// No-op: no companion file for in-memory sessions
|
|
52
52
|
},
|
|
53
53
|
getSessionPath() {
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
//
|
|
54
|
+
// Wire-edge diagnostic: ephemeral sub-agent sessions never persist a
|
|
55
|
+
// JSONL file, so there is no path to return. Empty string signals
|
|
56
|
+
// "no persisted file"; the bridge's wire-diff hook short-circuits when
|
|
57
|
+
// jsonlPath.length === 0.
|
|
58
58
|
return "";
|
|
59
59
|
},
|
|
60
60
|
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace-internal data env resolver.
|
|
3
|
+
*
|
|
4
|
+
* Returns environment variables for python/matplotlib subprocesses that
|
|
5
|
+
* derive ALL paths from `workspaceDir`. Avoids slow pip installs in the
|
|
6
|
+
* chart hot path and matplotlib Fontconfig errors from a non-writable
|
|
7
|
+
* default cache dir.
|
|
8
|
+
*
|
|
9
|
+
* This file contains no host-env reads. Subprocesses inheriting the
|
|
10
|
+
* daemon's full environment can pick up host paths (e.g.
|
|
11
|
+
* `/root/.cache/matplotlib`) that fail under read-only systemd hardening
|
|
12
|
+
* (`ProtectSystem=strict`) and leak host PATH into the agent's tool
|
|
13
|
+
* execution.
|
|
14
|
+
*
|
|
15
|
+
* matplotlib + python deps install into the agent workspace's `venv/`.
|
|
16
|
+
* The Dockerfile pre-warms the default workspace's venv at image build
|
|
17
|
+
* time so first-chart latency drops; subsequent chart calls reuse the
|
|
18
|
+
* venv. Full Docker image size goes up (acceptable trade-off).
|
|
19
|
+
*
|
|
20
|
+
* Mirrors workspace-resolver.ts's safePath + workspaceDir precedent
|
|
21
|
+
* (no path.join, no host-env reads).
|
|
22
|
+
*
|
|
23
|
+
* @module
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Resolve workspace-internal env vars for python/matplotlib subprocesses.
|
|
27
|
+
*
|
|
28
|
+
* The returned record is intended to be MERGED over an existing subprocess
|
|
29
|
+
* env at the call site (e.g. exec-tool's `{ ...baseEnv, ...resolveDataEnv(...) }`),
|
|
30
|
+
* so the workspace-internal values win on collision and the host PATH /
|
|
31
|
+
* cache dirs are not surfaced inside the subprocess.
|
|
32
|
+
*
|
|
33
|
+
* @param opts.workspaceDir - Absolute path to the agent workspace.
|
|
34
|
+
* @returns env-var record suitable for `child_process.spawn(..., { env })`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function resolveDataEnv(opts: {
|
|
37
|
+
workspaceDir: string;
|
|
38
|
+
}): Record<string, string>;
|