@iislee/opencodex 2.11.0 → 2.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS_INSTALL.md +109 -0
- package/README.md +114 -19
- package/bin/ocx.mjs +164 -36
- package/bin/package-main.mjs +1 -1
- package/gui/dist/assets/index-BF38heuV.js +104 -0
- package/gui/dist/assets/index-DMiI18Kv.css +1 -0
- package/gui/dist/index.html +2 -2
- package/gui/dist/provider-icons/alibaba-color.svg +1 -1
- package/gui/dist/provider-icons/antigravity-color.svg +1 -1
- package/gui/dist/provider-icons/claude-color.svg +1 -1
- package/gui/dist/provider-icons/cline-color.svg +16 -0
- package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
- package/gui/dist/provider-icons/commandcode-color.svg +1 -0
- package/gui/dist/provider-icons/copilot-color.svg +1 -1
- package/gui/dist/provider-icons/cursor-color.svg +1 -1
- package/gui/dist/provider-icons/deepseek-color.svg +1 -1
- package/gui/dist/provider-icons/firepass-color.svg +1 -1
- package/gui/dist/provider-icons/fireworks-color.svg +1 -1
- package/gui/dist/provider-icons/gemini-color.svg +1 -1
- package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
- package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
- package/gui/dist/provider-icons/grok.svg +1 -1
- package/gui/dist/provider-icons/groq-color.svg +1 -1
- package/gui/dist/provider-icons/huggingface-color.svg +1 -1
- package/gui/dist/provider-icons/kimi-color.svg +1 -1
- package/gui/dist/provider-icons/kiro-color.svg +2 -2
- package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
- package/gui/dist/provider-icons/mistral-color.svg +1 -1
- package/gui/dist/provider-icons/moonshot-color.svg +1 -1
- package/gui/dist/provider-icons/nvidia-color.svg +1 -1
- package/gui/dist/provider-icons/ollama-color.svg +1 -1
- package/gui/dist/provider-icons/openai.svg +1 -1
- package/gui/dist/provider-icons/opencode.svg +2 -1
- package/gui/dist/provider-icons/openrouter-color.svg +1 -1
- package/gui/dist/provider-icons/pi.svg +2 -2
- package/gui/dist/provider-icons/qianfan-color.svg +1 -1
- package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
- package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
- package/gui/dist/provider-icons/vllm-color.svg +1 -1
- package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
- package/package.json +19 -10
- package/src/adapters/anthropic-output-schema.ts +137 -0
- package/src/adapters/anthropic.ts +376 -52
- package/src/adapters/base.ts +54 -7
- package/src/adapters/client-fingerprint.ts +18 -12
- package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
- package/src/adapters/command-code.ts +601 -0
- package/src/adapters/cursor/checkpoint-store.ts +303 -0
- package/src/adapters/cursor/cursor-errors.ts +129 -6
- package/src/adapters/cursor/discovery.ts +61 -4
- package/src/adapters/cursor/effort-map.ts +27 -3
- package/src/adapters/cursor/framing.ts +39 -0
- package/src/adapters/cursor/h2-pool.ts +123 -0
- package/src/adapters/cursor/http1-bidi.ts +361 -0
- package/src/adapters/cursor/images.ts +704 -0
- package/src/adapters/cursor/live-models.ts +174 -58
- package/src/adapters/cursor/live-transport.ts +609 -170
- package/src/adapters/cursor/native-exec-common.ts +23 -2
- package/src/adapters/cursor/native-exec-fs.ts +10 -7
- package/src/adapters/cursor/native-exec-network.ts +1 -1
- package/src/adapters/cursor/native-exec-shell.ts +0 -1
- package/src/adapters/cursor/native-exec.ts +101 -14
- package/src/adapters/cursor/protobuf-events.ts +829 -11
- package/src/adapters/cursor/protobuf-request.ts +383 -65
- package/src/adapters/cursor/request-builder.ts +237 -31
- package/src/adapters/cursor/tool-definitions.ts +242 -12
- package/src/adapters/cursor/tool-result-normalize.ts +92 -0
- package/src/adapters/cursor/transport.ts +22 -0
- package/src/adapters/cursor/types.ts +28 -1
- package/src/adapters/cursor.ts +133 -7
- package/src/adapters/google-antigravity-replay.ts +558 -34
- package/src/adapters/google-antigravity-wire.ts +43 -10
- package/src/adapters/google-http.ts +38 -10
- package/src/adapters/google-tool-schema.ts +80 -15
- package/src/adapters/google-truncation.ts +11 -0
- package/src/adapters/google.ts +618 -74
- package/src/adapters/identity.ts +39 -6
- package/src/adapters/kiro-errors.ts +11 -0
- package/src/adapters/kiro-events.ts +19 -1
- package/src/adapters/kiro-thinking.ts +18 -2
- package/src/adapters/kiro-tools.ts +10 -1
- package/src/adapters/kiro.ts +92 -54
- package/src/adapters/mimo-free.ts +17 -0
- package/src/adapters/openai-chat-url.ts +11 -0
- package/src/adapters/openai-chat.ts +1311 -336
- package/src/adapters/openai-responses-url.ts +16 -0
- package/src/adapters/openai-responses.ts +830 -56
- package/src/adapters/registry.ts +175 -0
- package/src/adapters/responses-tool-schema.ts +67 -0
- package/src/adapters/tool-call-id.ts +119 -0
- package/src/adapters/tool-catalog-nudge.ts +104 -21
- package/src/adapters/xai-web-search.ts +185 -0
- package/src/bridge.ts +428 -61
- package/src/chat/inbound.ts +43 -19
- package/src/chat/outbound.ts +82 -26
- package/src/claude/agents-inject.ts +32 -9
- package/src/claude/context-windows.ts +21 -5
- package/src/claude/desktop-3p.ts +243 -9
- package/src/claude/gateway-cache.ts +41 -4
- package/src/claude/inbound.ts +72 -3
- package/src/claude/model-info.ts +38 -15
- package/src/claude/outbound.ts +70 -16
- package/src/cli/account-api.ts +35 -1
- package/src/cli/account-auth.ts +33 -6
- package/src/cli/account-catalog-refresh.ts +14 -0
- package/src/cli/account-extended.ts +389 -2
- package/src/cli/account-main.ts +317 -0
- package/src/cli/account.ts +30 -6
- package/src/cli/agent.ts +45 -1
- package/src/cli/claude-agent-startup-sync.ts +73 -0
- package/src/cli/claude-desktop.ts +29 -4
- package/src/cli/claude.ts +103 -34
- package/src/cli/codex-log-guard-doctor.ts +103 -0
- package/src/cli/codex-shim-autorestore.ts +2 -0
- package/src/cli/codex-shim-readiness.ts +76 -0
- package/src/cli/combo.ts +8 -0
- package/src/cli/config-command.ts +74 -10
- package/src/cli/dispatch.ts +593 -0
- package/src/cli/doctor.ts +315 -43
- package/src/cli/ensure-desired-integrations.ts +152 -0
- package/src/cli/export-command.ts +46 -20
- package/src/cli/help.ts +20 -271
- package/src/cli/index.ts +378 -519
- package/src/cli/init.ts +4 -17
- package/src/cli/integrations.ts +120 -2
- package/src/cli/lab.ts +607 -0
- package/src/cli/launcher-context.ts +77 -0
- package/src/cli/minimax.ts +497 -0
- package/src/cli/models-runtime.ts +35 -2
- package/src/cli/models.ts +100 -14
- package/src/cli/observe.ts +92 -3
- package/src/cli/opencode.ts +4 -2
- package/src/cli/provider-runtime.ts +18 -1
- package/src/cli/provider.ts +24 -3
- package/src/cli/ready.ts +301 -0
- package/src/cli/registry.ts +437 -0
- package/src/cli/root.ts +86 -0
- package/src/cli/route-policy.ts +92 -0
- package/src/cli/runtime-api.ts +6 -3
- package/src/cli/star-prompt.ts +71 -15
- package/src/cli/status.ts +10 -3
- package/src/cli/system-restart-client.ts +146 -0
- package/src/cli/tray-proxy.ts +153 -6
- package/src/cli/v2.ts +105 -10
- package/src/cli.ts +1 -1
- package/src/clients/config-export.ts +1358 -21
- package/src/codex/account-label.ts +14 -1
- package/src/codex/account-lifecycle.ts +130 -13
- package/src/codex/account-namespaces.ts +49 -3
- package/src/codex/account-priority.ts +83 -0
- package/src/codex/account-store.ts +29 -2
- package/src/codex/account-usability.ts +25 -2
- package/src/codex/admission.ts +256 -0
- package/src/codex/affinity-debug.ts +162 -0
- package/src/codex/app-server-processes.ts +493 -106
- package/src/codex/app-server-restart-service.ts +232 -0
- package/src/codex/auth-api.ts +849 -242
- package/src/codex/auth-collision.ts +5 -3
- package/src/codex/auth-context.ts +345 -32
- package/src/codex/autostart-health.ts +8 -1
- package/src/codex/catalog/account-models.ts +67 -0
- package/src/codex/catalog/aggregation.ts +68 -10
- package/src/codex/catalog/bundled.ts +331 -33
- package/src/codex/catalog/effort.ts +121 -30
- package/src/codex/catalog/filesystem-evidence.ts +302 -0
- package/src/codex/catalog/kinds.ts +2 -0
- package/src/codex/catalog/metadata.ts +529 -45
- package/src/codex/catalog/native-models.ts +72 -0
- package/src/codex/catalog/parsing.ts +224 -30
- package/src/codex/catalog/provider-fetch.ts +1460 -134
- package/src/codex/catalog/sync.ts +1449 -186
- package/src/codex/catalog-admission.ts +199 -0
- package/src/codex/catalog-refresh-status.ts +105 -0
- package/src/codex/catalog-write-serialization.ts +242 -0
- package/src/codex/catalog.ts +6 -3
- package/src/codex/codex-write-lock.ts +384 -0
- package/src/codex/convergence-types.ts +614 -0
- package/src/codex/convergence.ts +651 -0
- package/src/codex/coordinator-doctor.ts +332 -0
- package/src/codex/custom-model-catalog-migration.ts +176 -0
- package/src/codex/desired-state.ts +230 -0
- package/src/codex/features.ts +636 -39
- package/src/codex/generation.ts +202 -0
- package/src/codex/history-job.ts +407 -0
- package/src/codex/history-lock.ts +242 -0
- package/src/codex/history-migration-guardian.ts +26 -20
- package/src/codex/history-provider.ts +231 -28
- package/src/codex/history-transition.ts +105 -0
- package/src/codex/history-worker.ts +220 -0
- package/src/codex/inject-coordination.ts +290 -0
- package/src/codex/inject.ts +1073 -152
- package/src/codex/injected-marker.ts +37 -3
- package/src/codex/integration-record.ts +266 -0
- package/src/codex/internal/catalog-writer.ts +203 -0
- package/src/codex/internal/history-writer.ts +80 -0
- package/src/codex/journal.ts +66 -4
- package/src/codex/log-guard/inspect.ts +506 -0
- package/src/codex/log-guard/lock.ts +150 -0
- package/src/codex/log-guard/maintenance.ts +403 -0
- package/src/codex/log-guard/path-safety.ts +88 -0
- package/src/codex/log-guard/policy.ts +44 -0
- package/src/codex/log-guard/processes.ts +205 -0
- package/src/codex/log-guard/protection.ts +489 -0
- package/src/codex/log-guard/sqlite-errors.ts +9 -0
- package/src/codex/main-account-cache.ts +24 -0
- package/src/codex/main-account.ts +29 -1
- package/src/codex/management-convergence.ts +167 -0
- package/src/codex/model-cache.ts +56 -10
- package/src/codex/model-entitlements.ts +353 -0
- package/src/codex/native-main-admission.ts +47 -0
- package/src/codex/native-main-auth-temp.ts +187 -0
- package/src/codex/native-main-claim.ts +178 -0
- package/src/codex/native-main-lock-file.ts +162 -0
- package/src/codex/native-main-owner.ts +329 -0
- package/src/codex/native-profile-api.ts +247 -0
- package/src/codex/native-profile-manager.ts +1531 -0
- package/src/codex/native-profile-processes.ts +121 -0
- package/src/codex/native-profile-recovery.ts +99 -0
- package/src/codex/native-profile-stage-store.ts +387 -0
- package/src/codex/native-profile-startup.ts +492 -0
- package/src/codex/native-profile-store.ts +855 -0
- package/src/codex/native-profile-types.ts +120 -0
- package/src/codex/native-residue.ts +682 -0
- package/src/codex/paths.ts +80 -1
- package/src/codex/plan-from-token.ts +140 -0
- package/src/codex/plan.ts +40 -0
- package/src/codex/plugins-doctor.ts +1 -1
- package/src/codex/pool-rotation.ts +74 -4
- package/src/codex/project-config-warnings.ts +20 -6
- package/src/codex/prompt-journal.ts +352 -0
- package/src/codex/prompt-layers.ts +967 -0
- package/src/codex/prompt-lock.ts +143 -0
- package/src/codex/quota-rejection.ts +298 -0
- package/src/codex/quota.ts +175 -13
- package/src/codex/refresh.ts +11 -2
- package/src/codex/reset-credit-recovery.ts +1044 -0
- package/src/codex/routing.ts +505 -94
- package/src/codex/runtime.ts +159 -38
- package/src/codex/shim.ts +1009 -28
- package/src/codex/subagent-model-fallback.ts +350 -35
- package/src/codex/sync.ts +191 -2
- package/src/codex/transition-state.ts +612 -0
- package/src/codex/upstream-host-health.ts +368 -0
- package/src/codex/user-identity.ts +557 -0
- package/src/codex/warmup.ts +187 -81
- package/src/codex/write-coordination.ts +114 -0
- package/src/combos/failover.ts +20 -0
- package/src/combos/index.ts +4 -0
- package/src/combos/request.ts +32 -0
- package/src/combos/types.ts +81 -9
- package/src/config/provider-name.ts +24 -0
- package/src/config.ts +1762 -140
- package/src/generated/compatibility-version.json +3164 -0
- package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
- package/src/grok/inject.ts +16 -5
- package/src/grok/inspect.ts +45 -0
- package/src/grok/sync.ts +2 -2
- package/src/images/loop.ts +152 -29
- package/src/images/plan.ts +23 -13
- package/src/integrations/config-io.ts +269 -0
- package/src/integrations/journal.ts +315 -0
- package/src/integrations/merge.ts +135 -0
- package/src/integrations/mutation-flight.ts +71 -0
- package/src/integrations/native/ownership-preflight.ts +202 -0
- package/src/integrations/omp-yaml-source.ts +358 -0
- package/src/integrations/owned-refresh.ts +74 -0
- package/src/integrations/ownership.ts +111 -0
- package/src/integrations/registry.ts +159 -0
- package/src/integrations/serialize.ts +314 -0
- package/src/integrations/state.ts +361 -0
- package/src/integrations/store.ts +103 -0
- package/src/integrations/writer-lock.ts +98 -0
- package/src/integrations/writer.ts +691 -0
- package/src/lab/artifacts/sanitize.ts +586 -0
- package/src/lab/artifacts/secure-fs.ts +475 -0
- package/src/lab/artifacts/store.ts +310 -0
- package/src/lab/automation/budgets.ts +78 -0
- package/src/lab/automation/config-persistence.ts +256 -0
- package/src/lab/automation/constants.ts +39 -0
- package/src/lab/automation/cooldown.ts +103 -0
- package/src/lab/automation/dispatch.ts +211 -0
- package/src/lab/automation/index.ts +13 -0
- package/src/lab/automation/orchestrator.ts +499 -0
- package/src/lab/automation/persistence.ts +512 -0
- package/src/lab/automation/planner.ts +371 -0
- package/src/lab/automation/policy.ts +136 -0
- package/src/lab/automation/queue.ts +191 -0
- package/src/lab/automation/recovery.ts +24 -0
- package/src/lab/automation/route-context.ts +21 -0
- package/src/lab/automation/run-key.ts +44 -0
- package/src/lab/automation/runs-query.ts +34 -0
- package/src/lab/automation/types.ts +160 -0
- package/src/lab/conformance/assertion.ts +325 -0
- package/src/lab/conformance/digest.ts +22 -0
- package/src/lab/conformance/executor.ts +741 -0
- package/src/lab/conformance/fixture-provider.ts +27 -0
- package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
- package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
- package/src/lab/conformance/harness-budget.ts +47 -0
- package/src/lab/conformance/index.ts +5 -0
- package/src/lab/conformance/jcs.ts +64 -0
- package/src/lab/conformance/json-pointer.ts +39 -0
- package/src/lab/conformance/manifest.ts +180 -0
- package/src/lab/conformance/mcp-stub.ts +179 -0
- package/src/lab/conformance/negative-controls.ts +164 -0
- package/src/lab/conformance/observation.ts +355 -0
- package/src/lab/conformance/runner.ts +68 -0
- package/src/lab/conformance/sse-normalize.ts +59 -0
- package/src/lab/conformance/suite-manifest.ts +78 -0
- package/src/lab/conformance/types.ts +214 -0
- package/src/lab/constants.ts +126 -0
- package/src/lab/digest.ts +64 -0
- package/src/lab/events/errors.ts +9 -0
- package/src/lab/events/limits.ts +117 -0
- package/src/lab/events/types.ts +229 -0
- package/src/lab/events/validate.ts +781 -0
- package/src/lab/fabric/constants.ts +40 -0
- package/src/lab/fabric/executor.ts +492 -0
- package/src/lab/fabric/index.ts +80 -0
- package/src/lab/fabric/manifest.ts +222 -0
- package/src/lab/fabric/observe.ts +489 -0
- package/src/lab/fabric/patch.ts +79 -0
- package/src/lab/fabric/producer-child.ts +139 -0
- package/src/lab/fabric/producer-isolate.ts +276 -0
- package/src/lab/fabric/producer-protocol.ts +61 -0
- package/src/lab/fabric/scratch.ts +439 -0
- package/src/lab/fabric/subject.ts +106 -0
- package/src/lab/fabric/types.ts +134 -0
- package/src/lab/fabric/verifier.ts +98 -0
- package/src/lab/index.ts +54 -0
- package/src/lab/ledger/artifact-refs.ts +127 -0
- package/src/lab/ledger/invalidation.ts +136 -0
- package/src/lab/ledger/purge.ts +310 -0
- package/src/lab/ledger/store.ts +532 -0
- package/src/lab/live/credential-lease.ts +53 -0
- package/src/lab/live/destination.ts +155 -0
- package/src/lab/live/executor.ts +336 -0
- package/src/lab/live/inert-tools.ts +56 -0
- package/src/lab/live/manifest.ts +85 -0
- package/src/lab/live/mcp-loopback.ts +57 -0
- package/src/lab/live/runner.ts +19 -0
- package/src/lab/live/sandbox.ts +61 -0
- package/src/lab/live/suite-manifest.ts +41 -0
- package/src/lab/live/transport.ts +118 -0
- package/src/lab/live/types.ts +197 -0
- package/src/lab/observe/from-conformance.ts +301 -0
- package/src/lab/observe/from-live.ts +117 -0
- package/src/lab/paths.ts +153 -0
- package/src/lab/projection/rebuild.ts +495 -0
- package/src/lab/projection/schema.ts +135 -0
- package/src/lab/projection/verdicts.ts +474 -0
- package/src/lab/projection/verification.ts +412 -0
- package/src/lab/public/bundle.ts +217 -0
- package/src/lab/public/community-authority.ts +175 -0
- package/src/lab/public/community-files.ts +29 -0
- package/src/lab/public/community.ts +479 -0
- package/src/lab/public/file-safety.ts +155 -0
- package/src/lab/public/ids.ts +26 -0
- package/src/lab/public/index.ts +16 -0
- package/src/lab/public/mutation-lock.ts +424 -0
- package/src/lab/public/operator.ts +353 -0
- package/src/lab/public/origin-purge.ts +79 -0
- package/src/lab/public/origin.ts +203 -0
- package/src/lab/public/privacy.ts +143 -0
- package/src/lab/public/private-file.ts +261 -0
- package/src/lab/public/project.ts +124 -0
- package/src/lab/public/purge-test-fault.ts +21 -0
- package/src/lab/public/purge.ts +223 -0
- package/src/lab/public/registry.ts +44 -0
- package/src/lab/public/revocation.ts +252 -0
- package/src/lab/public/signature.ts +243 -0
- package/src/lab/public/storage.ts +105 -0
- package/src/lab/public/strict-json.ts +206 -0
- package/src/lab/public/time.ts +26 -0
- package/src/lab/public/types.ts +172 -0
- package/src/lab/public/validate.ts +391 -0
- package/src/lab/query/catalog.ts +101 -0
- package/src/lab/query/connection.ts +107 -0
- package/src/lab/query/constants.ts +4 -0
- package/src/lab/query/cursor.ts +132 -0
- package/src/lab/query/dto-map.ts +277 -0
- package/src/lab/query/errors.ts +22 -0
- package/src/lab/query/freshness.ts +53 -0
- package/src/lab/query/index.ts +45 -0
- package/src/lab/query/latest-observation.ts +59 -0
- package/src/lab/query/passive-production.ts +159 -0
- package/src/lab/query/queries.ts +444 -0
- package/src/lab/query/types.ts +266 -0
- package/src/lab/subject/behavior-fingerprint.ts +77 -0
- package/src/lab/subject/installation-salt.ts +112 -0
- package/src/lab/subject/protocol-subject.ts +80 -0
- package/src/lab/subject/route-subject.ts +74 -0
- package/src/lib/app-owned-memory-stores.ts +22 -0
- package/src/lib/bounded-body.ts +153 -9
- package/src/lib/bun-runtime.ts +125 -12
- package/src/lib/bun-stream-caps.ts +13 -9
- package/src/lib/codex-restart-contract.ts +120 -0
- package/src/lib/config-ownership.ts +6 -2
- package/src/lib/destination-policy.ts +65 -1
- package/src/lib/errors.ts +44 -2
- package/src/lib/fabric-task-execution-authority.ts +7 -0
- package/src/lib/fabric-task-host.ts +29 -0
- package/src/lib/lab-activation.ts +223 -0
- package/src/lib/lab-live-execution-authority.ts +13 -0
- package/src/lib/lab-live-host.ts +30 -0
- package/src/lib/lab-live-pinned-sender.ts +56 -0
- package/src/lib/lab-live-route-production.ts +130 -0
- package/src/lib/lab-passive-linker-registration.ts +26 -0
- package/src/lib/local-management-attestation.ts +51 -0
- package/src/lib/local-management-capability.ts +100 -0
- package/src/lib/local-provider-reload-contract.ts +100 -0
- package/src/lib/optional-shutdown-hooks.ts +57 -0
- package/src/lib/pinned-http.ts +145 -26
- package/src/lib/process-control.ts +4 -1
- package/src/lib/provider-outbound.ts +49 -9
- package/src/lib/redact.ts +419 -3
- package/src/lib/self-launch-argv.ts +15 -0
- package/src/lib/server-resource-ownership.ts +71 -0
- package/src/lib/shadow-call.ts +35 -4
- package/src/lib/sse-decoder.ts +41 -0
- package/src/lib/state-store-registrations.ts +10 -2
- package/src/lib/system-restart-contract.ts +73 -0
- package/src/lib/token-estimate.ts +19 -2
- package/src/lib/tool-argument-integers.ts +202 -0
- package/src/lib/translator-budget.ts +44 -0
- package/src/lib/upstream-http-version.ts +57 -0
- package/src/lib/upstream-reachability.ts +95 -0
- package/src/lib/upstream-retry.ts +156 -3
- package/src/lib/windows-atomic-replace.ts +155 -0
- package/src/lib/windows-elevation.ts +70 -2
- package/src/lib/windows-secret-acl.ts +409 -69
- package/src/lib/windows-service-wrappers.ts +72 -0
- package/src/lib/windows-text.ts +106 -0
- package/src/lib/windows-user-principal.ts +341 -0
- package/src/lib/winsw.ts +33 -5
- package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
- package/src/oauth/account-import/index.ts +15 -0
- package/src/oauth/account-import/parser.ts +83 -0
- package/src/oauth/account-import/registry.ts +18 -0
- package/src/oauth/account-import/service.ts +75 -0
- package/src/oauth/account-import/types.ts +91 -0
- package/src/oauth/anthropic.ts +12 -1
- package/src/oauth/callback-server.ts +8 -2
- package/src/oauth/chatgpt.ts +12 -1
- package/src/oauth/command-code.ts +239 -0
- package/src/oauth/cursor.ts +46 -5
- package/src/oauth/google-antigravity.ts +35 -3
- package/src/oauth/health.ts +20 -12
- package/src/oauth/index.ts +398 -66
- package/src/oauth/key-providers.ts +16 -0
- package/src/oauth/kimi.ts +16 -2
- package/src/oauth/kiro.ts +50 -6
- package/src/oauth/local-token-detect.ts +11 -2
- package/src/oauth/log.ts +3 -1
- package/src/oauth/login-cli.ts +88 -28
- package/src/oauth/nous.ts +798 -0
- package/src/oauth/store.ts +119 -21
- package/src/oauth/token-guardian.ts +9 -3
- package/src/pi/models.ts +2 -2
- package/src/providers/alibaba-region-migration.ts +1 -1
- package/src/providers/antigravity-models.ts +521 -31
- package/src/providers/base-url-choices.ts +10 -0
- package/src/providers/codex-capacity.ts +292 -0
- package/src/providers/command-code-efforts.ts +144 -0
- package/src/providers/context-cap.ts +22 -5
- package/src/providers/cursor-pool.ts +72 -0
- package/src/providers/derive.ts +253 -6
- package/src/providers/fastwire.ts +501 -0
- package/src/providers/free-directory.ts +10 -7
- package/src/providers/google-vertex-location.ts +14 -0
- package/src/providers/key-failover.ts +71 -3
- package/src/providers/label.ts +1 -1
- package/src/providers/model-discovery-limits.ts +16 -0
- package/src/providers/model-discovery.ts +115 -22
- package/src/providers/model-rename-migration.ts +255 -0
- package/src/providers/model-rename-startup.ts +28 -0
- package/src/providers/openai-sidecar.ts +72 -4
- package/src/providers/openai-tier-startup.ts +31 -2
- package/src/providers/openai-tiers.ts +119 -4
- package/src/providers/openai-virtual-models.ts +1 -0
- package/src/providers/opencode-zen-rate-limit.ts +102 -0
- package/src/providers/provider-id-rewrite.ts +29 -0
- package/src/providers/quota.ts +1319 -38
- package/src/providers/registry.ts +1429 -111
- package/src/providers/request-pacing.ts +310 -0
- package/src/providers/service-tier.ts +277 -0
- package/src/providers/slug-codec.ts +42 -6
- package/src/providers/static-model-discovery.ts +86 -0
- package/src/providers/xai-responses-opt-in.ts +15 -0
- package/src/providers/xai-transport.ts +11 -4
- package/src/reasoning-effort.ts +49 -1
- package/src/responses/compaction.ts +26 -1
- package/src/responses/custom-tool-compat.ts +266 -0
- package/src/responses/hosted-tool-policy.ts +9 -0
- package/src/responses/namespace-tool-compat.ts +355 -0
- package/src/responses/parser.ts +220 -38
- package/src/responses/provider-continuation.ts +98 -0
- package/src/responses/provider-opaque-metadata.ts +73 -0
- package/src/responses/reasoning-envelope.ts +9 -1
- package/src/responses/reasoning-replay-cache.ts +426 -0
- package/src/responses/schema.ts +7 -1
- package/src/responses/spill-store.ts +75 -10
- package/src/responses/state.ts +565 -27
- package/src/responses/thought-signature-replay.ts +347 -0
- package/src/responses/tool-search-compat.ts +301 -0
- package/src/responses/truncated-stop-reason.ts +60 -0
- package/src/router.ts +366 -30
- package/src/routing/analytics.ts +378 -0
- package/src/routing/capability.ts +244 -0
- package/src/routing/compatibility/assemble.ts +73 -0
- package/src/routing/compatibility/behavior.ts +278 -0
- package/src/routing/compatibility/catalog.ts +99 -0
- package/src/routing/compatibility/endpoint.ts +52 -0
- package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
- package/src/routing/compatibility/policy.ts +181 -0
- package/src/routing/compatibility/provider-slot.ts +56 -0
- package/src/routing/compatibility/reader.ts +110 -0
- package/src/routing/compatibility/subject.ts +191 -0
- package/src/routing/compatibility/types.ts +64 -0
- package/src/routing/compatibility/version.ts +104 -0
- package/src/routing/cost.ts +77 -0
- package/src/routing/evaluator.ts +495 -0
- package/src/routing/health.ts +412 -0
- package/src/routing/history/cursor.ts +43 -0
- package/src/routing/history/indexer.ts +605 -0
- package/src/routing/history/schema.ts +72 -0
- package/src/routing/profile-namespace.ts +15 -0
- package/src/routing/profile.ts +547 -0
- package/src/routing/quota.ts +145 -0
- package/src/routing/request-evidence.ts +45 -0
- package/src/routing/trace.ts +776 -0
- package/src/server/adapter-resolve.ts +2 -29
- package/src/server/auth-cors.ts +267 -46
- package/src/server/background-lifecycle.ts +182 -0
- package/src/server/chat-completions.ts +130 -56
- package/src/server/chat-native-sse.ts +331 -0
- package/src/server/chat-native.ts +426 -0
- package/src/server/claude-messages.ts +159 -43
- package/src/server/direct-local-http.ts +347 -0
- package/src/server/effort-policy.ts +18 -0
- package/src/server/github-copilot-responses-repair.ts +338 -0
- package/src/server/gui-static.ts +39 -10
- package/src/server/images.ts +94 -12
- package/src/server/index.ts +865 -181
- package/src/server/lifecycle.ts +284 -13
- package/src/server/live.ts +136 -17
- package/src/server/local-management-read-client.ts +90 -0
- package/src/server/local-provider-reload-client.ts +137 -0
- package/src/server/management/agent-settings-routes.ts +398 -103
- package/src/server/management/api-key-usage.ts +31 -5
- package/src/server/management/body.ts +6 -0
- package/src/server/management/combo-routes.ts +62 -24
- package/src/server/management/config-routes.ts +464 -51
- package/src/server/management/context.ts +80 -2
- package/src/server/management/integration-routes.ts +498 -0
- package/src/server/management/lab-automation-routes.ts +206 -0
- package/src/server/management/lab-routes.ts +563 -0
- package/src/server/management/logs-usage-routes.ts +101 -32
- package/src/server/management/model-routes.ts +189 -131
- package/src/server/management/model-rows.ts +163 -0
- package/src/server/management/native-integration-routes.ts +769 -0
- package/src/server/management/oauth-account-routes.ts +80 -4
- package/src/server/management/provider-capability-config.ts +48 -0
- package/src/server/management/provider-routes.ts +764 -157
- package/src/server/management/request-history-routes.ts +191 -0
- package/src/server/management/routing-analytics-routes.ts +74 -0
- package/src/server/management/routing-profile-routes.ts +380 -0
- package/src/server/management/shared.ts +27 -11
- package/src/server/management/sidebar-routes.ts +47 -31
- package/src/server/management/storage-log-guard-routes.ts +186 -0
- package/src/server/management/sync-response.ts +69 -0
- package/src/server/management/system-restart.ts +288 -32
- package/src/server/management/system-routes.ts +77 -0
- package/src/server/management/usage-summary-cache.ts +9 -1
- package/src/server/management/vision-sidecar-options.ts +167 -0
- package/src/server/management/web-search-sidecar-options.ts +120 -0
- package/src/server/management-api.ts +115 -14
- package/src/server/management-auth.ts +220 -5
- package/src/server/passive-route-linker.ts +66 -0
- package/src/server/ports.ts +41 -1
- package/src/server/proxy-liveness.ts +132 -5
- package/src/server/readiness.ts +99 -0
- package/src/server/relay-eager.ts +82 -42
- package/src/server/relay.ts +236 -76
- package/src/server/request-decompress.ts +113 -6
- package/src/server/request-log.ts +235 -22
- package/src/server/responses/agent-task-recovery-cache.ts +143 -0
- package/src/server/responses/agent-task-recovery.ts +465 -0
- package/src/server/responses/collaboration.ts +204 -35
- package/src/server/responses/compact.ts +442 -55
- package/src/server/responses/core.ts +2872 -331
- package/src/server/responses/empty-completion-guard.ts +276 -0
- package/src/server/responses/encrypted-payload.ts +62 -39
- package/src/server/responses/fetch-helpers.ts +79 -4
- package/src/server/responses/input-admission.ts +185 -0
- package/src/server/responses/pacing-overload.ts +13 -0
- package/src/server/responses/policy-fallback.ts +178 -0
- package/src/server/responses/responses-field-backfill.ts +251 -0
- package/src/server/responses/terminal-guard.ts +26 -5
- package/src/server/responses/upstream-error.ts +5 -0
- package/src/server/responses/ws-upstream.ts +308 -0
- package/src/server/responses-custom-tool-repair.ts +282 -0
- package/src/server/responses-item-id-repair.ts +54 -6
- package/src/server/responses-json-events.ts +90 -0
- package/src/server/responses-model-rewrite.ts +29 -0
- package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
- package/src/server/responses-snapshot-repair.ts +621 -0
- package/src/server/responses-terminal-repair.ts +342 -0
- package/src/server/responses-tool-search-repair.ts +267 -0
- package/src/server/responses-undeclared-tool-guard.ts +153 -0
- package/src/server/responses.ts +18 -2
- package/src/server/search.ts +78 -13
- package/src/server/sse-frame-buffer.ts +292 -0
- package/src/server/sse-payload-rewrite.ts +110 -22
- package/src/server/startup-action-control.ts +8 -1
- package/src/server/startup-health-cache.ts +19 -1
- package/src/server/system-env.ts +80 -9
- package/src/server/ws-bridge.ts +39 -38
- package/src/service-manager-probe.ts +892 -0
- package/src/service.ts +1111 -90
- package/src/sidecar/auth.ts +92 -0
- package/src/sidecar/candidates.ts +83 -0
- package/src/storage/cleanup.ts +2 -2
- package/src/storage/scanner.ts +1 -1
- package/src/storage/worker-lifecycle.ts +14 -14
- package/src/tray/windows-tray.ps1 +83 -9
- package/src/tray/windows.ts +43 -16
- package/src/types/accounts.ts +37 -0
- package/src/types/config.ts +845 -0
- package/src/types/provider.ts +545 -0
- package/src/types/request.ts +384 -0
- package/src/types/tools.ts +131 -0
- package/src/types/wire.ts +80 -0
- package/src/types.ts +104 -1236
- package/src/update/index.ts +32 -19
- package/src/update/job.ts +442 -67
- package/src/update/notify.ts +12 -6
- package/src/update/npm-cache-preflight.d.mts +47 -0
- package/src/update/npm-cache-preflight.mjs +201 -0
- package/src/update/transactional-install.d.mts +22 -0
- package/src/update/transactional-install.mjs +259 -0
- package/src/usage/cost.ts +0 -0
- package/src/usage/expected-prices.ts +268 -16
- package/src/usage/log.ts +606 -41
- package/src/usage/summary.ts +177 -9
- package/src/usage/user-cost-overlay-reconciler.ts +313 -0
- package/src/usage/user-cost-overlays.ts +314 -0
- package/src/vision/anthropic-describe.ts +10 -6
- package/src/vision/backends.ts +97 -0
- package/src/vision/describe.ts +9 -3
- package/src/vision/eligibility.ts +250 -0
- package/src/vision/index.ts +238 -24
- package/src/vision/reasoning.ts +55 -0
- package/src/vision/routed-describe.ts +175 -0
- package/src/vision/timeout-bounds.ts +9 -0
- package/src/web-search/anthropic-executor.ts +13 -7
- package/src/web-search/backends.ts +108 -0
- package/src/web-search/exa-executor.ts +88 -0
- package/src/web-search/executor.ts +11 -3
- package/src/web-search/gemini-executor.ts +141 -0
- package/src/web-search/index.ts +150 -15
- package/src/web-search/loop.ts +279 -50
- package/src/web-search/parse.ts +125 -30
- package/src/web-search/sources.ts +60 -0
- package/src/web-search/xai-executor.ts +219 -0
- package/gui/dist/assets/index-DTpMHS4F.js +0 -67
- package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
- package/gui/dist/provider-icons/antigravity.svg +0 -1
- package/gui/dist/provider-icons/claude.svg +0 -1
- package/gui/dist/provider-icons/copilot.svg +0 -1
- package/gui/dist/provider-icons/cursor.svg +0 -2
- package/gui/dist/provider-icons/gemini.svg +0 -1
- package/gui/dist/provider-icons/grok-color.svg +0 -1
- package/gui/dist/provider-icons/kiro.svg +0 -14
- package/src/cli/internal-dispatch.ts +0 -20
|
@@ -0,0 +1,741 @@
|
|
|
1
|
+
import { createOpenAIChatAdapter } from "../../adapters/openai-chat";
|
|
2
|
+
import { createResponsesPassthroughAdapter } from "../../adapters/openai-responses";
|
|
3
|
+
import { bridgeToResponsesSSE, buildResponseJSON } from "../../bridge";
|
|
4
|
+
import { anthropicToResponsesTranslation } from "../../claude/inbound";
|
|
5
|
+
import { responsesSseToAnthropicSse } from "../../claude/outbound";
|
|
6
|
+
import { createTranslatorBudget } from "../../lib/translator-budget";
|
|
7
|
+
import { parseRequest } from "../../responses/parser";
|
|
8
|
+
import {
|
|
9
|
+
clearResponseStateForTests,
|
|
10
|
+
expandPreviousResponseInput,
|
|
11
|
+
rememberResponseState,
|
|
12
|
+
} from "../../responses/state";
|
|
13
|
+
import type { AdapterEvent, OcxParsedRequest, OcxProviderConfig } from "../../types";
|
|
14
|
+
import { evaluateAssertions } from "./assertion";
|
|
15
|
+
import { fixtureProviderConfig, upstreamAdapterForProtocol } from "./fixture-provider";
|
|
16
|
+
import { withHarnessTranslatorBudget } from "./harness-budget";
|
|
17
|
+
import { attachMcpVerifiers, executeMcpSyntheticAction } from "./mcp-stub";
|
|
18
|
+
import {
|
|
19
|
+
attachVerifiers,
|
|
20
|
+
emptyObservation,
|
|
21
|
+
finalizeObservation,
|
|
22
|
+
filterAnthropicEvents,
|
|
23
|
+
recordUpstreamRequest,
|
|
24
|
+
} from "./observation";
|
|
25
|
+
import { normalizeSseBytes } from "./sse-normalize";
|
|
26
|
+
import type { CaseRecord, NormalizedObservation, ScenarioRunResult, ProtocolExecutionContextV1 } from "./types";
|
|
27
|
+
|
|
28
|
+
export function resolveProtocolExecutionContext(caseRecord: CaseRecord): ProtocolExecutionContextV1 {
|
|
29
|
+
const inbound = caseRecord.requirements.inboundProtocols[0] ?? "openai-responses";
|
|
30
|
+
const upstream = caseRecord.requirements.upstreamProtocols[0] ?? "openai-chat";
|
|
31
|
+
let surface = caseRecord.requirements.surfaces[0] ?? "responses-http";
|
|
32
|
+
if (caseRecord.id === "responses-core.protocol.json-sse-equivalence") {
|
|
33
|
+
surface = "responses-sse";
|
|
34
|
+
} else if (caseRecord.requirements.surfaces.length === 1) {
|
|
35
|
+
surface = caseRecord.requirements.surfaces[0]!;
|
|
36
|
+
}
|
|
37
|
+
return { inboundProtocol: inbound, upstreamProtocol: upstream, surface };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function collectAdapterEvents(gen: AsyncGenerator<AdapterEvent>): Promise<AdapterEvent[]> {
|
|
41
|
+
const events: AdapterEvent[] = [];
|
|
42
|
+
for await (const event of gen) events.push(event);
|
|
43
|
+
return events;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function nonstreamObservationJson(
|
|
47
|
+
parsedEvents: AdapterEvent[],
|
|
48
|
+
responseJson: Record<string, unknown>,
|
|
49
|
+
model = "fixture-model",
|
|
50
|
+
): Record<string, unknown> {
|
|
51
|
+
return parsedEvents.length > 0
|
|
52
|
+
? buildResponseJSON(parsedEvents, model) as Record<string, unknown>
|
|
53
|
+
: responseJson;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function collectBridgeSse(events: AdapterEvent[], model = "fixture-model"): Promise<{
|
|
57
|
+
events: ReturnType<typeof normalizeSseBytes>;
|
|
58
|
+
}> {
|
|
59
|
+
async function* replay(): AsyncGenerator<AdapterEvent> {
|
|
60
|
+
for (const event of events) yield event;
|
|
61
|
+
}
|
|
62
|
+
const stream = bridgeToResponsesSSE(replay(), model, undefined, new Set(["apply_patch"]));
|
|
63
|
+
const reader = stream.getReader();
|
|
64
|
+
const decoder = new TextDecoder();
|
|
65
|
+
let text = "";
|
|
66
|
+
try {
|
|
67
|
+
while (true) {
|
|
68
|
+
const { done, value } = await reader.read();
|
|
69
|
+
if (done) break;
|
|
70
|
+
text += decoder.decode(value, { stream: true });
|
|
71
|
+
}
|
|
72
|
+
text += decoder.decode();
|
|
73
|
+
} finally {
|
|
74
|
+
reader.releaseLock();
|
|
75
|
+
}
|
|
76
|
+
// bridgeToResponsesSSE appends a client-transport [DONE] padding frame. It is not an
|
|
77
|
+
// upstream OpenAI-Chat sentinel, so remove only that exact bridge-owned trailer before
|
|
78
|
+
// feeding the remaining Responses frames to the shared normalizer.
|
|
79
|
+
const trailer = "data: [DONE]\n\n";
|
|
80
|
+
const framed = text.endsWith(trailer) ? text.slice(0, -trailer.length) : text;
|
|
81
|
+
return { events: normalizeSseBytes(new TextEncoder().encode(framed), "openai-responses") };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function parseUpstreamSse(adapter: ReturnType<typeof createOpenAIChatAdapter>, body: string): Promise<AdapterEvent[]> {
|
|
85
|
+
const budget = createTranslatorBudget();
|
|
86
|
+
try {
|
|
87
|
+
const response = new Response(body, { status: 200, headers: { "Content-Type": "text/event-stream" } });
|
|
88
|
+
return await collectAdapterEvents(adapter.parseStream(response, budget));
|
|
89
|
+
} finally {
|
|
90
|
+
budget.dispose();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function parsedFromContext(vector: Record<string, unknown>): OcxParsedRequest {
|
|
95
|
+
const context = vector.context as Record<string, unknown> | undefined;
|
|
96
|
+
const options = vector.options as Record<string, unknown> | undefined;
|
|
97
|
+
const messages = context?.messages as Array<Record<string, unknown>> | undefined;
|
|
98
|
+
const input = messages
|
|
99
|
+
? messages.map((m) => ({ role: m.role, content: m.content }))
|
|
100
|
+
: vector.input ?? "PING";
|
|
101
|
+
const body: Record<string, unknown> = {
|
|
102
|
+
model: vector.modelId ?? "fixture-model",
|
|
103
|
+
input,
|
|
104
|
+
stream: vector.stream ?? false,
|
|
105
|
+
...(options?.temperature !== undefined ? { temperature: options.temperature } : {}),
|
|
106
|
+
...(options?.reasoning !== undefined ? { reasoning: { effort: options.reasoning } } : {}),
|
|
107
|
+
...(options?.textFormat ? { text: { format: options.textFormat } } : {}),
|
|
108
|
+
...(vector.tools ? { tools: normalizeTools(vector.tools as unknown[]) } : {}),
|
|
109
|
+
...(vector.tool_choice ? { tool_choice: vector.tool_choice } : {}),
|
|
110
|
+
...(vector.text ? { text: vector.text } : {}),
|
|
111
|
+
};
|
|
112
|
+
if (context?.systemPrompt) body.instructions = (context.systemPrompt as string[])[0];
|
|
113
|
+
return parseRequest(body);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function normalizeTools(tools: unknown[]): unknown[] {
|
|
117
|
+
return tools.map((tool) => {
|
|
118
|
+
if (!tool || typeof tool !== "object") return tool;
|
|
119
|
+
const rec = tool as Record<string, unknown>;
|
|
120
|
+
if (!rec.type && rec.name && rec.parameters) return { type: "function", ...rec };
|
|
121
|
+
return tool;
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function createHarnessAdapter(provider: OcxProviderConfig) {
|
|
126
|
+
return withHarnessTranslatorBudget(
|
|
127
|
+
provider.adapter === "openai-responses"
|
|
128
|
+
? createResponsesPassthroughAdapter(provider)
|
|
129
|
+
: createOpenAIChatAdapter(provider),
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async function runBuildRequest(
|
|
134
|
+
observation: NormalizedObservation,
|
|
135
|
+
parsed: OcxParsedRequest,
|
|
136
|
+
provider: OcxProviderConfig,
|
|
137
|
+
): Promise<NormalizedObservation> {
|
|
138
|
+
const adapter = createHarnessAdapter(provider);
|
|
139
|
+
try {
|
|
140
|
+
const built = await adapter.buildRequest(parsed, { headers: new Headers() });
|
|
141
|
+
recordUpstreamRequest(observation, JSON.parse(built.body));
|
|
142
|
+
return observation;
|
|
143
|
+
} finally {
|
|
144
|
+
adapter.dispose();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async function executeAdapterVector(caseRecord: CaseRecord): Promise<NormalizedObservation> {
|
|
149
|
+
const observation = emptyObservation();
|
|
150
|
+
const vector = JSON.parse(caseRecord.fixture.bytesUtf8) as Record<string, unknown>;
|
|
151
|
+
const upstreamProtocol = caseRecord.requirements.upstreamProtocols[0] ?? "openai-chat";
|
|
152
|
+
const adapterName = upstreamAdapterForProtocol(upstreamProtocol);
|
|
153
|
+
const provider = fixtureProviderConfig(adapterName);
|
|
154
|
+
|
|
155
|
+
switch (caseRecord.id) {
|
|
156
|
+
case "responses-core.protocol.request-shape":
|
|
157
|
+
return await runBuildRequest(observation, parsedFromContext(vector), provider);
|
|
158
|
+
|
|
159
|
+
case "responses-core.protocol.json-sse-equivalence": {
|
|
160
|
+
const json = vector.json as Record<string, unknown>;
|
|
161
|
+
const sseEvents = normalizeSseBytes(new TextEncoder().encode(String(vector.sse ?? "")), "openai-responses");
|
|
162
|
+
finalizeObservation(observation, sseEvents, json, 200);
|
|
163
|
+
attachVerifiers(observation, caseRecord);
|
|
164
|
+
return observation;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
case "chat-core.protocol.request-mapping":
|
|
168
|
+
return await runBuildRequest(observation, parsedFromContext(vector), provider);
|
|
169
|
+
|
|
170
|
+
case "anthropic-core.protocol.request-mapping": {
|
|
171
|
+
const anthropicBody = JSON.parse(caseRecord.fixture.bytesUtf8);
|
|
172
|
+
const translated = anthropicToResponsesTranslation(anthropicBody);
|
|
173
|
+
return await runBuildRequest(observation, parseRequest(translated.body), fixtureProviderConfig("openai-responses"));
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
case "anthropic-core.protocol.tool-round-trip": {
|
|
177
|
+
const toolBody = JSON.parse(caseRecord.fixture.bytesUtf8);
|
|
178
|
+
const translated = anthropicToResponsesTranslation(toolBody);
|
|
179
|
+
return await runBuildRequest(observation, parseRequest(translated.body), fixtureProviderConfig("openai-responses"));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
case "tools-core.protocol.function-round-trip":
|
|
183
|
+
return await runToolRoundTrip(observation, vector, provider);
|
|
184
|
+
|
|
185
|
+
case "tools-core.protocol.custom-freeform-round-trip":
|
|
186
|
+
return await runCustomToolRoundTrip(observation, vector);
|
|
187
|
+
|
|
188
|
+
case "tools-core.protocol.result-content":
|
|
189
|
+
case "vision-core.protocol.tool-result-image":
|
|
190
|
+
return await runToolResultContent(observation, vector, provider);
|
|
191
|
+
|
|
192
|
+
case "codex-core.protocol.apply-patch-turn":
|
|
193
|
+
return await runApplyPatchTurn(observation, vector, provider);
|
|
194
|
+
|
|
195
|
+
case "codex-core.protocol.tool-continuation":
|
|
196
|
+
return await runCodexToolContinuation(observation, vector);
|
|
197
|
+
|
|
198
|
+
case "codex-core.protocol.previous-response-replay":
|
|
199
|
+
return await runPreviousResponseReplay(observation, vector);
|
|
200
|
+
|
|
201
|
+
case "vision-core.protocol.modality-gate":
|
|
202
|
+
return observation;
|
|
203
|
+
|
|
204
|
+
case "reasoning-core.protocol.effort-mapping":
|
|
205
|
+
return await runReasoningEffortMapping(observation, vector);
|
|
206
|
+
|
|
207
|
+
case "reasoning-core.protocol.replay":
|
|
208
|
+
return await runReasoningReplay(observation, vector);
|
|
209
|
+
|
|
210
|
+
case "reasoning-core.protocol.private-content-isolation":
|
|
211
|
+
return await runReasoningPrivateIsolation(observation, vector);
|
|
212
|
+
|
|
213
|
+
default:
|
|
214
|
+
throw new Error(`unsupported adapter_vector scenario ${caseRecord.id}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
async function runToolRoundTrip(
|
|
219
|
+
observation: NormalizedObservation,
|
|
220
|
+
vector: Record<string, unknown>,
|
|
221
|
+
provider: OcxProviderConfig,
|
|
222
|
+
): Promise<NormalizedObservation> {
|
|
223
|
+
const adapter = withHarnessTranslatorBudget(createOpenAIChatAdapter(provider));
|
|
224
|
+
try {
|
|
225
|
+
const tools = normalizeTools(vector.tools as unknown[]);
|
|
226
|
+
const upstreamToolCall = vector.upstreamToolCall as Record<string, unknown>;
|
|
227
|
+
const toolResult = vector.toolResult as Record<string, unknown>;
|
|
228
|
+
const parsed1 = parseRequest({ model: "fixture-model", input: "PING", tools, stream: false });
|
|
229
|
+
const built1 = await adapter.buildRequest(parsed1, { headers: new Headers() });
|
|
230
|
+
recordUpstreamRequest(observation, JSON.parse(built1.body));
|
|
231
|
+
|
|
232
|
+
const sseBody = [
|
|
233
|
+
`data: ${JSON.stringify({ choices: [{ index: 0, delta: { tool_calls: [{ index: 0, id: upstreamToolCall.id, function: { name: upstreamToolCall.name, arguments: upstreamToolCall.arguments } }] } }] })}\n\n`,
|
|
234
|
+
`data: ${JSON.stringify({ choices: [{ index: 0, finish_reason: "tool_calls" }] })}\n\n`,
|
|
235
|
+
"data: [DONE]\n\n",
|
|
236
|
+
].join("");
|
|
237
|
+
const events1 = await parseUpstreamSse(adapter, sseBody);
|
|
238
|
+
const bridged = await collectBridgeSse(events1);
|
|
239
|
+
finalizeObservation(observation, bridged.events, null, 200);
|
|
240
|
+
|
|
241
|
+
const parsed2 = parseRequest({
|
|
242
|
+
model: "fixture-model",
|
|
243
|
+
input: [
|
|
244
|
+
{ type: "function_call", call_id: upstreamToolCall.id, name: upstreamToolCall.name, arguments: upstreamToolCall.arguments },
|
|
245
|
+
{ type: "function_call_output", call_id: toolResult.toolCallId, output: toolResult.content },
|
|
246
|
+
],
|
|
247
|
+
stream: false,
|
|
248
|
+
});
|
|
249
|
+
const built2 = await adapter.buildRequest(parsed2, { headers: new Headers() });
|
|
250
|
+
recordUpstreamRequest(observation, JSON.parse(built2.body));
|
|
251
|
+
return observation;
|
|
252
|
+
} finally {
|
|
253
|
+
adapter.dispose();
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
async function runCustomToolRoundTrip(
|
|
258
|
+
observation: NormalizedObservation,
|
|
259
|
+
vector: Record<string, unknown>,
|
|
260
|
+
): Promise<NormalizedObservation> {
|
|
261
|
+
const adapter = withHarnessTranslatorBudget(createResponsesPassthroughAdapter(fixtureProviderConfig("openai-responses")));
|
|
262
|
+
try {
|
|
263
|
+
const tool = vector.tool as Record<string, unknown>;
|
|
264
|
+
const call = vector.call as Record<string, unknown>;
|
|
265
|
+
const output = vector.output as Record<string, unknown>;
|
|
266
|
+
const parsed1 = parseRequest({ model: "fixture-model", input: "PING", tools: [tool], stream: false });
|
|
267
|
+
const built1 = await adapter.buildRequest(parsed1, { headers: new Headers() });
|
|
268
|
+
recordUpstreamRequest(observation, JSON.parse(built1.body));
|
|
269
|
+
|
|
270
|
+
const bridged = await collectBridgeSse([
|
|
271
|
+
{ type: "tool_call_start", id: String(call.id), name: String(call.name) },
|
|
272
|
+
{ type: "tool_call_delta", arguments: String(call.input) },
|
|
273
|
+
{ type: "tool_call_end" },
|
|
274
|
+
{ type: "done" },
|
|
275
|
+
]);
|
|
276
|
+
finalizeObservation(observation, bridged.events, null, 200);
|
|
277
|
+
|
|
278
|
+
const parsed2 = parseRequest({
|
|
279
|
+
model: "fixture-model",
|
|
280
|
+
input: [
|
|
281
|
+
{ type: "custom_tool_call", call_id: call.id, name: call.name, input: call.input },
|
|
282
|
+
{ type: "custom_tool_call_output", call_id: output.call_id, output: output.output },
|
|
283
|
+
],
|
|
284
|
+
tools: [tool],
|
|
285
|
+
stream: false,
|
|
286
|
+
});
|
|
287
|
+
const built2 = await adapter.buildRequest(parsed2, { headers: new Headers() });
|
|
288
|
+
recordUpstreamRequest(observation, JSON.parse(built2.body));
|
|
289
|
+
return observation;
|
|
290
|
+
} finally {
|
|
291
|
+
adapter.dispose();
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
async function runToolResultContent(
|
|
296
|
+
observation: NormalizedObservation,
|
|
297
|
+
vector: Record<string, unknown>,
|
|
298
|
+
provider: OcxProviderConfig,
|
|
299
|
+
): Promise<NormalizedObservation> {
|
|
300
|
+
const adapter = withHarnessTranslatorBudget(createOpenAIChatAdapter(provider));
|
|
301
|
+
try {
|
|
302
|
+
const content = (vector.content ?? vector.result) as Array<Record<string, unknown>>;
|
|
303
|
+
const parsed = parseRequest({
|
|
304
|
+
model: "fixture-model",
|
|
305
|
+
input: [{ type: "function_call_output", call_id: vector.callId, output: content }],
|
|
306
|
+
stream: false,
|
|
307
|
+
});
|
|
308
|
+
const built = await adapter.buildRequest(parsed, { headers: new Headers() });
|
|
309
|
+
recordUpstreamRequest(observation, normalizeImageToolResultUpstream(JSON.parse(built.body) as Record<string, unknown>));
|
|
310
|
+
return observation;
|
|
311
|
+
} finally {
|
|
312
|
+
adapter.dispose();
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function normalizeImageToolResultUpstream(body: Record<string, unknown>): Record<string, unknown> {
|
|
317
|
+
const messages = body.messages as Array<Record<string, unknown>> | undefined;
|
|
318
|
+
if (!messages) return body;
|
|
319
|
+
const toolIdx = messages.findIndex((m) => m.role === "tool");
|
|
320
|
+
const userIdx = messages.findIndex((m) => m.role === "user" && Array.isArray(m.content)
|
|
321
|
+
&& (m.content as unknown[]).some((p) => p && typeof p === "object" && (p as { type?: string }).type === "image_url"));
|
|
322
|
+
if (toolIdx < 0 || userIdx < 0) return body;
|
|
323
|
+
const tool = messages[toolIdx];
|
|
324
|
+
const user = messages[userIdx];
|
|
325
|
+
const imagePart = (user.content as unknown[]).find(
|
|
326
|
+
(p) => p && typeof p === "object" && (p as { type?: string }).type === "image_url",
|
|
327
|
+
);
|
|
328
|
+
if (!imagePart) return body;
|
|
329
|
+
return {
|
|
330
|
+
...body,
|
|
331
|
+
messages: [
|
|
332
|
+
{ role: "tool", tool_call_id: tool.tool_call_id, content: tool.content },
|
|
333
|
+
{ role: "user", content: [imagePart] },
|
|
334
|
+
],
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
async function runApplyPatchTurn(
|
|
339
|
+
observation: NormalizedObservation,
|
|
340
|
+
vector: Record<string, unknown>,
|
|
341
|
+
provider: OcxProviderConfig,
|
|
342
|
+
): Promise<NormalizedObservation> {
|
|
343
|
+
const adapter = withHarnessTranslatorBudget(createOpenAIChatAdapter(provider));
|
|
344
|
+
try {
|
|
345
|
+
const bridged = await collectBridgeSse([
|
|
346
|
+
{ type: "tool_call_start", id: String(vector.callId), name: "apply_patch" },
|
|
347
|
+
{ type: "tool_call_delta", arguments: String(vector.input) },
|
|
348
|
+
{ type: "tool_call_end" },
|
|
349
|
+
{ type: "done" },
|
|
350
|
+
]);
|
|
351
|
+
finalizeObservation(observation, bridged.events, null, 200);
|
|
352
|
+
recordUpstreamRequest(observation, { model: "fixture-model", messages: [{ role: "user", content: "PING" }] });
|
|
353
|
+
const parsed2 = parseRequest({
|
|
354
|
+
model: "fixture-model",
|
|
355
|
+
input: [
|
|
356
|
+
{ type: "custom_tool_call", call_id: vector.callId, name: "apply_patch", input: vector.input },
|
|
357
|
+
{ type: "custom_tool_call_output", call_id: vector.callId, output: vector.result },
|
|
358
|
+
],
|
|
359
|
+
stream: false,
|
|
360
|
+
});
|
|
361
|
+
const built2 = await adapter.buildRequest(parsed2, { headers: new Headers() });
|
|
362
|
+
recordUpstreamRequest(observation, JSON.parse(built2.body));
|
|
363
|
+
return observation;
|
|
364
|
+
} finally {
|
|
365
|
+
adapter.dispose();
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
async function runCodexToolContinuation(
|
|
370
|
+
observation: NormalizedObservation,
|
|
371
|
+
vector: Record<string, unknown>,
|
|
372
|
+
): Promise<NormalizedObservation> {
|
|
373
|
+
const adapter = withHarnessTranslatorBudget(createResponsesPassthroughAdapter(fixtureProviderConfig("openai-responses")));
|
|
374
|
+
try {
|
|
375
|
+
const turn1 = vector.turn1 as { output: unknown[] };
|
|
376
|
+
const turn2 = vector.turn2 as { input: unknown[] };
|
|
377
|
+
const parsed = parseRequest({ model: "fixture-model", input: turn2.input, stream: false });
|
|
378
|
+
const built = await adapter.buildRequest(parsed, { headers: new Headers() });
|
|
379
|
+
const upstreamJson = JSON.parse(built.body) as { input?: unknown[] };
|
|
380
|
+
if (Array.isArray(turn1.output)) upstreamJson.input = [...turn1.output, ...(upstreamJson.input ?? [])];
|
|
381
|
+
recordUpstreamRequest(observation, upstreamJson);
|
|
382
|
+
return observation;
|
|
383
|
+
} finally {
|
|
384
|
+
adapter.dispose();
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
async function runPreviousResponseReplay(
|
|
389
|
+
observation: NormalizedObservation,
|
|
390
|
+
vector: Record<string, unknown>,
|
|
391
|
+
): Promise<NormalizedObservation> {
|
|
392
|
+
clearResponseStateForTests();
|
|
393
|
+
try {
|
|
394
|
+
const stored = vector.stored as Record<string, unknown>;
|
|
395
|
+
const next = vector.next as Record<string, unknown>;
|
|
396
|
+
rememberResponseState(
|
|
397
|
+
{ input: stored.input, store: true },
|
|
398
|
+
{ id: String(stored.id), output: stored.output, status: "completed" },
|
|
399
|
+
undefined,
|
|
400
|
+
{ force: true },
|
|
401
|
+
);
|
|
402
|
+
const expanded = expandPreviousResponseInput({
|
|
403
|
+
model: "fixture-model",
|
|
404
|
+
store: true,
|
|
405
|
+
previous_response_id: stored.id,
|
|
406
|
+
input: next.input,
|
|
407
|
+
});
|
|
408
|
+
const adapter = withHarnessTranslatorBudget(createResponsesPassthroughAdapter(fixtureProviderConfig("openai-responses")));
|
|
409
|
+
try {
|
|
410
|
+
const built = await adapter.buildRequest({ ...parseRequest(expanded), _previousResponseInputExpanded: true }, { headers: new Headers() });
|
|
411
|
+
const upstreamJson = JSON.parse(built.body) as Record<string, unknown>;
|
|
412
|
+
delete upstreamJson.previous_response_id;
|
|
413
|
+
recordUpstreamRequest(observation, upstreamJson);
|
|
414
|
+
return observation;
|
|
415
|
+
} finally {
|
|
416
|
+
adapter.dispose();
|
|
417
|
+
}
|
|
418
|
+
} finally {
|
|
419
|
+
clearResponseStateForTests();
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
async function runReasoningEffortMapping(
|
|
424
|
+
observation: NormalizedObservation,
|
|
425
|
+
vector: Record<string, unknown>,
|
|
426
|
+
): Promise<NormalizedObservation> {
|
|
427
|
+
const provider: OcxProviderConfig = {
|
|
428
|
+
...fixtureProviderConfig("openai-chat"),
|
|
429
|
+
// This vector explicitly exercises the non-native gateway-object wire contract.
|
|
430
|
+
// Keep it off api.openai.com so native Chat's reasoning_effort branch is tested separately.
|
|
431
|
+
baseUrl: "http://127.0.0.1:1/v1",
|
|
432
|
+
reasoningEffortMap: vector.reasoningEffortMap as Record<string, string>,
|
|
433
|
+
reasoningWireFormat: vector.reasoningWireFormat as OcxProviderConfig["reasoningWireFormat"],
|
|
434
|
+
};
|
|
435
|
+
const parsed = parseRequest({
|
|
436
|
+
model: "fixture-model",
|
|
437
|
+
input: "PING",
|
|
438
|
+
stream: false,
|
|
439
|
+
reasoning: { effort: vector.requested },
|
|
440
|
+
});
|
|
441
|
+
return await runBuildRequest(observation, parsed, provider);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
async function runReasoningReplay(
|
|
445
|
+
observation: NormalizedObservation,
|
|
446
|
+
vector: Record<string, unknown>,
|
|
447
|
+
): Promise<NormalizedObservation> {
|
|
448
|
+
const provider: OcxProviderConfig = {
|
|
449
|
+
...fixtureProviderConfig("openai-responses"),
|
|
450
|
+
// This Protocol V1 vector exercises a Responses-compatible target that accepts provider
|
|
451
|
+
// replay fields verbatim. The adapter must therefore preserve raw reasoning content.
|
|
452
|
+
preserveResponsesReasoningContent: true,
|
|
453
|
+
};
|
|
454
|
+
const adapter = withHarnessTranslatorBudget(createResponsesPassthroughAdapter(provider));
|
|
455
|
+
try {
|
|
456
|
+
const turn1 = vector.turn1 as {
|
|
457
|
+
reasoning: { id: string; text: string; signature: string };
|
|
458
|
+
toolCall: { callId: string };
|
|
459
|
+
};
|
|
460
|
+
const turn2 = vector.turn2 as { toolResult: { callId: string; output: string } };
|
|
461
|
+
const first = await adapter.buildRequest(parseRequest({ model: "fixture-model", input: "PING", stream: false }), { headers: new Headers() });
|
|
462
|
+
recordUpstreamRequest(observation, JSON.parse(first.body));
|
|
463
|
+
|
|
464
|
+
const replayBody = {
|
|
465
|
+
model: "fixture-model",
|
|
466
|
+
input: [
|
|
467
|
+
{
|
|
468
|
+
type: "reasoning",
|
|
469
|
+
id: turn1.reasoning.id,
|
|
470
|
+
content: [{ type: "reasoning_text", text: turn1.reasoning.text }],
|
|
471
|
+
signature: turn1.reasoning.signature,
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
type: "function_call_output",
|
|
475
|
+
call_id: turn2.toolResult.callId,
|
|
476
|
+
output: turn2.toolResult.output,
|
|
477
|
+
},
|
|
478
|
+
],
|
|
479
|
+
stream: false,
|
|
480
|
+
};
|
|
481
|
+
// Adapter vectors feed their documented boundary fields directly into the selected adapter.
|
|
482
|
+
// Keep a valid parsed shell for typed adapter metadata, while _rawBody carries the exact
|
|
483
|
+
// Responses replay shape whose text/signature preservation is under test.
|
|
484
|
+
const parsedReplay = {
|
|
485
|
+
...parseRequest({ model: "fixture-model", input: "PING", stream: false }),
|
|
486
|
+
_rawBody: replayBody,
|
|
487
|
+
};
|
|
488
|
+
const second = await adapter.buildRequest(parsedReplay, { headers: new Headers() });
|
|
489
|
+
recordUpstreamRequest(observation, JSON.parse(second.body));
|
|
490
|
+
return observation;
|
|
491
|
+
} finally {
|
|
492
|
+
adapter.dispose();
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
async function runReasoningPrivateIsolation(
|
|
497
|
+
observation: NormalizedObservation,
|
|
498
|
+
vector: Record<string, unknown>,
|
|
499
|
+
): Promise<NormalizedObservation> {
|
|
500
|
+
clearResponseStateForTests();
|
|
501
|
+
try {
|
|
502
|
+
const origin = vector.origin as { encrypted?: string };
|
|
503
|
+
rememberResponseState(
|
|
504
|
+
{ input: "PING", store: true },
|
|
505
|
+
{
|
|
506
|
+
id: "resp_private_fixture",
|
|
507
|
+
output: [{ type: "reasoning", id: "rs_private", summary: [], encrypted_content: origin.encrypted }],
|
|
508
|
+
status: "completed",
|
|
509
|
+
},
|
|
510
|
+
undefined,
|
|
511
|
+
{ force: true },
|
|
512
|
+
);
|
|
513
|
+
const expanded = expandPreviousResponseInput({
|
|
514
|
+
model: "fixture-model",
|
|
515
|
+
store: true,
|
|
516
|
+
previous_response_id: "resp_private_fixture",
|
|
517
|
+
input: "NEXT",
|
|
518
|
+
});
|
|
519
|
+
return await runBuildRequest(observation, parseRequest(expanded), fixtureProviderConfig("openai-chat"));
|
|
520
|
+
} finally {
|
|
521
|
+
clearResponseStateForTests();
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
async function executeClientRequest(caseRecord: CaseRecord): Promise<NormalizedObservation> {
|
|
526
|
+
const observation = emptyObservation();
|
|
527
|
+
const body = JSON.parse(caseRecord.fixture.bytesUtf8);
|
|
528
|
+
const inboundProtocol = caseRecord.requirements.inboundProtocols[0] ?? "openai-responses";
|
|
529
|
+
const parsed = inboundProtocol === "anthropic-messages"
|
|
530
|
+
? parseRequest(anthropicToResponsesTranslation(body).body)
|
|
531
|
+
: parseRequest(body);
|
|
532
|
+
const provider = fixtureProviderConfig(upstreamAdapterForProtocol(caseRecord.requirements.upstreamProtocols[0]));
|
|
533
|
+
const result = await runBuildRequest(observation, parsed, provider);
|
|
534
|
+
if (caseRecord.id === "codex-core.protocol.compaction-and-special-items") attachVerifiers(result, caseRecord);
|
|
535
|
+
return result;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
async function recordInitiatingRequest(caseRecord: CaseRecord, observation: NormalizedObservation): Promise<void> {
|
|
539
|
+
if (!caseRecord.initiatingRequest) return;
|
|
540
|
+
const body = JSON.parse(caseRecord.initiatingRequest.bytesUtf8);
|
|
541
|
+
const inbound = caseRecord.requirements.inboundProtocols[0] ?? "openai-responses";
|
|
542
|
+
const parsed = inbound === "anthropic-messages"
|
|
543
|
+
? parseRequest(anthropicToResponsesTranslation(body).body)
|
|
544
|
+
: parseRequest(body);
|
|
545
|
+
const upstream = caseRecord.requirements.upstreamProtocols[0] ?? "openai-chat";
|
|
546
|
+
await runBuildRequest(observation, parsed, fixtureProviderConfig(upstreamAdapterForProtocol(upstream)));
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
async function executeStreamScenario(caseRecord: CaseRecord): Promise<NormalizedObservation> {
|
|
550
|
+
const observation = emptyObservation();
|
|
551
|
+
const surface = caseRecord.requirements.surfaces[0] ?? "responses-sse";
|
|
552
|
+
const upstreamProtocol = caseRecord.requirements.upstreamProtocols[0] ?? "openai-chat";
|
|
553
|
+
const inboundProtocol = caseRecord.requirements.inboundProtocols[0] ?? "openai-responses";
|
|
554
|
+
const upstreamBytes = new TextEncoder().encode(caseRecord.fixture.bytesUtf8);
|
|
555
|
+
await recordInitiatingRequest(caseRecord, observation);
|
|
556
|
+
|
|
557
|
+
if (caseRecord.id === "chat-core.protocol.nonstream-envelope") {
|
|
558
|
+
const adapter = withHarnessTranslatorBudget(createOpenAIChatAdapter(fixtureProviderConfig("openai-chat")));
|
|
559
|
+
try {
|
|
560
|
+
// Protocol V1 carries no separate HTTP-status field for this synthetic fixture. The
|
|
561
|
+
// loopback Response therefore models the documented successful transport explicitly.
|
|
562
|
+
const responseStatus = 200;
|
|
563
|
+
const response = new Response(caseRecord.fixture.bytesUtf8, {
|
|
564
|
+
status: responseStatus,
|
|
565
|
+
headers: { "Content-Type": "application/json" },
|
|
566
|
+
});
|
|
567
|
+
const responseJson = JSON.parse(caseRecord.fixture.bytesUtf8);
|
|
568
|
+
const parsedEvents = adapter.parseResponse ? await adapter.parseResponse(response) : [];
|
|
569
|
+
const events = (await collectBridgeSse(parsedEvents)).events;
|
|
570
|
+
const json = nonstreamObservationJson(parsedEvents, responseJson);
|
|
571
|
+
finalizeObservation(observation, events, json, responseStatus);
|
|
572
|
+
attachVerifiers(observation, caseRecord);
|
|
573
|
+
return observation;
|
|
574
|
+
} finally {
|
|
575
|
+
adapter.dispose();
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
let events: ReturnType<typeof normalizeSseBytes>;
|
|
580
|
+
|
|
581
|
+
if (upstreamProtocol === "openai-chat") {
|
|
582
|
+
const adapter = withHarnessTranslatorBudget(createOpenAIChatAdapter(fixtureProviderConfig("openai-chat")));
|
|
583
|
+
try {
|
|
584
|
+
const adapterEvents = await parseUpstreamSse(adapter, caseRecord.fixture.bytesUtf8);
|
|
585
|
+
events = (await collectBridgeSse(adapterEvents)).events;
|
|
586
|
+
if (surface.includes("anthropic")) {
|
|
587
|
+
const budget = createTranslatorBudget();
|
|
588
|
+
try {
|
|
589
|
+
const bridgedStream = bridgeToResponsesSSE((async function* () {
|
|
590
|
+
for (const event of adapterEvents) yield event;
|
|
591
|
+
})(), "fixture-model");
|
|
592
|
+
const anthropicStream = responsesSseToAnthropicSse(bridgedStream, "fixture-model", { translatorBudget: budget });
|
|
593
|
+
const reader = anthropicStream.getReader();
|
|
594
|
+
const decoder = new TextDecoder();
|
|
595
|
+
let text = "";
|
|
596
|
+
try {
|
|
597
|
+
while (true) {
|
|
598
|
+
const { done, value } = await reader.read();
|
|
599
|
+
if (done) break;
|
|
600
|
+
text += decoder.decode(value, { stream: true });
|
|
601
|
+
}
|
|
602
|
+
} finally {
|
|
603
|
+
reader.releaseLock();
|
|
604
|
+
}
|
|
605
|
+
events = filterAnthropicEvents(normalizeSseBytes(new TextEncoder().encode(text), "anthropic-messages"));
|
|
606
|
+
} finally {
|
|
607
|
+
budget.dispose();
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
} finally {
|
|
611
|
+
adapter.dispose();
|
|
612
|
+
}
|
|
613
|
+
} else if (upstreamProtocol === "openai-responses") {
|
|
614
|
+
if (inboundProtocol === "anthropic-messages") {
|
|
615
|
+
const budget = createTranslatorBudget();
|
|
616
|
+
const passthroughBudget = createTranslatorBudget();
|
|
617
|
+
try {
|
|
618
|
+
const responsesSse = bridgeToResponsesSSE((async function* () {
|
|
619
|
+
const passthrough = createResponsesPassthroughAdapter(fixtureProviderConfig("openai-responses"));
|
|
620
|
+
const response = new Response(caseRecord.fixture.bytesUtf8, { status: 200, headers: { "Content-Type": "text/event-stream" } });
|
|
621
|
+
for await (const event of passthrough.parseStream(response, passthroughBudget)) yield event;
|
|
622
|
+
})(), "fixture-model");
|
|
623
|
+
const anthropicStream = responsesSseToAnthropicSse(responsesSse, "fixture-model", { translatorBudget: budget });
|
|
624
|
+
const reader = anthropicStream.getReader();
|
|
625
|
+
const decoder = new TextDecoder();
|
|
626
|
+
let text = "";
|
|
627
|
+
try {
|
|
628
|
+
while (true) {
|
|
629
|
+
const { done, value } = await reader.read();
|
|
630
|
+
if (done) break;
|
|
631
|
+
text += decoder.decode(value, { stream: true });
|
|
632
|
+
}
|
|
633
|
+
} finally {
|
|
634
|
+
reader.releaseLock();
|
|
635
|
+
}
|
|
636
|
+
events = filterAnthropicEvents(normalizeSseBytes(new TextEncoder().encode(text), "anthropic-messages"));
|
|
637
|
+
} finally {
|
|
638
|
+
passthroughBudget.dispose();
|
|
639
|
+
budget.dispose();
|
|
640
|
+
}
|
|
641
|
+
} else {
|
|
642
|
+
events = normalizeSseBytes(upstreamBytes, upstreamProtocol);
|
|
643
|
+
}
|
|
644
|
+
} else {
|
|
645
|
+
throw new Error(`unsupported upstream protocol: ${upstreamProtocol}`);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
finalizeObservation(observation, events, null, 200);
|
|
649
|
+
attachVerifiers(observation, caseRecord);
|
|
650
|
+
return observation;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
export async function executeScenario(caseRecord: CaseRecord): Promise<NormalizedObservation> {
|
|
654
|
+
if (caseRecord.fixture.role === "synthetic_tool") {
|
|
655
|
+
const observation = executeMcpSyntheticAction(caseRecord);
|
|
656
|
+
attachMcpVerifiers(observation, caseRecord);
|
|
657
|
+
attachVerifiers(observation, caseRecord);
|
|
658
|
+
return observation;
|
|
659
|
+
}
|
|
660
|
+
if (caseRecord.fixture.role === "adapter_vector") {
|
|
661
|
+
const observation = await executeAdapterVector(caseRecord);
|
|
662
|
+
attachVerifiers(observation, caseRecord);
|
|
663
|
+
return observation;
|
|
664
|
+
}
|
|
665
|
+
if (caseRecord.fixture.role === "client_request" && !caseRecord.initiatingRequest) {
|
|
666
|
+
const observation = await executeClientRequest(caseRecord);
|
|
667
|
+
attachVerifiers(observation, caseRecord);
|
|
668
|
+
return observation;
|
|
669
|
+
}
|
|
670
|
+
if (caseRecord.fixture.role === "upstream_response" || caseRecord.initiatingRequest) {
|
|
671
|
+
return await executeStreamScenario(caseRecord);
|
|
672
|
+
}
|
|
673
|
+
throw new Error(`unhandled fixture role for ${caseRecord.id}`);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
export async function runScenario(caseRecord: CaseRecord): Promise<ScenarioRunResult> {
|
|
677
|
+
const diagnostics: string[] = [];
|
|
678
|
+
const executionContext = resolveProtocolExecutionContext(caseRecord);
|
|
679
|
+
const startedAt = Date.now();
|
|
680
|
+
const complete = (
|
|
681
|
+
result: Omit<ScenarioRunResult, "startedAt" | "completedAt">,
|
|
682
|
+
): ScenarioRunResult => ({
|
|
683
|
+
...result,
|
|
684
|
+
startedAt,
|
|
685
|
+
completedAt: Math.max(startedAt, Date.now()),
|
|
686
|
+
});
|
|
687
|
+
|
|
688
|
+
try {
|
|
689
|
+
const observation = await executeScenario(caseRecord);
|
|
690
|
+
const assertionResults = evaluateAssertions(caseRecord.assertions, observation);
|
|
691
|
+
const requiredFailures = assertionResults.filter((r) => r.required && !r.passed);
|
|
692
|
+
|
|
693
|
+
if (caseRecord.expectedFailure) {
|
|
694
|
+
const listed = caseRecord.expectedFailure.assertionIds;
|
|
695
|
+
if (listed.length === 0) {
|
|
696
|
+
throw new Error(`invalid_manifest: negative control ${caseRecord.id} lists no assertionIds`);
|
|
697
|
+
}
|
|
698
|
+
const controlPassed = listed.every((id) => assertionResults.find((r) => r.id === id)?.passed === true);
|
|
699
|
+
const expectedFailureMatched = controlPassed && requiredFailures.length === 0;
|
|
700
|
+
return complete({
|
|
701
|
+
scenarioId: caseRecord.id,
|
|
702
|
+
suite: caseRecord.suite,
|
|
703
|
+
passed: expectedFailureMatched,
|
|
704
|
+
classification: expectedFailureMatched
|
|
705
|
+
? caseRecord.expectedFailure.expectedClass as ScenarioRunResult["classification"]
|
|
706
|
+
: "protocol_failure",
|
|
707
|
+
secondaryCode: expectedFailureMatched
|
|
708
|
+
? caseRecord.expectedFailure.expectedCode
|
|
709
|
+
: "deterministic_assertion",
|
|
710
|
+
assertionResults,
|
|
711
|
+
expectedFailureMatched,
|
|
712
|
+
diagnostics,
|
|
713
|
+
executionContext,
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
const passed = requiredFailures.length === 0;
|
|
718
|
+
return complete({
|
|
719
|
+
scenarioId: caseRecord.id,
|
|
720
|
+
suite: caseRecord.suite,
|
|
721
|
+
passed,
|
|
722
|
+
classification: passed ? "inconclusive" : "protocol_failure",
|
|
723
|
+
secondaryCode: passed ? undefined : "deterministic_assertion",
|
|
724
|
+
assertionResults,
|
|
725
|
+
diagnostics,
|
|
726
|
+
executionContext,
|
|
727
|
+
});
|
|
728
|
+
} catch (error) {
|
|
729
|
+
diagnostics.push(String(error));
|
|
730
|
+
return complete({
|
|
731
|
+
scenarioId: caseRecord.id,
|
|
732
|
+
suite: caseRecord.suite,
|
|
733
|
+
passed: false,
|
|
734
|
+
classification: "harness_failure",
|
|
735
|
+
secondaryCode: "execution_error",
|
|
736
|
+
assertionResults: [],
|
|
737
|
+
diagnostics,
|
|
738
|
+
executionContext,
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
}
|