@yansigit/opencodex 2.31.0
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 +109 -0
- package/LICENSE +21 -0
- package/README.md +303 -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 +587 -0
- package/bin/package-main.mjs +9 -0
- package/gui/dist/assets/index-BNJ7r4Gd.js +102 -0
- package/gui/dist/assets/index-CGoDO3uO.css +1 -0
- package/gui/dist/favicon.png +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 +108 -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-output-schema.ts +137 -0
- package/src/adapters/anthropic.ts +1327 -0
- package/src/adapters/azure.ts +36 -0
- package/src/adapters/base.ts +121 -0
- package/src/adapters/client-fingerprint.ts +65 -0
- package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
- package/src/adapters/command-code.ts +601 -0
- package/src/adapters/cursor/arg-codec.ts +38 -0
- package/src/adapters/cursor/arg-normalize.ts +104 -0
- package/src/adapters/cursor/checkpoint-store.ts +303 -0
- package/src/adapters/cursor/cursor-errors.ts +288 -0
- package/src/adapters/cursor/discovery.ts +333 -0
- package/src/adapters/cursor/effort-map.ts +151 -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/h2-pool.ts +123 -0
- package/src/adapters/cursor/http1-bidi.ts +361 -0
- package/src/adapters/cursor/images.ts +704 -0
- package/src/adapters/cursor/kv-store.ts +52 -0
- package/src/adapters/cursor/live-models.ts +269 -0
- package/src/adapters/cursor/live-smoke-gate.ts +41 -0
- package/src/adapters/cursor/live-transport.ts +1653 -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 +76 -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 +547 -0
- package/src/adapters/cursor/native-exec-tools.ts +118 -0
- package/src/adapters/cursor/native-exec.ts +663 -0
- package/src/adapters/cursor/protobuf-events.ts +1381 -0
- package/src/adapters/cursor/protobuf-request.ts +1032 -0
- package/src/adapters/cursor/request-builder.ts +461 -0
- package/src/adapters/cursor/thread-continuity.ts +67 -0
- package/src/adapters/cursor/tool-definitions.ts +735 -0
- package/src/adapters/cursor/tool-result-normalize.ts +92 -0
- package/src/adapters/cursor/transport-retry.ts +132 -0
- package/src/adapters/cursor/transport.ts +79 -0
- package/src/adapters/cursor/types.ts +79 -0
- package/src/adapters/cursor.ts +322 -0
- package/src/adapters/google-antigravity-hosts.ts +48 -0
- package/src/adapters/google-antigravity-replay.ts +827 -0
- package/src/adapters/google-antigravity-tools.ts +105 -0
- package/src/adapters/google-antigravity-wire.ts +141 -0
- package/src/adapters/google-errors.ts +92 -0
- package/src/adapters/google-http.ts +460 -0
- package/src/adapters/google-tool-schema.ts +238 -0
- package/src/adapters/google-truncation.ts +24 -0
- package/src/adapters/google-wire-compiler.ts +232 -0
- package/src/adapters/google.ts +1377 -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 +112 -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 +1936 -0
- package/src/adapters/mimo-free.ts +280 -0
- package/src/adapters/openai-chat-url.ts +11 -0
- package/src/adapters/openai-chat.ts +1980 -0
- package/src/adapters/openai-responses-url.ts +16 -0
- package/src/adapters/openai-responses.ts +1911 -0
- package/src/adapters/registry.ts +175 -0
- package/src/adapters/responses-tool-schema.ts +67 -0
- package/src/adapters/run-turn-queue.ts +114 -0
- package/src/adapters/tool-call-id.ts +119 -0
- package/src/adapters/tool-catalog-nudge.ts +154 -0
- package/src/adapters/upstream-http-error.ts +48 -0
- package/src/adapters/xai-web-search.ts +185 -0
- package/src/bridge.ts +1986 -0
- package/src/chat/inbound.ts +319 -0
- package/src/chat/outbound.ts +821 -0
- package/src/claude/agents-inject.ts +266 -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 +205 -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 +615 -0
- package/src/claude/desktop-health.ts +26 -0
- package/src/claude/desktop-profile.ts +263 -0
- package/src/claude/gateway-cache.ts +107 -0
- package/src/claude/inbound-debug.ts +163 -0
- package/src/claude/inbound.ts +578 -0
- package/src/claude/model-info.ts +174 -0
- package/src/claude/outbound.ts +926 -0
- package/src/cli/access.ts +108 -0
- package/src/cli/account-api.ts +302 -0
- package/src/cli/account-auth.ts +250 -0
- package/src/cli/account-catalog-refresh.ts +14 -0
- package/src/cli/account-extended.ts +737 -0
- package/src/cli/account-main.ts +317 -0
- package/src/cli/account.ts +299 -0
- package/src/cli/agent-driven.ts +70 -0
- package/src/cli/agent.ts +290 -0
- package/src/cli/catalog-prewarm.ts +27 -0
- package/src/cli/claude-agent-startup-sync.ts +73 -0
- package/src/cli/claude-desktop.ts +213 -0
- package/src/cli/claude.ts +355 -0
- package/src/cli/codex-log-guard-doctor.ts +103 -0
- package/src/cli/codex-shim-autorestore.ts +47 -0
- package/src/cli/codex-shim-readiness.ts +76 -0
- package/src/cli/combo.ts +127 -0
- package/src/cli/config-command.ts +209 -0
- package/src/cli/debug.ts +228 -0
- package/src/cli/dispatch.ts +585 -0
- package/src/cli/doctor.ts +1202 -0
- package/src/cli/ensure-desired-integrations.ts +152 -0
- package/src/cli/export-command.ts +213 -0
- package/src/cli/help.ts +101 -0
- package/src/cli/index.ts +973 -0
- package/src/cli/init.ts +211 -0
- package/src/cli/integrations.ts +260 -0
- package/src/cli/interactive-confirm.ts +133 -0
- package/src/cli/lab.ts +607 -0
- package/src/cli/launcher-context.ts +77 -0
- package/src/cli/minimax.ts +497 -0
- package/src/cli/models-runtime.ts +245 -0
- package/src/cli/models.ts +422 -0
- package/src/cli/observe.ts +206 -0
- package/src/cli/opencode.ts +588 -0
- package/src/cli/provider-replit.ts +232 -0
- package/src/cli/provider-runtime.ts +179 -0
- package/src/cli/provider.ts +492 -0
- package/src/cli/ready.ts +301 -0
- package/src/cli/registry.ts +422 -0
- package/src/cli/replit-gateway-key-input.ts +138 -0
- package/src/cli/root.ts +86 -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 +328 -0
- package/src/cli/system-command.ts +112 -0
- package/src/cli/system-restart-client.ts +146 -0
- package/src/cli/tray-proxy.ts +199 -0
- package/src/cli/v2.ts +268 -0
- package/src/cli.ts +10 -0
- package/src/clients/config-export.ts +1704 -0
- package/src/codex/account-id.ts +34 -0
- package/src/codex/account-label.ts +47 -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 +544 -0
- package/src/codex/account-usability.ts +43 -0
- package/src/codex/admission.ts +256 -0
- package/src/codex/affinity-debug.ts +162 -0
- package/src/codex/agent-roles-sync.ts +225 -0
- package/src/codex/agent-roles.ts +238 -0
- package/src/codex/app-server-processes.ts +1143 -0
- package/src/codex/app-server-restart-service.ts +232 -0
- package/src/codex/auth-api.ts +2147 -0
- package/src/codex/auth-collision.ts +109 -0
- package/src/codex/auth-context.ts +665 -0
- package/src/codex/autostart-health.ts +156 -0
- package/src/codex/catalog/account-models.ts +67 -0
- package/src/codex/catalog/aggregation.ts +436 -0
- package/src/codex/catalog/bundled.ts +549 -0
- package/src/codex/catalog/effort.ts +446 -0
- package/src/codex/catalog/filesystem-evidence.ts +302 -0
- package/src/codex/catalog/kinds.ts +2 -0
- package/src/codex/catalog/metadata.ts +664 -0
- package/src/codex/catalog/native-models.ts +72 -0
- package/src/codex/catalog/parsing.ts +650 -0
- package/src/codex/catalog/provider-fetch.ts +2064 -0
- package/src/codex/catalog/sync.ts +1883 -0
- package/src/codex/catalog-admission.ts +199 -0
- package/src/codex/catalog-refresh-status.ts +105 -0
- package/src/codex/catalog-write-serialization.ts +242 -0
- package/src/codex/catalog.ts +14 -0
- package/src/codex/codex-write-lock.ts +384 -0
- package/src/codex/convergence-types.ts +614 -0
- package/src/codex/convergence.ts +651 -0
- package/src/codex/coordinator-doctor.ts +332 -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/exec-invocation.ts +22 -0
- package/src/codex/features.ts +1566 -0
- package/src/codex/generation.ts +202 -0
- package/src/codex/history-job.ts +407 -0
- package/src/codex/history-lock.ts +242 -0
- package/src/codex/history-migration-guardian.ts +108 -0
- package/src/codex/history-provider.ts +979 -0
- package/src/codex/history-transition.ts +105 -0
- package/src/codex/history-worker.ts +220 -0
- package/src/codex/home.ts +206 -0
- package/src/codex/inject-coordination.ts +290 -0
- package/src/codex/inject.ts +1733 -0
- package/src/codex/injected-marker.ts +106 -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 +80 -0
- package/src/codex/journal.ts +225 -0
- package/src/codex/log-guard/inspect.ts +506 -0
- package/src/codex/log-guard/lock.ts +150 -0
- package/src/codex/log-guard/maintenance.ts +403 -0
- package/src/codex/log-guard/path-safety.ts +88 -0
- package/src/codex/log-guard/policy.ts +44 -0
- package/src/codex/log-guard/processes.ts +205 -0
- package/src/codex/log-guard/protection.ts +489 -0
- package/src/codex/log-guard/sqlite-errors.ts +9 -0
- package/src/codex/main-account-cache.ts +56 -0
- package/src/codex/main-account.ts +68 -0
- package/src/codex/management-convergence.ts +167 -0
- package/src/codex/model-cache.ts +273 -0
- package/src/codex/model-entitlements.ts +353 -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 +178 -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 +492 -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 +682 -0
- package/src/codex/paths.ts +144 -0
- package/src/codex/plan-from-token.ts +140 -0
- package/src/codex/plan.ts +40 -0
- package/src/codex/plugins-doctor.ts +242 -0
- package/src/codex/pool-rotation.ts +295 -0
- package/src/codex/project-config-warnings.ts +425 -0
- package/src/codex/prompt-journal.ts +352 -0
- package/src/codex/prompt-layers.ts +967 -0
- package/src/codex/prompt-lock.ts +143 -0
- package/src/codex/quota-rejection.ts +298 -0
- package/src/codex/quota.ts +573 -0
- package/src/codex/refresh.ts +62 -0
- package/src/codex/reset-credit-recovery.ts +1044 -0
- package/src/codex/routing.ts +1888 -0
- package/src/codex/runtime.ts +659 -0
- package/src/codex/shim.ts +2170 -0
- package/src/codex/subagent-defaults.ts +550 -0
- package/src/codex/subagent-model-fallback.ts +784 -0
- package/src/codex/sync.ts +319 -0
- package/src/codex/transition-state.ts +612 -0
- package/src/codex/upstream-host-health.ts +368 -0
- package/src/codex/user-identity.ts +557 -0
- package/src/codex/warmup.ts +298 -0
- package/src/codex/websocket-registry.ts +100 -0
- package/src/codex/write-coordination.ts +114 -0
- package/src/combos/failover.ts +160 -0
- package/src/combos/index.ts +45 -0
- package/src/combos/request.ts +94 -0
- package/src/combos/resolve.ts +232 -0
- package/src/combos/types.ts +398 -0
- package/src/config/provider-name.ts +24 -0
- package/src/config.ts +4041 -0
- package/src/fork/register.ts +3 -0
- package/src/generated/compatibility-version.json +3116 -0
- package/src/generated/model-metadata.ts +106 -0
- package/src/github/star-state.ts +203 -0
- package/src/grok/inject.ts +530 -0
- package/src/grok/inspect.ts +45 -0
- package/src/grok/status.ts +121 -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 +955 -0
- package/src/images/plan.ts +143 -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 +269 -0
- package/src/integrations/journal.ts +315 -0
- package/src/integrations/merge.ts +135 -0
- package/src/integrations/mutation-flight.ts +71 -0
- package/src/integrations/native/ownership-preflight.ts +202 -0
- package/src/integrations/omp-yaml-source.ts +358 -0
- package/src/integrations/owned-refresh.ts +74 -0
- package/src/integrations/ownership.ts +111 -0
- package/src/integrations/registry.ts +159 -0
- package/src/integrations/serialize.ts +314 -0
- package/src/integrations/state.ts +361 -0
- package/src/integrations/store.ts +103 -0
- package/src/integrations/writer-lock.ts +98 -0
- package/src/integrations/writer.ts +691 -0
- package/src/lab/artifacts/sanitize.ts +586 -0
- package/src/lab/artifacts/secure-fs.ts +475 -0
- package/src/lab/artifacts/store.ts +310 -0
- package/src/lab/automation/budgets.ts +78 -0
- package/src/lab/automation/config-persistence.ts +256 -0
- package/src/lab/automation/constants.ts +39 -0
- package/src/lab/automation/cooldown.ts +103 -0
- package/src/lab/automation/dispatch.ts +211 -0
- package/src/lab/automation/index.ts +13 -0
- package/src/lab/automation/orchestrator.ts +499 -0
- package/src/lab/automation/persistence.ts +512 -0
- package/src/lab/automation/planner.ts +371 -0
- package/src/lab/automation/policy.ts +136 -0
- package/src/lab/automation/queue.ts +191 -0
- package/src/lab/automation/recovery.ts +24 -0
- package/src/lab/automation/route-context.ts +21 -0
- package/src/lab/automation/run-key.ts +44 -0
- package/src/lab/automation/runs-query.ts +34 -0
- package/src/lab/automation/types.ts +160 -0
- package/src/lab/conformance/assertion.ts +325 -0
- package/src/lab/conformance/digest.ts +22 -0
- package/src/lab/conformance/executor.ts +741 -0
- package/src/lab/conformance/fixture-provider.ts +27 -0
- package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
- package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
- package/src/lab/conformance/harness-budget.ts +47 -0
- package/src/lab/conformance/index.ts +5 -0
- package/src/lab/conformance/jcs.ts +64 -0
- package/src/lab/conformance/json-pointer.ts +39 -0
- package/src/lab/conformance/manifest.ts +180 -0
- package/src/lab/conformance/mcp-stub.ts +179 -0
- package/src/lab/conformance/negative-controls.ts +164 -0
- package/src/lab/conformance/observation.ts +355 -0
- package/src/lab/conformance/runner.ts +68 -0
- package/src/lab/conformance/sse-normalize.ts +59 -0
- package/src/lab/conformance/suite-manifest.ts +78 -0
- package/src/lab/conformance/types.ts +214 -0
- package/src/lab/constants.ts +126 -0
- package/src/lab/digest.ts +64 -0
- package/src/lab/events/errors.ts +9 -0
- package/src/lab/events/limits.ts +117 -0
- package/src/lab/events/types.ts +229 -0
- package/src/lab/events/validate.ts +781 -0
- package/src/lab/fabric/constants.ts +40 -0
- package/src/lab/fabric/executor.ts +492 -0
- package/src/lab/fabric/index.ts +80 -0
- package/src/lab/fabric/manifest.ts +222 -0
- package/src/lab/fabric/observe.ts +489 -0
- package/src/lab/fabric/patch.ts +79 -0
- package/src/lab/fabric/producer-child.ts +139 -0
- package/src/lab/fabric/producer-isolate.ts +276 -0
- package/src/lab/fabric/producer-protocol.ts +61 -0
- package/src/lab/fabric/scratch.ts +439 -0
- package/src/lab/fabric/subject.ts +106 -0
- package/src/lab/fabric/types.ts +134 -0
- package/src/lab/fabric/verifier.ts +98 -0
- package/src/lab/index.ts +54 -0
- package/src/lab/ledger/artifact-refs.ts +127 -0
- package/src/lab/ledger/invalidation.ts +136 -0
- package/src/lab/ledger/purge.ts +310 -0
- package/src/lab/ledger/store.ts +532 -0
- package/src/lab/live/credential-lease.ts +53 -0
- package/src/lab/live/destination.ts +155 -0
- package/src/lab/live/executor.ts +336 -0
- package/src/lab/live/inert-tools.ts +56 -0
- package/src/lab/live/manifest.ts +85 -0
- package/src/lab/live/mcp-loopback.ts +57 -0
- package/src/lab/live/runner.ts +19 -0
- package/src/lab/live/sandbox.ts +61 -0
- package/src/lab/live/suite-manifest.ts +41 -0
- package/src/lab/live/transport.ts +118 -0
- package/src/lab/live/types.ts +197 -0
- package/src/lab/observe/from-conformance.ts +301 -0
- package/src/lab/observe/from-live.ts +117 -0
- package/src/lab/paths.ts +153 -0
- package/src/lab/projection/rebuild.ts +495 -0
- package/src/lab/projection/schema.ts +135 -0
- package/src/lab/projection/verdicts.ts +474 -0
- package/src/lab/projection/verification.ts +412 -0
- package/src/lab/public/bundle.ts +217 -0
- package/src/lab/public/community-authority.ts +175 -0
- package/src/lab/public/community-files.ts +29 -0
- package/src/lab/public/community.ts +479 -0
- package/src/lab/public/file-safety.ts +155 -0
- package/src/lab/public/ids.ts +26 -0
- package/src/lab/public/index.ts +16 -0
- package/src/lab/public/mutation-lock.ts +424 -0
- package/src/lab/public/operator.ts +353 -0
- package/src/lab/public/origin-purge.ts +79 -0
- package/src/lab/public/origin.ts +203 -0
- package/src/lab/public/privacy.ts +143 -0
- package/src/lab/public/private-file.ts +261 -0
- package/src/lab/public/project.ts +124 -0
- package/src/lab/public/purge-test-fault.ts +21 -0
- package/src/lab/public/purge.ts +223 -0
- package/src/lab/public/registry.ts +44 -0
- package/src/lab/public/revocation.ts +252 -0
- package/src/lab/public/signature.ts +243 -0
- package/src/lab/public/storage.ts +105 -0
- package/src/lab/public/strict-json.ts +206 -0
- package/src/lab/public/time.ts +26 -0
- package/src/lab/public/types.ts +172 -0
- package/src/lab/public/validate.ts +391 -0
- package/src/lab/query/catalog.ts +101 -0
- package/src/lab/query/connection.ts +107 -0
- package/src/lab/query/constants.ts +4 -0
- package/src/lab/query/cursor.ts +132 -0
- package/src/lab/query/dto-map.ts +277 -0
- package/src/lab/query/errors.ts +22 -0
- package/src/lab/query/freshness.ts +53 -0
- package/src/lab/query/index.ts +45 -0
- package/src/lab/query/latest-observation.ts +59 -0
- package/src/lab/query/passive-production.ts +159 -0
- package/src/lab/query/queries.ts +444 -0
- package/src/lab/query/types.ts +266 -0
- package/src/lab/subject/behavior-fingerprint.ts +77 -0
- package/src/lab/subject/installation-salt.ts +112 -0
- package/src/lab/subject/protocol-subject.ts +80 -0
- package/src/lab/subject/route-subject.ts +74 -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 +195 -0
- package/src/lib/app-owned-memory.ts +265 -0
- package/src/lib/bounded-body.ts +346 -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 +130 -0
- package/src/lib/codex-restart-contract.ts +120 -0
- package/src/lib/config-ownership.ts +364 -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 +380 -0
- package/src/lib/errors.ts +406 -0
- package/src/lib/eventstream-decoder.ts +253 -0
- package/src/lib/fabric-task-execution-authority.ts +7 -0
- package/src/lib/fabric-task-host.ts +29 -0
- package/src/lib/gcp-adc.ts +341 -0
- package/src/lib/injection-debug-log.ts +58 -0
- package/src/lib/lab-activation.ts +223 -0
- package/src/lib/lab-live-execution-authority.ts +13 -0
- package/src/lib/lab-live-host.ts +30 -0
- package/src/lib/lab-live-pinned-sender.ts +56 -0
- package/src/lib/lab-live-route-production.ts +130 -0
- package/src/lib/lab-passive-linker-registration.ts +26 -0
- package/src/lib/local-management-attestation.ts +51 -0
- package/src/lib/local-management-capability.ts +100 -0
- package/src/lib/local-provider-reload-contract.ts +100 -0
- package/src/lib/open-url.ts +25 -0
- package/src/lib/optional-shutdown-hooks.ts +57 -0
- package/src/lib/pinned-http.ts +270 -0
- package/src/lib/privacy.ts +20 -0
- package/src/lib/process-control.ts +168 -0
- package/src/lib/provider-outbound.ts +210 -0
- package/src/lib/provider-url.ts +14 -0
- package/src/lib/proxy-env.ts +18 -0
- package/src/lib/redact.ts +521 -0
- package/src/lib/retry-after.ts +55 -0
- package/src/lib/self-launch-argv.ts +15 -0
- package/src/lib/server-resource-ownership.ts +71 -0
- package/src/lib/service-secrets.ts +25 -0
- package/src/lib/shadow-call.ts +61 -0
- package/src/lib/sidecar-tracker.ts +52 -0
- package/src/lib/sse-decoder.ts +364 -0
- package/src/lib/state-store-registrations.ts +119 -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 +90 -0
- package/src/lib/token-estimate.ts +86 -0
- package/src/lib/tool-argument-integers.ts +202 -0
- package/src/lib/translator-budget.ts +400 -0
- package/src/lib/upstream-http-version.ts +57 -0
- package/src/lib/upstream-reachability.ts +95 -0
- package/src/lib/upstream-retry.ts +392 -0
- package/src/lib/win-exec.ts +115 -0
- package/src/lib/win-paths.ts +68 -0
- package/src/lib/windows-atomic-replace.ts +156 -0
- package/src/lib/windows-elevation.ts +773 -0
- package/src/lib/windows-secret-acl.ts +854 -0
- package/src/lib/windows-service-wrappers.ts +72 -0
- package/src/lib/windows-text.ts +106 -0
- package/src/lib/windows-user-principal.ts +341 -0
- package/src/lib/winsw.ts +403 -0
- package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
- package/src/oauth/account-import/index.ts +15 -0
- package/src/oauth/account-import/parser.ts +83 -0
- package/src/oauth/account-import/registry.ts +18 -0
- package/src/oauth/account-import/service.ts +75 -0
- package/src/oauth/account-import/types.ts +91 -0
- package/src/oauth/anthropic-routing.ts +594 -0
- package/src/oauth/anthropic.ts +188 -0
- package/src/oauth/antigravity-routing.ts +151 -0
- package/src/oauth/callback-server.ts +300 -0
- package/src/oauth/chatgpt.ts +161 -0
- package/src/oauth/command-code.ts +239 -0
- package/src/oauth/cursor.ts +252 -0
- package/src/oauth/github-copilot.ts +428 -0
- package/src/oauth/google-antigravity.ts +262 -0
- package/src/oauth/health.ts +407 -0
- package/src/oauth/index.ts +1504 -0
- package/src/oauth/key-providers.ts +124 -0
- package/src/oauth/kimi.ts +227 -0
- package/src/oauth/kiro-credentials.ts +726 -0
- package/src/oauth/kiro.ts +621 -0
- package/src/oauth/local-token-detect.ts +130 -0
- package/src/oauth/log.ts +50 -0
- package/src/oauth/login-cli.ts +223 -0
- package/src/oauth/nous.ts +798 -0
- package/src/oauth/pkce.ts +15 -0
- package/src/oauth/store.ts +728 -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 +695 -0
- package/src/providers/antigravity-quota.ts +216 -0
- package/src/providers/api-keys.ts +140 -0
- package/src/providers/base-url-choices.ts +74 -0
- package/src/providers/codex-capacity.ts +292 -0
- package/src/providers/command-code-efforts.ts +144 -0
- package/src/providers/context-cap.ts +82 -0
- package/src/providers/cursor-pool.ts +72 -0
- package/src/providers/derive.ts +586 -0
- package/src/providers/fastwire.ts +501 -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 +449 -0
- package/src/providers/model-rename-migration.ts +255 -0
- package/src/providers/model-rename-startup.ts +28 -0
- package/src/providers/openai-sidecar.ts +243 -0
- package/src/providers/openai-tier-startup.ts +56 -0
- package/src/providers/openai-tiers.ts +423 -0
- package/src/providers/openai-virtual-models.ts +83 -0
- package/src/providers/opencode-zen-rate-limit.ts +102 -0
- package/src/providers/openrouter-routing.ts +102 -0
- package/src/providers/provider-id-rewrite.ts +185 -0
- package/src/providers/quota.ts +2345 -0
- package/src/providers/registry.ts +2918 -0
- package/src/providers/replit/constants.ts +27 -0
- package/src/providers/replit/derive.ts +85 -0
- package/src/providers/replit/headers.ts +28 -0
- package/src/providers/replit/origin.ts +55 -0
- package/src/providers/replit/pair-install-response.ts +72 -0
- package/src/providers/replit/probe.ts +199 -0
- package/src/providers/replit/setup.ts +350 -0
- package/src/providers/request-pacing.ts +310 -0
- package/src/providers/service-tier.ts +277 -0
- package/src/providers/slug-codec.ts +103 -0
- package/src/providers/static-model-discovery.ts +86 -0
- package/src/providers/xai-responses-opt-in.ts +15 -0
- package/src/providers/xai-transport.ts +148 -0
- package/src/reasoning-effort.ts +183 -0
- package/src/responses/compaction.ts +142 -0
- package/src/responses/custom-tool-compat.ts +266 -0
- package/src/responses/hosted-tool-policy.ts +9 -0
- package/src/responses/namespace-tool-compat.ts +355 -0
- package/src/responses/parser.ts +838 -0
- package/src/responses/provider-continuation.ts +98 -0
- package/src/responses/provider-opaque-metadata.ts +73 -0
- package/src/responses/reasoning-envelope.ts +60 -0
- package/src/responses/reasoning-replay-cache.ts +426 -0
- package/src/responses/schema.ts +165 -0
- package/src/responses/spill-store.ts +459 -0
- package/src/responses/state.ts +1433 -0
- package/src/responses/thought-signature-replay.ts +347 -0
- package/src/responses/tool-groups.ts +19 -0
- package/src/responses/tool-search-compat.ts +301 -0
- package/src/responses/truncated-stop-reason.ts +60 -0
- package/src/router.ts +761 -0
- package/src/routing/analytics.ts +378 -0
- package/src/routing/capability.ts +244 -0
- package/src/routing/compatibility/assemble.ts +73 -0
- package/src/routing/compatibility/behavior.ts +278 -0
- package/src/routing/compatibility/catalog.ts +99 -0
- package/src/routing/compatibility/endpoint.ts +52 -0
- package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
- package/src/routing/compatibility/policy.ts +181 -0
- package/src/routing/compatibility/provider-slot.ts +56 -0
- package/src/routing/compatibility/reader.ts +110 -0
- package/src/routing/compatibility/subject.ts +191 -0
- package/src/routing/compatibility/types.ts +64 -0
- package/src/routing/compatibility/version.ts +104 -0
- package/src/routing/cost.ts +77 -0
- package/src/routing/evaluator.ts +495 -0
- package/src/routing/health.ts +412 -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 +547 -0
- package/src/routing/quota.ts +145 -0
- package/src/routing/request-evidence.ts +45 -0
- package/src/routing/trace.ts +776 -0
- package/src/server/adapter-resolve.ts +53 -0
- package/src/server/auth-cors.ts +751 -0
- package/src/server/background-lifecycle.ts +182 -0
- package/src/server/chat-completions.ts +442 -0
- package/src/server/chat-native-sse.ts +331 -0
- package/src/server/chat-native.ts +426 -0
- package/src/server/claude-messages.ts +1030 -0
- package/src/server/direct-local-http.ts +347 -0
- package/src/server/effort-policy.ts +190 -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 +568 -0
- package/src/server/index.ts +1813 -0
- package/src/server/lifecycle.ts +498 -0
- package/src/server/live.ts +717 -0
- package/src/server/local-management-read-client.ts +90 -0
- package/src/server/local-provider-reload-client.ts +137 -0
- package/src/server/management/agent-settings-routes.ts +1433 -0
- package/src/server/management/api-access.ts +141 -0
- package/src/server/management/api-key-usage.ts +193 -0
- package/src/server/management/body.ts +41 -0
- package/src/server/management/combo-routes.ts +263 -0
- package/src/server/management/config-routes.ts +835 -0
- package/src/server/management/context.ts +113 -0
- package/src/server/management/integration-routes.ts +498 -0
- package/src/server/management/lab-automation-routes.ts +206 -0
- package/src/server/management/lab-routes.ts +563 -0
- package/src/server/management/logs-usage-routes.ts +586 -0
- package/src/server/management/model-routes.ts +560 -0
- package/src/server/management/model-rows.ts +163 -0
- package/src/server/management/native-integration-routes.ts +769 -0
- package/src/server/management/oauth-account-routes.ts +637 -0
- package/src/server/management/provider-capability-config.ts +48 -0
- package/src/server/management/provider-routes.ts +1033 -0
- package/src/server/management/replit-provider-routes.ts +86 -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 +385 -0
- package/src/server/management/shared.ts +286 -0
- package/src/server/management/sidebar-routes.ts +106 -0
- package/src/server/management/storage-log-guard-routes.ts +186 -0
- package/src/server/management/sync-response.ts +69 -0
- package/src/server/management/system-restart.ts +435 -0
- package/src/server/management/system-routes.ts +194 -0
- package/src/server/management/usage-summary-cache.ts +94 -0
- package/src/server/management/vision-sidecar-options.ts +167 -0
- package/src/server/management/web-search-sidecar-options.ts +120 -0
- package/src/server/management-api.ts +314 -0
- package/src/server/management-auth.ts +482 -0
- package/src/server/memory-watchdog.ts +156 -0
- package/src/server/passive-route-linker.ts +66 -0
- package/src/server/port-reclaim.ts +307 -0
- package/src/server/ports.ts +156 -0
- package/src/server/proxy-liveness.ts +328 -0
- package/src/server/readiness.ts +99 -0
- package/src/server/relay-eager.ts +353 -0
- package/src/server/relay.ts +1209 -0
- package/src/server/request-decompress.ts +239 -0
- package/src/server/request-log-conversation.ts +168 -0
- package/src/server/request-log.ts +1259 -0
- package/src/server/responses/agent-task-recovery-cache.ts +143 -0
- package/src/server/responses/agent-task-recovery.ts +465 -0
- package/src/server/responses/collaboration.ts +551 -0
- package/src/server/responses/compact.ts +771 -0
- package/src/server/responses/core.ts +5389 -0
- package/src/server/responses/empty-completion-guard.ts +276 -0
- package/src/server/responses/encrypted-payload.ts +331 -0
- package/src/server/responses/fetch-helpers.ts +232 -0
- package/src/server/responses/input-admission.ts +185 -0
- package/src/server/responses/pacing-overload.ts +13 -0
- package/src/server/responses/passthrough-error.ts +78 -0
- package/src/server/responses/policy-fallback.ts +178 -0
- package/src/server/responses/responses-field-backfill.ts +251 -0
- package/src/server/responses/terminal-guard.ts +251 -0
- package/src/server/responses/upstream-error.ts +53 -0
- package/src/server/responses/ws-upstream.ts +308 -0
- package/src/server/responses-custom-tool-repair.ts +282 -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 +90 -0
- package/src/server/responses-model-rewrite.ts +29 -0
- package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
- package/src/server/responses-snapshot-repair.ts +621 -0
- package/src/server/responses-terminal-repair.ts +342 -0
- package/src/server/responses-tool-search-repair.ts +267 -0
- package/src/server/responses-undeclared-tool-guard.ts +153 -0
- package/src/server/responses.ts +25 -0
- package/src/server/search.ts +201 -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 +315 -0
- package/src/server/startup-health-cache.ts +131 -0
- package/src/server/system-env.ts +484 -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 +472 -0
- package/src/service-manager-probe.ts +892 -0
- package/src/service.ts +3575 -0
- package/src/sidecar/auth.ts +92 -0
- package/src/sidecar/candidates.ts +83 -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 +757 -0
- package/src/types/accounts.ts +37 -0
- package/src/types/config.ts +876 -0
- package/src/types/provider.ts +545 -0
- package/src/types/request.ts +384 -0
- package/src/types/tools.ts +131 -0
- package/src/types/wire.ts +80 -0
- package/src/types.ts +106 -0
- package/src/update/badge.ts +72 -0
- package/src/update/index.ts +415 -0
- package/src/update/job.ts +1887 -0
- package/src/update/notify.ts +263 -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/transactional-install.d.mts +22 -0
- package/src/update/transactional-install.mjs +259 -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 +625 -0
- package/src/usage/debug.ts +97 -0
- package/src/usage/expected-prices.ts +416 -0
- package/src/usage/log.ts +1223 -0
- package/src/usage/summary.ts +753 -0
- package/src/usage/totals.ts +14 -0
- package/src/usage/user-cost-overlay-reconciler.ts +313 -0
- package/src/usage/user-cost-overlays.ts +314 -0
- package/src/vision/anthropic-describe.ts +189 -0
- package/src/vision/backends.ts +97 -0
- package/src/vision/describe.ts +131 -0
- package/src/vision/eligibility.ts +250 -0
- package/src/vision/index.ts +681 -0
- package/src/vision/reasoning.ts +55 -0
- package/src/vision/routed-describe.ts +175 -0
- package/src/vision/timeout-bounds.ts +9 -0
- package/src/web-search/anthropic-executor.ts +195 -0
- package/src/web-search/backends.ts +108 -0
- package/src/web-search/exa-executor.ts +88 -0
- package/src/web-search/executor.ts +113 -0
- package/src/web-search/format-result.ts +89 -0
- package/src/web-search/gemini-executor.ts +141 -0
- package/src/web-search/index.ts +331 -0
- package/src/web-search/loop.ts +896 -0
- package/src/web-search/parse.ts +315 -0
- package/src/web-search/progress-stream.ts +342 -0
- package/src/web-search/sources.ts +60 -0
- package/src/web-search/synthetic-tool.ts +47 -0
- package/src/web-search/xai-executor.ts +219 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
export type AppOwnedRetainedCategory = "logs" | "caches" | "blobs" | "continuation";
|
|
2
|
+
export type AppOwnedObservedCategory = "translator" | "serialized_tails";
|
|
3
|
+
|
|
4
|
+
export interface RetainedStoreSnapshot {
|
|
5
|
+
count: number;
|
|
6
|
+
bytes: number;
|
|
7
|
+
evictableBytes: number;
|
|
8
|
+
pinnedBytes: number;
|
|
9
|
+
oldestAt: number | null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface RetainedStoreRegistration {
|
|
13
|
+
id: string;
|
|
14
|
+
category: AppOwnedRetainedCategory;
|
|
15
|
+
snapshot(): RetainedStoreSnapshot;
|
|
16
|
+
evictOldest(): number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ObservedBufferRegistration {
|
|
20
|
+
id: string;
|
|
21
|
+
category: AppOwnedObservedCategory;
|
|
22
|
+
snapshot(): { currentBytes: number; highWaterBytes: number; active: number };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface AppOwnedBytesSnapshot {
|
|
26
|
+
budgetBytes: number;
|
|
27
|
+
retainedBytes: number;
|
|
28
|
+
evictableBytes: number;
|
|
29
|
+
pinnedBytes: number;
|
|
30
|
+
overBudgetBytes: number;
|
|
31
|
+
stores: Record<string, RetainedStoreSnapshot>;
|
|
32
|
+
observedInFlight: Record<string, { currentBytes: number; highWaterBytes: number; active: number }>;
|
|
33
|
+
enforcement: {
|
|
34
|
+
runs: number;
|
|
35
|
+
entriesDemoted: number;
|
|
36
|
+
bytesReleased: number;
|
|
37
|
+
noEvictableCandidate: number;
|
|
38
|
+
snapshotFailures: number;
|
|
39
|
+
oldestAtContractViolations: number;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const DEFAULT_APP_OWNED_MEMORY_BUDGET_BYTES = 256 * 1024 * 1024;
|
|
44
|
+
/**
|
|
45
|
+
* The budget above is an eviction target, not a hard resident limit: active/pinned
|
|
46
|
+
* state may temporarily keep retained bytes above it. Every pin-capable owner has
|
|
47
|
+
* its own finite admission cap; their documented aggregate must remain below this
|
|
48
|
+
* process-owned hard ceiling.
|
|
49
|
+
*/
|
|
50
|
+
export const APP_OWNED_WORST_CASE_PINNED_BYTES = 512 * 1024 * 1024;
|
|
51
|
+
export const MIN_APP_OWNED_MEMORY_BUDGET_MB = 64;
|
|
52
|
+
export const MAX_APP_OWNED_MEMORY_BUDGET_MB = 4_096;
|
|
53
|
+
|
|
54
|
+
const CATEGORY_ORDER: readonly AppOwnedRetainedCategory[] = [
|
|
55
|
+
"logs",
|
|
56
|
+
"caches",
|
|
57
|
+
"blobs",
|
|
58
|
+
"continuation",
|
|
59
|
+
];
|
|
60
|
+
const WARN_INTERVAL_MS = 60_000;
|
|
61
|
+
const ZERO_RETAINED_SNAPSHOT: RetainedStoreSnapshot = {
|
|
62
|
+
count: 0,
|
|
63
|
+
bytes: 0,
|
|
64
|
+
evictableBytes: 0,
|
|
65
|
+
pinnedBytes: 0,
|
|
66
|
+
oldestAt: null,
|
|
67
|
+
};
|
|
68
|
+
const ZERO_OBSERVED_SNAPSHOT = { currentBytes: 0, highWaterBytes: 0, active: 0 };
|
|
69
|
+
|
|
70
|
+
const retainedStores = new Map<string, RetainedStoreRegistration>();
|
|
71
|
+
const observedBuffers = new Map<string, ObservedBufferRegistration>();
|
|
72
|
+
let budgetBytes = DEFAULT_APP_OWNED_MEMORY_BUDGET_BYTES;
|
|
73
|
+
let lastSaturationWarningAt = Number.NEGATIVE_INFINITY;
|
|
74
|
+
const enforcementCounters = {
|
|
75
|
+
runs: 0,
|
|
76
|
+
entriesDemoted: 0,
|
|
77
|
+
bytesReleased: 0,
|
|
78
|
+
noEvictableCandidate: 0,
|
|
79
|
+
snapshotFailures: 0,
|
|
80
|
+
oldestAtContractViolations: 0,
|
|
81
|
+
};
|
|
82
|
+
let isEnforcing = false;
|
|
83
|
+
|
|
84
|
+
export function resolveAppOwnedMemoryBudgetBytes(value: unknown): number {
|
|
85
|
+
return typeof value === "number"
|
|
86
|
+
&& Number.isInteger(value)
|
|
87
|
+
&& value >= MIN_APP_OWNED_MEMORY_BUDGET_MB
|
|
88
|
+
&& value <= MAX_APP_OWNED_MEMORY_BUDGET_MB
|
|
89
|
+
? value * 1024 * 1024
|
|
90
|
+
: DEFAULT_APP_OWNED_MEMORY_BUDGET_BYTES;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function registerRetainedStore(registration: RetainedStoreRegistration): () => void {
|
|
94
|
+
retainedStores.set(registration.id, registration);
|
|
95
|
+
return () => {
|
|
96
|
+
if (retainedStores.get(registration.id) === registration) retainedStores.delete(registration.id);
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function registerObservedBuffer(registration: ObservedBufferRegistration): () => void {
|
|
101
|
+
observedBuffers.set(registration.id, registration);
|
|
102
|
+
return () => {
|
|
103
|
+
if (observedBuffers.get(registration.id) === registration) observedBuffers.delete(registration.id);
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function configureAppOwnedMemoryBudget(bytes: number): void {
|
|
108
|
+
budgetBytes = bytes;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function retainedSnapshot(registration: RetainedStoreRegistration): RetainedStoreSnapshot {
|
|
112
|
+
try {
|
|
113
|
+
return registration.snapshot();
|
|
114
|
+
} catch {
|
|
115
|
+
enforcementCounters.snapshotFailures += 1;
|
|
116
|
+
return { ...ZERO_RETAINED_SNAPSHOT };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function observedSnapshot(
|
|
121
|
+
registration: ObservedBufferRegistration,
|
|
122
|
+
): { currentBytes: number; highWaterBytes: number; active: number } {
|
|
123
|
+
try {
|
|
124
|
+
return registration.snapshot();
|
|
125
|
+
} catch {
|
|
126
|
+
enforcementCounters.snapshotFailures += 1;
|
|
127
|
+
return { ...ZERO_OBSERVED_SNAPSHOT };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function appOwnedBytesSnapshot(): AppOwnedBytesSnapshot {
|
|
132
|
+
return appOwnedBytesSnapshotFrom(retainedSnapshots().stores);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function appOwnedBytesSnapshotFrom(
|
|
136
|
+
retained: ReadonlyMap<string, RetainedStoreSnapshot>,
|
|
137
|
+
): AppOwnedBytesSnapshot {
|
|
138
|
+
const stores: Record<string, RetainedStoreSnapshot> = {};
|
|
139
|
+
let retainedBytes = 0;
|
|
140
|
+
let evictableBytes = 0;
|
|
141
|
+
let pinnedBytes = 0;
|
|
142
|
+
for (const registration of retainedStores.values()) {
|
|
143
|
+
const snapshot = retained.get(registration.id) ?? ZERO_RETAINED_SNAPSHOT;
|
|
144
|
+
stores[registration.id] = snapshot;
|
|
145
|
+
retainedBytes += snapshot.bytes;
|
|
146
|
+
evictableBytes += snapshot.evictableBytes;
|
|
147
|
+
pinnedBytes += snapshot.pinnedBytes;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const observedInFlight: AppOwnedBytesSnapshot["observedInFlight"] = {};
|
|
151
|
+
for (const registration of observedBuffers.values()) {
|
|
152
|
+
observedInFlight[registration.id] = observedSnapshot(registration);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
budgetBytes,
|
|
157
|
+
retainedBytes,
|
|
158
|
+
evictableBytes,
|
|
159
|
+
pinnedBytes,
|
|
160
|
+
overBudgetBytes: Math.max(0, retainedBytes - budgetBytes),
|
|
161
|
+
stores,
|
|
162
|
+
observedInFlight,
|
|
163
|
+
enforcement: { ...enforcementCounters },
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function nextCandidate(
|
|
168
|
+
snapshots: ReadonlyMap<string, RetainedStoreSnapshot>,
|
|
169
|
+
ineligible: Set<string>,
|
|
170
|
+
): RetainedStoreRegistration | undefined {
|
|
171
|
+
for (const category of CATEGORY_ORDER) {
|
|
172
|
+
let candidate: RetainedStoreRegistration | undefined;
|
|
173
|
+
let candidateAt = Number.POSITIVE_INFINITY;
|
|
174
|
+
for (const registration of retainedStores.values()) {
|
|
175
|
+
if (registration.category !== category || ineligible.has(registration.id)) continue;
|
|
176
|
+
const snapshot = snapshots.get(registration.id);
|
|
177
|
+
if (!snapshot || snapshot.evictableBytes <= 0) continue;
|
|
178
|
+
const oldestAt = snapshot.oldestAt;
|
|
179
|
+
if (oldestAt === null || !Number.isFinite(oldestAt)) {
|
|
180
|
+
enforcementCounters.oldestAtContractViolations += 1;
|
|
181
|
+
ineligible.add(registration.id);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (!candidate || oldestAt < candidateAt) {
|
|
185
|
+
candidate = registration;
|
|
186
|
+
candidateAt = oldestAt;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (candidate) return candidate;
|
|
190
|
+
}
|
|
191
|
+
return undefined;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function retainedSnapshots(): { total: number; stores: Map<string, RetainedStoreSnapshot> } {
|
|
195
|
+
const stores = new Map<string, RetainedStoreSnapshot>();
|
|
196
|
+
let total = 0;
|
|
197
|
+
for (const registration of retainedStores.values()) {
|
|
198
|
+
const snapshot = retainedSnapshot(registration);
|
|
199
|
+
stores.set(registration.id, snapshot);
|
|
200
|
+
total += snapshot.bytes;
|
|
201
|
+
}
|
|
202
|
+
return { total, stores };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function warnPinnedSaturation(): void {
|
|
206
|
+
const at = Date.now();
|
|
207
|
+
if (at - lastSaturationWarningAt < WARN_INTERVAL_MS) return;
|
|
208
|
+
lastSaturationWarningAt = at;
|
|
209
|
+
console.warn("[app-owned-memory] retained state remains over budget with no evictable candidate");
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export function enforceAppOwnedMemoryBudget(): AppOwnedBytesSnapshot {
|
|
213
|
+
if (isEnforcing) return appOwnedBytesSnapshot();
|
|
214
|
+
isEnforcing = true;
|
|
215
|
+
enforcementCounters.runs += 1;
|
|
216
|
+
try {
|
|
217
|
+
const ineligible = new Set<string>();
|
|
218
|
+
const current = retainedSnapshots();
|
|
219
|
+
while (current.total > budgetBytes) {
|
|
220
|
+
const candidate = nextCandidate(current.stores, ineligible);
|
|
221
|
+
if (!candidate) {
|
|
222
|
+
enforcementCounters.noEvictableCandidate += 1;
|
|
223
|
+
warnPinnedSaturation();
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
let reportedReleased = 0;
|
|
228
|
+
try {
|
|
229
|
+
reportedReleased = candidate.evictOldest();
|
|
230
|
+
} catch {
|
|
231
|
+
ineligible.add(candidate.id);
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
const previousSnapshot = current.stores.get(candidate.id) ?? ZERO_RETAINED_SNAPSHOT;
|
|
235
|
+
const nextSnapshot = retainedSnapshot(candidate);
|
|
236
|
+
current.stores.set(candidate.id, nextSnapshot);
|
|
237
|
+
const nextTotal = Math.max(0, current.total - previousSnapshot.bytes + nextSnapshot.bytes);
|
|
238
|
+
const actualReleased = Math.max(0, current.total - nextTotal);
|
|
239
|
+
if (reportedReleased <= 0 || actualReleased <= 0) {
|
|
240
|
+
ineligible.add(candidate.id);
|
|
241
|
+
} else {
|
|
242
|
+
enforcementCounters.entriesDemoted += 1;
|
|
243
|
+
enforcementCounters.bytesReleased += actualReleased;
|
|
244
|
+
}
|
|
245
|
+
current.total = nextTotal;
|
|
246
|
+
}
|
|
247
|
+
return appOwnedBytesSnapshotFrom(current.stores);
|
|
248
|
+
} finally {
|
|
249
|
+
isEnforcing = false;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export function resetAppOwnedMemoryForTests(): void {
|
|
254
|
+
retainedStores.clear();
|
|
255
|
+
observedBuffers.clear();
|
|
256
|
+
budgetBytes = DEFAULT_APP_OWNED_MEMORY_BUDGET_BYTES;
|
|
257
|
+
lastSaturationWarningAt = Number.NEGATIVE_INFINITY;
|
|
258
|
+
enforcementCounters.runs = 0;
|
|
259
|
+
enforcementCounters.entriesDemoted = 0;
|
|
260
|
+
enforcementCounters.bytesReleased = 0;
|
|
261
|
+
enforcementCounters.noEvictableCandidate = 0;
|
|
262
|
+
enforcementCounters.snapshotFailures = 0;
|
|
263
|
+
enforcementCounters.oldestAtContractViolations = 0;
|
|
264
|
+
isEnforcing = false;
|
|
265
|
+
}
|
|
@@ -0,0 +1,346 @@
|
|
|
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
|
+
export interface BoundedBytesOptions {
|
|
48
|
+
/** Abort the read with this signal. Its reason is rethrown by identity. */
|
|
49
|
+
signal?: AbortSignal;
|
|
50
|
+
/** Maximum number of raw bytes retained from the response body. */
|
|
51
|
+
maxBytes: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface BoundedBytesResult {
|
|
55
|
+
/**
|
|
56
|
+
* Exact raw bytes retained from the response. Empty when the cap was exceeded.
|
|
57
|
+
*
|
|
58
|
+
* This is a view over internal storage, so `bytes.buffer.byteLength` can exceed
|
|
59
|
+
* `bytes.byteLength`. Consumers must honor the view's byteOffset and byteLength
|
|
60
|
+
* instead of reading or transferring the backing buffer directly.
|
|
61
|
+
*/
|
|
62
|
+
bytes: Uint8Array<ArrayBuffer>;
|
|
63
|
+
/** True when the body was observed to exceed the byte cap. */
|
|
64
|
+
oversized: boolean;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const TOTAL_TIMEOUT = Symbol("bounded body total timeout");
|
|
68
|
+
const INACTIVITY_TIMEOUT = Symbol("bounded body inactivity timeout");
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Test-only instrumentation: how many times the retained buffer was reallocated
|
|
72
|
+
* during the most recent read. The accumulator grows geometrically, so this is
|
|
73
|
+
* logarithmic in the body size and independent of how many chunks the peer sends.
|
|
74
|
+
* The per-chunk array it replaced retained one object per chunk instead, which a
|
|
75
|
+
* fragmenting peer can inflate far past the payload ceiling — a property no
|
|
76
|
+
* correctness assertion can see, which is why it is observable here.
|
|
77
|
+
*/
|
|
78
|
+
let bufferGrowthsForTests = 0;
|
|
79
|
+
export function boundedBodyBufferGrowthsForTests(): number {
|
|
80
|
+
return bufferGrowthsForTests;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function timeoutPromise(ms: number, value: symbol): { promise: Promise<symbol>; clear: () => void } {
|
|
84
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
85
|
+
const promise = new Promise<symbol>((resolve) => {
|
|
86
|
+
timer = setTimeout(() => resolve(value), Math.max(0, ms));
|
|
87
|
+
});
|
|
88
|
+
return {
|
|
89
|
+
promise,
|
|
90
|
+
clear: () => {
|
|
91
|
+
if (timer !== undefined) clearTimeout(timer);
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function cancelWithoutWaiting(reader: ReadableStreamDefaultReader<Uint8Array>, reason?: unknown): void {
|
|
97
|
+
// A hostile/broken stream may reject or never settle cancel(). Neither should
|
|
98
|
+
// escape as an unhandled rejection or extend this primitive's own deadline.
|
|
99
|
+
try {
|
|
100
|
+
void reader.cancel(reason).catch(() => undefined);
|
|
101
|
+
} catch {
|
|
102
|
+
// Some stream implementations throw synchronously from cancel().
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Consume the original response body as raw bytes under a strict memory ceiling.
|
|
108
|
+
*
|
|
109
|
+
* The caller owns any wall-clock deadline through `signal`, which lets one budget
|
|
110
|
+
* cover both response headers and body consumption. No decoding, cloning, or teeing
|
|
111
|
+
* occurs, so arbitrary upstream bytes remain unchanged.
|
|
112
|
+
*/
|
|
113
|
+
export async function readBoundedResponseBytes(
|
|
114
|
+
response: Response,
|
|
115
|
+
options: BoundedBytesOptions,
|
|
116
|
+
): Promise<BoundedBytesResult> {
|
|
117
|
+
const signal = options.signal;
|
|
118
|
+
if (signal?.aborted) throw signal.reason;
|
|
119
|
+
|
|
120
|
+
const body = response.body;
|
|
121
|
+
if (!body) return { bytes: new Uint8Array(0), oversized: false };
|
|
122
|
+
|
|
123
|
+
const reader = body.getReader();
|
|
124
|
+
const maxBytes = options.maxBytes;
|
|
125
|
+
let retained = new Uint8Array(Math.min(maxBytes, 64 * 1024));
|
|
126
|
+
let retainedBytes = 0;
|
|
127
|
+
let mustCancel = false;
|
|
128
|
+
let cancelReason: unknown;
|
|
129
|
+
|
|
130
|
+
let rejectForAbort: ((reason: unknown) => void) | undefined;
|
|
131
|
+
const aborted = new Promise<never>((_resolve, reject) => {
|
|
132
|
+
rejectForAbort = reject;
|
|
133
|
+
});
|
|
134
|
+
const onAbort = () => rejectForAbort?.(signal?.reason);
|
|
135
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
136
|
+
// Close the narrow race between the preflight check and listener install.
|
|
137
|
+
if (signal?.aborted) onAbort();
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
while (true) {
|
|
141
|
+
const read = reader.read();
|
|
142
|
+
// Observe a late read rejection when abort/cancellation wins the race.
|
|
143
|
+
void read.catch(() => undefined);
|
|
144
|
+
const outcome = await Promise.race([read, aborted]);
|
|
145
|
+
if (signal?.aborted) {
|
|
146
|
+
mustCancel = true;
|
|
147
|
+
cancelReason = signal.reason;
|
|
148
|
+
throw signal.reason;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const { value, done } = outcome;
|
|
152
|
+
if (done) {
|
|
153
|
+
return { bytes: retained.subarray(0, retainedBytes), oversized: false };
|
|
154
|
+
}
|
|
155
|
+
if (!value || value.byteLength === 0) continue;
|
|
156
|
+
|
|
157
|
+
if (value.byteLength > maxBytes - retainedBytes) {
|
|
158
|
+
mustCancel = true;
|
|
159
|
+
cancelReason = new DOMException("Response body size limit reached", "QuotaExceededError");
|
|
160
|
+
retained = new Uint8Array(0);
|
|
161
|
+
retainedBytes = 0;
|
|
162
|
+
return { bytes: retained, oversized: true };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (retainedBytes + value.byteLength > retained.length) {
|
|
166
|
+
const grown = new Uint8Array(
|
|
167
|
+
Math.min(maxBytes, Math.max(retained.length * 2, retainedBytes + value.byteLength)),
|
|
168
|
+
);
|
|
169
|
+
grown.set(retained.subarray(0, retainedBytes));
|
|
170
|
+
retained = grown;
|
|
171
|
+
}
|
|
172
|
+
retained.set(value, retainedBytes);
|
|
173
|
+
retainedBytes += value.byteLength;
|
|
174
|
+
}
|
|
175
|
+
} catch (error) {
|
|
176
|
+
mustCancel = true;
|
|
177
|
+
cancelReason = error;
|
|
178
|
+
throw error;
|
|
179
|
+
} finally {
|
|
180
|
+
signal?.removeEventListener("abort", onAbort);
|
|
181
|
+
if (mustCancel) cancelWithoutWaiting(reader, cancelReason);
|
|
182
|
+
try {
|
|
183
|
+
reader.releaseLock();
|
|
184
|
+
} catch {
|
|
185
|
+
// A pending read can keep the lock briefly while cancel settles.
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function decodeUtf8(chunks: readonly Uint8Array[], fatal: boolean): string {
|
|
191
|
+
const decoder = new TextDecoder("utf-8", { fatal });
|
|
192
|
+
let text = "";
|
|
193
|
+
for (const chunk of chunks) text += decoder.decode(chunk, { stream: true });
|
|
194
|
+
// Flush an incomplete trailing UTF-8 sequence deterministically.
|
|
195
|
+
text += decoder.decode();
|
|
196
|
+
return text;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Consume the original response body under strict memory and time bounds.
|
|
201
|
+
*
|
|
202
|
+
* This deliberately calls `getReader()` on `response.body`: it never clones or
|
|
203
|
+
* tees the response. Once an over-limit byte is observed, all retained raw data
|
|
204
|
+
* is discarded so an untrusted prefix can never become a client-facing error.
|
|
205
|
+
*/
|
|
206
|
+
export async function readBoundedResponseBody(
|
|
207
|
+
response: Response,
|
|
208
|
+
options: BoundedBodyOptions = {},
|
|
209
|
+
): Promise<BoundedBodyResult> {
|
|
210
|
+
const signal = options.signal;
|
|
211
|
+
if (signal?.aborted) throw signal.reason;
|
|
212
|
+
|
|
213
|
+
const body = response.body;
|
|
214
|
+
if (!body) {
|
|
215
|
+
return {
|
|
216
|
+
text: "",
|
|
217
|
+
truncated: false,
|
|
218
|
+
timedOut: false,
|
|
219
|
+
totalTimedOut: false,
|
|
220
|
+
inactivityTimedOut: false,
|
|
221
|
+
oversized: false,
|
|
222
|
+
displaySafe: true,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const reader = body.getReader();
|
|
227
|
+
const maxBytes = options.maxBytes ?? BOUNDED_BODY_MAX_BYTES;
|
|
228
|
+
// Geometrically growing single buffer: per-chunk arrays would retain one object per
|
|
229
|
+
// transport chunk, which a hostile peer could inflate into metadata amplification far
|
|
230
|
+
// beyond the payload ceiling on large budgets.
|
|
231
|
+
let retained = new Uint8Array(Math.min(maxBytes, 64 * 1024));
|
|
232
|
+
let retainedBytes = 0;
|
|
233
|
+
bufferGrowthsForTests = 0;
|
|
234
|
+
let mustCancel = false;
|
|
235
|
+
let cancelReason: unknown;
|
|
236
|
+
const total = timeoutPromise(options.totalTimeoutMs ?? BOUNDED_BODY_TIMEOUT_MS, TOTAL_TIMEOUT);
|
|
237
|
+
let inactivity = timeoutPromise(
|
|
238
|
+
options.firstByteTimeoutMs ?? options.inactivityTimeoutMs ?? BOUNDED_BODY_TIMEOUT_MS,
|
|
239
|
+
INACTIVITY_TIMEOUT,
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
let rejectForAbort: ((reason: unknown) => void) | undefined;
|
|
243
|
+
const aborted = new Promise<never>((_resolve, reject) => {
|
|
244
|
+
rejectForAbort = reject;
|
|
245
|
+
});
|
|
246
|
+
const onAbort = () => rejectForAbort?.(signal?.reason);
|
|
247
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
248
|
+
// Close the narrow race between the preflight check and listener install.
|
|
249
|
+
if (signal?.aborted) onAbort();
|
|
250
|
+
|
|
251
|
+
try {
|
|
252
|
+
while (true) {
|
|
253
|
+
// Attach a rejection handler before racing. If a deadline wins and
|
|
254
|
+
// cancellation later rejects this read, it remains observed.
|
|
255
|
+
const read = reader.read();
|
|
256
|
+
void read.catch(() => undefined);
|
|
257
|
+
const outcome = await Promise.race([read, total.promise, inactivity.promise, aborted]);
|
|
258
|
+
// Cancellation owns the body lifetime even when EOF/readability settles in
|
|
259
|
+
// the same turn. Promise.race otherwise lets array order hide the abort.
|
|
260
|
+
if (signal?.aborted) {
|
|
261
|
+
mustCancel = true;
|
|
262
|
+
cancelReason = signal.reason;
|
|
263
|
+
throw signal.reason;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (outcome === TOTAL_TIMEOUT || outcome === INACTIVITY_TIMEOUT) {
|
|
267
|
+
mustCancel = true;
|
|
268
|
+
cancelReason = new DOMException(
|
|
269
|
+
outcome === TOTAL_TIMEOUT ? "Error body total timeout" : "Error body inactivity timeout",
|
|
270
|
+
"TimeoutError",
|
|
271
|
+
);
|
|
272
|
+
return {
|
|
273
|
+
text: decodeUtf8([retained.subarray(0, retainedBytes)], options.fatalUtf8 === true),
|
|
274
|
+
truncated: true,
|
|
275
|
+
timedOut: true,
|
|
276
|
+
totalTimedOut: outcome === TOTAL_TIMEOUT,
|
|
277
|
+
inactivityTimedOut: outcome === INACTIVITY_TIMEOUT,
|
|
278
|
+
oversized: false,
|
|
279
|
+
displaySafe: false,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const { value, done } = outcome as ReadableStreamReadResult<Uint8Array>;
|
|
284
|
+
if (done) {
|
|
285
|
+
return {
|
|
286
|
+
text: decodeUtf8([retained.subarray(0, retainedBytes)], options.fatalUtf8 === true),
|
|
287
|
+
truncated: false,
|
|
288
|
+
timedOut: false,
|
|
289
|
+
totalTimedOut: false,
|
|
290
|
+
inactivityTimedOut: false,
|
|
291
|
+
oversized: false,
|
|
292
|
+
displaySafe: true,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (!value || value.byteLength === 0) continue;
|
|
297
|
+
|
|
298
|
+
inactivity.clear();
|
|
299
|
+
inactivity = timeoutPromise(
|
|
300
|
+
options.inactivityTimeoutMs ?? BOUNDED_BODY_TIMEOUT_MS,
|
|
301
|
+
INACTIVITY_TIMEOUT,
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
if (value.byteLength > maxBytes - retainedBytes) {
|
|
305
|
+
mustCancel = true;
|
|
306
|
+
cancelReason = new DOMException("Error body size limit reached", "QuotaExceededError");
|
|
307
|
+
retained = new Uint8Array(0);
|
|
308
|
+
retainedBytes = 0;
|
|
309
|
+
return {
|
|
310
|
+
text: "",
|
|
311
|
+
truncated: true,
|
|
312
|
+
timedOut: false,
|
|
313
|
+
totalTimedOut: false,
|
|
314
|
+
inactivityTimedOut: false,
|
|
315
|
+
oversized: true,
|
|
316
|
+
displaySafe: false,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (retainedBytes + value.byteLength > retained.length) {
|
|
321
|
+
const grown = new Uint8Array(
|
|
322
|
+
Math.min(maxBytes, Math.max(retained.length * 2, retainedBytes + value.byteLength)),
|
|
323
|
+
);
|
|
324
|
+
grown.set(retained.subarray(0, retainedBytes));
|
|
325
|
+
retained = grown;
|
|
326
|
+
bufferGrowthsForTests += 1;
|
|
327
|
+
}
|
|
328
|
+
retained.set(value, retainedBytes);
|
|
329
|
+
retainedBytes += value.byteLength;
|
|
330
|
+
}
|
|
331
|
+
} catch (error) {
|
|
332
|
+
mustCancel = true;
|
|
333
|
+
cancelReason = error;
|
|
334
|
+
throw error;
|
|
335
|
+
} finally {
|
|
336
|
+
total.clear();
|
|
337
|
+
inactivity.clear();
|
|
338
|
+
signal?.removeEventListener("abort", onAbort);
|
|
339
|
+
if (mustCancel) cancelWithoutWaiting(reader, cancelReason);
|
|
340
|
+
try {
|
|
341
|
+
reader.releaseLock();
|
|
342
|
+
} catch {
|
|
343
|
+
// A pending read can keep the lock briefly while cancel settles.
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
@@ -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
|
+
}
|