@remodex/rmx 1.0.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/AGENTS_INSTALL.md +91 -0
- package/LICENSE +21 -0
- package/README.md +242 -0
- package/assets/architecture.png +0 -0
- package/assets/banner.png +0 -0
- package/assets/claude-code-models.gif +0 -0
- package/assets/codex-app-picker.png +0 -0
- package/bin/ocx.mjs +584 -0
- package/bin/package-main.mjs +9 -0
- package/gui/dist/assets/index-CZqebSPQ.css +1 -0
- package/gui/dist/assets/index-CkETtt7P.js +71 -0
- package/gui/dist/favicon.png +0 -0
- package/gui/dist/fonts/google-sans-cyrillic.woff2 +0 -0
- package/gui/dist/fonts/google-sans-latin.woff2 +0 -0
- package/gui/dist/icons.svg +24 -0
- package/gui/dist/index.html +25 -0
- package/gui/dist/logo.png +0 -0
- package/gui/dist/provider-icons/alibaba-color.svg +1 -0
- package/gui/dist/provider-icons/antigravity-color.svg +1 -0
- package/gui/dist/provider-icons/claude-color.svg +1 -0
- package/gui/dist/provider-icons/cline-color.svg +16 -0
- package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -0
- package/gui/dist/provider-icons/commandcode-color.svg +1 -0
- package/gui/dist/provider-icons/copilot-color.svg +1 -0
- package/gui/dist/provider-icons/cursor-color.svg +2 -0
- package/gui/dist/provider-icons/deepseek-color.svg +1 -0
- package/gui/dist/provider-icons/discord.svg +1 -0
- package/gui/dist/provider-icons/firepass-color.svg +1 -0
- package/gui/dist/provider-icons/fireworks-color.svg +1 -0
- package/gui/dist/provider-icons/gemini-color.svg +1 -0
- package/gui/dist/provider-icons/github-copilot-color.svg +1 -0
- package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -0
- package/gui/dist/provider-icons/grok.svg +1 -0
- package/gui/dist/provider-icons/groq-color.svg +1 -0
- package/gui/dist/provider-icons/huggingface-color.svg +1 -0
- package/gui/dist/provider-icons/kimi-color.svg +1 -0
- package/gui/dist/provider-icons/kiro-color.svg +15 -0
- package/gui/dist/provider-icons/lm-studio-color.svg +1 -0
- package/gui/dist/provider-icons/mistral-color.svg +1 -0
- package/gui/dist/provider-icons/moonshot-color.svg +1 -0
- package/gui/dist/provider-icons/nvidia-color.svg +1 -0
- package/gui/dist/provider-icons/ollama-color.svg +1 -0
- package/gui/dist/provider-icons/openai.svg +1 -0
- package/gui/dist/provider-icons/opencode.svg +2 -0
- package/gui/dist/provider-icons/openrouter-color.svg +1 -0
- package/gui/dist/provider-icons/pi.svg +21 -0
- package/gui/dist/provider-icons/qianfan-color.svg +1 -0
- package/gui/dist/provider-icons/qwen-portal-color.svg +1 -0
- package/gui/dist/provider-icons/telegram.svg +1 -0
- package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -0
- package/gui/dist/provider-icons/vllm-color.svg +1 -0
- package/gui/dist/provider-icons/xiaomi-color.svg +1 -0
- package/package.json +118 -0
- package/src/AGENTS.md +28 -0
- package/src/adapters/anthropic-image-guard.ts +251 -0
- package/src/adapters/anthropic-image-normalize.ts +518 -0
- package/src/adapters/anthropic.ts +1205 -0
- package/src/adapters/azure.ts +36 -0
- package/src/adapters/base.ts +83 -0
- package/src/adapters/client-fingerprint.ts +59 -0
- package/src/adapters/command-code.ts +453 -0
- package/src/adapters/cursor/arg-codec.ts +38 -0
- package/src/adapters/cursor/arg-normalize.ts +104 -0
- package/src/adapters/cursor/cursor-errors.ts +165 -0
- package/src/adapters/cursor/discovery.ts +276 -0
- package/src/adapters/cursor/effort-map.ts +139 -0
- package/src/adapters/cursor/exec-policy.ts +88 -0
- package/src/adapters/cursor/framing.ts +250 -0
- package/src/adapters/cursor/gen/agent_pb.ts +15274 -0
- package/src/adapters/cursor/kv-store.ts +52 -0
- package/src/adapters/cursor/live-models.ts +153 -0
- package/src/adapters/cursor/live-smoke-gate.ts +41 -0
- package/src/adapters/cursor/live-transport.ts +1235 -0
- package/src/adapters/cursor/mcp-config.ts +42 -0
- package/src/adapters/cursor/mcp-manager.ts +333 -0
- package/src/adapters/cursor/message-mapper.ts +49 -0
- package/src/adapters/cursor/native-exec-common.ts +59 -0
- package/src/adapters/cursor/native-exec-desktop.ts +184 -0
- package/src/adapters/cursor/native-exec-fs.ts +332 -0
- package/src/adapters/cursor/native-exec-mcp.ts +153 -0
- package/src/adapters/cursor/native-exec-network.ts +43 -0
- package/src/adapters/cursor/native-exec-shell.ts +548 -0
- package/src/adapters/cursor/native-exec-tools.ts +118 -0
- package/src/adapters/cursor/native-exec.ts +604 -0
- package/src/adapters/cursor/protobuf-events.ts +735 -0
- package/src/adapters/cursor/protobuf-request.ts +719 -0
- package/src/adapters/cursor/request-builder.ts +280 -0
- package/src/adapters/cursor/thread-continuity.ts +67 -0
- package/src/adapters/cursor/tool-definitions.ts +621 -0
- package/src/adapters/cursor/transport-retry.ts +132 -0
- package/src/adapters/cursor/transport.ts +57 -0
- package/src/adapters/cursor/types.ts +59 -0
- package/src/adapters/cursor.ts +196 -0
- package/src/adapters/google-antigravity-replay.ts +520 -0
- package/src/adapters/google-antigravity-wire.ts +140 -0
- package/src/adapters/google-errors.ts +85 -0
- package/src/adapters/google-http.ts +100 -0
- package/src/adapters/google-tool-schema.ts +173 -0
- package/src/adapters/google-truncation.ts +24 -0
- package/src/adapters/google-wire-compiler.ts +232 -0
- package/src/adapters/google.ts +859 -0
- package/src/adapters/identity.ts +77 -0
- package/src/adapters/image.ts +23 -0
- package/src/adapters/kiro-constants.ts +16 -0
- package/src/adapters/kiro-errors.ts +208 -0
- package/src/adapters/kiro-events.ts +197 -0
- package/src/adapters/kiro-images.ts +129 -0
- package/src/adapters/kiro-retry.ts +312 -0
- package/src/adapters/kiro-thinking.ts +104 -0
- package/src/adapters/kiro-tool-fallback.ts +36 -0
- package/src/adapters/kiro-tools.ts +224 -0
- package/src/adapters/kiro-truncation.ts +33 -0
- package/src/adapters/kiro-wire.ts +129 -0
- package/src/adapters/kiro.ts +1924 -0
- package/src/adapters/mimo-free.ts +263 -0
- package/src/adapters/openai-chat.ts +1265 -0
- package/src/adapters/openai-responses.ts +1309 -0
- package/src/adapters/run-turn-queue.ts +114 -0
- package/src/adapters/tool-catalog-nudge.ts +71 -0
- package/src/adapters/upstream-http-error.ts +48 -0
- package/src/android-remote/assets.ts +218 -0
- package/src/android-remote/attachments.ts +168 -0
- package/src/android-remote/auth.ts +237 -0
- package/src/android-remote/cloudflare-provisioning.ts +409 -0
- package/src/android-remote/cloudflare-secret.ts +106 -0
- package/src/android-remote/cloudflare-tunnel.ts +488 -0
- package/src/android-remote/cloudflared.ts +286 -0
- package/src/android-remote/codex-app-server.ts +565 -0
- package/src/android-remote/desktop-history-page.ts +936 -0
- package/src/android-remote/desktop-ipc.ts +3643 -0
- package/src/android-remote/desktop-ownership-store.ts +98 -0
- package/src/android-remote/desktop-project-registration.ts +129 -0
- package/src/android-remote/desktop-session-stream.ts +1110 -0
- package/src/android-remote/desktop-workspace-state.ts +443 -0
- package/src/android-remote/file-change-parser.ts +112 -0
- package/src/android-remote/gateway.ts +9108 -0
- package/src/android-remote/mutation-store.ts +299 -0
- package/src/android-remote/projection.ts +1780 -0
- package/src/android-remote/queued-turn-store.ts +248 -0
- package/src/android-remote/session-command-recovery.ts +1384 -0
- package/src/android-remote/store.ts +466 -0
- package/src/android-remote/thread-reconciliation.ts +133 -0
- package/src/android-remote/thread-source-paths.ts +307 -0
- package/src/android-remote/thread-stream.ts +546 -0
- package/src/android-remote/turn-activity.ts +235 -0
- package/src/android-remote/user-message-identity.ts +94 -0
- package/src/bridge.ts +1793 -0
- package/src/chat/inbound.ts +295 -0
- package/src/chat/outbound.ts +821 -0
- package/src/claude/agents-inject.ts +267 -0
- package/src/claude/alias.ts +149 -0
- package/src/claude/auth-detect.ts +229 -0
- package/src/claude/auth-mode-migration.ts +32 -0
- package/src/claude/auth-mode.ts +62 -0
- package/src/claude/context-windows.ts +189 -0
- package/src/claude/desktop-3p-guard.ts +35 -0
- package/src/claude/desktop-3p-paths.ts +84 -0
- package/src/claude/desktop-3p.ts +601 -0
- package/src/claude/desktop-health.ts +26 -0
- package/src/claude/desktop-profile.ts +263 -0
- package/src/claude/gateway-cache.ts +70 -0
- package/src/claude/inbound-debug.ts +163 -0
- package/src/claude/inbound.ts +519 -0
- package/src/claude/model-info.ts +154 -0
- package/src/claude/outbound.ts +898 -0
- package/src/cli/access.ts +108 -0
- package/src/cli/account-api.ts +296 -0
- package/src/cli/account-auth.ts +250 -0
- package/src/cli/account-catalog-refresh.ts +14 -0
- package/src/cli/account-extended.ts +476 -0
- package/src/cli/account-main.ts +317 -0
- package/src/cli/account.ts +297 -0
- package/src/cli/agent-driven.ts +70 -0
- package/src/cli/agent.ts +184 -0
- package/src/cli/catalog-prewarm.ts +27 -0
- package/src/cli/claude-desktop.ts +211 -0
- package/src/cli/claude.ts +302 -0
- package/src/cli/codex-shim-autorestore.ts +45 -0
- package/src/cli/codex-shim-readiness.ts +69 -0
- package/src/cli/combo.ts +124 -0
- package/src/cli/config-command.ts +183 -0
- package/src/cli/debug.ts +228 -0
- package/src/cli/desktop-first-run.ts +25 -0
- package/src/cli/doctor.ts +1022 -0
- package/src/cli/export-command.ts +201 -0
- package/src/cli/help.ts +370 -0
- package/src/cli/index.ts +1565 -0
- package/src/cli/init.ts +224 -0
- package/src/cli/integrations.ts +225 -0
- package/src/cli/interactive-confirm.ts +133 -0
- package/src/cli/internal-dispatch.ts +35 -0
- package/src/cli/launcher-context.ts +77 -0
- package/src/cli/models-runtime.ts +224 -0
- package/src/cli/models.ts +340 -0
- package/src/cli/observe.ts +170 -0
- package/src/cli/opencode.ts +587 -0
- package/src/cli/provider-runtime.ts +179 -0
- package/src/cli/provider.ts +476 -0
- package/src/cli/ready.ts +301 -0
- package/src/cli/route-policy.ts +92 -0
- package/src/cli/runtime-api.ts +328 -0
- package/src/cli/star-prompt.ts +211 -0
- package/src/cli/status-oauth.ts +78 -0
- package/src/cli/status.ts +321 -0
- package/src/cli/system-command.ts +196 -0
- package/src/cli/system-restart-client.ts +146 -0
- package/src/cli/tray-proxy.ts +205 -0
- package/src/cli/v2.ts +200 -0
- package/src/cli.ts +10 -0
- package/src/clients/config-export.ts +1109 -0
- package/src/codex/account-id.ts +34 -0
- package/src/codex/account-label.ts +34 -0
- package/src/codex/account-lifecycle.ts +172 -0
- package/src/codex/account-namespace-match.ts +63 -0
- package/src/codex/account-namespaces.ts +195 -0
- package/src/codex/account-pause.ts +20 -0
- package/src/codex/account-priority.ts +83 -0
- package/src/codex/account-runtime-state.ts +31 -0
- package/src/codex/account-store.ts +517 -0
- package/src/codex/account-usability.ts +40 -0
- package/src/codex/admission.ts +263 -0
- package/src/codex/app-server-processes.ts +799 -0
- package/src/codex/auth-api.ts +2098 -0
- package/src/codex/auth-collision.ts +107 -0
- package/src/codex/auth-context.ts +480 -0
- package/src/codex/autostart-health.ts +156 -0
- package/src/codex/catalog/account-models.ts +67 -0
- package/src/codex/catalog/aggregation.ts +471 -0
- package/src/codex/catalog/bundled.ts +533 -0
- package/src/codex/catalog/effort.ts +432 -0
- package/src/codex/catalog/filesystem-evidence.ts +302 -0
- package/src/codex/catalog/kinds.ts +2 -0
- package/src/codex/catalog/metadata.ts +287 -0
- package/src/codex/catalog/native-models.ts +7 -0
- package/src/codex/catalog/parsing.ts +503 -0
- package/src/codex/catalog/provider-fetch.ts +2267 -0
- package/src/codex/catalog/sync.ts +1606 -0
- package/src/codex/catalog-admission.ts +197 -0
- package/src/codex/catalog-refresh-status.ts +87 -0
- package/src/codex/catalog-write-serialization.ts +242 -0
- package/src/codex/catalog.ts +15 -0
- package/src/codex/codex-write-lock.ts +384 -0
- package/src/codex/convergence-types.ts +593 -0
- package/src/codex/convergence.ts +580 -0
- package/src/codex/custom-model-catalog-migration.ts +176 -0
- package/src/codex/data/upstream-models.json +830 -0
- package/src/codex/desired-state.ts +230 -0
- package/src/codex/desktop-client-processes.ts +521 -0
- package/src/codex/exec-invocation.ts +22 -0
- package/src/codex/features.ts +1091 -0
- package/src/codex/generation.ts +202 -0
- package/src/codex/history-job.ts +347 -0
- package/src/codex/history-lock.ts +242 -0
- package/src/codex/history-migration-guardian.ts +115 -0
- package/src/codex/history-provider.ts +1075 -0
- package/src/codex/history-transition.ts +105 -0
- package/src/codex/history-worker.ts +204 -0
- package/src/codex/home.ts +206 -0
- package/src/codex/inject-coordination.ts +257 -0
- package/src/codex/inject.ts +1857 -0
- package/src/codex/injected-marker.ts +79 -0
- package/src/codex/integration-record.ts +266 -0
- package/src/codex/internal/catalog-writer.ts +203 -0
- package/src/codex/internal/history-writer.ts +105 -0
- package/src/codex/journal.ts +172 -0
- package/src/codex/main-account-cache.ts +56 -0
- package/src/codex/main-account.ts +40 -0
- package/src/codex/management-convergence.ts +114 -0
- package/src/codex/model-cache.ts +267 -0
- package/src/codex/native-main-admission.ts +47 -0
- package/src/codex/native-main-auth-temp.ts +187 -0
- package/src/codex/native-main-claim.ts +167 -0
- package/src/codex/native-main-lock-file.ts +162 -0
- package/src/codex/native-main-owner.ts +329 -0
- package/src/codex/native-profile-api.ts +247 -0
- package/src/codex/native-profile-manager.ts +1531 -0
- package/src/codex/native-profile-processes.ts +121 -0
- package/src/codex/native-profile-recovery.ts +99 -0
- package/src/codex/native-profile-stage-store.ts +387 -0
- package/src/codex/native-profile-startup.ts +348 -0
- package/src/codex/native-profile-store.ts +855 -0
- package/src/codex/native-profile-types.ts +120 -0
- package/src/codex/native-residue.ts +691 -0
- package/src/codex/paths.ts +78 -0
- package/src/codex/plugins-doctor.ts +242 -0
- package/src/codex/pool-rotation.ts +295 -0
- package/src/codex/project-config-warnings.ts +426 -0
- package/src/codex/prompt-journal.ts +311 -0
- package/src/codex/prompt-layers.ts +967 -0
- package/src/codex/prompt-lock.ts +143 -0
- package/src/codex/provider-adoption.ts +242 -0
- package/src/codex/quota-rejection.ts +224 -0
- package/src/codex/quota.ts +494 -0
- package/src/codex/refresh.ts +60 -0
- package/src/codex/routing.ts +1855 -0
- package/src/codex/runtime.ts +659 -0
- package/src/codex/shim.ts +1215 -0
- package/src/codex/subagent-defaults.ts +557 -0
- package/src/codex/subagent-model-fallback.ts +560 -0
- package/src/codex/sync.ts +238 -0
- package/src/codex/transition-state.ts +612 -0
- package/src/codex/upstream-host-health.ts +368 -0
- package/src/codex/user-identity.ts +374 -0
- package/src/codex/warmup.ts +192 -0
- package/src/codex/websocket-registry.ts +100 -0
- package/src/codex/write-coordination.ts +114 -0
- package/src/combos/failover.ts +140 -0
- package/src/combos/index.ts +44 -0
- package/src/combos/request.ts +64 -0
- package/src/combos/resolve.ts +232 -0
- package/src/combos/types.ts +392 -0
- package/src/config.ts +3270 -0
- package/src/generated/model-metadata.ts +144 -0
- package/src/github/star-state.ts +203 -0
- package/src/grok/inject.ts +540 -0
- package/src/grok/inspect.ts +45 -0
- package/src/grok/status.ts +127 -0
- package/src/grok/sync.ts +66 -0
- package/src/images/artifacts.ts +516 -0
- package/src/images/fulfill-video.ts +163 -0
- package/src/images/fulfill.ts +149 -0
- package/src/images/index.ts +4 -0
- package/src/images/loop.ts +922 -0
- package/src/images/plan.ts +133 -0
- package/src/images/synthetic-tool.ts +133 -0
- package/src/images/types.ts +41 -0
- package/src/images/xai-client.ts +141 -0
- package/src/images/xai-video-client.ts +163 -0
- package/src/index.ts +22 -0
- package/src/integrations/config-io.ts +151 -0
- package/src/integrations/journal.ts +315 -0
- package/src/integrations/merge.ts +135 -0
- package/src/integrations/native/ownership-preflight.ts +202 -0
- package/src/integrations/ownership.ts +111 -0
- package/src/integrations/registry.ts +108 -0
- package/src/integrations/serialize.ts +235 -0
- package/src/integrations/state.ts +290 -0
- package/src/integrations/store.ts +103 -0
- package/src/integrations/writer.ts +492 -0
- package/src/lib/abort.ts +146 -0
- package/src/lib/admin-secrets.ts +25 -0
- package/src/lib/admission.ts +83 -0
- package/src/lib/app-owned-memory-stores.ts +173 -0
- package/src/lib/app-owned-memory.ts +265 -0
- package/src/lib/bounded-body.ts +242 -0
- package/src/lib/bun-binary-validator.d.mts +3 -0
- package/src/lib/bun-binary-validator.mjs +18 -0
- package/src/lib/bun-runtime.ts +184 -0
- package/src/lib/bun-stream-caps.ts +127 -0
- package/src/lib/config-ownership.ts +438 -0
- package/src/lib/crash-guard.ts +344 -0
- package/src/lib/debug-log-buffer.ts +83 -0
- package/src/lib/debug-settings.ts +108 -0
- package/src/lib/debug.ts +31 -0
- package/src/lib/destination-policy.ts +316 -0
- package/src/lib/errors.ts +364 -0
- package/src/lib/eventstream-decoder.ts +253 -0
- package/src/lib/gcp-adc.ts +341 -0
- package/src/lib/injection-debug-log.ts +58 -0
- package/src/lib/local-management-attestation.ts +51 -0
- package/src/lib/open-url.ts +25 -0
- package/src/lib/pinned-http.ts +182 -0
- package/src/lib/privacy.ts +20 -0
- package/src/lib/process-control.ts +168 -0
- package/src/lib/provider-environment.ts +470 -0
- package/src/lib/provider-outbound.ts +203 -0
- package/src/lib/provider-url.ts +14 -0
- package/src/lib/proxy-env.ts +18 -0
- package/src/lib/redact.ts +510 -0
- package/src/lib/remodex-home.ts +616 -0
- package/src/lib/retry-after.ts +55 -0
- package/src/lib/service-secrets.ts +178 -0
- package/src/lib/shadow-call.ts +54 -0
- package/src/lib/sidecar-tracker.ts +52 -0
- package/src/lib/sse-decoder.ts +364 -0
- package/src/lib/state-store-registrations.ts +109 -0
- package/src/lib/state-store-sweeper.ts +184 -0
- package/src/lib/system-restart-contract.ts +73 -0
- package/src/lib/test-home-guard.ts +98 -0
- package/src/lib/token-estimate.ts +69 -0
- package/src/lib/translator-budget.ts +366 -0
- package/src/lib/upstream-reachability.ts +91 -0
- package/src/lib/upstream-retry.ts +508 -0
- package/src/lib/win-exec.ts +115 -0
- package/src/lib/win-paths.ts +68 -0
- package/src/lib/windows-elevation.ts +705 -0
- package/src/lib/windows-secret-acl.ts +817 -0
- package/src/lib/windows-user-principal.ts +283 -0
- package/src/lib/winsw.ts +402 -0
- package/src/model-sources.ts +73 -0
- package/src/oauth/anthropic-routing.ts +594 -0
- package/src/oauth/anthropic.ts +177 -0
- package/src/oauth/callback-server.ts +294 -0
- package/src/oauth/chatgpt.ts +150 -0
- package/src/oauth/command-code.ts +239 -0
- package/src/oauth/cursor.ts +231 -0
- package/src/oauth/github-copilot.ts +428 -0
- package/src/oauth/google-antigravity.ts +230 -0
- package/src/oauth/health.ts +443 -0
- package/src/oauth/index.ts +1280 -0
- package/src/oauth/key-providers.ts +128 -0
- package/src/oauth/kimi.ts +213 -0
- package/src/oauth/kiro-credentials.ts +726 -0
- package/src/oauth/kiro.ts +621 -0
- package/src/oauth/local-token-detect.ts +121 -0
- package/src/oauth/log.ts +48 -0
- package/src/oauth/login-cli.ts +163 -0
- package/src/oauth/pkce.ts +15 -0
- package/src/oauth/store.ts +655 -0
- package/src/oauth/token-guardian.ts +309 -0
- package/src/oauth/types.ts +62 -0
- package/src/oauth/xai.ts +241 -0
- package/src/providers/alibaba-region-backup.ts +75 -0
- package/src/providers/alibaba-region-migration.ts +156 -0
- package/src/providers/alibaba-region-startup.ts +36 -0
- package/src/providers/antigravity-models.ts +317 -0
- package/src/providers/api-keys.ts +140 -0
- package/src/providers/base-url-choices.ts +64 -0
- package/src/providers/codex-capacity.ts +288 -0
- package/src/providers/command-code-efforts.ts +85 -0
- package/src/providers/context-cap.ts +73 -0
- package/src/providers/derive.ts +451 -0
- package/src/providers/free-directory.ts +187 -0
- package/src/providers/github-copilot-transport.ts +56 -0
- package/src/providers/google-vertex-location.ts +14 -0
- package/src/providers/key-failover.ts +271 -0
- package/src/providers/kiro-models.ts +67 -0
- package/src/providers/label.ts +19 -0
- package/src/providers/model-discovery-limits.ts +16 -0
- package/src/providers/model-discovery.ts +361 -0
- package/src/providers/openai-sidecar.ts +235 -0
- package/src/providers/openai-tier-startup.ts +27 -0
- package/src/providers/openai-tiers.ts +301 -0
- package/src/providers/openai-virtual-models.ts +83 -0
- package/src/providers/openrouter-routing.ts +102 -0
- package/src/providers/provider-id-rewrite.ts +179 -0
- package/src/providers/quota.ts +1942 -0
- package/src/providers/reasoning-capabilities.ts +336 -0
- package/src/providers/registry.ts +2375 -0
- package/src/providers/slug-codec.ts +74 -0
- package/src/providers/xai-transport.ts +149 -0
- package/src/reasoning-effort.ts +243 -0
- package/src/responses/compaction.ts +124 -0
- package/src/responses/hosted-tool-policy.ts +9 -0
- package/src/responses/parser.ts +714 -0
- package/src/responses/reasoning-envelope.ts +60 -0
- package/src/responses/reasoning-replay-cache.ts +106 -0
- package/src/responses/schema.ts +159 -0
- package/src/responses/spill-store.ts +431 -0
- package/src/responses/state.ts +1039 -0
- package/src/responses/tool-groups.ts +19 -0
- package/src/router.ts +802 -0
- package/src/routing/analytics.ts +377 -0
- package/src/routing/capability.ts +205 -0
- package/src/routing/cost.ts +77 -0
- package/src/routing/evaluator.ts +444 -0
- package/src/routing/health.ts +401 -0
- package/src/routing/history/cursor.ts +43 -0
- package/src/routing/history/indexer.ts +605 -0
- package/src/routing/history/schema.ts +72 -0
- package/src/routing/profile-namespace.ts +15 -0
- package/src/routing/profile.ts +424 -0
- package/src/routing/quota.ts +145 -0
- package/src/routing/request-evidence.ts +45 -0
- package/src/routing/trace.ts +686 -0
- package/src/server/adapter-resolve.ts +83 -0
- package/src/server/auth-cors.ts +606 -0
- package/src/server/chat-completions.ts +379 -0
- package/src/server/claude-messages.ts +980 -0
- package/src/server/effort-policy.ts +251 -0
- package/src/server/github-copilot-responses-repair.ts +338 -0
- package/src/server/gui-static.ts +152 -0
- package/src/server/image-retry.ts +42 -0
- package/src/server/images.ts +485 -0
- package/src/server/index.ts +1633 -0
- package/src/server/lifecycle.ts +482 -0
- package/src/server/live.ts +609 -0
- package/src/server/management/agent-settings-routes.ts +1180 -0
- package/src/server/management/android-remote-routes.ts +390 -0
- package/src/server/management/api-access.ts +141 -0
- package/src/server/management/api-key-usage.ts +167 -0
- package/src/server/management/body.ts +35 -0
- package/src/server/management/combo-routes.ts +244 -0
- package/src/server/management/config-routes.ts +602 -0
- package/src/server/management/context.ts +88 -0
- package/src/server/management/integration-routes.ts +538 -0
- package/src/server/management/logs-usage-routes.ts +516 -0
- package/src/server/management/model-routes.ts +519 -0
- package/src/server/management/model-rows.ts +143 -0
- package/src/server/management/native-integration-routes.ts +781 -0
- package/src/server/management/oauth-account-routes.ts +573 -0
- package/src/server/management/provider-routes.ts +781 -0
- package/src/server/management/request-history-routes.ts +191 -0
- package/src/server/management/routing-analytics-routes.ts +74 -0
- package/src/server/management/routing-profile-routes.ts +384 -0
- package/src/server/management/shared.ts +277 -0
- package/src/server/management/sidebar-routes.ts +106 -0
- package/src/server/management/sync-response.ts +69 -0
- package/src/server/management/system-restart.ts +433 -0
- package/src/server/management/system-routes.ts +141 -0
- package/src/server/management/usage-summary-cache.ts +86 -0
- package/src/server/management-api.ts +269 -0
- package/src/server/management-auth.ts +353 -0
- package/src/server/memory-watchdog.ts +156 -0
- package/src/server/port-reclaim.ts +307 -0
- package/src/server/ports.ts +156 -0
- package/src/server/proxy-liveness.ts +326 -0
- package/src/server/proxy-stop.ts +92 -0
- package/src/server/readiness.ts +99 -0
- package/src/server/relay-eager.ts +353 -0
- package/src/server/relay.ts +1179 -0
- package/src/server/request-decompress.ts +132 -0
- package/src/server/request-log-conversation.ts +168 -0
- package/src/server/request-log.ts +1072 -0
- package/src/server/responses/collaboration.ts +409 -0
- package/src/server/responses/compact.ts +710 -0
- package/src/server/responses/core.ts +3561 -0
- package/src/server/responses/encrypted-payload.ts +308 -0
- package/src/server/responses/fetch-helpers.ts +171 -0
- package/src/server/responses/passthrough-error.ts +78 -0
- package/src/server/responses/policy-fallback.ts +152 -0
- package/src/server/responses/terminal-guard.ts +230 -0
- package/src/server/responses/upstream-error.ts +48 -0
- package/src/server/responses-image-gen-repair.ts +132 -0
- package/src/server/responses-item-id-repair.ts +272 -0
- package/src/server/responses-json-events.ts +52 -0
- package/src/server/responses-model-rewrite.ts +29 -0
- package/src/server/responses-snapshot-repair.ts +621 -0
- package/src/server/responses.ts +10 -0
- package/src/server/search.ts +181 -0
- package/src/server/sse-frame-buffer.ts +292 -0
- package/src/server/sse-payload-rewrite.ts +263 -0
- package/src/server/startup-action-control.ts +308 -0
- package/src/server/startup-health-cache.ts +119 -0
- package/src/server/system-env.ts +418 -0
- package/src/server/windows-tcp-drop.ts +184 -0
- package/src/server/windows-tray-control.ts +41 -0
- package/src/server/ws-bridge.ts +470 -0
- package/src/service-manager-probe.ts +824 -0
- package/src/service.ts +3011 -0
- package/src/stall-timeout.ts +20 -0
- package/src/storage/cleanup-job.ts +57 -0
- package/src/storage/cleanup.ts +3085 -0
- package/src/storage/policy-job.ts +457 -0
- package/src/storage/policy-scheduler.ts +40 -0
- package/src/storage/policy-worker.ts +59 -0
- package/src/storage/policy.ts +527 -0
- package/src/storage/restore-job.ts +299 -0
- package/src/storage/restore-worker.ts +58 -0
- package/src/storage/scanner.ts +238 -0
- package/src/storage/storage-mutation-coordinator.ts +139 -0
- package/src/storage/worker-lifecycle.ts +215 -0
- package/src/tray/assets/opencodex-tray-offline.ico +0 -0
- package/src/tray/assets/opencodex-tray-online.ico +0 -0
- package/src/tray/assets/opencodex-tray-warning.ico +0 -0
- package/src/tray/assets/opencodex-tray.png +0 -0
- package/src/tray/windows-tray.ps1 +364 -0
- package/src/tray/windows.ts +738 -0
- package/src/types.ts +1531 -0
- package/src/update/badge.ts +72 -0
- package/src/update/desktop-release.ts +1620 -0
- package/src/update/index.ts +402 -0
- package/src/update/job.ts +1906 -0
- package/src/update/notify.ts +261 -0
- package/src/update/npm-cache-preflight.d.mts +47 -0
- package/src/update/npm-cache-preflight.mjs +201 -0
- package/src/update/npm-invocation.d.mts +23 -0
- package/src/update/npm-invocation.mjs +94 -0
- package/src/update/tray-update-plan.d.mts +18 -0
- package/src/update/tray-update-plan.mjs +38 -0
- package/src/usage/cost.ts +0 -0
- package/src/usage/debug.ts +97 -0
- package/src/usage/expected-prices.ts +283 -0
- package/src/usage/log.ts +695 -0
- package/src/usage/summary.ts +585 -0
- package/src/usage/totals.ts +14 -0
- package/src/vision/anthropic-describe.ts +185 -0
- package/src/vision/describe.ts +127 -0
- package/src/vision/index.ts +558 -0
- package/src/vision/reasoning.ts +55 -0
- package/src/web-search/anthropic-executor.ts +189 -0
- package/src/web-search/executor.ts +105 -0
- package/src/web-search/format-result.ts +89 -0
- package/src/web-search/index.ts +196 -0
- package/src/web-search/loop.ts +791 -0
- package/src/web-search/parse.ts +235 -0
- package/src/web-search/progress-stream.ts +342 -0
- package/src/web-search/synthetic-tool.ts +47 -0
|
@@ -0,0 +1,621 @@
|
|
|
1
|
+
import { create, fromJson, toBinary, type JsonValue } from "@bufbuild/protobuf";
|
|
2
|
+
import { ValueSchema } from "@bufbuild/protobuf/wkt";
|
|
3
|
+
import type { OcxRequestOptions, OcxTool } from "../../types";
|
|
4
|
+
import { namespacedToolName, toolChoiceAliases } from "../../types";
|
|
5
|
+
import { McpToolDefinitionSchema, McpToolsSchema, type McpToolDefinition } from "./gen/agent_pb";
|
|
6
|
+
|
|
7
|
+
export const OCX_RESPONSES_TOOL_PROVIDER = "opencodex-responses";
|
|
8
|
+
export const CODEX_EXEC_COMMAND_TOOL = "exec_command";
|
|
9
|
+
export const CODEX_SHELL_COMMAND_TOOL = "shell_command";
|
|
10
|
+
export const CODEX_APPLY_PATCH_TOOL = "apply_patch";
|
|
11
|
+
export const CURSOR_EDIT_FILE_TOOL = "edit_file";
|
|
12
|
+
export const CURSOR_MULTI_EDIT_TOOL = "multi_edit";
|
|
13
|
+
export const CURSOR_STRUCTURED_EDIT_TOOLS = [CURSOR_EDIT_FILE_TOOL, CURSOR_MULTI_EDIT_TOOL] as const;
|
|
14
|
+
export const CURSOR_EXEC_COMMAND_TOOL = CODEX_EXEC_COMMAND_TOOL;
|
|
15
|
+
export const CODEX_SHELL_BRIDGE_TOOL_NAMES = [CODEX_EXEC_COMMAND_TOOL, CODEX_SHELL_COMMAND_TOOL] as const;
|
|
16
|
+
export const CURSOR_SHELL_ALIAS_SYSTEM_NOTE =
|
|
17
|
+
'Shell commands use the Codex shell bridge tool shown in this turn\'s catalog (`shell_command` or `exec_command`) with JSON arguments like {"cmd":"..."}. The long `mcp_opencodex-responses_*` display name is the same tool. Prefer it over Cursor-native Shell; never say native shell is blocked.';
|
|
18
|
+
const NEIGHBOR_AGENT_TOOL_NAMES = ["Read", "Grep", "Glob", "Bash", "LS"] as const;
|
|
19
|
+
|
|
20
|
+
export const CURSOR_GENERIC_TOOL_USE_USER_HINT = [
|
|
21
|
+
"For generic tool-use/count demos, satisfy the request with repeated Codex shell bridge calls (`shell_command` or `exec_command`) for harmless commands.",
|
|
22
|
+
"`shell_command` / `exec_command` are the Codex Responses shell bridge exposed through Cursor's tool protocol; do not describe them as an external MCP server tool.",
|
|
23
|
+
"Do not use `run_shell` unless this turn's tool catalog lists it.",
|
|
24
|
+
"A request for N tools means N separate shell-bridge invocations/results; never satisfy it with one chained shell command such as `cmd1 && cmd2`.",
|
|
25
|
+
"For independent read-only or output-only commands, emit all requested shell-bridge calls in the same response before waiting when the runtime supports parallel tool calls.",
|
|
26
|
+
"The Cursor bridge may suspend after the first returned bridge tool call, so emit sibling calls together before any result is needed.",
|
|
27
|
+
"If parallel emission is unavailable, continue with separate shell-bridge calls until the requested count has returned.",
|
|
28
|
+
"Do not use `tool_search`, external MCP, or resource discovery just to pad the count unless explicitly asked.",
|
|
29
|
+
"Do not suggest or switch to neighboring-agent tools such as `Grep`, `Read`, `Glob`, `Bash`, or `LS` unless this turn's catalog lists those exact names.",
|
|
30
|
+
"Never tell the user that shell or read access is blocked, disabled, or denied unless the Codex shell bridge tool itself fails. Do not narrate Cursor-native Shell/Read routing.",
|
|
31
|
+
].join(" ");
|
|
32
|
+
|
|
33
|
+
export const CURSOR_EXEC_COMMAND_INPUT_SCHEMA = {
|
|
34
|
+
type: "object",
|
|
35
|
+
properties: {
|
|
36
|
+
cmd: { type: "string", description: "Shell command to execute." },
|
|
37
|
+
workdir: { type: "string", description: "Working directory for the command. Defaults to the turn cwd." },
|
|
38
|
+
shell: { type: "string", description: "Shell binary to launch. Defaults to the user's default shell." },
|
|
39
|
+
tty: { type: "boolean", description: "True allocates a PTY for the command; false or omitted uses plain pipes." },
|
|
40
|
+
yield_time_ms: { type: "number", description: "Wait before yielding output. Defaults to 10000 ms; effective range is 250-30000 ms." },
|
|
41
|
+
max_output_tokens: { type: "number", description: "Output token budget. Defaults to 10000 tokens; larger requests may be capped by policy." },
|
|
42
|
+
},
|
|
43
|
+
required: ["cmd"],
|
|
44
|
+
additionalProperties: false,
|
|
45
|
+
} as const;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Structured single-replacement schema advertised to Cursor models in addition to the freeform
|
|
49
|
+
* `apply_patch` tool. Cursor-trained models reliably emit exact-match replacements (the native
|
|
50
|
+
* Edit shape) but cannot produce Codex's freeform patch grammar, so every file edit attempt on the
|
|
51
|
+
* Cursor route produced malformed `apply_patch` payloads that the Codex client rejected locally
|
|
52
|
+
* (#1017). Calls to this tool are converted server-side into a valid apply_patch payload.
|
|
53
|
+
*/
|
|
54
|
+
export const CURSOR_EDIT_FILE_INPUT_SCHEMA = {
|
|
55
|
+
type: "object",
|
|
56
|
+
properties: {
|
|
57
|
+
file_path: { type: "string", description: "Path of the file to edit, relative to the workspace root." },
|
|
58
|
+
old_string: { type: "string", description: "Exact text to replace. Must match the current file content, including line breaks." },
|
|
59
|
+
new_string: { type: "string", description: "Replacement text. Empty removes the matched text." },
|
|
60
|
+
},
|
|
61
|
+
required: ["file_path", "old_string", "new_string"],
|
|
62
|
+
additionalProperties: false,
|
|
63
|
+
} as const;
|
|
64
|
+
|
|
65
|
+
/** Structured multi-replacement schema; mirrors Cursor's native MultiEdit shape. */
|
|
66
|
+
export const CURSOR_MULTI_EDIT_INPUT_SCHEMA = {
|
|
67
|
+
type: "object",
|
|
68
|
+
properties: {
|
|
69
|
+
file_path: { type: "string", description: "Path of the file to edit, relative to the workspace root." },
|
|
70
|
+
edits: {
|
|
71
|
+
type: "array",
|
|
72
|
+
items: {
|
|
73
|
+
type: "object",
|
|
74
|
+
properties: {
|
|
75
|
+
old_string: { type: "string", description: "Exact text to replace. Must match the current file content, including line breaks." },
|
|
76
|
+
new_string: { type: "string", description: "Replacement text. Empty removes the matched text." },
|
|
77
|
+
},
|
|
78
|
+
required: ["old_string", "new_string"],
|
|
79
|
+
additionalProperties: false,
|
|
80
|
+
},
|
|
81
|
+
description: "Ordered replacement edits for this file. Each old_string must match the current file content.",
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
required: ["file_path", "edits"],
|
|
85
|
+
additionalProperties: false,
|
|
86
|
+
} as const;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Responses/Codex-side schema used ONLY for arg-key normalization after Cursor returns a call.
|
|
90
|
+
* Cursor models are trained to emit `cmd`; Codex `shell_command` / `exec_command` validate
|
|
91
|
+
* `command`. Keeping `cmd` out of this schema lets `normalizeArgKeys` rewrite `cmd` → `command`.
|
|
92
|
+
*/
|
|
93
|
+
export const CODEX_SHELL_BRIDGE_ARG_NORMALIZE_SCHEMA = {
|
|
94
|
+
type: "object",
|
|
95
|
+
properties: {
|
|
96
|
+
command: { type: "string", description: "Shell command to execute." },
|
|
97
|
+
workdir: { type: "string", description: "Working directory for the command. Defaults to the turn cwd." },
|
|
98
|
+
shell: { type: "string", description: "Shell binary to launch. Defaults to the user's default shell." },
|
|
99
|
+
tty: { type: "boolean", description: "True allocates a PTY for the command; false or omitted uses plain pipes." },
|
|
100
|
+
yield_time_ms: { type: "number", description: "Wait before yielding output. Defaults to 10000 ms; effective range is 250-30000 ms." },
|
|
101
|
+
max_output_tokens: { type: "number", description: "Output token budget. Defaults to 10000 tokens; larger requests may be capped by policy." },
|
|
102
|
+
max_output_chars: { type: "number", description: "Output character budget when the Responses tool uses chars instead of tokens." },
|
|
103
|
+
},
|
|
104
|
+
required: ["command"],
|
|
105
|
+
} as const;
|
|
106
|
+
|
|
107
|
+
export function isCodexShellBridgeToolName(name: string): boolean {
|
|
108
|
+
return (CODEX_SHELL_BRIDGE_TOOL_NAMES as readonly string[]).includes(name);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Direct key lookup, then shell_command/exec_command sibling aliases when the key is a bridge name.
|
|
113
|
+
* Used for catalog admission, schema normalize maps, and Responses name maps (#399).
|
|
114
|
+
*/
|
|
115
|
+
export function resolveShellBridgeAliasKey<T>(
|
|
116
|
+
key: string,
|
|
117
|
+
lookup: (name: string) => T | undefined,
|
|
118
|
+
): T | undefined {
|
|
119
|
+
const direct = lookup(key);
|
|
120
|
+
if (direct !== undefined) return direct;
|
|
121
|
+
if (!isCodexShellBridgeToolName(key)) return undefined;
|
|
122
|
+
for (const alias of CODEX_SHELL_BRIDGE_TOOL_NAMES) {
|
|
123
|
+
if (alias === key) continue;
|
|
124
|
+
const hit = lookup(alias);
|
|
125
|
+
if (hit !== undefined) return hit;
|
|
126
|
+
}
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function cursorToolChoiceAliases(tool: Pick<OcxTool, "namespace" | "name">): string[] {
|
|
131
|
+
const aliases = new Set(toolChoiceAliases(tool));
|
|
132
|
+
if (isBareCodexShellBridgeTool(tool)) {
|
|
133
|
+
for (const alias of CODEX_SHELL_BRIDGE_TOOL_NAMES) aliases.add(alias);
|
|
134
|
+
}
|
|
135
|
+
return [...aliases];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function catalogHasBareCodexShellBridge(
|
|
139
|
+
catalog: readonly Pick<OcxTool, "namespace" | "name">[],
|
|
140
|
+
): boolean {
|
|
141
|
+
return catalog.some(isBareCodexShellBridgeTool);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Catalog-aware tool_choice matching for Cursor.
|
|
146
|
+
* When a bare Codex shell bridge is in the catalog, raw `shell_command` / `exec_command`
|
|
147
|
+
* choices select only that bridge (never a namespaced remote with the same raw name).
|
|
148
|
+
* When no bare bridge exists, raw bridge names may select a namespaced tool by raw name.
|
|
149
|
+
* Explicit wire names (`mcp__remote__exec_command`) always match the namespaced tool.
|
|
150
|
+
*/
|
|
151
|
+
function cursorToolChoiceMatches(
|
|
152
|
+
tool: Pick<OcxTool, "namespace" | "name">,
|
|
153
|
+
choiceName: string,
|
|
154
|
+
catalog: readonly Pick<OcxTool, "namespace" | "name">[],
|
|
155
|
+
): boolean {
|
|
156
|
+
if (isCodexShellBridgeToolName(choiceName)) {
|
|
157
|
+
if (catalogHasBareCodexShellBridge(catalog)) {
|
|
158
|
+
return isBareCodexShellBridgeTool(tool);
|
|
159
|
+
}
|
|
160
|
+
return tool.name === choiceName || cursorToolWireName(tool) === choiceName;
|
|
161
|
+
}
|
|
162
|
+
if (tool.name === choiceName || cursorToolWireName(tool) === choiceName) return true;
|
|
163
|
+
return cursorToolChoiceAliases(tool).includes(choiceName);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function isBareCodexShellBridgeTool(tool: Pick<OcxTool, "namespace" | "name">): boolean {
|
|
167
|
+
return !tool.namespace && isCodexShellBridgeToolName(tool.name);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** @deprecated Prefer isBareCodexShellBridgeTool; kept for older call sites/tests. */
|
|
171
|
+
function isBareCodexExecCommandTool(tool: Pick<OcxTool, "namespace" | "name">): boolean {
|
|
172
|
+
return isBareCodexShellBridgeTool(tool);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export function cursorRequestHasShellAlias(tools: readonly Pick<OcxTool, "namespace" | "name">[] | undefined): boolean {
|
|
176
|
+
return tools?.some(isBareCodexExecCommandTool) ?? false;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function cursorRequestAdvertisesApplyPatch(
|
|
180
|
+
tools: readonly Pick<OcxTool, "namespace" | "name" | "freeform">[] | undefined,
|
|
181
|
+
toolChoice?: OcxRequestOptions["toolChoice"],
|
|
182
|
+
): boolean {
|
|
183
|
+
const catalog = tools ?? [];
|
|
184
|
+
return catalog.some(tool => !tool.namespace && tool.name === CODEX_APPLY_PATCH_TOOL && tool.freeform === true && cursorToolAllowedByChoice(tool, toolChoice, catalog));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function isCursorStructuredEditToolName(name: string): boolean {
|
|
188
|
+
return (CURSOR_STRUCTURED_EDIT_TOOLS as readonly string[]).includes(name);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** Internal provenance gate for synthetic edits after prompt filtering and catalog budgeting. */
|
|
192
|
+
export function isCursorSyntheticStructuredEditTool(
|
|
193
|
+
tool: Pick<OcxTool, "namespace" | "name" | "cursorStructuredEdit">,
|
|
194
|
+
): boolean {
|
|
195
|
+
return !tool.namespace && tool.cursorStructuredEdit === true && isCursorStructuredEditToolName(tool.name);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Synthetic structured edit tools for the Cursor route (#1017).
|
|
200
|
+
*
|
|
201
|
+
* Codex exposes `apply_patch` as a freeform custom tool whose body must be the exact Codex patch
|
|
202
|
+
* grammar (`*** Begin Patch` envelope, `@@` hunks, `-`/`+` prefixes). Cursor-trained models are
|
|
203
|
+
* trained on exact-match edit tools instead and emit malformed patch text on every attempt, which
|
|
204
|
+
* the Codex client then rejects locally ("invalid hunk"). When the request advertises the freeform
|
|
205
|
+
* `apply_patch` tool, also advertise Cursor-native-shaped `edit_file` / `multi_edit` tools; the
|
|
206
|
+
* adapter converts their exact-match replacements into a valid apply_patch payload (see
|
|
207
|
+
* protobuf-events.translateStructuredEditCall).
|
|
208
|
+
*
|
|
209
|
+
* Never widened when the caller pinned an explicit tool choice: a forced `apply_patch` selection
|
|
210
|
+
* must not gain sibling tools the client did not ask for.
|
|
211
|
+
*/
|
|
212
|
+
export function cursorStructuredEditTools(
|
|
213
|
+
tools: readonly Pick<OcxTool, "namespace" | "name" | "freeform">[] | undefined,
|
|
214
|
+
toolChoice?: OcxRequestOptions["toolChoice"],
|
|
215
|
+
): OcxTool[] {
|
|
216
|
+
if (!cursorRequestAdvertisesApplyPatch(tools, toolChoice)) return [];
|
|
217
|
+
if (toolChoice && toolChoice !== "auto" && toolChoice !== "required") return [];
|
|
218
|
+
// Never shadow an already-advertised bare tool with the same name (a client catalog could
|
|
219
|
+
// legitimately expose its own `edit_file` / `multi_edit` MCP-style tools).
|
|
220
|
+
const existingBareNames = new Set(
|
|
221
|
+
(tools ?? []).filter(tool => !tool.namespace).map(tool => tool.name),
|
|
222
|
+
);
|
|
223
|
+
const candidates: OcxTool[] = [
|
|
224
|
+
{
|
|
225
|
+
name: CURSOR_EDIT_FILE_TOOL,
|
|
226
|
+
cursorStructuredEdit: true,
|
|
227
|
+
description:
|
|
228
|
+
"Replace one block of exact text in a file. Remodex converts the replacement into a Codex apply_patch change, which the Codex client applies with its normal approval and sandbox policy. old_string must match the current file content exactly at exactly one location (apply_patch rejects ambiguous hunks). Matching is line-based, so an edit cannot add or remove only the file's final newline, and old_string/new_string that are identical after line normalization are rejected as a no-op.",
|
|
229
|
+
parameters: { ...CURSOR_EDIT_FILE_INPUT_SCHEMA },
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
name: CURSOR_MULTI_EDIT_TOOL,
|
|
233
|
+
cursorStructuredEdit: true,
|
|
234
|
+
description:
|
|
235
|
+
"Apply several exact-text replacements to one file. Remodex converts the edits into a single Codex apply_patch change, which the Codex client applies with its normal approval and sandbox policy. Each old_string must match the current file content exactly at exactly one location (apply_patch rejects ambiguous hunks). Edits are independent: every old_string is matched against the ORIGINAL file content, so a later edit must not rely on text introduced by an earlier one. Matching is line-based, so an edit cannot add or remove only the file's final newline, and old_string/new_string that are identical after line normalization are rejected as a no-op.",
|
|
236
|
+
parameters: { ...CURSOR_MULTI_EDIT_INPUT_SCHEMA },
|
|
237
|
+
},
|
|
238
|
+
];
|
|
239
|
+
return candidates.filter(tool => !existingBareNames.has(tool.name));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* True when this request actually advertises the synthetic structured edit tools (`edit_file` /
|
|
244
|
+
* `multi_edit`) — i.e. a freeform `apply_patch` is advertised, no tool-choice pin blocks widening,
|
|
245
|
+
* and neither name is shadowed by an existing bare tool in the client catalog.
|
|
246
|
+
*/
|
|
247
|
+
export function cursorRequestAdvertisesStructuredEdits(
|
|
248
|
+
tools: readonly Pick<OcxTool, "namespace" | "name" | "freeform">[] | undefined,
|
|
249
|
+
toolChoice?: OcxRequestOptions["toolChoice"],
|
|
250
|
+
): boolean {
|
|
251
|
+
return cursorStructuredEditTools(tools, toolChoice).length > 0;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export function cursorToolWireName(tool: Pick<OcxTool, "namespace" | "name">): string {
|
|
255
|
+
return namespacedToolName(tool.namespace, tool.name);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Cursor's harness shows MCP tools to the model as `mcp_<providerIdentifier>_<toolName>`; models
|
|
260
|
+
* sometimes call that display name verbatim instead of the advertised short name (live 20:41/21:00
|
|
261
|
+
* sessions: `mcp_opencodex-responses_exec_command` / `mcp_opencodex-responses_shell_command`).
|
|
262
|
+
* Fold the display prefix back to the advertised wire name, and treat `shell_command` /
|
|
263
|
+
* `exec_command` as the same Codex shell bridge, so alias thrash does not become "tool not found".
|
|
264
|
+
*/
|
|
265
|
+
const CURSOR_MCP_DISPLAY_PREFIX = `mcp_${OCX_RESPONSES_TOOL_PROVIDER}_`;
|
|
266
|
+
|
|
267
|
+
export function normalizeCursorWireName(name: string): string {
|
|
268
|
+
return name.startsWith(CURSOR_MCP_DISPLAY_PREFIX) ? name.slice(CURSOR_MCP_DISPLAY_PREFIX.length) : name;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export function responsesToolNameFromCursorWire(name: string, cursorToolNameMap?: ReadonlyMap<string, string>): string {
|
|
272
|
+
const normalized = normalizeCursorWireName(name);
|
|
273
|
+
if (!cursorToolNameMap) return normalized;
|
|
274
|
+
return resolveShellBridgeAliasKey(normalized, alias => cursorToolNameMap.get(alias)) ?? normalized;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/** Schema advertised to Cursor for this tool (may use Cursor-preferred field names like `cmd`). */
|
|
278
|
+
export function cursorToolInputSchema(tool: OcxTool): unknown {
|
|
279
|
+
return isBareCodexExecCommandTool(tool) ? CURSOR_EXEC_COMMAND_INPUT_SCHEMA : (tool.parameters ?? {});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Schema used to normalize completed Cursor tool args back to Responses/Codex field names.
|
|
284
|
+
* Must NOT reuse `cursorToolInputSchema` for the shell bridge: advertising `cmd` while also
|
|
285
|
+
* treating `cmd` as canonical prevents the `cmd` → `command` rewrite Codex requires (#399).
|
|
286
|
+
*/
|
|
287
|
+
export function cursorToolArgNormalizeSchema(tool: OcxTool): unknown {
|
|
288
|
+
if (isBareCodexShellBridgeTool(tool)) {
|
|
289
|
+
return shellBridgeArgNormalizeSchema(tool);
|
|
290
|
+
}
|
|
291
|
+
return tool.parameters ?? {};
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function shellBridgeArgNormalizeSchema(tool: OcxTool): unknown {
|
|
295
|
+
const parameters = tool.parameters;
|
|
296
|
+
if (!parameters || typeof parameters !== "object") return CODEX_SHELL_BRIDGE_ARG_NORMALIZE_SCHEMA;
|
|
297
|
+
const base = parameters as Record<string, unknown>;
|
|
298
|
+
const rawProps = base.properties && typeof base.properties === "object"
|
|
299
|
+
? { ...(base.properties as Record<string, unknown>) }
|
|
300
|
+
: {};
|
|
301
|
+
const required = Array.isArray(base.required) ? [...base.required as unknown[]] : [];
|
|
302
|
+
const requiresCommand = required.includes("command") || "command" in rawProps;
|
|
303
|
+
const requiresCmd = required.includes("cmd") || "cmd" in rawProps;
|
|
304
|
+
const shouldRewriteCmdToCommand = tool.name === CODEX_SHELL_COMMAND_TOOL || requiresCommand;
|
|
305
|
+
|
|
306
|
+
if (!shouldRewriteCmdToCommand && requiresCmd) {
|
|
307
|
+
return parameters;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Drop Cursor-preferred aliases so normalizeArgKeys can rewrite them to Responses keys.
|
|
311
|
+
delete rawProps.cmd;
|
|
312
|
+
const properties = {
|
|
313
|
+
...CODEX_SHELL_BRIDGE_ARG_NORMALIZE_SCHEMA.properties,
|
|
314
|
+
...rawProps,
|
|
315
|
+
command: rawProps.command ?? CODEX_SHELL_BRIDGE_ARG_NORMALIZE_SCHEMA.properties.command,
|
|
316
|
+
};
|
|
317
|
+
return {
|
|
318
|
+
...base,
|
|
319
|
+
type: "object",
|
|
320
|
+
properties,
|
|
321
|
+
required: requiresCommand ? required : ["command"],
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
export function isGenericToolUseCountDemoPrompt(text: string): boolean {
|
|
326
|
+
const trimmed = text.trim();
|
|
327
|
+
if (trimmed.length === 0) return false;
|
|
328
|
+
return [
|
|
329
|
+
/\b(?:use|call|invoke|try|exercise)\s+(?:any\s+)?\d+\s+tools?\b/i,
|
|
330
|
+
/\buse\s+any\s+tools?\b/i,
|
|
331
|
+
/\bactually\s+(?:call|use|invoke)\s+(?:the\s+)?tools?\b/i,
|
|
332
|
+
/\b\d+\s+tools?\b/i,
|
|
333
|
+
/\btools?\s+\d+\b/i,
|
|
334
|
+
/\btool\s+use\b/i,
|
|
335
|
+
/아무\s*(?:tool|tools?|도구|툴)/i,
|
|
336
|
+
/(?:tool|tools?|도구|툴)\s*\d+\s*(?:개|번)?/i,
|
|
337
|
+
/\d+\s*(?:개|번)?\s*(?:tool|tools?|도구|툴)/i,
|
|
338
|
+
/(?:도구|툴).{0,12}(?:써|사용|호출).{0,12}\d+\s*(?:개|번)?/i,
|
|
339
|
+
].some(pattern => pattern.test(trimmed));
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export function requestedCursorToolUseCount(text: string): number | undefined {
|
|
343
|
+
const patterns = [
|
|
344
|
+
/\b(?:use|call|invoke|try|exercise)\s+(?:any\s+)?(\d+)\s+tools?\b/i,
|
|
345
|
+
/\b(\d+)\s+tools?\b/i,
|
|
346
|
+
/\btools?\s+(\d+)\b/i,
|
|
347
|
+
/(?:tool|tools?|도구|툴)\s*(\d+)\s*(?:개|번)?/i,
|
|
348
|
+
/(\d+)\s*(?:개|번)?\s*(?:tool|tools?|도구|툴)/i,
|
|
349
|
+
/(?:도구|툴).{0,12}(?:써|사용|호출).{0,12}(\d+)\s*(?:개|번)?/i,
|
|
350
|
+
];
|
|
351
|
+
for (const pattern of patterns) {
|
|
352
|
+
const match = pattern.exec(text);
|
|
353
|
+
const count = Number(match?.[1]);
|
|
354
|
+
if (Number.isInteger(count) && count > 0 && count <= 50) return count;
|
|
355
|
+
}
|
|
356
|
+
return undefined;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function cursorGenericToolUseHint(text: string): string {
|
|
360
|
+
const count = requestedCursorToolUseCount(text);
|
|
361
|
+
if (!count) return CURSOR_GENERIC_TOOL_USE_USER_HINT;
|
|
362
|
+
return [
|
|
363
|
+
`This turn requests ${count} tool uses: emit exactly ${count} separate Codex shell bridge function calls/results (\`shell_command\` or \`exec_command\`).`,
|
|
364
|
+
`One shell-bridge call containing chained commands counts as 1 tool call, not ${count}.`,
|
|
365
|
+
`Prefer one parallel tool-call batch containing all ${count} independent shell-bridge calls before waiting for results.`,
|
|
366
|
+
CURSOR_GENERIC_TOOL_USE_USER_HINT,
|
|
367
|
+
].join(" ");
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function activeTextMentionsGenericToolUseHint(text: string): boolean {
|
|
371
|
+
return text.includes("Codex native exec tool")
|
|
372
|
+
|| text.includes("Codex Responses bridge exec tool")
|
|
373
|
+
|| text.includes("generic tool-use/count demos");
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export function shouldAppendCursorGenericToolUseHint(
|
|
377
|
+
tools: readonly Pick<OcxTool, "namespace" | "name">[] | undefined,
|
|
378
|
+
text: string,
|
|
379
|
+
): boolean {
|
|
380
|
+
const trimmed = text.trim();
|
|
381
|
+
return trimmed.length > 0
|
|
382
|
+
&& cursorRequestHasShellAlias(tools)
|
|
383
|
+
&& isGenericToolUseCountDemoPrompt(trimmed)
|
|
384
|
+
&& !activeTextMentionsGenericToolUseHint(trimmed);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export function appendCursorGenericToolUseHint(
|
|
388
|
+
tools: readonly Pick<OcxTool, "namespace" | "name">[] | undefined,
|
|
389
|
+
text: string,
|
|
390
|
+
): string {
|
|
391
|
+
if (!shouldAppendCursorGenericToolUseHint(tools, text)) return text;
|
|
392
|
+
return `${text}${text.endsWith("\n") ? "\n" : "\n\n"}${cursorGenericToolUseHint(text)}`;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
export function shouldUseNativeExecOnlyForGenericToolUse(
|
|
396
|
+
tools: readonly Pick<OcxTool, "namespace" | "name">[] | undefined,
|
|
397
|
+
text: string,
|
|
398
|
+
): boolean {
|
|
399
|
+
const trimmed = text.trim();
|
|
400
|
+
if (trimmed.length === 0 || !cursorRequestHasShellAlias(tools) || !isGenericToolUseCountDemoPrompt(trimmed)) return false;
|
|
401
|
+
return !/\b(?:mcp|resource|resources|tool_search|plugin|plugins|app connector|github)\b/i.test(trimmed)
|
|
402
|
+
&& !/(?:리소스|플러그인|깃허브|github)/i.test(trimmed);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
export function cursorToolsForActivePrompt<T extends Pick<OcxTool, "namespace" | "name">>(
|
|
406
|
+
tools: readonly T[] | undefined,
|
|
407
|
+
activeText: string,
|
|
408
|
+
toolChoice?: OcxRequestOptions["toolChoice"],
|
|
409
|
+
): readonly T[] | undefined {
|
|
410
|
+
if (!shouldUseNativeExecOnlyForGenericToolUse(tools, activeText)) return tools;
|
|
411
|
+
const execTools = tools?.filter(isBareCodexExecCommandTool);
|
|
412
|
+
const catalog = tools ?? [];
|
|
413
|
+
if (execTools?.length && !execTools.some(tool => cursorToolAllowedByChoice(tool, toolChoice, catalog))) return tools;
|
|
414
|
+
return execTools && execTools.length > 0 ? execTools : tools;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Required command payload keys for a shell bridge tool, derived from the advertised schema when present.
|
|
419
|
+
*/
|
|
420
|
+
export function shellBridgeRequiredCommandKeys(
|
|
421
|
+
toolName: string,
|
|
422
|
+
schema?: unknown,
|
|
423
|
+
): readonly ("cmd" | "command")[] {
|
|
424
|
+
if (schema && typeof schema === "object") {
|
|
425
|
+
const required = (schema as Record<string, unknown>).required;
|
|
426
|
+
if (Array.isArray(required)) {
|
|
427
|
+
const keys = required.filter((key): key is "cmd" | "command" => key === "cmd" || key === "command");
|
|
428
|
+
if (keys.length > 0) return keys;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
return toolName === CODEX_SHELL_COMMAND_TOOL ? ["command"] : ["cmd"];
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/** Normalize-schema defaults used when validating stateless synthetic shell-bridge calls. */
|
|
435
|
+
export function defaultShellBridgeArgNormalizeSchema(toolName: string): unknown {
|
|
436
|
+
return toolName === CODEX_SHELL_COMMAND_TOOL
|
|
437
|
+
? CODEX_SHELL_BRIDGE_ARG_NORMALIZE_SCHEMA
|
|
438
|
+
: {
|
|
439
|
+
type: "object",
|
|
440
|
+
properties: CURSOR_EXEC_COMMAND_INPUT_SCHEMA.properties,
|
|
441
|
+
required: ["cmd"],
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
export function cursorShellBridgeDropError(toolName: string): string {
|
|
446
|
+
return `Cursor emitted ${toolName} without a non-empty command; the tool call was dropped.`;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Extract a non-empty shell command from completed Cursor bridge args using the schema's required
|
|
451
|
+
* command key (`cmd` for bare exec_command, `command` for shell_command).
|
|
452
|
+
*/
|
|
453
|
+
export function nonEmptyShellBridgeCommandFromArgs(
|
|
454
|
+
finalArgs: string,
|
|
455
|
+
toolName: string,
|
|
456
|
+
schema?: unknown,
|
|
457
|
+
): string | undefined {
|
|
458
|
+
let parsed: unknown;
|
|
459
|
+
try {
|
|
460
|
+
parsed = finalArgs.length > 0 ? JSON.parse(finalArgs) : {};
|
|
461
|
+
} catch {
|
|
462
|
+
return undefined;
|
|
463
|
+
}
|
|
464
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return undefined;
|
|
465
|
+
const record = parsed as Record<string, unknown>;
|
|
466
|
+
for (const key of shellBridgeRequiredCommandKeys(toolName, schema)) {
|
|
467
|
+
const value = record[key];
|
|
468
|
+
if (typeof value === "string" && value.trim().length > 0) return value.trim();
|
|
469
|
+
}
|
|
470
|
+
return undefined;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
export function cursorShellBridgeArgsValid(
|
|
474
|
+
finalArgs: string,
|
|
475
|
+
toolName: string,
|
|
476
|
+
schema?: unknown,
|
|
477
|
+
): boolean {
|
|
478
|
+
return !isCodexShellBridgeToolName(toolName)
|
|
479
|
+
|| nonEmptyShellBridgeCommandFromArgs(finalArgs, toolName, schema) !== undefined;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
export function cursorToolAllowedByChoice(
|
|
483
|
+
tool: Pick<OcxTool, "namespace" | "name">,
|
|
484
|
+
toolChoice: OcxRequestOptions["toolChoice"] | undefined,
|
|
485
|
+
catalog: readonly Pick<OcxTool, "namespace" | "name">[] = [tool],
|
|
486
|
+
): boolean {
|
|
487
|
+
if (!toolChoice || toolChoice === "auto" || toolChoice === "required") return true;
|
|
488
|
+
if (toolChoice === "none") return false;
|
|
489
|
+
if ("allowedTools" in toolChoice) {
|
|
490
|
+
return toolChoice.allowedTools.some(choiceName => cursorToolChoiceMatches(tool, choiceName, catalog));
|
|
491
|
+
}
|
|
492
|
+
return cursorToolChoiceMatches(tool, toolChoice.name, catalog);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
function quotedNames(names: readonly string[]): string {
|
|
496
|
+
return names.map(name => `\`${name}\``).join(", ");
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function unavailableNeighborAgentToolNames(wireNames: readonly string[]): string[] {
|
|
500
|
+
const advertised = new Set(wireNames);
|
|
501
|
+
return NEIGHBOR_AGENT_TOOL_NAMES.filter(name => !advertised.has(name));
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
function discoveryToolLabel(wireNames: readonly string[]): string | undefined {
|
|
505
|
+
const labels: string[] = [];
|
|
506
|
+
if (wireNames.includes("tool_search")) labels.push("`tool_search`");
|
|
507
|
+
if (wireNames.some(name => name.startsWith("mcp__"))) labels.push("MCP");
|
|
508
|
+
if (wireNames.some(name => /resource/i.test(name))) labels.push("resource discovery");
|
|
509
|
+
return labels.length > 0 ? labels.join(", ") : undefined;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
export function buildCursorToolGuidanceSystemNote(
|
|
513
|
+
tools: readonly Pick<OcxTool, "namespace" | "name" | "freeform">[] | undefined,
|
|
514
|
+
toolChoice?: OcxRequestOptions["toolChoice"],
|
|
515
|
+
): string | undefined {
|
|
516
|
+
if (!tools?.length) return undefined;
|
|
517
|
+
const wireNames = [...new Set(
|
|
518
|
+
tools
|
|
519
|
+
.filter(tool => cursorToolAllowedByChoice(tool, toolChoice, tools))
|
|
520
|
+
.map(tool => cursorToolWireName(tool)),
|
|
521
|
+
)];
|
|
522
|
+
if (wireNames.length === 0) return undefined;
|
|
523
|
+
|
|
524
|
+
const listedNames = quotedNames(wireNames);
|
|
525
|
+
const shellBridgeNames = wireNames.filter(isCodexShellBridgeToolName);
|
|
526
|
+
const hasBareExec = shellBridgeNames.length > 0;
|
|
527
|
+
const shellBridgeLabel = quotedNames(shellBridgeNames.length > 0 ? shellBridgeNames : [...CODEX_SHELL_BRIDGE_TOOL_NAMES]);
|
|
528
|
+
const hasApplyPatch = cursorRequestAdvertisesApplyPatch(tools, toolChoice);
|
|
529
|
+
const structuredEditNames = tools
|
|
530
|
+
?.filter(tool => !tool.namespace && isCursorStructuredEditToolName(tool.name))
|
|
531
|
+
.map(tool => tool.name) ?? [];
|
|
532
|
+
const discoveryTools = discoveryToolLabel(wireNames);
|
|
533
|
+
const unavailableNeighborNames = unavailableNeighborAgentToolNames(wireNames);
|
|
534
|
+
// Host-shell-neutral: the Codex client executes bridge commands, and may differ from
|
|
535
|
+
// the Remodex proxy OS (LAN/SSH remote-proxy). Always cover PowerShell 5.1 pitfalls.
|
|
536
|
+
const hostShellNote = hasBareExec
|
|
537
|
+
? "Match shell syntax to the Codex client host that runs the bridge (not only the proxy OS). Windows PowerShell 5.1: no CMD `cd /d`, no bash heredocs (`<<EOF`); `&&`/`||` are unsupported parser errors — prefer the bridge working-directory argument for directory changes, and use `if ($?) { ... }` for success-gated follow-up steps; do not treat `;` as a substitute for `&&`. POSIX: use portable commands. After a shell failure, make at most one corrected bridge attempt, then report the error and stop — do not repeat equivalent failing commands."
|
|
538
|
+
: undefined;
|
|
539
|
+
const notes = [
|
|
540
|
+
`Cursor tool calls: available tool names are exactly ${listedNames}.`,
|
|
541
|
+
"Use the current tool catalog as ground truth and call only those exact names with their listed argument keys.",
|
|
542
|
+
unavailableNeighborNames.length > 0
|
|
543
|
+
? `This turn does not expose neighboring-agent tool names ${quotedNames(unavailableNeighborNames)}; do not call or suggest them unless the catalog lists them.`
|
|
544
|
+
: undefined,
|
|
545
|
+
hasBareExec
|
|
546
|
+
? `${shellBridgeLabel} is the Codex Responses shell bridge for this turn, exposed through Cursor's tool protocol; it is not an external MCP server tool. \`shell_command\` and \`exec_command\` are aliases of the same bridge.`
|
|
547
|
+
: undefined,
|
|
548
|
+
hasBareExec
|
|
549
|
+
? "Your tool list may display it under a longer `mcp_opencodex-responses_shell_command` / `mcp_opencodex-responses_exec_command` name; those are the SAME tool — call whichever your list shows, and do not comment on the naming difference to the user."
|
|
550
|
+
: undefined,
|
|
551
|
+
hasBareExec
|
|
552
|
+
? "Never tell the user that shell or read access is blocked, disabled, or denied unless the Codex shell bridge tool itself fails. Prefer the bridge over Cursor-native Shell/Read; do not narrate phrases like \"Native shell access is blocked\" — silently call `shell_command` / `exec_command`."
|
|
553
|
+
: undefined,
|
|
554
|
+
hostShellNote,
|
|
555
|
+
"Cursor product features (Chronicle, screen recording, Notes, Plans, background agents) are available only if this turn's catalog lists a matching tool; do not offer or promise them otherwise.",
|
|
556
|
+
hasBareExec
|
|
557
|
+
? `For file read/search/listing, use ${shellBridgeLabel} when no more specific listed tool is available.`
|
|
558
|
+
: undefined,
|
|
559
|
+
hasApplyPatch
|
|
560
|
+
? structuredEditNames.length > 0
|
|
561
|
+
? `For file edits, prefer the structured edit tools ${quotedNames(structuredEditNames)} — they take exact-match replacements that Remodex converts into Codex \`apply_patch\` changes for approval. Use \`apply_patch\` directly only when you can emit its exact freeform syntax (\`*** Begin Patch\` envelope with \`@@\` hunks and \`-\`/\`+\` line prefixes); never emit patch-like plain text as tool arguments.`
|
|
562
|
+
: "For file edits, use the `apply_patch` tool, not built-in file write/delete tools."
|
|
563
|
+
: undefined,
|
|
564
|
+
hasBareExec
|
|
565
|
+
? "For tool-count demos, each counted tool must be a separate Codex shell-bridge invocation/result; do not collapse several requested tools into one chained shell command."
|
|
566
|
+
: undefined,
|
|
567
|
+
"For independent read-only tool-count or batch requests, prefer one response containing multiple tool calls before waiting for results when the runtime supports parallel tool calls.",
|
|
568
|
+
hasBareExec
|
|
569
|
+
? "For bridge tool-count batches, emit sibling shell-bridge calls together before any result is needed because the bridge may suspend after a returned tool call."
|
|
570
|
+
: undefined,
|
|
571
|
+
discoveryTools
|
|
572
|
+
? `Use ${discoveryTools} only for explicit discovery/resource tasks, not generic tool-count demos.`
|
|
573
|
+
: undefined,
|
|
574
|
+
"Do not count or report a tool call unless a tool result was actually returned.",
|
|
575
|
+
hasBareExec
|
|
576
|
+
? `If a Cursor-native file read, directory listing, grep, or shell operation is rejected by the runtime, silently use ${shellBridgeLabel} with an equivalent host-shell-safe command (POSIX: \`cat\`/\`ls\`/\`rg\`; Windows PowerShell: \`Get-Content\`/\`Get-ChildItem\`/\`Select-String\`). Do not tell the user access is blocked. For file edits, use ${structuredEditNames.length > 0 ? `the structured edit tools (${quotedNames(structuredEditNames)}) or ` : ""}\`apply_patch\` when available.`
|
|
577
|
+
: undefined,
|
|
578
|
+
].filter((note): note is string => typeof note === "string");
|
|
579
|
+
return notes.join(" ");
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
export function encodeCursorInputSchema(schema: unknown): Uint8Array {
|
|
583
|
+
const value: JsonValue = schema && typeof schema === "object"
|
|
584
|
+
? schema as JsonValue
|
|
585
|
+
: { type: "object", properties: {}, required: [] };
|
|
586
|
+
return toBinary(ValueSchema, fromJson(ValueSchema, value));
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
export function buildCursorToolDefinitions(
|
|
590
|
+
tools: readonly OcxTool[] | undefined,
|
|
591
|
+
toolChoice?: OcxRequestOptions["toolChoice"],
|
|
592
|
+
): McpToolDefinition[] {
|
|
593
|
+
if (!tools?.length) return [];
|
|
594
|
+
return tools.filter(tool => cursorToolAllowedByChoice(tool, toolChoice, tools)).map(tool => {
|
|
595
|
+
const wireName = cursorToolWireName(tool);
|
|
596
|
+
return create(McpToolDefinitionSchema, {
|
|
597
|
+
name: wireName,
|
|
598
|
+
toolName: wireName,
|
|
599
|
+
providerIdentifier: OCX_RESPONSES_TOOL_PROVIDER,
|
|
600
|
+
description: tool.description,
|
|
601
|
+
inputSchema: encodeCursorInputSchema(cursorToolInputSchema(tool)),
|
|
602
|
+
});
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/** Exact byte size of the protobuf field value Cursor receives for client tool registration. */
|
|
607
|
+
export function cursorMcpToolsEncodedSize(
|
|
608
|
+
tools: readonly OcxTool[] | undefined,
|
|
609
|
+
toolChoice?: OcxRequestOptions["toolChoice"],
|
|
610
|
+
): number {
|
|
611
|
+
const definitions = buildCursorToolDefinitions(tools, toolChoice);
|
|
612
|
+
return toBinary(McpToolsSchema, create(McpToolsSchema, { mcpTools: definitions })).byteLength;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/** Exact additive contribution of one repeated McpToolDefinition entry. */
|
|
616
|
+
export function cursorMcpToolEncodedSize(
|
|
617
|
+
tool: OcxTool,
|
|
618
|
+
toolChoice?: OcxRequestOptions["toolChoice"],
|
|
619
|
+
): number {
|
|
620
|
+
return cursorMcpToolsEncodedSize([tool], toolChoice);
|
|
621
|
+
}
|