@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,242 @@
|
|
|
1
|
+
/** Maximum number of response-body bytes that may be retained for an error. */
|
|
2
|
+
export const BOUNDED_BODY_MAX_BYTES = 65_536;
|
|
3
|
+
|
|
4
|
+
/** Default wall-clock and continuous-silence deadlines. */
|
|
5
|
+
export const BOUNDED_BODY_TIMEOUT_MS = 5_000;
|
|
6
|
+
|
|
7
|
+
export interface BoundedBodyOptions {
|
|
8
|
+
/** Abort the read with this signal. Its reason is rethrown by identity. */
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
/**
|
|
11
|
+
* Reject the returned promise with TypeError on malformed or truncated UTF-8
|
|
12
|
+
* instead of replacing invalid bytes, including during timeout-path flushes.
|
|
13
|
+
* Reader cancellation and lock release still run. Defaults to false.
|
|
14
|
+
*/
|
|
15
|
+
fatalUtf8?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Byte ceiling for retained body data. Defaults to BOUNDED_BODY_MAX_BYTES (64 KiB),
|
|
18
|
+
* which suits error bodies; callers materializing whole success payloads (e.g. a
|
|
19
|
+
* non-streaming upstream JSON completion) pass a larger explicit budget.
|
|
20
|
+
*/
|
|
21
|
+
maxBytes?: number;
|
|
22
|
+
/** Total wall-clock deadline. Exposed for focused tests. */
|
|
23
|
+
totalTimeoutMs?: number;
|
|
24
|
+
/** Deadline between non-empty raw chunks. Exposed for focused tests. */
|
|
25
|
+
inactivityTimeoutMs?: number;
|
|
26
|
+
/** Deadline for the first non-empty raw chunk. Defaults to inactivityTimeoutMs. */
|
|
27
|
+
firstByteTimeoutMs?: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface BoundedBodyResult {
|
|
31
|
+
/** UTF-8 text retained from the response. Empty when the size limit was exceeded. */
|
|
32
|
+
text: string;
|
|
33
|
+
/** True when EOF was not observed. */
|
|
34
|
+
truncated: boolean;
|
|
35
|
+
/** True for either total-deadline or inactivity-deadline expiry. */
|
|
36
|
+
timedOut: boolean;
|
|
37
|
+
/** Distinguishes the wall-clock deadline from an inactivity deadline. */
|
|
38
|
+
totalTimedOut: boolean;
|
|
39
|
+
/** True only when continuous inactivity caused the timeout. */
|
|
40
|
+
inactivityTimedOut: boolean;
|
|
41
|
+
/** True when the body was observed to exceed the byte cap. */
|
|
42
|
+
oversized: boolean;
|
|
43
|
+
/** False means callers should use a status-only fallback, not `text`. */
|
|
44
|
+
displaySafe: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const TOTAL_TIMEOUT = Symbol("bounded body total timeout");
|
|
48
|
+
const INACTIVITY_TIMEOUT = Symbol("bounded body inactivity timeout");
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Test-only instrumentation: how many times the retained buffer was reallocated
|
|
52
|
+
* during the most recent read. The accumulator grows geometrically, so this is
|
|
53
|
+
* logarithmic in the body size and independent of how many chunks the peer sends.
|
|
54
|
+
* The per-chunk array it replaced retained one object per chunk instead, which a
|
|
55
|
+
* fragmenting peer can inflate far past the payload ceiling — a property no
|
|
56
|
+
* correctness assertion can see, which is why it is observable here.
|
|
57
|
+
*/
|
|
58
|
+
let bufferGrowthsForTests = 0;
|
|
59
|
+
export function boundedBodyBufferGrowthsForTests(): number {
|
|
60
|
+
return bufferGrowthsForTests;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function timeoutPromise(ms: number, value: symbol): { promise: Promise<symbol>; clear: () => void } {
|
|
64
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
65
|
+
const promise = new Promise<symbol>((resolve) => {
|
|
66
|
+
timer = setTimeout(() => resolve(value), Math.max(0, ms));
|
|
67
|
+
});
|
|
68
|
+
return {
|
|
69
|
+
promise,
|
|
70
|
+
clear: () => {
|
|
71
|
+
if (timer !== undefined) clearTimeout(timer);
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function cancelWithoutWaiting(reader: ReadableStreamDefaultReader<Uint8Array>, reason?: unknown): void {
|
|
77
|
+
// A hostile/broken stream may reject or never settle cancel(). Neither should
|
|
78
|
+
// escape as an unhandled rejection or extend this primitive's own deadline.
|
|
79
|
+
try {
|
|
80
|
+
void reader.cancel(reason).catch(() => undefined);
|
|
81
|
+
} catch {
|
|
82
|
+
// Some stream implementations throw synchronously from cancel().
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function decodeUtf8(chunks: readonly Uint8Array[], fatal: boolean): string {
|
|
87
|
+
const decoder = new TextDecoder("utf-8", { fatal });
|
|
88
|
+
let text = "";
|
|
89
|
+
for (const chunk of chunks) text += decoder.decode(chunk, { stream: true });
|
|
90
|
+
// Flush an incomplete trailing UTF-8 sequence deterministically.
|
|
91
|
+
text += decoder.decode();
|
|
92
|
+
return text;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Consume the original response body under strict memory and time bounds.
|
|
97
|
+
*
|
|
98
|
+
* This deliberately calls `getReader()` on `response.body`: it never clones or
|
|
99
|
+
* tees the response. Once an over-limit byte is observed, all retained raw data
|
|
100
|
+
* is discarded so an untrusted prefix can never become a client-facing error.
|
|
101
|
+
*/
|
|
102
|
+
export async function readBoundedResponseBody(
|
|
103
|
+
response: Response,
|
|
104
|
+
options: BoundedBodyOptions = {},
|
|
105
|
+
): Promise<BoundedBodyResult> {
|
|
106
|
+
const signal = options.signal;
|
|
107
|
+
if (signal?.aborted) throw signal.reason;
|
|
108
|
+
|
|
109
|
+
const body = response.body;
|
|
110
|
+
if (!body) {
|
|
111
|
+
return {
|
|
112
|
+
text: "",
|
|
113
|
+
truncated: false,
|
|
114
|
+
timedOut: false,
|
|
115
|
+
totalTimedOut: false,
|
|
116
|
+
inactivityTimedOut: false,
|
|
117
|
+
oversized: false,
|
|
118
|
+
displaySafe: true,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const reader = body.getReader();
|
|
123
|
+
const maxBytes = options.maxBytes ?? BOUNDED_BODY_MAX_BYTES;
|
|
124
|
+
// Geometrically growing single buffer: per-chunk arrays would retain one object per
|
|
125
|
+
// transport chunk, which a hostile peer could inflate into metadata amplification far
|
|
126
|
+
// beyond the payload ceiling on large budgets.
|
|
127
|
+
let retained = new Uint8Array(Math.min(maxBytes, 64 * 1024));
|
|
128
|
+
let retainedBytes = 0;
|
|
129
|
+
bufferGrowthsForTests = 0;
|
|
130
|
+
let mustCancel = false;
|
|
131
|
+
let cancelReason: unknown;
|
|
132
|
+
const total = timeoutPromise(options.totalTimeoutMs ?? BOUNDED_BODY_TIMEOUT_MS, TOTAL_TIMEOUT);
|
|
133
|
+
let inactivity = timeoutPromise(
|
|
134
|
+
options.firstByteTimeoutMs ?? options.inactivityTimeoutMs ?? BOUNDED_BODY_TIMEOUT_MS,
|
|
135
|
+
INACTIVITY_TIMEOUT,
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
let rejectForAbort: ((reason: unknown) => void) | undefined;
|
|
139
|
+
const aborted = new Promise<never>((_resolve, reject) => {
|
|
140
|
+
rejectForAbort = reject;
|
|
141
|
+
});
|
|
142
|
+
const onAbort = () => rejectForAbort?.(signal?.reason);
|
|
143
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
144
|
+
// Close the narrow race between the preflight check and listener install.
|
|
145
|
+
if (signal?.aborted) onAbort();
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
while (true) {
|
|
149
|
+
// Attach a rejection handler before racing. If a deadline wins and
|
|
150
|
+
// cancellation later rejects this read, it remains observed.
|
|
151
|
+
const read = reader.read();
|
|
152
|
+
void read.catch(() => undefined);
|
|
153
|
+
const outcome = await Promise.race([read, total.promise, inactivity.promise, aborted]);
|
|
154
|
+
// Cancellation owns the body lifetime even when EOF/readability settles in
|
|
155
|
+
// the same turn. Promise.race otherwise lets array order hide the abort.
|
|
156
|
+
if (signal?.aborted) {
|
|
157
|
+
mustCancel = true;
|
|
158
|
+
cancelReason = signal.reason;
|
|
159
|
+
throw signal.reason;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (outcome === TOTAL_TIMEOUT || outcome === INACTIVITY_TIMEOUT) {
|
|
163
|
+
mustCancel = true;
|
|
164
|
+
cancelReason = new DOMException(
|
|
165
|
+
outcome === TOTAL_TIMEOUT ? "Error body total timeout" : "Error body inactivity timeout",
|
|
166
|
+
"TimeoutError",
|
|
167
|
+
);
|
|
168
|
+
return {
|
|
169
|
+
text: decodeUtf8([retained.subarray(0, retainedBytes)], options.fatalUtf8 === true),
|
|
170
|
+
truncated: true,
|
|
171
|
+
timedOut: true,
|
|
172
|
+
totalTimedOut: outcome === TOTAL_TIMEOUT,
|
|
173
|
+
inactivityTimedOut: outcome === INACTIVITY_TIMEOUT,
|
|
174
|
+
oversized: false,
|
|
175
|
+
displaySafe: false,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const { value, done } = outcome as ReadableStreamReadResult<Uint8Array>;
|
|
180
|
+
if (done) {
|
|
181
|
+
return {
|
|
182
|
+
text: decodeUtf8([retained.subarray(0, retainedBytes)], options.fatalUtf8 === true),
|
|
183
|
+
truncated: false,
|
|
184
|
+
timedOut: false,
|
|
185
|
+
totalTimedOut: false,
|
|
186
|
+
inactivityTimedOut: false,
|
|
187
|
+
oversized: false,
|
|
188
|
+
displaySafe: true,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (!value || value.byteLength === 0) continue;
|
|
193
|
+
|
|
194
|
+
inactivity.clear();
|
|
195
|
+
inactivity = timeoutPromise(
|
|
196
|
+
options.inactivityTimeoutMs ?? BOUNDED_BODY_TIMEOUT_MS,
|
|
197
|
+
INACTIVITY_TIMEOUT,
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
if (value.byteLength > maxBytes - retainedBytes) {
|
|
201
|
+
mustCancel = true;
|
|
202
|
+
cancelReason = new DOMException("Error body size limit reached", "QuotaExceededError");
|
|
203
|
+
retained = new Uint8Array(0);
|
|
204
|
+
retainedBytes = 0;
|
|
205
|
+
return {
|
|
206
|
+
text: "",
|
|
207
|
+
truncated: true,
|
|
208
|
+
timedOut: false,
|
|
209
|
+
totalTimedOut: false,
|
|
210
|
+
inactivityTimedOut: false,
|
|
211
|
+
oversized: true,
|
|
212
|
+
displaySafe: false,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (retainedBytes + value.byteLength > retained.length) {
|
|
217
|
+
const grown = new Uint8Array(
|
|
218
|
+
Math.min(maxBytes, Math.max(retained.length * 2, retainedBytes + value.byteLength)),
|
|
219
|
+
);
|
|
220
|
+
grown.set(retained.subarray(0, retainedBytes));
|
|
221
|
+
retained = grown;
|
|
222
|
+
bufferGrowthsForTests += 1;
|
|
223
|
+
}
|
|
224
|
+
retained.set(value, retainedBytes);
|
|
225
|
+
retainedBytes += value.byteLength;
|
|
226
|
+
}
|
|
227
|
+
} catch (error) {
|
|
228
|
+
mustCancel = true;
|
|
229
|
+
cancelReason = error;
|
|
230
|
+
throw error;
|
|
231
|
+
} finally {
|
|
232
|
+
total.clear();
|
|
233
|
+
inactivity.clear();
|
|
234
|
+
signal?.removeEventListener("abort", onAbort);
|
|
235
|
+
if (mustCancel) cancelWithoutWaiting(reader, cancelReason);
|
|
236
|
+
try {
|
|
237
|
+
reader.releaseLock();
|
|
238
|
+
} catch {
|
|
239
|
+
// A pending read can keep the lock briefly while cancel settles.
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { existsSync, statSync } from "node:fs";
|
|
2
|
+
|
|
3
|
+
// The `bun` package leaves a tiny ASCII placeholder at bin/bun.exe until its
|
|
4
|
+
// postinstall downloads the real ~60MB binary. Keep the threshold and the
|
|
5
|
+
// false-on-filesystem-error contract shared by the Node launcher and Bun code.
|
|
6
|
+
export const REAL_BUN_MIN_BYTES = 1_000_000;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {string} path
|
|
10
|
+
* @returns {boolean}
|
|
11
|
+
*/
|
|
12
|
+
export function isRealBunBinary(path) {
|
|
13
|
+
try {
|
|
14
|
+
return existsSync(path) && statSync(path).size >= REAL_BUN_MIN_BYTES;
|
|
15
|
+
} catch {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundled Bun runtime resolution.
|
|
3
|
+
*
|
|
4
|
+
* Remodex ships the Bun runtime via the `bun` npm dependency (esbuild-style:
|
|
5
|
+
* a tiny main package + platform-specific `@oven/bun-*` optionalDependencies,
|
|
6
|
+
* finalized by the package's own postinstall `node install.js`). The npm `bin`
|
|
7
|
+
* launcher (bin/ocx.mjs) and the durable service/shim integrations both need a
|
|
8
|
+
* stable path to that binary. This module is the single source of truth.
|
|
9
|
+
*
|
|
10
|
+
* In a from-source dev checkout the `bun` dependency may be absent; callers fall
|
|
11
|
+
* back to `process.execPath` (which is itself Bun when run via `bun src/cli/index.ts`).
|
|
12
|
+
*/
|
|
13
|
+
import { createRequire } from "node:module";
|
|
14
|
+
import { realpathSync } from "node:fs";
|
|
15
|
+
import { dirname, join } from "node:path";
|
|
16
|
+
import { isRealBunBinary } from "./bun-binary-validator.mjs";
|
|
17
|
+
|
|
18
|
+
export { isRealBunBinary };
|
|
19
|
+
|
|
20
|
+
const require = createRequire(import.meta.url);
|
|
21
|
+
|
|
22
|
+
const BUN_OVERRIDE_ENV = "OPENCODEX_BUN_PATH";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Env marker stamped by whichever launcher selected the Bun binary, then read back
|
|
26
|
+
* inside the launched process.
|
|
27
|
+
*
|
|
28
|
+
* Provenance has to travel with the launch because it cannot be recovered afterwards:
|
|
29
|
+
* resolving it at report time answers "what would this shell pick now", not "what was
|
|
30
|
+
* this service started with", and those differ exactly when the answer matters.
|
|
31
|
+
*/
|
|
32
|
+
export const BUN_RUNTIME_SOURCE_ENV = "OCX_BUN_RUNTIME_SOURCE";
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The binary the marker was minted for. Stamped beside the source so a reader can tell
|
|
36
|
+
* whether a marker still describes the process holding it, without re-deriving the
|
|
37
|
+
* selection from an environment that may no longer contain it.
|
|
38
|
+
*/
|
|
39
|
+
export const BUN_RUNTIME_PATH_ENV = "OCX_BUN_RUNTIME_PATH";
|
|
40
|
+
|
|
41
|
+
export type BunRuntimeSource = "override" | "bundled" | "process";
|
|
42
|
+
|
|
43
|
+
/** The only provenance values any surface may accept off the wire or out of the env. */
|
|
44
|
+
export const BUN_RUNTIME_SOURCES: readonly BunRuntimeSource[] = ["override", "bundled", "process"];
|
|
45
|
+
|
|
46
|
+
export type DurableBunRuntime = {
|
|
47
|
+
path: string;
|
|
48
|
+
source: BunRuntimeSource;
|
|
49
|
+
overrideEnv: typeof BUN_OVERRIDE_ENV;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The provenance this process was launched with, or `undefined` when nothing
|
|
54
|
+
* trustworthy is recorded.
|
|
55
|
+
*
|
|
56
|
+
* Deliberately never falls back to `durableBunRuntime()`. A service installed before
|
|
57
|
+
* the marker existed has no provenance, and guessing one from the current environment
|
|
58
|
+
* would report a confident wrong answer — "unknown" is the honest result and callers
|
|
59
|
+
* are expected to say so. Values outside the allowlist are treated as absent rather
|
|
60
|
+
* than passed through.
|
|
61
|
+
*/
|
|
62
|
+
export function reportedBunRuntimeSource(
|
|
63
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
64
|
+
): BunRuntimeSource | undefined {
|
|
65
|
+
const raw = env[BUN_RUNTIME_SOURCE_ENV]?.trim();
|
|
66
|
+
const source = BUN_RUNTIME_SOURCES.find(candidate => candidate === raw);
|
|
67
|
+
if (!source) return undefined;
|
|
68
|
+
// Source and binary are a PAIR: without a recorded path that names THIS
|
|
69
|
+
// executable, the marker describes some other launch and must not be
|
|
70
|
+
// reported (a bare OCX_BUN_RUNTIME_SOURCE inherited from an unrelated
|
|
71
|
+
// parent would otherwise claim a confident wrong origin).
|
|
72
|
+
const recordedPath = env[BUN_RUNTIME_PATH_ENV]?.trim();
|
|
73
|
+
if (!recordedPath || !samePath(recordedPath, process.execPath)) return undefined;
|
|
74
|
+
return source;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Env pair a launcher stamps for the binary it just selected. */
|
|
78
|
+
export function bunRuntimeProvenanceEnv(runtime: DurableBunRuntime): Record<string, string> {
|
|
79
|
+
return { [BUN_RUNTIME_SOURCE_ENV]: runtime.source, [BUN_RUNTIME_PATH_ENV]: runtime.path };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Child environment for a proxy started with `process.execPath` — the runtime this
|
|
84
|
+
* process is already using.
|
|
85
|
+
*
|
|
86
|
+
* These launchers re-exec the current runtime rather than resolving a binary, so the
|
|
87
|
+
* provenance to report is whatever launched THIS process. Without this the marker would
|
|
88
|
+
* be silently dropped on `rmx ensure`, GUI start, restart, and update-relaunch, and the
|
|
89
|
+
* service would report an unknown origin it actually knows.
|
|
90
|
+
*
|
|
91
|
+
* An inherited marker is carried forward only when the binary it was minted for is the
|
|
92
|
+
* one about to be re-executed. Inheritance travels down a process tree, so a marker can
|
|
93
|
+
* outlive its binary — something started under a marked process but running a different
|
|
94
|
+
* Bun would otherwise relaunch the daemon with a provenance contradicting the binary
|
|
95
|
+
* actually serving it. The check compares the recorded path rather than re-deriving the
|
|
96
|
+
* selection, because a service installed with a shell-local override keeps neither that
|
|
97
|
+
* shell nor its `OPENCODEX_BUN_PATH`, and re-deriving would demote a correct `override`
|
|
98
|
+
* to `process` on its first relaunch.
|
|
99
|
+
*/
|
|
100
|
+
export function withProcessRuntimeProvenance(
|
|
101
|
+
env: NodeJS.ProcessEnv,
|
|
102
|
+
): NodeJS.ProcessEnv {
|
|
103
|
+
return { ...env, ...bunRuntimeProvenanceEnv(currentRuntimeProvenance(env)) };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Provenance for `process.execPath`: the inherited claim when it was minted for this
|
|
108
|
+
* exact executable, otherwise what this executable actually is.
|
|
109
|
+
*/
|
|
110
|
+
function currentRuntimeProvenance(env: NodeJS.ProcessEnv): DurableBunRuntime {
|
|
111
|
+
const recorded = recordedCurrentRuntime(env);
|
|
112
|
+
if (recorded) return recorded;
|
|
113
|
+
// No marker that describes this binary: report what is running. One resolution
|
|
114
|
+
// supplies both halves so the pair can never disagree.
|
|
115
|
+
const runtime = unmarkedDurableBunRuntime();
|
|
116
|
+
return samePath(runtime.path, process.execPath)
|
|
117
|
+
? runtime
|
|
118
|
+
: { path: process.execPath, source: "process", overrideEnv: BUN_OVERRIDE_ENV };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function recordedCurrentRuntime(env: NodeJS.ProcessEnv): DurableBunRuntime | null {
|
|
122
|
+
const source = reportedBunRuntimeSource(env);
|
|
123
|
+
const path = env[BUN_RUNTIME_PATH_ENV]?.trim();
|
|
124
|
+
if (!source || !path || !samePath(path, process.execPath)) return null;
|
|
125
|
+
return { path, source, overrideEnv: BUN_OVERRIDE_ENV };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Same file, allowing for the aliases a path can pick up between launch and relaunch:
|
|
130
|
+
* symlinks/junctions, mapped drives, and Windows case differences. Falls back to a
|
|
131
|
+
* lexical comparison when a path cannot be resolved (it may be gone).
|
|
132
|
+
*/
|
|
133
|
+
function samePath(left: string, right: string): boolean {
|
|
134
|
+
const canonical = (value: string): string => {
|
|
135
|
+
let resolved = value;
|
|
136
|
+
try { resolved = realpathSync(value); } catch { /* keep the literal path */ }
|
|
137
|
+
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
138
|
+
};
|
|
139
|
+
return canonical(left) === canonical(right);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Absolute path to the bundled Bun binary, or null if the `bun` dependency is
|
|
144
|
+
* not installed/resolvable (or only the un-downloaded placeholder is present).
|
|
145
|
+
* The npm `bun` package ships the binary as `bin/bun.exe` on every platform;
|
|
146
|
+
* we also probe `bin/bun` for forward compatibility.
|
|
147
|
+
*/
|
|
148
|
+
export function bundledBunPath(): string | null {
|
|
149
|
+
try {
|
|
150
|
+
const bunDir = dirname(require.resolve("bun/package.json"));
|
|
151
|
+
for (const name of ["bun.exe", "bun"]) {
|
|
152
|
+
const p = join(bunDir, "bin", name);
|
|
153
|
+
if (isRealBunBinary(p)) return p;
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
} catch {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function unmarkedDurableBunRuntime(): DurableBunRuntime {
|
|
162
|
+
const bundled = bundledBunPath();
|
|
163
|
+
if (bundled) return { path: bundled, source: "bundled", overrideEnv: BUN_OVERRIDE_ENV };
|
|
164
|
+
return { path: process.execPath, source: "process", overrideEnv: BUN_OVERRIDE_ENV };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function durableBunRuntime(): DurableBunRuntime {
|
|
168
|
+
// A durable artifact must use the runtime selected BEFORE Bun auto-loaded a
|
|
169
|
+
// project dotenv. The Node launcher and owned service/shim launchers stamp the
|
|
170
|
+
// selected source/path pair; it is accepted only when it names this exact
|
|
171
|
+
// running executable. Re-reading OPENCODEX_BUN_PATH here would let a project
|
|
172
|
+
// `.env` persist an arbitrary executable into a shim or service.
|
|
173
|
+
return recordedCurrentRuntime(process.env) ?? unmarkedDurableBunRuntime();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Bun path to bake into durable artifacts (launchd/systemd/Task Scheduler and
|
|
178
|
+
* the Codex auto-start shim). Prefer the bundled binary — it lives under the
|
|
179
|
+
* npm global prefix and survives across `rmx update` — and fall back to the
|
|
180
|
+
* current runtime, which is Bun when launched normally.
|
|
181
|
+
*/
|
|
182
|
+
export function durableBunPath(): string {
|
|
183
|
+
return durableBunRuntime().path;
|
|
184
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bun runtime stream-capability gate for eager SSE passthrough (#314).
|
|
3
|
+
*
|
|
4
|
+
* The eager bounded relay (src/server/relay-eager.ts) uses a JS async producer
|
|
5
|
+
* loop — the exact shape of the Bun#32111 use-after-free (fixed upstream by Bun
|
|
6
|
+
* PR #32120, merged 2026-06-21). No RELEASED Bun version is proven to carry
|
|
7
|
+
* that fix yet, so `MIN_FIXED_BUN_VERSION` is null: every runtime is
|
|
8
|
+
* "known-bad" until a bundle-bump commit sets it. Windows no-rewrite traffic
|
|
9
|
+
* follows this runtime/config decision, preserving the explicit legacy-tee
|
|
10
|
+
* safety pin. Darwin no-rewrite traffic stays on tee
|
|
11
|
+
* for `auto` regardless of runtime capability and reaches eager relay only via
|
|
12
|
+
* explicit `streamMode: "eager-relay"` opt-in (see
|
|
13
|
+
* devlog/_fin/260731_macos_rss_retention/100_darwin_eager_optin.md).
|
|
14
|
+
*
|
|
15
|
+
* Prerelease conservatism: a version carrying a prerelease suffix (e.g.
|
|
16
|
+
* `1.4.0-canary.3`) is NEVER treated as fixed even when its numeric triple
|
|
17
|
+
* reaches the threshold — canaries are exactly the OPENCODEX_BUN_PATH audience
|
|
18
|
+
* and may predate the fix commit.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Bump in the SAME commit that bumps package.json's bundled Bun to a version
|
|
23
|
+
* verified to include Bun PR #32120. null = no released version is known-fixed.
|
|
24
|
+
*/
|
|
25
|
+
export const MIN_FIXED_BUN_VERSION: string | null = null;
|
|
26
|
+
|
|
27
|
+
export type StreamMode = "auto" | "legacy-tee" | "eager-relay";
|
|
28
|
+
|
|
29
|
+
export const STREAM_MODES: readonly StreamMode[] = ["auto", "legacy-tee", "eager-relay"];
|
|
30
|
+
|
|
31
|
+
export function isStreamMode(value: unknown): value is StreamMode {
|
|
32
|
+
return typeof value === "string" && (STREAM_MODES as readonly string[]).includes(value);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Numeric [major, minor, patch] triple, or null for unparseable input. */
|
|
36
|
+
export function parseBunVersion(version: string): [number, number, number] | null {
|
|
37
|
+
const m = /^(\d+)\.(\d+)\.(\d+)/.exec(version.trim());
|
|
38
|
+
if (!m) return null;
|
|
39
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Compare two version strings numerically; null when either is unparseable. */
|
|
43
|
+
export function compareBunVersions(a: string, b: string): number | null {
|
|
44
|
+
const pa = parseBunVersion(a);
|
|
45
|
+
const pb = parseBunVersion(b);
|
|
46
|
+
if (!pa || !pb) return null;
|
|
47
|
+
for (let i = 0; i < 3; i++) {
|
|
48
|
+
if (pa[i]! !== pb[i]!) return pa[i]! - pb[i]!;
|
|
49
|
+
}
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function hasPrereleaseSuffix(version: string): boolean {
|
|
54
|
+
return /^\d+\.\d+\.\d+-/.test(version.trim());
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* True only when `version` is proven to carry the Bun#32120 async-pull cancel
|
|
59
|
+
* fix. Conservative: unknown, unparseable, prerelease, or no threshold → false.
|
|
60
|
+
*/
|
|
61
|
+
export function bunHasAsyncPullCancelFix(
|
|
62
|
+
version: string,
|
|
63
|
+
minFixed: string | null = MIN_FIXED_BUN_VERSION,
|
|
64
|
+
): boolean {
|
|
65
|
+
if (!minFixed) return false;
|
|
66
|
+
if (hasPrereleaseSuffix(version)) return false;
|
|
67
|
+
const cmp = compareBunVersions(version, minFixed);
|
|
68
|
+
return cmp !== null && cmp >= 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export type EagerRelayDecision = {
|
|
72
|
+
useEagerRelay: boolean;
|
|
73
|
+
reason: "config-legacy" | "config-eager" | "auto-fixed-runtime" | "auto-known-bad";
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Decide the runtime/config SSE client-path capability. `version`/`minFixed`
|
|
78
|
+
* are injectable for tests; `selectEagerPath` applies platform policy.
|
|
79
|
+
*/
|
|
80
|
+
export function decideEagerRelay(
|
|
81
|
+
mode: StreamMode,
|
|
82
|
+
version: string = Bun.version,
|
|
83
|
+
minFixed: string | null = MIN_FIXED_BUN_VERSION,
|
|
84
|
+
): EagerRelayDecision {
|
|
85
|
+
if (mode === "legacy-tee") return { useEagerRelay: false, reason: "config-legacy" };
|
|
86
|
+
if (mode === "eager-relay") return { useEagerRelay: true, reason: "config-eager" };
|
|
87
|
+
return bunHasAsyncPullCancelFix(version, minFixed)
|
|
88
|
+
? { useEagerRelay: true, reason: "auto-fixed-runtime" }
|
|
89
|
+
: { useEagerRelay: false, reason: "auto-known-bad" };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Apply the two-platform eager-relay policy to the runtime/config capability.
|
|
94
|
+
* Windows preserves the decision for no-rewrite traffic. Darwin permits only
|
|
95
|
+
* explicit config opt-in; `auto` remains tee even on a future fixed runtime.
|
|
96
|
+
* Returns the normalized effective decision, or null when platform policy,
|
|
97
|
+
* Windows rewrite needs, or a Darwin non-config-eager mode selects tee.
|
|
98
|
+
*/
|
|
99
|
+
export function selectEagerPath(
|
|
100
|
+
platform: NodeJS.Platform,
|
|
101
|
+
needsClientRewrite: boolean,
|
|
102
|
+
mode: StreamMode,
|
|
103
|
+
version: string = Bun.version,
|
|
104
|
+
minFixed: string | null = MIN_FIXED_BUN_VERSION,
|
|
105
|
+
): EagerRelayDecision | null {
|
|
106
|
+
if (platform !== "win32" && platform !== "darwin") {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const decision = decideEagerRelay(mode, version, minFixed);
|
|
111
|
+
if (platform === "win32") return needsClientRewrite ? null : decision;
|
|
112
|
+
return decision.reason === "config-eager" ? decision : null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* #864 transport gate: win32 traffic that needs a client payload rewrite must
|
|
117
|
+
* use the eager single reader with the rewrite applied inline, because the
|
|
118
|
+
* alternative tee()+JS-pull chain is the Bun#32111-unsafe path that loses the
|
|
119
|
+
* terminal SSE block on Windows. Independent of the version-based eager
|
|
120
|
+
* policy: the pull chain is unsafe on the AFFECTED runtimes by definition.
|
|
121
|
+
*/
|
|
122
|
+
export function isWin32EagerRewrite(
|
|
123
|
+
platform: NodeJS.Platform,
|
|
124
|
+
needsClientRewrite: boolean,
|
|
125
|
+
): boolean {
|
|
126
|
+
return platform === "win32" && needsClientRewrite;
|
|
127
|
+
}
|