comisai 1.0.33 → 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/health/watchdog.js +18 -3
- 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
|
@@ -11,15 +11,20 @@
|
|
|
11
11
|
* @module
|
|
12
12
|
*/
|
|
13
13
|
let sdNotify = null;
|
|
14
|
+
let sdNotifyLoadError = null;
|
|
14
15
|
try {
|
|
15
16
|
// Dynamic import of sd-notify. This will fail on macOS since it's a
|
|
16
17
|
// Linux-native C addon. When unavailable, all operations become no-ops.
|
|
17
18
|
const mod = await import("sd-notify");
|
|
18
19
|
sdNotify = (mod.default ?? mod);
|
|
19
20
|
}
|
|
20
|
-
catch {
|
|
21
|
+
catch (err) {
|
|
21
22
|
// sd-notify not available (macOS, missing native build, etc.)
|
|
22
|
-
// All watchdog operations will be no-ops.
|
|
23
|
+
// All watchdog operations will be no-ops. Capture the failure reason so
|
|
24
|
+
// startWatchdog() can surface it loudly when running under systemd
|
|
25
|
+
// (NOTIFY_SOCKET set) — silent fallback there leaves Type=notify units
|
|
26
|
+
// hung in 'activating (start)' until TimeoutStartSec fires.
|
|
27
|
+
sdNotifyLoadError = err instanceof Error ? err.message : String(err);
|
|
23
28
|
}
|
|
24
29
|
// ---------------------------------------------------------------------------
|
|
25
30
|
// Factory
|
|
@@ -37,7 +42,17 @@ export function startWatchdog(deps) {
|
|
|
37
42
|
const threshold = deps.eventLoopDelayThresholdMs ?? 500;
|
|
38
43
|
let timer;
|
|
39
44
|
if (!notify) {
|
|
40
|
-
|
|
45
|
+
// eslint-disable-next-line no-restricted-syntax -- process.env access needed for systemd detection; NOTIFY_SOCKET is set by systemd, not a secret
|
|
46
|
+
if (process.env["NOTIFY_SOCKET"]) {
|
|
47
|
+
deps.logger.warn({
|
|
48
|
+
errorKind: "config",
|
|
49
|
+
hint: "Reinstall comisai with libsystemd-dev + pkg-config available so the sd-notify native addon builds. Without it, systemd receives no READY/WATCHDOG signals and the unit will hang in 'activating' until TimeoutStartSec, then enter a respawn loop.",
|
|
50
|
+
loadError: sdNotifyLoadError ?? "unknown",
|
|
51
|
+
}, "sd-notify not loaded but NOTIFY_SOCKET is set; systemd integration disabled");
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
deps.logger.debug("sd-notify not available, watchdog disabled (expected on macOS)");
|
|
55
|
+
}
|
|
41
56
|
return { stop: () => { } };
|
|
42
57
|
}
|
|
43
58
|
// Signal ready to systemd
|
|
@@ -7,3 +7,5 @@ export { createAnnouncementDeadLetterQueue } from "./announcement-dead-letter.js
|
|
|
7
7
|
export type { AnnouncementDeadLetterQueue, DeadLetterEntry } from "./announcement-dead-letter.js";
|
|
8
8
|
export { createContextHandlers } from "./rpc/context-handlers.js";
|
|
9
9
|
export type { ContextHandlerDeps } from "./rpc/context-handlers.js";
|
|
10
|
+
export { createAgentHandlers } from "./rpc/agent-handlers.js";
|
|
11
|
+
export type { AgentHandlerDeps } from "./rpc/agent-handlers.js";
|
|
@@ -10,3 +10,8 @@ export { sweepResultFiles, buildAnnouncementMessage, deliverFailureNotification
|
|
|
10
10
|
export { createAnnouncementDeadLetterQueue } from "./announcement-dead-letter.js";
|
|
11
11
|
// Context handlers: DAG context engine RPC handlers
|
|
12
12
|
export { createContextHandlers } from "./rpc/context-handlers.js";
|
|
13
|
+
// Agent management RPC handlers — re-exported so the multi-account
|
|
14
|
+
// integration test can drive the actual `agents.update` RPC handler against a
|
|
15
|
+
// shared `agents` map, mirroring the daemon-runtime container.config.agents
|
|
16
|
+
// pattern at daemon.ts:594/634.
|
|
17
|
+
export { createAgentHandlers } from "./rpc/agent-handlers.js";
|
|
@@ -56,7 +56,7 @@ export function setupChannelHealthLogging(deps) {
|
|
|
56
56
|
lastMessageAt,
|
|
57
57
|
hint,
|
|
58
58
|
errorKind: ERROR_KIND_MAP[currentState] ?? "internal",
|
|
59
|
-
|
|
59
|
+
submodule: MODULE,
|
|
60
60
|
}, "Channel health degraded: %s -> %s", previousState, currentState);
|
|
61
61
|
}
|
|
62
62
|
else {
|
|
@@ -66,7 +66,7 @@ export function setupChannelHealthLogging(deps) {
|
|
|
66
66
|
previousState,
|
|
67
67
|
currentState,
|
|
68
68
|
connectionMode,
|
|
69
|
-
|
|
69
|
+
submodule: MODULE,
|
|
70
70
|
}, "Channel health changed: %s -> %s", previousState, currentState);
|
|
71
71
|
}
|
|
72
72
|
});
|
|
@@ -76,7 +76,7 @@ export function setupChannelHealthLogging(deps) {
|
|
|
76
76
|
channelType: event.channelType,
|
|
77
77
|
state: event.state,
|
|
78
78
|
responseTimeMs: event.responseTimeMs,
|
|
79
|
-
|
|
79
|
+
submodule: MODULE,
|
|
80
80
|
}, "Health check: %s = %s", event.channelType, event.state);
|
|
81
81
|
});
|
|
82
82
|
}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
export function setupDeliveryQueueLogging(deps) {
|
|
22
22
|
const { eventBus, logger } = deps;
|
|
23
23
|
const MODULE = "delivery-queue";
|
|
24
|
-
const log = logger.child({
|
|
24
|
+
const log = logger.child({ submodule: MODULE });
|
|
25
25
|
// 1. Enqueue: message enters queue (boundary event -> INFO)
|
|
26
26
|
eventBus.on("delivery:enqueued", (data) => {
|
|
27
27
|
log.info({
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* the runtime agents map, and returns structured results.
|
|
13
13
|
* @module
|
|
14
14
|
*/
|
|
15
|
-
import type { PerAgentConfig, ProviderEntry } from "@comis/core";
|
|
15
|
+
import type { PerAgentConfig, ProviderEntry, OAuthCredentialStorePort } from "@comis/core";
|
|
16
16
|
import { type PersistToConfigDeps } from "./persist-to-config.js";
|
|
17
17
|
import type { RpcHandler } from "./types.js";
|
|
18
18
|
/** Dependencies required by agent management RPC handlers. */
|
|
@@ -36,6 +36,27 @@ export interface AgentHandlerDeps {
|
|
|
36
36
|
};
|
|
37
37
|
/** Provider entries map for probe lookups when agents switch providers. */
|
|
38
38
|
providerEntries?: Record<string, ProviderEntry>;
|
|
39
|
+
/**
|
|
40
|
+
* Optional OAuth credential store for validating that `oauthProfiles`
|
|
41
|
+
* patches reference existing stored profile IDs. The
|
|
42
|
+
* agents.update handler iterates over each (provider, profileId) entry
|
|
43
|
+
* in the patched config and calls `has(profileId)`; on miss it throws
|
|
44
|
+
* with the documented "not found in store" wording BEFORE the
|
|
45
|
+
* `deps.agents[agentId] = parsedConfig` reference-replacement at the
|
|
46
|
+
* end of the handler — failure leaves the daemon's in-memory map AND
|
|
47
|
+
* the YAML both unchanged. When this field is absent (e.g. test
|
|
48
|
+
* contexts without OAuth wiring) the validation block is a no-op so
|
|
49
|
+
* existing behavior is preserved.
|
|
50
|
+
*/
|
|
51
|
+
oauthCredentialStore?: OAuthCredentialStorePort;
|
|
52
|
+
/**
|
|
53
|
+
* Models config — passed to the credential resolver so that
|
|
54
|
+
* `provider: "default"` is resolved to `models.defaultProvider` for the
|
|
55
|
+
* key check, mirroring runtime resolution in `resolveAgentModel`.
|
|
56
|
+
*/
|
|
57
|
+
modelsConfig?: {
|
|
58
|
+
defaultProvider?: string;
|
|
59
|
+
};
|
|
39
60
|
}
|
|
40
61
|
/**
|
|
41
62
|
* Create a record of agent management RPC handlers bound to the given deps.
|
|
@@ -39,12 +39,12 @@ export function createAgentHandlers(deps) {
|
|
|
39
39
|
if (deps.agents[agentId] !== undefined) {
|
|
40
40
|
throw new Error(`Agent already exists: ${agentId}`);
|
|
41
41
|
}
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
//
|
|
47
|
-
//
|
|
42
|
+
// Extract inlineContent BEFORE config processing. role/identity
|
|
43
|
+
// are write-once side-effects (ROLE.md / IDENTITY.md file writes),
|
|
44
|
+
// NOT durable state — they NEVER enter the persisted config patch.
|
|
45
|
+
// The tool boundary is responsible for stripping them from
|
|
46
|
+
// `config.workspace` before this RPC is called; this handler only
|
|
47
|
+
// consumes the dedicated top-level `inlineContent`
|
|
48
48
|
// field. If a (mis)caller leaves them inside config.workspace, the
|
|
49
49
|
// downstream Zod strict-object will reject them — that's an
|
|
50
50
|
// explicit failure mode, not a silent drop.
|
|
@@ -69,17 +69,37 @@ export function createAgentHandlers(deps) {
|
|
|
69
69
|
existingSkills.builtinTools = { ...DEFAULT_BUILTIN_TOOLS, ...existingBt };
|
|
70
70
|
raw.skills = existingSkills;
|
|
71
71
|
const parsedConfig = PerAgentConfigSchema.parse(config);
|
|
72
|
-
// Credential guard
|
|
73
|
-
//
|
|
72
|
+
// Credential guard: fail-loud if the new agent's provider has no
|
|
73
|
+
// resolvable API key. Mirrors agents.update guard
|
|
74
74
|
// ordering — runs BEFORE the in-memory commit so rejection prevents
|
|
75
75
|
// assignment, file persist, and hot-add. Same helper as the patch /
|
|
76
76
|
// update call sites for cross-handler consistency.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
//
|
|
78
|
+
// Also plumb agents.<id>.oauthProfiles + the daemon-level OAuth
|
|
79
|
+
// credential store so OAuth-only providers (e.g. openai-codex) can
|
|
80
|
+
// resolve via Source C. Pre-resolve has() so the resolver itself stays
|
|
81
|
+
// synchronous (port-side validator does no I/O).
|
|
82
|
+
{
|
|
83
|
+
const targetProvider = parsedConfig.provider;
|
|
84
|
+
// eslint-disable-next-line security/detect-object-injection -- typed Record<string, string> read; targetProvider validated by schema parse
|
|
85
|
+
const configuredProfileId = parsedConfig.oauthProfiles?.[targetProvider];
|
|
86
|
+
let loaderHasProfile = false;
|
|
87
|
+
if (configuredProfileId && deps.oauthCredentialStore) {
|
|
88
|
+
const hasResult = await deps.oauthCredentialStore.has(configuredProfileId);
|
|
89
|
+
loaderHasProfile = hasResult.ok && hasResult.value === true;
|
|
90
|
+
}
|
|
91
|
+
const credCheck = resolveProviderCredential(targetProvider, {
|
|
92
|
+
providerEntries: deps.providerEntries ?? {},
|
|
93
|
+
secretManager: deps.secretManager,
|
|
94
|
+
modelsConfig: deps.modelsConfig,
|
|
95
|
+
oauthProfiles: parsedConfig.oauthProfiles,
|
|
96
|
+
oauthProfileLoader: configuredProfileId
|
|
97
|
+
? { has: (id) => id === configuredProfileId && loaderHasProfile }
|
|
98
|
+
: undefined,
|
|
99
|
+
});
|
|
100
|
+
if (!credCheck.ok) {
|
|
101
|
+
throw new Error(credCheck.reason);
|
|
102
|
+
}
|
|
83
103
|
}
|
|
84
104
|
deps.agents[agentId] = parsedConfig;
|
|
85
105
|
// Best-effort persistence to config.yaml
|
|
@@ -109,7 +129,7 @@ export function createAgentHandlers(deps) {
|
|
|
109
129
|
}
|
|
110
130
|
}
|
|
111
131
|
const workspaceDir = resolveWorkspaceDir(parsedConfig, agentId);
|
|
112
|
-
//
|
|
132
|
+
// Best-effort inline ROLE.md / IDENTITY.md write.
|
|
113
133
|
// Only invoke when inlineContent has at least one populated field
|
|
114
134
|
// AND the persistDeps logger is available (the helper requires a
|
|
115
135
|
// structured logger; the in-memory-only test path skips it).
|
|
@@ -220,20 +240,63 @@ export function createAgentHandlers(deps) {
|
|
|
220
240
|
}
|
|
221
241
|
const merged = { ...existing, ...config };
|
|
222
242
|
const parsedConfig = PerAgentConfigSchema.parse(merged);
|
|
223
|
-
//
|
|
224
|
-
//
|
|
225
|
-
//
|
|
226
|
-
//
|
|
243
|
+
// Validate oauthProfiles patch — each profileId must exist in the
|
|
244
|
+
// OAuth credential store. Skipped when no oauthCredentialStore is
|
|
245
|
+
// wired (test contexts; non-OAuth-aware setups). Critical: this
|
|
246
|
+
// throws BEFORE the `deps.agents[agentId] = parsedConfig`
|
|
247
|
+
// reference-replacement at the end of the handler, so on failure the
|
|
248
|
+
// daemon's in-memory map AND the YAML are both unchanged. The
|
|
249
|
+
// Zod-layer format check has already run during
|
|
250
|
+
// PerAgentConfigSchema.parse(merged) above — this block ONLY checks
|
|
251
|
+
// existence in the store.
|
|
252
|
+
if (parsedConfig.oauthProfiles !== undefined && deps.oauthCredentialStore) {
|
|
253
|
+
for (const [provider, profileId] of Object.entries(parsedConfig.oauthProfiles)) {
|
|
254
|
+
const has = await deps.oauthCredentialStore.has(profileId);
|
|
255
|
+
if (!has.ok || !has.value) {
|
|
256
|
+
throw new Error(`profile ${profileId} not found in store. Run "comis auth list" to see available profiles.`);
|
|
257
|
+
}
|
|
258
|
+
// The provider variable is iterated for completeness; the
|
|
259
|
+
// existence check is keyed on profileId alone (validateProfileId
|
|
260
|
+
// — invoked by the Zod refine — already enforced that the
|
|
261
|
+
// profile-id's provider portion equals the map key).
|
|
262
|
+
void provider;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
// Credential guard + probe: when provider changes,
|
|
266
|
+
// (a) GUARD — fail-loud if the resulting provider's API key is not
|
|
267
|
+
// resolvable from any source (no silent skip), then (b) PROBE —
|
|
268
|
+
// preexisting wire validation when an explicit providers.entries
|
|
227
269
|
// record with apiKeyName exists. Order matters: guard runs first
|
|
228
270
|
// (cheap, all paths), probe runs second (only when applicable).
|
|
271
|
+
//
|
|
272
|
+
// Model-only changes with unchanged provider DO NOT fire the guard
|
|
273
|
+
// or probe — they introduce no new credential surface.
|
|
274
|
+
// Stale-broken-config detection moves to the next chat turn
|
|
275
|
+
// (fail-loud at the request boundary), where the message is
|
|
276
|
+
// correctly shaped for the actual failure mode (not a pre-emptive
|
|
277
|
+
// API-key prompt that is wrong for OAuth providers like
|
|
278
|
+
// openai-codex). Also plumbs agents.<id>.oauthProfiles + the
|
|
279
|
+
// daemon-level OAuth credential store so Source C can fire.
|
|
229
280
|
const providerChanging = config.provider !== undefined && config.provider !== existing.provider;
|
|
230
|
-
|
|
231
|
-
if (providerChanging || modelChanging) {
|
|
281
|
+
if (providerChanging) {
|
|
232
282
|
const targetProvider = parsedConfig.provider;
|
|
283
|
+
// Pre-resolve has() at the daemon edge so the resolver stays sync.
|
|
284
|
+
// eslint-disable-next-line security/detect-object-injection -- typed Record<string, string> read; targetProvider validated by schema parse
|
|
285
|
+
const configuredProfileId = parsedConfig.oauthProfiles?.[targetProvider];
|
|
286
|
+
let loaderHasProfile = false;
|
|
287
|
+
if (configuredProfileId && deps.oauthCredentialStore) {
|
|
288
|
+
const hasResult = await deps.oauthCredentialStore.has(configuredProfileId);
|
|
289
|
+
loaderHasProfile = hasResult.ok && hasResult.value === true;
|
|
290
|
+
}
|
|
233
291
|
// (a) GUARD — fail-loud if no credential source resolves
|
|
234
292
|
const resolution = resolveProviderCredential(targetProvider, {
|
|
235
293
|
providerEntries: deps.providerEntries ?? {},
|
|
236
294
|
secretManager: deps.secretManager,
|
|
295
|
+
modelsConfig: deps.modelsConfig,
|
|
296
|
+
oauthProfiles: parsedConfig.oauthProfiles,
|
|
297
|
+
oauthProfileLoader: configuredProfileId
|
|
298
|
+
? { has: (id) => id === configuredProfileId && loaderHasProfile }
|
|
299
|
+
: undefined,
|
|
237
300
|
});
|
|
238
301
|
if (!resolution.ok) {
|
|
239
302
|
throw new Error(resolution.reason);
|
|
@@ -63,7 +63,7 @@ async function attemptWrite(deps, agentId, filename, targetPath, content) {
|
|
|
63
63
|
catch (e) {
|
|
64
64
|
const message = e instanceof Error ? e.message : String(e);
|
|
65
65
|
deps.logger.warn({
|
|
66
|
-
|
|
66
|
+
submodule: "rpc.agent-handlers",
|
|
67
67
|
agentId,
|
|
68
68
|
file: filename,
|
|
69
69
|
err: e,
|
|
@@ -128,7 +128,7 @@ export async function writeInlineWorkspaceFiles(deps, params) {
|
|
|
128
128
|
// Pure no-op invocations (both fields absent) stay silent.
|
|
129
129
|
if (roleWritten || identityWritten) {
|
|
130
130
|
deps.logger.info({
|
|
131
|
-
|
|
131
|
+
submodule: "rpc.agent-handlers",
|
|
132
132
|
agentId: params.agentId,
|
|
133
133
|
roleBytes: roleWritten ? params.role.length : 0,
|
|
134
134
|
identityBytes: identityWritten ? params.identity.length : 0,
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Extracted from daemon.ts rpcCallInner switch block
|
|
8
8
|
* @module
|
|
9
9
|
*/
|
|
10
|
-
import { type AppContainer, type ConfigGitManager } from "@comis/core";
|
|
10
|
+
import { type AppContainer, type ConfigGitManager, type OAuthCredentialStorePort } from "@comis/core";
|
|
11
11
|
import type { ComisLogger } from "@comis/infra";
|
|
12
12
|
import { z } from "zod";
|
|
13
13
|
import type { RpcHandler } from "./types.js";
|
|
@@ -26,6 +26,14 @@ export interface ConfigHandlerDeps {
|
|
|
26
26
|
timeoutMs?: number;
|
|
27
27
|
secret?: string;
|
|
28
28
|
};
|
|
29
|
+
/**
|
|
30
|
+
* Optional OAuth credential store, used by the credential guard to
|
|
31
|
+
* confirm that an agent's `oauthProfiles[provider]` entry refers to a
|
|
32
|
+
* profile that actually exists in ~/.comis/auth-profiles.json (or the
|
|
33
|
+
* encrypted-SQLite equivalent). When absent, the OAuth branch of the
|
|
34
|
+
* resolver is a no-op — existing API-key behavior is preserved.
|
|
35
|
+
*/
|
|
36
|
+
oauthCredentialStore?: OAuthCredentialStorePort;
|
|
29
37
|
}
|
|
30
38
|
/**
|
|
31
39
|
* Unwrap Zod schema wrappers (Optional / Nullable / Default / Pipe) to get
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Extracted from daemon.ts rpcCallInner switch block
|
|
9
9
|
* @module
|
|
10
10
|
*/
|
|
11
|
-
import { isImmutableConfigPath, getConfigSchema, getConfigSections, deepMerge, AppConfigSchema, redactConfigSecrets, warnSuspiciousEnvValues, getManagedSectionRedirect, formatRedirectHint, } from "@comis/core";
|
|
11
|
+
import { isImmutableConfigPath, getConfigSchema, getConfigSections, deepMerge, AppConfigSchema, redactConfigSecrets, warnSuspiciousEnvValues, findUnresolvedEnvRefs, formatMissingEnvRefError, getManagedSectionRedirect, formatRedirectHint, } from "@comis/core";
|
|
12
12
|
import { suppressError } from "@comis/shared";
|
|
13
13
|
import { stringify as yamlStringify } from "yaml";
|
|
14
14
|
import { existsSync, readFileSync, writeFileSync, mkdirSync, renameSync } from "node:fs";
|
|
@@ -444,7 +444,7 @@ export function createConfigHandlers(deps) {
|
|
|
444
444
|
// pre-flight and bridge metadata validator catch this earlier for
|
|
445
445
|
// LLM tool calls -- this path is reached when those layers are
|
|
446
446
|
// bypassed. Emit the same redirect hint so all clients see
|
|
447
|
-
// identical, model-agnostic recovery instructions
|
|
447
|
+
// identical, model-agnostic recovery instructions.
|
|
448
448
|
if (isImmutableConfigPath(section, key)) {
|
|
449
449
|
const redirect = getManagedSectionRedirect(section, key);
|
|
450
450
|
const suffix = redirect
|
|
@@ -452,29 +452,74 @@ export function createConfigHandlers(deps) {
|
|
|
452
452
|
: " This setting requires manual operator intervention via config files.";
|
|
453
453
|
throw new Error(`Config path "${key ? `${section}.${key}` : section}" is immutable and cannot be modified at runtime.${suffix}`);
|
|
454
454
|
}
|
|
455
|
-
// Credential guard
|
|
456
|
-
//
|
|
457
|
-
//
|
|
458
|
-
//
|
|
459
|
-
//
|
|
460
|
-
//
|
|
455
|
+
// Credential guard: when a patch targets an agent's provider/model
|
|
456
|
+
// field, verify the resulting provider's API key is resolvable from
|
|
457
|
+
// at least one source pi-coding-agent will consult at runtime.
|
|
458
|
+
// Fail-loud here rather than letting an unauthorized provider
|
|
459
|
+
// config persist and explode at the next chat turn.
|
|
460
|
+
//
|
|
461
|
+
// Model-only patches with unchanged provider introduce no new
|
|
462
|
+
// credential surface — short-circuit the guard entirely. The
|
|
463
|
+
// runtime auth chain that just authenticated the LLM call making
|
|
464
|
+
// this patch will keep working. Stale-broken-config detection
|
|
465
|
+
// moves back to the next chat turn (fail-loud at the request
|
|
466
|
+
// boundary), where the message is correctly shaped for the actual
|
|
467
|
+
// failure mode (not a pre-emptive API-key prompt that is wrong for
|
|
468
|
+
// OAuth providers like openai-codex).
|
|
461
469
|
if (section === "agents" && isAgentProviderOrModelKey(key)) {
|
|
462
470
|
const targetProvider = extractTargetProvider(key, coercedValue, deps.container.config);
|
|
463
471
|
if (targetProvider !== undefined) {
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
472
|
+
// For `.model` keys, extractTargetProvider returns the agent's
|
|
473
|
+
// CURRENT provider (config-handlers.ts:65-69) — so the resolved
|
|
474
|
+
// targetProvider always equals the current provider. The
|
|
475
|
+
// model-only short-circuit therefore always fires for `.model`
|
|
476
|
+
// keys; we still compute the equality explicitly so the
|
|
477
|
+
// intent is readable and the check survives any future change
|
|
478
|
+
// to extractTargetProvider's contract.
|
|
479
|
+
const isModelOnlyPatch = key.endsWith(".model");
|
|
480
|
+
const agentId = key.split(".")[0];
|
|
481
|
+
// eslint-disable-next-line security/detect-object-injection -- agentId from validated key; agents map is typed Record
|
|
482
|
+
const currentProvider = agentId
|
|
483
|
+
? deps.container.config.agents?.[agentId]?.provider
|
|
484
|
+
: undefined;
|
|
485
|
+
const providerUnchanged = currentProvider === targetProvider;
|
|
486
|
+
if (!(isModelOnlyPatch && providerUnchanged)) {
|
|
487
|
+
// Provider is changing (or this is a `.provider` patch where
|
|
488
|
+
// targetProvider is the new value) — run the credential guard.
|
|
489
|
+
// eslint-disable-next-line security/detect-object-injection -- agentId from validated key; agents map is typed Record
|
|
490
|
+
const agentOauthProfiles = (agentId
|
|
491
|
+
? deps.container.config.agents?.[agentId]?.oauthProfiles
|
|
492
|
+
: undefined);
|
|
493
|
+
// Pre-resolve the loader has() for the configured profile so the
|
|
494
|
+
// resolver can stay synchronous. This keeps Hexagonal port-side
|
|
495
|
+
// validators I/O-free.
|
|
496
|
+
// eslint-disable-next-line security/detect-object-injection -- typed Record<string, string> read; targetProvider validated above
|
|
497
|
+
const configuredProfileId = agentOauthProfiles?.[targetProvider];
|
|
498
|
+
let loaderHasProfile = false;
|
|
499
|
+
if (configuredProfileId && deps.oauthCredentialStore) {
|
|
500
|
+
const hasResult = await deps.oauthCredentialStore.has(configuredProfileId);
|
|
501
|
+
loaderHasProfile = hasResult.ok && hasResult.value === true;
|
|
502
|
+
}
|
|
503
|
+
const resolution = resolveProviderCredential(targetProvider, {
|
|
504
|
+
providerEntries: deps.container.config.providers?.entries ?? {},
|
|
505
|
+
secretManager: deps.container.secretManager,
|
|
506
|
+
modelsConfig: deps.container.config.models,
|
|
507
|
+
oauthProfiles: agentOauthProfiles,
|
|
508
|
+
oauthProfileLoader: configuredProfileId
|
|
509
|
+
? { has: (id) => id === configuredProfileId && loaderHasProfile }
|
|
510
|
+
: undefined,
|
|
511
|
+
});
|
|
512
|
+
if (!resolution.ok) {
|
|
513
|
+
deps.logger.warn({
|
|
514
|
+
method: "config.patch",
|
|
515
|
+
section,
|
|
516
|
+
key,
|
|
517
|
+
targetProvider,
|
|
518
|
+
hint: "Provider credential not resolvable",
|
|
519
|
+
errorKind: "validation",
|
|
520
|
+
}, "Config patch rejected: missing provider credential");
|
|
521
|
+
throw new Error(resolution.reason);
|
|
522
|
+
}
|
|
478
523
|
}
|
|
479
524
|
}
|
|
480
525
|
}
|
|
@@ -537,6 +582,42 @@ export function createConfigHandlers(deps) {
|
|
|
537
582
|
throw new Error(`Suspicious env value(s) in config patch: ${hints}. ` +
|
|
538
583
|
`Use \${VAR_NAME} syntax to reference secrets stored via env_set.`);
|
|
539
584
|
}
|
|
585
|
+
// Reject patches that reference env vars not in the secrets store, on
|
|
586
|
+
// enabled MCP servers only. The env-substitution skip on disabled
|
|
587
|
+
// servers makes `enabled:false + ${VAR}` harmless at bootstrap; this
|
|
588
|
+
// gate forbids the partially-valid `enabled:true + missing ${VAR}`
|
|
589
|
+
// shape.
|
|
590
|
+
//
|
|
591
|
+
// We walk `patch` (not the deep-merged config) because we only
|
|
592
|
+
// validate what's being WRITTEN this RPC. `restoreMcpServerEnv` above
|
|
593
|
+
// already restored env from existing YAML for partial-update-without-
|
|
594
|
+
// env patches, so `patch.integrations.mcp.servers[].env` is the
|
|
595
|
+
// post-restore truth. Full-config validation would re-flag pre-
|
|
596
|
+
// existing valid-at-write-time refs whose secrets were later removed
|
|
597
|
+
// (out of scope, separate problem).
|
|
598
|
+
const patchInteg = patch.integrations;
|
|
599
|
+
const patchMcp = patchInteg?.mcp;
|
|
600
|
+
const patchServers = patchMcp?.servers;
|
|
601
|
+
if (Array.isArray(patchServers)) {
|
|
602
|
+
for (const s of patchServers) {
|
|
603
|
+
if (!s || typeof s !== "object")
|
|
604
|
+
continue;
|
|
605
|
+
const server = s;
|
|
606
|
+
// McpServerEntrySchema.enabled defaults to true → absent = enabled.
|
|
607
|
+
// Only explicit `enabled: false` skips the check (preserves the
|
|
608
|
+
// placeholder-for-later pattern).
|
|
609
|
+
if (server.enabled === false)
|
|
610
|
+
continue;
|
|
611
|
+
if (!server.env)
|
|
612
|
+
continue;
|
|
613
|
+
const serverName = typeof server.name === "string" ? server.name : "<unnamed>";
|
|
614
|
+
const unresolved = findUnresolvedEnvRefs(server.env, (key) => deps.container.secretManager.get(key));
|
|
615
|
+
if (unresolved.length > 0) {
|
|
616
|
+
const missingNames = unresolved.map((u) => u.varName);
|
|
617
|
+
throw new Error(formatMissingEnvRefError(serverName, missingNames));
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
540
621
|
const updatedLocal = deepMerge(existingLocal, patch);
|
|
541
622
|
// ${VAR} env var references in string values are preserved
|
|
542
623
|
// through YAML round-trip. yamlStringify writes them literally, parseYaml
|
|
@@ -651,7 +732,7 @@ export function createConfigHandlers(deps) {
|
|
|
651
732
|
}
|
|
652
733
|
// Check immutable paths -- entire section is being replaced.
|
|
653
734
|
// Backstop for direct-RPC clients; LLM tool calls hit the same redirect
|
|
654
|
-
// earlier via gateway-tool / bridge validator
|
|
735
|
+
// earlier via gateway-tool / bridge validator.
|
|
655
736
|
if (isImmutableConfigPath(section)) {
|
|
656
737
|
const redirect = getManagedSectionRedirect(section);
|
|
657
738
|
const suffix = redirect
|
|
@@ -6,12 +6,41 @@ export interface CredentialResolverDeps {
|
|
|
6
6
|
secretManager?: {
|
|
7
7
|
has(key: string): boolean;
|
|
8
8
|
};
|
|
9
|
+
/**
|
|
10
|
+
* Models config — used to resolve `provider: "default"` to the operator's
|
|
11
|
+
* configured `models.defaultProvider`, mirroring runtime resolution in
|
|
12
|
+
* `resolveAgentModel`. When omitted or `defaultProvider` is empty, a
|
|
13
|
+
* literal `"default"` input passes through and produces a clear rejection
|
|
14
|
+
* pointing the operator at `models.defaultProvider`.
|
|
15
|
+
*/
|
|
16
|
+
modelsConfig?: {
|
|
17
|
+
defaultProvider?: string;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Per-agent OAuth profile map (Record<provider, profileId>) sourced from
|
|
21
|
+
* `agents.<id>.oauthProfiles` on the daemon's container.config. When an
|
|
22
|
+
* entry exists for the resolved provider AND `oauthProfileLoader.has`
|
|
23
|
+
* returns true, the resolver returns ok with source: "oauth_profile".
|
|
24
|
+
*/
|
|
25
|
+
oauthProfiles?: Record<string, string>;
|
|
26
|
+
/**
|
|
27
|
+
* Synchronous facade over OAuthCredentialStorePort.has. The async port
|
|
28
|
+
* call MUST be performed at the daemon edge (config-handlers /
|
|
29
|
+
* agent-handlers) and adapted to this sync shape — the resolver itself
|
|
30
|
+
* does no I/O (hexagonal: port-side validator). Pass a closure such as
|
|
31
|
+
* `{ has: () => storeHasResult.ok && storeHasResult.value }`.
|
|
32
|
+
*/
|
|
33
|
+
oauthProfileLoader?: {
|
|
34
|
+
has(profileId: string): boolean;
|
|
35
|
+
};
|
|
9
36
|
}
|
|
10
37
|
export interface CredentialResolution {
|
|
11
38
|
ok: boolean;
|
|
12
39
|
/** When ok=false: actionable error message ready to throw. */
|
|
13
40
|
reason?: string;
|
|
14
41
|
/** When ok=true: which source resolved. Useful for debug logs. */
|
|
15
|
-
source?: "keyless" | "providers_entry" | "env_canonical";
|
|
42
|
+
source?: "keyless" | "providers_entry" | "env_canonical" | "oauth_profile";
|
|
43
|
+
/** When ok=true: the provider name actually checked (after "default" resolution). */
|
|
44
|
+
resolvedProvider?: string;
|
|
16
45
|
}
|
|
17
46
|
export declare function resolveProviderCredential(targetProvider: string, deps: CredentialResolverDeps): CredentialResolution;
|