mixdog 1.2.6 → 1.3.1
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/LICENSES/simple-icons-CC0-1.0.txt +30 -0
- package/NOTICE.md +71 -9
- package/package.json +4 -1
- package/scripts/check-model-recommendations.mjs +89 -0
- package/scripts/gate-local.mjs +7 -0
- package/scripts/lib/isolated-test-env.mjs +16 -0
- package/src/agents/reviewer/AGENT.md +4 -2
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +10 -0
- package/src/defaults/skills/browser-use/SKILL.md +5 -0
- package/src/defaults/skills/memory-management/SKILL.md +4 -1
- package/src/defaults/skills/setup/references/actions.md +14 -4
- package/src/defaults/skills/setup-guide/SKILL.md +178 -0
- package/src/defaults/skills/setup-guide/model-recommendations.json +333 -0
- package/src/lib/rules-builder.cjs +55 -6
- package/src/output-styles/common.md +13 -8
- package/src/rules/agent/AGENT.md +4 -0
- package/src/rules/agent-mode/AGENT_MODE.md +24 -0
- package/src/rules/agent-mode/MIXY.md +28 -0
- package/src/rules/agent-mode/ROUTINE.md +6 -0
- package/src/rules/lead/LEAD.md +7 -3
- package/src/rules/shared/70-delivery.md +3 -0
- package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +86 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +77 -14
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +241 -14
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +4 -2
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +216 -0
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +5 -4
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +10 -1
- package/src/runtime/agent/orchestrator/mcp/client.mjs +115 -11
- package/src/runtime/agent/orchestrator/mcp/oauth-account.mjs +97 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +49 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +59 -9
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +32 -7
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +45 -6
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +195 -6
- package/src/runtime/agent/orchestrator/mcp/server-connectors.mjs +17 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +7 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +10 -3
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +7 -8
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/lib/tool-call-wire-ids.mjs +65 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +8 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +17 -12
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +14 -2
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +17 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +96 -1
- package/src/runtime/agent/orchestrator/runtime-core/context-status-shape.mjs +4 -0
- package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +6 -4
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +14 -0
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +1 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +12 -6
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +32 -5
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +21 -5
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +40 -7
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +52 -20
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/agent-home.d.mts +4 -0
- package/src/runtime/agent/orchestrator/session/agent-home.mjs +33 -0
- package/src/runtime/agent/orchestrator/session/agent-mode.mjs +62 -0
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +31 -0
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +241 -0
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +166 -0
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +650 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +192 -0
- package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +221 -0
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +195 -0
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +167 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +108 -6
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +74 -15
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +9 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +5 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +13 -3
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +49 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +18 -8
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-lifecycle-epoch.mjs +0 -8
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +44 -16
- package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +50 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -5
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +39 -4
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +33 -24
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +58 -8
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +58 -0
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +32 -5
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +86 -0
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +329 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/store-record-strict-scan.mjs +28 -9
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -12
- package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +46 -0
- package/src/runtime/agent/orchestrator/session/store-summary-visibility.mjs +0 -4
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +58 -10
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +92 -15
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +12 -0
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-client.mjs +113 -5
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +4 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +25 -1
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +6 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +3 -0
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +75 -57
- package/src/runtime/attachments/store.mjs +6 -0
- package/src/runtime/browser-bridge/client.mjs +24 -0
- package/src/runtime/channels/lib/scheduler.mjs +40 -12
- package/src/runtime/channels/lib/schedules-db.mjs +71 -12
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +36 -16
- package/src/runtime/channels/lib/webhook.mjs +0 -1
- package/src/runtime/channels/lib/webhooks-db.mjs +100 -10
- package/src/runtime/channels/lib/worker-main.mjs +17 -20
- package/src/runtime/computer-bridge/client.mjs +28 -1
- package/src/runtime/connectors/gmail-app-password.mjs +690 -0
- package/src/runtime/connectors/google-mcp.mjs +446 -0
- package/src/runtime/effort-judge/judge-client.mjs +1 -1
- package/src/runtime/effort-judge/model-manifest.json +7 -7
- package/src/runtime/memory/lib/core-memory-access.mjs +69 -0
- package/src/runtime/memory/lib/core-memory-file.mjs +16 -8
- package/src/runtime/memory/lib/core-memory-index.mjs +15 -9
- package/src/runtime/memory/lib/core-memory-management.mjs +10 -4
- package/src/runtime/memory/lib/core-memory-store.mjs +53 -30
- package/src/runtime/memory/lib/core-memory-uniqueness.mjs +10 -6
- package/src/runtime/memory/lib/http-router/session-routes.mjs +3 -2
- package/src/runtime/memory/lib/memory-action-handlers/core-actions.mjs +44 -14
- package/src/runtime/memory/lib/memory-schema/core-and-meta.mjs +11 -0
- package/src/runtime/memory/lib/memory.mjs +7 -1
- package/src/runtime/memory/lib/query-core-recall.mjs +9 -1
- package/src/runtime/memory/lib/query-hybrid-search.mjs +2 -0
- package/src/runtime/memory/lib/tool-call-handler.mjs +2 -0
- package/src/runtime/memory/tool-defs.mjs +5 -0
- package/src/runtime/shared/agent-avatar-sprites.mjs +445 -0
- package/src/runtime/shared/agent-avatar.d.mts +64 -0
- package/src/runtime/shared/agent-avatar.mjs +320 -0
- package/src/runtime/shared/agent-kind.mjs +152 -0
- package/src/runtime/shared/agent-route-config.d.mts +4 -0
- package/src/runtime/shared/agent-route-config.mjs +30 -0
- package/src/runtime/shared/agent-store.mjs +132 -0
- package/src/runtime/shared/atomic-file.mjs +14 -1
- package/src/runtime/shared/bot-split-migration.mjs +457 -0
- package/src/runtime/shared/config-patch.mjs +20 -1
- package/src/runtime/shared/config.mjs +8 -1
- package/src/runtime/shared/connector-accounts.mjs +15 -0
- package/src/runtime/shared/connector-catalog.d.mts +51 -0
- package/src/runtime/shared/connector-catalog.mjs +228 -0
- package/src/runtime/shared/connector-triggers.d.mts +3 -0
- package/src/runtime/shared/connector-triggers.mjs +45 -0
- package/src/runtime/shared/err-text.mjs +3 -1
- package/src/runtime/shared/error-presentation.mjs +91 -6
- package/src/runtime/shared/google-oauth-client.mjs +24 -0
- package/src/runtime/shared/handoff-artifacts.d.mts +20 -0
- package/src/runtime/shared/handoff-artifacts.mjs +61 -0
- package/src/runtime/shared/held-request-host.d.mts +12 -0
- package/src/runtime/shared/held-request-host.mjs +71 -0
- package/src/runtime/shared/llm/provider-model-identities.mjs +6 -1
- package/src/runtime/shared/llm/usage-accounting.mjs +7 -1
- package/src/runtime/shared/model-route-fallback.mjs +79 -7
- package/src/runtime/shared/plain-preview.d.mts +1 -0
- package/src/runtime/shared/plain-preview.mjs +33 -0
- package/src/runtime/shared/routine-limits.d.mts +11 -0
- package/src/runtime/shared/routine-limits.mjs +21 -0
- package/src/runtime/shared/routine-trigger.d.mts +10 -0
- package/src/runtime/shared/routine-trigger.mjs +44 -0
- package/src/runtime/shared/schedule-model-ref.mjs +9 -10
- package/src/runtime/shared/sensitive-path-rules.d.mts +15 -0
- package/src/runtime/shared/sensitive-path-rules.mjs +256 -0
- package/src/runtime/shared/slow-span.mjs +4 -12
- package/src/runtime/shared/statusline/statusline-segments.mjs +13 -1
- package/src/runtime/shared/transcript-metadata.mjs +10 -0
- package/src/runtime/shared/turn-changes.mjs +0 -8
- package/src/runtime/shared/usage-readout-totals.mjs +58 -0
- package/src/runtime/shared/user-data-guard.mjs +119 -38
- package/src/session-runtime/agent-home-delivery.mjs +826 -0
- package/src/session-runtime/agent-profile-changes.mjs +21 -0
- package/src/session-runtime/agent-room-delivery.mjs +133 -0
- package/src/session-runtime/agent-task-sessions.mjs +460 -0
- package/src/session-runtime/boot/apis.mjs +63 -18
- package/src/session-runtime/boot/facade.mjs +5 -8
- package/src/session-runtime/boot/infrastructure.mjs +28 -17
- package/src/session-runtime/boot/providers.mjs +14 -4
- package/src/session-runtime/boot/tools.mjs +3 -0
- package/src/session-runtime/channel-config-api.mjs +53 -5
- package/src/session-runtime/config-lifecycle.mjs +43 -2
- package/src/session-runtime/cwd-plugins/core-memory-context.mjs +36 -20
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +6 -1
- package/src/session-runtime/handoff-attachments.mjs +593 -0
- package/src/session-runtime/held-requests.mjs +228 -0
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +121 -0
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +31 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +56 -3
- package/src/session-runtime/internal-tool-executor.mjs +2 -0
- package/src/session-runtime/lifecycle/session-catalog.mjs +9 -0
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +4 -0
- package/src/session-runtime/lifecycle/shared.mjs +6 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +8 -0
- package/src/session-runtime/mcp-glue/server-input.mjs +3 -0
- package/src/session-runtime/mcp-oauth-login.mjs +112 -15
- package/src/session-runtime/model-route/route-persist.mjs +2 -2
- package/src/session-runtime/model-route/route-tuning.mjs +7 -1
- package/src/session-runtime/model-route/set-route.mjs +35 -4
- package/src/session-runtime/native-web-search.mjs +2 -2
- package/src/session-runtime/new-session-config.mjs +6 -1
- package/src/session-runtime/owned-automation-run.mjs +229 -0
- package/src/session-runtime/resource-api.mjs +5 -0
- package/src/session-runtime/resource-mcp-api.mjs +107 -13
- package/src/session-runtime/resource-skills-api.mjs +12 -0
- package/src/session-runtime/room-member-gate.mjs +48 -0
- package/src/session-runtime/route-resolution.mjs +5 -11
- package/src/session-runtime/routine-home-turn.mjs +156 -0
- package/src/session-runtime/routine-owner.mjs +48 -0
- package/src/session-runtime/schedule-session-run.mjs +30 -64
- package/src/session-runtime/services/agent-tool/helpers.mjs +30 -1
- package/src/session-runtime/services/agent-tool/send-flow.mjs +11 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +19 -4
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +2 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +4 -1
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +5 -8
- package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
- package/src/session-runtime/services/channel-admin.mjs +93 -24
- package/src/session-runtime/services/memory-access.mjs +37 -0
- package/src/session-runtime/services/provider-admin.mjs +74 -39
- package/src/session-runtime/services/schedule-access.mjs +91 -0
- package/src/session-runtime/session-create/session-options.mjs +34 -7
- package/src/session-runtime/session-hooks.mjs +16 -8
- package/src/session-runtime/setup-tool/executor.mjs +79 -6
- package/src/session-runtime/setup-tool/extended-actions.mjs +90 -20
- package/src/session-runtime/setup-tool/settings-contract.mjs +14 -6
- package/src/session-runtime/setup-tool/tool-defs.mjs +8 -0
- package/src/session-runtime/skills-api.mjs +16 -1
- package/src/session-runtime/tool-policy-refresh.mjs +249 -29
- package/src/session-runtime/turn/session-ops.mjs +8 -1
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +10 -2
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +14 -0
- package/src/session-runtime/webhook-session-run.mjs +49 -67
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +239 -0
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +650 -25
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +67 -7
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +11 -4
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +11 -1
- package/src/session-runtime/workflow-agents-api.mjs +4 -1
- package/src/standalone/daemon-agent-control.mjs +1 -8
- package/src/standalone/daemon-session-control.mjs +21 -4
- package/src/standalone/daemon.mjs +31 -5
- package/src/standalone/session-protocol.mjs +27 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +46 -3
- package/src/standalone/session-service/agent-tree.mjs +4 -3
- package/src/standalone/session-service/session-calls/session-turns.mjs +28 -0
- package/src/standalone/session-service.mjs +19 -0
- package/src/tui/app/slash-commands.mjs +20 -0
- package/src/tui/dist/index.mjs +234 -95
- package/src/tui/session/context-state.mjs +6 -1
- package/src/tui/session/notice-surface.mjs +34 -4
- package/src/tui/session/queue-helpers.mjs +2 -1
- package/src/tui/session/session-api/extensions.mjs +4 -0
- package/src/tui/session/session-api/intake/submission.mjs +5 -0
- package/src/tui/session/session-api/integrations.mjs +8 -0
- package/src/tui/session/session-api/lifecycle/session-reset.mjs +13 -3
- package/src/tui/session/session-api/lifecycle.mjs +17 -1
- package/src/tui/session/session-api/routes.mjs +61 -5
- package/src/tui/session/session-flow/drain.mjs +12 -3
- package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -1
- package/src/tui/session/session-flow/queue/take-entries.mjs +3 -2
- package/src/tui/session/session-flow/steering.mjs +58 -24
- package/src/tui/session/tool-approval.mjs +26 -5
- package/src/tui/session/transcript-intake.mjs +8 -2
- package/src/tui/session/transcript-spill.mjs +5 -1
- package/src/tui/session/tui-steering-persist.mjs +65 -42
- package/src/tui/session/turn-live-call.mjs +64 -0
- package/src/tui/session/turn.mjs +34 -8
- package/src/session-runtime/automation-agents.mjs +0 -94
- package/src/session-runtime/automation-workflow.mjs +0 -59
|
@@ -1,18 +1,33 @@
|
|
|
1
1
|
import { normalizeMcpTransportUrl } from './client-config.mjs';
|
|
2
|
+
import { withAccountParams } from './oauth-account.mjs';
|
|
2
3
|
import { loginFailed, reauthenticationRequired } from './oauth-shared.mjs';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* The SDK's OAuth client provider over one connection's credential `cache`
|
|
6
7
|
* and login `flow` state.
|
|
7
8
|
*/
|
|
8
|
-
export function createOAuthProvider({ cache, flow, lifetimeSignal }) {
|
|
9
|
+
export function createOAuthProvider({ cache, flow, lifetimeSignal, client = null, credentialStore = null }) {
|
|
9
10
|
const { creds, ready, update } = cache;
|
|
10
11
|
// The SDK saves only inside a login, which holds the lock and has just
|
|
11
12
|
// adopted the stored entry.
|
|
12
13
|
const save = async (change) => {
|
|
13
14
|
if (!(await update(change))) throw loginFailed();
|
|
14
15
|
};
|
|
16
|
+
// A pre-registered client (oauth-client.mjs) is the static client
|
|
17
|
+
// information: nothing is registered, and its secret (the user's lives in
|
|
18
|
+
// the keychain) goes with the token requests.
|
|
19
|
+
const staticClient = async () => {
|
|
20
|
+
const secret = client.secretAccount
|
|
21
|
+
? await credentialStore?.getSecretAsync(client.secretAccount)
|
|
22
|
+
: client.clientSecret;
|
|
23
|
+
return { client_id: client.clientId, ...(secret ? { client_secret: secret } : {}) };
|
|
24
|
+
};
|
|
15
25
|
return {
|
|
26
|
+
/** A pre-registered client: a refresh needs no stored registration. */
|
|
27
|
+
preRegistered: Boolean(client),
|
|
28
|
+
// A pre-registered client's provider issues tokens for its own APIs
|
|
29
|
+
// (Google): no RFC 8707 resource indicator is sent.
|
|
30
|
+
...(client ? { validateResourceURL: async () => undefined } : {}),
|
|
16
31
|
get redirectUrl() {
|
|
17
32
|
return creds.redirectUrl;
|
|
18
33
|
},
|
|
@@ -23,11 +38,13 @@ export function createOAuthProvider({ cache, flow, lifetimeSignal }) {
|
|
|
23
38
|
grant_types: ['authorization_code', 'refresh_token'],
|
|
24
39
|
response_types: ['code'],
|
|
25
40
|
token_endpoint_auth_method: 'none',
|
|
41
|
+
...(client?.scopes ? { scope: client.scopes.join(' ') } : {}),
|
|
26
42
|
};
|
|
27
43
|
},
|
|
28
44
|
state: () => flow.state,
|
|
29
45
|
clientInformation: async () => {
|
|
30
46
|
await ready();
|
|
47
|
+
if (client) return staticClient();
|
|
31
48
|
// A connect that cannot open a sign-in never registers a client (the
|
|
32
49
|
// SDK registers one after dropping a rejected registration): the next
|
|
33
50
|
// explicit sign-in registers it.
|
|
@@ -46,6 +63,11 @@ export function createOAuthProvider({ cache, flow, lifetimeSignal }) {
|
|
|
46
63
|
lifetimeSignal.throwIfAborted();
|
|
47
64
|
await save(() => {
|
|
48
65
|
creds.tokens = value;
|
|
66
|
+
// A browser sign-in may be another account: its identity replaces the
|
|
67
|
+
// stored one (null when the server named nobody). A refresh keeps it
|
|
68
|
+
// unless the response names the account again.
|
|
69
|
+
if (flow.browserOpened) creds.identity = flow.identity ?? null;
|
|
70
|
+
else if (flow.identity) creds.identity = flow.identity;
|
|
49
71
|
});
|
|
50
72
|
},
|
|
51
73
|
saveCodeVerifier: (value) => {
|
|
@@ -56,10 +78,11 @@ export function createOAuthProvider({ cache, flow, lifetimeSignal }) {
|
|
|
56
78
|
return flow.verifier;
|
|
57
79
|
},
|
|
58
80
|
discoveryState: () => creds.discovery,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
81
|
+
// Kept in memory and stored with the login's next write (the client
|
|
82
|
+
// registration or the tokens), sparing a keychain write of its own.
|
|
83
|
+
saveDiscoveryState: (value) => {
|
|
84
|
+
creds.discovery = value;
|
|
85
|
+
},
|
|
63
86
|
// The SDK invalidates 'all' when the token endpoint rejects the client
|
|
64
87
|
// (invalid_client / unauthorized_client) and 'tokens' when it rejects the
|
|
65
88
|
// grant (invalid_grant). The registration goes in both cases: an
|
|
@@ -88,8 +111,24 @@ export function createOAuthProvider({ cache, flow, lifetimeSignal }) {
|
|
|
88
111
|
!flow.verifier
|
|
89
112
|
)
|
|
90
113
|
throw loginFailed();
|
|
114
|
+
// A pre-registered client is stored with this login's redirect, as a
|
|
115
|
+
// registration would be: the exchange and later refreshes (and the
|
|
116
|
+
// revocation on 연결 해제) read them from the entry.
|
|
117
|
+
if (client) {
|
|
118
|
+
const issuedTo = await staticClient();
|
|
119
|
+
await save(() => {
|
|
120
|
+
creds.clientInformation = issuedTo;
|
|
121
|
+
});
|
|
122
|
+
}
|
|
91
123
|
flow.browserOpened = true;
|
|
92
|
-
|
|
124
|
+
// A pre-registered client asks for its own scopes (the server's list
|
|
125
|
+
// may name far more) plus its provider's parameters (Google's
|
|
126
|
+
// access_type=offline, without which no refresh token is issued).
|
|
127
|
+
if (client?.scopes) target.searchParams.set('scope', client.scopes.join(' '));
|
|
128
|
+
for (const [key, value] of Object.entries(client?.authParams || {})) target.searchParams.set(key, value);
|
|
129
|
+
// The explicit sign-in's account mode (mcp-oauth-login.mjs) decides the
|
|
130
|
+
// provider's documented account-choice parameter, if any.
|
|
131
|
+
await flow.launchBrowser(withAccountParams(target.href, flow.launchBrowser.accountMode || 'connect').href);
|
|
93
132
|
},
|
|
94
133
|
};
|
|
95
134
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto';
|
|
1
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
2
2
|
import { readFileSync } from 'node:fs';
|
|
3
3
|
import keychain from '../../../../lib/keychain-cjs.cjs';
|
|
4
4
|
import { openInBrowser } from '../../../shared/open-url.mjs';
|
|
@@ -12,8 +12,10 @@ import {
|
|
|
12
12
|
TOKENS_FLAG,
|
|
13
13
|
createCredentialCache,
|
|
14
14
|
credentialFile,
|
|
15
|
+
readIdentityFile,
|
|
15
16
|
readStoredCredentials,
|
|
16
17
|
withCredentialLock,
|
|
18
|
+
writeIdentityFile,
|
|
17
19
|
writeRevisionMarker,
|
|
18
20
|
} from './oauth-credentials.mjs';
|
|
19
21
|
import { createLoginFlow } from './oauth-login.mjs';
|
|
@@ -55,18 +57,198 @@ export function hasStoredMcpOAuthTokens(url) {
|
|
|
55
57
|
}
|
|
56
58
|
}
|
|
57
59
|
|
|
60
|
+
/** Who the stored sign-in of one MCP server URL belongs to, without a keychain
|
|
61
|
+
* read: `{ account, workspace, forcedChoice }` (empty strings when the server
|
|
62
|
+
* named nobody), or null when signed out. */
|
|
63
|
+
export function storedMcpOAuthIdentity(url) {
|
|
64
|
+
return readIdentityFile(mcpOAuthAccount(normalizeMcpTransportUrl(url)));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// RFC 7009 revocation of the stored grant, only where the authorization server
|
|
68
|
+
// advertises its revocation endpoint (RFC 8414 metadata): it revokes the token
|
|
69
|
+
// this client was issued, nothing workspace-wide. True when the server
|
|
70
|
+
// confirmed it.
|
|
71
|
+
async function revokeStoredGrant(saved, fetchImpl) {
|
|
72
|
+
let value;
|
|
73
|
+
try {
|
|
74
|
+
value = JSON.parse(saved);
|
|
75
|
+
} catch {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const endpoint = value?.discovery?.authorizationServerMetadata?.revocation_endpoint;
|
|
79
|
+
const token = value?.tokens?.refresh_token || value?.tokens?.access_token;
|
|
80
|
+
const clientId = value?.clientInformation?.client_id;
|
|
81
|
+
if (typeof endpoint !== 'string' || !/^https:\/\//.test(endpoint) || !token || !clientId) return false;
|
|
82
|
+
const body = new URLSearchParams({
|
|
83
|
+
token,
|
|
84
|
+
token_type_hint: value.tokens.refresh_token ? 'refresh_token' : 'access_token',
|
|
85
|
+
client_id: clientId,
|
|
86
|
+
});
|
|
87
|
+
if (value.clientInformation.client_secret) body.set('client_secret', value.clientInformation.client_secret);
|
|
88
|
+
try {
|
|
89
|
+
const response = await fetchImpl(endpoint, {
|
|
90
|
+
method: 'POST',
|
|
91
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
92
|
+
body,
|
|
93
|
+
redirect: 'error',
|
|
94
|
+
signal: AbortSignal.timeout(5_000),
|
|
95
|
+
});
|
|
96
|
+
return response.ok;
|
|
97
|
+
} catch {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
58
102
|
/** Log out of one MCP server URL: delete its stored tokens and client
|
|
59
103
|
* registration and drop them from live connections, which then need an
|
|
60
|
-
* explicit reconnect to log in again.
|
|
61
|
-
|
|
104
|
+
* explicit reconnect to log in again. With `revoke`, the grant is first
|
|
105
|
+
* revoked at the authorization server where it documents a revocation
|
|
106
|
+
* endpoint. Resolves `{ revoked }`. */
|
|
107
|
+
export async function clearMcpOAuth({ url, credentialStore = keychain, revoke = false, fetchImpl = fetch }) {
|
|
62
108
|
url = normalizeMcpTransportUrl(url);
|
|
63
109
|
const account = mcpOAuthAccount(url);
|
|
110
|
+
let revoked = false;
|
|
64
111
|
await withCredentialLock(account, async () => {
|
|
112
|
+
const saved = await readStoredCredentials(credentialStore, account);
|
|
113
|
+
if (revoke && saved != null) revoked = await revokeStoredGrant(saved, fetchImpl);
|
|
65
114
|
await writeRevisionMarker(account, null);
|
|
66
|
-
if (
|
|
67
|
-
|
|
115
|
+
if (saved != null) await credentialStore.deleteSecretAsync(account);
|
|
116
|
+
await writeIdentityFile(account, null);
|
|
68
117
|
});
|
|
69
118
|
scopes.get(credentialStore)?.get(url)?.oauth.clear();
|
|
119
|
+
return { revoked };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async function storeEntry(account, url, value, credentialStore) {
|
|
123
|
+
const revision = randomBytes(16).toString('hex');
|
|
124
|
+
const { tokens, clientInformation, redirectUrl, discovery, identity } = value;
|
|
125
|
+
await writeRevisionMarker(account, revision, Boolean(tokens));
|
|
126
|
+
await credentialStore.setSecretAsync(
|
|
127
|
+
account,
|
|
128
|
+
JSON.stringify({ url, revision, tokens, clientInformation, redirectUrl, discovery, identity })
|
|
129
|
+
);
|
|
130
|
+
await writeIdentityFile(account, value);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* 계정 바꾸기 for one MCP server URL, transactionally: a browser sign-in with
|
|
135
|
+
* the provider's documented account choice that runs beside the stored
|
|
136
|
+
* sign-in, reusing its client registration and discovery but never its tokens,
|
|
137
|
+
* and stores nothing. `done` resolves the new sign-in (`{ tokens, identity, … }`)
|
|
138
|
+
* or rejects (cancel, denial, timeout), leaving the stored sign-in and every
|
|
139
|
+
* live connection as they were. `answer(pasted)` completes it with a pasted
|
|
140
|
+
* redirect URL (remote sign-in); `cancel()` aborts it.
|
|
141
|
+
*/
|
|
142
|
+
export function startMcpOAuthSwitch({
|
|
143
|
+
url,
|
|
144
|
+
launch,
|
|
145
|
+
serverName,
|
|
146
|
+
credentialStore = keychain,
|
|
147
|
+
fetchImpl = fetch,
|
|
148
|
+
timeoutMs = MCP_OAUTH_TIMEOUT_MS,
|
|
149
|
+
oauthClient = null,
|
|
150
|
+
}) {
|
|
151
|
+
url = normalizeMcpTransportUrl(url);
|
|
152
|
+
const lifetime = new AbortController();
|
|
153
|
+
const creds = {
|
|
154
|
+
tokens: undefined,
|
|
155
|
+
clientInformation: undefined,
|
|
156
|
+
redirectUrl: undefined,
|
|
157
|
+
discovery: undefined,
|
|
158
|
+
identity: undefined,
|
|
159
|
+
// Never null: the in-memory entry always exists.
|
|
160
|
+
observed: 'switch',
|
|
161
|
+
};
|
|
162
|
+
// An in-memory entry: a registration made during the switch stays here
|
|
163
|
+
// until the commit stores it with the tokens.
|
|
164
|
+
const cache = {
|
|
165
|
+
creds,
|
|
166
|
+
held: new Set(),
|
|
167
|
+
ready: async () => {},
|
|
168
|
+
adoptStored: async () => {},
|
|
169
|
+
update: async (change) => {
|
|
170
|
+
change();
|
|
171
|
+
return true;
|
|
172
|
+
},
|
|
173
|
+
withLock: (fn) => fn(),
|
|
174
|
+
};
|
|
175
|
+
const flow = {
|
|
176
|
+
listener: undefined,
|
|
177
|
+
state: undefined,
|
|
178
|
+
verifier: undefined,
|
|
179
|
+
allowBrowser: false,
|
|
180
|
+
browserOpened: false,
|
|
181
|
+
launchBrowser: launch,
|
|
182
|
+
finishCallback: undefined,
|
|
183
|
+
};
|
|
184
|
+
const provider = createOAuthProvider({
|
|
185
|
+
cache,
|
|
186
|
+
flow,
|
|
187
|
+
lifetimeSignal: lifetime.signal,
|
|
188
|
+
client: oauthClient,
|
|
189
|
+
credentialStore,
|
|
190
|
+
});
|
|
191
|
+
const loginFlow = createLoginFlow({
|
|
192
|
+
url,
|
|
193
|
+
cache,
|
|
194
|
+
flow,
|
|
195
|
+
provider,
|
|
196
|
+
lifetimeSignal: lifetime.signal,
|
|
197
|
+
openBrowser: launch,
|
|
198
|
+
fetchImpl,
|
|
199
|
+
timeoutMs,
|
|
200
|
+
});
|
|
201
|
+
const done = (async () => {
|
|
202
|
+
const saved = await readStoredCredentials(credentialStore, mcpOAuthAccount(url));
|
|
203
|
+
if (saved) {
|
|
204
|
+
const value = JSON.parse(saved);
|
|
205
|
+
if (value.url === url) {
|
|
206
|
+
creds.clientInformation = value.clientInformation;
|
|
207
|
+
creds.redirectUrl = value.redirectUrl;
|
|
208
|
+
creds.discovery = value.discovery;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
await loginFlow.login({}, lifetime.signal, true, launch, undefined, serverName);
|
|
212
|
+
const { tokens, clientInformation, redirectUrl, discovery, identity } = creds;
|
|
213
|
+
if (!tokens) throw new Error('MCP OAuth login failed, cancelled, or timed out');
|
|
214
|
+
return { tokens, clientInformation, redirectUrl, discovery, identity: identity ?? null };
|
|
215
|
+
})();
|
|
216
|
+
return {
|
|
217
|
+
done,
|
|
218
|
+
answer(pasted) {
|
|
219
|
+
if (!flow.finishCallback || !flow.browserOpened || !flow.state || !creds.redirectUrl) {
|
|
220
|
+
throw new Error(MCP_OAUTH_CALLBACK_NOT_PENDING);
|
|
221
|
+
}
|
|
222
|
+
const { code } = parsePastedMcpOAuthCallback(pasted, { redirectUrl: creds.redirectUrl, state: flow.state });
|
|
223
|
+
loginFlow.stopListening();
|
|
224
|
+
loginFlow.answerCallback(code);
|
|
225
|
+
},
|
|
226
|
+
cancel() {
|
|
227
|
+
lifetime.abort();
|
|
228
|
+
flow.finishCallback?.();
|
|
229
|
+
loginFlow.closeListener();
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** Store the sign-in a switch returned as the URL's sign-in; resolves a
|
|
235
|
+
* `rollback()` that restores the previous one (or none). Live connections
|
|
236
|
+
* adopt either through the revision marker on their next request. */
|
|
237
|
+
export async function commitMcpOAuthSwitch({ url, signIn, credentialStore = keychain }) {
|
|
238
|
+
url = normalizeMcpTransportUrl(url);
|
|
239
|
+
const account = mcpOAuthAccount(url);
|
|
240
|
+
let previous = null;
|
|
241
|
+
await withCredentialLock(account, async () => {
|
|
242
|
+
previous = await readStoredCredentials(credentialStore, account);
|
|
243
|
+
await storeEntry(account, url, signIn, credentialStore);
|
|
244
|
+
});
|
|
245
|
+
return () =>
|
|
246
|
+
withCredentialLock(account, async () => {
|
|
247
|
+
if (previous) return storeEntry(account, url, JSON.parse(previous), credentialStore);
|
|
248
|
+
await writeRevisionMarker(account, null);
|
|
249
|
+
await credentialStore.deleteSecretAsync(account);
|
|
250
|
+
await writeIdentityFile(account, null);
|
|
251
|
+
});
|
|
70
252
|
}
|
|
71
253
|
|
|
72
254
|
// The keychain is the only durable store. Exact URLs, including query strings,
|
|
@@ -166,6 +348,7 @@ function createSharedOAuth({
|
|
|
166
348
|
openBrowser = openInBrowser,
|
|
167
349
|
fetchImpl = fetch,
|
|
168
350
|
timeoutMs = MCP_OAUTH_TIMEOUT_MS,
|
|
351
|
+
oauthClient = null,
|
|
169
352
|
}) {
|
|
170
353
|
const lifetime = new AbortController();
|
|
171
354
|
const cache = createCredentialCache({ url, credentialStore, account: mcpOAuthAccount(url) });
|
|
@@ -179,7 +362,13 @@ function createSharedOAuth({
|
|
|
179
362
|
launchBrowser: openBrowser,
|
|
180
363
|
finishCallback: undefined,
|
|
181
364
|
};
|
|
182
|
-
const provider = createOAuthProvider({
|
|
365
|
+
const provider = createOAuthProvider({
|
|
366
|
+
cache,
|
|
367
|
+
flow,
|
|
368
|
+
lifetimeSignal: lifetime.signal,
|
|
369
|
+
client: oauthClient,
|
|
370
|
+
credentialStore,
|
|
371
|
+
});
|
|
183
372
|
const { login, stopListening, closeListener, answerCallback } = createLoginFlow({
|
|
184
373
|
url,
|
|
185
374
|
cache,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Which catalog connector each connected MCP server is (connector-catalog.mjs
|
|
2
|
+
// connectorOfServer), recorded by the client as servers connect, so a tool
|
|
3
|
+
// name alone (`mcp__<server>__<tool>`) finds its catalog defaults at dispatch.
|
|
4
|
+
import { connectorOfServer } from '../../../shared/connector-catalog.mjs';
|
|
5
|
+
|
|
6
|
+
const byServer = new Map();
|
|
7
|
+
|
|
8
|
+
export function rememberServerConnector(name, cfg) {
|
|
9
|
+
const id = connectorOfServer(cfg);
|
|
10
|
+
if (id) byServer.set(String(name), id);
|
|
11
|
+
else byServer.delete(String(name));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** The catalog id of connected server `name`, or ''. */
|
|
15
|
+
export function serverConnector(name) {
|
|
16
|
+
return byServer.get(String(name)) || '';
|
|
17
|
+
}
|
|
@@ -10,7 +10,7 @@ import { createNpmVersionSource, maxSemver } from './npm-cli-version.mjs';
|
|
|
10
10
|
// source release just to advance the user-agent version.
|
|
11
11
|
// Claude Opus 5.5 requires 2.1.280 or newer. The release workflow raises this
|
|
12
12
|
// to the published CLI version (scripts/sync-client-version-floors.mjs).
|
|
13
|
-
export const DEFAULT_CLI_VERSION = '2.1.
|
|
13
|
+
export const DEFAULT_CLI_VERSION = '2.1.304';
|
|
14
14
|
export const CLAUDE_CLI_NPM_PACKAGE = '@anthropic-ai/claude-code';
|
|
15
15
|
|
|
16
16
|
const CACHE_SCHEMA_VERSION = 1;
|
|
@@ -209,6 +209,7 @@ export function describeAnthropicOAuthCredentials() {
|
|
|
209
209
|
return {
|
|
210
210
|
...oauthCredentialStatus({ hasRefresh, expiresAt, detail, refreshSkewMs: TOKEN_REFRESH_SKEW_MS }),
|
|
211
211
|
...accountIdentityFields(creds.identity),
|
|
212
|
+
plan: creds.subscriptionType || null,
|
|
212
213
|
};
|
|
213
214
|
} catch (err) {
|
|
214
215
|
return {
|
|
@@ -187,9 +187,14 @@ export function normalizeAntigravityCatalog(rawModels) {
|
|
|
187
187
|
return models.sort((a, b) => a.display.localeCompare(b.display));
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
-
/**
|
|
190
|
+
/**
|
|
191
|
+
* Catalog to resolve wire ids against: in-memory mirror, disk cache, then the
|
|
192
|
+
* curated fallback. Sends never refresh the catalog, so the account's last live
|
|
193
|
+
* list is used even past its TTL: it names the wire ids this account was
|
|
194
|
+
* offered, which the curated list can only approximate.
|
|
195
|
+
*/
|
|
191
196
|
function antigravityCatalogModels() {
|
|
192
|
-
if (!_mirror) _mirror = antigravityModelCache.loadSync();
|
|
197
|
+
if (!_mirror) _mirror = antigravityModelCache.loadSync({ allowStale: true });
|
|
193
198
|
return _mirror || ANTIGRAVITY_MODELS;
|
|
194
199
|
}
|
|
195
200
|
|
|
@@ -218,7 +218,12 @@ async function provisionProject(context, tierId) {
|
|
|
218
218
|
}
|
|
219
219
|
|
|
220
220
|
/** Resolve account eligibility and return the project from a fresh status load. */
|
|
221
|
-
export async function discoverProject(
|
|
221
|
+
export async function discoverProject(accessToken, options = {}) {
|
|
222
|
+
return (await discoverAccount(accessToken, options)).projectId;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** Project plus the account's tier id (paid tier first), from the same status load. */
|
|
226
|
+
export async function discoverAccount(
|
|
222
227
|
accessToken,
|
|
223
228
|
{ fetchFn = fetch, onProgress = null, signal = null, email = '' } = {}
|
|
224
229
|
) {
|
|
@@ -235,7 +240,8 @@ export async function discoverProject(
|
|
|
235
240
|
const refreshed = await loadProjectState(context);
|
|
236
241
|
const projectId = extractProjectId(refreshed);
|
|
237
242
|
if (!projectId) throw new Error('[antigravity-oauth] loadCodeAssist did not return a cloudaicompanionProject');
|
|
238
|
-
|
|
243
|
+
const tierId = refreshed.paidTier?.id || refreshed.currentTier?.id;
|
|
244
|
+
return { projectId, tierId: typeof tierId === 'string' ? tierId : '' };
|
|
239
245
|
}
|
|
240
246
|
|
|
241
247
|
export async function exchangeAuthorizationCode({ code, verifier, fetchFn = fetch, onProgress = null, signal = null }) {
|
|
@@ -267,12 +273,13 @@ export async function exchangeAuthorizationCode({ code, verifier, fetchFn = fetc
|
|
|
267
273
|
throw new Error('[antigravity-oauth] token exchange response missing access_token or refresh_token');
|
|
268
274
|
}
|
|
269
275
|
const { email, userId } = await fetchAccountInfo(json.access_token, { fetchFn, signal });
|
|
270
|
-
const projectId = await
|
|
276
|
+
const { projectId, tierId } = await discoverAccount(json.access_token, { fetchFn, onProgress, signal, email });
|
|
271
277
|
const tokens = {
|
|
272
278
|
access_token: json.access_token,
|
|
273
279
|
refresh_token: json.refresh_token,
|
|
274
280
|
expires_at: typeof json.expires_in === 'number' ? Date.now() + json.expires_in * 1000 : 0,
|
|
275
281
|
project_id: projectId,
|
|
282
|
+
tier_id: tierId,
|
|
276
283
|
email,
|
|
277
284
|
user_id: userId,
|
|
278
285
|
};
|
|
@@ -204,6 +204,7 @@ export function loadTokens() {
|
|
|
204
204
|
refresh_token: String(raw.refresh_token),
|
|
205
205
|
expires_at: _normalizeExpiresAt(raw.expires_at ?? raw.expiresAt),
|
|
206
206
|
project_id: String(raw.project_id || raw.projectId || ''),
|
|
207
|
+
tier_id: String(raw.tier_id || ''),
|
|
207
208
|
email: String(raw.email || ''),
|
|
208
209
|
user_id: String(raw.user_id || raw.userId || ''),
|
|
209
210
|
source: 'own',
|
|
@@ -222,6 +223,7 @@ export function saveTokens(tokens) {
|
|
|
222
223
|
refresh_token: tokens.refresh_token,
|
|
223
224
|
expires_at: tokens.expires_at || 0,
|
|
224
225
|
project_id: tokens.project_id || tokens.projectId || '',
|
|
226
|
+
tier_id: tokens.tier_id || '',
|
|
225
227
|
email: tokens.email || '',
|
|
226
228
|
user_id: tokens.user_id || tokens.userId || '',
|
|
227
229
|
},
|
|
@@ -274,6 +276,7 @@ export function describeAntigravityOAuthCredentials() {
|
|
|
274
276
|
...accountIdentityFields({ id: tokens.user_id, email: tokens.email }),
|
|
275
277
|
email: tokens.email || '',
|
|
276
278
|
projectId: tokens.project_id || '',
|
|
279
|
+
plan: tokens.tier_id || null,
|
|
277
280
|
};
|
|
278
281
|
} catch {
|
|
279
282
|
return credentialsNotSet();
|
|
@@ -340,6 +343,7 @@ export function refreshTokens({ fetchFn = fetch } = {}) {
|
|
|
340
343
|
refresh_token: json.refresh_token || current.refresh_token,
|
|
341
344
|
expires_at: typeof json.expires_in === 'number' ? Date.now() + json.expires_in * 1000 : 0,
|
|
342
345
|
project_id: current.project_id,
|
|
346
|
+
tier_id: current.tier_id,
|
|
343
347
|
email: current.email,
|
|
344
348
|
user_id: current.user_id,
|
|
345
349
|
};
|
|
@@ -31,14 +31,14 @@ export const AUTO_EFFORT_LEVELS = Object.freeze(['easy', 'normal', 'hard', 'very
|
|
|
31
31
|
const STEP_OF_LEVEL = [-1, 0, 1, 2];
|
|
32
32
|
|
|
33
33
|
// The chosen level minimises the expected cost under the judge distribution.
|
|
34
|
-
// A miss costs one per level, plus extra for an opposite call
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
//
|
|
34
|
+
// A miss costs one per level, plus extra for an opposite call. Opposite calls
|
|
35
|
+
// are asymmetric: "easy" for a hard turn degrades the answer, "hard" for an
|
|
36
|
+
// easy turn only costs tokens. On the held-out test splits the heavier
|
|
37
|
+
// under-call cost cut hard-as-easy calls by a third (20 -> 13 of 7,180) for
|
|
38
|
+
// -0.2 points of exact accuracy. "Very hard" carries no extra cost: an extra
|
|
39
|
+
// penalty there let judge v7 pick xhigh on only 17% of very hard turns.
|
|
39
40
|
export const AUTO_EFFORT_UNDER_OPPOSITE_COST = 3;
|
|
40
41
|
export const AUTO_EFFORT_OVER_OPPOSITE_COST = 1;
|
|
41
|
-
export const AUTO_EFFORT_FALSE_VERY_HARD_COST = 1;
|
|
42
42
|
// Ties keep the default first, then the cheaper side.
|
|
43
43
|
const TIE_ORDER = [1, 0, 2, 3];
|
|
44
44
|
|
|
@@ -49,8 +49,7 @@ function expectedCost(values, level) {
|
|
|
49
49
|
p *
|
|
50
50
|
(Math.abs(level - actual) +
|
|
51
51
|
(level === 0 && actual >= 2 ? AUTO_EFFORT_UNDER_OPPOSITE_COST : 0) +
|
|
52
|
-
(actual === 0 && level >= 2 ? AUTO_EFFORT_OVER_OPPOSITE_COST : 0)
|
|
53
|
-
(level === 3 && actual < 3 ? AUTO_EFFORT_FALSE_VERY_HARD_COST : 0));
|
|
52
|
+
(actual === 0 && level >= 2 ? AUTO_EFFORT_OVER_OPPOSITE_COST : 0));
|
|
54
53
|
});
|
|
55
54
|
return cost;
|
|
56
55
|
}
|
|
@@ -4,7 +4,7 @@ import { createRemoteVersionSource } from './npm-cli-version.mjs';
|
|
|
4
4
|
// documented version endpoint; the official installer script embeds the
|
|
5
5
|
// current build (…/lab/<build>/…), parsed best-effort. Any format change or
|
|
6
6
|
// failure falls back to the floor.
|
|
7
|
-
export const CURSOR_CLIENT_VERSION_FLOOR = 'cli-2026.10.
|
|
7
|
+
export const CURSOR_CLIENT_VERSION_FLOOR = 'cli-2026.10.19-6bbf2c4';
|
|
8
8
|
const BUILD_PATTERN = /downloads\.cursor\.com\/lab\/(\d{4}\.\d{2}\.\d{2}-[0-9a-f]{6,40})\//;
|
|
9
9
|
export const CURSOR_INSTALL_URL = 'https://cursor.com/install';
|
|
10
10
|
|
|
@@ -10,6 +10,7 @@ import { mergeFlatSchemaProperty } from './flat-schema-merge.mjs';
|
|
|
10
10
|
import { reportedCostUsd } from './usage-primitives.mjs';
|
|
11
11
|
import { reportInvalidTool, wireInputSchema } from './claude-bridge-schema.mjs';
|
|
12
12
|
import { normalizeServerToolUse } from './anthropic-server-tool-usage.mjs';
|
|
13
|
+
import { ANTHROPIC_TOOL_CALL_IDS, withWireToolCallIds } from './tool-call-wire-ids.mjs';
|
|
13
14
|
export const ANTHROPIC_CACHE_TTL_STABLE = { type: 'ephemeral', ttl: '1h' };
|
|
14
15
|
const ANTHROPIC_CACHE_TTL_VOLATILE = { type: 'ephemeral' };
|
|
15
16
|
|
|
@@ -232,7 +233,8 @@ const ANTHROPIC_NATIVE_PROVIDERS = new Set(['anthropic', 'anthropic-oauth']);
|
|
|
232
233
|
|
|
233
234
|
// `provider`: the engine's provider name. A gateway on a native Messages
|
|
234
235
|
// route (wire-route.mjs) also replays the references it tagged itself.
|
|
235
|
-
export function toAnthropicMessages(
|
|
236
|
+
export function toAnthropicMessages(transcript, availableTools, provider = '') {
|
|
237
|
+
const messages = withWireToolCallIds(transcript, ANTHROPIC_TOOL_CALL_IDS);
|
|
236
238
|
const ownProvider = String(provider || '').toLowerCase();
|
|
237
239
|
const availableNames = anthropicToolNameSet(availableTools);
|
|
238
240
|
const result = [];
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Tool-call ids at the wire. A transcript keeps each tool call's id as the
|
|
2
|
+
// provider that produced it minted it; after a model switch another provider
|
|
3
|
+
// may refuse it (Anthropic accepts only [A-Za-z0-9_-]; OpenAI chat caps the
|
|
4
|
+
// length). Each request builder projects the ids onto its own rule just
|
|
5
|
+
// before lowering: a valid id passes unchanged (so native replay items and
|
|
6
|
+
// the provider's own ids stay byte-exact), an invalid one becomes a
|
|
7
|
+
// deterministic, collision-free stand-in, and a call and its result always
|
|
8
|
+
// map to the same value. Persisted history is never rewritten.
|
|
9
|
+
import { createHash } from 'node:crypto';
|
|
10
|
+
|
|
11
|
+
export const ANTHROPIC_TOOL_CALL_IDS = Object.freeze({ allowed: /^[A-Za-z0-9_-]+$/, maxLength: 64 });
|
|
12
|
+
export const OPENAI_RESPONSES_TOOL_CALL_IDS = Object.freeze({ allowed: /^[A-Za-z0-9_.:-]+$/, maxLength: 64 });
|
|
13
|
+
export const OPENAI_CHAT_TOOL_CALL_IDS = Object.freeze({ allowed: /^[A-Za-z0-9_.:-]+$/, maxLength: 40 });
|
|
14
|
+
|
|
15
|
+
const HASH_CHARS = 10;
|
|
16
|
+
|
|
17
|
+
function standIn(id, rule, salt) {
|
|
18
|
+
const hash = createHash('sha256').update(`${salt}\u0000${id}`).digest('hex').slice(0, HASH_CHARS);
|
|
19
|
+
const stem = String(id)
|
|
20
|
+
.replace(/[^A-Za-z0-9_-]+/g, '_')
|
|
21
|
+
.replace(/^_+|_+$/g, '')
|
|
22
|
+
.slice(0, Math.max(0, rule.maxLength - HASH_CHARS - 1));
|
|
23
|
+
return stem ? `${stem}_${hash}` : `call_${hash}`.slice(0, rule.maxLength);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const isValid = (id, rule) => id.length > 0 && id.length <= rule.maxLength && rule.allowed.test(id);
|
|
27
|
+
|
|
28
|
+
/** id → wire id for every tool call and result in `messages` under `rule`. */
|
|
29
|
+
export function toolCallWireIdMap(messages, rule) {
|
|
30
|
+
const ids = new Set();
|
|
31
|
+
for (const message of Array.isArray(messages) ? messages : []) {
|
|
32
|
+
if (message?.role === 'assistant')
|
|
33
|
+
for (const call of message.toolCalls || []) if (call?.id) ids.add(String(call.id));
|
|
34
|
+
if (message?.role === 'tool' && message.toolCallId) ids.add(String(message.toolCallId));
|
|
35
|
+
}
|
|
36
|
+
const map = new Map();
|
|
37
|
+
const taken = new Set([...ids].filter((id) => isValid(id, rule)));
|
|
38
|
+
for (const id of ids) {
|
|
39
|
+
if (isValid(id, rule)) continue;
|
|
40
|
+
let salt = 0;
|
|
41
|
+
let wire = standIn(id, rule, salt);
|
|
42
|
+
while (taken.has(wire)) wire = standIn(id, rule, ++salt);
|
|
43
|
+
taken.add(wire);
|
|
44
|
+
map.set(id, wire);
|
|
45
|
+
}
|
|
46
|
+
return map;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** `messages` with tool-call ids projected onto `rule`; the same array when none needs it. */
|
|
50
|
+
export function withWireToolCallIds(messages, rule) {
|
|
51
|
+
const map = toolCallWireIdMap(messages, rule);
|
|
52
|
+
if (!map.size) return messages;
|
|
53
|
+
return messages.map((message) => {
|
|
54
|
+
if (message?.role === 'tool' && map.has(String(message.toolCallId))) {
|
|
55
|
+
return { ...message, toolCallId: map.get(String(message.toolCallId)) };
|
|
56
|
+
}
|
|
57
|
+
if (message?.role !== 'assistant' || !message.toolCalls?.some((call) => map.has(String(call?.id)))) return message;
|
|
58
|
+
return {
|
|
59
|
+
...message,
|
|
60
|
+
toolCalls: message.toolCalls.map((call) =>
|
|
61
|
+
map.has(String(call?.id)) ? { ...call, id: map.get(String(call.id)) } : call
|
|
62
|
+
),
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
}
|
|
@@ -104,10 +104,16 @@ export const COMPAT_RETRY_PROFILES = Object.freeze({
|
|
|
104
104
|
}),
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
// A provider without a profile (custom endpoints, gateways, local servers)
|
|
108
|
+
// keeps the shared ladder, but a Retry-After beyond a minute is not waited
|
|
109
|
+
// out: it surfaces with its wait so the account pool can rotate and the
|
|
110
|
+
// notice can name when to try again.
|
|
111
|
+
export const COMPAT_DEFAULT_MAX_RETRY_AFTER_MS = 60_000;
|
|
112
|
+
|
|
113
|
+
/** withRetry options (attempt budget, schedule, jitter) for a provider; only the advice ceiling for the shared defaults. */
|
|
108
114
|
export function compatRetryOptions(providerName) {
|
|
109
115
|
const profile = COMPAT_RETRY_PROFILES[providerName];
|
|
110
|
-
if (!profile) return {};
|
|
116
|
+
if (!profile) return { maxRetryAfterMs: COMPAT_DEFAULT_MAX_RETRY_AFTER_MS };
|
|
111
117
|
return {
|
|
112
118
|
maxAttempts: profile.maxAttempts,
|
|
113
119
|
backoffMs: profile.backoffMs,
|
|
@@ -17,6 +17,11 @@ import {
|
|
|
17
17
|
} from './media-normalization.mjs';
|
|
18
18
|
import { customToolCallFromResponseItem, nativeToolSearchCallFromArguments } from './custom-tool-wire.mjs';
|
|
19
19
|
import { providerReplayItems } from './lib/provider-replay.mjs';
|
|
20
|
+
import {
|
|
21
|
+
OPENAI_CHAT_TOOL_CALL_IDS,
|
|
22
|
+
OPENAI_RESPONSES_TOOL_CALL_IDS,
|
|
23
|
+
withWireToolCallIds,
|
|
24
|
+
} from './lib/tool-call-wire-ids.mjs';
|
|
20
25
|
import { acceptedWireTools } from './lib/claude-bridge-schema.mjs';
|
|
21
26
|
import { ensureResponsesCallOutputs } from './lib/wire-pairing.mjs';
|
|
22
27
|
import { responsesEffortUpdates } from './effort-configuration.mjs';
|
|
@@ -34,7 +39,8 @@ export function resolveCompatMaxOutputTokens(opts = {}) {
|
|
|
34
39
|
);
|
|
35
40
|
}
|
|
36
41
|
|
|
37
|
-
export function toOpenAIMessages(
|
|
42
|
+
export function toOpenAIMessages(transcript, providerName, options = {}) {
|
|
43
|
+
const messages = withWireToolCallIds(transcript, OPENAI_CHAT_TOOL_CALL_IDS);
|
|
38
44
|
// NOTE: chat.completions has no equivalent slot for replaying reasoning
|
|
39
45
|
// encrypted_content the way the Responses API does (no `type:'reasoning'`
|
|
40
46
|
// input item). Whatever reasoningItems may be attached to assistant
|
|
@@ -421,7 +427,8 @@ export function xaiSystemInstructions(messages) {
|
|
|
421
427
|
return instructions || undefined;
|
|
422
428
|
}
|
|
423
429
|
|
|
424
|
-
export function toXaiResponsesInput(
|
|
430
|
+
export function toXaiResponsesInput(transcript, providerState, options = {}) {
|
|
431
|
+
const messages = withWireToolCallIds(transcript, OPENAI_RESPONSES_TOOL_CALL_IDS);
|
|
425
432
|
const includeSystem = options.includeSystem !== false;
|
|
426
433
|
// Generic Responses callers (opencode-go gateway) keep their own state
|
|
427
434
|
// slot and replay tag so a provider switch never replays foreign items.
|