Commit Graph

4 Commits

Author SHA1 Message Date
backryun
f664af8f36 feat(github): refresh Copilot model catalog (#8226)
* feat(github): refresh Copilot model catalog

* feat(github): refresh Copilot model catalog (gpt-5.6 family)

Dropped the claude-opus-4.6 reinstatement (contradicts #7223/#2821 with no new
evidence; risks a production 400 on /v1/messages). Kept the gpt-5.6-sol/terra/luna
additions, which already exist on the Codex provider.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: backryun <backryun@users.noreply.github.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
2026-07-23 04:34:38 -03:00
hppsc1215
b3d3dd5954 feat(providers): Complete GHE Copilot OAuth provider implementation (#7546)
* docs: add design spec for GHE Copilot provider

* feat(mitm): add GHE Copilot target descriptor

* feat(executors): add GheCopilotExecutor for GHE Copilot

* feat(executors): register GheCopilotExecutor in factory

* feat(providers): add ghe-copilot provider with gheUrl validation

* feat(providers): add ghe-copilot to OAUTH_PROVIDERS and enforce HTTPS gheUrl validation

* test(ghe-copilot): add unit tests for GheCopilotExecutor and GHE_COPILOT_TARGET

* feat: complete GHE Copilot provider implementation

* feat: register ghe-copilot provider in registry

Add GHE Copilot registry entry (executor: "ghe-copilot") so the
provider is resolvable by the API routes and gets the same model
catalog as github Copilot.

* feat: wire ghe-copilot into OAuth flow with per-connection gheUrl

- Add gheCopilot OAuth provider (device-code flow targeting GHE host)
- Register in OAuth PROVIDERS map
- Thread gheUrl from query param → device-code request → poll →
  postExchange → providerSpecificData so the GHE host is used end-to-end
- Restore corrupted src/lib/oauth/providers/github.ts from HEAD

* feat: add ghe-copilot device-code UI with gheUrl input

- Route ghe-copilot through the device-code OAuth branch (was falling
  through to browser OAuth → "Browser OAuth unavailable" error)
- Add a gheUrl collection step so the enterprise host is supplied before
  the device-code request, and thread it into /device-code + /poll

* fix: thread gheUrl through GHE Copilot pollToken + postExchange

pollToken read gheUrl from config (GITHUB_CONFIG, which has none) and
threw "gheUrl is required" on every poll — the connection hung forever
after device authorization. Now reads gheUrl from extraData (passed by
the route), and postExchange carries it forward into mapTokens so it is
persisted in providerSpecificData for the executor.

* fix: GHE Copilot chat routing + account test

- Capture endpoints.proxy from the GHE token response and store it as
  copilotProxyUrl; route chat/responses traffic to that enterprise host
  instead of the static gheUrl/chat/completions path (was 406/404).
- Always route GHE Copilot to /chat/completions (GHE proxy 404s on
  /responses); the Responses API is served via the chat transformer.
- Strip the ghe-copilot/ prefix from the upstream model id.
- Remove openai-responses targetFormat from GHE models so chatCore does
  not run the Responses transformer (which dropped `messages`).
- Add ghe-copilot to OAUTH_TEST_CONFIG (account test was "unsupported").
- Register executor in eslint suppressions.

* fix: drop stream:false for GHE Copilot

The GHE Copilot proxy rejects `stream: false` ("stream": false is not
supported). Only forward the flag when actually streaming; omit it
otherwise.

* fix: force stream:true upstream for GHE Copilot (streaming-only proxy)

The GHE Copilot proxy rejects `stream: false`. forceStream:true in the
registry makes chatCore pass upstreamStream=true, but GithubExecutor
.transformRequest ignores the stream arg (void stream) and keeps the
client's stream:false. Override transformRequest in GheCopilotExecutor to
force stream:true so the proxy accepts the request; chatCore drains the
SSE back to JSON for non-stream clients.

* fix: GHE Copilot live model discovery from copilotProxyUrl/models

- Add fetchGheCopilotModels/parseGheCopilotModels using enterprise proxy URL
  and { models: [{ name }] } response shape (no static allowlist)
- Wire ghe-copilot into models-import route; use plain fetch (safeOutboundFetch
  header guard strips the copilot bearer token -> 403)
- Import now returns real enterprise models (copilot-nes-oct, etc.) and chat
  resolves them correctly

* fix: GHE Copilot uses endpoints.api host for chat + model discovery

The GHE token endpoint returns two hosts:
  - endpoints.api   (copilotApiUrl)   -> chat/completions + real chat model
    catalog, shape { data: [{ id }] }
  - endpoints.proxy (copilotProxyUrl) -> NES/autocomplete/instant-apply only,
    shape { models: [{ name }] }

We were routing chat AND model discovery to endpoints.proxy, so import only
returned completion models (copilot-nes-*, instant-apply) and never the real
chat models (claude-*, gpt-*, gemini-*).

- Executor: capture endpoints.api as copilotApiUrl; buildUrl prefers it
- OAuth postExchange/mapTokens: persist copilotApiUrl from endpoints.api
- Model discovery: fetch from copilotApiUrl/models, parse { data:[{id}] }
  (and proxy { models:[{name}] }) shapes, no allowlist
- All traffic stays on the configured GHE host (deutschebahn.ghe.com),
  never api.githubcopilot.com

Verified: import returns 28 real chat models; chat with gpt-4o streams OK.

* feat(providers): finalize GHE Copilot implementation and add changelog fragment

* fix(providers): resolve ghe-copilot no-explicit-any + complexity ratchet

- Replace the 6 explicit `any` types in GheCopilotExecutor
  (transformRequest, refreshCredentials) with proper ProviderCredentials /
  unknown / ExecutorLog types, and drop the config/quality/eslint-suppressions.json
  allowlist entry added for them — policy requires new violations be fixed,
  not frozen.
- Extract refreshViaGitHubToken() and buildRefreshedProviderSpecificData()
  helpers out of refreshCredentials() to bring its cyclomatic complexity
  (21) back under the repo's ratchet threshold (15); behavior unchanged.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* fix(oauth): unblock #7546 file-size gate for GHE Copilot OAuth provider

Extracts the GHE enterprise-URL config step from OAuthModal.tsx into a
new leaf component (src/shared/components/oauthModal/GheConfigStep.tsx)
to shrink the frozen file's own growth, and rebaselines the two
remaining irreducible wiring bumps (device-code route.ts 960->963,
OAuthModal.tsx 1030->1056) with justification comments, mirroring the
existing #7399/#6636 precedent on this same file.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* chore(ghe-copilot): drop planning spec from docs/ and revert out-of-scope eslint bump

Planning artifacts live outside the repo tree; package.json/lock restored to the
release state (the eslint patch bump was unrelated drift from the fork's history).

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* fix(oauth): validate gheUrl (HTTPS-only) at both raw entry points of the device-code flow

Applies the PR's existing providerSpecificData HTTPS rule to the OAuth route's
searchParams and device-flow extraData entry points, rejecting malformed or
non-HTTPS enterprise URLs with 400 before any upstream fetch. Private-IP hosts
stay allowed by design — on-prem GHE Server is the primary use case.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* chore(quality): extend oauth route file-size note for the gheUrl validation guards (963->970)

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: Alexander Helm <alexander.helm@deutschebahn.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouzapw@users.noreply.github.com>
Co-authored-by: hppsc1215 <hppsc1215@users.noreply.github.com>
2026-07-19 21:22:37 -03:00
backryun
e755c5ac68 fix(providers): refresh GitHub Copilot catalog (#6154)
* fix(providers): refresh github copilot catalog

Limit GitHub Copilot discovery to the curated supported model set and keep the provider cooldown panel client-safe by moving countdown formatting out of localDb.

* chore(quality): rebaseline providerPageHelpers.ts file-size (+13, #6154 copilot catalog)

The GitHub Copilot catalog refresh grows the provider-page model-section helper
(1021->1034). Fast-path PR->release skips check:file-size, so the bump lands with
the PR. Justification recorded in file-size-baseline.json.

Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>

---------

Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
2026-07-05 02:33:32 -03:00
Diego Rodrigues de Sa e Souza
68d5a0ab27 Release v3.8.10 (#3140)
* chore(release): open v3.8.10 development cycle

Bump 3.8.9 → 3.8.10 across package.json, lockfile, electron, open-sse, and
docs/reference/openapi.yaml; add the [3.8.10] CHANGELOG section (root + 41 i18n
mirrors) as the integration target for the cycle. Entries land here as work
merges into release/v3.8.10; finalized by the release flow.

* fix(providers): resolve web provider alias collisions

Assign unique aliases to HuggingChat, Kimi Web, and Qwen Web so they no longer shadow primary providers or trigger startup warnings.

Add a unit test to enforce provider alias uniqueness and prevent future collisions. Also expand local ignore and VS Code exclude rules for agent, build, and worktree artifacts.

* fix(responses): normalize image_url parts across input paths (#3150)

Normalize image_url parts across all Responses input paths. Integrated into release/v3.8.10.

* fix(api-manager): preserve API key expiration local time (#3146)

Preserve API key expiration local time + clear button. Integrated into release/v3.8.10.

* Strip previous_response_id for stateless Responses upstreams (#3143)

Strip previous_response_id for stateless Responses upstreams (auto/strip/preserve). Integrated into release/v3.8.10.

* fix(opencode-plugin): map thinking cap to interleaved in model+combo (#3138)

Map caps.thinking to ModelV2.capabilities.interleaved for opencode-plugin. Integrated into release/v3.8.10.

* fix(providers): use synced models as fallback for all providers (#3148)

Use synced models as authoritative local catalog for all providers (+regression test). Integrated into release/v3.8.10.

* fix(qoder): bifurcate validation by token type — PAT→Cosy, regular API key→dashscope (#3149)

Bifurcate Qoder validation by token type (PAT→Cosy, regular→dashscope) +regression test. Integrated into release/v3.8.10.

* fix(antigravity): dynamic model resolution via MITM alias table (#3144)

Dynamic antigravity MITM model resolution in the executor (+bug fix +regression test; DB import dropped from client-reachable config). Integrated into release/v3.8.10.

* Feature/batch allow big (#3128)

Podman deployment options + larger upload body-size limits (+CONTAINER_HOST docs). Integrated into release/v3.8.10.

* fix(fireworks): preserve fully-qualified router/model IDs (#3133) (#3160)

Fireworks router IDs (accounts/fireworks/routers/...) were double-prefixed
with accounts/fireworks/models/ → upstream 404. Add optional
acceptedModelIdPrefixes to the registry entry and skip the prepend when the
model already starts with an accepted prefix.

Co-authored-by: KooshaPari <KooshaPari@users.noreply.github.com>

* fix(llama-cpp): route to configured local baseUrl instead of OpenAI (#3136) (#3161)

llama-cpp was missing from the local-provider group in buildUrl(), so it
fell through to the OpenAI baseUrl and returned an OpenAI 401. Add the
case to resolve the connection's providerSpecificData.baseUrl.

Co-authored-by: tjengbudi <tjengbudi@users.noreply.github.com>

* fix(t3-chat-web): parse cookies + convexSessionId from stored credential (#3007) (#3162)

The executor read credentials.cookies/convexSessionId, but the pipeline
only stores the pasted string under apiKey → t3.chat always 400'd. Parse
both values from apiKey (fallback accessToken), mirroring validation.ts.

Co-authored-by: minhtran162 <minhtran162@users.noreply.github.com>

* fix(minimax): stop capping MiniMax-M3 / M2.7 max_tokens at 8192 (#3141) (#3163)

MiniMax-M3 had no MODEL_SPECS entry and capitalized MiniMax-M2.7 missed
its lowercase spec (case-sensitive lookup) → both fell to the 8192 default
cap. Add the M3 spec (512K output), alias the capitalized ids, and make
getModelSpec lookups case-insensitive.

Co-authored-by: totaltube <totaltube@users.noreply.github.com>

* fix(github-copilot): discover model catalog live from api.githubcopilot.com (#3120, #3121) (#3164)

The github (Copilot) provider had a static hardcoded catalog with no
discovery source, so Import Models never refreshed (#3120) and advertised
non-entitled models that 400 on use (#3121). Add a live /models fetch with
fallback to the static list.

Co-authored-by: gabrielmoreira <gabrielmoreira@users.noreply.github.com>

* fix(combo): invalidate nested-combo cache on edits + log DATA_DIR (#3147) (#3165)

Editing a combo did not invalidate the 10s nested-combo expansion caches
(chat.ts getCombosCachedForChat + chatCore.ts getCombosCached; the exported
clearCombosCache was dead code), so a removed nested target/model could be
served as a phantom for up to 10s. Wire a shared monotonic combos-cache
version in readCache (bumped by invalidateDbCache("combos") on every combo
write); both cache layers treat a version mismatch as a miss.

Also log the resolved DATA_DIR/SQLITE_FILE absolute path at DB init so the
reporter's 'persists across restart + volume wipe' symptom (a multi-replica
Docker volume/DATA_DIR mismatch, not a routing bug) is diagnosable from logs.

Includes consolidated CHANGELOG entries for #3133/#3136/#3007/#3141/#3120/#3121.

Co-authored-by: ViFigueiredo <ViFigueiredo@users.noreply.github.com>

* fix(web-tools): parse bare JSON tool calls (#3157)

Parse bare JSON tool calls for deepseek-web (#2820) + fuzzy tool-name matching. Integrated into release/v3.8.10.

* fix(misc): minor fixes across reasoning cache, account fallback, binary manager (#3177)

Misc: ProviderProfile export, DeepSeek reasoning regex, binary guard. Integrated into release/v3.8.10.

* fix(kiro): minor OAuth social exchange tweaks (#3176)

Kiro social OAuth: optional targetProvider passthrough. Integrated into release/v3.8.10.

* deps: bump hono from 4.12.18 to 4.12.23 (#3179)

Bump hono to 4.12.23. Integrated into release/v3.8.10.

* fix(providerRegistry): update kilocode format and executor (#3166)

kilocode: openai format + default executor (matches kilo-gateway) + registry test. Integrated into release/v3.8.10.

* feat(metrics): cross-request TTFT and gap latency after tool calls (#3173)

Cross-request TTFT + gap-after-tool latency metrics (+test). Integrated into release/v3.8.10.

* feat(dashboard): provider stats API endpoint and dashboard page (#3175)

Provider stats dashboard + API (SQL moved to db module per Hard Rule #5, +test). Integrated into release/v3.8.10.

* fix(usage): sequential+spaced OAuth quota sync, reactive force-refresh, actionable 401 (#3156)

Sequential+spaced OAuth quota sync, reactive force-refresh on 401, actionable 401 in UI. Integrated into release/v3.8.10.

* fix(healthcheck): per-provider proactive-refresh skip list (rescue short-TTL OAuth) (#3159)

Per-provider proactive-refresh skip list (OMNIROUTE_HEALTHCHECK_SKIP_PROVIDERS) to rescue short-TTL OAuth. Integrated into release/v3.8.10.

* feat(quota): show OAuth token expiry on provider cards (small, blue, informative) (#3178)

Show OAuth token expiry on provider cards (small, blue, informative). Integrated into release/v3.8.10.

* fix(providers): empty refresh must not resurface just-cleared synced models (#3181)

Empty refresh must not resurface just-cleared synced models (fixes the release-blocking provider-models-route test). Integrated into release/v3.8.10.

* chore(release): v3.8.10 — 2026-06-04 (finalize CHANGELOG)

---------

Co-authored-by: Wilson <pedbookmed@gmail.com>
Co-authored-by: Xiangzhe <32761048+xz-dev@users.noreply.github.com>
Co-authored-by: Jan Leon <Jan.gaschler@gmail.com>
Co-authored-by: M.M <mr.maatoug@gmail.com>
Co-authored-by: Hernan Javier Ardila Sanchez <hjasgr@gmail.com>
Co-authored-by: Markus Hartung <mail@hartmark.se>
Co-authored-by: KooshaPari <KooshaPari@users.noreply.github.com>
Co-authored-by: tjengbudi <tjengbudi@users.noreply.github.com>
Co-authored-by: minhtran162 <minhtran162@users.noreply.github.com>
Co-authored-by: totaltube <totaltube@users.noreply.github.com>
Co-authored-by: gabrielmoreira <gabrielmoreira@users.noreply.github.com>
Co-authored-by: ViFigueiredo <ViFigueiredo@users.noreply.github.com>
Co-authored-by: PizzaV <103120356+pizzav-xyz@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Nicolas Lorin <androw95220@gmail.com>
2026-06-04 20:05:38 -03:00