comisai 1.0.28 → 1.0.30
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/bootstrap/sections/tool-descriptions.js +62 -8
- package/node_modules/@comis/agent/dist/bootstrap/sections/tooling-sections.js +3 -1
- package/node_modules/@comis/agent/dist/bridge/pi-event-bridge.d.ts +7 -0
- package/node_modules/@comis/agent/dist/bridge/pi-event-bridge.js +26 -0
- package/node_modules/@comis/agent/dist/context-engine/signature-replay-scrubber.d.ts +21 -0
- package/node_modules/@comis/agent/dist/context-engine/signature-replay-scrubber.js +29 -9
- package/node_modules/@comis/agent/dist/context-engine/signature-surrogate-guard.d.ts +10 -2
- package/node_modules/@comis/agent/dist/context-engine/signature-surrogate-guard.js +15 -9
- package/node_modules/@comis/agent/dist/context-engine/thinking-block-cleaner.d.ts +17 -2
- package/node_modules/@comis/agent/dist/context-engine/thinking-block-cleaner.js +19 -8
- package/node_modules/@comis/agent/dist/executor/executor-prompt-runner.js +28 -0
- package/node_modules/@comis/agent/dist/executor/executor-response-filter.js +3 -0
- package/node_modules/@comis/agent/dist/executor/executor-tool-assembly.js +3 -1
- package/node_modules/@comis/agent/dist/executor/phase-filter.d.ts +20 -4
- package/node_modules/@comis/agent/dist/executor/phase-filter.js +62 -19
- package/node_modules/@comis/agent/dist/executor/pi-executor.js +6 -0
- package/node_modules/@comis/agent/dist/executor/stream-wrappers/config-resolver.js +2 -3
- package/node_modules/@comis/agent/dist/executor/stream-wrappers/request-body-injector.js +2 -3
- package/node_modules/@comis/agent/dist/executor/ttl-guard.js +2 -3
- package/node_modules/@comis/agent/dist/index.d.ts +4 -2
- package/node_modules/@comis/agent/dist/index.js +3 -2
- package/node_modules/@comis/agent/dist/model/compaction-model-resolver.d.ts +41 -0
- package/node_modules/@comis/agent/dist/model/compaction-model-resolver.js +51 -0
- package/node_modules/@comis/agent/dist/model/model-registry-adapter.js +113 -26
- package/node_modules/@comis/agent/dist/model/model-scanner.d.ts +27 -0
- package/node_modules/@comis/agent/dist/model/model-scanner.js +64 -23
- package/node_modules/@comis/agent/dist/model/operation-model-defaults.d.ts +37 -15
- package/node_modules/@comis/agent/dist/model/operation-model-defaults.js +70 -25
- package/node_modules/@comis/agent/dist/model/operation-model-resolver.d.ts +2 -2
- package/node_modules/@comis/agent/dist/model/operation-model-resolver.js +12 -8
- package/node_modules/@comis/agent/dist/provider/capabilities.d.ts +21 -0
- package/node_modules/@comis/agent/dist/provider/capabilities.js +28 -0
- package/node_modules/@comis/agent/dist/session/orphaned-message-repair.js +61 -1
- package/node_modules/@comis/agent/dist/workspace/templates.js +1 -1
- package/node_modules/@comis/agent/package.json +1 -1
- package/node_modules/@comis/channels/dist/shared/channel-manager.d.ts +19 -1
- package/node_modules/@comis/channels/dist/shared/channel-manager.js +59 -3
- package/node_modules/@comis/channels/dist/shared/deliver-to-channel.d.ts +10 -0
- package/node_modules/@comis/channels/dist/shared/deliver-to-channel.js +25 -10
- package/node_modules/@comis/channels/dist/shared/execution-deliver.d.ts +1 -1
- package/node_modules/@comis/channels/dist/shared/execution-deliver.js +1 -1
- package/node_modules/@comis/channels/dist/shared/execution-pipeline.d.ts +8 -0
- package/node_modules/@comis/channels/dist/shared/inbound-pipeline.d.ts +8 -0
- package/node_modules/@comis/channels/dist/shared/inbound-route.d.ts +1 -1
- package/node_modules/@comis/channels/dist/shared/inbound-route.js +1 -0
- package/node_modules/@comis/channels/package.json +1 -1
- package/node_modules/@comis/cli/package.json +1 -1
- package/node_modules/@comis/core/dist/config/schema-agent.d.ts +15 -3
- package/node_modules/@comis/core/dist/config/schema-agent.js +6 -2
- package/node_modules/@comis/core/dist/config/schema-integrations.d.ts +4 -4
- package/node_modules/@comis/core/dist/config/schema-integrations.js +3 -3
- package/node_modules/@comis/core/dist/config/schema-models.d.ts +4 -2
- package/node_modules/@comis/core/dist/config/schema-models.js +4 -2
- package/node_modules/@comis/core/package.json +1 -1
- package/node_modules/@comis/daemon/dist/daemon.js +51 -8
- package/node_modules/@comis/daemon/dist/rpc/agent-handlers.js +40 -9
- package/node_modules/@comis/daemon/dist/rpc/builtin-provider-guard.d.ts +16 -0
- package/node_modules/@comis/daemon/dist/rpc/builtin-provider-guard.js +60 -0
- package/node_modules/@comis/daemon/dist/rpc/config-handlers.js +59 -0
- package/node_modules/@comis/daemon/dist/rpc/credential-resolver.d.ts +17 -0
- package/node_modules/@comis/daemon/dist/rpc/credential-resolver.js +99 -0
- package/node_modules/@comis/daemon/dist/rpc/message-handlers.d.ts +5 -0
- package/node_modules/@comis/daemon/dist/rpc/message-handlers.js +25 -4
- package/node_modules/@comis/daemon/dist/rpc/model-handlers.d.ts +4 -3
- package/node_modules/@comis/daemon/dist/rpc/model-handlers.js +21 -3
- package/node_modules/@comis/daemon/dist/rpc/provider-handlers.js +82 -6
- package/node_modules/@comis/daemon/dist/rpc/rpc-dispatch.d.ts +4 -0
- package/node_modules/@comis/daemon/dist/wiring/inbound-message-id-resolver.d.ts +48 -0
- package/node_modules/@comis/daemon/dist/wiring/inbound-message-id-resolver.js +58 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-agents.d.ts +18 -6
- package/node_modules/@comis/daemon/dist/wiring/setup-agents.js +98 -46
- package/node_modules/@comis/daemon/dist/wiring/setup-channels.d.ts +13 -1
- package/node_modules/@comis/daemon/dist/wiring/setup-channels.js +2 -1
- package/node_modules/@comis/daemon/dist/wiring/setup-gateway-rpc.js +1 -1
- package/node_modules/@comis/daemon/package.json +2 -2
- package/node_modules/@comis/gateway/package.json +1 -1
- package/node_modules/@comis/infra/package.json +1 -1
- package/node_modules/@comis/memory/package.json +1 -1
- package/node_modules/@comis/scheduler/package.json +1 -1
- package/node_modules/@comis/shared/package.json +1 -1
- package/node_modules/@comis/skills/dist/bridge/mcp-tool-bridge.d.ts +1 -1
- package/node_modules/@comis/skills/dist/bridge/mcp-tool-bridge.js +1 -1
- package/node_modules/@comis/skills/dist/bridge/tool-audit.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/exec-tool.d.ts +12 -11
- package/node_modules/@comis/skills/dist/builtin/exec-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/file/apply-patch-tool.d.ts +3 -2
- package/node_modules/@comis/skills/dist/builtin/file/apply-patch-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/file-tools/edit-tool.d.ts +7 -6
- package/node_modules/@comis/skills/dist/builtin/file-tools/edit-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/file-tools/find-tool.d.ts +6 -5
- package/node_modules/@comis/skills/dist/builtin/file-tools/find-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/file-tools/grep-tool.d.ts +16 -15
- package/node_modules/@comis/skills/dist/builtin/file-tools/grep-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/file-tools/ls-tool.d.ts +4 -3
- package/node_modules/@comis/skills/dist/builtin/file-tools/ls-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/file-tools/notebook-edit-tool.d.ts +7 -6
- package/node_modules/@comis/skills/dist/builtin/file-tools/notebook-edit-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/file-tools/read-tool.d.ts +6 -5
- package/node_modules/@comis/skills/dist/builtin/file-tools/read-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/file-tools/write-tool.d.ts +5 -4
- package/node_modules/@comis/skills/dist/builtin/file-tools/write-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/admin-manage-factory.d.ts +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/agents-manage-tool.d.ts +28 -27
- package/node_modules/@comis/skills/dist/builtin/platform/agents-manage-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/background-tasks-tool.d.ts +4 -3
- package/node_modules/@comis/skills/dist/builtin/platform/background-tasks-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/browser-tool-schema.d.ts +67 -66
- package/node_modules/@comis/skills/dist/builtin/platform/browser-tool-schema.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/channels-manage-tool.d.ts +6 -5
- package/node_modules/@comis/skills/dist/builtin/platform/channels-manage-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/cron-tool.d.ts +20 -19
- package/node_modules/@comis/skills/dist/builtin/platform/cron-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/ctx-expand-tool.d.ts +4 -3
- package/node_modules/@comis/skills/dist/builtin/platform/ctx-expand-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/ctx-inspect-tool.d.ts +3 -2
- package/node_modules/@comis/skills/dist/builtin/platform/ctx-inspect-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/ctx-recall-tool.d.ts +6 -5
- package/node_modules/@comis/skills/dist/builtin/platform/ctx-recall-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/ctx-search-tool.d.ts +6 -5
- package/node_modules/@comis/skills/dist/builtin/platform/ctx-search-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/describe-video-tool.d.ts +4 -3
- package/node_modules/@comis/skills/dist/builtin/platform/describe-video-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/discord-action-tool.d.ts +2 -1
- package/node_modules/@comis/skills/dist/builtin/platform/discord-action-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/extract-document-tool.d.ts +4 -3
- package/node_modules/@comis/skills/dist/builtin/platform/extract-document-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/gateway-tool.d.ts +12 -11
- package/node_modules/@comis/skills/dist/builtin/platform/gateway-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/heartbeat-manage-tool.d.ts +23 -22
- package/node_modules/@comis/skills/dist/builtin/platform/heartbeat-manage-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/image-generate-tool.d.ts +4 -3
- package/node_modules/@comis/skills/dist/builtin/platform/image-generate-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/image-tool.d.ts +8 -7
- package/node_modules/@comis/skills/dist/builtin/platform/image-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/mcp-manage-tool.d.ts +9 -8
- package/node_modules/@comis/skills/dist/builtin/platform/mcp-manage-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/memory-get-tool.d.ts +5 -4
- package/node_modules/@comis/skills/dist/builtin/platform/memory-get-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/memory-manage-tool.d.ts +12 -11
- package/node_modules/@comis/skills/dist/builtin/platform/memory-manage-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/memory-search-tool.d.ts +4 -3
- package/node_modules/@comis/skills/dist/builtin/platform/memory-search-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/memory-store-tool.d.ts +4 -3
- package/node_modules/@comis/skills/dist/builtin/platform/memory-store-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/message-tool.d.ts +32 -31
- package/node_modules/@comis/skills/dist/builtin/platform/message-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/messaging-factory.d.ts +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/models-manage-tool.d.ts +4 -3
- package/node_modules/@comis/skills/dist/builtin/platform/models-manage-tool.js +11 -4
- package/node_modules/@comis/skills/dist/builtin/platform/notify-tool.d.ts +6 -5
- package/node_modules/@comis/skills/dist/builtin/platform/notify-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/obs-query-tool.d.ts +11 -10
- package/node_modules/@comis/skills/dist/builtin/platform/obs-query-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/pipeline-tool.d.ts +37 -36
- package/node_modules/@comis/skills/dist/builtin/platform/pipeline-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/platform-action-tool.d.ts +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/providers-manage-tool.d.ts +21 -20
- package/node_modules/@comis/skills/dist/builtin/platform/providers-manage-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/session-search-tool.d.ts +6 -5
- package/node_modules/@comis/skills/dist/builtin/platform/session-search-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/session-status-tool.d.ts +3 -2
- package/node_modules/@comis/skills/dist/builtin/platform/session-status-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/sessions-history-tool.d.ts +5 -4
- package/node_modules/@comis/skills/dist/builtin/platform/sessions-history-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/sessions-list-tool.d.ts +4 -3
- package/node_modules/@comis/skills/dist/builtin/platform/sessions-list-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/sessions-manage-tool.d.ts +5 -4
- package/node_modules/@comis/skills/dist/builtin/platform/sessions-manage-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/sessions-send-tool.d.ts +7 -6
- package/node_modules/@comis/skills/dist/builtin/platform/sessions-send-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/sessions-spawn-tool.d.ts +15 -14
- package/node_modules/@comis/skills/dist/builtin/platform/sessions-spawn-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/skills-manage-tool.d.ts +8 -7
- package/node_modules/@comis/skills/dist/builtin/platform/skills-manage-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/slack-action-tool.d.ts +2 -1
- package/node_modules/@comis/skills/dist/builtin/platform/slack-action-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/subagents-tool.d.ts +7 -6
- package/node_modules/@comis/skills/dist/builtin/platform/subagents-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/telegram-action-tool.d.ts +2 -1
- package/node_modules/@comis/skills/dist/builtin/platform/telegram-action-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/tokens-manage-tool.d.ts +5 -4
- package/node_modules/@comis/skills/dist/builtin/platform/tokens-manage-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/transcribe-audio-tool.d.ts +4 -3
- package/node_modules/@comis/skills/dist/builtin/platform/transcribe-audio-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/tts-tool.d.ts +6 -5
- package/node_modules/@comis/skills/dist/builtin/platform/tts-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/unified-context-tool.d.ts +13 -12
- package/node_modules/@comis/skills/dist/builtin/platform/unified-context-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/unified-memory-tool.d.ts +18 -17
- package/node_modules/@comis/skills/dist/builtin/platform/unified-memory-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/unified-session-tool.d.ts +11 -10
- package/node_modules/@comis/skills/dist/builtin/platform/unified-session-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/whatsapp-action-tool.d.ts +2 -1
- package/node_modules/@comis/skills/dist/builtin/platform/whatsapp-action-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/process-tool.d.ts +6 -5
- package/node_modules/@comis/skills/dist/builtin/process-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/web-fetch-tool.d.ts +5 -4
- package/node_modules/@comis/skills/dist/builtin/web-fetch-tool.js +1 -1
- package/node_modules/@comis/skills/dist/builtin/web-search-tool.d.ts +9 -8
- package/node_modules/@comis/skills/dist/builtin/web-search-tool.js +1 -1
- package/node_modules/@comis/skills/package.json +1 -1
- package/node_modules/@comis/web/dist/assets/{agent-detail-DqL6Artv.js → agent-detail-71BSbSfD.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{agent-editor-CNM_h94Y.js → agent-editor-CTSDZhwT.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{agent-list-Dbh-xD_F.js → agent-list-BEhni2ea.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{billing-view-C1DmtyzK.js → billing-view-DVP1IvVs.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{channel-detail-CtCH22N1.js → channel-detail-N_YK74xC.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{channel-list-C7xXn-60.js → channel-list-DRk6ZJaF.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{chat-console-C51pjFwk.js → chat-console-Dm-GtSf9.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{config-editor-BLArYRB7.js → config-editor-CIferYX6.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{context-dag-browser-fuyMinNI.js → context-dag-browser-CL84rXXM.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{context-engine-Bngf2bH0.js → context-engine-B1HOTEZv.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{delivery-view-C80hucxX.js → delivery-view-Y6JKYVFw.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{diagnostics-view-Cl4VbHZ6.js → diagnostics-view-DWV1UQjz.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{ic-chat-message-ByFUoMm6.js → ic-chat-message-DfSERzzg.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{ic-connection-dot-C4nDHgY2.js → ic-connection-dot-CXyhlJup.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{ic-tool-call-Bh5kq-yY.js → ic-tool-call-DNmwTjek.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{index-BBkuC-EU.js → index-CBr0Tm9_.js} +2 -2
- package/node_modules/@comis/web/dist/assets/{mcp-management-DB-phOo7.js → mcp-management-BaH2-vox.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{media-config-CRqZ1ZUH.js → media-config-CZLshJoN.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{media-test-C9vE20Oy.js → media-test-C9NUWgo_.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{memory-inspector-CeqfnxMZ.js → memory-inspector-D_fmTcRN.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{message-center-Daup7Mof.js → message-center-BBFlNCZn.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{models-DLYnEU8E.js → models-BytGLm99.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{observe-view-BTSt_PO5.js → observe-view-VXtHqaqq.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{pipeline-builder-DknfzyLt.js → pipeline-builder-CfXczlfJ.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{pipeline-history-JnHZdeU_.js → pipeline-history-CPmXFnbe.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{pipeline-history-detail-Dg4knsEb.js → pipeline-history-detail-DcueTMs9.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{pipeline-list-AEnibjsp.js → pipeline-list-B-xG5WZh.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{pipeline-monitor-DG7RbIOO.js → pipeline-monitor-pnIOYaSY.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{scheduler-uL1fYKAT.js → scheduler-BtUIFHhA.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{security-C3DywRLH.js → security-C8mWRq2y.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{session-detail-BtqCNWXV.js → session-detail-DgdkO5ka.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{session-list-CJXWa2XT.js → session-list-DcylcfTn.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{setup-wizard-ywn7oJvu.js → setup-wizard-BP5yjsuL.js} +75 -39
- package/node_modules/@comis/web/dist/assets/{skills-DX0KYnWD.js → skills-DXt1bX8Z.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{subagents-B8p5YJEB.js → subagents-C7YbUHXY.js} +1 -1
- package/node_modules/@comis/web/dist/assets/{workspace-manager-CgzNIrw1.js → workspace-manager-DP6pW4wa.js} +1 -1
- package/node_modules/@comis/web/dist/index.html +1 -1
- package/node_modules/@comis/web/package.json +1 -1
- package/npm-shrinkwrap.json +6126 -0
- package/package.json +74 -74
|
@@ -397,7 +397,11 @@ export declare const ContextEngineConfigSchema: z.ZodObject<{
|
|
|
397
397
|
* triggers on model id / provider / api change (those checks are
|
|
398
398
|
* unconditional regardless of this idle threshold). Range: 1 min .. 24 h. */
|
|
399
399
|
replayDriftIdleMs: z.ZodDefault<z.ZodNumber>;
|
|
400
|
-
/** Model for LLM compaction in "provider:modelId" format.
|
|
400
|
+
/** Model for LLM compaction in "provider:modelId" format. Empty string
|
|
401
|
+
* (the default) triggers runtime resolution against the agent's primary
|
|
402
|
+
* provider via pi-ai catalog (fast-tier cost model). Avoids pinning a
|
|
403
|
+
* hardcoded Anthropic literal that goes stale on pi-ai upgrades and
|
|
404
|
+
* cross-routes background ops to Claude when primary is OpenRouter/Google/etc. */
|
|
401
405
|
compactionModel: z.ZodDefault<z.ZodString>;
|
|
402
406
|
/** Minimum age (in tool result positions) before content is eligible for dead content eviction. */
|
|
403
407
|
evictionMinAge: z.ZodDefault<z.ZodNumber>;
|
|
@@ -1616,7 +1620,11 @@ export declare const PerAgentConfigSchema: z.ZodObject<{
|
|
|
1616
1620
|
* triggers on model id / provider / api change (those checks are
|
|
1617
1621
|
* unconditional regardless of this idle threshold). Range: 1 min .. 24 h. */
|
|
1618
1622
|
replayDriftIdleMs: z.ZodDefault<z.ZodNumber>;
|
|
1619
|
-
/** Model for LLM compaction in "provider:modelId" format.
|
|
1623
|
+
/** Model for LLM compaction in "provider:modelId" format. Empty string
|
|
1624
|
+
* (the default) triggers runtime resolution against the agent's primary
|
|
1625
|
+
* provider via pi-ai catalog (fast-tier cost model). Avoids pinning a
|
|
1626
|
+
* hardcoded Anthropic literal that goes stale on pi-ai upgrades and
|
|
1627
|
+
* cross-routes background ops to Claude when primary is OpenRouter/Google/etc. */
|
|
1620
1628
|
compactionModel: z.ZodDefault<z.ZodString>;
|
|
1621
1629
|
/** Minimum age (in tool result positions) before content is eligible for dead content eviction. */
|
|
1622
1630
|
evictionMinAge: z.ZodDefault<z.ZodNumber>;
|
|
@@ -2309,7 +2317,11 @@ export declare const AgentsMapSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
|
2309
2317
|
* triggers on model id / provider / api change (those checks are
|
|
2310
2318
|
* unconditional regardless of this idle threshold). Range: 1 min .. 24 h. */
|
|
2311
2319
|
replayDriftIdleMs: z.ZodDefault<z.ZodNumber>;
|
|
2312
|
-
/** Model for LLM compaction in "provider:modelId" format.
|
|
2320
|
+
/** Model for LLM compaction in "provider:modelId" format. Empty string
|
|
2321
|
+
* (the default) triggers runtime resolution against the agent's primary
|
|
2322
|
+
* provider via pi-ai catalog (fast-tier cost model). Avoids pinning a
|
|
2323
|
+
* hardcoded Anthropic literal that goes stale on pi-ai upgrades and
|
|
2324
|
+
* cross-routes background ops to Claude when primary is OpenRouter/Google/etc. */
|
|
2313
2325
|
compactionModel: z.ZodDefault<z.ZodString>;
|
|
2314
2326
|
/** Minimum age (in tool result positions) before content is eligible for dead content eviction. */
|
|
2315
2327
|
evictionMinAge: z.ZodDefault<z.ZodNumber>;
|
|
@@ -294,8 +294,12 @@ export const ContextEngineConfigSchema = z.strictObject({
|
|
|
294
294
|
* triggers on model id / provider / api change (those checks are
|
|
295
295
|
* unconditional regardless of this idle threshold). Range: 1 min .. 24 h. */
|
|
296
296
|
replayDriftIdleMs: z.number().int().min(60_000).max(24 * 60 * 60_000).default(30 * 60_000),
|
|
297
|
-
/** Model for LLM compaction in "provider:modelId" format.
|
|
298
|
-
|
|
297
|
+
/** Model for LLM compaction in "provider:modelId" format. Empty string
|
|
298
|
+
* (the default) triggers runtime resolution against the agent's primary
|
|
299
|
+
* provider via pi-ai catalog (fast-tier cost model). Avoids pinning a
|
|
300
|
+
* hardcoded Anthropic literal that goes stale on pi-ai upgrades and
|
|
301
|
+
* cross-routes background ops to Claude when primary is OpenRouter/Google/etc. */
|
|
302
|
+
compactionModel: z.string().default(""),
|
|
299
303
|
/** Minimum age (in tool result positions) before content is eligible for dead content eviction. */
|
|
300
304
|
evictionMinAge: z.number().int().min(3).max(50).default(15),
|
|
301
305
|
// --- Pipeline mode ---
|
|
@@ -306,10 +306,10 @@ export declare const VisionConfigSchema: z.ZodObject<{
|
|
|
306
306
|
* Link understanding configuration.
|
|
307
307
|
*
|
|
308
308
|
* Controls automatic URL detection, fetching, and content extraction
|
|
309
|
-
* from inbound messages.
|
|
309
|
+
* from inbound messages.
|
|
310
310
|
*/
|
|
311
311
|
export declare const LinkUnderstandingConfigSchema: z.ZodObject<{
|
|
312
|
-
/** Enable automatic link understanding (default:
|
|
312
|
+
/** Enable automatic link understanding (default: true) */
|
|
313
313
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
314
314
|
/** Maximum number of links to process per message (default: 3) */
|
|
315
315
|
maxLinks: z.ZodDefault<z.ZodNumber>;
|
|
@@ -541,7 +541,7 @@ export declare const MediaConfigSchema: z.ZodObject<{
|
|
|
541
541
|
}, z.core.$strict>>;
|
|
542
542
|
/** Link understanding settings */
|
|
543
543
|
linkUnderstanding: z.ZodDefault<z.ZodObject<{
|
|
544
|
-
/** Enable automatic link understanding (default:
|
|
544
|
+
/** Enable automatic link understanding (default: true) */
|
|
545
545
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
546
546
|
/** Maximum number of links to process per message (default: 3) */
|
|
547
547
|
maxLinks: z.ZodDefault<z.ZodNumber>;
|
|
@@ -848,7 +848,7 @@ export declare const IntegrationsConfigSchema: z.ZodObject<{
|
|
|
848
848
|
}, z.core.$strict>>;
|
|
849
849
|
/** Link understanding settings */
|
|
850
850
|
linkUnderstanding: z.ZodDefault<z.ZodObject<{
|
|
851
|
-
/** Enable automatic link understanding (default:
|
|
851
|
+
/** Enable automatic link understanding (default: true) */
|
|
852
852
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
853
853
|
/** Maximum number of links to process per message (default: 3) */
|
|
854
854
|
maxLinks: z.ZodDefault<z.ZodNumber>;
|
|
@@ -197,11 +197,11 @@ export const VisionConfigSchema = z.strictObject({
|
|
|
197
197
|
* Link understanding configuration.
|
|
198
198
|
*
|
|
199
199
|
* Controls automatic URL detection, fetching, and content extraction
|
|
200
|
-
* from inbound messages.
|
|
200
|
+
* from inbound messages.
|
|
201
201
|
*/
|
|
202
202
|
export const LinkUnderstandingConfigSchema = z.strictObject({
|
|
203
|
-
/** Enable automatic link understanding (default:
|
|
204
|
-
enabled: z.boolean().default(
|
|
203
|
+
/** Enable automatic link understanding (default: true) */
|
|
204
|
+
enabled: z.boolean().default(true),
|
|
205
205
|
/** Maximum number of links to process per message (default: 3) */
|
|
206
206
|
maxLinks: z.number().int().positive().default(3),
|
|
207
207
|
/** Timeout for fetching each URL in milliseconds (default: 10000) */
|
|
@@ -34,10 +34,12 @@ export declare const ModelsConfigSchema: z.ZodObject<{
|
|
|
34
34
|
modelId: z.ZodString;
|
|
35
35
|
}, z.core.$strict>>>;
|
|
36
36
|
/** Default model identifier. When a per-agent config sets model: "default", this value is used.
|
|
37
|
-
*
|
|
37
|
+
* When empty (the default), runtime resolution picks the mid-tier cost
|
|
38
|
+
* model from the resolved provider's pi-ai catalog (resolveOperationDefaults). */
|
|
38
39
|
defaultModel: z.ZodDefault<z.ZodString>;
|
|
39
40
|
/** Default provider. When a per-agent config sets provider: "default", this value is used.
|
|
40
|
-
*
|
|
41
|
+
* When empty (the default), runtime resolution picks the most-populated
|
|
42
|
+
* native provider from the pi-ai catalog (heuristic). */
|
|
41
43
|
defaultProvider: z.ZodDefault<z.ZodString>;
|
|
42
44
|
}, z.core.$strict>;
|
|
43
45
|
/** Inferred models configuration type. */
|
|
@@ -28,9 +28,11 @@ export const ModelsConfigSchema = z.strictObject({
|
|
|
28
28
|
/** Friendly model aliases (e.g., "claude" -> anthropic/claude-sonnet-4) */
|
|
29
29
|
aliases: z.array(ModelAliasSchema).default([]),
|
|
30
30
|
/** Default model identifier. When a per-agent config sets model: "default", this value is used.
|
|
31
|
-
*
|
|
31
|
+
* When empty (the default), runtime resolution picks the mid-tier cost
|
|
32
|
+
* model from the resolved provider's pi-ai catalog (resolveOperationDefaults). */
|
|
32
33
|
defaultModel: z.string().default(""),
|
|
33
34
|
/** Default provider. When a per-agent config sets provider: "default", this value is used.
|
|
34
|
-
*
|
|
35
|
+
* When empty (the default), runtime resolution picks the most-populated
|
|
36
|
+
* native provider from the pi-ai catalog (heuristic). */
|
|
35
37
|
defaultProvider: z.string().default(""),
|
|
36
38
|
});
|
|
@@ -9,7 +9,7 @@ import { ok, err, suppressError } from "@comis/shared";
|
|
|
9
9
|
import { createGatewayServer } from "@comis/gateway";
|
|
10
10
|
import { setupLogging, setupObservability, setupHealth, setupMemory, setupAgents, setupSchedulers, setupChannels, setupMedia, setupCrossSession, setupMcp, setupTools, setupMonitoring, setupHeartbeat, setupTaskExtraction, setupShutdown, setupGateway, setupRpcBridge, setupDeliveryQueue, setupDeliveryMirror, setupNotifications, setupBackgroundTasks, } from "./wiring/index.js";
|
|
11
11
|
import { setupSingleAgent } from "./wiring/setup-agents.js";
|
|
12
|
-
import { createActiveRunRegistry, createModelCatalog, wireSessionStateCleanup, wireMcpDisconnectCleanup, createGeminiCacheManager, wireGeminiCacheCleanup, createSessionTrackerRegistry } from "@comis/agent";
|
|
12
|
+
import { createActiveRunRegistry, createModelCatalog, wireSessionStateCleanup, wireMcpDisconnectCleanup, createGeminiCacheManager, wireGeminiCacheCleanup, createSessionTrackerRegistry, validateProviderOverrides } from "@comis/agent";
|
|
13
13
|
import { detectSandboxProvider, createImageGenProvider, createImageGenRateLimiter, createFileStateTracker } from "@comis/skills";
|
|
14
14
|
import { createGraphCoordinator, createNodeTypeRegistry } from "./graph/index.js";
|
|
15
15
|
import { createChannelHealthMonitor } from "@comis/channels";
|
|
@@ -33,6 +33,7 @@ import { writeFile as fsWriteFile, rm } from "node:fs/promises";
|
|
|
33
33
|
import { createExecGit } from "./config/exec-git.js";
|
|
34
34
|
import { saveLastKnownGood, buildRollbackSuggestion, handleRestoreFlag } from "./config/last-known-good.js";
|
|
35
35
|
import { createRestartContinuationTracker, loadContinuations, buildMcpStatusLine } from "./wiring/restart-continuation.js";
|
|
36
|
+
import { createInboundMessageIdResolver } from "./wiring/inbound-message-id-resolver.js";
|
|
36
37
|
import { logOperationModelDryRun } from "./wiring/startup-dry-run.js";
|
|
37
38
|
import os from "node:os";
|
|
38
39
|
import { join as pathJoin, dirname as pathDirname, resolve as pathResolve } from "node:path";
|
|
@@ -327,6 +328,11 @@ export async function main(overrides = {}) {
|
|
|
327
328
|
if (approvalsWarning) {
|
|
328
329
|
daemonLogger.warn({ hint: "Set approvals.enabled: true or remove unused rules", errorKind: "config" }, approvalsWarning);
|
|
329
330
|
}
|
|
331
|
+
// 3.6. Validate PROVIDER_OVERRIDES vs live pi-ai catalog (Layer 3C -- 260501-07g).
|
|
332
|
+
// Emits one structured WARN per orphaned override key (provider listed in
|
|
333
|
+
// PROVIDER_OVERRIDES that pi-ai no longer ships). Fire-and-forget: never
|
|
334
|
+
// throws, daemon continues to boot with dead override entries.
|
|
335
|
+
validateProviderOverrides(agentLogger);
|
|
330
336
|
// 4. Observability
|
|
331
337
|
const { tokenTracker, latencyRecorder, sharedCostTracker, // needed for obs.reset billing clear
|
|
332
338
|
diagnosticCollector, billingEstimator, channelActivityTracker, deliveryTracer, } = setupObservability({ eventBus: container.eventBus, _createTokenTracker, _createLatencyRecorder, logger: logLevelManager.getLogger("observability"), dataDir });
|
|
@@ -620,11 +626,20 @@ export async function main(overrides = {}) {
|
|
|
620
626
|
// before setupTools completes).
|
|
621
627
|
// Deferred notification session tracker ref: wired after setupNotifications returns.
|
|
622
628
|
// The onMessageProcessed callback reads this at call time (not definition time),
|
|
623
|
-
// so it is always set before any message arrives.
|
|
629
|
+
// so it is always set before any message arrives. recordActivity MUST stay in
|
|
630
|
+
// the post-processing callback because the ref is wired AFTER setupChannels
|
|
631
|
+
// returns; tracker.track moved to onMessageReceived which has no such dep.
|
|
624
632
|
const sessionTrackerRef = {};
|
|
625
633
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- matches assembleToolsForAgent signature from setup-tools.ts
|
|
626
634
|
const toolAssemblerRef = {};
|
|
627
|
-
|
|
635
|
+
// Resolver translating daemon UUIDs (NormalizedMessage.id) back to platform-
|
|
636
|
+
// native message ids (e.g. Telegram integer message_id) for the
|
|
637
|
+
// message.delete/edit/react RPC handlers. Built post-setupChannels (needs
|
|
638
|
+
// channelCapabilities from the return), captured by reference inside the
|
|
639
|
+
// onMessageReceived lambda below — safe because no inbound message can fire
|
|
640
|
+
// before channelManager.start() runs later.
|
|
641
|
+
let inboundMessageIdResolver;
|
|
642
|
+
const { adaptersByType, channelManager, resolveAttachment, lifecycleReactors, channelPlugins, channelCapabilities, commandQueue } = await setupChannels({
|
|
628
643
|
container, executors, defaultAgentId, sessionManager, sessionStore,
|
|
629
644
|
logger, channelsLogger,
|
|
630
645
|
linkRunner,
|
|
@@ -654,8 +669,16 @@ export async function main(overrides = {}) {
|
|
|
654
669
|
rpcCall,
|
|
655
670
|
// Task extraction callback (gated by config.scheduler.tasks.enabled)
|
|
656
671
|
onTaskExtraction: extractFromConversation,
|
|
657
|
-
// Restart continuation: track recently-active sessions for SIGUSR2 replay
|
|
658
|
-
|
|
672
|
+
// Restart continuation: track recently-active sessions for SIGUSR2 replay.
|
|
673
|
+
// Two-callback timing split (260430-s4m corrects the r4i-A flaw):
|
|
674
|
+
// onMessageReceived fires BEFORE processInboundMessage so the tracker
|
|
675
|
+
// Map is populated before any tool call could trigger SIGUSR2 mid-
|
|
676
|
+
// execution. Without this, multi-restart chains saw 0 captured records
|
|
677
|
+
// and the next instance had nothing to replay -> silent bot.
|
|
678
|
+
// onMessageProcessed fires AFTER processing for sessionTrackerRef
|
|
679
|
+
// because the ref is wired post-setupNotifications (deferred-ref
|
|
680
|
+
// pattern); calling it pre-processing would fire on an undefined ref.
|
|
681
|
+
onMessageReceived: (msg, channelType) => {
|
|
659
682
|
// Preserve channel-native chat type so post-restart synthetic messages
|
|
660
683
|
// can frame group sessions correctly. Without this, group inbounds are
|
|
661
684
|
// mis-framed as DMs on first turn after restart.
|
|
@@ -671,8 +694,16 @@ export async function main(overrides = {}) {
|
|
|
671
694
|
tenantId: container.config.tenantId,
|
|
672
695
|
timestamp: Date.now(),
|
|
673
696
|
});
|
|
697
|
+
// Translate daemon UUID -> platform-native message id so message.delete/
|
|
698
|
+
// edit/react can call channel adapters with what they actually expect.
|
|
699
|
+
// Resolver is assigned just after setupChannels returns (below).
|
|
700
|
+
inboundMessageIdResolver?.record(msg, channelType);
|
|
701
|
+
},
|
|
702
|
+
onMessageProcessed: (msg, channelType) => {
|
|
674
703
|
// Record session activity for notification channel resolution fallback.
|
|
675
|
-
// sessionTrackerRef is populated
|
|
704
|
+
// sessionTrackerRef.ref is populated post-construction by
|
|
705
|
+
// setupNotifications (line 879 below), so this MUST stay in the
|
|
706
|
+
// after-processing callback -- moving it earlier would fire on undefined.
|
|
676
707
|
sessionTrackerRef.ref?.recordActivity(defaultAgentId, channelType, msg.channelId);
|
|
677
708
|
},
|
|
678
709
|
// /approve and /deny chat command interception
|
|
@@ -687,6 +718,18 @@ export async function main(overrides = {}) {
|
|
|
687
718
|
});
|
|
688
719
|
// Populate channel plugins ref for per-message char limit resolution.
|
|
689
720
|
channelPluginsRef.ref = channelPlugins;
|
|
721
|
+
// Build the inbound message id resolver now that we have channelCapabilities.
|
|
722
|
+
// Each enabled channel contributes its `replyToMetaKey` (e.g. "telegramMessageId")
|
|
723
|
+
// so the resolver knows which metadata field to read on inbound to capture
|
|
724
|
+
// the platform-native id. Safe to assign now: setupChannels has not started
|
|
725
|
+
// adapters yet, so no inbound message has fired the onMessageReceived lambda.
|
|
726
|
+
{
|
|
727
|
+
const metaKeyByChannel = new Map();
|
|
728
|
+
for (const [type, cap] of channelCapabilities) {
|
|
729
|
+
metaKeyByChannel.set(type, cap.replyToMetaKey);
|
|
730
|
+
}
|
|
731
|
+
inboundMessageIdResolver = createInboundMessageIdResolver({ metaKeyByChannel });
|
|
732
|
+
}
|
|
690
733
|
// Populate channelAdapters ref now that setupChannels has returned.
|
|
691
734
|
// The drain cycle needs adapters to re-deliver pending messages.
|
|
692
735
|
for (const [type, adapter] of adaptersByType) {
|
|
@@ -1029,7 +1072,7 @@ export async function main(overrides = {}) {
|
|
|
1029
1072
|
agentDataDir: pathJoin(container.config.dataDir ?? pathJoin(os.homedir(), ".comis"), "agents"),
|
|
1030
1073
|
sessionStore: sessionStoreBridge,
|
|
1031
1074
|
crossSessionSender, subAgentRunner, graphCoordinator, namedGraphStore, nodeTypeRegistry,
|
|
1032
|
-
securityConfig: container.config.security, adaptersByType, visionRegistry,
|
|
1075
|
+
securityConfig: container.config.security, adaptersByType, inboundMessageIdResolver, visionRegistry,
|
|
1033
1076
|
mediaConfig: container.config.integrations.media, ttsAdapter, linkRunner,
|
|
1034
1077
|
logger, container, configPaths, defaultConfigPaths: DEFAULT_CONFIG_PATHS,
|
|
1035
1078
|
configGitManager,
|
|
@@ -1167,7 +1210,7 @@ export async function main(overrides = {}) {
|
|
|
1167
1210
|
errorKind: "dependency",
|
|
1168
1211
|
}, "MCP connection failures detected during restart continuation replay");
|
|
1169
1212
|
}
|
|
1170
|
-
const baseText = "[system: daemon restarted
|
|
1213
|
+
const baseText = "[system: daemon restarted to apply a config change. The result of your previous tool call is in the conversation above — react to it naturally, confirm or surface any issue, then yield to the user.]";
|
|
1171
1214
|
for (const record of continuations) {
|
|
1172
1215
|
// Skip sessions that already received a message during this startup cycle
|
|
1173
1216
|
// (e.g., Telegram webhook delivered before continuation replay ran).
|
|
@@ -18,6 +18,7 @@ import { resolveWorkspaceDir, resolveOperationModel, resolveProviderFamily, OPER
|
|
|
18
18
|
import { persistToConfig } from "./persist-to-config.js";
|
|
19
19
|
import { writeInlineWorkspaceFiles, } from "./agent-inline-workspace.js";
|
|
20
20
|
import { probeProviderAuth } from "./probe-provider-auth.js";
|
|
21
|
+
import { resolveProviderCredential } from "./credential-resolver.js";
|
|
21
22
|
// ---------------------------------------------------------------------------
|
|
22
23
|
// Factory
|
|
23
24
|
// ---------------------------------------------------------------------------
|
|
@@ -68,6 +69,18 @@ export function createAgentHandlers(deps) {
|
|
|
68
69
|
existingSkills.builtinTools = { ...DEFAULT_BUILTIN_TOOLS, ...existingBt };
|
|
69
70
|
raw.skills = existingSkills;
|
|
70
71
|
const parsedConfig = PerAgentConfigSchema.parse(config);
|
|
72
|
+
// Credential guard (260501-2pz): fail-loud if the new agent's
|
|
73
|
+
// provider has no resolvable API key. Mirrors agents.update guard
|
|
74
|
+
// ordering — runs BEFORE the in-memory commit so rejection prevents
|
|
75
|
+
// assignment, file persist, and hot-add. Same helper as the patch /
|
|
76
|
+
// update call sites for cross-handler consistency.
|
|
77
|
+
const credCheck = resolveProviderCredential(parsedConfig.provider, {
|
|
78
|
+
providerEntries: deps.providerEntries ?? {},
|
|
79
|
+
secretManager: deps.secretManager,
|
|
80
|
+
});
|
|
81
|
+
if (!credCheck.ok) {
|
|
82
|
+
throw new Error(credCheck.reason);
|
|
83
|
+
}
|
|
71
84
|
deps.agents[agentId] = parsedConfig;
|
|
72
85
|
// Best-effort persistence to config.yaml
|
|
73
86
|
if (deps.persistDeps) {
|
|
@@ -207,18 +220,36 @@ export function createAgentHandlers(deps) {
|
|
|
207
220
|
}
|
|
208
221
|
const merged = { ...existing, ...config };
|
|
209
222
|
const parsedConfig = PerAgentConfigSchema.parse(merged);
|
|
210
|
-
//
|
|
223
|
+
// Credential guard + probe (260501-2pz): when provider OR model
|
|
224
|
+
// changes, (a) GUARD — fail-loud if the resulting provider's API key
|
|
225
|
+
// is not resolvable from any source (no silent skip), then (b) PROBE
|
|
226
|
+
// — preexisting wire validation when an explicit providers.entries
|
|
227
|
+
// record with apiKeyName exists. Order matters: guard runs first
|
|
228
|
+
// (cheap, all paths), probe runs second (only when applicable).
|
|
211
229
|
const providerChanging = config.provider !== undefined && config.provider !== existing.provider;
|
|
212
230
|
const modelChanging = config.model !== undefined && config.model !== existing.model;
|
|
213
|
-
if (
|
|
231
|
+
if (providerChanging || modelChanging) {
|
|
214
232
|
const targetProvider = parsedConfig.provider;
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
233
|
+
// (a) GUARD — fail-loud if no credential source resolves
|
|
234
|
+
const resolution = resolveProviderCredential(targetProvider, {
|
|
235
|
+
providerEntries: deps.providerEntries ?? {},
|
|
236
|
+
secretManager: deps.secretManager,
|
|
237
|
+
});
|
|
238
|
+
if (!resolution.ok) {
|
|
239
|
+
throw new Error(resolution.reason);
|
|
240
|
+
}
|
|
241
|
+
// (b) PROBE — preexisting behavior, fires only when an explicit
|
|
242
|
+
// providers.entries record with apiKeyName exists and the secret
|
|
243
|
+
// is retrievable. Validates the key works against the wire.
|
|
244
|
+
if (deps.providerEntries) {
|
|
245
|
+
const providerEntry = deps.providerEntries[targetProvider];
|
|
246
|
+
if (providerEntry?.apiKeyName && deps.secretManager) {
|
|
247
|
+
const apiKey = deps.secretManager.get(providerEntry.apiKeyName);
|
|
248
|
+
if (apiKey) {
|
|
249
|
+
const probeResult = await probeProviderAuth(providerEntry.baseUrl, apiKey, parsedConfig.model);
|
|
250
|
+
if (!probeResult.ok) {
|
|
251
|
+
throw new Error(`Cannot switch agent "${agentId}" to provider "${targetProvider}": ${probeResult.error}`);
|
|
252
|
+
}
|
|
222
253
|
}
|
|
223
254
|
}
|
|
224
255
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type BuiltInProviderGuardResult = {
|
|
2
|
+
ok: true;
|
|
3
|
+
} | {
|
|
4
|
+
ok: false;
|
|
5
|
+
reason: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Check whether a providers.create call would land a redundant custom
|
|
9
|
+
* entry that shadows pi-ai's dynamic catalog. Returns ok=true when the
|
|
10
|
+
* call is legitimate (genuine custom provider OR proxy with distinct
|
|
11
|
+
* baseUrl), ok=false with an actionable reason otherwise.
|
|
12
|
+
*/
|
|
13
|
+
export declare function checkBuiltInProviderRedundancy(providerId: string, config: {
|
|
14
|
+
baseUrl?: string;
|
|
15
|
+
apiKeyName?: string;
|
|
16
|
+
}): BuiltInProviderGuardResult;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* Built-in provider redundancy guard for providers.create (260501-gyy FIX 2).
|
|
4
|
+
*
|
|
5
|
+
* Rejects providers_manage create attempts that would shadow pi-ai's
|
|
6
|
+
* dynamic catalog with a redundant custom entry. A built-in provider
|
|
7
|
+
* (one in pi-ai's getProviders()) already has its full model list
|
|
8
|
+
* available via the catalog -- custom entries are only legitimate for
|
|
9
|
+
* proxies (different baseUrl) or non-SDK providers. Without this guard,
|
|
10
|
+
* an LLM agent that creates a catalog-shadowing entry with a stale or
|
|
11
|
+
* invented model id sets up downstream 404 / "model not found" failures
|
|
12
|
+
* (production: 2026-05-01 08:53-08:54 trace).
|
|
13
|
+
*
|
|
14
|
+
* Generic by construction: rejection message uses ${providerId} +
|
|
15
|
+
* ${apiKeyName} interpolation only -- no per-provider hardcoded names
|
|
16
|
+
* in the source template (catalog-agnostic). Pinned by source-grep
|
|
17
|
+
* regression test in builtin-provider-guard.test.ts.
|
|
18
|
+
*
|
|
19
|
+
* Mirrors credential-resolver.ts shape (260501-2pz precedent).
|
|
20
|
+
*
|
|
21
|
+
* @module
|
|
22
|
+
*/
|
|
23
|
+
import { getProviders, getModels } from "@mariozechner/pi-ai";
|
|
24
|
+
/**
|
|
25
|
+
* Check whether a providers.create call would land a redundant custom
|
|
26
|
+
* entry that shadows pi-ai's dynamic catalog. Returns ok=true when the
|
|
27
|
+
* call is legitimate (genuine custom provider OR proxy with distinct
|
|
28
|
+
* baseUrl), ok=false with an actionable reason otherwise.
|
|
29
|
+
*/
|
|
30
|
+
export function checkBuiltInProviderRedundancy(providerId, config) {
|
|
31
|
+
const native = new Set(getProviders());
|
|
32
|
+
if (!native.has(providerId)) {
|
|
33
|
+
// Genuine custom provider -- never redundant.
|
|
34
|
+
return { ok: true };
|
|
35
|
+
}
|
|
36
|
+
const catalogBaseUrl = getModels(providerId)[0]?.baseUrl;
|
|
37
|
+
const userBaseUrl = config.baseUrl?.trim();
|
|
38
|
+
if (userBaseUrl && userBaseUrl !== catalogBaseUrl) {
|
|
39
|
+
// Legitimate proxy -- user pointed at a non-catalog URL.
|
|
40
|
+
return { ok: true };
|
|
41
|
+
}
|
|
42
|
+
// Built-in + catalog/absent baseUrl -> redundant.
|
|
43
|
+
return {
|
|
44
|
+
ok: false,
|
|
45
|
+
reason: buildRejectionMessage(providerId, config),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function buildRejectionMessage(providerId, config) {
|
|
49
|
+
const apiKeyName = config.apiKeyName ?? "<APIKEY_NAME>";
|
|
50
|
+
const lines = [];
|
|
51
|
+
lines.push(`Cannot create custom provider entry for "${providerId}": this provider is built-in to the pi-ai SDK with its full model catalog available dynamically. Custom entries are only needed for proxies (different baseUrl) or non-SDK providers.`);
|
|
52
|
+
lines.push("");
|
|
53
|
+
lines.push("To use this provider:");
|
|
54
|
+
lines.push(` 1. gateway env_set ${apiKeyName}=<your-key> (find name via gateway env_list)`);
|
|
55
|
+
lines.push(` 2. gateway patch agents.<id>.provider = "${providerId}"`);
|
|
56
|
+
lines.push(` 3. gateway patch agents.<id>.model = "<model-id>" (find available models via models_manage list provider:${providerId})`);
|
|
57
|
+
lines.push("");
|
|
58
|
+
lines.push(`If you intended a custom proxy with a different base URL, supply a distinct provider_id (e.g., "${providerId}-proxy") and your custom baseUrl.`);
|
|
59
|
+
return lines.join("\n");
|
|
60
|
+
}
|
|
@@ -14,6 +14,39 @@ import { stringify as yamlStringify } from "yaml";
|
|
|
14
14
|
import { existsSync, readFileSync, writeFileSync, mkdirSync, renameSync } from "node:fs";
|
|
15
15
|
import { dirname } from "node:path";
|
|
16
16
|
import { z } from "zod";
|
|
17
|
+
import { resolveProviderCredential } from "./credential-resolver.js";
|
|
18
|
+
/**
|
|
19
|
+
* True when the patch key writes a provider/model field.
|
|
20
|
+
* Matches `<id>.provider` or `<id>.model` (leaf only — does not match
|
|
21
|
+
* nested paths like modelFailover.fallbackModels.0.provider, which is
|
|
22
|
+
* deliberately out-of-scope for the credential guard).
|
|
23
|
+
*/
|
|
24
|
+
function isAgentProviderOrModelKey(key) {
|
|
25
|
+
if (!key)
|
|
26
|
+
return false;
|
|
27
|
+
return /(^|\.)(provider|model)$/.test(key);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Resolve the provider value the patch is establishing.
|
|
31
|
+
* - For `.provider` patches, the new value IS the provider.
|
|
32
|
+
* - For `.model`-only patches, look up the agent's CURRENT provider
|
|
33
|
+
* (validates that the agent's existing auth chain still resolves —
|
|
34
|
+
* surfaces stale broken configs at patch time rather than at next chat).
|
|
35
|
+
* Returns undefined for paths the guard doesn't validate.
|
|
36
|
+
*/
|
|
37
|
+
function extractTargetProvider(key, newValue, currentConfig) {
|
|
38
|
+
if (key.endsWith(".provider")) {
|
|
39
|
+
return typeof newValue === "string" ? newValue : undefined;
|
|
40
|
+
}
|
|
41
|
+
if (key.endsWith(".model")) {
|
|
42
|
+
const agentId = key.split(".")[0];
|
|
43
|
+
if (!agentId)
|
|
44
|
+
return undefined;
|
|
45
|
+
// eslint-disable-next-line security/detect-object-injection -- agents map is typed Record; agentId from validated key
|
|
46
|
+
return currentConfig.agents?.[agentId]?.provider;
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
17
50
|
/**
|
|
18
51
|
* Restore MCP server `env` from existing YAML when the UI patch
|
|
19
52
|
* omits it (because config.read redacted secret values to "[REDACTED]").
|
|
@@ -419,6 +452,32 @@ export function createConfigHandlers(deps) {
|
|
|
419
452
|
: " This setting requires manual operator intervention via config files.";
|
|
420
453
|
throw new Error(`Config path "${key ? `${section}.${key}` : section}" is immutable and cannot be modified at runtime.${suffix}`);
|
|
421
454
|
}
|
|
455
|
+
// Credential guard (260501-2pz): when a patch targets an agent's
|
|
456
|
+
// provider/model field, verify the resulting provider's API key is
|
|
457
|
+
// resolvable from at least one source pi-coding-agent will consult
|
|
458
|
+
// at runtime. Fail-loud here rather than letting an unauthorized
|
|
459
|
+
// provider config persist and explode at the next chat turn.
|
|
460
|
+
// See `.planning/design/daemon-credential-guard/PLAN.md`.
|
|
461
|
+
if (section === "agents" && isAgentProviderOrModelKey(key)) {
|
|
462
|
+
const targetProvider = extractTargetProvider(key, coercedValue, deps.container.config);
|
|
463
|
+
if (targetProvider !== undefined) {
|
|
464
|
+
const resolution = resolveProviderCredential(targetProvider, {
|
|
465
|
+
providerEntries: deps.container.config.providers?.entries ?? {},
|
|
466
|
+
secretManager: deps.container.secretManager,
|
|
467
|
+
});
|
|
468
|
+
if (!resolution.ok) {
|
|
469
|
+
deps.logger.warn({
|
|
470
|
+
method: "config.patch",
|
|
471
|
+
section,
|
|
472
|
+
key,
|
|
473
|
+
targetProvider,
|
|
474
|
+
hint: "Provider credential not resolvable",
|
|
475
|
+
errorKind: "validation",
|
|
476
|
+
}, "Config patch rejected: missing provider credential");
|
|
477
|
+
throw new Error(resolution.reason);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
422
481
|
// Build patch object (use coerced value for the actual data, keep original for audit)
|
|
423
482
|
let patch;
|
|
424
483
|
if (key) {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ProviderEntry } from "@comis/core";
|
|
2
|
+
export interface CredentialResolverDeps {
|
|
3
|
+
/** Provider-entry map from comis config (providers.entries). */
|
|
4
|
+
providerEntries?: Record<string, ProviderEntry>;
|
|
5
|
+
/** Secret manager backing process.env / ~/.comis/.env. */
|
|
6
|
+
secretManager?: {
|
|
7
|
+
has(key: string): boolean;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export interface CredentialResolution {
|
|
11
|
+
ok: boolean;
|
|
12
|
+
/** When ok=false: actionable error message ready to throw. */
|
|
13
|
+
reason?: string;
|
|
14
|
+
/** When ok=true: which source resolved. Useful for debug logs. */
|
|
15
|
+
source?: "keyless" | "providers_entry" | "env_canonical";
|
|
16
|
+
}
|
|
17
|
+
export declare function resolveProviderCredential(targetProvider: string, deps: CredentialResolverDeps): CredentialResolution;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* Pre-write credential validator for agent provider/model patches.
|
|
4
|
+
*
|
|
5
|
+
* When a patch sets agents.<id>.provider, verify the API key is resolvable
|
|
6
|
+
* from one of the sources pi-coding-agent will consult at runtime. Reject
|
|
7
|
+
* fail-loud with an actionable error if no source resolves.
|
|
8
|
+
*
|
|
9
|
+
* Resolution chain (matches pi-coding-agent runtime semantics):
|
|
10
|
+
* 1. KEYLESS_PROVIDER_TYPES.has(entry.type) — ollama / lm-studio
|
|
11
|
+
* 2. providers.entries.<provider>.apiKeyName → secretManager.has(...)
|
|
12
|
+
* 3. pi-ai's getEnvApiKey(provider) — canonical env + OAuth + ADC + AWS
|
|
13
|
+
*
|
|
14
|
+
* @module
|
|
15
|
+
*/
|
|
16
|
+
import { getEnvApiKey } from "@mariozechner/pi-ai";
|
|
17
|
+
/**
|
|
18
|
+
* Provider types that don't need an API key. Mirrors agent's
|
|
19
|
+
* KEYLESS_PROVIDER_TYPES at model-registry-adapter.ts:60 — extended here to
|
|
20
|
+
* include lm-studio (the agent-side may also extend in a follow-up; the
|
|
21
|
+
* tool guide already documents lm-studio as keyless).
|
|
22
|
+
*/
|
|
23
|
+
const KEYLESS_PROVIDER_TYPES = new Set(["ollama", "lm-studio"]);
|
|
24
|
+
export function resolveProviderCredential(targetProvider, deps) {
|
|
25
|
+
if (!targetProvider || typeof targetProvider !== "string") {
|
|
26
|
+
return {
|
|
27
|
+
ok: false,
|
|
28
|
+
reason: `Invalid provider value: must be a non-empty string (got ${JSON.stringify(targetProvider)})`,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
// eslint-disable-next-line security/detect-object-injection -- typed Record<string, ProviderEntry> read; targetProvider validated above
|
|
32
|
+
const entry = deps.providerEntries?.[targetProvider];
|
|
33
|
+
// 1. Keyless types
|
|
34
|
+
if (entry && KEYLESS_PROVIDER_TYPES.has(entry.type)) {
|
|
35
|
+
return { ok: true, source: "keyless" };
|
|
36
|
+
}
|
|
37
|
+
// 2. Source A: providers.entries with secret-manager-resolvable apiKeyName
|
|
38
|
+
if (entry?.apiKeyName && deps.secretManager?.has(entry.apiKeyName)) {
|
|
39
|
+
return { ok: true, source: "providers_entry" };
|
|
40
|
+
}
|
|
41
|
+
// 3. Source B: pi-ai canonical env / OAuth / ADC chain
|
|
42
|
+
if (getEnvApiKey(targetProvider)) {
|
|
43
|
+
return { ok: true, source: "env_canonical" };
|
|
44
|
+
}
|
|
45
|
+
return { ok: false, reason: buildRejectionMessage(targetProvider, entry) };
|
|
46
|
+
}
|
|
47
|
+
function buildRejectionMessage(targetProvider, entry) {
|
|
48
|
+
const lines = [];
|
|
49
|
+
lines.push(`Cannot set agent provider to "${targetProvider}": no API key found.`);
|
|
50
|
+
if (entry?.apiKeyName) {
|
|
51
|
+
lines.push(`The configured providers.entries.${targetProvider}.apiKeyName is "${entry.apiKeyName}", but that name is not in env.`);
|
|
52
|
+
lines.push(`Recovery:`);
|
|
53
|
+
lines.push(` Run gateway({action:"env_set", env_key:"${entry.apiKeyName}", env_value:"<key>"}) to store the key, then retry this patch.`);
|
|
54
|
+
lines.push(` Run gateway({action:"env_list", filter:"${targetProvider.toUpperCase()}*"}) to see what's already configured.`);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
const canonical = canonicalEnvKeyHint(targetProvider);
|
|
58
|
+
lines.push(`No providers.entries.${targetProvider} exists, and the canonical env key${canonical ? ` (${canonical})` : ""} is not set.`);
|
|
59
|
+
lines.push(`Recovery options (pick one):`);
|
|
60
|
+
lines.push(canonical
|
|
61
|
+
? ` (a) Run gateway({action:"env_set", env_key:"${canonical}", env_value:"<key>"}) to store the key, then retry this patch.`
|
|
62
|
+
: ` (a) Run gateway({action:"env_list", filter:"${targetProvider.toUpperCase()}*"}) to find the env name, then env_set it.`);
|
|
63
|
+
lines.push(` (b) Run providers_manage({action:"create", provider_id:"${targetProvider}", config:{apiKeyName:"<KEY_NAME>", models:[{id:"<model_id>"}]}}) referencing an apiKeyName that already exists in env.`);
|
|
64
|
+
lines.push(`Always run gateway({action:"env_list", filter:"${targetProvider.toUpperCase()}*"}) FIRST to check before asking the user.`);
|
|
65
|
+
}
|
|
66
|
+
return lines.join("\n");
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Best-effort hint at the canonical env key name for a provider, for use in
|
|
70
|
+
* error messages. Returns undefined when pi-ai doesn't have a canonical
|
|
71
|
+
* mapping (custom providers must use providers.entries).
|
|
72
|
+
*
|
|
73
|
+
* Note: this duplicates pi-ai's internal envMap (env-api-keys.js) for
|
|
74
|
+
* messaging only — not used for resolution. The actual check uses
|
|
75
|
+
* getEnvApiKey() which always wins. Acceptable to be slightly out-of-sync
|
|
76
|
+
* with pi-ai upgrades: hint quality only, never load-bearing.
|
|
77
|
+
*/
|
|
78
|
+
function canonicalEnvKeyHint(provider) {
|
|
79
|
+
const knownMap = {
|
|
80
|
+
openai: "OPENAI_API_KEY",
|
|
81
|
+
"azure-openai-responses": "AZURE_OPENAI_API_KEY",
|
|
82
|
+
google: "GEMINI_API_KEY",
|
|
83
|
+
groq: "GROQ_API_KEY",
|
|
84
|
+
cerebras: "CEREBRAS_API_KEY",
|
|
85
|
+
xai: "XAI_API_KEY",
|
|
86
|
+
openrouter: "OPENROUTER_API_KEY",
|
|
87
|
+
"vercel-ai-gateway": "AI_GATEWAY_API_KEY",
|
|
88
|
+
zai: "ZAI_API_KEY",
|
|
89
|
+
mistral: "MISTRAL_API_KEY",
|
|
90
|
+
minimax: "MINIMAX_API_KEY",
|
|
91
|
+
"minimax-cn": "MINIMAX_CN_API_KEY",
|
|
92
|
+
huggingface: "HF_TOKEN",
|
|
93
|
+
opencode: "OPENCODE_API_KEY",
|
|
94
|
+
"kimi-coding": "KIMI_API_KEY",
|
|
95
|
+
anthropic: "ANTHROPIC_API_KEY",
|
|
96
|
+
};
|
|
97
|
+
// eslint-disable-next-line security/detect-object-injection -- read of static const map indexed by validated provider string
|
|
98
|
+
return knownMap[provider];
|
|
99
|
+
}
|
|
@@ -31,6 +31,11 @@ export interface MessageHandlerDeps {
|
|
|
31
31
|
onGatewayAttachment?: (channelId: string, marker: string) => void;
|
|
32
32
|
/** Delivery queue for crash-safe persistence */
|
|
33
33
|
deliveryQueue?: import("@comis/core").DeliveryQueuePort;
|
|
34
|
+
/** Resolves daemon NormalizedMessage.id UUIDs to platform-native message
|
|
35
|
+
* ids for delete/edit/react handlers. Optional — when absent, message_id
|
|
36
|
+
* passes through unchanged (which fails on Telegram for inbound UUIDs but
|
|
37
|
+
* works for native ids returned by message.send). */
|
|
38
|
+
inboundMessageIdResolver?: import("../wiring/inbound-message-id-resolver.js").InboundMessageIdResolver;
|
|
34
39
|
}
|
|
35
40
|
/**
|
|
36
41
|
* Create message and platform-action RPC handlers.
|