Skip to content

feat(desktop): align connection tests with the generate invoke contract - #421

Open
Lxr-max wants to merge 1 commit into
OpenCoworkAI:mainfrom
Lxr-max:cursor/connection-test-invoke-parity-15f0
Open

Lxr-max wants to merge 1 commit into
OpenCoworkAI:mainfrom
Lxr-max:cursor/connection-test-invoke-parity-15f0

Conversation

@Lxr-max

@Lxr-max Lxr-max commented Sep 14, 2026

Copy link
Copy Markdown

Summary

Connection tests (connection:v1:test-active / connection:v1:test-provider) now validate the same effective provider contract that generate uses, instead of treating a GET /models 200 as Connection OK.

Fixes #216 (slice of epic #214). Does not implement sibling #213.

Shared contract

resolveEffectiveInvokeContract() in apps/desktop/src/main/effective-provider-contract.ts is the single resolver for:

  • test-active: same resolveActiveModel() snap-to-config as generate (stale renderer provider is ignored when cfg.activeProvider is set)
  • test-provider: named-provider resolution (resolveProviderModel) with no snap to the active slot
  • Auth: resolveCredentialForProvider() — ChatGPT Codex uses getValidAccessToken(), other providers share the same API-key / env / keyless rules as generate
  • Headers: Authorization: Bearer vs x-api-key from authHeaderNameForProvider()
  • baseUrl: canonicalInvokeBaseUrl() (trailing slash + /v1 for OpenAI-compatible wires)
  • Wire: invokeUrlForWire() — Codex Responses vs Anthropic messages vs OpenAI chat completions
  • Keyless: empty Bearer is still sent when allowKeyless is true

Generate and memory IPC now pass that canonical baseUrl into complete(), and complete() canonicalizes once more so runtime cannot silently diverge.

/models vs real wire

modelsProbeRelationForWire() in packages/shared:

  • optional-discovery: GET /models is not the generate contract. Generate never calls it. A 200 on /models is not Connection OK.
  • unavailable: ChatGPT Codex — no /models probe; OAuth token resolution is the test.

Probe both discovery and inference when discovery is optional:

/models invoke result
fail pass ok: true, compatibility: 'degraded', invokeParity: 'degraded-discovery'
pass fail ok: false, compatibility: 'diverges', code: 'INVOKE_DIVERGED'
pass pass ok: true, compatibility: 'compatible'
fail fail ok: false with invoke error

Renderer toasts distinguish success / degraded discovery / reachable but diverges from real invoke / hard failure.

Tests

  • Active snap-to-config vs named-provider no-snap
  • Codex OAuth uses refreshed token, not tokenStore.read()
  • Keyless proxy empty Bearer
  • OpenAI-compatible gateway uses /chat/completions, not /responses
  • Regression: /models 200 + invoke 404 → diverges (test must not pass when runtime would fail)
  • Regression: /models 404 + invoke 200 → degraded pass (test must not fail when runtime would succeed)
  • Responses wire must not false-positive via /chat/completions

Principles 5b

  • Compatible: existing IPC channels; extra structured fields are additive
  • Upgradeable: schemaVersion unchanged; new result fields are optional for older renderers
  • No bloat: no new deps; shared URL helpers instead of a second HTTP client
  • Elegant: one contract object consumed by test-active, test-provider, and generate

Constraints

  • BYOK / local-first unchanged; credentials stay in local config
  • No provider SDKs; probes stay as fetch against the same URLs complete() uses

Make connection:v1:test-active and test-provider share active-provider
resolution, auth/headers, canonical baseUrl, wire, and keyless/OAuth
rules with generate. Probe the real inference endpoint and treat GET
/models as optional discovery, with structured diverges results when
the host is reachable but invoke would fail.

Fixes OpenCoworkAI#216

Signed-off-by: Xuanrui Li <xuanrui.li@se24.qmul.ac.uk>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:desktop apps/desktop (Electron shell, renderer) area:providers packages/providers (pi-ai adapter, model calls) docs Documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: 对齐“测试连接”和“实际调用”链路 / Ensure connection-test and actual-invocation parity

1 participant