From 02a3636366d9932d46d2dee59e9b44a9fb322852 Mon Sep 17 00:00:00 2001 From: jun Date: Sat, 5 Sep 2026 04:38:18 +0900 Subject: [PATCH 1/3] test(layout): move providers and codex-integration into tests// (#3497) --- .github/scripts/pr-hygiene.test.cjs | 2 +- .../2026-07-26-oauth-reliability-integrity.md | 24 ++--- ...eek-responses-streaming-terminal-repair.md | 26 ++--- .../2026-08-09-routed-computer-use-browser.md | 28 +++--- .../2026-08-13-cl10-deep-review-hardening.md | 2 +- ...-26-discovered-model-display-names-core.md | 40 ++++---- ...ponses-streaming-terminal-repair-design.md | 2 +- scripts/generate-model-metadata.ts | 4 +- scripts/openai-provider-option-final-gates.ts | 10 +- scripts/test-layout/layout.json | 2 + scripts/test-layout/schema.ts | 54 ++++++---- scripts/test.ts | 6 +- src/adapters/cursor/protobuf-request.ts | 4 +- src/clients/config-export.ts | 2 +- src/codex/catalog/metadata.ts | 2 +- src/codex/catalog/provider-fetch.ts | 2 +- src/providers/derive.ts | 2 +- src/providers/registry.ts | 6 +- .../management/agent-settings-routes.ts | 2 +- src/server/responses/core.ts | 2 +- src/service-manager-probe.ts | 2 +- structure/03_catalog-and-subagents.md | 2 +- structure/04_transports-and-sidecars.md | 2 +- structure/11_compatibility-contracts.md | 2 +- tests/bump-dev-version.test.ts | 2 +- tests/ci-workflows.test.ts | 4 +- .../active-registry-admission.test.ts | 18 ++-- .../app-owned-memory.test.ts | 20 ++-- .../bearer-admission-routed-provider.test.ts | 18 ++-- .../catalog-cursor-search.test.ts | 2 +- .../catalog-input-modality-enum.test.ts | 18 ++-- .../catalog-llamacpp-capabilities.test.ts | 4 +- .../catalog-oauth-observation.test.ts | 12 +-- .../catalog-retain-models.test.ts | 12 +-- .../catalog-verbosity-default.test.ts | 8 +- .../catalog-vision-sidecar-modalities.test.ts | 18 ++-- .../codex-account-delete-atomicity.test.ts | 18 ++-- .../codex-account-label.test.ts | 2 +- .../codex-account-namespaces.test.ts | 12 +-- .../codex-account-store.test.ts | 98 +++++++++---------- .../codex-admission-primitives.test.ts | 17 ++-- .../codex-admission.test.ts | 8 +- .../codex-affinity-debug.test.ts | 6 +- .../codex-app-server-path-spaces.test.ts | 2 +- .../codex-app-server-processes.test.ts | 15 +-- .../codex-app-server-restart-service.test.ts | 8 +- .../codex-auth-api.test.ts | 92 ++++++++--------- .../codex-auth-collision.test.ts | 10 +- .../codex-auth-context.test.ts | 32 +++--- .../codex-catalog-admission.test.ts | 10 +- .../codex-catalog-golden.test.ts | 2 +- .../codex-catalog-model-picker-order.test.ts | 4 +- .../codex-catalog-refresh-status.test.ts | 4 +- .../codex-catalog-restore.test.ts | 4 +- .../codex-catalog-sync-hardening.test.ts | 6 +- .../codex-catalog-write-serialization.test.ts | 6 +- .../codex-catalog-writer.test.ts | 10 +- .../codex-catalog.test.ts | 72 +++++++------- .../codex-cli-install-provenance.test.ts | 6 +- .../codex-cli-update-launcher-policy.test.ts | 5 +- .../codex-cli-update-zero-effect.test.ts | 15 +-- .../codex-composed-acceptance.test.ts | 15 +-- .../codex-config-generation.test.ts | 11 ++- ...odex-convergence-account-selectors.test.ts | 32 +++--- .../codex-convergence-contract.test.ts | 35 +++---- .../codex-cooldown-recovery.test.ts | 14 +-- .../codex-coordinator-doctor.test.ts | 12 +-- .../codex-desired-state.test.ts | 8 +- ...odex-envkey-admission-substitution.test.ts | 16 +-- .../codex-exec-invocation.test.ts | 4 +- .../codex-features-cache.test.ts | 6 +- .../codex-features-residual.test.ts | 4 +- .../codex-filesystem-evidence.test.ts | 14 +-- .../codex-gather-authority.test.ts | 12 +-- .../codex-history-job.test.ts | 7 +- .../codex-history-lock.test.ts | 7 +- .../codex-history-provider.test.ts | 4 +- .../codex-history-reachability.test.ts | 3 +- .../codex-history-worker-boundary.test.ts | 10 +- .../codex-history-worker.test.ts | 9 +- .../codex-history-writer.test.ts | 6 +- .../codex-home-wsl.test.ts | 6 +- .../codex-inject-history-wording.test.ts | 11 ++- .../codex-inject-integration.test.ts | 8 +- .../codex-inject-write-lock.test.ts | 11 ++- .../codex-inject.test.ts | 6 +- .../codex-injected-marker.test.ts | 2 +- .../codex-integration-record.test.ts | 8 +- .../codex-journal.test.ts | 10 +- .../codex-log-guard-coderabbit.test.ts | 8 +- .../codex-log-guard-doctor-coderabbit.test.ts | 4 +- .../codex-log-guard-doctor-protection.test.ts | 4 +- .../codex-log-guard-doctor.test.ts | 4 +- .../codex-log-guard-inspect.test.ts | 4 +- .../codex-log-guard-lock.test.ts | 4 +- ...x-log-guard-maintenance-coderabbit.test.ts | 4 +- .../codex-log-guard-maintenance.test.ts | 24 ++--- .../codex-log-guard-policy.test.ts | 4 +- .../codex-log-guard-processes.test.ts | 2 +- .../codex-log-guard-protection.test.ts | 4 +- .../codex-log-guard-status-zero-write.test.ts | 4 +- .../codex-main-account-refresh.test.ts | 6 +- .../codex-main-rotation.test.ts | 18 ++-- .../codex-management-convergence.test.ts | 8 +- .../codex-metadata-integrity.test.ts | 8 +- .../codex-model-entitlements.test.ts | 20 ++-- .../codex-models-cache-invalidate.test.ts | 16 +-- .../codex-native-residue.test.ts | 16 +-- .../codex-plan.test.ts | 16 +-- .../codex-plugins-doctor.test.ts | 6 +- .../codex-pool-rotation.test.ts | 18 ++-- .../codex-prompt-adopt.test.ts | 4 +- .../codex-prompt-base-variants.test.ts | 4 +- .../codex-prompt-journal.test.ts | 6 +- .../codex-prompt-layers-read.test.ts | 4 +- .../codex-prompt-layers-write.test.ts | 6 +- .../codex-prompt-layers.test.ts | 2 +- .../codex-prompt-lock.test.ts | 4 +- .../codex-prompt-route.test.ts | 22 ++--- .../codex-prompt-text-probe.test.ts | 4 +- .../codex-quota-parser-parity.test.ts | 4 +- .../codex-quota-prime.test.ts | 22 ++--- .../codex-quota-rejection.test.ts | 6 +- .../codex-refresh.test.ts | 8 +- .../codex-reset-credit-auto-redeem.test.ts | 4 +- ...odex-reset-credit-operation-ledger.test.ts | 11 ++- .../codex-reset-credit-recovery.test.ts | 4 +- .../codex-restart-contract-parity.test.ts | 4 +- .../codex-restart-route.test.ts | 12 +-- .../codex-restore-app-rewrite.test.ts | 4 +- .../codex-retained-root-serialization.test.ts | 9 +- .../codex-routing.test.ts | 28 +++--- .../codex-runtime.test.ts | 12 +-- ...ex-service-manager-probe-hardening.test.ts | 12 +-- .../codex-service-manager-probe.test.ts | 8 +- .../codex-shim-autorestore.test.ts | 15 +-- .../codex-shim-readiness.test.ts | 6 +- .../codex-shim.test.ts | 15 +-- .../codex-spark-visibility.test.ts | 8 +- .../codex-sqlite-home.test.ts | 8 +- .../codex-sync-api.test.ts | 19 ++-- .../codex-sync-response.test.ts | 4 +- .../codex-tool-mode.test.ts | 24 ++--- .../codex-transition-state-adoption.test.ts | 11 ++- ...nsition-state-first-use-regression.test.ts | 6 +- .../codex-transition-state-race.test.ts | 9 +- .../codex-transition-state.test.ts | 10 +- .../codex-user-identity.test.ts | 7 +- .../codex-v2-gate.test.ts | 18 ++-- .../codex-warmup.test.ts | 2 +- .../codex-websocket-registry.test.ts | 6 +- .../codex-write-lock.test.ts | 11 ++- tests/{ => codex-integration}/combos.test.ts | 28 +++--- .../compatibility-manifest.test.ts | 23 ++--- .../custom-model-catalog-migration.test.ts | 4 +- tests/{ => codex-integration}/doctor.test.ts | 12 +-- .../effort-policy.test.ts | 18 ++-- .../fast-row-listing.test.ts | 8 +- .../{ => codex-integration}/fast-row.test.ts | 10 +- ...gather-routed-models-single-flight.test.ts | 10 +- .../history-migration-guardian.test.ts | 2 +- .../injection-model-api.test.ts | 14 +-- .../issue-452-empty-503.test.ts | 32 +++--- .../issue-702-expired-replay-state.test.ts | 20 ++-- .../issue-914-transport-attribution.test.ts | 16 +-- .../model-cache-generation-tombstone.test.ts | 2 +- .../model-cache.test.ts | 2 +- ...model-display-names-management-api.test.ts | 10 +- .../model-metadata-sync.test.ts | 9 +- .../model-visibility-management-api.test.ts | 22 ++--- .../multi-agent-compat.test.ts | 18 ++-- .../multi-agent-keep-native-v1.test.ts | 18 ++-- ...ative-alias-maintainer-regressions.test.ts | 6 +- .../native-claude-code-toggle.test.ts | 4 +- .../native-claude-desktop-toggle.test.ts | 12 +-- .../native-codex-toggle.test.ts | 8 +- .../native-grok-toggle.test.ts | 23 ++--- .../native-main-auth-temp.test.ts | 8 +- .../native-main-claim-cache.test.ts | 2 +- .../native-main-claim.test.ts | 13 +-- .../native-main-owner-lifetime.test.ts | 23 ++--- .../native-model-toggle.test.ts | 18 ++-- .../native-profile-api.test.ts | 12 +-- .../native-profile-crash-boundaries.test.ts | 27 ++--- .../native-profile-drain-server.test.ts | 36 +++---- .../native-profile-manager.test.ts | 19 ++-- .../native-profile-processes.test.ts | 6 +- .../native-profile-recovery.test.ts | 2 +- .../native-profile-route-security.test.ts | 16 +-- .../native-profile-stage-lifecycle.test.ts | 6 +- .../native-profile-startup.test.ts | 33 ++++--- .../native-profile-store.test.ts | 8 +- .../parallel-tool-calls-optin.test.ts | 8 +- .../project-config-warnings.test.ts | 4 +- .../reasoning-effort.test.ts | 16 +-- .../selected-models.test.ts | 4 +- .../slug-codec.test.ts | 14 +-- .../token-guardian.test.ts | 14 +-- .../ultrafast-tier-honesty.test.ts | 6 +- .../upstream-reachability.test.ts | 10 +- tests/{ => codex-integration}/warmup.test.ts | 2 +- tests/helpers/repo-root.ts | 5 + .../lib/transient-budget-scope-source.test.ts | 2 +- .../alibaba-region-backup.test.ts | 4 +- .../alibaba-region-migration.test.ts | 10 +- .../alibaba-region-startup.test.ts | 8 +- tests/{ => providers}/aside-client.test.ts | 16 +-- .../auto-compact-budget.test.ts | 2 +- tests/{ => providers}/azure-adapter.test.ts | 10 +- .../azure-model-router-tool-schema.test.ts | 4 +- .../{ => providers}/baseten-provider.test.ts | 27 ++--- tests/{ => providers}/chutes-provider.test.ts | 31 +++--- ...cline-pass-deepseek-v4-tool-replay.test.ts | 10 +- .../cline-pass-provider.test.ts | 14 +-- .../cline-pass-reasoning-efforts.test.ts | 8 +- tests/{ => providers}/cline-provider.test.ts | 8 +- .../command-code-error-finish.test.ts | 8 +- .../command-code-provider.test.ts | 14 +-- .../command-code-quota.test.ts | 8 +- .../command-code-workspace-cache.test.ts | 2 +- .../commandcode-provider.test.ts | 31 +++--- .../context-cap-unknown-window.test.ts | 2 +- .../cursor}/cursor-adapter.test.ts | 20 ++-- .../cursor}/cursor-arg-normalize.test.ts | 2 +- .../cursor}/cursor-blob-integrity.test.ts | 2 +- .../cursor}/cursor-blob.test.ts | 22 ++--- .../cursor}/cursor-call-id.test.ts | 8 +- .../cursor}/cursor-cancel-provenance.test.ts | 10 +- .../cursor}/cursor-catalog.test.ts | 4 +- .../cursor}/cursor-claude-id.test.ts | 2 +- ...cursor-default-catalog-suppression.test.ts | 4 +- .../cursor}/cursor-desktop-exec.test.ts | 8 +- .../cursor}/cursor-discovery.test.ts | 2 +- .../cursor}/cursor-display-names.test.ts | 12 +-- .../cursor}/cursor-effort-rows.test.ts | 24 ++--- .../cursor}/cursor-effort-suffix.test.ts | 8 +- .../cursor}/cursor-effort-table.test.ts | 9 +- .../cursor-envelope-echo-retry.test.ts | 10 +- .../cursor}/cursor-eof-terminal.test.ts | 10 +- .../cursor}/cursor-errors.test.ts | 4 +- .../cursor}/cursor-exec-empty-result.test.ts | 2 +- .../cursor}/cursor-fast-listing.test.ts | 18 ++-- .../cursor}/cursor-fast-tier.test.ts | 14 +-- .../cursor}/cursor-framing.test.ts | 4 +- .../cursor}/cursor-h2-pool-shutdown.test.ts | 4 +- .../cursor}/cursor-hardening.test.ts | 18 ++-- .../cursor}/cursor-http1-transport.test.ts | 14 +-- .../cursor}/cursor-images.test.ts | 22 ++--- .../cursor}/cursor-integration-status.test.ts | 23 ++--- .../cursor}/cursor-interaction-query.test.ts | 24 ++--- .../cursor}/cursor-kv-store.test.ts | 4 +- .../cursor}/cursor-live-smoke-gate.test.ts | 2 +- .../cursor}/cursor-live-transport.test.ts | 14 +-- .../cursor-local-models-schema.test.ts | 16 +-- .../cursor}/cursor-mcp-manager.test.ts | 12 +-- .../cursor}/cursor-mcp-stdio.test.ts | 10 +- .../cursor}/cursor-message-mapper.test.ts | 8 +- .../cursor}/cursor-native-exec-common.test.ts | 4 +- .../cursor}/cursor-native-exec-policy.test.ts | 16 +-- .../cursor}/cursor-native-exec-shell.test.ts | 4 +- .../cursor}/cursor-native-exec.test.ts | 6 +- .../cursor}/cursor-oauth-shell.test.ts | 8 +- .../cursor}/cursor-oauth.test.ts | 2 +- .../cursor}/cursor-pool.test.ts | 2 +- .../cursor}/cursor-protobuf-events.test.ts | 10 +- .../cursor}/cursor-repetition-breaker.test.ts | 8 +- .../cursor}/cursor-request-builder.test.ts | 16 +-- .../cursor}/cursor-silent-redirect.test.ts | 2 +- .../cursor}/cursor-static-catalog.test.ts | 16 +-- .../cursor}/cursor-stream-health.test.ts | 10 +- .../cursor}/cursor-structured-edit.test.ts | 12 +-- .../cursor}/cursor-tool-arg-decoding.test.ts | 4 +- .../cursor}/cursor-tool-choice.test.ts | 8 +- .../cursor}/cursor-tool-continuation.test.ts | 14 +-- .../cursor}/cursor-tool-definitions.test.ts | 6 +- .../cursor}/cursor-tool-finalize-race.test.ts | 10 +- .../cursor}/cursor-tool-result-image.test.ts | 8 +- .../cursor-tool-result-invocation.test.ts | 8 +- .../cursor-tool-suspended-checkpoint.test.ts | 12 +-- .../cursor-toolresult-normalize.test.ts | 10 +- .../cursor}/cursor-transport-retry.test.ts | 6 +- .../cursor}/cursor-ultra-mode.test.ts | 10 +- .../cursor}/cursor-umbrella-rows.test.ts | 8 +- .../cursor-uncallable-quarantine.test.ts | 4 +- .../cursor-vision-wire-harness.test.ts | 10 +- .../cyber-policy-error-fidelity.test.ts | 20 ++-- .../deepinfra-provider.test.ts | 29 +++--- .../deepseek-inbound-wire.test.ts | 20 ++-- .../deepseek-reasoning-replay-gaps.test.ts | 12 +-- .../deepseek-reasoning-replay.test.ts | 12 +-- .../deepseek-responses-item-id-repair.test.ts | 12 +-- .../digitalocean-scaleway-provider.test.ts | 31 +++--- tests/{ => providers}/exa-web-search.test.ts | 16 +-- .../{ => providers}/fast-row-ingress.test.ts | 12 +-- .../featherless-provider.test.ts | 33 ++++--- .../forward-admission-separation.test.ts | 10 +- .../github-copilot-account-origin.test.ts | 10 +- .../github-copilot-oauth.test.ts | 10 +- .../github-copilot-sse-rewrite.test.ts | 6 +- .../github-copilot-stream-contract.test.ts | 8 +- .../github-copilot-wire-defaults.test.ts | 12 +-- .../hyperbolic-provider.test.ts | 29 +++--- .../kimi-oauth-identity.test.ts | 6 +- .../kiro}/kiro-account-quota.test.ts | 8 +- .../{ => providers/kiro}/kiro-adapter.test.ts | 30 +++--- .../kiro}/kiro-builder-id-profile.test.ts | 14 +-- .../kiro}/kiro-calibration.test.ts | 2 +- .../{ => providers/kiro}/kiro-images.test.ts | 12 +-- tests/{ => providers/kiro}/kiro-oauth.test.ts | 6 +- .../kiro}/kiro-pool-rank.test.ts | 16 +-- .../kiro}/kiro-reasoning-roundtrip.test.ts | 10 +- tests/{ => providers/kiro}/kiro-retry.test.ts | 6 +- .../kiro}/kiro-review-regressions.test.ts | 14 +-- .../{ => providers/kiro}/kiro-stream.test.ts | 32 +++--- .../kiro}/kiro-usage-quota.test.ts | 2 +- .../kiro}/kiro-windows-cli-db-path.test.ts | 4 +- .../kiro-windows-cli-executable-path.test.ts | 2 +- .../meta-model-api-provider.test.ts | 12 +-- tests/{ => providers}/meta-muse-oauth.test.ts | 12 +-- tests/{ => providers}/mimo-effort.test.ts | 2 +- .../mimo-free-provider.test.ts | 10 +- .../mimo-token-plan-provider.test.ts | 14 +-- tests/{ => providers}/minimax-clients.test.ts | 9 +- .../minimax-reasoning-split.test.ts | 10 +- tests/{ => providers}/model-presets.test.ts | 4 +- .../model-rename-migration.test.ts | 6 +- .../moonshot-endpoints.test.ts | 6 +- .../moonshot-tool-schema.test.ts | 6 +- .../muse-passive-quota-cache.test.ts | 16 +-- .../muse-passive-quota-observation.test.ts | 14 +-- .../muse-spark-web-search-compat.test.ts | 8 +- .../muse-subscription-usage.test.ts | 2 +- .../{ => providers}/new-model-policy.test.ts | 2 +- tests/{ => providers}/nous-oauth-live.test.ts | 8 +- tests/{ => providers}/nous-oauth.test.ts | 12 +-- tests/{ => providers}/novita-provider.test.ts | 31 +++--- .../nscale-vultr-provider.test.ts | 29 +++--- .../nvidia-nim-hardening.test.ts | 14 +-- .../ollama}/ollama-native-parser.test.ts | 12 +-- .../ollama-native-reasoning-wire.test.ts | 10 +- .../ollama-native-structured-output.test.ts | 4 +- .../ollama}/ollama-native-v4.test.ts | 10 +- .../ollama}/ollama-native.test.ts | 12 +-- .../ollama}/ollama-show-enrichment-v7.test.ts | 14 +-- .../ollama}/ollama-show-enrichment.test.ts | 10 +- .../ollama}/ollama-show-ignore-abort.test.ts | 2 +- tests/{ => providers}/opencode-cli.test.ts | 14 +-- .../opencode-free-provider.test.ts | 14 +-- .../opencode-go-deepseek.test.ts | 6 +- .../opencode-go-grok46-responses.test.ts | 12 +-- .../opencode-go-luna-wire.test.ts | 10 +- .../opencode-go-muse-context.test.ts | 8 +- .../opencode-go-muse-vision.test.ts | 8 +- .../{ => providers}/opencode-go-quota.test.ts | 4 +- .../opencode-go-session-header.test.ts | 10 +- .../opencode-zen-deepseek-reasoning.test.ts | 6 +- .../opencode-zen-rate-limit.test.ts | 10 +- .../openrouter-provider-routing.test.ts | 16 +-- ...provider-account-quota-persistence.test.ts | 6 +- .../provider-account-quota.test.ts | 22 ++--- .../{ => providers}/provider-api-keys.test.ts | 12 +-- .../{ => providers}/provider-capacity.test.ts | 2 +- .../provider-config-batch-management.test.ts | 20 ++-- .../provider-config-validation.test.ts | 2 +- .../provider-connection-test.test.ts | 20 ++-- .../provider-cost-overlay-config.test.ts | 10 +- ...provider-discovery-log-suppression.test.ts | 2 +- .../provider-id-rewrite.test.ts | 8 +- .../provider-key-store.test.ts | 18 ++-- .../provider-live-models.test.ts | 6 +- .../provider-model-aliases.test.ts | 6 +- .../provider-model-discovery-contract.test.ts | 29 +++--- .../provider-outbound-private-network.test.ts | 4 +- .../{ => providers}/provider-outbound.test.ts | 28 +++--- .../provider-quota-observed-marker.test.ts | 12 +-- tests/{ => providers}/provider-quota.test.ts | 23 ++--- .../provider-registry-parity.test.ts | 28 +++--- .../provider-static-model-discovery.test.ts | 12 +-- .../qwen38-preserve-reasoning.test.ts | 6 +- .../{ => providers}/rate-limit-retry.test.ts | 6 +- .../sambanova-nebius-provider.test.ts | 33 ++++--- tests/{ => providers}/umans-provider.test.ts | 10 +- .../upstream-transient-retry.test.ts | 6 +- .../vercel-gateway-provider-routing.test.ts | 12 +-- .../volcengine-ark-assistant-content.test.ts | 4 +- .../xai}/grok-attribution.test.ts | 10 +- .../xai}/grok-config-inject.test.ts | 4 +- .../xai}/grok-effort-inject.test.ts | 20 ++-- .../xai}/grok-lifecycle.test.ts | 37 +++---- .../xai}/grok-management-api.test.ts | 14 +-- .../xai}/grok-models-effort-list.test.ts | 12 +-- .../xai}/grok-orphan-adoption.test.ts | 4 +- .../xai}/grok-selection.test.ts | 12 +-- tests/{ => providers/xai}/grok-status.test.ts | 6 +- tests/{ => providers/xai}/grok-sync.test.ts | 14 +-- .../xai}/grok-writer-boundary.test.ts | 2 +- .../xai}/xai-oauth-retry.test.ts | 2 +- .../xai}/xai-refresh-lock.test.ts | 6 +- .../xai}/xai-tool-schema.test.ts | 6 +- .../{ => providers/xai}/xai-transport.test.ts | 16 +-- .../xai}/xai-web-search-compat.test.ts | 6 +- .../xai}/xai-web-search.test.ts | 26 ++--- tests/{ => providers}/zcode-client.test.ts | 6 +- .../zhipu-bigmodel-provider.test.ts | 14 +-- .../responses-inbound-store-default.test.ts | 2 +- .../responses-undeclared-tool-guard.test.ts | 2 +- tests/server-auth.test.ts | 2 +- tests/server-management-auth.test.ts | 2 +- tests/service/stop-deferred-teardown.test.ts | 2 +- tests/test-layout-tooling.test.ts | 22 ++++- tests/windows/windows-tray.test.ts | 2 +- 411 files changed, 2360 insertions(+), 2275 deletions(-) rename tests/{ => codex-integration}/active-registry-admission.test.ts (95%) rename tests/{ => codex-integration}/app-owned-memory.test.ts (95%) rename tests/{ => codex-integration}/bearer-admission-routed-provider.test.ts (96%) rename tests/{ => codex-integration}/catalog-cursor-search.test.ts (99%) rename tests/{ => codex-integration}/catalog-input-modality-enum.test.ts (96%) rename tests/{ => codex-integration}/catalog-llamacpp-capabilities.test.ts (97%) rename tests/{ => codex-integration}/catalog-oauth-observation.test.ts (96%) rename tests/{ => codex-integration}/catalog-retain-models.test.ts (94%) rename tests/{ => codex-integration}/catalog-verbosity-default.test.ts (92%) rename tests/{ => codex-integration}/catalog-vision-sidecar-modalities.test.ts (97%) rename tests/{ => codex-integration}/codex-account-delete-atomicity.test.ts (93%) rename tests/{ => codex-integration}/codex-account-label.test.ts (97%) rename tests/{ => codex-integration}/codex-account-namespaces.test.ts (98%) rename tests/{ => codex-integration}/codex-account-store.test.ts (95%) rename tests/{ => codex-integration}/codex-admission-primitives.test.ts (96%) rename tests/{ => codex-integration}/codex-admission.test.ts (97%) rename tests/{ => codex-integration}/codex-affinity-debug.test.ts (98%) rename tests/{ => codex-integration}/codex-app-server-path-spaces.test.ts (95%) rename tests/{ => codex-integration}/codex-app-server-processes.test.ts (99%) rename tests/{ => codex-integration}/codex-app-server-restart-service.test.ts (98%) rename tests/{ => codex-integration}/codex-auth-api.test.ts (98%) rename tests/{ => codex-integration}/codex-auth-collision.test.ts (93%) rename tests/{ => codex-integration}/codex-auth-context.test.ts (98%) rename tests/{ => codex-integration}/codex-catalog-admission.test.ts (96%) rename tests/{ => codex-integration}/codex-catalog-golden.test.ts (98%) rename tests/{ => codex-integration}/codex-catalog-model-picker-order.test.ts (99%) rename tests/{ => codex-integration}/codex-catalog-refresh-status.test.ts (95%) rename tests/{ => codex-integration}/codex-catalog-restore.test.ts (99%) rename tests/{ => codex-integration}/codex-catalog-sync-hardening.test.ts (99%) rename tests/{ => codex-integration}/codex-catalog-write-serialization.test.ts (97%) rename tests/{ => codex-integration}/codex-catalog-writer.test.ts (97%) rename tests/{ => codex-integration}/codex-catalog.test.ts (99%) rename tests/{ => codex-integration}/codex-cli-install-provenance.test.ts (99%) rename tests/{ => codex-integration}/codex-cli-update-launcher-policy.test.ts (84%) rename tests/{ => codex-integration}/codex-cli-update-zero-effect.test.ts (88%) rename tests/{ => codex-integration}/codex-composed-acceptance.test.ts (98%) rename tests/{ => codex-integration}/codex-config-generation.test.ts (97%) rename tests/{ => codex-integration}/codex-convergence-account-selectors.test.ts (97%) rename tests/{ => codex-integration}/codex-convergence-contract.test.ts (94%) rename tests/{ => codex-integration}/codex-cooldown-recovery.test.ts (98%) rename tests/{ => codex-integration}/codex-coordinator-doctor.test.ts (96%) rename tests/{ => codex-integration}/codex-desired-state.test.ts (98%) rename tests/{ => codex-integration}/codex-envkey-admission-substitution.test.ts (95%) rename tests/{ => codex-integration}/codex-exec-invocation.test.ts (96%) rename tests/{ => codex-integration}/codex-features-cache.test.ts (94%) rename tests/{ => codex-integration}/codex-features-residual.test.ts (86%) rename tests/{ => codex-integration}/codex-filesystem-evidence.test.ts (95%) rename tests/{ => codex-integration}/codex-gather-authority.test.ts (97%) rename tests/{ => codex-integration}/codex-history-job.test.ts (98%) rename tests/{ => codex-integration}/codex-history-lock.test.ts (96%) rename tests/{ => codex-integration}/codex-history-provider.test.ts (99%) rename tests/{ => codex-integration}/codex-history-reachability.test.ts (98%) rename tests/{ => codex-integration}/codex-history-worker-boundary.test.ts (96%) rename tests/{ => codex-integration}/codex-history-worker.test.ts (98%) rename tests/{ => codex-integration}/codex-history-writer.test.ts (96%) rename tests/{ => codex-integration}/codex-home-wsl.test.ts (93%) rename tests/{ => codex-integration}/codex-inject-history-wording.test.ts (94%) rename tests/{ => codex-integration}/codex-inject-integration.test.ts (99%) rename tests/{ => codex-integration}/codex-inject-write-lock.test.ts (98%) rename tests/{ => codex-integration}/codex-inject.test.ts (99%) rename tests/{ => codex-integration}/codex-injected-marker.test.ts (89%) rename tests/{ => codex-integration}/codex-integration-record.test.ts (97%) rename tests/{ => codex-integration}/codex-journal.test.ts (98%) rename tests/{ => codex-integration}/codex-log-guard-coderabbit.test.ts (97%) rename tests/{ => codex-integration}/codex-log-guard-doctor-coderabbit.test.ts (90%) rename tests/{ => codex-integration}/codex-log-guard-doctor-protection.test.ts (94%) rename tests/{ => codex-integration}/codex-log-guard-doctor.test.ts (97%) rename tests/{ => codex-integration}/codex-log-guard-inspect.test.ts (99%) rename tests/{ => codex-integration}/codex-log-guard-lock.test.ts (88%) rename tests/{ => codex-integration}/codex-log-guard-maintenance-coderabbit.test.ts (98%) rename tests/{ => codex-integration}/codex-log-guard-maintenance.test.ts (91%) rename tests/{ => codex-integration}/codex-log-guard-policy.test.ts (93%) rename tests/{ => codex-integration}/codex-log-guard-processes.test.ts (98%) rename tests/{ => codex-integration}/codex-log-guard-protection.test.ts (99%) rename tests/{ => codex-integration}/codex-log-guard-status-zero-write.test.ts (96%) rename tests/{ => codex-integration}/codex-main-account-refresh.test.ts (98%) rename tests/{ => codex-integration}/codex-main-rotation.test.ts (97%) rename tests/{ => codex-integration}/codex-management-convergence.test.ts (95%) rename tests/{ => codex-integration}/codex-metadata-integrity.test.ts (95%) rename tests/{ => codex-integration}/codex-model-entitlements.test.ts (99%) rename tests/{ => codex-integration}/codex-models-cache-invalidate.test.ts (95%) rename tests/{ => codex-integration}/codex-native-residue.test.ts (98%) rename tests/{ => codex-integration}/codex-plan.test.ts (95%) rename tests/{ => codex-integration}/codex-plugins-doctor.test.ts (98%) rename tests/{ => codex-integration}/codex-pool-rotation.test.ts (98%) rename tests/{ => codex-integration}/codex-prompt-adopt.test.ts (98%) rename tests/{ => codex-integration}/codex-prompt-base-variants.test.ts (98%) rename tests/{ => codex-integration}/codex-prompt-journal.test.ts (98%) rename tests/{ => codex-integration}/codex-prompt-layers-read.test.ts (98%) rename tests/{ => codex-integration}/codex-prompt-layers-write.test.ts (99%) rename tests/{ => codex-integration}/codex-prompt-layers.test.ts (99%) rename tests/{ => codex-integration}/codex-prompt-lock.test.ts (98%) rename tests/{ => codex-integration}/codex-prompt-route.test.ts (98%) rename tests/{ => codex-integration}/codex-prompt-text-probe.test.ts (99%) rename tests/{ => codex-integration}/codex-quota-parser-parity.test.ts (98%) rename tests/{ => codex-integration}/codex-quota-prime.test.ts (98%) rename tests/{ => codex-integration}/codex-quota-rejection.test.ts (98%) rename tests/{ => codex-integration}/codex-refresh.test.ts (97%) rename tests/{ => codex-integration}/codex-reset-credit-auto-redeem.test.ts (98%) rename tests/{ => codex-integration}/codex-reset-credit-operation-ledger.test.ts (99%) rename tests/{ => codex-integration}/codex-reset-credit-recovery.test.ts (99%) rename tests/{ => codex-integration}/codex-restart-contract-parity.test.ts (97%) rename tests/{ => codex-integration}/codex-restart-route.test.ts (92%) rename tests/{ => codex-integration}/codex-restore-app-rewrite.test.ts (98%) rename tests/{ => codex-integration}/codex-retained-root-serialization.test.ts (99%) rename tests/{ => codex-integration}/codex-routing.test.ts (99%) rename tests/{ => codex-integration}/codex-runtime.test.ts (99%) rename tests/{ => codex-integration}/codex-service-manager-probe-hardening.test.ts (98%) rename tests/{ => codex-integration}/codex-service-manager-probe.test.ts (99%) rename tests/{ => codex-integration}/codex-shim-autorestore.test.ts (94%) rename tests/{ => codex-integration}/codex-shim-readiness.test.ts (96%) rename tests/{ => codex-integration}/codex-shim.test.ts (99%) rename tests/{ => codex-integration}/codex-spark-visibility.test.ts (94%) rename tests/{ => codex-integration}/codex-sqlite-home.test.ts (94%) rename tests/{ => codex-integration}/codex-sync-api.test.ts (97%) rename tests/{ => codex-integration}/codex-sync-response.test.ts (97%) rename tests/{ => codex-integration}/codex-tool-mode.test.ts (90%) rename tests/{ => codex-integration}/codex-transition-state-adoption.test.ts (90%) rename tests/{ => codex-integration}/codex-transition-state-first-use-regression.test.ts (93%) rename tests/{ => codex-integration}/codex-transition-state-race.test.ts (97%) rename tests/{ => codex-integration}/codex-transition-state.test.ts (98%) rename tests/{ => codex-integration}/codex-user-identity.test.ts (98%) rename tests/{ => codex-integration}/codex-v2-gate.test.ts (99%) rename tests/{ => codex-integration}/codex-warmup.test.ts (99%) rename tests/{ => codex-integration}/codex-websocket-registry.test.ts (96%) rename tests/{ => codex-integration}/codex-write-lock.test.ts (98%) rename tests/{ => codex-integration}/combos.test.ts (98%) rename tests/{ => codex-integration}/compatibility-manifest.test.ts (91%) rename tests/{ => codex-integration}/custom-model-catalog-migration.test.ts (97%) rename tests/{ => codex-integration}/doctor.test.ts (99%) rename tests/{ => codex-integration}/effort-policy.test.ts (97%) rename tests/{ => codex-integration}/fast-row-listing.test.ts (94%) rename tests/{ => codex-integration}/fast-row.test.ts (98%) rename tests/{ => codex-integration}/gather-routed-models-single-flight.test.ts (97%) rename tests/{ => codex-integration}/history-migration-guardian.test.ts (98%) rename tests/{ => codex-integration}/injection-model-api.test.ts (97%) rename tests/{ => codex-integration}/issue-452-empty-503.test.ts (94%) rename tests/{ => codex-integration}/issue-702-expired-replay-state.test.ts (96%) rename tests/{ => codex-integration}/issue-914-transport-attribution.test.ts (93%) rename tests/{ => codex-integration}/model-cache-generation-tombstone.test.ts (98%) rename tests/{ => codex-integration}/model-cache.test.ts (97%) rename tests/{ => codex-integration}/model-display-names-management-api.test.ts (97%) rename tests/{ => codex-integration}/model-metadata-sync.test.ts (86%) rename tests/{ => codex-integration}/model-visibility-management-api.test.ts (95%) rename tests/{ => codex-integration}/multi-agent-compat.test.ts (99%) rename tests/{ => codex-integration}/multi-agent-keep-native-v1.test.ts (96%) rename tests/{ => codex-integration}/native-alias-maintainer-regressions.test.ts (96%) rename tests/{ => codex-integration}/native-claude-code-toggle.test.ts (98%) rename tests/{ => codex-integration}/native-claude-desktop-toggle.test.ts (97%) rename tests/{ => codex-integration}/native-codex-toggle.test.ts (96%) rename tests/{ => codex-integration}/native-grok-toggle.test.ts (95%) rename tests/{ => codex-integration}/native-main-auth-temp.test.ts (94%) rename tests/{ => codex-integration}/native-main-claim-cache.test.ts (97%) rename tests/{ => codex-integration}/native-main-claim.test.ts (95%) rename tests/{ => codex-integration}/native-main-owner-lifetime.test.ts (97%) rename tests/{ => codex-integration}/native-model-toggle.test.ts (98%) rename tests/{ => codex-integration}/native-profile-api.test.ts (98%) rename tests/{ => codex-integration}/native-profile-crash-boundaries.test.ts (95%) rename tests/{ => codex-integration}/native-profile-drain-server.test.ts (93%) rename tests/{ => codex-integration}/native-profile-manager.test.ts (99%) rename tests/{ => codex-integration}/native-profile-processes.test.ts (98%) rename tests/{ => codex-integration}/native-profile-recovery.test.ts (98%) rename tests/{ => codex-integration}/native-profile-route-security.test.ts (95%) rename tests/{ => codex-integration}/native-profile-stage-lifecycle.test.ts (98%) rename tests/{ => codex-integration}/native-profile-startup.test.ts (98%) rename tests/{ => codex-integration}/native-profile-store.test.ts (98%) rename tests/{ => codex-integration}/parallel-tool-calls-optin.test.ts (97%) rename tests/{ => codex-integration}/project-config-warnings.test.ts (99%) rename tests/{ => codex-integration}/reasoning-effort.test.ts (98%) rename tests/{ => codex-integration}/selected-models.test.ts (98%) rename tests/{ => codex-integration}/slug-codec.test.ts (97%) rename tests/{ => codex-integration}/token-guardian.test.ts (96%) rename tests/{ => codex-integration}/ultrafast-tier-honesty.test.ts (97%) rename tests/{ => codex-integration}/upstream-reachability.test.ts (98%) rename tests/{ => codex-integration}/warmup.test.ts (99%) rename tests/{ => providers}/alibaba-region-backup.test.ts (96%) rename tests/{ => providers}/alibaba-region-migration.test.ts (95%) rename tests/{ => providers}/alibaba-region-startup.test.ts (91%) rename tests/{ => providers}/aside-client.test.ts (97%) rename tests/{ => providers}/auto-compact-budget.test.ts (97%) rename tests/{ => providers}/azure-adapter.test.ts (94%) rename tests/{ => providers}/azure-model-router-tool-schema.test.ts (93%) rename tests/{ => providers}/baseten-provider.test.ts (92%) rename tests/{ => providers}/chutes-provider.test.ts (89%) rename tests/{ => providers}/cline-pass-deepseek-v4-tool-replay.test.ts (92%) rename tests/{ => providers}/cline-pass-provider.test.ts (96%) rename tests/{ => providers}/cline-pass-reasoning-efforts.test.ts (95%) rename tests/{ => providers}/cline-provider.test.ts (91%) rename tests/{ => providers}/command-code-error-finish.test.ts (92%) rename tests/{ => providers}/command-code-provider.test.ts (98%) rename tests/{ => providers}/command-code-quota.test.ts (98%) rename tests/{ => providers}/command-code-workspace-cache.test.ts (98%) rename tests/{ => providers}/commandcode-provider.test.ts (91%) rename tests/{ => providers}/context-cap-unknown-window.test.ts (95%) rename tests/{ => providers/cursor}/cursor-adapter.test.ts (97%) rename tests/{ => providers/cursor}/cursor-arg-normalize.test.ts (97%) rename tests/{ => providers/cursor}/cursor-blob-integrity.test.ts (96%) rename tests/{ => providers/cursor}/cursor-blob.test.ts (99%) rename tests/{ => providers/cursor}/cursor-call-id.test.ts (94%) rename tests/{ => providers/cursor}/cursor-cancel-provenance.test.ts (94%) rename tests/{ => providers/cursor}/cursor-catalog.test.ts (99%) rename tests/{ => providers/cursor}/cursor-claude-id.test.ts (98%) rename tests/{ => providers/cursor}/cursor-default-catalog-suppression.test.ts (91%) rename tests/{ => providers/cursor}/cursor-desktop-exec.test.ts (97%) rename tests/{ => providers/cursor}/cursor-discovery.test.ts (99%) rename tests/{ => providers/cursor}/cursor-display-names.test.ts (88%) rename tests/{ => providers/cursor}/cursor-effort-rows.test.ts (93%) rename tests/{ => providers/cursor}/cursor-effort-suffix.test.ts (98%) rename tests/{ => providers/cursor}/cursor-effort-table.test.ts (93%) rename tests/{ => providers/cursor}/cursor-envelope-echo-retry.test.ts (98%) rename tests/{ => providers/cursor}/cursor-eof-terminal.test.ts (96%) rename tests/{ => providers/cursor}/cursor-errors.test.ts (98%) rename tests/{ => providers/cursor}/cursor-exec-empty-result.test.ts (98%) rename tests/{ => providers/cursor}/cursor-fast-listing.test.ts (86%) rename tests/{ => providers/cursor}/cursor-fast-tier.test.ts (91%) rename tests/{ => providers/cursor}/cursor-framing.test.ts (99%) rename tests/{ => providers/cursor}/cursor-h2-pool-shutdown.test.ts (94%) rename tests/{ => providers/cursor}/cursor-hardening.test.ts (98%) rename tests/{ => providers/cursor}/cursor-http1-transport.test.ts (97%) rename tests/{ => providers/cursor}/cursor-images.test.ts (97%) rename tests/{ => providers/cursor}/cursor-integration-status.test.ts (93%) rename tests/{ => providers/cursor}/cursor-interaction-query.test.ts (90%) rename tests/{ => providers/cursor}/cursor-kv-store.test.ts (86%) rename tests/{ => providers/cursor}/cursor-live-smoke-gate.test.ts (97%) rename tests/{ => providers/cursor}/cursor-live-transport.test.ts (96%) rename tests/{ => providers/cursor}/cursor-local-models-schema.test.ts (95%) rename tests/{ => providers/cursor}/cursor-mcp-manager.test.ts (97%) rename tests/{ => providers/cursor}/cursor-mcp-stdio.test.ts (93%) rename tests/{ => providers/cursor}/cursor-message-mapper.test.ts (93%) rename tests/{ => providers/cursor}/cursor-native-exec-common.test.ts (95%) rename tests/{ => providers/cursor}/cursor-native-exec-policy.test.ts (96%) rename tests/{ => providers/cursor}/cursor-native-exec-shell.test.ts (99%) rename tests/{ => providers/cursor}/cursor-native-exec.test.ts (99%) rename tests/{ => providers/cursor}/cursor-oauth-shell.test.ts (83%) rename tests/{ => providers/cursor}/cursor-oauth.test.ts (99%) rename tests/{ => providers/cursor}/cursor-pool.test.ts (96%) rename tests/{ => providers/cursor}/cursor-protobuf-events.test.ts (99%) rename tests/{ => providers/cursor}/cursor-repetition-breaker.test.ts (96%) rename tests/{ => providers/cursor}/cursor-request-builder.test.ts (99%) rename tests/{ => providers/cursor}/cursor-silent-redirect.test.ts (94%) rename tests/{ => providers/cursor}/cursor-static-catalog.test.ts (92%) rename tests/{ => providers/cursor}/cursor-stream-health.test.ts (95%) rename tests/{ => providers/cursor}/cursor-structured-edit.test.ts (99%) rename tests/{ => providers/cursor}/cursor-tool-arg-decoding.test.ts (99%) rename tests/{ => providers/cursor}/cursor-tool-choice.test.ts (94%) rename tests/{ => providers/cursor}/cursor-tool-continuation.test.ts (96%) rename tests/{ => providers/cursor}/cursor-tool-definitions.test.ts (99%) rename tests/{ => providers/cursor}/cursor-tool-finalize-race.test.ts (96%) rename tests/{ => providers/cursor}/cursor-tool-result-image.test.ts (98%) rename tests/{ => providers/cursor}/cursor-tool-result-invocation.test.ts (99%) rename tests/{ => providers/cursor}/cursor-tool-suspended-checkpoint.test.ts (92%) rename tests/{ => providers/cursor}/cursor-toolresult-normalize.test.ts (95%) rename tests/{ => providers/cursor}/cursor-transport-retry.test.ts (98%) rename tests/{ => providers/cursor}/cursor-ultra-mode.test.ts (92%) rename tests/{ => providers/cursor}/cursor-umbrella-rows.test.ts (96%) rename tests/{ => providers/cursor}/cursor-uncallable-quarantine.test.ts (94%) rename tests/{ => providers/cursor}/cursor-vision-wire-harness.test.ts (93%) rename tests/{ => providers}/cyber-policy-error-fidelity.test.ts (97%) rename tests/{ => providers}/deepinfra-provider.test.ts (88%) rename tests/{ => providers}/deepseek-inbound-wire.test.ts (98%) rename tests/{ => providers}/deepseek-reasoning-replay-gaps.test.ts (98%) rename tests/{ => providers}/deepseek-reasoning-replay.test.ts (94%) rename tests/{ => providers}/deepseek-responses-item-id-repair.test.ts (96%) rename tests/{ => providers}/digitalocean-scaleway-provider.test.ts (92%) rename tests/{ => providers}/exa-web-search.test.ts (95%) rename tests/{ => providers}/fast-row-ingress.test.ts (92%) rename tests/{ => providers}/featherless-provider.test.ts (88%) rename tests/{ => providers}/forward-admission-separation.test.ts (93%) rename tests/{ => providers/github-copilot}/github-copilot-account-origin.test.ts (96%) rename tests/{ => providers/github-copilot}/github-copilot-oauth.test.ts (97%) rename tests/{ => providers/github-copilot}/github-copilot-sse-rewrite.test.ts (97%) rename tests/{ => providers/github-copilot}/github-copilot-stream-contract.test.ts (96%) rename tests/{ => providers/github-copilot}/github-copilot-wire-defaults.test.ts (92%) rename tests/{ => providers}/hyperbolic-provider.test.ts (88%) rename tests/{ => providers}/kimi-oauth-identity.test.ts (98%) rename tests/{ => providers/kiro}/kiro-account-quota.test.ts (96%) rename tests/{ => providers/kiro}/kiro-adapter.test.ts (99%) rename tests/{ => providers/kiro}/kiro-builder-id-profile.test.ts (95%) rename tests/{ => providers/kiro}/kiro-calibration.test.ts (99%) rename tests/{ => providers/kiro}/kiro-images.test.ts (96%) rename tests/{ => providers/kiro}/kiro-oauth.test.ts (99%) rename tests/{ => providers/kiro}/kiro-pool-rank.test.ts (97%) rename tests/{ => providers/kiro}/kiro-reasoning-roundtrip.test.ts (94%) rename tests/{ => providers/kiro}/kiro-retry.test.ts (98%) rename tests/{ => providers/kiro}/kiro-review-regressions.test.ts (97%) rename tests/{ => providers/kiro}/kiro-stream.test.ts (99%) rename tests/{ => providers/kiro}/kiro-usage-quota.test.ts (99%) rename tests/{ => providers/kiro}/kiro-windows-cli-db-path.test.ts (97%) rename tests/{ => providers/kiro}/kiro-windows-cli-executable-path.test.ts (98%) rename tests/{ => providers}/meta-model-api-provider.test.ts (95%) rename tests/{ => providers}/meta-muse-oauth.test.ts (97%) rename tests/{ => providers}/mimo-effort.test.ts (92%) rename tests/{ => providers}/mimo-free-provider.test.ts (97%) rename tests/{ => providers}/mimo-token-plan-provider.test.ts (94%) rename tests/{ => providers}/minimax-clients.test.ts (98%) rename tests/{ => providers}/minimax-reasoning-split.test.ts (97%) rename tests/{ => providers}/model-presets.test.ts (97%) rename tests/{ => providers}/model-rename-migration.test.ts (97%) rename tests/{ => providers}/moonshot-endpoints.test.ts (89%) rename tests/{ => providers}/moonshot-tool-schema.test.ts (99%) rename tests/{ => providers}/muse-passive-quota-cache.test.ts (94%) rename tests/{ => providers}/muse-passive-quota-observation.test.ts (96%) rename tests/{ => providers}/muse-spark-web-search-compat.test.ts (96%) rename tests/{ => providers}/muse-subscription-usage.test.ts (98%) rename tests/{ => providers}/new-model-policy.test.ts (98%) rename tests/{ => providers}/nous-oauth-live.test.ts (95%) rename tests/{ => providers}/nous-oauth.test.ts (99%) rename tests/{ => providers}/novita-provider.test.ts (88%) rename tests/{ => providers}/nscale-vultr-provider.test.ts (90%) rename tests/{ => providers}/nvidia-nim-hardening.test.ts (97%) rename tests/{ => providers/ollama}/ollama-native-parser.test.ts (98%) rename tests/{ => providers/ollama}/ollama-native-reasoning-wire.test.ts (94%) rename tests/{ => providers/ollama}/ollama-native-structured-output.test.ts (97%) rename tests/{ => providers/ollama}/ollama-native-v4.test.ts (93%) rename tests/{ => providers/ollama}/ollama-native.test.ts (96%) rename tests/{ => providers/ollama}/ollama-show-enrichment-v7.test.ts (97%) rename tests/{ => providers/ollama}/ollama-show-enrichment.test.ts (97%) rename tests/{ => providers/ollama}/ollama-show-ignore-abort.test.ts (98%) rename tests/{ => providers}/opencode-cli.test.ts (98%) rename tests/{ => providers}/opencode-free-provider.test.ts (95%) rename tests/{ => providers}/opencode-go-deepseek.test.ts (96%) rename tests/{ => providers}/opencode-go-grok46-responses.test.ts (91%) rename tests/{ => providers}/opencode-go-luna-wire.test.ts (90%) rename tests/{ => providers}/opencode-go-muse-context.test.ts (92%) rename tests/{ => providers}/opencode-go-muse-vision.test.ts (95%) rename tests/{ => providers}/opencode-go-quota.test.ts (98%) rename tests/{ => providers}/opencode-go-session-header.test.ts (93%) rename tests/{ => providers}/opencode-zen-deepseek-reasoning.test.ts (95%) rename tests/{ => providers}/opencode-zen-rate-limit.test.ts (94%) rename tests/{ => providers}/openrouter-provider-routing.test.ts (97%) rename tests/{ => providers}/provider-account-quota-persistence.test.ts (94%) rename tests/{ => providers}/provider-account-quota.test.ts (97%) rename tests/{ => providers}/provider-api-keys.test.ts (94%) rename tests/{ => providers}/provider-capacity.test.ts (99%) rename tests/{ => providers}/provider-config-batch-management.test.ts (95%) rename tests/{ => providers}/provider-config-validation.test.ts (99%) rename tests/{ => providers}/provider-connection-test.test.ts (96%) rename tests/{ => providers}/provider-cost-overlay-config.test.ts (98%) rename tests/{ => providers}/provider-discovery-log-suppression.test.ts (98%) rename tests/{ => providers}/provider-id-rewrite.test.ts (97%) rename tests/{ => providers}/provider-key-store.test.ts (94%) rename tests/{ => providers}/provider-live-models.test.ts (98%) rename tests/{ => providers}/provider-model-aliases.test.ts (94%) rename tests/{ => providers}/provider-model-discovery-contract.test.ts (96%) rename tests/{ => providers}/provider-outbound-private-network.test.ts (97%) rename tests/{ => providers}/provider-outbound.test.ts (94%) rename tests/{ => providers}/provider-quota-observed-marker.test.ts (93%) rename tests/{ => providers}/provider-quota.test.ts (99%) rename tests/{ => providers}/provider-registry-parity.test.ts (98%) rename tests/{ => providers}/provider-static-model-discovery.test.ts (94%) rename tests/{ => providers}/qwen38-preserve-reasoning.test.ts (94%) rename tests/{ => providers}/rate-limit-retry.test.ts (98%) rename tests/{ => providers}/sambanova-nebius-provider.test.ts (92%) rename tests/{ => providers}/umans-provider.test.ts (97%) rename tests/{ => providers}/upstream-transient-retry.test.ts (98%) rename tests/{ => providers}/vercel-gateway-provider-routing.test.ts (96%) rename tests/{ => providers}/volcengine-ark-assistant-content.test.ts (98%) rename tests/{ => providers/xai}/grok-attribution.test.ts (88%) rename tests/{ => providers/xai}/grok-config-inject.test.ts (99%) rename tests/{ => providers/xai}/grok-effort-inject.test.ts (96%) rename tests/{ => providers/xai}/grok-lifecycle.test.ts (94%) rename tests/{ => providers/xai}/grok-management-api.test.ts (95%) rename tests/{ => providers/xai}/grok-models-effort-list.test.ts (95%) rename tests/{ => providers/xai}/grok-orphan-adoption.test.ts (99%) rename tests/{ => providers/xai}/grok-selection.test.ts (94%) rename tests/{ => providers/xai}/grok-status.test.ts (96%) rename tests/{ => providers/xai}/grok-sync.test.ts (96%) rename tests/{ => providers/xai}/grok-writer-boundary.test.ts (96%) rename tests/{ => providers/xai}/xai-oauth-retry.test.ts (96%) rename tests/{ => providers/xai}/xai-refresh-lock.test.ts (96%) rename tests/{ => providers/xai}/xai-tool-schema.test.ts (98%) rename tests/{ => providers/xai}/xai-transport.test.ts (98%) rename tests/{ => providers/xai}/xai-web-search-compat.test.ts (96%) rename tests/{ => providers/xai}/xai-web-search.test.ts (92%) rename tests/{ => providers}/zcode-client.test.ts (97%) rename tests/{ => providers}/zhipu-bigmodel-provider.test.ts (92%) diff --git a/.github/scripts/pr-hygiene.test.cjs b/.github/scripts/pr-hygiene.test.cjs index e36435ed339..ff2d5d3c9c8 100644 --- a/.github/scripts/pr-hygiene.test.cjs +++ b/.github/scripts/pr-hygiene.test.cjs @@ -225,7 +225,7 @@ describe("collectDeterministicHygieneFailures", () => { const failures = collectDeterministicHygieneFailures({ files: [ { filename: "src/codex/auth-api.ts", patch: "+change" }, - { filename: "tests/codex-auth-api.test.ts", patch: "+test" }, + { filename: "tests/codex-integration/codex-auth-api.test.ts", patch: "+test" }, ], authorHasPushPermission: true, }); diff --git a/docs/superpowers/plans/2026-07-26-oauth-reliability-integrity.md b/docs/superpowers/plans/2026-07-26-oauth-reliability-integrity.md index fb535a1ca4e..15bc508f210 100644 --- a/docs/superpowers/plans/2026-07-26-oauth-reliability-integrity.md +++ b/docs/superpowers/plans/2026-07-26-oauth-reliability-integrity.md @@ -209,7 +209,7 @@ EOF **Files:** - Modify: `src/oauth/index.ts` (`refreshAndPersistAccessToken` generic branch ~352–400) -- Test: `tests/oauth/oauth-refresh-generic-lock.test.ts` (new; mirror patterns from `tests/xai-refresh-lock.test.ts` / `tests/oauth/oauth-refresh.test.ts`) +- Test: `tests/oauth/oauth-refresh-generic-lock.test.ts` (new; mirror patterns from `tests/providers/xai/xai-refresh-lock.test.ts` / `tests/oauth/oauth-refresh.test.ts`) **Interfaces:** - Consumes: `createOAuthRefreshIntentLock`, `mergeAccountCredential`, `credentialGeneration`, `markAccountNeedsReauthIfGeneration`, `getAccountCredential`, `logOAuthEvent` @@ -308,7 +308,7 @@ Also log `"OAuth refresh joined existing operation"` when `tokenRefreshes.get(ke Run: ```bash -bun test tests/oauth/oauth-refresh-generic-lock.test.ts tests/oauth/oauth-refresh.test.ts tests/xai-refresh-lock.test.ts +bun test tests/oauth/oauth-refresh-generic-lock.test.ts tests/oauth/oauth-refresh.test.ts tests/providers/xai/xai-refresh-lock.test.ts ``` Expected: PASS (no regressions on xAI/Anthropic) @@ -420,7 +420,7 @@ Set `action` strings: - [ ] **Step 4: Run test to verify it passes** -Run: `bun test tests/oauth/oauth-health.test.ts tests/codex-routing.test.ts` +Run: `bun test tests/oauth/oauth-health.test.ts tests/codex-integration/codex-routing.test.ts` Expected: PASS @@ -502,7 +502,7 @@ EOF **Files:** - Modify: `src/cli/doctor.ts` -- Test: `tests/service/doctor-oauth.test.ts` (or extend `tests/doctor.test.ts`) +- Test: `tests/service/doctor-oauth.test.ts` (or extend `tests/codex-integration/doctor.test.ts`) **Interfaces:** - Consumes: `collectOAuthHealthEntries`, auth store writability checks, refresh lock path helpers if exported @@ -529,7 +529,7 @@ Add `collectOAuthDoctorChecks(): Array<{ level: "OK" | "WARN"; message: string } - [ ] **Step 4: Run tests** -Run: `bun test tests/service/doctor-oauth.test.ts tests/doctor.test.ts` +Run: `bun test tests/service/doctor-oauth.test.ts tests/codex-integration/doctor.test.ts` Expected: PASS @@ -607,9 +607,9 @@ EOF ### Task 8: Codex metadata integrity regressions + 401 replay invariants **Files:** -- Test: `tests/codex-metadata-integrity.test.ts` (new) +- Test: `tests/codex-integration/codex-metadata-integrity.test.ts` (new) - Modify only if a real gap is found: `src/codex/auth-context.ts`, `src/adapters/openai-responses.ts` -- Confirm existing: `tests/server-xai-oauth-401-replay.test.ts`, `tests/server-kiro-oauth-401-replay.test.ts`, `tests/codex-routing.test.ts` (policy A) +- Confirm existing: `tests/server-xai-oauth-401-replay.test.ts`, `tests/server-kiro-oauth-401-replay.test.ts`, `tests/codex-integration/codex-routing.test.ts` (policy A) **Interfaces:** - Consumes: `headersForCodexAuthContext`, `FORWARD_HEADERS` @@ -644,7 +644,7 @@ test("preserves genuine originator", () => { - [ ] **Step 2: Run tests** -Run: `bun test tests/codex-metadata-integrity.test.ts` +Run: `bun test tests/codex-integration/codex-metadata-integrity.test.ts` Expected: FAIL only if implementation gap exists; if PASS immediately, keep tests as regressions and skip code changes. @@ -655,7 +655,7 @@ If fabrication or account-id mismatch is found, fix the minimal header path. Do - [ ] **Step 4: Run related suite** ```bash -bun test tests/codex-metadata-integrity.test.ts tests/codex-auth-context.test.ts tests/codex-routing.test.ts tests/session-affinity.test.ts tests/server-xai-oauth-401-replay.test.ts tests/server-kiro-oauth-401-replay.test.ts +bun test tests/codex-integration/codex-metadata-integrity.test.ts tests/codex-integration/codex-auth-context.test.ts tests/codex-integration/codex-routing.test.ts tests/session-affinity.test.ts tests/server-xai-oauth-401-replay.test.ts tests/server-kiro-oauth-401-replay.test.ts ``` Expected: PASS @@ -663,7 +663,7 @@ Expected: PASS - [ ] **Step 5: Commit** ```bash -git add tests/codex-metadata-integrity.test.ts src/codex/auth-context.ts src/adapters/openai-responses.ts +git add tests/codex-integration/codex-metadata-integrity.test.ts src/codex/auth-context.ts src/adapters/openai-responses.ts git commit -m "$(cat <<'EOF' test(codex): lock metadata pass-through and non-fabrication @@ -713,8 +713,8 @@ EOF - [ ] **Step 1: Run verification commands** ```bash -bun test tests/lib/privacy-mask-account.test.ts tests/oauth/oauth-log.test.ts tests/oauth/oauth-refresh-generic-lock.test.ts tests/oauth/oauth-health.test.ts tests/cli/cli-status-oauth-health.test.ts tests/service/doctor-oauth.test.ts tests/oauth/oauth-accounts-api.test.ts tests/codex-metadata-integrity.test.ts -bun test tests/oauth/oauth-refresh.test.ts tests/xai-refresh-lock.test.ts tests/codex-routing.test.ts tests/session-affinity.test.ts tests/codex-auth-context.test.ts +bun test tests/lib/privacy-mask-account.test.ts tests/oauth/oauth-log.test.ts tests/oauth/oauth-refresh-generic-lock.test.ts tests/oauth/oauth-health.test.ts tests/cli/cli-status-oauth-health.test.ts tests/service/doctor-oauth.test.ts tests/oauth/oauth-accounts-api.test.ts tests/codex-integration/codex-metadata-integrity.test.ts +bun test tests/oauth/oauth-refresh.test.ts tests/providers/xai/xai-refresh-lock.test.ts tests/codex-integration/codex-routing.test.ts tests/session-affinity.test.ts tests/codex-integration/codex-auth-context.test.ts bun run test bun run typecheck bun run lint:gui diff --git a/docs/superpowers/plans/2026-08-06-deepseek-responses-streaming-terminal-repair.md b/docs/superpowers/plans/2026-08-06-deepseek-responses-streaming-terminal-repair.md index 11976200cdd..4720749b10a 100644 --- a/docs/superpowers/plans/2026-08-06-deepseek-responses-streaming-terminal-repair.md +++ b/docs/superpowers/plans/2026-08-06-deepseek-responses-streaming-terminal-repair.md @@ -27,7 +27,7 @@ - `src/server/responses-terminal-repair.ts` — owns SSE lifecycle tracking, bounded retained state, grace scheduling, and synthetic terminal creation. - `src/server/responses/core.ts` — activates the repair before existing transport-specific relay branches. - `tests/responses/responses-terminal-repair.test.ts` — unit state-machine and stream-race coverage. -- `tests/deepseek-inbound-wire.test.ts` — end-to-end official DeepSeek wire and HTTP activation. +- `tests/providers/deepseek-inbound-wire.test.ts` — end-to-end official DeepSeek wire and HTTP activation. - `tests/responses/ws-endpoint.test.ts` — WebSocket event parity for real and repaired terminals. - `structure/04_transports-and-sidecars.md` — architectural contract for the provider-scoped streaming repair. - `docs/superpowers/specs/2026-08-06-deepseek-responses-streaming-terminal-repair-design.md` — approved design authority; implementation must remain consistent with it. @@ -40,8 +40,8 @@ - Modify: `src/providers/registry.ts:150-170` - Modify: `src/providers/registry.ts:1143-1162` - Modify: `src/providers/registry.ts:1834-1842` -- Modify: `tests/deepseek-inbound-wire.test.ts:1-175` -- Modify: `tests/deepseek-responses-item-id-repair.test.ts` +- Modify: `tests/providers/deepseek-inbound-wire.test.ts:1-175` +- Modify: `tests/providers/deepseek-responses-item-id-repair.test.ts` **Interfaces:** - Produces: `ResponsesTerminalRepairPolicy` @@ -74,7 +74,7 @@ test("Codex HTTP and WebSocket turns keep DeepSeek streaming upstream", async () Delete or rewrite the tests whose asserted contract is specifically `stream:false`/bounded JSON for built-in DeepSeek. Keep the bounded-JSON helper coverage that is provider-neutral. In -`tests/deepseek-responses-item-id-repair.test.ts`, retain the pure +`tests/providers/deepseek-responses-item-id-repair.test.ts`, retain the pure `repairResponsesJsonItemIds()` unit test but remove the built-in-DeepSeek HTTP activation assertion; Task 4 replaces it with streaming repair composition. @@ -83,7 +83,7 @@ activation assertion; Task 4 replaces it with streaming repair composition. Run: ```bash -bun test tests/deepseek-inbound-wire.test.ts +bun test tests/providers/deepseek-inbound-wire.test.ts ``` Expected: compile/test failure because `providerModelResponsesTerminalRepair` @@ -134,7 +134,7 @@ export function providerModelResponsesTerminalRepair( Run: ```bash -bun test tests/deepseek-inbound-wire.test.ts tests/deepseek-responses-item-id-repair.test.ts tests/provider-registry-parity.test.ts +bun test tests/providers/deepseek-inbound-wire.test.ts tests/providers/deepseek-responses-item-id-repair.test.ts tests/providers/provider-registry-parity.test.ts ``` Expected: all selected tests pass; captured HTTP and WebSocket request bodies @@ -143,7 +143,7 @@ carry `stream:true`. - [ ] **Step 5: Commit** ```bash -git add src/providers/registry.ts tests/deepseek-inbound-wire.test.ts tests/deepseek-responses-item-id-repair.test.ts +git add src/providers/registry.ts tests/providers/deepseek-inbound-wire.test.ts tests/providers/deepseek-responses-item-id-repair.test.ts git commit -m "fix(deepseek): restore Responses upstream streaming" ``` @@ -386,8 +386,8 @@ git commit -m "fix(responses): fail closed on unsafe terminal repair" **Files:** - Modify: `src/server/responses/core.ts:95-115` - Modify: `src/server/responses/core.ts:2030-2230` -- Modify: `tests/deepseek-inbound-wire.test.ts:115-330` -- Modify: `tests/deepseek-responses-item-id-repair.test.ts` +- Modify: `tests/providers/deepseek-inbound-wire.test.ts:115-330` +- Modify: `tests/providers/deepseek-responses-item-id-repair.test.ts` - Modify: `tests/responses/ws-endpoint.test.ts` **Interfaces:** @@ -432,7 +432,7 @@ WebSocket handling. Assert the client receives progressive delta frames, one Run: ```bash -bun test tests/deepseek-inbound-wire.test.ts tests/responses/ws-endpoint.test.ts +bun test tests/providers/deepseek-inbound-wire.test.ts tests/responses/ws-endpoint.test.ts ``` Expected: requests now carry `stream:true` from Task 1 but no provider-scoped @@ -482,7 +482,7 @@ streaming resolver still returns `false`. Run: ```bash -bun test tests/deepseek-inbound-wire.test.ts tests/responses/ws-endpoint.test.ts tests/responses/responses-state.test.ts tests/deepseek-responses-item-id-repair.test.ts tests/deepseek-reasoning-replay.test.ts +bun test tests/providers/deepseek-inbound-wire.test.ts tests/responses/ws-endpoint.test.ts tests/responses/responses-state.test.ts tests/providers/deepseek-responses-item-id-repair.test.ts tests/providers/deepseek-reasoning-replay.test.ts ``` Expected: progressive output precedes terminal, both transports close once, @@ -491,7 +491,7 @@ item ids are stable, and continuation state retains reasoning/function output. - [ ] **Step 6: Commit** ```bash -git add src/server/responses/core.ts tests/deepseek-inbound-wire.test.ts tests/deepseek-responses-item-id-repair.test.ts tests/responses/ws-endpoint.test.ts +git add src/server/responses/core.ts tests/providers/deepseek-inbound-wire.test.ts tests/providers/deepseek-responses-item-id-repair.test.ts tests/responses/ws-endpoint.test.ts git commit -m "fix(deepseek): repair terminal-less Responses streams" ``` @@ -560,7 +560,7 @@ git commit -m "docs(deepseek): describe streaming terminal repair" Run: ```bash -bun test tests/responses/responses-terminal-repair.test.ts tests/deepseek-inbound-wire.test.ts tests/responses/ws-endpoint.test.ts tests/responses/sse-failed-tail.test.ts tests/relay-eager.test.ts tests/responses/responses-item-id-repair.test.ts tests/deepseek-responses-item-id-repair.test.ts tests/deepseek-reasoning-replay.test.ts tests/responses/responses-state.test.ts +bun test tests/responses/responses-terminal-repair.test.ts tests/providers/deepseek-inbound-wire.test.ts tests/responses/ws-endpoint.test.ts tests/responses/sse-failed-tail.test.ts tests/relay-eager.test.ts tests/responses/responses-item-id-repair.test.ts tests/providers/deepseek-responses-item-id-repair.test.ts tests/providers/deepseek-reasoning-replay.test.ts tests/responses/responses-state.test.ts ``` Expected: 0 failures. diff --git a/docs/superpowers/plans/2026-08-09-routed-computer-use-browser.md b/docs/superpowers/plans/2026-08-09-routed-computer-use-browser.md index 55121abd8ec..ac2a9a66359 100644 --- a/docs/superpowers/plans/2026-08-09-routed-computer-use-browser.md +++ b/docs/superpowers/plans/2026-08-09-routed-computer-use-browser.md @@ -13,9 +13,9 @@ ## Task 1: Lock the routed catalog contract with failing tests **Files:** -- Modify: `tests/codex-catalog.test.ts:280-300` -- Modify: `tests/codex-catalog.test.ts:1011-1045` -- Modify: `tests/codex-catalog.test.ts:1230-1255` +- Modify: `tests/codex-integration/codex-catalog.test.ts:280-300` +- Modify: `tests/codex-integration/codex-catalog.test.ts:1011-1045` +- Modify: `tests/codex-integration/codex-catalog.test.ts:1230-1255` **Step 1: Change the combo assertion to require the explicit routed mode** @@ -68,7 +68,7 @@ expect(rows.find(row => row.slug === "team/gpt-5.5")?.tool_mode).toBe("code"); Run: ```bash -bun test tests/codex-catalog.test.ts +bun test tests/codex-integration/codex-catalog.test.ts ``` Expected: routed/template/combo/fallback assertions fail because current production code deletes or omits `tool_mode`; native preservation assertions remain green. @@ -76,7 +76,7 @@ Expected: routed/template/combo/fallback assertions fail because current product **Step 6: Commit the red tests only** ```bash -git add tests/codex-catalog.test.ts +git add tests/codex-integration/codex-catalog.test.ts git commit -m "test(codex): require code mode for routed models" ``` @@ -86,7 +86,7 @@ git commit -m "test(codex): require code mode for routed models" - Modify: `src/codex/catalog/parsing.ts:341-375` - Modify: `src/codex/catalog/sync.ts:33` - Modify: `src/codex/catalog/sync.ts:276-310` -- Test: `tests/codex-catalog.test.ts` +- Test: `tests/codex-integration/codex-catalog.test.ts` **Step 1: Add a named compatibility helper** @@ -128,7 +128,7 @@ Do not call the full routed normalizer from the fallback branch; that would broa **Step 4: Run the focused tests and confirm GREEN** ```bash -bun test tests/codex-catalog.test.ts +bun test tests/codex-integration/codex-catalog.test.ts ``` Expected: all catalog tests pass, including native/account preservation. @@ -151,8 +151,8 @@ git commit -m "fix(codex): enable code mode for routed models" ## Task 3: Prove on-disk catalog synchronization preserves the policy **Files:** -- Modify: `tests/codex-catalog-sync-hardening.test.ts` -- Test: `tests/codex-catalog-sync-hardening.test.ts` +- Modify: `tests/codex-integration/codex-catalog-sync-hardening.test.ts` +- Test: `tests/codex-integration/codex-catalog-sync-hardening.test.ts` **Step 1: Add a real sync fixture assertion** @@ -169,7 +169,7 @@ Also assert a generated native account-qualified row retains `"code"` if the fix **Step 2: Run the sync test** ```bash -bun test tests/codex-catalog-sync-hardening.test.ts +bun test tests/codex-integration/codex-catalog-sync-hardening.test.ts ``` Expected: pass and prove the serialized catalog, not merely the in-memory builder. @@ -177,7 +177,7 @@ Expected: pass and prove the serialized catalog, not merely the in-memory builde **Step 3: Commit the persistence test** ```bash -git add tests/codex-catalog-sync-hardening.test.ts +git add tests/codex-integration/codex-catalog-sync-hardening.test.ts git commit -m "test(codex): persist routed code mode policy" ``` @@ -229,7 +229,7 @@ git commit -m "docs(codex): explain routed local tool access" Run: ```bash -bun test tests/responses/responses-parser.test.ts tests/adapters/bridge.test.ts tests/multi-agent-compat.test.ts +bun test tests/responses/responses-parser.test.ts tests/adapters/bridge.test.ts tests/codex-integration/multi-agent-compat.test.ts ``` Expected: custom declaration, streaming `custom_tool_call`, exact freeform input, and output replay remain green. Add no production protocol change unless one of these tests proves a real gap. @@ -239,7 +239,7 @@ Expected: custom declaration, streaming `custom_tool_call`, exact freeform input Run: ```bash -bun test tests/responses/responses-terminal-repair.test.ts tests/deepseek-inbound-wire.test.ts tests/deepseek-responses-item-id-repair.test.ts tests/responses/passthrough-abort.test.ts +bun test tests/responses/responses-terminal-repair.test.ts tests/providers/deepseek-inbound-wire.test.ts tests/providers/deepseek-responses-item-id-repair.test.ts tests/responses/passthrough-abort.test.ts ``` Expected: progressive deltas, strict terminal repair, item IDs, and cancellation pass. @@ -249,7 +249,7 @@ Expected: progressive deltas, strict terminal repair, item IDs, and cancellation Run: ```bash -bun test tests/vision/vision-sidecar-e2e.test.ts tests/vision/vision-anthropic.test.ts tests/vision/vision-cache.test.ts tests/vision/vision-fail-closed.test.ts tests/catalog-vision-sidecar-modalities.test.ts tests/responses/openai-responses-passthrough.test.ts +bun test tests/vision/vision-sidecar-e2e.test.ts tests/vision/vision-anthropic.test.ts tests/vision/vision-cache.test.ts tests/vision/vision-fail-closed.test.ts tests/codex-integration/catalog-vision-sidecar-modalities.test.ts tests/responses/openai-responses-passthrough.test.ts ``` Expected: captions replace raw image parts in passthrough bodies, empty references do not consume captions, and partial/failure paths omit pixels safely. diff --git a/docs/superpowers/plans/2026-08-13-cl10-deep-review-hardening.md b/docs/superpowers/plans/2026-08-13-cl10-deep-review-hardening.md index 32abc929e52..ce8233cbf38 100644 --- a/docs/superpowers/plans/2026-08-13-cl10-deep-review-hardening.md +++ b/docs/superpowers/plans/2026-08-13-cl10-deep-review-hardening.md @@ -175,7 +175,7 @@ ### Task 12: Move catalog timeout to the flaky test only **Files:** -- Modify: `tests/codex-catalog-sync-hardening.test.ts` +- Modify: `tests/codex-integration/codex-catalog-sync-hardening.test.ts` - Modify: `scripts/ci/run-bun-test-batches.sh` **Interfaces:** diff --git a/docs/superpowers/plans/2026-08-26-discovered-model-display-names-core.md b/docs/superpowers/plans/2026-08-26-discovered-model-display-names-core.md index 6d7c1776db5..81e41fc72dc 100644 --- a/docs/superpowers/plans/2026-08-26-discovered-model-display-names-core.md +++ b/docs/superpowers/plans/2026-08-26-discovered-model-display-names-core.md @@ -33,11 +33,11 @@ - `src/codex/catalog/provider-fetch.ts`: resolves operator display names at the shared catalog boundary. - `src/server/management/model-rows.ts`: exposes effective display names and their source. - `src/server/management/model-routes.ts`: sets and resets one provider model display name. -- `tests/provider-config-validation.test.ts`: covers strict validator behavior. +- `tests/providers/provider-config-validation.test.ts`: covers strict validator behavior. - `tests/config/config-load-degrade.test.ts`: covers safe hand edited config loading. - `tests/config/config-user-edits.test.ts`: covers persistence and concurrent unrelated map edits. -- `tests/codex-catalog.test.ts`: covers label precedence and routing invariants. -- `tests/model-display-names-management-api.test.ts`: covers read and mutation API behavior. +- `tests/codex-integration/codex-catalog.test.ts`: covers label precedence and routing invariants. +- `tests/codex-integration/model-display-names-management-api.test.ts`: covers read and mutation API behavior. - `docs-site/src/content/docs/reference/configuration/providers.md`: documents the field and exact key rules. - `structure/02_config-and-codex-home.md`: records the new persisted provider field. - `structure/03_catalog-and-subagents.md`: records display precedence at catalog assembly. @@ -50,7 +50,7 @@ - Modify: `src/types/provider.ts` - Modify: `src/config/provider-validation.ts` - Modify: `src/config.ts` -- Test: `tests/provider-config-validation.test.ts` +- Test: `tests/providers/provider-config-validation.test.ts` - Test: `tests/config/config-load-degrade.test.ts` **Interfaces:** @@ -75,7 +75,7 @@ expect(modelDisplayNamesConfigError({ "grok-4.6": "Grok\n4.6" })).toContain("con Run: ```text -bun test tests/provider-config-validation.test.ts +bun test tests/providers/provider-config-validation.test.ts ``` Expected: failure because `modelDisplayNamesConfigError` does not exist. @@ -105,7 +105,7 @@ The validator accepts only a plain own property object, at most 2,000 entries, e Run: ```text -bun test tests/provider-config-validation.test.ts +bun test tests/providers/provider-config-validation.test.ts ``` Expected: all tests pass. @@ -126,7 +126,7 @@ Write a real config file fixture containing one valid and one invalid label. Ass Run: ```text -bun test tests/config/config-load-degrade.test.ts tests/provider-config-validation.test.ts +bun test tests/config/config-load-degrade.test.ts tests/providers/provider-config-validation.test.ts ``` Expected: the candidate accepts unvalidated values or the load path does not sanitize them. @@ -152,7 +152,7 @@ Add `sanitizeModelDisplayNamesForLoad(parsed)` before `configSchema.safeParse(pa Run: ```text -bun test tests/config/config-load-degrade.test.ts tests/provider-config-validation.test.ts +bun test tests/config/config-load-degrade.test.ts tests/providers/provider-config-validation.test.ts ``` Expected: all tests pass with no unexpected warnings. @@ -160,7 +160,7 @@ Expected: all tests pass with no unexpected warnings. - [ ] **Step 9: Commit the config contract** ```text -git add src/types/provider.ts src/config/provider-validation.ts src/config.ts tests/provider-config-validation.test.ts tests/config/config-load-degrade.test.ts +git add src/types/provider.ts src/config/provider-validation.ts src/config.ts tests/providers/provider-config-validation.test.ts tests/config/config-load-degrade.test.ts git commit -m "feat(config): add discovered model display names" ``` @@ -170,7 +170,7 @@ git commit -m "feat(config): add discovered model display names" **Files:** - Modify: `src/codex/catalog/provider-fetch.ts` -- Test: `tests/codex-catalog.test.ts` +- Test: `tests/codex-integration/codex-catalog.test.ts` **Interfaces:** - Consumes: `OcxProviderConfig.modelDisplayNames` @@ -195,7 +195,7 @@ Cover exact case sensitive matching, same native ID under two providers, operato Run: ```text -bun test tests/codex-catalog.test.ts +bun test tests/codex-integration/codex-catalog.test.ts ``` Expected: the discovered row keeps its old metadata or slug instead of the configured label. @@ -224,7 +224,7 @@ Add `modelDisplayNames` to `providerCatalogFingerprint`, because `gatherFlightKe Run: ```text -bun test tests/codex-catalog.test.ts +bun test tests/codex-integration/codex-catalog.test.ts ``` Expected: all catalog tests pass and routing identity stays byte equivalent. @@ -232,7 +232,7 @@ Expected: all catalog tests pass and routing identity stays byte equivalent. - [ ] **Step 5: Commit catalog propagation** ```text -git add src/codex/catalog/provider-fetch.ts tests/codex-catalog.test.ts +git add src/codex/catalog/provider-fetch.ts tests/codex-integration/codex-catalog.test.ts git commit -m "feat(catalog): apply provider model display names" ``` @@ -243,7 +243,7 @@ git commit -m "feat(catalog): apply provider model display names" **Files:** - Modify: `src/server/management/model-rows.ts` - Modify: `src/server/management/model-routes.ts` -- Create: `tests/model-display-names-management-api.test.ts` +- Create: `tests/codex-integration/model-display-names-management-api.test.ts` **Interfaces:** - Produces: `ManagementModelRow.displayNameSource?: "operator" | "provider" | "fallback"` @@ -261,7 +261,7 @@ Use `listManagementModelRows` with a real provider model fixture. Assert the row Run: ```text -bun test tests/model-display-names-management-api.test.ts +bun test tests/codex-integration/model-display-names-management-api.test.ts ``` Expected: `displayNameOverride` and `displayNameSource` are absent. @@ -282,7 +282,7 @@ Use `operator` when the exact configured map owns the ID, `provider` when `Catal Run: ```text -bun test tests/model-display-names-management-api.test.ts +bun test tests/codex-integration/model-display-names-management-api.test.ts ``` Expected: read tests pass. @@ -309,7 +309,7 @@ Use a persistence seam that clones the actual config snapshot. Assert final stat Run: ```text -bun test tests/model-display-names-management-api.test.ts +bun test tests/codex-integration/model-display-names-management-api.test.ts ``` Expected: route returns `null` or 404 because it is not registered. @@ -345,7 +345,7 @@ Do not require the model ID to exist in live discovery. Run: ```text -bun test tests/model-display-names-management-api.test.ts +bun test tests/codex-integration/model-display-names-management-api.test.ts ``` Expected: all API tests pass. @@ -367,7 +367,7 @@ If the first run passes, record that the existing recursive provider merge alrea - [ ] **Step 11: Commit the management API** ```text -git add src/server/management/model-rows.ts src/server/management/model-routes.ts tests/model-display-names-management-api.test.ts tests/config/config-user-edits.test.ts src/config.ts +git add src/server/management/model-rows.ts src/server/management/model-routes.ts tests/codex-integration/model-display-names-management-api.test.ts tests/config/config-user-edits.test.ts src/config.ts git commit -m "feat(api): manage discovered model display names" ``` @@ -441,7 +441,7 @@ Check exact ID matching, no route identity changes, no secret fields in DTOs, no - [ ] **Step 2: Run focused tests** ```text -bun test tests/provider-config-validation.test.ts tests/config/config-load-degrade.test.ts tests/config/config-user-edits.test.ts tests/codex-catalog.test.ts tests/model-display-names-management-api.test.ts +bun test tests/providers/provider-config-validation.test.ts tests/config/config-load-degrade.test.ts tests/config/config-user-edits.test.ts tests/codex-integration/codex-catalog.test.ts tests/codex-integration/model-display-names-management-api.test.ts ``` Expected: all pass. diff --git a/docs/superpowers/specs/2026-08-06-deepseek-responses-streaming-terminal-repair-design.md b/docs/superpowers/specs/2026-08-06-deepseek-responses-streaming-terminal-repair-design.md index da50bea61aa..f8fdc8af500 100644 --- a/docs/superpowers/specs/2026-08-06-deepseek-responses-streaming-terminal-repair-design.md +++ b/docs/superpowers/specs/2026-08-06-deepseek-responses-streaming-terminal-repair-design.md @@ -228,7 +228,7 @@ The implementation is expected to touch these responsibility boundaries: - `src/server/responses/core.ts`: resolve the provider policy and wrap the SSE body before transport-specific relay branches. - `tests/responses/responses-terminal-repair.test.ts`: unit state-machine coverage. -- `tests/deepseek-inbound-wire.test.ts`: end-to-end wire, progressive delivery, +- `tests/providers/deepseek-inbound-wire.test.ts`: end-to-end wire, progressive delivery, repair composition, and WebSocket/HTTP activation. - Existing relay and item-id tests only where an explicit integration contract needs to be pinned. diff --git a/scripts/generate-model-metadata.ts b/scripts/generate-model-metadata.ts index af13fed7113..2441e32bc9e 100644 --- a/scripts/generate-model-metadata.ts +++ b/scripts/generate-model-metadata.ts @@ -26,7 +26,7 @@ type RawModel = { // the generator runs correctly from any working directory. const sourcePath = resolve(import.meta.dir, "model-metadata.source.json"); // `MODEL_METADATA_OUT` lets the sync guard regenerate into a temp file and byte-compare without -// any risk of clobbering the committed output (tests/model-metadata-sync.test.ts). +// any risk of clobbering the committed output (tests/codex-integration/model-metadata-sync.test.ts). const outPath = process.env.MODEL_METADATA_OUT ? resolve(process.env.MODEL_METADATA_OUT) : resolve(import.meta.dir, "../src/generated/model-metadata.ts"); @@ -52,7 +52,7 @@ const allowedProviders = Array.from( // `opencode-go/hy3-preview` returns `Provider error 400 ... model_not_supported` because it is not // on the Zen Go lite model list, yet upstream keeps re-adding `tencent/hy3-preview`. Without this // block, every regeneration resurrects it as a selectable model and users hit that 400 again. -// Keyed as `/`; `tests/codex-catalog.test.ts` asserts the slug stays absent. +// Keyed as `/`; `tests/codex-integration/codex-catalog.test.ts` asserts the slug stays absent. const EXCLUDED_MODELS = new Set([ "opencode-go/hy3-preview", ]); diff --git a/scripts/openai-provider-option-final-gates.ts b/scripts/openai-provider-option-final-gates.ts index d07458721cc..a6cf3f9bd4f 100644 --- a/scripts/openai-provider-option-final-gates.ts +++ b/scripts/openai-provider-option-final-gates.ts @@ -47,15 +47,15 @@ const focusedTests = [ "tests/adapters/openai/openai-provider-option-startup.test.ts", "tests/adapters/openai/openai-provider-option-e2e.test.ts", "tests/adapters/openai/openai-provider-option-tooling.test.ts", - "tests/provider-registry-parity.test.ts", + "tests/providers/provider-registry-parity.test.ts", "tests/gui/provider-payload.test.ts", "tests/gui/codex-account-mode-state.test.ts", "tests/routing/router.test.ts", - "tests/codex-routing.test.ts", + "tests/codex-integration/codex-routing.test.ts", "tests/server-auth.test.ts", - "tests/codex-catalog.test.ts", - "tests/codex-quota-prime.test.ts", - "tests/provider-quota.test.ts", + "tests/codex-integration/codex-catalog.test.ts", + "tests/codex-integration/codex-quota-prime.test.ts", + "tests/providers/provider-quota.test.ts", "tests/server-images.test.ts", "tests/server-search.test.ts", ]; diff --git a/scripts/test-layout/layout.json b/scripts/test-layout/layout.json index 654ff714033..a019b798787 100644 --- a/scripts/test-layout/layout.json +++ b/scripts/test-layout/layout.json @@ -1232,11 +1232,13 @@ "claude-integration", "cli", "clients", + "codex-integration", "config", "gui", "lab", "lib", "oauth", + "providers", "responses", "routing", "service", diff --git a/scripts/test-layout/schema.ts b/scripts/test-layout/schema.ts index d88410d6ddf..f5cbb2a4edd 100644 --- a/scripts/test-layout/schema.ts +++ b/scripts/test-layout/schema.ts @@ -140,7 +140,7 @@ export function rewriteSource(source: string, depth: number): string { export const LOCAL_MARKER = "// layout: local"; -const HELPER_NAMES = ["helperPath", "repoPath", "repoRoot"] as const; +const HELPER_NAMES = ["fixturePath", "helperPath", "repoPath", "repoRoot"] as const; /** * The source with comments, templates and regex bodies blanked but string literals kept, so @@ -186,8 +186,11 @@ export function rewriteMetaDirEscapes(source: string, depth: number): { source: [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\."\s*,\s*/g, () => "repoPath("], [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\.\/([^"]+)"/g, m => `repoPath("${m[1]}"`], [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"helpers"\s*,\s*/g, () => "helperPath("], - [/\bfileURLToPath\(\s*new\s+URL\(\s*"\.\.\/"\s*,\s*import\.meta\.url\s*\)\s*\)/g, () => "repoRoot()"], - [/\bresolve\(\s*dirname\(\s*fileURLToPath\(\s*import\.meta\.url\s*\)\s*\)\s*,\s*"\.\."\s*\)/g, () => "repoRoot()"], + [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"helpers\/([^"]+)"/g, m => `helperPath("${m[1]}"`], + [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"fixtures"\s*,\s*/g, () => "fixturePath("], + [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"fixtures\/([^"]+)"/g, m => `fixturePath("${m[1]}"`], + [/\bfileURLToPath\(\s*new\s+URL\(\s*"\.\.\/"\s*,\s*import\.meta\.url\s*\)\s*\)/g, () => rootCall], + [/\bresolve\(\s*dirname\(\s*fileURLToPath\(\s*import\.meta\.url\s*\)\s*\)\s*,\s*"\.\."\s*\)/g, () => rootCall], ]; const edits: Array<{ start: number; end: number; text: string }> = []; for (const [re, build] of rules) { @@ -206,9 +209,9 @@ export function rewriteMetaDirEscapes(source: string, depth: number): { source: } out += source.slice(cursor); const codeOut = maskNonCode(out); - const used = HELPER_NAMES.filter(name => new RegExp(`\\b${name}\\(`).test(codeOut)).map(name => (name === "repoRoot" && rebindsRoot ? "repoRoot as resolveRepoRoot" : name)); - if (rebindsRoot && !used.includes("repoRoot as resolveRepoRoot")) used.push("repoRoot as resolveRepoRoot"); - if (/\bpathToFileURL\(repoRoot\(\)/.test(codeOut) && !/\bimport\s*\{[^}]*\bpathToFileURL\b[^}]*\}\s*from\s*["']node:url["']/.test(view)) { + const used: string[] = HELPER_NAMES.filter(name => new RegExp(`\\b${name}\\(`).test(codeOut) && !(rebindsRoot && name === "repoRoot")); + if (rebindsRoot) used.push("repoRoot as resolveRepoRoot"); + if (/\bpathToFileURL\((?:resolveRepoRoot|repoRoot)\(\)/.test(codeOut) && !/\bimport\s*\{[^}]*\bpathToFileURL\b[^}]*\}\s*from\s*["']node:url["']/.test(view)) { out = insertAfterImports(out, 'import { pathToFileURL } from "node:url";'); } const existing = /^import\s*\{([^}]*)\}\s*from\s*(["'])([^"']*helpers\/repo-root)\2;?/m.exec(maskKeepStrings(out)); @@ -225,25 +228,34 @@ export function rewriteMetaDirEscapes(source: string, depth: number): { source: return { source: out, rewrites: applied }; } -/** Insert a line after the last top-level import / export-from statement (multi-line aware). */ +/** + * Insert a line after the leading block of top-level import / export-from statements: the + * run of such statements that starts at the top of the file (comments and blank lines + * allowed between them). An import that appears later, after real code, is not part of that + * block, so the helper never lands at the bottom of a file that happens to end with an import. + */ export function insertAfterImports(source: string, line: string): string { const tokens = tokenize(source); const masked = maskNonCode(source, tokens); let insertAt = 0; - for (const site of specifierSites(source, tokens)) { - // Walk back over the statement to its first non-blank column-0 keyword. - const before = masked.slice(0, site.token.start); - const stmtStart = Math.max(before.lastIndexOf("\nimport"), before.lastIndexOf("\nexport"), before.startsWith("import") || before.startsWith("export") ? 0 : -1); - if (stmtStart === -1) continue; - const between = masked.slice(stmtStart, site.token.start); - if (between.includes(";")) continue; // the keyword belongs to an earlier statement - // The statement ends at the first ";" or line break after the specifier, whichever is - // first: a semicolonless import must not swallow the next statement. - const semi = masked.indexOf(";", site.token.end); - const nl = masked.indexOf("\n", site.token.end); - const stop = semi !== -1 && (nl === -1 || semi < nl) ? semi : site.token.end; + let cursor = 0; + const n = masked.length; + while (cursor < n) { + // Skip blank lines (comments are already blanked in `masked`). + const lineEnd = masked.indexOf("\n", cursor); + const lineStop = lineEnd === -1 ? n : lineEnd; + const text = masked.slice(cursor, lineStop); + if (text.trim() === "") { cursor = lineStop + 1; continue; } + if (!/^(?:import|export)\b/.test(text) || /^(?:import|export)\s*\(/.test(text)) break; + // Statement ends at the first ";" or, failing that, the end of the line holding the closing quote. + const site = specifierSites(source, tokens).find(s => s.token.start >= cursor); + const specEnd = site ? site.token.end : lineStop; + const semi = masked.indexOf(";", specEnd); + const nl = masked.indexOf("\n", specEnd); + const stop = semi !== -1 && (nl === -1 || semi <= nl) ? semi : specEnd; const eol = masked.indexOf("\n", stop); - insertAt = Math.max(insertAt, eol === -1 ? source.length : eol + 1); + insertAt = eol === -1 ? n : eol + 1; + cursor = insertAt; } return source.slice(0, insertAt) + line + "\n" + source.slice(insertAt); } @@ -307,3 +319,5 @@ export function scanEscapes(source: string): EscapeHit[] { export function layoutDir(): string { return dirname(LAYOUT_PATH); } + + diff --git a/scripts/test.ts b/scripts/test.ts index 7b95acf35eb..d69549a8249 100644 --- a/scripts/test.ts +++ b/scripts/test.ts @@ -325,9 +325,9 @@ export function resolveBunTestArgs( // Paths relative to tests/. An entry moves with its file (scripts/test-layout/move.ts rewrites // it); the lane label, the ignore glob, and the timeout table all key on the basename. export const SERIAL_FULL_SUITE_FILES = [ - "codex-shim.test.ts", - "cursor-native-exec-shell.test.ts", - "issue-452-empty-503.test.ts", + "codex-integration/codex-shim.test.ts", + "providers/cursor/cursor-native-exec-shell.test.ts", + "codex-integration/issue-452-empty-503.test.ts", "adapters/openai/openai-provider-option-e2e.test.ts", "release-helper.test.ts", "update/update-stop-first.test.ts", diff --git a/src/adapters/cursor/protobuf-request.ts b/src/adapters/cursor/protobuf-request.ts index f3dec71d788..c4378540d22 100644 --- a/src/adapters/cursor/protobuf-request.ts +++ b/src/adapters/cursor/protobuf-request.ts @@ -379,7 +379,7 @@ function rootPromptMessages( } // Assistant tool CALLS are NOT replayed as a separate visible "[Tool Call]" entry: a model // few-shot-mimics that marker and emits later tool calls as inert text (363-B guard in - // tests/cursor-tool-continuation.test.ts). The invocation is instead named INSIDE the paired + // tests/providers/cursor/cursor-tool-continuation.test.ts). The invocation is instead named INSIDE the paired // "[Tool Result]" envelope below, which carries the same information without a mimickable // call template (devlog 260829 002_audit_round2). } else if (message.role === "toolResult") { @@ -954,7 +954,7 @@ function toolCallArgumentsText(args: Record): string { * * Why not a separate "[Tool Call]" entry: a model few-shot-mimics that marker and starts emitting * later tool calls as inert text instead of real tool frames, which halts multi-tool continuations - * (363-B guard, tests/cursor-tool-continuation.test.ts). Why it must exist at all: without any + * (363-B guard, tests/providers/cursor/cursor-tool-continuation.test.ts). Why it must exist at all: without any * record of the invocation, the replayed result is orphaned — its `call_id` refers to nothing the * model can see — and live cursor/grok-4.6 turns re-ran commands that had already succeeded while * narrating a phantom interrupt (devlog 260829 000_rca). A prose line inside the result satisfies diff --git a/src/clients/config-export.ts b/src/clients/config-export.ts index eb2c29aa9d8..ea1b623f31a 100644 --- a/src/clients/config-export.ts +++ b/src/clients/config-export.ts @@ -740,7 +740,7 @@ function outputBudgetFor(context: number): number { * single `audio` model takes every routed model down with it. That is not * hypothetical: zenmux/meta-muse-spark-1.1 advertises audio and did exactly * this. It is also the same defect the Codex catalog had with `video`, where - * the app showed zero apps (tests/catalog-input-modality-enum.test.ts). + * the app showed zero apps (tests/codex-integration/catalog-input-modality-enum.test.ts). * * UNKNOWN and INCOMPATIBLE are different inputs, and the Codex fix could * conflate them safely only because its enum is wider. A model with nothing diff --git a/src/codex/catalog/metadata.ts b/src/codex/catalog/metadata.ts index 439633f1e75..dce891ac820 100644 --- a/src/codex/catalog/metadata.ts +++ b/src/codex/catalog/metadata.ts @@ -671,7 +671,7 @@ function isAccountBoundOpenAiNativeSlug(slug: string): boolean { * malformed and minimal hand-written rows. It cannot distinguish a genuine upstream observation * from a complete row typed by hand into `$CODEX_HOME/models_cache.json`: there is no signature, * source identity, or server attestation to check. A full-shape forged row is accepted, and - * `observedFullShapeRowIsAccepted` in tests/native-model-toggle.test.ts pins that so nobody + * `observedFullShapeRowIsAccepted` in tests/codex-integration/native-model-toggle.test.ts pins that so nobody * later mistakes this predicate for a security boundary. * * That is acceptable here because the file is user-owned and written by Codex itself: anyone diff --git a/src/codex/catalog/provider-fetch.ts b/src/codex/catalog/provider-fetch.ts index fee52029ec6..99e6eafc107 100644 --- a/src/codex/catalog/provider-fetch.ts +++ b/src/codex/catalog/provider-fetch.ts @@ -717,7 +717,7 @@ function configuredVerbositySupport(name: string, prov: OcxProviderConfig | unde // Read from the PROVIDER CONFIG, never from PROVIDER_REGISTRY. A gather flight captures its // registry authority up front and forbids any later registry read, so consulting the registry // here made a custom-destination flight fall back to "configured" instead of serving its own - // discovery result (tests/codex-gather-authority.test.ts). `applyVerbosityDefaults` in + // discovery result (tests/codex-integration/codex-gather-authority.test.ts). `applyVerbosityDefaults` in // providers/derive.ts materializes the registry default into the config at seed/enrich time. return prov.supportsVerbosity; } diff --git a/src/providers/derive.ts b/src/providers/derive.ts index 5852e9c89e8..f17ff4d6901 100644 --- a/src/providers/derive.ts +++ b/src/providers/derive.ts @@ -403,7 +403,7 @@ function serviceTierModelDefaultsFor( * The catalog hint pass must not read PROVIDER_REGISTRY: a gather flight captures its registry * authority up front and forbids any later read, so consulting the registry per model turned * every hint pass into a post-lookup read and dropped a custom-destination flight's own - * discovery result (tests/codex-gather-authority.test.ts). + * discovery result (tests/codex-integration/codex-gather-authority.test.ts). * * Registry values go in first so an explicit user entry still wins, matching * `applyReasoningSummaryDefaults`. `supportsVerbosity` is the provider-wide default, expanded diff --git a/src/providers/registry.ts b/src/providers/registry.ts index 5598f4f5319..888cf2cfc42 100644 --- a/src/providers/registry.ts +++ b/src/providers/registry.ts @@ -632,7 +632,7 @@ const OPENCODE_FREE_DEEPSEEK_MODELS = ["deepseek-v4-flash-free"]; * `mimo-v2.5-free` and `longcat-2.0-free` ACCEPT images and are deliberately * absent. Adding them would silently replace a working image with a caption, * which is worse than the loud 400 this list exists to prevent — see the negative - * assertion in tests/provider-registry-parity.test.ts. + * assertion in tests/providers/provider-registry-parity.test.ts. * * Zen's roster is discovered live while this list is static, so it is a dated * exception list, not a capability model. Re-probe before extending it. @@ -688,7 +688,7 @@ const DEEPSEEK_FLASH_REASONING_MAP: Record = { /** * Flash-versus-Pro classification for DeepSeek V4 model ids, including prefixed * (`deepseek/deepseek-v4-pro`) and suffixed (`deepseek-v4-flash-free`) forms. - * `tests/provider-registry-parity.test.ts` enumerates every id the registry + * `tests/providers/provider-registry-parity.test.ts` enumerates every id the registry * actually passes here, so a future id this substring test would misread cannot * land silently. */ @@ -1541,7 +1541,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [ modelContextWindows: Object.fromEntries(META_MUSE_MODELS.map(id => [id, META_MUSE_CONTEXT_WINDOW])), // text+image only. Meta also documents video, audio (degraded on 1.3), and PDF, but // the catalog modality enum is text/image and over-advertising poisons the exported - // client config (see tests/catalog-input-modality-enum.test.ts). + // client config (see tests/codex-integration/catalog-input-modality-enum.test.ts). modelInputModalities: Object.fromEntries(META_MUSE_MODELS.map(id => [id, ["text", "image"] as ["text", "image"]])), modelReasoningEfforts: Object.fromEntries(META_MUSE_MODELS.map(id => [id, META_MUSE_REASONING_EFFORTS])), modelReasoningEffortMap: Object.fromEntries(META_MUSE_MODELS.map(id => [id, META_MUSE_REASONING_EFFORT_MAP])), diff --git a/src/server/management/agent-settings-routes.ts b/src/server/management/agent-settings-routes.ts index 193f9841fa7..75bcaf36ae9 100644 --- a/src/server/management/agent-settings-routes.ts +++ b/src/server/management/agent-settings-routes.ts @@ -377,7 +377,7 @@ export async function handleAgentSettingsRoutes(ctx: ManagementContext): Promise // sequence after the transition. A failure here is a persistence failure (the // writers' ok:false result or a throw from the underlying atomic write helper), // reported as 502 naming the failed key plus the writes that already landed. - // NOTE: do not name that helper literally here — tests/grok-writer-boundary.test.ts + // NOTE: do not name that helper literally here — tests/providers/xai/grok-writer-boundary.test.ts // asserts this route file contains no direct write primitive, and matches on the // symbol name even inside a comment. const scalarWrites: Array<{ field: string; run: () => { ok: true; changed: boolean } | { ok: false; error: string } }> = []; diff --git a/src/server/responses/core.ts b/src/server/responses/core.ts index cb1e00678ea..edc958087f9 100644 --- a/src/server/responses/core.ts +++ b/src/server/responses/core.ts @@ -3826,7 +3826,7 @@ async function handleResponsesInner( // The guard needs a catalog to compare against, so it stands down when the request omits one. // An explicit empty catalog is still authoritative: it declares that no client tools may be // called. A passthrough request can legitimately omit `tools` entirely and still receive a call - // the client understands — `tests/github-copilot-stream-contract.test.ts` sends + // the client understands — `tests/providers/github-copilot/github-copilot-stream-contract.test.ts` sends // `{model, input, stream}` with no tools and Copilot answers with a `custom_tool_call` for // `apply_patch`. Policing an absent catalog truncates that turn. An unreadable body lands there // too because the proxy cannot establish the caller's declared authorization boundary. diff --git a/src/service-manager-probe.ts b/src/service-manager-probe.ts index 2e612a69a9e..d3d722bcfb5 100644 --- a/src/service-manager-probe.ts +++ b/src/service-manager-probe.ts @@ -619,7 +619,7 @@ function windowsTaskListContains(body: string, taskName: string): boolean { * denied", so a locked-down host answers the control and the real query * identically, and comparing them yields a false `absent` — the one direction * that lets an unattended write proceed into a home another process owns. - * `tests/codex-service-manager-probe.test.ts` covers exactly that host. + * `tests/codex-integration/codex-service-manager-probe.test.ts` covers exactly that host. */ const SCHTASKS_TASK_NOT_FOUND_EN = /cannot find the file specified/i; diff --git a/structure/03_catalog-and-subagents.md b/structure/03_catalog-and-subagents.md index d30e3737b35..20170f90c77 100644 --- a/structure/03_catalog-and-subagents.md +++ b/structure/03_catalog-and-subagents.md @@ -230,7 +230,7 @@ is omitted *and* the `model`/`reasoning_effort` schema fields are removed). And Codex-visible `priority` while `SPAWN_PRIORITY_FIELD` preserves the natural priority the roster sorts by, so a display reorder can never change candidate membership. That divergence from upstream's own ordering is the feature's purpose, not a defect — -`tests/codex-catalog-model-picker-order.test.ts` pins it. +`tests/codex-integration/codex-catalog-model-picker-order.test.ts` pins it. Full derivation with per-line citations: `devlog/_plan/260816_codexrs_multiagent_v2_and_history_perf/013_five_cap_v1_vs_v2.md`. diff --git a/structure/04_transports-and-sidecars.md b/structure/04_transports-and-sidecars.md index d652a99082b..4c47dd02330 100644 --- a/structure/04_transports-and-sidecars.md +++ b/structure/04_transports-and-sidecars.md @@ -590,7 +590,7 @@ sentinel, and live probes (2026-08-07) confirm the stream closes on the terminal terminal-output boundary (`src/server/relay.ts`) cuts the stream at that event and synthesizes `[DONE]` itself, so DeepSeek streams live again; the registry knob remains as a one-line rollback for upstreams that regress, kept suite-reachable by a synthetic-registry fixture in -`tests/deepseek-inbound-wire.test.ts`. +`tests/providers/deepseek-inbound-wire.test.ts`. Synthesized output is capped at 10,000 items across HTTP and WebSocket reframing. HTTP frames are encoded incrementally, so bounded upstream JSON cannot expand into an unbounded event array or SSE string. diff --git a/structure/11_compatibility-contracts.md b/structure/11_compatibility-contracts.md index d8be62e2539..27a446eb2ae 100644 --- a/structure/11_compatibility-contracts.md +++ b/structure/11_compatibility-contracts.md @@ -18,7 +18,7 @@ evidence before they can be added. | `src/compatibility/openai-responses.ts` | First bundled compatibility manifest. | | `src/compatibility/index.ts` | Manifest catalog for future CLI and GUI readers. | | `tests/fixtures/compatibility/` | Secret-free request vectors plus destination, header-boundary, and assertion-level expected behavior. | -| `tests/compatibility-manifest.test.ts` | Executes fixtures against production adapters and proves every claim has evidence. | +| `tests/codex-integration/compatibility-manifest.test.ts` | Executes fixtures against production adapters and proves every claim has evidence. | ## Dispositions diff --git a/tests/bump-dev-version.test.ts b/tests/bump-dev-version.test.ts index 9e9630a373d..87c42daf7aa 100644 --- a/tests/bump-dev-version.test.ts +++ b/tests/bump-dev-version.test.ts @@ -156,7 +156,7 @@ describe("dev version bump rule", () => { // Skipped on Windows: `chmod 0500` is not access control there, so the write would // succeed and this test would fail red for a reason that has nothing to do with the - // behavior under test. Same guard as tests/codex-native-residue.test.ts uses for its + // behavior under test. Same guard as tests/codex-integration/codex-native-residue.test.ts uses for its // EACCES case. The POSIX runners still cover the failure path. const unwritableTest = process.platform === "win32" ? test.skip : test; unwritableTest("an unwritable target fails closed with the original intact", () => { diff --git a/tests/ci-workflows.test.ts b/tests/ci-workflows.test.ts index cf85e491892..e2f8ab0b5ee 100644 --- a/tests/ci-workflows.test.ts +++ b/tests/ci-workflows.test.ts @@ -1716,7 +1716,7 @@ describe("GitHub Actions hardening", () => { maintainersFile: MAINTAINERS_FIXTURE, files: [ { filename: "src/codex/auth-api.ts", patch: "+change" }, - { filename: "tests/codex-auth-api.test.ts", patch: "+test" }, + { filename: "tests/codex-integration/codex-auth-api.test.ts", patch: "+test" }, ], }); @@ -1753,7 +1753,7 @@ describe("GitHub Actions hardening", () => { labels: ["maintainer-sponsored"], files: [ { filename: "src/codex/auth-api.ts", patch: "+change" }, - { filename: "tests/codex-auth-api.test.ts", patch: "+test" }, + { filename: "tests/codex-integration/codex-auth-api.test.ts", patch: "+test" }, ], }); diff --git a/tests/active-registry-admission.test.ts b/tests/codex-integration/active-registry-admission.test.ts similarity index 95% rename from tests/active-registry-admission.test.ts rename to tests/codex-integration/active-registry-admission.test.ts index 38d023b9651..88bbeb5790c 100644 --- a/tests/active-registry-admission.test.ts +++ b/tests/codex-integration/active-registry-admission.test.ts @@ -2,29 +2,29 @@ import { describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { MAX_ACTIVE_TURNS, abortAndReleaseAllTurns, activeRegistryMetrics, trackStreamLifetime, tryAdmitTurn, unregisterTurn } from "../src/server/lifecycle"; +import { MAX_ACTIVE_TURNS, abortAndReleaseAllTurns, activeRegistryMetrics, trackStreamLifetime, tryAdmitTurn, unregisterTurn } from "../../src/server/lifecycle"; import { MAX_TRACKED_CODEX_WEBSOCKETS, getTrackedCodexWebSocketCountForAccount, tryReserveCodexWebSocket, -} from "../src/codex/websocket-registry"; +} from "../../src/codex/websocket-registry"; import { MAX_ACTIVE_STORAGE_HOME_SLOTS, tryBeginStorageMutation, -} from "../src/storage/storage-mutation-coordinator"; +} from "../../src/storage/storage-mutation-coordinator"; import { tryReserveStorageWorker, withStorageWorkerSpawnGate, -} from "../src/storage/worker-lifecycle"; +} from "../../src/storage/worker-lifecycle"; import { anthropicSessionAffinitySizeForTests, bindAnthropicSessionAffinity, clearAnthropicAccountPoolState, -} from "../src/oauth/anthropic-routing"; -import { saveConfig } from "../src/config"; -import { startServer } from "../src/server"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/oauth/anthropic-routing"; +import { saveConfig } from "../../src/config"; +import { startServer } from "../../src/server"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; describe("active registry admission", () => { test("active turn 257 returns structured server_busy before handler work", async () => { diff --git a/tests/app-owned-memory.test.ts b/tests/codex-integration/app-owned-memory.test.ts similarity index 95% rename from tests/app-owned-memory.test.ts rename to tests/codex-integration/app-owned-memory.test.ts index 51feebf86c8..375dabd36cf 100644 --- a/tests/app-owned-memory.test.ts +++ b/tests/codex-integration/app-owned-memory.test.ts @@ -9,27 +9,27 @@ import { resetAppOwnedMemoryForTests, type AppOwnedRetainedCategory, type RetainedStoreSnapshot, -} from "../src/lib/app-owned-memory"; -import { CURSOR_BLOB_MAX_TOTAL_BYTES } from "../src/adapters/cursor/native-exec"; -import { MAX_STORED_RESPONSE_BYTES } from "../src/responses/state"; -import { IMAGE_NORMALIZE_CACHE_MAX_BYTES } from "../src/adapters/anthropic-image-normalize"; -import { VISION_DESCRIPTION_CACHE_MAX_BYTES } from "../src/vision"; -import { ANTIGRAVITY_REPLAY_MAX_TOTAL_BYTES } from "../src/adapters/google-antigravity-replay"; +} from "../../src/lib/app-owned-memory"; +import { CURSOR_BLOB_MAX_TOTAL_BYTES } from "../../src/adapters/cursor/native-exec"; +import { MAX_STORED_RESPONSE_BYTES } from "../../src/responses/state"; +import { IMAGE_NORMALIZE_CACHE_MAX_BYTES } from "../../src/adapters/anthropic-image-normalize"; +import { VISION_DESCRIPTION_CACHE_MAX_BYTES } from "../../src/vision"; +import { ANTIGRAVITY_REPLAY_MAX_TOTAL_BYTES } from "../../src/adapters/google-antigravity-replay"; import { clearRequestLogsForTests, evictOldestRequestLogForBudget, hydrateRequestLogsFromDisk, requestLogEntryFromPersistedUsage, requestLogRetainedStoreSnapshot, -} from "../src/server/request-log"; +} from "../../src/server/request-log"; import { clearModelCache, evictOldestModelCacheForBudget, modelCacheRetainedStoreSnapshot, setCached, -} from "../src/codex/model-cache"; -import type { PersistedUsageEntry } from "../src/usage/log"; -import { registerDefaultAppOwnedObservedBuffers } from "../src/lib/app-owned-memory-stores"; +} from "../../src/codex/model-cache"; +import type { PersistedUsageEntry } from "../../src/usage/log"; +import { registerDefaultAppOwnedObservedBuffers } from "../../src/lib/app-owned-memory-stores"; interface Row { bytes: number; at: number; pinned?: boolean } diff --git a/tests/bearer-admission-routed-provider.test.ts b/tests/codex-integration/bearer-admission-routed-provider.test.ts similarity index 96% rename from tests/bearer-admission-routed-provider.test.ts rename to tests/codex-integration/bearer-admission-routed-provider.test.ts index 1e049fc77cd..e74cd0ce216 100644 --- a/tests/bearer-admission-routed-provider.test.ts +++ b/tests/codex-integration/bearer-admission-routed-provider.test.ts @@ -2,18 +2,18 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; -import { startServer } from "../src/server"; +import { saveConfig } from "../../src/config"; +import { startServer } from "../../src/server"; import { acquireNativeMainProfileDrain, getNativeMainProfileRequestCount, -} from "../src/server/lifecycle"; -import { waitForNativeMainStartupGate } from "../src/codex/native-profile-startup"; -import { handleNativeProfileAPI } from "../src/codex/native-profile-api"; -import type { NativeProfileManager } from "../src/codex/native-profile-manager"; -import type { OcxConfig } from "../src/types"; -import { ownedServiceHomeInspection } from "./helpers/owned-service-home-inspection"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/server/lifecycle"; +import { waitForNativeMainStartupGate } from "../../src/codex/native-profile-startup"; +import { handleNativeProfileAPI } from "../../src/codex/native-profile-api"; +import type { NativeProfileManager } from "../../src/codex/native-profile-manager"; +import type { OcxConfig } from "../../src/types"; +import { ownedServiceHomeInspection } from "../helpers/owned-service-home-inspection"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * Issue #2132: bearer admission must not require a stored ChatGPT credential. diff --git a/tests/catalog-cursor-search.test.ts b/tests/codex-integration/catalog-cursor-search.test.ts similarity index 99% rename from tests/catalog-cursor-search.test.ts rename to tests/codex-integration/catalog-cursor-search.test.ts index 72990c3bc29..c60bc0d8126 100644 --- a/tests/catalog-cursor-search.test.ts +++ b/tests/codex-integration/catalog-cursor-search.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { buildCatalogEntries, normalizeRoutedCatalogEntry } from "../src/codex/catalog"; +import { buildCatalogEntries, normalizeRoutedCatalogEntry } from "../../src/codex/catalog"; describe("routed catalog search advertising", () => { test("cursor entries enable deferred discovery without advertising hosted web search", () => { diff --git a/tests/catalog-input-modality-enum.test.ts b/tests/codex-integration/catalog-input-modality-enum.test.ts similarity index 96% rename from tests/catalog-input-modality-enum.test.ts rename to tests/codex-integration/catalog-input-modality-enum.test.ts index 37d245ffac2..4d9342eba4f 100644 --- a/tests/catalog-input-modality-enum.test.ts +++ b/tests/codex-integration/catalog-input-modality-enum.test.ts @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, test } from "bun:test"; -import { ensureStrictCatalogFields } from "../src/codex/catalog/parsing"; -import { catalogHintsFromModelsApiItem } from "../src/codex/catalog/provider-fetch"; -import type { OcxConfig } from "../src/types"; +import { ensureStrictCatalogFields } from "../../src/codex/catalog/parsing"; +import { catalogHintsFromModelsApiItem } from "../../src/codex/catalog/provider-fetch"; +import type { OcxConfig } from "../../src/types"; /** * Codex parses `input_modalities` as a closed enum of text | image | audio. A single out-of-enum @@ -79,7 +79,7 @@ describe("custom-model API rejects out-of-enum input modalities", () => { body: unknown, pathname = "/api/custom-models", ): Promise { - const { handleModelRoutes } = await import("../src/server/management/model-routes"); + const { handleModelRoutes } = await import("../../src/server/management/model-routes"); const url = new URL(`http://127.0.0.1:10199${pathname}`); const req = new Request(url, { method, @@ -207,7 +207,7 @@ describe("custom-model API validates reasoning-effort ladders", () => { body: unknown, pathname = "/api/custom-models", ): Promise { - const { handleModelRoutes } = await import("../src/server/management/model-routes"); + const { handleModelRoutes } = await import("../../src/server/management/model-routes"); const url = new URL(`http://127.0.0.1:10199${pathname}`); const req = new Request(url, { method, @@ -441,7 +441,7 @@ describe("custom-model API allows slash model ids", () => { body: unknown, pathname = "/api/custom-models", ): Promise { - const { handleModelRoutes } = await import("../src/server/management/model-routes"); + const { handleModelRoutes } = await import("../../src/server/management/model-routes"); const url = new URL(`http://127.0.0.1:10199${pathname}`); const req = new Request(url, { method, @@ -500,7 +500,7 @@ describe("custom-model API allows slash model ids", () => { test("POST rejects a slash id that encodes to an existing native id", async () => { persistCalls = 0; - const { handleModelRoutes } = await import("../src/server/management/model-routes"); + const { handleModelRoutes } = await import("../../src/server/management/model-routes"); const url = new URL("http://127.0.0.1:10199/api/custom-models"); const req = new Request(url, { method: "POST", @@ -538,7 +538,7 @@ describe("custom-model API allows slash model ids", () => { test("PUT rejects renaming onto a colliding native id", async () => { persistCalls = 0; - const { handleModelRoutes } = await import("../src/server/management/model-routes"); + const { handleModelRoutes } = await import("../../src/server/management/model-routes"); const url = new URL("http://127.0.0.1:10199/api/custom-models/existing-uuid"); const req = new Request(url, { method: "PUT", @@ -579,7 +579,7 @@ describe("custom-model API allows slash model ids", () => { test("POST rejects a slash id that encodes to defaultModel only", async () => { persistCalls = 0; - const { handleModelRoutes } = await import("../src/server/management/model-routes"); + const { handleModelRoutes } = await import("../../src/server/management/model-routes"); const url = new URL("http://127.0.0.1:10199/api/custom-models"); const req = new Request(url, { method: "POST", diff --git a/tests/catalog-llamacpp-capabilities.test.ts b/tests/codex-integration/catalog-llamacpp-capabilities.test.ts similarity index 97% rename from tests/catalog-llamacpp-capabilities.test.ts rename to tests/codex-integration/catalog-llamacpp-capabilities.test.ts index 1eb433fd80c..bac43cf66aa 100644 --- a/tests/catalog-llamacpp-capabilities.test.ts +++ b/tests/codex-integration/catalog-llamacpp-capabilities.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { catalogHintsFromModelsApiItem } from "../src/codex/catalog/provider-fetch"; -import { extractProviderModelItems } from "../src/providers/model-discovery"; +import { catalogHintsFromModelsApiItem } from "../../src/codex/catalog/provider-fetch"; +import { extractProviderModelItems } from "../../src/providers/model-discovery"; /** * Regression coverage for #1797 (llama.cpp dual-envelope metadata). diff --git a/tests/catalog-oauth-observation.test.ts b/tests/codex-integration/catalog-oauth-observation.test.ts similarity index 96% rename from tests/catalog-oauth-observation.test.ts rename to tests/codex-integration/catalog-oauth-observation.test.ts index adeba1e633d..b8bba6fcd5a 100644 --- a/tests/catalog-oauth-observation.test.ts +++ b/tests/codex-integration/catalog-oauth-observation.test.ts @@ -14,16 +14,16 @@ import { join } from "node:path"; import { observeActiveOAuthAccessToken, OAUTH_PROVIDERS, -} from "../src/oauth"; +} from "../../src/oauth"; import { gatherRoutedModelsForCatalogGather, type CatalogGatherProviderAuthOutcome, type CatalogGatherProviderModelOutcome, -} from "../src/codex/catalog/provider-fetch"; -import { clearModelCache } from "../src/codex/model-cache"; -import { getAuthRefreshIntentPath } from "../src/oauth/store"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/catalog/provider-fetch"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { getAuthRefreshIntentPath } from "../../src/oauth/store"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; interface FileSnapshot { readonly bytes: Buffer; diff --git a/tests/catalog-retain-models.test.ts b/tests/codex-integration/catalog-retain-models.test.ts similarity index 94% rename from tests/catalog-retain-models.test.ts rename to tests/codex-integration/catalog-retain-models.test.ts index 0b8e45eea7f..2067af00297 100644 --- a/tests/catalog-retain-models.test.ts +++ b/tests/codex-integration/catalog-retain-models.test.ts @@ -2,12 +2,12 @@ import { afterEach, describe, expect, test } from "bun:test"; import { mergeConfiguredModelsIntoLiveCatalog, shouldRetainConfiguredProviderModel, -} from "../src/codex/catalog/provider-fetch"; -import { gatherRoutedModels as gatherRoutedModelsDirect, resetCatalogRuntimeStateForTests } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import type { OcxConfig } from "../src/types"; -import type { OcxProviderConfig } from "../src/types"; +} from "../../src/codex/catalog/provider-fetch"; +import { gatherRoutedModels as gatherRoutedModelsDirect, resetCatalogRuntimeStateForTests } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import type { OcxConfig } from "../../src/types"; +import type { OcxProviderConfig } from "../../src/types"; const originalFetch = globalThis.fetch; diff --git a/tests/catalog-verbosity-default.test.ts b/tests/codex-integration/catalog-verbosity-default.test.ts similarity index 92% rename from tests/catalog-verbosity-default.test.ts rename to tests/codex-integration/catalog-verbosity-default.test.ts index 75a07cca665..1ed5c8f1645 100644 --- a/tests/catalog-verbosity-default.test.ts +++ b/tests/codex-integration/catalog-verbosity-default.test.ts @@ -1,8 +1,8 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { buildCatalogEntries, gatherRoutedModels as gatherRoutedModelsDirect, upstreamNativeEntry } from "../src/codex/catalog"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import { resetCatalogRuntimeStateForTests, resetOpenAiApiCatalogWarningStateForTests } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; +import { buildCatalogEntries, gatherRoutedModels as gatherRoutedModelsDirect, upstreamNativeEntry } from "../../src/codex/catalog"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { resetCatalogRuntimeStateForTests, resetOpenAiApiCatalogWarningStateForTests } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; const gatherRoutedModels: typeof gatherRoutedModelsDirect = (config, options) => gatherRoutedModelsDirect(withStubbedProviderFetch(config), options); diff --git a/tests/catalog-vision-sidecar-modalities.test.ts b/tests/codex-integration/catalog-vision-sidecar-modalities.test.ts similarity index 97% rename from tests/catalog-vision-sidecar-modalities.test.ts rename to tests/codex-integration/catalog-vision-sidecar-modalities.test.ts index 8e71876dff0..3e51ac0d019 100644 --- a/tests/catalog-vision-sidecar-modalities.test.ts +++ b/tests/codex-integration/catalog-vision-sidecar-modalities.test.ts @@ -1,13 +1,13 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { applyProviderConfigHints, gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import type { OcxProviderConfig } from "../src/types"; -import { deriveComboCatalogModel } from "../src/codex/catalog"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { enrichProviderFromRegistry } from "../src/providers/derive"; -import { CURSOR_NO_VISION_MODELS, CURSOR_STATIC_MODELS } from "../src/adapters/cursor/discovery"; -import { modelInList } from "../src/types"; -import type { CatalogModel } from "../src/types"; +import { applyProviderConfigHints, gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import type { OcxProviderConfig } from "../../src/types"; +import { deriveComboCatalogModel } from "../../src/codex/catalog"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { enrichProviderFromRegistry } from "../../src/providers/derive"; +import { CURSOR_NO_VISION_MODELS, CURSOR_STATIC_MODELS } from "../../src/adapters/cursor/discovery"; +import { modelInList } from "../../src/types"; +import type { CatalogModel } from "../../src/types"; const base: OcxProviderConfig = { adapter: "openai-chat", diff --git a/tests/codex-account-delete-atomicity.test.ts b/tests/codex-integration/codex-account-delete-atomicity.test.ts similarity index 93% rename from tests/codex-account-delete-atomicity.test.ts rename to tests/codex-integration/codex-account-delete-atomicity.test.ts index 8b25bf2e9b8..fccaa8abe5c 100644 --- a/tests/codex-account-delete-atomicity.test.ts +++ b/tests/codex-integration/codex-account-delete-atomicity.test.ts @@ -1,27 +1,27 @@ import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test"; import { existsSync, mkdirSync, readFileSync} from "node:fs"; import { join } from "node:path"; -import * as accountStoreModule from "../src/codex/account-store"; +import * as accountStoreModule from "../../src/codex/account-store"; import { getCodexAccountCredential, saveCodexAccountCredential, -} from "../src/codex/account-store"; +} from "../../src/codex/account-store"; import { CodexAccountDeleteCleanupError, deleteCodexAccount, -} from "../src/codex/account-lifecycle"; +} from "../../src/codex/account-lifecycle"; import { isAccountNeedsReauth, markAccountNeedsReauth, -} from "../src/codex/account-runtime-state"; +} from "../../src/codex/account-runtime-state"; import { getAccountQuota, updateAccountQuota, -} from "../src/codex/quota"; -import { getConfigPath, loadConfig, saveConfig } from "../src/config"; -import * as configModule from "../src/config"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/quota"; +import { getConfigPath, loadConfig, saveConfig } from "../../src/config"; +import * as configModule from "../../src/config"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-codex-account-delete-atomicity"); const ACCOUNT_ID = "delete-atomicity"; diff --git a/tests/codex-account-label.test.ts b/tests/codex-integration/codex-account-label.test.ts similarity index 97% rename from tests/codex-account-label.test.ts rename to tests/codex-integration/codex-account-label.test.ts index 914b3f8c6c9..9680e3f8b9d 100644 --- a/tests/codex-account-label.test.ts +++ b/tests/codex-integration/codex-account-label.test.ts @@ -5,7 +5,7 @@ import { createCodexAccountLogLabel, fallbackCodexAccountLogLabel, withCodexAccountLogLabel, -} from "../src/codex/account-label"; +} from "../../src/codex/account-label"; describe("codex account privacy labels", () => { test("generates non-PII log labels", () => { diff --git a/tests/codex-account-namespaces.test.ts b/tests/codex-integration/codex-account-namespaces.test.ts similarity index 98% rename from tests/codex-account-namespaces.test.ts rename to tests/codex-integration/codex-account-namespaces.test.ts index 948d160db3f..d5ca0299607 100644 --- a/tests/codex-account-namespaces.test.ts +++ b/tests/codex-integration/codex-account-namespaces.test.ts @@ -1,15 +1,15 @@ import { describe, expect, spyOn, test } from "bun:test"; -import * as accountLabels from "../src/codex/account-label"; +import * as accountLabels from "../../src/codex/account-label"; import { CODEX_ACCOUNT_LOG_LABEL_RE, fallbackCodexAccountLogLabel, -} from "../src/codex/account-label"; +} from "../../src/codex/account-label"; import { codexAccountIdNamespaceCollisionError, codexAccountNamespaceProviderCollisionError, codexAccountNamespaceForModel, hasCodexAccountNamespace, -} from "../src/codex/account-namespace-match"; +} from "../../src/codex/account-namespace-match"; import { appendDefaultCodexAccountNamespace, codexAccountPickerEnabled, @@ -18,9 +18,9 @@ import { initializeDefaultCodexAccountNamespaces, isMainCodexAccountTarget, isValidCodexAccountNamespaceTarget, -} from "../src/codex/account-namespaces"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/main-account"; -import type { OcxConfig } from "../src/types"; +} from "../../src/codex/account-namespaces"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/main-account"; +import type { OcxConfig } from "../../src/types"; type InitializableAccountNamespaceConfig = Pick< OcxConfig, diff --git a/tests/codex-account-store.test.ts b/tests/codex-integration/codex-account-store.test.ts similarity index 95% rename from tests/codex-account-store.test.ts rename to tests/codex-integration/codex-account-store.test.ts index 5c8f52af4e6..8b9ad8d9abd 100644 --- a/tests/codex-account-store.test.ts +++ b/tests/codex-integration/codex-account-store.test.ts @@ -3,9 +3,9 @@ import { createHash } from "node:crypto"; import { existsSync, mkdtempSync, readdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { setAsyncIcaclsRunnerForTests, setIcaclsRunnerForTests } from "../src/lib/windows-secret-acl"; -import { flushConfigDirHardeningForTests } from "../src/config/paths"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { setAsyncIcaclsRunnerForTests, setIcaclsRunnerForTests } from "../../src/lib/windows-secret-acl"; +import { flushConfigDirHardeningForTests } from "../../src/config/paths"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * Per-test scratch home. A fixed repo-local directory meant that ONE failed teardown (Windows @@ -61,7 +61,7 @@ describe("codex-account-store CRUD", () => { afterEach(async () => { await removeScratchHome(); }); test("save and load credential round-trip", async () => { - const { saveCodexAccountCredential, getCodexAccountCredential } = await import("../src/codex/account-store"); + const { saveCodexAccountCredential, getCodexAccountCredential } = await import("../../src/codex/account-store"); const cred = { accessToken: "tk_a", refreshToken: "rf_a", expiresAt: Date.now() + 3600_000, chatgptAccountId: "acc_a" }; saveCodexAccountCredential("work", cred); expect(existsSync(ACCOUNTS_PATH)).toBe(true); @@ -70,7 +70,7 @@ describe("codex-account-store CRUD", () => { }); test("legacy flat credential JSON loads through the compatibility projection", async () => { - const { getCodexAccountCredential, loadCodexAccountStore, readCodexAccountRecord } = await import("../src/codex/account-store"); + const { getCodexAccountCredential, loadCodexAccountStore, readCodexAccountRecord } = await import("../../src/codex/account-store"); const cred = { accessToken: "legacy_tk", refreshToken: "legacy_rf", expiresAt: Date.now() + 3600_000, chatgptAccountId: "legacy_acc" }; writeFileSync(ACCOUNTS_PATH, JSON.stringify({ legacy: cred }, null, 2)); @@ -80,7 +80,7 @@ describe("codex-account-store CRUD", () => { }); test("malformed credential store is backed up before a new save overwrites it", async () => { - const { saveCodexAccountCredential } = await import("../src/codex/account-store"); + const { saveCodexAccountCredential } = await import("../../src/codex/account-store"); writeFileSync(ACCOUNTS_PATH, "{not valid json", "utf8"); saveCodexAccountCredential("fresh", { @@ -96,7 +96,7 @@ describe("codex-account-store CRUD", () => { }); test("new saves write generation wrapper records", async () => { - const { readCodexAccountRecord, saveCodexAccountCredential } = await import("../src/codex/account-store"); + const { readCodexAccountRecord, saveCodexAccountCredential } = await import("../../src/codex/account-store"); const cred = { accessToken: "tk_a", refreshToken: "rf_a", expiresAt: Date.now() + 3600_000, chatgptAccountId: "acc_a" }; saveCodexAccountCredential("wrapped", cred); @@ -113,8 +113,8 @@ describe("codex-account-store CRUD", () => { saveCodexAccountCredential, saveCodexAccountCredentialIfGeneration, tombstoneCodexAccount, - } = await import("../src/codex/account-store"); - const { codexCredentialMutationEpoch } = await import("../src/codex/credential-mutation-epoch"); + } = await import("../../src/codex/account-store"); + const { codexCredentialMutationEpoch } = await import("../../src/codex/credential-mutation-epoch"); const first = { accessToken: "epoch-a", refreshToken: "epoch-r-a", expiresAt: Date.now() + 3600_000, chatgptAccountId: "epoch-account" }; const second = { ...first, accessToken: "epoch-b", refreshToken: "epoch-r-b" }; const third = { ...second, accessToken: "epoch-c", refreshToken: "epoch-r-c" }; @@ -141,7 +141,7 @@ describe("codex-account-store CRUD", () => { }); test("remove credential deletes entry", async () => { - const { saveCodexAccountCredential, removeCodexAccountCredential, getCodexAccountCredential, listCodexAccountIds, readCodexAccountRecord } = await import("../src/codex/account-store"); + const { saveCodexAccountCredential, removeCodexAccountCredential, getCodexAccountCredential, listCodexAccountIds, readCodexAccountRecord } = await import("../../src/codex/account-store"); saveCodexAccountCredential("temp", { accessToken: "t", refreshToken: "r", expiresAt: 0, chatgptAccountId: "c" }); removeCodexAccountCredential("temp"); expect(getCodexAccountCredential("temp")).toBeNull(); @@ -151,7 +151,7 @@ describe("codex-account-store CRUD", () => { }); test("tokenful tombstone is treated as absent", async () => { - const { getCodexAccountCredential, listCodexAccountIds, loadCodexAccountStore } = await import("../src/codex/account-store"); + const { getCodexAccountCredential, listCodexAccountIds, loadCodexAccountStore } = await import("../../src/codex/account-store"); const cred = { accessToken: "deleted_tk", refreshToken: "deleted_rf", expiresAt: Date.now() + 3600_000, chatgptAccountId: "deleted_acc" }; writeFileSync(ACCOUNTS_PATH, JSON.stringify({ deleted: { credential: cred, generation: 2, deletedAt: Date.now() }, @@ -163,7 +163,7 @@ describe("codex-account-store CRUD", () => { }); test("listCodexAccountIds returns stored ids", async () => { - const { saveCodexAccountCredential, listCodexAccountIds } = await import("../src/codex/account-store"); + const { saveCodexAccountCredential, listCodexAccountIds } = await import("../../src/codex/account-store"); saveCodexAccountCredential("a", { accessToken: "1", refreshToken: "1", expiresAt: 0, chatgptAccountId: "1" }); saveCodexAccountCredential("b", { accessToken: "2", refreshToken: "2", expiresAt: 0, chatgptAccountId: "2" }); expect(listCodexAccountIds()).toContain("a"); @@ -171,7 +171,7 @@ describe("codex-account-store CRUD", () => { }); test("getValidCodexToken returns cached token when not expired", async () => { - const { saveCodexAccountCredential, getValidCodexToken } = await import("../src/codex/account-store"); + const { saveCodexAccountCredential, getValidCodexToken } = await import("../../src/codex/account-store"); const future = Date.now() + 3600_000; saveCodexAccountCredential("fresh", { accessToken: "valid_tk", refreshToken: "rf", expiresAt: future, chatgptAccountId: "acc_id" }); const result = await getValidCodexToken("fresh"); @@ -181,7 +181,7 @@ describe("codex-account-store CRUD", () => { }); test("getValidCodexToken throws when account not found", async () => { - const { getValidCodexToken } = await import("../src/codex/account-store"); + const { getValidCodexToken } = await import("../../src/codex/account-store"); try { await getValidCodexToken("nonexistent-local-alias"); throw new Error("expected getValidCodexToken to reject"); @@ -197,7 +197,7 @@ describe("codex-account-store CRUD", () => { getValidCodexToken, saveCodexAccountCredential, TokenRefreshError, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("sensitive-local-alias", { accessToken: "sensitive-access-token", refreshToken: "sensitive-refresh-token", @@ -234,7 +234,7 @@ describe("codex-account-store CRUD", () => { readCodexAccountRecord, saveCodexAccountCredential, saveCodexAccountCredentialIfGeneration, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); const first = { accessToken: "first", refreshToken: "first-r", expiresAt: 1, chatgptAccountId: "acc" }; const second = { accessToken: "second", refreshToken: "second-r", expiresAt: 2, chatgptAccountId: "acc" }; saveCodexAccountCredential("cas", first); @@ -253,7 +253,7 @@ describe("codex-account-store CRUD", () => { readCodexAccountRecord, saveCodexAccountCredential, saveCodexAccountCredentialIfGeneration, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); const first = { accessToken: "first", refreshToken: "first-r", expiresAt: 1, chatgptAccountId: "acc" }; const second = { accessToken: "second", refreshToken: "second-r", expiresAt: 2, chatgptAccountId: "acc" }; const third = { accessToken: "third", refreshToken: "third-r", expiresAt: 3, chatgptAccountId: "acc" }; @@ -282,7 +282,7 @@ describe("codex-account-store CRUD", () => { markCodexAccountValidationFailed, readCodexAccountRecord, saveCodexAccountCredential, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("failed-warmup", { accessToken: "sensitive-access", refreshToken: "sensitive-refresh", expiresAt: 1, chatgptAccountId: "sensitive-account" }); markCodexAccountValidated("failed-warmup", 1234); markCodexAccountValidationFailed("failed-warmup", "http_status:401"); @@ -301,7 +301,7 @@ describe("codex-account-store CRUD", () => { readCodexAccountRecord, saveCodexAccountCredential, refreshGrantFingerprintForToken, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("refresh-success", { accessToken: "old", refreshToken: "old-r", expiresAt: 0, chatgptAccountId: "acc" }); const startGeneration = readCodexAccountRecord("refresh-success")!.generation; const startFingerprint = readCodexAccountRecord("refresh-success")!.refreshGrantFingerprint; @@ -328,7 +328,7 @@ describe("codex-account-store CRUD", () => { getCodexAccountCredential, getValidCodexToken, saveCodexAccountCredential, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("refresh-bad-expiry", { accessToken: "old", refreshToken: "old-r", expiresAt: 0, chatgptAccountId: "acc" }); const originalFetch = globalThis.fetch; // JSON.stringify turns NaN into null; hand-write 1e999 so JSON.parse yields Infinity, @@ -355,7 +355,7 @@ describe("codex-account-store CRUD", () => { getCodexAccountCredential, getValidCodexToken, saveCodexAccountCredential, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("refresh-overflow-expiry", { accessToken: "old", refreshToken: "old-r", expiresAt: 0, chatgptAccountId: "acc" }); const originalFetch = globalThis.fetch; // Number.MAX_VALUE passes Number.isFinite but overflows to Infinity when @@ -382,7 +382,7 @@ describe("codex-account-store CRUD", () => { getCodexAccountCredential, getValidCodexToken, saveCodexAccountCredential, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("refresh-negative-expiry", { accessToken: "old", refreshToken: "old-r", expiresAt: 0, chatgptAccountId: "acc" }); const originalFetch = globalThis.fetch; globalThis.fetch = (async () => new Response( @@ -408,7 +408,7 @@ describe("codex-account-store CRUD", () => { readCodexAccountRecord, saveCodexAccountCredential, saveCodexAccountCredentialIfGeneration, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("refresh-wait", { accessToken: "old", refreshToken: "old-r", expiresAt: 0, chatgptAccountId: "acc" }); const generation = readCodexAccountRecord("refresh-wait")!.generation; const lockPath = refreshLockPathForToken("old-r"); @@ -435,7 +435,7 @@ describe("codex-account-store CRUD", () => { }); test("stale refresh lock is reclaimed", async () => { - const { getValidCodexToken, saveCodexAccountCredential } = await import("../src/codex/account-store"); + const { getValidCodexToken, saveCodexAccountCredential } = await import("../../src/codex/account-store"); saveCodexAccountCredential("refresh-stale-lock", { accessToken: "old", refreshToken: "old-r", expiresAt: 0, chatgptAccountId: "acc" }); writeFileSync(refreshLockPathForToken("old-r"), JSON.stringify({ acquiredAt: Date.now() - 61_000, pid: 12345 }) + "\n"); const originalFetch = globalThis.fetch; @@ -455,7 +455,7 @@ describe("codex-account-store CRUD", () => { getCodexAccountCredential, getValidCodexToken, saveCodexAccountCredential, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("alias-a", { accessToken: "old-a", refreshToken: "shared-r", expiresAt: 0, chatgptAccountId: "acc" }); saveCodexAccountCredential("alias-b", { accessToken: "old-b", refreshToken: "shared-r", expiresAt: 0, chatgptAccountId: "acc" }); let fetchCalls = 0; @@ -490,7 +490,7 @@ describe("codex-account-store CRUD", () => { CodexCredentialRefreshBusyError, getValidCodexToken, saveCodexAccountCredential, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); for (let index = 0; index < 33; index++) { saveCodexAccountCredential(`flight-${index}`, { accessToken: `old-${index}`, @@ -526,7 +526,7 @@ describe("codex-account-store CRUD", () => { CodexCredentialRefreshStaleError, getValidCodexToken, saveCodexAccountCredential, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("stale-flight", { accessToken: "old", refreshToken: "stale-refresh", @@ -567,7 +567,7 @@ describe("codex-account-store CRUD", () => { readCodexAccountRecord, saveCodexAccountCredential, saveCodexAccountCredentialIfGeneration, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); const original = { accessToken: "original", refreshToken: "original-r", expiresAt: 1, chatgptAccountId: "acc" }; const replacement = { accessToken: "replacement", refreshToken: "replacement-r", expiresAt: 2, chatgptAccountId: "acc" }; const stale = { accessToken: "stale", refreshToken: "stale-r", expiresAt: 3, chatgptAccountId: "acc" }; @@ -586,7 +586,7 @@ describe("codex-account-store CRUD", () => { removeCodexAccountCredential, saveCodexAccountCredential, saveCodexAccountCredentialIfGeneration, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); const original = { accessToken: "original", refreshToken: "original-r", expiresAt: 1, chatgptAccountId: "acc" }; const stale = { accessToken: "stale", refreshToken: "stale-r", expiresAt: 2, chatgptAccountId: "acc" }; saveCodexAccountCredential("delete-race", original); @@ -606,7 +606,7 @@ describe("codex-account-store CRUD", () => { readCodexAccountRecord, removeCodexAccountCredential, saveCodexAccountCredential, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); saveCodexAccountCredential("refresh-delete", { accessToken: "old", refreshToken: "old-r", expiresAt: 0, chatgptAccountId: "acc" }); const originalFetch = globalThis.fetch; globalThis.fetch = (async () => { @@ -629,7 +629,7 @@ describe("codex-account-store CRUD", () => { getCodexAccountCredential, getValidCodexToken, saveCodexAccountCredential, - } = await import("../src/codex/account-store"); + } = await import("../../src/codex/account-store"); const replacement = { accessToken: "replacement", refreshToken: "replacement-r", expiresAt: Date.now() + 3600_000, chatgptAccountId: "acc" }; saveCodexAccountCredential("refresh-replace", { accessToken: "old", refreshToken: "old-r", expiresAt: 0, chatgptAccountId: "acc" }); const originalFetch = globalThis.fetch; @@ -648,7 +648,7 @@ describe("codex-account-store CRUD", () => { test("a forced refresh rotates a time-valid credential that upstream rejected (#2887)", async () => { const { forceRefreshCodexPoolToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); // Far beyond the refresh skew: getValidCodexToken would return this untouched, which is // exactly why a 401 on it was unrecoverable. saveCodexAccountCredential("forced", { @@ -681,7 +681,7 @@ describe("codex-account-store CRUD", () => { test("a forced refresh whose generation was already superseded spends no rotation (#2887)", async () => { const { forceRefreshCodexPoolToken, saveCodexAccountCredential, readCodexAccountRecord } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); saveCodexAccountCredential("forced-stale", { accessToken: "rejected", refreshToken: "grant", @@ -720,7 +720,7 @@ describe("codex-account-store CRUD", () => { test("concurrent forced refreshes of one rejected generation collapse to a single token call (#2887)", async () => { const { forceRefreshCodexPoolToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); saveCodexAccountCredential("forced-concurrent", { accessToken: "rejected", refreshToken: "grant", @@ -761,7 +761,7 @@ describe("codex-account-store CRUD", () => { */ test("cancelling the caller that opened a refresh flight does not cancel a live joiner (#2892)", async () => { const { forceRefreshCodexPoolToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); saveCodexAccountCredential("cancel-owner", { accessToken: "rejected", refreshToken: "cancel-grant", @@ -825,7 +825,7 @@ describe("codex-account-store CRUD", () => { // written from the lock-acquisition hook rather than from inside `fetch`: by fetch time // the grant comparison has already happened and a different branch handles the case. const { forceRefreshCodexPoolToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); const shared = { refreshToken: "shared-grant", expiresAt: Date.now() + 3600_000, chatgptAccountId: "acc" }; saveCodexAccountCredential("owner", { ...shared, accessToken: "owner-rejected" }); saveCodexAccountCredential("joiner", { ...shared, accessToken: "joiner-rejected" }); @@ -880,7 +880,7 @@ describe("codex-account-store CRUD", () => { // caller that quarantines on rotated===false must fence on the RETURNED generation — // fencing on the one it rejected silently suppresses its own quarantine. const { forceRefreshCodexPoolToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); saveCodexAccountCredential("same-bearer", { accessToken: "still-rejected", refreshToken: "grant", @@ -914,7 +914,7 @@ describe("codex-account-store CRUD", () => { // same-account joiner that re-writes the identical credential would move it to G+2 and // invalidate that handoff. const { forceRefreshCodexPoolToken, getValidCodexToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); saveCodexAccountCredential("double-bump", { accessToken: "rejected", refreshToken: "grant", @@ -956,7 +956,7 @@ describe("codex-account-store CRUD", () => { // Upstream sends invalid_grant with no description. Classified "unknown" it reads as // transient, so a dead grant is never retired and every request repeats the refresh. const { forceRefreshCodexPoolToken, readCodexAccountRecord, saveCodexAccountCredential, TokenRefreshError } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); saveCodexAccountCredential("dead-grant", { accessToken: "rejected", refreshToken: "grant", @@ -988,7 +988,7 @@ describe("codex-account-store CRUD", () => { // lineage from the stored record instead is tautological — the caller reads the same // record the check would re-read. const { forceRefreshCodexPoolToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); saveCodexAccountCredential("external", { accessToken: "rejected", refreshToken: "grant", @@ -1029,7 +1029,7 @@ describe("codex-account-store CRUD", () => { // Matching the phrase anywhere in the combined code+description text would retire a // healthy account on an upstream blip — reintroducing the defect this path fixes. const { forceRefreshCodexPoolToken, readCodexAccountRecord, saveCodexAccountCredential, TokenRefreshError } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); saveCodexAccountCredential("blip", { accessToken: "rejected", refreshToken: "grant", @@ -1059,7 +1059,7 @@ describe("codex-account-store CRUD", () => { test("a successful refresh advances an untouched dormant same-grant alias in the same write (#2892 gap 3)", async () => { const { getValidCodexToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); const expiresAt = 0; const shared = { refreshToken: "dormant-grant", expiresAt, chatgptAccountId: "acc" }; // Owner drives the refresh. `dormant` is an untouched duplicate that never calls in — the @@ -1129,7 +1129,7 @@ describe("codex-account-store CRUD", () => { test("a tombstoned same-grant record is not resurrected by grant propagation (#2892 gap 3)", async () => { const { getValidCodexToken, readCodexAccountRecord, saveCodexAccountCredential, tombstoneCodexAccount } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); const shared = { accessToken: "tomb-old", refreshToken: "tomb-grant", expiresAt: 0, chatgptAccountId: "acc" }; saveCodexAccountCredential("tomb-owner", { ...shared }); saveCodexAccountCredential("tomb-deleted", { ...shared }); @@ -1159,7 +1159,7 @@ describe("codex-account-store CRUD", () => { // or a tombstone raced by a concurrent save, produces exactly this record. `tokenful tombstone is // treated as absent` earlier in this file pins the same shape for the read path. const { getValidCodexToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); const shared = { accessToken: "tokenful-old", refreshToken: "tokenful-grant", @@ -1198,7 +1198,7 @@ describe("codex-account-store CRUD", () => { test("a same-grant sibling on a DIFFERENT upstream identity is never adopted (#2892 review)", async () => { const { forceRefreshCodexPoolToken, getCodexAccountCredential, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); // Both records share one stored grant, but they claim different upstream accounts. Adoption // copies BOTH tokens, so treating a shared fingerprint as proof of identity would hand this // caller another account's credential. @@ -1250,9 +1250,9 @@ describe("shared refresh flight plan reconciliation (#2892 gap 2 follow-up)", () // chatgpt_plan_type would otherwise commit while codexAccounts[].plan stayed stale // for the rest of the process, skewing plan-selected quota projection. const { forceRefreshCodexPoolToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); - const { loadConfig, saveConfig } = await import("../src/config"); - const { resetJwtPlanNotesForTests } = await import("../src/codex/plan-from-token"); + await import("../../src/codex/account-store"); + const { loadConfig, saveConfig } = await import("../../src/config"); + const { resetJwtPlanNotesForTests } = await import("../../src/codex/plan-from-token"); resetJwtPlanNotesForTests(); saveConfig({ @@ -1317,7 +1317,7 @@ describe("shared refresh flight plan reconciliation (#2892 gap 2 follow-up)", () test("records with EMPTY account ids are never treated as the same identity (#2892 review)", async () => { const { getValidCodexToken, readCodexAccountRecord, saveCodexAccountCredential } = - await import("../src/codex/account-store"); + await import("../../src/codex/account-store"); // Grant fingerprint, access token and expiry all match, and both ids are "". Two empty strings // compare equal but prove nothing about which upstream account either record was meant to use, // so propagation must fail closed rather than write a credential into an unidentified record. diff --git a/tests/codex-admission-primitives.test.ts b/tests/codex-integration/codex-admission-primitives.test.ts similarity index 96% rename from tests/codex-admission-primitives.test.ts rename to tests/codex-integration/codex-admission-primitives.test.ts index a9326ea0211..b2f1746a80c 100644 --- a/tests/codex-admission-primitives.test.ts +++ b/tests/codex-integration/codex-admission-primitives.test.ts @@ -19,13 +19,14 @@ import { readConfigGenerationInCurrentMutationTransaction, saveConfig, withConfigMutationLockSync, -} from "../src/config"; -import { hashAuthority } from "../src/codex/admission"; -import { captureCatalogAdmissionSnapshot } from "../src/codex/catalog-admission"; -import { JOURNAL_PATH } from "../src/codex/journal"; -import type { AdmissionSnapshot } from "../src/codex/convergence-types"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/config"; +import { hashAuthority } from "../../src/codex/admission"; +import { captureCatalogAdmissionSnapshot } from "../../src/codex/catalog-admission"; +import { JOURNAL_PATH } from "../../src/codex/journal"; +import type { AdmissionSnapshot } from "../../src/codex/convergence-types"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath } from "../helpers/repo-root"; let root = ""; let previousOpencodexHome: string | undefined; @@ -326,7 +327,7 @@ describe("the journal has one owner", () => { */ test("admission derives no journal path of its own", async () => { const source = await Bun.file( - join(import.meta.dir, "..", "src", "codex", "admission.ts"), + repoPath("src", "codex", "admission.ts"), ).text(); expect(source).toContain("JOURNAL_PATH"); expect(source).not.toContain("codex-journal.json"); diff --git a/tests/codex-admission.test.ts b/tests/codex-integration/codex-admission.test.ts similarity index 97% rename from tests/codex-admission.test.ts rename to tests/codex-integration/codex-admission.test.ts index d2cb92f6c47..8fdc5629be5 100644 --- a/tests/codex-admission.test.ts +++ b/tests/codex-integration/codex-admission.test.ts @@ -12,8 +12,8 @@ import { existsSync, mkdirSync, mkdtempSync, readdirSync, writeFileSync } from " import { tmpdir } from "node:os"; import { join } from "node:path"; -import { admitCodexWrite as admitRaw, hashAuthority } from "../src/codex/admission"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { admitCodexWrite as admitRaw, hashAuthority } from "../../src/codex/admission"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /* * Ownership is proven by shelling out to the platform service manager, and a @@ -23,8 +23,8 @@ import { removeTreeWithRetry } from "./helpers/remove-tree"; */ const admitCodexWrite = (): ReturnType => admitRaw({ inspectOwnership: () => ({ ownership: "owned", reason: "pinned by fixture" }) }); -import { JOURNAL_PATH } from "../src/codex/journal"; -import type { OcxConfig } from "../src/types"; +import { JOURNAL_PATH } from "../../src/codex/journal"; +import type { OcxConfig } from "../../src/types"; let root = ""; let codexHome = ""; diff --git a/tests/codex-affinity-debug.test.ts b/tests/codex-integration/codex-affinity-debug.test.ts similarity index 98% rename from tests/codex-affinity-debug.test.ts rename to tests/codex-integration/codex-affinity-debug.test.ts index 42221f95b2a..d2c25c536ce 100644 --- a/tests/codex-affinity-debug.test.ts +++ b/tests/codex-integration/codex-affinity-debug.test.ts @@ -2,9 +2,9 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { captureCodexAffinityDiagnostic, CODEX_AFFINITY_DEBUG_SAFE_HEADERS, -} from "../src/codex/affinity-debug"; -import { getDebugLogEntries, resetDebugLogBufferForTests } from "../src/lib/debug-log-buffer"; -import { resetDebugSettingsForTests, setDebugSettings } from "../src/lib/debug-settings"; +} from "../../src/codex/affinity-debug"; +import { getDebugLogEntries, resetDebugLogBufferForTests } from "../../src/lib/debug-log-buffer"; +import { resetDebugSettingsForTests, setDebugSettings } from "../../src/lib/debug-settings"; function diagnosticPayload(): Record { const line = getDebugLogEntries().at(-1)?.line ?? ""; diff --git a/tests/codex-app-server-path-spaces.test.ts b/tests/codex-integration/codex-app-server-path-spaces.test.ts similarity index 95% rename from tests/codex-app-server-path-spaces.test.ts rename to tests/codex-integration/codex-app-server-path-spaces.test.ts index 2d9ef0cef02..738bf8e48e9 100644 --- a/tests/codex-app-server-path-spaces.test.ts +++ b/tests/codex-integration/codex-app-server-path-spaces.test.ts @@ -3,7 +3,7 @@ import { describe, expect, test } from "bun:test"; import { isCodexAppServerCommandLine, listCodexAppServerProcesses, -} from "../src/codex/app-server-processes"; +} from "../../src/codex/app-server-processes"; describe("Codex app-server flattened command lines", () => { test("matches unquoted official executable paths containing spaces", () => { diff --git a/tests/codex-app-server-processes.test.ts b/tests/codex-integration/codex-app-server-processes.test.ts similarity index 99% rename from tests/codex-app-server-processes.test.ts rename to tests/codex-integration/codex-app-server-processes.test.ts index cb51e3abbca..d98f5abbc3c 100644 --- a/tests/codex-app-server-processes.test.ts +++ b/tests/codex-integration/codex-app-server-processes.test.ts @@ -2,12 +2,12 @@ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test } fr import { spawn } from "node:child_process"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { setTrustedWindowsElevationExecutablesForTests } from "../src/lib/windows-elevation"; +import { setTrustedWindowsElevationExecutablesForTests } from "../../src/lib/windows-elevation"; import { createWindowsPowerShellFixture, probeWindowsPowerShellFixture, type WindowsPowerShellFixture, -} from "./helpers/windows-power-shell-fixture"; +} from "../helpers/windows-power-shell-fixture"; import { afterCatalogWriteHandleAppServers, attachStaleAppServerHint, @@ -26,7 +26,8 @@ import { STALE_CODEX_APP_SERVER_HINT, warnIfStaleCodexAppServersAfterStartupWrite, WINDOWS_CODEX_BASENAME_CANDIDATE_RE, -} from "../src/codex/app-server-processes"; +} from "../../src/codex/app-server-processes"; +import { repoPath } from "../helpers/repo-root"; describe("collectCodexAppServerCatalogState (#857)", () => { const APP_SERVER_CMD = "/usr/local/bin/codex app-server"; @@ -702,9 +703,9 @@ describe("Codex app-server process matching (#476)", () => { }); describe("CLI /api sync wiring for stale app-servers (#476)", () => { - const dispatchSource = readFileSync(join(import.meta.dir, "..", "src", "cli", "dispatch.ts"), "utf8"); + const dispatchSource = readFileSync(repoPath("src", "cli", "dispatch.ts"), "utf8"); const configRoutesSource = readFileSync( - join(import.meta.dir, "..", "src", "server", "management", "config-routes.ts"), + repoPath("src", "server", "management", "config-routes.ts"), "utf8", ); @@ -809,7 +810,7 @@ describe("CLI /api sync wiring for stale app-servers (#476)", () => { describe("process utility invocation source guards", () => { const processSource = readFileSync( - join(import.meta.dir, "..", "src", "codex", "app-server-processes.ts"), + repoPath("src", "codex", "app-server-processes.ts"), "utf8", ); @@ -821,7 +822,7 @@ describe("process utility invocation source guards", () => { describe("Windows Win32_Process owner enumeration (#476)", () => { const processSource = readFileSync( - join(import.meta.dir, "..", "src", "codex", "app-server-processes.ts"), + repoPath("src", "codex", "app-server-processes.ts"), "utf8", ); diff --git a/tests/codex-app-server-restart-service.test.ts b/tests/codex-integration/codex-app-server-restart-service.test.ts similarity index 98% rename from tests/codex-app-server-restart-service.test.ts rename to tests/codex-integration/codex-app-server-restart-service.test.ts index 9884ea9de94..64c1d1c3bb1 100644 --- a/tests/codex-app-server-restart-service.test.ts +++ b/tests/codex-integration/codex-app-server-restart-service.test.ts @@ -12,10 +12,10 @@ import { performCodexRestart, readCodexAppServerState, resetCodexRestartInFlightForTests, -} from "../src/codex/app-server-restart-service"; -import type { CodexRestartServiceIo } from "../src/codex/app-server-restart-service"; -import type { CodexAppServerProcess } from "../src/codex/app-server-processes"; -import { isCodexRestartResponse } from "../src/lib/codex-restart-contract"; +} from "../../src/codex/app-server-restart-service"; +import type { CodexRestartServiceIo } from "../../src/codex/app-server-restart-service"; +import type { CodexAppServerProcess } from "../../src/codex/app-server-processes"; +import { isCodexRestartResponse } from "../../src/lib/codex-restart-contract"; function proc(pid: number, commandLine = `/opt/codex app-server --pid ${pid}`): CodexAppServerProcess { return { pid, commandLine }; diff --git a/tests/codex-auth-api.test.ts b/tests/codex-integration/codex-auth-api.test.ts similarity index 98% rename from tests/codex-auth-api.test.ts rename to tests/codex-integration/codex-auth-api.test.ts index 75cf062c5e9..1cba651ee57 100644 --- a/tests/codex-auth-api.test.ts +++ b/tests/codex-integration/codex-auth-api.test.ts @@ -8,8 +8,8 @@ import { acquireNativeMainProfileDrain, getNativeMainProfileRequestCount, resetLifecycleDrainStateForTests, -} from "../src/server/lifecycle"; -import { fallbackCodexAccountLogLabel } from "../src/codex/account-label"; +} from "../../src/server/lifecycle"; +import { fallbackCodexAccountLogLabel } from "../../src/codex/account-label"; import { handleCodexAuthAPI, updateAccountQuota, getAccountQuota, checkAccountIdCollision, getMainChatgptAccountId, @@ -19,14 +19,14 @@ import { type CodexAuthAccountDto, listCodexAuthAccounts, setAccountQuotaFromParsed, -} from "../src/codex/auth-api"; +} from "../../src/codex/auth-api"; import { getCodexAccountCredential, listCodexAccountIds, readCodexAccountRecord, saveCodexAccountCredential, -} from "../src/codex/account-store"; -import * as accountStoreModule from "../src/codex/account-store"; +} from "../../src/codex/account-store"; +import * as accountStoreModule from "../../src/codex/account-store"; import { clearCodexUpstreamHealth, clearThreadAccountMap, @@ -34,47 +34,47 @@ import { recordCodexUpstreamOutcome, resetCodexRoutingForManualSelection, resolveCodexAccountForThread, -} from "../src/codex/routing"; -import { clearPoolRotationState } from "../src/codex/pool-rotation"; +} from "../../src/codex/routing"; +import { clearPoolRotationState } from "../../src/codex/pool-rotation"; import { clearCodexWebSocketRegistry, getTrackedCodexWebSocketCountForAccount, registerCodexWebSocket, -} from "../src/codex/websocket-registry"; -import type { OcxConfig } from "../src/types"; -import type { WsData } from "../src/server/ws-bridge"; -import { handleNativeProfileAPI } from "../src/codex/native-profile-api"; -import type { NativeProfileManager } from "../src/codex/native-profile-manager"; -import { MAIN_CODEX_ACCOUNT_ID, setMainAccountPlan } from "../src/codex/main-account"; -import { reconcileCodexPlansFromTokens, resetJwtPlanNotesForTests } from "../src/codex/plan-from-token"; +} from "../../src/codex/websocket-registry"; +import type { OcxConfig } from "../../src/types"; +import type { WsData } from "../../src/server/ws-bridge"; +import { handleNativeProfileAPI } from "../../src/codex/native-profile-api"; +import type { NativeProfileManager } from "../../src/codex/native-profile-manager"; +import { MAIN_CODEX_ACCOUNT_ID, setMainAccountPlan } from "../../src/codex/main-account"; +import { reconcileCodexPlansFromTokens, resetJwtPlanNotesForTests } from "../../src/codex/plan-from-token"; import { deleteCodexAccount, reconcileMainCodexAccountRuntimeState, resetMainCodexAccountIdentityTrackingForTests, -} from "../src/codex/account-lifecycle"; +} from "../../src/codex/account-lifecycle"; import { ConfigMutationLockError, getConfigPath, loadConfig, saveConfig, setPersistedConfigMutationBeforeCommitForTests, -} from "../src/config"; -import * as configModule from "../src/config"; -import type { CatalogDisposition } from "../src/codex/convergence-types"; -import { captureConfigGeneration, registerStateStore } from "../src/lib/state-store-sweeper"; +} from "../../src/config"; +import * as configModule from "../../src/config"; +import type { CatalogDisposition } from "../../src/codex/convergence-types"; +import { captureConfigGeneration, registerStateStore } from "../../src/lib/state-store-sweeper"; import { reconcileLiveStateStores, setLiveStateStoreConfig, STATE_STORE_REGISTRATIONS, -} from "../src/lib/state-store-registrations"; +} from "../../src/lib/state-store-registrations"; import { listOpenAiForwardSidecarCandidates, resolveFirstUsableOpenAiSidecar, -} from "../src/providers/openai-sidecar"; -import { BOUNDED_BODY_MAX_BYTES } from "../src/lib/bounded-body"; -import { flushConfigDirHardeningForTests } from "../src/config/paths"; -import { setAsyncIcaclsRunnerForTests, setIcaclsRunnerForTests } from "../src/lib/windows-secret-acl"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/openai-sidecar"; +import { BOUNDED_BODY_MAX_BYTES } from "../../src/lib/bounded-body"; +import { flushConfigDirHardeningForTests } from "../../src/config/paths"; +import { setAsyncIcaclsRunnerForTests, setIcaclsRunnerForTests } from "../../src/lib/windows-secret-acl"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let TEST_DIR = ""; let TEST_CODEX_HOME = ""; @@ -134,9 +134,9 @@ async function completeMockCodexOAuth(options: { catalogRefreshPending?: boolean; }; }> { - const oauth = await import("../src/oauth"); - const oauthStore = await import("../src/oauth/store"); - const openUrlMod = await import("../src/lib/open-url"); + const oauth = await import("../../src/oauth"); + const oauthStore = await import("../../src/oauth/store"); + const openUrlMod = await import("../../src/lib/open-url"); await oauthStore.saveCredential("chatgpt", { access: `access-${options.requestBody.id}`, refresh: `refresh-${options.requestBody.id}`, @@ -3436,7 +3436,7 @@ describe("codex-auth API", () => { // Deliberately no NaN case: JSON.stringify turns NaN into null, which this route // legitimately reads as a reset, so asserting a 400 would assert something unreachable. // NaN is covered where it can occur, against parseAccountPriority in - // tests/codex-pool-rotation.test.ts. + // tests/codex-integration/codex-pool-rotation.test.ts. ["a missing value", undefined], ] as const)("rejects %s as a selection order", async (_label, priority) => { const config = makeConfig(); @@ -4083,8 +4083,8 @@ describe("codex-auth API", () => { * type and a browser spawn that cannot work. */ test("POST /api/codex-auth/login with device:true returns the code and opens no browser", async () => { - const oauth = await import("../src/oauth"); - const openUrlModule = await import("../src/lib/open-url"); + const oauth = await import("../../src/oauth"); + const openUrlModule = await import("../../src/lib/open-url"); const startSpy = spyOn(oauth, "startLoginFlow").mockImplementation(async () => ({ url: "https://auth.openai.com/codex/device", instructions: "Enter code: ABCD-EFGH", @@ -4115,7 +4115,7 @@ describe("codex-auth API", () => { test("the device poll budget covers the 15-minute grant", async () => { // The budget is a loop bound with no observable output, so a regression to // the 5-minute browser budget would pass every behavioral test above. - const source = await Bun.file(new URL("../src/codex/auth-api.ts", import.meta.url)).text(); + const source = await Bun.file(new URL("../../src/codex/auth-api.ts", import.meta.url)).text(); const budget = /const pollAttempts = useDeviceFlow \? (\d+) : (\d+);/.exec(source); expect(budget).toBeTruthy(); // 900s is the grant; the extra margin covers post-grant settlement, so an @@ -4125,7 +4125,7 @@ describe("codex-auth API", () => { }); test("Codex OAuth login responses project raw provider errors", async () => { - const oauth = await import("../src/oauth"); + const oauth = await import("../../src/oauth"); const startSpy = spyOn(oauth, "startLoginFlow").mockImplementation(async () => { throw new Error("already in progress at C:\\Users\\Alice\\.opencodex\\auth.json.ocx-tmp sk-secret-provider-key"); }); @@ -4148,8 +4148,8 @@ describe("codex-auth API", () => { }); test("Codex OAuth login responses preserve actionable OAuth errors", async () => { - const oauth = await import("../src/oauth"); - const { OAuthMutationBusyError } = await import("../src/oauth/store"); + const oauth = await import("../../src/oauth"); + const { OAuthMutationBusyError } = await import("../../src/oauth/store"); const startSpy = spyOn(oauth, "startLoginFlow"); const cases: Array<{ error: Error; expected: string }> = [ { @@ -4189,8 +4189,8 @@ describe("codex-auth API", () => { }); test("Codex OAuth login status projects late provider errors", async () => { - const oauth = await import("../src/oauth"); - const openUrlMod = await import("../src/lib/open-url"); + const oauth = await import("../../src/oauth"); + const openUrlMod = await import("../../src/lib/open-url"); const originalLogin = oauth.OAUTH_PROVIDERS.chatgpt.login; oauth.OAUTH_PROVIDERS.chatgpt.login = async (controller) => { controller.onAuth({ url: "https://example.test/oauth" }); @@ -4240,9 +4240,9 @@ describe("codex-auth API", () => { }); test("Codex OAuth login status preserves actionable late OAuth errors", async () => { - const oauth = await import("../src/oauth"); - const { OAuthMutationBusyError } = await import("../src/oauth/store"); - const openUrlMod = await import("../src/lib/open-url"); + const oauth = await import("../../src/oauth"); + const { OAuthMutationBusyError } = await import("../../src/oauth/store"); + const openUrlMod = await import("../../src/lib/open-url"); const originalLogin = oauth.OAUTH_PROVIDERS.chatgpt.login; const openSpy = spyOn(openUrlMod, "openUrl").mockImplementation(() => {}); const timeoutSpy = spyOn(globalThis, "setTimeout").mockImplementation((( @@ -4324,8 +4324,8 @@ describe("codex-auth API", () => { describe("POST /api/codex-auth/login/code", () => { async function startPendingFlow() { - const oauth = await import("../src/oauth"); - const openUrlMod = await import("../src/lib/open-url"); + const oauth = await import("../../src/oauth"); + const openUrlMod = await import("../../src/lib/open-url"); const startSpy = spyOn(oauth, "startLoginFlow").mockResolvedValue({ url: "https://example.test/oauth" }); const statusSpy = spyOn(oauth, "getLoginStatus").mockReturnValue({ done: false, @@ -4384,7 +4384,7 @@ describe("codex-auth API", () => { }); test("rejects missing and unknown flow ids before submitting", async () => { - const oauth = await import("../src/oauth"); + const oauth = await import("../../src/oauth"); const submitSpy = spyOn(oauth, "submitManualLoginCode"); try { for (const body of [{ input: "code" }, { flowId: "", input: "code" }, { flowId: "unknown", input: "code" }]) { @@ -4561,7 +4561,7 @@ describe("codex-auth API", () => { }); test("POST /api/codex-auth/login rejects an id owned by a namespace before OAuth starts", async () => { - const oauth = await import("../src/oauth"); + const oauth = await import("../../src/oauth"); const startSpy = spyOn(oauth, "startLoginFlow"); try { const config = makeConfig({ codexAccountNamespaces: { work: "pool-a" } }); @@ -4650,8 +4650,8 @@ describe("codex-auth API", () => { chatgptAccountId: "acc-pool-reauth", }); - const oauth = await import("../src/oauth"); - const openUrlMod = await import("../src/lib/open-url"); + const oauth = await import("../../src/oauth"); + const openUrlMod = await import("../../src/lib/open-url"); const startSpy = spyOn(oauth, "startLoginFlow").mockResolvedValue({ url: "https://example.test/oauth" }); const statusSpy = spyOn(oauth, "getLoginStatus").mockReturnValue({ done: true, diff --git a/tests/codex-auth-collision.test.ts b/tests/codex-integration/codex-auth-collision.test.ts similarity index 93% rename from tests/codex-auth-collision.test.ts rename to tests/codex-integration/codex-auth-collision.test.ts index a4fe5889cb1..ceeff1a0da9 100644 --- a/tests/codex-auth-collision.test.ts +++ b/tests/codex-integration/codex-auth-collision.test.ts @@ -1,11 +1,11 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, writeFileSync } from "node:fs"; import { join } from "node:path"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { checkAccountIdCollision } from "../src/codex/auth-api"; -import { saveConfig } from "../src/config"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { checkAccountIdCollision } from "../../src/codex/auth-api"; +import { saveConfig } from "../../src/config"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-codex-auth-collision-test"); const TEST_CODEX_HOME = join(TEST_DIR, "codex"); diff --git a/tests/codex-auth-context.test.ts b/tests/codex-integration/codex-auth-context.test.ts similarity index 98% rename from tests/codex-auth-context.test.ts rename to tests/codex-integration/codex-auth-context.test.ts index b002caee305..bb4f24a098b 100644 --- a/tests/codex-auth-context.test.ts +++ b/tests/codex-integration/codex-auth-context.test.ts @@ -23,7 +23,7 @@ import { resolveCodexAuthContext, shouldMarkAccountNeedsReauthForCodexAuthFailure, stripCodexRuntimeProviderFields, -} from "../src/codex/auth-context"; +} from "../../src/codex/auth-context"; import { CodexCredentialGenerationConflictError, CodexCredentialRefreshLockTimeoutError, @@ -34,13 +34,13 @@ import { readCodexAccountRecord, removeCodexAccountCredential, saveCodexAccountCredential, -} from "../src/codex/account-store"; -import { ConfigMutationLockError, getConfigPath } from "../src/config"; +} from "../../src/codex/account-store"; +import { ConfigMutationLockError, getConfigPath } from "../../src/config"; import { getMainAccountPlan, MAIN_CODEX_ACCOUNT_ID, setMainAccountPlan, -} from "../src/codex/main-account"; +} from "../../src/codex/main-account"; import { clearAccountNeedsReauth, clearAccountQuota, @@ -48,8 +48,8 @@ import { isAccountNeedsReauth, markAccountNeedsReauth, setAccountQuotaFromParsed, -} from "../src/codex/auth-api"; -import { __resetGuardianState, guardianSweep } from "../src/oauth/token-guardian"; +} from "../../src/codex/auth-api"; +import { __resetGuardianState, guardianSweep } from "../../src/oauth/token-guardian"; import { CODEX_THREAD_AFFINITY_IDLE_TTL_MS, CODEX_QUOTA_PROBE_INTERVAL_MS, @@ -57,23 +57,23 @@ import { clearThreadAccountMap, recordCodexUpstreamOutcome, resetCodexRoutingForManualSelection, -} from "../src/codex/routing"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { setIcaclsRunnerForTests } from "../src/lib/windows-secret-acl"; +} from "../../src/codex/routing"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { setIcaclsRunnerForTests } from "../../src/lib/windows-secret-acl"; import { blockNativeMainStartupForUnownedServiceHome, completeNativeMainRecovery, initializeNativeMainStartupGate, -} from "../src/codex/native-profile-startup"; -import type { NativeProfileManager } from "../src/codex/native-profile-manager"; +} from "../../src/codex/native-profile-startup"; +import type { NativeProfileManager } from "../../src/codex/native-profile-manager"; import { acquireNativeMainProfileDrain, codexAccountSelectionForTurn, tryAdmitTurn, -} from "../src/server/lifecycle"; -import type { CodexModelEntitlementSnapshot } from "../src/codex/model-entitlements"; -import { hasForwardableCodexBearer } from "../src/server/auth-cors"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/server/lifecycle"; +import type { CodexModelEntitlementSnapshot } from "../../src/codex/model-entitlements"; +import { hasForwardableCodexBearer } from "../../src/server/auth-cors"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testDir: string; let previousOpencodexHome: string | undefined; @@ -2000,7 +2000,7 @@ describe("Codex auth context", () => { ["busy", new CodexCredentialRefreshBusyError()], ["stale", new CodexCredentialRefreshStaleError()], ])("login returns a retryable response for a %s credential refresh failure", async (_kind, refreshError) => { - const oauth = await import("../src/oauth"); + const oauth = await import("../../src/oauth"); const startLogin = spyOn(oauth, "startLoginFlow").mockRejectedValue(refreshError); const cfg = config(); try { diff --git a/tests/codex-catalog-admission.test.ts b/tests/codex-integration/codex-catalog-admission.test.ts similarity index 96% rename from tests/codex-catalog-admission.test.ts rename to tests/codex-integration/codex-catalog-admission.test.ts index 1abe9a853e3..3867fe14691 100644 --- a/tests/codex-catalog-admission.test.ts +++ b/tests/codex-integration/codex-catalog-admission.test.ts @@ -11,17 +11,17 @@ import { import { tmpdir } from "node:os"; import { join } from "node:path"; -import { captureCatalogAdmissionSnapshot } from "../src/codex/catalog-admission"; +import { captureCatalogAdmissionSnapshot } from "../../src/codex/catalog-admission"; import type { CatalogConditionalSourceObservations, CatalogConditionalSourceRole, CatalogRequiredSourceObservations, CatalogRequiredSourceRole, CatalogSourceEvidence, -} from "../src/codex/convergence-types"; -import { saveConfig } from "../src/config"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/convergence-types"; +import { saveConfig } from "../../src/config"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const CONDITIONAL_SOURCE_ROLES = [ "active-catalog-merge", diff --git a/tests/codex-catalog-golden.test.ts b/tests/codex-integration/codex-catalog-golden.test.ts similarity index 98% rename from tests/codex-catalog-golden.test.ts rename to tests/codex-integration/codex-catalog-golden.test.ts index eacc50003ba..35eeb82bbc3 100644 --- a/tests/codex-catalog-golden.test.ts +++ b/tests/codex-integration/codex-catalog-golden.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { buildCatalogEntries } from "../src/codex/catalog"; +import { buildCatalogEntries } from "../../src/codex/catalog"; // Behavior-preservation ORACLE for the future codex-catalog.ts split (devlog 260701). // buildCatalogEntries is the pure core (no fs/network). This snapshots its full serialized diff --git a/tests/codex-catalog-model-picker-order.test.ts b/tests/codex-integration/codex-catalog-model-picker-order.test.ts similarity index 99% rename from tests/codex-catalog-model-picker-order.test.ts rename to tests/codex-integration/codex-catalog-model-picker-order.test.ts index 17be5661042..7ef43e0c3fd 100644 --- a/tests/codex-catalog-model-picker-order.test.ts +++ b/tests/codex-integration/codex-catalog-model-picker-order.test.ts @@ -3,8 +3,8 @@ import { buildCatalogEntriesFromObservedState, effectiveSubagentRoster, MAX_SPAWN_AGENT_MODEL_OVERRIDES, -} from "../src/codex/catalog/sync"; -import type { CatalogModel } from "../src/types"; +} from "../../src/codex/catalog/sync"; +import type { CatalogModel } from "../../src/types"; // #1649: config.modelPickerOrder assigns a deterministic priority band to non-featured routed // rows so a catalog with more than 5 routed models keeps a stable picker order across rebuilds, diff --git a/tests/codex-catalog-refresh-status.test.ts b/tests/codex-integration/codex-catalog-refresh-status.test.ts similarity index 95% rename from tests/codex-catalog-refresh-status.test.ts rename to tests/codex-integration/codex-catalog-refresh-status.test.ts index 85e0d299cfb..ed4e97ab249 100644 --- a/tests/codex-catalog-refresh-status.test.ts +++ b/tests/codex-integration/codex-catalog-refresh-status.test.ts @@ -2,8 +2,8 @@ import { describe, expect, test } from "bun:test"; import { catalogRefreshIsPending, normalizeCatalogDisposition, -} from "../src/codex/catalog-refresh-status"; -import type { CatalogDisposition } from "../src/codex/convergence-types"; +} from "../../src/codex/catalog-refresh-status"; +import type { CatalogDisposition } from "../../src/codex/convergence-types"; describe("catalogRefreshIsPending", () => { test("only committed catalog state is complete", () => { diff --git a/tests/codex-catalog-restore.test.ts b/tests/codex-integration/codex-catalog-restore.test.ts similarity index 99% rename from tests/codex-catalog-restore.test.ts rename to tests/codex-integration/codex-catalog-restore.test.ts index 64465a7c9d9..a2117015781 100644 --- a/tests/codex-catalog-restore.test.ts +++ b/tests/codex-integration/codex-catalog-restore.test.ts @@ -5,9 +5,9 @@ import { spawnSync } from "node:child_process"; import { tmpdir } from "node:os"; import { dirname, join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); function backupPathForTestCatalog(codexHome: string, opencodexHome: string, catalogName: string): string { const catalogPath = join(realpathSync.native(codexHome), catalogName); diff --git a/tests/codex-catalog-sync-hardening.test.ts b/tests/codex-integration/codex-catalog-sync-hardening.test.ts similarity index 99% rename from tests/codex-catalog-sync-hardening.test.ts rename to tests/codex-integration/codex-catalog-sync-hardening.test.ts index 39da672c997..6f7e7e38fd8 100644 --- a/tests/codex-catalog-sync-hardening.test.ts +++ b/tests/codex-integration/codex-catalog-sync-hardening.test.ts @@ -4,10 +4,10 @@ import { spawnSync } from "node:child_process"; import { tmpdir } from "node:os"; import { dirname, join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; -import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../src/codex/catalog/native-models"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../../src/codex/catalog/native-models"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); function runScript( codexHome: string, diff --git a/tests/codex-catalog-write-serialization.test.ts b/tests/codex-integration/codex-catalog-write-serialization.test.ts similarity index 97% rename from tests/codex-catalog-write-serialization.test.ts rename to tests/codex-integration/codex-catalog-write-serialization.test.ts index 873d82806ce..3cd1fa0cc1a 100644 --- a/tests/codex-catalog-write-serialization.test.ts +++ b/tests/codex-integration/codex-catalog-write-serialization.test.ts @@ -8,13 +8,13 @@ import { isCatalogWritePermitLive, withCatalogWriteSerialization, type CatalogWritePermit, -} from "../src/codex/catalog-write-serialization"; +} from "../../src/codex/catalog-write-serialization"; import { resolveCodexCatalogSerializationDatabasePath, resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/user-identity"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let codexHome = ""; let otherHome = ""; diff --git a/tests/codex-catalog-writer.test.ts b/tests/codex-integration/codex-catalog-writer.test.ts similarity index 97% rename from tests/codex-catalog-writer.test.ts rename to tests/codex-integration/codex-catalog-writer.test.ts index ed7bf313bcf..b73789ef200 100644 --- a/tests/codex-catalog-writer.test.ts +++ b/tests/codex-integration/codex-catalog-writer.test.ts @@ -18,16 +18,16 @@ import { import { tmpdir } from "node:os"; import { join } from "node:path"; -import type { AtomicWriteIO } from "../src/config"; +import type { AtomicWriteIO } from "../../src/config"; import { type CatalogWritePermit, CatalogWritePermitRefusal, withCatalogWriteSerialization, -} from "../src/codex/catalog-write-serialization"; +} from "../../src/codex/catalog-write-serialization"; import { resolveCodexCatalogSerializationDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; +} from "../../src/codex/user-identity"; import { type CatalogBackupWriteIO, type PreparedCatalogFileWrite, @@ -35,8 +35,8 @@ import { publishLegacyCodexCatalogBackup, replaceActiveCodexCatalog, replaceCodexModelsCache, -} from "../src/codex/internal/catalog-writer"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/internal/catalog-writer"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; interface MutatorCase { readonly name: string; diff --git a/tests/codex-catalog.test.ts b/tests/codex-integration/codex-catalog.test.ts similarity index 99% rename from tests/codex-catalog.test.ts rename to tests/codex-integration/codex-catalog.test.ts index a46fc64115e..d8cd9d068b7 100644 --- a/tests/codex-catalog.test.ts +++ b/tests/codex-integration/codex-catalog.test.ts @@ -2,21 +2,21 @@ import { afterEach, describe, expect, spyOn, test } from "bun:test"; import { existsSync, mkdtempSync, readFileSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { codexAccountGatedCanonicalWireModel } from "../src/server/responses/core"; -import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../src/codex/catalog/native-models"; -import { isGpt56NativeSlug } from "../src/codex/catalog/effort"; -import { nativeOpenAiContextTier, nativeOpenAiMaxInputTokens } from "../src/codex/catalog"; -import { shouldUpgradeToUpstreamEntry } from "../src/codex/catalog/metadata"; -import { applyNativeVisibility, augmentRoutedModelsWithMetadata, augmentRoutedModelsWithRegistryOpenAiApiRows, buildCatalogEntries, buildComboCatalogOmission, catalogModelSlug, clampCatalogModelsToCodexSupport, clampEntryToCodexSupportedEfforts, clampedDefaultEffort, CODEX_ACCOUNT_BOUND_CATALOG_KIND, CODEX_NATIVE_ALIAS_CATALOG_KIND, comboCatalogOmissionReason, deriveComboCatalogModel, exactComboCatalogSlugs, filterCatalogVisibleModels, filterSupportedNativeSlugs, gatherRoutedModels as gatherRoutedModelsDirect, isDatedVariantId, isMediaGenerationModelId, loadBundledCodexCatalog, materializeBundledCodexCatalog, mergeCatalogEntriesForSync, NATIVE_DAYBREAK_BLUE_MODEL, NATIVE_GPT6_ASTRA_MODEL, NATIVE_OPENAI_MODELS, nativeDefaultReasoningEffort, nativeInputModalities, nativeOpenAiCapabilitySourceSlug, nativeOpenAiContextWindow, nativeReasoningEfforts, normalizeRoutedCatalogEntry, resetCatalogRuntimeStateForTests, resetOpenAiApiCatalogWarningStateForTests, resolveComboCatalogMember, shouldExposeRoutedModel, upstreamNativeEntry } from "../src/codex/catalog"; -import { applyProviderConfigHints, mergeConfiguredModelsIntoLiveCatalog } from "../src/codex/catalog/provider-fetch"; +import { codexAccountGatedCanonicalWireModel } from "../../src/server/responses/core"; +import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../../src/codex/catalog/native-models"; +import { isGpt56NativeSlug } from "../../src/codex/catalog/effort"; +import { nativeOpenAiContextTier, nativeOpenAiMaxInputTokens } from "../../src/codex/catalog"; +import { shouldUpgradeToUpstreamEntry } from "../../src/codex/catalog/metadata"; +import { applyNativeVisibility, augmentRoutedModelsWithMetadata, augmentRoutedModelsWithRegistryOpenAiApiRows, buildCatalogEntries, buildComboCatalogOmission, catalogModelSlug, clampCatalogModelsToCodexSupport, clampEntryToCodexSupportedEfforts, clampedDefaultEffort, CODEX_ACCOUNT_BOUND_CATALOG_KIND, CODEX_NATIVE_ALIAS_CATALOG_KIND, comboCatalogOmissionReason, deriveComboCatalogModel, exactComboCatalogSlugs, filterCatalogVisibleModels, filterSupportedNativeSlugs, gatherRoutedModels as gatherRoutedModelsDirect, isDatedVariantId, isMediaGenerationModelId, loadBundledCodexCatalog, materializeBundledCodexCatalog, mergeCatalogEntriesForSync, NATIVE_DAYBREAK_BLUE_MODEL, NATIVE_GPT6_ASTRA_MODEL, NATIVE_OPENAI_MODELS, nativeDefaultReasoningEffort, nativeInputModalities, nativeOpenAiCapabilitySourceSlug, nativeOpenAiContextWindow, nativeReasoningEfforts, normalizeRoutedCatalogEntry, resetCatalogRuntimeStateForTests, resetOpenAiApiCatalogWarningStateForTests, resolveComboCatalogMember, shouldExposeRoutedModel, upstreamNativeEntry } from "../../src/codex/catalog"; +import { applyProviderConfigHints, mergeConfiguredModelsIntoLiveCatalog } from "../../src/codex/catalog/provider-fetch"; import { CODEX_CUSTOM_MODEL_CATALOG_KIND, CODEX_PROVIDER_MODEL_CATALOG_KIND, ensureStrictCatalogFields, findNativeTemplate, findSupportedNativeTemplate, -} from "../src/codex/catalog/parsing"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; +} from "../../src/codex/catalog/parsing"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; import { CURSOR_STATIC_MODELS, filterCursorConfiguredModelsByLiveDiscovery, @@ -24,9 +24,9 @@ import { cursorModelIds, cursorModelInputModalities, cursorModelReasoningEfforts, -} from "../src/adapters/cursor/discovery"; -import { getModelMetadata, resolveMetadataProvider } from "../src/generated/model-metadata"; -import { resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests } from "../src/codex/model-entitlements"; +} from "../../src/adapters/cursor/discovery"; +import { getModelMetadata, resolveMetadataProvider } from "../../src/generated/model-metadata"; +import { resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests } from "../../src/codex/model-entitlements"; import { clearModelCache, getProviderDiscoveryStatus, @@ -34,25 +34,25 @@ import { markProviderDiscoveryFailed, setCached, type ProviderModelDiscoveryStatus, -} from "../src/codex/model-cache"; -import type { OcxConfig } from "../src/types"; -import { COMBO_NAMESPACE } from "../src/combos"; -import type { NormalizedComboConfig } from "../src/combos/types"; -import { enrichProviderFromRegistry, providerConfigSeed } from "../src/providers/derive"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { enrichProviderFromCatalog } from "../src/oauth/key-providers"; -import { handleManagementAPI } from "../src/server/management-api"; -import { OAUTH_PROVIDERS } from "../src/oauth"; +} from "../../src/codex/model-cache"; +import type { OcxConfig } from "../../src/types"; +import { COMBO_NAMESPACE } from "../../src/combos"; +import type { NormalizedComboConfig } from "../../src/combos/types"; +import { enrichProviderFromRegistry, providerConfigSeed } from "../../src/providers/derive"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { enrichProviderFromCatalog } from "../../src/oauth/key-providers"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { OAUTH_PROVIDERS } from "../../src/oauth"; import { clampCatalogModelsToObservedCodexSupport, supportedCodexReasoningEffortsFromObservedCatalog, -} from "../src/codex/catalog/effort"; +} from "../../src/codex/catalog/effort"; import { CANONICAL_NATIVE_CATALOG_CONTENT_POLICY, mergeCatalogEntriesFromObservedState, type ObservedCatalogMergeInput, -} from "../src/codex/catalog/sync"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/catalog/sync"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const originalFetch = globalThis.fetch; @@ -1073,7 +1073,7 @@ describe("combo catalog capability intersection", () => { expect(String(warn.mock.calls[0]?.[0])).toContain("[REDACTED]"); expect(String(warn.mock.calls[0]?.[0])).not.toContain(warningSentinel); expect(second).toEqual(first); - const { getLastComboCatalogOmissions } = await import("../src/codex/catalog"); + const { getLastComboCatalogOmissions } = await import("../../src/codex/catalog"); const hidden = getLastComboCatalogOmissions().find(item => item.id === "hidden"); expect(hidden).toMatchObject({ id: "hidden", @@ -1123,7 +1123,7 @@ describe("combo catalog capability intersection", () => { resetCatalogRuntimeStateForTests(); const models = await gatherRoutedModels(config); expect(models.some(model => model.provider === "combo" && model.id === "disjoint")).toBe(false); - const { getLastComboCatalogOmissions } = await import("../src/codex/catalog"); + const { getLastComboCatalogOmissions } = await import("../../src/codex/catalog"); const omission = getLastComboCatalogOmissions().find(item => item.id === "disjoint"); expect(omission).toMatchObject({ id: "disjoint", @@ -1433,7 +1433,7 @@ describe("combo catalog capability intersection", () => { expect(combo!.reasoningEfforts).toEqual(["low", "medium"]); // Synthesized member must not leak as a standalone routed row. expect(rows.some(r => r.provider === "a" && r.id === "unlisted")).toBe(false); - const { getLastComboCatalogOmissions } = await import("../src/codex/catalog"); + const { getLastComboCatalogOmissions } = await import("../../src/codex/catalog"); expect(getLastComboCatalogOmissions().some(item => item.id === "recovered")).toBe(false); } finally { warn.mockRestore(); @@ -1685,7 +1685,7 @@ describe("combo catalog capability intersection", () => { const rows = await gatherRoutedModels(config); expect(rows.some(r => r.provider === "combo" && r.id === "disjoint")).toBe(false); expect(rows.some(r => r.provider === "combo" && r.id === "ghost")).toBe(false); - const { getLastComboCatalogOmissions } = await import("../src/codex/catalog"); + const { getLastComboCatalogOmissions } = await import("../../src/codex/catalog"); const omissions = getLastComboCatalogOmissions(); expect(omissions.find(item => item.id === "disjoint")).toMatchObject({ reason: "incompatible_modalities", @@ -1778,7 +1778,7 @@ describe("combo catalog capability intersection", () => { const warningText = warning.mock.calls.flat().join(" "); expect(warningText).not.toContain("member capabilities are incomplete"); expect(warningText).not.toContain("omitted configured model ids"); - const { getLastComboCatalogOmissions } = await import("../src/codex/catalog"); + const { getLastComboCatalogOmissions } = await import("../../src/codex/catalog"); expect(getLastComboCatalogOmissions().some(item => item.id === "failover")).toBe(false); } finally { warning.mockRestore(); @@ -6490,7 +6490,7 @@ describe("Codex reasoning-effort capability clamp", () => { describe("auto_review_model configuration (#1225)", () => { test("applyAutoReviewModelOverride sets auto_review_model_override across all entries", () => { - const { applyAutoReviewModelOverride } = require("../src/codex/catalog/sync"); + const { applyAutoReviewModelOverride } = require("../../src/codex/catalog/sync"); const entries = [ { slug: "gpt-5.5", auto_review_model_override: null }, { slug: "opencode-go/deepseek-v4-flash", auto_review_model_override: null }, @@ -6502,7 +6502,7 @@ describe("auto_review_model configuration (#1225)", () => { }); test("applyAutoReviewModelOverride clears routed state when autoReviewModel is null or empty", () => { - const { applyAutoReviewModelOverride } = require("../src/codex/catalog/sync"); + const { applyAutoReviewModelOverride } = require("../../src/codex/catalog/sync"); const entries = [ { slug: "gpt-5.5", auto_review_model_override: "existing-model" }, { slug: "opencode-go/glm-5.2", auto_review_model_override: "old-model" }, @@ -6517,7 +6517,7 @@ describe("auto_review_model configuration (#1225)", () => { }); test("applyAutoReviewModelOverride rejects invalid format with control chars or inner spaces", () => { - const { applyAutoReviewModelOverride, isValidAutoReviewModel } = require("../src/codex/catalog/sync"); + const { applyAutoReviewModelOverride, isValidAutoReviewModel } = require("../../src/codex/catalog/sync"); const entries = [ { slug: "gpt-5.5", auto_review_model_override: "native-preserved" }, ]; @@ -6530,13 +6530,13 @@ describe("auto_review_model configuration (#1225)", () => { }); test("readConfiguredAutoReviewModel reads auto_review_model from config.toml", () => { - const { readConfiguredAutoReviewModel } = require("../src/codex/catalog/parsing"); + const { readConfiguredAutoReviewModel } = require("../../src/codex/catalog/parsing"); expect(typeof readConfiguredAutoReviewModel).toBe("function"); }); test("writeRetainedCatalogSync stamps auto_review_model_override into persisted catalog", () => { - const { applyAutoReviewModelOverride } = require("../src/codex/catalog/sync"); - const { readConfiguredAutoReviewModel } = require("../src/codex/catalog/parsing"); + const { applyAutoReviewModelOverride } = require("../../src/codex/catalog/sync"); + const { readConfiguredAutoReviewModel } = require("../../src/codex/catalog/parsing"); // Simulate a config-driven write path: entries are regenerated from a template, // then the override is stamped before serialization. @@ -6560,7 +6560,7 @@ describe("auto_review_model configuration (#1225)", () => { expect(entries[1].auto_review_model_override).toBe(trimmedValue); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; describe("#2465 model preset management routes", () => { const originalFetchForPresets = globalThis.fetch; diff --git a/tests/codex-cli-install-provenance.test.ts b/tests/codex-integration/codex-cli-install-provenance.test.ts similarity index 99% rename from tests/codex-cli-install-provenance.test.ts rename to tests/codex-integration/codex-cli-install-provenance.test.ts index 1914f2b07b9..31635b2afdc 100644 --- a/tests/codex-cli-install-provenance.test.ts +++ b/tests/codex-integration/codex-cli-install-provenance.test.ts @@ -7,9 +7,9 @@ import { isAppBundledCodexPath, isCodexCliUpdateVersionManagerPath, type CodexCliInstallProvenanceDeps, -} from "../src/codex/cli-install-provenance"; -import { buildUnixCodexShim } from "../src/codex/shim"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/cli-install-provenance"; +import { buildUnixCodexShim } from "../../src/codex/shim"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-cli-update-launcher-policy.test.ts b/tests/codex-integration/codex-cli-update-launcher-policy.test.ts similarity index 84% rename from tests/codex-cli-update-launcher-policy.test.ts rename to tests/codex-integration/codex-cli-update-launcher-policy.test.ts index b8e4cf84ec8..b9bc83299be 100644 --- a/tests/codex-cli-update-launcher-policy.test.ts +++ b/tests/codex-integration/codex-cli-update-launcher-policy.test.ts @@ -1,7 +1,8 @@ import { describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { isCodexCliUpdateInspectionArgv } from "../src/update/codex-cli-update-launch-policy.mjs"; +import { isCodexCliUpdateInspectionArgv } from "../../src/update/codex-cli-update-launch-policy.mjs"; +import { repoPath } from "../helpers/repo-root"; describe("Codex CLI updater launcher policy", () => { test("covers the whole exact namespace including malformed actions", () => { @@ -17,7 +18,7 @@ describe("Codex CLI updater launcher policy", () => { }); test("launcher skips boot repair and lazy Bun installation for this namespace", () => { - const source = readFileSync(join(import.meta.dir, "..", "bin", "ocx.mjs"), "utf8"); + const source = readFileSync(repoPath("bin", "ocx.mjs"), "utf8"); expect(source).toContain("!codexCliUpdateInspection && isNodeModulesInstall()"); expect(source).toContain("resolveBun({ allowInstall: !codexCliUpdateInspection })"); expect(source).toContain("if (allowInstall && existsSync(installJs))"); diff --git a/tests/codex-cli-update-zero-effect.test.ts b/tests/codex-integration/codex-cli-update-zero-effect.test.ts similarity index 88% rename from tests/codex-cli-update-zero-effect.test.ts rename to tests/codex-integration/codex-cli-update-zero-effect.test.ts index 2cedd734bca..bc878b80e29 100644 --- a/tests/codex-cli-update-zero-effect.test.ts +++ b/tests/codex-integration/codex-cli-update-zero-effect.test.ts @@ -3,7 +3,8 @@ import { spawnSync } from "node:child_process"; import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath, repoRoot } from "../helpers/repo-root"; const roots: string[] = []; afterEach(() => { @@ -13,10 +14,10 @@ afterEach(() => { describe("Codex CLI updater zero-effect boundary", () => { test("direct Bun execution of the Node launcher fails before updater inspection", () => { const result = spawnSync(process.execPath, [ - join(import.meta.dir, "..", "bin", "ocx.mjs"), + repoPath("bin", "ocx.mjs"), "system", "codex-cli-update", "check", "--json", ], { - cwd: join(import.meta.dir, ".."), encoding: "utf8", timeout: 15_000, + cwd: repoRoot(), encoding: "utf8", timeout: 15_000, env: { ...process.env }, windowsHide: true, }); expect(result.error).toBeUndefined(); @@ -38,8 +39,8 @@ describe("Codex CLI updater zero-effect boundary", () => { const statePath = join(home, "codex-shim.json"); writeFileSync(statePath, "{broken", "utf8"); const before = readFileSync(statePath); - const result = spawnSync("node", [join(import.meta.dir, "..", "bin", "ocx.mjs"), "system", "codex-cli-update", "check", "--json"], { - cwd: join(import.meta.dir, ".."), + const result = spawnSync("node", [repoPath("bin", "ocx.mjs"), "system", "codex-cli-update", "check", "--json"], { + cwd: repoRoot(), encoding: "utf8", timeout: 15_000, env: { ...process.env, OPENCODEX_HOME: home, CODEX_CLI_PATH: launcher }, @@ -75,11 +76,11 @@ describe("Codex CLI updater zero-effect boundary", () => { writeFileSync(statePath, "{broken", "utf8"); const before = readFileSync(statePath); const result = spawnSync("node", [ - join(import.meta.dir, "..", "bin", "ocx.mjs"), + repoPath("bin", "ocx.mjs"), "--ocx-internal-launch-proof=bad", "system", "codex-cli-update", "invalid", ], { - cwd: join(import.meta.dir, ".."), encoding: "utf8", timeout: 15_000, + cwd: repoRoot(), encoding: "utf8", timeout: 15_000, env: { ...process.env, OPENCODEX_HOME: home, CODEX_CLI_PATH: launcher }, windowsHide: true, }); expect(result.error).toBeUndefined(); diff --git a/tests/codex-composed-acceptance.test.ts b/tests/codex-integration/codex-composed-acceptance.test.ts similarity index 98% rename from tests/codex-composed-acceptance.test.ts rename to tests/codex-integration/codex-composed-acceptance.test.ts index 32312b3e7f2..4dac153f14f 100644 --- a/tests/codex-composed-acceptance.test.ts +++ b/tests/codex-integration/codex-composed-acceptance.test.ts @@ -23,8 +23,8 @@ import { join, relative, resolve } from "node:path"; import { createHash } from "node:crypto"; import { Database } from "bun:sqlite"; -import { watchdogMs } from "./helpers/ci-watchdog"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { watchdogMs } from "../helpers/ci-watchdog"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * Per-case budget. A case can start a server twice and stop it, so it must exceed the sum of @@ -35,15 +35,16 @@ const CASE_TIMEOUT_MS = process.env.CI === "true" ? 150_000 : 45_000; import { canonicalizeCodexHome, -} from "../src/codex/codex-write-lock"; +} from "../../src/codex/codex-write-lock"; import { resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import { claimOwnedServiceHome, withOwnedServiceHomePreload } from "./helpers/owned-service-home"; -import { SERVER_BUDGET_MS } from "./helpers/test-budget"; +} from "../../src/codex/user-identity"; +import { claimOwnedServiceHome, withOwnedServiceHomePreload } from "../helpers/owned-service-home"; +import { SERVER_BUDGET_MS } from "../helpers/test-budget"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; -const repoRoot = resolve(import.meta.dir, ".."); +const repoRoot = resolveRepoRoot(); const cliPath = resolve(repoRoot, "src/cli/index.ts"); const lockChildPath = resolve(repoRoot, "tests/helpers/codex-write-lock-child.ts"); const roots: Fixture[] = []; diff --git a/tests/codex-config-generation.test.ts b/tests/codex-integration/codex-config-generation.test.ts similarity index 97% rename from tests/codex-config-generation.test.ts rename to tests/codex-integration/codex-config-generation.test.ts index e45df077db6..59a6377a71b 100644 --- a/tests/codex-config-generation.test.ts +++ b/tests/codex-integration/codex-config-generation.test.ts @@ -22,12 +22,13 @@ import { saveConfig, saveConfigPreservingClaudeCode, withExpectedConfigGenerationSync, -} from "../src/config"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/config"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath, repoRoot } from "../helpers/repo-root"; const CHILD_TIMEOUT_MS = 10_000; -const configModuleUrl = pathToFileURL(join(import.meta.dir, "../src/config.ts")).href; +const configModuleUrl = pathToFileURL(repoPath("src/config.ts")).href; const generationGuardRaceScript = ` import { existsSync, writeFileSync } from "node:fs"; import { withExpectedConfigGenerationSync } from ${JSON.stringify(configModuleUrl)}; @@ -272,7 +273,7 @@ test("two real processes racing one generation run exactly one callback", async peerOutcomePath: join(testRoot, `${peerId}.outcome`), }; return Bun.spawn([process.execPath, "--eval", generationGuardRaceScript], { - cwd: join(import.meta.dir, ".."), + cwd: repoRoot(), env: { ...process.env, HOME: testRoot, diff --git a/tests/codex-convergence-account-selectors.test.ts b/tests/codex-integration/codex-convergence-account-selectors.test.ts similarity index 97% rename from tests/codex-convergence-account-selectors.test.ts rename to tests/codex-integration/codex-convergence-account-selectors.test.ts index 4512d225fde..ae83c1f2bf4 100644 --- a/tests/codex-convergence-account-selectors.test.ts +++ b/tests/codex-integration/codex-convergence-account-selectors.test.ts @@ -12,42 +12,42 @@ import { import { tmpdir } from "node:os"; import { join } from "node:path"; -import { captureCatalogAdmissionSnapshot } from "../src/codex/catalog-admission"; +import { captureCatalogAdmissionSnapshot } from "../../src/codex/catalog-admission"; import { CODEX_ACCOUNT_BOUND_CATALOG_KIND, loadBundledCodexCatalog, NATIVE_OPENAI_MODELS, resetCatalogRuntimeStateForTests, syncCatalogModels, -} from "../src/codex/catalog"; +} from "../../src/codex/catalog"; import { commitCodexCatalogCandidate, convergeCodexCatalog, gatherCodexCatalogCandidate, -} from "../src/codex/convergence"; +} from "../../src/codex/convergence"; import { catalogBackupPathFor, type RawCatalog, type RawEntry, -} from "../src/codex/catalog/parsing"; +} from "../../src/codex/catalog/parsing"; import { resolveCodexCatalogSerializationDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import { getConfigPath, saveConfig } from "../src/config"; -import { CODEX_FORWARD_BASE_URL } from "../src/providers/openai-tiers"; -import type { OcxConfig } from "../src/types"; -import { setBundledCatalogCacheForTests } from "../src/codex/catalog/bundled"; +} from "../../src/codex/user-identity"; +import { getConfigPath, saveConfig } from "../../src/config"; +import { CODEX_FORWARD_BASE_URL } from "../../src/providers/openai-tiers"; +import type { OcxConfig } from "../../src/types"; +import { setBundledCatalogCacheForTests } from "../../src/codex/catalog/bundled"; import { resetCodexRuntimeResolveCacheForTests, setCodexRuntimeResolveCacheForTests, -} from "../src/codex/runtime"; -import { markModelsFetchFailure } from "../src/codex/model-cache"; -import { legacyCustomModelCatalogSlugs } from "../src/codex/custom-model-catalog-migration"; -import { resetCodexModelEntitlementCacheForTests } from "../src/codex/model-entitlements"; -import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../src/codex/catalog/native-models"; -import { removeCodexAccountCredential, saveCodexAccountCredential } from "../src/codex/account-store"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/runtime"; +import { markModelsFetchFailure } from "../../src/codex/model-cache"; +import { legacyCustomModelCatalogSlugs } from "../../src/codex/custom-model-catalog-migration"; +import { resetCodexModelEntitlementCacheForTests } from "../../src/codex/model-entitlements"; +import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../../src/codex/catalog/native-models"; +import { removeCodexAccountCredential, saveCodexAccountCredential } from "../../src/codex/account-store"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; // The canonical-bytes case spawns real syncs and runs ~2.5s in isolation, on this // tree and on a clean baseline alike. That is half of bun's 5s default, but full diff --git a/tests/codex-convergence-contract.test.ts b/tests/codex-integration/codex-convergence-contract.test.ts similarity index 94% rename from tests/codex-convergence-contract.test.ts rename to tests/codex-integration/codex-convergence-contract.test.ts index 98e9d97b958..db379630957 100644 --- a/tests/codex-convergence-contract.test.ts +++ b/tests/codex-integration/codex-convergence-contract.test.ts @@ -15,32 +15,33 @@ import { import { tmpdir } from "node:os"; import { join, relative } from "node:path"; -import { captureCatalogAdmissionSnapshot } from "../src/codex/catalog-admission"; +import { captureCatalogAdmissionSnapshot } from "../../src/codex/catalog-admission"; import { commitCodexCatalogCandidate, gatherCodexCatalogCandidate, type CodexCatalogCandidate, -} from "../src/codex/convergence"; -import { CODEX_NATIVE_ALIAS_CATALOG_KIND, resetCatalogRuntimeStateForTests } from "../src/codex/catalog"; +} from "../../src/codex/convergence"; +import { CODEX_NATIVE_ALIAS_CATALOG_KIND, resetCatalogRuntimeStateForTests } from "../../src/codex/catalog"; import { persistCodexRuntime, resetCodexRuntimeResolveCacheForTests, setCodexRuntimeResolveCacheForTests, -} from "../src/codex/runtime"; +} from "../../src/codex/runtime"; import { invalidateBundledCatalogCache, setBundledCatalogCacheForTests, -} from "../src/codex/catalog/bundled"; +} from "../../src/codex/catalog/bundled"; import { resolveCodexCatalogSerializationDatabasePath, resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import { saveConfig } from "../src/config"; -import { handleManagementAPI } from "../src/server/management-api"; -import type { OcxConfig } from "../src/types"; -import { ManagementRequest } from "./helpers/management-auth"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/user-identity"; +import { saveConfig } from "../../src/config"; +import { handleManagementAPI } from "../../src/server/management-api"; +import type { OcxConfig } from "../../src/types"; +import { ManagementRequest } from "../helpers/management-auth"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath } from "../helpers/repo-root"; let root = ""; let codexHome = ""; @@ -380,7 +381,7 @@ test("the route inventory contains exactly the specified 8 + 14 + 2 + 2 converge ["combo-routes.ts", 2], ["agent-settings-routes.ts", 2], ].map(([file, expected]) => { - const source = readFileSync(join(import.meta.dir, "..", "src", "server", "management", file as string), "utf8"); + const source = readFileSync(repoPath("src", "server", "management", file as string), "utf8"); const count = source.match(/await convergeCodexCatalog\(\)/g)?.length ?? 0; expect(count).toBe(expected); expect(source).not.toContain("refreshCodexCatalogBestEffort"); @@ -395,7 +396,7 @@ test("the route inventory contains exactly the specified 8 + 14 + 2 + 2 converge }); test("both model-discovery write paths converge the Codex catalog", () => { - const source = readFileSync(join(import.meta.dir, "..", "src", "server", "management", "model-routes.ts"), "utf8"); + const source = readFileSync(repoPath("src", "server", "management", "model-routes.ts"), "utf8"); const settings = source.slice(source.indexOf('url.pathname === "/api/model-discovery" && req.method === "PUT"'), source.indexOf('url.pathname === "/api/model-discovery/acknowledge"')); // Sliced to the NEXT route rather than to /api/catalog: the alias routes (#2463) landed // between them, so a fixed far boundary would swallow their convergence calls and count @@ -406,7 +407,7 @@ test("both model-discovery write paths converge the Codex catalog", () => { }); test("all three alias write routes converge the Codex catalog", () => { - const source = readFileSync(join(import.meta.dir, "..", "src", "server", "management", "model-routes.ts"), "utf8"); + const source = readFileSync(repoPath("src", "server", "management", "model-routes.ts"), "utf8"); for (const marker of ["providerAliasMatch && req.method", "modelAliasMatch && req.method", 'url.pathname === "/api/default-aliases"']) { const start = source.indexOf(marker); expect(start).toBeGreaterThan(-1); @@ -426,7 +427,7 @@ test("all three alias write routes converge the Codex catalog", () => { */ test("both model-preset write paths converge the Codex catalog", () => { const source = readFileSync( - join(import.meta.dir, "..", "src", "server", "management", "model-routes.ts"), + repoPath("src", "server", "management", "model-routes.ts"), "utf8", ); const handlerStart = source.indexOf('url.pathname === "/api/model-presets" && req.method === "PUT"'); @@ -447,7 +448,7 @@ test("both model-preset write paths converge the Codex catalog", () => { */ test("the attested reload route converges the Codex catalog like the other write paths", () => { const source = readFileSync( - join(import.meta.dir, "..", "src", "server", "management", "provider-routes.ts"), + repoPath("src", "server", "management", "provider-routes.ts"), "utf8", ); const handlerStart = source.indexOf("LOCAL_PROVIDER_RELOAD_PATH && req.method === \"POST\""); @@ -465,7 +466,7 @@ test("the attested reload route converges the Codex catalog like the other write */ test("the atomic provider batch route converges the Codex catalog once", () => { const source = readFileSync( - join(import.meta.dir, "..", "src", "server", "management", "provider-routes.ts"), + repoPath("src", "server", "management", "provider-routes.ts"), "utf8", ); const handlerStart = source.indexOf('url.pathname === "/api/providers" && req.method === "PUT"'); diff --git a/tests/codex-cooldown-recovery.test.ts b/tests/codex-integration/codex-cooldown-recovery.test.ts similarity index 98% rename from tests/codex-cooldown-recovery.test.ts rename to tests/codex-integration/codex-cooldown-recovery.test.ts index 1fc6fcaf413..a196adcfe83 100644 --- a/tests/codex-cooldown-recovery.test.ts +++ b/tests/codex-integration/codex-cooldown-recovery.test.ts @@ -6,8 +6,8 @@ import { clearAccountQuota, runCodexCooldownRecoveryProbes, seedCodexAuthAdmissionForTests, -} from "../src/codex/auth-api"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; +} from "../../src/codex/auth-api"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; import { codexQuotaWindowForPlan, getAccountQuota, @@ -15,17 +15,17 @@ import { parseUsageQuota, setAccountQuotaFromParsed, updateAccountQuota, -} from "../src/codex/quota"; -import upstreamModels from "../src/codex/data/upstream-models.json"; +} from "../../src/codex/quota"; +import upstreamModels from "../../src/codex/data/upstream-models.json"; import { CODEX_QUOTA_PROBE_INTERVAL_MS, clearCodexUpstreamHealth, getCodexQuotaHealthSnapshot, recordCodexUpstreamOutcome, resolveCodexAccountForThread, -} from "../src/codex/routing"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/routing"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-codex-cooldown-recovery-test"); const TEST_CODEX_HOME = join(TEST_DIR, "codex"); diff --git a/tests/codex-coordinator-doctor.test.ts b/tests/codex-integration/codex-coordinator-doctor.test.ts similarity index 96% rename from tests/codex-coordinator-doctor.test.ts rename to tests/codex-integration/codex-coordinator-doctor.test.ts index 531a73f2149..acbf312ca26 100644 --- a/tests/codex-coordinator-doctor.test.ts +++ b/tests/codex-integration/codex-coordinator-doctor.test.ts @@ -8,20 +8,20 @@ import { Database } from "bun:sqlite"; import { inspectCodexCoordinator, recoverZeroByteCodexCoordinator, -} from "../src/codex/coordinator-doctor"; +} from "../../src/codex/coordinator-doctor"; import { codexWriteCoordinationEligibility, STABLE_ZERO_BYTE_COORDINATOR_AGE_MS, -} from "../src/codex/inject-coordination"; +} from "../../src/codex/inject-coordination"; import { openCodexCoordinatorTransaction, -} from "../src/codex/transition-state"; +} from "../../src/codex/transition-state"; import { resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import { formatCoordinatorDoctorLines } from "../src/cli/doctor"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/user-identity"; +import { formatCoordinatorDoctorLines } from "../../src/cli/doctor"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let codexHome = ""; let opencodexHome = ""; diff --git a/tests/codex-desired-state.test.ts b/tests/codex-integration/codex-desired-state.test.ts similarity index 98% rename from tests/codex-desired-state.test.ts rename to tests/codex-integration/codex-desired-state.test.ts index 43c82d6acca..92651f2293b 100644 --- a/tests/codex-desired-state.test.ts +++ b/tests/codex-integration/codex-desired-state.test.ts @@ -12,7 +12,7 @@ import { mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { loadConfig, saveConfig } from "../src/config"; +import { loadConfig, saveConfig } from "../../src/config"; import { codexIntegrationEnabled, codexIntegrationEnabledNow, @@ -22,9 +22,9 @@ import { shouldSyncCodexOnStart, shouldSyncGrokOnStart, syncCodexOnStartIfEnabled, -} from "../src/codex/desired-state"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/desired-state"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testRoot = ""; let previousOpencodexHome: string | undefined; diff --git a/tests/codex-envkey-admission-substitution.test.ts b/tests/codex-integration/codex-envkey-admission-substitution.test.ts similarity index 95% rename from tests/codex-envkey-admission-substitution.test.ts rename to tests/codex-integration/codex-envkey-admission-substitution.test.ts index 32fe999cdfc..cb1a0853d13 100644 --- a/tests/codex-envkey-admission-substitution.test.ts +++ b/tests/codex-integration/codex-envkey-admission-substitution.test.ts @@ -2,20 +2,20 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; -import { startServer } from "../src/server"; -import type { OcxConfig } from "../src/types"; -import { getDebugLogEntries, resetDebugLogBufferForTests } from "../src/lib/debug-log-buffer"; -import { resetDebugSettingsForTests, setDebugSettings } from "../src/lib/debug-settings"; -import { waitForNativeMainStartupGate } from "../src/codex/native-profile-startup"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { saveConfig } from "../../src/config"; +import { startServer } from "../../src/server"; +import type { OcxConfig } from "../../src/types"; +import { getDebugLogEntries, resetDebugLogBufferForTests } from "../../src/lib/debug-log-buffer"; +import { resetDebugSettingsForTests, setDebugSettings } from "../../src/lib/debug-settings"; +import { waitForNativeMainStartupGate } from "../../src/codex/native-profile-startup"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * #1686 end to end: a Codex client injected with `env_key` presents the proxy admission * secret as `Authorization: Bearer`. Direct must ADMIT that request and substitute the * stored main credential; the admission secret must never appear upstream. * - * The unit matrix in tests/codex-auth-context.test.ts proves the materializer in isolation. + * The unit matrix in tests/codex-integration/codex-auth-context.test.ts proves the materializer in isolation. * It cannot prove the HTTP handler passes the presentation source down to it, which is the * half that was missing: the source was resolved at the door and dropped one frame later. */ diff --git a/tests/codex-exec-invocation.test.ts b/tests/codex-integration/codex-exec-invocation.test.ts similarity index 96% rename from tests/codex-exec-invocation.test.ts rename to tests/codex-integration/codex-exec-invocation.test.ts index ace665fa172..bb632b505f5 100644 --- a/tests/codex-exec-invocation.test.ts +++ b/tests/codex-integration/codex-exec-invocation.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { escapeCmdArg, escapeCmdCommand } from "../src/lib/win-exec"; -import { codexExecInvocation, isSpawnableCodexCandidate } from "../src/codex/catalog"; +import { escapeCmdArg, escapeCmdCommand } from "../../src/lib/win-exec"; +import { codexExecInvocation, isSpawnableCodexCandidate } from "../../src/codex/catalog"; describe("codexExecInvocation", () => { test("routes Windows .cmd/.bat through ComSpec with escaped args (no shell:true)", () => { diff --git a/tests/codex-features-cache.test.ts b/tests/codex-integration/codex-features-cache.test.ts similarity index 94% rename from tests/codex-features-cache.test.ts rename to tests/codex-integration/codex-features-cache.test.ts index 4b802a7149d..8f748689fa9 100644 --- a/tests/codex-features-cache.test.ts +++ b/tests/codex-integration/codex-features-cache.test.ts @@ -7,12 +7,12 @@ import { MODE_HINT_CAPABILITY_CACHE_MAX_ENTRIES, modeHintCapabilityCache, probeCodexSupportsModeHint, -} from "../src/codex/features"; +} from "../../src/codex/features"; import { resetCodexRuntimeResolveCacheForTests, setCodexRuntimeResolveCacheForTests, -} from "../src/codex/runtime"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/runtime"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-features-residual.test.ts b/tests/codex-integration/codex-features-residual.test.ts similarity index 86% rename from tests/codex-features-residual.test.ts rename to tests/codex-integration/codex-features-residual.test.ts index 737be1a6fe8..ecef9514061 100644 --- a/tests/codex-features-residual.test.ts +++ b/tests/codex-integration/codex-features-residual.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { isAtomicResidualError } from "../src/codex/features"; -import { AtomicWriteResidualTempError, AtomicWriteSecretResidualError } from "../src/config"; +import { isAtomicResidualError } from "../../src/codex/features"; +import { AtomicWriteResidualTempError, AtomicWriteSecretResidualError } from "../../src/config"; describe("migration memo release gate", () => { test("both residual classes retain the destination memo", () => { diff --git a/tests/codex-filesystem-evidence.test.ts b/tests/codex-integration/codex-filesystem-evidence.test.ts similarity index 95% rename from tests/codex-filesystem-evidence.test.ts rename to tests/codex-integration/codex-filesystem-evidence.test.ts index 74c3552e90e..39bfe9ca583 100644 --- a/tests/codex-filesystem-evidence.test.ts +++ b/tests/codex-integration/codex-filesystem-evidence.test.ts @@ -13,11 +13,11 @@ import { import { tmpdir } from "node:os"; import { join } from "node:path"; -import { captureCatalogAdmissionSnapshot } from "../src/codex/catalog-admission"; +import { captureCatalogAdmissionSnapshot } from "../../src/codex/catalog-admission"; import { resetBundledCatalogCacheForTests, resolveCatalogSourceForGather, -} from "../src/codex/catalog/bundled"; +} from "../../src/codex/catalog/bundled"; import { acceptCatalogGatherSourcePath, captureAndSealCatalogHomeSelection, @@ -26,11 +26,11 @@ import { readCatalogGatherSource, sealCatalogGatherEvidenceSession, type CatalogGatherProviderAuthEvidence, -} from "../src/codex/catalog/filesystem-evidence"; -import type { CatalogSourceEvidence } from "../src/codex/convergence-types"; -import { saveConfig } from "../src/config"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/catalog/filesystem-evidence"; +import type { CatalogSourceEvidence } from "../../src/codex/convergence-types"; +import { saveConfig } from "../../src/config"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; interface ManifestEntry { readonly path: string; diff --git a/tests/codex-gather-authority.test.ts b/tests/codex-integration/codex-gather-authority.test.ts similarity index 97% rename from tests/codex-gather-authority.test.ts rename to tests/codex-integration/codex-gather-authority.test.ts index 5b9724971e0..ae3204a0a74 100644 --- a/tests/codex-gather-authority.test.ts +++ b/tests/codex-integration/codex-gather-authority.test.ts @@ -4,12 +4,12 @@ import { createHash } from "node:crypto"; import { clearGatherRoutedModelsInflight, gatherRoutedModels, -} from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { PROVIDER_REGISTRY, type ProviderModelDiscoverySpec } from "../src/providers/registry"; -import type { OcxConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import { withRegistryDiscovery } from "./helpers/provider-registry-discovery"; +} from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { PROVIDER_REGISTRY, type ProviderModelDiscoverySpec } from "../../src/providers/registry"; +import type { OcxConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { withRegistryDiscovery } from "../helpers/provider-registry-discovery"; const originalFetch = globalThis.fetch; diff --git a/tests/codex-history-job.test.ts b/tests/codex-integration/codex-history-job.test.ts similarity index 98% rename from tests/codex-history-job.test.ts rename to tests/codex-integration/codex-history-job.test.ts index 210f3c51234..219575e045d 100644 --- a/tests/codex-history-job.test.ts +++ b/tests/codex-integration/codex-history-job.test.ts @@ -11,8 +11,9 @@ import { describeHistoryJobFailure, deriveCodexHistoryOperation, runCodexHistoryJob, -} from "../src/codex/history-job"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/history-job"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; const sandboxes: string[] = []; let previousCodexHome: string | undefined; @@ -284,7 +285,7 @@ test("a hard history error reaches the caller with its real message", async () = * must leave it tagged, and the default must restore its exact original tuple. */ test("the synchronous restore body is gated on skipHistory", () => { - const repoRoot = join(import.meta.dir, ".."); + const repoRoot = resolveRepoRoot(); const root = mkdtempSync(join(tmpdir(), "ocx-restore-skiphistory-")); const fixtureCodexHome = join(root, ".codex"); const fixtureOcxHome = join(root, ".opencodex"); diff --git a/tests/codex-history-lock.test.ts b/tests/codex-integration/codex-history-lock.test.ts similarity index 96% rename from tests/codex-history-lock.test.ts rename to tests/codex-integration/codex-history-lock.test.ts index 63ba943e043..b752b60e53e 100644 --- a/tests/codex-history-lock.test.ts +++ b/tests/codex-integration/codex-history-lock.test.ts @@ -8,10 +8,11 @@ import { isHistoryWritePermitLive, withHistoryWriteSerialization, type HistoryWritePermit, -} from "../src/codex/history-lock"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/history-lock"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; -const repoRoot = resolve(import.meta.dir, ".."); +const repoRoot = resolveRepoRoot(); const sandboxes: string[] = []; interface Sandbox { diff --git a/tests/codex-history-provider.test.ts b/tests/codex-integration/codex-history-provider.test.ts similarity index 99% rename from tests/codex-history-provider.test.ts rename to tests/codex-integration/codex-history-provider.test.ts index 1fd083e1383..fbc97238ded 100644 --- a/tests/codex-history-provider.test.ts +++ b/tests/codex-integration/codex-history-provider.test.ts @@ -3,8 +3,8 @@ import { tmpdir } from "node:os"; import { join } from "node:path"; import { Database } from "bun:sqlite"; import { afterEach, describe, expect, setDefaultTimeout, test } from "bun:test"; -import { classifyRecoverableHistoryError, countPendingOpencodexHistory, historyBackupPathFor, isRecoverableHistoryError, migrateHistoryToOpenai, restoreLegacyOpenaiHistory, restoredUserEventFor, setAfterNoopPendingCountForTests, setAfterStrictHistoryRolloutAppendForTests, setBeforeHistoryApplyTransactionForTests, setBeforeHistoryBackupConsumeForTests, setBeforeStrictHistoryRolloutAppendForTests, setHistoryDbBusyTimeoutForTests, snapshotCodexHistoryNoop, syncCodexHistoryProvider, withHistoryRetry } from "../src/codex/history-provider"; -import { INVALID_HISTORY_BACKUP_FIXTURES, validHistoryBackupFixture } from "./helpers/codex-history-manifest-fixtures"; +import { classifyRecoverableHistoryError, countPendingOpencodexHistory, historyBackupPathFor, isRecoverableHistoryError, migrateHistoryToOpenai, restoreLegacyOpenaiHistory, restoredUserEventFor, setAfterNoopPendingCountForTests, setAfterStrictHistoryRolloutAppendForTests, setBeforeHistoryApplyTransactionForTests, setBeforeHistoryBackupConsumeForTests, setBeforeStrictHistoryRolloutAppendForTests, setHistoryDbBusyTimeoutForTests, snapshotCodexHistoryNoop, syncCodexHistoryProvider, withHistoryRetry } from "../../src/codex/history-provider"; +import { INVALID_HISTORY_BACKUP_FIXTURES, validHistoryBackupFixture } from "../helpers/codex-history-manifest-fixtures"; // Windows CI: a transient file lock can consume the full production 5s busy timeout, tripping // bun's 5s default per-test timeout by itself. Fail fast into withHistoryRetry instead. diff --git a/tests/codex-history-reachability.test.ts b/tests/codex-integration/codex-history-reachability.test.ts similarity index 98% rename from tests/codex-history-reachability.test.ts rename to tests/codex-integration/codex-history-reachability.test.ts index af95102ac7a..553049da4dd 100644 --- a/tests/codex-history-reachability.test.ts +++ b/tests/codex-integration/codex-history-reachability.test.ts @@ -1,6 +1,7 @@ import { expect, test } from "bun:test"; import { readFileSync, readdirSync, statSync } from "node:fs"; import { join, relative, resolve } from "node:path"; +import { repoPath } from "../helpers/repo-root"; /** * Who may reach a history writer, checked by walking imports rather than counting @@ -15,7 +16,7 @@ import { join, relative, resolve } from "node:path"; * mutates the database, the manifest and the rollouts; only `history-worker.ts` * runs inside H, so only it may reach those symbols. */ -const SRC = resolve(import.meta.dir, "..", "src"); +const SRC = repoPath("src"); /** Modules whose exports mutate Codex history. */ const HISTORY_WRITER = "codex/internal/history-writer.ts"; diff --git a/tests/codex-history-worker-boundary.test.ts b/tests/codex-integration/codex-history-worker-boundary.test.ts similarity index 96% rename from tests/codex-history-worker-boundary.test.ts rename to tests/codex-integration/codex-history-worker-boundary.test.ts index c2ea56cbb21..f92ff49442b 100644 --- a/tests/codex-history-worker-boundary.test.ts +++ b/tests/codex-integration/codex-history-worker-boundary.test.ts @@ -11,8 +11,8 @@ import { mkdirSync, mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { runCodexHistoryJob } from "../src/codex/history-job"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { runCodexHistoryJob } from "../../src/codex/history-job"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let root = ""; let previousCodexHome: string | undefined; @@ -65,7 +65,7 @@ describe("the result validator", () => { // {requestId, type:"done"} with nothing else used to read as converged with // undefined rows. The module-level validator is the contract, exercised // through the job's own classification seam rather than a fabricated cast. - const { isPlausibleWorkerResultForTests } = await import("../src/codex/history-job"); + const { isPlausibleWorkerResultForTests } = await import("../../src/codex/history-job"); expect(isPlausibleWorkerResultForTests( { requestId: "r", type: "done" }, "r", "j", )).toBe(false); @@ -131,7 +131,7 @@ describe("the result validator", () => { }); test("blocked carries exactly its three reasons", async () => { - const { isPlausibleWorkerResultForTests } = await import("../src/codex/history-job"); + const { isPlausibleWorkerResultForTests } = await import("../../src/codex/history-job"); for (const reason of ["busy", "database", "unsafe-path"] as const) { expect(isPlausibleWorkerResultForTests( { requestId: "r", jobId: "j", type: "blocked", reason }, "r", "j", @@ -143,7 +143,7 @@ describe("the result validator", () => { }); test("the parent preserves partial progress from a valid worker error", async () => { - const { classifyWorkerResultForTests } = await import("../src/codex/history-job"); + const { classifyWorkerResultForTests } = await import("../../src/codex/history-job"); expect(classifyWorkerResultForTests({ requestId: "r", jobId: "j", diff --git a/tests/codex-history-worker.test.ts b/tests/codex-integration/codex-history-worker.test.ts similarity index 98% rename from tests/codex-history-worker.test.ts rename to tests/codex-integration/codex-history-worker.test.ts index c269947cdd5..454efa72e53 100644 --- a/tests/codex-history-worker.test.ts +++ b/tests/codex-integration/codex-history-worker.test.ts @@ -5,20 +5,21 @@ import { dirname, join, resolve } from "node:path"; import { Database } from "bun:sqlite"; -import { historyBackupPathFor, setBeforeHistoryBackupConsumeForTests, setHistoryDbBusyTimeoutForTests } from "../src/codex/history-provider"; +import { historyBackupPathFor, setBeforeHistoryBackupConsumeForTests, setHistoryDbBusyTimeoutForTests } from "../../src/codex/history-provider"; import { isHistoryWorkerRunMessage, runHistoryUnitUnderLock, type HistoryWorkerRunMessage, -} from "../src/codex/history-worker"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/history-worker"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; // A held write lock otherwise costs the full production 5s busy timeout per // attempt, tripping bun's 5s default per-test timeout. setHistoryDbBusyTimeoutForTests(250); setDefaultTimeout(30_000); -const repoRoot = resolve(import.meta.dir, ".."); +const repoRoot = resolveRepoRoot(); const sandboxes: string[] = []; const backupArtifacts: string[] = []; diff --git a/tests/codex-history-writer.test.ts b/tests/codex-integration/codex-history-writer.test.ts similarity index 96% rename from tests/codex-history-writer.test.ts rename to tests/codex-integration/codex-history-writer.test.ts index 1c72aeeaa28..db8d672245e 100644 --- a/tests/codex-history-writer.test.ts +++ b/tests/codex-integration/codex-history-writer.test.ts @@ -8,13 +8,13 @@ import { Database } from "bun:sqlite"; import { withHistoryWriteSerialization, type HistoryWritePermit, -} from "../src/codex/history-lock"; +} from "../../src/codex/history-lock"; import { writeHistoryProviderTransition, writeLegacyOpenaiHistoryRecovery, type HistoryWriteTarget, -} from "../src/codex/internal/history-writer"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/internal/history-writer"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const sandboxes: string[] = []; diff --git a/tests/codex-home-wsl.test.ts b/tests/codex-integration/codex-home-wsl.test.ts similarity index 93% rename from tests/codex-home-wsl.test.ts rename to tests/codex-integration/codex-home-wsl.test.ts index 2441776eceb..671eb4a5a6c 100644 --- a/tests/codex-home-wsl.test.ts +++ b/tests/codex-integration/codex-home-wsl.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { wslAutomountRoot, listWslWindowsCodexHomes } from "../src/codex/home"; -import { isWindowsInteropDir } from "../src/codex/shim"; -import { currentServiceHomes } from "../src/service"; +import { wslAutomountRoot, listWslWindowsCodexHomes } from "../../src/codex/home"; +import { isWindowsInteropDir } from "../../src/codex/shim"; +import { currentServiceHomes } from "../../src/service"; describe("wsl.conf automount root", () => { test("defaults to /mnt when wsl.conf is absent or silent", () => { diff --git a/tests/codex-inject-history-wording.test.ts b/tests/codex-integration/codex-inject-history-wording.test.ts similarity index 94% rename from tests/codex-inject-history-wording.test.ts rename to tests/codex-integration/codex-inject-history-wording.test.ts index ab867a67676..9a681f120f3 100644 --- a/tests/codex-inject-history-wording.test.ts +++ b/tests/codex-integration/codex-inject-history-wording.test.ts @@ -5,13 +5,14 @@ import { resolve } from "node:path"; import { failedHistoryRestoreFromOutcome, formatApplyHistoryFailure, -} from "../src/codex/inject"; +} from "../../src/codex/inject"; +import { repoPath } from "../helpers/repo-root"; -const injectSource = readFileSync(resolve(import.meta.dir, "../src/codex/inject.ts"), "utf8"); -const doctorSource = readFileSync(resolve(import.meta.dir, "../src/cli/doctor.ts"), "utf8"); -const cliSource = readFileSync(resolve(import.meta.dir, "../src/cli/index.ts"), "utf8"); +const injectSource = readFileSync(repoPath("src/codex/inject.ts"), "utf8"); +const doctorSource = readFileSync(repoPath("src/cli/doctor.ts"), "utf8"); +const cliSource = readFileSync(repoPath("src/cli/index.ts"), "utf8"); const integrationGuide = readFileSync( - resolve(import.meta.dir, "../docs-site/src/content/docs/guides/codex-integration.md"), + repoPath("docs-site/src/content/docs/guides/codex-integration.md"), "utf8", ); diff --git a/tests/codex-inject-integration.test.ts b/tests/codex-integration/codex-inject-integration.test.ts similarity index 99% rename from tests/codex-inject-integration.test.ts rename to tests/codex-integration/codex-inject-integration.test.ts index 8c1ca474a20..3a5345098e1 100644 --- a/tests/codex-inject-integration.test.ts +++ b/tests/codex-integration/codex-inject-integration.test.ts @@ -8,11 +8,11 @@ import { Database } from "bun:sqlite"; import { MANAGED_AGENTS_TABLE_MARKER, MANAGED_SUBAGENT_DEFAULT_MARKER, -} from "../src/codex/subagent-defaults"; -import { SPAWN_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/subagent-defaults"; +import { SPAWN_BUDGET_MS } from "../helpers/test-budget"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); setDefaultTimeout(SPAWN_BUDGET_MS); diff --git a/tests/codex-inject-write-lock.test.ts b/tests/codex-integration/codex-inject-write-lock.test.ts similarity index 98% rename from tests/codex-inject-write-lock.test.ts rename to tests/codex-integration/codex-inject-write-lock.test.ts index 044c60b1c81..824e75f21f2 100644 --- a/tests/codex-inject-write-lock.test.ts +++ b/tests/codex-integration/codex-inject-write-lock.test.ts @@ -14,17 +14,18 @@ import { join } from "node:path"; import { resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; +} from "../../src/codex/user-identity"; import { boundProvenanceEntries, CODEX_PROVENANCE_MAX_BYTES, CODEX_PROVENANCE_MAX_TRANSACTIONS, STABLE_ZERO_BYTE_COORDINATOR_AGE_MS, -} from "../src/codex/inject-coordination"; -import { SPAWN_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/inject-coordination"; +import { SPAWN_BUDGET_MS } from "../helpers/test-budget"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; -const repoRoot = join(import.meta.dir, ".."); +const repoRoot = resolveRepoRoot(); const CHILD = join(repoRoot, "tests", "helpers", "codex-inject-race-child.ts"); const LOCK_CHILD = join(repoRoot, "tests", "helpers", "codex-write-lock-child.ts"); // Leave teardown and assertion headroom inside the surrounding test budget. A real diff --git a/tests/codex-inject.test.ts b/tests/codex-integration/codex-inject.test.ts similarity index 99% rename from tests/codex-inject.test.ts rename to tests/codex-integration/codex-inject.test.ts index 4133d333bca..84ac5f67b68 100644 --- a/tests/codex-inject.test.ts +++ b/tests/codex-integration/codex-inject.test.ts @@ -12,12 +12,12 @@ import { stripOpencodexConfig, stripRootContextWindowOverrides, standaloneCodexRoutingTarget, -} from "../src/codex/inject"; -import { stripJournaledOpenaiBaseUrl } from "../src/codex/injected-marker"; +} from "../../src/codex/inject"; +import { stripJournaledOpenaiBaseUrl } from "../../src/codex/injected-marker"; import { MANAGED_AGENTS_TABLE_MARKER, MANAGED_SUBAGENT_DEFAULT_MARKER, -} from "../src/codex/subagent-defaults"; +} from "../../src/codex/subagent-defaults"; describe("Codex config injection", () => { test("standalone routing-target wrappers remain byte-compatible", () => { diff --git a/tests/codex-injected-marker.test.ts b/tests/codex-integration/codex-injected-marker.test.ts similarity index 89% rename from tests/codex-injected-marker.test.ts rename to tests/codex-integration/codex-injected-marker.test.ts index 2d4dee47de7..84f892fbf3c 100644 --- a/tests/codex-injected-marker.test.ts +++ b/tests/codex-integration/codex-injected-marker.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { providerTableString, rootTomlString } from "../src/codex/injected-marker"; +import { providerTableString, rootTomlString } from "../../src/codex/injected-marker"; describe("Codex injected marker TOML strings", () => { test("decodes escaped basic strings", () => { diff --git a/tests/codex-integration-record.test.ts b/tests/codex-integration/codex-integration-record.test.ts similarity index 97% rename from tests/codex-integration-record.test.ts rename to tests/codex-integration/codex-integration-record.test.ts index e9e87550ec0..dce96985af5 100644 --- a/tests/codex-integration-record.test.ts +++ b/tests/codex-integration/codex-integration-record.test.ts @@ -5,14 +5,14 @@ import { join } from "node:path"; import { readIntegrationRecord, updateIntegrationRecord, -} from "../src/codex/integration-record"; -import { boundProvenanceEntries } from "../src/codex/inject-coordination"; +} from "../../src/codex/integration-record"; +import { boundProvenanceEntries } from "../../src/codex/inject-coordination"; import type { CodexArtifactId, CodexIntegrationRecord, CodexProvenanceEntry, -} from "../src/codex/convergence-types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/convergence-types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let opencodexHome = ""; let previousOpencodexHome: string | undefined; diff --git a/tests/codex-journal.test.ts b/tests/codex-integration/codex-journal.test.ts similarity index 98% rename from tests/codex-journal.test.ts rename to tests/codex-integration/codex-journal.test.ts index 847f298f08d..3b46be997af 100644 --- a/tests/codex-journal.test.ts +++ b/tests/codex-integration/codex-journal.test.ts @@ -8,11 +8,11 @@ import { fileURLToPath } from "node:url"; import { MANAGED_AGENTS_TABLE_MARKER, MANAGED_SUBAGENT_DEFAULT_MARKER, -} from "../src/codex/subagent-defaults"; -import { SPAWN_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/subagent-defaults"; +import { SPAWN_BUDGET_MS } from "../helpers/test-budget"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); setDefaultTimeout(SPAWN_BUDGET_MS); @@ -544,7 +544,7 @@ describe("codex-journal", () => { /** * The reachable case a "replace only when a journal exists" gate would miss: * an injected config with NO journal, which is exactly where the legacy upgrade - * path in tests/codex-inject-integration.test.ts starts. + * path in tests/codex-integration/codex-inject-integration.test.ts starts. */ test("an injected config with no journal is never captured as the original (#477)", () => { const injected = [ diff --git a/tests/codex-log-guard-coderabbit.test.ts b/tests/codex-integration/codex-log-guard-coderabbit.test.ts similarity index 97% rename from tests/codex-log-guard-coderabbit.test.ts rename to tests/codex-integration/codex-log-guard-coderabbit.test.ts index 307eb8058b5..2b79bb7d5fb 100644 --- a/tests/codex-log-guard-coderabbit.test.ts +++ b/tests/codex-integration/codex-log-guard-coderabbit.test.ts @@ -4,14 +4,14 @@ import { mkdirSync, mkdtempSync, realpathSync, symlinkSync, writeFileSync } from import { tmpdir } from "node:os"; import { join } from "node:path"; -import { codexLogGuardLockDigest } from "../src/codex/log-guard/lock"; -import { sameLogGuardPathIdentity } from "../src/codex/log-guard/path-safety"; +import { codexLogGuardLockDigest } from "../../src/codex/log-guard/lock"; +import { sameLogGuardPathIdentity } from "../../src/codex/log-guard/path-safety"; import { getCodexLogGuardProtectionStatus, protectCodexLogs, unprotectCodexLogs, -} from "../src/codex/log-guard/protection"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/log-guard/protection"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-log-guard-doctor-coderabbit.test.ts b/tests/codex-integration/codex-log-guard-doctor-coderabbit.test.ts similarity index 90% rename from tests/codex-log-guard-doctor-coderabbit.test.ts rename to tests/codex-integration/codex-log-guard-doctor-coderabbit.test.ts index 036708d4a06..7dc0637afec 100644 --- a/tests/codex-log-guard-doctor-coderabbit.test.ts +++ b/tests/codex-integration/codex-log-guard-doctor-coderabbit.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { formatCodexLogGuardDoctor } from "../src/cli/codex-log-guard-doctor"; -import type { CodexLogGuardStatus } from "../src/codex/log-guard/protection"; +import { formatCodexLogGuardDoctor } from "../../src/cli/codex-log-guard-doctor"; +import type { CodexLogGuardStatus } from "../../src/codex/log-guard/protection"; function status(schema: CodexLogGuardStatus["schema"]): CodexLogGuardStatus { const supported = schema.state === "compatible"; diff --git a/tests/codex-log-guard-doctor-protection.test.ts b/tests/codex-integration/codex-log-guard-doctor-protection.test.ts similarity index 94% rename from tests/codex-log-guard-doctor-protection.test.ts rename to tests/codex-integration/codex-log-guard-doctor-protection.test.ts index 7d4c0d18d4e..43f1556bb82 100644 --- a/tests/codex-log-guard-doctor-protection.test.ts +++ b/tests/codex-integration/codex-log-guard-doctor-protection.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { formatCodexLogGuardDoctor, printCodexLogGuardDoctor } from "../src/cli/codex-log-guard-doctor"; -import type { CodexLogGuardStatus } from "../src/codex/log-guard/protection"; +import { formatCodexLogGuardDoctor, printCodexLogGuardDoctor } from "../../src/cli/codex-log-guard-doctor"; +import type { CodexLogGuardStatus } from "../../src/codex/log-guard/protection"; function status(state: CodexLogGuardStatus["protection"]): CodexLogGuardStatus { return { diff --git a/tests/codex-log-guard-doctor.test.ts b/tests/codex-integration/codex-log-guard-doctor.test.ts similarity index 97% rename from tests/codex-log-guard-doctor.test.ts rename to tests/codex-integration/codex-log-guard-doctor.test.ts index de9be399d0f..7a7c29188c7 100644 --- a/tests/codex-log-guard-doctor.test.ts +++ b/tests/codex-integration/codex-log-guard-doctor.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { formatCodexLogGuardDoctor, printCodexLogGuardDoctor } from "../src/cli/codex-log-guard-doctor"; -import type { CodexLogGuardInspection } from "../src/codex/log-guard/inspect"; +import { formatCodexLogGuardDoctor, printCodexLogGuardDoctor } from "../../src/cli/codex-log-guard-doctor"; +import type { CodexLogGuardInspection } from "../../src/codex/log-guard/inspect"; function report(overrides: Partial = {}): CodexLogGuardInspection { return { diff --git a/tests/codex-log-guard-inspect.test.ts b/tests/codex-integration/codex-log-guard-inspect.test.ts similarity index 99% rename from tests/codex-log-guard-inspect.test.ts rename to tests/codex-integration/codex-log-guard-inspect.test.ts index 3c3538eb51a..063a64a605f 100644 --- a/tests/codex-log-guard-inspect.test.ts +++ b/tests/codex-integration/codex-log-guard-inspect.test.ts @@ -14,8 +14,8 @@ import { import { tmpdir } from "node:os"; import { join } from "node:path"; -import { inspectCodexLogs, resetCodexLogGuardInspectionCache } from "../src/codex/log-guard/inspect"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { inspectCodexLogs, resetCodexLogGuardInspectionCache } from "../../src/codex/log-guard/inspect"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-log-guard-lock.test.ts b/tests/codex-integration/codex-log-guard-lock.test.ts similarity index 88% rename from tests/codex-log-guard-lock.test.ts rename to tests/codex-integration/codex-log-guard-lock.test.ts index bd7e1b7a2a8..c1f72ebf547 100644 --- a/tests/codex-log-guard-lock.test.ts +++ b/tests/codex-integration/codex-log-guard-lock.test.ts @@ -3,8 +3,8 @@ import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { withCodexLogGuardLock } from "../src/codex/log-guard/lock"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { withCodexLogGuardLock } from "../../src/codex/log-guard/lock"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-log-guard-maintenance-coderabbit.test.ts b/tests/codex-integration/codex-log-guard-maintenance-coderabbit.test.ts similarity index 98% rename from tests/codex-log-guard-maintenance-coderabbit.test.ts rename to tests/codex-integration/codex-log-guard-maintenance-coderabbit.test.ts index 32edb54706a..54e83bba2a6 100644 --- a/tests/codex-log-guard-maintenance-coderabbit.test.ts +++ b/tests/codex-integration/codex-log-guard-maintenance-coderabbit.test.ts @@ -13,8 +13,8 @@ import { join } from "node:path"; import { compactCodexLogs, type CodexLogGuardMaintenanceDeps, -} from "../src/codex/log-guard/maintenance"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/log-guard/maintenance"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-log-guard-maintenance.test.ts b/tests/codex-integration/codex-log-guard-maintenance.test.ts similarity index 91% rename from tests/codex-log-guard-maintenance.test.ts rename to tests/codex-integration/codex-log-guard-maintenance.test.ts index 53afbc43e1e..dfeec4194fe 100644 --- a/tests/codex-log-guard-maintenance.test.ts +++ b/tests/codex-integration/codex-log-guard-maintenance.test.ts @@ -3,7 +3,7 @@ import { Database } from "bun:sqlite"; import { mkdirSync, mkdtempSync, statSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; @@ -122,7 +122,7 @@ afterEach(() => { describe("Codex Log Guard reclaim", () => { test("incrementally reclaims freelist pages while preserving every logical row and trigger", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); expect(mod).not.toBeNull(); if (!mod) return; @@ -146,7 +146,7 @@ describe("Codex Log Guard reclaim", () => { }); test("is a safe no-op when there is nothing reclaimable", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); expect(mod).not.toBeNull(); if (!mod) return; @@ -159,7 +159,7 @@ describe("Codex Log Guard reclaim", () => { }); test("refuses databases that are not already auto_vacuum=INCREMENTAL", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); expect(mod).not.toBeNull(); if (!mod) return; @@ -175,7 +175,7 @@ describe("Codex Log Guard reclaim", () => { }); test("refuses unknown log schemas before maintenance", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); expect(mod).not.toBeNull(); if (!mod) return; @@ -191,7 +191,7 @@ describe("Codex Log Guard reclaim", () => { }); test("fails closed when Codex is running or process enumeration is uncertain", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); expect(mod).not.toBeNull(); if (!mod) return; @@ -208,7 +208,7 @@ describe("Codex Log Guard reclaim", () => { }); test("fails closed when the Log Guard lock is busy", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); expect(mod).not.toBeNull(); if (!mod) return; const { codexHome } = fixture(); @@ -218,7 +218,7 @@ describe("Codex Log Guard reclaim", () => { }); test("requires quick_check before changing any pages", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); expect(mod).not.toBeNull(); if (!mod) return; const { codexHome, databasePath } = fixture(); @@ -238,7 +238,7 @@ describe("Codex Log Guard reclaim", () => { }); test("reports a post-maintenance quick_check failure explicitly", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); expect(mod).not.toBeNull(); if (!mod) return; const { codexHome } = fixture(); @@ -256,7 +256,7 @@ describe("Codex Log Guard reclaim", () => { }); test("stops at the per-run page budget and reports remaining work", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); expect(mod).not.toBeNull(); if (!mod) return; const { codexHome } = fixture(); @@ -273,7 +273,7 @@ describe("Codex Log Guard reclaim", () => { expect(result.report.after.freelistPages).toBeGreaterThan(0); }); test("derives batch budgets from the real page size, not a fixed page count", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); if (!mod) return; // The guide promises ~8 MiB batches and ~256 MiB per run, converted with the // database's page size. Fixed page counts meant something different at every @@ -291,7 +291,7 @@ describe("Codex Log Guard reclaim", () => { }); test("reports logicalBytesReclaimed alongside the physical figure", async () => { - const mod = await import("../src/codex/log-guard/maintenance").catch(() => null); + const mod = await import("../../src/codex/log-guard/maintenance").catch(() => null); if (!mod) return; // Documented before it existed. It is deliberately distinct from the // physical figure: an incremental vacuum can return pages to the free list diff --git a/tests/codex-log-guard-policy.test.ts b/tests/codex-integration/codex-log-guard-policy.test.ts similarity index 93% rename from tests/codex-log-guard-policy.test.ts rename to tests/codex-integration/codex-log-guard-policy.test.ts index 3f76d3f59d9..5c85c7fd730 100644 --- a/tests/codex-log-guard-policy.test.ts +++ b/tests/codex-integration/codex-log-guard-policy.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { readCodexLogGuardMode, writeCodexLogGuardMode } from "../src/codex/log-guard/policy"; -import type { OcxConfig } from "../src/types"; +import { readCodexLogGuardMode, writeCodexLogGuardMode } from "../../src/codex/log-guard/policy"; +import type { OcxConfig } from "../../src/types"; describe("Codex Log Guard desired-state policy", () => { test("defaults missing or invalid modes to off", () => { diff --git a/tests/codex-log-guard-processes.test.ts b/tests/codex-integration/codex-log-guard-processes.test.ts similarity index 98% rename from tests/codex-log-guard-processes.test.ts rename to tests/codex-integration/codex-log-guard-processes.test.ts index b733a956c12..a2f42a07e9f 100644 --- a/tests/codex-log-guard-processes.test.ts +++ b/tests/codex-integration/codex-log-guard-processes.test.ts @@ -3,7 +3,7 @@ import { describe, expect, test } from "bun:test"; import { isCodexWriterCommandLine, listRunningCodexProcesses, -} from "../src/codex/log-guard/processes"; +} from "../../src/codex/log-guard/processes"; describe("Codex Log Guard process gate", () => { test("matches official Codex writer command lines without broad codex substring matching", () => { diff --git a/tests/codex-log-guard-protection.test.ts b/tests/codex-integration/codex-log-guard-protection.test.ts similarity index 99% rename from tests/codex-log-guard-protection.test.ts rename to tests/codex-integration/codex-log-guard-protection.test.ts index d9dec0cf7af..1b2deee7f3a 100644 --- a/tests/codex-log-guard-protection.test.ts +++ b/tests/codex-integration/codex-log-guard-protection.test.ts @@ -9,8 +9,8 @@ import { protectCodexLogs, repairCodexLogGuardProtection, unprotectCodexLogs, -} from "../src/codex/log-guard/protection"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/log-guard/protection"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-log-guard-status-zero-write.test.ts b/tests/codex-integration/codex-log-guard-status-zero-write.test.ts similarity index 96% rename from tests/codex-log-guard-status-zero-write.test.ts rename to tests/codex-integration/codex-log-guard-status-zero-write.test.ts index d11a7a104ae..615ecf128e7 100644 --- a/tests/codex-log-guard-status-zero-write.test.ts +++ b/tests/codex-integration/codex-log-guard-status-zero-write.test.ts @@ -4,8 +4,8 @@ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, statSync, wri import { tmpdir } from "node:os"; import { join } from "node:path"; -import { getCodexLogGuardProtectionStatus } from "../src/codex/log-guard/protection"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { getCodexLogGuardProtectionStatus } from "../../src/codex/log-guard/protection"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-main-account-refresh.test.ts b/tests/codex-integration/codex-main-account-refresh.test.ts similarity index 98% rename from tests/codex-main-account-refresh.test.ts rename to tests/codex-integration/codex-main-account-refresh.test.ts index d60beb0fb0a..d1ae3807955 100644 --- a/tests/codex-main-account-refresh.test.ts +++ b/tests/codex-integration/codex-main-account-refresh.test.ts @@ -5,9 +5,9 @@ import { join } from "node:path"; import { getValidMainAccountToken, setMainAuthJsonBeforeRenameHookForTests, -} from "../src/codex/main-account"; -import { codexCredentialMutationEpoch } from "../src/codex/credential-mutation-epoch"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/main-account"; +import { codexCredentialMutationEpoch } from "../../src/codex/credential-mutation-epoch"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let home: string; let previousCodexHome: string | undefined; diff --git a/tests/codex-main-rotation.test.ts b/tests/codex-integration/codex-main-rotation.test.ts similarity index 97% rename from tests/codex-main-rotation.test.ts rename to tests/codex-integration/codex-main-rotation.test.ts index 9f596da5a9a..d8fa96db864 100644 --- a/tests/codex-main-rotation.test.ts +++ b/tests/codex-integration/codex-main-rotation.test.ts @@ -9,20 +9,20 @@ import { pickLowestUsageCodexAccount, recordCodexUpstreamOutcome, resolveCodexAccountForThread, -} from "../src/codex/routing"; +} from "../../src/codex/routing"; import { CodexPoolAuthenticationError, headersForCodexAuthContext, isCodexAuthContextUsable, resolveCodexAuthContext, -} from "../src/codex/auth-context"; -import { isCodexAccountUsable } from "../src/codex/account-usability"; +} from "../../src/codex/auth-context"; +import { isCodexAccountUsable } from "../../src/codex/account-usability"; import { reconcileMainCodexAccountRuntimeState, resetMainCodexAccountIdentityTrackingForTests, -} from "../src/codex/account-lifecycle"; -import { MAIN_CODEX_ACCOUNT_ID, setMainAccountPlan } from "../src/codex/main-account"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; +} from "../../src/codex/account-lifecycle"; +import { MAIN_CODEX_ACCOUNT_ID, setMainAccountPlan } from "../../src/codex/main-account"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; import { clearAccountNeedsReauth, clearAccountQuota, @@ -33,9 +33,9 @@ import { markAccountNeedsReauth, primeCodexPoolQuotas, updateAccountQuota, -} from "../src/codex/auth-api"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/auth-api"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const STORE_DIR = join(import.meta.dir, ".tmp-main-rotation-store"); const CODEX_DIR = join(import.meta.dir, ".tmp-main-rotation-codex"); diff --git a/tests/codex-management-convergence.test.ts b/tests/codex-integration/codex-management-convergence.test.ts similarity index 95% rename from tests/codex-management-convergence.test.ts rename to tests/codex-integration/codex-management-convergence.test.ts index 6f9df06da16..69a43034823 100644 --- a/tests/codex-management-convergence.test.ts +++ b/tests/codex-integration/codex-management-convergence.test.ts @@ -1,12 +1,12 @@ import { expect, test } from "bun:test"; -import { createCatalogConvergeRequest } from "../src/codex/catalog-admission"; +import { createCatalogConvergeRequest } from "../../src/codex/catalog-admission"; import { createManagementConvergeCodex, projectCatalogOnlyOutcome, -} from "../src/codex/management-convergence"; -import type { CatalogDisposition } from "../src/codex/convergence-types"; -import type { OcxConfig } from "../src/types"; +} from "../../src/codex/management-convergence"; +import type { CatalogDisposition } from "../../src/codex/convergence-types"; +import type { OcxConfig } from "../../src/types"; function config(): OcxConfig { return { port: 10100, providers: {}, defaultProvider: "openai" }; diff --git a/tests/codex-metadata-integrity.test.ts b/tests/codex-integration/codex-metadata-integrity.test.ts similarity index 95% rename from tests/codex-metadata-integrity.test.ts rename to tests/codex-integration/codex-metadata-integrity.test.ts index 4182770d38e..79cdeea2500 100644 --- a/tests/codex-metadata-integrity.test.ts +++ b/tests/codex-integration/codex-metadata-integrity.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { FORWARD_HEADERS, createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../src/adapters/openai-responses"; -import { headersForCodexAuthContext } from "../src/codex/auth-context"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { FORWARD_HEADERS, createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../../src/adapters/openai-responses"; +import { headersForCodexAuthContext } from "../../src/codex/auth-context"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; const createResponsesPassthroughAdapter = (...args: Parameters) => withTestTranslatorBudget(createResponsesPassthroughAdapterProduction(...args)); diff --git a/tests/codex-model-entitlements.test.ts b/tests/codex-integration/codex-model-entitlements.test.ts similarity index 99% rename from tests/codex-model-entitlements.test.ts rename to tests/codex-integration/codex-model-entitlements.test.ts index 9ca38fb9a55..219ec7dcc81 100644 --- a/tests/codex-model-entitlements.test.ts +++ b/tests/codex-integration/codex-model-entitlements.test.ts @@ -24,21 +24,21 @@ import { seedCodexModelEntitlementsForTests, type CodexModelEntitlementCredentialSnapshot, type CodexModelEntitlementState, -} from "../src/codex/model-entitlements"; +} from "../../src/codex/model-entitlements"; import { forceRefreshMainAccountToken, MAIN_CODEX_ACCOUNT_ID, -} from "../src/codex/main-account"; +} from "../../src/codex/main-account"; import { readCodexAccountRecord, saveCodexAccountCredential, -} from "../src/codex/account-store"; -import { clearCodexRuntimeResolveCache, loadPersistedCodexRuntime } from "../src/codex/runtime"; -import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../src/codex/catalog/native-models"; -import upstreamModelsSnapshot from "../src/codex/data/upstream-models.json"; -import { readCodexAccountRecord, saveCodexAccountCredential } from "../src/codex/account-store"; -import { installIsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/account-store"; +import { clearCodexRuntimeResolveCache, loadPersistedCodexRuntime } from "../../src/codex/runtime"; +import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../../src/codex/catalog/native-models"; +import upstreamModelsSnapshot from "../../src/codex/data/upstream-models.json"; +import { readCodexAccountRecord, saveCodexAccountCredential } from "../../src/codex/account-store"; +import { installIsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_CLIENT_VERSION = "0.146.0"; const DAYBREAK = "gpt-daybreak-blue-latest"; @@ -1084,7 +1084,7 @@ describe("entitlement client version (#2886)", () => { // been resolved, no persisted runtime either — yet it is the path that publishes // account-confirmed native rows. An earlier revision of this fix skipped discovery in // that state, which suppressed exactly the rows the fix exists to restore - // (tests/claude-integration/claude-models-discovery.test.ts and tests/codex-catalog-sync-hardening.test.ts + // (tests/claude-integration/claude-models-discovery.test.ts and tests/codex-integration/codex-catalog-sync-hardening.test.ts // both failed on it). The last tier therefore has to be a real, answerable version. expect(resolveCodexEntitlementClientVersion(null, () => null)) .toBe(GATED_MODEL_CLIENT_VERSION_FLOOR); diff --git a/tests/codex-models-cache-invalidate.test.ts b/tests/codex-integration/codex-models-cache-invalidate.test.ts similarity index 95% rename from tests/codex-models-cache-invalidate.test.ts rename to tests/codex-integration/codex-models-cache-invalidate.test.ts index cd222a8f51d..3efb3165118 100644 --- a/tests/codex-models-cache-invalidate.test.ts +++ b/tests/codex-integration/codex-models-cache-invalidate.test.ts @@ -2,14 +2,14 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { invalidateCodexModelsCache } from "../src/codex/catalog"; -import { invalidateCodexModelsCacheWithPermit } from "../src/codex/catalog/sync"; -import { withCatalogWriteSerialization } from "../src/codex/catalog-write-serialization"; -import { afterCatalogWriteHandleAppServers } from "../src/codex/app-server-processes"; -import { refreshCodexModelCatalog } from "../src/codex/refresh"; -import { syncModelsToCodex } from "../src/codex/sync"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { invalidateCodexModelsCache } from "../../src/codex/catalog"; +import { invalidateCodexModelsCacheWithPermit } from "../../src/codex/catalog/sync"; +import { withCatalogWriteSerialization } from "../../src/codex/catalog-write-serialization"; +import { afterCatalogWriteHandleAppServers } from "../../src/codex/app-server-processes"; +import { refreshCodexModelCatalog } from "../../src/codex/refresh"; +import { syncModelsToCodex } from "../../src/codex/sync"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const emptyConfig = { port: 10100, diff --git a/tests/codex-native-residue.test.ts b/tests/codex-integration/codex-native-residue.test.ts similarity index 98% rename from tests/codex-native-residue.test.ts rename to tests/codex-integration/codex-native-residue.test.ts index 61b9759355e..07dcffe46aa 100644 --- a/tests/codex-native-residue.test.ts +++ b/tests/codex-integration/codex-native-residue.test.ts @@ -21,17 +21,17 @@ import { buildCatalogEntries, readCodexCatalogPath, syncCatalogModels, -} from "../src/codex/catalog"; -import { buildProfileFile } from "../src/codex/inject"; -import { classifyNativeRoutedResidue } from "../src/codex/native-residue"; -import { readCodexTransitionState } from "../src/codex/transition-state"; +} from "../../src/codex/catalog"; +import { buildProfileFile } from "../../src/codex/inject"; +import { classifyNativeRoutedResidue } from "../../src/codex/native-residue"; +import { readCodexTransitionState } from "../../src/codex/transition-state"; import { resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import type { OcxConfig } from "../src/types"; -import { INVALID_HISTORY_BACKUP_FIXTURES, validHistoryBackupFixture } from "./helpers/codex-history-manifest-fixtures"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/user-identity"; +import type { OcxConfig } from "../../src/types"; +import { INVALID_HISTORY_BACKUP_FIXTURES, validHistoryBackupFixture } from "../helpers/codex-history-manifest-fixtures"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let codexHome = ""; let opencodexHome = ""; diff --git a/tests/codex-plan.test.ts b/tests/codex-integration/codex-plan.test.ts similarity index 95% rename from tests/codex-plan.test.ts rename to tests/codex-integration/codex-plan.test.ts index c4bf31fa2ce..df02a8167e0 100644 --- a/tests/codex-plan.test.ts +++ b/tests/codex-integration/codex-plan.test.ts @@ -1,16 +1,16 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, writeFileSync } from "node:fs"; import { join } from "node:path"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { getMainAccountPlan, setMainAccountPlan } from "../src/codex/main-account"; -import { extractChatgptPlanType } from "../src/codex/plan"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { getMainAccountPlan, setMainAccountPlan } from "../../src/codex/main-account"; +import { extractChatgptPlanType } from "../../src/codex/plan"; import { reconcileCodexPlansFromTokens, resetJwtPlanNotesForTests, -} from "../src/codex/plan-from-token"; -import { loadConfig, saveConfig } from "../src/config"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/plan-from-token"; +import { loadConfig, saveConfig } from "../../src/config"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-codex-plan-test"); const TEST_CODEX_HOME = join(TEST_DIR, "codex"); @@ -202,7 +202,7 @@ describe("WHAM-wins plan provenance gate (release-audit fix)", () => { describe("rotated-JWT plan reconciliation across propagated aliases (#2892 gap 3)", () => { test("a plan-changing rotated JWT reconciles the alias, not just the refresh owner", async () => { - const { getValidCodexToken, readCodexAccountRecord } = await import("../src/codex/account-store"); + const { getValidCodexToken, readCodexAccountRecord } = await import("../../src/codex/account-store"); const oldJwt = chatgptPlanJwt("plus"); const shared = { refreshToken: "plan-grant", expiresAt: 0, chatgptAccountId: "acct" }; saveCodexAccountCredential("plan-owner", { accessToken: oldJwt, ...shared }); diff --git a/tests/codex-plugins-doctor.test.ts b/tests/codex-integration/codex-plugins-doctor.test.ts similarity index 98% rename from tests/codex-plugins-doctor.test.ts rename to tests/codex-integration/codex-plugins-doctor.test.ts index 939d31c7830..ce47b8c4c5c 100644 --- a/tests/codex-plugins-doctor.test.ts +++ b/tests/codex-integration/codex-plugins-doctor.test.ts @@ -4,10 +4,10 @@ import { mkdtempSync, mkdirSync, readdirSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import { diagnoseCodexBundledPlugins, locateCurrentBundledMarketplace } from "../src/codex/plugins-doctor"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { diagnoseCodexBundledPlugins, locateCurrentBundledMarketplace } from "../../src/codex/plugins-doctor"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); const cliPath = join(repoRoot, "src", "cli", "index.ts"); function makeConfig(body: string): { dir: string; configPath: string } { diff --git a/tests/codex-pool-rotation.test.ts b/tests/codex-integration/codex-pool-rotation.test.ts similarity index 98% rename from tests/codex-pool-rotation.test.ts rename to tests/codex-integration/codex-pool-rotation.test.ts index 5fed0251e03..1a69a0e2698 100644 --- a/tests/codex-pool-rotation.test.ts +++ b/tests/codex-integration/codex-pool-rotation.test.ts @@ -7,14 +7,14 @@ import { peekRoundRobinAccount, pickRoundRobinAccount, selectPriorityTier, -} from "../src/codex/pool-rotation"; +} from "../../src/codex/pool-rotation"; import { clearCodexAccountPin, codexAccountPriorityLookup, forgetCodexAccountPriority, getCodexAccountPriority, setCodexAccountPriority, -} from "../src/codex/account-priority"; +} from "../../src/codex/account-priority"; import { clearCodexUpstreamHealth, clearThreadAccountMap, @@ -26,16 +26,16 @@ import { recordCodexUpstreamOutcome, resetCodexRoutingForManualSelection, resolveCodexAccountForThread, -} from "../src/codex/routing"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/account-id"; -import { clearAccountQuota, updateAccountQuota } from "../src/codex/auth-api"; -import { getConfigPath } from "../src/config"; -import type { OcxConfig } from "../src/types"; +} from "../../src/codex/routing"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/account-id"; +import { clearAccountQuota, updateAccountQuota } from "../../src/codex/auth-api"; +import { getConfigPath } from "../../src/config"; +import type { OcxConfig } from "../../src/types"; import { existsSync, mkdirSync, rmSync } from "node:fs"; import { join } from "node:path"; import { describe, expect, test, beforeEach, afterEach } from "bun:test"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-codex-pool-rotation-test"); let previousOpencodexHome: string | undefined; diff --git a/tests/codex-prompt-adopt.test.ts b/tests/codex-integration/codex-prompt-adopt.test.ts similarity index 98% rename from tests/codex-prompt-adopt.test.ts rename to tests/codex-integration/codex-prompt-adopt.test.ts index f750a8f10cd..7bffd6dedce 100644 --- a/tests/codex-prompt-adopt.test.ts +++ b/tests/codex-integration/codex-prompt-adopt.test.ts @@ -16,8 +16,8 @@ import { previewSalvage, readPromptLayers, salvageProjection, -} from "../src/codex/prompt-layers"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/prompt-layers"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const MARKER = "# Auto-injected by opencodex"; const roots: string[] = []; diff --git a/tests/codex-prompt-base-variants.test.ts b/tests/codex-integration/codex-prompt-base-variants.test.ts similarity index 98% rename from tests/codex-prompt-base-variants.test.ts rename to tests/codex-integration/codex-prompt-base-variants.test.ts index 935c75d9ec3..e80be5391e2 100644 --- a/tests/codex-prompt-base-variants.test.ts +++ b/tests/codex-integration/codex-prompt-base-variants.test.ts @@ -13,8 +13,8 @@ import { readPromptLayers, selectBaseVariant, writeBaseVariant, -} from "../src/codex/prompt-layers"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/prompt-layers"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-prompt-journal.test.ts b/tests/codex-integration/codex-prompt-journal.test.ts similarity index 98% rename from tests/codex-prompt-journal.test.ts rename to tests/codex-integration/codex-prompt-journal.test.ts index 3d04f1e24d9..7034c6da060 100644 --- a/tests/codex-prompt-journal.test.ts +++ b/tests/codex-integration/codex-prompt-journal.test.ts @@ -19,14 +19,14 @@ import { recoverIfNeeded, sameRecoveryPath, type JournalRecord, -} from "../src/codex/prompt-journal"; +} from "../../src/codex/prompt-journal"; import { hardenedSecretPathCountForTests, resetHardenedStateForTests, setIcaclsRunnerForTests, setPlatformForTests, -} from "../src/lib/windows-secret-acl"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/lib/windows-secret-acl"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-prompt-layers-read.test.ts b/tests/codex-integration/codex-prompt-layers-read.test.ts similarity index 98% rename from tests/codex-prompt-layers-read.test.ts rename to tests/codex-integration/codex-prompt-layers-read.test.ts index 54af244f7d7..7d74628d494 100644 --- a/tests/codex-prompt-layers-read.test.ts +++ b/tests/codex-integration/codex-prompt-layers-read.test.ts @@ -13,8 +13,8 @@ import { inspectOwnership, parseStore, readPromptLayers, -} from "../src/codex/prompt-layers"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/prompt-layers"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const MARKER = "# Auto-injected by opencodex"; const roots: string[] = []; diff --git a/tests/codex-prompt-layers-write.test.ts b/tests/codex-integration/codex-prompt-layers-write.test.ts similarity index 99% rename from tests/codex-prompt-layers-write.test.ts rename to tests/codex-integration/codex-prompt-layers-write.test.ts index 103ba9496c7..09c7d6da093 100644 --- a/tests/codex-prompt-layers-write.test.ts +++ b/tests/codex-integration/codex-prompt-layers-write.test.ts @@ -12,13 +12,13 @@ import { setToggle, writeCustomLayers, type CustomLayer, -} from "../src/codex/prompt-layers"; +} from "../../src/codex/prompt-layers"; import { encodeJournal, hashBytes, type JournalRecord, -} from "../src/codex/prompt-journal"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/prompt-journal"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const MARKER = "# Auto-injected by opencodex"; const roots: string[] = []; diff --git a/tests/codex-prompt-layers.test.ts b/tests/codex-integration/codex-prompt-layers.test.ts similarity index 99% rename from tests/codex-prompt-layers.test.ts rename to tests/codex-integration/codex-prompt-layers.test.ts index 64e715ab264..fa95b7c3df6 100644 --- a/tests/codex-prompt-layers.test.ts +++ b/tests/codex-integration/codex-prompt-layers.test.ts @@ -17,7 +17,7 @@ import { findInvalidCharacter, isToggleId, normalizeBody, -} from "../src/codex/prompt-layers"; +} from "../../src/codex/prompt-layers"; /** TOML basic-string grammar, hand-written so it does not share code with the encoder. */ const BASIC_STRING = /^"(?:[^"\\\u0000-\u001f]|\\["\\bfnrt]|\\u[0-9A-Fa-f]{4})*"$/; diff --git a/tests/codex-prompt-lock.test.ts b/tests/codex-integration/codex-prompt-lock.test.ts similarity index 98% rename from tests/codex-prompt-lock.test.ts rename to tests/codex-integration/codex-prompt-lock.test.ts index dcd9d46cd39..b2ff4741a32 100644 --- a/tests/codex-prompt-lock.test.ts +++ b/tests/codex-integration/codex-prompt-lock.test.ts @@ -17,8 +17,8 @@ import { stillHeld, tryAcquire, type LockDeps, -} from "../src/codex/prompt-lock"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/prompt-lock"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/codex-prompt-route.test.ts b/tests/codex-integration/codex-prompt-route.test.ts similarity index 98% rename from tests/codex-prompt-route.test.ts rename to tests/codex-integration/codex-prompt-route.test.ts index 8b13007b337..f69dd8ea2d8 100644 --- a/tests/codex-prompt-route.test.ts +++ b/tests/codex-integration/codex-prompt-route.test.ts @@ -10,16 +10,16 @@ import { afterEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; -import { handleManagementAPI } from "../src/server/management-api"; -import { LAYER_INVENTORY, readPromptLayers } from "../src/codex/prompt-layers"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { LAYER_INVENTORY, readPromptLayers } from "../../src/codex/prompt-layers"; import { promptTextProbeSpawnAttemptsForTests, resetPromptTextProbeForTests, setPromptTextProbeCommandForTests, -} from "../src/codex/prompt-text-probe"; -import type { ManagementPrincipal } from "../src/server/management-auth"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/prompt-text-probe"; +import type { ManagementPrincipal } from "../../src/server/management-auth"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const MARKER = "# Auto-injected by opencodex"; const config = { port: 10100, defaultProvider: "openai", providers: {} } as OcxConfig; @@ -470,7 +470,7 @@ describe("dispatch and safety", () => { test("20. every mapped write error carries a client-facing status", async () => { // A TypeScript union does not exist at runtime, so exhaustiveness is a // typecheck property of Record. This asserts the values. - const { WRITE_ERROR_STATUS_FOR_TESTS } = await import("../src/server/management/codex-prompt-routes"); + const { WRITE_ERROR_STATUS_FOR_TESTS } = await import("../../src/server/management/codex-prompt-routes"); const statuses = Object.values(WRITE_ERROR_STATUS_FOR_TESTS); expect(statuses.length).toBeGreaterThanOrEqual(10); for (const status of statuses) expect(status).toBeGreaterThanOrEqual(400); @@ -598,7 +598,7 @@ describe("020 coverage completions", () => { test("20d. each write error keeps its exact status, not merely a 4xx", async () => { // A range assertion would still pass if unknown_layer silently became a 409. - const { WRITE_ERROR_STATUS_FOR_TESTS } = await import("../src/server/management/codex-prompt-routes"); + const { WRITE_ERROR_STATUS_FOR_TESTS } = await import("../../src/server/management/codex-prompt-routes"); expect(WRITE_ERROR_STATUS_FOR_TESTS).toEqual({ config_unreadable: 409, stale_revision: 409, @@ -803,12 +803,12 @@ describe("020 coverage completions", () => { // A cwd parameter let an authenticated request read any readable folder's // AGENTS.md through the dashboard, and described a prompt from wherever the // caller pointed rather than the configuration this page reports on. - const source = await Bun.file(new URL("../src/server/management/codex-prompt-routes.ts", import.meta.url)).text(); + const source = await Bun.file(new URL("../../src/server/management/codex-prompt-routes.ts", import.meta.url)).text(); const textRoute = source.slice(source.indexOf("/api/codex-prompt/text")); expect(textRoute).not.toContain("searchParams.get(\"cwd\")"); expect(textRoute.slice(0, 900)).not.toContain("process.cwd()"); - const probe = await Bun.file(new URL("../src/codex/prompt-text-probe.ts", import.meta.url)).text(); + const probe = await Bun.file(new URL("../../src/codex/prompt-text-probe.ts", import.meta.url)).text(); // The probe resolves CODEX_HOME itself; it must not accept a directory. expect(probe).toContain("resolveCodexHomeDir()"); expect(probe).toMatch(/export async function probePromptText\(\s*timeoutMs/); @@ -817,7 +817,7 @@ describe("020 coverage completions", () => { test("26. the probe is bounded in bytes as well as in time", async () => { // A 15-second window with no output ceiling let a noisy binary balloon the // server. Both bounds must exist, and the process must settle exactly once. - const probe = await Bun.file(new URL("../src/codex/prompt-text-probe.ts", import.meta.url)).text(); + const probe = await Bun.file(new URL("../../src/codex/prompt-text-probe.ts", import.meta.url)).text(); expect(probe).toContain("MAX_PROBE_OUTPUT_BYTES"); expect(probe).toContain("if (settled) return;"); // Decoding per chunk corrupts UTF-8 that straddles a chunk boundary. diff --git a/tests/codex-prompt-text-probe.test.ts b/tests/codex-integration/codex-prompt-text-probe.test.ts similarity index 99% rename from tests/codex-prompt-text-probe.test.ts rename to tests/codex-integration/codex-prompt-text-probe.test.ts index cf3252543b9..f9c70e1729a 100644 --- a/tests/codex-prompt-text-probe.test.ts +++ b/tests/codex-integration/codex-prompt-text-probe.test.ts @@ -17,8 +17,8 @@ import { resetPromptTextProbeForTests, setPromptTextProbeCloseBarrierForTests, setPromptTextProbeCommandForTests, -} from "../src/codex/prompt-text-probe"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/prompt-text-probe"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const lifecycleRoots: string[] = []; const VALID_PROBE_OUTPUT = JSON.stringify([{ diff --git a/tests/codex-quota-parser-parity.test.ts b/tests/codex-integration/codex-quota-parser-parity.test.ts similarity index 98% rename from tests/codex-quota-parser-parity.test.ts rename to tests/codex-integration/codex-quota-parser-parity.test.ts index 1f909f4f4e2..172168ada88 100644 --- a/tests/codex-quota-parser-parity.test.ts +++ b/tests/codex-integration/codex-quota-parser-parity.test.ts @@ -4,8 +4,8 @@ import { parseUpstreamQuotaHeaders, parseUsageQuota, setAccountQuotaFromParsed, -} from "../src/codex/quota"; -import { codexPoolQuotaEvidence } from "../src/routing/quota"; +} from "../../src/codex/quota"; +import { codexPoolQuotaEvidence } from "../../src/routing/quota"; /** * The two quota parsers, pinned against each other. diff --git a/tests/codex-quota-prime.test.ts b/tests/codex-integration/codex-quota-prime.test.ts similarity index 98% rename from tests/codex-quota-prime.test.ts rename to tests/codex-integration/codex-quota-prime.test.ts index 2e2f4469458..94a605d5f27 100644 --- a/tests/codex-quota-prime.test.ts +++ b/tests/codex-integration/codex-quota-prime.test.ts @@ -11,29 +11,29 @@ import { clearMainAccountInfoCache, seedCodexAuthAdmissionForTests, setCodexPoolQuotaTokenResolverForTests, -} from "../src/codex/auth-api"; +} from "../../src/codex/auth-api"; import { CodexCredentialGenerationConflictError, CodexCredentialRefreshLockTimeoutError, readCodexAccountRecord, saveCodexAccountCredential, -} from "../src/codex/account-store"; -import { resetMainCodexAccountIdentityTrackingForTests } from "../src/codex/account-lifecycle"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/main-account"; +} from "../../src/codex/account-store"; +import { resetMainCodexAccountIdentityTrackingForTests } from "../../src/codex/account-lifecycle"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/main-account"; import { completeNativeMainRecovery, initializeNativeMainStartupGate, -} from "../src/codex/native-profile-startup"; -import { handleNativeProfileAPI } from "../src/codex/native-profile-api"; -import type { NativeProfileManager } from "../src/codex/native-profile-manager"; -import { resolveCodexAccountForThread, clearThreadAccountMap } from "../src/codex/routing"; +} from "../../src/codex/native-profile-startup"; +import { handleNativeProfileAPI } from "../../src/codex/native-profile-api"; +import type { NativeProfileManager } from "../../src/codex/native-profile-manager"; +import { resolveCodexAccountForThread, clearThreadAccountMap } from "../../src/codex/routing"; import { acquireNativeMainProfileDrain, getNativeMainProfileRequestCount, resetLifecycleDrainStateForTests, -} from "../src/server/lifecycle"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/server/lifecycle"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; // Phase 20 (260630_wsl-account-autoswitch): startup/lazy quota priming. diff --git a/tests/codex-quota-rejection.test.ts b/tests/codex-integration/codex-quota-rejection.test.ts similarity index 98% rename from tests/codex-quota-rejection.test.ts rename to tests/codex-integration/codex-quota-rejection.test.ts index 7cf0310c018..1183cac6070 100644 --- a/tests/codex-quota-rejection.test.ts +++ b/tests/codex-integration/codex-quota-rejection.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { classifyCodexPreStreamRejection } from "../src/codex/quota-rejection"; -import { BOUNDED_BODY_MAX_BYTES } from "../src/lib/bounded-body"; -import { shouldRetryCodexPoolAccountQuota } from "../src/server/responses/core"; +import { classifyCodexPreStreamRejection } from "../../src/codex/quota-rejection"; +import { BOUNDED_BODY_MAX_BYTES } from "../../src/lib/bounded-body"; +import { shouldRetryCodexPoolAccountQuota } from "../../src/server/responses/core"; function jsonRejection(status: number, error: Record): Response { return Response.json({ error }, { status }); diff --git a/tests/codex-refresh.test.ts b/tests/codex-integration/codex-refresh.test.ts similarity index 97% rename from tests/codex-refresh.test.ts rename to tests/codex-integration/codex-refresh.test.ts index 4000eb9e7cd..d31add73cad 100644 --- a/tests/codex-refresh.test.ts +++ b/tests/codex-integration/codex-refresh.test.ts @@ -2,10 +2,10 @@ import { afterEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { invalidateCodexModelsCache, syncCatalogModels } from "../src/codex/catalog"; -import { refreshCodexModelCatalog } from "../src/codex/refresh"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { invalidateCodexModelsCache, syncCatalogModels } from "../../src/codex/catalog"; +import { refreshCodexModelCatalog } from "../../src/codex/refresh"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const config = { port: 10100, diff --git a/tests/codex-reset-credit-auto-redeem.test.ts b/tests/codex-integration/codex-reset-credit-auto-redeem.test.ts similarity index 98% rename from tests/codex-reset-credit-auto-redeem.test.ts rename to tests/codex-integration/codex-reset-credit-auto-redeem.test.ts index 21f651eef92..f19f208cc1d 100644 --- a/tests/codex-reset-credit-auto-redeem.test.ts +++ b/tests/codex-integration/codex-reset-credit-auto-redeem.test.ts @@ -7,8 +7,8 @@ import { planAutoRedeem, resolveResetCreditAutoRedeemSettings, type ResetCredit, -} from "../src/codex/reset-credit-auto-redeem"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/reset-credit-auto-redeem"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const T0 = Date.parse("2026-09-02T10:00:00Z"); const MIN = 60_000; diff --git a/tests/codex-reset-credit-operation-ledger.test.ts b/tests/codex-integration/codex-reset-credit-operation-ledger.test.ts similarity index 99% rename from tests/codex-reset-credit-operation-ledger.test.ts rename to tests/codex-integration/codex-reset-credit-operation-ledger.test.ts index e5eaf39ac66..d47c3cdc970 100644 --- a/tests/codex-reset-credit-operation-ledger.test.ts +++ b/tests/codex-integration/codex-reset-credit-operation-ledger.test.ts @@ -8,8 +8,8 @@ import { NestedConfigMutationError, prepareConfigMutationDatabasePathForWrite, withConfigMutationLockSync, -} from "../src/config"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/account-id"; +} from "../../src/config"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/account-id"; import { MAX_MANUAL_RESET_CREDIT_OPERATION_IDS, MAX_RESET_CREDIT_OPERATION_ACCOUNTS, @@ -21,12 +21,13 @@ import { settleManualResetCreditOperation, settleResetCreditOperation, type ManualResetCreditOperationIdentity, -} from "../src/codex/reset-credit-operation-ledger"; +} from "../../src/codex/reset-credit-operation-ledger"; import { compareCodexResetCreditRecoveryGenerationOrder, isCodexResetCreditOperationId, type CodexResetCreditRecoveryGeneration, -} from "../src/codex/reset-credit-recovery"; +} from "../../src/codex/reset-credit-recovery"; +import { repoRoot } from "../helpers/repo-root"; const GENERATION: CodexResetCreditRecoveryGeneration = { accountId: "pool-a", @@ -1192,7 +1193,7 @@ describe("Codex reset-credit operation ledger", () => { writeFileSync(process.env.OCX_LEDGER_READY_PATH, "ready"); while (true) Bun.sleepSync(50); `], { - cwd: join(import.meta.dir, ".."), + cwd: repoRoot(), env: { ...process.env, OCX_LEDGER_DB_PATH: databasePath(), diff --git a/tests/codex-reset-credit-recovery.test.ts b/tests/codex-integration/codex-reset-credit-recovery.test.ts similarity index 99% rename from tests/codex-reset-credit-recovery.test.ts rename to tests/codex-integration/codex-reset-credit-recovery.test.ts index d26f8ec9ade..27919163a71 100644 --- a/tests/codex-reset-credit-recovery.test.ts +++ b/tests/codex-integration/codex-reset-credit-recovery.test.ts @@ -11,8 +11,8 @@ import { type CodexResetCreditRecoveryDependencies, type CodexResetCreditRecoveryGeneration, type CodexResetCreditRevalidationResult, -} from "../src/codex/reset-credit-recovery"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/account-id"; +} from "../../src/codex/reset-credit-recovery"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/account-id"; const BASE_GENERATION: CodexResetCreditRecoveryGeneration = { accountId: "account-a", diff --git a/tests/codex-restart-contract-parity.test.ts b/tests/codex-integration/codex-restart-contract-parity.test.ts similarity index 97% rename from tests/codex-restart-contract-parity.test.ts rename to tests/codex-integration/codex-restart-contract-parity.test.ts index 0545c9395b5..cb9435c32c7 100644 --- a/tests/codex-restart-contract-parity.test.ts +++ b/tests/codex-integration/codex-restart-contract-parity.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { performCodexRestart, resetCodexRestartInFlightForTests } from "../src/codex/app-server-restart-service"; -import { isCodexRestartResponse } from "../src/lib/codex-restart-contract"; +import { performCodexRestart, resetCodexRestartInFlightForTests } from "../../src/codex/app-server-restart-service"; +import { isCodexRestartResponse } from "../../src/lib/codex-restart-contract"; /** * The GUI rejects a response that fails isCodexRestartResponse, so an invariant diff --git a/tests/codex-restart-route.test.ts b/tests/codex-integration/codex-restart-route.test.ts similarity index 92% rename from tests/codex-restart-route.test.ts rename to tests/codex-integration/codex-restart-route.test.ts index 94351c47132..f917c83a331 100644 --- a/tests/codex-restart-route.test.ts +++ b/tests/codex-integration/codex-restart-route.test.ts @@ -3,24 +3,24 @@ * * The service seam is injected through ManagementApiDeps so this suite never * enumerates or signals a real process. Service-level branch coverage lives in - * tests/codex-app-server-restart-service.test.ts. + * tests/codex-integration/codex-app-server-restart-service.test.ts. * * Plan: devlog/_fin/260815_gui_codex_restart/010_phase1_backend_endpoint.md */ import { describe, expect, test } from "bun:test"; -import { handleSystemRoutes } from "../src/server/management/system-routes"; -import type { ManagementContext } from "../src/server/management/context"; +import { handleSystemRoutes } from "../../src/server/management/system-routes"; +import type { ManagementContext } from "../../src/server/management/context"; import { CODEX_APP_SERVER_STATE_PATH, CODEX_RESTART_PATH, isCodexAppServerStateResponse, isCodexRestartResponse, -} from "../src/lib/codex-restart-contract"; +} from "../../src/lib/codex-restart-contract"; import type { CodexAppServerStateResponse, CodexRestartResponse, -} from "../src/lib/codex-restart-contract"; -import { loadConfig } from "../src/config"; +} from "../../src/lib/codex-restart-contract"; +import { loadConfig } from "../../src/config"; const STOPPED: CodexRestartResponse = { success: true, diff --git a/tests/codex-restore-app-rewrite.test.ts b/tests/codex-integration/codex-restore-app-rewrite.test.ts similarity index 98% rename from tests/codex-restore-app-rewrite.test.ts rename to tests/codex-integration/codex-restore-app-rewrite.test.ts index af24378a254..d81324960ae 100644 --- a/tests/codex-restore-app-rewrite.test.ts +++ b/tests/codex-integration/codex-restore-app-rewrite.test.ts @@ -4,7 +4,7 @@ import { spawnSync } from "node:child_process"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * #1798: the Codex app rewrites config.toml AFTER injection, so the journal's @@ -18,7 +18,7 @@ import { removeTreeWithRetry } from "./helpers/remove-tree"; * reserializer would (values kept, comments gone), then restore. */ -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); /** Inject, simulate the app's comment-dropping rewrite, then restore. */ const INJECT_REWRITE_RESTORE = [ diff --git a/tests/codex-retained-root-serialization.test.ts b/tests/codex-integration/codex-retained-root-serialization.test.ts similarity index 99% rename from tests/codex-retained-root-serialization.test.ts rename to tests/codex-integration/codex-retained-root-serialization.test.ts index 5befb5b73c1..b0c56bffbfb 100644 --- a/tests/codex-retained-root-serialization.test.ts +++ b/tests/codex-integration/codex-retained-root-serialization.test.ts @@ -15,11 +15,12 @@ import { join, resolve } from "node:path"; import { resolveCodexCatalogSerializationDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import { claimOwnedServiceHome, withOwnedServiceHomePreload } from "./helpers/owned-service-home"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/user-identity"; +import { claimOwnedServiceHome, withOwnedServiceHomePreload } from "../helpers/owned-service-home"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; -const repoRoot = resolve(import.meta.dir, ".."); +const repoRoot = resolveRepoRoot(); const sandboxes: Sandbox[] = []; interface Sandbox { diff --git a/tests/codex-routing.test.ts b/tests/codex-integration/codex-routing.test.ts similarity index 99% rename from tests/codex-routing.test.ts rename to tests/codex-integration/codex-routing.test.ts index 8a27f92bd34..96ab4e75b95 100644 --- a/tests/codex-routing.test.ts +++ b/tests/codex-integration/codex-routing.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test, beforeEach, afterEach } from "bun:test"; import { existsSync, mkdirSync, writeFileSync } from "node:fs"; import { join } from "node:path"; -import { STORE_BUDGET_MS } from "./helpers/test-budget"; +import { STORE_BUDGET_MS } from "../helpers/test-budget"; import { CODEX_FAILURE_WINDOW_MS, CODEX_QUOTA_PROBE_INTERVAL_MS, @@ -32,10 +32,10 @@ import { resolveCodexAccountForThread, resolveCodexAccountForThreadDetailed, tryAcquireCodexQuotaProbeLease, -} from "../src/codex/routing"; -import { clearPoolRotationState } from "../src/codex/pool-rotation"; -import { captureConfigGeneration } from "../src/lib/state-store-sweeper"; -import { readCodexAccountRecord, removeCodexAccountCredential, saveCodexAccountCredential } from "../src/codex/account-store"; +} from "../../src/codex/routing"; +import { clearPoolRotationState } from "../../src/codex/pool-rotation"; +import { captureConfigGeneration } from "../../src/lib/state-store-sweeper"; +import { readCodexAccountRecord, removeCodexAccountCredential, saveCodexAccountCredential } from "../../src/codex/account-store"; import { clearAccountNeedsReauth, clearAccountQuota, @@ -45,14 +45,14 @@ import { parseUsageQuota, setAccountQuotaFromParsed, updateAccountQuota, -} from "../src/codex/auth-api"; -import { CODEX_UNKNOWN_USAGE_SCORE, isCodexQuotaExhausted } from "../src/codex/quota"; -import { setCodexAccountPriority } from "../src/codex/account-priority"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/main-account"; -import { routeModel } from "../src/router"; -import { consumeForInspection } from "../src/server/relay"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/auth-api"; +import { CODEX_UNKNOWN_USAGE_SCORE, isCodexQuotaExhausted } from "../../src/codex/quota"; +import { setCodexAccountPriority } from "../../src/codex/account-priority"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/main-account"; +import { routeModel } from "../../src/router"; +import { consumeForInspection } from "../../src/server/relay"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-codex-routing-test"); let previousOpencodexHome: string | undefined; @@ -686,7 +686,7 @@ describe("codex routing", () => { test("a sidecar 401 does not quarantine the credential that replaced it (#2892 gap 4 review)", async () => { - const { sidecarOutcomeRecorder } = await import("../src/server/responses/core"); + const { sidecarOutcomeRecorder } = await import("../../src/server/responses/core"); const config = makeConfig(); updateAccountQuota("a", 10); updateAccountQuota("b", 20); diff --git a/tests/codex-runtime.test.ts b/tests/codex-integration/codex-runtime.test.ts similarity index 99% rename from tests/codex-runtime.test.ts rename to tests/codex-integration/codex-runtime.test.ts index 55fbc2e0661..2dc5d6347d5 100644 --- a/tests/codex-runtime.test.ts +++ b/tests/codex-integration/codex-runtime.test.ts @@ -34,7 +34,7 @@ import { resetCodexRuntimeResolveCacheForTests, setCodexRuntimeResolveCacheForTests, type RuntimeExecFile, -} from "../src/codex/runtime"; +} from "../../src/codex/runtime"; import { bundledCatalogCacheState, invalidateBundledCatalogCache, @@ -43,7 +43,7 @@ import { resolveCatalogSourceForGather, setBundledCatalogCacheForTests, type CatalogGatherEvidenceSession, -} from "../src/codex/catalog/bundled"; +} from "../../src/codex/catalog/bundled"; function tempConfigDir(): string { return mkdtempSync(join(tmpdir(), "ocx-runtime-")); @@ -661,7 +661,7 @@ describe("resolveCodexRuntime", () => { const { loadBundledCodexCatalog, resetBundledCatalogCacheForTests, - } = await import("../src/codex/catalog/bundled"); + } = await import("../../src/codex/catalog/bundled"); const home = tempConfigDir(); const binDir = join(home, "bin"); @@ -813,7 +813,7 @@ describe("resolveCodexRuntime", () => { }); test("catalog clamp clears diagnostics inside deps.configDir when probe fails", async () => { - const { clampCatalogModelsToCodexSupport } = await import("../src/codex/catalog/effort"); + const { clampCatalogModelsToCodexSupport } = await import("../../src/codex/catalog/effort"); const nested = join(tempConfigDir(), "nested", "opencodex-home"); const configured = join(nested, "codex.exe"); persistEffortClamp({ @@ -844,7 +844,7 @@ describe("resolveCodexRuntime", () => { const { loadBundledCodexCatalog, resetBundledCatalogCacheForTests, - } = await import("../src/codex/catalog/bundled"); + } = await import("../../src/codex/catalog/bundled"); const home = tempConfigDir(); const oldDir = join(home, "old"); @@ -938,7 +938,7 @@ describe("resolveCodexRuntime", () => { }); test("clamp diagnostics include unsupported default_reasoning_level changes", async () => { - const { clampCatalogModelsToCodexSupport } = await import("../src/codex/catalog/effort"); + const { clampCatalogModelsToCodexSupport } = await import("../../src/codex/catalog/effort"); const diagnostics: Array<{ removedEfforts: string[]; affectedModels: string[] }> = []; const models = [{ slug: "openrouter/example", diff --git a/tests/codex-service-manager-probe-hardening.test.ts b/tests/codex-integration/codex-service-manager-probe-hardening.test.ts similarity index 98% rename from tests/codex-service-manager-probe-hardening.test.ts rename to tests/codex-integration/codex-service-manager-probe-hardening.test.ts index e353e50cffb..2f9e3b6bfab 100644 --- a/tests/codex-service-manager-probe-hardening.test.ts +++ b/tests/codex-integration/codex-service-manager-probe-hardening.test.ts @@ -8,12 +8,12 @@ import { inspectServiceManagerInstallation, type ServiceManagerInstallation, type RawProbeRunner, -} from "../src/service-manager-probe"; -import { inspectNativeCodexOwnership } from "../src/integrations/native/ownership-preflight"; -import { setTrustedWindowsSystemDirectoryResolverForTests } from "../src/lib/windows-elevation"; -import { getDefaultConfig } from "../src/config"; -import { startServer } from "../src/server"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/service-manager-probe"; +import { inspectNativeCodexOwnership } from "../../src/integrations/native/ownership-preflight"; +import { setTrustedWindowsSystemDirectoryResolverForTests } from "../../src/lib/windows-elevation"; +import { getDefaultConfig } from "../../src/config"; +import { startServer } from "../../src/server"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let home = ""; let configDir = ""; diff --git a/tests/codex-service-manager-probe.test.ts b/tests/codex-integration/codex-service-manager-probe.test.ts similarity index 99% rename from tests/codex-service-manager-probe.test.ts rename to tests/codex-integration/codex-service-manager-probe.test.ts index 69232cc5fb6..7d0dff0cbae 100644 --- a/tests/codex-service-manager-probe.test.ts +++ b/tests/codex-integration/codex-service-manager-probe.test.ts @@ -16,10 +16,10 @@ import { inspectServiceManagerInstallation, type ProbeRunner, type RawProbeRunner, -} from "../src/service-manager-probe"; -import { inspectNativeCodexOwnership } from "../src/integrations/native/ownership-preflight"; -import { setTrustedWindowsSystemDirectoryResolverForTests } from "../src/lib/windows-elevation"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/service-manager-probe"; +import { inspectNativeCodexOwnership } from "../../src/integrations/native/ownership-preflight"; +import { setTrustedWindowsSystemDirectoryResolverForTests } from "../../src/lib/windows-elevation"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let home = ""; const cleanup: string[] = []; diff --git a/tests/codex-shim-autorestore.test.ts b/tests/codex-integration/codex-shim-autorestore.test.ts similarity index 94% rename from tests/codex-shim-autorestore.test.ts rename to tests/codex-integration/codex-shim-autorestore.test.ts index 6d2ac3110a5..75562bbc567 100644 --- a/tests/codex-shim-autorestore.test.ts +++ b/tests/codex-integration/codex-shim-autorestore.test.ts @@ -3,15 +3,16 @@ import { spawnSync } from "node:child_process"; import { chmodSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import type { CodexShimAutoRestoreResult } from "../src/codex/shim"; -import { getDefaultConfig } from "../src/config"; +import type { CodexShimAutoRestoreResult } from "../../src/codex/shim"; +import { getDefaultConfig } from "../../src/config"; import { maybeAutoRestoreCodexShim, skipsCodexShimAutoRestore, type CodexShimAutoRestoreCliDeps, -} from "../src/cli/codex-shim-autorestore"; -import { autoRestoreCodexShim, CODEX_SHIM_STATE_MAX_BYTES, installCodexShim } from "../src/codex/shim"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/cli/codex-shim-autorestore"; +import { autoRestoreCodexShim, CODEX_SHIM_STATE_MAX_BYTES, installCodexShim } from "../../src/codex/shim"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath } from "../helpers/repo-root"; const SHIM_MARKER = "opencodex codex autostart shim"; @@ -154,7 +155,7 @@ describe("Codex shim CLI auto-restore policy", () => { const beforeState = readFileSync(statePath); const result = spawnSync(process.execPath, [ - join(import.meta.dir, "..", "src", "cli", "index.ts"), + repoPath("src", "cli", "index.ts"), "system", "codex-cli-update", "check", "--json", ], { encoding: "utf8", @@ -196,7 +197,7 @@ describe("Codex shim CLI auto-restore policy", () => { chmodSync(wrapper, 0o755); await Bun.sleep(120); - const result = spawnSync(process.execPath, [join(import.meta.dir, "..", "src", "cli", "index.ts"), "codex-shim", "status"], { + const result = spawnSync(process.execPath, [repoPath("src", "cli", "index.ts"), "codex-shim", "status"], { encoding: "utf8", env: { ...process.env, PATH: binDir, OPENCODEX_HOME: home }, }); diff --git a/tests/codex-shim-readiness.test.ts b/tests/codex-integration/codex-shim-readiness.test.ts similarity index 96% rename from tests/codex-shim-readiness.test.ts rename to tests/codex-integration/codex-shim-readiness.test.ts index 080f3a3e637..9780321d48b 100644 --- a/tests/codex-shim-readiness.test.ts +++ b/tests/codex-integration/codex-shim-readiness.test.ts @@ -9,10 +9,10 @@ import { import { tmpdir } from "node:os"; import { delimiter, dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -import { codexShimReadinessWarnings } from "../src/cli/codex-shim-readiness"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { codexShimReadinessWarnings } from "../../src/cli/codex-shim-readiness"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; -const repoRoot = dirname(fileURLToPath(new URL("../package.json", import.meta.url))); +const repoRoot = dirname(fileURLToPath(new URL("../../package.json", import.meta.url))); const cliPath = join(repoRoot, "src", "cli", "index.ts"); const ready = { diff --git a/tests/codex-shim.test.ts b/tests/codex-integration/codex-shim.test.ts similarity index 99% rename from tests/codex-shim.test.ts rename to tests/codex-integration/codex-shim.test.ts index f1a3e5bc956..fc36d7c8b04 100644 --- a/tests/codex-shim.test.ts +++ b/tests/codex-integration/codex-shim.test.ts @@ -3,8 +3,9 @@ import { spawnSync } from "node:child_process"; import { chmodSync, copyFileSync, existsSync, linkSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, rmSync, statSync, symlinkSync, utimesSync, writeFileSync } from "node:fs"; import { delimiter, dirname, join } from "node:path"; import { tmpdir } from "node:os"; -import { autoRestoreCodexShim, buildUnixCodexShim, buildWindowsCodexShim, buildWindowsPowerShellCodexShim, diagnoseCodexShim, findCodexOnPath, inspectCodexShimBackingForCommand, installCodexShim, isLocalAbsoluteInspectionPath, isVersionManagerOwnedCodexPath, isWindowsInteropDir, lastCodexDiscoveryError, setCodexShimFreshWriteHookForTests, setCodexShimGuardedWriteHookForTests, setCodexShimProbeHookForTests, setCodexShimProbeObservationMsForTests, setCodexShimProbeShellForTests, setCodexShimRollbackRestoreHookForTests, uninstallCodexShim } from "../src/codex/shim"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { autoRestoreCodexShim, buildUnixCodexShim, buildWindowsCodexShim, buildWindowsPowerShellCodexShim, diagnoseCodexShim, findCodexOnPath, inspectCodexShimBackingForCommand, installCodexShim, isLocalAbsoluteInspectionPath, isVersionManagerOwnedCodexPath, isWindowsInteropDir, lastCodexDiscoveryError, setCodexShimFreshWriteHookForTests, setCodexShimGuardedWriteHookForTests, setCodexShimProbeHookForTests, setCodexShimProbeObservationMsForTests, setCodexShimProbeShellForTests, setCodexShimRollbackRestoreHookForTests, uninstallCodexShim } from "../../src/codex/shim"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath, repoRoot } from "../helpers/repo-root"; const SHIM_MARKER = "opencodex codex autostart shim"; const UNIX_SHIM_REVISION_MARKER = "opencodex unix codex shim revision 2"; @@ -234,13 +235,13 @@ describe("Codex autostart shim", () => { }); test("PowerShell shim is written with a UTF-8 BOM (Windows PowerShell 5.1 decodes BOM-less ps1 as ANSI)", async () => { - const source = readFileSync(join(import.meta.dir, "..", "src", "codex", "shim.ts"), "utf8"); + const source = readFileSync(repoPath("src", "codex", "shim.ts"), "utf8"); expect(source).toContain("`\\uFEFF${buildWindowsPowerShellCodexShim(realCodexPath, bun, cli, bunRuntimeSource)}`"); }); test("Windows target discovery includes the extensionless Git-Bash launcher and writeShim emits a forward-slash sh shim for it", () => { - const source = readFileSync(join(import.meta.dir, "..", "src", "codex", "shim.ts"), "utf8"); + const source = readFileSync(repoPath("src", "codex", "shim.ts"), "utf8"); expect(source).toContain('const gitBashLauncher = join(dir, "codex");'); expect(source).toContain("for (const path of [cmd, ps1, gitBashLauncher])"); @@ -1667,7 +1668,7 @@ exit 127 writeFileSync(wrapper, replacement, "utf8"); if (process.platform !== "win32") chmodSync(wrapper, 0o755); - const shimModule = join(import.meta.dir, "..", "src", "codex", "shim.ts"); + const shimModule = repoPath("src", "codex", "shim.ts"); const firstScript = ` import { existsSync, readFileSync, readdirSync, utimesSync, writeFileSync } from "node:fs"; import { join } from "node:path"; @@ -1695,7 +1696,7 @@ exit 127 `; const childEnv = { ...process.env, PATH: binDir, OPENCODEX_HOME: home }; first = Bun.spawn([process.execPath, "-e", firstScript], { - cwd: join(import.meta.dir, ".."), + cwd: repoRoot(), env: childEnv, stdout: "pipe", stderr: "pipe", @@ -1705,7 +1706,7 @@ exit 127 expect(existsSync(readyPath)).toBe(true); const second = spawnSync(process.execPath, ["-e", secondScript], { - cwd: join(import.meta.dir, ".."), + cwd: repoRoot(), env: childEnv, encoding: "utf8", }); diff --git a/tests/codex-spark-visibility.test.ts b/tests/codex-integration/codex-spark-visibility.test.ts similarity index 94% rename from tests/codex-spark-visibility.test.ts rename to tests/codex-integration/codex-spark-visibility.test.ts index 2ddd285ab34..c5dfe1c8a7e 100644 --- a/tests/codex-spark-visibility.test.ts +++ b/tests/codex-integration/codex-spark-visibility.test.ts @@ -1,12 +1,12 @@ import { describe, expect, test } from "bun:test"; -import { withSparkVisibility } from "../src/codex/auth-api"; -import { loadConfig, saveConfig } from "../src/config"; +import { withSparkVisibility } from "../../src/codex/auth-api"; +import { loadConfig, saveConfig } from "../../src/config"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { beforeEach, afterEach } from "bun:test"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const SPARK = "GPT-5.3-Codex-Spark Weekly"; const originalHome = process.env.OPENCODEX_HOME; diff --git a/tests/codex-sqlite-home.test.ts b/tests/codex-integration/codex-sqlite-home.test.ts similarity index 94% rename from tests/codex-sqlite-home.test.ts rename to tests/codex-integration/codex-sqlite-home.test.ts index 4d676feffe8..f8f7c088bb0 100644 --- a/tests/codex-sqlite-home.test.ts +++ b/tests/codex-integration/codex-sqlite-home.test.ts @@ -3,10 +3,10 @@ import { mkdtempSync, mkdirSync, unlinkSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; -import { resolveCodexHistoryJobTarget } from "../src/codex/history-job"; -import { historyBackupPathFor } from "../src/codex/history-provider"; -import { resolveCodexLogsDbPath, resolveCodexSqliteHome, resolveCodexStateDbPath } from "../src/codex/paths"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { resolveCodexHistoryJobTarget } from "../../src/codex/history-job"; +import { historyBackupPathFor } from "../../src/codex/history-provider"; +import { resolveCodexLogsDbPath, resolveCodexSqliteHome, resolveCodexStateDbPath } from "../../src/codex/paths"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const originalCodexHome = process.env.CODEX_HOME; const originalSqliteHome = process.env.CODEX_SQLITE_HOME; diff --git a/tests/codex-sync-api.test.ts b/tests/codex-integration/codex-sync-api.test.ts similarity index 97% rename from tests/codex-sync-api.test.ts rename to tests/codex-integration/codex-sync-api.test.ts index cafc181f832..496952d5d8b 100644 --- a/tests/codex-sync-api.test.ts +++ b/tests/codex-integration/codex-sync-api.test.ts @@ -3,18 +3,19 @@ import { spawnSync } from "node:child_process"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { syncModelsToCodex } from "../src/codex/sync"; -import { MANAGED_AGENTS_TABLE_MARKER, MANAGED_SUBAGENT_DEFAULT_MARKER } from "../src/codex/subagent-defaults"; -import type { OcxConfig } from "../src/types"; -import type { OrcaCodexHomeDiagnostic } from "../src/codex/home"; -import { claimOwnedServiceHome, withOwnedServiceHomePreload } from "./helpers/owned-service-home"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { syncModelsToCodex } from "../../src/codex/sync"; +import { MANAGED_AGENTS_TABLE_MARKER, MANAGED_SUBAGENT_DEFAULT_MARKER } from "../../src/codex/subagent-defaults"; +import type { OcxConfig } from "../../src/types"; +import type { OrcaCodexHomeDiagnostic } from "../../src/codex/home"; +import { claimOwnedServiceHome, withOwnedServiceHomePreload } from "../helpers/owned-service-home"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; const TEST_DIR = join(import.meta.dir, ".tmp-codex-sync-api"); const TEST_CODEX_HOME = join(TEST_DIR, "codex"); const TEST_OCX_HOME = join(TEST_DIR, "ocx"); const TEST_HOME = join(TEST_DIR, "home"); -const repoRoot = join(import.meta.dir, ".."); +const repoRoot = resolveRepoRoot(); let prevCodexHome: string | undefined; let prevOpenCodexHome: string | undefined; let prevHome: string | undefined; @@ -514,7 +515,7 @@ describe("GUI/CLI Codex sync backend", () => { ); console.log(JSON.stringify({ status: response.status, body: await response.json() })); `]), { - cwd: join(import.meta.dir, ".."), + cwd: resolveRepoRoot(), env: childEnv({ CODEX_HOME: TEST_CODEX_HOME, OPENCODEX_HOME: ocxHome }), encoding: "utf8", }); @@ -577,4 +578,4 @@ describe("GUI/CLI Codex sync backend", () => { ]); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/codex-sync-response.test.ts b/tests/codex-integration/codex-sync-response.test.ts similarity index 97% rename from tests/codex-sync-response.test.ts rename to tests/codex-integration/codex-sync-response.test.ts index e7b4c296889..61c1ee49395 100644 --- a/tests/codex-sync-response.test.ts +++ b/tests/codex-integration/codex-sync-response.test.ts @@ -4,8 +4,8 @@ import type { CodexHistoryState, CodexObservedState, ConvergeOutcome, -} from "../src/codex/convergence-types"; -import { toSyncResponse } from "../src/server/management/sync-response"; +} from "../../src/codex/convergence-types"; +import { toSyncResponse } from "../../src/server/management/sync-response"; const history: CodexHistoryState = { status: "converged", diff --git a/tests/codex-tool-mode.test.ts b/tests/codex-integration/codex-tool-mode.test.ts similarity index 90% rename from tests/codex-tool-mode.test.ts rename to tests/codex-integration/codex-tool-mode.test.ts index 92d80ffcd94..2f703d03f08 100644 --- a/tests/codex-tool-mode.test.ts +++ b/tests/codex-integration/codex-tool-mode.test.ts @@ -4,12 +4,12 @@ import { normalizeRoutedCatalogEntry, ROUTED_CODEX_TOOL_MODE, type RawEntry, -} from "../src/codex/catalog/parsing"; -import { buildCatalogEntries } from "../src/codex/catalog"; +} from "../../src/codex/catalog/parsing"; +import { buildCatalogEntries } from "../../src/codex/catalog"; import { collectDeclaredWireToolNames, undeclaredToolCallName, -} from "../src/server/responses-undeclared-tool-guard"; +} from "../../src/server/responses-undeclared-tool-guard"; describe("Codex tool mode configuration (#2106)", () => { test("applyRoutedCodexToolMode defaults to code_mode_only", () => { @@ -100,7 +100,7 @@ describe("Codex tool mode configuration (#2106)", () => { }); test("catalogHintsFromProviderConfig propagates codexToolMode", () => { - const { catalogHintsFromProviderConfig } = require("../src/codex/catalog/provider-fetch"); + const { catalogHintsFromProviderConfig } = require("../../src/codex/catalog/provider-fetch"); const hints = catalogHintsFromProviderConfig( "deepseek", { @@ -114,7 +114,7 @@ describe("Codex tool mode configuration (#2106)", () => { }); test("deriveComboCatalogModel sets codexToolMode = shell when all members specify shell", () => { - const { deriveComboCatalogModel } = require("../src/codex/catalog/aggregation"); + const { deriveComboCatalogModel } = require("../../src/codex/catalog/aggregation"); const combo = { name: "all-shell-combo", targets: [ @@ -138,8 +138,8 @@ describe("Codex tool mode configuration (#2106)", () => { }); test("gatherRoutedModels custom model inherits provider codexToolMode when undiscovered", async () => { - const { gatherRoutedModels } = require("../src/codex/catalog"); - const { withStubbedProviderFetch } = require("./helpers/catalog-provider-fetch"); + const { gatherRoutedModels } = require("../../src/codex/catalog"); + const { withStubbedProviderFetch } = require("../helpers/catalog-provider-fetch"); const config = { providers: { customprov: { @@ -163,8 +163,8 @@ describe("Codex tool mode configuration (#2106)", () => { }); test("gatherRoutedModels custom model explicit codexToolMode overrides provider setting", async () => { - const { gatherRoutedModels } = require("../src/codex/catalog"); - const { withStubbedProviderFetch } = require("./helpers/catalog-provider-fetch"); + const { gatherRoutedModels } = require("../../src/codex/catalog"); + const { withStubbedProviderFetch } = require("../helpers/catalog-provider-fetch"); const config = { providers: { customprov: { @@ -189,8 +189,8 @@ describe("Codex tool mode configuration (#2106)", () => { }); test("buildCatalogEntries with codexForwardNativeCapabilityAlias applies codexToolMode = shell", () => { - const { buildCatalogEntries, NATIVE_DAYBREAK_BLUE_MODEL, upstreamNativeEntry } = require("../src/codex/catalog"); - const { CODEX_CUSTOM_MODEL_CATALOG_KIND, findNativeTemplate } = require("../src/codex/catalog/parsing"); + const { buildCatalogEntries, NATIVE_DAYBREAK_BLUE_MODEL, upstreamNativeEntry } = require("../../src/codex/catalog"); + const { CODEX_CUSTOM_MODEL_CATALOG_KIND, findNativeTemplate } = require("../../src/codex/catalog/parsing"); const nativeTemplate = () => findNativeTemplate({ models: [upstreamNativeEntry("gpt-5.6-sol")!] }); const models = [{ id: NATIVE_DAYBREAK_BLUE_MODEL, @@ -210,7 +210,7 @@ describe("Codex tool mode configuration (#2106)", () => { describe("#2503 combo derivation preserves a member's verbosity opt-out", () => { - const { deriveComboCatalogModel } = require("../src/codex/catalog/aggregation"); + const { deriveComboCatalogModel } = require("../../src/codex/catalog/aggregation"); const combo = { name: "mixed-combo", targets: [ diff --git a/tests/codex-transition-state-adoption.test.ts b/tests/codex-integration/codex-transition-state-adoption.test.ts similarity index 90% rename from tests/codex-transition-state-adoption.test.ts rename to tests/codex-integration/codex-transition-state-adoption.test.ts index 9730d85c98f..b025f12a7d2 100644 --- a/tests/codex-transition-state-adoption.test.ts +++ b/tests/codex-integration/codex-transition-state-adoption.test.ts @@ -4,14 +4,15 @@ import { closeSync, existsSync, fsyncSync, mkdtempSync, openSync, realpathSync, import { tmpdir } from "node:os"; import { join } from "node:path"; -import { openCodexCoordinatorTransaction } from "../src/codex/transition-state"; +import { openCodexCoordinatorTransaction } from "../../src/codex/transition-state"; import { resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/user-identity"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { helperPath, repoRoot } from "../helpers/repo-root"; -const CHILD = join(import.meta.dir, "helpers", "codex-adoption-crash-child.ts"); +const CHILD = helperPath("codex-adoption-crash-child.ts"); let root = ""; let codexHome = ""; let opencodexHome = ""; @@ -39,7 +40,7 @@ afterEach(() => { for (const checkpoint of ["temp-created", "temp-committed", "published"] as const) { test(`a kill at ${checkpoint} leaves the home adoptable`, () => { const child = spawnSync(process.execPath, [CHILD], { - cwd: join(import.meta.dir, ".."), + cwd: repoRoot(), env: { ...process.env, CODEX_HOME: codexHome, diff --git a/tests/codex-transition-state-first-use-regression.test.ts b/tests/codex-integration/codex-transition-state-first-use-regression.test.ts similarity index 93% rename from tests/codex-transition-state-first-use-regression.test.ts rename to tests/codex-integration/codex-transition-state-first-use-regression.test.ts index 78e538540b1..2c50d4d9dee 100644 --- a/tests/codex-transition-state-first-use-regression.test.ts +++ b/tests/codex-integration/codex-transition-state-first-use-regression.test.ts @@ -5,12 +5,12 @@ import { tmpdir } from "node:os"; import { Database } from "bun:sqlite"; -import { beginCodexTransition } from "../src/codex/transition-state"; +import { beginCodexTransition } from "../../src/codex/transition-state"; import { resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/user-identity"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let codexHome = ""; let opencodexHome = ""; diff --git a/tests/codex-transition-state-race.test.ts b/tests/codex-integration/codex-transition-state-race.test.ts similarity index 97% rename from tests/codex-transition-state-race.test.ts rename to tests/codex-integration/codex-transition-state-race.test.ts index d8a06de4f7e..31c87a194a9 100644 --- a/tests/codex-transition-state-race.test.ts +++ b/tests/codex-integration/codex-transition-state-race.test.ts @@ -14,18 +14,19 @@ import { pathToFileURL } from "node:url"; import { Database } from "bun:sqlite"; -import { openCodexCoordinatorTransaction } from "../src/codex/transition-state"; +import { openCodexCoordinatorTransaction } from "../../src/codex/transition-state"; import { resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; +} from "../../src/codex/user-identity"; +import { repoPath } from "../helpers/repo-root"; const CHILD_TIMEOUT_MS = 10_000; const transitionStateModuleUrl = pathToFileURL( - join(import.meta.dir, "..", "src", "codex", "transition-state.ts"), + repoPath("src", "codex", "transition-state.ts"), ).href; const userIdentityModuleUrl = pathToFileURL( - join(import.meta.dir, "..", "src", "codex", "user-identity.ts"), + repoPath("src", "codex", "user-identity.ts"), ).href; const transitionProbe = ` diff --git a/tests/codex-transition-state.test.ts b/tests/codex-integration/codex-transition-state.test.ts similarity index 98% rename from tests/codex-transition-state.test.ts rename to tests/codex-integration/codex-transition-state.test.ts index 7877d1dd87a..9032dfcbe47 100644 --- a/tests/codex-transition-state.test.ts +++ b/tests/codex-integration/codex-transition-state.test.ts @@ -10,14 +10,14 @@ import { openCodexCoordinatorTransaction, readCodexTransitionState, updateCodexHistoryTransition, -} from "../src/codex/transition-state"; -import { resolveCodexHistoryTransition } from "../src/codex/history-transition"; -import { historyBackupPathFor } from "../src/codex/history-provider"; +} from "../../src/codex/transition-state"; +import { resolveCodexHistoryTransition } from "../../src/codex/history-transition"; +import { historyBackupPathFor } from "../../src/codex/history-provider"; import { resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/user-identity"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let codexHome = ""; let opencodexHome = ""; diff --git a/tests/codex-user-identity.test.ts b/tests/codex-integration/codex-user-identity.test.ts similarity index 98% rename from tests/codex-user-identity.test.ts rename to tests/codex-integration/codex-user-identity.test.ts index c2d58b38b05..9635bdb5262 100644 --- a/tests/codex-user-identity.test.ts +++ b/tests/codex-integration/codex-user-identity.test.ts @@ -12,15 +12,16 @@ import { resolveEffectiveUserRuntimeRoot, probeCodexCoordinatorNamespace, samePathIdentity, -} from "../src/codex/user-identity"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/user-identity"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath } from "../helpers/repo-root"; let codexHome = ""; let previousHome: string | undefined; const CHILD_TIMEOUT_MS = 10_000; const userIdentityModuleUrl = pathToFileURL( - join(import.meta.dir, "..", "src", "codex", "user-identity.ts"), + repoPath("src", "codex", "user-identity.ts"), ).href; const identityProbe = ` import { diff --git a/tests/codex-v2-gate.test.ts b/tests/codex-integration/codex-v2-gate.test.ts similarity index 99% rename from tests/codex-v2-gate.test.ts rename to tests/codex-integration/codex-v2-gate.test.ts index 7d813b5f09e..8d3e2d9dc54 100644 --- a/tests/codex-v2-gate.test.ts +++ b/tests/codex-integration/codex-v2-gate.test.ts @@ -15,11 +15,11 @@ import { nativeEffortClamp, shouldApplyNativeEffortClamp, type MultiAgentMode, -} from "../src/codex/catalog"; +} from "../../src/codex/catalog"; import { buildCatalogEntriesFromObservedState, mergeCatalogEntriesFromObservedState, -} from "../src/codex/catalog/sync"; +} from "../../src/codex/catalog/sync"; import { getAgentsEnabled, getAgentsMaxDepth, @@ -42,11 +42,11 @@ import { transitionMultiAgentV2, v1ChildLimitToV2TotalLimit, v2TotalLimitToV1ChildLimit, -} from "../src/codex/features"; -import { resetCodexRuntimeResolveCacheForTests, setCodexRuntimeResolveCacheForTests } from "../src/codex/runtime"; -import { cmdV2, codexFeaturesInvocation, v2StatusLine, multiAgentModeLine } from "../src/cli/v2"; -import { handleManagementAPI } from "../src/server/management-api"; -import { catalogConvergenceFactory } from "./helpers/catalog-convergence"; +} from "../../src/codex/features"; +import { resetCodexRuntimeResolveCacheForTests, setCodexRuntimeResolveCacheForTests } from "../../src/codex/runtime"; +import { cmdV2, codexFeaturesInvocation, v2StatusLine, multiAgentModeLine } from "../../src/cli/v2"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { catalogConvergenceFactory } from "../helpers/catalog-convergence"; function template(): Record { return { @@ -994,7 +994,7 @@ describe("v1<->v2 root-slot translation", () => { describe("config-surface parity: agents.enabled, max_depth, subagent_developer_instructions", () => { test("opencodex mirrors exactly one upstream feature key", async () => { - const source = await Bun.file(new URL("../src/codex/features.ts", import.meta.url)).text(); + const source = await Bun.file(new URL("../../src/codex/features.ts", import.meta.url)).text(); // Upstream feature keys are snake_case, so the underscore requirement is the // discriminator: JS member accesses on locals named `features` (features.match, // features.slice, features.ts) are camelCase and never match, while a mirrored @@ -2014,4 +2014,4 @@ describe("3-state multi-agent mode", () => { expect(native.multi_agent_version).toBeUndefined(); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/codex-warmup.test.ts b/tests/codex-integration/codex-warmup.test.ts similarity index 99% rename from tests/codex-warmup.test.ts rename to tests/codex-integration/codex-warmup.test.ts index bfd4f4768f2..14dd1455ff7 100644 --- a/tests/codex-warmup.test.ts +++ b/tests/codex-integration/codex-warmup.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { CodexWarmupError, warmCodexAccount } from "../src/codex/warmup"; +import { CodexWarmupError, warmCodexAccount } from "../../src/codex/warmup"; const originalFetch = globalThis.fetch; diff --git a/tests/codex-websocket-registry.test.ts b/tests/codex-integration/codex-websocket-registry.test.ts similarity index 96% rename from tests/codex-websocket-registry.test.ts rename to tests/codex-integration/codex-websocket-registry.test.ts index 0fad252cb53..3a710ae015c 100644 --- a/tests/codex-websocket-registry.test.ts +++ b/tests/codex-integration/codex-websocket-registry.test.ts @@ -7,9 +7,9 @@ import { registerCodexWebSocket, unregisterCodexWebSocket, updateCodexWebSocketAuthContext, -} from "../src/codex/websocket-registry"; -import { applyConfirmedMainCodexAccountTransition } from "../src/codex/account-lifecycle"; -import type { WsData } from "../src/server/ws-bridge"; +} from "../../src/codex/websocket-registry"; +import { applyConfirmedMainCodexAccountTransition } from "../../src/codex/account-lifecycle"; +import type { WsData } from "../../src/server/ws-bridge"; function mockWs(data: WsData): { ws: ServerWebSocket; diff --git a/tests/codex-write-lock.test.ts b/tests/codex-integration/codex-write-lock.test.ts similarity index 98% rename from tests/codex-write-lock.test.ts rename to tests/codex-integration/codex-write-lock.test.ts index e20fbd3ecc3..e33163361d3 100644 --- a/tests/codex-write-lock.test.ts +++ b/tests/codex-integration/codex-write-lock.test.ts @@ -13,7 +13,7 @@ import { mkdirSync, mkdtempSync, realpathSync, rmSync, symlinkSync, writeFileSyn import { resolveCodexCoordinatorDatabasePath, resolveEffectiveUserIdentity, -} from "../src/codex/user-identity"; +} from "../../src/codex/user-identity"; import { tmpdir } from "node:os"; import { join } from "node:path"; @@ -21,9 +21,10 @@ import { CODEX_WRITE_LOCK_MAX_TIMEOUT_MS, canonicalizeCodexHome, withCodexWriteLock, -} from "../src/codex/codex-write-lock"; -import type { AdmissionSnapshot } from "../src/codex/convergence-types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/codex-write-lock"; +import type { AdmissionSnapshot } from "../../src/codex/convergence-types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { helperPath } from "../helpers/repo-root"; let root = ""; let codexHome = ""; @@ -280,7 +281,7 @@ describe("two real processes contend for one lock", () => { * like a race and was not one. So: a real child process, calling the * production module. */ - const childPath = join(import.meta.dir, "helpers", "codex-write-lock-child.ts"); + const childPath = helperPath("codex-write-lock-child.ts"); function spawnChild(payload: Record) { return Bun.spawn(["bun", childPath], { diff --git a/tests/combos.test.ts b/tests/codex-integration/combos.test.ts similarity index 98% rename from tests/combos.test.ts rename to tests/codex-integration/combos.test.ts index 51ae4fa1a98..a50385c54c0 100644 --- a/tests/combos.test.ts +++ b/tests/codex-integration/combos.test.ts @@ -39,29 +39,29 @@ import { targetKey, tryPickComboModel, UnknownComboError, -} from "../src/combos"; +} from "../../src/combos"; import { comboFailureCooldownScope, comboFailureDecision, isTransientRequestRateLimit, -} from "../src/combos/failover"; -import { comboUnavailableResponse } from "../src/server/responses/core"; -import { getConfigPath, readConfigDiagnostics, saveConfig } from "../src/config"; -import { routeModel } from "../src/router"; -import { handleManagementAPI } from "../src/server/management-api"; -import { handleResponses } from "../src/server/responses"; -import type { OcxConfig } from "../src/types"; -import { syncCatalogModels } from "../src/codex/catalog"; -import { injectClaudeAgentDefs } from "../src/claude/agents-inject"; -import { reconcileComboRotationState } from "../src/combos/resolve"; +} from "../../src/combos/failover"; +import { comboUnavailableResponse } from "../../src/server/responses/core"; +import { getConfigPath, readConfigDiagnostics, saveConfig } from "../../src/config"; +import { routeModel } from "../../src/router"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { handleResponses } from "../../src/server/responses"; +import type { OcxConfig } from "../../src/types"; +import { syncCatalogModels } from "../../src/codex/catalog"; +import { injectClaudeAgentDefs } from "../../src/claude/agents-inject"; +import { reconcileComboRotationState } from "../../src/combos/resolve"; import { clearCachedProviderQuotas, getCachedProviderQuota, replaceCachedProviderQuotas, setCachedProviderQuotaForTests, -} from "../src/providers/quota-routing-cache"; -import { catalogConvergenceFactory } from "./helpers/catalog-convergence"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/quota-routing-cache"; +import { catalogConvergenceFactory } from "../helpers/catalog-convergence"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const VALID_COMBO = { targets: [{ provider: "a", model: "m1" }] }; diff --git a/tests/compatibility-manifest.test.ts b/tests/codex-integration/compatibility-manifest.test.ts similarity index 91% rename from tests/compatibility-manifest.test.ts rename to tests/codex-integration/compatibility-manifest.test.ts index ed74a5cfc91..85761369554 100644 --- a/tests/compatibility-manifest.test.ts +++ b/tests/codex-integration/compatibility-manifest.test.ts @@ -2,20 +2,21 @@ import { describe, expect, test } from "bun:test"; import { existsSync, readFileSync } from "node:fs"; import { dirname, join, resolve } from "node:path"; import { fileURLToPath } from "node:url"; -import { createRegisteredAdapter, effectiveAdapterContract } from "../src/adapters/registry"; +import { createRegisteredAdapter, effectiveAdapterContract } from "../../src/adapters/registry"; import { COMPATIBILITY_MANIFESTS, OPENAI_CODEX_FORWARD_GPT56_SOL_MANIFEST, compatibilityManifestIssues, -} from "../src/compatibility"; -import { createTranslatorBudget } from "../src/lib/translator-budget"; -import { listScenarioIds } from "../src/lab/conformance/runner"; -import { providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { SUPPORTED_NATIVE_OPENAI_SLUGS } from "../src/codex/catalog/native-models"; -import { parseRequest } from "../src/responses/parser"; -import { resolveJsonPointer } from "../src/lab/conformance/json-pointer"; -import fixtureJson from "./fixtures/compatibility/openai-codex-forward-gpt56-sol-v1.json"; +} from "../../src/compatibility"; +import { createTranslatorBudget } from "../../src/lib/translator-budget"; +import { listScenarioIds } from "../../src/lab/conformance/runner"; +import { providerConfigSeed } from "../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; +import { SUPPORTED_NATIVE_OPENAI_SLUGS } from "../../src/codex/catalog/native-models"; +import { parseRequest } from "../../src/responses/parser"; +import { resolveJsonPointer } from "../../src/lab/conformance/json-pointer"; +import fixtureJson from "../fixtures/compatibility/openai-codex-forward-gpt56-sol-v1.json"; +import { repoRoot as resolveRepoRoot } from "../helpers/repo-root"; type FixtureAssertion = { id: string; @@ -39,7 +40,7 @@ type CompatibilityFixture = { }; const fixture = fixtureJson as CompatibilityFixture; -const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); +const repoRoot = resolveRepoRoot(); const RUNTIME_IMPORT_RE = /^\s*import\s+(?!type\b)[^;]*?from\s+["']([^"']+)["']|^\s*import\s+["']([^"']+)["']|^\s*export\s+(?!type\b)[^;]*?from\s+["']([^"']+)["']|\bimport\s*\(\s*["']([^"']+)["']\s*\)/gm; function resolveRuntimeImport(specifier: string, fromFile: string): string | null { diff --git a/tests/custom-model-catalog-migration.test.ts b/tests/codex-integration/custom-model-catalog-migration.test.ts similarity index 97% rename from tests/custom-model-catalog-migration.test.ts rename to tests/codex-integration/custom-model-catalog-migration.test.ts index 4a8134b0a47..a39dcdb8d8e 100644 --- a/tests/custom-model-catalog-migration.test.ts +++ b/tests/codex-integration/custom-model-catalog-migration.test.ts @@ -3,8 +3,8 @@ import { describe, expect, test } from "bun:test"; import { projectCustomModelCatalogMigration, legacyCustomModelCatalogSlugs, -} from "../src/codex/custom-model-catalog-migration"; -import type { OcxConfig, OcxCustomModel } from "../src/types"; +} from "../../src/codex/custom-model-catalog-migration"; +import type { OcxConfig, OcxCustomModel } from "../../src/types"; function config(customModels?: OcxCustomModel[]): OcxConfig { return { diff --git a/tests/doctor.test.ts b/tests/codex-integration/doctor.test.ts similarity index 99% rename from tests/doctor.test.ts rename to tests/codex-integration/doctor.test.ts index 6261b7c1065..9fdb7ee30d1 100644 --- a/tests/doctor.test.ts +++ b/tests/codex-integration/doctor.test.ts @@ -19,9 +19,9 @@ import { resolveCodexHomeDir, runDoctor, type ServiceMemoryData, -} from "../src/cli/doctor"; -import { collectOrcaCodexHomeDiagnostic } from "../src/codex/home"; -import { NativeProfileError } from "../src/codex/native-profile-types"; +} from "../../src/cli/doctor"; +import { collectOrcaCodexHomeDiagnostic } from "../../src/codex/home"; +import { NativeProfileError } from "../../src/codex/native-profile-types"; import { LOCAL_MANAGEMENT_CAPABILITY_HEADER, LOCAL_MANAGEMENT_CAPABILITY_EXPIRES_AT_HEADER, @@ -29,9 +29,9 @@ import { LOCAL_MANAGEMENT_NONCE_HEADER, LOCAL_MANAGEMENT_READ_PATHS, verifyLocalManagementReadCapability, -} from "../src/lib/local-management-capability"; -import { findDeadPid } from "./helpers/dead-pid"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/lib/local-management-capability"; +import { findDeadPid } from "../helpers/dead-pid"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-doctor-test"); const TEST_CODEX_HOME = join(TEST_DIR, "codex"); diff --git a/tests/effort-policy.test.ts b/tests/codex-integration/effort-policy.test.ts similarity index 97% rename from tests/effort-policy.test.ts rename to tests/codex-integration/effort-policy.test.ts index f704ee53a70..3f2262ade62 100644 --- a/tests/effort-policy.test.ts +++ b/tests/codex-integration/effort-policy.test.ts @@ -7,14 +7,14 @@ import { afterEach, describe, expect, test } from "bun:test"; import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { applyEffortCap, effortCapAppliesTo, effortCapFor, isThreadSpawnRequest, resolveCappedEffort, stripEmptyLadderEffort, supportedLadderFor } from "../src/server/effort-policy"; -import { collabSurface } from "../src/server/responses"; -import { handleManagementAPI } from "../src/server/management-api"; -import { NoEnabledOpenAiProviderError, routeModel } from "../src/router"; -import { mapReasoningEffort } from "../src/reasoning-effort"; -import { nativeEffortClamp } from "../src/codex/catalog"; -import type { OcxConfig, OcxParsedRequest } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { applyEffortCap, effortCapAppliesTo, effortCapFor, isThreadSpawnRequest, resolveCappedEffort, stripEmptyLadderEffort, supportedLadderFor } from "../../src/server/effort-policy"; +import { collabSurface } from "../../src/server/responses"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { NoEnabledOpenAiProviderError, routeModel } from "../../src/router"; +import { mapReasoningEffort } from "../../src/reasoning-effort"; +import { nativeEffortClamp } from "../../src/codex/catalog"; +import type { OcxConfig, OcxParsedRequest } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const savedHome = process.env.OPENCODEX_HOME; const savedCodexHome = process.env.CODEX_HOME; @@ -490,4 +490,4 @@ describe("/api/effort-caps", () => { expect(config.subagentEffortCap).toBe("low"); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/fast-row-listing.test.ts b/tests/codex-integration/fast-row-listing.test.ts similarity index 94% rename from tests/fast-row-listing.test.ts rename to tests/codex-integration/fast-row-listing.test.ts index 7d038345801..ccdd2b38816 100644 --- a/tests/fast-row-listing.test.ts +++ b/tests/codex-integration/fast-row-listing.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { AUTO_CONTEXT_OFF } from "../src/claude/context-windows"; -import { desktop3pAlias } from "../src/claude/desktop-3p"; -import { buildAnthropicModelInfos } from "../src/claude/model-info"; -import type { CatalogModel } from "../src/codex/catalog"; +import { AUTO_CONTEXT_OFF } from "../../src/claude/context-windows"; +import { desktop3pAlias } from "../../src/claude/desktop-3p"; +import { buildAnthropicModelInfos } from "../../src/claude/model-info"; +import type { CatalogModel } from "../../src/codex/catalog"; /** * Fast rows on Claude Code discovery (devlog 260904_external_fast_wire/020). diff --git a/tests/fast-row.test.ts b/tests/codex-integration/fast-row.test.ts similarity index 98% rename from tests/fast-row.test.ts rename to tests/codex-integration/fast-row.test.ts index d9c0005a206..6a0437b8afb 100644 --- a/tests/fast-row.test.ts +++ b/tests/codex-integration/fast-row.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { clearModelCache, setCached } from "../src/codex/model-cache"; -import { knownEffortRowIds, parseEffortRowId, parseRequestEffortRowId } from "../src/server/effort-row"; +import { clearModelCache, setCached } from "../../src/codex/model-cache"; +import { knownEffortRowIds, parseEffortRowId, parseRequestEffortRowId } from "../../src/server/effort-row"; import { effortBaseCarriesFastMarker, expandFastRow, @@ -10,9 +10,9 @@ import { parseFastOnlyRowId, parseFastRowId, parseSyntheticRowId, -} from "../src/server/fast-row"; -import { isDeclaredReasoningEffort } from "../src/reasoning-effort"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +} from "../../src/server/fast-row"; +import { isDeclaredReasoningEffort } from "../../src/reasoning-effort"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; /** * Synthetic Fast selectors (devlog 260904_external_fast_wire/010). diff --git a/tests/gather-routed-models-single-flight.test.ts b/tests/codex-integration/gather-routed-models-single-flight.test.ts similarity index 97% rename from tests/gather-routed-models-single-flight.test.ts rename to tests/codex-integration/gather-routed-models-single-flight.test.ts index 40055d08c94..0957cf7d6b1 100644 --- a/tests/gather-routed-models-single-flight.test.ts +++ b/tests/codex-integration/gather-routed-models-single-flight.test.ts @@ -5,11 +5,11 @@ import { gatherRoutedModels as gatherRoutedModelsDirect, resetCatalogRuntimeStateForTests, type ComboCatalogOmission, -} from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import type { OcxConfig } from "../src/types"; -import { CatalogGatherBusyError } from "../src/codex/catalog/provider-fetch"; +} from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import type { OcxConfig } from "../../src/types"; +import { CatalogGatherBusyError } from "../../src/codex/catalog/provider-fetch"; const originalFetch = globalThis.fetch; diff --git a/tests/history-migration-guardian.test.ts b/tests/codex-integration/history-migration-guardian.test.ts similarity index 98% rename from tests/history-migration-guardian.test.ts rename to tests/codex-integration/history-migration-guardian.test.ts index 65b90cc7ed7..ad044cc98af 100644 --- a/tests/history-migration-guardian.test.ts +++ b/tests/codex-integration/history-migration-guardian.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { startHistoryMigrationGuardian } from "../src/codex/history-migration-guardian"; +import { startHistoryMigrationGuardian } from "../../src/codex/history-migration-guardian"; /** * Manual scheduler: collects scheduled callbacks so tests drive ticks diff --git a/tests/injection-model-api.test.ts b/tests/codex-integration/injection-model-api.test.ts similarity index 97% rename from tests/injection-model-api.test.ts rename to tests/codex-integration/injection-model-api.test.ts index 645584bfa0d..71fa8c35bed 100644 --- a/tests/injection-model-api.test.ts +++ b/tests/codex-integration/injection-model-api.test.ts @@ -7,12 +7,12 @@ import { afterEach, describe, expect, test } from "bun:test"; import { existsSync, mkdtempSync, readFileSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { getConfigPath, loadConfig } from "../src/config"; -import { refreshCodexModelCatalog } from "../src/codex/refresh"; -import { handleManagementAPI } from "../src/server/management-api"; -import { CODEX_REASONING_LEVELS } from "../src/reasoning-effort"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { getConfigPath, loadConfig } from "../../src/config"; +import { refreshCodexModelCatalog } from "../../src/codex/refresh"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { CODEX_REASONING_LEVELS } from "../../src/reasoning-effort"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const savedHome = process.env.OPENCODEX_HOME; let tempHome: string | null = null; @@ -413,4 +413,4 @@ describe("/api/injection-model guidance kill switch + partial update", () => { }); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/issue-452-empty-503.test.ts b/tests/codex-integration/issue-452-empty-503.test.ts similarity index 94% rename from tests/issue-452-empty-503.test.ts rename to tests/codex-integration/issue-452-empty-503.test.ts index 92e2328050e..c04b6a8fdfb 100644 --- a/tests/issue-452-empty-503.test.ts +++ b/tests/codex-integration/issue-452-empty-503.test.ts @@ -1,22 +1,22 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync} from "node:fs"; import { join } from "node:path"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { clearAccountNeedsReauth, clearAccountQuota, updateAccountQuota } from "../src/codex/auth-api"; -import { clearCodexUpstreamHealth, clearThreadAccountMap } from "../src/codex/routing"; -import { saveConfig } from "../src/config"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { BOUNDED_BODY_MAX_BYTES } from "../src/lib/bounded-body"; -import { getDebugLogEntries, resetDebugLogBufferForTests } from "../src/lib/debug-log-buffer"; -import { resetDebugSettingsForTests } from "../src/lib/debug-settings"; -import { setDraining } from "../src/server/lifecycle"; -import { startServer } from "../src/server"; -import { readDisplaySafeErrorText } from "../src/server/responses/core"; -import { formatPassthroughUpstreamError } from "../src/server/responses/passthrough-error"; -import type { OcxConfig, OcxParsedRequest } from "../src/types"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { SERVER_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { clearAccountNeedsReauth, clearAccountQuota, updateAccountQuota } from "../../src/codex/auth-api"; +import { clearCodexUpstreamHealth, clearThreadAccountMap } from "../../src/codex/routing"; +import { saveConfig } from "../../src/config"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { BOUNDED_BODY_MAX_BYTES } from "../../src/lib/bounded-body"; +import { getDebugLogEntries, resetDebugLogBufferForTests } from "../../src/lib/debug-log-buffer"; +import { resetDebugSettingsForTests } from "../../src/lib/debug-settings"; +import { setDraining } from "../../src/server/lifecycle"; +import { startServer } from "../../src/server"; +import { readDisplaySafeErrorText } from "../../src/server/responses/core"; +import { formatPassthroughUpstreamError } from "../../src/server/responses/passthrough-error"; +import type { OcxConfig, OcxParsedRequest } from "../../src/types"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { SERVER_BUDGET_MS } from "../helpers/test-budget"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const previousApiToken = process.env.OPENCODEX_API_AUTH_TOKEN; const previousOpencodexHome = process.env.OPENCODEX_HOME; diff --git a/tests/issue-702-expired-replay-state.test.ts b/tests/codex-integration/issue-702-expired-replay-state.test.ts similarity index 96% rename from tests/issue-702-expired-replay-state.test.ts rename to tests/codex-integration/issue-702-expired-replay-state.test.ts index 476e795306b..b73439ecc98 100644 --- a/tests/issue-702-expired-replay-state.test.ts +++ b/tests/codex-integration/issue-702-expired-replay-state.test.ts @@ -2,11 +2,11 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync, readdirSync, unlinkSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; +import { saveConfig } from "../../src/config"; import { resetSubagentModelFallbackStateForTests, setSubagentQuotaPrimeForTests, -} from "../src/codex/subagent-model-fallback"; +} from "../../src/codex/subagent-model-fallback"; import { clearResponseStateForTests, clearResponseStateMemoryForTests, @@ -15,14 +15,14 @@ import { responseStateMetrics, setResponseStateByteCapForTests, type ResponseStateMetrics, -} from "../src/responses/state"; -import { responseSpillDirectory } from "../src/responses/spill-store"; -import { startServer } from "../src/server"; -import type { OcxConfig } from "../src/types"; -import { fakeChatGptJwt } from "./helpers/fake-chatgpt-jwt"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { SERVER_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/responses/state"; +import { responseSpillDirectory } from "../../src/responses/spill-store"; +import { startServer } from "../../src/server"; +import type { OcxConfig } from "../../src/types"; +import { fakeChatGptJwt } from "../helpers/fake-chatgpt-jwt"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { SERVER_BUDGET_MS } from "../helpers/test-budget"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const originalFetch = globalThis.fetch; const previousOpencodexHome = process.env.OPENCODEX_HOME; diff --git a/tests/issue-914-transport-attribution.test.ts b/tests/codex-integration/issue-914-transport-attribution.test.ts similarity index 93% rename from tests/issue-914-transport-attribution.test.ts rename to tests/codex-integration/issue-914-transport-attribution.test.ts index e2236a48d54..6823c7b6e37 100644 --- a/tests/issue-914-transport-attribution.test.ts +++ b/tests/codex-integration/issue-914-transport-attribution.test.ts @@ -8,20 +8,20 @@ import { isCodexAccountSoftAvoided, recordCodexUpstreamOutcome, resolveCodexAccountForThread, -} from "../src/codex/routing"; +} from "../../src/codex/routing"; import { clearUpstreamHostHealth, getUpstreamHostHealth, upstreamHostHealthKey, -} from "../src/codex/upstream-host-health"; -import { classifyTransportFailureKind } from "../src/lib/upstream-reachability"; -import { fetchWithResetRetry, fetchWithTransientRetry } from "../src/lib/upstream-retry"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { getConfigPath } from "../src/config"; -import type { OcxConfig } from "../src/types"; +} from "../../src/codex/upstream-host-health"; +import { classifyTransportFailureKind } from "../../src/lib/upstream-reachability"; +import { fetchWithResetRetry, fetchWithTransientRetry } from "../../src/lib/upstream-retry"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { getConfigPath } from "../../src/config"; +import type { OcxConfig } from "../../src/types"; import { existsSync, mkdirSync} from "node:fs"; import { join } from "node:path"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-issue-914-test"); let previousOpencodexHome: string | undefined; diff --git a/tests/model-cache-generation-tombstone.test.ts b/tests/codex-integration/model-cache-generation-tombstone.test.ts similarity index 98% rename from tests/model-cache-generation-tombstone.test.ts rename to tests/codex-integration/model-cache-generation-tombstone.test.ts index 1e2cc5b4b2a..48d914a945a 100644 --- a/tests/model-cache-generation-tombstone.test.ts +++ b/tests/codex-integration/model-cache-generation-tombstone.test.ts @@ -5,7 +5,7 @@ import { providerCacheGenerations, reconcileModelCacheProviders, setCached, -} from "../src/codex/model-cache"; +} from "../../src/codex/model-cache"; let reconciliationGeneration = Date.now(); diff --git a/tests/model-cache.test.ts b/tests/codex-integration/model-cache.test.ts similarity index 97% rename from tests/model-cache.test.ts rename to tests/codex-integration/model-cache.test.ts index d3b30f37202..58ab24eacff 100644 --- a/tests/model-cache.test.ts +++ b/tests/codex-integration/model-cache.test.ts @@ -5,7 +5,7 @@ import { getStaleCached, reconcileModelCacheProviders, setCached, -} from "../src/codex/model-cache"; +} from "../../src/codex/model-cache"; const provider = "removed-provider-generation"; diff --git a/tests/model-display-names-management-api.test.ts b/tests/codex-integration/model-display-names-management-api.test.ts similarity index 97% rename from tests/model-display-names-management-api.test.ts rename to tests/codex-integration/model-display-names-management-api.test.ts index 468584536e4..ea11600e833 100644 --- a/tests/model-display-names-management-api.test.ts +++ b/tests/codex-integration/model-display-names-management-api.test.ts @@ -1,9 +1,9 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { clearModelCache, getFreshCached, setCached } from "../src/codex/model-cache"; -import type { CatalogDisposition } from "../src/codex/convergence-types"; -import { listManagementModelRows, toExportModel } from "../src/server/management/model-rows"; -import { handleModelRoutes } from "../src/server/management/model-routes"; -import type { OcxConfig } from "../src/types"; +import { clearModelCache, getFreshCached, setCached } from "../../src/codex/model-cache"; +import type { CatalogDisposition } from "../../src/codex/convergence-types"; +import { listManagementModelRows, toExportModel } from "../../src/server/management/model-rows"; +import { handleModelRoutes } from "../../src/server/management/model-routes"; +import type { OcxConfig } from "../../src/types"; const DISPLAY_PROVIDER = "display-test"; diff --git a/tests/model-metadata-sync.test.ts b/tests/codex-integration/model-metadata-sync.test.ts similarity index 86% rename from tests/model-metadata-sync.test.ts rename to tests/codex-integration/model-metadata-sync.test.ts index dfe5ae43709..47d7c5b8953 100644 --- a/tests/model-metadata-sync.test.ts +++ b/tests/codex-integration/model-metadata-sync.test.ts @@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test"; import { existsSync, mkdtempSync, readFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; +import { repoPath, repoRoot } from "../helpers/repo-root"; /** * `src/generated/model-metadata.ts` is generated from the vendored snapshot @@ -15,10 +16,10 @@ import { join, resolve } from "node:path"; * everywhere, including CI. Refreshing the metadata is one deliberate commit: replace the * snapshot and rerun `bun run generate:model-metadata`. */ -const GENERATED = resolve(import.meta.dir, "../src/generated/model-metadata.ts"); +const GENERATED = repoPath("src/generated/model-metadata.ts"); // Mirror the generator's fixed source: the vendored snapshot next to the script, so the guard is // deterministic in worktrees and CI. -const SOURCE = resolve(import.meta.dir, "../scripts/model-metadata.source.json"); +const SOURCE = repoPath("scripts/model-metadata.source.json"); describe("generated model metadata stays in sync with its source", () => { test.skipIf(!existsSync(SOURCE))( @@ -28,9 +29,9 @@ describe("generated model metadata stays in sync with its source", () => { const outPath = join(outDir, "model-metadata.ts"); const proc = Bun.spawn( - ["bun", resolve(import.meta.dir, "../scripts/generate-model-metadata.ts")], + ["bun", repoPath("scripts/generate-model-metadata.ts")], { - cwd: resolve(import.meta.dir, ".."), + cwd: repoRoot(), env: { ...process.env, MODEL_METADATA_OUT: outPath }, stdout: "pipe", stderr: "pipe", diff --git a/tests/model-visibility-management-api.test.ts b/tests/codex-integration/model-visibility-management-api.test.ts similarity index 95% rename from tests/model-visibility-management-api.test.ts rename to tests/codex-integration/model-visibility-management-api.test.ts index 17375779353..6259818667f 100644 --- a/tests/model-visibility-management-api.test.ts +++ b/tests/codex-integration/model-visibility-management-api.test.ts @@ -1,12 +1,12 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync} from "node:fs"; import { join } from "node:path"; -import { nativeModelRows } from "../src/codex/catalog"; -import { loadConfig, saveConfig } from "../src/config"; -import { handleManagementAPI } from "../src/server/management-api"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { catalogConvergenceFactory } from "./helpers/catalog-convergence"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { nativeModelRows } from "../../src/codex/catalog"; +import { loadConfig, saveConfig } from "../../src/config"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { catalogConvergenceFactory } from "../helpers/catalog-convergence"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, `.tmp-model-visibility-management-${process.pid}`); const previousOpencodexHome = process.env.OPENCODEX_HOME; @@ -65,10 +65,10 @@ async function put(body: unknown): Promise { describe("atomic model visibility management", () => { test("catalog busy maps management and v1 models to 503 startup to warn-skip and system-env to skip", async () => { - const management = await Bun.file(new URL("../src/server/management-api.ts", import.meta.url)).text(); - const server = await Bun.file(new URL("../src/server/index.ts", import.meta.url)).text(); - const prewarm = await Bun.file(new URL("../src/cli/catalog-prewarm.ts", import.meta.url)).text(); - const systemEnv = await Bun.file(new URL("../src/server/system-env.ts", import.meta.url)).text(); + const management = await Bun.file(new URL("../../src/server/management-api.ts", import.meta.url)).text(); + const server = await Bun.file(new URL("../../src/server/index.ts", import.meta.url)).text(); + const prewarm = await Bun.file(new URL("../../src/cli/catalog-prewarm.ts", import.meta.url)).text(); + const systemEnv = await Bun.file(new URL("../../src/server/system-env.ts", import.meta.url)).text(); for (const source of [management, server]) { expect(source).toContain("CatalogGatherBusyError"); expect(source).toContain('"catalog_busy"'); @@ -365,4 +365,4 @@ describe("atomic model visibility management", () => { expect(loadConfig()).toEqual(before); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/multi-agent-compat.test.ts b/tests/codex-integration/multi-agent-compat.test.ts similarity index 99% rename from tests/multi-agent-compat.test.ts rename to tests/codex-integration/multi-agent-compat.test.ts index c295a25e27e..ac5956c5c70 100644 --- a/tests/multi-agent-compat.test.ts +++ b/tests/codex-integration/multi-agent-compat.test.ts @@ -7,18 +7,18 @@ import { afterAll, afterEach, beforeAll, describe, expect, test } from "bun:test import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { injectDeveloperMessage, multiAgentGuidanceText, sanitizeEncryptedContentInPlace } from "../src/server/responses"; -import { parseRequest } from "../src/responses/parser"; -import type { OcxParsedRequest } from "../src/types"; -import { CODEX_ACCOUNT_BOUND_CATALOG_KIND, effectiveSubagentRoster } from "../src/codex/catalog"; -import { collectCodexAppServerCatalogState, resetCodexAppServerCatalogStateCache } from "../src/codex/app-server-processes"; -import { setTrustedWindowsElevationExecutablesForTests } from "../src/lib/windows-elevation"; -import { createWindowsPowerShellFixture, type WindowsPowerShellFixture } from "./helpers/windows-power-shell-fixture"; -import { clearDebugSettings, setDebugSettings } from "../src/lib/debug-settings"; +import { injectDeveloperMessage, multiAgentGuidanceText, sanitizeEncryptedContentInPlace } from "../../src/server/responses"; +import { parseRequest } from "../../src/responses/parser"; +import type { OcxParsedRequest } from "../../src/types"; +import { CODEX_ACCOUNT_BOUND_CATALOG_KIND, effectiveSubagentRoster } from "../../src/codex/catalog"; +import { collectCodexAppServerCatalogState, resetCodexAppServerCatalogStateCache } from "../../src/codex/app-server-processes"; +import { setTrustedWindowsElevationExecutablesForTests } from "../../src/lib/windows-elevation"; +import { createWindowsPowerShellFixture, type WindowsPowerShellFixture } from "../helpers/windows-power-shell-fixture"; +import { clearDebugSettings, setDebugSettings } from "../../src/lib/debug-settings"; import { getInjectionDebugLogEntries, resetInjectionDebugLogBufferForTests, -} from "../src/lib/injection-debug-log"; +} from "../../src/lib/injection-debug-log"; const savedCodexHome = process.env.CODEX_HOME; const savedCatalogStateOverride = process.env.OPENCODEX_APP_SERVER_CATALOG_STATE_OVERRIDE; diff --git a/tests/multi-agent-keep-native-v1.test.ts b/tests/codex-integration/multi-agent-keep-native-v1.test.ts similarity index 96% rename from tests/multi-agent-keep-native-v1.test.ts rename to tests/codex-integration/multi-agent-keep-native-v1.test.ts index da951b5c4a8..d774c6e8e7d 100644 --- a/tests/multi-agent-keep-native-v1.test.ts +++ b/tests/codex-integration/multi-agent-keep-native-v1.test.ts @@ -6,15 +6,15 @@ import { applyMultiAgentMode, catalogEntryIsNativeChatGpt, type RawEntry, -} from "../src/codex/catalog/parsing"; -import { CODEX_NATIVE_ALIAS_CATALOG_KIND } from "../src/codex/catalog/kinds"; -import { buildCatalogEntriesFromObservedState } from "../src/codex/catalog/sync"; -import { cmdV2 } from "../src/cli/v2"; -import { loadConfig, saveConfig } from "../src/config"; -import { isMultiAgentV2Enabled } from "../src/codex/features"; -import { handleManagementAPI } from "../src/server/management-api"; -import { catalogConvergenceFactory } from "./helpers/catalog-convergence"; -import type { OcxConfig } from "../src/types"; +} from "../../src/codex/catalog/parsing"; +import { CODEX_NATIVE_ALIAS_CATALOG_KIND } from "../../src/codex/catalog/kinds"; +import { buildCatalogEntriesFromObservedState } from "../../src/codex/catalog/sync"; +import { cmdV2 } from "../../src/cli/v2"; +import { loadConfig, saveConfig } from "../../src/config"; +import { isMultiAgentV2Enabled } from "../../src/codex/features"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { catalogConvergenceFactory } from "../helpers/catalog-convergence"; +import type { OcxConfig } from "../../src/types"; describe("keepNativeChatGptOnV1", () => { test("v2 without the switch stamps every row v2", () => { diff --git a/tests/native-alias-maintainer-regressions.test.ts b/tests/codex-integration/native-alias-maintainer-regressions.test.ts similarity index 96% rename from tests/native-alias-maintainer-regressions.test.ts rename to tests/codex-integration/native-alias-maintainer-regressions.test.ts index f93edc500ec..6426b712c96 100644 --- a/tests/native-alias-maintainer-regressions.test.ts +++ b/tests/codex-integration/native-alias-maintainer-regressions.test.ts @@ -3,13 +3,13 @@ import { catalogHasRoutedEntries, type CatalogModel, type RawEntry, -} from "../src/codex/catalog/parsing"; +} from "../../src/codex/catalog/parsing"; import { buildCatalogEntries, mergeCatalogEntriesForSync, mergeCatalogModelsWithNativeRecovery, -} from "../src/codex/catalog/sync"; -import { CODEX_NATIVE_ALIAS_CATALOG_KIND } from "../src/codex/catalog/kinds"; +} from "../../src/codex/catalog/sync"; +import { CODEX_NATIVE_ALIAS_CATALOG_KIND } from "../../src/codex/catalog/kinds"; function aliasModel(slug: string): CatalogModel { return { diff --git a/tests/native-claude-code-toggle.test.ts b/tests/codex-integration/native-claude-code-toggle.test.ts similarity index 98% rename from tests/native-claude-code-toggle.test.ts rename to tests/codex-integration/native-claude-code-toggle.test.ts index 59ad138bf20..e0ae5dffb34 100644 --- a/tests/native-claude-code-toggle.test.ts +++ b/tests/codex-integration/native-claude-code-toggle.test.ts @@ -1,6 +1,6 @@ import { expect, test } from "bun:test"; -import { handleManagementAPI } from "../src/server/management-api"; -import type { OcxConfig } from "../src/types"; +import { handleManagementAPI } from "../../src/server/management-api"; +import type { OcxConfig } from "../../src/types"; /** * Route contract for devlog/_fin/260803_integrations_toggle_all/011. diff --git a/tests/native-claude-desktop-toggle.test.ts b/tests/codex-integration/native-claude-desktop-toggle.test.ts similarity index 97% rename from tests/native-claude-desktop-toggle.test.ts rename to tests/codex-integration/native-claude-desktop-toggle.test.ts index 248f24d85ab..8f843f7c518 100644 --- a/tests/native-claude-desktop-toggle.test.ts +++ b/tests/codex-integration/native-claude-desktop-toggle.test.ts @@ -2,12 +2,12 @@ import { afterEach, beforeEach, expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { handleManagementAPI } from "../src/server/management-api"; -import { setIntegrationEnabled } from "../src/codex/desired-state"; -import { MANAGEMENT_JSON_BODY_MAX_BYTES } from "../src/server/management/body"; -import type { ManagementApiDeps } from "../src/server/management/context"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { setIntegrationEnabled } from "../../src/codex/desired-state"; +import { MANAGEMENT_JSON_BODY_MAX_BYTES } from "../../src/server/management/body"; +import type { ManagementApiDeps } from "../../src/server/management/context"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let root = ""; let library = ""; diff --git a/tests/native-codex-toggle.test.ts b/tests/codex-integration/native-codex-toggle.test.ts similarity index 96% rename from tests/native-codex-toggle.test.ts rename to tests/codex-integration/native-codex-toggle.test.ts index bd15a3f2c50..d78e41c1d29 100644 --- a/tests/native-codex-toggle.test.ts +++ b/tests/codex-integration/native-codex-toggle.test.ts @@ -16,10 +16,10 @@ import { mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { homedir, tmpdir } from "node:os"; import { join } from "node:path"; -import { handleManagementAPI } from "../src/server/management-api"; -import type { ManagementApiDeps } from "../src/server/management/context"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { handleManagementAPI } from "../../src/server/management-api"; +import type { ManagementApiDeps } from "../../src/server/management/context"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let fixtureRoot = ""; let previousOpencodexHome: string | undefined; diff --git a/tests/native-grok-toggle.test.ts b/tests/codex-integration/native-grok-toggle.test.ts similarity index 95% rename from tests/native-grok-toggle.test.ts rename to tests/codex-integration/native-grok-toggle.test.ts index e73113eed25..d7c53f22244 100644 --- a/tests/native-grok-toggle.test.ts +++ b/tests/codex-integration/native-grok-toggle.test.ts @@ -2,12 +2,13 @@ import { afterEach, beforeEach, expect, test } from "bun:test"; import { mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { homedir, tmpdir } from "node:os"; import { join } from "node:path"; -import { handleManagementAPI } from "../src/server/management-api"; -import type { ManagementApiDeps } from "../src/server/management/context"; -import { syncGrokConfig } from "../src/grok/sync"; -import { injectGrokConfig, type GrokInjectModel } from "../src/grok/inject"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { handleManagementAPI } from "../../src/server/management-api"; +import type { ManagementApiDeps } from "../../src/server/management/context"; +import { syncGrokConfig } from "../../src/grok/sync"; +import { injectGrokConfig, type GrokInjectModel } from "../../src/grok/inject"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { repoPath } from "../helpers/repo-root"; /** * Route contract for devlog/_fin/260803_integrations_toggle_all/012 (Rev 3). @@ -334,14 +335,14 @@ test("a catalog failure refuses and writes nothing", async () => { }); test("the route never calls syncGrokConfig, and the inspector never re-implements the parser", () => { - const routeSource = readFileSync(join(import.meta.dir, "../src/server/management/native-integration-routes.ts"), "utf8"); + const routeSource = readFileSync(repoPath("src/server/management/native-integration-routes.ts"), "utf8"); // Comments may NAME the wrapper (they explain why it is bypassed); what must // not exist is an import of it or a call to it. expect(routeSource).not.toMatch(/import\s*\{[^}]*syncGrokConfig/); expect(routeSource).not.toMatch(/[^A-Za-z]syncGrokConfig\s*\(/); - const inspectSource = readFileSync(join(import.meta.dir, "../src/grok/inspect.ts"), "utf8"); + const inspectSource = readFileSync(repoPath("src/grok/inspect.ts"), "utf8"); expect(inspectSource).not.toContain("function findManagedRegion"); - const injectSource = readFileSync(join(import.meta.dir, "../src/grok/inject.ts"), "utf8"); + const injectSource = readFileSync(repoPath("src/grok/inject.ts"), "utf8"); expect(injectSource.match(/function findManagedRegion/g)).toHaveLength(1); }); @@ -499,12 +500,12 @@ test("a second concurrent PUT gets 409 config_busy and writes nothing", async () test("no journal row and no snapshot exist for this toggle", () => { // The module must not touch the file-client bookkeeping at all — a static // check that the imports were never widened (012 §OUT). - const routeSource = readFileSync(join(import.meta.dir, "../src/server/management/native-integration-routes.ts"), "utf8"); + const routeSource = readFileSync(repoPath("src/server/management/native-integration-routes.ts"), "utf8"); expect(routeSource).not.toMatch(/import[^;]*integrations\/(journal|store|writer)/); }); test("the ownership preflight itself is reachable, not declared", async () => { - const { assertNativeTeardownOwned } = await import("../src/integrations/native/ownership-preflight"); + const { assertNativeTeardownOwned } = await import("../../src/integrations/native/ownership-preflight"); // The beforeEach fixture already records the CURRENT homes under // OPENCODEX_HOME: owned. expect(assertNativeTeardownOwned().ok).toBe(true); diff --git a/tests/native-main-auth-temp.test.ts b/tests/codex-integration/native-main-auth-temp.test.ts similarity index 94% rename from tests/native-main-auth-temp.test.ts rename to tests/codex-integration/native-main-auth-temp.test.ts index 673b1e0eead..ab924f8e27e 100644 --- a/tests/native-main-auth-temp.test.ts +++ b/tests/codex-integration/native-main-auth-temp.test.ts @@ -13,10 +13,10 @@ import { import { tmpdir } from "node:os"; import { join } from "node:path"; -import { scrubNativeMainAuthTempResidues } from "../src/codex/native-main-auth-temp"; -import { resolveNativeProfileContext } from "../src/codex/native-profile-store"; -import { NativeProfileError } from "../src/codex/native-profile-types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { scrubNativeMainAuthTempResidues } from "../../src/codex/native-main-auth-temp"; +import { resolveNativeProfileContext } from "../../src/codex/native-profile-store"; +import { NativeProfileError } from "../../src/codex/native-profile-types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; diff --git a/tests/native-main-claim-cache.test.ts b/tests/codex-integration/native-main-claim-cache.test.ts similarity index 97% rename from tests/native-main-claim-cache.test.ts rename to tests/codex-integration/native-main-claim-cache.test.ts index b4adbf8a032..af19c6394d9 100644 --- a/tests/native-main-claim-cache.test.ts +++ b/tests/codex-integration/native-main-claim-cache.test.ts @@ -4,7 +4,7 @@ import { hardenedIdentities, NATIVE_MAIN_HARDENED_IDENTITY_MAX_ENTRIES, rememberHardenedIdentity, -} from "../src/codex/native-main-claim"; +} from "../../src/codex/native-main-claim"; beforeEach(() => { hardenedIdentities.clear(); diff --git a/tests/native-main-claim.test.ts b/tests/codex-integration/native-main-claim.test.ts similarity index 95% rename from tests/native-main-claim.test.ts rename to tests/codex-integration/native-main-claim.test.ts index 05316650fd8..f4754b550bf 100644 --- a/tests/native-main-claim.test.ts +++ b/tests/codex-integration/native-main-claim.test.ts @@ -7,10 +7,11 @@ import { nativeMainClaimPath, withNativeMainExclusiveClaim, withNativeMainSharedClaim, -} from "../src/codex/native-main-claim"; -import { retainNativeMainOwner } from "../src/codex/native-main-owner"; -import type { NativeProfileContext } from "../src/codex/native-profile-store"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/native-main-claim"; +import { retainNativeMainOwner } from "../../src/codex/native-main-owner"; +import type { NativeProfileContext } from "../../src/codex/native-profile-store"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { helperPath, repoRoot } from "../helpers/repo-root"; const roots: string[] = []; const noHardening = async (): Promise => {}; @@ -118,9 +119,9 @@ describe("native-main shared and exclusive claims", () => { const child = Bun.spawn([ process.execPath, - join(import.meta.dir, "helpers", "native-main-claim-child.ts"), + helperPath("native-main-claim-child.ts"), context.codexHome, - ], { cwd: join(import.meta.dir, ".."), stdout: "pipe", stderr: "pipe" }); + ], { cwd: repoRoot(), stdout: "pipe", stderr: "pipe" }); const [exitCode, stdout, stderr] = await Promise.all([ child.exited, new Response(child.stdout).text(), diff --git a/tests/native-main-owner-lifetime.test.ts b/tests/codex-integration/native-main-owner-lifetime.test.ts similarity index 97% rename from tests/native-main-owner-lifetime.test.ts rename to tests/codex-integration/native-main-owner-lifetime.test.ts index b88a05f56e1..49d42dcae6b 100644 --- a/tests/native-main-owner-lifetime.test.ts +++ b/tests/codex-integration/native-main-owner-lifetime.test.ts @@ -11,21 +11,22 @@ import { } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; -import { watchdogMs } from "./helpers/ci-watchdog"; +import { watchdogMs } from "../helpers/ci-watchdog"; -import { saveConfig } from "../src/config"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/main-account"; +import { saveConfig } from "../../src/config"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/main-account"; import { NATIVE_MAIN_OWNER_DB, nativeMainOwnerFilesystemSupported, retainNativeMainOwner, withNativeMainOwnerOperation, -} from "../src/codex/native-main-owner"; -import { NativeProfileManager } from "../src/codex/native-profile-manager"; -import { probeNativeProfileRecoveryState } from "../src/codex/native-profile-store"; -import type { NativeProfileKey, NativeProfileKeyProvider } from "../src/codex/native-profile-types"; -import type { OcxConfig } from "../src/types"; +} from "../../src/codex/native-main-owner"; +import { NativeProfileManager } from "../../src/codex/native-profile-manager"; +import { probeNativeProfileRecoveryState } from "../../src/codex/native-profile-store"; +import type { NativeProfileKey, NativeProfileKeyProvider } from "../../src/codex/native-profile-types"; +import type { OcxConfig } from "../../src/types"; +import { helperPath, repoRoot } from "../helpers/repo-root"; const roots: string[] = []; const previousCodexHome = process.env.CODEX_HOME; @@ -165,8 +166,8 @@ class ChildHarness { private readonly waiters = new Set<() => void>(); constructor(f: Fixture, extraEnv: Record = {}) { - this.child = Bun.spawn([process.execPath, join(import.meta.dir, "helpers", "native-main-owner-child.ts")], { - cwd: join(import.meta.dir, ".."), + this.child = Bun.spawn([process.execPath, helperPath("native-main-owner-child.ts")], { + cwd: repoRoot(), env: { ...process.env, HOME: f.root, diff --git a/tests/native-model-toggle.test.ts b/tests/codex-integration/native-model-toggle.test.ts similarity index 98% rename from tests/native-model-toggle.test.ts rename to tests/codex-integration/native-model-toggle.test.ts index 60bc5e7ec27..52044cde5af 100644 --- a/tests/native-model-toggle.test.ts +++ b/tests/codex-integration/native-model-toggle.test.ts @@ -22,18 +22,18 @@ import { trustedAccountBoundNativeCatalogSlug, visibleCodexAccountSelectors, visibleNativeSlugs, -} from "../src/codex/catalog"; -import { handleManagementAPI } from "../src/server/management-api"; -import { applyMultiAgentMode, applyNativeOpenAiContextOverride } from "../src/codex/catalog/parsing"; -import { NATIVE_GPT56_CONTEXT_WINDOW, NATIVE_GPT56_OPT_IN_CONTEXT_WINDOW, nativeOpenAiContextTier, nativeOpenAiContextWindow } from "../src/codex/catalog"; -import type { OcxConfig } from "../src/types"; -import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../src/codex/catalog/native-models"; +} from "../../src/codex/catalog"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { applyMultiAgentMode, applyNativeOpenAiContextOverride } from "../../src/codex/catalog/parsing"; +import { NATIVE_GPT56_CONTEXT_WINDOW, NATIVE_GPT56_OPT_IN_CONTEXT_WINDOW, nativeOpenAiContextTier, nativeOpenAiContextWindow } from "../../src/codex/catalog"; +import type { OcxConfig } from "../../src/types"; +import { ACCOUNT_GATED_NATIVE_OPENAI_MODELS } from "../../src/codex/catalog/native-models"; import { GATED_MODEL_CLIENT_VERSION_FLOOR, resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests, -} from "../src/codex/model-entitlements"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/model-entitlements"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; afterEach(() => resetCodexModelEntitlementCacheForTests()); @@ -835,7 +835,7 @@ describe("native GPT model toggles (bare slugs in disabledModels)", () => { } }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; describe("#2574 a stale on-disk row is what a subagent reads", () => { /** diff --git a/tests/native-profile-api.test.ts b/tests/codex-integration/native-profile-api.test.ts similarity index 98% rename from tests/native-profile-api.test.ts rename to tests/codex-integration/native-profile-api.test.ts index 89a3ff36ea8..dafe059a6b4 100644 --- a/tests/native-profile-api.test.ts +++ b/tests/codex-integration/native-profile-api.test.ts @@ -1,21 +1,21 @@ import { afterEach, describe, expect, test } from "bun:test"; import { join } from "node:path"; import { tmpdir, userInfo } from "node:os"; -import type { OcxConfig } from "../src/types"; -import { handleNativeProfileAPI } from "../src/codex/native-profile-api"; -import type { NativeProfileManager } from "../src/codex/native-profile-manager"; -import { NativeProfileError } from "../src/codex/native-profile-types"; +import type { OcxConfig } from "../../src/types"; +import { handleNativeProfileAPI } from "../../src/codex/native-profile-api"; +import type { NativeProfileManager } from "../../src/codex/native-profile-manager"; +import { NativeProfileError } from "../../src/codex/native-profile-types"; import { codexAccountSelectionForTurn, resetLifecycleDrainStateForTests, tryAdmitTurn, -} from "../src/server/lifecycle"; +} from "../../src/server/lifecycle"; import { blockNativeMainRecovery, completeNativeMainRecovery, initializeNativeMainStartupGate, nativeMainStartupGateSnapshot, -} from "../src/codex/native-profile-startup"; +} from "../../src/codex/native-profile-startup"; const originalCodexHome = process.env.CODEX_HOME; diff --git a/tests/native-profile-crash-boundaries.test.ts b/tests/codex-integration/native-profile-crash-boundaries.test.ts similarity index 95% rename from tests/native-profile-crash-boundaries.test.ts rename to tests/codex-integration/native-profile-crash-boundaries.test.ts index 48bd106b90b..59624a379a1 100644 --- a/tests/native-profile-crash-boundaries.test.ts +++ b/tests/codex-integration/native-profile-crash-boundaries.test.ts @@ -3,15 +3,16 @@ import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/main-account"; -import { NativeProfileManager, type NativeProfileSwitchBoundary } from "../src/codex/native-profile-manager"; -import { readNativeProfileJournal, readNativeProfileVault } from "../src/codex/native-profile-store"; -import type { NativeProfileKey, NativeProfileKeyProvider } from "../src/codex/native-profile-types"; -import type { OcxConfig } from "../src/types"; -import { INTERNAL_DEADLINE_MS } from "./helpers/test-budget"; -import { watchdogMs } from "./helpers/ci-watchdog"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { saveConfig } from "../../src/config"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/main-account"; +import { NativeProfileManager, type NativeProfileSwitchBoundary } from "../../src/codex/native-profile-manager"; +import { readNativeProfileJournal, readNativeProfileVault } from "../../src/codex/native-profile-store"; +import type { NativeProfileKey, NativeProfileKeyProvider } from "../../src/codex/native-profile-types"; +import type { OcxConfig } from "../../src/types"; +import { INTERNAL_DEADLINE_MS } from "../helpers/test-budget"; +import { watchdogMs } from "../helpers/ci-watchdog"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { helperPath, repoRoot } from "../helpers/repo-root"; /** * How long to wait for a spawned startup child to publish its port file. @@ -160,8 +161,8 @@ async function stopStartup( } function spawnSwitch(f: Awaited>, options: { boundary?: NativeProfileSwitchBoundary; marker?: string; release?: string; contention?: string; result: string }) { - return Bun.spawn([process.execPath, join(import.meta.dir, "helpers", "native-profile-switch-child.ts")], { - cwd: join(import.meta.dir, ".."), + return Bun.spawn([process.execPath, helperPath("native-profile-switch-child.ts")], { + cwd: repoRoot(), env: { ...process.env, HOME: f.home, @@ -190,8 +191,8 @@ function spawnStartup( p: ReturnType, extraEnv: Record = {}, ) { - return Bun.spawn([process.execPath, join(import.meta.dir, "helpers", "native-profile-startup-child.ts")], { - cwd: join(import.meta.dir, ".."), + return Bun.spawn([process.execPath, helperPath("native-profile-startup-child.ts")], { + cwd: repoRoot(), env: { ...process.env, HOME: f.home, USERPROFILE: f.home, CODEX_HOME: f.codexHome, OPENCODEX_HOME: f.configDir, OPENCODEX_ADMIN_AUTH_TOKEN: "crash-test-admin", diff --git a/tests/native-profile-drain-server.test.ts b/tests/codex-integration/native-profile-drain-server.test.ts similarity index 93% rename from tests/native-profile-drain-server.test.ts rename to tests/codex-integration/native-profile-drain-server.test.ts index 48ecbe9b606..34fc9f71c5f 100644 --- a/tests/native-profile-drain-server.test.ts +++ b/tests/codex-integration/native-profile-drain-server.test.ts @@ -3,29 +3,29 @@ import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { request as httpRequest } from "node:http"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { resetMainCodexAccountIdentityTrackingForTests } from "../src/codex/account-lifecycle"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/account-id"; -import { clearMainAccountInfoCache } from "../src/codex/main-account-cache"; -import { clearAccountQuota, updateAccountQuota } from "../src/codex/quota"; -import { clearThreadAccountMap } from "../src/codex/routing"; -import { saveConfig } from "../src/config"; -import { handleNativeProfileAPI } from "../src/codex/native-profile-api"; -import { CODEX_MAIN_PROFILE_MAINTENANCE_MESSAGE } from "../src/codex/auth-context"; -import type { NativeProfileManager } from "../src/codex/native-profile-manager"; -import { waitForNativeMainStartupGate } from "../src/codex/native-profile-startup"; -import { startServer } from "../src/server"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { resetMainCodexAccountIdentityTrackingForTests } from "../../src/codex/account-lifecycle"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/account-id"; +import { clearMainAccountInfoCache } from "../../src/codex/main-account-cache"; +import { clearAccountQuota, updateAccountQuota } from "../../src/codex/quota"; +import { clearThreadAccountMap } from "../../src/codex/routing"; +import { saveConfig } from "../../src/config"; +import { handleNativeProfileAPI } from "../../src/codex/native-profile-api"; +import { CODEX_MAIN_PROFILE_MAINTENANCE_MESSAGE } from "../../src/codex/auth-context"; +import type { NativeProfileManager } from "../../src/codex/native-profile-manager"; +import { waitForNativeMainStartupGate } from "../../src/codex/native-profile-startup"; +import { startServer } from "../../src/server"; import { acquireNativeMainProfileDrain, getNativeMainProfileRequestCount, resetLifecycleDrainStateForTests, -} from "../src/server/lifecycle"; -import type { OcxConfig } from "../src/types"; -import { fakeChatGptJwt } from "./helpers/fake-chatgpt-jwt"; -import { ownedServiceHomeInspection } from "./helpers/owned-service-home-inspection"; +} from "../../src/server/lifecycle"; +import type { OcxConfig } from "../../src/types"; +import { fakeChatGptJwt } from "../helpers/fake-chatgpt-jwt"; +import { ownedServiceHomeInspection } from "../helpers/owned-service-home-inspection"; -import { watchdogMs } from "./helpers/ci-watchdog"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { watchdogMs } from "../helpers/ci-watchdog"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** These cases sandbox CODEX_HOME/OPENCODEX_HOME, so the installed service is not their evidence. */ const inspectNativeCodexOwnership = ownedServiceHomeInspection("native-profile drain server test"); diff --git a/tests/native-profile-manager.test.ts b/tests/codex-integration/native-profile-manager.test.ts similarity index 99% rename from tests/native-profile-manager.test.ts rename to tests/codex-integration/native-profile-manager.test.ts index 8e0d6547963..5d7a29509f2 100644 --- a/tests/native-profile-manager.test.ts +++ b/tests/codex-integration/native-profile-manager.test.ts @@ -2,7 +2,7 @@ import { afterEach, describe, expect, test } from "bun:test"; import { existsSync, linkSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; -import { NativeProfileManager } from "../src/codex/native-profile-manager"; +import { NativeProfileManager } from "../../src/codex/native-profile-manager"; import { decryptNativeEnvelope, MAX_NATIVE_PROFILE_JOURNAL_BYTES, @@ -12,10 +12,11 @@ import { probeNativeProfileRecoveryState, readNativeProfileVault, type NativeEnvelopeSnapshot, -} from "../src/codex/native-profile-store"; -import { NativeProfileError, type NativeProfileKey, type NativeProfileKeyProvider } from "../src/codex/native-profile-types"; -import { codexCredentialMutationEpoch } from "../src/codex/credential-mutation-epoch"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/native-profile-store"; +import { NativeProfileError, type NativeProfileKey, type NativeProfileKeyProvider } from "../../src/codex/native-profile-types"; +import { codexCredentialMutationEpoch } from "../../src/codex/credential-mutation-epoch"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { helperPath, repoRoot } from "../helpers/repo-root"; const roots: string[] = []; @@ -155,8 +156,8 @@ function spawnLockHolder( releasePath: string, options: { crash?: boolean; contention?: string } = {}, ): ReturnType { - return Bun.spawn([process.execPath, join(import.meta.dir, "helpers", "native-profile-lock-child.ts")], { - cwd: join(import.meta.dir, ".."), + return Bun.spawn([process.execPath, helperPath("native-profile-lock-child.ts")], { + cwd: repoRoot(), env: { ...process.env, NATIVE_PROFILE_TEST_CODEX_HOME: f.codexHome, @@ -176,8 +177,8 @@ function spawnLockProbe( f: ReturnType, resultPath: string, ): ReturnType { - return Bun.spawn([process.execPath, join(import.meta.dir, "helpers", "native-profile-lock-child.ts")], { - cwd: join(import.meta.dir, ".."), + return Bun.spawn([process.execPath, helperPath("native-profile-lock-child.ts")], { + cwd: repoRoot(), env: { ...process.env, NATIVE_PROFILE_TEST_CODEX_HOME: f.codexHome, diff --git a/tests/native-profile-processes.test.ts b/tests/codex-integration/native-profile-processes.test.ts similarity index 98% rename from tests/native-profile-processes.test.ts rename to tests/codex-integration/native-profile-processes.test.ts index 84278116763..0a5c449d123 100644 --- a/tests/native-profile-processes.test.ts +++ b/tests/codex-integration/native-profile-processes.test.ts @@ -6,9 +6,9 @@ import { executeNativeProcess, probeNativeCodexProcesses, type NativeProcessExecutor, -} from "../src/codex/native-profile-processes"; -import { setTrustedWindowsSystemDirectoryResolverForTests } from "../src/lib/windows-elevation"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/native-profile-processes"; +import { setTrustedWindowsSystemDirectoryResolverForTests } from "../../src/lib/windows-elevation"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; async function withTrustedWindowsPowerShell(run: (powershell: string) => Promise): Promise { const systemDirectory = mkdtempSync(join(tmpdir(), "ocx-system32-")); diff --git a/tests/native-profile-recovery.test.ts b/tests/codex-integration/native-profile-recovery.test.ts similarity index 98% rename from tests/native-profile-recovery.test.ts rename to tests/codex-integration/native-profile-recovery.test.ts index 4e7eb57f4ed..b9cce8ed1c5 100644 --- a/tests/native-profile-recovery.test.ts +++ b/tests/codex-integration/native-profile-recovery.test.ts @@ -4,7 +4,7 @@ import { decideNativeProfileRecovery, type NativeProfileAuthObservation, type NativeProfileJournalPhase, -} from "../src/codex/native-profile-recovery"; +} from "../../src/codex/native-profile-recovery"; const phases: NativeProfileJournalPhase[] = [ "prepared", diff --git a/tests/native-profile-route-security.test.ts b/tests/codex-integration/native-profile-route-security.test.ts similarity index 95% rename from tests/native-profile-route-security.test.ts rename to tests/codex-integration/native-profile-route-security.test.ts index 87075959ea6..4185b2f19c5 100644 --- a/tests/native-profile-route-security.test.ts +++ b/tests/codex-integration/native-profile-route-security.test.ts @@ -2,14 +2,14 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; -import type { NativeProfileManager } from "../src/codex/native-profile-manager"; -import { startServer } from "../src/server"; -import { initializeManagementAuthState, issueGuiSession, type ManagementAuthState } from "../src/server/management-auth"; -import { consumeGuiPairingGrant, createGuiPairingGrant } from "../src/server/gui-session"; -import type { OcxConfig } from "../src/types"; -import { SERVER_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { saveConfig } from "../../src/config"; +import type { NativeProfileManager } from "../../src/codex/native-profile-manager"; +import { startServer } from "../../src/server"; +import { initializeManagementAuthState, issueGuiSession, type ManagementAuthState } from "../../src/server/management-auth"; +import { consumeGuiPairingGrant, createGuiPairingGrant } from "../../src/server/gui-session"; +import type { OcxConfig } from "../../src/types"; +import { SERVER_BUDGET_MS } from "../helpers/test-budget"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const previousHome = process.env.HOME; const previousOpenCodexHome = process.env.OPENCODEX_HOME; diff --git a/tests/native-profile-stage-lifecycle.test.ts b/tests/codex-integration/native-profile-stage-lifecycle.test.ts similarity index 98% rename from tests/native-profile-stage-lifecycle.test.ts rename to tests/codex-integration/native-profile-stage-lifecycle.test.ts index dd521089eb8..bc697118842 100644 --- a/tests/native-profile-stage-lifecycle.test.ts +++ b/tests/codex-integration/native-profile-stage-lifecycle.test.ts @@ -14,12 +14,12 @@ import { import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; -import { NativeProfileManager } from "../src/codex/native-profile-manager"; +import { NativeProfileManager } from "../../src/codex/native-profile-manager"; import { startNativeMainStartupLifecycle, type NativeMainStartupLifecycle, -} from "../src/codex/native-profile-startup"; -import { NativeProfileError, type NativeProfileKey, type NativeProfileKeyProvider } from "../src/codex/native-profile-types"; +} from "../../src/codex/native-profile-startup"; +import { NativeProfileError, type NativeProfileKey, type NativeProfileKeyProvider } from "../../src/codex/native-profile-types"; const roots: string[] = []; const lifecycles: NativeMainStartupLifecycle[] = []; diff --git a/tests/native-profile-startup.test.ts b/tests/codex-integration/native-profile-startup.test.ts similarity index 98% rename from tests/native-profile-startup.test.ts rename to tests/codex-integration/native-profile-startup.test.ts index d9e9123d134..ed0a6227699 100644 --- a/tests/native-profile-startup.test.ts +++ b/tests/codex-integration/native-profile-startup.test.ts @@ -9,11 +9,11 @@ import { import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { MAIN_CODEX_ACCOUNT_ID } from "../src/codex/main-account"; -import { NativeProfileManager } from "../src/codex/native-profile-manager"; -import { handleNativeProfileAPI } from "../src/codex/native-profile-api"; +import { saveConfig } from "../../src/config"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { MAIN_CODEX_ACCOUNT_ID } from "../../src/codex/main-account"; +import { NativeProfileManager } from "../../src/codex/native-profile-manager"; +import { handleNativeProfileAPI } from "../../src/codex/native-profile-api"; import { encryptNativeEnvelope, probeNativeProfileRecoveryState, @@ -21,13 +21,13 @@ import { readNativeProfileVault, inspectNativeProfileJournal, serializeNativeProfileJournal, -} from "../src/codex/native-profile-store"; +} from "../../src/codex/native-profile-store"; import type { NativeProfileKey, NativeProfileKeyProvider, NativeProfileSwitchJournalV1, -} from "../src/codex/native-profile-types"; -import type { OcxConfig } from "../src/types"; +} from "../../src/codex/native-profile-types"; +import type { OcxConfig } from "../../src/types"; import { bindNativeMainStartupLifecycle, blockNativeMainStartupForUnownedServiceHome, @@ -40,19 +40,20 @@ import { type NativeMainStartupLifecycle, waitForNativeMainStartupGate, __resetNativeMainOwnershipRetries, -} from "../src/codex/native-profile-startup"; -import type { NativeCodexOwnership } from "../src/integrations/native/ownership-preflight"; +} from "../../src/codex/native-profile-startup"; +import type { NativeCodexOwnership } from "../../src/integrations/native/ownership-preflight"; import { tryAcquireNativeMainProfileClaim, tryClaimNativeMainProfileForTurn, -} from "../src/codex/native-main-admission"; +} from "../../src/codex/native-main-admission"; import { getNativeMainProfileRequestCount, resetLifecycleDrainStateForTests, tryAdmitTurn, -} from "../src/server/lifecycle"; -import { startServer } from "../src/server"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/server/lifecycle"; +import { startServer } from "../../src/server"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import { helperPath, repoRoot } from "../helpers/repo-root"; const roots: string[] = []; const previousOpencodexHome = process.env.OPENCODEX_HOME; @@ -262,8 +263,8 @@ function childPaths(f: Fixture) { } function spawnChild(f: Fixture, paths: ReturnType): ReturnType { - return Bun.spawn([process.execPath, join(import.meta.dir, "helpers", "native-profile-startup-child.ts")], { - cwd: join(import.meta.dir, ".."), + return Bun.spawn([process.execPath, helperPath("native-profile-startup-child.ts")], { + cwd: repoRoot(), env: { ...process.env, OPENCODEX_HOME: f.configDir, diff --git a/tests/native-profile-store.test.ts b/tests/codex-integration/native-profile-store.test.ts similarity index 98% rename from tests/native-profile-store.test.ts rename to tests/codex-integration/native-profile-store.test.ts index a133c91d03b..13b26b5b424 100644 --- a/tests/native-profile-store.test.ts +++ b/tests/codex-integration/native-profile-store.test.ts @@ -15,15 +15,15 @@ import { resolveNativeProfileContext, serializeNativeProfileJournal, type NativeProfileContext, -} from "../src/codex/native-profile-store"; +} from "../../src/codex/native-profile-store"; import { NativeProfileError, type EncryptedNativeEnvelopeV1, type NativeMainProfileRecordV1, type NativeMainProfileVaultV1, type NativeProfileSwitchJournalV1, -} from "../src/codex/native-profile-types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/native-profile-types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const roots: string[] = []; const HOME_ID = "a".repeat(64); @@ -391,7 +391,7 @@ describe("native-profile recovery journal storage", () => { const configDir = join(base, "opencodex"); mkdirSync(codexHome, { mode: 0o700 }); mkdirSync(configDir, { mode: 0o700 }); - const moduleUrl = new URL("../src/codex/native-profile-store.ts", import.meta.url).href; + const moduleUrl = new URL("../../src/codex/native-profile-store.ts", import.meta.url).href; const childSource = ` import { execFileSync } from "node:child_process"; import { lstatSync, mkdirSync, unlinkSync, writeFileSync } from "node:fs"; diff --git a/tests/parallel-tool-calls-optin.test.ts b/tests/codex-integration/parallel-tool-calls-optin.test.ts similarity index 97% rename from tests/parallel-tool-calls-optin.test.ts rename to tests/codex-integration/parallel-tool-calls-optin.test.ts index 5b154e6ba86..689fd207f80 100644 --- a/tests/parallel-tool-calls-optin.test.ts +++ b/tests/codex-integration/parallel-tool-calls-optin.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { applyProviderConfigHints, normalizeRoutedCatalogEntry } from "../src/codex/catalog"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxParsedRequest, OcxTool } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { applyProviderConfigHints, normalizeRoutedCatalogEntry } from "../../src/codex/catalog"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxParsedRequest, OcxTool } from "../../src/types"; const tools: OcxTool[] = [{ name: "shell", description: "run", parameters: { type: "object" } }]; diff --git a/tests/project-config-warnings.test.ts b/tests/codex-integration/project-config-warnings.test.ts similarity index 99% rename from tests/project-config-warnings.test.ts rename to tests/codex-integration/project-config-warnings.test.ts index f59f7ba99e5..16f9dd258dc 100644 --- a/tests/project-config-warnings.test.ts +++ b/tests/codex-integration/project-config-warnings.test.ts @@ -13,8 +13,8 @@ import { parseTrustedProjectPathsFromCodexConfig, relPath, resolveEffectiveProjectModelProvider, -} from "../src/codex/project-config-warnings"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/codex/project-config-warnings"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; describe("relPath home containment (devlog 260715_cross_platform_audit/030)", () => { let savedUserProfile: string | undefined; diff --git a/tests/reasoning-effort.test.ts b/tests/codex-integration/reasoning-effort.test.ts similarity index 98% rename from tests/reasoning-effort.test.ts rename to tests/codex-integration/reasoning-effort.test.ts index cf34b8070ba..a5d3cd11140 100644 --- a/tests/reasoning-effort.test.ts +++ b/tests/codex-integration/reasoning-effort.test.ts @@ -1,12 +1,12 @@ import { describe, expect, test } from "bun:test"; -import { buildCatalogEntries } from "../src/codex/catalog"; -import { createAnthropicAdapter } from "../src/adapters/anthropic"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import type { AdapterRequest } from "../src/adapters/base"; -import { configuredReasoningEfforts, mapReasoningEffort, sanitizeCodexReasoningEfforts } from "../src/reasoning-effort"; -import { routeModel } from "../src/router"; -import { resolveWireProtocolOverride } from "../src/server/adapter-resolve"; -import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { buildCatalogEntries } from "../../src/codex/catalog"; +import { createAnthropicAdapter } from "../../src/adapters/anthropic"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import type { AdapterRequest } from "../../src/adapters/base"; +import { configuredReasoningEfforts, mapReasoningEffort, sanitizeCodexReasoningEfforts } from "../../src/reasoning-effort"; +import { routeModel } from "../../src/router"; +import { resolveWireProtocolOverride } from "../../src/server/adapter-resolve"; +import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../../src/types"; function nativeTemplate(): Record { return { diff --git a/tests/selected-models.test.ts b/tests/codex-integration/selected-models.test.ts similarity index 98% rename from tests/selected-models.test.ts rename to tests/codex-integration/selected-models.test.ts index 755060410cc..df6aa225865 100644 --- a/tests/selected-models.test.ts +++ b/tests/codex-integration/selected-models.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { filterCatalogVisibleModels, type CatalogModel } from "../src/codex/catalog"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { filterCatalogVisibleModels, type CatalogModel } from "../../src/codex/catalog"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; function m(provider: string, id: string): CatalogModel { return { provider, id, owned_by: provider }; diff --git a/tests/slug-codec.test.ts b/tests/codex-integration/slug-codec.test.ts similarity index 97% rename from tests/slug-codec.test.ts rename to tests/codex-integration/slug-codec.test.ts index 5482fcca17b..611754ce18c 100644 --- a/tests/slug-codec.test.ts +++ b/tests/codex-integration/slug-codec.test.ts @@ -14,13 +14,13 @@ import { slugEquals, slugEquivalenceKey, slugsEquivalent, -} from "../src/providers/slug-codec"; -import { knownModelIdsForProvider, routeModel } from "../src/router"; -import { buildCatalogEntries, resetCatalogRuntimeStateForTests } from "../src/codex/catalog"; -import { clearModelCache, setCached } from "../src/codex/model-cache"; -import { getModelMetadata } from "../src/generated/model-metadata"; -import type { RawEntry } from "../src/codex/catalog"; -import type { OcxConfig } from "../src/types"; +} from "../../src/providers/slug-codec"; +import { knownModelIdsForProvider, routeModel } from "../../src/router"; +import { buildCatalogEntries, resetCatalogRuntimeStateForTests } from "../../src/codex/catalog"; +import { clearModelCache, setCached } from "../../src/codex/model-cache"; +import { getModelMetadata } from "../../src/generated/model-metadata"; +import type { RawEntry } from "../../src/codex/catalog"; +import type { OcxConfig } from "../../src/types"; beforeEach(() => { clearModelCache(); diff --git a/tests/token-guardian.test.ts b/tests/codex-integration/token-guardian.test.ts similarity index 96% rename from tests/token-guardian.test.ts rename to tests/codex-integration/token-guardian.test.ts index d3bcf99ec74..7c8e09ec85e 100644 --- a/tests/token-guardian.test.ts +++ b/tests/codex-integration/token-guardian.test.ts @@ -2,17 +2,17 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveCredential } from "../src/oauth/store"; -import { getConfigPath } from "../src/config"; -import { markCodexAccountValidated, readCodexAccountRecord, saveCodexAccountCredential } from "../src/codex/account-store"; -import { __resetGuardianState, guardianSweep } from "../src/oauth/token-guardian"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { saveCredential } from "../../src/oauth/store"; +import { getConfigPath } from "../../src/config"; +import { markCodexAccountValidated, readCodexAccountRecord, saveCodexAccountCredential } from "../../src/codex/account-store"; +import { __resetGuardianState, guardianSweep } from "../../src/oauth/token-guardian"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; import { acquireNativeMainProfileDrain, getNativeMainProfileRequestCount, resetLifecycleDrainStateForTests, -} from "../src/server/lifecycle"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/server/lifecycle"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const origHome = process.env.HOME; const origOcxHome = process.env.OPENCODEX_HOME; diff --git a/tests/ultrafast-tier-honesty.test.ts b/tests/codex-integration/ultrafast-tier-honesty.test.ts similarity index 97% rename from tests/ultrafast-tier-honesty.test.ts rename to tests/codex-integration/ultrafast-tier-honesty.test.ts index a1f97af6def..9ba3a77d876 100644 --- a/tests/ultrafast-tier-honesty.test.ts +++ b/tests/codex-integration/ultrafast-tier-honesty.test.ts @@ -12,9 +12,9 @@ * for nothing. These tests pin the corrected accounting. */ import { describe, expect, test } from "bun:test"; -import { canonicalFastTierMarker, createAdapterTierMetadata, decideTier, tierObservationContext } from "../src/providers/fastwire"; -import { requestLogSpeedLabel } from "../src/server/request-log"; -import { normalizeRoutedCatalogEntry } from "../src/codex/catalog/parsing"; +import { canonicalFastTierMarker, createAdapterTierMetadata, decideTier, tierObservationContext } from "../../src/providers/fastwire"; +import { requestLogSpeedLabel } from "../../src/server/request-log"; +import { normalizeRoutedCatalogEntry } from "../../src/codex/catalog/parsing"; describe("ultrafast intent is recognised, not mistaken for silence", () => { test("the caller marker folds ultrafast to its own canonical, not to priority", () => { diff --git a/tests/upstream-reachability.test.ts b/tests/codex-integration/upstream-reachability.test.ts similarity index 98% rename from tests/upstream-reachability.test.ts rename to tests/codex-integration/upstream-reachability.test.ts index 6c3a32a2d72..064131bec4f 100644 --- a/tests/upstream-reachability.test.ts +++ b/tests/codex-integration/upstream-reachability.test.ts @@ -4,8 +4,8 @@ import { isPreConnectReachabilityError, transportErrorCode, MAX_REACHABILITY_CAUSE_DEPTH, -} from "../src/lib/upstream-reachability"; -import { UpstreamRetryEvidenceError } from "../src/lib/upstream-retry"; +} from "../../src/lib/upstream-reachability"; +import { UpstreamRetryEvidenceError } from "../../src/lib/upstream-retry"; import { UPSTREAM_HOST_CIRCUIT_COOLDOWN_MS, UPSTREAM_HOST_CIRCUIT_MAX_THRESHOLD, @@ -21,13 +21,13 @@ import { resetUpstreamHostHealth, upstreamHostHealthKey, type UpstreamHostAdmissionLease, -} from "../src/codex/upstream-host-health"; +} from "../../src/codex/upstream-host-health"; import { maybePrimeSubagentQuota, resetSubagentModelFallbackStateForTests, setSubagentQuotaPrimeForTests, -} from "../src/codex/subagent-model-fallback"; -import type { OcxConfig } from "../src/types"; +} from "../../src/codex/subagent-model-fallback"; +import type { OcxConfig } from "../../src/types"; beforeEach(() => { clearUpstreamHostHealth(); diff --git a/tests/warmup.test.ts b/tests/codex-integration/warmup.test.ts similarity index 99% rename from tests/warmup.test.ts rename to tests/codex-integration/warmup.test.ts index 57276270218..33fb3504a15 100644 --- a/tests/warmup.test.ts +++ b/tests/codex-integration/warmup.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect, mock, spyOn, test } from "bun:test"; -import { CodexWarmupError, codexWarmupFailureReason, warmCodexAccount } from "../src/codex/warmup"; +import { CodexWarmupError, codexWarmupFailureReason, warmCodexAccount } from "../../src/codex/warmup"; const originalFetch = globalThis.fetch; diff --git a/tests/helpers/repo-root.ts b/tests/helpers/repo-root.ts index 84850bdae92..7943005cc1d 100644 --- a/tests/helpers/repo-root.ts +++ b/tests/helpers/repo-root.ts @@ -38,3 +38,8 @@ export function repoPath(...segments: string[]): string { export function helperPath(name: string): string { return join(repoRoot(), "tests", "helpers", name); } + +/** Absolute path of a file under tests/fixtures. */ +export function fixturePath(...segments: string[]): string { + return join(repoRoot(), "tests", "fixtures", ...segments); +} diff --git a/tests/lib/transient-budget-scope-source.test.ts b/tests/lib/transient-budget-scope-source.test.ts index 3c63b493df4..e693deb0ff3 100644 --- a/tests/lib/transient-budget-scope-source.test.ts +++ b/tests/lib/transient-budget-scope-source.test.ts @@ -16,7 +16,7 @@ const source = (relative: string): string => * The continuation leg shipped on the raw policy value instead, so a request that reached it * received a fresh full `attempts` allowance: with `attempts: 3` an initial send that had * already spent its budget could still emit three more upstream sends. Runtime coverage in - * `tests/upstream-transient-retry.test.ts` proves the helper reports and honors a remainder; + * `tests/providers/upstream-transient-retry.test.ts` proves the helper reports and honors a remainder; * it cannot prove that every call site asks for one, because a site that forgets simply * passes a larger number. This asserts the wiring at the source, which is the only place the * omission is visible. diff --git a/tests/alibaba-region-backup.test.ts b/tests/providers/alibaba-region-backup.test.ts similarity index 96% rename from tests/alibaba-region-backup.test.ts rename to tests/providers/alibaba-region-backup.test.ts index ff5ae930cc7..6084c5c7b64 100644 --- a/tests/alibaba-region-backup.test.ts +++ b/tests/providers/alibaba-region-backup.test.ts @@ -5,8 +5,8 @@ import { join } from "node:path"; import { AlibabaBackupIntegrityError, backupConfigBeforeAlibabaRegionMigration, -} from "../src/providers/alibaba-region-backup"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/alibaba-region-backup"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; test("absent source produces no backup", () => { const dir = mkdtempSync(join(tmpdir(), "ocx-bak-")); diff --git a/tests/alibaba-region-migration.test.ts b/tests/providers/alibaba-region-migration.test.ts similarity index 95% rename from tests/alibaba-region-migration.test.ts rename to tests/providers/alibaba-region-migration.test.ts index e08a75bf66d..0406fea22b7 100644 --- a/tests/alibaba-region-migration.test.ts +++ b/tests/providers/alibaba-region-migration.test.ts @@ -2,11 +2,11 @@ import { expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { loadConfig, saveConfig } from "../src/config"; -import { projectAlibabaRegionMigration } from "../src/providers/alibaba-region-migration"; -import { routeModel } from "../src/router"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { loadConfig, saveConfig } from "../../src/config"; +import { projectAlibabaRegionMigration } from "../../src/providers/alibaba-region-migration"; +import { routeModel } from "../../src/router"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const INTL_URL = "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1"; diff --git a/tests/alibaba-region-startup.test.ts b/tests/providers/alibaba-region-startup.test.ts similarity index 91% rename from tests/alibaba-region-startup.test.ts rename to tests/providers/alibaba-region-startup.test.ts index eda003d503a..ba578cb11b2 100644 --- a/tests/alibaba-region-startup.test.ts +++ b/tests/providers/alibaba-region-startup.test.ts @@ -1,8 +1,8 @@ import { expect, test } from "bun:test"; -import { AlibabaBackupIntegrityError } from "../src/providers/alibaba-region-backup"; -import { projectAlibabaRegionMigration } from "../src/providers/alibaba-region-migration"; -import { runAlibabaRegionStartupMigration } from "../src/providers/alibaba-region-startup"; -import type { OcxConfig } from "../src/types"; +import { AlibabaBackupIntegrityError } from "../../src/providers/alibaba-region-backup"; +import { projectAlibabaRegionMigration } from "../../src/providers/alibaba-region-migration"; +import { runAlibabaRegionStartupMigration } from "../../src/providers/alibaba-region-startup"; +import type { OcxConfig } from "../../src/types"; const INTL_URL = "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1"; diff --git a/tests/aside-client.test.ts b/tests/providers/aside-client.test.ts similarity index 97% rename from tests/aside-client.test.ts rename to tests/providers/aside-client.test.ts index 6cb30bea509..abf4146ba8c 100644 --- a/tests/aside-client.test.ts +++ b/tests/providers/aside-client.test.ts @@ -14,14 +14,14 @@ import { buildClientContribution, type ExportContext, type PiGeneratedConfig, -} from "../src/clients/config-export"; -import { INTEGRATION_CLIENTS, resolveIntegrationPaths, unresolvedPathHintFor } from "../src/integrations/registry"; -import { readIntegrationState } from "../src/integrations/state"; -import { createIntegrationStateStore } from "../src/integrations/store"; -import { defaultIntegrationIO } from "../src/integrations/config-io"; -import { applyIntegration } from "../src/integrations/writer"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/clients/config-export"; +import { INTEGRATION_CLIENTS, resolveIntegrationPaths, unresolvedPathHintFor } from "../../src/integrations/registry"; +import { readIntegrationState } from "../../src/integrations/state"; +import { createIntegrationStateStore } from "../../src/integrations/store"; +import { defaultIntegrationIO } from "../../src/integrations/config-io"; +import { applyIntegration } from "../../src/integrations/writer"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const CONFIG = { port: 10100, diff --git a/tests/auto-compact-budget.test.ts b/tests/providers/auto-compact-budget.test.ts similarity index 97% rename from tests/auto-compact-budget.test.ts rename to tests/providers/auto-compact-budget.test.ts index f7973d92473..7441757dbd9 100644 --- a/tests/auto-compact-budget.test.ts +++ b/tests/providers/auto-compact-budget.test.ts @@ -3,7 +3,7 @@ import { describe, expect, test } from "bun:test"; import { clampAutoCompactTokenLimit, modelAutoCompactTokenLimitsConfigError, -} from "../src/providers/auto-compact-budget"; +} from "../../src/providers/auto-compact-budget"; describe("per-model auto-compaction budgets", () => { test("configuration only lowers the effective hard-limit envelope", () => { diff --git a/tests/azure-adapter.test.ts b/tests/providers/azure-adapter.test.ts similarity index 94% rename from tests/azure-adapter.test.ts rename to tests/providers/azure-adapter.test.ts index 9a680339175..f309734da94 100644 --- a/tests/azure-adapter.test.ts +++ b/tests/providers/azure-adapter.test.ts @@ -2,11 +2,11 @@ import { describe, expect, test } from "bun:test"; import { existsSync, mkdtempSync, readdirSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { createAzureAdapter as createAzureAdapterProduction } from "../src/adapters/azure"; -import { getConfigPath, loadConfig, readConfigDiagnostics } from "../src/config"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { createAzureAdapter as createAzureAdapterProduction } from "../../src/adapters/azure"; +import { getConfigPath, loadConfig, readConfigDiagnostics } from "../../src/config"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const createAzureAdapter = (...args: Parameters) => withTestTranslatorBudget(createAzureAdapterProduction(...args)); diff --git a/tests/azure-model-router-tool-schema.test.ts b/tests/providers/azure-model-router-tool-schema.test.ts similarity index 93% rename from tests/azure-model-router-tool-schema.test.ts rename to tests/providers/azure-model-router-tool-schema.test.ts index 352c0006820..e1022e3c2d3 100644 --- a/tests/azure-model-router-tool-schema.test.ts +++ b/tests/providers/azure-model-router-tool-schema.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../src/types"; const toolSchema = { oneOf: [ diff --git a/tests/baseten-provider.test.ts b/tests/providers/baseten-provider.test.ts similarity index 92% rename from tests/baseten-provider.test.ts rename to tests/providers/baseten-provider.test.ts index 70f168e9d40..8f3da5ed25f 100644 --- a/tests/baseten-provider.test.ts +++ b/tests/providers/baseten-provider.test.ts @@ -1,24 +1,25 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; +} from "../../src/providers/derive"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; -const FIXTURE = readFileSync(join(import.meta.dir, "fixtures/baseten-models.json"), "utf8"); +const FIXTURE = readFileSync(fixturePath("baseten-models.json"), "utf8"); const originalFetch = globalThis.fetch; afterEach(() => { diff --git a/tests/chutes-provider.test.ts b/tests/providers/chutes-provider.test.ts similarity index 89% rename from tests/chutes-provider.test.ts rename to tests/providers/chutes-provider.test.ts index b7e945023ee..3a49a5bdbaa 100644 --- a/tests/chutes-provider.test.ts +++ b/tests/providers/chutes-provider.test.ts @@ -1,25 +1,26 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { resolveProviderModelDiscovery } from "../src/providers/model-discovery"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; - -const CHUTES_FIXTURE = readFileSync(join(import.meta.dir, "fixtures/chutes-models.json"), "utf8"); +} from "../../src/providers/derive"; +import { resolveProviderModelDiscovery } from "../../src/providers/model-discovery"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; + +const CHUTES_FIXTURE = readFileSync(fixturePath("chutes-models.json"), "utf8"); const BASE_URL = "https://llm.chutes.ai/v1"; const MODELS_URL = `${BASE_URL}/models`; const TEST_KEY = "chutes-test-key"; diff --git a/tests/cline-pass-deepseek-v4-tool-replay.test.ts b/tests/providers/cline-pass-deepseek-v4-tool-replay.test.ts similarity index 92% rename from tests/cline-pass-deepseek-v4-tool-replay.test.ts rename to tests/providers/cline-pass-deepseek-v4-tool-replay.test.ts index 16ef1e2c78a..0cba245597a 100644 --- a/tests/cline-pass-deepseek-v4-tool-replay.test.ts +++ b/tests/providers/cline-pass-deepseek-v4-tool-replay.test.ts @@ -1,11 +1,11 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { createRegisteredAdapter } from "../src/adapters/registry"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { createRegisteredAdapter } from "../../src/adapters/registry"; import { stripClinePassDeepSeekV4ToolReplayNarration, -} from "../src/adapters/cline-pass-deepseek-v4-tool-replay"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../src/adapters/cline-pass-deepseek-v4-tool-replay"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../src/types"; +import { createTestTranslatorBudget } from "../helpers/translator-budget"; const TARGET_MODELS = [ "cline-pass/deepseek-v4-flash", diff --git a/tests/cline-pass-provider.test.ts b/tests/providers/cline-pass-provider.test.ts similarity index 96% rename from tests/cline-pass-provider.test.ts rename to tests/providers/cline-pass-provider.test.ts index c5e80cbecf9..3db66eccd6e 100644 --- a/tests/cline-pass-provider.test.ts +++ b/tests/providers/cline-pass-provider.test.ts @@ -1,11 +1,11 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { createTranslatorBudget } from "../src/lib/translator-budget"; -import { KEY_LOGIN_PROVIDERS } from "../src/oauth/key-providers"; -import { enrichProviderFromRegistry, providerConfigSeed } from "../src/providers/derive"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxParsedRequest } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { createTranslatorBudget } from "../../src/lib/translator-budget"; +import { KEY_LOGIN_PROVIDERS } from "../../src/oauth/key-providers"; +import { enrichProviderFromRegistry, providerConfigSeed } from "../../src/providers/derive"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxParsedRequest } from "../../src/types"; const OFFICIAL_CLINE_PASS_MODELS = [ "cline-pass/glm-5.3", diff --git a/tests/cline-pass-reasoning-efforts.test.ts b/tests/providers/cline-pass-reasoning-efforts.test.ts similarity index 95% rename from tests/cline-pass-reasoning-efforts.test.ts rename to tests/providers/cline-pass-reasoning-efforts.test.ts index 5b56b7b744b..a0acff6078a 100644 --- a/tests/cline-pass-reasoning-efforts.test.ts +++ b/tests/providers/cline-pass-reasoning-efforts.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxParsedRequest } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxParsedRequest } from "../../src/types"; const CLINE_PASS_MODELS = [ "cline-pass/glm-5.2", diff --git a/tests/cline-provider.test.ts b/tests/providers/cline-provider.test.ts similarity index 91% rename from tests/cline-provider.test.ts rename to tests/providers/cline-provider.test.ts index 3e912f98e12..4fee3563791 100644 --- a/tests/cline-provider.test.ts +++ b/tests/providers/cline-provider.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { providerConfigSeed, deriveKeyLoginMap, deriveProviderPresets } from "../src/providers/derive"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { providerConfigSeed, deriveKeyLoginMap, deriveProviderPresets } from "../../src/providers/derive"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../src/types"; function minimalRequest(model: string): OcxParsedRequest { return { diff --git a/tests/command-code-error-finish.test.ts b/tests/providers/command-code-error-finish.test.ts similarity index 92% rename from tests/command-code-error-finish.test.ts rename to tests/providers/command-code-error-finish.test.ts index fc1ff3fcbcb..44e969ca538 100644 --- a/tests/command-code-error-finish.test.ts +++ b/tests/providers/command-code-error-finish.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { createCommandCodeAdapter } from "../src/adapters/command-code"; -import { buildResponseJSON } from "../src/bridge"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import type { AdapterEvent, OcxProviderConfig } from "../src/types"; +import { createCommandCodeAdapter } from "../../src/adapters/command-code"; +import { buildResponseJSON } from "../../src/bridge"; +import { createTestTranslatorBudget } from "../helpers/translator-budget"; +import type { AdapterEvent, OcxProviderConfig } from "../../src/types"; const provider: OcxProviderConfig = { adapter: "command-code", diff --git a/tests/command-code-provider.test.ts b/tests/providers/command-code-provider.test.ts similarity index 98% rename from tests/command-code-provider.test.ts rename to tests/providers/command-code-provider.test.ts index 76aed55ccff..e4bb3c4d90b 100644 --- a/tests/command-code-provider.test.ts +++ b/tests/providers/command-code-provider.test.ts @@ -1,15 +1,15 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { createCommandCodeAdapter } from "../src/adapters/command-code"; -import { loginCommandCode, parseCommandCodeCallback, shouldImportLocalCommandCodeAuth } from "../src/oauth/command-code"; -import { buildModelsRequest, OAUTH_PROVIDERS } from "../src/oauth"; +import { createCommandCodeAdapter } from "../../src/adapters/command-code"; +import { loginCommandCode, parseCommandCodeCallback, shouldImportLocalCommandCodeAuth } from "../../src/oauth/command-code"; +import { buildModelsRequest, OAUTH_PROVIDERS } from "../../src/oauth"; import { commandCodeReasoningEfforts, refreshCommandCodeReasoningEfforts, resetCommandCodeReasoningEffortsForTest, -} from "../src/providers/command-code-efforts"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../src/providers/command-code-efforts"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../src/types"; +import { createTestTranslatorBudget } from "../helpers/translator-budget"; const provider: OcxProviderConfig = { adapter: "command-code", diff --git a/tests/command-code-quota.test.ts b/tests/providers/command-code-quota.test.ts similarity index 98% rename from tests/command-code-quota.test.ts rename to tests/providers/command-code-quota.test.ts index 634adce216c..32d607aa039 100644 --- a/tests/command-code-quota.test.ts +++ b/tests/providers/command-code-quota.test.ts @@ -2,10 +2,10 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveCredential } from "../src/oauth/store"; -import { clearProviderQuotaCache, fetchProviderQuotaReports } from "../src/providers/quota"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { saveCredential } from "../../src/oauth/store"; +import { clearProviderQuotaCache, fetchProviderQuotaReports } from "../../src/providers/quota"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const originalFetch = globalThis.fetch; const previousOpencodexHome = process.env.OPENCODEX_HOME; diff --git a/tests/command-code-workspace-cache.test.ts b/tests/providers/command-code-workspace-cache.test.ts similarity index 98% rename from tests/command-code-workspace-cache.test.ts rename to tests/providers/command-code-workspace-cache.test.ts index 6a8e6e536d6..0b26a2521c7 100644 --- a/tests/command-code-workspace-cache.test.ts +++ b/tests/providers/command-code-workspace-cache.test.ts @@ -3,7 +3,7 @@ import { workspaceMetadataCache, pruneWorkspaceMetadataCache, MAX_WORKSPACE_METADATA_ENTRIES, -} from "../src/adapters/command-code"; +} from "../../src/adapters/command-code"; beforeEach(() => { workspaceMetadataCache.clear(); diff --git a/tests/commandcode-provider.test.ts b/tests/providers/commandcode-provider.test.ts similarity index 91% rename from tests/commandcode-provider.test.ts rename to tests/providers/commandcode-provider.test.ts index b6d27a03669..e76355dc4f9 100644 --- a/tests/commandcode-provider.test.ts +++ b/tests/providers/commandcode-provider.test.ts @@ -1,25 +1,26 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { providerModelDiscoverySpecError } from "../src/providers/model-discovery"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; - -const FIXTURE = readFileSync(join(import.meta.dir, "fixtures/commandcode-models.json"), "utf8"); +} from "../../src/providers/derive"; +import { providerModelDiscoverySpecError } from "../../src/providers/model-discovery"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; + +const FIXTURE = readFileSync(fixturePath("commandcode-models.json"), "utf8"); const originalFetch = globalThis.fetch; afterEach(() => { diff --git a/tests/context-cap-unknown-window.test.ts b/tests/providers/context-cap-unknown-window.test.ts similarity index 95% rename from tests/context-cap-unknown-window.test.ts rename to tests/providers/context-cap-unknown-window.test.ts index 79e46ff4109..87ed6d2d30f 100644 --- a/tests/context-cap-unknown-window.test.ts +++ b/tests/providers/context-cap-unknown-window.test.ts @@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test"; import { applyProviderContextCap, resolveUnknownRoutedContextWindow, -} from "../src/providers/context-cap"; +} from "../../src/providers/context-cap"; describe("unknown routed context windows", () => { test("an enabled cap fills a missing window instead of inventing 128k", () => { diff --git a/tests/cursor-adapter.test.ts b/tests/providers/cursor/cursor-adapter.test.ts similarity index 97% rename from tests/cursor-adapter.test.ts rename to tests/providers/cursor/cursor-adapter.test.ts index b891e06ba75..a86df7c2432 100644 --- a/tests/cursor-adapter.test.ts +++ b/tests/providers/cursor/cursor-adapter.test.ts @@ -2,23 +2,23 @@ import { describe, expect, test } from "bun:test"; import { createCursorAdapter as createCursorAdapterProduction, cursorExecDeniedMessage, -} from "../src/adapters/cursor"; +} from "../../../src/adapters/cursor"; import { clearCursorThreadContinuityForTests, lookupCursorThreadConversation, -} from "../src/adapters/cursor/thread-continuity"; +} from "../../../src/adapters/cursor/thread-continuity"; import { clearCursorCheckpointsForTests, commitCursorCheckpoint, getCursorCheckpoint, -} from "../src/adapters/cursor/checkpoint-store"; +} from "../../../src/adapters/cursor/checkpoint-store"; import { create, toBinary } from "@bufbuild/protobuf"; -import { ConversationStateStructureSchema } from "../src/adapters/cursor/gen/agent_pb"; -import type { AdapterEvent, OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import type { CursorClientMessage, CursorRunRequest, CursorServerMessage } from "../src/adapters/cursor/types"; -import type { CursorTransportFactoryInput } from "../src/adapters/cursor/transport"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; -import { CursorRootEnvelopeLimitError } from "../src/adapters/cursor/cursor-errors"; +import { ConversationStateStructureSchema } from "../../../src/adapters/cursor/gen/agent_pb"; +import type { AdapterEvent, OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; +import type { CursorClientMessage, CursorRunRequest, CursorServerMessage } from "../../../src/adapters/cursor/types"; +import type { CursorTransportFactoryInput } from "../../../src/adapters/cursor/transport"; +import { withTestTranslatorBudget } from "../../helpers/translator-budget"; +import { CursorRootEnvelopeLimitError } from "../../../src/adapters/cursor/cursor-errors"; const createCursorAdapter = (...args: Parameters) => withTestTranslatorBudget(createCursorAdapterProduction(...args)); @@ -130,7 +130,7 @@ describe("Cursor adapter live transport", () => { // happens inside the live transport (`prepareCursorRunRequest` in live-transport.ts), which a // mock replaces, so a mocked run can never reach the guard itself. What is under test here is // the adapter's terminal catch, not the guard — the guard has its own tests in - // tests/cursor-blob.test.ts. + // tests/providers/cursor/cursor-blob.test.ts. const adapter = createCursorAdapter(provider, { createTransport: () => ({ async *run(): AsyncGenerator { diff --git a/tests/cursor-arg-normalize.test.ts b/tests/providers/cursor/cursor-arg-normalize.test.ts similarity index 97% rename from tests/cursor-arg-normalize.test.ts rename to tests/providers/cursor/cursor-arg-normalize.test.ts index fc16102f184..a56afa0a38a 100644 --- a/tests/cursor-arg-normalize.test.ts +++ b/tests/providers/cursor/cursor-arg-normalize.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { normalizeArgKeys } from "../src/adapters/cursor/arg-normalize"; +import { normalizeArgKeys } from "../../../src/adapters/cursor/arg-normalize"; const schema = { type: "object", diff --git a/tests/cursor-blob-integrity.test.ts b/tests/providers/cursor/cursor-blob-integrity.test.ts similarity index 96% rename from tests/cursor-blob-integrity.test.ts rename to tests/providers/cursor/cursor-blob-integrity.test.ts index b97d2e537fe..b2231d54b8f 100644 --- a/tests/cursor-blob-integrity.test.ts +++ b/tests/providers/cursor/cursor-blob-integrity.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; import { createHash } from "node:crypto"; -import { cursorBlobServeIntegrityOk, storeCursorBlob } from "../src/adapters/cursor/native-exec"; +import { cursorBlobServeIntegrityOk, storeCursorBlob } from "../../../src/adapters/cursor/native-exec"; describe("cursor blob serve-time integrity (devlog 260826 080)", () => { test("content-addressed blob passes when bytes match the id", () => { diff --git a/tests/cursor-blob.test.ts b/tests/providers/cursor/cursor-blob.test.ts similarity index 99% rename from tests/cursor-blob.test.ts rename to tests/providers/cursor/cursor-blob.test.ts index de927588704..b173345d1d4 100644 --- a/tests/cursor-blob.test.ts +++ b/tests/providers/cursor/cursor-blob.test.ts @@ -17,7 +17,7 @@ import { setCursorBlobLimitsForTests, storeCursorBlob, type CursorBlobRequestScopeToken, -} from "../src/adapters/cursor/native-exec"; +} from "../../../src/adapters/cursor/native-exec"; import { clearCursorCheckpointsForTests, commitCursorCheckpoint, @@ -25,13 +25,13 @@ import { cursorCheckpointStoreMetricsForTests, installCursorCheckpointClockForTests, invalidateCursorCheckpoint, -} from "../src/adapters/cursor/checkpoint-store"; +} from "../../../src/adapters/cursor/checkpoint-store"; import { configureAppOwnedMemoryBudget, registerRetainedStore, resetAppOwnedMemoryForTests, -} from "../src/lib/app-owned-memory"; -import { resetDebugSettingsForTests } from "../src/lib/debug-settings"; +} from "../../../src/lib/app-owned-memory"; +import { resetDebugSettingsForTests } from "../../../src/lib/debug-settings"; import { CURSOR_EXTERNAL_ROOT_BYTE_LIMIT, CURSOR_EXTERNAL_TOOL_CONTINUATION_TEXT, @@ -39,12 +39,12 @@ import { CURSOR_ROUTING_LEVEL_PARAMETER_ID, encodeCursorRunRequest, prepareCursorRunRequest, -} from "../src/adapters/cursor/protobuf-request"; -import { estimateTokens } from "../src/lib/token-estimate"; -import type { OcxAssistantContentPart } from "../src/types"; -import { CursorRootEnvelopeLimitError } from "../src/adapters/cursor/cursor-errors"; -import { isRetryableCursorError } from "../src/adapters/cursor/transport-retry"; -import { encodeCursorCallId, resetCursorCallIdProvenanceForTests } from "../src/adapters/cursor/call-id"; +} from "../../../src/adapters/cursor/protobuf-request"; +import { estimateTokens } from "../../../src/lib/token-estimate"; +import type { OcxAssistantContentPart } from "../../../src/types"; +import { CursorRootEnvelopeLimitError } from "../../../src/adapters/cursor/cursor-errors"; +import { isRetryableCursorError } from "../../../src/adapters/cursor/transport-retry"; +import { encodeCursorCallId, resetCursorCallIdProvenanceForTests } from "../../../src/adapters/cursor/call-id"; import { AgentClientMessageSchema, ConversationStepSchema, @@ -54,7 +54,7 @@ import { KvServerMessageSchema, SetBlobArgsSchema, UserMessageSchema, -} from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; beforeEach(() => { resetCursorBlobStateForTests(); diff --git a/tests/cursor-call-id.test.ts b/tests/providers/cursor/cursor-call-id.test.ts similarity index 94% rename from tests/cursor-call-id.test.ts rename to tests/providers/cursor/cursor-call-id.test.ts index eb500f520e1..6405f5deb6a 100644 --- a/tests/cursor-call-id.test.ts +++ b/tests/providers/cursor/cursor-call-id.test.ts @@ -3,10 +3,10 @@ import { decodeCursorCallId, encodeCursorCallId, resetCursorCallIdProvenanceForTests, -} from "../src/adapters/cursor/call-id"; -import { mapCursorServerMessage } from "../src/adapters/cursor/message-mapper"; -import type { CursorMessageMapperState } from "../src/adapters/cursor/message-mapper"; -import type { CursorKvStore } from "../src/adapters/cursor/kv-store"; +} from "../../../src/adapters/cursor/call-id"; +import { mapCursorServerMessage } from "../../../src/adapters/cursor/message-mapper"; +import type { CursorMessageMapperState } from "../../../src/adapters/cursor/message-mapper"; +import type { CursorKvStore } from "../../../src/adapters/cursor/kv-store"; const COMPOSITE = "call-9aee6d07-edc0-442f-8466-9d3924e16e03-0\nfc_5a1a53c6-32ce-9602-bc56-459030165589_0"; diff --git a/tests/cursor-cancel-provenance.test.ts b/tests/providers/cursor/cursor-cancel-provenance.test.ts similarity index 94% rename from tests/cursor-cancel-provenance.test.ts rename to tests/providers/cursor/cursor-cancel-provenance.test.ts index c954f641842..f4ab0a917b1 100644 --- a/tests/cursor-cancel-provenance.test.ts +++ b/tests/providers/cursor/cursor-cancel-provenance.test.ts @@ -1,13 +1,13 @@ import { describe, expect, test } from "bun:test"; -import { createLiveCursorTransport } from "../src/adapters/cursor/live-transport"; +import { createLiveCursorTransport } from "../../../src/adapters/cursor/live-transport"; import { classifyCursorError, CursorUnexpectedCancelError, isCursorBenignCancelError, -} from "../src/adapters/cursor/cursor-errors"; -import { resetCursorBlobStateForTests } from "../src/adapters/cursor/native-exec"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import type { CursorServerMessage } from "../src/adapters/cursor/types"; +} from "../../../src/adapters/cursor/cursor-errors"; +import { resetCursorBlobStateForTests } from "../../../src/adapters/cursor/native-exec"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; +import type { CursorServerMessage } from "../../../src/adapters/cursor/types"; type OpenFn = ( encoded: Uint8Array, diff --git a/tests/cursor-catalog.test.ts b/tests/providers/cursor/cursor-catalog.test.ts similarity index 99% rename from tests/cursor-catalog.test.ts rename to tests/providers/cursor/cursor-catalog.test.ts index a5826fd151b..4d8a79e352f 100644 --- a/tests/cursor-catalog.test.ts +++ b/tests/providers/cursor/cursor-catalog.test.ts @@ -6,13 +6,13 @@ import { recordLiveCursorClaudeModels, resetLiveCursorClaudeWireIdentitiesForTests, resolveCursorSelection, -} from "../src/adapters/cursor/catalog"; +} from "../../../src/adapters/cursor/catalog"; import { cursorEffortSuffix, cursorModelHasEffortTiers, cursorRequestWireModelIdWithEffort, CURSOR_THINKING_MODEL_IDS, -} from "../src/adapters/cursor/effort-map"; +} from "../../../src/adapters/cursor/effort-map"; /** * The frozen legacy picker ids (discovery.ts static seed minus the 4 router diff --git a/tests/cursor-claude-id.test.ts b/tests/providers/cursor/cursor-claude-id.test.ts similarity index 98% rename from tests/cursor-claude-id.test.ts rename to tests/providers/cursor/cursor-claude-id.test.ts index 7c424d17bfc..238cd1f4fea 100644 --- a/tests/cursor-claude-id.test.ts +++ b/tests/providers/cursor/cursor-claude-id.test.ts @@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test"; import { composeCursorClaudeWireId, normalizeCursorClaudeId, -} from "../src/adapters/cursor/claude-id"; +} from "../../../src/adapters/cursor/claude-id"; describe("Cursor Claude id normalization", () => { test("normalizes every observed Fable 5.1 spelling to one capability base", () => { diff --git a/tests/cursor-default-catalog-suppression.test.ts b/tests/providers/cursor/cursor-default-catalog-suppression.test.ts similarity index 91% rename from tests/cursor-default-catalog-suppression.test.ts rename to tests/providers/cursor/cursor-default-catalog-suppression.test.ts index 2d6871076db..6399f4cda53 100644 --- a/tests/cursor-default-catalog-suppression.test.ts +++ b/tests/providers/cursor/cursor-default-catalog-suppression.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { createCursorRequest } from "../src/adapters/cursor/request-builder"; -import type { OcxParsedRequest } from "../src/types/request"; +import { createCursorRequest } from "../../../src/adapters/cursor/request-builder"; +import type { OcxParsedRequest } from "../../../src/types/request"; function parsedRequest(overrides: Partial = {}): OcxParsedRequest { return { diff --git a/tests/cursor-desktop-exec.test.ts b/tests/providers/cursor/cursor-desktop-exec.test.ts similarity index 97% rename from tests/cursor-desktop-exec.test.ts rename to tests/providers/cursor/cursor-desktop-exec.test.ts index 5d6085b0860..43023799ad5 100644 --- a/tests/cursor-desktop-exec.test.ts +++ b/tests/providers/cursor/cursor-desktop-exec.test.ts @@ -5,10 +5,10 @@ import { ComputerUseArgsSchema, ExecServerMessageSchema, RecordScreenArgsSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import { handleCursorNativeExec } from "../src/adapters/cursor/native-exec"; -import { desktopDepsFromConfig } from "../src/adapters/cursor/native-exec-desktop"; -import { shellInvocation } from "../src/lib/win-exec"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { handleCursorNativeExec } from "../../../src/adapters/cursor/native-exec"; +import { desktopDepsFromConfig } from "../../../src/adapters/cursor/native-exec-desktop"; +import { shellInvocation } from "../../../src/lib/win-exec"; function execMessage(message: Parameters>[1]["message"]) { return create(ExecServerMessageSchema, { id: 3, execId: "exec-test", message }); diff --git a/tests/cursor-discovery.test.ts b/tests/providers/cursor/cursor-discovery.test.ts similarity index 99% rename from tests/cursor-discovery.test.ts rename to tests/providers/cursor/cursor-discovery.test.ts index 0087a2bb8ea..32656dd12df 100644 --- a/tests/cursor-discovery.test.ts +++ b/tests/providers/cursor/cursor-discovery.test.ts @@ -20,7 +20,7 @@ import { isCursorNativeWireModel, cursorNeedsExternalToolContinuation, normalizeCursorModels, -} from "../src/adapters/cursor/discovery"; +} from "../../../src/adapters/cursor/discovery"; describe("Cursor discovery metadata", () => { test("no-vision list is a curated explicit subset of the static seed", () => { diff --git a/tests/cursor-display-names.test.ts b/tests/providers/cursor/cursor-display-names.test.ts similarity index 88% rename from tests/cursor-display-names.test.ts rename to tests/providers/cursor/cursor-display-names.test.ts index 8c36f136154..3751601445c 100644 --- a/tests/cursor-display-names.test.ts +++ b/tests/providers/cursor/cursor-display-names.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from "bun:test"; -import { cursorModelDisplayNames, CURSOR_STATIC_MODELS, isCursorBrandedLabel } from "../src/adapters/cursor/discovery"; -import { cursorUmbrellaRows } from "../src/adapters/cursor/catalog"; -import { enrichProviderFromRegistry, providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { configuredModelDisplayName } from "../src/codex/catalog/provider-fetch"; -import type { OcxProviderConfig } from "../src/types"; +import { cursorModelDisplayNames, CURSOR_STATIC_MODELS, isCursorBrandedLabel } from "../../../src/adapters/cursor/discovery"; +import { cursorUmbrellaRows } from "../../../src/adapters/cursor/catalog"; +import { enrichProviderFromRegistry, providerConfigSeed } from "../../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../../src/providers/registry"; +import { configuredModelDisplayName } from "../../../src/codex/catalog/provider-fetch"; +import type { OcxProviderConfig } from "../../../src/types"; /** * `routedDisplayName` (codex/catalog/sync.ts) passes a routed slug through unchanged, so a diff --git a/tests/cursor-effort-rows.test.ts b/tests/providers/cursor/cursor-effort-rows.test.ts similarity index 93% rename from tests/cursor-effort-rows.test.ts rename to tests/providers/cursor/cursor-effort-rows.test.ts index 4929696af8a..ea97860228b 100644 --- a/tests/cursor-effort-rows.test.ts +++ b/tests/providers/cursor/cursor-effort-rows.test.ts @@ -3,25 +3,25 @@ import { mkdtempSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; +import { saveConfig } from "../../../src/config"; import { resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests, -} from "../src/codex/model-entitlements"; -import { buildCursorIntegrationStatus } from "../src/server/management/cursor-integration-routes"; -import { handleChatCompletions } from "../src/server/chat-completions"; -import { handleClaudeMessages } from "../src/server/claude-messages"; +} from "../../../src/codex/model-entitlements"; +import { buildCursorIntegrationStatus } from "../../../src/server/management/cursor-integration-routes"; +import { handleChatCompletions } from "../../../src/server/chat-completions"; +import { handleClaudeMessages } from "../../../src/server/claude-messages"; import { effortRowId, expandCursorEffortRow, parseEffortRowId, -} from "../src/server/effort-row"; -import { handleResponses } from "../src/server/responses"; -import { startServer } from "../src/server"; -import type { RequestLogContext } from "../src/server/request-log"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; -import { SERVER_BUDGET_MS } from "./helpers/test-budget"; +} from "../../../src/server/effort-row"; +import { handleResponses } from "../../../src/server/responses"; +import { startServer } from "../../../src/server"; +import type { RequestLogContext } from "../../../src/server/request-log"; +import type { OcxConfig } from "../../../src/types"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; +import { SERVER_BUDGET_MS } from "../../helpers/test-budget"; setDefaultTimeout(SERVER_BUDGET_MS); diff --git a/tests/cursor-effort-suffix.test.ts b/tests/providers/cursor/cursor-effort-suffix.test.ts similarity index 98% rename from tests/cursor-effort-suffix.test.ts rename to tests/providers/cursor/cursor-effort-suffix.test.ts index 917c2b1b2e9..b0c314deeba 100644 --- a/tests/cursor-effort-suffix.test.ts +++ b/tests/providers/cursor/cursor-effort-suffix.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { createCursorRequest } from "../src/adapters/cursor/request-builder"; -import { CANONICAL_EFFORT_SUFFIXES, cursorEffortSuffix, cursorModelEffortLadder, cursorWireModelIdWithEffort, CURSOR_THINKING_MODEL_IDS } from "../src/adapters/cursor/effort-map"; -import { CURSOR_STATIC_MODELS, isCursorModelAvailableForAccount } from "../src/adapters/cursor/discovery"; -import type { OcxParsedRequest } from "../src/types"; +import { createCursorRequest } from "../../../src/adapters/cursor/request-builder"; +import { CANONICAL_EFFORT_SUFFIXES, cursorEffortSuffix, cursorModelEffortLadder, cursorWireModelIdWithEffort, CURSOR_THINKING_MODEL_IDS } from "../../../src/adapters/cursor/effort-map"; +import { CURSOR_STATIC_MODELS, isCursorModelAvailableForAccount } from "../../../src/adapters/cursor/discovery"; +import type { OcxParsedRequest } from "../../../src/types"; // Static fixture recorded from Cursor GetUsableModels on 2026-08-06. This pins the // exact wire ids observed during the incident; live availability normalization is diff --git a/tests/cursor-effort-table.test.ts b/tests/providers/cursor/cursor-effort-table.test.ts similarity index 93% rename from tests/cursor-effort-table.test.ts rename to tests/providers/cursor/cursor-effort-table.test.ts index f3f32fda588..973941d5744 100644 --- a/tests/cursor-effort-table.test.ts +++ b/tests/providers/cursor/cursor-effort-table.test.ts @@ -7,11 +7,12 @@ import { resetCursorEffortTableCacheForTests, type CursorEffortTable, type CursorEffortTableDeps, -} from "../src/integrations/cursor-effort-table"; -import type { CursorInstall } from "../src/integrations/cursor-detect"; -import { predictCursorEffort } from "../src/server/models-capabilities"; +} from "../../../src/integrations/cursor-effort-table"; +import type { CursorInstall } from "../../../src/integrations/cursor-detect"; +import { predictCursorEffort } from "../../../src/server/models-capabilities"; +import { fixturePath } from "../../helpers/repo-root"; -const FIXTURE = readFileSync(join(import.meta.dir, "fixtures/cursor-agent-exec-effort-table.min.js"), "utf8"); +const FIXTURE = readFileSync(fixturePath("cursor-agent-exec-effort-table.min.js"), "utf8"); const INSTALL: CursorInstall = { build: "private-inference", path: "/Applications/Cursor Private Inference.app", version: "3.18.25" }; function parsedFixtureTable(): CursorEffortTable { diff --git a/tests/cursor-envelope-echo-retry.test.ts b/tests/providers/cursor/cursor-envelope-echo-retry.test.ts similarity index 98% rename from tests/cursor-envelope-echo-retry.test.ts rename to tests/providers/cursor/cursor-envelope-echo-retry.test.ts index e4f4e65ff19..0470eee8c64 100644 --- a/tests/cursor-envelope-echo-retry.test.ts +++ b/tests/providers/cursor/cursor-envelope-echo-retry.test.ts @@ -1,15 +1,15 @@ import { describe, expect, test } from "bun:test"; -import { createCursorAdapter as createCursorAdapterProduction } from "../src/adapters/cursor"; +import { createCursorAdapter as createCursorAdapterProduction } from "../../../src/adapters/cursor"; import { CURSOR_ECHO_RETRY_CONTINUATION_TEXT, CursorEnvelopeEchoSniffer, CursorMidstreamEchoObserver, CursorRoutingCommentarySniffer, MAX_MIDSTREAM_SCAN_LENGTH, -} from "../src/adapters/cursor/envelope-echo"; -import type { AdapterEvent, OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import type { CursorRunRequest, CursorServerMessage } from "../src/adapters/cursor/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../../src/adapters/cursor/envelope-echo"; +import type { AdapterEvent, OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; +import type { CursorRunRequest, CursorServerMessage } from "../../../src/adapters/cursor/types"; +import { withTestTranslatorBudget } from "../../helpers/translator-budget"; const createCursorAdapter = (...args: Parameters) => withTestTranslatorBudget(createCursorAdapterProduction(...args)); diff --git a/tests/cursor-eof-terminal.test.ts b/tests/providers/cursor/cursor-eof-terminal.test.ts similarity index 96% rename from tests/cursor-eof-terminal.test.ts rename to tests/providers/cursor/cursor-eof-terminal.test.ts index 614f04498b6..d06651f5afd 100644 --- a/tests/cursor-eof-terminal.test.ts +++ b/tests/providers/cursor/cursor-eof-terminal.test.ts @@ -10,11 +10,11 @@ import { ToolCallSchema, ToolCallStartedUpdateSchema, TurnEndedUpdateSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import { encodeConnectFrame } from "../src/adapters/cursor/framing"; -import { createLiveCursorTransport } from "../src/adapters/cursor/live-transport"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import type { CursorRunRequest, CursorServerMessage } from "../src/adapters/cursor/types"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { encodeConnectFrame } from "../../../src/adapters/cursor/framing"; +import { createLiveCursorTransport } from "../../../src/adapters/cursor/live-transport"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; +import type { CursorRunRequest, CursorServerMessage } from "../../../src/adapters/cursor/types"; const PROVIDER = "opencodex-responses"; diff --git a/tests/cursor-errors.test.ts b/tests/providers/cursor/cursor-errors.test.ts similarity index 98% rename from tests/cursor-errors.test.ts rename to tests/providers/cursor/cursor-errors.test.ts index a3307f982a7..4d55bdd7110 100644 --- a/tests/cursor-errors.test.ts +++ b/tests/providers/cursor/cursor-errors.test.ts @@ -4,8 +4,8 @@ import { isCursorBenignCancelError, isCursorInvalidArgumentError, safeCursorErrorMessage, -} from "../src/adapters/cursor/cursor-errors"; -import { inferHttpStatusFromAdapterMessage } from "../src/lib/errors"; +} from "../../../src/adapters/cursor/cursor-errors"; +import { inferHttpStatusFromAdapterMessage } from "../../../src/lib/errors"; describe("classifyCursorError", () => { test("rate limit and resource exhaustion stay distinct", () => { diff --git a/tests/cursor-exec-empty-result.test.ts b/tests/providers/cursor/cursor-exec-empty-result.test.ts similarity index 98% rename from tests/cursor-exec-empty-result.test.ts rename to tests/providers/cursor/cursor-exec-empty-result.test.ts index 57f42c00760..330390582c6 100644 --- a/tests/cursor-exec-empty-result.test.ts +++ b/tests/providers/cursor/cursor-exec-empty-result.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { normalizeCursorToolResultText } from "../src/adapters/cursor/tool-result-normalize"; +import { normalizeCursorToolResultText } from "../../../src/adapters/cursor/tool-result-normalize"; describe("codex exec bridge empty-result normalization (devlog 260826 gap-7)", () => { test("empty exec cell output becomes explanatory text, not an error", () => { diff --git a/tests/cursor-fast-listing.test.ts b/tests/providers/cursor/cursor-fast-listing.test.ts similarity index 86% rename from tests/cursor-fast-listing.test.ts rename to tests/providers/cursor/cursor-fast-listing.test.ts index d764eb5799c..8a67badf533 100644 --- a/tests/cursor-fast-listing.test.ts +++ b/tests/providers/cursor/cursor-fast-listing.test.ts @@ -1,13 +1,13 @@ import { describe, expect, test } from "bun:test"; -import { cursorFastCapableBases, cursorFastIdFor, resolveCursorSelection } from "../src/adapters/cursor/catalog"; -import { buildAnthropicModelInfos } from "../src/claude/model-info"; -import { AUTO_CONTEXT_OFF } from "../src/claude/context-windows"; -import { desktop3pAlias } from "../src/claude/desktop-3p"; -import { providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { decideTier } from "../src/providers/fastwire"; -import { fastPolicyForModel } from "../src/providers/service-tier"; -import type { CatalogModel } from "../src/codex/catalog"; +import { cursorFastCapableBases, cursorFastIdFor, resolveCursorSelection } from "../../../src/adapters/cursor/catalog"; +import { buildAnthropicModelInfos } from "../../../src/claude/model-info"; +import { AUTO_CONTEXT_OFF } from "../../../src/claude/context-windows"; +import { desktop3pAlias } from "../../../src/claude/desktop-3p"; +import { providerConfigSeed } from "../../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../../src/providers/registry"; +import { decideTier } from "../../../src/providers/fastwire"; +import { fastPolicyForModel } from "../../../src/providers/service-tier"; +import type { CatalogModel } from "../../../src/codex/catalog"; function cursorModel(id: string, contextWindow = 1_000_000): CatalogModel { return { provider: "cursor", id, contextWindow, reasoningEfforts: ["low", "high"] } as CatalogModel; diff --git a/tests/cursor-fast-tier.test.ts b/tests/providers/cursor/cursor-fast-tier.test.ts similarity index 91% rename from tests/cursor-fast-tier.test.ts rename to tests/providers/cursor/cursor-fast-tier.test.ts index 43ec6bd66b4..bcdcc9c47f3 100644 --- a/tests/cursor-fast-tier.test.ts +++ b/tests/providers/cursor/cursor-fast-tier.test.ts @@ -1,11 +1,11 @@ import { describe, expect, test } from "bun:test"; -import { cursorFastCapableBases, upgradeToFast } from "../src/adapters/cursor/catalog"; -import { createCursorRequest, cursorRequestEmitsFastVariant } from "../src/adapters/cursor/request-builder"; -import { providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { decideTier } from "../src/providers/fastwire"; -import { fastPolicyForModel, serviceTierSupportFromPolicy } from "../src/providers/service-tier"; -import type { OcxParsedRequest, TierDecision } from "../src/types"; +import { cursorFastCapableBases, upgradeToFast } from "../../../src/adapters/cursor/catalog"; +import { createCursorRequest, cursorRequestEmitsFastVariant } from "../../../src/adapters/cursor/request-builder"; +import { providerConfigSeed } from "../../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../../src/providers/registry"; +import { decideTier } from "../../../src/providers/fastwire"; +import { fastPolicyForModel, serviceTierSupportFromPolicy } from "../../../src/providers/service-tier"; +import type { OcxParsedRequest, TierDecision } from "../../../src/types"; const FAST_DECISION: TierDecision = { kind: "set", value: "fast" }; diff --git a/tests/cursor-framing.test.ts b/tests/providers/cursor/cursor-framing.test.ts similarity index 99% rename from tests/cursor-framing.test.ts rename to tests/providers/cursor/cursor-framing.test.ts index 7d4156f6175..a6bb583a3ab 100644 --- a/tests/cursor-framing.test.ts +++ b/tests/providers/cursor/cursor-framing.test.ts @@ -11,13 +11,13 @@ import { isConnectFrameCompressed, isConnectFrameEndStream, tryDecodeConnectFrame, -} from "../src/adapters/cursor/framing"; +} from "../../../src/adapters/cursor/framing"; import { CURSOR_MAX_CONNECT_FRAME_BYTES, CURSOR_MAX_EFFECTIVE_CONNECT_PAYLOAD_BYTES, CURSOR_MAX_PENDING_FRAMES, createTranslatorBudget, -} from "../src/lib/translator-budget"; +} from "../../../src/lib/translator-budget"; const bytes = (...values: number[]) => new Uint8Array(values); diff --git a/tests/cursor-h2-pool-shutdown.test.ts b/tests/providers/cursor/cursor-h2-pool-shutdown.test.ts similarity index 94% rename from tests/cursor-h2-pool-shutdown.test.ts rename to tests/providers/cursor/cursor-h2-pool-shutdown.test.ts index f832206f807..3efb7cc04a7 100644 --- a/tests/cursor-h2-pool-shutdown.test.ts +++ b/tests/providers/cursor/cursor-h2-pool-shutdown.test.ts @@ -1,10 +1,10 @@ import http2 from "node:http2"; import { afterEach, describe, expect, test } from "bun:test"; -import { CursorH2SessionPool } from "../src/adapters/cursor/h2-pool"; +import { CursorH2SessionPool } from "../../../src/adapters/cursor/h2-pool"; import { resetOptionalShutdownHooksForTests, runOptionalShutdownHooks, -} from "../src/lib/optional-shutdown-hooks"; +} from "../../../src/lib/optional-shutdown-hooks"; afterEach(() => { resetOptionalShutdownHooksForTests(); diff --git a/tests/cursor-hardening.test.ts b/tests/providers/cursor/cursor-hardening.test.ts similarity index 98% rename from tests/cursor-hardening.test.ts rename to tests/providers/cursor/cursor-hardening.test.ts index 519f3ea7c45..0a8edc988b4 100644 --- a/tests/cursor-hardening.test.ts +++ b/tests/providers/cursor/cursor-hardening.test.ts @@ -15,14 +15,14 @@ import { ToolCallSchema, ToolCallStartedUpdateSchema, InteractionUpdateSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import { CONNECT_FLAG_END_STREAM, encodeConnectFrame } from "../src/adapters/cursor/framing"; -import { fetchCursorUsableModels } from "../src/adapters/cursor/live-models"; -import { armTimeoutDestroyFallback, createLiveCursorTransport, createTerminalSettler } from "../src/adapters/cursor/live-transport"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache, getProviderDiscoveryStatus } from "../src/codex/model-cache"; -import { handleManagementAPI } from "../src/server/management-api"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { CONNECT_FLAG_END_STREAM, encodeConnectFrame } from "../../../src/adapters/cursor/framing"; +import { fetchCursorUsableModels } from "../../../src/adapters/cursor/live-models"; +import { armTimeoutDestroyFallback, createLiveCursorTransport, createTerminalSettler } from "../../../src/adapters/cursor/live-transport"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; +import { gatherRoutedModels } from "../../../src/codex/catalog"; +import { clearModelCache, getProviderDiscoveryStatus } from "../../../src/codex/model-cache"; +import { handleManagementAPI } from "../../../src/server/management-api"; async function withDiscoveryServer( handler: (stream: http2.ServerHttp2Stream, headers: http2.IncomingHttpHeaders) => void, @@ -1130,4 +1130,4 @@ describe("Cursor live transport incomplete-frame EOF", () => { }); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../../helpers/management-auth"; diff --git a/tests/cursor-http1-transport.test.ts b/tests/providers/cursor/cursor-http1-transport.test.ts similarity index 97% rename from tests/cursor-http1-transport.test.ts rename to tests/providers/cursor/cursor-http1-transport.test.ts index 9c57963fcfc..7e60f1f593d 100644 --- a/tests/cursor-http1-transport.test.ts +++ b/tests/providers/cursor/cursor-http1-transport.test.ts @@ -13,16 +13,16 @@ import { TextDeltaUpdateSchema, ToolCallSchema, ToolCallStartedUpdateSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import { decodeConnectFrame, encodeConnectFrame } from "../src/adapters/cursor/framing"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { decodeConnectFrame, encodeConnectFrame } from "../../../src/adapters/cursor/framing"; import { cursorBidiAppendRequestSize, encodeCursorBidiAppendRequest, -} from "../src/adapters/cursor/http1-bidi"; -import { createLiveCursorTransport } from "../src/adapters/cursor/live-transport"; -import type { CursorRunRequest, CursorServerMessage } from "../src/adapters/cursor/types"; -import type { OcxProviderConfig } from "../src/types"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../../src/adapters/cursor/http1-bidi"; +import { createLiveCursorTransport } from "../../../src/adapters/cursor/live-transport"; +import type { CursorRunRequest, CursorServerMessage } from "../../../src/adapters/cursor/types"; +import type { OcxProviderConfig } from "../../../src/types"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; interface DecodedAppend { data: string; diff --git a/tests/cursor-images.test.ts b/tests/providers/cursor/cursor-images.test.ts similarity index 97% rename from tests/cursor-images.test.ts rename to tests/providers/cursor/cursor-images.test.ts index 50839515624..515254af264 100644 --- a/tests/cursor-images.test.ts +++ b/tests/providers/cursor/cursor-images.test.ts @@ -20,18 +20,18 @@ import { resolveCursorImages, sniffCursorImageDimensions, sniffCursorImageFormat, -} from "../src/adapters/cursor/images"; +} from "../../../src/adapters/cursor/images"; import { handleCursorNativeKv, resetCursorBlobStateForTests, -} from "../src/adapters/cursor/native-exec"; -import { cursorRequestMessagesFromRaw } from "../src/adapters/cursor/request-builder"; -import { activePromptText, encodeCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; +} from "../../../src/adapters/cursor/native-exec"; +import { cursorRequestMessagesFromRaw } from "../../../src/adapters/cursor/request-builder"; +import { activePromptText, encodeCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; import { AgentClientMessageSchema, GetBlobArgsSchema, KvServerMessageSchema, -} from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; /** Minimal valid 1×1 PNG (real IHDR; not a signature-only stub). */ const PNG_BYTES = Uint8Array.from( @@ -43,7 +43,7 @@ const PNG_BYTES = Uint8Array.from( const PNG_DATA_URL = `data:image/png;base64,${Buffer.from(PNG_BYTES).toString("base64")}`; async function oversizedDecodablePng(): Promise { - const pngPath = new URL("./helpers/cursor-grumpy-fixture.png", import.meta.url); + const pngPath = new URL("../../helpers/cursor-grumpy-fixture.png", import.meta.url); const src = new Uint8Array(await Bun.file(pngPath).arrayBuffer()); return new Uint8Array(await new Bun.Image(src).resize(2400, 2400).png().bytes()); } @@ -243,7 +243,7 @@ describe("Cursor image resolver", () => { }); test("prepareCursorImageForWire re-encodes large PNG as JPEG under the soft cap", async () => { - const pngPath = new URL("./helpers/cursor-grumpy-fixture.png", import.meta.url); + const pngPath = new URL("../../helpers/cursor-grumpy-fixture.png", import.meta.url); const png = new Uint8Array(await Bun.file(pngPath).arrayBuffer()); expect(png.byteLength).toBeGreaterThan(CURSOR_VISION_SOFT_MAX_BYTES); @@ -262,7 +262,7 @@ describe("Cursor image resolver", () => { }); test("detail original/high uses a higher soft tier than auto", async () => { - const pngPath = new URL("./helpers/cursor-grumpy-fixture.png", import.meta.url); + const pngPath = new URL("../../helpers/cursor-grumpy-fixture.png", import.meta.url); const png = new Uint8Array(await Bun.file(pngPath).arrayBuffer()); const auto = await prepareCursorImageForWire({ data: png, @@ -310,7 +310,7 @@ describe("Cursor image resolver", () => { }); test("prepareCursorRawMessages JPEG-preps active-turn user data URLs", async () => { - const pngPath = new URL("./helpers/cursor-grumpy-fixture.png", import.meta.url); + const pngPath = new URL("../../helpers/cursor-grumpy-fixture.png", import.meta.url); const png = new Uint8Array(await Bun.file(pngPath).arrayBuffer()); const imageUrl = `data:image/png;base64,${Buffer.from(png).toString("base64")}`; const prepared = await prepareCursorRawMessages([ @@ -623,7 +623,7 @@ describe("Cursor image resolver", () => { }); test("prepareCursorImageForWire never returns ready JPEG above the detail soft cap", async () => { - const pngPath = new URL("./helpers/cursor-grumpy-fixture.png", import.meta.url); + const pngPath = new URL("../../helpers/cursor-grumpy-fixture.png", import.meta.url); const png = new Uint8Array(await Bun.file(pngPath).arrayBuffer()); const oversized = await oversizedDecodablePng(); for (const [label, input, detail, softMax] of [ @@ -644,7 +644,7 @@ describe("Cursor image resolver", () => { }); test("omits when shrink ladder best JPEG still exceeds soft cap", async () => { - const pngPath = new URL("./helpers/cursor-grumpy-fixture.png", import.meta.url); + const pngPath = new URL("../../helpers/cursor-grumpy-fixture.png", import.meta.url); const png = new Uint8Array(await Bun.file(pngPath).arrayBuffer()); const outcome = await prepareCursorImageForWire({ data: png, diff --git a/tests/cursor-integration-status.test.ts b/tests/providers/cursor/cursor-integration-status.test.ts similarity index 93% rename from tests/cursor-integration-status.test.ts rename to tests/providers/cursor/cursor-integration-status.test.ts index 35348dc933a..6cb18458aa8 100644 --- a/tests/cursor-integration-status.test.ts +++ b/tests/providers/cursor/cursor-integration-status.test.ts @@ -2,19 +2,20 @@ import { afterEach, beforeEach, describe, expect, setDefaultTimeout, test } from import { mkdtempSync, readFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; +import { saveConfig } from "../../../src/config"; import { resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests, -} from "../src/codex/model-entitlements"; -import { cursorProductJsonCandidates, detectCursorInstalls, type CursorDetectDeps } from "../src/integrations/cursor-detect"; -import { parseCursorEffortTable, type CursorEffortTable } from "../src/integrations/cursor-effort-table"; -import { cursorLastSeen, recordCursorSeen, resetCursorSeenForTests } from "../src/integrations/cursor-seen"; -import { cursorEffortFamily } from "../src/server/models-capabilities"; -import { startServer } from "../src/server"; -import type { OcxConfig } from "../src/types"; -import { SERVER_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/codex/model-entitlements"; +import { cursorProductJsonCandidates, detectCursorInstalls, type CursorDetectDeps } from "../../../src/integrations/cursor-detect"; +import { parseCursorEffortTable, type CursorEffortTable } from "../../../src/integrations/cursor-effort-table"; +import { cursorLastSeen, recordCursorSeen, resetCursorSeenForTests } from "../../../src/integrations/cursor-seen"; +import { cursorEffortFamily } from "../../../src/server/models-capabilities"; +import { startServer } from "../../../src/server"; +import type { OcxConfig } from "../../../src/types"; +import { SERVER_BUDGET_MS } from "../../helpers/test-budget"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; +import { fixturePath } from "../../helpers/repo-root"; setDefaultTimeout(SERVER_BUDGET_MS); @@ -94,7 +95,7 @@ describe("cursorEffortFamily", () => { const previousHome = process.env.OPENCODEX_HOME; let testHome = ""; -const CURSOR_EFFORT_FIXTURE = readFileSync(join(import.meta.dir, "fixtures/cursor-agent-exec-effort-table.min.js"), "utf8"); +const CURSOR_EFFORT_FIXTURE = readFileSync(fixturePath("cursor-agent-exec-effort-table.min.js"), "utf8"); const STATIC_CURSOR_EFFORT_DEPS = { managementApi: { loadCursorEffortTable: () => null } }; function fixtureEffortTable(): CursorEffortTable { diff --git a/tests/cursor-interaction-query.test.ts b/tests/providers/cursor/cursor-interaction-query.test.ts similarity index 90% rename from tests/cursor-interaction-query.test.ts rename to tests/providers/cursor/cursor-interaction-query.test.ts index 626da20fc65..4003dbb6a5c 100644 --- a/tests/cursor-interaction-query.test.ts +++ b/tests/providers/cursor/cursor-interaction-query.test.ts @@ -18,8 +18,8 @@ import { ToolCallStartedUpdateSchema, WebSearchRequestQuerySchema, type InteractionQuery, -} from "../src/adapters/cursor/gen/agent_pb"; -import { isClientToolFrame, planInteractionQueryReply } from "../src/adapters/cursor/live-transport"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { isClientToolFrame, planInteractionQueryReply } from "../../../src/adapters/cursor/live-transport"; function query(id: number, q: InteractionQuery["query"]): InteractionQuery { return create(InteractionQuerySchema, { id, query: q }); @@ -147,8 +147,8 @@ describe("isClientToolFrame", () => { describe("partialUsageFromEventState", () => { test("reports checkpoint-derived cumulative usage on failure", async () => { - const { partialUsageFromEventState } = await import("../src/adapters/cursor/live-transport"); - const { createCursorProtobufEventState } = await import("../src/adapters/cursor/protobuf-events"); + const { partialUsageFromEventState } = await import("../../../src/adapters/cursor/live-transport"); + const { createCursorProtobufEventState } = await import("../../../src/adapters/cursor/protobuf-events"); const state = createCursorProtobufEventState(); state.usage.outputTokens = 42; state.contextTokens = 10_300; @@ -161,16 +161,16 @@ describe("partialUsageFromEventState", () => { }); test("reports output-only usage without a checkpoint", async () => { - const { partialUsageFromEventState } = await import("../src/adapters/cursor/live-transport"); - const { createCursorProtobufEventState } = await import("../src/adapters/cursor/protobuf-events"); + const { partialUsageFromEventState } = await import("../../../src/adapters/cursor/live-transport"); + const { createCursorProtobufEventState } = await import("../../../src/adapters/cursor/protobuf-events"); const state = createCursorProtobufEventState(); state.usage.outputTokens = 7; expect(partialUsageFromEventState(state)).toEqual({ inputTokens: 0, outputTokens: 7, estimated: true }); }); test("carries prior context usage on failure when the current turn had no checkpoint", async () => { - const { partialUsageFromEventState } = await import("../src/adapters/cursor/live-transport"); - const { createCursorContextUsageTracker, createCursorProtobufEventState } = await import("../src/adapters/cursor/protobuf-events"); + const { partialUsageFromEventState } = await import("../../../src/adapters/cursor/live-transport"); + const { createCursorContextUsageTracker, createCursorProtobufEventState } = await import("../../../src/adapters/cursor/protobuf-events"); const tracker = createCursorContextUsageTracker(); tracker.record("cursor_conv_1", 18_000); const state = createCursorProtobufEventState({ @@ -186,14 +186,14 @@ describe("partialUsageFromEventState", () => { }); test("returns undefined when the stream died before any token signal", async () => { - const { partialUsageFromEventState } = await import("../src/adapters/cursor/live-transport"); - const { createCursorProtobufEventState } = await import("../src/adapters/cursor/protobuf-events"); + const { partialUsageFromEventState } = await import("../../../src/adapters/cursor/live-transport"); + const { createCursorProtobufEventState } = await import("../../../src/adapters/cursor/protobuf-events"); expect(partialUsageFromEventState(createCursorProtobufEventState())).toBeUndefined(); }); test("does not report seeded carry when a fresh turn failed before any token signal", async () => { - const { partialUsageFromEventState } = await import("../src/adapters/cursor/live-transport"); - const { createCursorContextUsageTracker, createCursorProtobufEventState } = await import("../src/adapters/cursor/protobuf-events"); + const { partialUsageFromEventState } = await import("../../../src/adapters/cursor/live-transport"); + const { createCursorContextUsageTracker, createCursorProtobufEventState } = await import("../../../src/adapters/cursor/protobuf-events"); const tracker = createCursorContextUsageTracker(); tracker.record("cursor_conv_1", 18_000); diff --git a/tests/cursor-kv-store.test.ts b/tests/providers/cursor/cursor-kv-store.test.ts similarity index 86% rename from tests/cursor-kv-store.test.ts rename to tests/providers/cursor/cursor-kv-store.test.ts index 4162f025e65..eb4a782997c 100644 --- a/tests/cursor-kv-store.test.ts +++ b/tests/providers/cursor/cursor-kv-store.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { createCursorKvStore } from "../src/adapters/cursor/kv-store"; -import { createTranslatorBudget } from "../src/lib/translator-budget"; +import { createCursorKvStore } from "../../../src/adapters/cursor/kv-store"; +import { createTranslatorBudget } from "../../../src/lib/translator-budget"; const bytes = (...values: number[]) => new Uint8Array(values); const store = (seed: Record = {}) => createCursorKvStore(seed, createTranslatorBudget()); diff --git a/tests/cursor-live-smoke-gate.test.ts b/tests/providers/cursor/cursor-live-smoke-gate.test.ts similarity index 97% rename from tests/cursor-live-smoke-gate.test.ts rename to tests/providers/cursor/cursor-live-smoke-gate.test.ts index d585fb78d04..b317fe75c5a 100644 --- a/tests/cursor-live-smoke-gate.test.ts +++ b/tests/providers/cursor/cursor-live-smoke-gate.test.ts @@ -5,7 +5,7 @@ import { cursorLiveSmokeSkipMessage, getCursorLiveSmokeToken, readCursorLiveSmokeGate, -} from "../src/adapters/cursor/live-smoke-gate"; +} from "../../../src/adapters/cursor/live-smoke-gate"; const fakeSecret = "secret-cursor-token-123"; diff --git a/tests/cursor-live-transport.test.ts b/tests/providers/cursor/cursor-live-transport.test.ts similarity index 96% rename from tests/cursor-live-transport.test.ts rename to tests/providers/cursor/cursor-live-transport.test.ts index d2217fa0004..082230eaa53 100644 --- a/tests/cursor-live-transport.test.ts +++ b/tests/providers/cursor/cursor-live-transport.test.ts @@ -3,22 +3,22 @@ import { PassThrough } from "node:stream"; import type { ChildProcessWithoutNullStreams } from "node:child_process"; import { create } from "@bufbuild/protobuf"; import { afterEach, describe, expect, test } from "bun:test"; -import { createLiveCursorTransport, CursorMissingCredentialError, parseConnectEndStreamError, resolveCursorToken } from "../src/adapters/cursor/live-transport"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import { prepareCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; +import { createLiveCursorTransport, CursorMissingCredentialError, parseConnectEndStreamError, resolveCursorToken } from "../../../src/adapters/cursor/live-transport"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; +import { prepareCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; import { CursorBlobAdmissionError, cursorBlobRetainedStoreSnapshot, resetCursorBlobStateForTests, setCursorBlobLimitsForTests, -} from "../src/adapters/cursor/native-exec"; +} from "../../../src/adapters/cursor/native-exec"; import { backgroundShellSpawnExec, resetBackgroundShellStateForTests, setBackgroundShellRuntimeForTests, -} from "../src/adapters/cursor/native-exec-shell"; -import { BackgroundShellSpawnArgsSchema, ExecServerMessageSchema } from "../src/adapters/cursor/gen/agent_pb"; -import type { CursorProtobufEventState } from "../src/adapters/cursor/protobuf-events"; +} from "../../../src/adapters/cursor/native-exec-shell"; +import { BackgroundShellSpawnArgsSchema, ExecServerMessageSchema } from "../../../src/adapters/cursor/gen/agent_pb"; +import type { CursorProtobufEventState } from "../../../src/adapters/cursor/protobuf-events"; class TransportFakeChild extends EventEmitter { readonly stdin = new PassThrough(); diff --git a/tests/cursor-local-models-schema.test.ts b/tests/providers/cursor/cursor-local-models-schema.test.ts similarity index 95% rename from tests/cursor-local-models-schema.test.ts rename to tests/providers/cursor/cursor-local-models-schema.test.ts index 2b0c9759c03..93c4be1840b 100644 --- a/tests/cursor-local-models-schema.test.ts +++ b/tests/providers/cursor/cursor-local-models-schema.test.ts @@ -2,21 +2,21 @@ import { afterEach, beforeEach, describe, expect, setDefaultTimeout, test } from import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; -import { nativeOpenAiContextTier, nativeReasoningEfforts } from "../src/codex/catalog"; +import { saveConfig } from "../../../src/config"; +import { nativeOpenAiContextTier, nativeReasoningEfforts } from "../../../src/codex/catalog"; import { resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests, -} from "../src/codex/model-entitlements"; -import { startServer } from "../src/server"; +} from "../../../src/codex/model-entitlements"; +import { startServer } from "../../../src/server"; import { modelCapabilityFields, OPENAI_FAMILY_API_TYPES, OPENCODEX_MODEL_API_TYPES, -} from "../src/server/models-capabilities"; -import type { OcxConfig } from "../src/types"; -import { SERVER_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/server/models-capabilities"; +import type { OcxConfig } from "../../../src/types"; +import { SERVER_BUDGET_MS } from "../../helpers/test-budget"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; // Cursor's local-agent runtime ("Private Inference" build) only enables its reasoning-effort // control when a GET /v1/models row carries api_types (+ optional capabilities). These cases diff --git a/tests/cursor-mcp-manager.test.ts b/tests/providers/cursor/cursor-mcp-manager.test.ts similarity index 97% rename from tests/cursor-mcp-manager.test.ts rename to tests/providers/cursor/cursor-mcp-manager.test.ts index 1fcbc89b1d6..f6b3d8ffbbb 100644 --- a/tests/cursor-mcp-manager.test.ts +++ b/tests/providers/cursor/cursor-mcp-manager.test.ts @@ -11,12 +11,12 @@ import { McpArgsSchema, ReadMcpResourceExecArgsSchema, RequestContextArgsSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import { handleCursorNativeExec } from "../src/adapters/cursor/native-exec"; -import { resolveMcpServers } from "../src/adapters/cursor/mcp-config"; -import { CursorMcpManager, CursorMcpPayloadTooLargeError, McpCatalogLimitError } from "../src/adapters/cursor/mcp-manager"; -import { buildMcpToolDefinitions, mcpDepsFromManager } from "../src/adapters/cursor/native-exec-mcp"; -import type { OcxProviderConfig } from "../src/types"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { handleCursorNativeExec } from "../../../src/adapters/cursor/native-exec"; +import { resolveMcpServers } from "../../../src/adapters/cursor/mcp-config"; +import { CursorMcpManager, CursorMcpPayloadTooLargeError, McpCatalogLimitError } from "../../../src/adapters/cursor/mcp-manager"; +import { buildMcpToolDefinitions, mcpDepsFromManager } from "../../../src/adapters/cursor/native-exec-mcp"; +import type { OcxProviderConfig } from "../../../src/types"; const textEncoder = new TextEncoder(); // 1x1 transparent PNG, base64 — exercises real image-content fidelity (not a placeholder). diff --git a/tests/cursor-mcp-stdio.test.ts b/tests/providers/cursor/cursor-mcp-stdio.test.ts similarity index 93% rename from tests/cursor-mcp-stdio.test.ts rename to tests/providers/cursor/cursor-mcp-stdio.test.ts index c938c56b3ea..73008ad99cf 100644 --- a/tests/cursor-mcp-stdio.test.ts +++ b/tests/providers/cursor/cursor-mcp-stdio.test.ts @@ -2,7 +2,7 @@ import { fromBinary, create } from "@bufbuild/protobuf"; import { afterEach, beforeEach, describe, expect, setDefaultTimeout, test } from "bun:test"; import { mkdtempSync, writeFileSync } from "node:fs"; import { join } from "node:path"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; // Real child-process spawns resolve packages through bun's install cache; Windows CI runners // ("Slow filesystem detected") can take >5s for the first spawn. Explicit headroom. @@ -11,10 +11,10 @@ import { AgentClientMessageSchema, ExecServerMessageSchema, McpArgsSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import { handleCursorNativeExec } from "../src/adapters/cursor/native-exec"; -import { CursorMcpManager } from "../src/adapters/cursor/mcp-manager"; -import { buildMcpToolDefinitions, mcpDepsFromManager } from "../src/adapters/cursor/native-exec-mcp"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { handleCursorNativeExec } from "../../../src/adapters/cursor/native-exec"; +import { CursorMcpManager } from "../../../src/adapters/cursor/mcp-manager"; +import { buildMcpToolDefinitions, mcpDepsFromManager } from "../../../src/adapters/cursor/native-exec-mcp"; /** * Live stdio integration: spawns a REAL MCP server as a child process over actual stdio diff --git a/tests/cursor-message-mapper.test.ts b/tests/providers/cursor/cursor-message-mapper.test.ts similarity index 93% rename from tests/cursor-message-mapper.test.ts rename to tests/providers/cursor/cursor-message-mapper.test.ts index a404a6a4367..7218887d929 100644 --- a/tests/cursor-message-mapper.test.ts +++ b/tests/providers/cursor/cursor-message-mapper.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { createCursorKvStore } from "../src/adapters/cursor/kv-store"; -import { mapCursorServerMessage } from "../src/adapters/cursor/message-mapper"; -import type { CursorClientMessage } from "../src/adapters/cursor/types"; -import { createTranslatorBudget } from "../src/lib/translator-budget"; +import { createCursorKvStore } from "../../../src/adapters/cursor/kv-store"; +import { mapCursorServerMessage } from "../../../src/adapters/cursor/message-mapper"; +import type { CursorClientMessage } from "../../../src/adapters/cursor/types"; +import { createTranslatorBudget } from "../../../src/lib/translator-budget"; const bytes = (...values: number[]) => new Uint8Array(values); const kvStore = (seed: Record = {}) => createCursorKvStore(seed, createTranslatorBudget()); diff --git a/tests/cursor-native-exec-common.test.ts b/tests/providers/cursor/cursor-native-exec-common.test.ts similarity index 95% rename from tests/cursor-native-exec-common.test.ts rename to tests/providers/cursor/cursor-native-exec-common.test.ts index dcc9cd4629e..8518a9c00d7 100644 --- a/tests/cursor-native-exec-common.test.ts +++ b/tests/providers/cursor/cursor-native-exec-common.test.ts @@ -1,6 +1,6 @@ import { create, fromBinary } from "@bufbuild/protobuf"; import { describe, expect, test } from "bun:test"; -import { execBytes } from "../src/adapters/cursor/native-exec-common"; +import { execBytes } from "../../../src/adapters/cursor/native-exec-common"; import { AgentClientMessageSchema, DiagnosticsErrorSchema, @@ -11,7 +11,7 @@ import { RequestContextSuccessSchema, RequestContextResultSchema, RequestContextSchema, -} from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; function execServerMessage(message: Parameters>[1]["message"]) { return create(ExecServerMessageSchema, { id: 7, execId: "exec-test", message }); diff --git a/tests/cursor-native-exec-policy.test.ts b/tests/providers/cursor/cursor-native-exec-policy.test.ts similarity index 96% rename from tests/cursor-native-exec-policy.test.ts rename to tests/providers/cursor/cursor-native-exec-policy.test.ts index 1cf33ba21bb..24b63e28ea5 100644 --- a/tests/cursor-native-exec-policy.test.ts +++ b/tests/providers/cursor/cursor-native-exec-policy.test.ts @@ -3,12 +3,12 @@ import { tmpdir } from "node:os"; import { join } from "node:path"; import { create, fromBinary } from "@bufbuild/protobuf"; import { afterEach, describe, expect, test } from "bun:test"; -import { createCursorAdapter } from "../src/adapters/cursor"; +import { createCursorAdapter } from "../../../src/adapters/cursor"; import { cursorRequestDeclaresFullAccess, effectiveCursorNativeExecAllow, resolveCursorNativeExecMode, -} from "../src/adapters/cursor/exec-policy"; +} from "../../../src/adapters/cursor/exec-policy"; import { AgentClientMessageSchema, BackgroundShellSpawnArgsSchema, @@ -16,15 +16,15 @@ import { FetchArgsSchema, ReadArgsSchema, ShellArgsSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import { handleCursorNativeExec } from "../src/adapters/cursor/native-exec"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { handleCursorNativeExec } from "../../../src/adapters/cursor/native-exec"; import { resetBackgroundShellStateForTests, setBackgroundShellRuntimeForTests, -} from "../src/adapters/cursor/native-exec-shell"; -import type { CursorTransportFactoryInput } from "../src/adapters/cursor/transport"; -import { parseRequest } from "../src/responses/parser"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +} from "../../../src/adapters/cursor/native-exec-shell"; +import type { CursorTransportFactoryInput } from "../../../src/adapters/cursor/transport"; +import { parseRequest } from "../../../src/responses/parser"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; const fullAccessDeclaration = "`sandbox_mode` is `danger-full-access`"; diff --git a/tests/cursor-native-exec-shell.test.ts b/tests/providers/cursor/cursor-native-exec-shell.test.ts similarity index 99% rename from tests/cursor-native-exec-shell.test.ts rename to tests/providers/cursor/cursor-native-exec-shell.test.ts index a5a8e96c643..bb0cdd9c75e 100644 --- a/tests/cursor-native-exec-shell.test.ts +++ b/tests/providers/cursor/cursor-native-exec-shell.test.ts @@ -10,7 +10,7 @@ import { ShellArgsSchema, WriteShellStdinArgsSchema, type AgentClientMessage, -} from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; import { CURSOR_BACKGROUND_SHELL_ABSOLUTE_MS, CURSOR_BACKGROUND_SHELL_IDLE_MS, @@ -26,7 +26,7 @@ import { terminateAllBackgroundShells, terminateBackgroundShellsForSession, writeShellStdinExec, -} from "../src/adapters/cursor/native-exec-shell"; +} from "../../../src/adapters/cursor/native-exec-shell"; function decodeClient(bytes: Uint8Array): AgentClientMessage { return fromBinary(AgentClientMessageSchema, bytes); diff --git a/tests/cursor-native-exec.test.ts b/tests/providers/cursor/cursor-native-exec.test.ts similarity index 99% rename from tests/cursor-native-exec.test.ts rename to tests/providers/cursor/cursor-native-exec.test.ts index be1ac99c474..6fb24ff1126 100644 --- a/tests/cursor-native-exec.test.ts +++ b/tests/providers/cursor/cursor-native-exec.test.ts @@ -3,12 +3,12 @@ import { tmpdir } from "node:os"; import { join } from "node:path"; import { create, fromBinary } from "@bufbuild/protobuf"; import { afterEach, describe, expect, test } from "bun:test"; -import { handleCursorNativeExec } from "../src/adapters/cursor/native-exec"; +import { handleCursorNativeExec } from "../../../src/adapters/cursor/native-exec"; import { backgroundShellAdmissionMetrics, resetBackgroundShellStateForTests, setBackgroundShellRuntimeForTests, -} from "../src/adapters/cursor/native-exec-shell"; +} from "../../../src/adapters/cursor/native-exec-shell"; import { AgentClientMessageSchema, BackgroundShellSpawnArgsSchema, @@ -33,7 +33,7 @@ import { ShellArgsSchema, WriteShellStdinArgsSchema, WriteArgsSchema, -} from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; function execMessage(message: Parameters>[1]["message"]) { return create(ExecServerMessageSchema, { diff --git a/tests/cursor-oauth-shell.test.ts b/tests/providers/cursor/cursor-oauth-shell.test.ts similarity index 83% rename from tests/cursor-oauth-shell.test.ts rename to tests/providers/cursor/cursor-oauth-shell.test.ts index 9b231d8492c..2b422bbc106 100644 --- a/tests/cursor-oauth-shell.test.ts +++ b/tests/providers/cursor/cursor-oauth-shell.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from "bun:test"; -import { buildInitProviders } from "../src/cli/init"; -import { isOAuthProvider, listOAuthProviders } from "../src/oauth"; -import { deriveProviderPresets } from "../src/providers/derive"; +import { buildInitProviders } from "../../../src/cli/init"; +import { isOAuthProvider, listOAuthProviders } from "../../../src/oauth"; +import { deriveProviderPresets } from "../../../src/providers/derive"; // WP16 (devlog 350.100): the disabled OAuth shell was replaced by the real PKCE flow — the flow -// itself is covered by tests/cursor-oauth.test.ts. These tests cover cursor's provider-routing, +// itself is covered by tests/providers/cursor/cursor-oauth.test.ts. These tests cover cursor's provider-routing, // init/preset metadata, and the OAuth module's standalone property (no local fs/process/http2). describe("Cursor provider routing + standalone OAuth module", () => { // WP17 (devlog 350.101): cursor is now registered in OAUTH_PROVIDERS. diff --git a/tests/cursor-oauth.test.ts b/tests/providers/cursor/cursor-oauth.test.ts similarity index 99% rename from tests/cursor-oauth.test.ts rename to tests/providers/cursor/cursor-oauth.test.ts index c4f3b2651ba..640301564da 100644 --- a/tests/cursor-oauth.test.ts +++ b/tests/providers/cursor/cursor-oauth.test.ts @@ -6,7 +6,7 @@ import { loginCursor, pollCursorAuth, refreshCursorToken, -} from "../src/oauth/cursor"; +} from "../../../src/oauth/cursor"; const realFetch = globalThis.fetch; afterEach(() => { diff --git a/tests/cursor-pool.test.ts b/tests/providers/cursor/cursor-pool.test.ts similarity index 96% rename from tests/cursor-pool.test.ts rename to tests/providers/cursor/cursor-pool.test.ts index 25881e8c489..a636b14e2aa 100644 --- a/tests/cursor-pool.test.ts +++ b/tests/providers/cursor/cursor-pool.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { CursorCredentialRouter, NoAvailableCursorCredentialError } from "../src/providers/cursor-pool"; +import { CursorCredentialRouter, NoAvailableCursorCredentialError } from "../../../src/providers/cursor-pool"; describe("CursorCredentialRouter", () => { test("weighted round-robin distributes picks proportionally", () => { diff --git a/tests/cursor-protobuf-events.test.ts b/tests/providers/cursor/cursor-protobuf-events.test.ts similarity index 99% rename from tests/cursor-protobuf-events.test.ts rename to tests/providers/cursor/cursor-protobuf-events.test.ts index 8da54852158..53c198772bb 100644 --- a/tests/cursor-protobuf-events.test.ts +++ b/tests/providers/cursor/cursor-protobuf-events.test.ts @@ -13,17 +13,17 @@ import { ToolCallCompletedUpdateSchema, ToolCallSchema, ToolCallStartedUpdateSchema, -} from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; import { createCursorContextUsageTracker, createCursorProtobufEventState, finalizeTurnEvents, mapCursorProtobufServerMessage, mapSyntheticMcpExecToToolEvents, -} from "../src/adapters/cursor/protobuf-events"; -import { createTranslatorBudget } from "../src/lib/translator-budget"; -import { observeEmptyCompletion } from "../src/server/responses/empty-completion-guard"; -import type { AdapterEvent } from "../src/types"; +} from "../../../src/adapters/cursor/protobuf-events"; +import { createTranslatorBudget } from "../../../src/lib/translator-budget"; +import { observeEmptyCompletion } from "../../../src/server/responses/empty-completion-guard"; +import type { AdapterEvent } from "../../../src/types"; const encoder = new TextEncoder(); diff --git a/tests/cursor-repetition-breaker.test.ts b/tests/providers/cursor/cursor-repetition-breaker.test.ts similarity index 96% rename from tests/cursor-repetition-breaker.test.ts rename to tests/providers/cursor/cursor-repetition-breaker.test.ts index bba00b39e92..48b9ca0ac2a 100644 --- a/tests/cursor-repetition-breaker.test.ts +++ b/tests/providers/cursor/cursor-repetition-breaker.test.ts @@ -1,14 +1,14 @@ import { describe, expect, test } from "bun:test"; import { fromBinary } from "@bufbuild/protobuf"; -import { encodeCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; -import { handleCursorNativeKv } from "../src/adapters/cursor/native-exec"; +import { encodeCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; +import { handleCursorNativeKv } from "../../../src/adapters/cursor/native-exec"; import { create } from "@bufbuild/protobuf"; import { AgentClientMessageSchema, GetBlobArgsSchema, KvServerMessageSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import type { OcxMessage } from "../src/types"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import type { OcxMessage } from "../../../src/types"; function blobData(blobId: Uint8Array): Uint8Array { const reply = fromBinary(AgentClientMessageSchema, handleCursorNativeKv(create(KvServerMessageSchema, { diff --git a/tests/cursor-request-builder.test.ts b/tests/providers/cursor/cursor-request-builder.test.ts similarity index 99% rename from tests/cursor-request-builder.test.ts rename to tests/providers/cursor/cursor-request-builder.test.ts index 4ecd87993f2..0e1b355b30d 100644 --- a/tests/cursor-request-builder.test.ts +++ b/tests/providers/cursor/cursor-request-builder.test.ts @@ -1,13 +1,13 @@ import { describe, expect, test } from "bun:test"; import { create, toBinary } from "@bufbuild/protobuf"; -import { ConversationStateStructureSchema } from "../src/adapters/cursor/gen/agent_pb"; +import { ConversationStateStructureSchema } from "../../../src/adapters/cursor/gen/agent_pb"; import { clearCursorCheckpointsForTests, commitCursorCheckpoint, CURSOR_CHECKPOINT_TTL_MS, getCursorCheckpoint, installCursorCheckpointClockForTests, -} from "../src/adapters/cursor/checkpoint-store"; +} from "../../../src/adapters/cursor/checkpoint-store"; import { applyCursorToolBudget, createCursorRequest, @@ -15,12 +15,12 @@ import { cursorInstructionDigest, CURSOR_TOOL_BYTES_LIMIT, CURSOR_TOOL_COUNT_LIMIT, -} from "../src/adapters/cursor/request-builder"; -import { cursorCheckpointModelAffinityId } from "../src/adapters/cursor/discovery"; -import { cursorMcpToolsEncodedSize } from "../src/adapters/cursor/tool-definitions"; -import { encodeCursorCallId, resetCursorCallIdProvenanceForTests } from "../src/adapters/cursor/call-id"; -import { parseRequest } from "../src/responses/parser"; -import type { OcxParsedRequest } from "../src/types"; +} from "../../../src/adapters/cursor/request-builder"; +import { cursorCheckpointModelAffinityId } from "../../../src/adapters/cursor/discovery"; +import { cursorMcpToolsEncodedSize } from "../../../src/adapters/cursor/tool-definitions"; +import { encodeCursorCallId, resetCursorCallIdProvenanceForTests } from "../../../src/adapters/cursor/call-id"; +import { parseRequest } from "../../../src/responses/parser"; +import type { OcxParsedRequest } from "../../../src/types"; const base: OcxParsedRequest = { modelId: "cursor/auto", diff --git a/tests/cursor-silent-redirect.test.ts b/tests/providers/cursor/cursor-silent-redirect.test.ts similarity index 94% rename from tests/cursor-silent-redirect.test.ts rename to tests/providers/cursor/cursor-silent-redirect.test.ts index 8f63daf4b31..3699f21ab28 100644 --- a/tests/cursor-silent-redirect.test.ts +++ b/tests/providers/cursor/cursor-silent-redirect.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { nativeShellDisabledMessage } from "../src/adapters/cursor/native-exec-shell"; +import { nativeShellDisabledMessage } from "../../../src/adapters/cursor/native-exec-shell"; /** * Devlog 260826 gap-8: native-tool denial payloads must read as silent redirects. diff --git a/tests/cursor-static-catalog.test.ts b/tests/providers/cursor/cursor-static-catalog.test.ts similarity index 92% rename from tests/cursor-static-catalog.test.ts rename to tests/providers/cursor/cursor-static-catalog.test.ts index 87f73320b91..511cb8ac3f3 100644 --- a/tests/cursor-static-catalog.test.ts +++ b/tests/providers/cursor/cursor-static-catalog.test.ts @@ -1,14 +1,14 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { buildCatalogEntries, gatherRoutedModels } from "../src/codex/catalog"; +import { buildCatalogEntries, gatherRoutedModels } from "../../../src/codex/catalog"; import { CURSOR_STATIC_MODELS, cursorModelContextWindows, cursorModelIds, cursorModelInputModalities, cursorModelReasoningEfforts, -} from "../src/adapters/cursor/discovery"; -import { cursorModelHasEffortTiers } from "../src/adapters/cursor/effort-map"; -import { clearModelCache } from "../src/codex/model-cache"; +} from "../../../src/adapters/cursor/discovery"; +import { cursorModelHasEffortTiers } from "../../../src/adapters/cursor/effort-map"; +import { clearModelCache } from "../../../src/codex/model-cache"; const originalFetch = globalThis.fetch; @@ -125,8 +125,8 @@ describe("Opus Fast catalog families (devlog 300, live-verified 260822)", () => // Umbrella merge (devlog 260828): the -fast rows folded into their bases. // The alias path still resolves them with the exact live-verified ladders. test("fast rows folded into bases; aliases keep resolving with tier semantics", async () => { - const { CURSOR_STATIC_MODELS } = await import("../src/adapters/cursor/discovery"); - const { resolveCursorSelection } = await import("../src/adapters/cursor/catalog"); + const { CURSOR_STATIC_MODELS } = await import("../../../src/adapters/cursor/discovery"); + const { resolveCursorSelection } = await import("../../../src/adapters/cursor/catalog"); for (const id of ["claude-opus-4-7-fast", "claude-opus-4-8-fast", "claude-opus-5-fast"]) { expect(CURSOR_STATIC_MODELS.some(model => model.id === id)).toBe(false); // Alias never sends a bare -fast id (not_found on the wire). @@ -136,14 +136,14 @@ describe("Opus Fast catalog families (devlog 300, live-verified 260822)", () => }); test("tier ladders match the 260822 GetUsableModels dump", async () => { - const { cursorModelEffortLadder } = await import("../src/adapters/cursor/effort-map"); + const { cursorModelEffortLadder } = await import("../../../src/adapters/cursor/effort-map"); expect(cursorModelEffortLadder("claude-opus-4-7-fast")).toEqual(["low", "medium", "high", "xhigh", "max"]); expect(cursorModelEffortLadder("claude-opus-4-8-fast")).toEqual(["low", "medium", "high", "xhigh", "max"]); expect(cursorModelEffortLadder("claude-opus-5-fast")).toEqual(["low", "medium", "high"]); }); test("wire-id derivation produces the live-verified suffixed forms and never a bare -fast id", async () => { - const { cursorWireModelIdWithEffort, cursorEffortSuffix } = await import("../src/adapters/cursor/effort-map"); + const { cursorWireModelIdWithEffort, cursorEffortSuffix } = await import("../../../src/adapters/cursor/effort-map"); expect(cursorWireModelIdWithEffort("claude-opus-4-8-fast", "high")).toBe("claude-opus-4-8-high-fast"); expect(cursorWireModelIdWithEffort("claude-opus-5-fast", "medium")).toBe("claude-opus-5-medium-fast"); expect(cursorWireModelIdWithEffort("claude-opus-4-7-fast", "max")).toBe("claude-opus-4-7-max-fast"); diff --git a/tests/cursor-stream-health.test.ts b/tests/providers/cursor/cursor-stream-health.test.ts similarity index 95% rename from tests/cursor-stream-health.test.ts rename to tests/providers/cursor/cursor-stream-health.test.ts index 3c8450b4ab0..dc7b572bf11 100644 --- a/tests/cursor-stream-health.test.ts +++ b/tests/providers/cursor/cursor-stream-health.test.ts @@ -8,11 +8,11 @@ import { InteractionUpdateSchema, TextDeltaUpdateSchema, TurnEndedUpdateSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import { encodeConnectFrame } from "../src/adapters/cursor/framing"; -import { createLiveCursorTransport } from "../src/adapters/cursor/live-transport"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import type { CursorRunRequest, CursorServerMessage } from "../src/adapters/cursor/types"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { encodeConnectFrame } from "../../../src/adapters/cursor/framing"; +import { createLiveCursorTransport } from "../../../src/adapters/cursor/live-transport"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; +import type { CursorRunRequest, CursorServerMessage } from "../../../src/adapters/cursor/types"; /** * T04 (devlog 260822_senpi_cursor_transfer/110): inbound stream-health watchdog. diff --git a/tests/cursor-structured-edit.test.ts b/tests/providers/cursor/cursor-structured-edit.test.ts similarity index 99% rename from tests/cursor-structured-edit.test.ts rename to tests/providers/cursor/cursor-structured-edit.test.ts index 294dc394cd4..b04e8ed1245 100644 --- a/tests/cursor-structured-edit.test.ts +++ b/tests/providers/cursor/cursor-structured-edit.test.ts @@ -1,6 +1,6 @@ import { create } from "@bufbuild/protobuf"; import { describe, expect, test } from "bun:test"; -import type { OcxTool } from "../src/types"; +import type { OcxTool } from "../../../src/types"; import { AgentServerMessageSchema, ExecServerMessageSchema, @@ -11,7 +11,7 @@ import { ToolCallCompletedUpdateSchema, ToolCallSchema, ToolCallStartedUpdateSchema, -} from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; import { createCursorProtobufEventState, foldSequentialStructuredEdits, @@ -20,11 +20,11 @@ import { sanitizeCodexApplyPatch, sanitizeEmittedApplyPatchArgs, translateStructuredEditCall, -} from "../src/adapters/cursor/protobuf-events"; -import { planMcpArgsHandling } from "../src/adapters/cursor/live-transport"; +} from "../../../src/adapters/cursor/protobuf-events"; +import { planMcpArgsHandling } from "../../../src/adapters/cursor/live-transport"; import { applyCursorToolBudget, -} from "../src/adapters/cursor/request-builder"; +} from "../../../src/adapters/cursor/request-builder"; import { buildCursorToolGuidanceSystemNote, CURSOR_EDIT_FILE_INPUT_SCHEMA, @@ -34,7 +34,7 @@ import { cursorStructuredEditTools, cursorToolsForActivePrompt, isCursorSyntheticStructuredEditTool, -} from "../src/adapters/cursor/tool-definitions"; +} from "../../../src/adapters/cursor/tool-definitions"; const encoder = new TextEncoder(); diff --git a/tests/cursor-tool-arg-decoding.test.ts b/tests/providers/cursor/cursor-tool-arg-decoding.test.ts similarity index 99% rename from tests/cursor-tool-arg-decoding.test.ts rename to tests/providers/cursor/cursor-tool-arg-decoding.test.ts index 5980ad92e15..9bcdd47f605 100644 --- a/tests/cursor-tool-arg-decoding.test.ts +++ b/tests/providers/cursor/cursor-tool-arg-decoding.test.ts @@ -9,12 +9,12 @@ import { ToolCallStartedUpdateSchema, ToolCallCompletedUpdateSchema, ToolCallSchema, -} from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; import { createCursorProtobufEventState, mapCursorProtobufServerMessage, mapSyntheticMcpExecToToolEvents, -} from "../src/adapters/cursor/protobuf-events"; +} from "../../../src/adapters/cursor/protobuf-events"; const encoder = new TextEncoder(); diff --git a/tests/cursor-tool-choice.test.ts b/tests/providers/cursor/cursor-tool-choice.test.ts similarity index 94% rename from tests/cursor-tool-choice.test.ts rename to tests/providers/cursor/cursor-tool-choice.test.ts index fe6da06331e..0a0861d0ab2 100644 --- a/tests/cursor-tool-choice.test.ts +++ b/tests/providers/cursor/cursor-tool-choice.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { buildCursorToolDefinitions } from "../src/adapters/cursor/tool-definitions"; -import { createCursorRequest } from "../src/adapters/cursor/request-builder"; -import { parseRequest } from "../src/responses/parser"; -import type { OcxTool } from "../src/types"; +import { buildCursorToolDefinitions } from "../../../src/adapters/cursor/tool-definitions"; +import { createCursorRequest } from "../../../src/adapters/cursor/request-builder"; +import { parseRequest } from "../../../src/responses/parser"; +import type { OcxTool } from "../../../src/types"; const tools: OcxTool[] = [ { name: "read_file", namespace: "mcp__fs", description: "Read", parameters: {} }, diff --git a/tests/cursor-tool-continuation.test.ts b/tests/providers/cursor/cursor-tool-continuation.test.ts similarity index 96% rename from tests/cursor-tool-continuation.test.ts rename to tests/providers/cursor/cursor-tool-continuation.test.ts index 2772245035c..6196af58da2 100644 --- a/tests/cursor-tool-continuation.test.ts +++ b/tests/providers/cursor/cursor-tool-continuation.test.ts @@ -1,13 +1,13 @@ import { describe, expect, test } from "bun:test"; import { create, fromBinary } from "@bufbuild/protobuf"; -import { handleCursorNativeKv } from "../src/adapters/cursor/native-exec"; -import { encodeCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; +import { handleCursorNativeKv } from "../../../src/adapters/cursor/native-exec"; +import { encodeCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; import { AgentClientMessageSchema, GetBlobArgsSchema, KvServerMessageSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import type { OcxMessage } from "../src/types"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import type { OcxMessage } from "../../../src/types"; function blobData(blobId: Uint8Array): Uint8Array { const reply = fromBinary(AgentClientMessageSchema, handleCursorNativeKv(create(KvServerMessageSchema, { @@ -119,9 +119,9 @@ describe("363-B: tool result reaches the model via rootPromptMessagesJson", () = }); import { create as createPb } from "@bufbuild/protobuf"; -import { ExecServerMessageSchema, McpArgsSchema } from "../src/adapters/cursor/gen/agent_pb"; -import { createCursorContextUsageTracker, createCursorProtobufEventState } from "../src/adapters/cursor/protobuf-events"; -import { planMcpArgsHandling, finalizeAfterDrain } from "../src/adapters/cursor/live-transport"; +import { ExecServerMessageSchema, McpArgsSchema } from "../../../src/adapters/cursor/gen/agent_pb"; +import { createCursorContextUsageTracker, createCursorProtobufEventState } from "../../../src/adapters/cursor/protobuf-events"; +import { planMcpArgsHandling, finalizeAfterDrain } from "../../../src/adapters/cursor/live-transport"; function execMcpArgs(opts: { provider?: string; toolName?: string; toolCallId?: string; args?: Record }) { return createPb(ExecServerMessageSchema, { diff --git a/tests/cursor-tool-definitions.test.ts b/tests/providers/cursor/cursor-tool-definitions.test.ts similarity index 99% rename from tests/cursor-tool-definitions.test.ts rename to tests/providers/cursor/cursor-tool-definitions.test.ts index d87d77d0679..f21ae2fb279 100644 --- a/tests/cursor-tool-definitions.test.ts +++ b/tests/providers/cursor/cursor-tool-definitions.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; import { fromBinary, toJson } from "@bufbuild/protobuf"; import { ValueSchema } from "@bufbuild/protobuf/wkt"; -import { normalizeArgKeys } from "../src/adapters/cursor/arg-normalize"; +import { normalizeArgKeys } from "../../../src/adapters/cursor/arg-normalize"; import { appendCursorGenericToolUseHint, buildCursorToolDefinitions, @@ -16,8 +16,8 @@ import { cursorToolWireName, isGenericToolUseCountDemoPrompt, nonEmptyShellBridgeCommandFromArgs, -} from "../src/adapters/cursor/tool-definitions"; -import type { OcxTool } from "../src/types"; +} from "../../../src/adapters/cursor/tool-definitions"; +import type { OcxTool } from "../../../src/types"; describe("Cursor tool definitions", () => { test("converts Responses tools to Cursor request context definitions", () => { diff --git a/tests/cursor-tool-finalize-race.test.ts b/tests/providers/cursor/cursor-tool-finalize-race.test.ts similarity index 96% rename from tests/cursor-tool-finalize-race.test.ts rename to tests/providers/cursor/cursor-tool-finalize-race.test.ts index 867d9425613..e16a6c28f8a 100644 --- a/tests/cursor-tool-finalize-race.test.ts +++ b/tests/providers/cursor/cursor-tool-finalize-race.test.ts @@ -1,9 +1,9 @@ import { describe, expect, test } from "bun:test"; import { create, toBinary } from "@bufbuild/protobuf"; -import { clientToolFinalizeGraceMsForRequest, createLiveCursorTransport } from "../src/adapters/cursor/live-transport"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import { createCursorProtobufEventState } from "../src/adapters/cursor/protobuf-events"; -import type { CursorRunRequest, CursorServerMessage } from "../src/adapters/cursor/types"; +import { clientToolFinalizeGraceMsForRequest, createLiveCursorTransport } from "../../../src/adapters/cursor/live-transport"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; +import { createCursorProtobufEventState } from "../../../src/adapters/cursor/protobuf-events"; +import type { CursorRunRequest, CursorServerMessage } from "../../../src/adapters/cursor/types"; import { AgentServerMessageSchema, ExecServerMessageSchema, @@ -13,7 +13,7 @@ import { ToolCallCompletedUpdateSchema, ToolCallStartedUpdateSchema, InteractionUpdateSchema, -} from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; const PROVIDER = "opencodex-responses"; diff --git a/tests/cursor-tool-result-image.test.ts b/tests/providers/cursor/cursor-tool-result-image.test.ts similarity index 98% rename from tests/cursor-tool-result-image.test.ts rename to tests/providers/cursor/cursor-tool-result-image.test.ts index 610c25e3c44..90c09ffaab4 100644 --- a/tests/cursor-tool-result-image.test.ts +++ b/tests/providers/cursor/cursor-tool-result-image.test.ts @@ -1,15 +1,15 @@ import { describe, expect, test } from "bun:test"; import { create, fromBinary } from "@bufbuild/protobuf"; -import { handleCursorNativeKv, setCursorBlobLimitsForTests } from "../src/adapters/cursor/native-exec"; -import { encodeCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; +import { handleCursorNativeKv, setCursorBlobLimitsForTests } from "../../../src/adapters/cursor/native-exec"; +import { encodeCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; import { AgentClientMessageSchema, ConversationTurnStructureSchema, ConversationStepSchema, GetBlobArgsSchema, KvServerMessageSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import type { OcxMessage } from "../src/types"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import type { OcxMessage } from "../../../src/types"; const PNG_BYTES = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x01, 0x02, 0x03, 0x04]); const PNG_B64 = Buffer.from(PNG_BYTES).toString("base64"); diff --git a/tests/cursor-tool-result-invocation.test.ts b/tests/providers/cursor/cursor-tool-result-invocation.test.ts similarity index 99% rename from tests/cursor-tool-result-invocation.test.ts rename to tests/providers/cursor/cursor-tool-result-invocation.test.ts index 2c87fe0942a..aa3b9d16d07 100644 --- a/tests/cursor-tool-result-invocation.test.ts +++ b/tests/providers/cursor/cursor-tool-result-invocation.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; import { create, fromBinary, toBinary } from "@bufbuild/protobuf"; -import { CURSOR_INVOCATION_ARGUMENTS_BYTE_LIMIT, encodeCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; -import { handleCursorNativeKv, storeCursorBlob } from "../src/adapters/cursor/native-exec"; +import { CURSOR_INVOCATION_ARGUMENTS_BYTE_LIMIT, encodeCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; +import { handleCursorNativeKv, storeCursorBlob } from "../../../src/adapters/cursor/native-exec"; import { AgentClientMessageSchema, ConversationStepSchema, @@ -9,8 +9,8 @@ import { ConversationTurnStructureSchema, GetBlobArgsSchema, KvServerMessageSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import type { OcxMessage } from "../src/types"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import type { OcxMessage } from "../../../src/types"; function blobData(blobId: Uint8Array): Uint8Array { const reply = fromBinary(AgentClientMessageSchema, handleCursorNativeKv(create(KvServerMessageSchema, { diff --git a/tests/cursor-tool-suspended-checkpoint.test.ts b/tests/providers/cursor/cursor-tool-suspended-checkpoint.test.ts similarity index 92% rename from tests/cursor-tool-suspended-checkpoint.test.ts rename to tests/providers/cursor/cursor-tool-suspended-checkpoint.test.ts index 6461d20a48a..4ce1152173e 100644 --- a/tests/cursor-tool-suspended-checkpoint.test.ts +++ b/tests/providers/cursor/cursor-tool-suspended-checkpoint.test.ts @@ -1,11 +1,11 @@ import { describe, expect, test } from "bun:test"; -import { createCursorAdapter as createCursorAdapterProduction } from "../src/adapters/cursor"; -import { clearCursorCheckpointsForTests, getCursorCheckpoint } from "../src/adapters/cursor/checkpoint-store"; +import { createCursorAdapter as createCursorAdapterProduction } from "../../../src/adapters/cursor"; +import { clearCursorCheckpointsForTests, getCursorCheckpoint } from "../../../src/adapters/cursor/checkpoint-store"; import { create, toBinary } from "@bufbuild/protobuf"; -import { ConversationStateStructureSchema } from "../src/adapters/cursor/gen/agent_pb"; -import type { AdapterEvent, OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import type { CursorServerMessage } from "../src/adapters/cursor/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { ConversationStateStructureSchema } from "../../../src/adapters/cursor/gen/agent_pb"; +import type { AdapterEvent, OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; +import type { CursorServerMessage } from "../../../src/adapters/cursor/types"; +import { withTestTranslatorBudget } from "../../helpers/translator-budget"; const createCursorAdapter = (...args: Parameters) => withTestTranslatorBudget(createCursorAdapterProduction(...args)); diff --git a/tests/cursor-toolresult-normalize.test.ts b/tests/providers/cursor/cursor-toolresult-normalize.test.ts similarity index 95% rename from tests/cursor-toolresult-normalize.test.ts rename to tests/providers/cursor/cursor-toolresult-normalize.test.ts index e4d52835449..c62ad8e27b2 100644 --- a/tests/cursor-toolresult-normalize.test.ts +++ b/tests/providers/cursor/cursor-toolresult-normalize.test.ts @@ -1,16 +1,16 @@ import { describe, expect, test } from "bun:test"; import { create, fromBinary } from "@bufbuild/protobuf"; -import { handleCursorNativeKv } from "../src/adapters/cursor/native-exec"; -import { encodeCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; -import { normalizeCursorToolResultText } from "../src/adapters/cursor/tool-result-normalize"; +import { handleCursorNativeKv } from "../../../src/adapters/cursor/native-exec"; +import { encodeCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; +import { normalizeCursorToolResultText } from "../../../src/adapters/cursor/tool-result-normalize"; import { AgentClientMessageSchema, ConversationTurnStructureSchema, ConversationStepSchema, GetBlobArgsSchema, KvServerMessageSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import type { OcxMessage, OcxToolResultMessage } from "../src/types"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import type { OcxMessage, OcxToolResultMessage } from "../../../src/types"; function blobData(blobId: Uint8Array): Uint8Array { const reply = fromBinary(AgentClientMessageSchema, handleCursorNativeKv(create(KvServerMessageSchema, { diff --git a/tests/cursor-transport-retry.test.ts b/tests/providers/cursor/cursor-transport-retry.test.ts similarity index 98% rename from tests/cursor-transport-retry.test.ts rename to tests/providers/cursor/cursor-transport-retry.test.ts index 2c85c985184..fe55b0f825c 100644 --- a/tests/cursor-transport-retry.test.ts +++ b/tests/providers/cursor/cursor-transport-retry.test.ts @@ -3,9 +3,9 @@ import { cursorRetryDelayMs, isRetryableCursorError, runCursorTurnWithRetry, -} from "../src/adapters/cursor/transport-retry"; -import type { CursorRunRequest, CursorServerMessage } from "../src/adapters/cursor/types"; -import type { CursorTransport } from "../src/adapters/cursor/transport"; +} from "../../../src/adapters/cursor/transport-retry"; +import type { CursorRunRequest, CursorServerMessage } from "../../../src/adapters/cursor/types"; +import type { CursorTransport } from "../../../src/adapters/cursor/transport"; const request = {} as CursorRunRequest; diff --git a/tests/cursor-ultra-mode.test.ts b/tests/providers/cursor/cursor-ultra-mode.test.ts similarity index 92% rename from tests/cursor-ultra-mode.test.ts rename to tests/providers/cursor/cursor-ultra-mode.test.ts index b45c70a91ed..57587c290b4 100644 --- a/tests/cursor-ultra-mode.test.ts +++ b/tests/providers/cursor/cursor-ultra-mode.test.ts @@ -4,12 +4,12 @@ import { CURSOR_ULTRA_1M_MODEL_IDS, cursorUltraBaseModelId, filterCursorConfiguredModelsByLiveDiscovery, -} from "../src/adapters/cursor/discovery"; -import { createCursorRequest } from "../src/adapters/cursor/request-builder"; -import { encodeCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; +} from "../../../src/adapters/cursor/discovery"; +import { createCursorRequest } from "../../../src/adapters/cursor/request-builder"; +import { encodeCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; import { fromBinary } from "@bufbuild/protobuf"; -import { AgentClientMessageSchema, type AgentRunRequest } from "../src/adapters/cursor/gen/agent_pb"; -import type { OcxParsedRequest } from "../src/types/request"; +import { AgentClientMessageSchema, type AgentRunRequest } from "../../../src/adapters/cursor/gen/agent_pb"; +import type { OcxParsedRequest } from "../../../src/types/request"; function decodeRunRequest(bytes: Uint8Array): AgentRunRequest { const msg = fromBinary(AgentClientMessageSchema, bytes); diff --git a/tests/cursor-umbrella-rows.test.ts b/tests/providers/cursor/cursor-umbrella-rows.test.ts similarity index 96% rename from tests/cursor-umbrella-rows.test.ts rename to tests/providers/cursor/cursor-umbrella-rows.test.ts index 7cb1bb11869..f616f7f5055 100644 --- a/tests/cursor-umbrella-rows.test.ts +++ b/tests/providers/cursor/cursor-umbrella-rows.test.ts @@ -6,7 +6,7 @@ import { recordLiveCursorMaxModeModels, resetLiveCursorClaudeWireIdentitiesForTests, resolveCursorSelection, -} from "../src/adapters/cursor/catalog"; +} from "../../../src/adapters/cursor/catalog"; import { CURSOR_PRODUCT_MODELS, CURSOR_REAL_ID_EXCEPTIONS, @@ -14,9 +14,9 @@ import { CURSOR_STATIC_MODELS, cursorModelDisplayNames, cursorModelReasoningEfforts, -} from "../src/adapters/cursor/discovery"; -import { createCursorRequest } from "../src/adapters/cursor/request-builder"; -import type { OcxParsedRequest } from "../src/types"; +} from "../../../src/adapters/cursor/discovery"; +import { createCursorRequest } from "../../../src/adapters/cursor/request-builder"; +import type { OcxParsedRequest } from "../../../src/types"; function parsedFor(modelId: string, reasoning?: string): OcxParsedRequest { return { diff --git a/tests/cursor-uncallable-quarantine.test.ts b/tests/providers/cursor/cursor-uncallable-quarantine.test.ts similarity index 94% rename from tests/cursor-uncallable-quarantine.test.ts rename to tests/providers/cursor/cursor-uncallable-quarantine.test.ts index 64eb0b0b585..104a5bd3ba6 100644 --- a/tests/cursor-uncallable-quarantine.test.ts +++ b/tests/providers/cursor/cursor-uncallable-quarantine.test.ts @@ -3,7 +3,7 @@ import { CURSOR_KNOWN_UNCALLABLE_MODEL_IDS, CURSOR_STATIC_MODELS, filterCursorConfiguredModelsByLiveDiscovery, -} from "../src/adapters/cursor/discovery"; +} from "../../../src/adapters/cursor/discovery"; describe("cursor uncallable-model quarantine (devlog 260826 060)", () => { // Umbrella merge (devlog 260828): the base row RETURNED to the seed because @@ -18,7 +18,7 @@ describe("cursor uncallable-model quarantine (devlog 260826 060)", () => { }); test("the quarantined REGULAR variant is never sent for the bare slug (resolver-level quarantine)", async () => { - const { resolveCursorSelection, CURSOR_CAPABILITIES } = await import("../src/adapters/cursor/catalog"); + const { resolveCursorSelection, CURSOR_CAPABILITIES } = await import("../../../src/adapters/cursor/catalog"); expect(CURSOR_CAPABILITIES["claude-opus-5"]!.variants.regular?.quarantined).toBe(true); // The bare slug routes the healthy thinking family, never claude-opus-5-. expect(resolveCursorSelection("claude-opus-5", "high").wireId).toBe("claude-opus-5-thinking-high"); diff --git a/tests/cursor-vision-wire-harness.test.ts b/tests/providers/cursor/cursor-vision-wire-harness.test.ts similarity index 93% rename from tests/cursor-vision-wire-harness.test.ts rename to tests/providers/cursor/cursor-vision-wire-harness.test.ts index 6b26c369313..35194f39eca 100644 --- a/tests/cursor-vision-wire-harness.test.ts +++ b/tests/providers/cursor/cursor-vision-wire-harness.test.ts @@ -1,14 +1,14 @@ import { describe, expect, test } from "bun:test"; import { fromBinary } from "@bufbuild/protobuf"; -import { encodeCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; -import { CURSOR_VISION_IMAGE_HISTORY_MARKER } from "../src/adapters/cursor/images"; +import { encodeCursorRunRequest } from "../../../src/adapters/cursor/protobuf-request"; +import { CURSOR_VISION_IMAGE_HISTORY_MARKER } from "../../../src/adapters/cursor/images"; import { AgentClientMessageSchema, ConversationStepSchema, ConversationTurnStructureSchema, -} from "../src/adapters/cursor/gen/agent_pb"; -import { handleCursorNativeKv, resetCursorBlobStateForTests } from "../src/adapters/cursor/native-exec"; -import { GetBlobArgsSchema, KvServerMessageSchema } from "../src/adapters/cursor/gen/agent_pb"; +} from "../../../src/adapters/cursor/gen/agent_pb"; +import { handleCursorNativeKv, resetCursorBlobStateForTests } from "../../../src/adapters/cursor/native-exec"; +import { GetBlobArgsSchema, KvServerMessageSchema } from "../../../src/adapters/cursor/gen/agent_pb"; import { create } from "@bufbuild/protobuf"; function blobData(blobId: Uint8Array): Uint8Array { diff --git a/tests/cyber-policy-error-fidelity.test.ts b/tests/providers/cyber-policy-error-fidelity.test.ts similarity index 97% rename from tests/cyber-policy-error-fidelity.test.ts rename to tests/providers/cyber-policy-error-fidelity.test.ts index 86e6b61656b..adcf36be018 100644 --- a/tests/cyber-policy-error-fidelity.test.ts +++ b/tests/providers/cyber-policy-error-fidelity.test.ts @@ -1,23 +1,23 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter as createOpenAIChatAdapterProduction } from "../src/adapters/openai-chat"; -import { bridgeToResponsesSSE, buildResponseJSON, formatErrorResponse } from "../src/bridge"; +import { createOpenAIChatAdapter as createOpenAIChatAdapterProduction } from "../../src/adapters/openai-chat"; +import { bridgeToResponsesSSE, buildResponseJSON, formatErrorResponse } from "../../src/bridge"; import { chatCompletionsErrorBody, chatCompletionsErrorResponse, responsesSseToChatCompletionsSse as responsesSseToChatCompletionsSseProduction, -} from "../src/chat/outbound"; -import { comboFailureDecision } from "../src/combos/failover"; +} from "../../src/chat/outbound"; +import { comboFailureDecision } from "../../src/combos/failover"; import { adapterFailureFromMessage, classifyError, CYBER_POLICY_ERROR_CODE, httpStatusFromTerminalError, -} from "../src/lib/errors"; -import { formatPassthroughUpstreamError } from "../src/server/responses/passthrough-error"; -import { consumeComboFailure } from "../src/server/responses/core"; -import { handleResponses } from "../src/server/responses"; -import type { AdapterEvent, OcxConfig } from "../src/types"; -import { createTestTranslatorBudget, withTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../src/lib/errors"; +import { formatPassthroughUpstreamError } from "../../src/server/responses/passthrough-error"; +import { consumeComboFailure } from "../../src/server/responses/core"; +import { handleResponses } from "../../src/server/responses"; +import type { AdapterEvent, OcxConfig } from "../../src/types"; +import { createTestTranslatorBudget, withTestTranslatorBudget } from "../helpers/translator-budget"; const createOpenAIChatAdapter = (...args: Parameters) => withTestTranslatorBudget(createOpenAIChatAdapterProduction(...args)); diff --git a/tests/deepinfra-provider.test.ts b/tests/providers/deepinfra-provider.test.ts similarity index 88% rename from tests/deepinfra-provider.test.ts rename to tests/providers/deepinfra-provider.test.ts index 39385652a86..f98f8151e1f 100644 --- a/tests/deepinfra-provider.test.ts +++ b/tests/providers/deepinfra-provider.test.ts @@ -1,24 +1,25 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { PROVIDER_REGISTRY, type ProviderRegistryEntry } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; - -const FIXTURE = readFileSync(join(import.meta.dir, "fixtures/deepinfra-models.json"), "utf8"); +} from "../../src/providers/derive"; +import { PROVIDER_REGISTRY, type ProviderRegistryEntry } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; + +const FIXTURE = readFileSync(fixturePath("deepinfra-models.json"), "utf8"); const BASE_URL = "https://api.deepinfra.com/v1/openai"; const MODELS_URL = "https://api.deepinfra.com/v1/models"; const API_KEY = "di-test-key"; diff --git a/tests/deepseek-inbound-wire.test.ts b/tests/providers/deepseek-inbound-wire.test.ts similarity index 98% rename from tests/deepseek-inbound-wire.test.ts rename to tests/providers/deepseek-inbound-wire.test.ts index 1f298bacce5..fa2b686a2df 100644 --- a/tests/deepseek-inbound-wire.test.ts +++ b/tests/providers/deepseek-inbound-wire.test.ts @@ -12,20 +12,20 @@ * assert the captured upstream URL, which is externally observable. */ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; -import { enrichProviderFromRegistry, providerConfigSeed } from "../src/providers/derive"; +import { enrichProviderFromRegistry, providerConfigSeed } from "../../src/providers/derive"; import { getProviderRegistryEntry, providerModelResponsesTerminalRepair, PROVIDER_REGISTRY, -} from "../src/providers/registry"; -import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../src/adapters/openai-responses"; -import { resolveWireProtocolOverride } from "../src/server/adapter-resolve"; -import { handleResponses } from "../src/server/responses/core"; -import { MAX_SYNTHESIZED_OUTPUT_ITEMS } from "../src/server/responses-json-events"; -import type { ResponsesTerminalRepairScheduler } from "../src/server/responses-terminal-repair"; -import { sendResponseToWebSocket } from "../src/server/ws-bridge"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../src/providers/registry"; +import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../../src/adapters/openai-responses"; +import { resolveWireProtocolOverride } from "../../src/server/adapter-resolve"; +import { handleResponses } from "../../src/server/responses/core"; +import { MAX_SYNTHESIZED_OUTPUT_ITEMS } from "../../src/server/responses-json-events"; +import type { ResponsesTerminalRepairScheduler } from "../../src/server/responses-terminal-repair"; +import { sendResponseToWebSocket } from "../../src/server/ws-bridge"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; const createResponsesPassthroughAdapter = (...args: Parameters) => withTestTranslatorBudget(createResponsesPassthroughAdapterProduction(...args)); diff --git a/tests/deepseek-reasoning-replay-gaps.test.ts b/tests/providers/deepseek-reasoning-replay-gaps.test.ts similarity index 98% rename from tests/deepseek-reasoning-replay-gaps.test.ts rename to tests/providers/deepseek-reasoning-replay-gaps.test.ts index bf1bd0248e4..4e5c6ea3cae 100644 --- a/tests/deepseek-reasoning-replay-gaps.test.ts +++ b/tests/providers/deepseek-reasoning-replay-gaps.test.ts @@ -1,19 +1,19 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { buildResponseJSON } from "../src/bridge"; -import { parseRequest } from "../src/responses/parser"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { buildResponseJSON } from "../../src/bridge"; +import { parseRequest } from "../../src/responses/parser"; import { clearReasoningReplayCacheForTests, peekReasoningForCall as peekReasoningForCallRaw, rememberReasoningForCall as rememberReasoningForCallRaw, -} from "../src/responses/reasoning-replay-cache"; -import { routeModel } from "../src/router"; +} from "../../src/responses/reasoning-replay-cache"; +import { routeModel } from "../../src/router"; import type { AdapterEvent, OcxConfig, OcxParsedRequest, OcxReasoningReplayScopeRef, -} from "../src/types"; +} from "../../src/types"; /** * Regression coverage for opencodex issue #950: OpenCode Go DeepSeek V4 Flash diff --git a/tests/deepseek-reasoning-replay.test.ts b/tests/providers/deepseek-reasoning-replay.test.ts similarity index 94% rename from tests/deepseek-reasoning-replay.test.ts rename to tests/providers/deepseek-reasoning-replay.test.ts index b67b2c17985..37869afa179 100644 --- a/tests/deepseek-reasoning-replay.test.ts +++ b/tests/providers/deepseek-reasoning-replay.test.ts @@ -7,12 +7,12 @@ * still stripping proxy-minted `ocxr1` envelopes no upstream can decrypt. */ import { describe, expect, test } from "bun:test"; -import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction, sanitizeReasoningInputContent } from "../src/adapters/openai-responses"; -import { enrichProviderFromRegistry, providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { OCX_REASONING_PREFIX } from "../src/responses/reasoning-envelope"; -import type { OcxProviderConfig } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction, sanitizeReasoningInputContent } from "../../src/adapters/openai-responses"; +import { enrichProviderFromRegistry, providerConfigSeed } from "../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; +import { OCX_REASONING_PREFIX } from "../../src/responses/reasoning-envelope"; +import type { OcxProviderConfig } from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; const createResponsesPassthroughAdapter = (...args: Parameters) => withTestTranslatorBudget(createResponsesPassthroughAdapterProduction(...args)); diff --git a/tests/deepseek-responses-item-id-repair.test.ts b/tests/providers/deepseek-responses-item-id-repair.test.ts similarity index 96% rename from tests/deepseek-responses-item-id-repair.test.ts rename to tests/providers/deepseek-responses-item-id-repair.test.ts index 374e81a9a4c..ed95f2394ce 100644 --- a/tests/deepseek-responses-item-id-repair.test.ts +++ b/tests/providers/deepseek-responses-item-id-repair.test.ts @@ -1,14 +1,14 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { enrichProviderFromRegistry, providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; +import { enrichProviderFromRegistry, providerConfigSeed } from "../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; import { createResponsesItemIdPayloadRewrite, hasResponsesItemIdRepair, repairResponsesJsonItemIds, -} from "../src/server/responses-item-id-repair"; -import { handleResponses } from "../src/server/responses/core"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../src/server/responses-item-id-repair"; +import { handleResponses } from "../../src/server/responses/core"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { createTestTranslatorBudget } from "../helpers/translator-budget"; const UUID_MSG = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"; const UUID_RS = "1b9d6bcd-bbfd-4b2d-9b9d-5c0a2fb41a1b"; diff --git a/tests/digitalocean-scaleway-provider.test.ts b/tests/providers/digitalocean-scaleway-provider.test.ts similarity index 92% rename from tests/digitalocean-scaleway-provider.test.ts rename to tests/providers/digitalocean-scaleway-provider.test.ts index 7b84ef05449..34464c65aa3 100644 --- a/tests/digitalocean-scaleway-provider.test.ts +++ b/tests/providers/digitalocean-scaleway-provider.test.ts @@ -1,26 +1,27 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { FREE_PROVIDER_DIRECTORY } from "../src/providers/free-directory"; -import { PROVIDER_REGISTRY, type ProviderRegistryEntry } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; +} from "../../src/providers/derive"; +import { FREE_PROVIDER_DIRECTORY } from "../../src/providers/free-directory"; +import { PROVIDER_REGISTRY, type ProviderRegistryEntry } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; -const DIGITALOCEAN_FIXTURE = readFileSync(join(import.meta.dir, "fixtures/digitalocean-models.json"), "utf8"); -const SCALEWAY_FIXTURE = readFileSync(join(import.meta.dir, "fixtures/scaleway-models.json"), "utf8"); +const DIGITALOCEAN_FIXTURE = readFileSync(fixturePath("digitalocean-models.json"), "utf8"); +const SCALEWAY_FIXTURE = readFileSync(fixturePath("scaleway-models.json"), "utf8"); const originalFetch = globalThis.fetch; type ProviderId = "digitalocean" | "scaleway"; diff --git a/tests/exa-web-search.test.ts b/tests/providers/exa-web-search.test.ts similarity index 95% rename from tests/exa-web-search.test.ts rename to tests/providers/exa-web-search.test.ts index f9202f768b4..6422254573c 100644 --- a/tests/exa-web-search.test.ts +++ b/tests/providers/exa-web-search.test.ts @@ -1,12 +1,12 @@ import { describe, expect, test } from "bun:test"; -import { mapExaSearchResponse, runExaWebSearch } from "../src/web-search/exa-executor"; -import { planWebSearch } from "../src/web-search"; -import { parseRequest } from "../src/responses/parser"; -import { runWithWebSearch, type WebSearchLoopDeps } from "../src/web-search/loop"; -import { MAX_SIDECAR_RESPONSE_BYTES } from "../src/web-search/parse"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import type { AdapterEvent, ProviderAdapter } from "../src/adapters/base"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { mapExaSearchResponse, runExaWebSearch } from "../../src/web-search/exa-executor"; +import { planWebSearch } from "../../src/web-search"; +import { parseRequest } from "../../src/responses/parser"; +import { runWithWebSearch, type WebSearchLoopDeps } from "../../src/web-search/loop"; +import { MAX_SIDECAR_RESPONSE_BYTES } from "../../src/web-search/parse"; +import { createTestTranslatorBudget } from "../helpers/translator-budget"; +import type { AdapterEvent, ProviderAdapter } from "../../src/adapters/base"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; const routed: OcxProviderConfig = { adapter: "openai-chat", baseUrl: "https://routed.test/v1", apiKey: "k" }; function config(overrides: Partial = {}): OcxConfig { diff --git a/tests/fast-row-ingress.test.ts b/tests/providers/fast-row-ingress.test.ts similarity index 92% rename from tests/fast-row-ingress.test.ts rename to tests/providers/fast-row-ingress.test.ts index ed3be17f114..46ce6b038cd 100644 --- a/tests/fast-row-ingress.test.ts +++ b/tests/providers/fast-row-ingress.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from "bun:test"; -import { decideTier, tierValueAfterDecision } from "../src/providers/fastwire"; -import { providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { fastPolicyForModel } from "../src/providers/service-tier"; -import { parseFastOnlyRowId, parseSyntheticRowId } from "../src/server/fast-row"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { decideTier, tierValueAfterDecision } from "../../src/providers/fastwire"; +import { providerConfigSeed } from "../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; +import { fastPolicyForModel } from "../../src/providers/service-tier"; +import { parseFastOnlyRowId, parseSyntheticRowId } from "../../src/server/fast-row"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; /** * Ingress round-trip semantics for synthetic Fast selectors diff --git a/tests/featherless-provider.test.ts b/tests/providers/featherless-provider.test.ts similarity index 88% rename from tests/featherless-provider.test.ts rename to tests/providers/featherless-provider.test.ts index 7316f02f8d0..b1b673943f7 100644 --- a/tests/featherless-provider.test.ts +++ b/tests/providers/featherless-provider.test.ts @@ -1,26 +1,27 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { catalogHintsFromModelsApiItem } from "../src/codex/catalog/provider-fetch"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { catalogHintsFromModelsApiItem } from "../../src/codex/catalog/provider-fetch"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { resolveProviderModelDiscovery } from "../src/providers/model-discovery"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; - -const FEATHERLESS_FIXTURE = readFileSync(join(import.meta.dir, "fixtures/featherless-models.json"), "utf8"); +} from "../../src/providers/derive"; +import { resolveProviderModelDiscovery } from "../../src/providers/model-discovery"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; + +const FEATHERLESS_FIXTURE = readFileSync(fixturePath("featherless-models.json"), "utf8"); const BASE_URL = "https://api.featherless.ai/v1"; const TEST_KEY = "featherless-test-key"; const DISCOVERY_QUERY = { diff --git a/tests/forward-admission-separation.test.ts b/tests/providers/forward-admission-separation.test.ts similarity index 93% rename from tests/forward-admission-separation.test.ts rename to tests/providers/forward-admission-separation.test.ts index ad63317389b..bb6d66a88e1 100644 --- a/tests/forward-admission-separation.test.ts +++ b/tests/providers/forward-admission-separation.test.ts @@ -2,11 +2,11 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; -import { resolveFirstUsableOpenAiSidecar } from "../src/providers/openai-sidecar"; -import { startServer } from "../src/server"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { saveConfig } from "../../src/config"; +import { resolveFirstUsableOpenAiSidecar } from "../../src/providers/openai-sidecar"; +import { startServer } from "../../src/server"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const originalFetch = globalThis.fetch; const previousHome = process.env.OPENCODEX_HOME; diff --git a/tests/github-copilot-account-origin.test.ts b/tests/providers/github-copilot/github-copilot-account-origin.test.ts similarity index 96% rename from tests/github-copilot-account-origin.test.ts rename to tests/providers/github-copilot/github-copilot-account-origin.test.ts index f6ed6ad6866..5f464a1d7ee 100644 --- a/tests/github-copilot-account-origin.test.ts +++ b/tests/providers/github-copilot/github-copilot-account-origin.test.ts @@ -2,11 +2,11 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { clearGenericFailoverHealth } from "../src/oauth/generic-account-failover"; -import { getAccountSet, saveCredential, setActiveAccount } from "../src/oauth/store"; -import { handleResponses } from "../src/server/responses"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { clearGenericFailoverHealth } from "../../../src/oauth/generic-account-failover"; +import { getAccountSet, saveCredential, setActiveAccount } from "../../../src/oauth/store"; +import { handleResponses } from "../../../src/server/responses"; +import type { OcxConfig } from "../../../src/types"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const ACCOUNT_A_ORIGIN = "https://a.githubcopilot.com"; const ACCOUNT_B_ORIGIN = "https://b.githubcopilot.com"; diff --git a/tests/github-copilot-oauth.test.ts b/tests/providers/github-copilot/github-copilot-oauth.test.ts similarity index 97% rename from tests/github-copilot-oauth.test.ts rename to tests/providers/github-copilot/github-copilot-oauth.test.ts index 045b2f741ac..9deaac3a9da 100644 --- a/tests/github-copilot-oauth.test.ts +++ b/tests/providers/github-copilot/github-copilot-oauth.test.ts @@ -7,8 +7,8 @@ import { refreshGithubCopilotToken, resolveCopilotApiBaseUrl, validateCopilotApiBaseUrl, -} from "../src/oauth/github-copilot"; -import type { OAuthController } from "../src/oauth/types"; +} from "../../../src/oauth/github-copilot"; +import type { OAuthController } from "../../../src/oauth/types"; const realFetch = globalThis.fetch; afterEach(() => { @@ -314,7 +314,7 @@ describe("github-copilot security repairs (absorb hardening)", () => { describe("github-copilot transport fail-closed host allowlist", () => { test("an OAuth credential without endpoints.api never sends the bearer to a foreign baseUrl", async () => { - const { resolveGithubCopilotTransport } = await import("../src/providers/github-copilot-transport"); + const { resolveGithubCopilotTransport } = await import("../../../src/providers/github-copilot-transport"); const resolved = resolveGithubCopilotTransport({ adapter: "openai-chat", authMode: "oauth", @@ -324,7 +324,7 @@ describe("github-copilot transport fail-closed host allowlist", () => { }); test("a valid credential apiBaseUrl still wins for OAuth transports", async () => { - const { resolveGithubCopilotTransport } = await import("../src/providers/github-copilot-transport"); + const { resolveGithubCopilotTransport } = await import("../../../src/providers/github-copilot-transport"); const resolved = resolveGithubCopilotTransport({ adapter: "openai-chat", authMode: "oauth", @@ -336,7 +336,7 @@ describe("github-copilot transport fail-closed host allowlist", () => { describe("copilot token redaction", () => { test("the Copilot tid= token grammar and GitHub token prefixes are fully redacted", async () => { - const { redactSecretString } = await import("../src/lib/redact"); + const { redactSecretString } = await import("../../../src/lib/redact"); const copilotish = "tid=abc-123;exp=1699999999;sku=copilot_pro;8kp=1:B64sig+value="; const redacted = redactSecretString(`upstream said: ${copilotish} and ${GH_ACCESS} plus body {"token":"${copilotish}"}`); expect(redacted).not.toContain("abc-123"); diff --git a/tests/github-copilot-sse-rewrite.test.ts b/tests/providers/github-copilot/github-copilot-sse-rewrite.test.ts similarity index 97% rename from tests/github-copilot-sse-rewrite.test.ts rename to tests/providers/github-copilot/github-copilot-sse-rewrite.test.ts index 80b7d3e6b74..7c8b562281b 100644 --- a/tests/github-copilot-sse-rewrite.test.ts +++ b/tests/providers/github-copilot/github-copilot-sse-rewrite.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { createGithubCopilotResponsesBlockRewrite } from "../src/server/github-copilot-responses-repair"; -import { relaySseWithBlockRewrite } from "../src/server/sse-payload-rewrite"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; +import { createGithubCopilotResponsesBlockRewrite } from "../../../src/server/github-copilot-responses-repair"; +import { relaySseWithBlockRewrite } from "../../../src/server/sse-payload-rewrite"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; function streamFromChunks(...chunks: string[]): ReadableStream { const encoder = new TextEncoder(); diff --git a/tests/github-copilot-stream-contract.test.ts b/tests/providers/github-copilot/github-copilot-stream-contract.test.ts similarity index 96% rename from tests/github-copilot-stream-contract.test.ts rename to tests/providers/github-copilot/github-copilot-stream-contract.test.ts index 7843f914db2..21ba36336e7 100644 --- a/tests/github-copilot-stream-contract.test.ts +++ b/tests/providers/github-copilot/github-copilot-stream-contract.test.ts @@ -7,10 +7,10 @@ * The proxy must expose one internally consistent, plaintext Responses stream. */ import { afterEach, describe, expect, test } from "bun:test"; -import { providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { handleResponses } from "../src/server/responses/core"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { providerConfigSeed } from "../../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../../src/providers/registry"; +import { handleResponses } from "../../../src/server/responses/core"; +import type { OcxConfig, OcxProviderConfig } from "../../../src/types"; interface SseEvent { event?: string; diff --git a/tests/github-copilot-wire-defaults.test.ts b/tests/providers/github-copilot/github-copilot-wire-defaults.test.ts similarity index 92% rename from tests/github-copilot-wire-defaults.test.ts rename to tests/providers/github-copilot/github-copilot-wire-defaults.test.ts index a3bbc316f95..29af09048d1 100644 --- a/tests/github-copilot-wire-defaults.test.ts +++ b/tests/providers/github-copilot/github-copilot-wire-defaults.test.ts @@ -6,14 +6,14 @@ * * The resolver-only cases would pass even if the handleResponses replay silently * flipped the wire back, so the end-to-end cases assert the captured upstream URL — - * the externally observable wire. Pattern mirrors tests/deepseek-inbound-wire.test.ts. + * the externally observable wire. Pattern mirrors tests/providers/deepseek-inbound-wire.test.ts. */ import { afterEach, describe, expect, test } from "bun:test"; -import { providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { resolveWireProtocolOverride } from "../src/server/adapter-resolve"; -import { handleResponses } from "../src/server/responses/core"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { providerConfigSeed } from "../../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../../src/providers/registry"; +import { resolveWireProtocolOverride } from "../../../src/server/adapter-resolve"; +import { handleResponses } from "../../../src/server/responses/core"; +import type { OcxConfig, OcxProviderConfig } from "../../../src/types"; const RESPONSES_ONLY = [ "gpt-5.3-codex", diff --git a/tests/hyperbolic-provider.test.ts b/tests/providers/hyperbolic-provider.test.ts similarity index 88% rename from tests/hyperbolic-provider.test.ts rename to tests/providers/hyperbolic-provider.test.ts index 7cdaf36efc2..7ae77c7bf15 100644 --- a/tests/hyperbolic-provider.test.ts +++ b/tests/providers/hyperbolic-provider.test.ts @@ -1,24 +1,25 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { PROVIDER_REGISTRY, type ProviderRegistryEntry } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; - -const FIXTURE = readFileSync(join(import.meta.dir, "fixtures/hyperbolic-models.json"), "utf8"); +} from "../../src/providers/derive"; +import { PROVIDER_REGISTRY, type ProviderRegistryEntry } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; + +const FIXTURE = readFileSync(fixturePath("hyperbolic-models.json"), "utf8"); const BASE_URL = "https://api.hyperbolic.xyz/v1"; const API_KEY = "hyperbolic-test-key"; const originalFetch = globalThis.fetch; diff --git a/tests/kimi-oauth-identity.test.ts b/tests/providers/kimi-oauth-identity.test.ts similarity index 98% rename from tests/kimi-oauth-identity.test.ts rename to tests/providers/kimi-oauth-identity.test.ts index b48d4fa89c3..f69a251a124 100644 --- a/tests/kimi-oauth-identity.test.ts +++ b/tests/providers/kimi-oauth-identity.test.ts @@ -1,9 +1,9 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync} from "node:fs"; import { join } from "node:path"; -import { identityFromKimiTokens, refreshKimiToken } from "../src/oauth/kimi"; -import { getCredential, listAccounts, saveCredential } from "../src/oauth/store"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { identityFromKimiTokens, refreshKimiToken } from "../../src/oauth/kimi"; +import { getCredential, listAccounts, saveCredential } from "../../src/oauth/store"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-kimi-oauth-identity-test"); let previousOpencodexHome: string | undefined; diff --git a/tests/kiro-account-quota.test.ts b/tests/providers/kiro/kiro-account-quota.test.ts similarity index 96% rename from tests/kiro-account-quota.test.ts rename to tests/providers/kiro/kiro-account-quota.test.ts index 2f0151c3382..f5a869c20d8 100644 --- a/tests/kiro-account-quota.test.ts +++ b/tests/providers/kiro/kiro-account-quota.test.ts @@ -2,16 +2,16 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveCredential } from "../src/oauth/store"; +import { saveCredential } from "../../../src/oauth/store"; import { clearAccountQuotaCache, clearProviderQuotaCache, fetchProviderAccountQuotas, getCachedProviderAccountQuota, supportsPerAccountQuota, -} from "../src/providers/quota"; -import { getKiroAccountExhaustion } from "../src/providers/kiro-usage"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/providers/quota"; +import { getKiroAccountExhaustion } from "../../../src/providers/kiro-usage"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const originalFetch = globalThis.fetch; const previousOpencodexHome = process.env.OPENCODEX_HOME; diff --git a/tests/kiro-adapter.test.ts b/tests/providers/kiro/kiro-adapter.test.ts similarity index 99% rename from tests/kiro-adapter.test.ts rename to tests/providers/kiro/kiro-adapter.test.ts index 4731bc6d698..cb530a8d518 100644 --- a/tests/kiro-adapter.test.ts +++ b/tests/providers/kiro/kiro-adapter.test.ts @@ -3,7 +3,7 @@ import { Database } from "bun:sqlite"; import { mkdirSync, mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { createKiroAdapter } from "../src/adapters/kiro"; +import { createKiroAdapter } from "../../../src/adapters/kiro"; import { KIRO_ANSWER_DELIVERED_MESSAGE, KIRO_COMPLETION_INSTRUCTIONS, @@ -12,18 +12,18 @@ import { KIRO_CONTINUATION_MESSAGE, KIRO_EMPTY_TOOL_RESULT_MESSAGE, KIRO_TOOL_RESULT_CARRIER_MESSAGE, -} from "../src/adapters/kiro-constants"; -import { EMPTY_EXEC_OUTPUT_MESSAGE, FAILED_EXEC_OUTPUT_MESSAGE } from "../src/adapters/exec-tool-result-normalize"; -import { MAX_KIRO_TOOL_CATALOG_BYTES, MAX_KIRO_TOOL_COUNT } from "../src/adapters/kiro-tools"; -import { applyProviderConfigHints, buildCatalogEntries } from "../src/codex/catalog"; -import { getValidAccessTokenSnapshot } from "../src/oauth"; -import { saveCredential } from "../src/oauth/store"; -import { normalizeKiroModelId } from "../src/providers/kiro-models"; -import { configuredReasoningEfforts, mapReasoningEffort } from "../src/reasoning-effort"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { parseRequest } from "../src/responses/parser"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/adapters/kiro-constants"; +import { EMPTY_EXEC_OUTPUT_MESSAGE, FAILED_EXEC_OUTPUT_MESSAGE } from "../../../src/adapters/exec-tool-result-normalize"; +import { MAX_KIRO_TOOL_CATALOG_BYTES, MAX_KIRO_TOOL_COUNT } from "../../../src/adapters/kiro-tools"; +import { applyProviderConfigHints, buildCatalogEntries } from "../../../src/codex/catalog"; +import { getValidAccessTokenSnapshot } from "../../../src/oauth"; +import { saveCredential } from "../../../src/oauth/store"; +import { normalizeKiroModelId } from "../../../src/providers/kiro-models"; +import { configuredReasoningEfforts, mapReasoningEffort } from "../../../src/reasoning-effort"; +import { PROVIDER_REGISTRY } from "../../../src/providers/registry"; +import { parseRequest } from "../../../src/responses/parser"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const origHome = process.env.HOME; const origLocalAppData = process.env.LOCALAPPDATA; @@ -1517,8 +1517,8 @@ describe("the completion contract survives a hostile tool catalog intact", () => describe("boundedInjectedInstruction surrogate safety", () => { test("a budget cut never ends on a lone high surrogate", async () => { - const { boundedInjectedInstructionForTests } = await import("../src/adapters/kiro"); - const { MAX_KIRO_INJECTED_INSTRUCTION_CHARS } = await import("../src/adapters/kiro-constants"); + const { boundedInjectedInstructionForTests } = await import("../../../src/adapters/kiro"); + const { MAX_KIRO_INJECTED_INSTRUCTION_CHARS } = await import("../../../src/adapters/kiro-constants"); // Place an astral character exactly at the budget boundary. const prefix = "가".repeat(MAX_KIRO_INJECTED_INSTRUCTION_CHARS - 1); const text = `${prefix}🎆tail`; diff --git a/tests/kiro-builder-id-profile.test.ts b/tests/providers/kiro/kiro-builder-id-profile.test.ts similarity index 95% rename from tests/kiro-builder-id-profile.test.ts rename to tests/providers/kiro/kiro-builder-id-profile.test.ts index 7d0632e3c62..800ca83a341 100644 --- a/tests/kiro-builder-id-profile.test.ts +++ b/tests/providers/kiro/kiro-builder-id-profile.test.ts @@ -3,11 +3,11 @@ import { Database } from "bun:sqlite"; import { existsSync, mkdirSync, mkdtempSync, readFileSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { createKiroAdapter } from "../src/adapters/kiro"; -import { KIRO_BUILDER_ID_SERVICE_PROFILE_ARN } from "../src/adapters/kiro-constants"; -import { getValidAccessTokenSnapshot } from "../src/oauth"; -import { resolveKiroApiRegion, resolveKiroProfileArn, resolveKiroRequestProfileArn } from "../src/oauth/kiro"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { createKiroAdapter } from "../../../src/adapters/kiro"; +import { KIRO_BUILDER_ID_SERVICE_PROFILE_ARN } from "../../../src/adapters/kiro-constants"; +import { getValidAccessTokenSnapshot } from "../../../src/oauth"; +import { resolveKiroApiRegion, resolveKiroProfileArn, resolveKiroRequestProfileArn } from "../../../src/oauth/kiro"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; /** Mirrors resolveKiroCliNativeSessionEntries so an accountless request reads a real local import. */ function seedKiroCliBuilderIdSession(): void { @@ -32,8 +32,8 @@ function seedKiroCliBuilderIdSession(): void { ]); db.close(); } -import { saveCredential } from "../src/oauth/store"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { saveCredential } from "../../../src/oauth/store"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; /** * Issue #993 follow-up: an AWS Builder ID account authenticates through SSO OIDC and never receives diff --git a/tests/kiro-calibration.test.ts b/tests/providers/kiro/kiro-calibration.test.ts similarity index 99% rename from tests/kiro-calibration.test.ts rename to tests/providers/kiro/kiro-calibration.test.ts index 7a9c1162267..8743be7634f 100644 --- a/tests/kiro-calibration.test.ts +++ b/tests/providers/kiro/kiro-calibration.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, test } from "bun:test"; -import { calibrateKiroEstimate, recordKiroCalibration, rekeyKiroCalibration, resetKiroCalibration } from "../src/adapters/kiro-calibration"; +import { calibrateKiroEstimate, recordKiroCalibration, rekeyKiroCalibration, resetKiroCalibration } from "../../../src/adapters/kiro-calibration"; beforeEach(() => resetKiroCalibration()); diff --git a/tests/kiro-images.test.ts b/tests/providers/kiro/kiro-images.test.ts similarity index 96% rename from tests/kiro-images.test.ts rename to tests/providers/kiro/kiro-images.test.ts index b614bb5d61b..414a355864b 100644 --- a/tests/kiro-images.test.ts +++ b/tests/providers/kiro/kiro-images.test.ts @@ -2,12 +2,12 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { createKiroAdapter } from "../src/adapters/kiro"; -import { normalizeKiroImages, KIRO_IMAGE_BASE64_BUDGET, KIRO_MAX_IMAGES_PER_MESSAGE, type KiroImage } from "../src/adapters/kiro-images"; -import { resetNormalizeStateForTests, TIER_SPECS, type EncodeFn } from "../src/adapters/anthropic-image-normalize"; -import { sniffImageDimensions } from "../src/adapters/anthropic-image-guard"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { createKiroAdapter } from "../../../src/adapters/kiro"; +import { normalizeKiroImages, KIRO_IMAGE_BASE64_BUDGET, KIRO_MAX_IMAGES_PER_MESSAGE, type KiroImage } from "../../../src/adapters/kiro-images"; +import { resetNormalizeStateForTests, TIER_SPECS, type EncodeFn } from "../../../src/adapters/anthropic-image-normalize"; +import { sniffImageDimensions } from "../../../src/adapters/anthropic-image-guard"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const origHome = process.env.HOME; const origRegion = process.env.KIRO_REGION; diff --git a/tests/kiro-oauth.test.ts b/tests/providers/kiro/kiro-oauth.test.ts similarity index 99% rename from tests/kiro-oauth.test.ts rename to tests/providers/kiro/kiro-oauth.test.ts index e3c87839fe8..cd2e6898421 100644 --- a/tests/kiro-oauth.test.ts +++ b/tests/providers/kiro/kiro-oauth.test.ts @@ -3,9 +3,9 @@ import { Database } from "bun:sqlite"; import { existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { OAUTH_PROVIDERS, runLogin } from "../src/oauth"; -import { inspectKiroCliSqlite, kiroCliInstallGuidance, loginKiro, readKiroCliSqlite, refreshKiroToken, resolveKiroApiRegion, resolveKiroProfileArn, resolveKiroRegion, settleKiroLoginTransaction } from "../src/oauth/kiro"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { OAUTH_PROVIDERS, runLogin } from "../../../src/oauth"; +import { inspectKiroCliSqlite, kiroCliInstallGuidance, loginKiro, readKiroCliSqlite, refreshKiroToken, resolveKiroApiRegion, resolveKiroProfileArn, resolveKiroRegion, settleKiroLoginTransaction } from "../../../src/oauth/kiro"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; // Windows CI cold runners take 5-7s for the real SQLite create/inspect cycles here // (same flake class as 810fa115); the default 5s harness timeout is too tight. diff --git a/tests/kiro-pool-rank.test.ts b/tests/providers/kiro/kiro-pool-rank.test.ts similarity index 97% rename from tests/kiro-pool-rank.test.ts rename to tests/providers/kiro/kiro-pool-rank.test.ts index b66b917ed37..b42eb969d0d 100644 --- a/tests/kiro-pool-rank.test.ts +++ b/tests/providers/kiro/kiro-pool-rank.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { exhaustedCooldownMs, rankAccountsByHeadroom } from "../src/oauth/account-quota-rank"; +import { exhaustedCooldownMs, rankAccountsByHeadroom } from "../../../src/oauth/account-quota-rank"; import { mkdtempSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; @@ -9,25 +9,25 @@ import { genericFailoverRetryAfterSeconds, preferredInitialAccount, rotateGenericOAuthAccountOn429, -} from "../src/oauth/generic-account-failover"; +} from "../../../src/oauth/generic-account-failover"; import { getAccountSet, markAccountNeedsReauth, removeAccount, saveCredential, setActiveAccount, -} from "../src/oauth/store"; -import { getValidAccessSnapshotForAccount } from "../src/oauth"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +} from "../../../src/oauth/store"; +import { getValidAccessSnapshotForAccount } from "../../../src/oauth"; +import type { OcxConfig, OcxProviderConfig } from "../../../src/types"; import { clearAccountQuotaCache, setCachedProviderAccountQuotaForTests, -} from "../src/providers/quota"; +} from "../../../src/providers/quota"; import { clearKiroAccountUsageState, commitKiroAccountUsageState, -} from "../src/providers/kiro-usage"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/providers/kiro-usage"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const realFetch = globalThis.fetch; diff --git a/tests/kiro-reasoning-roundtrip.test.ts b/tests/providers/kiro/kiro-reasoning-roundtrip.test.ts similarity index 94% rename from tests/kiro-reasoning-roundtrip.test.ts rename to tests/providers/kiro/kiro-reasoning-roundtrip.test.ts index a38121d59be..9cf598f3725 100644 --- a/tests/kiro-reasoning-roundtrip.test.ts +++ b/tests/providers/kiro/kiro-reasoning-roundtrip.test.ts @@ -1,9 +1,9 @@ import { describe, expect, test } from "bun:test"; -import { bridgeToResponsesSSE, buildResponseJSON } from "../src/bridge"; -import { parseRequest } from "../src/responses/parser"; -import { decodeReasoningEnvelope } from "../src/responses/reasoning-envelope"; -import type { AdapterEvent } from "../src/types"; -import { createTranslatorBudget } from "../src/lib/translator-budget"; +import { bridgeToResponsesSSE, buildResponseJSON } from "../../../src/bridge"; +import { parseRequest } from "../../../src/responses/parser"; +import { decodeReasoningEnvelope } from "../../../src/responses/reasoning-envelope"; +import type { AdapterEvent } from "../../../src/types"; +import { createTranslatorBudget } from "../../../src/lib/translator-budget"; const BLOB = "LktUUn5+ZXlKbGJtTnllWEIwYVc5dVVtVm5hVzl1SWpvaQ=="; diff --git a/tests/kiro-retry.test.ts b/tests/providers/kiro/kiro-retry.test.ts similarity index 98% rename from tests/kiro-retry.test.ts rename to tests/providers/kiro/kiro-retry.test.ts index df4285546b7..1ccc23d830d 100644 --- a/tests/kiro-retry.test.ts +++ b/tests/providers/kiro/kiro-retry.test.ts @@ -1,10 +1,10 @@ import { afterEach, describe, expect, test } from "bun:test"; -import type { AdapterRequest } from "../src/adapters/base"; +import type { AdapterRequest } from "../../../src/adapters/base"; import { fetchKiroWithRetry, noteKiroTransientThrottle, resetKiroThrottleStateForTests, -} from "../src/adapters/kiro-retry"; +} from "../../../src/adapters/kiro-retry"; const realFetch = globalThis.fetch; @@ -369,7 +369,7 @@ describe("kiro retry fetch", () => { describe("kiro adapter error formatter", () => { test("is classified, redacted, and does not copy secret headers", async () => { - const { createKiroAdapter } = await import("../src/adapters/kiro"); + const { createKiroAdapter } = await import("../../../src/adapters/kiro"); const adapter = createKiroAdapter({ adapter: "kiro", apiKey: "unused" } as never); const text = adapter.formatErrorBody!(403, new Headers({ authorization: "Bearer header-secret", diff --git a/tests/kiro-review-regressions.test.ts b/tests/providers/kiro/kiro-review-regressions.test.ts similarity index 97% rename from tests/kiro-review-regressions.test.ts rename to tests/providers/kiro/kiro-review-regressions.test.ts index b5efece4f55..3c1b212beed 100644 --- a/tests/kiro-review-regressions.test.ts +++ b/tests/providers/kiro/kiro-review-regressions.test.ts @@ -3,18 +3,18 @@ import { Database } from "bun:sqlite"; import { existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { getValidAccessTokenSnapshot, OAUTH_PROVIDERS, runLogin } from "../src/oauth"; -import { loginKiro, refreshKiroToken } from "../src/oauth/kiro"; +import { getValidAccessTokenSnapshot, OAUTH_PROVIDERS, runLogin } from "../../../src/oauth"; +import { loginKiro, refreshKiroToken } from "../../../src/oauth/kiro"; import { inspectKiroCliSessionSnapshot, persistKiroCliSessionRecovery, readKiroCliSqliteCredential, restoreStaleKiroCliSessionRecovery, -} from "../src/oauth/kiro-credentials"; -import { getAccountCredential, getAccountSet, saveCredential, setActiveAccount } from "../src/oauth/store"; -import type { OAuthController, OAuthCredentials } from "../src/oauth/types"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/oauth/kiro-credentials"; +import { getAccountCredential, getAccountSet, saveCredential, setActiveAccount } from "../../../src/oauth/store"; +import type { OAuthController, OAuthCredentials } from "../../../src/oauth/types"; +import type { OcxConfig } from "../../../src/types"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const ENV_KEYS = [ "HOME", diff --git a/tests/kiro-stream.test.ts b/tests/providers/kiro/kiro-stream.test.ts similarity index 99% rename from tests/kiro-stream.test.ts rename to tests/providers/kiro/kiro-stream.test.ts index db1098b4b44..acecd471ec5 100644 --- a/tests/kiro-stream.test.ts +++ b/tests/providers/kiro/kiro-stream.test.ts @@ -6,22 +6,22 @@ import { createKiroAdapter as createKiroAdapterProduction, isRetryableKiroStreamCatchError, parseKiroStream, -} from "../src/adapters/kiro"; +} from "../../../src/adapters/kiro"; import { KIRO_COMPLETION_RETRY_MESSAGE, KIRO_COMPLETION_TOOL_NAME, KIRO_TOOL_RESULT_CARRIER_MESSAGE, -} from "../src/adapters/kiro-constants"; -import { parseKiroEvent } from "../src/adapters/kiro-events"; -import { resetKiroThrottleStateForTests } from "../src/adapters/kiro-retry"; -import { resetKiroCalibration } from "../src/adapters/kiro-calibration"; -import { buildResponseJSON } from "../src/bridge"; -import { encodeMessage } from "../src/lib/eventstream-decoder"; -import { estimateTokens } from "../src/lib/token-estimate"; -import { createTranslatorBudget } from "../src/lib/translator-budget"; -import type { OcxParsedRequest, OcxProviderConfig, OcxUsage } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/adapters/kiro-constants"; +import { parseKiroEvent } from "../../../src/adapters/kiro-events"; +import { resetKiroThrottleStateForTests } from "../../../src/adapters/kiro-retry"; +import { resetKiroCalibration } from "../../../src/adapters/kiro-calibration"; +import { buildResponseJSON } from "../../../src/bridge"; +import { encodeMessage } from "../../../src/lib/eventstream-decoder"; +import { estimateTokens } from "../../../src/lib/token-estimate"; +import { createTranslatorBudget } from "../../../src/lib/translator-budget"; +import type { OcxParsedRequest, OcxProviderConfig, OcxUsage } from "../../../src/types"; +import { withTestTranslatorBudget } from "../../helpers/translator-budget"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; function createKiroAdapter(...args: Parameters) { return withTestTranslatorBudget(createKiroAdapterProduction(...args)); @@ -88,8 +88,8 @@ function streamOf(...frames: Uint8Array[]): ReadableStream { }); } -async function collectAdapterEvents(events: AsyncGenerator) { - const out: import("../src/types").AdapterEvent[] = []; +async function collectAdapterEvents(events: AsyncGenerator) { + const out: import("../../../src/types").AdapterEvent[] = []; for await (const event of events) out.push(event); return out; } @@ -2164,7 +2164,7 @@ describe("kiro adapter — non-streaming parseResponse", () => { describe("surrogate safety at kiro boundaries", () => { test("the reasoning carry never emits a delta ending on a lone high surrogate", async () => { - const { KiroThinkingParser } = await import("../src/adapters/kiro-thinking"); + const { KiroThinkingParser } = await import("../../../src/adapters/kiro-thinking"); const parser = new KiroThinkingParser(); // An astral char exactly at the carry/send boundary. const events = parser.feed("🎆aaaaaaaaaaa"); @@ -2179,7 +2179,7 @@ describe("surrogate safety at kiro boundaries", () => { }); test("a truncated tool description never ends on a lone high surrogate", async () => { - const { truncateDescriptionForTests } = await import("../src/adapters/kiro-tools"); + const { truncateDescriptionForTests } = await import("../../../src/adapters/kiro-tools"); const description = "a".repeat(1022) + "🎆cd"; const out = truncateDescriptionForTests(description, 1024); expect(out.endsWith("…")).toBe(true); diff --git a/tests/kiro-usage-quota.test.ts b/tests/providers/kiro/kiro-usage-quota.test.ts similarity index 99% rename from tests/kiro-usage-quota.test.ts rename to tests/providers/kiro/kiro-usage-quota.test.ts index f5221a1f9a7..8dcb42f347d 100644 --- a/tests/kiro-usage-quota.test.ts +++ b/tests/providers/kiro/kiro-usage-quota.test.ts @@ -6,7 +6,7 @@ import { getKiroAccountExhaustion, kiroUsageManagementUrl, reconcileKiroAccountUsageState, -} from "../src/providers/kiro-usage"; +} from "../../../src/providers/kiro-usage"; const realFetch = globalThis.fetch; diff --git a/tests/kiro-windows-cli-db-path.test.ts b/tests/providers/kiro/kiro-windows-cli-db-path.test.ts similarity index 97% rename from tests/kiro-windows-cli-db-path.test.ts rename to tests/providers/kiro/kiro-windows-cli-db-path.test.ts index 132360b2ac3..d94e1669547 100644 --- a/tests/kiro-windows-cli-db-path.test.ts +++ b/tests/providers/kiro/kiro-windows-cli-db-path.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; -import { resolveKiroCliNativeSessionEntries } from "../src/oauth/kiro-credentials"; +import { resolveKiroCliNativeSessionEntries } from "../../../src/oauth/kiro-credentials"; /** * Issue #710: `ocx login kiro` could not import an existing Windows Kiro CLI session because the @@ -101,7 +101,7 @@ describe("kiro-cli native session store resolution", () => { // observable by reading which joiner the source uses, so that is what this checks. test("darwin and linux branches pin posix.join so a Windows host cannot flip the separator", () => { const source = readFileSync( - new URL("../src/oauth/kiro-credentials.ts", import.meta.url), + new URL("../../../src/oauth/kiro-credentials.ts", import.meta.url), "utf-8", ); const resolver = source.slice(source.indexOf("export function resolveKiroCliNativeSessionEntries")); diff --git a/tests/kiro-windows-cli-executable-path.test.ts b/tests/providers/kiro/kiro-windows-cli-executable-path.test.ts similarity index 98% rename from tests/kiro-windows-cli-executable-path.test.ts rename to tests/providers/kiro/kiro-windows-cli-executable-path.test.ts index 8dc26209623..73a4d28bd77 100644 --- a/tests/kiro-windows-cli-executable-path.test.ts +++ b/tests/providers/kiro/kiro-windows-cli-executable-path.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { resolveKiroCliExecutable } from "../src/oauth/kiro-credentials"; +import { resolveKiroCliExecutable } from "../../../src/oauth/kiro-credentials"; /** * Forced/add-account Kiro login still shells out to the local CLI. After #710 fixed Windows diff --git a/tests/meta-model-api-provider.test.ts b/tests/providers/meta-model-api-provider.test.ts similarity index 95% rename from tests/meta-model-api-provider.test.ts rename to tests/providers/meta-model-api-provider.test.ts index deb462874b7..cb487ea2f58 100644 --- a/tests/meta-model-api-provider.test.ts +++ b/tests/providers/meta-model-api-provider.test.ts @@ -13,12 +13,12 @@ * - the note carrying the billing disclosure had no regression at all. */ import { describe, expect, test } from "bun:test"; -import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../src/adapters/openai-responses"; -import { enrichProviderFromRegistry, providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../../src/adapters/openai-responses"; +import { enrichProviderFromRegistry, providerConfigSeed } from "../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; const createResponsesPassthroughAdapter = (...args: Parameters) => withTestTranslatorBudget(createResponsesPassthroughAdapterProduction(...args)); diff --git a/tests/meta-muse-oauth.test.ts b/tests/providers/meta-muse-oauth.test.ts similarity index 97% rename from tests/meta-muse-oauth.test.ts rename to tests/providers/meta-muse-oauth.test.ts index 7ea46c7d904..08f824fc531 100644 --- a/tests/meta-muse-oauth.test.ts +++ b/tests/providers/meta-muse-oauth.test.ts @@ -9,12 +9,12 @@ * reaches a message or a status object. */ import { describe, expect, test } from "bun:test"; -import { OAUTH_PROVIDERS } from "../src/oauth"; -import { loginMetaMuse, refreshMetaMuseToken } from "../src/oauth/meta-muse"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { supportsPerAccountQuota } from "../src/providers/quota"; -import { routeModel } from "../src/router"; -import type { OcxConfig } from "../src/types"; +import { OAUTH_PROVIDERS } from "../../src/oauth"; +import { loginMetaMuse, refreshMetaMuseToken } from "../../src/oauth/meta-muse"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; +import { supportsPerAccountQuota } from "../../src/providers/quota"; +import { routeModel } from "../../src/router"; +import type { OcxConfig } from "../../src/types"; const MODELS = ["muse-spark-1.3", "muse-spark-1.3-contributor"] as const; diff --git a/tests/mimo-effort.test.ts b/tests/providers/mimo-effort.test.ts similarity index 92% rename from tests/mimo-effort.test.ts rename to tests/providers/mimo-effort.test.ts index 0f9b2c77127..bf095f3b4ad 100644 --- a/tests/mimo-effort.test.ts +++ b/tests/providers/mimo-effort.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; const entry = PROVIDER_REGISTRY.find(provider => provider.id === "mimo-free")!; diff --git a/tests/mimo-free-provider.test.ts b/tests/providers/mimo-free-provider.test.ts similarity index 97% rename from tests/mimo-free-provider.test.ts rename to tests/providers/mimo-free-provider.test.ts index cc9477c7121..04cd2c908ed 100644 --- a/tests/mimo-free-provider.test.ts +++ b/tests/providers/mimo-free-provider.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test, mock, beforeEach } from "bun:test"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { providerConfigSeed, deriveKeyLoginMap, deriveFeaturedProviderIds } from "../src/providers/derive"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { providerConfigSeed, deriveKeyLoginMap, deriveFeaturedProviderIds } from "../../src/providers/derive"; import { getMimoClientId, resetMimoClientIdCache, @@ -10,8 +10,8 @@ import { MIMO_SYSTEM_MARKER, MIMO_CHAT_URL, createMimoFreeAdapter, -} from "../src/adapters/mimo-free"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +} from "../../src/adapters/mimo-free"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../src/types"; function minimalRequest(model = "mimo-auto"): OcxParsedRequest { return { @@ -349,7 +349,7 @@ describe("mimo-free adapter request building", () => { describe("mimo-free GUI preset", () => { test("deriveProviderPresets exposes keyOptional for picker", () => { - const { deriveProviderPresets } = require("../src/providers/derive"); + const { deriveProviderPresets } = require("../../src/providers/derive"); const presets = deriveProviderPresets(); const preset = presets.find((p: { id: string }) => p.id === "mimo-free"); expect(preset).toBeDefined(); diff --git a/tests/mimo-token-plan-provider.test.ts b/tests/providers/mimo-token-plan-provider.test.ts similarity index 94% rename from tests/mimo-token-plan-provider.test.ts rename to tests/providers/mimo-token-plan-provider.test.ts index bf282ac89a7..60924520349 100644 --- a/tests/mimo-token-plan-provider.test.ts +++ b/tests/providers/mimo-token-plan-provider.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from "bun:test"; -import { applyProviderConfigHints } from "../src/codex/catalog"; -import { KEY_LOGIN_PROVIDERS } from "../src/oauth/key-providers"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { mapReasoningEffort } from "../src/reasoning-effort"; -import { routeModel } from "../src/router"; -import type { OcxConfig } from "../src/types"; +import { applyProviderConfigHints } from "../../src/codex/catalog"; +import { KEY_LOGIN_PROVIDERS } from "../../src/oauth/key-providers"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { mapReasoningEffort } from "../../src/reasoning-effort"; +import { routeModel } from "../../src/router"; +import type { OcxConfig } from "../../src/types"; describe("Xiaomi MiMo public OpenAI Chat endpoint (#1483)", () => { const baseUrl = "https://api.xiaomimimo.com/v1"; @@ -123,7 +123,7 @@ describe("Xiaomi MiMo token plan (#1158)", () => { // than an oversight: `healMappedTiers` treats a wire map as authoritative evidence of the // tiers the upstream can emit and merges its Codex values into the ladder, which is what lets // a stale persisted ladder recover a newly documented tier without rewriting user config - // (see "stale reasoning-ladder self-heal" in tests/reasoning-effort.test.ts). + // (see "stale reasoning-ladder self-heal" in tests/codex-integration/reasoning-effort.test.ts). // // So the registry clamp protects the DEFAULT route, not a user who has deliberately written a // conflicting map. This test records that boundary so the next reader does not mistake the diff --git a/tests/minimax-clients.test.ts b/tests/providers/minimax-clients.test.ts similarity index 98% rename from tests/minimax-clients.test.ts rename to tests/providers/minimax-clients.test.ts index c95c0d6722d..651e6c96695 100644 --- a/tests/minimax-clients.test.ts +++ b/tests/providers/minimax-clients.test.ts @@ -13,7 +13,7 @@ import { mcodeHomeDir, type ExportContext, type McodeGeneratedConfig, -} from "../src/clients/config-export"; +} from "../../src/clients/config-export"; import { buildMmxEnv, finishMmxClientCleanup, @@ -25,8 +25,9 @@ import { isStandaloneInformationalInvocation, startMmxTextBridge, usableMinimaxLiveProxy, -} from "../src/cli/minimax"; -import type { OcxConfig } from "../src/types"; +} from "../../src/cli/minimax"; +import type { OcxConfig } from "../../src/types"; +import { fixturePath } from "../helpers/repo-root"; const CONFIG = { port: 10100, @@ -162,7 +163,7 @@ describe("MiniMax CLI wrapper", () => { }); await new Promise((resolve, reject) => reservation.close(error => error ? reject(error) : resolve())); - const child = Bun.spawn([process.execPath, join(import.meta.dir, "fixtures/minimax-bridge-direct.ts")], { + const child = Bun.spawn([process.execPath, fixturePath("minimax-bridge-direct.ts")], { env: { ...process.env, HTTP_PROXY: `http://127.0.0.1:${proxyPort}`, diff --git a/tests/minimax-reasoning-split.test.ts b/tests/providers/minimax-reasoning-split.test.ts similarity index 97% rename from tests/minimax-reasoning-split.test.ts rename to tests/providers/minimax-reasoning-split.test.ts index ad2b44d57ea..4d21ff08f1c 100644 --- a/tests/minimax-reasoning-split.test.ts +++ b/tests/providers/minimax-reasoning-split.test.ts @@ -1,9 +1,9 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { createTranslatorBudget } from "../src/lib/translator-budget"; -import { enrichProviderFromRegistry } from "../src/providers/derive"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { createTranslatorBudget } from "../../src/lib/translator-budget"; +import { enrichProviderFromRegistry } from "../../src/providers/derive"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../../src/types"; type ReasoningEffort = OcxParsedRequest["options"]["reasoning"]; diff --git a/tests/model-presets.test.ts b/tests/providers/model-presets.test.ts similarity index 97% rename from tests/model-presets.test.ts rename to tests/providers/model-presets.test.ts index 7af8fe9aed9..8fcbb44dc2f 100644 --- a/tests/model-presets.test.ts +++ b/tests/providers/model-presets.test.ts @@ -5,8 +5,8 @@ import { materializeModelPreset, modelPresetFor, MODEL_PRESETS, -} from "../src/providers/model-presets"; -import type { OcxProviderConfig } from "../src/types"; +} from "../../src/providers/model-presets"; +import type { OcxProviderConfig } from "../../src/types"; describe("#2465 model presets", () => { test("rules match vendor snapshot suffixes, not just bare ids", () => { diff --git a/tests/model-rename-migration.test.ts b/tests/providers/model-rename-migration.test.ts similarity index 97% rename from tests/model-rename-migration.test.ts rename to tests/providers/model-rename-migration.test.ts index 61796018ce9..40803a4ed16 100644 --- a/tests/model-rename-migration.test.ts +++ b/tests/providers/model-rename-migration.test.ts @@ -3,9 +3,9 @@ import { MODEL_RENAMES, projectModelRenames, type ModelRename, -} from "../src/providers/model-rename-migration"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import type { OcxConfig } from "../src/types"; +} from "../../src/providers/model-rename-migration"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import type { OcxConfig } from "../../src/types"; const INTL_BASE_URL = "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1"; diff --git a/tests/moonshot-endpoints.test.ts b/tests/providers/moonshot-endpoints.test.ts similarity index 89% rename from tests/moonshot-endpoints.test.ts rename to tests/providers/moonshot-endpoints.test.ts index 3898bd1390f..107a9771b9e 100644 --- a/tests/moonshot-endpoints.test.ts +++ b/tests/providers/moonshot-endpoints.test.ts @@ -4,9 +4,9 @@ import { MOONSHOT_CN_BASE_URL, MOONSHOT_INTL_BASE_URL, matchBaseUrlChoice, -} from "../src/providers/base-url-choices"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { deriveProviderPresets } from "../src/providers/derive"; +} from "../../src/providers/base-url-choices"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { deriveProviderPresets } from "../../src/providers/derive"; describe("moonshot endpoint choices", () => { test("registry defaults to international and exposes china + custom choices", () => { diff --git a/tests/moonshot-tool-schema.test.ts b/tests/providers/moonshot-tool-schema.test.ts similarity index 99% rename from tests/moonshot-tool-schema.test.ts rename to tests/providers/moonshot-tool-schema.test.ts index 66289843405..ed1626927ad 100644 --- a/tests/moonshot-tool-schema.test.ts +++ b/tests/providers/moonshot-tool-schema.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter as createOpenAIChatAdapterProduction } from "../src/adapters/openai-chat"; -import type { OcxParsedRequest, OcxTool } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { createOpenAIChatAdapter as createOpenAIChatAdapterProduction } from "../../src/adapters/openai-chat"; +import type { OcxParsedRequest, OcxTool } from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; const createOpenAIChatAdapter = ( ...args: Parameters diff --git a/tests/muse-passive-quota-cache.test.ts b/tests/providers/muse-passive-quota-cache.test.ts similarity index 94% rename from tests/muse-passive-quota-cache.test.ts rename to tests/providers/muse-passive-quota-cache.test.ts index cf144dbca5f..48433851f76 100644 --- a/tests/muse-passive-quota-cache.test.ts +++ b/tests/providers/muse-passive-quota-cache.test.ts @@ -2,7 +2,7 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { getAccountSet, saveCredential } from "../src/oauth/store"; +import { getAccountSet, saveCredential } from "../../src/oauth/store"; import { clearAccountQuotaCache, getCachedProviderAccountQuota, @@ -12,11 +12,11 @@ import { resetProviderQuotaReconcileStateForTests, setCachedProviderAccountQuotaForTests, supportsPerAccountQuota, -} from "../src/providers/quota"; -import { hasHeadroomEvidence, rankAccountsByHeadroom } from "../src/oauth/account-quota-rank"; -import { captureConfigGeneration } from "../src/lib/state-store-sweeper"; -import type { ProviderQuota } from "../src/providers/quota-types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/quota"; +import { hasHeadroomEvidence, rankAccountsByHeadroom } from "../../src/oauth/account-quota-rank"; +import { captureConfigGeneration } from "../../src/lib/state-store-sweeper"; +import type { ProviderQuota } from "../../src/providers/quota-types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const previousOpencodexHome = process.env.OPENCODEX_HOME; let opencodexHome: string; @@ -95,7 +95,7 @@ describe("passive Muse quota cache", () => { test("discards a write whose config generation has been superseded", () => { // Generation 0 predates any reconciliation; a stale writer must not commit. - const { reconcileStateGeneration } = require("../src/lib/state-store-sweeper"); + const { reconcileStateGeneration } = require("../../src/lib/state-store-sweeper"); reconcileStateGeneration({ generation: 0, oauthAccountKeys: new Set(), providerNames: new Set() }); recordPassiveAccountQuota("meta-muse", FIRST.accountId, quotaAt(42), -1); expect(getCachedProviderAccountQuota("meta-muse", FIRST.accountId)).toBeNull(); @@ -198,7 +198,7 @@ describe("passive quota and routing headroom", () => { expect(hasHeadroomEvidence("anthropic", [FIRST.accountId])).toBe(true); }); }); -import { readPersistedAccountQuotas } from "../src/providers/account-quota-disk"; +import { readPersistedAccountQuotas } from "../../src/providers/account-quota-disk"; /** PERSIST_DEBOUNCE_MS is 250ms in account-quota-disk.ts; wait past it. */ const PERSIST_SETTLE_MS = 400; diff --git a/tests/muse-passive-quota-observation.test.ts b/tests/providers/muse-passive-quota-observation.test.ts similarity index 96% rename from tests/muse-passive-quota-observation.test.ts rename to tests/providers/muse-passive-quota-observation.test.ts index ed48130d298..56d7d74b43d 100644 --- a/tests/muse-passive-quota-observation.test.ts +++ b/tests/providers/muse-passive-quota-observation.test.ts @@ -10,8 +10,8 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { createSseInspector } from "../src/server/relay"; -import { handleOauthAccountRoutes } from "../src/server/management/oauth-account-routes"; +import { createSseInspector } from "../../src/server/relay"; +import { handleOauthAccountRoutes } from "../../src/server/management/oauth-account-routes"; import { clearAccountQuotaCache, clearProviderQuotaCache, @@ -19,15 +19,15 @@ import { getCachedProviderAccountQuota, recordPassiveAccountQuota, resetProviderQuotaReconcileStateForTests, -} from "../src/providers/quota"; +} from "../../src/providers/quota"; import { isMuseSubscriptionUsagePayload, MUSE_SUBSCRIPTION_USAGE_TYPE, parseMuseSubscriptionUsage, -} from "../src/providers/muse-subscription-usage"; -import { captureConfigGeneration } from "../src/lib/state-store-sweeper"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/muse-subscription-usage"; +import { captureConfigGeneration } from "../../src/lib/state-store-sweeper"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const previousHome = process.env.OPENCODEX_HOME; let testDir = ""; diff --git a/tests/muse-spark-web-search-compat.test.ts b/tests/providers/muse-spark-web-search-compat.test.ts similarity index 96% rename from tests/muse-spark-web-search-compat.test.ts rename to tests/providers/muse-spark-web-search-compat.test.ts index 04e0f56a73c..ed22b4e0369 100644 --- a/tests/muse-spark-web-search-compat.test.ts +++ b/tests/providers/muse-spark-web-search-compat.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from "bun:test"; -import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../src/adapters/openai-responses"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import type { OcxProviderConfig } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../../src/adapters/openai-responses"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; +import type { OcxProviderConfig } from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; const createResponsesPassthroughAdapter = (...args: Parameters) => withTestTranslatorBudget(createResponsesPassthroughAdapterProduction(...args)); diff --git a/tests/muse-subscription-usage.test.ts b/tests/providers/muse-subscription-usage.test.ts similarity index 98% rename from tests/muse-subscription-usage.test.ts rename to tests/providers/muse-subscription-usage.test.ts index 2b8b2ed86be..154b6ac5096 100644 --- a/tests/muse-subscription-usage.test.ts +++ b/tests/providers/muse-subscription-usage.test.ts @@ -3,7 +3,7 @@ import { isMuseSubscriptionUsagePayload, MUSE_SUBSCRIPTION_USAGE_TYPE, parseMuseSubscriptionUsage, -} from "../src/providers/muse-subscription-usage"; +} from "../../src/providers/muse-subscription-usage"; /** The payload measured against the live endpoint on 2026-09-03 (003 §E). */ function measuredPayload(): unknown { diff --git a/tests/new-model-policy.test.ts b/tests/providers/new-model-policy.test.ts similarity index 98% rename from tests/new-model-policy.test.ts rename to tests/providers/new-model-policy.test.ts index be6656dada2..dbf591bec38 100644 --- a/tests/new-model-policy.test.ts +++ b/tests/providers/new-model-policy.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { applyNewModelPolicy, reconcileSuccessfulModelDiscoveries } from "../src/providers/new-model-policy"; +import { applyNewModelPolicy, reconcileSuccessfulModelDiscoveries } from "../../src/providers/new-model-policy"; const now = "2026-08-24T02:11:00Z"; diff --git a/tests/nous-oauth-live.test.ts b/tests/providers/nous-oauth-live.test.ts similarity index 95% rename from tests/nous-oauth-live.test.ts rename to tests/providers/nous-oauth-live.test.ts index 83204a84af3..51e4ad47b1f 100644 --- a/tests/nous-oauth-live.test.ts +++ b/tests/providers/nous-oauth-live.test.ts @@ -21,10 +21,10 @@ * accepting either an OpenAI-style `{ data: [...] }` body or a bare array. */ import { describe, expect, test } from "bun:test"; -import { getAccountCredential, getAccountSet, getCredential } from "../src/oauth/store"; -import { NOUS_INFERENCE_BASE_URL, refreshNousToken } from "../src/oauth/nous"; -import { refreshGenericAccountWithLock } from "../src/oauth/index"; -import type { OAuthCredentials } from "../src/oauth/types"; +import { getAccountCredential, getAccountSet, getCredential } from "../../src/oauth/store"; +import { NOUS_INFERENCE_BASE_URL, refreshNousToken } from "../../src/oauth/nous"; +import { refreshGenericAccountWithLock } from "../../src/oauth/index"; +import type { OAuthCredentials } from "../../src/oauth/types"; const LIVE = process.env.NOUS_LIVE_TEST === "1"; diff --git a/tests/nous-oauth.test.ts b/tests/providers/nous-oauth.test.ts similarity index 99% rename from tests/nous-oauth.test.ts rename to tests/providers/nous-oauth.test.ts index e6fc200020e..c1294cfc5fa 100644 --- a/tests/nous-oauth.test.ts +++ b/tests/providers/nous-oauth.test.ts @@ -2,12 +2,12 @@ import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test"; import { createHash } from "node:crypto"; import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { join } from "node:path"; -import { clearNousRefreshIntent, identityFromNousTokens, loginNous, nousRefreshIntentBlocksReplay, refreshNousToken, RefreshIntentIOError } from "../src/oauth/nous"; -import { getCredential, listAccounts, saveCredential } from "../src/oauth/store"; -import type { OAuthController } from "../src/oauth/types"; -import * as configModule from "../src/config"; -import { BOUNDED_BODY_MAX_BYTES } from "../src/lib/bounded-body"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { clearNousRefreshIntent, identityFromNousTokens, loginNous, nousRefreshIntentBlocksReplay, refreshNousToken, RefreshIntentIOError } from "../../src/oauth/nous"; +import { getCredential, listAccounts, saveCredential } from "../../src/oauth/store"; +import type { OAuthController } from "../../src/oauth/types"; +import * as configModule from "../../src/config"; +import { BOUNDED_BODY_MAX_BYTES } from "../../src/lib/bounded-body"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(import.meta.dir, ".tmp-nous-oauth-test"); const TEST_PORTAL = "https://portal.test"; diff --git a/tests/novita-provider.test.ts b/tests/providers/novita-provider.test.ts similarity index 88% rename from tests/novita-provider.test.ts rename to tests/providers/novita-provider.test.ts index 1b8320dece3..d1c6ba2ff50 100644 --- a/tests/novita-provider.test.ts +++ b/tests/providers/novita-provider.test.ts @@ -1,25 +1,26 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { resolveProviderModelDiscovery } from "../src/providers/model-discovery"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; - -const NOVITA_FIXTURE = readFileSync(join(import.meta.dir, "fixtures/novita-models.json"), "utf8"); +} from "../../src/providers/derive"; +import { resolveProviderModelDiscovery } from "../../src/providers/model-discovery"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; + +const NOVITA_FIXTURE = readFileSync(fixturePath("novita-models.json"), "utf8"); const BASE_URL = "https://api.novita.ai/openai/v1"; const MODELS_URL = `${BASE_URL}/models`; const TEST_KEY = "novita-test-key"; diff --git a/tests/nscale-vultr-provider.test.ts b/tests/providers/nscale-vultr-provider.test.ts similarity index 90% rename from tests/nscale-vultr-provider.test.ts rename to tests/providers/nscale-vultr-provider.test.ts index 37042629d9e..0a787856472 100644 --- a/tests/nscale-vultr-provider.test.ts +++ b/tests/providers/nscale-vultr-provider.test.ts @@ -1,22 +1,23 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; +} from "../../src/providers/derive"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; const NSCALE_BASE_URL = "https://inference.api.nscale.com/v1"; const VULTR_BASE_URL = "https://api.vultrinference.com/v1"; @@ -24,8 +25,8 @@ const NSCALE_MODEL = "meta-llama/Llama-3.1-8B-Instruct"; const VULTR_MODEL = "kimi-k2-instruct"; const API_KEY = "provider-test-key"; const fixtures = { - nscale: readFileSync(join(import.meta.dir, "fixtures/nscale-models.json"), "utf8"), - vultr: readFileSync(join(import.meta.dir, "fixtures/vultr-models.json"), "utf8"), + nscale: readFileSync(fixturePath("nscale-models.json"), "utf8"), + vultr: readFileSync(fixturePath("vultr-models.json"), "utf8"), }; const originalFetch = globalThis.fetch; diff --git a/tests/nvidia-nim-hardening.test.ts b/tests/providers/nvidia-nim-hardening.test.ts similarity index 97% rename from tests/nvidia-nim-hardening.test.ts rename to tests/providers/nvidia-nim-hardening.test.ts index 7a1c0b397f9..17d553c3f1b 100644 --- a/tests/nvidia-nim-hardening.test.ts +++ b/tests/providers/nvidia-nim-hardening.test.ts @@ -5,13 +5,13 @@ // natively image-capable models do not. Plan/evidence: // devlog/_fin/260804_stack7_service_vision (010 design, 011 per-id audit). import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter, formatOpenAIChatErrorBody } from "../src/adapters/openai-chat"; -import { applyProviderConfigHints, normalizeRoutedCatalogEntry } from "../src/codex/catalog"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { parseRequest } from "../src/responses/parser"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxParsedRequest, OcxTool } from "../src/types"; -import { planVisionSidecar } from "../src/vision"; +import { createOpenAIChatAdapter, formatOpenAIChatErrorBody } from "../../src/adapters/openai-chat"; +import { applyProviderConfigHints, normalizeRoutedCatalogEntry } from "../../src/codex/catalog"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { parseRequest } from "../../src/responses/parser"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxParsedRequest, OcxTool } from "../../src/types"; +import { planVisionSidecar } from "../../src/vision"; const tools: OcxTool[] = [{ name: "shell", description: "run", parameters: { type: "object" } }]; diff --git a/tests/ollama-native-parser.test.ts b/tests/providers/ollama/ollama-native-parser.test.ts similarity index 98% rename from tests/ollama-native-parser.test.ts rename to tests/providers/ollama/ollama-native-parser.test.ts index 589d84e3fc8..71bfad723ae 100644 --- a/tests/ollama-native-parser.test.ts +++ b/tests/providers/ollama/ollama-native-parser.test.ts @@ -1,9 +1,9 @@ import { describe, expect, test } from "bun:test"; -import { createOllamaNativeAdapter } from "../src/adapters/ollama-native"; -import { ollamaNativeChatUrl } from "../src/adapters/ollama-native-url"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import type { AdapterEvent } from "../src/types"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { createOllamaNativeAdapter } from "../../../src/adapters/ollama-native"; +import { ollamaNativeChatUrl } from "../../../src/adapters/ollama-native-url"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; +import type { AdapterEvent } from "../../../src/types"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; /** * Parser/request contract tests for the native Ollama transport. @@ -49,7 +49,7 @@ async function collect(adapter: ReturnType, re describe("ollama-native — observer-free streaming", () => { test("no structural-receipt machinery exists in the module surface", async () => { - const mod = await import("../src/adapters/ollama-native") as unknown as Record; + const mod = await import("../../../src/adapters/ollama-native") as unknown as Record; for (const name of [ "setOllamaNativeObservationSink", "createOllamaNativeObservationBuffer", diff --git a/tests/ollama-native-reasoning-wire.test.ts b/tests/providers/ollama/ollama-native-reasoning-wire.test.ts similarity index 94% rename from tests/ollama-native-reasoning-wire.test.ts rename to tests/providers/ollama/ollama-native-reasoning-wire.test.ts index fc84e37cf3b..c1fe09dcafa 100644 --- a/tests/ollama-native-reasoning-wire.test.ts +++ b/tests/providers/ollama/ollama-native-reasoning-wire.test.ts @@ -1,9 +1,9 @@ import { describe, expect, test } from "bun:test"; -import { createOllamaNativeAdapter } from "../src/adapters/ollama-native"; -import { buildCatalogEntries, gatherRoutedModels as gatherRoutedModelsDirect } from "../src/codex/catalog"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import { REASONING_EFFORT_OMIT_SENTINEL } from "../src/reasoning-effort"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { createOllamaNativeAdapter } from "../../../src/adapters/ollama-native"; +import { buildCatalogEntries, gatherRoutedModels as gatherRoutedModelsDirect } from "../../../src/codex/catalog"; +import { withStubbedProviderFetch } from "../../helpers/catalog-provider-fetch"; +import { REASONING_EFFORT_OMIT_SENTINEL } from "../../../src/reasoning-effort"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; const gatherRoutedModels: typeof gatherRoutedModelsDirect = (config, options) => gatherRoutedModelsDirect(withStubbedProviderFetch(config), options); diff --git a/tests/ollama-native-structured-output.test.ts b/tests/providers/ollama/ollama-native-structured-output.test.ts similarity index 97% rename from tests/ollama-native-structured-output.test.ts rename to tests/providers/ollama/ollama-native-structured-output.test.ts index 4e2bcfa0016..ed2df673807 100644 --- a/tests/ollama-native-structured-output.test.ts +++ b/tests/providers/ollama/ollama-native-structured-output.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { createOllamaNativeAdapter } from "../src/adapters/ollama-native"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { createOllamaNativeAdapter } from "../../../src/adapters/ollama-native"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; /** * Structured output is a capability boundary, not a formatting preference. diff --git a/tests/ollama-native-v4.test.ts b/tests/providers/ollama/ollama-native-v4.test.ts similarity index 93% rename from tests/ollama-native-v4.test.ts rename to tests/providers/ollama/ollama-native-v4.test.ts index 4da76379d0d..13fa0269a53 100644 --- a/tests/ollama-native-v4.test.ts +++ b/tests/providers/ollama/ollama-native-v4.test.ts @@ -1,9 +1,9 @@ import { describe, expect, test } from "bun:test"; -import { createOllamaNativeAdapter } from "../src/adapters/ollama-native"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import { REASONING_EFFORT_OMIT_SENTINEL } from "../src/reasoning-effort"; -import type { AdapterEvent } from "../src/types"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { createOllamaNativeAdapter } from "../../../src/adapters/ollama-native"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; +import { REASONING_EFFORT_OMIT_SENTINEL } from "../../../src/reasoning-effort"; +import type { AdapterEvent } from "../../../src/types"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; function provider(overrides: Partial = {}): OcxProviderConfig { return { diff --git a/tests/ollama-native.test.ts b/tests/providers/ollama/ollama-native.test.ts similarity index 96% rename from tests/ollama-native.test.ts rename to tests/providers/ollama/ollama-native.test.ts index 65c90c5848f..d22cdc1ce4b 100644 --- a/tests/ollama-native.test.ts +++ b/tests/providers/ollama/ollama-native.test.ts @@ -1,13 +1,13 @@ import { describe, expect, test } from "bun:test"; -import { createOllamaNativeAdapter } from "../src/adapters/ollama-native"; +import { createOllamaNativeAdapter } from "../../../src/adapters/ollama-native"; import { ollamaNativeChatUrl, ollamaNativeEndpointKind, -} from "../src/adapters/ollama-native-url"; -import { buildCatalogEntries, gatherRoutedModels as gatherRoutedModelsDirect, upstreamNativeEntry } from "../src/codex/catalog"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +} from "../../../src/adapters/ollama-native-url"; +import { buildCatalogEntries, gatherRoutedModels as gatherRoutedModelsDirect, upstreamNativeEntry } from "../../../src/codex/catalog"; +import { getProviderRegistryEntry } from "../../../src/providers/registry"; +import { withStubbedProviderFetch } from "../../helpers/catalog-provider-fetch"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; const gatherRoutedModels: typeof gatherRoutedModelsDirect = (config, options) => gatherRoutedModelsDirect(withStubbedProviderFetch(config), options); diff --git a/tests/ollama-show-enrichment-v7.test.ts b/tests/providers/ollama/ollama-show-enrichment-v7.test.ts similarity index 97% rename from tests/ollama-show-enrichment-v7.test.ts rename to tests/providers/ollama/ollama-show-enrichment-v7.test.ts index a82f8a336d1..9595db263a3 100644 --- a/tests/ollama-show-enrichment-v7.test.ts +++ b/tests/providers/ollama/ollama-show-enrichment-v7.test.ts @@ -1,6 +1,6 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { gatherRoutedModels, resetCatalogRuntimeStateForTests, resetOpenAiApiCatalogWarningStateForTests } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; +import { gatherRoutedModels, resetCatalogRuntimeStateForTests, resetOpenAiApiCatalogWarningStateForTests } from "../../../src/codex/catalog"; +import { clearModelCache } from "../../../src/codex/model-cache"; afterEach(() => { // The provider-model cache is keyed by provider name; without this, one test's gather would @@ -12,9 +12,9 @@ afterEach(() => { }); const originalFetch = globalThis.fetch; -import { fetchOllamaShowEnrichment, ollamaShowMetadataFromPayload, showHeadersFromCaptured } from "../src/providers/ollama-show"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import type { OcxConfig } from "../src/types"; +import { fetchOllamaShowEnrichment, ollamaShowMetadataFromPayload, showHeadersFromCaptured } from "../../../src/providers/ollama-show"; +import { withStubbedProviderFetch } from "../../helpers/catalog-provider-fetch"; +import type { OcxConfig } from "../../../src/types"; /** * V7: auth/outbound-policy integration, aggregate fan-out bounds, and models-API precedence. @@ -368,8 +368,8 @@ describe("ollama /api/show — payload extraction contract (input not mutated)", }); // The adapter-level third surface is exercised directly below via the real adapter factory, // which is what the native /api/chat route uses. -import { createOllamaNativeAdapter } from "../src/adapters/ollama-native"; -import type { OcxParsedRequest } from "../src/types"; +import { createOllamaNativeAdapter } from "../../../src/adapters/ollama-native"; +import type { OcxParsedRequest } from "../../../src/types"; function nativeParsed(modelId = "glm-5.3-flash"): OcxParsedRequest { return { modelId, stream: true, options: {}, context: { messages: [{ role: "user", content: "hi" }] } } as unknown as OcxParsedRequest; diff --git a/tests/ollama-show-enrichment.test.ts b/tests/providers/ollama/ollama-show-enrichment.test.ts similarity index 97% rename from tests/ollama-show-enrichment.test.ts rename to tests/providers/ollama/ollama-show-enrichment.test.ts index 240a2665d6d..8517913a77e 100644 --- a/tests/ollama-show-enrichment.test.ts +++ b/tests/providers/ollama/ollama-show-enrichment.test.ts @@ -1,6 +1,6 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { gatherRoutedModels, resetCatalogRuntimeStateForTests, resetOpenAiApiCatalogWarningStateForTests } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; +import { gatherRoutedModels, resetCatalogRuntimeStateForTests, resetOpenAiApiCatalogWarningStateForTests } from "../../../src/codex/catalog"; +import { clearModelCache } from "../../../src/codex/model-cache"; afterEach(() => { // The provider-model cache is keyed by provider name; without this, one test's gather would @@ -12,9 +12,9 @@ afterEach(() => { }); const originalFetch = globalThis.fetch; -import { ollamaShowMetadataFromPayload } from "../src/providers/ollama-show"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import type { OcxConfig } from "../src/types"; +import { ollamaShowMetadataFromPayload } from "../../../src/providers/ollama-show"; +import { withStubbedProviderFetch } from "../../helpers/catalog-provider-fetch"; +import type { OcxConfig } from "../../../src/types"; /** * Bounded /api/show metadata enrichment for Ollama Cloud live discovery. diff --git a/tests/ollama-show-ignore-abort.test.ts b/tests/providers/ollama/ollama-show-ignore-abort.test.ts similarity index 98% rename from tests/ollama-show-ignore-abort.test.ts rename to tests/providers/ollama/ollama-show-ignore-abort.test.ts index 0a87075d59a..327524ce716 100644 --- a/tests/ollama-show-ignore-abort.test.ts +++ b/tests/providers/ollama/ollama-show-ignore-abort.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { fetchOllamaShowEnrichment } from "../src/providers/ollama-show"; +import { fetchOllamaShowEnrichment } from "../../../src/providers/ollama-show"; /** * V10: the aggregate deadline TIMER ITSELF is the return bound. diff --git a/tests/opencode-cli.test.ts b/tests/providers/opencode-cli.test.ts similarity index 98% rename from tests/opencode-cli.test.ts rename to tests/providers/opencode-cli.test.ts index 1b8cce02d79..e1aed8a045b 100644 --- a/tests/opencode-cli.test.ts +++ b/tests/providers/opencode-cli.test.ts @@ -2,8 +2,8 @@ import { describe, expect, test } from "bun:test"; import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { clearModelCache } from "../src/codex/model-cache"; -import { loadServiceTokenFromFile, serviceApiTokenFilePath } from "../src/lib/service-secrets"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { loadServiceTokenFromFile, serviceApiTokenFilePath } from "../../src/lib/service-secrets"; import { OPENCODE_API_KEY_ENV, OPENCODE_API_KEY_ENV_REF, @@ -31,8 +31,8 @@ import { parseJsonc, projectConfigOverridesProvider, serializeOpencodeRuntimeConfig, -} from "../src/cli/opencode"; -import type { OcxConfig } from "../src/types"; +} from "../../src/cli/opencode"; +import type { OcxConfig } from "../../src/types"; function cfg(extra?: Partial): OcxConfig { return { @@ -273,7 +273,7 @@ describe("ocx opencode proxy model catalog", () => { delete process.env[ENV_KEY]; clearModelCache(PROVIDER); try { - const { fetchAllModels } = await import("../src/server/management/shared"); + const { fetchAllModels } = await import("../../src/server/management/shared"); const cliModels = await fetchAllModels(config); const cliIds = cliModels.filter(m => m.provider === PROVIDER).map(m => m.id).sort(); expect(cliIds).toEqual(["static-fallback"]); @@ -283,7 +283,7 @@ describe("ocx opencode proxy model catalog", () => { clearModelCache(PROVIDER); requestedAuth = undefined; - const { handleManagementAPI } = await import("../src/server/management-api"); + const { handleManagementAPI } = await import("../../src/server/management-api"); const modelsRes = await handleManagementAPI( new Request("http://localhost/api/models"), new URL("http://localhost/api/models"), @@ -668,4 +668,4 @@ describe("ocx opencode not-found hint", () => { expect(opencodeNotFoundHint(0, null, "win32")).toBeNull(); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/opencode-free-provider.test.ts b/tests/providers/opencode-free-provider.test.ts similarity index 95% rename from tests/opencode-free-provider.test.ts rename to tests/providers/opencode-free-provider.test.ts index 0db4aafb3ee..c468af2cc01 100644 --- a/tests/opencode-free-provider.test.ts +++ b/tests/providers/opencode-free-provider.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from "bun:test"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { providerConfigSeed, deriveKeyLoginMap, deriveFeaturedProviderIds } from "../src/providers/derive"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { routedProviderConfig } from "../src/router"; -import { buildModelsRequest } from "../src/oauth"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { providerConfigSeed, deriveKeyLoginMap, deriveFeaturedProviderIds } from "../../src/providers/derive"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { routedProviderConfig } from "../../src/router"; +import { buildModelsRequest } from "../../src/oauth"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../src/types"; function minimalRequest(model = "kimi-k2.7-code"): OcxParsedRequest { return { @@ -208,7 +208,7 @@ describe("opencode-free provider", () => { }); test("deriveProviderPresets exposes keyOptional for GUI picker", () => { - const { deriveProviderPresets } = require("../src/providers/derive"); + const { deriveProviderPresets } = require("../../src/providers/derive"); const presets = deriveProviderPresets(); const preset = presets.find((p: { id: string }) => p.id === "opencode-free"); expect(preset).toBeDefined(); diff --git a/tests/opencode-go-deepseek.test.ts b/tests/providers/opencode-go-deepseek.test.ts similarity index 96% rename from tests/opencode-go-deepseek.test.ts rename to tests/providers/opencode-go-deepseek.test.ts index dd972e36b1d..edf42a48152 100644 --- a/tests/opencode-go-deepseek.test.ts +++ b/tests/providers/opencode-go-deepseek.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { routeModel } from "../src/router"; -import type { OcxConfig } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { routeModel } from "../../src/router"; +import type { OcxConfig } from "../../src/types"; function configFor(modelId: string): OcxConfig { return { diff --git a/tests/opencode-go-grok46-responses.test.ts b/tests/providers/opencode-go-grok46-responses.test.ts similarity index 91% rename from tests/opencode-go-grok46-responses.test.ts rename to tests/providers/opencode-go-grok46-responses.test.ts index 175e29c3135..19c2addd468 100644 --- a/tests/opencode-go-grok46-responses.test.ts +++ b/tests/providers/opencode-go-grok46-responses.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from "bun:test"; -import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../src/adapters/openai-responses"; -import { providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { resolveWireProtocolOverride } from "../src/server/adapter-resolve"; -import type { OcxProviderConfig } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { createResponsesPassthroughAdapter as createResponsesPassthroughAdapterProduction } from "../../src/adapters/openai-responses"; +import { providerConfigSeed } from "../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; +import { resolveWireProtocolOverride } from "../../src/server/adapter-resolve"; +import type { OcxProviderConfig } from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; const createResponsesPassthroughAdapter = (...args: Parameters) => withTestTranslatorBudget(createResponsesPassthroughAdapterProduction(...args)); diff --git a/tests/opencode-go-luna-wire.test.ts b/tests/providers/opencode-go-luna-wire.test.ts similarity index 90% rename from tests/opencode-go-luna-wire.test.ts rename to tests/providers/opencode-go-luna-wire.test.ts index 72e383abdfd..152783b9bd6 100644 --- a/tests/opencode-go-luna-wire.test.ts +++ b/tests/providers/opencode-go-luna-wire.test.ts @@ -5,11 +5,11 @@ * boundary that lets operators opt out if the upstream changes. */ import { afterEach, describe, expect, test } from "bun:test"; -import { providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { resolveWireProtocolOverride } from "../src/server/adapter-resolve"; -import { handleResponses } from "../src/server/responses/core"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { providerConfigSeed } from "../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; +import { resolveWireProtocolOverride } from "../../src/server/adapter-resolve"; +import { handleResponses } from "../../src/server/responses/core"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; const MODEL = "gpt-5.6-luna"; diff --git a/tests/opencode-go-muse-context.test.ts b/tests/providers/opencode-go-muse-context.test.ts similarity index 92% rename from tests/opencode-go-muse-context.test.ts rename to tests/providers/opencode-go-muse-context.test.ts index 56bdc9dcc2c..26c1e5444a5 100644 --- a/tests/opencode-go-muse-context.test.ts +++ b/tests/providers/opencode-go-muse-context.test.ts @@ -8,10 +8,10 @@ * in and prove the catalog advertises the full 1M window for Muse. */ import { describe, expect, test } from "bun:test"; -import { applyProviderConfigHints } from "../src/codex/catalog"; -import { getProviderRegistryEntry, PROVIDER_REGISTRY } from "../src/providers/registry"; -import { providerConfigSeed } from "../src/providers/derive"; -import type { OcxProviderConfig } from "../src/types"; +import { applyProviderConfigHints } from "../../src/codex/catalog"; +import { getProviderRegistryEntry, PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { providerConfigSeed } from "../../src/providers/derive"; +import type { OcxProviderConfig } from "../../src/types"; const MUSE_MODEL = "muse-spark-1.2-contributor"; const MUSE_13_MODEL = "muse-spark-1.3-contributor"; diff --git a/tests/opencode-go-muse-vision.test.ts b/tests/providers/opencode-go-muse-vision.test.ts similarity index 95% rename from tests/opencode-go-muse-vision.test.ts rename to tests/providers/opencode-go-muse-vision.test.ts index b8eca82a6ce..0a39bdb92a0 100644 --- a/tests/opencode-go-muse-vision.test.ts +++ b/tests/providers/opencode-go-muse-vision.test.ts @@ -9,10 +9,10 @@ * and prove the catalog advertises image input for Muse. */ import { describe, expect, test } from "bun:test"; -import { applyProviderConfigHints } from "../src/codex/catalog"; -import { getProviderRegistryEntry, PROVIDER_REGISTRY } from "../src/providers/registry"; -import { providerConfigSeed } from "../src/providers/derive"; -import type { OcxProviderConfig } from "../src/types"; +import { applyProviderConfigHints } from "../../src/codex/catalog"; +import { getProviderRegistryEntry, PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { providerConfigSeed } from "../../src/providers/derive"; +import type { OcxProviderConfig } from "../../src/types"; const MUSE_MODEL = "muse-spark-1.2-contributor"; const MUSE_13_MODEL = "muse-spark-1.3-contributor"; diff --git a/tests/opencode-go-quota.test.ts b/tests/providers/opencode-go-quota.test.ts similarity index 98% rename from tests/opencode-go-quota.test.ts rename to tests/providers/opencode-go-quota.test.ts index df2bb525256..26d9463ee1d 100644 --- a/tests/opencode-go-quota.test.ts +++ b/tests/providers/opencode-go-quota.test.ts @@ -1,6 +1,6 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; -import { clearProviderQuotaCache, fetchProviderQuotaReports } from "../src/providers/quota"; -import type { OcxConfig } from "../src/types"; +import { clearProviderQuotaCache, fetchProviderQuotaReports } from "../../src/providers/quota"; +import type { OcxConfig } from "../../src/types"; const originalFetch = globalThis.fetch; diff --git a/tests/opencode-go-session-header.test.ts b/tests/providers/opencode-go-session-header.test.ts similarity index 93% rename from tests/opencode-go-session-header.test.ts rename to tests/providers/opencode-go-session-header.test.ts index 2a4de51b6c8..00684f065bd 100644 --- a/tests/opencode-go-session-header.test.ts +++ b/tests/providers/opencode-go-session-header.test.ts @@ -1,9 +1,9 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { providerConfigSeed } from "../src/providers/derive"; -import { resolveOpenCodeGoTransport } from "../src/providers/opencode-go-transport"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { handleResponses } from "../src/server/responses/core"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { providerConfigSeed } from "../../src/providers/derive"; +import { resolveOpenCodeGoTransport } from "../../src/providers/opencode-go-transport"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; +import { handleResponses } from "../../src/server/responses/core"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; const MUSE_MODEL = "muse-spark-1.3-contributor"; const CHAT_MODEL = "glm-5.2"; diff --git a/tests/opencode-zen-deepseek-reasoning.test.ts b/tests/providers/opencode-zen-deepseek-reasoning.test.ts similarity index 95% rename from tests/opencode-zen-deepseek-reasoning.test.ts rename to tests/providers/opencode-zen-deepseek-reasoning.test.ts index 4c29e34ed79..5074a510f1f 100644 --- a/tests/opencode-zen-deepseek-reasoning.test.ts +++ b/tests/providers/opencode-zen-deepseek-reasoning.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { routeModel } from "../src/router"; -import type { OcxConfig } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { routeModel } from "../../src/router"; +import type { OcxConfig } from "../../src/types"; function configFor(modelId: string): OcxConfig { return { diff --git a/tests/opencode-zen-rate-limit.test.ts b/tests/providers/opencode-zen-rate-limit.test.ts similarity index 94% rename from tests/opencode-zen-rate-limit.test.ts rename to tests/providers/opencode-zen-rate-limit.test.ts index ae56694c560..5678a35b778 100644 --- a/tests/opencode-zen-rate-limit.test.ts +++ b/tests/providers/opencode-zen-rate-limit.test.ts @@ -1,14 +1,14 @@ import { describe, expect, test } from "bun:test"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; import { OPENCODE_ZEN_OBSERVED_RPM_HINT, OPENCODE_ZEN_SYNTHETIC_RETRY_AFTER_SEC, enrichOpenCodeZenRateLimitMessage, isOpenCodeZenRateLimitProvider, -} from "../src/providers/opencode-zen-rate-limit"; -import { resolveClientRetryAfter } from "../src/lib/retry-after"; -import { safeConfigDTO } from "../src/server/auth-cors"; -import type { OcxConfig } from "../src/types"; +} from "../../src/providers/opencode-zen-rate-limit"; +import { resolveClientRetryAfter } from "../../src/lib/retry-after"; +import { safeConfigDTO } from "../../src/server/auth-cors"; +import type { OcxConfig } from "../../src/types"; describe("opencode-zen rate-limit guidance (#1145)", () => { test("registry note documents the observed short-window RPM", () => { diff --git a/tests/openrouter-provider-routing.test.ts b/tests/providers/openrouter-provider-routing.test.ts similarity index 97% rename from tests/openrouter-provider-routing.test.ts rename to tests/providers/openrouter-provider-routing.test.ts index 7a833a5b7a0..8211c8f0085 100644 --- a/tests/openrouter-provider-routing.test.ts +++ b/tests/providers/openrouter-provider-routing.test.ts @@ -2,17 +2,17 @@ import { describe, expect, test } from "bun:test"; import { mkdtempSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { buildOpenAIChatPassthroughRequest, createOpenAIChatAdapter } from "../src/adapters/openai-chat"; +import { buildOpenAIChatPassthroughRequest, createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; import { openRouterRoutingConfigError, openRouterProviderPayload, -} from "../src/providers/openrouter-routing"; -import { fastPolicyForModel } from "../src/providers/service-tier"; -import { clearKeyCooldowns, rotateProviderTransportOn429 } from "../src/providers/key-failover"; -import { routeModel } from "../src/router"; -import { providerManagementConfigError, safeConfigDTO } from "../src/server/auth-cors"; -import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/openrouter-routing"; +import { fastPolicyForModel } from "../../src/providers/service-tier"; +import { clearKeyCooldowns, rotateProviderTransportOn429 } from "../../src/providers/key-failover"; +import { routeModel } from "../../src/router"; +import { providerManagementConfigError, safeConfigDTO } from "../../src/server/auth-cors"; +import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; function provider(baseUrl: string, overrides: Partial = {}): OcxProviderConfig { return { adapter: "openai-chat", baseUrl, apiKey: "test-key", ...overrides }; diff --git a/tests/provider-account-quota-persistence.test.ts b/tests/providers/provider-account-quota-persistence.test.ts similarity index 94% rename from tests/provider-account-quota-persistence.test.ts rename to tests/providers/provider-account-quota-persistence.test.ts index 672ad73966c..d9a8f05ef40 100644 --- a/tests/provider-account-quota-persistence.test.ts +++ b/tests/providers/provider-account-quota-persistence.test.ts @@ -6,9 +6,9 @@ import { cancelPendingAccountQuotaPersist, readPersistedAccountQuotas, schedulePersistAccountQuotas, -} from "../src/providers/account-quota-disk"; -import type { ProviderQuota } from "../src/providers/quota-types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/account-quota-disk"; +import type { ProviderQuota } from "../../src/providers/quota-types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const previousHome = process.env.OPENCODEX_HOME; let home: string; diff --git a/tests/provider-account-quota.test.ts b/tests/providers/provider-account-quota.test.ts similarity index 97% rename from tests/provider-account-quota.test.ts rename to tests/providers/provider-account-quota.test.ts index 11b3d694895..ccebd5c0320 100644 --- a/tests/provider-account-quota.test.ts +++ b/tests/providers/provider-account-quota.test.ts @@ -2,8 +2,8 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveCredential } from "../src/oauth/store"; -import type { OcxConfig } from "../src/types"; +import { saveCredential } from "../../src/oauth/store"; +import type { OcxConfig } from "../../src/types"; import { clearAccountQuotaCache, clearProviderQuotaCache, @@ -13,8 +13,8 @@ import { reconcileProviderAccountQuotaRows, resetProviderQuotaReconcileStateForTests, supportsPerAccountQuota, -} from "../src/providers/quota"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/quota"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const originalFetch = globalThis.fetch; const previousOpencodexHome = process.env.OPENCODEX_HOME; @@ -171,7 +171,7 @@ describe("fetchProviderAccountQuotas", () => { access: "token-bg", refresh: "refresh-bg", expires, accountId: "acct-bg", email: "bg@example.com", source: "local-cli", }); - const { getAccountSet, setActiveAccount } = await import("../src/oauth/store"); + const { getAccountSet, setActiveAccount } = await import("../../src/oauth/store"); const set = getAccountSet("anthropic"); const active = set?.accounts.find(a => a.credential.email === "active@example.com"); const background = set?.accounts.find(a => a.credential.email === "bg@example.com"); @@ -223,7 +223,7 @@ describe("fetchProviderAccountQuotas", () => { test("provider-report probe seeds the active account cache for per-account reads", async () => { await seedTwoAccounts(); - const { getAccountSet, setActiveAccount } = await import("../src/oauth/store"); + const { getAccountSet, setActiveAccount } = await import("../../src/oauth/store"); const set = getAccountSet("anthropic"); const first = set?.accounts.find(a => a.credential.email === "first@example.com"); expect(first).toBeTruthy(); @@ -277,7 +277,7 @@ describe("fetchProviderAccountQuotas", () => { access: "token-bg", refresh: "refresh-bg", expires, accountId: "acct-bg", email: "bg@example.com", source: "oauth", }); - const { getAccountSet, setActiveAccount } = await import("../src/oauth/store"); + const { getAccountSet, setActiveAccount } = await import("../../src/oauth/store"); const set = getAccountSet("anthropic"); const active = set?.accounts.find(a => a.credential.email === "active@example.com"); const background = set?.accounts.find(a => a.credential.email === "bg@example.com"); @@ -327,7 +327,7 @@ describe("fetchProviderAccountQuotas", () => { test("provider-report seeding binds to the probed account across an active switch", async () => { await seedTwoAccounts(); - const { getAccountSet, setActiveAccount } = await import("../src/oauth/store"); + const { getAccountSet, setActiveAccount } = await import("../../src/oauth/store"); const set = getAccountSet("anthropic"); const first = set?.accounts.find(a => a.credential.email === "first@example.com"); const second = set?.accounts.find(a => a.credential.email === "second@example.com"); @@ -384,7 +384,7 @@ describe("fetchProviderAccountQuotas", () => { test("provider removal during an Anthropic report probe cannot recreate its account quota row", async () => { await seedTwoAccounts(); - const { getAccountSet, setActiveAccount } = await import("../src/oauth/store"); + const { getAccountSet, setActiveAccount } = await import("../../src/oauth/store"); const first = getAccountSet("anthropic")?.accounts.find(account => account.credential.email === FIRST.email); expect(first).toBeTruthy(); await setActiveAccount("anthropic", first!.id); @@ -425,8 +425,8 @@ describe("fetchProviderAccountQuotas", () => { }); describe("google-antigravity per-account quota (#1082)", () => { - const { setAntigravityAccountQuotaTransportForTests } = require("../src/providers/quota") as typeof import("../src/providers/quota"); - const { getAccountSet } = require("../src/oauth/store") as typeof import("../src/oauth/store"); + const { setAntigravityAccountQuotaTransportForTests } = require("../../src/providers/quota") as typeof import("../../src/providers/quota"); + const { getAccountSet } = require("../../src/oauth/store") as typeof import("../../src/oauth/store"); const idFor = (email: string) => getAccountSet("google-antigravity")!.accounts.find(a => a.credential.email === email)!.id; function antigravityBody(gemRemaining: number, claRemaining: number): string { diff --git a/tests/provider-api-keys.test.ts b/tests/providers/provider-api-keys.test.ts similarity index 94% rename from tests/provider-api-keys.test.ts rename to tests/providers/provider-api-keys.test.ts index 10ff2f4bb5f..88bb2393b7f 100644 --- a/tests/provider-api-keys.test.ts +++ b/tests/providers/provider-api-keys.test.ts @@ -1,13 +1,13 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; -import { managementFetch as fetch } from "./helpers/management-auth"; +import { managementFetch as fetch } from "../helpers/management-auth"; import { mkdtempSync, readFileSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; -import { startServer } from "../src/server"; -import type { OcxConfig } from "../src/types"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { saveConfig } from "../../src/config"; +import { startServer } from "../../src/server"; +import type { OcxConfig } from "../../src/types"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; let testDir = ""; let previousHome: string | undefined; diff --git a/tests/provider-capacity.test.ts b/tests/providers/provider-capacity.test.ts similarity index 99% rename from tests/provider-capacity.test.ts rename to tests/providers/provider-capacity.test.ts index 978cb39bc89..5c3f9bf9182 100644 --- a/tests/provider-capacity.test.ts +++ b/tests/providers/provider-capacity.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { aggregateCodexPoolCapacity, CODEX_CAPACITY_MAX_QUOTA_AGE_MS, type CodexCapacityAccount } from "../src/providers/codex-capacity"; +import { aggregateCodexPoolCapacity, CODEX_CAPACITY_MAX_QUOTA_AGE_MS, type CodexCapacityAccount } from "../../src/providers/codex-capacity"; const NOW = 1_800_000_000_000; const account = ( diff --git a/tests/provider-config-batch-management.test.ts b/tests/providers/provider-config-batch-management.test.ts similarity index 95% rename from tests/provider-config-batch-management.test.ts rename to tests/providers/provider-config-batch-management.test.ts index 250c1e5afdd..ae3af067f5c 100644 --- a/tests/provider-config-batch-management.test.ts +++ b/tests/providers/provider-config-batch-management.test.ts @@ -2,16 +2,16 @@ import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test"; import { mkdirSync, mkdtempSync, readFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import * as configModule from "../src/config"; -import { getConfigPath, loadConfig, saveConfig } from "../src/config"; -import * as destinationPolicy from "../src/lib/destination-policy"; -import { safeConfigDTO } from "../src/server/auth-cors"; -import { handleManagementAPI } from "../src/server/management-api"; -import type { OcxConfig } from "../src/types"; -import { catalogConvergenceFactory } from "./helpers/catalog-convergence"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { ManagementRequest as Request } from "./helpers/management-auth"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import * as configModule from "../../src/config"; +import { getConfigPath, loadConfig, saveConfig } from "../../src/config"; +import * as destinationPolicy from "../../src/lib/destination-policy"; +import { safeConfigDTO } from "../../src/server/auth-cors"; +import { handleManagementAPI } from "../../src/server/management-api"; +import type { OcxConfig } from "../../src/types"; +import { catalogConvergenceFactory } from "../helpers/catalog-convergence"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import { ManagementRequest as Request } from "../helpers/management-auth"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; type EditorConfig = { defaultProvider: string; diff --git a/tests/provider-config-validation.test.ts b/tests/providers/provider-config-validation.test.ts similarity index 99% rename from tests/provider-config-validation.test.ts rename to tests/providers/provider-config-validation.test.ts index 73238884e4b..fc3a2808cac 100644 --- a/tests/provider-config-validation.test.ts +++ b/tests/providers/provider-config-validation.test.ts @@ -12,7 +12,7 @@ import { providerHeadersConfigError, reasoningSummaryDeliveryRecordConfigError, upstreamHttpVersionConfigError, -} from "../src/config/provider-validation"; +} from "../../src/config/provider-validation"; describe("provider config validation leaf", () => { test("accepts only credential-free HTTP(S) base URLs", () => { diff --git a/tests/provider-connection-test.test.ts b/tests/providers/provider-connection-test.test.ts similarity index 96% rename from tests/provider-connection-test.test.ts rename to tests/providers/provider-connection-test.test.ts index 892b45bef41..aefcad49c92 100644 --- a/tests/provider-connection-test.test.ts +++ b/tests/providers/provider-connection-test.test.ts @@ -2,15 +2,15 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync} from "node:fs"; import { join } from "node:path"; import { tmpdir } from "node:os"; -import { setFetchCursorUsableModelsForTests } from "../src/adapters/cursor/live-models"; -import { handleManagementAPI } from "../src/server/management-api"; -import { saveConfig } from "../src/config"; -import { OAUTH_PROVIDERS } from "../src/oauth"; -import { saveCredential } from "../src/oauth/store"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import type { OcxConfig } from "../src/types"; -import { withRegistryDiscovery } from "./helpers/provider-registry-discovery"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { setFetchCursorUsableModelsForTests } from "../../src/adapters/cursor/live-models"; +import { handleManagementAPI } from "../../src/server/management-api"; +import { saveConfig } from "../../src/config"; +import { OAUTH_PROVIDERS } from "../../src/oauth"; +import { saveCredential } from "../../src/oauth/store"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import type { OcxConfig } from "../../src/types"; +import { withRegistryDiscovery } from "../helpers/provider-registry-discovery"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const TEST_DIR = join(tmpdir(), "ocx-conn-test"); const previousHome = process.env.OPENCODEX_HOME; @@ -411,4 +411,4 @@ describe("POST /api/oauth/login/cancel (WP040)", () => { expect(ok.body).toEqual({ ok: true, cancelled: false }); }); }); -import { ManagementRequest as Request } from "./helpers/management-auth"; +import { ManagementRequest as Request } from "../helpers/management-auth"; diff --git a/tests/provider-cost-overlay-config.test.ts b/tests/providers/provider-cost-overlay-config.test.ts similarity index 98% rename from tests/provider-cost-overlay-config.test.ts rename to tests/providers/provider-cost-overlay-config.test.ts index eb721ee07f7..011e74c0141 100644 --- a/tests/provider-cost-overlay-config.test.ts +++ b/tests/providers/provider-cost-overlay-config.test.ts @@ -8,11 +8,11 @@ import { providerModelCostsConfigError, saveConfig, validateConfigCandidate, -} from "../src/config"; -import { providerManagementConfigError, safeConfigDTO } from "../src/server/auth-cors"; -import { activeUserCostOverlays, refreshUserCostOverlays, userCostOverlayVersion } from "../src/usage/user-cost-overlays"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/config"; +import { providerManagementConfigError, safeConfigDTO } from "../../src/server/auth-cors"; +import { activeUserCostOverlays, refreshUserCostOverlays, userCostOverlayVersion } from "../../src/usage/user-cost-overlays"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const VALID_COSTS = { "deepseek-v4-flash": { input: 0.14, output: 0.28, cacheRead: 0.0028, cacheWrite: 0 }, diff --git a/tests/provider-discovery-log-suppression.test.ts b/tests/providers/provider-discovery-log-suppression.test.ts similarity index 98% rename from tests/provider-discovery-log-suppression.test.ts rename to tests/providers/provider-discovery-log-suppression.test.ts index ad803a4a343..b9d69729e39 100644 --- a/tests/provider-discovery-log-suppression.test.ts +++ b/tests/providers/provider-discovery-log-suppression.test.ts @@ -4,7 +4,7 @@ import { markProviderDiscoveryFailed, markProviderDiscoveryOk, shouldLogDiscoveryFailure, -} from "../src/codex/model-cache"; +} from "../../src/codex/model-cache"; const P = "azure-foundry-anthropic"; diff --git a/tests/provider-id-rewrite.test.ts b/tests/providers/provider-id-rewrite.test.ts similarity index 97% rename from tests/provider-id-rewrite.test.ts rename to tests/providers/provider-id-rewrite.test.ts index 5c6fc5a8b09..1df8753b82e 100644 --- a/tests/provider-id-rewrite.test.ts +++ b/tests/providers/provider-id-rewrite.test.ts @@ -1,8 +1,8 @@ import { expect, test } from "bun:test"; -import { comboConfigError } from "../src/combos"; -import { providerContextCap } from "../src/providers/context-cap"; -import { dropProviderCustomModels, rewriteProviderReferences } from "../src/providers/provider-id-rewrite"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { comboConfigError } from "../../src/combos"; +import { providerContextCap } from "../../src/providers/context-cap"; +import { dropProviderCustomModels, rewriteProviderReferences } from "../../src/providers/provider-id-rewrite"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; const FROM = "alibaba-token-plan"; const TO = "alibaba-token-plan-intl"; diff --git a/tests/provider-key-store.test.ts b/tests/providers/provider-key-store.test.ts similarity index 94% rename from tests/provider-key-store.test.ts rename to tests/providers/provider-key-store.test.ts index 94fe8e313fe..645920e32c0 100644 --- a/tests/provider-key-store.test.ts +++ b/tests/providers/provider-key-store.test.ts @@ -2,8 +2,8 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { mkdtempSync, readFileSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { loadConfig, saveConfig } from "../src/config"; -import { maskApiKey } from "../src/providers/api-keys"; +import { loadConfig, saveConfig } from "../../src/config"; +import { maskApiKey } from "../../src/providers/api-keys"; import { PROVIDER_KEYCHAIN_SERVICE, probeProviderKeychain, @@ -13,13 +13,13 @@ import { setProviderKeychainEntryFactoryForTests, storeProviderKeyInKeychain, type ProviderKeychainEntry, -} from "../src/providers/key-store"; -import { routedProviderConfig } from "../src/router"; -import { managementFetch as fetch } from "./helpers/management-auth"; -import { startServer } from "../src/server"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../src/providers/key-store"; +import { routedProviderConfig } from "../../src/router"; +import { managementFetch as fetch } from "../helpers/management-auth"; +import { startServer } from "../../src/server"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../helpers/isolated-codex-home"; +import type { OcxConfig } from "../../src/types"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; /** In-memory keychain: service/account → secret, with optional fault injection. */ function fakeKeychain(options: { unavailable?: boolean; readBackMismatch?: boolean } = {}) { diff --git a/tests/provider-live-models.test.ts b/tests/providers/provider-live-models.test.ts similarity index 98% rename from tests/provider-live-models.test.ts rename to tests/providers/provider-live-models.test.ts index d3958e86060..ea7b8249a0a 100644 --- a/tests/provider-live-models.test.ts +++ b/tests/providers/provider-live-models.test.ts @@ -1,7 +1,7 @@ import { afterEach, describe, expect, spyOn, test } from "bun:test"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; // Phase 2 of devlog/model_update/260709_model_refresh: live /models discovery is the // authoritative lineup; static config lists are the fallback seed. These tests pin the diff --git a/tests/provider-model-aliases.test.ts b/tests/providers/provider-model-aliases.test.ts similarity index 94% rename from tests/provider-model-aliases.test.ts rename to tests/providers/provider-model-aliases.test.ts index dda94842a84..4ecc4198e1a 100644 --- a/tests/provider-model-aliases.test.ts +++ b/tests/providers/provider-model-aliases.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { effectiveModelAliases } from "../src/providers/default-aliases"; -import { routeModel } from "../src/router"; -import type { OcxConfig } from "../src/types"; +import { effectiveModelAliases } from "../../src/providers/default-aliases"; +import { routeModel } from "../../src/router"; +import type { OcxConfig } from "../../src/types"; function config(): OcxConfig { return { diff --git a/tests/provider-model-discovery-contract.test.ts b/tests/providers/provider-model-discovery-contract.test.ts similarity index 96% rename from tests/provider-model-discovery-contract.test.ts rename to tests/providers/provider-model-discovery-contract.test.ts index a78977d1615..a4a5d6ec435 100644 --- a/tests/provider-model-discovery-contract.test.ts +++ b/tests/providers/provider-model-discovery-contract.test.ts @@ -1,30 +1,31 @@ import { afterEach, describe, expect, spyOn, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { catalogHintsFromModelsApiItem } from "../src/codex/catalog/provider-fetch"; -import { clearModelCache, getFreshCached, setCached } from "../src/codex/model-cache"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; -import { deriveKeyLoginMap, providerConfigSeed } from "../src/providers/derive"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { catalogHintsFromModelsApiItem } from "../../src/codex/catalog/provider-fetch"; +import { clearModelCache, getFreshCached, setCached } from "../../src/codex/model-cache"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; +import { deriveKeyLoginMap, providerConfigSeed } from "../../src/providers/derive"; import { extractProviderModelItems, providerModelDiscoverySpecError, readBoundedDiscoveryJson, resolveProviderModelDiscovery, resolveProviderModelDiscoveryUrl, -} from "../src/providers/model-discovery"; +} from "../../src/providers/model-discovery"; import { PROVIDER_REGISTRY, registryEntryForProviderDestination, type ProviderModelDiscoverySpec, -} from "../src/providers/registry"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; -import { withRegistryDiscovery } from "./helpers/provider-registry-discovery"; - -const FIXTURE = readFileSync(join(import.meta.dir, "fixtures/provider-model-discovery.json"), "utf8"); +} from "../../src/providers/registry"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { withRegistryDiscovery } from "../helpers/provider-registry-discovery"; +import { fixturePath } from "../helpers/repo-root"; + +const FIXTURE = readFileSync(fixturePath("provider-model-discovery.json"), "utf8"); const originalFetch = globalThis.fetch; afterEach(() => { diff --git a/tests/provider-outbound-private-network.test.ts b/tests/providers/provider-outbound-private-network.test.ts similarity index 97% rename from tests/provider-outbound-private-network.test.ts rename to tests/providers/provider-outbound-private-network.test.ts index 3c17d307b3f..54e3f46eaf6 100644 --- a/tests/provider-outbound-private-network.test.ts +++ b/tests/providers/provider-outbound-private-network.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { providerOutboundGet, ProviderOutboundPolicyError } from "../src/lib/provider-outbound"; -import { resolvePublicAddresses } from "../src/lib/destination-policy"; +import { providerOutboundGet, ProviderOutboundPolicyError } from "../../src/lib/provider-outbound"; +import { resolvePublicAddresses } from "../../src/lib/destination-policy"; /** * #758: a stock Ollama provider passed config validation -- which consults the registry's diff --git a/tests/provider-outbound.test.ts b/tests/providers/provider-outbound.test.ts similarity index 94% rename from tests/provider-outbound.test.ts rename to tests/providers/provider-outbound.test.ts index d7d9bd16310..5cf7d60039d 100644 --- a/tests/provider-outbound.test.ts +++ b/tests/providers/provider-outbound.test.ts @@ -2,9 +2,9 @@ import { afterEach, describe, expect, mock, test } from "bun:test"; import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import type { ProviderOutboundDependencies } from "../src/lib/provider-outbound"; -import { PROXY_ENV_KEYS } from "../src/lib/proxy-env"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import type { ProviderOutboundDependencies } from "../../src/lib/provider-outbound"; +import { PROXY_ENV_KEYS } from "../../src/lib/proxy-env"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; const proxyKeys = PROXY_ENV_KEYS.flatMap(key => [key, key.toLowerCase()]); const originalProxyEnv = Object.fromEntries(proxyKeys.map(key => [key, process.env[key]])); @@ -54,7 +54,7 @@ function directDependencies( describe("provider outbound GET transport", () => { test("direct HTTPS connects only to the validated address with TLS verification", async () => { for (const key of proxyKeys) delete process.env[key]; - const { providerOutboundGet } = await import("../src/lib/provider-outbound"); + const { providerOutboundGet } = await import("../../src/lib/provider-outbound"); const { dependencies, captured } = directDependencies(new Response('{"data":[]}', { status: 200, headers: { "content-type": "application/json" }, @@ -82,7 +82,7 @@ describe("provider outbound GET transport", () => { process.env.https_proxy = proxyUrl; process.env.NO_PROXY = "localhost,127.0.0.1,::1,[::1]"; process.env.no_proxy = "localhost,127.0.0.1,::1,[::1]"; - const { providerOutboundGet } = await import("../src/lib/provider-outbound"); + const { providerOutboundGet } = await import("../../src/lib/provider-outbound"); const { dependencies, captured } = directDependencies(new Response(null, { status: 200 }), { privateNetwork: true, address: "192.168.1.50", @@ -115,7 +115,7 @@ describe("provider outbound GET transport", () => { }) as typeof fetch; globalThis.fetch = fetchMock; try { - const { providerOutboundGet } = await import("../src/lib/provider-outbound"); + const { providerOutboundGet } = await import("../../src/lib/provider-outbound"); const resolveOptions: { allowBenchmarkAddresses?: boolean }[] = []; const { dependencies, captured } = directDependencies(new Response(null, { status: 500 })); const innerResolve = dependencies.resolveAddresses!; @@ -151,7 +151,7 @@ describe("provider outbound GET transport", () => { test("Clash fake-IP without a configured proxy is not granted the benchmark opt-in (#1748)", async () => { for (const key of proxyKeys) delete process.env[key]; - const { providerOutboundGet } = await import("../src/lib/provider-outbound"); + const { providerOutboundGet } = await import("../../src/lib/provider-outbound"); const resolveOptions: { allowBenchmarkAddresses?: boolean }[] = []; const { dependencies, captured } = directDependencies(new Response(null, { status: 500 })); dependencies.resolveAddresses = mock(async (_url: string, options?: { allowBenchmarkAddresses?: boolean }) => { @@ -181,7 +181,7 @@ describe("provider outbound GET transport", () => { const fetchMock = mock(async () => new Response("unexpected", { status: 500 })) as typeof fetch; globalThis.fetch = fetchMock; try { - const { providerOutboundGet } = await import("../src/lib/provider-outbound"); + const { providerOutboundGet } = await import("../../src/lib/provider-outbound"); const resolveOptions: { allowBenchmarkAddresses?: boolean }[] = []; const { dependencies, captured } = directDependencies(new Response(null, { status: 500 })); dependencies.resolveAddresses = mock(async (_url: string, options?: { allowBenchmarkAddresses?: boolean }) => { @@ -207,7 +207,7 @@ describe("provider outbound GET transport", () => { test("built-in ollama admits loopback discovery without an explicit allowPrivateNetwork flag (#758)", async () => { for (const key of proxyKeys) delete process.env[key]; - const { providerOutboundGet } = await import("../src/lib/provider-outbound"); + const { providerOutboundGet } = await import("../../src/lib/provider-outbound"); let sawAllowPrivate: boolean | undefined; const dependencies: ProviderOutboundDependencies = { resolveAddresses: mock(async (_url, options) => { @@ -240,7 +240,7 @@ describe("provider outbound GET transport", () => { const redirectTarget = new URL("https://final.example/v1/models?token=secret#fragment"); redirectTarget.username = "user"; redirectTarget.password = "password"; - const { providerOutboundGet, providerRedirectError } = await import("../src/lib/provider-outbound"); + const { providerOutboundGet, providerRedirectError } = await import("../../src/lib/provider-outbound"); const { dependencies } = directDependencies(new Response(null, { status: 302, headers: { location: redirectTarget.toString() }, @@ -275,7 +275,7 @@ describe("provider outbound GET transport", () => { baseUrl: "https://override.example/v1", fetch: override, } as { baseUrl: string; fetch: typeof fetch }; - const { providerOutboundGet } = await import("../src/lib/provider-outbound"); + const { providerOutboundGet } = await import("../../src/lib/provider-outbound"); const response = await providerOutboundGet( "override", @@ -357,7 +357,7 @@ describe("provider outbound GET transport", () => { describe("provider outbound POST transport", () => { test("direct HTTPS posts only to the validated address with its credential and body", async () => { for (const key of proxyKeys) delete process.env[key]; - const { providerOutboundPost } = await import("../src/lib/provider-outbound"); + const { providerOutboundPost } = await import("../../src/lib/provider-outbound"); const { dependencies, captured } = directDependencies(new Response('{"models":{}}', { status: 200, headers: { "content-type": "application/json" }, @@ -382,7 +382,7 @@ describe("provider outbound POST transport", () => { }); test("blocks an unsafe POST destination before invoking a caller-owned executor", async () => { - const { providerOutboundPost, ProviderOutboundPolicyError } = await import("../src/lib/provider-outbound"); + const { providerOutboundPost, ProviderOutboundPolicyError } = await import("../../src/lib/provider-outbound"); let calls = 0; const provider = { baseUrl: "https://provider.example", @@ -402,7 +402,7 @@ describe("provider outbound POST transport", () => { }); test("requires HTTPS before invoking a caller-owned executor", async () => { - const { providerOutboundPost, ProviderOutboundPolicyError } = await import("../src/lib/provider-outbound"); + const { providerOutboundPost, ProviderOutboundPolicyError } = await import("../../src/lib/provider-outbound"); let calls = 0; const provider = { baseUrl: "https://provider.example", diff --git a/tests/provider-quota-observed-marker.test.ts b/tests/providers/provider-quota-observed-marker.test.ts similarity index 93% rename from tests/provider-quota-observed-marker.test.ts rename to tests/providers/provider-quota-observed-marker.test.ts index 4925acfebfe..d9c36bedf86 100644 --- a/tests/provider-quota-observed-marker.test.ts +++ b/tests/providers/provider-quota-observed-marker.test.ts @@ -12,16 +12,16 @@ import { afterEach, beforeEach, expect, test } from "bun:test"; import { mkdtempSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveCredential } from "../src/oauth/store"; +import { saveCredential } from "../../src/oauth/store"; import { clearAccountQuotaCache, clearProviderQuotaCache, fetchProviderQuotaReports, recordPassiveAccountQuota, -} from "../src/providers/quota"; -import { captureConfigGeneration } from "../src/lib/state-store-sweeper"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; -import type { OcxConfig } from "../src/types"; +} from "../../src/providers/quota"; +import { captureConfigGeneration } from "../../src/lib/state-store-sweeper"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; +import type { OcxConfig } from "../../src/types"; const originalHome = process.env.OPENCODEX_HOME; const originalFetch = globalThis.fetch; @@ -71,7 +71,7 @@ async function seedObservation(ageMs: number): Promise { accountId: "muse-account", email: "muse@example.test", }); - const { getAccountSet } = await import("../src/oauth/store"); + const { getAccountSet } = await import("../../src/oauth/store"); const accountId = getAccountSet("meta-muse")!.accounts[0]!.id; recordPassiveAccountQuota("meta-muse", accountId, { fiveHourPercent: 1, diff --git a/tests/provider-quota.test.ts b/tests/providers/provider-quota.test.ts similarity index 99% rename from tests/provider-quota.test.ts rename to tests/providers/provider-quota.test.ts index 4c659df5b8b..582b03b4570 100644 --- a/tests/provider-quota.test.ts +++ b/tests/providers/provider-quota.test.ts @@ -1,15 +1,15 @@ import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test"; import { existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { removeTreeWithRetry } from "../helpers/remove-tree"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import * as authApi from "../src/codex/auth-api"; -import { clearAccountNeedsReauth, markAccountNeedsReauth } from "../src/codex/account-runtime-state"; -import { clearMainAccountInfoCache } from "../src/codex/main-account-cache"; -import { clearAccountQuota, updateAccountQuota } from "../src/codex/quota"; -import { clearCodexUpstreamHealth } from "../src/codex/routing"; -import { saveCodexAccountCredential } from "../src/codex/account-store"; -import { saveCredential } from "../src/oauth/store"; +import * as authApi from "../../src/codex/auth-api"; +import { clearAccountNeedsReauth, markAccountNeedsReauth } from "../../src/codex/account-runtime-state"; +import { clearMainAccountInfoCache } from "../../src/codex/main-account-cache"; +import { clearAccountQuota, updateAccountQuota } from "../../src/codex/quota"; +import { clearCodexUpstreamHealth } from "../../src/codex/routing"; +import { saveCodexAccountCredential } from "../../src/codex/account-store"; +import { saveCredential } from "../../src/oauth/store"; import { clearProviderQuotaCache, fetchProviderQuotaReports, @@ -17,8 +17,9 @@ import { QUOTA_RESPONSE_MAX_BYTES, readProviderQuotaJsonForTests, setProviderQuotaBeforePublishForTests, -} from "../src/providers/quota"; -import type { OcxConfig } from "../src/types"; +} from "../../src/providers/quota"; +import type { OcxConfig } from "../../src/types"; +import { repoPath } from "../helpers/repo-root"; const originalFetch = globalThis.fetch; const previousOpencodexHome = process.env.OPENCODEX_HOME; const previousCodexHome = process.env.CODEX_HOME; @@ -101,7 +102,7 @@ afterEach(() => { describe("fetchProviderQuotaReports", () => { test("provider quota probes have no direct Response.json calls", () => { - const source = readFileSync(join(import.meta.dir, "../src/providers/quota.ts"), "utf8"); + const source = readFileSync(repoPath("src/providers/quota.ts"), "utf8"); expect(source).not.toMatch(/\.\s*json\s*\(/); }); diff --git a/tests/provider-registry-parity.test.ts b/tests/providers/provider-registry-parity.test.ts similarity index 98% rename from tests/provider-registry-parity.test.ts rename to tests/providers/provider-registry-parity.test.ts index 2ed9856cd60..ecfb66e88ea 100644 --- a/tests/provider-registry-parity.test.ts +++ b/tests/providers/provider-registry-parity.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from "bun:test"; -import { buildCatalogEntries } from "../src/codex/catalog"; -import { CURSOR_NO_VISION_MODELS } from "../src/adapters/cursor/discovery"; -import { getModelMetadata, resolveMetadataProvider } from "../src/generated/model-metadata"; -import { buildInitProviders } from "../src/cli/init"; -import { OAUTH_PROVIDERS } from "../src/oauth"; -import { enrichProviderFromCatalog, KEY_LOGIN_PROVIDERS } from "../src/oauth/key-providers"; +import { buildCatalogEntries } from "../../src/codex/catalog"; +import { CURSOR_NO_VISION_MODELS } from "../../src/adapters/cursor/discovery"; +import { getModelMetadata, resolveMetadataProvider } from "../../src/generated/model-metadata"; +import { buildInitProviders } from "../../src/cli/init"; +import { OAUTH_PROVIDERS } from "../../src/oauth"; +import { enrichProviderFromCatalog, KEY_LOGIN_PROVIDERS } from "../../src/oauth/key-providers"; import { deriveFeaturedProviderIds, deriveInitProviders, @@ -12,13 +12,13 @@ import { deriveKeyLoginMap, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { FREE_PROVIDER_DIRECTORY } from "../src/providers/free-directory"; -import { applyProviderConfigHints } from "../src/codex/catalog"; -import { routeModel } from "../src/router"; -import { resolveAdapter } from "../src/server"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +} from "../../src/providers/derive"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { FREE_PROVIDER_DIRECTORY } from "../../src/providers/free-directory"; +import { applyProviderConfigHints } from "../../src/codex/catalog"; +import { routeModel } from "../../src/router"; +import { resolveAdapter } from "../../src/server"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; function nativeTemplate(): Record { return { @@ -603,7 +603,7 @@ describe("provider registry parity", () => { }); test("freeTier propagates through config seed, enrich backfill, and presets without overwriting user config", async () => { - const { enrichProviderFromRegistry } = await import("../src/providers/derive"); + const { enrichProviderFromRegistry } = await import("../../src/providers/derive"); const nvidia = PROVIDER_REGISTRY.find(entry => entry.id === "nvidia")!; // Seed propagation. diff --git a/tests/provider-static-model-discovery.test.ts b/tests/providers/provider-static-model-discovery.test.ts similarity index 94% rename from tests/provider-static-model-discovery.test.ts rename to tests/providers/provider-static-model-discovery.test.ts index 01cc31b8837..88006aaf3ea 100644 --- a/tests/provider-static-model-discovery.test.ts +++ b/tests/providers/provider-static-model-discovery.test.ts @@ -1,14 +1,14 @@ import { describe, expect, test } from "bun:test"; -import { createMimoFreeAdapter, MIMO_CHAT_URL } from "../src/adapters/mimo-free"; -import { enrichProviderFromRegistry, providerConfigSeed } from "../src/providers/derive"; -import { getProviderRegistryEntry } from "../src/providers/registry"; +import { createMimoFreeAdapter, MIMO_CHAT_URL } from "../../src/adapters/mimo-free"; +import { enrichProviderFromRegistry, providerConfigSeed } from "../../src/providers/derive"; +import { getProviderRegistryEntry } from "../../src/providers/registry"; import { providerMatchesRegistryTransportWithStaticGuards, providerSupportsLiveModelDiscovery, registryEntrySupportsLiveModelDiscovery, -} from "../src/providers/static-model-discovery"; -import { routedProviderConfig } from "../src/router"; -import type { OcxProviderConfig } from "../src/types"; +} from "../../src/providers/static-model-discovery"; +import { routedProviderConfig } from "../../src/router"; +import type { OcxProviderConfig } from "../../src/types"; function provider(overrides: Partial): OcxProviderConfig { return { diff --git a/tests/qwen38-preserve-reasoning.test.ts b/tests/providers/qwen38-preserve-reasoning.test.ts similarity index 94% rename from tests/qwen38-preserve-reasoning.test.ts rename to tests/providers/qwen38-preserve-reasoning.test.ts index a14d1d7513d..237e681cd63 100644 --- a/tests/qwen38-preserve-reasoning.test.ts +++ b/tests/providers/qwen38-preserve-reasoning.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import type { OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import type { OcxParsedRequest, OcxProviderConfig } from "../../src/types"; function provider(overrides: Partial = {}): OcxProviderConfig { return { @@ -103,7 +103,7 @@ describe("Qwen 3.8 reasoning_content preservation", () => { }); test("registry includes qwen3.8-max in alibaba-token-plan preserveReasoningContentModels", async () => { - const { PROVIDER_REGISTRY } = await import("../src/providers/registry"); + const { PROVIDER_REGISTRY } = await import("../../src/providers/registry"); const alibaba = PROVIDER_REGISTRY.find(e => e.id === "alibaba-token-plan"); expect(alibaba).toBeDefined(); expect(alibaba!.preserveReasoningContentModels).toContain("qwen3.8-max"); diff --git a/tests/rate-limit-retry.test.ts b/tests/providers/rate-limit-retry.test.ts similarity index 98% rename from tests/rate-limit-retry.test.ts rename to tests/providers/rate-limit-retry.test.ts index 244d244f178..709ccdae128 100644 --- a/tests/rate-limit-retry.test.ts +++ b/tests/providers/rate-limit-retry.test.ts @@ -2,9 +2,9 @@ import { afterEach, describe, expect, test } from "bun:test"; import { rateLimitRetryDelayMs, rateLimitRetryPolicyFor, -} from "../src/providers/key-failover"; -import { handleResponses } from "../src/server/responses"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +} from "../../src/providers/key-failover"; +import { handleResponses } from "../../src/server/responses"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; describe("rateLimitRetryPolicyFor", () => { test("null when absent or explicitly disabled", () => { diff --git a/tests/sambanova-nebius-provider.test.ts b/tests/providers/sambanova-nebius-provider.test.ts similarity index 92% rename from tests/sambanova-nebius-provider.test.ts rename to tests/providers/sambanova-nebius-provider.test.ts index 9313daf9e5c..2aa3892d760 100644 --- a/tests/sambanova-nebius-provider.test.ts +++ b/tests/providers/sambanova-nebius-provider.test.ts @@ -1,27 +1,28 @@ import { afterEach, describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { gatherRoutedModels } from "../src/codex/catalog"; -import { clearModelCache } from "../src/codex/model-cache"; -import { buildInitProviders } from "../src/cli/init"; -import { buildModelsRequest } from "../src/oauth"; -import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../src/oauth/key-providers"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { gatherRoutedModels } from "../../src/codex/catalog"; +import { clearModelCache } from "../../src/codex/model-cache"; +import { buildInitProviders } from "../../src/cli/init"; +import { buildModelsRequest } from "../../src/oauth"; +import { KEY_LOGIN_PROVIDERS, validateApiKey } from "../../src/oauth/key-providers"; import { deriveInitProviders, deriveProviderPresets, providerConfigSeed, -} from "../src/providers/derive"; -import { FREE_PROVIDER_DIRECTORY } from "../src/providers/free-directory"; -import { resolveProviderModelDiscovery } from "../src/providers/model-discovery"; -import { PROVIDER_REGISTRY, type ProviderRegistryEntry } from "../src/providers/registry"; -import { routedSlug } from "../src/providers/slug-codec"; -import { routeModel } from "../src/router"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; -import { withStubbedProviderFetch } from "./helpers/catalog-provider-fetch"; +} from "../../src/providers/derive"; +import { FREE_PROVIDER_DIRECTORY } from "../../src/providers/free-directory"; +import { resolveProviderModelDiscovery } from "../../src/providers/model-discovery"; +import { PROVIDER_REGISTRY, type ProviderRegistryEntry } from "../../src/providers/registry"; +import { routedSlug } from "../../src/providers/slug-codec"; +import { routeModel } from "../../src/router"; +import type { OcxConfig, OcxProviderConfig } from "../../src/types"; +import { withStubbedProviderFetch } from "../helpers/catalog-provider-fetch"; +import { fixturePath } from "../helpers/repo-root"; -const SAMBANOVA_FIXTURE = readFileSync(join(import.meta.dir, "fixtures/sambanova-models.json"), "utf8"); -const NEBIUS_FIXTURE = readFileSync(join(import.meta.dir, "fixtures/nebius-models.json"), "utf8"); +const SAMBANOVA_FIXTURE = readFileSync(fixturePath("sambanova-models.json"), "utf8"); +const NEBIUS_FIXTURE = readFileSync(fixturePath("nebius-models.json"), "utf8"); const originalFetch = globalThis.fetch; type ProviderId = "sambanova" | "nebius"; diff --git a/tests/umans-provider.test.ts b/tests/providers/umans-provider.test.ts similarity index 97% rename from tests/umans-provider.test.ts rename to tests/providers/umans-provider.test.ts index 3654177d75d..755b50570a6 100644 --- a/tests/umans-provider.test.ts +++ b/tests/providers/umans-provider.test.ts @@ -1,9 +1,9 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { createAnthropicAdapter as createAnthropicAdapterProduction } from "../src/adapters/anthropic"; -import { providerConfigFromKeyLoginProvider } from "../src/oauth/login-cli"; -import { enrichProviderFromCatalog, KEY_LOGIN_PROVIDERS, validateApiKey, type KeyLoginProvider } from "../src/oauth/key-providers"; -import type { AdapterEvent, OcxParsedRequest, OcxProviderConfig } from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { createAnthropicAdapter as createAnthropicAdapterProduction } from "../../src/adapters/anthropic"; +import { providerConfigFromKeyLoginProvider } from "../../src/oauth/login-cli"; +import { enrichProviderFromCatalog, KEY_LOGIN_PROVIDERS, validateApiKey, type KeyLoginProvider } from "../../src/oauth/key-providers"; +import type { AdapterEvent, OcxParsedRequest, OcxProviderConfig } from "../../src/types"; +import { withTestTranslatorBudget } from "../helpers/translator-budget"; const createAnthropicAdapter = (...args: Parameters) => withTestTranslatorBudget(createAnthropicAdapterProduction(...args)); diff --git a/tests/upstream-transient-retry.test.ts b/tests/providers/upstream-transient-retry.test.ts similarity index 98% rename from tests/upstream-transient-retry.test.ts rename to tests/providers/upstream-transient-retry.test.ts index 420060b02ed..58199ac55a9 100644 --- a/tests/upstream-transient-retry.test.ts +++ b/tests/providers/upstream-transient-retry.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { fetchWithTransientRetry, isTransientUpstreamStatus } from "../src/lib/upstream-retry"; -import { transientRetryPolicyFor } from "../src/providers/key-failover"; -import type { OcxProviderConfig } from "../src/types"; +import { fetchWithTransientRetry, isTransientUpstreamStatus } from "../../src/lib/upstream-retry"; +import { transientRetryPolicyFor } from "../../src/providers/key-failover"; +import type { OcxProviderConfig } from "../../src/types"; function bodyResponse(status: number, headers?: Record): Response { // ReadableStream body so cancel() is observable. diff --git a/tests/vercel-gateway-provider-routing.test.ts b/tests/providers/vercel-gateway-provider-routing.test.ts similarity index 96% rename from tests/vercel-gateway-provider-routing.test.ts rename to tests/providers/vercel-gateway-provider-routing.test.ts index d031ba61c97..dbe11aad674 100644 --- a/tests/vercel-gateway-provider-routing.test.ts +++ b/tests/providers/vercel-gateway-provider-routing.test.ts @@ -1,13 +1,13 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter, buildOpenAIChatPassthroughRequest } from "../src/adapters/openai-chat"; +import { createOpenAIChatAdapter, buildOpenAIChatPassthroughRequest } from "../../src/adapters/openai-chat"; import { vercelGatewayRoutingConfigError, vercelGatewayProviderPayload, -} from "../src/providers/vercel-gateway-routing"; -import { fastPolicyForModel } from "../src/providers/service-tier"; -import { routeModel } from "../src/router"; -import { safeConfigDTO, providerManagementConfigError } from "../src/server/auth-cors"; -import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../src/types"; +} from "../../src/providers/vercel-gateway-routing"; +import { fastPolicyForModel } from "../../src/providers/service-tier"; +import { routeModel } from "../../src/router"; +import { safeConfigDTO, providerManagementConfigError } from "../../src/server/auth-cors"; +import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../../src/types"; function provider(baseUrl: string, overrides: Partial = {}): OcxProviderConfig { return { adapter: "openai-chat", baseUrl, apiKey: "test-key", ...overrides }; diff --git a/tests/volcengine-ark-assistant-content.test.ts b/tests/providers/volcengine-ark-assistant-content.test.ts similarity index 98% rename from tests/volcengine-ark-assistant-content.test.ts rename to tests/providers/volcengine-ark-assistant-content.test.ts index 992bb5f35c8..cb48dc2a19a 100644 --- a/tests/volcengine-ark-assistant-content.test.ts +++ b/tests/providers/volcengine-ark-assistant-content.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import type { OcxMessage, OcxParsedRequest, OcxProviderConfig } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import type { OcxMessage, OcxParsedRequest, OcxProviderConfig } from "../../src/types"; /** * #796: Volcengine Ark validates an assistant message's text as a REQUIRED parameter and treats diff --git a/tests/grok-attribution.test.ts b/tests/providers/xai/grok-attribution.test.ts similarity index 88% rename from tests/grok-attribution.test.ts rename to tests/providers/xai/grok-attribution.test.ts index 29281fc59f4..25c43a4e1a1 100644 --- a/tests/grok-attribution.test.ts +++ b/tests/providers/xai/grok-attribution.test.ts @@ -2,11 +2,11 @@ import { expect, test } from "bun:test"; import { mkdirSync, mkdtempSync, readFileSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { buildGrokManagedBlock, injectGrokConfig } from "../src/grok/inject"; -import { handleChatCompletions } from "../src/server/chat-completions"; -import type { RequestLogContext } from "../src/server/request-log"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { buildGrokManagedBlock, injectGrokConfig } from "../../../src/grok/inject"; +import { handleChatCompletions } from "../../../src/server/chat-completions"; +import type { RequestLogContext } from "../../../src/server/request-log"; +import type { OcxConfig } from "../../../src/types"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; /** * D3 activation evidence: the fence stamps `x-opencodex-grok` on every registered diff --git a/tests/grok-config-inject.test.ts b/tests/providers/xai/grok-config-inject.test.ts similarity index 99% rename from tests/grok-config-inject.test.ts rename to tests/providers/xai/grok-config-inject.test.ts index a5f08c66d08..9c6b0d02de4 100644 --- a/tests/grok-config-inject.test.ts +++ b/tests/providers/xai/grok-config-inject.test.ts @@ -2,8 +2,8 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { buildGrokManagedBlock, injectGrokConfig, stripGrokConfig } from "../src/grok/inject"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { buildGrokManagedBlock, injectGrokConfig, stripGrokConfig } from "../../../src/grok/inject"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const BEGIN_MARKER = "# >>> opencodex managed block — do not edit (removed by `ocx stop`) >>>"; const END_MARKER = "# <<< opencodex managed block <<<"; diff --git a/tests/grok-effort-inject.test.ts b/tests/providers/xai/grok-effort-inject.test.ts similarity index 96% rename from tests/grok-effort-inject.test.ts rename to tests/providers/xai/grok-effort-inject.test.ts index 680e1fe2683..179bfc5dae8 100644 --- a/tests/grok-effort-inject.test.ts +++ b/tests/providers/xai/grok-effort-inject.test.ts @@ -6,19 +6,19 @@ import { nativeDefaultReasoningEffort, nativeReasoningEfforts, type CatalogModel, -} from "../src/codex/catalog"; +} from "../../../src/codex/catalog"; import { resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests, -} from "../src/codex/model-entitlements"; -import { buildGrokManagedBlock, injectGrokConfig, type GrokInjectModel } from "../src/grok/inject"; -import { grokDefaultReasoningEffort, sanitizeGrokReasoningEfforts } from "../src/grok/effort"; -import { buildGrokInjectModels } from "../src/grok/models"; -import { syncGrokConfig } from "../src/grok/sync"; -import { handleManagementAPI } from "../src/server/management-api"; -import type { ManagementApiDeps } from "../src/server/management/context"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/codex/model-entitlements"; +import { buildGrokManagedBlock, injectGrokConfig, type GrokInjectModel } from "../../../src/grok/inject"; +import { grokDefaultReasoningEffort, sanitizeGrokReasoningEfforts } from "../../../src/grok/effort"; +import { buildGrokInjectModels } from "../../../src/grok/models"; +import { syncGrokConfig } from "../../../src/grok/sync"; +import { handleManagementAPI } from "../../../src/server/management-api"; +import type { ManagementApiDeps } from "../../../src/server/management/context"; +import type { OcxConfig } from "../../../src/types"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const NATIVE_SOL = "gpt-5.6-sol"; const ROUTED_WITH_LADDER: CatalogModel = { diff --git a/tests/grok-lifecycle.test.ts b/tests/providers/xai/grok-lifecycle.test.ts similarity index 94% rename from tests/grok-lifecycle.test.ts rename to tests/providers/xai/grok-lifecycle.test.ts index 7166a99dfcd..4ae5564cdeb 100644 --- a/tests/grok-lifecycle.test.ts +++ b/tests/providers/xai/grok-lifecycle.test.ts @@ -1,14 +1,15 @@ import { describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; -import { classifyWindowsServiceStop, installedServiceRespawnRisk, isServiceOwnershipError, ServiceOwnershipError } from "../src/service"; +import { classifyWindowsServiceStop, installedServiceRespawnRisk, isServiceOwnershipError, ServiceOwnershipError } from "../../../src/service"; +import { repoPath } from "../../helpers/repo-root"; -const CLI_SOURCE = readFileSync(join(import.meta.dir, "..", "src", "cli", "index.ts"), "utf8"); -const ENSURE_SOURCE = readFileSync(join(import.meta.dir, "..", "src", "cli", "ensure-desired-integrations.ts"), "utf8"); -const DISPATCH_SOURCE = readFileSync(join(import.meta.dir, "..", "src", "cli", "dispatch.ts"), "utf8"); -const SERVICE_SOURCE = readFileSync(join(import.meta.dir, "..", "src", "service.ts"), "utf8"); -const MANAGEMENT_SOURCE = readFileSync(join(import.meta.dir, "..", "src", "server", "management-api.ts"), "utf8"); -const PROCESS_CONTROL_SOURCE = readFileSync(join(import.meta.dir, "..", "src", "lib", "process-control.ts"), "utf8"); +const CLI_SOURCE = readFileSync(repoPath("src", "cli", "index.ts"), "utf8"); +const ENSURE_SOURCE = readFileSync(repoPath("src", "cli", "ensure-desired-integrations.ts"), "utf8"); +const DISPATCH_SOURCE = readFileSync(repoPath("src", "cli", "dispatch.ts"), "utf8"); +const SERVICE_SOURCE = readFileSync(repoPath("src", "service.ts"), "utf8"); +const MANAGEMENT_SOURCE = readFileSync(repoPath("src", "server", "management-api.ts"), "utf8"); +const PROCESS_CONTROL_SOURCE = readFileSync(repoPath("src", "lib", "process-control.ts"), "utf8"); function sliceFn(source: string, start: string, end: string): string { const from = source.indexOf(start); @@ -175,7 +176,7 @@ describe("Grok fence lifecycle wiring", () => { test("only Task Scheduler earns the respawn wait", () => { const stopFn = sliceFn(CLI_SOURCE, "async function handleStop(", "async function handleUninstall("); - const serviceSource = readFileSync(join(import.meta.dir, "..", "src", "service.ts"), "utf8"); + const serviceSource = readFileSync(repoPath("src", "service.ts"), "utf8"); // schtasks /end leaves the `cmd :loop` wrapper alive to respawn its child (#764). // launchd, systemd and WinSW are down when they report stopped, so charging them a // seven-second poll on every ocx stop would be a regression in ordinary use. @@ -188,8 +189,8 @@ describe("Grok fence lifecycle wiring", () => { test("ocx stop defers shared teardown so a respawn survivor keeps its config", () => { const stopFn = sliceFn(CLI_SOURCE, "async function handleStop(", "async function handleUninstall("); - const apiSource = readFileSync(join(import.meta.dir, "..", "src", "server", "management-api.ts"), "utf8"); - const controlSource = readFileSync(join(import.meta.dir, "..", "src", "lib", "process-control.ts"), "utf8"); + const apiSource = readFileSync(repoPath("src", "server", "management-api.ts"), "utf8"); + const controlSource = readFileSync(repoPath("src", "lib", "process-control.ts"), "utf8"); // POST /api/stop normally restores native Codex and strips the Grok fence itself. If // ocx stop let it, a scheduler wrapper that respawns seconds later would already have // lost its client config, and the parent ownershipBlocked guard could only prevent a @@ -285,9 +286,9 @@ describe("Grok fence lifecycle wiring", () => { // After a parent crashed mid-deferral the service, pid and runtime records can all be // absent while shared client config still points at a proxy that is gone. Installing // over that skips the recovery the receipt exists to trigger (#3008). - const updateSource = readFileSync(join(import.meta.dir, "..", "src", "update", "index.ts"), "utf8"); + const updateSource = readFileSync(repoPath("src", "update", "index.ts"), "utf8"); expect(updateSource).toContain("readPid() || readRuntimePort() || pendingTeardownOutstanding()"); - const launcherSource = readFileSync(join(import.meta.dir, "..", "bin", "ocx.mjs"), "utf8"); + const launcherSource = readFileSync(repoPath("bin", "ocx.mjs"), "utf8"); // The launcher runs under plain Node, so it shares the naming rule as ESM rather than // spelling it out — which is how it ended up watching the retired singleton filename // after receipts moved to one file per claim, silently seeing none of them. @@ -297,11 +298,11 @@ describe("Grok fence lifecycle wiring", () => { // Checked AFTER the stop too: a quarantined receipt lets the stop succeed, so a // pre-stop check alone let the retry install over a teardown that never ran. expect(launcherSource).toContain("teardownOutstanding: hasPendingTeardownIn(readdirSync, configDir())"); - const updateSource2 = readFileSync(join(import.meta.dir, "..", "src", "update", "index.ts"), "utf8"); + const updateSource2 = readFileSync(repoPath("src", "update", "index.ts"), "utf8"); expect(updateSource2).toContain("teardownOutstanding: pendingTeardownOutstanding()"); - const decisionSource = readFileSync(join(import.meta.dir, "..", "src", "update", "stop-decision.mjs"), "utf8"); + const decisionSource = readFileSync(repoPath("src", "update", "stop-decision.mjs"), "utf8"); expect(decisionSource).toContain('if (teardownOutstanding) return { proceed: false, reason: "teardown-outstanding" };'); - const receiptSource = readFileSync(join(import.meta.dir, "..", "src", "config", "pending-teardown.ts"), "utf8"); + const receiptSource = readFileSync(repoPath("src", "config", "pending-teardown.ts"), "utf8"); expect(receiptSource).toContain('from "./pending-teardown-names.mjs"'); expect(receiptSource).toContain("isPendingTeardownFileName(name)"); }); @@ -384,13 +385,13 @@ describe("POST /api/stop teardown", () => { // the route still delegates to it rather than growing a second copy. const handler = sliceFn(MANAGEMENT_SOURCE, '"/api/stop"', "/api/codex-auth/"); expect(handler).toContain("performStopTeardown(url, { ownsReceipt: deferralMatchesReceipt })"); - const teardownSource = readFileSync(join(import.meta.dir, "..", "src", "server", "stop-teardown.ts"), "utf8"); + const teardownSource = readFileSync(repoPath("src", "server", "stop-teardown.ts"), "utf8"); expect(teardownSource).toContain('await import("../grok/inject")'); expect(teardownSource).toContain("stripGrokConfig()"); }); test("an unreadable scheduler state gets the same diagnosis from the CLI and the API", () => { - const serviceSource = readFileSync(join(import.meta.dir, "..", "src", "service.ts"), "utf8"); + const serviceSource = readFileSync(repoPath("src", "service.ts"), "utf8"); // A manager that refused to stop and a query that could not answer are different // problems: reporting the second as "did not stop" sends the operator looking for the // wrong thing, and `ocx stop` was the command the API told them to run (#3008). @@ -483,7 +484,7 @@ describe("POST /api/stop teardown", () => { }); test("direct service stop and uninstall fail when a shared teardown half fails", () => { - const serviceSource = readFileSync(join(import.meta.dir, "..", "src", "service.ts"), "utf8"); + const serviceSource = readFileSync(repoPath("src", "service.ts"), "utf8"); // These paths logged the failure and exited 0, so a script could not tell a complete // teardown from one that left Grok aimed at a stopped proxy. const stopCase = serviceSource.slice( diff --git a/tests/grok-management-api.test.ts b/tests/providers/xai/grok-management-api.test.ts similarity index 95% rename from tests/grok-management-api.test.ts rename to tests/providers/xai/grok-management-api.test.ts index d8038f9cf01..5afe23efc1f 100644 --- a/tests/grok-management-api.test.ts +++ b/tests/providers/xai/grok-management-api.test.ts @@ -1,14 +1,14 @@ import { afterEach, beforeEach, expect, setDefaultTimeout, test } from "bun:test"; -import { managementFetch as fetch } from "./helpers/management-auth"; +import { managementFetch as fetch } from "../../helpers/management-auth"; import { mkdirSync, mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { loadConfig, saveConfig } from "../src/config"; -import { startServer } from "../src/server"; -import type { OcxConfig } from "../src/types"; -import { installIsolatedCodexHome, type IsolatedCodexHome } from "./helpers/isolated-codex-home"; -import { GROK_APPLY_TERMINAL_MS, runGrokApplyFlightForTests, setGrokApplyFlightTestHooks } from "../src/server/management/agent-settings-routes"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { loadConfig, saveConfig } from "../../../src/config"; +import { startServer } from "../../../src/server"; +import type { OcxConfig } from "../../../src/types"; +import { installIsolatedCodexHome, type IsolatedCodexHome } from "../../helpers/isolated-codex-home"; +import { GROK_APPLY_TERMINAL_MS, runGrokApplyFlightForTests, setGrokApplyFlightTestHooks } from "../../../src/server/management/agent-settings-routes"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; // Full-suite Windows load: startServer + management flows often exceed bun's default // 5s per-test budget (same flake class as claude-management-api.test.ts). diff --git a/tests/grok-models-effort-list.test.ts b/tests/providers/xai/grok-models-effort-list.test.ts similarity index 95% rename from tests/grok-models-effort-list.test.ts rename to tests/providers/xai/grok-models-effort-list.test.ts index c64964cef7d..65fb31e9327 100644 --- a/tests/grok-models-effort-list.test.ts +++ b/tests/providers/xai/grok-models-effort-list.test.ts @@ -2,15 +2,15 @@ import { afterEach, beforeEach, describe, expect, setDefaultTimeout, test } from import { mkdtempSync} from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { saveConfig } from "../src/config"; +import { saveConfig } from "../../../src/config"; import { resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests, -} from "../src/codex/model-entitlements"; -import { startServer } from "../src/server"; -import type { OcxConfig } from "../src/types"; -import { SERVER_BUDGET_MS } from "./helpers/test-budget"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/codex/model-entitlements"; +import { startServer } from "../../../src/server"; +import type { OcxConfig } from "../../../src/types"; +import { SERVER_BUDGET_MS } from "../../helpers/test-budget"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; // These cases start a real server and hit /v1/models. Keep the budget at the // server class so a slow runner does not turn a discovery probe into a flake. diff --git a/tests/grok-orphan-adoption.test.ts b/tests/providers/xai/grok-orphan-adoption.test.ts similarity index 99% rename from tests/grok-orphan-adoption.test.ts rename to tests/providers/xai/grok-orphan-adoption.test.ts index c844f007ec6..5017ec3888f 100644 --- a/tests/grok-orphan-adoption.test.ts +++ b/tests/providers/xai/grok-orphan-adoption.test.ts @@ -2,8 +2,8 @@ import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { injectGrokConfig, stripGrokConfig } from "../src/grok/inject"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { injectGrokConfig, stripGrokConfig } from "../../../src/grok/inject"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; /** * #511 — Grok Build reported 200k for every model. diff --git a/tests/grok-selection.test.ts b/tests/providers/xai/grok-selection.test.ts similarity index 94% rename from tests/grok-selection.test.ts rename to tests/providers/xai/grok-selection.test.ts index 6911c54ae68..b0385aab9fe 100644 --- a/tests/grok-selection.test.ts +++ b/tests/providers/xai/grok-selection.test.ts @@ -2,12 +2,12 @@ import { expect, test } from "bun:test"; import { mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { buildGrokManagedBlock, injectGrokConfig } from "../src/grok/inject"; -import { syncGrokConfig } from "../src/grok/sync"; -import { nativeOpenAiContextWindow, visibleNativeSlugs } from "../src/codex/catalog"; -import type { CatalogModel } from "../src/codex/catalog"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { buildGrokManagedBlock, injectGrokConfig } from "../../../src/grok/inject"; +import { syncGrokConfig } from "../../../src/grok/sync"; +import { nativeOpenAiContextWindow, visibleNativeSlugs } from "../../../src/codex/catalog"; +import type { CatalogModel } from "../../../src/codex/catalog"; +import type { OcxConfig } from "../../../src/types"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; /** * Alias-stable exclusion (WP3, audit blocker 3): aliases are allocated over the diff --git a/tests/grok-status.test.ts b/tests/providers/xai/grok-status.test.ts similarity index 96% rename from tests/grok-status.test.ts rename to tests/providers/xai/grok-status.test.ts index 34a039e65c6..355472798dd 100644 --- a/tests/grok-status.test.ts +++ b/tests/providers/xai/grok-status.test.ts @@ -2,9 +2,9 @@ import { describe, expect, test } from "bun:test"; import { mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { injectGrokConfig } from "../src/grok/inject"; -import { grokFenceEndpointDrift, readGrokStatus } from "../src/grok/status"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { injectGrokConfig } from "../../../src/grok/inject"; +import { grokFenceEndpointDrift, readGrokStatus } from "../../../src/grok/status"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; function tempGrokHome(): { root: string; grokHome: string } { const root = mkdtempSync(join(tmpdir(), "ocx-grok-status-")); diff --git a/tests/grok-sync.test.ts b/tests/providers/xai/grok-sync.test.ts similarity index 96% rename from tests/grok-sync.test.ts rename to tests/providers/xai/grok-sync.test.ts index 0b6fadd2af7..af67b4dff6b 100644 --- a/tests/grok-sync.test.ts +++ b/tests/providers/xai/grok-sync.test.ts @@ -2,16 +2,16 @@ import { afterEach, describe, expect, test } from "bun:test"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; -import { injectGrokConfig, type GrokInjectModel } from "../src/grok/inject"; -import { syncGrokConfig } from "../src/grok/sync"; -import { nativeOpenAiContextWindow, nativeOpenAiSlugs, visibleNativeSlugs } from "../src/codex/catalog"; -import type { CatalogModel } from "../src/codex/catalog"; +import { injectGrokConfig, type GrokInjectModel } from "../../../src/grok/inject"; +import { syncGrokConfig } from "../../../src/grok/sync"; +import { nativeOpenAiContextWindow, nativeOpenAiSlugs, visibleNativeSlugs } from "../../../src/codex/catalog"; +import type { CatalogModel } from "../../../src/codex/catalog"; import { resetCodexModelEntitlementCacheForTests, seedCodexModelEntitlementsForTests, -} from "../src/codex/model-entitlements"; -import type { OcxConfig } from "../src/types"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +} from "../../../src/codex/model-entitlements"; +import type { OcxConfig } from "../../../src/types"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const baseConfig = { port: 10100, defaultProvider: "openai", providers: {} } as unknown as OcxConfig; diff --git a/tests/grok-writer-boundary.test.ts b/tests/providers/xai/grok-writer-boundary.test.ts similarity index 96% rename from tests/grok-writer-boundary.test.ts rename to tests/providers/xai/grok-writer-boundary.test.ts index ad70d210ca5..ad1ce21a5b3 100644 --- a/tests/grok-writer-boundary.test.ts +++ b/tests/providers/xai/grok-writer-boundary.test.ts @@ -21,7 +21,7 @@ function* walk(dir: string): Generator { // fileURLToPath, not .pathname: on Windows .pathname keeps a leading slash before the // drive letter (\D:\a\...), which breaks fs calls on CI. -const SRC = fileURLToPath(new URL("../src", import.meta.url)); +const SRC = fileURLToPath(new URL("../../../src", import.meta.url)); test("only src/grok/inject.ts writes a grok config.toml", () => { const writers: string[] = []; diff --git a/tests/xai-oauth-retry.test.ts b/tests/providers/xai/xai-oauth-retry.test.ts similarity index 96% rename from tests/xai-oauth-retry.test.ts rename to tests/providers/xai/xai-oauth-retry.test.ts index 05f4e335a3b..542b594a3c9 100644 --- a/tests/xai-oauth-retry.test.ts +++ b/tests/providers/xai/xai-oauth-retry.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect, test } from "bun:test"; -import { postXaiToken, XaiTokenRequestError } from "../src/oauth/xai"; +import { postXaiToken, XaiTokenRequestError } from "../../../src/oauth/xai"; const original=globalThis.fetch; afterEach(()=>{globalThis.fetch=original;}); function queue(items:Array){let n=0;globalThis.fetch=(async()=>{const x=items[n++]!;if(x instanceof Error)throw x;return x;}) as typeof fetch;return()=>n;} const body={grant_type:"refresh_token",client_id:"client",refresh_token:"secret"}; const ok=()=>new Response(JSON.stringify({access_token:"a",refresh_token:"r",expires_in:3600})); diff --git a/tests/xai-refresh-lock.test.ts b/tests/providers/xai/xai-refresh-lock.test.ts similarity index 96% rename from tests/xai-refresh-lock.test.ts rename to tests/providers/xai/xai-refresh-lock.test.ts index 4b526e62fb5..26144dbf849 100644 --- a/tests/xai-refresh-lock.test.ts +++ b/tests/providers/xai/xai-refresh-lock.test.ts @@ -1,8 +1,8 @@ import { afterEach,beforeEach,describe,expect,test } from "bun:test"; import { mkdirSync,readFileSync,utimesSync,writeFileSync } from "node:fs";import{tmpdir}from"node:os";import{join}from"node:path"; -import { OAUTH_PROVIDERS,OAuthLoginRequiredError,refreshXaiAccountWithLock } from "../src/oauth";import{XaiTokenRequestError}from"../src/oauth/xai"; -import{createOAuthFileLock,createOAuthRefreshIntentLock,getAccountCredential,getAccountSet,getAuthRefreshIntentLockPath,OAuthFileLockError,saveCredential}from"../src/oauth/store"; -import { removeTreeWithRetry } from "./helpers/remove-tree"; +import { OAUTH_PROVIDERS,OAuthLoginRequiredError,refreshXaiAccountWithLock } from "../../../src/oauth";import{XaiTokenRequestError}from"../../../src/oauth/xai"; +import{createOAuthFileLock,createOAuthRefreshIntentLock,getAccountCredential,getAccountSet,getAuthRefreshIntentLockPath,OAuthFileLockError,saveCredential}from"../../../src/oauth/store"; +import { removeTreeWithRetry } from "../../helpers/remove-tree"; const oldHome=process.env.HOME,oldOcx=process.env.OPENCODEX_HOME;let root:string;beforeEach(()=>{root=join(tmpdir(),`xai-lock-${crypto.randomUUID()}`);process.env.HOME=root;process.env.OPENCODEX_HOME=join(root,"ocx");mkdirSync(process.env.OPENCODEX_HOME,{recursive:true});});afterEach(()=>{if(oldHome===undefined)delete process.env.HOME;else process.env.HOME=oldHome;if(oldOcx===undefined)delete process.env.OPENCODEX_HOME;else process.env.OPENCODEX_HOME=oldOcx;removeTreeWithRetry(root);}); async function seed(){await saveCredential("xai",{access:"old",refresh:"rotating",expires:1,accountId:"acct"});return getAccountSet("xai")!.activeAccountId;}function def(c:{n:number},gate?:Promise){return{...OAUTH_PROVIDERS.xai!,refresh:async()=>{c.n++;if(gate)await gate;return{access:"fresh",refresh:"next",expires:Date.now()+3600000}}};} describe("two-lock xAI refresh",()=>{ diff --git a/tests/xai-tool-schema.test.ts b/tests/providers/xai/xai-tool-schema.test.ts similarity index 98% rename from tests/xai-tool-schema.test.ts rename to tests/providers/xai/xai-tool-schema.test.ts index 0937137b754..67edf07154d 100644 --- a/tests/xai-tool-schema.test.ts +++ b/tests/providers/xai/xai-tool-schema.test.ts @@ -1,12 +1,12 @@ import { describe, expect, test } from "bun:test"; import { createOpenAIChatAdapter as createOpenAIChatAdapterProduction, -} from "../src/adapters/openai-chat"; +} from "../../../src/adapters/openai-chat"; import type { OcxParsedRequest, OcxTool, -} from "../src/types"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +} from "../../../src/types"; +import { withTestTranslatorBudget } from "../../helpers/translator-budget"; const createOpenAIChatAdapter = ( ...args: Parameters diff --git a/tests/xai-transport.test.ts b/tests/providers/xai/xai-transport.test.ts similarity index 98% rename from tests/xai-transport.test.ts rename to tests/providers/xai/xai-transport.test.ts index 0de3b6ba68b..5b87d9bad6f 100644 --- a/tests/xai-transport.test.ts +++ b/tests/providers/xai/xai-transport.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { parseRequest } from "../src/responses/parser"; -import { buildModelsRequest } from "../src/oauth"; +import { createOpenAIChatAdapter } from "../../../src/adapters/openai-chat"; +import { parseRequest } from "../../../src/responses/parser"; +import { buildModelsRequest } from "../../../src/oauth"; import { isXaiResponsesDestination, resolveProviderTransport, @@ -9,11 +9,11 @@ import { XAI_CONV_ID_HEADER, XAI_GROK_CLI_BASE_URL, XAI_GROK_CLIENT_VERSION, -} from "../src/providers/xai-transport"; -import { getProviderRegistryEntry } from "../src/providers/registry"; -import { XAI_RESPONSES_OPT_IN_MODELS } from "../src/providers/xai-responses-opt-in"; -import { resolveWireProtocolOverride } from "../src/server/adapter-resolve"; -import type { OcxAssistantMessage, OcxParsedRequest, OcxProviderConfig } from "../src/types"; +} from "../../../src/providers/xai-transport"; +import { getProviderRegistryEntry } from "../../../src/providers/registry"; +import { XAI_RESPONSES_OPT_IN_MODELS } from "../../../src/providers/xai-responses-opt-in"; +import { resolveWireProtocolOverride } from "../../../src/server/adapter-resolve"; +import type { OcxAssistantMessage, OcxParsedRequest, OcxProviderConfig } from "../../../src/types"; const UUID_V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; const OMITTED = [ diff --git a/tests/xai-web-search-compat.test.ts b/tests/providers/xai/xai-web-search-compat.test.ts similarity index 96% rename from tests/xai-web-search-compat.test.ts rename to tests/providers/xai/xai-web-search-compat.test.ts index 6230264a235..67faa1c3f9e 100644 --- a/tests/xai-web-search-compat.test.ts +++ b/tests/providers/xai/xai-web-search-compat.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; -import { createResponsesPassthroughAdapter as createProductionAdapter } from "../src/adapters/openai-responses"; -import { normalizeXaiResponsesWebSearch } from "../src/adapters/xai-web-search"; -import { withTestTranslatorBudget } from "./helpers/translator-budget"; +import { createResponsesPassthroughAdapter as createProductionAdapter } from "../../../src/adapters/openai-responses"; +import { normalizeXaiResponsesWebSearch } from "../../../src/adapters/xai-web-search"; +import { withTestTranslatorBudget } from "../../helpers/translator-budget"; function createXaiAdapter() { return withTestTranslatorBudget(createProductionAdapter({ diff --git a/tests/xai-web-search.test.ts b/tests/providers/xai/xai-web-search.test.ts similarity index 92% rename from tests/xai-web-search.test.ts rename to tests/providers/xai/xai-web-search.test.ts index 41e4a42c90b..b755481a936 100644 --- a/tests/xai-web-search.test.ts +++ b/tests/providers/xai/xai-web-search.test.ts @@ -1,22 +1,22 @@ import { afterEach, describe, expect, mock, test } from "bun:test"; -import * as storeModule from "../src/oauth/store"; +import * as storeModule from "../../../src/oauth/store"; let accountSets: Record; activeAccountId?: string }> = {}; -mock.module("../src/oauth/store", () => ({ +mock.module("../../../src/oauth/store", () => ({ ...storeModule, getAccountSet: (provider: string) => accountSets[provider] ?? null, })); -import * as oauthModule from "../src/oauth"; -mock.module("../src/oauth", () => ({ +import * as oauthModule from "../../../src/oauth"; +mock.module("../../../src/oauth", () => ({ ...oauthModule, getValidAccessToken: async () => "test-token-xyz", })); -import { parseXaiResponsesSSE, validateXaiSearchOptions } from "../src/web-search/xai-executor"; -import { findXaiSidecarProvider, planWebSearch, xaiSearchOptionsFromConfig } from "../src/web-search"; -import { MAX_SIDECAR_RESPONSE_BYTES } from "../src/web-search/parse"; -import { parseRequest } from "../src/responses/parser"; -import type { OcxConfig, OcxProviderConfig } from "../src/types"; +import { parseXaiResponsesSSE, validateXaiSearchOptions } from "../../../src/web-search/xai-executor"; +import { findXaiSidecarProvider, planWebSearch, xaiSearchOptionsFromConfig } from "../../../src/web-search"; +import { MAX_SIDECAR_RESPONSE_BYTES } from "../../../src/web-search/parse"; +import { parseRequest } from "../../../src/responses/parser"; +import type { OcxConfig, OcxProviderConfig } from "../../../src/types"; const routed: OcxProviderConfig = { adapter: "openai-chat", baseUrl: "https://routed.test/v1", apiKey: "k" }; const xaiProvider: OcxProviderConfig = { adapter: "openai-chat", baseUrl: "https://api.x.ai/v1", authMode: "oauth" }; @@ -148,7 +148,7 @@ describe("credential pinning + loop fail-closed (review blockers)", () => { }) as typeof fetch; try { const evil: OcxProviderConfig = { adapter: "openai-chat", baseUrl: "https://api.x.ai.evil/v1", authMode: "oauth" }; - const { runXaiWebSearch } = await import("../src/web-search/xai-executor"); + const { runXaiWebSearch } = await import("../../../src/web-search/xai-executor"); const out = await runXaiWebSearch("q", "xai", evil, { model: "grok-4.6", reasoning: "low", timeoutMs: 5000, describeImages: false }, {}); expect(captured.length).toBeGreaterThanOrEqual(1); for (const url of captured) expect(new URL(url).origin).toBe("https://api.x.ai"); @@ -159,9 +159,9 @@ describe("credential pinning + loop fail-closed (review blockers)", () => { }); }); -import { runWithWebSearch, type WebSearchLoopDeps } from "../src/web-search/loop"; -import { createTestTranslatorBudget } from "./helpers/translator-budget"; -import type { AdapterEvent, ProviderAdapter } from "../src/adapters/base"; +import { runWithWebSearch, type WebSearchLoopDeps } from "../../../src/web-search/loop"; +import { createTestTranslatorBudget } from "../../helpers/translator-budget"; +import type { AdapterEvent, ProviderAdapter } from "../../../src/adapters/base"; describe("loop dispatch: xai arm fails closed without a sidecar (review blocker)", () => { test("missing xaiSidecar yields the invariant error tool-result; forward executor and pool recorder untouched", async () => { diff --git a/tests/zcode-client.test.ts b/tests/providers/zcode-client.test.ts similarity index 97% rename from tests/zcode-client.test.ts rename to tests/providers/zcode-client.test.ts index c287f6b41b8..a8586babb79 100644 --- a/tests/zcode-client.test.ts +++ b/tests/providers/zcode-client.test.ts @@ -11,9 +11,9 @@ import { zcodeHomeDir, type ExportContext, type ZcodeGeneratedConfig, -} from "../src/clients/config-export"; -import type { OcxConfig } from "../src/types"; -import { handleZcodeCommand } from "../src/cli/integrations"; +} from "../../src/clients/config-export"; +import type { OcxConfig } from "../../src/types"; +import { handleZcodeCommand } from "../../src/cli/integrations"; const CONFIG = { port: 10100, diff --git a/tests/zhipu-bigmodel-provider.test.ts b/tests/providers/zhipu-bigmodel-provider.test.ts similarity index 92% rename from tests/zhipu-bigmodel-provider.test.ts rename to tests/providers/zhipu-bigmodel-provider.test.ts index 5cef6dfbbe0..889cf6997d4 100644 --- a/tests/zhipu-bigmodel-provider.test.ts +++ b/tests/providers/zhipu-bigmodel-provider.test.ts @@ -1,11 +1,11 @@ import { describe, expect, test } from "bun:test"; -import { createOpenAIChatAdapter } from "../src/adapters/openai-chat"; -import { KEY_LOGIN_PROVIDERS } from "../src/oauth/key-providers"; -import { deriveJawcodeAliases, deriveProviderPresets } from "../src/providers/derive"; -import { FREE_PROVIDER_DIRECTORY } from "../src/providers/free-directory"; -import { PROVIDER_REGISTRY } from "../src/providers/registry"; -import { routeModel } from "../src/router"; -import type { OcxConfig } from "../src/types"; +import { createOpenAIChatAdapter } from "../../src/adapters/openai-chat"; +import { KEY_LOGIN_PROVIDERS } from "../../src/oauth/key-providers"; +import { deriveJawcodeAliases, deriveProviderPresets } from "../../src/providers/derive"; +import { FREE_PROVIDER_DIRECTORY } from "../../src/providers/free-directory"; +import { PROVIDER_REGISTRY } from "../../src/providers/registry"; +import { routeModel } from "../../src/router"; +import type { OcxConfig } from "../../src/types"; const BASE_URL = "https://open.bigmodel.cn/api/paas/v4"; diff --git a/tests/responses/responses-inbound-store-default.test.ts b/tests/responses/responses-inbound-store-default.test.ts index 0289e5b510b..23bcc6aee10 100644 --- a/tests/responses/responses-inbound-store-default.test.ts +++ b/tests/responses/responses-inbound-store-default.test.ts @@ -12,7 +12,7 @@ * * End-to-end cases assert the captured upstream request body — the externally * observable payload. Pattern mirrors tests/responses/responses-compaction-routing.test.ts - * and tests/github-copilot-wire-defaults.test.ts. + * and tests/providers/github-copilot/github-copilot-wire-defaults.test.ts. */ import { afterEach, describe, expect, test } from "bun:test"; import { CODEX_FORWARD_BASE_URL } from "../../src/providers/openai-tiers"; diff --git a/tests/responses/responses-undeclared-tool-guard.test.ts b/tests/responses/responses-undeclared-tool-guard.test.ts index d9b2b8dc9f4..41d8383a6ce 100644 --- a/tests/responses/responses-undeclared-tool-guard.test.ts +++ b/tests/responses/responses-undeclared-tool-guard.test.ts @@ -917,7 +917,7 @@ describe("empty and absent tool catalogs", () => { ); // A passthrough request may omit `tools` entirely and still receive a tool call the client - // understands — the Copilot contract in tests/github-copilot-stream-contract.test.ts does + // understands — the Copilot contract in tests/providers/github-copilot/github-copilot-stream-contract.test.ts does // exactly that with `apply_patch`. With no catalog the proxy has no authorization boundary to // enforce, so the call remains untouched on both transports. test("non-streaming, no tools field — relayed, not refused", async () => { diff --git a/tests/server-auth.test.ts b/tests/server-auth.test.ts index 37db545e46b..6fd98e29c86 100644 --- a/tests/server-auth.test.ts +++ b/tests/server-auth.test.ts @@ -3435,7 +3435,7 @@ describe("server local API auth", () => { // attacker-controlled bytes back to the client is precisely what #2398 stopped, so the // caller now gets #452's bounded status-only JSON instead of the original prefix // (pinned from the other side by "oversized passthrough errors become bounded - // status-only JSON" in tests/issue-452-empty-503.test.ts). + // status-only JSON" in tests/codex-integration/issue-452-empty-503.test.ts). // // The upstream's own headers still survive, which is what keeps pool-retry diagnostics // honest — that part is still checked below. diff --git a/tests/server-management-auth.test.ts b/tests/server-management-auth.test.ts index c256dede2a2..9b8e4046abb 100644 --- a/tests/server-management-auth.test.ts +++ b/tests/server-management-auth.test.ts @@ -1581,7 +1581,7 @@ describe("management and data-plane credential separation", () => { describe("codex app-server restart routes ride the management gate", () => { // The service itself is unit-tested with injected seams - // (tests/codex-app-server-restart-service.test.ts). These cases exist for one + // (tests/codex-integration/codex-app-server-restart-service.test.ts). These cases exist for one // reason: the route terminates the user's Codex app-servers, so it must be // unreachable without management credentials and from a foreign origin. test("both routes reject an unauthenticated caller and a cross-origin caller", async () => { diff --git a/tests/service/stop-deferred-teardown.test.ts b/tests/service/stop-deferred-teardown.test.ts index 14ba8987d5f..61eadbdc937 100644 --- a/tests/service/stop-deferred-teardown.test.ts +++ b/tests/service/stop-deferred-teardown.test.ts @@ -10,7 +10,7 @@ import { removeTreeWithRetry } from "../helpers/remove-tree"; /** * Behavioural cover for the deferred shared teardown (#3008). * - * The wiring assertions in tests/grok-lifecycle.test.ts read source text, which cannot + * The wiring assertions in tests/providers/xai/grok-lifecycle.test.ts read source text, which cannot * tell a working deferral from a plausible-looking one. These tests call the real * functions: the graceful-stop client that builds the URL, the teardown decision the * route delegates to, and the on-disk receipts that decide whether a deferral is an owned diff --git a/tests/test-layout-tooling.test.ts b/tests/test-layout-tooling.test.ts index acffde06245..dc3ee6bf31a 100644 --- a/tests/test-layout-tooling.test.ts +++ b/tests/test-layout-tooling.test.ts @@ -82,11 +82,15 @@ describe("scanEscapes", () => { 'const c = copyFileSync(join(import.meta.dir, "helpers", "child.ts"), out);', 'const d = join(import.meta.dir, "..");', 'const e = fileURLToPath(new URL("../", import.meta.url));', + 'const f = readFileSync(join(import.meta.dir, "fixtures/x.json"), "utf8");', + 'const g = join(import.meta.dir, "helpers/child.ts");', 'const local = join(import.meta.dir, ".tmp-x");', ].join("\n"); const { source, rewrites } = rewriteMetaDirEscapes(src, 1); - expect(rewrites).toBe(5); - expect(source).toContain('import { helperPath, repoPath, repoRoot } from "../helpers/repo-root";'); + expect(rewrites).toBe(7); + expect(source).toContain('import { fixturePath, helperPath, repoPath, repoRoot } from "../helpers/repo-root";'); + expect(source).toContain('readFileSync(fixturePath("x.json"), "utf8")'); + expect(source).toContain('const g = helperPath("child.ts");'); expect(source).toContain('readFileSync(repoPath("src", "cli", "index.ts"), "utf8")'); expect(source).toContain('repoPath("src/lib/winsw.ts")'); expect(source).toContain('copyFileSync(helperPath("child.ts"), out)'); @@ -124,6 +128,20 @@ describe("scanEscapes", () => { expect(out.source).toContain('readFileSync(join(repoRoot, rel), "utf8")'); expect(scanEscapes(out.source)).toEqual([]); + // A second escape in the same file must call the alias, never the local string; and a + // dynamic import() deep in the file must not drag the helper import to the bottom. + const two = 'import { join } from "node:path";\nconst repoRoot = join(import.meta.dir, "..");\nasync function f() {\n const m = await import("../src/x");\n return { cwd: join(import.meta.dir, "..") };\n}\n'; + const outTwo = rewriteMetaDirEscapes(two, 1); + expect(outTwo.source.split("\n")[1]).toBe('import { repoRoot as resolveRepoRoot } from "../helpers/repo-root";'); + expect(outTwo.source).toContain("return { cwd: resolveRepoRoot() };"); + expect(outTwo.source).not.toContain("repoRoot()"); + + // A file whose last line is a stray import still gets the helper in the leading block. + const trailing = 'import { join } from "node:path";\n\nconst r = join(import.meta.dir, "..");\nimport { X } from "../helpers/x";\n'; + const outTrailing = rewriteMetaDirEscapes(trailing, 1).source.split("\n"); + expect(outTrailing[1]).toBe('import { repoRoot } from "../helpers/repo-root";'); + expect(outTrailing[outTrailing.length - 2]).toBe('import { X } from "../helpers/x";'); + const url = 'import { join } from "node:path";\nconst root = new URL("../../", import.meta.url);\nconst t = await Bun.file(new URL(p, root)).text();\n'; const outUrl = rewriteMetaDirEscapes(url, 2); expect(outUrl.source).toContain('const root = pathToFileURL(repoRoot() + "/");'); diff --git a/tests/windows/windows-tray.test.ts b/tests/windows/windows-tray.test.ts index 4867834db70..60cfd9f3230 100644 --- a/tests/windows/windows-tray.test.ts +++ b/tests/windows/windows-tray.test.ts @@ -9,6 +9,7 @@ import { writeFileSync, } from "node:fs"; import { tmpdir } from "node:os"; +import { helperPath, repoPath, repoRoot } from "../helpers/repo-root"; import { join } from "node:path"; import { buildWindowsTrayLauncherScript, @@ -557,4 +558,3 @@ describe("Windows tray packaging and command safety", () => { }); }); import { ManagementRequest as Request } from "../helpers/management-auth"; -import { helperPath, repoPath, repoRoot } from "../helpers/repo-root"; From 03433b1cf654ae3640a7fb87416e178560826d28 Mon Sep 17 00:00:00 2001 From: jun Date: Sat, 5 Sep 2026 04:40:13 +0900 Subject: [PATCH 2/3] test(layout): declare rootCall before the rewrite rules use it --- scripts/test-layout/schema.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/test-layout/schema.ts b/scripts/test-layout/schema.ts index f5cbb2a4edd..50a97031e55 100644 --- a/scripts/test-layout/schema.ts +++ b/scripts/test-layout/schema.ts @@ -178,11 +178,14 @@ export function rewriteMetaDirEscapes(source: string, depth: number): { source: const rebindsRoot = localRoot.test(view); const otherLocals = new RegExp(`\\b(?:const|let|var|function)\\s+(?:${HELPER_NAMES.filter(n => !(rebindsRoot && n === "repoRoot")).join("|")})\\b`); if (otherLocals.test(code)) return { source, rewrites: 0 }; + // When the file keeps a local string named repoRoot, the other rules must not emit a call + // to repoRoot() (that would call the string); they use the alias the rebind imports. + const rootCall = rebindsRoot ? "resolveRepoRoot()" : "repoRoot()"; const rules: Array<[RegExp, (m: RegExpMatchArray) => string]> = [ [new RegExp(localRoot.source, "g"), () => "const repoRoot = resolveRepoRoot();"], // `const root = new URL("../../", import.meta.url)` -> a file URL of the repository root. - [/\bconst\s+root\s*=\s*new\s+URL\(\s*"(?:\.\.\/)+"\s*,\s*import\.meta\.url\s*\)\s*;/g, () => 'const root = pathToFileURL(repoRoot() + "/");'], - [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\."\s*\)/g, () => "repoRoot()"], + [/\bconst\s+root\s*=\s*new\s+URL\(\s*"(?:\.\.\/)+"\s*,\s*import\.meta\.url\s*\)\s*;/g, () => `const root = pathToFileURL(${rootCall} + "/");`], + [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\."\s*\)/g, () => rootCall], [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\."\s*,\s*/g, () => "repoPath("], [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\.\/([^"]+)"/g, m => `repoPath("${m[1]}"`], [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"helpers"\s*,\s*/g, () => "helperPath("], @@ -320,4 +323,3 @@ export function layoutDir(): string { return dirname(LAYOUT_PATH); } - From a6d6e138c5ddc460ec90af37ce7c91230ea8636c Mon Sep 17 00:00:00 2001 From: jun Date: Sat, 5 Sep 2026 05:55:05 +0900 Subject: [PATCH 3/3] test(layout): honour #3523 placement of anthropic-quorum-cache; map docs-429-failover-claims --- scripts/test-layout/layout.json | 3 +- scripts/test-layout/move.ts | 18 ++- scripts/test-layout/schema.ts | 11 +- .../anthropic/anthropic-quorum-cache.test.ts | 146 ------------------ tests/fixtures/test-layout-expected.json | 3 +- tests/test-layout-tooling.test.ts | 11 +- 6 files changed, 33 insertions(+), 159 deletions(-) delete mode 100644 tests/adapters/anthropic/anthropic-quorum-cache.test.ts diff --git a/scripts/test-layout/layout.json b/scripts/test-layout/layout.json index a019b798787..ab49a9ddfd8 100644 --- a/scripts/test-layout/layout.json +++ b/scripts/test-layout/layout.json @@ -201,7 +201,7 @@ "anthropic-image-retry-e2e.test.ts": "adapters/anthropic", "anthropic-image-retry.test.ts": "adapters/anthropic", "anthropic-pool-toggle-copy.test.ts": "adapters/anthropic", - "anthropic-quorum-cache.test.ts": "adapters/anthropic", + "anthropic-quorum-cache.test.ts": "routing", "anthropic-reasoning.test.ts": "adapters/anthropic", "anthropic-stream-hardening.test.ts": "adapters/anthropic", "anthropic-tail-guard.test.ts": "adapters/anthropic", @@ -576,6 +576,7 @@ "desktop-profile.test.ts": "clients", "destination-policy-resolved.test.ts": "routing", "digitalocean-scaleway-provider.test.ts": "providers", + "docs-429-failover-claims.test.ts": "ci-workflows", "docs-bun-source-requirement.test.ts": "ci-workflows", "doctor-codex-envkey-readiness.test.ts": "service", "doctor-oauth.test.ts": "service", diff --git a/scripts/test-layout/move.ts b/scripts/test-layout/move.ts index 51e9d3678e3..5a930cff27f 100644 --- a/scripts/test-layout/move.ts +++ b/scripts/test-layout/move.ts @@ -141,12 +141,18 @@ export function runMove(options: MoveOptions): MoveReport { const path = join(root, byFrom.get(file) ?? file); let text = readFileSync(path, "utf8"); const original = text; - for (const [from, to] of byFrom) { - text = text.split(from).join(to); - if (file === SERIAL_LANE_SOURCE && serial.has(basename(from))) { - const rel = from.slice("tests/".length); - text = text.split(`"${rel}"`).join(`"${to.slice("tests/".length)}"`); - } + for (const [from, to] of byFrom) text = text.split(from).join(to); + if (file === SERIAL_LANE_SOURCE) { + // Only the SERIAL_FULL_SUITE_FILES array holds tests/-relative paths; the timeout table + // next to it is keyed by basename and must not change. + text = text.replace(/SERIAL_FULL_SUITE_FILES = \[([\s\S]*?)\]/, (whole, body: string) => { + let next = body; + for (const [from, to] of byFrom) { + if (!serial.has(basename(from))) continue; + next = next.split(`"${from.slice("tests/".length)}"`).join(`"${to.slice("tests/".length)}"`); + } + return whole.replace(body, next); + }); } if (text !== original) { writeFileSync(path, text); diff --git a/scripts/test-layout/schema.ts b/scripts/test-layout/schema.ts index 50a97031e55..de75004d000 100644 --- a/scripts/test-layout/schema.ts +++ b/scripts/test-layout/schema.ts @@ -42,6 +42,8 @@ export function loadLayout(path: string = LAYOUT_PATH): Layout { * Explicit entries win, then child regexes, then domain regexes; first match wins. */ export function resolveTarget(layout: Layout, basename: string): string | null { + // A keep-at-root file never resolves to a domain, whatever the seeds say about its name. + if (layout.keepAtRoot.includes(basename)) return null; const explicit = layout.explicit[basename]; if (explicit !== undefined) return explicit; for (const [domain, spec] of Object.entries(layout.domains)) { @@ -174,7 +176,7 @@ export function rewriteMetaDirEscapes(source: string, depth: number): { source: // `const repoRoot = join(import.meta.dir, "..")` is the commonest escape of all: rebind the // local through an aliased import instead of refusing the file. Any other local named like a // helper (or a function) still stops the rewrite so nothing gets shadowed. - const localRoot = /\bconst\s+repoRoot\s*=\s*(?:(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\."\s*\)|fileURLToPath\(\s*new\s+URL\(\s*"(?:\.\.\/)+"\s*,\s*import\.meta\.url\s*\)\s*\)|resolve\(\s*dirname\(\s*fileURLToPath\(\s*import\.meta\.url\s*\)\s*\)\s*,\s*"\.\."\s*\))\s*;/; + const localRoot = /\bconst\s+repoRoot\s*=\s*(?:(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"\.\."\s*\)|fileURLToPath\(\s*new\s+URL\(\s*"(?:\.\.\/)*\.\.\/?"\s*,\s*import\.meta\.url\s*\)\s*\)|resolve\(\s*dirname\(\s*fileURLToPath\(\s*import\.meta\.url\s*\)\s*\)\s*,\s*"\.\."\s*\))\s*;/; const rebindsRoot = localRoot.test(view); const otherLocals = new RegExp(`\\b(?:const|let|var|function)\\s+(?:${HELPER_NAMES.filter(n => !(rebindsRoot && n === "repoRoot")).join("|")})\\b`); if (otherLocals.test(code)) return { source, rewrites: 0 }; @@ -192,7 +194,9 @@ export function rewriteMetaDirEscapes(source: string, depth: number): { source: [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"helpers\/([^"]+)"/g, m => `helperPath("${m[1]}"`], [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"fixtures"\s*,\s*/g, () => "fixturePath("], [/\b(?:join|resolve)\(\s*import\.meta\.dir\s*,\s*"fixtures\/([^"]+)"/g, m => `fixturePath("${m[1]}"`], - [/\bfileURLToPath\(\s*new\s+URL\(\s*"\.\.\/"\s*,\s*import\.meta\.url\s*\)\s*\)/g, () => rootCall], + [/\bfileURLToPath\(\s*new\s+URL\(\s*"\.\.\/?"\s*,\s*import\.meta\.url\s*\)\s*\)/g, () => rootCall], + // `new URL("..", import.meta.url).href` as a root URL string. + [/\bnew\s+URL\(\s*"\.\.\/?"\s*,\s*import\.meta\.url\s*\)\.href/g, () => `pathToFileURL(${rootCall} + "/").href`], [/\bresolve\(\s*dirname\(\s*fileURLToPath\(\s*import\.meta\.url\s*\)\s*\)\s*,\s*"\.\."\s*\)/g, () => rootCall], ]; const edits: Array<{ start: number; end: number; text: string }> = []; @@ -266,7 +270,7 @@ export function insertAfterImports(source: string, line: string): string { /** A string argument that leaves the file's directory toward the repo or the tests/ siblings. */ const ESCAPE_ARG = /^["'](?:\.\.(?:["'\/])|helpers\b|fixtures\b|src\/|gui\/|scripts\/|tests\/)/; /** `new URL("../", import.meta.url)`: a URL used as a directory root, not a re-anchored specifier. */ -const URL_ROOT = /new\s+URL\s*\(\s*(["'])(?:\.\.\/)+\1\s*,\s*import\.meta\.url/; +const URL_ROOT = /new\s+URL\s*\(\s*(["'])(?:\.\.\/)*\.\.\/?\1\s*,\s*import\.meta\.url/; export interface EscapeHit { line: number; @@ -322,4 +326,3 @@ export function scanEscapes(source: string): EscapeHit[] { export function layoutDir(): string { return dirname(LAYOUT_PATH); } - diff --git a/tests/adapters/anthropic/anthropic-quorum-cache.test.ts b/tests/adapters/anthropic/anthropic-quorum-cache.test.ts deleted file mode 100644 index 6aaad77aa85..00000000000 --- a/tests/adapters/anthropic/anthropic-quorum-cache.test.ts +++ /dev/null @@ -1,146 +0,0 @@ -/** - * The quorum predicate must not read the auth store on every request. - * - * `hasAnthropicFailoverQuorum` decides whether an Anthropic request records the account that - * served it, so it runs on the INITIAL resolution of ordinary traffic -- not only after a 429. - * `getAccountSet` goes through `loadAuthStore`, which has no cache: it chmods the config dir, - * chmods the secret, reads the whole file and normalizes it on every call. An uncached predicate - * therefore puts a synchronous file read in front of every Anthropic turn. - * - * The generic module already solved this with a TTL-bounded count cache. These tests pin the same - * three properties for the Anthropic twin: the read is shared inside the window, a fresh login is - * still visible once it expires, and a rotation invalidates immediately rather than answering the - * next question from a pre-failure count. - */ -import { afterEach, beforeEach, describe, expect, test } from "bun:test"; -import { mkdtempSync, statSync, utimesSync } from "node:fs"; -import { tmpdir } from "node:os"; -import { join } from "node:path"; -import { - clearAnthropicAccountPoolState, - clearAnthropicSessionAffinityForAccount, - forgetAnthropicFailoverQuorum, - hasAnthropicFailoverQuorum, - resetAnthropicRoutingForManualSelection, - rotateAnthropicAccountOn429, -} from "../../../src/oauth/anthropic-routing"; -import { getAccountSet, saveCredential } from "../../../src/oauth/store"; -import { removeTreeWithRetry } from "../../helpers/remove-tree"; - -const originalHome = process.env.OPENCODEX_HOME; -let home: string; - -beforeEach(() => { - home = mkdtempSync(join(tmpdir(), "ocx-quorum-cache-")); - process.env.OPENCODEX_HOME = home; - clearAnthropicAccountPoolState(); - forgetAnthropicFailoverQuorum(); -}); - -afterEach(() => { - clearAnthropicAccountPoolState(); - forgetAnthropicFailoverQuorum(); - if (originalHome === undefined) delete process.env.OPENCODEX_HOME; - else process.env.OPENCODEX_HOME = originalHome; - removeTreeWithRetry(home); -}); - -async function seed(count: number, offset = 0): Promise { - for (let i = offset; i < offset + count; i++) { - await saveCredential("anthropic", { - access: `access-${i}`, - refresh: `refresh-${i}`, - expires: Date.now() + 3_600_000, - accountId: `uuid-${i}`, - email: `user${i}@example.test`, - } as never); - } - return getAccountSet("anthropic")?.accounts.map(a => a.id) ?? []; -} - -/** - * Observe the store read without stubbing the module: `loadAuthStore` calls `readFileSync`, - * which updates atime. Pinning atime into the past and checking whether it moved is a direct - * observation of the syscall this cache exists to avoid. - */ -function storePath(): string { - return join(home, "auth.json"); -} - -function markStoreUnread(): void { - const stats = statSync(storePath()); - utimesSync(storePath(), new Date(Date.now() - 60_000), stats.mtime); -} - -function storeWasRead(): boolean { - return statSync(storePath()).atimeMs > Date.now() - 30_000; -} - -describe("Anthropic failover quorum cache", () => { - test("a burst of requests inside the TTL window shares one store read", async () => { - const start = Date.now(); - await seed(2); - // Prime the cache, then prove the next calls do not touch the file at all. - expect(hasAnthropicFailoverQuorum(start)).toBe(true); - markStoreUnread(); - for (let i = 0; i < 25; i++) expect(hasAnthropicFailoverQuorum(start + i)).toBe(true); - expect(storeWasRead()).toBe(false); - }); - - test("a fresh login is visible once the window expires", async () => { - // The cache must not be able to strand an operator who just logged a second account in: - // a stale false would keep failover off for exactly the traffic that needs it. - const start = Date.now(); - await seed(1); - expect(hasAnthropicFailoverQuorum(start)).toBe(false); - await seed(1, 1); - // Same instant: still the memoized answer. - expect(hasAnthropicFailoverQuorum(start)).toBe(false); - // Past the window: seen without any explicit invalidation call. - expect(hasAnthropicFailoverQuorum(start + 2_001)).toBe(true); - }); - - test("a rotation invalidates immediately rather than waiting out the TTL", async () => { - const start = Date.now(); - const ids = await seed(2); - expect(hasAnthropicFailoverQuorum(start)).toBe(true); - expect(rotateAnthropicAccountOn429({ providers: {} } as never, ids[0]!, null, null, start)).toBe(ids[1]); - // The roster in use just changed, so the next question re-reads instead of answering from - // the count taken before the failure. - markStoreUnread(); - hasAnthropicFailoverQuorum(start + 1); - expect(storeWasRead()).toBe(true); - }); - - test("the cache holds no credential material", async () => { - // A boolean derived from a count. If this ever became an id or a token the cache would - // outlive the store's own hardening, which is the thing loadAuthStore re-applies per read. - await seed(2); - expect(typeof hasAnthropicFailoverQuorum()).toBe("boolean"); - }); - - test("removing an account invalidates immediately, not after the TTL", async () => { - // The management DELETE route calls clearAnthropicSessionAffinityForAccount for Anthropic. - // Without invalidation there, deleting the second account would leave quorum true for up to - // 2s -- long enough for a request to record an id whose credential is already gone. - const start = Date.now(); - const ids = await seed(2); - expect(hasAnthropicFailoverQuorum(start)).toBe(true); - clearAnthropicSessionAffinityForAccount(ids[1]!); - markStoreUnread(); - hasAnthropicFailoverQuorum(start + 1); - expect(storeWasRead()).toBe(true); - }); - - test("a manual account selection invalidates immediately", async () => { - // An operator picking an account is a statement about the roster, so the next activation - // question must not be answered from a count read before it. - const start = Date.now(); - const ids = await seed(2); - expect(hasAnthropicFailoverQuorum(start)).toBe(true); - resetAnthropicRoutingForManualSelection(ids[0]!); - markStoreUnread(); - hasAnthropicFailoverQuorum(start + 1); - expect(storeWasRead()).toBe(true); - }); -}); diff --git a/tests/fixtures/test-layout-expected.json b/tests/fixtures/test-layout-expected.json index 802cb98a8d7..9a84ed21317 100644 --- a/tests/fixtures/test-layout-expected.json +++ b/tests/fixtures/test-layout-expected.json @@ -38,7 +38,7 @@ "anthropic-image-retry-e2e.test.ts": "adapters/anthropic", "anthropic-image-retry.test.ts": "adapters/anthropic", "anthropic-pool-toggle-copy.test.ts": "adapters/anthropic", - "anthropic-quorum-cache.test.ts": "adapters/anthropic", + "anthropic-quorum-cache.test.ts": "routing", "anthropic-reasoning.test.ts": "adapters/anthropic", "anthropic-stream-hardening.test.ts": "adapters/anthropic", "anthropic-tail-guard.test.ts": "adapters/anthropic", @@ -413,6 +413,7 @@ "desktop-profile.test.ts": "clients", "destination-policy-resolved.test.ts": "routing", "digitalocean-scaleway-provider.test.ts": "providers", + "docs-429-failover-claims.test.ts": "ci-workflows", "docs-bun-source-requirement.test.ts": "ci-workflows", "doctor-codex-envkey-readiness.test.ts": "service", "doctor-oauth.test.ts": "service", diff --git a/tests/test-layout-tooling.test.ts b/tests/test-layout-tooling.test.ts index dc3ee6bf31a..6a9066aa298 100644 --- a/tests/test-layout-tooling.test.ts +++ b/tests/test-layout-tooling.test.ts @@ -202,6 +202,9 @@ describe("scanEscapes", () => { // A rewritten URL specifier is what a correct move looks like; a bare "../" root URL is not. expect(scanEscapes('const u = new URL("../../package.json", import.meta.url);')).toEqual([]); expect(scanEscapes('const root = fileURLToPath(new URL("../", import.meta.url));')).toHaveLength(1); + expect(scanEscapes('const root = fileURLToPath(new URL("..", import.meta.url));')).toHaveLength(1); + expect(rewriteMetaDirEscapes('const R = fileURLToPath(new URL("..", import.meta.url));\nconst U = new URL("..", import.meta.url).href;\n', 1).source) + .toContain('const R = repoRoot();\nconst U = pathToFileURL(repoRoot() + "/").href;'); expect(scanEscapes('const c = join(import.meta.dir, "helpers", "child.ts");')).toHaveLength(1); expect(scanEscapes('const r = resolve(\n import.meta.dir,\n "..",\n);')).toHaveLength(1); expect(scanEscapes('const t = `${import.meta.dir}/../src/x.ts`;')).toHaveLength(1); @@ -225,6 +228,7 @@ describe("resolver", () => { }; test("explicit beats child regex beats domain regex; unknown is null", () => { + expect(resolveTarget({ ...layout, keepAtRoot: ["server-kept.test.ts"] }, "server-kept.test.ts")).toBeNull(); expect(resolveTarget(layout, "cursor-odd.test.ts")).toBe("server"); expect(resolveTarget(layout, "cursor-adapter.test.ts")).toBe("providers/cursor"); expect(resolveTarget(layout, "provider-x.test.ts")).toBe("providers"); @@ -280,7 +284,12 @@ describe("membership oracle", () => { // (the 001 §2 "9 disagreeing files" whose name says one thing and whose imports say another). // Anything else is a seed pointing at the wrong domain, which would place a brand-new file // incorrectly on the day it is added. - const pinnedOverrides = new Set(["openai-responses-passthrough.test.ts"]); + const pinnedOverrides = new Set([ + "openai-responses-passthrough.test.ts", + // Placed under routing/ by its author in #3523 (it exercises the oauth routing quorum, + // not the Anthropic adapter); the anthropic- seed would say otherwise. + "anthropic-quorum-cache.test.ts", + ]); const mismatches: string[] = []; let resolved = 0; for (const [name, target] of Object.entries(layout.explicit)) {