mixdog 1.2.1 → 1.2.2
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/package.json +1 -1
- package/scripts/gate-local.mjs +19 -3
- package/scripts/model-catalog-audit.mjs +1 -15
- package/src/agents/reviewer/AGENT.md +3 -3
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +1 -0
- package/src/repl/slash-commands.mjs +16 -1
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -4
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +10 -0
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +36 -7
- package/src/runtime/agent/orchestrator/mcp/client-handshake.mjs +49 -10
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +40 -3
- package/src/runtime/agent/orchestrator/mcp/client.mjs +230 -96
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +103 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +150 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +111 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +87 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +95 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-request.mjs +122 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +9 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +229 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +188 -29
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +94 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +96 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-fast-mode.mjs +39 -18
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +55 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +25 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-midstream-recovery.mjs +18 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +13 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-midstream.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-recovery.mjs +23 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +46 -20
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request.mjs +14 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +73 -35
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +69 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-server-fallback.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +8 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +34 -7
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +30 -9
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +30 -14
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +93 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +82 -9
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +38 -5
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-guards.mjs +97 -2
- package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +102 -23
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +103 -33
- package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +29 -6
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +18 -1
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +77 -17
- package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +29 -8
- package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +191 -0
- package/src/runtime/agent/orchestrator/providers/gemini-family.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/gemini-history-signatures.mjs +9 -4
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +180 -0
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +21 -82
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -12
- package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +21 -20
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +56 -23
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +68 -19
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +4 -9
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +4 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +22 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +50 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +23 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +16 -8
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-state.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +94 -13
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +193 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +66 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +4 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +23 -14
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +17 -3
- package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +42 -25
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +274 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +72 -32
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +18 -11
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-stamps.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +2 -3
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +1 -3
- package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +34 -3
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +22 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +5 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +5 -9
- package/src/runtime/agent/orchestrator/providers/openai-retry-policy.mjs +9 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-handshake.mjs +16 -8
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/policy.mjs +25 -14
- package/src/runtime/agent/orchestrator/providers/openai-ws-terminal.mjs +18 -11
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +31 -20
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +581 -0
- package/src/runtime/agent/orchestrator/providers/retry-backoff.mjs +46 -7
- package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +118 -219
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +148 -45
- package/src/runtime/agent/orchestrator/providers/retry-midstream.mjs +81 -16
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +0 -18
- package/src/runtime/agent/orchestrator/runtime-core/model-capabilities.mjs +57 -28
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +19 -16
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +1 -97
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +102 -18
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +30 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +41 -21
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +5 -10
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +18 -7
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +155 -29
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +22 -10
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +20 -1
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +12 -15
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +5 -5
- package/src/runtime/memory/lib/pg/process.mjs +34 -24
- package/src/runtime/memory/lib/pg/supervisor.mjs +16 -13
- package/src/runtime/office/README.md +1 -1
- package/src/runtime/office/shared/values.mjs +0 -5
- package/src/runtime/shared/background-tasks.mjs +92 -14
- package/src/runtime/shared/err-text.mjs +25 -0
- package/src/runtime/shared/error-presentation.mjs +159 -19
- package/src/runtime/shared/llm/anthropic-betas.mjs +4 -3
- package/src/runtime/shared/llm/anthropic-effort.mjs +123 -134
- package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +50 -14
- package/src/runtime/shared/llm/model-catalog.mjs +53 -40
- package/src/runtime/shared/llm/openai-daybreak.mjs +4 -16
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +11 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +13 -4
- package/src/runtime/shared/llm/usage-rollup.mjs +0 -1
- package/src/runtime/shared/model-display.mjs +13 -0
- package/src/runtime/shared/quota-resume-store.mjs +11 -0
- package/src/runtime/shared/session-baseline-store.mjs +960 -0
- package/src/runtime/shared/statusline/statusline-format.mjs +4 -4
- package/src/runtime/shared/task-notification-envelope.mjs +2 -2
- package/src/runtime/shared/turn-changes.mjs +447 -219
- package/src/runtime/shared/turn-snapshot-store.mjs +182 -1
- package/src/runtime/shared/turn-snapshot.mjs +170 -48
- package/src/runtime/shared/turn-worktree-snapshot.mjs +135 -46
- package/src/runtime/shared/worktrees/contract.mjs +0 -24
- package/src/runtime/shared/worktrees/test-support.mjs +19 -4
- package/src/session-runtime/boot/apis.mjs +6 -0
- package/src/session-runtime/boot/infrastructure.mjs +6 -0
- package/src/session-runtime/lifecycle/session-catalog.mjs +2 -0
- package/src/session-runtime/lifecycle/teardown.mjs +1 -1
- package/src/session-runtime/mcp-glue/connect.mjs +29 -9
- package/src/session-runtime/mcp-glue/server-catalog.mjs +20 -3
- package/src/session-runtime/mcp-glue.mjs +3 -0
- package/src/session-runtime/mcp-oauth-login.mjs +174 -0
- package/src/session-runtime/model-route/model-switch-target.mjs +34 -0
- package/src/session-runtime/model-route/set-route.mjs +83 -15
- package/src/session-runtime/model-route/web-search-route.mjs +1 -1
- package/src/session-runtime/native-web-search/routes.mjs +22 -3
- package/src/session-runtime/provider-models/model-meta.mjs +12 -3
- package/src/session-runtime/quick-model-rows/web-search-rows.mjs +13 -8
- package/src/session-runtime/quick-web-search-models.mjs +13 -38
- package/src/session-runtime/resource-extension-sync.mjs +4 -0
- package/src/session-runtime/resource-mcp-api.mjs +98 -2
- package/src/session-runtime/runtime-review-api.mjs +13 -0
- package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +13 -1
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +7 -2
- package/src/session-runtime/services/agent-tool/send-flow.mjs +22 -4
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +2 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +22 -5
- package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +8 -1
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -2
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +17 -0
- package/src/session-runtime/settings-compaction-api.mjs +1 -0
- package/src/standalone/daemon-drain-policy.mjs +8 -0
- package/src/standalone/daemon-telemetry.mjs +55 -0
- package/src/standalone/daemon.mjs +3 -7
- package/src/standalone/session-protocol.mjs +7 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +33 -2
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +26 -10
- package/src/standalone/session-service/agent-tree.mjs +12 -0
- package/src/standalone/session-service/quota-resume.mjs +8 -0
- package/src/standalone/session-service/retention/busy.mjs +15 -1
- package/src/standalone/session-service-api.mjs +5 -0
- package/src/standalone/session-service.mjs +1 -0
- package/src/tui/app/app-view.jsx +1 -0
- package/src/tui/app/create-app-pickers.mjs +4 -0
- package/src/tui/app/extension-pickers/mcp-login.mjs +107 -0
- package/src/tui/app/extension-pickers/mcp-servers-picker.mjs +2 -1
- package/src/tui/app/extension-pickers.mjs +2 -1
- package/src/tui/app/model-options.mjs +11 -16
- package/src/tui/app/slash-commands.mjs +7 -2
- package/src/tui/app/slash-dispatch/panel-commands.mjs +16 -1
- package/src/tui/components/StatusLine.jsx +2 -0
- package/src/tui/components/status-line/local-line.mjs +5 -2
- package/src/tui/components/status-line/use-statusline-text.mjs +7 -1
- package/src/tui/dist/index.mjs +816 -43
- package/src/tui/session/quota-resume.mjs +46 -14
- package/src/tui/session/session-api/commands.mjs +33 -24
- package/src/tui/session/session-api/extensions.mjs +22 -0
- package/src/tui/session/session-api/integrations.mjs +7 -0
- package/src/tui/session/session-api/lifecycle.mjs +5 -1
- package/src/tui/session/session-api/routes.mjs +71 -7
- package/src/tui/session/session-api/settings.mjs +5 -14
- package/src/tui/session/session-flow/drain.mjs +7 -1
- package/src/tui/session/session-flow/failed-turn-rewind.mjs +10 -4
- package/src/tui/session/turn.mjs +38 -15
- package/src/tui/statusline-ansi-bridge.mjs +1 -1
- package/src/ui/statusline-agents.mjs +15 -4
- package/src/ui/statusline.mjs +7 -3
- package/src/ui/streaming-markdown-heal.mjs +34 -3
- package/src/vendor/statusline/src/gateway/claude-current.mjs +14 -4
- package/src/runtime/memory/lib/memory-session-merge.mjs +0 -32
- package/src/runtime/shared/llm/usage-session-history.mjs +0 -266
package/package.json
CHANGED
package/scripts/gate-local.mjs
CHANGED
|
@@ -2,10 +2,17 @@
|
|
|
2
2
|
// Local pre-push check. Mirrors the test legs of .github/workflows/release-gate.yml
|
|
3
3
|
// (jobs: runtime, runtime-slow, desktop, desktop-tests fast/slow). It MUST be
|
|
4
4
|
// updated together with that workflow whenever those commands change.
|
|
5
|
+
// Up front, before any build or leg, it runs two fast source checks and stops
|
|
6
|
+
// if either fails: the gate's shipped-history job (build-shipped-history.mjs
|
|
7
|
+
// --check; needs a full clone, a shallow one keeps the committed file), and the
|
|
8
|
+
// released-section changelog check the desktop fast lane asserts
|
|
9
|
+
// (changelog-locales.test.mjs; Deploy's plan adds the Unreleased section).
|
|
5
10
|
// Not covered locally: runtime-macos, computer-backend (cargo + Linux X11),
|
|
6
11
|
// desktop-tests `computer` lane (windows-latest, src/main/computer/ only),
|
|
7
|
-
// relay (apps/relay tests), graph (cargo test)
|
|
8
|
-
//
|
|
12
|
+
// relay (apps/relay tests), graph (cargo test), patch (cargo test of the
|
|
13
|
+
// checked-out engine), mobile-scripts (Python unittest). The gate's path
|
|
14
|
+
// filtering is not applied: every check and leg always runs. Run `npm ci`
|
|
15
|
+
// (root and apps/desktop) first.
|
|
9
16
|
import { spawn, spawnSync } from 'node:child_process';
|
|
10
17
|
import fs from 'node:fs';
|
|
11
18
|
import os from 'node:os';
|
|
@@ -16,6 +23,15 @@ import { gateTestBudget, runGateLegs } from './lib/gate-scheduler.mjs';
|
|
|
16
23
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
17
24
|
const started = Date.now();
|
|
18
25
|
|
|
26
|
+
const preChecks = ['node scripts/build-shipped-history.mjs --check', 'node scripts/check-changelog-locales.mjs'];
|
|
27
|
+
const failedPreChecks = preChecks.filter(
|
|
28
|
+
(cmd) => spawnSync(cmd, { cwd: root, stdio: 'inherit', shell: true }).status !== 0
|
|
29
|
+
);
|
|
30
|
+
if (failedPreChecks.length) {
|
|
31
|
+
console.error(`[gate:local] pre-check failed: ${failedPreChecks.join('; ')}`);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
|
|
19
35
|
const build = spawnSync('npm run build:spawn:test', { cwd: root, stdio: 'inherit', shell: true });
|
|
20
36
|
if (build.status !== 0) {
|
|
21
37
|
console.error('[gate:local] build:spawn:test failed');
|
|
@@ -87,7 +103,7 @@ for (const leg of legs) {
|
|
|
87
103
|
}
|
|
88
104
|
}
|
|
89
105
|
console.log(
|
|
90
|
-
'Not covered locally: runtime-macos, computer-backend, desktop-tests computer lane (Windows-only), relay, graph'
|
|
106
|
+
'Not covered locally: runtime-macos, computer-backend, desktop-tests computer lane (Windows-only), relay, graph, patch, mobile-scripts'
|
|
91
107
|
);
|
|
92
108
|
console.log(`Total: ${((Date.now() - started) / 1000).toFixed(1)}s`);
|
|
93
109
|
process.exit(legs.every((l) => l.ok) ? 0 : 1);
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
warmModelMetadataCatalogs,
|
|
7
7
|
auditModelPricing,
|
|
8
8
|
} from '../src/runtime/agent/orchestrator/providers/model-catalog.mjs';
|
|
9
|
-
import { QUICK_WEB_SEARCH_MODELS } from '../src/session-runtime/quick-web-search-models.mjs';
|
|
10
9
|
|
|
11
10
|
const args = new Set(process.argv.slice(2));
|
|
12
11
|
const json = args.has('--json');
|
|
@@ -154,21 +153,8 @@ for (const [name, provider] of getAllProviders()) {
|
|
|
154
153
|
});
|
|
155
154
|
}
|
|
156
155
|
|
|
156
|
+
// Quick web-search rows carry no static windows any more (they come from the catalogs).
|
|
157
157
|
const quickRows = [];
|
|
158
|
-
for (const [provider, models] of Object.entries(QUICK_WEB_SEARCH_MODELS)) {
|
|
159
|
-
for (const model of models) {
|
|
160
|
-
if (model?.contextWindow == null) continue;
|
|
161
|
-
const external = externalMeta(modelsDev, litellm, provider, model.id);
|
|
162
|
-
const externalContext = external.modelsDevContext ?? external.litellmContext;
|
|
163
|
-
quickRows.push({
|
|
164
|
-
provider,
|
|
165
|
-
id: model.id,
|
|
166
|
-
staticContext: n(model.contextWindow),
|
|
167
|
-
externalContext,
|
|
168
|
-
mismatch: n(model.contextWindow) != null && externalContext != null && n(model.contextWindow) !== externalContext,
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
158
|
|
|
173
159
|
const mismatches = providerResults.flatMap((p) => p.rows.filter((r) => r.contextMismatch || r.outputMismatch));
|
|
174
160
|
const exactOneM = providerResults.flatMap((p) => p.rows.filter((r) => r.liveContext === 1_000_000));
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: Reviewer
|
|
3
|
-
description: Use
|
|
3
|
+
description: Use only at the end, as the final check of non-trivial work: after the implementation is written and verified, before reporting completion, to independently verify correctness, regressions, risks, and acceptance criteria. Skip for low-difficulty work.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Independent final-check review agent.
|
|
7
7
|
|
|
8
|
-
You are called
|
|
9
|
-
verification has run, before completion is reported.
|
|
8
|
+
You are called only at the end, after the deliverable is written and the
|
|
9
|
+
Lead's own verification has run, before completion is reported.
|
|
10
10
|
|
|
11
11
|
Inspect the diff, affected boundaries, existing tests, and stated acceptance
|
|
12
12
|
criteria with independent judgment. Run the necessary builds, tests, lint, or
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "reviewer",
|
|
3
3
|
"name": "Reviewer",
|
|
4
|
-
"description": "Use
|
|
4
|
+
"description": "Use only at the end, as the final check of non-trivial work: after the implementation is written and verified, before reporting completion, to independently verify correctness, regressions, risks, and acceptance criteria. Skip for low-difficulty work.",
|
|
5
5
|
"entry": "AGENT.md"
|
|
6
6
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* to `ctx.out`; only `/exit` and `/quit` return 'exit'.
|
|
4
4
|
*/
|
|
5
5
|
import { dim, green, red, yellow, colorEnabled } from '../runtime/shared/statusline/ansi.mjs';
|
|
6
|
+
import { switchesSessionModel } from '../session-runtime/model-route/model-switch-target.mjs';
|
|
6
7
|
import { createSessionStats } from '../ui/session-stats.mjs';
|
|
7
8
|
import { statuslineFor } from './turn-output.mjs';
|
|
8
9
|
|
|
@@ -65,7 +66,21 @@ async function setModel(ctx, arg) {
|
|
|
65
66
|
return;
|
|
66
67
|
}
|
|
67
68
|
const runtime = await ctx.ensureRuntime();
|
|
68
|
-
|
|
69
|
+
const request = { model: arg };
|
|
70
|
+
// The user's model choice switches this conversation in place; with
|
|
71
|
+
// auto-compact on model change (default on) the history is compacted on the
|
|
72
|
+
// current model first. A failed compaction never blocks the switch.
|
|
73
|
+
if (switchesSessionModel(runtime, request) && runtime.getCompactionSettings?.()?.onModelChange !== false) {
|
|
74
|
+
// An invalid or unavailable selector is rejected before anything compacts.
|
|
75
|
+
await runtime.setRoute(request, { validateOnly: true });
|
|
76
|
+
out.write(`${dim('compacting conversation before the model change…')}\n`);
|
|
77
|
+
try {
|
|
78
|
+
await runtime.compact();
|
|
79
|
+
} catch {
|
|
80
|
+
/* next-turn auto-compaction fits the new window */
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
await runtime.setRoute(request, { switchEstablished: true });
|
|
69
84
|
out.write(`${green(`✓ model → ${runtime.provider}/${runtime.model}`)}\n`);
|
|
70
85
|
}
|
|
71
86
|
|
|
@@ -59,6 +59,25 @@ function assistantMessageText(content) {
|
|
|
59
59
|
.join('\n');
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
// Visible assistant text inside a providerReplay envelope. Item shapes by
|
|
63
|
+
// provider: anthropic `{type:'text',text}`; openai/xai responses
|
|
64
|
+
// `{type:'message',content:[{type:'output_text',text}]}`; gemini/antigravity
|
|
65
|
+
// parts `{text}` (reasoning is `{thought:true,text}`). Reasoning/thinking and
|
|
66
|
+
// tool items are skipped.
|
|
67
|
+
function replayItemText(item) {
|
|
68
|
+
if (!item || typeof item !== 'object') return '';
|
|
69
|
+
if (item.type === 'message') return assistantMessageText(item.content);
|
|
70
|
+
if (item.type === 'text' || item.type === 'output_text' || (item.type === undefined && item.thought !== true)) {
|
|
71
|
+
return typeof item.text === 'string' ? item.text : '';
|
|
72
|
+
}
|
|
73
|
+
return '';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function providerReplayText(replay) {
|
|
77
|
+
const items = Array.isArray(replay?.items) ? replay.items : [];
|
|
78
|
+
return items.map(replayItemText).filter(Boolean).join('\n');
|
|
79
|
+
}
|
|
80
|
+
|
|
62
81
|
/** Message index at askSession start — salvage only assistant rows appended this run. */
|
|
63
82
|
export function resolveHandoffMessageStartIndex(session) {
|
|
64
83
|
const messages = Array.isArray(session?.messages) ? session.messages : [];
|
|
@@ -72,7 +91,8 @@ function collectSessionAssistantHandoffText(session, messageStartIndex = 0) {
|
|
|
72
91
|
for (let i = start; i < messages.length; i += 1) {
|
|
73
92
|
const m = messages[i];
|
|
74
93
|
if (m?.role !== 'assistant') continue;
|
|
75
|
-
const
|
|
94
|
+
const contentText = assistantMessageText(m.content).trim();
|
|
95
|
+
const t = contentText || providerReplayText(m.providerReplay).trim();
|
|
76
96
|
if (t && t !== '.') parts.push(t);
|
|
77
97
|
}
|
|
78
98
|
return parts.length ? parts.join('\n\n') : '';
|
|
@@ -80,9 +100,14 @@ function collectSessionAssistantHandoffText(session, messageStartIndex = 0) {
|
|
|
80
100
|
|
|
81
101
|
export function watchdogPartialHandoffFromError(error, session, messageStartIndex = 0) {
|
|
82
102
|
if (!isAgentProgressWatchdogAbortError(error)) return null;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
103
|
+
return turnPartialHandoff(error, session, messageStartIndex);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Assistant text a stopped turn produced before it stopped. A canonical agent
|
|
107
|
+
* turn cannot expose its live transcript here, so it reads the text itself
|
|
108
|
+
* and carries it on the turn's error. */
|
|
109
|
+
export function turnPartialHandoff(error, session, messageStartIndex = 0) {
|
|
110
|
+
if (typeof error?.partialHandoff === 'string') return error.partialHandoff;
|
|
86
111
|
return partialHandoffTextFromSession(session, messageStartIndex);
|
|
87
112
|
}
|
|
88
113
|
|
|
@@ -210,6 +210,16 @@ export function resolveProviderCacheKey(opts, provider) {
|
|
|
210
210
|
);
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
+
/** A cache identity as a prompt_cache_key: kept as is up to the 64-char wire
|
|
214
|
+
* limit, a bounded hash identity beyond it, '' when empty. */
|
|
215
|
+
export function normalizeCacheKey(value) {
|
|
216
|
+
const text = String(value ?? '').trim();
|
|
217
|
+
if (!text) return '';
|
|
218
|
+
const wellFormed = text.toWellFormed();
|
|
219
|
+
if (wellFormed.length <= 64) return wellFormed;
|
|
220
|
+
return `pc_${createHash('sha256').update(wellFormed).digest('hex').slice(0, 32)}`;
|
|
221
|
+
}
|
|
222
|
+
|
|
213
223
|
function shortHash(value, chars = 18) {
|
|
214
224
|
return createHash('sha256').update(stableHashStringify(value)).digest('hex').slice(0, chars);
|
|
215
225
|
}
|
|
@@ -79,20 +79,41 @@ export function mcpUrlForLog(raw) {
|
|
|
79
79
|
|
|
80
80
|
function replaceSecret(text, value) {
|
|
81
81
|
const secret = String(value || '');
|
|
82
|
-
return secret
|
|
82
|
+
return secret ? text.split(secret).join('[redacted]') : text;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
// Configured URL parts and header values shorter than 4 characters are left
|
|
86
|
+
// alone: redacting e.g. the `1` of `?v=1` would mangle every message. Known
|
|
87
|
+
// connection secrets (OAuth tokens) are redacted at any length.
|
|
88
|
+
function replaceConfiguredSecret(text, value) {
|
|
89
|
+
return String(value || '').length >= 4 ? replaceSecret(text, value) : text;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** `value` with every one of `secrets` redacted from its strings, recursing
|
|
93
|
+
* into arrays and plain objects (tool results, JSON-RPC error data). */
|
|
94
|
+
export function scrubMcpSecrets(value, secrets) {
|
|
95
|
+
if (secrets.length === 0) return value;
|
|
96
|
+
if (typeof value === 'string') return secrets.reduce(replaceSecret, value);
|
|
97
|
+
if (Array.isArray(value)) return value.map((item) => scrubMcpSecrets(item, secrets));
|
|
98
|
+
const proto = value && typeof value === 'object' ? Object.getPrototypeOf(value) : undefined;
|
|
99
|
+
if (proto !== Object.prototype && proto !== null) return value;
|
|
100
|
+
return Object.fromEntries(
|
|
101
|
+
Object.entries(value).map(([key, item]) => [scrubMcpSecrets(key, secrets), scrubMcpSecrets(item, secrets)])
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** `secrets` are values known only to the live connection (its OAuth tokens). */
|
|
106
|
+
export function scrubMcpConnectionMessage(value, cfg = {}, secrets = []) {
|
|
107
|
+
let text = scrubMcpSecrets(String(value || ''), secrets);
|
|
87
108
|
const rawUrl = expandEnvVars(String(cfg?.url || ''));
|
|
88
109
|
if (rawUrl) {
|
|
89
110
|
text = text.split(rawUrl).join(mcpUrlForLog(rawUrl));
|
|
90
111
|
try {
|
|
91
112
|
const parsed = new URL(rawUrl);
|
|
92
|
-
text =
|
|
93
|
-
text =
|
|
113
|
+
text = replaceConfiguredSecret(text, parsed.username);
|
|
114
|
+
text = replaceConfiguredSecret(text, parsed.password);
|
|
94
115
|
for (const paramValue of parsed.searchParams.values()) {
|
|
95
|
-
text =
|
|
116
|
+
text = replaceConfiguredSecret(text, paramValue);
|
|
96
117
|
}
|
|
97
118
|
} catch {
|
|
98
119
|
/* invalid URL is reported without echoing it */
|
|
@@ -101,7 +122,7 @@ export function scrubMcpConnectionMessage(value, cfg = {}) {
|
|
|
101
122
|
const headers = resolveMcpHttpHeaders(cfg);
|
|
102
123
|
for (const [name, headerValue] of Object.entries(headers)) {
|
|
103
124
|
if (/authorization|cookie|token|secret|api[-_]?key|signature/i.test(name)) {
|
|
104
|
-
text =
|
|
125
|
+
text = replaceConfiguredSecret(text, headerValue);
|
|
105
126
|
}
|
|
106
127
|
}
|
|
107
128
|
return text
|
|
@@ -286,6 +307,14 @@ export function resolveMcpTransportKind(cfg) {
|
|
|
286
307
|
throw new Error(`Invalid config: need autoDetect, type (stdio/http/sse/ws), url (http), or command (stdio)`);
|
|
287
308
|
}
|
|
288
309
|
|
|
310
|
+
/** The exact URL OAuth credentials of an HTTP/SSE server config are stored
|
|
311
|
+
* under; null for other transports. */
|
|
312
|
+
export function resolveMcpOAuthUrl(cfg) {
|
|
313
|
+
const kind = resolveMcpTransportKind(cfg);
|
|
314
|
+
if (kind !== 'http' && kind !== 'sse') return null;
|
|
315
|
+
return normalizeMcpTransportUrl(expandEnvVars(String(cfg.url ?? '')), kind);
|
|
316
|
+
}
|
|
317
|
+
|
|
289
318
|
// MCP per-tool-call timeout. Default 2min: a hung/unresponsive MCP server
|
|
290
319
|
// (e.g. a busy editor) must not stall a tool call indefinitely. Genuinely
|
|
291
320
|
// long-running tools can raise/disable it via MIXDOG_MCP_CALL_TIMEOUT_MS or a
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { markServiceUnreachable, isConnRefuseError } from '../../../shared/service-discovery.mjs';
|
|
7
7
|
import { MCP_MAX_TIMER_MS, resolveMcpStartupTimeoutMs } from './client-config.mjs';
|
|
8
8
|
import { appendMcpStderrTail } from './client-transport.mjs';
|
|
9
|
+
import { MCP_OAUTH_TIMEOUT_MS } from './oauth.mjs';
|
|
9
10
|
|
|
10
11
|
// tools/list pagination bounds: a server that never stops handing out cursors
|
|
11
12
|
// (or repeats one) cannot loop the client forever.
|
|
@@ -53,6 +54,15 @@ function startupTimeoutError(name, startupTimeoutMs) {
|
|
|
53
54
|
return err;
|
|
54
55
|
}
|
|
55
56
|
|
|
57
|
+
const oauthLoginError = () => new Error('MCP OAuth login failed, cancelled, or timed out');
|
|
58
|
+
|
|
59
|
+
/** Code of a connect cancelled (login cancel, disconnect, shutdown) before any
|
|
60
|
+
* interactive login started. */
|
|
61
|
+
export const MCP_CONNECT_CANCELLED = 'EMCPCONNECTCANCELLED';
|
|
62
|
+
function connectCancelledError(name) {
|
|
63
|
+
return Object.assign(new Error(`MCP server "${name}" connect cancelled`), { code: MCP_CONNECT_CANCELLED });
|
|
64
|
+
}
|
|
65
|
+
|
|
56
66
|
/**
|
|
57
67
|
* Bound the connect + listTools handshake so a slow/hung server can't stall
|
|
58
68
|
* boot or the first turn. On expiry the pending transport/child is torn down
|
|
@@ -73,17 +83,43 @@ export async function runBoundedHandshake({
|
|
|
73
83
|
}) {
|
|
74
84
|
const startupTimeoutMs = resolveMcpStartupTimeoutMs(cfg);
|
|
75
85
|
const guard = { timer: null, timedOut: false };
|
|
86
|
+
let rejectDeadline;
|
|
87
|
+
// True once an interactive login actually started (the server challenged
|
|
88
|
+
// and a browser sign-in was allowed).
|
|
89
|
+
let loginStarted = false;
|
|
90
|
+
const armDeadline = (ms, error = () => startupTimeoutError(name, ms)) => {
|
|
91
|
+
if (guard.timer) clearTimeout(guard.timer);
|
|
92
|
+
guard.timer = setTimeout(() => {
|
|
93
|
+
guard.timedOut = true;
|
|
94
|
+
rejectDeadline(error());
|
|
95
|
+
}, ms);
|
|
96
|
+
};
|
|
97
|
+
const deadline = new Promise((_, reject) => {
|
|
98
|
+
rejectDeadline = reject;
|
|
99
|
+
});
|
|
100
|
+
// A closed OAuth connection (login cancel, disconnect, shutdown) settles a
|
|
101
|
+
// handshake that would otherwise wait forever (an SSE stream closed while
|
|
102
|
+
// starting never settles). The SDK also closes the transport — and with it
|
|
103
|
+
// the OAuth connection — right before rethrowing a connect failure of its
|
|
104
|
+
// own (e.g. connection refused): deferring past the pending microtasks lets
|
|
105
|
+
// that real failure settle the race first.
|
|
106
|
+
const cancelOAuth = () =>
|
|
107
|
+
setImmediate(() => rejectDeadline(loginStarted ? oauthLoginError() : connectCancelledError(name)));
|
|
108
|
+
transport.oauth?.signal.addEventListener('abort', cancelOAuth, { once: true });
|
|
109
|
+
if (transport.oauth?.signal.aborted) cancelOAuth();
|
|
110
|
+
if (startupTimeoutMs > 0) armDeadline(startupTimeoutMs);
|
|
111
|
+
// Human authorization gets a separate, finite budget. The ordinary startup
|
|
112
|
+
// budget still applies until the server actually challenges authentication.
|
|
113
|
+
if (transport.oauth) {
|
|
114
|
+
transport.oauth.onStart = () => {
|
|
115
|
+
loginStarted = true;
|
|
116
|
+
armDeadline(MCP_OAUTH_TIMEOUT_MS, oauthLoginError);
|
|
117
|
+
};
|
|
118
|
+
}
|
|
76
119
|
const handshake = performHandshake(client, transport, {
|
|
77
|
-
timeout: startupTimeoutMs > 0 ? startupTimeoutMs : MCP_MAX_TIMER_MS,
|
|
120
|
+
timeout: !transport.oauth && startupTimeoutMs > 0 ? startupTimeoutMs : MCP_MAX_TIMER_MS,
|
|
78
121
|
});
|
|
79
122
|
try {
|
|
80
|
-
if (startupTimeoutMs <= 0) return await handshake;
|
|
81
|
-
const deadline = new Promise((_, rej) => {
|
|
82
|
-
guard.timer = setTimeout(() => {
|
|
83
|
-
guard.timedOut = true;
|
|
84
|
-
rej(startupTimeoutError(name, startupTimeoutMs));
|
|
85
|
-
}, startupTimeoutMs);
|
|
86
|
-
});
|
|
87
123
|
return await Promise.race([handshake, deadline]);
|
|
88
124
|
} catch (err) {
|
|
89
125
|
// A discovery-advert port that fails to connect is a corpse (recycled
|
|
@@ -92,7 +128,7 @@ export async function runBoundedHandshake({
|
|
|
92
128
|
// ONLY — a startup/handshake timeout is a slow-but-alive server.
|
|
93
129
|
if (autoDetectAdvert && isConnRefuseError(err))
|
|
94
130
|
markServiceUnreachable(autoDetectAdvert.service, autoDetectAdvert.port);
|
|
95
|
-
if (guard.timedOut) {
|
|
131
|
+
if (guard.timedOut || transport.oauth?.signal.aborted) {
|
|
96
132
|
// Tear down the pending transport/child so a hung handshake never
|
|
97
133
|
// leaks a stdio process or socket — fire-and-forget (like the
|
|
98
134
|
// tool-call timeout path) so a slow tree-kill never delays this
|
|
@@ -100,7 +136,7 @@ export async function runBoundedHandshake({
|
|
|
100
136
|
try {
|
|
101
137
|
closeServer({ client, transport }).catch(() => {});
|
|
102
138
|
} catch {
|
|
103
|
-
|
|
139
|
+
// Teardown is best effort: the handshake failure below is what gets reported.
|
|
104
140
|
}
|
|
105
141
|
// Never let the late handshake settle into an unhandled rejection.
|
|
106
142
|
handshake.catch(() => {});
|
|
@@ -112,6 +148,9 @@ export async function runBoundedHandshake({
|
|
|
112
148
|
}
|
|
113
149
|
throw tail ? new Error(appendMcpStderrTail(String(err), tail)) : err;
|
|
114
150
|
} finally {
|
|
151
|
+
transport.oauth?.finishConnect();
|
|
115
152
|
if (guard.timer) clearTimeout(guard.timer);
|
|
153
|
+
transport.oauth?.signal.removeEventListener('abort', cancelOAuth);
|
|
154
|
+
if (transport.oauth) transport.oauth.onStart = () => {};
|
|
116
155
|
}
|
|
117
156
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* WebSocket, or a stdio child.
|
|
5
5
|
*/
|
|
6
6
|
import { readServicePort } from '../../../shared/service-discovery.mjs';
|
|
7
|
+
import { createMcpOAuth } from './oauth.mjs';
|
|
7
8
|
import {
|
|
8
9
|
AUTO_DETECT_PORTS,
|
|
9
10
|
expandEnvVars,
|
|
@@ -11,6 +12,7 @@ import {
|
|
|
11
12
|
mcpUrlForLog,
|
|
12
13
|
normalizeMcpTransportUrl,
|
|
13
14
|
resolveMcpHttpHeaders,
|
|
15
|
+
resolveMcpOAuthUrl,
|
|
14
16
|
resolveMcpStdioEnvironment,
|
|
15
17
|
resolveMcpTransportKind,
|
|
16
18
|
scrubMcpConnectionMessage,
|
|
@@ -49,6 +51,19 @@ function requestInitFor(cfg) {
|
|
|
49
51
|
return headers && Object.keys(headers).length > 0 ? { requestInit: { headers } } : undefined;
|
|
50
52
|
}
|
|
51
53
|
|
|
54
|
+
// Configured authentication stays authoritative even when its variables are
|
|
55
|
+
// unset or resolve empty: the server then fails as configured instead of
|
|
56
|
+
// turning into an OAuth login.
|
|
57
|
+
export function hasConfiguredMcpAuth(cfg) {
|
|
58
|
+
const configured = (value) =>
|
|
59
|
+
value && typeof value === 'object' && !Array.isArray(value) && Object.keys(value).length > 0;
|
|
60
|
+
return (
|
|
61
|
+
Boolean(String(cfg.bearer_token_env_var || '').trim()) ||
|
|
62
|
+
configured(cfg.headers) ||
|
|
63
|
+
configured(cfg.env_http_headers)
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
52
67
|
// The SDK's WebSocket transport opens its socket without a way to set request
|
|
53
68
|
// headers. This subclass changes only socket creation: Node's WebSocket takes
|
|
54
69
|
// `{ protocols, headers }`; the guard and event wiring match the stock start().
|
|
@@ -88,7 +103,7 @@ function createHeaderWebSocketTransport(Base, messageSchema, url, headers) {
|
|
|
88
103
|
* transports. `strictEnv` (the caller passes it for plugin-declared servers)
|
|
89
104
|
* makes unset variables without a default fail the server; otherwise they
|
|
90
105
|
* expand to empty and are reported in `warnings` (names only). */
|
|
91
|
-
export function createMcpTransport({ name, cfg, sdk, log, strictEnv }) {
|
|
106
|
+
export function createMcpTransport({ name, cfg, sdk, log, strictEnv, oauthOptions }) {
|
|
92
107
|
const { StdioClientTransport, StreamableHTTPClientTransport, SSEClientTransport, WebSocketClientTransport } = sdk;
|
|
93
108
|
const kind = resolveMcpTransportKind(cfg);
|
|
94
109
|
const warnings = [];
|
|
@@ -113,11 +128,33 @@ export function createMcpTransport({ name, cfg, sdk, log, strictEnv }) {
|
|
|
113
128
|
}
|
|
114
129
|
if (kind === 'http' || kind === 'sse') {
|
|
115
130
|
const Transport = kind === 'http' ? StreamableHTTPClientTransport : SSEClientTransport;
|
|
116
|
-
const url =
|
|
131
|
+
const url = resolveMcpOAuthUrl(cfg);
|
|
117
132
|
const opts = requestInitFor(cfg);
|
|
133
|
+
// Explicit authentication remains authoritative (including custom API-key
|
|
134
|
+
// headers). Never forward those credentials to OAuth discovery endpoints.
|
|
135
|
+
let transport;
|
|
136
|
+
const oauth = hasConfiguredMcpAuth(cfg)
|
|
137
|
+
? null
|
|
138
|
+
: createMcpOAuth({
|
|
139
|
+
url,
|
|
140
|
+
serverName: name,
|
|
141
|
+
...oauthOptions,
|
|
142
|
+
// SSE advertises its POST endpoint on the authenticated event stream.
|
|
143
|
+
// No other path on the origin is allowed to receive this server's token.
|
|
144
|
+
isTransportEndpoint: (input) => kind === 'sse' && transport?._endpoint?.href === new URL(input).href,
|
|
145
|
+
});
|
|
146
|
+
transport = new Transport(new URL(url), oauth ? { fetch: oauth.fetch } : opts);
|
|
147
|
+
if (oauth) {
|
|
148
|
+
transport.oauth = oauth;
|
|
149
|
+
const close = transport.close.bind(transport);
|
|
150
|
+
transport.close = async () => {
|
|
151
|
+
oauth.close();
|
|
152
|
+
await close();
|
|
153
|
+
};
|
|
154
|
+
}
|
|
118
155
|
log(`[mcp-client] Connecting "${name}" via ${kind.toUpperCase()}: ${mcpUrlForLog(url)}\n`);
|
|
119
156
|
return {
|
|
120
|
-
transport
|
|
157
|
+
transport,
|
|
121
158
|
autoDetectAdvert: null,
|
|
122
159
|
stderrTail: noStderrTail,
|
|
123
160
|
warnings,
|