* feat(provider): add GMI Cloud as a provider and official partner
Add GMI Cloud (https://www.gmicloud.ai/) as a first-class
OpenAI-compatible provider and list it in the partner roster.
Provider (`gmi-cloud`):
- Gateway descriptor for https://api.gmi-serving.com/v1 with a hybrid
catalog: a short curated list plus authenticated /v1/models discovery.
Defaults to deepseek-ai/DeepSeek-V4-Pro.
- GMI_API_KEY is a dedicated credential. A generic OPENAI_API_KEY is
never sent to GMI, and the GMI key is never mirrored to another host.
- Reachable from /provider, `--provider gmi-cloud` (which also reads an
optional GMI_MODEL) and saved profiles, including relaunch.
- `--provider gmi-cloud` drops an API format or custom auth header left
by another provider, since GMI is Bearer-only chat completions.
- Routes by its default base URL only. The same host also serves GMI's
Anthropic-compatible API, which stays a custom Anthropic endpoint.
- Forwards GMI_API_KEY to spawned teammates.
Partner:
- README partners table and the website roster, with light and dark
logos under docs/assets/ and web/public/partners/.
Docs: README provider row, .env.example and the website provider and
configuration pages. Also corrects the README line that said the
Opengateway routes GMI Cloud models, which it no longer does.
* docs(readme): use Twigpine's dark logo in dark mode
The partners table showed the light Twigpine logo as a white tile on GitHub's dark theme. Serve https://twigpine.com/logo-dark.png there, the same markup the Zero README uses.
* fix(gmi-cloud): curate only models GMI's /v1/models serves
A live /v1/models call (79 models) shows GMI does not serve
anthropic/claude-sonnet-4.6 or anthropic/claude-opus-4.7 on the
OpenAI-compatible API, so drop them from the curated seed. DeepSeek V4
Pro and V4 Flash (GMI's own coding picks) remain; discovery lists the
rest.
Tests now use the item shape the live endpoint returns (`name`,
`context_length`, `pricing`, no output limit), and the GMI_MODEL
examples use a served model id.
* feat(gmi-cloud): default to Qwen 3.8 Max and curate Qwen 3.8 Max and Flash
GMI Cloud's partner models are Qwen 3.8 Max and Qwen 3.8 Flash. Add
shared descriptors for both (context as GMI's /v1/models reports it,
262,144 and 1,048,575; a conservative 65,536 output cap since GMI does
not publish one), curate them ahead of the DeepSeek V4 picks, and make
Qwen/Qwen3.8-Max the route default.
Verified live through a built CLI: read-a-file then write-a-file agent
turns succeed on both models, and `--provider gmi-cloud` with no
--model uses Qwen/Qwen3.8-Max.
* fix(gmi-cloud): keep the GMI key on GMI's HTTPS /v1 API (review feedback)
Address CodeRabbit's three findings on #2279:
- isGmiCloudBaseUrl now accepts only HTTPS on the default port, host
api.gmi-serving.com, and a /v1 path or one below it. Plain HTTP,
custom ports, the host root (GMI's Anthropic-compatible API) and
other paths are rejected.
- buildGmiCloudProfileEnv no longer falls back to an ambient
OPENAI_BASE_URL, which may belong to another provider. It keeps an
explicit GMI URL and otherwise uses the route default, so the key it
returns always targets GMI.
- The profile env mirror sets GMI_API_KEY only when the profile's URL is
GMI's, not for any gmi-cloud profile, matching the startup checks.
Each fix has a test that failed before the change.
* fix(gmi-cloud): withhold the GMI key from a retargeted gmi-cloud profile
Address CodeRabbit's follow-up on #2279. Applying a gmi-cloud profile
whose base URL is not GMI's inference API installed the saved key as
OPENAI_API_KEY for that URL. Withhold it there, the same way this
function already treats retargeted ApiSmart, Concentrate, API Route,
LLMTR and Command Code profiles.
A gmi-cloud profile with no base URL now resolves to the GMI default
(like those routes), and the GMI_API_KEY mirror follows the resolved
URL.
Tests cover the retargeted profile in-session (neither key installed),
the empty-URL profile, and the persisted startup env of a retargeted
profile (always GMI's URL, never the other host). The first two failed
before this change.
* fix(query): bound per-turn latency growth in long REPL sessions (#1949)
Addresses the progressive latency regression where consecutive prompts in a
single session grow non-linearly (2nd prompt ~10s, 3rd 10+ min) due to
unbounded message accumulation with no proactive compaction and no per-prompt
turn cap on the main thread.
- Cap the interactive REPL main thread at 50 turns per prompt (DEFAULT_REPL_MAX_TURNS).
Headless/print mode and the SDK are unchanged (--max-turns flag / SDK callers
still control it), preserving the SDK API contract.
- Default maxMessagesCompactionThreshold to '200' so message-count compaction
runs well before the context window fills, instead of 'off'.
- Lower the auto-compact threshold buffer from 13k -> 30k so compaction fires
earlier with less accumulated history. The effective-context floor buffer is
kept at 13k and getAutoCompactThreshold() falls back to it for small-context
models, so the threshold can never go negative (no #635 regression).
Test updates: isolate the hard-cap override test from the new 200-message
default, and correct an outdated constant reference in the autoCompact test.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(query): repair REPL latency guard
* fix(query): cover resume and default guard paths
* fix(query): enforce cap across interactive paths
* docs(compaction): clarify disabled message limits
* fix(query): retain explicit message thresholds
* fix(query): enforce explicit threshold recovery
* fix(query): honor legacy active-message limit
* fix(doctor): report effective message compaction limit
* fix(config): share message threshold validation
* test(doctor): cover disabled message compaction
* fix(compact): preserve latency guard coverage
* test(repl): exercise turn cap defaults
* fix(compact): honor disabled default message guard
* fix(swarm): honor disabled auto compaction
---------
Co-authored-by: Claude <noreply@anthropic.com>
* feat(api): rotate OpenAI credential pools
* fix(api): align pooled credential discovery
* fix(cache-probe): preserve GitHub credential precedence
* fix(provider): honor pooled OpenAI fallbacks
* fix(provider): validate pooled profile credential labels
* fix(api): harden OpenAI credential pool handling
Reject placeholder values in pooled OpenAI credentials before requests, discovery, diagnostics, and profile generation can use them.
Normalize pooled credentials to a single usable key for model discovery, runtime cache partitions, cache probing, and NVIDIA NIM cache lookups.
Preserve documented profile precedence by letting live shell credentials override saved pools, carrying OpenCode fallback pools through launch, and redacting individual pool members in profile display.
Add regression coverage for pooled credential validation, profile launch/rebuild behavior, discovery/cache callers, diagnostics, provider autodetect, and shim failover semantics.
* fix(provider): cover pooled key recommendation path
Import the pooled OpenAI credential validator in provider-recommend and split invalid credentials from unset credentials in user guidance.
Add a script-level regression that runs the OpenAI recommendation path with OPENAI_API_KEYS so the ts-nocheck script cannot regress with runtime ReferenceErrors.
Scrub pooled OpenAI keys before xAI OAuth profile env construction and loosen the invalid-pool discovery test to assert auth header absence instead of exact header shape.
* fix(tests): stabilize rebased provider checks
* fix(provider): address pooled credential review findings
* test(api): cover opencode go credential failover
* fix(provider): share OpenAI credential usability checks
* fix(provider): respect pooled credential precedence
* fix(model): preserve pooled discovery credential precedence
* fix(model): fall back from unusable pooled discovery keys