@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,302 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `rmx claude [claude args...]` — launch Claude Code wired to the local proxy.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors `ccr code` UX (devlog/260711_claude_inbound/020, 003 E1/E2/E5/G1):
|
|
5
|
+
* ensures the proxy is running, injects the Anthropic env slots, then execs the
|
|
6
|
+
* `claude` CLI with stdio inherited. User-exported env wins except when a stale
|
|
7
|
+
* loopback opencodex base URL points at a different proxy port.
|
|
8
|
+
*/
|
|
9
|
+
import { spawn } from "node:child_process";
|
|
10
|
+
import { loadConfig } from "../config";
|
|
11
|
+
import { injectClaudeAgentDefs } from "../claude/agents-inject";
|
|
12
|
+
import { effectiveModelEnv, resolveAutoContext } from "../claude/context-windows";
|
|
13
|
+
import { refreshGatewayModelCacheFromProxy } from "../claude/gateway-cache";
|
|
14
|
+
import { commandInvocation } from "../lib/win-exec";
|
|
15
|
+
import { findLiveProxy } from "../server/proxy-liveness";
|
|
16
|
+
import type { OcxConfig } from "../types";
|
|
17
|
+
import { configuredAdminToken } from "../lib/admin-secrets";
|
|
18
|
+
import { PROXY_MARKER, ownAdmissionTokens, defaultAuthDetectDeps, detectClaudeAuth, type AuthDetectDeps } from "../claude/auth-detect";
|
|
19
|
+
import { resolveClaudeAuthMode } from "../claude/auth-mode";
|
|
20
|
+
import { withProcessRuntimeProvenance } from "../lib/bun-runtime";
|
|
21
|
+
import { ANTHROPIC_PARENT_ENV_SLOTS, trustedNodeLauncherContext, type AnthropicParentEnvSlot } from "./launcher-context";
|
|
22
|
+
|
|
23
|
+
export interface ClaudeLaunchEnv {
|
|
24
|
+
[key: string]: string | undefined;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Injectable IO for tests. `env` is deliberately NOT injectable: it is bound to the
|
|
29
|
+
* launch base so detection and the spawned process can never disagree (audit R3-3).
|
|
30
|
+
*/
|
|
31
|
+
export type ClaudeEnvDeps = {
|
|
32
|
+
authDetect?: Omit<Partial<AuthDetectDeps>, "env" | "ownTokens">;
|
|
33
|
+
/** Test seam; production uses the authenticated Node-launcher context. */
|
|
34
|
+
preBunAnthropicSlots?: readonly AnthropicParentEnvSlot[] | null;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Pure env assembly (unit-tested): never sets ANTHROPIC_API_KEY (setting both
|
|
39
|
+
* token vars triggers Claude Code's auth-conflict warning, 003 E1), and never
|
|
40
|
+
* preserves Anthropic variables proven to exist in the parent Node launcher,
|
|
41
|
+
* apart from stale loopback ANTHROPIC_BASE_URL values owned by a previous
|
|
42
|
+
* Remodex launch. Unproven ambient values fail closed as project dotenv.
|
|
43
|
+
*/
|
|
44
|
+
export function buildClaudeEnv(
|
|
45
|
+
config: OcxConfig,
|
|
46
|
+
port: number,
|
|
47
|
+
base: ClaudeLaunchEnv,
|
|
48
|
+
contextWindows: Record<string, number> = {},
|
|
49
|
+
deps: ClaudeEnvDeps = {},
|
|
50
|
+
): ClaudeLaunchEnv {
|
|
51
|
+
const env: ClaudeLaunchEnv = { ...base };
|
|
52
|
+
// Step 1 — strip OUR OWN dummy from the inherited environment before anything reads
|
|
53
|
+
// or writes the token slot. setDefault below preserves any non-empty value, so a
|
|
54
|
+
// stale marker left in place would suppress the admission key and then be removed,
|
|
55
|
+
// leaving the child with no token at all (audit R2-1). It is Remodex state, never
|
|
56
|
+
// user auth, so dropping it unconditionally is safe.
|
|
57
|
+
if (env.ANTHROPIC_AUTH_TOKEN === PROXY_MARKER) delete env.ANTHROPIC_AUTH_TOKEN;
|
|
58
|
+
// Step 1b — drop Anthropic credentials AND destinations that Bun may have synthesized
|
|
59
|
+
// from a project `.env`/`.env.local`. The plain-Node launcher records genuine parent
|
|
60
|
+
// exports before Bun starts and pairs that context with an argv proof, so with a
|
|
61
|
+
// trusted context we know exactly which slots the user really exported.
|
|
62
|
+
//
|
|
63
|
+
// Without a trusted context all three slots are treated as project-controlled. An
|
|
64
|
+
// earlier revision of this branch preserved credentials here, reasoning that the
|
|
65
|
+
// destination is pinned below so a dotenv key would only ever reach the local proxy.
|
|
66
|
+
// That reasoning is wrong, and review caught it: `CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST`
|
|
67
|
+
// is only set when we own an auth token (see below, and #253 for why asserting it
|
|
68
|
+
// otherwise logs a subscriber out), so on a subscription launch Claude Code's
|
|
69
|
+
// settings.env merge can still replace `ANTHROPIC_BASE_URL` after we return. A
|
|
70
|
+
// preserved key then travels to that host. The repository documents that residual for
|
|
71
|
+
// subscription mode; it must not be widened into a credential leak.
|
|
72
|
+
//
|
|
73
|
+
// Direct `bun src/cli/index.ts` therefore loses ambient Anthropic values. That is a
|
|
74
|
+
// real cost to a documented entry point, and the escape hatch is the launcher: run
|
|
75
|
+
// through `rmx` (the canonical published bin) and genuine shell exports are preserved by proof.
|
|
76
|
+
const explicitSlots = deps.preBunAnthropicSlots;
|
|
77
|
+
const trustedSlots = explicitSlots === undefined
|
|
78
|
+
? trustedNodeLauncherContext()?.anthropicEnvSlots ?? []
|
|
79
|
+
: explicitSlots ?? [];
|
|
80
|
+
const exported = new Set<AnthropicParentEnvSlot>(trustedSlots);
|
|
81
|
+
for (const name of ANTHROPIC_PARENT_ENV_SLOTS) {
|
|
82
|
+
const value = env[name];
|
|
83
|
+
if (value !== undefined && value !== "" && !exported.has(name)) delete env[name];
|
|
84
|
+
}
|
|
85
|
+
// Never forward old or current provenance seams to Claude Code.
|
|
86
|
+
delete env.OCX_PRE_BUN_ANTHROPIC_ENV;
|
|
87
|
+
delete env.OCX_NODE_LAUNCH_CONTEXT;
|
|
88
|
+
const setDefault = (name: string, value: string | undefined) => {
|
|
89
|
+
if (value === undefined || value.length === 0) return;
|
|
90
|
+
if (env[name] !== undefined && env[name] !== "") return; // user wins
|
|
91
|
+
env[name] = value;
|
|
92
|
+
};
|
|
93
|
+
setDefault("ANTHROPIC_BASE_URL", `http://127.0.0.1:${port}`);
|
|
94
|
+
const existingBaseUrl = env.ANTHROPIC_BASE_URL;
|
|
95
|
+
if (existingBaseUrl) {
|
|
96
|
+
try {
|
|
97
|
+
const parsed = new URL(existingBaseUrl);
|
|
98
|
+
const isLoopback = parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1";
|
|
99
|
+
if (isLoopback && parsed.port !== "" && Number(parsed.port) !== port) {
|
|
100
|
+
const replacement = `http://127.0.0.1:${port}`;
|
|
101
|
+
console.error(`⚠ Replacing stale Remodex ANTHROPIC_BASE_URL ${existingBaseUrl} with ${replacement}.`);
|
|
102
|
+
env.ANTHROPIC_BASE_URL = replacement;
|
|
103
|
+
}
|
|
104
|
+
} catch {
|
|
105
|
+
// Preserve user-provided values that are not parseable URLs.
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Subscription-preserving default (teamclaude --no-mitm / Vercel gateway pattern):
|
|
109
|
+
// setting ANTHROPIC_AUTH_TOKEN/API_KEY disables claude.ai connectors and overrides
|
|
110
|
+
// the user's Claude login. Only inject a token when the proxy actually requires an
|
|
111
|
+
// admission key; otherwise Claude Code keeps its own OAuth and sends it to us —
|
|
112
|
+
// native claude models then pass through verbatim (see server/claude-messages.ts).
|
|
113
|
+
if ((config.apiKeys?.length ?? 0) > 0) {
|
|
114
|
+
setDefault("ANTHROPIC_AUTH_TOKEN", config.apiKeys![0].key);
|
|
115
|
+
}
|
|
116
|
+
// Detection reads the SANITIZED launch env — the exact object spawned below — so the
|
|
117
|
+
// resolver and the spawned process cannot disagree. It deliberately does NOT read the
|
|
118
|
+
// raw base: the provenance strip above already removed dotenv-only credentials, and
|
|
119
|
+
// letting a value the child never receives decide the marker left an auto-mode user
|
|
120
|
+
// with neither the credential NOR the proxy marker (#701 audit round 2). Injected deps
|
|
121
|
+
// are spread FIRST and `env` bound LAST, and the injection type excludes `env`, so a
|
|
122
|
+
// test fake cannot break that. `ownTokens` is bound last for the same reason: it is
|
|
123
|
+
// config-derived, and a fake that replaced it could make our own admission key look
|
|
124
|
+
// like user auth.
|
|
125
|
+
const resolved = resolveClaudeAuthMode(config, detectClaudeAuth({
|
|
126
|
+
...defaultAuthDetectDeps(env as NodeJS.ProcessEnv),
|
|
127
|
+
...(deps.authDetect ?? {}),
|
|
128
|
+
env: () => env as NodeJS.ProcessEnv,
|
|
129
|
+
ownTokens: ownAdmissionTokens(config),
|
|
130
|
+
}));
|
|
131
|
+
if (!env.ANTHROPIC_AUTH_TOKEN && resolved.markerMode === "proxy") {
|
|
132
|
+
env.ANTHROPIC_AUTH_TOKEN = PROXY_MARKER;
|
|
133
|
+
}
|
|
134
|
+
if (resolved.origin === "auto-unknown") {
|
|
135
|
+
console.error("⚠ Claude 인증을 확인하지 못했습니다 — 구독 방식으로 진행합니다. GUI에서 인증 모드를 직접 지정하면 이 판단을 덮어쓸 수 있습니다.");
|
|
136
|
+
}
|
|
137
|
+
// NOTE: do NOT set _CLAUDE_CODE_ASSUME_FIRST_PARTY_BASE_URL here. While it enables
|
|
138
|
+
// Design/Remote Control, it DISABLES gateway model discovery (Claude Code's eligibility
|
|
139
|
+
// check returns false when isFirstPartyBaseUrl() is true). Model routing through the
|
|
140
|
+
// proxy is essential; Design/Remote Control are secondary features.
|
|
141
|
+
// Connectors still work because they check OAuth state ($o()), not base URL (Gd()).
|
|
142
|
+
// Native /model picker discovery ("From gateway", Claude Code >= 2.1.129).
|
|
143
|
+
setDefault("CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY", "1");
|
|
144
|
+
// Host-managed routing guard (devlog 260720_claude_authmode_persist/020): with
|
|
145
|
+
// this flag in the spawn env, Claude Code strips provider-managed vars
|
|
146
|
+
// (ANTHROPIC_BASE_URL/AUTH_TOKEN/API_KEY, model slots) from settings-sourced
|
|
147
|
+
// env (managedEnv.ts), so a leftover cc-switch/CCR ~/.claude/settings.json
|
|
148
|
+
// env block cannot silently hijack proxy routing away from Remodex.
|
|
149
|
+
// setDefault: an explicit user export (e.g. =0, isEnvTruthy-false) still wins.
|
|
150
|
+
// Intentional contract change: settings.env model slots are also stripped in
|
|
151
|
+
// rmx claude runs — use the top-level settings "model" field or opt out.
|
|
152
|
+
// Claude Code 2.1.206+ also treats this as a host-auth assertion. Injecting it
|
|
153
|
+
// without a host token makes a valid claude.ai subscription look logged out,
|
|
154
|
+
// so the guard is only safe when Remodex actually owns authentication.
|
|
155
|
+
if (env.ANTHROPIC_AUTH_TOKEN) {
|
|
156
|
+
setDefault("CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST", "1");
|
|
157
|
+
}
|
|
158
|
+
// Opt-in effort forcing (devlog 136 B6): opus-shaped aliases already carry
|
|
159
|
+
// output_config.effort, so this is OFF unless the user enables it in config.
|
|
160
|
+
if (config.claudeCode?.alwaysEnableEffort === true) {
|
|
161
|
+
setDefault("CLAUDE_CODE_ALWAYS_ENABLE_EFFORT", "1");
|
|
162
|
+
}
|
|
163
|
+
// Context-window override: the official pair — MAX_CONTEXT_TOKENS alone is ignored
|
|
164
|
+
// for recognized claude-shaped ids unless DISABLE_COMPACT=1 rides along (devlog 135).
|
|
165
|
+
const maxCtx = config.claudeCode?.maxContextTokens;
|
|
166
|
+
if (typeof maxCtx === "number" && Number.isFinite(maxCtx) && maxCtx > 0) {
|
|
167
|
+
setDefault("CLAUDE_CODE_MAX_CONTEXT_TOKENS", String(Math.floor(maxCtx)));
|
|
168
|
+
setDefault("DISABLE_COMPACT", "1");
|
|
169
|
+
}
|
|
170
|
+
// Auto-context (devlog 260712 020): min(believed window, env) inside the CLI means
|
|
171
|
+
// one global env acts as a per-model floor — [1m]-marked models compact here while
|
|
172
|
+
// unmarked (200k-accounted) models keep their default behavior. Inert when the
|
|
173
|
+
// legacy maxContextTokens pair above is set (resolveAutoContext handles that).
|
|
174
|
+
// A user-exported value drives the marking predicate too (audit 021 #2) so the
|
|
175
|
+
// [1m] marker and the compaction threshold can never separate.
|
|
176
|
+
const userAutoCompact = typeof base.CLAUDE_CODE_AUTO_COMPACT_WINDOW === "string" && base.CLAUDE_CODE_AUTO_COMPACT_WINDOW !== ""
|
|
177
|
+
? base.CLAUDE_CODE_AUTO_COMPACT_WINDOW
|
|
178
|
+
: undefined;
|
|
179
|
+
const auto = resolveAutoContext(config.claudeCode, userAutoCompact);
|
|
180
|
+
if (auto.enabled) {
|
|
181
|
+
setDefault("CLAUDE_CODE_AUTO_COMPACT_WINDOW", String(auto.compactWindow));
|
|
182
|
+
}
|
|
183
|
+
// Model slots (devlog 260712 B2): default + four tier defaults + legacy small-fast,
|
|
184
|
+
// with automatic [1m] context-variant marking when the slot's target model has an
|
|
185
|
+
// authoritative >=1M window (Claude Code then accounts 1M, compaction preserved).
|
|
186
|
+
for (const [name, value] of Object.entries(effectiveModelEnv(config.claudeCode, contextWindows, auto))) {
|
|
187
|
+
setDefault(name, value);
|
|
188
|
+
}
|
|
189
|
+
return env;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Context-window map from the RUNNING proxy's management API (warm TTL cache; the
|
|
194
|
+
* daemon registers every selector form — audit R3#1). 3s bound + management auth header.
|
|
195
|
+
* (no [1m] marking, conservative).
|
|
196
|
+
*/
|
|
197
|
+
export async function fetchClaudeContextWindows(config: OcxConfig, port: number, timeoutMs = 3_000): Promise<Record<string, number>> {
|
|
198
|
+
try {
|
|
199
|
+
const headers = new Headers();
|
|
200
|
+
const token = configuredAdminToken();
|
|
201
|
+
if (token) headers.set("x-opencodex-api-key", token);
|
|
202
|
+
const res = await fetch(`http://127.0.0.1:${port}/api/claude-code`, {
|
|
203
|
+
headers,
|
|
204
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
205
|
+
});
|
|
206
|
+
if (!res.ok) return {};
|
|
207
|
+
const body = await res.json() as { contextWindows?: Record<string, number> };
|
|
208
|
+
return body.contextWindows && typeof body.contextWindows === "object" ? body.contextWindows : {};
|
|
209
|
+
} catch {
|
|
210
|
+
console.error("⚠ 모델 컨텍스트 정보를 불러오지 못했습니다 — 1M 자동 표시는 이번 실행에서 생략됩니다.");
|
|
211
|
+
return {};
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
async function ensureProxyForClaude(): Promise<number | null> {
|
|
216
|
+
const live = await findLiveProxy();
|
|
217
|
+
if (live) return live.port;
|
|
218
|
+
const cfgPort = loadConfig().port;
|
|
219
|
+
const pinPort = typeof cfgPort === "number" && cfgPort > 0 ? cfgPort : 10100;
|
|
220
|
+
const child = spawn(process.execPath, [process.argv[1], "start", "--port", String(pinPort)], {
|
|
221
|
+
detached: true,
|
|
222
|
+
stdio: "ignore",
|
|
223
|
+
windowsHide: true,
|
|
224
|
+
env: withProcessRuntimeProvenance({ ...process.env, OCX_SERVICE: "1" }),
|
|
225
|
+
});
|
|
226
|
+
child.unref();
|
|
227
|
+
const deadline = Date.now() + 8_000;
|
|
228
|
+
while (Date.now() < deadline) {
|
|
229
|
+
const started = await findLiveProxy();
|
|
230
|
+
if (started) return started.port;
|
|
231
|
+
await new Promise(resolve => setTimeout(resolve, 250));
|
|
232
|
+
}
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const CLAUDE_INSTALL_HINT = "❌ `claude` CLI not found. Install it first: npm install -g @anthropic-ai/claude-code";
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* cmd.exe reports command-not-found as exit 9009 (the win32 launcher routes `.cmd`
|
|
240
|
+
* shims through cmd.exe, so ENOENT never fires there). Signal exits are not hints.
|
|
241
|
+
* Devlog 260715_cross_platform_audit/020.
|
|
242
|
+
*/
|
|
243
|
+
export function claudeNotFoundHint(
|
|
244
|
+
code: number | null,
|
|
245
|
+
signal: NodeJS.Signals | null,
|
|
246
|
+
platform: NodeJS.Platform = process.platform,
|
|
247
|
+
): string | null {
|
|
248
|
+
return platform === "win32" && code === 9009 && !signal ? CLAUDE_INSTALL_HINT : null;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export async function cmdClaude(args: string[]): Promise<number> {
|
|
252
|
+
const config = loadConfig();
|
|
253
|
+
if (config.claudeCode?.enabled === false) {
|
|
254
|
+
console.error("Claude inbound is disabled (config.claudeCode.enabled=false — flip the Claude ON toggle in the GUI or edit config).");
|
|
255
|
+
return 1;
|
|
256
|
+
}
|
|
257
|
+
const port = await ensureProxyForClaude();
|
|
258
|
+
if (!port) {
|
|
259
|
+
console.error("❌ Proxy did not become healthy after starting.");
|
|
260
|
+
return 1;
|
|
261
|
+
}
|
|
262
|
+
const contextWindows = await fetchClaudeContextWindows(config, port);
|
|
263
|
+
const env = buildClaudeEnv(config, port, process.env, contextWindows);
|
|
264
|
+
// Pre-write the CLI's gateway-model cache (devlog 030): without a token the CLI
|
|
265
|
+
// never refreshes it, so the picker would keep showing yesterday's aliases.
|
|
266
|
+
try {
|
|
267
|
+
const cachePath = await refreshGatewayModelCacheFromProxy(port);
|
|
268
|
+
if (cachePath === null) {
|
|
269
|
+
console.error("⚠ Gateway model cache could not be refreshed; the model picker may be stale.");
|
|
270
|
+
}
|
|
271
|
+
} catch (error) {
|
|
272
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
273
|
+
console.error(`⚠ Gateway model cache could not be refreshed: ${message}`);
|
|
274
|
+
}
|
|
275
|
+
// Sync roster agents (devlog 070): subagentModels + self -> ~/.claude/agents/ocx-*.md.
|
|
276
|
+
try {
|
|
277
|
+
const written = injectClaudeAgentDefs(config, contextWindows);
|
|
278
|
+
if (written === null) {
|
|
279
|
+
console.error("⚠ Claude agent definitions could not be synced; check ~/.claude/agents permissions.");
|
|
280
|
+
}
|
|
281
|
+
} catch (error) {
|
|
282
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
283
|
+
console.error(`⚠ Claude agent definitions could not be synced: ${message}`);
|
|
284
|
+
}
|
|
285
|
+
return await new Promise<number>(resolve => {
|
|
286
|
+
const inv = commandInvocation("claude", args);
|
|
287
|
+
const child = spawn(inv.file, inv.args, { stdio: "inherit", env: env as NodeJS.ProcessEnv, ...inv.options });
|
|
288
|
+
child.on("error", (err: NodeJS.ErrnoException) => {
|
|
289
|
+
if (err.code === "ENOENT") {
|
|
290
|
+
console.error(CLAUDE_INSTALL_HINT);
|
|
291
|
+
} else {
|
|
292
|
+
console.error(`❌ Failed to launch claude: ${err.message}`);
|
|
293
|
+
}
|
|
294
|
+
resolve(1);
|
|
295
|
+
});
|
|
296
|
+
child.on("exit", (code, signal) => {
|
|
297
|
+
const hint = claudeNotFoundHint(code, signal);
|
|
298
|
+
if (hint) console.error(hint);
|
|
299
|
+
resolve(signal ? 1 : code ?? 0);
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { autoRestoreCodexShim } from "../codex/shim";
|
|
2
|
+
import { codexShimAutoRestoreEnabled, readConfigDiagnostics } from "../config";
|
|
3
|
+
|
|
4
|
+
export interface CodexShimAutoRestoreCliDeps {
|
|
5
|
+
env: NodeJS.ProcessEnv;
|
|
6
|
+
warn: (message: string) => void;
|
|
7
|
+
restore: typeof autoRestoreCodexShim;
|
|
8
|
+
readConfig: typeof readConfigDiagnostics;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const DEFAULT_DEPS: CodexShimAutoRestoreCliDeps = {
|
|
12
|
+
env: process.env,
|
|
13
|
+
warn: message => console.warn(message),
|
|
14
|
+
restore: autoRestoreCodexShim,
|
|
15
|
+
readConfig: readConfigDiagnostics,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export function skipsCodexShimAutoRestore(command: string | undefined, args: string[]): boolean {
|
|
19
|
+
if (command === "uninstall" || command === "remove") return true;
|
|
20
|
+
return command === "codex-shim" && ["install", "uninstall", "remove"].includes(args[1] ?? "");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function maybeAutoRestoreCodexShim(
|
|
24
|
+
command: string | undefined,
|
|
25
|
+
args: string[],
|
|
26
|
+
deps: CodexShimAutoRestoreCliDeps = DEFAULT_DEPS,
|
|
27
|
+
): void {
|
|
28
|
+
if (skipsCodexShimAutoRestore(command, args)) return;
|
|
29
|
+
try {
|
|
30
|
+
const result = deps.restore({
|
|
31
|
+
enabled: () => codexShimAutoRestoreEnabled(deps.readConfig().config, deps.env),
|
|
32
|
+
});
|
|
33
|
+
if (result.status === "restored") {
|
|
34
|
+
deps.warn(`⚠️ ${result.message} (automatic repair after Codex update)`);
|
|
35
|
+
} else if ((result.status === "deferred" || result.status === "ineligible") && result.message) {
|
|
36
|
+
deps.warn(`⚠️ ${result.message}`);
|
|
37
|
+
}
|
|
38
|
+
} catch (error) {
|
|
39
|
+
deps.warn(
|
|
40
|
+
`⚠️ Codex shim auto-restore failed; continuing without it: ${
|
|
41
|
+
error instanceof Error ? error.message : String(error)
|
|
42
|
+
}. Run 'rmx codex-shim install' after the Codex update finishes.`,
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {
|
|
2
|
+
currentExternalCodexModelProvider,
|
|
3
|
+
getCodexRoutingKind,
|
|
4
|
+
type CodexRoutingKind,
|
|
5
|
+
} from "../codex/inject";
|
|
6
|
+
import { loadConfig, resolveEnvValue } from "../config";
|
|
7
|
+
|
|
8
|
+
const PROXY_ENV_KEYS = [
|
|
9
|
+
"HTTP_PROXY",
|
|
10
|
+
"HTTPS_PROXY",
|
|
11
|
+
"ALL_PROXY",
|
|
12
|
+
"http_proxy",
|
|
13
|
+
"https_proxy",
|
|
14
|
+
"all_proxy",
|
|
15
|
+
] as const;
|
|
16
|
+
|
|
17
|
+
export interface CodexShimReadinessInputs {
|
|
18
|
+
routingKind: CodexRoutingKind;
|
|
19
|
+
externalProvider: string | null;
|
|
20
|
+
processProxyEnvPresent: boolean;
|
|
21
|
+
configuredProxyResolved: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function externalProviderLabel(provider: string | null): string {
|
|
25
|
+
return provider
|
|
26
|
+
? `external model_provider ${JSON.stringify(provider)}`
|
|
27
|
+
: "the active Codex route";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function codexShimReadinessWarnings(
|
|
31
|
+
inputs: CodexShimReadinessInputs,
|
|
32
|
+
): string[] {
|
|
33
|
+
const warnings: string[] = [];
|
|
34
|
+
const provider = externalProviderLabel(inputs.externalProvider);
|
|
35
|
+
|
|
36
|
+
if (inputs.routingKind === "unknown") {
|
|
37
|
+
warnings.push(
|
|
38
|
+
inputs.externalProvider
|
|
39
|
+
? `Codex still selects ${provider}. The shim can start Remodex, but it does not redirect that provider; point it at the live Remodex /v1 endpoint with wire_api = "responses", or switch to the built-in openai provider and run 'rmx sync'.`
|
|
40
|
+
: "Codex routing could not be verified. The shim can start Remodex, but it may not redirect Codex; run 'rmx doctor' before relying on autostart.",
|
|
41
|
+
);
|
|
42
|
+
} else if (inputs.routingKind === "custom-local") {
|
|
43
|
+
warnings.push(
|
|
44
|
+
`Codex uses ${provider} through a user-owned local gateway. The shim can start Remodex, but Remodex does not own that route; run 'rmx doctor' to verify its lifecycle.`,
|
|
45
|
+
);
|
|
46
|
+
} else if (inputs.routingKind === "custom-remote") {
|
|
47
|
+
warnings.push(
|
|
48
|
+
`Codex uses ${provider} through a remote gateway. The shim only starts a local Remodex proxy and will not affect those requests.`,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (inputs.processProxyEnvPresent && !inputs.configuredProxyResolved) {
|
|
53
|
+
warnings.push(
|
|
54
|
+
"Proxy environment variables are present only in this process while config.proxy is unset or unresolved. Codex launchers and background services may not inherit them; persist config.proxy before relying on autostart.",
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return warnings;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function collectCodexShimReadinessWarnings(): string[] {
|
|
62
|
+
const config = loadConfig();
|
|
63
|
+
return codexShimReadinessWarnings({
|
|
64
|
+
routingKind: getCodexRoutingKind(),
|
|
65
|
+
externalProvider: currentExternalCodexModelProvider(),
|
|
66
|
+
processProxyEnvPresent: PROXY_ENV_KEYS.some(key => Boolean(process.env[key]?.trim())),
|
|
67
|
+
configuredProxyResolved: Boolean(resolveEnvValue(config.proxy)?.trim()),
|
|
68
|
+
});
|
|
69
|
+
}
|
package/src/cli/combo.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CliUsageError,
|
|
3
|
+
printData,
|
|
4
|
+
rejectArgs,
|
|
5
|
+
runCliAction,
|
|
6
|
+
runtimeRequest,
|
|
7
|
+
takeFlag,
|
|
8
|
+
takeIntegerOption,
|
|
9
|
+
takeOption,
|
|
10
|
+
type RuntimeApiDeps,
|
|
11
|
+
} from "./runtime-api";
|
|
12
|
+
|
|
13
|
+
const USAGE = `Usage:
|
|
14
|
+
rmx combo [list] [--json]
|
|
15
|
+
rmx combo show <id> [--json]
|
|
16
|
+
rmx combo set <id> --targets <provider/model[:weight],...>
|
|
17
|
+
[--strategy <failover|round-robin>] [--sticky <1-100>]
|
|
18
|
+
[--effort <low|medium|high|xhigh|max|ultra|->] [--alias <name|->]
|
|
19
|
+
[--native-alias] [--display-name <label|->]
|
|
20
|
+
[--rename-from <id>] [--json]
|
|
21
|
+
rmx combo remove <id> --yes [--json]`;
|
|
22
|
+
|
|
23
|
+
type ComboRow = Record<string, unknown> & { id?: string; model?: string };
|
|
24
|
+
|
|
25
|
+
function parseTargets(value: string): Array<{ provider: string; model: string; weight?: number }> {
|
|
26
|
+
const targets = value.split(",").map(part => part.trim()).filter(Boolean).map(part => {
|
|
27
|
+
const colon = part.lastIndexOf(":");
|
|
28
|
+
let selector = part;
|
|
29
|
+
let weight: number | undefined;
|
|
30
|
+
if (colon > part.indexOf("/")) {
|
|
31
|
+
const maybeWeight = Number(part.slice(colon + 1));
|
|
32
|
+
if (Number.isInteger(maybeWeight)) {
|
|
33
|
+
selector = part.slice(0, colon);
|
|
34
|
+
weight = maybeWeight;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const slash = selector.indexOf("/");
|
|
38
|
+
if (slash <= 0 || slash === selector.length - 1) throw new CliUsageError(`invalid target "${part}"; use provider/model[:weight]`, USAGE);
|
|
39
|
+
const target = { provider: selector.slice(0, slash), model: selector.slice(slash + 1), ...(weight !== undefined ? { weight } : {}) };
|
|
40
|
+
if (weight !== undefined && (weight < 1 || weight > 10_000)) throw new CliUsageError(`target weight must be 1-10000: ${part}`, USAGE);
|
|
41
|
+
return target;
|
|
42
|
+
});
|
|
43
|
+
if (targets.length === 0) throw new CliUsageError("--targets requires at least one provider/model", USAGE);
|
|
44
|
+
return targets;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function list(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
48
|
+
const args = [...argv];
|
|
49
|
+
const wantsJson = takeFlag(args, "--json");
|
|
50
|
+
rejectArgs(args, USAGE);
|
|
51
|
+
const result = await runtimeRequest<{ combos?: ComboRow[] }>("/api/combos", {}, deps);
|
|
52
|
+
const rows = result.combos ?? [];
|
|
53
|
+
printData(result, wantsJson, rows.length ? rows.map(row => `${String(row.id)} ${String(row.model ?? `combo/${row.id}`)}`) : ["No combos configured."]);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function show(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
57
|
+
const args = [...argv];
|
|
58
|
+
const id = args.shift();
|
|
59
|
+
const wantsJson = takeFlag(args, "--json");
|
|
60
|
+
if (!id) throw new CliUsageError("combo id is required", USAGE);
|
|
61
|
+
rejectArgs(args, USAGE);
|
|
62
|
+
const result = await runtimeRequest<{ combos?: ComboRow[] }>("/api/combos", {}, deps);
|
|
63
|
+
const combo = (result.combos ?? []).find(row => row.id === id);
|
|
64
|
+
if (!combo) throw new CliUsageError(`unknown combo ${id}`);
|
|
65
|
+
printData(combo, wantsJson);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function set(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
69
|
+
const args = [...argv];
|
|
70
|
+
const id = args.shift()?.trim();
|
|
71
|
+
const wantsJson = takeFlag(args, "--json");
|
|
72
|
+
if (!id) throw new CliUsageError("combo id is required", USAGE);
|
|
73
|
+
const targetsRaw = takeOption(args, "--targets");
|
|
74
|
+
if (!targetsRaw) throw new CliUsageError("--targets is required", USAGE);
|
|
75
|
+
const strategy = takeOption(args, "--strategy") ?? "failover";
|
|
76
|
+
if (strategy !== "failover" && strategy !== "round-robin") throw new CliUsageError("--strategy must be failover or round-robin", USAGE);
|
|
77
|
+
const stickyLimit = takeIntegerOption(args, "--sticky", { min: 1 }) ?? 1;
|
|
78
|
+
if (stickyLimit > 100) throw new CliUsageError("--sticky must be <= 100", USAGE);
|
|
79
|
+
const effort = takeOption(args, "--effort");
|
|
80
|
+
const alias = takeOption(args, "--alias");
|
|
81
|
+
const nativeAlias = takeFlag(args, "--native-alias");
|
|
82
|
+
const displayName = takeOption(args, "--display-name");
|
|
83
|
+
const renameFrom = takeOption(args, "--rename-from");
|
|
84
|
+
rejectArgs(args, USAGE);
|
|
85
|
+
const combo: Record<string, unknown> = {
|
|
86
|
+
strategy,
|
|
87
|
+
stickyLimit,
|
|
88
|
+
targets: parseTargets(targetsRaw),
|
|
89
|
+
};
|
|
90
|
+
if (effort !== undefined) combo.defaultEffort = effort === "-" ? null : effort;
|
|
91
|
+
if (alias !== undefined) combo.alias = alias === "-" ? "" : alias;
|
|
92
|
+
if (nativeAlias) combo.nativeAlias = true;
|
|
93
|
+
if (displayName !== undefined) combo.displayName = displayName === "-" ? "" : displayName;
|
|
94
|
+
const result = await runtimeRequest("/api/combos", {
|
|
95
|
+
method: "PUT",
|
|
96
|
+
body: JSON.stringify({ id, combo, ...(renameFrom ? { renameFrom } : {}) }),
|
|
97
|
+
}, deps);
|
|
98
|
+
printData(result, wantsJson, [`Saved combo ${id}.`]);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function remove(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
102
|
+
const args = [...argv];
|
|
103
|
+
const id = args.shift()?.trim();
|
|
104
|
+
const wantsJson = takeFlag(args, "--json");
|
|
105
|
+
const yes = takeFlag(args, "--yes");
|
|
106
|
+
if (!id) throw new CliUsageError("combo id is required", USAGE);
|
|
107
|
+
if (!yes) throw new CliUsageError("remove requires --yes", USAGE);
|
|
108
|
+
rejectArgs(args, USAGE);
|
|
109
|
+
const result = await runtimeRequest(`/api/combos?id=${encodeURIComponent(id)}`, { method: "DELETE" }, deps);
|
|
110
|
+
printData(result, wantsJson, [`Removed combo ${id}.`]);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export async function handleComboCommand(argv: string[], deps: RuntimeApiDeps = {}): Promise<number> {
|
|
114
|
+
return runCliAction(async () => {
|
|
115
|
+
const [sub = "list", ...rest] = argv;
|
|
116
|
+
if (sub === "list") await list(rest, deps);
|
|
117
|
+
else if (sub === "show") await show(rest, deps);
|
|
118
|
+
else if (sub === "set" || sub === "create" || sub === "update") await set(rest, deps);
|
|
119
|
+
else if (sub === "remove" || sub === "delete") await remove(rest, deps);
|
|
120
|
+
else throw new CliUsageError(`unknown combo command ${sub}`, USAGE);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export const COMBO_USAGE = USAGE;
|