comisai 1.0.34 → 1.0.36
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.d.ts +11 -1
- package/node_modules/@comis/agent/dist/background/auto-background-middleware.js +21 -4
- package/node_modules/@comis/agent/dist/background/background-task-manager.d.ts +2 -2
- package/node_modules/@comis/agent/dist/background/background-task-manager.js +61 -20
- package/node_modules/@comis/agent/dist/background/background-task-persistence.js +10 -3
- package/node_modules/@comis/agent/dist/background/background-task-types.d.ts +10 -3
- package/node_modules/@comis/agent/dist/background/background-task-types.js +1 -1
- package/node_modules/@comis/agent/dist/background/completion-formatter.d.ts +39 -0
- package/node_modules/@comis/agent/dist/background/completion-formatter.js +77 -0
- package/node_modules/@comis/agent/dist/background/completion-runner.d.ts +53 -0
- package/node_modules/@comis/agent/dist/background/completion-runner.js +151 -0
- package/node_modules/@comis/agent/dist/background/index.d.ts +4 -0
- package/node_modules/@comis/agent/dist/background/index.js +2 -0
- package/node_modules/@comis/agent/dist/bridge/bridge-metrics.d.ts +17 -2
- package/node_modules/@comis/agent/dist/bridge/bridge-metrics.js +14 -2
- package/node_modules/@comis/agent/dist/bridge/pi-event-bridge.d.ts +23 -23
- package/node_modules/@comis/agent/dist/bridge/pi-event-bridge.js +72 -60
- package/node_modules/@comis/agent/dist/bridge/thinking-block-hash-invariant.d.ts +6 -7
- package/node_modules/@comis/agent/dist/bridge/thinking-block-hash-invariant.js +24 -25
- package/node_modules/@comis/agent/dist/budget/cost-tracker.d.ts +1 -1
- package/node_modules/@comis/agent/dist/context-engine/constants.d.ts +5 -5
- package/node_modules/@comis/agent/dist/context-engine/constants.js +12 -12
- package/node_modules/@comis/agent/dist/context-engine/context-engine.js +13 -4
- package/node_modules/@comis/agent/dist/context-engine/dag-annotator.d.ts +1 -2
- package/node_modules/@comis/agent/dist/context-engine/dag-annotator.js +1 -2
- package/node_modules/@comis/agent/dist/context-engine/llm-compaction.js +20 -16
- package/node_modules/@comis/agent/dist/context-engine/rehydration.js +6 -6
- package/node_modules/@comis/agent/dist/context-engine/signature-replay-scrubber.d.ts +12 -12
- package/node_modules/@comis/agent/dist/context-engine/signature-replay-scrubber.js +36 -22
- package/node_modules/@comis/agent/dist/context-engine/types-core.d.ts +15 -0
- package/node_modules/@comis/agent/dist/executor/cache-break-detection.d.ts +6 -6
- package/node_modules/@comis/agent/dist/executor/cache-break-detection.js +8 -8
- package/node_modules/@comis/agent/dist/executor/executor-context-engine-setup.d.ts +16 -0
- package/node_modules/@comis/agent/dist/executor/executor-context-engine-setup.js +46 -5
- package/node_modules/@comis/agent/dist/executor/executor-post-execution.d.ts +30 -0
- package/node_modules/@comis/agent/dist/executor/executor-post-execution.js +17 -1
- package/node_modules/@comis/agent/dist/executor/executor-prompt-runner.js +1 -1
- package/node_modules/@comis/agent/dist/executor/executor-response-filter.d.ts +7 -6
- package/node_modules/@comis/agent/dist/executor/executor-response-filter.js +9 -42
- package/node_modules/@comis/agent/dist/executor/executor-tool-assembly.js +2 -3
- package/node_modules/@comis/agent/dist/executor/gemini-cache-injector.d.ts +2 -2
- package/node_modules/@comis/agent/dist/executor/gemini-cache-injector.js +4 -4
- package/node_modules/@comis/agent/dist/executor/phase-filter.d.ts +2 -2
- package/node_modules/@comis/agent/dist/executor/phase-filter.js +5 -7
- package/node_modules/@comis/agent/dist/executor/pi-executor.d.ts +13 -0
- package/node_modules/@comis/agent/dist/executor/pi-executor.js +71 -6
- package/node_modules/@comis/agent/dist/executor/post-batch-continuation.js +7 -7
- package/node_modules/@comis/agent/dist/executor/stream-wrappers/request-body-injector.d.ts +1 -1
- package/node_modules/@comis/agent/dist/executor/stream-wrappers/request-body-injector.js +1 -1
- package/node_modules/@comis/agent/dist/executor/tool-deferral.d.ts +2 -2
- package/node_modules/@comis/agent/dist/executor/tool-deferral.js +7 -7
- package/node_modules/@comis/agent/dist/index.d.ts +17 -0
- package/node_modules/@comis/agent/dist/index.js +32 -11
- package/node_modules/@comis/agent/dist/model/auth-provider.d.ts +25 -2
- package/node_modules/@comis/agent/dist/model/auth-provider.js +6 -0
- package/node_modules/@comis/agent/dist/model/compaction-model-resolver.d.ts +3 -3
- package/node_modules/@comis/agent/dist/model/compaction-model-resolver.js +3 -3
- package/node_modules/@comis/agent/dist/model/oauth-credential-store-file.d.ts +37 -0
- package/node_modules/@comis/agent/dist/model/oauth-credential-store-file.js +279 -0
- package/node_modules/@comis/agent/dist/model/oauth-credential-store-selector.d.ts +49 -0
- package/node_modules/@comis/agent/dist/model/oauth-credential-store-selector.js +50 -0
- package/node_modules/@comis/agent/dist/model/oauth-device-code.d.ts +57 -0
- package/node_modules/@comis/agent/dist/model/oauth-device-code.js +302 -0
- package/node_modules/@comis/agent/dist/model/oauth-env.d.ts +33 -0
- package/node_modules/@comis/agent/dist/model/oauth-env.js +38 -0
- package/node_modules/@comis/agent/dist/model/oauth-errors.d.ts +41 -0
- package/node_modules/@comis/agent/dist/model/oauth-errors.js +88 -0
- package/node_modules/@comis/agent/dist/model/oauth-identity.d.ts +53 -0
- package/node_modules/@comis/agent/dist/model/oauth-identity.js +141 -0
- package/node_modules/@comis/agent/dist/model/oauth-login-runner.d.ts +99 -0
- package/node_modules/@comis/agent/dist/model/oauth-login-runner.js +374 -0
- package/node_modules/@comis/agent/dist/model/oauth-tls-preflight.d.ts +58 -0
- package/node_modules/@comis/agent/dist/model/oauth-tls-preflight.js +82 -0
- package/node_modules/@comis/agent/dist/model/oauth-token-manager.d.ts +86 -16
- package/node_modules/@comis/agent/dist/model/oauth-token-manager.js +961 -66
- package/node_modules/@comis/agent/dist/model/operation-model-defaults.d.ts +9 -4
- package/node_modules/@comis/agent/dist/model/operation-model-defaults.js +36 -9
- package/node_modules/@comis/agent/dist/model/resolve-provider-api-key.d.ts +48 -0
- package/node_modules/@comis/agent/dist/model/resolve-provider-api-key.js +66 -0
- package/node_modules/@comis/agent/dist/provider/capabilities.d.ts +5 -5
- package/node_modules/@comis/agent/dist/provider/capabilities.js +10 -23
- package/node_modules/@comis/agent/dist/safety/tool-output-safety.js +3 -3
- package/node_modules/@comis/agent/dist/session/comis-session-manager.d.ts +1 -1
- package/node_modules/@comis/agent/dist/session/comis-session-manager.js +1 -1
- package/node_modules/@comis/agent/dist/spawn/narrative-caster.d.ts +10 -0
- package/node_modules/@comis/agent/dist/spawn/narrative-caster.js +5 -1
- package/node_modules/@comis/agent/package.json +1 -1
- package/node_modules/@comis/channels/dist/email/email-adapter.js +6 -6
- package/node_modules/@comis/channels/dist/email/imap-lifecycle.js +7 -7
- package/node_modules/@comis/channels/dist/shared/deliver-to-channel.js +12 -10
- package/node_modules/@comis/channels/dist/telegram/telegram-adapter.js +1 -1
- package/node_modules/@comis/channels/package.json +1 -1
- package/node_modules/@comis/cli/dist/cli.js +2 -0
- package/node_modules/@comis/cli/dist/commands/agent.d.ts +3 -3
- package/node_modules/@comis/cli/dist/commands/agent.js +46 -3
- package/node_modules/@comis/cli/dist/commands/auth.d.ts +37 -0
- package/node_modules/@comis/cli/dist/commands/auth.js +433 -0
- package/node_modules/@comis/cli/dist/commands/doctor.d.ts +4 -1
- package/node_modules/@comis/cli/dist/commands/doctor.js +20 -5
- package/node_modules/@comis/cli/dist/doctor/checks/oauth-health.d.ts +39 -0
- package/node_modules/@comis/cli/dist/doctor/checks/oauth-health.js +399 -0
- package/node_modules/@comis/cli/dist/doctor/types.d.ts +19 -0
- package/node_modules/@comis/cli/dist/index.d.ts +1 -0
- package/node_modules/@comis/cli/dist/index.js +10 -4
- package/node_modules/@comis/cli/dist/output/relative-time.d.ts +23 -0
- package/node_modules/@comis/cli/dist/output/relative-time.js +36 -0
- package/node_modules/@comis/cli/dist/wizard/non-interactive.js +17 -8
- package/node_modules/@comis/cli/dist/wizard/steps/03-provider.js +2 -1
- package/node_modules/@comis/cli/dist/wizard/steps/04-credentials.js +223 -34
- package/node_modules/@comis/cli/dist/wizard/steps/10-write-config.js +14 -0
- package/node_modules/@comis/cli/dist/wizard/steps/11-daemon-start.js +3 -3
- package/node_modules/@comis/cli/dist/wizard/types.d.ts +7 -0
- package/node_modules/@comis/cli/package.json +1 -1
- package/node_modules/@comis/core/dist/bootstrap.d.ts +1 -1
- package/node_modules/@comis/core/dist/config/env-substitution.d.ts +66 -0
- package/node_modules/@comis/core/dist/config/env-substitution.js +115 -0
- package/node_modules/@comis/core/dist/config/index.d.ts +3 -1
- package/node_modules/@comis/core/dist/config/index.js +2 -1
- package/node_modules/@comis/core/dist/config/loader.js +61 -0
- package/node_modules/@comis/core/dist/config/managed-sections.d.ts +3 -3
- package/node_modules/@comis/core/dist/config/managed-sections.js +10 -5
- package/node_modules/@comis/core/dist/config/schema-agent.d.ts +4 -0
- package/node_modules/@comis/core/dist/config/schema-agent.js +16 -1
- package/node_modules/@comis/core/dist/config/schema-background-tasks.d.ts +7 -0
- package/node_modules/@comis/core/dist/config/schema-background-tasks.js +7 -0
- package/node_modules/@comis/core/dist/config/schema-delivery.d.ts +2 -0
- package/node_modules/@comis/core/dist/config/schema-delivery.js +2 -0
- package/node_modules/@comis/core/dist/config/schema-gemini-cache.d.ts +0 -2
- package/node_modules/@comis/core/dist/config/schema-gemini-cache.js +0 -2
- package/node_modules/@comis/core/dist/config/schema-oauth.d.ts +23 -0
- package/node_modules/@comis/core/dist/config/schema-oauth.js +19 -0
- package/node_modules/@comis/core/dist/config/schema-skills.d.ts +6 -8
- package/node_modules/@comis/core/dist/config/schema-skills.js +3 -4
- package/node_modules/@comis/core/dist/config/schema.d.ts +10 -0
- package/node_modules/@comis/core/dist/config/schema.js +3 -0
- package/node_modules/@comis/core/dist/domain/background-task-origin.d.ts +39 -0
- package/node_modules/@comis/core/dist/domain/background-task-origin.js +39 -0
- package/node_modules/@comis/core/dist/event-bus/events-infra.d.ts +71 -2
- package/node_modules/@comis/core/dist/exports/config.d.ts +2 -2
- package/node_modules/@comis/core/dist/exports/config.js +1 -1
- package/node_modules/@comis/core/dist/exports/domain.d.ts +2 -0
- package/node_modules/@comis/core/dist/exports/domain.js +1 -0
- 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/delivery-queue.d.ts +23 -0
- package/node_modules/@comis/core/dist/ports/delivery-queue.js +2 -0
- package/node_modules/@comis/core/dist/ports/index.d.ts +2 -0
- package/node_modules/@comis/core/dist/ports/index.js +1 -0
- package/node_modules/@comis/core/dist/ports/oauth-credential-store.d.ts +64 -0
- package/node_modules/@comis/core/dist/ports/oauth-credential-store.js +37 -0
- package/node_modules/@comis/core/dist/tool-metadata.d.ts +20 -0
- package/node_modules/@comis/core/package.json +1 -1
- package/node_modules/@comis/daemon/dist/daemon-types.d.ts +23 -3
- package/node_modules/@comis/daemon/dist/daemon.js +82 -19
- package/node_modules/@comis/daemon/dist/index.d.ts +2 -0
- package/node_modules/@comis/daemon/dist/index.js +5 -0
- package/node_modules/@comis/daemon/dist/observability/channel-health-logger.js +3 -3
- package/node_modules/@comis/daemon/dist/observability/delivery-queue-logger.js +1 -1
- package/node_modules/@comis/daemon/dist/rpc/agent-handlers.d.ts +22 -1
- package/node_modules/@comis/daemon/dist/rpc/agent-handlers.js +84 -21
- package/node_modules/@comis/daemon/dist/rpc/agent-inline-workspace.js +2 -2
- package/node_modules/@comis/daemon/dist/rpc/config-handlers.d.ts +9 -1
- package/node_modules/@comis/daemon/dist/rpc/config-handlers.js +104 -23
- package/node_modules/@comis/daemon/dist/rpc/credential-resolver.d.ts +30 -1
- package/node_modules/@comis/daemon/dist/rpc/credential-resolver.js +74 -11
- package/node_modules/@comis/daemon/dist/rpc/mcp-handlers.d.ts +8 -0
- package/node_modules/@comis/daemon/dist/rpc/mcp-handlers.js +22 -8
- package/node_modules/@comis/daemon/dist/rpc/provider-handlers.js +9 -12
- package/node_modules/@comis/daemon/dist/rpc/rpc-dispatch.d.ts +1 -0
- package/node_modules/@comis/daemon/dist/rpc/rpc-dispatch.js +27 -2
- package/node_modules/@comis/daemon/dist/setup-docker-restart-warn.js +0 -1
- 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/oauth-preflight.d.ts +21 -0
- package/node_modules/@comis/daemon/dist/wiring/oauth-preflight.js +134 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-agents.d.ts +46 -1
- package/node_modules/@comis/daemon/dist/wiring/setup-agents.js +127 -3
- package/node_modules/@comis/daemon/dist/wiring/setup-background-completion-runner.d.ts +39 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-background-completion-runner.js +32 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-background-tasks.d.ts +10 -3
- package/node_modules/@comis/daemon/dist/wiring/setup-background-tasks.js +11 -5
- package/node_modules/@comis/daemon/dist/wiring/setup-channels.js +20 -1
- package/node_modules/@comis/daemon/dist/wiring/setup-cross-session.js +1 -1
- package/node_modules/@comis/daemon/dist/wiring/setup-delivery.d.ts +14 -5
- package/node_modules/@comis/daemon/dist/wiring/setup-delivery.js +52 -19
- package/node_modules/@comis/daemon/dist/wiring/setup-schedulers.js +4 -0
- package/node_modules/@comis/daemon/package.json +1 -1
- package/node_modules/@comis/gateway/dist/index.d.ts +2 -0
- package/node_modules/@comis/gateway/dist/index.js +2 -0
- package/node_modules/@comis/gateway/dist/oauth/oauth-callback-route.d.ts +66 -0
- package/node_modules/@comis/gateway/dist/oauth/oauth-callback-route.js +212 -0
- package/node_modules/@comis/gateway/dist/server/hono-server.d.ts +14 -0
- package/node_modules/@comis/gateway/dist/server/hono-server.js +10 -0
- package/node_modules/@comis/gateway/package.json +1 -1
- package/node_modules/@comis/infra/dist/logging/log-fields.d.ts +23 -0
- package/node_modules/@comis/infra/package.json +1 -1
- package/node_modules/@comis/memory/dist/compaction.d.ts +3 -5
- package/node_modules/@comis/memory/dist/compaction.js +2 -3
- package/node_modules/@comis/memory/dist/delivery-queue-adapter.d.ts +2 -2
- package/node_modules/@comis/memory/dist/delivery-queue-adapter.js +49 -1
- package/node_modules/@comis/memory/dist/index.d.ts +2 -0
- package/node_modules/@comis/memory/dist/index.js +3 -0
- package/node_modules/@comis/memory/dist/memory-api.d.ts +1 -1
- package/node_modules/@comis/memory/dist/memory-api.js +1 -1
- package/node_modules/@comis/memory/dist/oauth-profile-schema.d.ts +17 -0
- package/node_modules/@comis/memory/dist/oauth-profile-schema.js +33 -0
- package/node_modules/@comis/memory/dist/oauth-profile-store-encrypted.d.ts +27 -0
- package/node_modules/@comis/memory/dist/oauth-profile-store-encrypted.js +144 -0
- package/node_modules/@comis/memory/dist/session-store.d.ts +1 -1
- package/node_modules/@comis/memory/dist/session-store.js +1 -1
- package/node_modules/@comis/memory/dist/sqlite-secret-store.d.ts +29 -3
- package/node_modules/@comis/memory/dist/sqlite-secret-store.js +11 -3
- package/node_modules/@comis/memory/package.json +1 -1
- package/node_modules/@comis/scheduler/dist/execution/execution-lock.d.ts +13 -0
- package/node_modules/@comis/scheduler/dist/execution/execution-lock.js +1 -1
- package/node_modules/@comis/scheduler/dist/execution/index.d.ts +2 -0
- package/node_modules/@comis/scheduler/dist/execution/index.js +2 -0
- package/node_modules/@comis/scheduler/dist/heartbeat/agent-heartbeat-source.js +1 -1
- package/node_modules/@comis/scheduler/dist/index.d.ts +2 -0
- package/node_modules/@comis/scheduler/dist/index.js +2 -0
- package/node_modules/@comis/scheduler/package.json +1 -1
- package/node_modules/@comis/shared/package.json +1 -1
- package/node_modules/@comis/skills/dist/bridge/schema-validator.d.ts +38 -0
- package/node_modules/@comis/skills/dist/bridge/schema-validator.js +169 -0
- package/node_modules/@comis/skills/dist/bridge/tool-metadata-enforcement.js +12 -0
- package/node_modules/@comis/skills/dist/bridge/tool-metadata-registry.js +130 -0
- package/node_modules/@comis/skills/dist/builtin/exec-diagnostics.d.ts +32 -0
- package/node_modules/@comis/skills/dist/builtin/exec-diagnostics.js +127 -0
- package/node_modules/@comis/skills/dist/builtin/exec-security.js +38 -0
- package/node_modules/@comis/skills/dist/builtin/exec-tool.js +9 -0
- package/node_modules/@comis/skills/dist/builtin/file-tools/grep-tool.js +6 -6
- package/node_modules/@comis/skills/dist/builtin/platform/agents-manage-tool.d.ts +5 -4
- package/node_modules/@comis/skills/dist/builtin/platform/agents-manage-tool.js +38 -27
- package/node_modules/@comis/skills/dist/builtin/platform/background-tasks-tool.d.ts +4 -1
- package/node_modules/@comis/skills/dist/builtin/platform/background-tasks-tool.js +3 -3
- package/node_modules/@comis/skills/dist/builtin/platform/cron-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/gateway-tool.js +6 -6
- package/node_modules/@comis/skills/dist/builtin/platform/mcp-manage-tool.d.ts +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/mcp-manage-tool.js +9 -9
- package/node_modules/@comis/skills/dist/builtin/sandbox/bwrap-provider.d.ts +11 -0
- package/node_modules/@comis/skills/dist/builtin/sandbox/bwrap-provider.js +114 -1
- package/node_modules/@comis/skills/dist/builtin/sandbox/detect-provider.js +40 -15
- package/node_modules/@comis/skills/dist/media/ssrf-fetcher.d.ts +7 -0
- package/node_modules/@comis/skills/dist/media/ssrf-fetcher.js +9 -2
- package/node_modules/@comis/skills/package.json +1 -1
- package/node_modules/@comis/web/dist/assets/{agent-detail-71BSbSfD.js → agent-detail-q8t1NB7w.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{agent-editor-CTSDZhwT.js → agent-editor-B46io5gv.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{agent-list-BEhni2ea.js → agent-list-DQ6g2Rcx.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{billing-view-DVP1IvVs.js → billing-view-IWPR8LgF.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{channel-detail-N_YK74xC.js → channel-detail-DlNNZuuC.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{channel-list-DRk6ZJaF.js → channel-list-DhGwxiMc.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{chat-console-Dm-GtSf9.js → chat-console-Nv6fM3Rc.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{config-editor-CIferYX6.js → config-editor-BYKuJF76.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{context-dag-browser-CL84rXXM.js → context-dag-browser-ClNEtzYE.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{context-engine-B1HOTEZv.js → context-engine-BZJ6HChd.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{delivery-view-Y6JKYVFw.js → delivery-view-Cb7I3vGu.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{diagnostics-view-DWV1UQjz.js → diagnostics-view-9u9Lyu5a.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{ic-chat-message-DfSERzzg.js → ic-chat-message-BFt3cVpx.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{ic-connection-dot-CXyhlJup.js → ic-connection-dot-y77LZ3Gu.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{ic-tool-call-DNmwTjek.js → ic-tool-call-qt6w1NQl.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{index-CBr0Tm9_.js → index-8Tg9oc-C.js} +2 -2
- package/node_modules/@comis/web/dist/assets/{mcp-management-BaH2-vox.js → mcp-management-69dtH_kY.js} +2 -2
- package/node_modules/@comis/web/dist/assets/{media-config-CZLshJoN.js → media-config-BdjLj5c1.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{media-test-C9NUWgo_.js → media-test-DuPqrixi.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{memory-inspector-D_fmTcRN.js → memory-inspector-B-Pepbq-.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{message-center-BBFlNCZn.js → message-center-B7l0yNYY.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{models-BytGLm99.js → models-JHFHuv5S.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{observe-view-VXtHqaqq.js → observe-view-r8mqhy4O.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{pipeline-builder-CfXczlfJ.js → pipeline-builder-XjkiZRcR.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{pipeline-history-CPmXFnbe.js → pipeline-history-CZqJv_Hj.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{pipeline-history-detail-DcueTMs9.js → pipeline-history-detail-BEFGMoDy.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{pipeline-list-B-xG5WZh.js → pipeline-list-B6q5LvO1.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{pipeline-monitor-pnIOYaSY.js → pipeline-monitor-BNomXjVL.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{scheduler-BtUIFHhA.js → scheduler-BJEjcGKA.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{security-C8mWRq2y.js → security-2G1jhBfV.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{session-detail-DgdkO5ka.js → session-detail-DmVPzFBR.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{session-list-DcylcfTn.js → session-list-CsqMQoHs.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{setup-wizard-BP5yjsuL.js → setup-wizard-CAdM-gSP.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{skills-DXt1bX8Z.js → skills-2ODqKaWr.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{subagents-C7YbUHXY.js → subagents-BFlwfTbD.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{workspace-manager-DP6pW4wa.js → workspace-manager--CbOx_dI.js} +1 -1
- package/node_modules/@comis/web/dist/index.html +1 -1
- package/node_modules/@comis/web/package.json +1 -1
- package/package.json +17 -16
|
@@ -7,6 +7,8 @@ export { createCronStore } from "./cron/index.js";
|
|
|
7
7
|
export { createCronScheduler } from "./cron/index.js";
|
|
8
8
|
// Execution safety
|
|
9
9
|
export { createExecutionTracker } from "./execution/index.js";
|
|
10
|
+
// File-based execution lock (consumed by @comis/agent OAuth file adapter + token manager)
|
|
11
|
+
export { withExecutionLock, isLocked } from "./execution/execution-lock.js";
|
|
10
12
|
// Heartbeat monitoring
|
|
11
13
|
export { HEARTBEAT_OK_TOKEN, createHeartbeatRunner } from "./heartbeat/index.js";
|
|
12
14
|
// Per-agent heartbeat config resolution
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic tool-entry schema validator.
|
|
3
|
+
*
|
|
4
|
+
* Pre-flight, action-aware shape gate that runs BEFORE per-tool
|
|
5
|
+
* `validateInput`. Catches malformed shapes such as
|
|
6
|
+
* `mcp_manage({action:"connect", server_name:"yfinance"})` at the
|
|
7
|
+
* tool-entry boundary and produces a self-correcting message:
|
|
8
|
+
*
|
|
9
|
+
* "[invalid_value] unknown key 'server_name' -- did you mean 'name'?.
|
|
10
|
+
* missing for action='connect': transport.
|
|
11
|
+
* valid keys: action, name, transport, command, args, url, headers"
|
|
12
|
+
*
|
|
13
|
+
* Generic by construction: every per-tool branch lives in the metadata
|
|
14
|
+
* registered via `registerToolMetadata({ validActions, validKeys,
|
|
15
|
+
* requiredByAction })`. This file contains zero tool-name conditionals.
|
|
16
|
+
*
|
|
17
|
+
* Reuses `levenshteinSimilarity` from
|
|
18
|
+
* ../builtin/file/path-suggest.js -- DO NOT duplicate the helper.
|
|
19
|
+
*
|
|
20
|
+
* Returns a single error string on failure (matches the
|
|
21
|
+
* `validateInput` contract used by `wrapWithMetadataEnforcement`),
|
|
22
|
+
* `undefined` on success. Caller prepends `[invalid_value]`.
|
|
23
|
+
*
|
|
24
|
+
* @module
|
|
25
|
+
*/
|
|
26
|
+
import type { ComisToolMetadata } from "@comis/core";
|
|
27
|
+
/**
|
|
28
|
+
* Validate tool-entry shape against registered metadata.
|
|
29
|
+
*
|
|
30
|
+
* @param params - Raw params object as the SDK would pass to `execute()`.
|
|
31
|
+
* @param meta - Metadata returned from `getToolMetadata(toolName)`. May be
|
|
32
|
+
* undefined or missing the entry-shape fields -- in either case this
|
|
33
|
+
* function returns undefined (no-op) so existing tools without
|
|
34
|
+
* registered shape metadata pass through unchanged.
|
|
35
|
+
* @returns A single error string when validation fails (caller prepends
|
|
36
|
+
* `[invalid_value]`), or `undefined` when validation passes / is skipped.
|
|
37
|
+
*/
|
|
38
|
+
export declare function validateToolEntry(params: unknown, meta: ComisToolMetadata | undefined): string | undefined;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* Generic tool-entry schema validator.
|
|
4
|
+
*
|
|
5
|
+
* Pre-flight, action-aware shape gate that runs BEFORE per-tool
|
|
6
|
+
* `validateInput`. Catches malformed shapes such as
|
|
7
|
+
* `mcp_manage({action:"connect", server_name:"yfinance"})` at the
|
|
8
|
+
* tool-entry boundary and produces a self-correcting message:
|
|
9
|
+
*
|
|
10
|
+
* "[invalid_value] unknown key 'server_name' -- did you mean 'name'?.
|
|
11
|
+
* missing for action='connect': transport.
|
|
12
|
+
* valid keys: action, name, transport, command, args, url, headers"
|
|
13
|
+
*
|
|
14
|
+
* Generic by construction: every per-tool branch lives in the metadata
|
|
15
|
+
* registered via `registerToolMetadata({ validActions, validKeys,
|
|
16
|
+
* requiredByAction })`. This file contains zero tool-name conditionals.
|
|
17
|
+
*
|
|
18
|
+
* Reuses `levenshteinSimilarity` from
|
|
19
|
+
* ../builtin/file/path-suggest.js -- DO NOT duplicate the helper.
|
|
20
|
+
*
|
|
21
|
+
* Returns a single error string on failure (matches the
|
|
22
|
+
* `validateInput` contract used by `wrapWithMetadataEnforcement`),
|
|
23
|
+
* `undefined` on success. Caller prepends `[invalid_value]`.
|
|
24
|
+
*
|
|
25
|
+
* @module
|
|
26
|
+
*/
|
|
27
|
+
import { levenshteinSimilarity } from "../builtin/file/path-suggest.js";
|
|
28
|
+
/**
|
|
29
|
+
* Min similarity for did-you-mean suggestion. Below this we say "unknown"
|
|
30
|
+
* with no suggestion to avoid misleading the LLM.
|
|
31
|
+
*
|
|
32
|
+
* We score with `tokenAwareSimilarity` (max of full-string similarity and
|
|
33
|
+
* the best per-token similarity after splitting on `_`/`-`). This catches
|
|
34
|
+
* payloads like `server_name -> name` (token "name" matches exactly,
|
|
35
|
+
* score 1.0) without spurious matches against short unrelated keys (`x`,
|
|
36
|
+
* `srver` -> max < 0.3 across all candidates in the 7-key mcp_manage
|
|
37
|
+
* shape, well below threshold).
|
|
38
|
+
*
|
|
39
|
+
* 0.5 was chosen empirically: `conect -> connect` scores 0.857 (fires);
|
|
40
|
+
* `srver -> headers` scores 0.286 (does not fire); the closest false
|
|
41
|
+
* positive across the manage-tool corpus is below 0.5.
|
|
42
|
+
*/
|
|
43
|
+
const SUGGEST_THRESHOLD = 0.5;
|
|
44
|
+
/**
|
|
45
|
+
* Validate tool-entry shape against registered metadata.
|
|
46
|
+
*
|
|
47
|
+
* @param params - Raw params object as the SDK would pass to `execute()`.
|
|
48
|
+
* @param meta - Metadata returned from `getToolMetadata(toolName)`. May be
|
|
49
|
+
* undefined or missing the entry-shape fields -- in either case this
|
|
50
|
+
* function returns undefined (no-op) so existing tools without
|
|
51
|
+
* registered shape metadata pass through unchanged.
|
|
52
|
+
* @returns A single error string when validation fails (caller prepends
|
|
53
|
+
* `[invalid_value]`), or `undefined` when validation passes / is skipped.
|
|
54
|
+
*/
|
|
55
|
+
export function validateToolEntry(params, meta) {
|
|
56
|
+
// Skip if no entry-shape metadata registered.
|
|
57
|
+
if (meta === undefined
|
|
58
|
+
|| (meta.validActions === undefined
|
|
59
|
+
&& meta.validKeys === undefined
|
|
60
|
+
&& meta.requiredByAction === undefined)) {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
// Shape gate: params MUST be a plain object. Reject null, primitives,
|
|
64
|
+
// and arrays. (Arrays would otherwise pass typeof === "object".)
|
|
65
|
+
if (params === null || typeof params !== "object" || Array.isArray(params)) {
|
|
66
|
+
return "params must be an object";
|
|
67
|
+
}
|
|
68
|
+
const p = params;
|
|
69
|
+
const segments = [];
|
|
70
|
+
// Action gate.
|
|
71
|
+
let action;
|
|
72
|
+
if (meta.validActions !== undefined) {
|
|
73
|
+
const raw = p.action;
|
|
74
|
+
if (raw === undefined) {
|
|
75
|
+
segments.push(`Missing required parameter: action. valid actions: ${meta.validActions.join(", ")}`);
|
|
76
|
+
}
|
|
77
|
+
else if (typeof raw !== "string") {
|
|
78
|
+
segments.push("action must be a string");
|
|
79
|
+
}
|
|
80
|
+
else if (!meta.validActions.includes(raw)) {
|
|
81
|
+
const suggestion = bestMatch(raw, meta.validActions);
|
|
82
|
+
const didYouMean = suggestion !== undefined ? ` -- did you mean '${suggestion}'?` : "";
|
|
83
|
+
segments.push(`invalid action '${raw}'${didYouMean}. valid actions: ${meta.validActions.join(", ")}`);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
action = raw;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else if (typeof p.action === "string") {
|
|
90
|
+
// No validActions registered but the tool still uses an action field
|
|
91
|
+
// (rare). Use it for requiredByAction lookup.
|
|
92
|
+
action = p.action;
|
|
93
|
+
}
|
|
94
|
+
// Unknown-key gate.
|
|
95
|
+
if (meta.validKeys !== undefined) {
|
|
96
|
+
const validSet = new Set(meta.validKeys);
|
|
97
|
+
const unknowns = [];
|
|
98
|
+
for (const key of Object.keys(p)) {
|
|
99
|
+
if (!validSet.has(key))
|
|
100
|
+
unknowns.push(key);
|
|
101
|
+
}
|
|
102
|
+
if (unknowns.length > 0) {
|
|
103
|
+
const parts = unknowns.map((k) => {
|
|
104
|
+
const suggestion = bestMatch(k, meta.validKeys);
|
|
105
|
+
return suggestion !== undefined
|
|
106
|
+
? `unknown key '${k}' -- did you mean '${suggestion}'?`
|
|
107
|
+
: `unknown key '${k}'`;
|
|
108
|
+
});
|
|
109
|
+
segments.push(parts.join("; "));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Required-fields gate (only when we have a known action).
|
|
113
|
+
if (action !== undefined && meta.requiredByAction !== undefined) {
|
|
114
|
+
const required = meta.requiredByAction[action];
|
|
115
|
+
if (required !== undefined && required.length > 0) {
|
|
116
|
+
const missing = required.filter((k) => !(k in p) || p[k] === undefined);
|
|
117
|
+
if (missing.length > 0) {
|
|
118
|
+
segments.push(`missing for action='${action}': ${missing.join(", ")}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (segments.length === 0)
|
|
123
|
+
return undefined;
|
|
124
|
+
// Always append valid-keys list when registered -- closes the LLM's
|
|
125
|
+
// self-correction loop in one turn.
|
|
126
|
+
if (meta.validKeys !== undefined) {
|
|
127
|
+
segments.push(`valid keys: ${meta.validKeys.join(", ")}`);
|
|
128
|
+
}
|
|
129
|
+
return segments.join(". ");
|
|
130
|
+
}
|
|
131
|
+
/** Pick the best-matching candidate above SUGGEST_THRESHOLD, or undefined. */
|
|
132
|
+
function bestMatch(input, candidates) {
|
|
133
|
+
let best;
|
|
134
|
+
const lowered = input.toLowerCase();
|
|
135
|
+
for (const candidate of candidates) {
|
|
136
|
+
const score = tokenAwareSimilarity(lowered, candidate.toLowerCase());
|
|
137
|
+
if (score >= SUGGEST_THRESHOLD && (best === undefined || score > best.score)) {
|
|
138
|
+
best = { value: candidate, score };
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return best?.value;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Token-aware similarity: max of full-string similarity and the best
|
|
145
|
+
* per-token similarity after splitting `input` on `_`/`-`.
|
|
146
|
+
*
|
|
147
|
+
* Plain Levenshtein on full strings misses snake_case key suggestions:
|
|
148
|
+
* `server_name` vs `name` is similarity 0.36, well below any reasonable
|
|
149
|
+
* threshold. Splitting on `_` exposes the `name` token (similarity 1.0
|
|
150
|
+
* vs `name`), which is the LLM-self-correction signal we want to surface.
|
|
151
|
+
*
|
|
152
|
+
* Inputs are assumed lowercased by the caller.
|
|
153
|
+
*/
|
|
154
|
+
function tokenAwareSimilarity(input, candidate) {
|
|
155
|
+
let best = levenshteinSimilarity(input, candidate);
|
|
156
|
+
// Split on '_' or '-' (skill, manage-tool, snake_case conventions). Empty
|
|
157
|
+
// tokens are dropped so leading/trailing/double-separators do not produce
|
|
158
|
+
// 0-length strings that would skew similarity to 1.0 against an empty
|
|
159
|
+
// candidate (defensive -- candidate is non-empty in practice).
|
|
160
|
+
const tokens = input.split(/[_-]+/);
|
|
161
|
+
for (const t of tokens) {
|
|
162
|
+
if (t.length === 0)
|
|
163
|
+
continue;
|
|
164
|
+
const score = levenshteinSimilarity(t, candidate);
|
|
165
|
+
if (score > best)
|
|
166
|
+
best = score;
|
|
167
|
+
}
|
|
168
|
+
return best;
|
|
169
|
+
}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* @module
|
|
12
12
|
*/
|
|
13
13
|
import { getToolMetadata, truncateContentBlocks } from "@comis/core";
|
|
14
|
+
import { validateToolEntry } from "./schema-validator.js";
|
|
14
15
|
/**
|
|
15
16
|
* Check whether a tool result's content is effectively empty.
|
|
16
17
|
*
|
|
@@ -60,6 +61,17 @@ export function wrapWithMetadataEnforcement(tool) {
|
|
|
60
61
|
...tool,
|
|
61
62
|
async execute(toolCallId, params, signal, onUpdate) {
|
|
62
63
|
const meta = getToolMetadata(tool.name);
|
|
64
|
+
// Generic tool-entry schema validation (260504-cac).
|
|
65
|
+
// Runs BEFORE per-tool validateInput so action-shape errors short-circuit
|
|
66
|
+
// before tool-specific business rules. Skips silently when the tool has
|
|
67
|
+
// not registered validActions / validKeys / requiredByAction.
|
|
68
|
+
const schemaError = validateToolEntry(params, meta);
|
|
69
|
+
if (schemaError !== undefined) {
|
|
70
|
+
const err = new Error(`[invalid_value] ${schemaError}`);
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- match existing errorKind propagation pattern
|
|
72
|
+
err.errorKind = "validation";
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
63
75
|
// Pre-flight validation
|
|
64
76
|
if (meta?.validateInput) {
|
|
65
77
|
const validationError = await meta.validateInput(params);
|
|
@@ -188,6 +188,136 @@ export function registerAllToolMetadata() {
|
|
|
188
188
|
},
|
|
189
189
|
});
|
|
190
190
|
// =========================================================================
|
|
191
|
+
// Tool-Entry Schema (260504-cac)
|
|
192
|
+
//
|
|
193
|
+
// Generic action enum + valid keys + per-action required fields. Consumed
|
|
194
|
+
// by validateToolEntry() in ./schema-validator.ts via
|
|
195
|
+
// wrapWithMetadataEnforcement BEFORE per-tool validateInput runs.
|
|
196
|
+
//
|
|
197
|
+
// Each tool's shape is sourced from its TypeBox Type.Union([Type.Literal(...)])
|
|
198
|
+
// action enum + each action handler's readStringParam(p, X) /
|
|
199
|
+
// throwToolError("missing_param", ...) calls in its actionOverrides.
|
|
200
|
+
//
|
|
201
|
+
// Cross-consistency: managed-section entries in
|
|
202
|
+
// @comis/core/src/config/managed-sections.ts also declare
|
|
203
|
+
// requiredByAction for the redirect-hint payload. The registrations
|
|
204
|
+
// here are the runtime gate; the managed-section entries are the
|
|
205
|
+
// user-facing redirect hint.
|
|
206
|
+
// =========================================================================
|
|
207
|
+
registerToolMetadata("mcp_manage", {
|
|
208
|
+
validActions: ["list", "status", "connect", "disconnect", "reconnect"],
|
|
209
|
+
validKeys: ["action", "server_name", "transport", "command", "args", "url", "headers"],
|
|
210
|
+
// connect requires [server_name, transport]; command (stdio) / url (sse|http) are
|
|
211
|
+
// transport-conditional and validated downstream by the handler.
|
|
212
|
+
requiredByAction: {
|
|
213
|
+
status: ["server_name"],
|
|
214
|
+
connect: ["server_name", "transport"],
|
|
215
|
+
disconnect: ["server_name"],
|
|
216
|
+
reconnect: ["server_name"],
|
|
217
|
+
},
|
|
218
|
+
});
|
|
219
|
+
registerToolMetadata("agents_manage", {
|
|
220
|
+
validActions: ["create", "get", "update", "delete", "suspend", "resume", "list"],
|
|
221
|
+
validKeys: ["action", "agent_id", "config"],
|
|
222
|
+
// agent_id is required for every action except list.
|
|
223
|
+
requiredByAction: {
|
|
224
|
+
create: ["agent_id", "config"],
|
|
225
|
+
get: ["agent_id"],
|
|
226
|
+
update: ["agent_id", "config"],
|
|
227
|
+
delete: ["agent_id"],
|
|
228
|
+
suspend: ["agent_id"],
|
|
229
|
+
resume: ["agent_id"],
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
registerToolMetadata("tokens_manage", {
|
|
233
|
+
validActions: ["list", "create", "revoke", "rotate"],
|
|
234
|
+
validKeys: ["action", "token_id", "scopes"],
|
|
235
|
+
// create: token_id is auto-generated when omitted (per the schema +
|
|
236
|
+
// handler's non-required readStringParam call); only scopes is strictly
|
|
237
|
+
// required.
|
|
238
|
+
requiredByAction: {
|
|
239
|
+
create: ["scopes"],
|
|
240
|
+
revoke: ["token_id"],
|
|
241
|
+
rotate: ["token_id"],
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
registerToolMetadata("providers_manage", {
|
|
245
|
+
validActions: ["list", "get", "create", "update", "delete", "enable", "disable"],
|
|
246
|
+
validKeys: ["action", "provider_id", "config"],
|
|
247
|
+
requiredByAction: {
|
|
248
|
+
get: ["provider_id"],
|
|
249
|
+
create: ["provider_id", "config"],
|
|
250
|
+
update: ["provider_id", "config"],
|
|
251
|
+
delete: ["provider_id"],
|
|
252
|
+
enable: ["provider_id"],
|
|
253
|
+
disable: ["provider_id"],
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
registerToolMetadata("channels_manage", {
|
|
257
|
+
validActions: ["list", "get", "enable", "disable", "restart", "configure"],
|
|
258
|
+
validKeys: ["action", "channel_type", "setting", "enabled"],
|
|
259
|
+
requiredByAction: {
|
|
260
|
+
get: ["channel_type"],
|
|
261
|
+
enable: ["channel_type"],
|
|
262
|
+
disable: ["channel_type"],
|
|
263
|
+
restart: ["channel_type"],
|
|
264
|
+
configure: ["channel_type", "setting", "enabled"],
|
|
265
|
+
},
|
|
266
|
+
});
|
|
267
|
+
registerToolMetadata("sessions_manage", {
|
|
268
|
+
validActions: ["delete", "reset", "export", "compact"],
|
|
269
|
+
validKeys: ["action", "session_key", "instructions"],
|
|
270
|
+
requiredByAction: {
|
|
271
|
+
delete: ["session_key"],
|
|
272
|
+
reset: ["session_key"],
|
|
273
|
+
export: ["session_key"],
|
|
274
|
+
compact: ["session_key"],
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
registerToolMetadata("skills_manage", {
|
|
278
|
+
validActions: ["list", "import", "delete", "create", "update"],
|
|
279
|
+
validKeys: ["action", "url", "name", "content", "description", "scope"],
|
|
280
|
+
requiredByAction: {
|
|
281
|
+
import: ["url"],
|
|
282
|
+
delete: ["name"],
|
|
283
|
+
create: ["name", "content"],
|
|
284
|
+
update: ["name", "content"],
|
|
285
|
+
},
|
|
286
|
+
});
|
|
287
|
+
registerToolMetadata("memory_manage", {
|
|
288
|
+
validActions: ["stats", "browse", "delete", "flush", "export"],
|
|
289
|
+
validKeys: [
|
|
290
|
+
"action", "tenant_id", "agent_id", "ids", "offset", "limit", "sort",
|
|
291
|
+
"memory_type", "trust_level", "tags",
|
|
292
|
+
],
|
|
293
|
+
// tenant_id / agent_id are scope filters with defaults; only ids is
|
|
294
|
+
// strictly required (for delete).
|
|
295
|
+
requiredByAction: {
|
|
296
|
+
delete: ["ids"],
|
|
297
|
+
},
|
|
298
|
+
});
|
|
299
|
+
registerToolMetadata("models_manage", {
|
|
300
|
+
validActions: ["list", "test", "list_providers"],
|
|
301
|
+
validKeys: ["action", "provider", "model"],
|
|
302
|
+
requiredByAction: {
|
|
303
|
+
test: ["provider", "model"],
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
registerToolMetadata("heartbeat_manage", {
|
|
307
|
+
validActions: ["get", "update", "status", "trigger"],
|
|
308
|
+
validKeys: [
|
|
309
|
+
"action", "agent_id", "enabled", "interval_ms", "prompt", "model",
|
|
310
|
+
"target_channel_type", "target_channel_id", "target_chat_id", "target_is_dm",
|
|
311
|
+
"light_context", "show_ok", "show_alerts", "allow_dm",
|
|
312
|
+
"skip_heartbeat_only_delivery", "ack_max_chars", "response_prefix", "session",
|
|
313
|
+
"alert_threshold", "alert_cooldown_ms", "stale_ms",
|
|
314
|
+
],
|
|
315
|
+
// Every action's params beyond `action` are Type.Optional. Empty
|
|
316
|
+
// requiredByAction still gates unknown action values + unknown keys via
|
|
317
|
+
// validActions / validKeys.
|
|
318
|
+
requiredByAction: {},
|
|
319
|
+
});
|
|
320
|
+
// =========================================================================
|
|
191
321
|
// Output Schemas
|
|
192
322
|
// =========================================================================
|
|
193
323
|
registerToolMetadata("read", {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exec failure diagnostics: pattern-based recovery hints for known-recoverable
|
|
3
|
+
* subprocess failures. Pure functions — no throws, no I/O beyond synchronous
|
|
4
|
+
* filesystem existence checks scoped to `cwd` via safePath.
|
|
5
|
+
*
|
|
6
|
+
* Wired into executeForeground's stderr finalization in exec-tool.ts. When a
|
|
7
|
+
* matcher returns non-null, its hint is prepended to finalStderr with a
|
|
8
|
+
* `RECOVERY HINT:` prefix so the LLM sees actionable recovery info at the head
|
|
9
|
+
* of the error stream — same surfacing pattern as the existing
|
|
10
|
+
* breakSystemWarning on stdout.
|
|
11
|
+
*
|
|
12
|
+
* Day 1 ships ONE matcher (Python ModuleNotFoundError + missing pyproject.toml).
|
|
13
|
+
* Future matchers register as additional entries in the matchers array — no
|
|
14
|
+
* edits to exec-tool.ts required.
|
|
15
|
+
*
|
|
16
|
+
* @module
|
|
17
|
+
*/
|
|
18
|
+
export interface ExecRecoveryInput {
|
|
19
|
+
/** Final stderr text (post-truncation, post-timeout/abort suffix). */
|
|
20
|
+
stderr: string;
|
|
21
|
+
/** Process exit code. Matchers may early-return on 0. */
|
|
22
|
+
exitCode: number;
|
|
23
|
+
/** Absolute working directory the command ran in. Already workspace-bounded by exec-tool's resolveCwd. */
|
|
24
|
+
cwd: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Run all registered matchers against the failed exec result. Returns the
|
|
28
|
+
* first non-null hint, or `null` if no matcher applies. Multiple-hint
|
|
29
|
+
* concatenation is intentionally not supported on Day 1 — keep the surface
|
|
30
|
+
* narrow until we have a second matcher to motivate the shape.
|
|
31
|
+
*/
|
|
32
|
+
export declare function matchExecRecoveryHint(input: ExecRecoveryInput): string | null;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* Exec failure diagnostics: pattern-based recovery hints for known-recoverable
|
|
4
|
+
* subprocess failures. Pure functions — no throws, no I/O beyond synchronous
|
|
5
|
+
* filesystem existence checks scoped to `cwd` via safePath.
|
|
6
|
+
*
|
|
7
|
+
* Wired into executeForeground's stderr finalization in exec-tool.ts. When a
|
|
8
|
+
* matcher returns non-null, its hint is prepended to finalStderr with a
|
|
9
|
+
* `RECOVERY HINT:` prefix so the LLM sees actionable recovery info at the head
|
|
10
|
+
* of the error stream — same surfacing pattern as the existing
|
|
11
|
+
* breakSystemWarning on stdout.
|
|
12
|
+
*
|
|
13
|
+
* Day 1 ships ONE matcher (Python ModuleNotFoundError + missing pyproject.toml).
|
|
14
|
+
* Future matchers register as additional entries in the matchers array — no
|
|
15
|
+
* edits to exec-tool.ts required.
|
|
16
|
+
*
|
|
17
|
+
* @module
|
|
18
|
+
*/
|
|
19
|
+
import { existsSync, statSync } from "node:fs";
|
|
20
|
+
import { safePath } from "@comis/core";
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Matcher: Python ModuleNotFoundError + missing pyproject.toml
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
/**
|
|
25
|
+
* Match `python -m foo` failures where stderr is one of:
|
|
26
|
+
* 1. `ModuleNotFoundError: No module named 'foo'` (Python traceback form,
|
|
27
|
+
* raised when the import fires inside Python code — e.g. `python -m a.b`
|
|
28
|
+
* where `a` imports a missing dep, or `python -m a.b.c` where `a` itself
|
|
29
|
+
* can't be found and Python re-raises through runpy).
|
|
30
|
+
* 2. `<python-binary>: No module named foo` (runpy CLI form, no quotes,
|
|
31
|
+
* end-of-line — what `python3 -m <pkg>` emits when `<pkg>` is not findable
|
|
32
|
+
* in sys.path. This is the most common real-world trigger.)
|
|
33
|
+
*
|
|
34
|
+
* Combined with `cwd/foo/` or `cwd/src/foo/` existing AND `cwd/pyproject.toml`
|
|
35
|
+
* missing, this means the user has a Python project but no installable package
|
|
36
|
+
* metadata. Suggest writing pyproject.toml + `pip install -e .`.
|
|
37
|
+
*/
|
|
38
|
+
// First alternation captures from the quoted ModuleNotFoundError form;
|
|
39
|
+
// second alternation captures from the bare `: No module named foo` runpy form.
|
|
40
|
+
// Anchored to end-of-line (m flag) so we don't accidentally swallow trailing
|
|
41
|
+
// content on the runpy form.
|
|
42
|
+
const PY_MODULE_NOT_FOUND_RE = /(?:ModuleNotFoundError:\s*No module named ['"]([^'"]+)['"]|: No module named ([A-Za-z_][A-Za-z0-9_.]*)\s*$)/m;
|
|
43
|
+
const SAFE_PKG_NAME_RE = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
44
|
+
function isDirectorySafe(p) {
|
|
45
|
+
try {
|
|
46
|
+
if (!existsSync(p))
|
|
47
|
+
return false;
|
|
48
|
+
return statSync(p).isDirectory();
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const matchPythonModuleNotFound = ({ stderr, exitCode, cwd }) => {
|
|
55
|
+
if (exitCode === 0)
|
|
56
|
+
return null;
|
|
57
|
+
const m = PY_MODULE_NOT_FOUND_RE.exec(stderr);
|
|
58
|
+
if (!m)
|
|
59
|
+
return null;
|
|
60
|
+
// Group 1 = quoted ModuleNotFoundError form; Group 2 = bare runpy form.
|
|
61
|
+
// For `python -m a.b.c` ModuleNotFoundError reports the LEADING segment
|
|
62
|
+
// ('a') when 'a' itself can't be found. Take the first dotted segment;
|
|
63
|
+
// anything else (hyphens, empty, leading digit) abstains via SAFE_PKG_NAME_RE.
|
|
64
|
+
const fullName = m[1] ?? m[2];
|
|
65
|
+
if (!fullName)
|
|
66
|
+
return null;
|
|
67
|
+
const pkg = fullName.split(".")[0];
|
|
68
|
+
if (!SAFE_PKG_NAME_RE.test(pkg))
|
|
69
|
+
return null;
|
|
70
|
+
try {
|
|
71
|
+
// Already-installable project — different bug, abstain.
|
|
72
|
+
const pyproject = safePath(cwd, "pyproject.toml");
|
|
73
|
+
if (existsSync(pyproject))
|
|
74
|
+
return null;
|
|
75
|
+
// Look for cwd/<pkg>/ or cwd/src/<pkg>/. Both must be directories.
|
|
76
|
+
const directDir = safePath(cwd, pkg);
|
|
77
|
+
let foundLayout = null;
|
|
78
|
+
if (isDirectorySafe(directDir)) {
|
|
79
|
+
foundLayout = "flat";
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
const srcDir = safePath(cwd, "src");
|
|
83
|
+
if (isDirectorySafe(srcDir)) {
|
|
84
|
+
const srcPkgDir = safePath(srcDir, pkg);
|
|
85
|
+
if (isDirectorySafe(srcPkgDir)) {
|
|
86
|
+
foundLayout = "src";
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (!foundLayout)
|
|
91
|
+
return null;
|
|
92
|
+
const pkgPathHint = foundLayout === "src" ? `src/${pkg}/` : `${pkg}/`;
|
|
93
|
+
const layoutTable = foundLayout === "src"
|
|
94
|
+
? `[tool.setuptools.packages.find] where=["src"]`
|
|
95
|
+
: `[tool.setuptools] packages=["${pkg}"]`;
|
|
96
|
+
return (`RECOVERY HINT: This Python project is missing pyproject.toml. ` +
|
|
97
|
+
`Found ${pkgPathHint} but no installable package metadata, so \`python -m ${pkg}\` cannot resolve it. ` +
|
|
98
|
+
`Fix: write a minimal pyproject.toml at the project root, then \`pip install -e .\`. ` +
|
|
99
|
+
`Example: [build-system] requires=["setuptools>=61"] [project] name="${pkg}" version="0.1.0" ` +
|
|
100
|
+
layoutTable);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// safePath/statSync surprise — abstain rather than break exec.
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
// Registry + entry point
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
const matchers = [
|
|
111
|
+
matchPythonModuleNotFound,
|
|
112
|
+
// Future: matchNodeModuleNotFound, matchCommandNotFound, matchEnvVarMissing, ...
|
|
113
|
+
];
|
|
114
|
+
/**
|
|
115
|
+
* Run all registered matchers against the failed exec result. Returns the
|
|
116
|
+
* first non-null hint, or `null` if no matcher applies. Multiple-hint
|
|
117
|
+
* concatenation is intentionally not supported on Day 1 — keep the surface
|
|
118
|
+
* narrow until we have a second matcher to motivate the shape.
|
|
119
|
+
*/
|
|
120
|
+
export function matchExecRecoveryHint(input) {
|
|
121
|
+
for (const m of matchers) {
|
|
122
|
+
const hit = m(input);
|
|
123
|
+
if (hit)
|
|
124
|
+
return hit;
|
|
125
|
+
}
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
@@ -263,6 +263,12 @@ export const DANGEROUS_COMMAND_PATTERNS = [
|
|
|
263
263
|
"to see which secret names are configured (names only, no values). " +
|
|
264
264
|
"Secret values are never returned to the agent.",
|
|
265
265
|
},
|
|
266
|
+
{
|
|
267
|
+
pattern: /\.comis\/auth-profiles\.json/,
|
|
268
|
+
reason: "Access to the OAuth credential store (auth-profiles.json) is blocked. " +
|
|
269
|
+
"It contains refresh and access tokens for every connected provider. " +
|
|
270
|
+
"Use the gateway tool to manage OAuth profiles -- token values are never returned to the agent.",
|
|
271
|
+
},
|
|
266
272
|
// Category E -- Config file modification bypass
|
|
267
273
|
// Defense-in-depth: the agent system prompt is the primary guard.
|
|
268
274
|
// These regexes can be bypassed via quoting, variable expansion, etc.
|
|
@@ -334,6 +340,38 @@ export const DANGEROUS_COMMAND_PATTERNS = [
|
|
|
334
340
|
pattern: /\.comis\/\.env.*(?:sed|awk|tee|cat\s*>|echo\s*>)/,
|
|
335
341
|
reason: "Direct .env file modification bypasses SecretManager and audit. Credentials must be managed through secure channels.",
|
|
336
342
|
},
|
|
343
|
+
{
|
|
344
|
+
pattern: /(?:sed|awk|tee|cp|mv|perl|ruby)\b.*\.comis\/auth-profiles\.json/,
|
|
345
|
+
reason: "Direct OAuth credential store (auth-profiles.json) modification bypasses atomic-write, per-profile-lock, and schema-version validation in oauth-credential-store-file.ts. Use the gateway tool to manage OAuth profiles.",
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
pattern: /(?:echo|cat)\b.*>.*\.comis\/auth-profiles\.json/,
|
|
349
|
+
reason: "Direct OAuth credential store (auth-profiles.json) modification bypasses atomic-write, per-profile-lock, and schema-version validation in oauth-credential-store-file.ts. Use the gateway tool to manage OAuth profiles.",
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
pattern: /\.comis\/auth-profiles\.json.*(?:sed|awk|tee|cat\s*>|echo\s*>)/,
|
|
353
|
+
reason: "Direct OAuth credential store (auth-profiles.json) modification bypasses atomic-write, per-profile-lock, and schema-version validation in oauth-credential-store-file.ts. Use the gateway tool to manage OAuth profiles.",
|
|
354
|
+
},
|
|
355
|
+
// Category L -- Network reverse-shell primitives
|
|
356
|
+
// Direct attack primitives that establish a remote shell without going
|
|
357
|
+
// through a pipe (so the existing Gate 2 "pipe to bash/sh/curl/wget/nc"
|
|
358
|
+
// wouldn't catch them). Defense-in-depth: the agent has no legitimate
|
|
359
|
+
// reason to use any of these — the surrounding skills wrap network access
|
|
360
|
+
// through the daemon's HTTP client. A network egress allowlist (iptables
|
|
361
|
+
// --uid-owner) is the actual security boundary; these patterns just
|
|
362
|
+
// surface intent earlier in the chain.
|
|
363
|
+
{
|
|
364
|
+
pattern: /\/dev\/tcp\//,
|
|
365
|
+
reason: "Bash /dev/tcp/<host>/<port> opens a raw TCP socket — reverse-shell primitive.",
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
pattern: /\bnc(?:at)?\b[^|;&]*\s-e\b/,
|
|
369
|
+
reason: "netcat -e (--exec) attaches a process to the socket — reverse-shell primitive.",
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
pattern: /\bsocat\b[^|;&]*\bexec\s*:/,
|
|
373
|
+
reason: "socat exec: target attaches a process to the socket — reverse-shell primitive.",
|
|
374
|
+
},
|
|
337
375
|
];
|
|
338
376
|
// --------------------------------------------------------------------------
|
|
339
377
|
// Dangerous path protection constants
|
|
@@ -33,6 +33,7 @@ import { generateSessionId, appendOutput } from "./process-registry.js";
|
|
|
33
33
|
import { truncateTail, formatSize, DEFAULT_MAX_BYTES } from "./truncate.js";
|
|
34
34
|
import { createOutputCleaner } from "./output-cleaner.js";
|
|
35
35
|
import { extractHeredoc, validateExecCommand, interpretExitCode } from "./exec-security.js";
|
|
36
|
+
import { matchExecRecoveryHint } from "./exec-diagnostics.js";
|
|
36
37
|
import { tryGetContext } from "@comis/core";
|
|
37
38
|
// ---------------------------------------------------------------------------
|
|
38
39
|
// Constants
|
|
@@ -722,6 +723,14 @@ function executeForeground(command, cwd, env, timeoutMs, input, signal, onUpdate
|
|
|
722
723
|
if (aborted) {
|
|
723
724
|
finalStderr += (finalStderr ? "\n" : "") + "Process aborted by signal";
|
|
724
725
|
}
|
|
726
|
+
// Recovery diagnostics: prepend a `RECOVERY HINT:` line for known-recoverable
|
|
727
|
+
// failures (e.g. Python ModuleNotFoundError + missing pyproject.toml). Same
|
|
728
|
+
// surfacing pattern as breakSystemWarning on stdout — gives the LLM an
|
|
729
|
+
// actionable next step at the HEAD of stderr instead of buried in JSON.
|
|
730
|
+
const recoveryHint = matchExecRecoveryHint({ stderr: finalStderr, exitCode, cwd });
|
|
731
|
+
if (recoveryHint) {
|
|
732
|
+
finalStderr = recoveryHint + (finalStderr ? "\n" + finalStderr : "");
|
|
733
|
+
}
|
|
725
734
|
const durationMs = Math.round(performance.now() - startTime);
|
|
726
735
|
logger?.debug({ toolName: "exec", durationMs, exitCode, ...(description && { description }) }, "Exec command complete");
|
|
727
736
|
const result = {
|