mixdog 1.1.1 → 1.2.0
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/README.md +1 -0
- package/package.json +2 -2
- package/scripts/lib/run-node-tests.mjs +9 -0
- package/scripts/prune-desktop-runtime.mjs +3 -0
- package/scripts/release-paths.mjs +39 -2
- package/scripts/test-direct.mjs +4 -2
- package/src/defaults/shipped-history.json +6 -0
- package/src/defaults/skills/setup/references/actions.md +5 -2
- package/src/defaults/skills/visualize/SKILL.md +157 -0
- package/src/defaults/skills/visualize/references/craft.md +88 -0
- package/src/headless-command.mjs +56 -3
- package/src/headless-exec.mjs +17 -1
- package/src/headless-role.mjs +2 -2
- package/src/help.mjs +2 -0
- package/src/lib/rules-builder.cjs +0 -23
- package/src/rules/lead/LEAD.md +2 -2
- package/src/rules/shared/70-delivery.md +2 -2
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +1 -0
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +2 -0
- package/src/runtime/agent/orchestrator/config-presets.mjs +2 -0
- package/src/runtime/agent/orchestrator/config-providers-merge.mjs +17 -11
- package/src/runtime/agent/orchestrator/config-storage.mjs +1 -0
- package/src/runtime/agent/orchestrator/config.mjs +9 -1
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +47 -7
- package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +51 -8
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +25 -5
- package/src/runtime/agent/orchestrator/mcp/client.mjs +348 -122
- package/src/runtime/agent/orchestrator/mcp/reconnect-singleflight.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +15 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +13 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +12 -4
- package/src/runtime/agent/orchestrator/providers/effort-rejection.mjs +244 -0
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +8 -40
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-tokens.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +51 -12
- package/src/runtime/agent/orchestrator/providers/model-cache.mjs +37 -2
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +67 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +521 -0
- package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +251 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth-tokens.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +69 -102
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +6 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog-store.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/registry.mjs +15 -1
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +10 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +36 -3
- package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +12 -11
- package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +16 -1
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +11 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +11 -8
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/cache/prefetch-cache.mjs +9 -5
- package/src/runtime/agent/orchestrator/session/cache/read-cache.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +10 -3
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +18 -11
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +362 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +253 -0
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +12 -14
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/continuation.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/diagnostic.mjs +1 -7
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/refusal.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +17 -7
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +37 -16
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +90 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +22 -12
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +32 -3
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +1 -5
- package/src/runtime/agent/orchestrator/session/message-ids.mjs +123 -0
- package/src/runtime/agent/orchestrator/session/message-ids.test-support.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +29 -19
- package/src/runtime/agent/orchestrator/session/read-dedup.mjs +0 -1
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +10 -3
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +11 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +23 -4
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +20 -3
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +28 -8
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +140 -0
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +52 -2
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +32 -22
- package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +10 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-cache-policy.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +31 -12
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +32 -35
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +11 -12
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +9 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +80 -66
- package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +8 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-source-windows.mjs +5 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +16 -7
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +137 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +11 -10
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +21 -11
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +12 -1
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +56 -13
- package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +58 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/trusted-roots.mjs +25 -1
- package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +78 -5
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +0 -10
- package/src/runtime/attachments/store.mjs +38 -0
- package/src/runtime/channels/index.mjs +1 -5
- package/src/runtime/channels/lib/runtime-paths.mjs +8 -23
- package/src/runtime/channels/lib/tool-dispatch.mjs +1 -13
- package/src/runtime/channels/lib/worker-ipc.mjs +2 -2
- package/src/runtime/channels/lib/worker-main.mjs +4 -34
- package/src/runtime/shared/atomic-file.mjs +8 -2
- package/src/runtime/shared/best-effort-stderr.mjs +8 -0
- package/src/runtime/shared/code-graph-state.mjs +12 -0
- package/src/runtime/shared/defaults-separation.mjs +2 -0
- package/src/runtime/shared/git-runner-worker.mjs +3 -2
- package/src/runtime/shared/git-runner.mjs +4 -3
- package/src/runtime/shared/llm/default-context-window.mjs +6 -0
- package/src/runtime/shared/llm/model-catalog-projection.mjs +5 -4
- package/src/runtime/shared/llm/model-catalog.mjs +240 -118
- package/src/runtime/shared/llm/provider-catalog-cache.mjs +36 -28
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +156 -0
- package/src/runtime/shared/llm/provider-seed-rosters.mjs +130 -0
- package/src/runtime/shared/model-proxy-mode.d.mts +3 -0
- package/src/runtime/shared/model-proxy-mode.mjs +19 -0
- package/src/runtime/shared/provider-accounts.mjs +2 -2
- package/src/runtime/shared/provider-api-key.mjs +21 -1
- package/src/runtime/shared/schedule-model-ref.mjs +11 -2
- package/src/runtime/shared/semver.d.mts +1 -0
- package/src/runtime/shared/semver.mjs +57 -0
- package/src/runtime/shared/session-usage-totals.mjs +19 -0
- package/src/runtime/shared/sharp-electron-linux.mjs +25 -0
- package/src/runtime/shared/singleton-owner.mjs +36 -6
- package/src/runtime/shared/statusline/statusline-segments.mjs +68 -14
- package/src/runtime/shared/tool-surface.mjs +9 -2
- package/src/runtime/shared/tool-work-units.mjs +14 -0
- package/src/runtime/shared/transcript-metadata.mjs +17 -1
- package/src/runtime/shared/turn-changes.mjs +791 -0
- package/src/runtime/shared/turn-snapshot-store.mjs +346 -12
- package/src/runtime/shared/turn-snapshot.mjs +690 -81
- package/src/runtime/shared/turn-worktree-snapshot.mjs +161 -11
- package/src/runtime/shared/update-checker.mjs +2 -31
- package/src/runtime/shared/worktrees/cache-cleanups.mjs +52 -0
- package/src/runtime/shared/worktrees/contract.mjs +551 -0
- package/src/runtime/shared/worktrees/disk.mjs +57 -0
- package/src/runtime/shared/worktrees/git.mjs +247 -0
- package/src/runtime/shared/worktrees/include.mjs +480 -0
- package/src/runtime/shared/worktrees/lock.mjs +46 -0
- package/src/runtime/shared/worktrees/maintenance.mjs +96 -0
- package/src/runtime/shared/worktrees/manager.mjs +1215 -0
- package/src/runtime/shared/worktrees/merge.mjs +182 -0
- package/src/runtime/shared/worktrees/owner.mjs +46 -0
- package/src/runtime/shared/worktrees/paths.mjs +62 -0
- package/src/runtime/shared/worktrees/registry.mjs +110 -0
- package/src/runtime/shared/worktrees/settings.mjs +84 -0
- package/src/runtime/shared/worktrees/slug.mjs +62 -0
- package/src/runtime/shared/worktrees/test-support.mjs +96 -0
- package/src/runtime/visualize-bridge/client.mjs +181 -0
- package/src/runtime/visualize-bridge/tool-defs.mjs +97 -0
- package/src/session-runtime/boot/apis.mjs +35 -0
- package/src/session-runtime/boot/begin.mjs +0 -2
- package/src/session-runtime/boot/config.mjs +2 -0
- package/src/session-runtime/boot/facade.mjs +20 -0
- package/src/session-runtime/boot/infrastructure.mjs +1 -0
- package/src/session-runtime/boot/session.mjs +1 -0
- package/src/session-runtime/boot/tools.mjs +9 -4
- package/src/session-runtime/config-lifecycle.mjs +10 -1
- package/src/session-runtime/cwd-plugins/cwd-apply.mjs +11 -1
- package/src/session-runtime/global-extensions.mjs +2 -2
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +27 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +32 -1
- package/src/session-runtime/internal-tool-executor.mjs +9 -1
- package/src/session-runtime/lifecycle/session-catalog.mjs +8 -1
- package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +5 -0
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +21 -3
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +16 -0
- package/src/session-runtime/mcp-glue/connect.mjs +11 -6
- package/src/session-runtime/mcp-glue/server-catalog.mjs +7 -3
- package/src/session-runtime/mcp-glue/server-input.mjs +29 -0
- package/src/session-runtime/model-route/route-persist.mjs +3 -0
- package/src/session-runtime/model-route/set-route.mjs +15 -2
- package/src/session-runtime/notification-bus.mjs +9 -1
- package/src/session-runtime/provider-models/row-hydration.mjs +2 -0
- package/src/session-runtime/resource-extension-sync.mjs +30 -7
- package/src/session-runtime/resource-mcp-api.mjs +27 -10
- package/src/session-runtime/route-resolution.mjs +10 -1
- package/src/session-runtime/route-state.mjs +16 -2
- package/src/session-runtime/runtime-bootstrap.mjs +0 -4
- package/src/session-runtime/runtime-core.mjs +5 -0
- package/src/session-runtime/runtime-facade.mjs +8 -0
- package/src/session-runtime/runtime-paths.mjs +0 -1
- package/src/session-runtime/runtime-review-api.mjs +9 -0
- package/src/session-runtime/services/agent-tool/helpers.mjs +5 -0
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +3 -0
- package/src/session-runtime/services/agent-tool/job-views/job-lookup.mjs +1 -0
- package/src/session-runtime/services/agent-tool/job-views/spawn-meta.mjs +1 -0
- package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +15 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +1 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +10 -2
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -7
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +2 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -0
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +1 -0
- package/src/session-runtime/services/agent-tool.mjs +1 -0
- package/src/session-runtime/services/channel-worker.mjs +1 -1
- package/src/session-runtime/services/daemon-candidate.mjs +3 -2
- package/src/session-runtime/services/daemon-crash-capture/spawn-capture.mjs +55 -0
- package/src/session-runtime/session-create/session-options.mjs +10 -1
- package/src/session-runtime/session-turn-api.mjs +1 -0
- package/src/session-runtime/settings-api.mjs +4 -2
- package/src/session-runtime/settings-builtin-tools-api.mjs +9 -2
- package/src/session-runtime/settings-profile-api.mjs +27 -2
- package/src/session-runtime/settings-worktree-api.mjs +17 -0
- package/src/session-runtime/setup-tool/executor.mjs +11 -4
- package/src/session-runtime/setup-tool/settings-contract.mjs +3 -1
- package/src/session-runtime/setup-tool/tool-defs.mjs +31 -3
- package/src/session-runtime/starter-guide-state.mjs +62 -0
- package/src/session-runtime/turn/agent-ops.mjs +12 -1
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +13 -3
- package/src/session-runtime/turn/turn-run/snapshot-tracker.mjs +20 -15
- package/src/session-runtime/turn/turn-run/turn-open.mjs +4 -5
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +29 -1
- package/src/session-runtime/turn/turn-run/turn-settle.mjs +6 -1
- package/src/session-runtime/turn/turn-run.mjs +6 -7
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -3
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -2
- package/src/session-runtime/workspace/admission-gate.mjs +197 -0
- package/src/session-runtime/workspace/project-branches.mjs +136 -0
- package/src/session-runtime/workspace/transition-steps.mjs +364 -0
- package/src/session-runtime/workspace/transitions.mjs +651 -0
- package/src/session-runtime/workspace/workspace-state.mjs +112 -0
- package/src/standalone/channel-binding.mjs +1 -2
- package/src/standalone/channel-transport/call-dispatch.mjs +4 -10
- package/src/standalone/channel-transport/http-routes.mjs +17 -0
- package/src/standalone/channel-transport.mjs +13 -1
- package/src/standalone/daemon-channels-loader.mjs +2 -3
- package/src/standalone/daemon-desktop-runtime.mjs +1 -0
- package/src/standalone/daemon-owner.mjs +372 -0
- package/src/standalone/daemon-stored-session-views.mjs +4 -1
- package/src/standalone/daemon.mjs +139 -5
- package/src/standalone/desktop-service-registry.mjs +20 -0
- package/src/standalone/local-session-runtime.mjs +13 -78
- package/src/standalone/session-client/attachment-calls.mjs +3 -1
- package/src/standalone/session-client/daemon-unavailable.mjs +62 -0
- package/src/standalone/session-client/lease-heartbeat.mjs +47 -0
- package/src/standalone/session-client.mjs +104 -13
- package/src/standalone/session-protocol.mjs +17 -0
- package/src/standalone/session-proxy.mjs +3 -0
- package/src/standalone/session-service/agent-tree/agent-child.mjs +4 -0
- package/src/standalone/session-service/agent-tree/agent-rehydrate.mjs +1 -0
- package/src/standalone/session-service/entries/lifecycle.mjs +6 -0
- package/src/standalone/session-service/projection/revisions.mjs +2 -0
- package/src/standalone/session-service/projection/transcript-window.mjs +149 -19
- package/src/standalone/session-service/projection/workspace.mjs +14 -0
- package/src/standalone/session-service/session-calls/session-action.mjs +11 -3
- package/src/standalone/session-transport/call-route.mjs +13 -0
- package/src/standalone/session-transport/client-registry/client-grace.mjs +45 -3
- package/src/standalone/session-transport/client-registry/registration-replays.mjs +1 -0
- package/src/standalone/session-transport/client-registry.mjs +20 -3
- package/src/standalone/session-transport/routes.mjs +79 -2
- package/src/standalone/session-transport/stack.mjs +2 -0
- package/src/standalone/session-transport.mjs +24 -1
- package/src/tui/app/message-selector.mjs +2 -1
- package/src/tui/app/model-options.mjs +35 -5
- package/src/tui/app/model-picker/provider-models-list.mjs +2 -2
- package/src/tui/app/model-picker.mjs +4 -2
- package/src/tui/dist/index.mjs +332 -36
- package/src/tui/index.jsx +10 -2
- package/src/tui/session/compaction-view.mjs +147 -0
- package/src/tui/session/context-state.mjs +6 -0
- package/src/tui/session/initial-state.mjs +3 -0
- package/src/tui/session/quota-resume.mjs +2 -1
- package/src/tui/session/session-api/commands.mjs +10 -2
- package/src/tui/session/session-api/controls.mjs +4 -0
- package/src/tui/session/session-api/extensions.mjs +12 -8
- package/src/tui/session/session-api/intake/rewind.mjs +2 -1
- package/src/tui/session/session-api/integrations.mjs +18 -0
- package/src/tui/session/session-api/lifecycle/dispose.mjs +6 -1
- package/src/tui/session/session-api/lifecycle/inheritance.mjs +2 -0
- package/src/tui/session/session-api/lifecycle/resume.mjs +3 -0
- package/src/tui/session/session-api/routes.mjs +10 -1
- package/src/tui/session/session-api/settings.mjs +2 -0
- package/src/tui/session/session-api/shared.mjs +10 -6
- package/src/tui/session/session-api/worktree.mjs +60 -0
- package/src/tui/session/session-api.mjs +2 -0
- package/src/tui/session/session-flow/auto-clear.mjs +31 -12
- package/src/tui/session/session-flow/drain.mjs +15 -1
- package/src/tui/session/session-flow/session-reset.mjs +4 -3
- package/src/tui/session/session-flow.mjs +2 -0
- package/src/tui/session/transcript-intake.mjs +14 -5
- package/src/tui/session/turn-stream.mjs +32 -4
- package/src/tui/session/turn-tool-cards.mjs +10 -2
- package/src/tui/session/turn.mjs +39 -10
- package/src/runtime/channels/tool-defs.mjs +0 -17
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
* - buildAgentRoleContent — BP3: agent role/system rules
|
|
10
10
|
* - buildAgentRetrievalInjectionContent — BP3: narrow read-only retrieval role
|
|
11
11
|
* - buildLeadMetaContent — BP2: Lead profile/settings context
|
|
12
|
-
* - buildInjectionContent — legacy joined Lead session content
|
|
13
12
|
*
|
|
14
13
|
* 4-BP cache layout (composeSystemPrompt):
|
|
15
14
|
* BP1 = shared tool policy
|
|
@@ -400,27 +399,6 @@ function buildLeadLanguageContent({ DATA_DIR }) {
|
|
|
400
399
|
return buildLanguageSection(DATA_DIR);
|
|
401
400
|
}
|
|
402
401
|
|
|
403
|
-
/**
|
|
404
|
-
* Build the Lead injection content.
|
|
405
|
-
*/
|
|
406
|
-
function buildInjectionContent({ PLUGIN_ROOT, DATA_DIR }) {
|
|
407
|
-
const parts = [];
|
|
408
|
-
|
|
409
|
-
const tool = buildSharedToolContent({ PLUGIN_ROOT });
|
|
410
|
-
if (tool) parts.push(tool);
|
|
411
|
-
|
|
412
|
-
const meta = buildLeadMetaContent({ PLUGIN_ROOT, DATA_DIR });
|
|
413
|
-
if (meta) parts.push(meta);
|
|
414
|
-
|
|
415
|
-
const role = buildLeadRoleContent({ PLUGIN_ROOT, DATA_DIR });
|
|
416
|
-
if (role) parts.push(role);
|
|
417
|
-
|
|
418
|
-
const language = buildLeadLanguageContent({ DATA_DIR });
|
|
419
|
-
if (language) parts.push(language);
|
|
420
|
-
|
|
421
|
-
return parts.join('\n\n');
|
|
422
|
-
}
|
|
423
|
-
|
|
424
402
|
function buildAgentRoleContent({ PLUGIN_ROOT, profile = 'full' }) {
|
|
425
403
|
const AGENT_DIR = path.join(PLUGIN_ROOT, 'rules', 'agent');
|
|
426
404
|
if (String(profile || 'full') === 'retrieval') {
|
|
@@ -455,7 +433,6 @@ module.exports = {
|
|
|
455
433
|
buildLeadMetaContent,
|
|
456
434
|
buildLeadLanguageContent,
|
|
457
435
|
buildAgentRoleContent,
|
|
458
|
-
buildInjectionContent,
|
|
459
436
|
buildAgentRetrievalInjectionContent,
|
|
460
437
|
omitToolRoutes,
|
|
461
438
|
};
|
package/src/rules/lead/LEAD.md
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
never per-call narration or plan repeats.
|
|
11
11
|
- Mid-task: a replacement supersedes, an addition folds in, a status question
|
|
12
12
|
gets a brief answer while work continues.
|
|
13
|
-
- Context is managed automatically: never
|
|
14
|
-
|
|
13
|
+
- Context is managed automatically: never stop or propose stopping because of
|
|
14
|
+
context size.
|
|
15
15
|
- Be a grounded, candid, and attentive collaborator: natural and respectful,
|
|
16
16
|
without flattery, forced humor, mimicry, or stereotyping.
|
|
17
17
|
<!-- tools: agent -->
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
`src/app.ts:42`); files outside the Project always by absolute path; never a
|
|
9
9
|
bare name, a path relative to another folder, or a `file://` URI.
|
|
10
10
|
- Deliver requested visual artifacts (SVG, diagrams, HTML pages) as saved files
|
|
11
|
-
and give their path
|
|
12
|
-
|
|
11
|
+
and give their path, which opens them in the browser panel; never open them
|
|
12
|
+
in the system browser or paste their source unless the user asks.
|
|
13
13
|
|
|
14
14
|
<!-- tools: git -->
|
|
15
15
|
- A commit request includes selecting and staging its changes; a stage-only
|
|
@@ -35,6 +35,7 @@ function maintenanceRouteToPreset(routeOrName, agent) {
|
|
|
35
35
|
const effort = String(routeOrName.effort || '').trim();
|
|
36
36
|
if (effort) out.effort = effort;
|
|
37
37
|
if (routeOrName.fast === true) out.fast = true;
|
|
38
|
+
if (routeOrName.autoEffort === false) out.autoEffort = false;
|
|
38
39
|
if (routeOrName.modelParameters && typeof routeOrName.modelParameters === 'object') {
|
|
39
40
|
out.modelParameters = { ...routeOrName.modelParameters };
|
|
40
41
|
}
|
|
@@ -77,6 +77,7 @@ export function prepareAgentSession({
|
|
|
77
77
|
sessionId,
|
|
78
78
|
mcpScopeId,
|
|
79
79
|
contextPercent,
|
|
80
|
+
contextTokens,
|
|
80
81
|
selectedContextWindow,
|
|
81
82
|
}) {
|
|
82
83
|
const effectivePermission = resolveAgentSessionPermission(agent, permission);
|
|
@@ -115,6 +116,7 @@ export function prepareAgentSession({
|
|
|
115
116
|
mcpScopeId: mcpScopeId || null,
|
|
116
117
|
};
|
|
117
118
|
if (contextPercent) sessionOpts.contextPercent = contextPercent;
|
|
119
|
+
if (contextTokens) sessionOpts.contextTokens = contextTokens;
|
|
118
120
|
if (selectedContextWindow) sessionOpts.selectedContextWindow = selectedContextWindow;
|
|
119
121
|
if (agentTag) sessionOpts.agentTag = agentTag;
|
|
120
122
|
if (effectivePermission) sessionOpts.permission = effectivePermission;
|
|
@@ -141,6 +141,8 @@ export function normalizePreset(preset) {
|
|
|
141
141
|
const out = { id, name, type: 'agent', provider, model };
|
|
142
142
|
if (preset.effort) out.effort = String(preset.effort).trim();
|
|
143
143
|
if (preset.fast === true && FAST_CAPABLE_PRESET_PROVIDERS.has(provider)) out.fast = true;
|
|
144
|
+
// Auto effort is on unless the preset opts out; only the off state is kept.
|
|
145
|
+
if (preset.autoEffort === false) out.autoEffort = false;
|
|
144
146
|
out.tools = ['full', 'readonly', 'mcp'].includes(preset.tools) ? preset.tools : 'full';
|
|
145
147
|
return out;
|
|
146
148
|
}
|
|
@@ -6,9 +6,21 @@
|
|
|
6
6
|
* is dropped.
|
|
7
7
|
*/
|
|
8
8
|
import { AGENT_PROVIDER_ENV, getAgentApiKey } from '../../shared/config.mjs';
|
|
9
|
+
import { hasAgentApiKey } from '../../shared/provider-api-key.mjs';
|
|
9
10
|
import { OPENAI_COMPAT_PRESETS } from './providers/openai-compat-presets.mjs';
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
/** `presenceOnly`: a stored key only marks its provider enabled; its value is
|
|
13
|
+
* neither read nor attached. */
|
|
14
|
+
export function mergeStoredProviders({ raw, defaults, includeSecrets, presenceOnly = false }) {
|
|
15
|
+
const storedKey = (name) => {
|
|
16
|
+
if (!presenceOnly) return getAgentApiKey(name);
|
|
17
|
+
return hasAgentApiKey(name) ? true : null;
|
|
18
|
+
};
|
|
19
|
+
const withKey = (entry, name, key) => ({
|
|
20
|
+
...(entry || {}),
|
|
21
|
+
...(presenceOnly ? {} : { apiKey: key }),
|
|
22
|
+
enabled: raw.providers?.[name]?.enabled !== false,
|
|
23
|
+
});
|
|
12
24
|
// Deep-merge provider subkeys: unknown per-provider values are
|
|
13
25
|
// preserved through save/load so future fields round-trip
|
|
14
26
|
// without schema updates here.
|
|
@@ -39,14 +51,8 @@ export function mergeStoredProviders({ raw, defaults, includeSecrets }) {
|
|
|
39
51
|
// stored key still ships 'no-key' → 401.
|
|
40
52
|
if (includeSecrets) {
|
|
41
53
|
for (const name of new Set([...Object.keys(AGENT_PROVIDER_ENV), ...Object.keys(OPENAI_COMPAT_PRESETS)])) {
|
|
42
|
-
const kc =
|
|
43
|
-
if (kc)
|
|
44
|
-
mergedProviders[name] = {
|
|
45
|
-
...(mergedProviders[name] || {}),
|
|
46
|
-
apiKey: kc,
|
|
47
|
-
enabled: raw.providers?.[name]?.enabled !== false,
|
|
48
|
-
};
|
|
49
|
-
}
|
|
54
|
+
const kc = storedKey(name);
|
|
55
|
+
if (kc) mergedProviders[name] = withKey(mergedProviders[name], name, kc);
|
|
50
56
|
}
|
|
51
57
|
}
|
|
52
58
|
// Custom providers: the keychain account is the generated custom-<uuid> id.
|
|
@@ -61,8 +67,8 @@ export function mergeStoredProviders({ raw, defaults, includeSecrets }) {
|
|
|
61
67
|
if (includeSecrets) {
|
|
62
68
|
for (const [name, val] of Object.entries(mergedProviders)) {
|
|
63
69
|
if (val?.type !== 'custom' || !name.startsWith('custom-') || val.auth === 'none') continue;
|
|
64
|
-
const kc =
|
|
65
|
-
if (kc) mergedProviders[name] =
|
|
70
|
+
const kc = storedKey(name);
|
|
71
|
+
if (kc) mergedProviders[name] = withKey(val, name, kc);
|
|
66
72
|
}
|
|
67
73
|
}
|
|
68
74
|
// Cursor account access is OAuth-only. The dashboard's "API"
|
|
@@ -103,6 +103,7 @@ export function normalizeMaintenanceRoutes(rawMaint) {
|
|
|
103
103
|
const effort = String(value.effort || '').trim();
|
|
104
104
|
if (effort) route.effort = effort;
|
|
105
105
|
if (value.fast === true) route.fast = true;
|
|
106
|
+
if (value.autoEffort === false) route.autoEffort = false;
|
|
106
107
|
out[slot] = route;
|
|
107
108
|
}
|
|
108
109
|
return out;
|
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
} from './config-storage.mjs';
|
|
45
45
|
import { oauthCredentialProbeState, isOAuthProviderAvailable } from './providers/oauth-credential-probes.mjs';
|
|
46
46
|
import { normalizeDeveloperConfig } from '../../shared/developer-options.mjs';
|
|
47
|
+
import { normalizeWorktreeSettings } from '../../shared/worktrees/settings.mjs';
|
|
47
48
|
|
|
48
49
|
export const {
|
|
49
50
|
PROFILE_LANGUAGES,
|
|
@@ -204,6 +205,10 @@ function storedInstructionFiles(agent) {
|
|
|
204
205
|
|
|
205
206
|
export function loadConfig(options = {}) {
|
|
206
207
|
const includeSecrets = options.secrets !== false;
|
|
208
|
+
// `secrets: 'presence'`: credentials are detected (env, OAuth files, which
|
|
209
|
+
// keychain entries exist) but no keychain value is read or attached — the
|
|
210
|
+
// availability view the model proxy answers a server with.
|
|
211
|
+
const presenceOnly = options.secrets === 'presence';
|
|
207
212
|
try {
|
|
208
213
|
ensureDefaultsSeparated({ stripRouteDefaults: separateStoredAgent });
|
|
209
214
|
} catch (err) {
|
|
@@ -219,7 +224,7 @@ export function loadConfig(options = {}) {
|
|
|
219
224
|
const storageNeedsMigration = agentConfigStorageNeedsMigration(raw);
|
|
220
225
|
raw = canonicalizeAgentStorage(raw);
|
|
221
226
|
const defaults = buildDefaultConfig({ detectCredentials: includeSecrets });
|
|
222
|
-
const mergedProviders = mergeStoredProviders({ raw, defaults, includeSecrets });
|
|
227
|
+
const mergedProviders = mergeStoredProviders({ raw, defaults, includeSecrets, presenceOnly });
|
|
223
228
|
// Drop unknown maintenance keys (e.g. truly legacy slot names from
|
|
224
229
|
// pre-removal installs). Every valid fallback slot lives in
|
|
225
230
|
// DEFAULT_MAINTENANCE, so the allow-list below is the single
|
|
@@ -274,6 +279,7 @@ export function loadConfig(options = {}) {
|
|
|
274
279
|
shell: raw.shell && typeof raw.shell === 'object' ? raw.shell : {},
|
|
275
280
|
update: raw.update && typeof raw.update === 'object' ? { ...raw.update } : {},
|
|
276
281
|
recap: recapConfig,
|
|
282
|
+
worktree: normalizeWorktreeSettings(raw.worktree),
|
|
277
283
|
developer: normalizeDeveloperConfig(raw.developer),
|
|
278
284
|
modules: canonicalizeModulesStorage(raw.modules) || {},
|
|
279
285
|
...(raw.builtins && typeof raw.builtins === 'object'
|
|
@@ -316,6 +322,7 @@ export function loadConfig(options = {}) {
|
|
|
316
322
|
shell: {},
|
|
317
323
|
update: {},
|
|
318
324
|
recap: { enabled: true },
|
|
325
|
+
worktree: normalizeWorktreeSettings(null),
|
|
319
326
|
developer: {},
|
|
320
327
|
modules: {},
|
|
321
328
|
// No stored section at all is a brand-new profile: its built-ins start
|
|
@@ -421,6 +428,7 @@ function buildAgentSaveBuilder(config) {
|
|
|
421
428
|
shell,
|
|
422
429
|
update: config.update || {},
|
|
423
430
|
recap: config.recap || {},
|
|
431
|
+
...(config.worktree ? { worktree: config.worktree } : {}),
|
|
424
432
|
modules,
|
|
425
433
|
builtins,
|
|
426
434
|
};
|
|
@@ -15,8 +15,16 @@ export const AUTO_DETECT_PORTS = {
|
|
|
15
15
|
'mixdog-memory': { discovery: 'memory', endpoint: '/mcp' },
|
|
16
16
|
};
|
|
17
17
|
const DEFAULT_MCP_CALL_TIMEOUT_MS = 120000;
|
|
18
|
-
// Per-server STARTUP handshake budget (connect + listTools):
|
|
19
|
-
|
|
18
|
+
// Per-server STARTUP handshake budget (connect + paginated listTools): 30s.
|
|
19
|
+
// Cold npx/uvx wrappers routinely need well over 10s to install and boot.
|
|
20
|
+
const DEFAULT_MCP_STARTUP_TIMEOUT_MS = 30000;
|
|
21
|
+
// Hard ceiling for a request that keeps reporting progress (each progress
|
|
22
|
+
// notification resets the per-call timeout, this caps the total): 30min.
|
|
23
|
+
const DEFAULT_MCP_MAX_TOTAL_TIMEOUT_MS = 1_800_000;
|
|
24
|
+
// Largest delay setTimeout honours; anything larger fires after 1ms. Used as
|
|
25
|
+
// the SDK request timeout when our own call timeout is disabled, so the SDK's
|
|
26
|
+
// built-in 60s default never applies.
|
|
27
|
+
export const MCP_MAX_TIMER_MS = 2_147_483_647;
|
|
20
28
|
|
|
21
29
|
function isLoopbackMcpHost(hostname) {
|
|
22
30
|
const host = String(hostname || '')
|
|
@@ -204,8 +212,9 @@ export function resolveMcpTransportKind(cfg) {
|
|
|
204
212
|
// (e.g. a busy editor) must not stall a tool call indefinitely. Genuinely
|
|
205
213
|
// long-running tools can raise/disable it via MIXDOG_MCP_CALL_TIMEOUT_MS or a
|
|
206
214
|
// per-server timeoutMs/callTimeoutMs config value (0/off/none/false disables).
|
|
207
|
-
// On expiry
|
|
208
|
-
//
|
|
215
|
+
// On expiry only the timed-out request is cancelled (notifications/cancelled);
|
|
216
|
+
// the server and its other in-flight calls stay up, and the timed-out call is
|
|
217
|
+
// never retried automatically (avoids side-effect dupes).
|
|
209
218
|
export function resolveMcpCallTimeoutMs(cfg = {}, env = process.env) {
|
|
210
219
|
const raw =
|
|
211
220
|
cfg?.timeoutMs ?? cfg?.timeout_ms ?? cfg?.callTimeoutMs ?? cfg?.call_timeout_ms ?? env?.MIXDOG_MCP_CALL_TIMEOUT_MS;
|
|
@@ -213,11 +222,42 @@ export function resolveMcpCallTimeoutMs(cfg = {}, env = process.env) {
|
|
|
213
222
|
if (typeof raw === 'string' && /^(0|off|none|false)$/i.test(raw.trim())) return 0;
|
|
214
223
|
const parsed = Number(raw);
|
|
215
224
|
if (!Number.isFinite(parsed) || parsed <= 0) return DEFAULT_MCP_CALL_TIMEOUT_MS;
|
|
216
|
-
return Math.round(parsed);
|
|
225
|
+
return Math.min(Math.round(parsed), MCP_MAX_TIMER_MS);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Total cap for a call whose server keeps reporting progress. Default 30min.
|
|
229
|
+
// Per-server override: maxTotalTimeoutMs / max_total_timeout_ms. Global env:
|
|
230
|
+
// MIXDOG_MCP_MAX_TOTAL_TIMEOUT_MS. 0/off/none/false removes the cap.
|
|
231
|
+
export function resolveMcpMaxTotalTimeoutMs(cfg = {}, env = process.env) {
|
|
232
|
+
const raw = cfg?.maxTotalTimeoutMs ?? cfg?.max_total_timeout_ms ?? env?.MIXDOG_MCP_MAX_TOTAL_TIMEOUT_MS;
|
|
233
|
+
if (raw == null || raw === '' || raw === false) return DEFAULT_MCP_MAX_TOTAL_TIMEOUT_MS;
|
|
234
|
+
if (raw === 0 || (typeof raw === 'string' && /^(0|off|none|false)$/i.test(raw.trim()))) return 0;
|
|
235
|
+
const parsed = Number(raw);
|
|
236
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return DEFAULT_MCP_MAX_TOTAL_TIMEOUT_MS;
|
|
237
|
+
return Math.min(Math.round(parsed), MCP_MAX_TIMER_MS);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* The effective limits of one MCP request:
|
|
242
|
+
* - callTimeoutMs: our per-call timeout (0 = disabled), reset on progress;
|
|
243
|
+
* - sdkTimeoutMs: what the SDK gets as `timeout` — the call timeout, or the
|
|
244
|
+
* largest timer when disabled so the SDK's 60s default never applies;
|
|
245
|
+
* - maxTotalTimeoutMs: the progress-reset ceiling (never below the call
|
|
246
|
+
* timeout), or undefined when the call is unbounded or the cap is off.
|
|
247
|
+
*/
|
|
248
|
+
export function resolveMcpRequestTimeouts(cfg = {}, env = process.env) {
|
|
249
|
+
const callTimeoutMs = resolveMcpCallTimeoutMs(cfg, env);
|
|
250
|
+
if (!(callTimeoutMs > 0)) return { callTimeoutMs: 0, sdkTimeoutMs: MCP_MAX_TIMER_MS, maxTotalTimeoutMs: undefined };
|
|
251
|
+
const cap = resolveMcpMaxTotalTimeoutMs(cfg, env);
|
|
252
|
+
return {
|
|
253
|
+
callTimeoutMs,
|
|
254
|
+
sdkTimeoutMs: callTimeoutMs,
|
|
255
|
+
maxTotalTimeoutMs: cap > 0 ? Math.max(cap, callTimeoutMs) : undefined,
|
|
256
|
+
};
|
|
217
257
|
}
|
|
218
258
|
|
|
219
259
|
// MCP per-server STARTUP timeout: bounds the connect + listTools handshake so a
|
|
220
|
-
// slow or hung server can't stall boot or the first turn. Default
|
|
260
|
+
// slow or hung server can't stall boot or the first turn. Default 30s.
|
|
221
261
|
// Per-server override: startupTimeoutMs / startupTimeoutSec. Global
|
|
222
262
|
// env: MIXDOG_MCP_STARTUP_TIMEOUT_MS. A value of 0/off/none/false disables it.
|
|
223
263
|
export function resolveMcpStartupTimeoutMs(cfg = {}, env = process.env) {
|
|
@@ -235,5 +275,5 @@ export function resolveMcpStartupTimeoutMs(cfg = {}, env = process.env) {
|
|
|
235
275
|
if (raw === 0 || (typeof raw === 'string' && /^(0|off|none|false)$/i.test(raw.trim()))) return 0;
|
|
236
276
|
const parsed = Number(raw) * scale;
|
|
237
277
|
if (!Number.isFinite(parsed) || parsed <= 0) return DEFAULT_MCP_STARTUP_TIMEOUT_MS;
|
|
238
|
-
return Math.round(parsed);
|
|
278
|
+
return Math.min(Math.round(parsed), MCP_MAX_TIMER_MS);
|
|
239
279
|
}
|
|
@@ -4,14 +4,40 @@
|
|
|
4
4
|
* and a discovery advert that refused the connection is distrusted.
|
|
5
5
|
*/
|
|
6
6
|
import { markServiceUnreachable, isConnRefuseError } from '../../../shared/service-discovery.mjs';
|
|
7
|
-
import { resolveMcpStartupTimeoutMs } from './client-config.mjs';
|
|
7
|
+
import { MCP_MAX_TIMER_MS, resolveMcpStartupTimeoutMs } from './client-config.mjs';
|
|
8
|
+
import { appendMcpStderrTail } from './client-transport.mjs';
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
// tools/list pagination bounds: a server that never stops handing out cursors
|
|
11
|
+
// (or repeats one) cannot loop the client forever.
|
|
12
|
+
const MAX_MCP_TOOL_PAGES = 100;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Every tool of a server: follows `nextCursor` until it is exhausted, repeats,
|
|
16
|
+
* or MAX_MCP_TOOL_PAGES is reached. A page with an invalid shape is returned
|
|
17
|
+
* as-is so the caller's shape validation reports it.
|
|
18
|
+
*/
|
|
19
|
+
export async function listAllMcpTools(client, requestOptions = undefined) {
|
|
20
|
+
const tools = [];
|
|
21
|
+
const seen = new Set();
|
|
22
|
+
let cursor = null;
|
|
23
|
+
for (let page = 0; page < MAX_MCP_TOOL_PAGES; page += 1) {
|
|
24
|
+
const result = await client.listTools(cursor ? { cursor } : undefined, requestOptions);
|
|
25
|
+
if (!result || !Array.isArray(result.tools)) return result;
|
|
26
|
+
tools.push(...result.tools);
|
|
27
|
+
const next = typeof result.nextCursor === 'string' && result.nextCursor ? result.nextCursor : null;
|
|
28
|
+
if (!next || seen.has(next)) break;
|
|
29
|
+
seen.add(next);
|
|
30
|
+
cursor = next;
|
|
31
|
+
}
|
|
32
|
+
return { tools };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function performHandshake(client, transport, requestOptions) {
|
|
36
|
+
await client.connect(transport, requestOptions);
|
|
11
37
|
const instructionsRaw = typeof client.getInstructions === 'function' ? client.getInstructions() : undefined;
|
|
12
38
|
const instructions = typeof instructionsRaw === 'string' ? instructionsRaw.trim() : '';
|
|
13
39
|
const capabilities = client.getServerCapabilities?.() || {};
|
|
14
|
-
const toolsResult = capabilities.tools ? await client
|
|
40
|
+
const toolsResult = capabilities.tools ? await listAllMcpTools(client, requestOptions) : { tools: [] };
|
|
15
41
|
return { instructions, toolsResult, capabilities };
|
|
16
42
|
}
|
|
17
43
|
|
|
@@ -28,12 +54,24 @@ function startupTimeoutError(name, startupTimeoutMs) {
|
|
|
28
54
|
* boot or the first turn. On expiry the pending transport/child is torn down
|
|
29
55
|
* (nothing leaks) and this server fails like any other connect failure — the
|
|
30
56
|
* parallel Promise.allSettled means other servers are unaffected.
|
|
31
|
-
*
|
|
57
|
+
* The SDK's per-request timeout follows the same budget (its own 60s default
|
|
58
|
+
* would otherwise cut a longer or disabled budget short). Failures carry the
|
|
59
|
+
* server's stderr tail. Returns { instructions, toolsResult, capabilities }.
|
|
32
60
|
*/
|
|
33
|
-
export async function runBoundedHandshake({
|
|
61
|
+
export async function runBoundedHandshake({
|
|
62
|
+
name,
|
|
63
|
+
cfg,
|
|
64
|
+
client,
|
|
65
|
+
transport,
|
|
66
|
+
autoDetectAdvert,
|
|
67
|
+
closeServer,
|
|
68
|
+
stderrTail = () => '',
|
|
69
|
+
}) {
|
|
34
70
|
const startupTimeoutMs = resolveMcpStartupTimeoutMs(cfg);
|
|
35
71
|
const guard = { timer: null, timedOut: false };
|
|
36
|
-
const handshake = performHandshake(client, transport
|
|
72
|
+
const handshake = performHandshake(client, transport, {
|
|
73
|
+
timeout: startupTimeoutMs > 0 ? startupTimeoutMs : MCP_MAX_TIMER_MS,
|
|
74
|
+
});
|
|
37
75
|
try {
|
|
38
76
|
if (startupTimeoutMs <= 0) return await handshake;
|
|
39
77
|
const deadline = new Promise((_, rej) => {
|
|
@@ -63,7 +101,12 @@ export async function runBoundedHandshake({ name, cfg, client, transport, autoDe
|
|
|
63
101
|
// Never let the late handshake settle into an unhandled rejection.
|
|
64
102
|
handshake.catch(() => {});
|
|
65
103
|
}
|
|
66
|
-
|
|
104
|
+
const tail = stderrTail();
|
|
105
|
+
if (tail && err instanceof Error) {
|
|
106
|
+
err.message = appendMcpStderrTail(err.message, tail);
|
|
107
|
+
throw err;
|
|
108
|
+
}
|
|
109
|
+
throw tail ? new Error(appendMcpStderrTail(String(err), tail)) : err;
|
|
67
110
|
} finally {
|
|
68
111
|
if (guard.timer) clearTimeout(guard.timer);
|
|
69
112
|
}
|
|
@@ -32,19 +32,35 @@ function resolveAutoDetectUrl(name, cfg) {
|
|
|
32
32
|
return { url: `http://127.0.0.1:${port}${spec.endpoint}`, advert: { service: spec.discovery, port } };
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
// Bounded tail of a stdio server's stderr, kept for failure messages (a server
|
|
36
|
+
// that dies at startup or mid-session usually says why on stderr).
|
|
37
|
+
const MCP_STDERR_TAIL_CHARS = 4096;
|
|
38
|
+
const noStderrTail = () => '';
|
|
39
|
+
|
|
40
|
+
/** Append a server's stderr tail to a failure message (unchanged when empty). */
|
|
41
|
+
export function appendMcpStderrTail(message, tail) {
|
|
42
|
+
const text = String(tail || '').trim();
|
|
43
|
+
return text ? `${message}\n--- server stderr (tail) ---\n${text}` : String(message);
|
|
44
|
+
}
|
|
45
|
+
|
|
35
46
|
function requestInitFor(cfg) {
|
|
36
47
|
const headers = resolveMcpHttpHeaders(cfg);
|
|
37
48
|
return headers && Object.keys(headers).length > 0 ? { requestInit: { headers } } : undefined;
|
|
38
49
|
}
|
|
39
50
|
|
|
40
|
-
/** Returns { transport, autoDetectAdvert }
|
|
51
|
+
/** Returns { transport, autoDetectAdvert, stderrTail } — stderrTail() is the
|
|
52
|
+
* last ~4 KB of a stdio server's (scrubbed) stderr, '' for remote transports. */
|
|
41
53
|
export function createMcpTransport({ name, cfg, sdk, log }) {
|
|
42
54
|
const { StdioClientTransport, StreamableHTTPClientTransport, SSEClientTransport, WebSocketClientTransport } = sdk;
|
|
43
55
|
const kind = resolveMcpTransportKind(cfg);
|
|
44
56
|
if (kind === 'autoDetect') {
|
|
45
57
|
const { url, advert } = resolveAutoDetectUrl(name, cfg);
|
|
46
58
|
log(`[mcp-client] Connecting "${name}" via autoDetect HTTP: ${url}\n`);
|
|
47
|
-
return {
|
|
59
|
+
return {
|
|
60
|
+
transport: new StreamableHTTPClientTransport(new URL(url)),
|
|
61
|
+
autoDetectAdvert: advert,
|
|
62
|
+
stderrTail: noStderrTail,
|
|
63
|
+
};
|
|
48
64
|
}
|
|
49
65
|
if (kind === 'http' || kind === 'sse') {
|
|
50
66
|
const Transport = kind === 'http' ? StreamableHTTPClientTransport : SSEClientTransport;
|
|
@@ -54,13 +70,14 @@ export function createMcpTransport({ name, cfg, sdk, log }) {
|
|
|
54
70
|
return {
|
|
55
71
|
transport: opts ? new Transport(new URL(url), opts) : new Transport(new URL(url)),
|
|
56
72
|
autoDetectAdvert: null,
|
|
73
|
+
stderrTail: noStderrTail,
|
|
57
74
|
};
|
|
58
75
|
}
|
|
59
76
|
if (kind === 'ws') {
|
|
60
77
|
// WebSocketClientTransport ctor takes only a URL; headers are ignored.
|
|
61
78
|
const url = normalizeMcpTransportUrl(expandEnvVars(String(cfg.url ?? '')), 'ws');
|
|
62
79
|
log(`[mcp-client] Connecting "${name}" via WebSocket: ${mcpUrlForLog(url)}\n`);
|
|
63
|
-
return { transport: new WebSocketClientTransport(new URL(url)), autoDetectAdvert: null };
|
|
80
|
+
return { transport: new WebSocketClientTransport(new URL(url)), autoDetectAdvert: null, stderrTail: noStderrTail };
|
|
64
81
|
}
|
|
65
82
|
if (kind === 'stdio') {
|
|
66
83
|
const transport = new StdioClientTransport({
|
|
@@ -70,10 +87,13 @@ export function createMcpTransport({ name, cfg, sdk, log }) {
|
|
|
70
87
|
env: resolveMcpStdioEnvironment(cfg),
|
|
71
88
|
stderr: cfg.stderr ?? 'pipe',
|
|
72
89
|
});
|
|
90
|
+
let tail = '';
|
|
73
91
|
transport.stderr?.on?.('data', (chunk) => {
|
|
74
|
-
|
|
92
|
+
const text = scrubMcpConnectionMessage(chunk, cfg);
|
|
93
|
+
tail = (tail + text).slice(-MCP_STDERR_TAIL_CHARS);
|
|
94
|
+
log(`[mcp:${name}:stderr] ${text}`);
|
|
75
95
|
});
|
|
76
|
-
return { transport, autoDetectAdvert: null };
|
|
96
|
+
return { transport, autoDetectAdvert: null, stderrTail: () => tail.trim() };
|
|
77
97
|
}
|
|
78
98
|
throw new Error(
|
|
79
99
|
`Invalid config for "${name}": need autoDetect, type (stdio/http/sse/ws), url (http), or command (stdio)`
|