mirror of
https://github.com/Gitlawb/openclaude.git
synced 2026-08-24 02:34:15 -05:00
main
96
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
39c3850c2e |
docs: tighten PR review expectations in CONTRIBUTING and AGENTS guides (#2151)
* docs: tighten PR review expectations in CONTRIBUTING and AGENTS guides - Add drift caveat to CodeRabbit findings: verify suggestions against PR intent before applying; decline out-of-scope with justification or ask a maintainer; never silently ignore findings - Add Keep Your Branch Current subsection (rebase duty, fix-churn warning) - Require full local CI-equivalent suite green before every push, with cross-platform exception - Add ignored/filler PR template submissions to close-without-review list - Expand follow-up guidance: multi-round review is normal, repeated fix requests signal root-cause investigation and better agent prompting - Mirror all of the above in AGENTS.md for coding agents * docs: address CodeRabbit findings on review-expectations guides - Make CONTRIBUTING.md Validation the single authoritative pre-push validation contract mirroring .github/workflows/pr-checks.yml exactly: --frozen-lockfile install, launcher compatibility checks, provider recommendation via npm as CI does, web job carve-out - Remove conflicting 'relevant subset' wording; cross-platform exception is the only carve-out from the full suite - AGENTS.md now defers to the CONTRIBUTING contract instead of defining a divergent core-checks list - Reword ambiguous 'submit the PR template ignored' bullet to 'submit a PR with the PR template ignored' * docs: align pre-push validation suite with CI semantics - Drop standalone 'bun run test:full'; bun run check already includes it - Document web workspace install (bun install --cwd web --frozen-lockfile) before web checks, matching the web CI job - Pass explicit --base/--head to security:pr-scan so local scans target the PR merge-base like CI does instead of script defaults * docs: use PR base commit ref for local security scan parity Replace git merge-base computation with origin/main and document the required invariant (fetch + keep branch rebased onto current origin/main) so the local scan matches CI's PR base.sha instead of diverging. * docs: use exact PR base for security scan * docs: make local validation contract portable * docs: scope local checks and baseline waivers * docs: harden contributor workflow guidance * docs: pin contributor safety contracts |
||
|
|
1e56d4e7b2 |
feat(providers): add focused LLMTR hybrid gateway (#2150)
* feat: add LLMTR hybrid gateway * feat: support LLMTR_API_KEY * fix: allow LLMTR provider env files * fix: protect LLMTR credential routing * fix: protect LLMTR profile credentials * fix: complete LLMTR env lifecycle * fix: select LLMTR model before client setup * fix: address LLMTR review findings * fix: route LLMTR auxiliary models correctly * fix: complete LLMTR credential boundaries * fix: clear persisted LLMTR startup keys * fix: normalize LLMTR generic credentials * fix: scope LLMTR credential support * fix: align LLMTR credential boundaries * fix: close LLMTR credential boundaries * fix: clear stale LLMTR auth state * fix: clear persisted LLMTR credentials * fix: complete LLMTR setup contracts * fix: close LLMTR lifecycle gaps * fix(providers): close LLMTR credential boundaries * fix(providers): preserve saved LLMTR profile keys |
||
|
|
6e3590303b |
feat(partners): add Concentrate and Exa to partner roster (#2141)
Adds Concentrate (concentrate.ai) and Exa (exa.ai) to the README partners table and the web landing page, with light/dark logo variants self-hosted under docs/assets/ and web/public/partners/. Co-authored-by: OpenClaude <openclaude@gitlawb.com> |
||
|
|
645d596ea4 |
fix(code-reviewer): require inline diff input and preserve read-only search in embedded-search builds (#2102)
* feat: add code reviewer agent * feat(agent): add code-reviewer built-in agent implementation and tests Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(code-reviewer): address review comments - Fix broken step numbering in system prompt (glob/grep as sub-bullets) - Remove unnecessary wrapper in getSystemPrompt - Drop unused beforeEach/afterEach lifecycle in tests - Remove redundant registration test (beforeAll already throws) - Fix CLAUDE_CONFIG_DIR leak in beforeAll (restore in finally) - Replace @ts-ignore with explicit ToolUseContext cast - Use placeholder in README agentRouting example Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: trigger rerun — pre-existing test failures on main * fix(code-reviewer): enforce read-only contract by disallowing Bash Add Bash to disallowedTools so the reviewer cannot run shell commands regardless of parent session's acceptEdits/bypassPermissions mode. resolveAgentTools() treated undefined tools as wildcard — Bash was available and could auto-approve mkdir/rm/mv in acceptEdits mode. Remove Bash guidance from system prompt; diff must now be supplied by the caller inline. Update test to assert Bash is in disallowedTools. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(code-reviewer): deny all shell tools (Bash and PowerShell) Use SHELL_TOOL_NAMES constant instead of just BASH_TOOL_NAME to ensure all shell-capable tools are denied from the code-reviewer agent. This prevents Windows sessions with PowerShell enabled from bypassing the read-only contract. - Import SHELL_TOOL_NAMES from shellToolUtils - Use spread operator to include both Bash and PowerShell in disallowedTools - Update test to verify PowerShell is denied Fixes the finding: [P2] Deny all shell tools for the reviewer agent * fix(code-reviewer): explicit read-only allow-list; drop unrelated artifacts Switch code-reviewer to an explicit `tools` allow-list (Read, Glob, Grep) instead of relying on wildcard access minus a deny-list. resolveAgentTools() resolves only the named tools, so write-capable mcp__* server tools (and any other mutation-capable tool) can never be handed to the read-only reviewer. Keep the mutation deny-list as defense-in-depth. Remove generated/scratch artifacts unrelated to the reviewer agent: AGENTS.md, ARCHITECTURE.md, the .openlore/ .gitignore rule, temp_reference/, and the .tmp/sdk-consumer-* scratch files. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: restore temp_reference/ gitignore entry from main Entry was present on main from #1350 and was unintentionally removed during PR cleanup. Restoring it so temp_reference/ scratch directories remain untracked after merge. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(code-reviewer): require inline diff input and preserve read-only search in embedded-search builds Summary: - Update the `code-reviewer` built-in agent to require the caller to provide the diff or changed hunks inline in the prompt. - Preserve read-only search behavior in embedded-search builds by omitting `Glob`/`Grep` from the explicit tool allow-list when embedded search tools are enabled. - Keep a strict read-only policy by disallowing shell and mutation tools. Usage: - The `code-reviewer` agent is now explicitly guided to only review changes when the diff is provided inline. - In embedded-search builds, the agent only receives `Read` and cannot access `Glob`/`Grep`. - This prevents the agent from attempting shell-based diff discovery and enforces caller-provided diff input. Test plan: - `bun test src/tools/AgentTool/built-in/codeReviewerAgent.test.ts` — 12 pass, 0 fail - `bun run build` — success - `bun run smoke` — success - `bun run security:pr-scan` — success - `git diff --check` — success Credit: prior work from #1381/#1420. * fix(code-reviewer): clear cached agent definitions and markdown loader cache after test cleanup * fix(code-reviewer): address all P2/P3 review findings from jatmn - Always list [Read, Glob, Grep] in the tool allow-list; in embedded-search builds resolveAgentTools() silently drops unavailable Glob/Grep at runtime. The system prompt explicitly documents the narrowed search contract for embedded builds instead of silently degrading. - Update the code-reviewer invocation example in prompt.ts to include the diff inline, satisfying the reviewer's contract and preventing an avoidable extra turn. - Rewrite the test suite with the same isolation protocol as loadAgentsDir.test.ts: shared mutation lock, OPENCLAUDE_CONFIG_DIR, setClaudeConfigHomeDirForTesting, setAllowedSettingSources, and full env/cache restore in finally blocks. - Exercise both embedded-search branches: non-embedded tests verify Glob/Grep guidance, embedded tests verify the limited-search documentation and Read-only path. - Fix settings file path in README.md and docs/agent-routing.md from ~/.openclaude.json to ~/.openclaude/settings.json (the path the runtime actually loads). - Add blank line after fenced code block (MD031), add code-reviewer to the routable built-in agent list in both README and agent-routing docs. * fix(code-reviewer): restore prior setting sources in test cleanup, add credential security warning - Capture getAllowedSettingSources() before overwriting and restore it in the finally block instead of resetting to the default list, preventing state leakage to concurrent suites. - Add plaintext-credential security warning before the agentModels JSON example in README. - Update 'All settings-driven' to 'Configured via settings, agent frontmatter, and environment variables' for accuracy. * fix(code-reviewer): address remaining PR feedback (P1/P3) * docs: document feature gate for Explore and Plan agents * docs: document inline-diff requirement for code-reviewer agent * fix(code-reviewer): address P1/P2 review findings — teammate boundary, resume safety, lock-aware tests [P1] Reject built-in agent types from teammate spawn path to preserve read-only boundary. The teammate branch bypasses resolveAgentTools(), so built-ins like code-reviewer would receive Bash/Edit/Write tools. Guard added in AgentTool.tsx before spawnTeammate is called. [P1] Fail closed when resuming an unavailable agent type instead of silently falling back to GENERAL_PURPOSE_AGENT. A resumed code-reviewer must never gain edit-capable tools through a compatibility fallback. [P2] Snapshot environment and config state only after acquiring the shared mutation lock in codeReviewerAgent.test.ts. Moved from module- scope const to post-lock capture in beforeAll, with cleanup and lock release in afterAll's finally block. Regression tests added for all three findings. * fix(code-reviewer): guard lock release against failed acquisition Only call releaseSharedMutationLock() in afterAll when the lock was successfully acquired. Prevents releasing another suite's lock if acquireSharedMutationLock() throws on timeout. * fix(code-reviewer): remove trailing whitespace * fix(code-reviewer): reliably block built-in teammate spawns Reject built-in agent types from the teammate spawn path by looking them up in allAgents rather than activeAgents. This ensures the restriction remains intact even when built-in agents are disabled (e.g. via CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS) and omitted from activeAgents. Regression test added. * fix(code-reviewer): preserve original agent identity when resuming a read-only reviewer Background-agent metadata persisted only agentType, so resuming selected whichever active definition currently had that name. A built-in code-reviewer could be started, followed by a project/SDK definition named code-reviewer taking precedence; resuming the original agent would then use the replacement's ordinary wildcard tool set and grant that reviewer transcript Bash/Edit/Write tools. Persist the agent definition source and verify it matches the resolved definition on resume, rejecting the resumption if the original was spoofed. * fix(code-reviewer): address remaining CodeRabbit feedback on test cleanup and metadata source * fix(code-reviewer): address P1/P2 issues for teammate spawns and resume safety * docs: make OpenLore prerequisite explicitly optional in AGENTS.md * docs: fix pinned OpenLore version in AGENTS.md * Fix review issues * Revert AGENTS.md changes * Restore AGENTS.md to match upstream/main * fix(agent): address maintainer feedback on teammate spawns and resume persistence * test(agent): add regression coverage for legacy source-less agent resume * fix(agent): propagation pass — batch fork regression, TeamCreate policy, trailing whitespace, verification gate docs * fix(batch): allow specific custom agent types while requiring subagent_type --------- Co-authored-by: Laurent FRANCOISE <lfrancoise@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
084bc53463 |
feat(gateway): add Concentrate AI provider with dynamic model discovery (#2140)
* feat(gateway): add Concentrate AI provider with dynamic model discovery * fix(concentrate): prompt for Concentrate API key in /provider instead of pre-filling OPENAI_API_KEY * docs(concentrate): remove standalone setup guide to match other gateways * fix(concentrate): dedicated-credential-only routing, env-only identity, and credential isolation - Make Concentrate dedicatedCredentialsOnly so ambient OPENAI_API_KEY is never forwarded. Only CONCENTRATE_API_KEY authenticates the route. - Resolve Concentrate env-only route identity from CONCENTRATE_API_KEY, CONCENTRATE_BASE_URL, CONCENTRATE_MODEL, or a Concentrate-shaped OPENAI_BASE_URL. - Mirror the dedicated credential into OPENAI_API_KEY only after the route identity is established and only for the canonical /v1 inference endpoint. - Add Concentrate support to --provider concentrate, saved profiles, startup env rebuild, and .env allowlist. - Add regression tests for env-only, flag, saved-profile, and client routing. - Fix adjacent ApiSmart keyless profile leaking string 'undefined' into OPENAI_API_KEY and extend the first providerProfiles test timeout for the now-slower fresh module import. * fix(concentrate): protect credentials on noncanonical urls * fix(concentrate): drop legacy keys on retargeted profiles * fix(concentrate): remove legacy generic keys on proxies * fix(concentrate): reject noncanonical credential routes * fix(concentrate): validate env-only credentials * fix(concentrate): align env-only route validation * fix(concentrate): clear headers before client setup * test(validation): isolate Concentrate model env * fix(concentrate): honor provider precedence and model defaults * test(concentrate): cover model resolution precedence * fix(concentrate): preserve legacy model fallback * fix(concentrate): normalize early model selection * fix(concentrate): validate and select rejected models safely * fix(concentrate): reset stale route state * fix(concentrate): preserve proxy profile capabilities |
||
|
|
108a413493 |
fix(bg): preserve detached session terminal outcomes (#2133)
* fix(bg): preserve detached session terminal outcomes * fix(bg): harden terminal outcome routing |
||
|
|
ea655163d3 |
feat(zai): expand Coding Plan catalog support (#2127)
* feat(zai): expand Coding Plan catalog support Signed-off-by: chioarub <chioarub@gmail.com> * fix(zai): use supported low reasoning mode Signed-off-by: chioarub <chioarub@gmail.com> --------- Signed-off-by: chioarub <chioarub@gmail.com> |
||
|
|
575b407275 |
feat(partners): add ApiSmart, refresh Novita AI logo (#2121)
- Add ApiSmart (https://www.apismart.ai) to the README partners table and the web partner strip, with a dark-theme logo variant (near-black wordmark recolored to white, white matte removed). - Replace the Novita AI PNG logo with the new SVG wordmark plus a generated dark variant, wired through the same prefers-color-scheme <picture> pattern (README) and logoDark field (web). Co-authored-by: OpenClaude <openclaude@gitlawb.com> |
||
|
|
ff91642364 |
feat(integrations): add ApiSmart OpenAI-compatible gateway provider (#2109)
* feat(integrations): add ApiSmart OpenAI-compatible gateway provider
Add a hybrid-catalog ApiSmart gateway with dedicated APISMART_API_KEY/APISMART_MODEL
env wiring, route detection, profile persistence, and regression tests so the
provider works via --provider, env-only setup, and saved profiles.
* fix(apismart): protect dedicated credentials
* fix(apismart): enforce route credential boundaries
* fix(apismart): honor explicit competing route models
* fix(apismart): validate credentials and default profiles
* test(apismart): isolate env-only client tests
* fix(apismart): align routing and validation contracts
* fix(apismart): centralize route capability contracts
* Revert "fix(apismart): centralize route capability contracts"
This reverts commit
|
||
|
|
d427a4b2bb |
perf(cli): enable Node module compile cache (#2092)
* perf(cli): enable Node module compile cache Warm CLI invocations spend substantial time compiling the bundled ESM entrypoint. Enable Node's optional on-disk compile cache only in the process that imports the bundle, while preserving early Node 22 compatibility and making cache failures non-fatal. Add deterministic launcher coverage, packaging checks, and a reproducible benchmark procedure so the startup benefit can be measured without flaky CI thresholds. * fix(ci): isolate minimum Node launcher check The full validation suite depends on knip and oxc-parser behavior unavailable in Node 22.0.0. Keep full CI on the active Node 22 line and exercise the declared runtime floor in a dedicated build-and-launch job. * fix(benchmark): harden startup measurements Keep environment setup outside the timed process window, document the API's Node 22.8 floor, and preserve completed benchmark results when git metadata is unavailable. * test(cli): verify compile cache disable behavior Pair NODE_DISABLE_COMPILE_CACHE with a temporary cache directory and assert that supported Node releases leave it empty while preserving normal launcher output. |
||
|
|
77c82829c4 |
docs(readme): add npm monthly downloads badge (#2069)
Co-authored-by: OpenClaude <openclaude@gitlawb.com> |
||
|
|
158bdd0dcf |
docs(readme): rename Sponsors to Partners, add AI/ML API and Novita AI, new wordmark (#2054)
- Rename the Sponsors section and nav link to Partners - Add AI/ML API and Novita AI to the partners table with local logo assets; AI/ML API ships light/dark SVG variants behind a <picture> element so the wordmark stays readable on both GitHub themes - Replace the green SVG header wordmark with the orange pixel-art OPENCLAUDE wordmark PNG Co-authored-by: OpenClaude <openclaude@gitlawb.com> |
||
|
|
8f81e48f0e |
feat: add LongCat as first-class OpenAI-compatible provider (#1986)
* feat: add LongCat as first-class OpenAI-compatible provider
Register LongCat-2.0 in the integration catalog with LONGCAT_API_KEY auth,
/provider preset support, and zai-compatible thinking controls that emit
thinking:{type} while stripping unverified reasoning_effort fields.
* fix: complete LongCat provider integration
* fix: complete LongCat provider integration
* test: isolate LongCat provider environment
* test: isolate LongCat environment in provider tests
* test: isolate LongCat environment in route tests
* test: isolate LongCat environment in utility tests
* fix: harden LongCat provider integration
* fix: complete LongCat transport support
* fix: keep LongCat requests text-only
* fix: normalize LongCat endpoint URLs
* fix: reject malformed LongCat base URLs
* fix: harden LongCat text-only transport
* fix: scope LongCat transport hardening
* fix: scope generic OpenAI credentials by route
* fix: preserve required provider API formats
* fix: align LongCat with documented tool support
* fix: harden LongCat environment routing
* fix: enable LongCat tool calling
* Revert "fix: enable LongCat tool calling"
This reverts commit
|
||
|
|
14648213a6 |
Chore/readme cleanup (#1976)
* docs: README cleanup, green wordmark header, Trendshift badges Header: the startup wordmark (src/constants/brand.ts half-block art) rendered as a green two-shade SVG (docs/assets/openclaude-wordmark.svg, textLength-pinned so rows align in any monospace font), with the three Trendshift badges (daily/monthly/repository) centered beneath it. Cleanup (536 -> ~430 lines, nothing lost): - Agent routing, maxSteps limits, and GitHub Copilot sub-agent tuning moved to docs/agent-routing.md; headless gRPC server moved to docs/grpc-server.md; README keeps linked summaries. - Build/test/validation commands were repeated in three sections — consolidated into one Development section; Contributing links to it. - New "Meet Your Buddy" section documenting the companion heroes and their /buddy commands; added to What Works and Why OpenClaude. - Star History moved from the header flow down beside Community. - Setup Guides indexes the new docs pages; fixed a missing blank line before Repository Structure and a curly quote. All relative links, image paths, and internal anchors validated. Co-Authored-By: OpenClaude <openclaude@gitlawb.com> * docs: pure-rect wordmark for crisp rendering; drop broken Star History The wordmark SVG previously drew the half-block art as monospace <text>, which rendered raggedly (font-dependent glyph stretching and seams). Regenerated as pure SVG rects computed from the brand.ts wordmark grid — no font dependence, pixel-crisp at any size, same two-shade green split. Star History chart removed: the badge endpoint errors and displays a broken image. Co-Authored-By: OpenClaude <openclaude@gitlawb.com> * docs: render the wordmark at full README column width Co-Authored-By: OpenClaude <openclaude@gitlawb.com> --------- Co-authored-by: OpenClaude <openclaude@gitlawb.com> |
||
|
|
eeed68f4fd |
feat(provider): add Cloudflare Workers AI integration (#1100) (#1178)
* feat(provider): add Cloudflare Workers AI integration
Adds Cloudflare Workers AI as a first-class OpenAI-compatible provider
preset, modeled on the Venice / Xiaomi MiMo descriptors.
- New `src/integrations/vendors/cloudflare.ts` descriptor:
- `classification: 'openai-compatible'`
- Default base URL with literal `<ACCOUNT_ID>` placeholder — users
substitute via `/provider` baseUrl edit, same shape as the Azure
OpenAI example already in `docs/advanced-setup.md`
- `CLOUDFLARE_API_TOKEN` env, with `OPENAI_API_KEY` as fallback
- `removeBodyFields: ['store']` since Workers AI rejects unknown
OpenAI body fields (mirrors Mistral / Gemini / Cerebras strip)
- Static catalog with current Workers AI chat models
(`@cf/meta/llama-3.3-70b-instruct-fp8-fast`,
`@cf/meta/llama-3.1-8b-instruct`,
`@cf/deepseek-ai/deepseek-r1-distill-qwen-32b`,
`@cf/qwen/qwen2.5-coder-32b-instruct`)
- Validation routing on `api.cloudflare.com` /
`gateway.ai.cloudflare.com` hosts so an env-pasted URL maps back
to the preset
- Env mirror sites in `src/utils/providerProfiles.ts`: mirror api key
into `CLOUDFLARE_API_TOKEN` when baseUrl contains a Cloudflare host
(3 sites: same-env check, openAIProfileEnv build, applyEnv).
- `CLOUDFLARE_API_TOKEN` added to `PROFILE_ENV_KEYS` / `SECRET_ENV_KEYS` /
`ProfileEnv` / `SecretValueSource` in `src/utils/providerProfile.ts`
so the profile-clean and secret-redact paths know about it.
- `src/utils/providerFlag.ts` `--provider <name>` startup flag now
detects a Cloudflare profile from `OPENAI_API_KEY ===
CLOUDFLARE_API_TOKEN` (mirrors how the other host-key mirrors are
reverse-mapped to their preset id).
- `bun run scripts/generate-integrations-artifacts.ts` regenerated
`integrationArtifacts.generated.ts` to include the cloudflare preset
+ route + vendor.
- Tests: `compatibility.test.ts` PRESETS list, new
`buildProfileSaveMessage` Cloudflare case in `provider.test.tsx`,
new `applyProviderProfileToProcessEnv` Cloudflare case in
`providerProfiles.test.ts`.
- Docs: README providers table row + `docs/advanced-setup.md` section
matching the MiMo / Mistral entries.
- Dedicated AI Gateway integration with `gateway_id` URL templating.
Today users can still paste a full Gateway URL into `OPENAI_BASE_URL`
and the preset's `matchBaseUrlHosts` picks `gateway.ai.cloudflare.com`
up.
- Dynamic `/models` discovery on the Groq #1143 / `mapModel` pattern —
Cloudflare's `/v1/models` returns the runnable model list and the
hybrid catalog path drops in cleanly. Left as a separate PR so this
one stays a focused preset add.
Closes #1100
* fix(cloudflare): narrow route matching to api.cloudflare.com host
`gateway.ai.cloudflare.com` is the shared host for *all* Cloudflare AI
Gateway routes (Workers AI, Anthropic, OpenAI, etc.), so matching it to
the Workers AI preset applied Workers-AI runtime metadata and
credential precedence (CLOUDFLARE_API_TOKEN before OPENAI_API_KEY, body
'store' strip, max_tokens field) to other providers' Gateway URLs.
Drop the shared host from the match list; a dedicated AI Gateway
integration with path-aware routing is the right follow-up.
Refs #1100.
* fix(provider-manager): keep Codex OAuth after DeepSeek when cloudflare added
The picker hardcoded `options.splice(7, 0, …)` to drop the Codex OAuth
entry right after DeepSeek. Adding cloudflare to ORDERED_PROVIDER_PRESETS
bumped DeepSeek to index 7, so the splice now lands Codex OAuth *before*
DeepSeek and breaks the test fixture that drives navigateToPreset by
keypress count.
Switch to a dynamic `findIndex('deepseek') + 1` lookup so any future
preset inserted between Bankr and DeepSeek keeps the established
ordering. Fixture updated to mirror the new picker order.
Caught by CI on 12b3ff… smoke-and-tests: 8 ProviderManager tests
timing out because navigateToPreset overshot/undershot the target.
* fix(cloudflare): exclude the shared AI Gateway host from Cloudflare routing
The profile env/alignment/startup paths mirrored CLOUDFLARE_API_TOKEN whenever
the profile URL merely contained 'gateway.ai.cloudflare.com'. That host is the
shared AI Gateway for all Cloudflare AI routes (Workers AI, OpenAI, Anthropic,
...), so a profile retargeted to /openai or /anthropic Gateway URLs was wrongly
tied to the Cloudflare route and credential precedence.
Add isCloudflareBaseUrl (hostname === api.cloudflare.com, matching the Workers
AI host and the descriptor's matchBaseUrlHosts) and route all three sites
through it, consistent with isXaiBaseUrl/isFireworksBaseUrl. Also restore
CLOUDFLARE_API_TOKEN in the provider profile test cleanup keys.
* fix(cloudflare): don't seed the placeholder base URL from the CLI shortcut
`openclaude --provider cloudflare` fell through the generic OpenAI-compatible
branch and applied the descriptor default base URL verbatim — including the
unresolved `<ACCOUNT_ID>` placeholder — leaving the shortcut 'configured' with
an endpoint that cannot serve a request. Skip seeding any base URL that still
contains a `<...>` placeholder, so the user must supply a real account-scoped
URL (OPENAI_BASE_URL / `/provider` edit) first, matching how the wizard treats
placeholder endpoints.
* test(cloudflare): assert exact null fallback for AI Gateway routes
The shared AI Gateway URL assertions used `.not.toBe('cloudflare')`, which
would also pass for any other non-cloudflare return value. The intended
fallback is null, so assert `.toBe(null)` to lock the regression boundary.
* fix(cloudflare): gate profile token mirroring on base URL host only
applyProviderProfileToProcessEnv mirrored CLOUDFLARE_API_TOKEN whenever
route.routeId === 'cloudflare'. route comes from the saved profile.provider,
so that disjunct is always true for a cloudflare profile, including one
retargeted to the shared gateway.ai.cloudflare.com AI Gateway host. The
sibling sites (isProcessEnvAlignedWithProfile, buildOpenAICompatibleStartupEnv)
already key on isCloudflareBaseUrl only; align this site with them so a
shared-gateway profile no longer leaks the token or stays pinned to the
cloudflare route. Add a regression test for the gateway.ai.cloudflare.com case.
* chore(integrations): regenerate artifacts for the Cloudflare vendor
The rebase took main's generated artifacts at the conflict; regenerate so the
Cloudflare vendor descriptor is registered in VENDOR_DESCRIPTORS and the
manifest alongside the providers main added.
* fix(cloudflare): mirror CLOUDFLARE_API_TOKEN into the OpenAI-compatible auth path
The --provider cloudflare shortcut fell through to the generic
OpenAI-compatible default branch and never copied CLOUDFLARE_API_TOKEN
into OPENAI_API_KEY, so a user who only set the token sent an
unauthenticated request. Add a dedicated cloudflare case that mirrors the
token (and clears a stale generic key when absent), keeping the
placeholder-URL skip.
buildOpenAICompatibleStartupEnv also returned from its strict-env branch
before the fallback CLOUDFLARE_API_TOKEN mirror, so a keyed Cloudflare
profile persisted a startup env that omitted the token and re-detected
inconsistently after relaunch. Mirror it in the strict branch alongside
nearai/fireworks. Add regression coverage for both paths.
* fix(cloudflare): gate token mirroring on a real Cloudflare endpoint
The cloudflare shortcut copied CLOUDFLARE_API_TOKEN into the generic
OPENAI_API_KEY unconditionally. The descriptor default carries an
unresolved `<ACCOUNT_ID>` placeholder and is never seeded, so with
OPENAI_BASE_URL unset (or still pointing at a previous OpenAI-compatible
provider) the token would be attached to the wrong host. Gate the mirror
on isCloudflareBaseUrl(getConfiguredOpenAIBaseUrl()) — only seed
OPENAI_API_KEY once the configured base URL resolves to
api.cloudflare.com, otherwise fail fast and leave it unset. Add
regression coverage for the unconfigured, stale-host, and AI-Gateway-host
cases.
* fix(cloudflare): reject placeholder URL and keep the OPENAI_API_KEY fallback
The token mirror keyed on the api.cloudflare.com host only, so the literal
<ACCOUNT_ID> placeholder URL (same host) passed the gate and copied the
token onto a non-working endpoint. It also deleted any generic
OPENAI_API_KEY when no token was set, breaking the documented
compatibility fallback for users authenticating a real Workers AI URL with
OPENAI_API_KEY. Mirror only on a real (non-placeholder) Cloudflare
endpoint, and preserve an existing generic key there when no dedicated
token is present.
Refs #1100
* refactor(cloudflare): model Workers AI as a gateway, not a vendor
Cloudflare Workers AI is a hosted OpenAI-compatible inference endpoint
reached over the shared openai transport, so it belongs with the gateway
providers (atlas-cloud, groq, together, ...) rather than the transport
vendors. Move it to gateways/cloudflare.ts via defineGateway (category
hosted, vendorId openai), regenerate the integration artifacts, and
allowlist its provider-specific @cf/* catalog ids in the gateway
descriptor check (no shared cross-provider descriptor exists, same as
azure-deployment).
Refs #1100
* fix(cloudflare): key Workers AI detection on the account path, not the host
api.cloudflare.com also serves the general Cloudflare REST API, so matching the
whole host treated unrelated URLs (e.g. /client/v4/user/tokens/verify) as the
Workers AI route and mirrored CLOUDFLARE_API_TOKEN into OPENAI_API_KEY for them.
isCloudflareBaseUrl now requires the Workers AI path
/client/v4/accounts/<account_id>/ai/v1 with a real (non-placeholder) account id,
and resolveRouteIdFromBaseUrl guards its cloudflare hostname match through the
same predicate. Both route detection and token/profile mirroring key on the
actual Workers AI endpoint.
Adds same-host negative regressions (general REST path is not routed and does
not mirror the token; unresolved <ACCOUNT_ID> placeholder is excluded) and
asserts the Cloudflare Workers AI preset appears in the first-run picker.
* fix(cloudflare): honor the Workers AI path boundary in the profile-provider fallback
resolveActiveRouteIdFromEnv returned the saved active-profile provider's route
id before consulting its base URL. For a `cloudflare` profile that had been
retargeted to a non-Workers URL — the shared AI Gateway host, or a general
api.cloudflare.com REST path — this still resolved as `cloudflare`, so the
Workers AI shim config (removeBodyFields: ['store'], Cloudflare model metadata)
and CLOUDFLARE_API_TOKEN mirroring were applied to a generic endpoint, even
though resolveRouteIdFromBaseUrl already excludes those URLs.
Gate the profile-provider shortcut through profileRouteHonorsBaseUrlBoundary,
which requires the path-aware isCloudflareBaseUrl for the cloudflare route (all
other routes are host-scoped by resolveProfileRoute and unaffected). A retargeted
profile now falls through to the generic openai/custom resolution; a genuine
Workers AI profile base URL still resolves as cloudflare.
Adds regressions for both retarget cases (gateway host + REST path) and the
positive Workers AI profile case.
* fix(cloudflare): require HTTPS and honor the Workers AI path in validation
isCloudflareBaseUrl accepted any scheme, so http://api.cloudflare.com/
client/v4/accounts/<id>/ai/v1 resolved as the cloudflare route and mirrored
CLOUDFLARE_API_TOKEN into OPENAI_API_KEY over cleartext. Require url.protocol
=== 'https:'.
Startup validation selected the Cloudflare target on host match alone, so a
non-Workers path like /client/v4/user/tokens/verify demanded Workers AI auth
instead of falling back to generic OpenAI validation. Gate the cloudflare
target on isCloudflareBaseUrl(request.baseUrl), mirroring the runtime route
resolver's path boundary.
* test(cloudflare): lock non-Workers path token boundary; fix stale host-only comments
The apply/persist paths already gate CLOUDFLARE_API_TOKEN mirroring on the
isCloudflareBaseUrl path predicate, but had no coverage for a same-host
non-Workers path (api.cloudflare.com/client/v4/user/tokens/verify) and the
comments beside the mirroring sites still described a host-only boundary.
Add negative apply and persist regressions asserting the token is not mirrored
or persisted for that non-Workers URL, and update the comments to describe the
real Workers AI path predicate instead of host-only matching.
* fix(cloudflare): fall back to a generic route for retargeted profiles
resolveProfileCapabilityRouteId returned the cloudflare capability route id for
any saved cloudflare profile whose base URL no longer resolves — including one
retargeted to gateway.ai.cloudflare.com or another OpenAI-compatible host. That
stripped generic capabilities (apiFormat, custom auth/request headers) from
profile sanitize/apply even though the runtime resolver runs such a profile as
a generic OpenAI-compatible route. Mirror the same isCloudflareBaseUrl boundary:
keep the cloudflare route only for the real Workers AI URL (or the unset
descriptor default) and fall back to 'custom' otherwise. Regression asserts a
retargeted cloudflare profile preserves OPENAI_API_FORMAT.
* test(cloudflare): assert retargeted profile resolves to the custom route
Pin both resolveActiveRouteIdFromEnv assertions for a retargeted cloudflare
profile to .toBe('custom') instead of .not.toBe('cloudflare'), so the test
locks the intended generic OpenAI-compatible fallback rather than merely
excluding the cloudflare route.
|
||
|
|
fb40d49e68 |
feat: add repo map codebase intelligence (#1867)
* feat: add Codebase Intelligence — repo map with PageRank-ranked structural summaries
Adds a new module that builds a structural map of the repository by parsing
source files with tree-sitter, building a cross-file reference graph weighted
by IDF, ranking files with PageRank, and rendering a token-budgeted summary
of the most important files and their signatures.
Surface:
- RepoMap tool the model can call on-demand, with focus_files / focus_symbols
- /repomap slash command with --tokens, --focus, --stats, --invalidate
- Auto-injection into session system context, gated by REPO_MAP=1 env var
(compile-time feature('REPO_MAP') flag stays off in scripts/build.ts)
How it works:
git ls-files → tree-sitter WASM parse → extract defs/refs →
IDF-weighted directed graph → PageRank → render top files until token budget
Files imported by many others rank highest. Common symbol names (get, set,
map, value) are down-weighted via IDF. Results cached to disk keyed by
(path, mtime, size) — only changed files are re-parsed.
Supported languages: TypeScript, JavaScript, Python.
Tree-sitter tag queries are inlined as string constants in queries.ts so
they ship inside dist/cli.mjs and work after npm install — the .scm source
files are kept for readability/Aider attribution but are not required at
runtime. A drift-guard test (queries.test.ts) asserts byte-equality between
the inlined strings and the .scm source files.
Dependencies added: web-tree-sitter, tree-sitter-wasms, graphology,
graphology-pagerank, graphology-operators, js-tiktoken.
* fix(repomap): invalidate rendered cache on file edits + Windows test fix
- computeMapHash now folds per-file mtime+size into the cache key so a
source edit (without changing the file list) no longer returns the
prior rendered map. Adds a regression test that edits a file and
confirms the second build reflects the new symbol without manual
invalidateCache().
- queries.test.ts byte-for-byte drift guard normalizes CRLF -> LF when
reading the .scm source so Windows checkouts pass. .gitattributes
also pins *.scm to LF on future checkouts.
- Externals: declare web-tree-sitter, tree-sitter-wasms, graphology*,
and js-tiktoken in scripts/externals.ts so build validation passes.
* fix(repomap): expand directory focus paths
* fix(repomap): satisfy deadcode check
* Fix repo map review findings
* Resolve remaining repo map review findings
* fix(repomap): address review findings
* fix(repomap): address review findings
* fix(repomap): resolve smoke and review follow-ups
* fix(repomap): preserve cached tag order
* fix(repomap): resolve review follow-ups
* fix(repomap): satisfy query promise lint
* Fix repo map context timeout cleanup
* fix: address repo map review findings
* fix: cancel timed-out repo map context builds
* fix(repomap): preserve git file path whitespace
* fix(repomap): handle graph and parsing edge cases
* fix(repomap): preserve shell token positions
* fix(repomap): respect configured cache home
* fix(repomap): address review findings
- Add explicit 10000ms timeout to the feature-flag-off context test to avoid cold-import flakes.
- Add --focus-symbols flag to /repomap and forward it to buildRepoMap, matching the RepoMap tool.
- Add parsing/command tests and docs coverage for --focus-symbols.
---------
Co-authored-by: gnanam1990 <gnanasekaran.sekareee@gmail.com>
|
||
|
|
8369f2018e |
feat(provider): add AI/ML API provider (#863)
* feat(provider): add AI/ML API integration Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(provider): preserve bootstrap model fallback * fix(provider): complete aimlapi env-only routing * test(provider): keep first-run preset assertions visible * fix(provider): align aimlapi attribution and setup docs * fix(provider): use aimlapi rebate attribution headers * fix(provider): report current integration version * fix(provider): prioritize dedicated aimlapi credentials * fix(provider): complete AI/ML API attribution headers --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Lookoff123 <bataryshkinairina@gmail.com> |
||
|
|
1bd273d4d3 |
fix: isolate OpenClaude config from Claude Code (#1875)
* Rename .claude paths to .openclaude * test: update skill watcher paths for openclaude * fix: preserve default secure storage key Co-authored-by: Cursor <cursoragent@cursor.com> * chore: address config isolation review comments * fix: canonicalize secure storage config paths * test: isolate secure storage config override * Fix keychain service name config dir handling Update macOS keychain service naming to honor `OPENCLAUDE_CONFIG_DIR` by resolving the env override directly before falling back to the default config home lookup. Adjust secure storage platform tests to import `envUtils` and keychain helpers dynamically with the same module suffix and restore module mocks correctly, keeping test state isolated and consistent. * Align diagnostics and keychain with OpenClaude Updates several utilities to use OpenClaude defaults and naming consistently. Doctor diagnostics now always checks a package name (falling back to `@gitlawb/openclaude`), macOS secure storage service names and related tests now use `OpenClaude`, and keychain prefetch docs were updated to match. This also removes an unused `homeDir` option from local install dir candidates and treats `.claude.json` as a dangerous filesystem target. * Fix doctor npm uninstall package fallback Update doctor diagnostics to generate npm global uninstall guidance using a single package-name variable. When `MACRO.PACKAGE_URL` is not set, it now falls back to `@gitlawb/openclaude` instead of `openclaude`, so the suggested cleanup command matches the scoped package install. * Protect legacy .claude paths from writes Add .claude to DANGEROUS_DIRECTORIES and sandbox denyWrite lists, extend isClaudeSettingsPath to cover legacy .claude/settings.json paths, and update README to clarify CLAUDE_CONFIG_DIR is not used for background-session storage. * Protect custom Claude config dir from sandbox writes * Protect legacy Claude config roots --------- Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
e2bbb0295a |
feat: smart auto-routing (per-turn simple-vs-strong model selection) (#1734)
* feat(smart-routing): add smartRouting settings schema and reader * feat(smart-routing): resolve role keys to a SmartRoutingConfig * feat(smart-routing): wire per-user-turn routing into the query loop Classify once per user turn (transition===undefined), pin the decision in a loop-local, and apply the model-only route before the blocking-limit math. Enforce the org allowlist by calling isModelAllowed directly (coerce disallowed to strong; disable for the session if strong is also disallowed). Strip thinking history on a model change only under the provider gate (preserve-reasoning providers are left untouched). Export stripThinkingBlocksIfProviderAllows. * feat(smart-routing): add routed-error fallback to the strong model A simple-routed turn whose model call hits a retryable error retries once on the strong model, reusing the existing attemptWithFallback retry loop. Aborts and 4xx client errors propagate. Adds a session routing tally (simple/strong counts and simple->strong escalations) for the observability surface. * feat(smart-routing): add /smartroute command and env defaults /smartroute shows status and sets/toggles the simple and strong roles from agentModels keys, warning when the simple model is not first-party-cheaper than the strong one. OPENCLAUDE_SMART_ROUTING(_SIMPLE/_STRONG) provide startup defaults; an explicit settings block overrides env. * feat(smart-routing): show routing summary in /cost Appends a session routing summary (turns simple/strong, simple->strong escalations) to /cost, with an estimated-savings line gated on first-party pricing and annotated unavailable for unknown third-party pricing. Per-turn cost is already attributed to the routed model via the existing per-model breakdown. * fix(smart-routing): re-pin to strong after a routed-error fallback Without this, a turn's later continuation passes re-applied the pinned simple model after a fallback, re-triggering the same failure each pass. Re-pinning to strong keeps the rest of the turn on the recovered model. * fix(review): provider-swap guard, tally reset, notice-storm, env docs - Add the KTD6 provider-swap guard: drop the per-turn routing pin when a mid-turn provider-fallback swap changes the active provider, so the old provider's model id is not replayed at the new endpoint (adversarial P1). - Reset the routing tally in resetCostState() so /cost does not show stale cross-session counts. - Don't emit the disabled-for-session notice on every turn when no sessionId is available (suppress instead of storm). - Document OPENCLAUDE_SMART_ROUTING* in the openaiShim env-var header. - Add tests: provider-swap-safe pin, undefined-session silence, /smartroute strong arm and no-value guard. * docs(smart-routing): document /smartroute, settings, and env vars Register /smartroute in the web command catalog, add the smartRouting setting and OPENCLAUDE_SMART_ROUTING* env vars to the configuration reference, add a docs/smart-routing.md usage guide, and link it from the README. * fix(review): clear tally on /login, extract+test swap predicate, cap disabled set - /login used the raw bootstrap resetCostState, leaking the routing tally across an account switch; switch it to the cost-tracker wrapper. - Extract the provider-swap drop check as a pure, tested shouldDropPinForProviderSwap() and use it in the query loop. - Cap the disabledSessions set so a long-lived host can't grow it unbounded. - Document the 404/429 retry-by-design rationale; add tests for it. - Clarify the routedFallbackUsed per-turn scope and the apply-after-guard comment; document cross-provider role rejection and the re-enable path. * test(smart-routing): make allowlist tests robust to cross-file module mocks The decideTurnModel allowlist tests spied the global settings singleton, which let another file's leaked mock.module of modelAllowlist (agent.test.ts) flip isModelAllowed out from under them in the full suite. Spy isModelAllowed directly and restore it in afterEach so the tests are deterministic regardless of suite ordering. * fix(smart-routing): address CodeRabbit review and green CI - index.test.ts: pin the allowlist in the three happy-path decideTurnModel tests so they no longer inherit a leaked cross-file isModelAllowed mock (the CI test failure) - smartroute/index.test.ts: narrow the LocalCommandResult union via an expectText helper instead of reading .value off the union (the CI typecheck failure) - conversationRecovery.ts: route deserialize's thinking-strip gate through stripThinkingBlocksIfProviderAllows, removing the duplicated provider detection - conversationRecovery.test.ts: replace the two as-any fixtures with a shared typed factory * fix(smart-routing): scope cost claims to first-party reference pricing Smart routing's savings estimate and "simple isn't cheaper" warning were derived from the static first-party MODEL_COSTS table via getKnownInputCost, with no knowledge of the active provider, gateway, or account pricing. For a multi-provider user whose model ids happen to exist in that table but bill differently, the /cost summary and /smartroute warning stated a savings figure as if it reflected what they are actually charged. Narrow the copy instead of inventing provider-aware pricing the code cannot verify: the /cost line, the /smartroute warning, and docs/smart-routing.md now label the numbers as first-party reference pricing and note the active provider may bill differently. Tests assert the qualifier on every reworded branch so it cannot silently regress. No routing logic changed. * fix(smart-routing): clarify simple role wording * Fix smart routing review findings * fix(smart-routing): honor env roles and non-text turns * test(smart-routing): cover non-text skip path --------- Co-authored-by: jatmn <the@jat.mn> |
||
|
|
f6ecee0c00 |
chore: remove unused Python helper suite (#1827)
Remove the unused Python helper island under python/, including the standalone Ollama adapter, smart router, pytest tests, and Python requirements file. Drop the corresponding Python setup, dependency install, and pytest steps from the PR checks workflow now that no repo-level Python helper suite remains. Clean contributor-facing references in README, AGENTS.md, and CONTRIBUTING.md so the repository map and validation guidance no longer point at deleted Python helper code. Validation: - bun run build: passed - bun run typecheck: passed - bun run typecheck:type-tests: passed - bun run test:provider-recommendation: passed - bun run security:pr-scan -- --base upstream/main --head HEAD: passed - bun run check: failed in existing broader test suites unrelated to this removal (bughunter git context, Conversation Arc Scale and Stability, xAI OAuth callback) - bun run test:provider: failed in existing xAI OAuth callback tests Co-authored-by: jatmn <jatmn@users.noreply.github.com> |
||
|
|
1827d84709 |
feat(agents): add per-agent step limits (#1815)
* feat(agents): add per-agent step limits Add maxSteps agent configuration for markdown, JSON, plugin, and SDK agent definitions. Enforce the limit in subagent query execution by blocking over-limit tool calls, preserving a no-tool summary turn, and recording an agent_step_limit terminal reason. Add focused coverage for default behavior, invalid values, multi-turn accumulation, plugin parsing, failure-loop interaction, and summary-tool blocking. * test(agents): isolate agent loader fixtures * test(agents): stabilize agent loader config fixtures * fix(agents): harden step-limit summaries * fix(sdk): harden agent injection follow-up * fix(sdk): report invalid agent step limits |
||
|
|
985984b9ff |
feat(ClinePass): add gateway provider with usage support (#1818)
* feat(integrations): add ClinePass gateway provider with usage support Adds ClinePass (https://cline.bot) as an OpenAI-compatible gateway provider. Gateway - New descriptor at src/integrations/gateways/clinepass.ts with 10 static models. - Uses wireFormat: 'reasoning_effort' and full granular levels (low/medium/high/xhigh) so each model can expose reasoning controls consistent with Atlas Cloud. - Dedicated credentials only: requires CLINE_API_KEY and ignores stale OPENAI_API_KEY. - Generated integration artifacts updated via bun run integrations:generate. /usage support - New service module under src/services/api/clinepassUsage/ for types, fetching, and normalizing the ClinePass usage-limits response. - New UI component src/components/Settings/ClinePassUsage.tsx rendered by Usage.tsx. - Displays 5-hour, weekly, and monthly usage progress bars with longer progress bars. Provider profile fixes - routeMetadata.ts now resolves the active provider from the saved profile even when CLAUDE_CODE_PROVIDER_PROFILE_ENV_APPLIED is not yet set, so /usage works immediately after switching providers with /provider. - providerProfile.ts / providerProfiles.ts learn CLINE_API_KEY so saved profiles apply the ClinePass credential alongside the OpenAI-compatible env vars. Tests & docs - Updated ProviderManager.test.tsx and compatibility.test.ts for the new preset. - Added routeMetadata.test.ts cases for ClinePass and generic profile fallback. - Added clinepassUsage.test.ts for payload normalization and row building. - Updated .env.example and README.md with CLINE_API_KEY instructions. Validation - bun run typecheck - bun run build - bun run test:provider (964 pass) - bun run check (5331 pass; 1 unrelated Windows file-mode failure in branch.test.ts) * fixup: wire CLINE_API_KEY/CLINE_API_MODEL into runtime routing and profile persistence - Add 'clinepass' to the ProviderProfile union so saved profiles can use it. - Add CLINE_API_KEY to PROFILE_ENV_KEYS so profile switching clears stale keys. - routeMetadata.ts: env-only CLINE_API_KEY now selects the clinepass route; other env-only intents treat CLINE_API_KEY as a competing credential. Added isClinePassBaseUrl/getClinePassBaseUrlOverride and activeProfileBaseUrl option to resolveActiveRouteIdFromEnv so custom/unknown profiles targeting api.cline.bot resolve correctly. - providerConfig.ts: resolveProviderRequest now reads CLINE_API_MODEL when CLINE_API_KEY is present and defaults the base URL to https://api.cline.bot/api/v1. - providerProfiles.ts: CLINE_API_KEY is mirrored into startup/profile env for clinepass and custom profiles at api.cline.bot, and is checked in isProcessEnvAlignedWithProfile. - parse.ts: toIsoDate drops invalid resetsAt values instead of echoing them. - Add fetchClinePassUsage tests covering auth, headers, non-OK responses, and errors. - Add routeMetadata and providerConfig regression tests for ClinePass env/model wiring. - Add providerProfiles tests for CLINE_API_KEY propagation in apply/env and startup persistence. - Remove extra blank line in .env.example. Validation: - bun run typecheck - bun run build - bun run test:provider (972 pass) - bun run check (5346 pass; 1 unrelated Windows file-mode failure in branch.test.ts) * fixup: address PR review findings for ClinePass env routing and profile persistence - routeMetadata.ts: Let the concrete OPENAI_BASE_URL match win before falling back to activeProfileProvider / activeProfileBaseUrl. Prevents a saved ClinePass profile from overriding an explicit CLAUDE_CODE_USE_OPENAI env pointing at another gateway. - providerConfig.ts: Gate the ClinePass model branch behind !isGithubMode so a stale CLINE_API_KEY/CLINE_API_MODEL does not override GitHub Copilot model selection. - providerProfiles.ts: Introduce isClinePassProfile() predicate that uses route resolution (routeId === 'clinepass' || baseUrl includes api.cline.bot) and share it across live application, alignment, and startup persistence paths so saved ClinePass profiles keep the dedicated credential consistently even with non-default base URLs. - Add regression tests covering all three findings. Validation: - bun run typecheck - bun run build - bun run test:provider (973 pass) * fixup: use hostname-based ClinePass detection in providerProfiles Replace includes('api.cline.bot') substring matching with isClinePassBaseUrl which validates the exact hostname via URL parsing, preventing spoofed hosts like api.cline.bot.evil.example from triggering CLINE_API_KEY mirroring. Validation: - bun run typecheck - bun run build - bun run test:provider (973 pass) * fixup: gate ClinePass model selection on resolved base URL Move base URL resolution before model selection in resolveProviderRequest so effectiveClinePassMode is only active when no explicit non-ClinePass base URL is set via options.baseUrl, OPENAI_BASE_URL, or OPENAI_API_BASE. Previously CLINE_API_KEY=cp-key + CLINE_API_MODEL=cline-pass/qwen3.7-max + OPENAI_BASE_URL=https://api.openai.com/v1 would return requestedModel=cline-pass/qwen3.7-max with baseUrl=https://api.openai.com/v1, sending a ClinePass model ID to a non-Cline provider. Now the resolver returns the correct OPENAI_MODEL and OpenAI base URL in that scenario, and only uses ClinePass model/default-base when the resolved base URL is absent or actually api.cline.bot. Added regression tests for: - CLINE_API_KEY + CLINE_API_MODEL + explicit OPENAI_BASE_URL - CLINE_API_KEY + CLINE_API_MODEL + explicit baseUrl option - CLINE_API_KEY + CLINE_API_MODEL with no base URL (ClinePass default) Validation: - bun run typecheck - bun run build - bun run test:provider (976 pass) * fixup: default ClinePass model for blank env Treat whitespace-only CLINE_API_MODEL as unset so OPENAI_MODEL can still provide the ClinePass model override. When CLINE_API_KEY selects ClinePass without any model env, fall back to the ClinePass route default instead of the generic codexplan alias. Validation: - timeout 600 bun test src/services/api/providerConfig.test.ts - timeout 600 bun test src/services/api/clinepassUsage.test.ts src/integrations/routeMetadata.test.ts src/services/api/providerConfig.test.ts src/utils/providerProfiles.test.ts src/integrations/compatibility.test.ts src/components/ProviderManager.test.tsx - timeout 600 bun test src/services/api/providerConfig.test.ts src/services/api/client.test.ts src/integrations/routeMetadata.test.ts src/integrations/runtimeMetadata.test.ts src/services/api/clinepassUsage.test.ts src/services/api/minimaxUsage.test.ts src/utils/providerProfiles.test.ts - timeout 600 bun run integrations:check - timeout 600 bun run typecheck - timeout 600 bun run build - timeout 600 bun run security:pr-scan - git diff --check origin/main...HEAD |
||
|
|
259c7ec27a |
fix(ollama): preserve chat history with native context (#1805)
* fix(ollama): preserve chat history with native context Route Ollama chat requests through the native /api/chat endpoint so OpenClaude can send request-level options.num_ctx instead of relying on Ollama's OpenAI-compatible shim. Default the Ollama request context to 32768 tokens, support OPENCLAUDE_OLLAMA_NUM_CTX and OLLAMA_CONTEXT_LENGTH overrides, and map max tokens/temperature/top_p into native Ollama options. Adapt native Ollama streaming and non-streaming responses back into the existing OpenAI-shaped conversion pipeline, including usage, text, structured tool calls, and tool_use stop reasons. Normalize native Ollama request messages for images and historical tool calls, avoiding OpenAI-only image_url/id/type payload fields in /api/chat requests. Add Ollama context diagnostics, loopback-only ollama ps status checks, regression coverage, and documentation for verifying active context length. * fix(ollama): address native routing review feedback * fix(ollama): restrict loopback host matching * fix(ollama): exclude wildcard bind address * fix(ollama): keep https localhost proxies on chat completions --------- Co-authored-by: jatmn <12479882+jatmn@users.noreply.github.com> |
||
|
|
8023356841 |
feat(session): harden fork-session branching (#1801)
* feat(session): harden fork-session branching Add explicit fork-session branching metadata, preserve fork-owned transcript state, and seed retained content replacement records for forked resumes. Document --fork-session behavior and cover forked resume transcript/materialization behavior with focused tests. * fix(session): respect print persistence for fork seeding |
||
|
|
38b0e27333 |
fix(opencode-go): sync model catalog with opencode.ai/go (#1745)
* fix(opencode-go): sync model catalog with opencode.ai/go The OpenCode Go subscription page (https://opencode.ai/go) lists 13 models, but the catalog had 20. Remove the 7 models no longer offered: glm-5, kimi-k2.5, minimax-m2.5, qwen3.5-plus, mimo-v2-pro, mimo-v2-omni, hy3-preview. Catalog now matches the page exactly: - OpenAI-compatible: GLM 5.2, GLM 5.1, Kimi K2.7 Code, Kimi K2.6, DeepSeek V4 Pro, DeepSeek V4 Flash, MiMo V2.5 Pro, MiMo V2.5 - Anthropic messages: MiniMax M3, MiniMax M2.7, Qwen3.7 Max, Qwen3.7 Plus, Qwen3.6 Plus Updates gateway catalog, model descriptors, generated artifacts, and tests. * fix(opencode-go): reorder model catalog to match opencode.ai/go listing Reorder both the gateway catalog and model descriptor lists to match the order models appear on https://opencode.ai/go, so the in-app model picker mirrors the subscription page. No model added or removed — purely a reorder. GLM-5.2 → Qwen3.7 Max → Kimi K2.7 Code → MiMo V2.5 Pro → DeepSeek V4 Pro → Qwen3.7 Plus → MiniMax M3 → MiMo V2.5 → DeepSeek V4 Flash → GLM 5.1 → Kimi K2.6 → Qwen3.6 Plus → MiniMax M2.7 * test(opencode-go): assert exact model set matches opencode.ai/go catalog Address CodeRabbit review on #1745 — the count-only test wouldn't catch catalog drift. Add a strict set assertion verifying the 13 expected IDs are present and no removed/unexpected IDs remain. * test(opencode-go): update Anthropic Messages route test for refreshed catalog The direct-env-routing test listed minimax-m2.5 and qwen3.5-plus, which were removed from the opencode-go catalog. Replace with the five /messages-endpoint models that remain: minimax-m3, minimax-m2.7, qwen3.7-max, qwen3.7-plus, qwen3.6-plus. Unblocks the smoke-and-tests CI check on #1745. * fix: update OpenCode Go model references to 13 models and add assertions |
||
|
|
5625f4217d |
fix: preserve provider route context metadata (#1741)
* fix: preserve provider route context metadata Resolve issue #1732 by keeping active provider-profile routes attached during context limit resolution and making gateway-prefixed model IDs resolve against provider-scoped metadata instead of falling through to global aliases. Preserve composite provider-path suffixes such as accounts/fireworks/models/... and fireworks/models/... before generic last-segment matching, so wrapped gateway IDs resolve Fireworks-specific limits instead of generic descriptors. Refresh OpenCode Zen and OpenCode Go catalog metadata, including route-specific context/output limits, regenerate integration artifacts, add DeepSeek V4 Pro on NVIDIA NIM, add the Gemini 3.1 Pro router alias, and update user-facing OpenCode model counts. Scope OpenCode descriptor default model names to OpenCode routes via providerModelMap so unprefixed vendor lookups are not hijacked by gateway descriptors. Add wrapper-path assertions for the user-facing max output token helper. Add regression coverage for provider-prefixed gateway models, active-profile route preservation, account-qualified composite paths, and OpenRouter-wrapped fireworks/models/... paths. Harden Windows/full-suite validation by normalizing plugin hook display paths and resetting status-redaction HOME/USERPROFILE state. Validation: bun install; bun run build; bun run smoke; bun run typecheck; bun run typecheck:type-tests; bun run check (4634 pass, 0 fail); bun run test:provider (857 pass, 0 fail); bun run test:provider-recommendation (91 pass, 0 fail); bun run integrations:check; bun run security:pr-scan -- --base upstream/main; git diff --check. Follow-up validation: bun test src/integrations/runtimeMetadata.test.ts --max-concurrency=1; bun test src/utils/context.test.ts src/integrations/runtimeMetadata.test.ts src/integrations/gateways/opencode.test.ts --max-concurrency=1; bun run test:provider; bun run integrations:check; bun run typecheck; git diff --check. # Conflicts: # src/integrations/gateways/opencode-go.ts # src/integrations/models/opencode.ts * fix: align OpenCode context metadata Refresh OpenCode Zen and Go descriptor context/output limits against the live OpenCode model lists and Models.dev provider metadata. Add a regression assertion for provider-specific OpenCode limits so route-scoped metadata does not fall back to generic model budgets. * fix: remove duplicate Gemini model descriptor Keep the canonical Gemini 3.1 Pro descriptor and rely on provider-prefixed suffix matching for google/gemini-3.1-pro runtime lookups. Also separate the OpenCode limit regression test from the following assertion for readability. * fix: preserve OpenCode Go messages auth metadata * test: cover OpenCode Go review cases |
||
|
|
b581bd9ece |
feat(zai): add GLM-5.2 support (#1689)
* feat(zai): add GLM-5.2 thinking support * fix(provider): derive GHE Copilot URL from base URL * fix(zai): gate GLM reasoning effort by model |
||
|
|
2aad6fc93e |
feat(config): add OPENCLAUDE_CONFIG_DIR override (#1683)
* feat(config): add OPENCLAUDE_CONFIG_DIR env var as preferred alias for CLAUDE_CONFIG_DIR (#454) The legacy CLAUDE_CONFIG_DIR name was the only way to point openclaude at a non-default config home, which leaked Anthropic branding for a fork that has otherwise rebranded to OpenClaude. Add OPENCLAUDE_CONFIG_DIR as the preferred name. CLAUDE_CONFIG_DIR continues to work for backward compatibility; when both are set with different values, OPENCLAUDE_CONFIG_DIR wins and a one-time warning is logged. - src/utils/envUtils.ts: introduce resolveConfigDirEnv() that picks OPENCLAUDE_CONFIG_DIR over CLAUDE_CONFIG_DIR and emits a conflict warning. Memoize cache key now tracks both env vars so changing either invalidates the cached result. - src/utils/env.ts: getGlobalClaudeFile() previously read CLAUDE_CONFIG_DIR directly, missing the new alias. Route through resolveConfigDirEnv() so the global config file path follows the same precedence. - src/utils/secureStorage/macOsKeychainHelpers.ts: the "is default dir" check used by keychain service-name scoping now considers both env vars. - src/utils/swarm/spawnUtils.ts: forward OPENCLAUDE_CONFIG_DIR to teammate processes alongside the legacy var. - src/utils/openclaudePaths.test.ts: +6 unit tests covering the new alias, fallthrough, conflict warning, and resolveConfigDirEnv() in isolation. - .env.example: document both env vars and the precedence rule. Verified locally on Linux: with only OPENCLAUDE_CONFIG_DIR set, with only CLAUDE_CONFIG_DIR set (legacy still works), with both set matching (silent), with both set conflicting (warn once + OPENCLAUDE wins), with neither set (default ~/.openclaude). Memo cache invalidates across 4 sequential env transitions. Built dist/cli.mjs honors the new var and emits the conflict warning to the user. * Fix config-dir warning and docs review findings Only mark the config-dir conflict warning as emitted when a warning callback actually receives it, add coverage for warn-once and silent callers, and update web configuration docs for OPENCLAUDE_CONFIG_DIR precedence. # Conflicts: # web/src/data/configuration.ts * Align configuration docs with openclaude paths Update the configuration page settings-file table to point default users at .openclaude settings and keybindings paths, matching the new config home behavior. * Align keybindings docs with openclaude config home Update the keybindings page, keybindings docs data, and skill index to point default users at ~/.openclaude/keybindings.json. * Align skill and hook labels with openclaude paths Update bundled config/keybindings skill prompts, public skills docs, hook/trust labels, and the user memory selector to use the active OpenClaude config home paths. # Conflicts: # src/components/TrustDialog/utils.ts # src/components/hooks/SelectEventMode.tsx # src/skills/bundled/updateConfig.ts # src/utils/hooks/hooksSettings.ts * Resolve config-home paths dynamically in skill prompts Use runtime settings/keybindings path helpers for bundled skill prompts and the restricted-hooks banner so custom OPENCLAUDE_CONFIG_DIR values are reflected in user-facing guidance. * Update active command prompts for openclaude paths Point statusline, setup/onboarding prompts, plugin messages, and the external user-memory warning at the active OpenClaude settings and memory paths. # Conflicts: # src/commands/auto-fix.ts # src/commands/onboard-github/onboard-github.tsx # src/commands/plugin/ManagePlugins.tsx # src/commands/statusline.tsx * Fix remaining config path review findings * Cover dynamic config paths in UI and storage tests * Fix config path smoke failures after rebase * Fix remaining config path review findings --------- Co-authored-by: gnanam1990 <gnanasekaran.sekareee@gmail.com> |
||
|
|
5af6f95c46 |
feat(config): add explicit provider env-file loading (#1668)
* feat(config): add explicit provider env-file loading * fix(config): handle escaped quotes in provider env files * fix(config): polish env-file parser review feedback * fix(config): preserve provider env-file precedence * test(config): cover provider env-file precedence * fix(config): preserve provider env-file values * fix(config): allow documented env-file setup vars * fix(config): preserve provider flag precedence |
||
|
|
a1b3346f65 |
feat(cli): add local background sessions (#1642)
* feat(cli): add local background sessions Add local detached background sessions backed by an OpenClaude-owned registry under the resolved config directory. - implement --bg spawning plus ps, logs, logs -f, kill, and an explicit attach limitation - harden registry metadata validation, atomic writes, ID/name collision handling, and terminal-name reuse - precreate child log files with precise ownership cleanup and register metadata only after spawn succeeds - verify live PIDs against the session command before treating registry entries as running - wait for process-tree termination and escalate to SIGKILL before marking sessions killed - skip live local background sessions during --continue transcript selection - preserve Node heap flags for detached children while avoiding stale launcher relaunch state - handle -- separators so dash-prefixed prompts remain positional - document storage, safety model, name reuse, and the current attach limitation Validation: - bun test - bun run typecheck - bun run smoke - isolated built-CLI --bg/ps/logs/kill smoke - CodeRabbit review findings addressed * test(utils): prevent bg registry mock leakage Restore complete bg registry and UDS module mocks after conversation recovery tests so Bun's process-global mock.module registry cannot leak partial module exports into later CLI tests. CI exposed this under Bun 1.3.13 when conversationRecovery.test ran before the bgRegistry and bg CLI test files. * test(utils): exercise bg registry without global mock Replace the conversation recovery bgRegistry module mock with real registry metadata backed by a short-lived live child process. This keeps UDS as the only mocked boundary and avoids leaking a mocked registry module into later CLI registry tests under Bun 1.3.13. * test(utils): isolate background registry state Stop the conversation recovery test from using process-wide bgRegistry mocks or real child processes by injecting the live-session dependencies directly. Pin and serialize the bg registry test config directory through the shared env mutation lock so path/cache state cannot leak from neighboring tests under Bun CI ordering. * test(utils): document Bun mock restoration Explain why conversation recovery tests re-register full module exports after mock.restore(), matching the CodeRabbit-requested Bun 1.3.13 isolation workaround. * test(cli): isolate background registry root Avoid relying on process-wide CLAUDE_CONFIG_DIR state in bgRegistry tests. Use a registry-local test root override so CI file ordering and mocked path modules cannot redirect background session metadata into another test's temp directory. * test(utils): cover live session fallback paths Add focused coverage for collectLiveBackgroundSessionIds when UDS discovery fails but registry data remains available, and when registry refresh fails but UDS data remains available. * fix(cli): harden background session management Validate persisted and newly-created background session PIDs before exposing them to management commands. Reserve named live sessions with an atomic registry write, release reservations when sessions become terminal, and cover concurrent duplicate-name attempts. Split local session management dispatch from background spawning so ps/logs/attach/kill avoid provider startup while --bg still inherits profile routing. * fix(cli): address background session review findings Preserve positional prompts when --bg is combined with optional-value flags such as --debug. Recover stale name reservations whose owner metadata is missing or terminal while preserving in-flight reservations from live creators. Cover both reviewer findings with focused parser and registry regression tests. * fix(cli): respect delimiter for background flags Limit background and print-mode flag detection to arguments before the -- delimiter so flag-shaped prompts remain positional. Keep optional resume/from-pr flags out of the required-value table and add regressions for delimiter and optional-flag prompt handling. * refactor(cli): share delimiter argument helper Move args-before-delimiter handling into the existing dependency-free CLI args utility. Use a dynamic import from the entrypoint so background flag routing shares the helper without adding top-level module load to version and management fast paths. * test(cli): cover background entrypoint routing Export the CLI entrypoint for controlled tests and add isolated importer injection so runtime routing tests do not leak global module mocks. Replace the delimiter source-layout assertion with execution-level coverage for management commands, real background flags, and flag-shaped prompt text after --. * fix(cli): preserve background resume selectors Keep space-separated --resume, -r, and --from-pr values attached when building background child args. Mark live background sessions stale when PID command identity cannot be read, avoiding termination of reused unrelated PIDs. * fix(cli): track unknown background session identity Represent unreadable live PID identity as a non-terminal unknown state so active sessions stay excluded from resume selection. Refuse to terminate unknown live PIDs because the process command cannot be positively matched to the background session. * fix(cli): honor background resume selectors Avoid adding a generated --session-id to non-forked background resume launches so the spawned print-mode child satisfies the existing resume/session-id contract. Pass --from-pr through headless print mode and resolve PR-linked sessions through the shared conversation recovery path. Add regression coverage for background resume launch args and PR selector matching. * fix(cli): treat PR resume as headless resume source Include --from-pr in print-mode resume guards so PR-linked headless resumes can run without a prompt and share resume-only options. Skip eager startup hooks for headless PR resumes and add explicit --session-id launch coverage. * fix(cli): keep background PR resumes live Resolve non-forked --from-pr background launches to the selected transcript id before writing registry metadata. Preserve PID identity refresh for PR-resume children by matching the stored invocation when argv does not carry the transcript id. Add regressions for launch registration and registry refresh. * test(cli): cover PR resume lookup failures Add regression coverage for non-forked background --from-pr launches when the selector cannot be resolved. Verify the launch planner returns the same clear error used by handleBgFlag(). |
||
|
|
a36ef463ce |
docs(readme): add social links and clarify license line (#1660)
- Add Discord (discord.gg/k68zFR6AcB) and X (x.com/gitlawb) as shields.io badges in the top badge row and as descriptive links in the Community section. - License section now notes contributor modifications are MIT while the derived Claude Code remains Anthropic's, with a "See more" link to LICENSE. Co-authored-by: OpenClaude <openclaude@gitlawb.com> |
||
|
|
d8dbf274b4 |
chore(runtime): align Node.js minimum version (#1644)
* chore(runtime): align Node.js runtime requirements * test(runtime): cover prefixed Node versions * fix(runtime): check node executable in doctor |
||
|
|
822eff39d1 |
fix(copilot): limit sub-agent concurrency to reduce Premium Request usage (#678) (#1534)
* fix(copilot): limit sub-agent concurrency to reduce Premium Request usage (#678) * fix(copilot): enforce sub-agent concurrency cap at Agent invocation level AgentTool.isConcurrencySafe() now returns false when getCopilotMaxConcurrentSubagents() > 0, preventing the tool scheduler from batching multiple Agent calls together. This ensures at most one sub-agent runs at a time when the cap is active. Previously, AgentTool was always concurrency-safe, allowing the scheduler's runToolsConcurrently to batch multiple Agent calls from a single assistant message — bypassing the documented MAX_SUBAGENTS cap. Add comprehensive copilotOptimization unit tests. * fix(copilot): enforce cap for any positive value and honor OPTIMIZATION_DISABLED - shouldForceSyncSubagentsInCopilotMode: gate on > 0 instead of === 1 so any configured cap (2, 3, ..., 10) forces serial execution - isConcurrencySafe: early-return true when OPTIMIZATION_DISABLED is set - Update log message to reflect any-cap behavior * fix(copilot): align scheduler with launch path, fix mock leak - isConcurrencySafe now uses shouldForceSyncSubagentsInCopilotMode() instead of raw cap check, matching the launch path at line 447 - Add afterAll(mock.restore) to copilotOptimization.test.ts to prevent providers.js mock leaking to AgentTool routing tests * fix(copilot): clarify MAX_SUBAGENTS semantics and fix remediation hint log - Document that only MAX_SUBAGENTS=0 and =1 are enforced; values 2-10 have no runtime effect. - Fix the log remediation hint to depend on the actual cause: MAX=0 suppresses sub-agents entirely (not just forces sync), FORCE_SYNC=1 requires unsetting the flag, and MAX>=1 requires ALLOW_SUBAGENTS=1 to restore parallel execution. * docs(env): document GITHUB_COPILOT_* tuning vars in .env.example The Copilot Premium Request optimization introduces four env vars (GITHUB_COPILOT_MAX_SUBAGENTS, GITHUB_COPILOT_ALLOW_SUBAGENTS, GITHUB_COPILOT_FORCE_SYNC_SUBAGENTS, GITHUB_COPILOT_OPTIMIZATION_DISABLED) that change how sub-agents run for CLAUDE_CODE_USE_GITHUB=1 sessions. Previously these were documented only in source comments, which made them undiscoverable for users affected by the new default. Add them to the GitHub Models section (Option 4) of .env.example with descriptions of each var's effect and default value, addressing the reviewer ask to put the new default behavior in user-facing docs. * fix(copilot): telemetry reflects final async mode; docs in README Address outstanding review gaps for #1534: 1. Telemetry is_async/isAsync now uses the final shouldRunAsync value computed once at the top of the function (was duplicating the partial expression, omitting isCoordinator/forceAsync/assistantForceAsync/ proactiveModule signals that contribute to the launch decision). 2. The shouldSuppressSubagentsInCopilotMode() throw now happens before the event log (so a suppressed-agent error isn't followed by a misleading 'is_async: true' event). 3. isCoordinator, forceAsync, assistantForceAsync are now computed once alongside forceSyncCopilot instead of being declared inline later. 4. README: add GitHub Copilot sub-agent optimization subsection under Provider Notes, with the env var table mirroring the .env.example entry (default behavior, cap semantics, all-opt-out). The doc comment in copilotOptimization.ts L16-29 already explains MAX_SUBAGENTS=0/1 enforcement; the test at L186-191 is consistent with the current implementation (positive cap = synchronous). Skipped: getEffectiveConcurrencyCap() in toolOrchestration.ts (the function no longer exists in the current code; the bot's review was based on an earlier version). * fix(copilot): skip <BackgroundHint /> when forced sync When forceSyncCopilot is true the task can no longer be backgrounded (registerAgentForeground is skipped at L918), but the background hint UI was still rendered once the progress threshold elapsed. That advertises a non-existent affordance on every long-running Copilot sub-agent, which is confusing for users. Gate the hint on the same !forceSyncCopilot condition as the foreground registration. Address the CodeRabbit P2 on round 6. * test(copilot): use spyOn instead of mock.module to avoid partial-mock leak CodeRabbit P2 review on round 7 found the copilotOptimization test registered mock.module('./model/providers.js', () => ({ only 4 exports })) which removed all other exports of providers.ts. Downstream tests in the same CI process (e.g. withRetry, domainCheck, apiPreconnect, agent) that import symbols like isFirstPartyAnthropicBaseUrl would then fail with 'Export named ... not found in module' errors. Switch to spyOn() on the real providers module's getAPIProvider. The real module's other exports remain available, and the spy is torn down via mockRestore() in afterEach. Also drop the cache-busting dynamic-import pattern: the spy persists across the static import, so the test no longer needs a fresh module per test. Also fix README P3: the earlier PowerShell heredoc introduced a TAB (0x09) and Form Feed (0x0C) in place of 't' and 'f' in the new Copilot section, rendering 'tengu_agent_tool_selected' as 'engu_...' and 'false' as 'alse'. Rewrite the line with proper 't' and 'f' characters and add backticks for code formatting (was unformatted plain text). Skipped: P2 scheduler-boundary coverage (CodeRabbit round 6 item). That requires driving multiple Agent tool-use blocks through the scheduler in AgentTool/StreamingToolExecutor, which is a larger change than the current PR's scope. * test(copilot): add FORCE_SYNC overrides ALLOW_SUBAGENTS precedence test CodeRabbit round 9: add a test that pins the precedence between GITHUB_COPILOT_FORCE_SYNC_SUBAGENTS=1 and GITHUB_COPILOT_ALLOW_SUBAGENTS=1. The user explicitly asking for synchronous execution must win over the softer "I'm fine with the cap" opt-out. A future reordering of the checks in shouldForceSyncSubagentsInCopilotMode() would silently allow parallel Copilot sub-agent launches when the user asked for sync; this test locks the precedence. Verified locally: 23/23 pass (was 22/22 before adding this test). * fix(copilot): address jatmn round 11 P2/P3 and add scheduler-boundary coverage This commit addresses the latest human + bot review feedback on #1534 across three findings: 1. **P3: Update GitHub Copilot comment in github.ts to use billing-cycle wording.** The previous comment hard-coded "per month (300 for Copilot Free)" — a calendar quota the runtime doesn't own. Mirror the wording from src/utils/copilotOptimization.ts: "per billing cycle, with the exact quota set by the user's Copilot plan." Same docstring shape across both files now. 2. **P2: Add afterEach cleanup to copilotOptimization.test.ts.** Captured the GITHUB_COPILOT_* env vars at module top-level and restore them in afterEach. Previously only beforeEach deleted them, so the precedence test (which sets FORCE_SYNC=1 + ALLOW_SUBAGENTS=1) left those values in process.env after the file completed. Verified by `bun test src/utils/copilotOptimization.test.ts ../copilot-env-probe.test.ts`: before the fix, the probe test sees FORCE_SYNC=1 leaked. After the fix, the probe sees the original env. This is the round 11 P2 review item from jatmn. 3. **P2: Add scheduler-boundary regression test.** New file src/tools/AgentTool/AgentTool.copilotScheduling.test.ts pins the launch↔scheduler alignment by calling `AgentTool.isConcurrencySafe()` directly under each Copilot flag combination. Seven matrix rows: OPTIMIZATION_DISABLED=1, default cap=1, cap=2, ALLOW_SUBAGENTS=1, FORCE_SYNC=1 alone, FORCE_SYNC=1 + ALLOW_SUBAGENTS=1 (precedence), cap=0 (suppressed). A future reorder of the helpers in copilotOptimization.ts that breaks the precedence would fail FORCE_SYNC + ALLOW_SUBAGENTS, locking the launch/scheduling alignment. This is the round 9 / round 11 P2 review item from CodeRabbit + jatmn that has been deferred across multiple rounds. The test uses spyOn on providers.getAPIProvider to control the provider state, then imports AgentTool via cache-busting (?copilotScheduling=... query string) — the same pattern as AgentTool.routing.test.ts. Per-test timeout of 30s absorbs the ~16s one-time AgentTool module load (subsequent tests are sub-1ms because the module is cached after the first beforeAll import). All three changes are verified locally: - `bun test src/utils/copilotOptimization.test.ts` — 23/23 pass - `bun test src/tools/AgentTool/AgentTool.copilotScheduling.test.ts` — 7/7 pass - `bun test --max-concurrency=1` of both files together — 30/30 pass * test(copilot): move per-test timeout to 3rd arg (bun:test API) * fix(copilot): let FORCE_SYNC override MAX_SUBAGENTS=0 + add scheduler-boundary test Two review findings: 1. FORCE_SYNC vs suppression: shouldSuppressSubagentsInCopilotMode() returned true for MAX_SUBAGENTS=0 before FORCE_SYNC was consulted, so GITHUB_COPILOT_MAX_SUBAGENTS=0 + GITHUB_COPILOT_FORCE_SYNC_SUBAGENTS=1 threw "Sub-agents are disabled" instead of running them synchronously, contradicting the documented behavior. FORCE_SYNC (like ALLOW_SUBAGENTS) now bypasses the =0 suppression; docs clarified accordingly. 2. Scheduler-boundary coverage: the existing tests only called isConcurrencySafe() directly. Added a regression that drives multiple Agent tool-use blocks through the real batching path (partitionToolCalls, now exposed via _test): forced-sync splits them into serial single-block batches, ALLOW_SUBAGENTS coalesces them into one concurrent batch. Catches a future divergence between launch and scheduling policy for multiple Agent blocks in one assistant message. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
9e902db866 |
feat(agent-routing): model-only agent routes (set the verifier or any agent's model on the current provider) (#1617)
* feat(agent-routing): allow model-only agentModels entries in settings schema * feat(agent-routing): resolve model-only agent routes that reuse the current provider * feat(agent-routing): enforce org model allowlist for model-only agent routes * docs(agent-routing): document model-only routes and built-in agent keys * test(agent-routing): stub and assert partial-entry routing warnings Silence the intentional console.error noise from partial agentModels entries in CI logs by stubbing console.error per describe block and asserting the expected warning message fires, so future routing warnings or failures are not masked. * test(agent-routing): consolidate shouldEnforceModelAllowlist import Move the import to the top import block instead of mid-file. |
||
|
|
0b24b60ce9 |
feat(provider): add Fireworks AI as official OpenAI-compatible provider (#1590)
* feat(provider): add Fireworks AI as official OpenAI-compatible provider
Includes vendor descriptor, brand descriptor (276 models), model
descriptors (full + merged), routing metadata, env auto-detection,
profile support, client defaults, and docs.
* test: add focused regression tests for Fireworks AI auth and routing
- Add 7 env-only routing tests in client.test.ts (shim routing,
stale model replacement, base URL override, shim option cleanup,
non-Fireworks override ignored, priority with MiniMax, Bedrock yield)
- Add FIREWORKS_API_KEY auto-detection test in providerAutoDetect.test.ts
- Add profile apply/persistence/env-drift tests in providerProfiles.test.ts
- Fix FIREWORKS_API_KEY propagation in strictEnv early return path
* fix: address reviewer comments on Fireworks integration
- Remove OPENAI_API_KEY exclusion so Fireworks cred wins over stale OpenAI key
- Fix TS type error in test by using String() wrapper
- Add Fireworks to detection priority comment in providerAutoDetect.ts
- Add useFireworksEnvOnlyProvider to shim condition for pattern consistency
- Replace loose .includes('fireworks.ai') with isFireworksBaseUrl() exact hostname check
* fix: add explicit case 'fireworks' in applyProviderFlag for credential precedence
- Add 'fireworks' to PREFERRED_PROVIDER_ORDER
- Add case 'fireworks' with dedicated key winning pattern (mirrors atlas-cloud)
- Add FIREWORKS_API_KEY to copiedOpenAIKeyProvider detection so stale
keys are cleaned up when switching away from Fireworks
* fix: guard fireworks defaultModel assignment against 'undefined' string coercion
* fix: remove leftover conflict marker in providerProfiles.ts
* docs(fireworks): add JSDoc to Fireworks functions for coderabbit docstring coverage
Adds JSDoc annotations to isFireworksBaseUrl, getFireworksBaseUrlOverride,
hasFireworksEnvOnlyProviderIntent, isFireworksModelName, and
applyFireworksEnvOnlyDefaults.
* fix(fireworks): cross-check NEARAI_API_KEY in env-only intent functions
hasNearaiEnvOnlyProviderIntent and hasFireworksEnvOnlyProviderIntent were
missing mutual cross-checks. When both NEARAI_API_KEY and FIREWORKS_API_KEY
are set, neither excludes the other, and nearai silently wins by ordering.
Adding !hasNonEmptyEnvValue(processEnv.FIREWORKS_API_KEY) to the nearai intent
and !hasNonEmptyEnvValue(processEnv.NEARAI_API_KEY) to the fireworks intent
ensures both return false, forcing explicit provider selection.
* fix(fireworks): fix typo in JSDoc — OPENAI_API_API_BASE -> OPENAI_API_BASE
* fix(fireworks): remove merge artifact and preserve no-key auth headers
- src/utils/providerAutoDetect.ts: remove leftover ======= conflict
marker and stale duplicate priority lines
- src/utils/providerProfiles.ts: preserve apiFormat, authHeader,
authScheme, authHeaderValue in the no-key OpenAI-compatible
fallback path so saved Responses mode / custom auth config
survives restart
* fix: Fireworks env-only startup preservation and MIMO priority comment
- Add FIREWORKS_API_KEY check to hasConcreteProviderSelection() so env-only
Fireworks setup is not overwritten by Gitlawb Opengateway default
- Add regression test verifying FIREWORKS_API_KEY survives no-profile startup
- Fix providerAutoDetect.ts priority comment to include MIMO_API_KEY (position 8)
and renumber subsequent entries to match actual detection order
* fix: also preserve env-only NEAR AI startup in hasConcreteProviderSelection()
* fix: remove duplicate Fireworks model descriptor, add FIREWORKS_API_KEY to test env cleanup
* fix: move duplicate model check to generation-time, add OPENAI_AUTH_* env cleanup to test harness
---------
Co-authored-by: Gravirei <gravirei@users.noreply.github.com>
|
||
|
|
eacc7d8fac |
feat: add NEAR AI provider integration (#1594)
* feat: add NEAR AI provider integration
- Create vendor, brand, and model descriptors for NEAR AI (22 models)
- Add NEAR AI to route metadata, client, provider auto-detect, and profiles
- Update compatibility tests and ProviderManager test PRESET_ORDER
- Add README and docs entries for NEAR AI provider
- Update .env.example with NEAR AI configuration
* fix: address CodeRabbit review comments
- Fix .env.example: change 'Option N' to 'Option 11' in quick reference
- Narrow isNearaiModelName to use explicit NearAI model prefixes instead of broad includes('/')
- Add NEARAI_API_KEY propagation in strictEnv startup path
* fix: align NEAR AI validation host matching with wildcard subdomain routing
- Add *.completions.near.ai to matchBaseUrlHosts in vendor descriptor
- Add matchHostnameAgainstRouteHosts helper with wildcard (*.) prefix support
- Use helper in both resolveRouteIdFromBaseUrl and getRuntimeValidationTarget
- Add regression test for qwen35-122b.completions.near.ai TEE endpoint
- Add NEARAI_API_KEY to test env cleanup list
* fix: align Near AI integration with env-only provider best practices
- Replace loose .includes('near.ai') with isNearaiBaseUrl() in providerProfiles.ts
for exact hostname validation (all 4 instances)
- Add NEARAI_API_KEY to copiedOpenAIKeyProvider detection in providerFlag.ts
- Add case 'nearai' to applyProviderFlag switch with dedicated key precedence
- Add 'nearai' to PREFERRED_PROVIDER_ORDER
- Add useNearaiEnvOnlyProvider to OpenAI shim condition in client.ts
- Remove OPENAI_API_KEY exclusion from hasNearaiEnvOnlyProviderIntent (dedicated
key wins over stale generic key, consistent with xAI pattern)
- Update detection priority comment in providerAutoDetect.ts to include
MIMO_API_KEY, XAI_API_KEY, and NEARAI_API_KEY
* fix: add exact completions.near.ai host to isNearaiBaseUrl
* fix: add higher-precedence provider key exclusions to hasNearaiEnvOnlyProviderIntent
* fix: add OPENAI_API_KEY and MINIMAX_API_KEY exclusions to hasNearaiEnvOnlyProviderIntent
* fix(near-ai): don't let stale OPENAI_API_KEY suppress Near AI routing
---------
Co-authored-by: Gravirei <gravirei@users.noreply.github.com>
|
||
|
|
286d403093 |
Update(zen-go): add claude-opus-4-8, minimax-m3, mimo-v2.5-free models and proper effort level integration for Zen/Go models (#1505)
* feat(provider): add OpenCode Zen/Go subscription support
Add OpenCode as a first-class provider, enabling users to connect their
Zen (pay-as-you-go) and Go ($10/mo) subscriptions via the /provider command.
New integration descriptors:
- vendors/opencode.ts — OpenCode Zen vendor (41 models)
- gateways/opencode-go.ts — OpenCode Go gateway (12 models)
- brands/opencode.ts — brand descriptor
- models/opencode.ts — full model catalog (GPT, Claude, Gemini, Qwen,
GLM, Kimi, MiniMax, Grok, DeepSeek, MiMo, Nemotron)
Modified files:
- integrationArtifacts.generated.ts — register descriptors and presets
- providerProfile.ts — add OPENCODE_API_KEY env/secret key, 'opencode'
profile type, and buildLaunchEnv handler
- providerConfig.ts — add DEFAULT_OPENCODE_BASE_URL constants
Auth: OPENCODE_API_KEY env var or interactive key entry in /provider
Transport: openai-compatible (chat_completions)
Base URLs: https://opencode.ai/zen/v1 (Zen), /zen/go/v1 (Go)
* feat(provider): add [Zen]/[Go] tags to OpenCode preset labels
Add visual tags in the /provider preset selection to distinguish
OpenCode Zen (pay-as-you-go) from OpenCode Go (subscription).
* feat(provider): enable dynamic model discovery for OpenCode
Switch OpenCode vendor and Go gateway from static to hybrid model
catalog with openai-compatible discovery. Models are fetched from
/v1/models on startup and cached for 1 hour. Manual refresh is
supported via the /provider UI.
Static model list is preserved as fallback when discovery fails.
* test(provider): add comprehensive OpenCode Zen/Go test suite
97 tests across 2 files covering:
Integration tests (72 tests):
- Vendor descriptor: id, label, classification, base URL, model, auth,
transport, preset, validation, catalog, discovery, usage metadata
- Gateway descriptor: id, label, vendorId, category, base URL, model,
auth, transport, preset, catalog, discovery
- Brand descriptor: id, label, canonicalVendorId, capabilities, modelIds
- Model catalog: registration, vendor/gateway associations, required
fields, valid classifications, reasoning/coding tags, no duplicates,
model counts (41 Zen, 12 Go), modelDescriptorId consistency
- Cross-reference: brand↔model, vendor↔model, gateway↔model,
shared OPENCODE_API_KEY
- Registry validation: no errors, no preset conflicts
- Edge cases: unique ids, unique apiNames, non-empty labels, valid
contextWindow/maxOutputTokens, valid defaultModel format, validation
message content, discovery config
Profile tests (25 tests):
- Type guard: isProviderProfile('opencode'), rejects invalid values
- buildLaunchEnv: persisted env, defaults, process env precedence,
OPENCODE_API_KEY mapping, whitespace/null/undefined/empty handling,
very long keys, special characters, concurrent access, boundary
values, no credential leakage
* fix(provider): add per-model endpoint routing (P1)
Add endpointPath field to OpenAIShimTransportConfig so catalog entries
can specify which API path to use per model. This addresses the
maintainer's [P1] finding that all models were routed to
/chat/completions regardless of their upstream endpoint.
Changes:
- descriptors.ts: add endpointPath?: string to OpenAIShimTransportConfig
- openaiShim.ts: buildRequestUrl checks shimConfig.endpointPath first
- vendors/opencode.ts: add transportOverrides to 31 catalog entries
(GPT→/responses, Claude/Qwen→/messages, Gemini→/models/<id>)
+ switch to source: 'static' to prevent free models from live API
- gateways/opencode-go.ts: add transportOverrides to 4 entries
(MiniMax/Qwen→/messages) + switch to source: 'static'
- opencode.test.ts: update tests for static source, remove discovery tests
* refactor(opencode): model OpenCode Zen/Go as gateways (P2)
* docs(provider): document OpenCode setup and move badge metadata to descriptors
- Add OpenCode Zen/Go rows to README supported providers table
- Add OpenCode Zen/Go examples and OPENCODE_API_KEY to advanced-setup.md
- Add PresetBadge type to descriptor/manifest with badge propagation in
artifact generator
- Move 4 hard-coded preset badges ([FREE], [Sponsor], [Zen], [Go]) from
ProviderManager.tsx into descriptor preset metadata
- Add badge field to providerUiMetadata so UI components read from manifest
- Update integration overview docs to recommend preset.badge for future
gateways
* fix(provider): match request body to endpoint format for OpenCode /messages and /responses (P1)
Extend the openaiShim transport so that endpointPath overrides select
both the URL and the correct body/response format:
- /responses → OpenAI Responses API body (input, max_output_tokens)
- /messages → Anthropic Messages API body (content blocks, system, max_tokens)
Also fixes: abort listener leak in SSE passthrough, system prompt
content-block flattening, and removes [Zen]/[Go] badge entries (P3).
Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
* fix(provider): add Google AI SDK body/response format for OpenCode Zen Gemini models (P1)
The three Gemini models in the OpenCode Zen catalog (gemini-3.5-flash,
gemini-3.1-pro, gemini-3-flash) were sending chat-completions body to
the /models/gemini-* endpoint, which expects Google AI SDK format.
- effectiveTransport now detects /models/gemini- endpointPath → 'gemini'
- buildGeminiBody() converts Anthropic messages → Google contents[]
with role mapping, systemInstruction, generationConfig, functionDeclarations
- geminiSseToAnthropic() parses Google SSE frames → Anthropic stream events
with text deltas, functionCall tool_use, finishReason mapping
- _convertGeminiToAnthropicResponse() for non-streaming responses
- Streaming/non-streaming routing via URL detection (/models/gemini-)
- serializeBody(), hasToolsPayload, omitGeminiTools all updated
* fix: prevent OpenCode model descriptors from shadowing canonical limits
P1: Prefix all defaultModel values in opencode.ts with 'opencode-'
so the fallback findModelDescriptorForApiName() doesn't match
canonical model names. The OpenCode descriptors are still found
via catalog entry lookup when the OpenCode route is active.
P2: Add 'OpenCode Go' and 'OpenCode Zen' to PRESET_ORDER in
ProviderManager.test.tsx between 'OpenAI' and 'OpenRouter'
so navigateToPreset() sends the correct number of j keypresses.
* fix: align OpenCode Go descriptor metadata with Zen
- category: 'hosted' → 'aggregating' (both are aggregating gateways)
- add validation block with OPENCODE_API_KEY guidance
- update test assertion from 'hosted' to 'aggregating'
* fix: accept OPENAI_API_KEY as fallback in OpenCode validation
When users set up OpenCode Zen/Go via /provider, the key is saved as
OPENAI_API_KEY (via buildCompatibilityProcessEnv). The validation block
only checked OPENCODE_API_KEY, causing a startup warning even though
the runtime auth header had the key it needed.
Add OPENAI_API_KEY to validation.credentialEnvVars for both gateways,
matching the pattern used by Hicap and Gitlawb Opengateway.
* chore: trigger mergeability recheck
* feat(shim): forward effort/thinking to OpenCode Zen/Go endpoints
- buildResponsesBody: add reasoning_effort + reasoning_summary + include
- buildAnthropicMessagesBody: add thinking config (adaptive/enabled/budget)
- buildGeminiBody: add thinkingConfig with thinkingLevel mapping
- modelSupportsEffort: allow OpenCode Claude and Gemini models
- modelSupportsMaxEffort: add opus-4-7
- getAvailableEffortLevels: show standard levels for OpenCode native models
- opencode-go: add missing validation block
* feat: update OpenCode Zen and Go model counts, add new models, and enhance effort level handling
* feat: implement xhigh effort support for specific models and adjust effort level handling
* fix(effort): address reviewer feedback on xhigh + new models
- docs/advanced-setup.md: bump OpenCode Go count 12 → 13
- openaiShim.ts: include opus-4-8 / opus-4.8 in the adaptive thinking
detection so the new model uses the adaptive + effort path instead
of falling back to budgetTokens
- effort.ts: modelUsesOpenAIEffort now also rejects models that include
'claude-' or 'gemini-' — without this, OpenCode Claude/Gemini
routes (provider=openai) were misclassified as OpenAI-style and
could leak xhigh past the new gate
- effort.codex.test.ts: lock in the new exclusion with a regression
test against the openai provider
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(effort): address reviewer feedback on xhigh effort + new models
Closes the three P2 findings from PR #1505 review:
1. Settings schema now accepts 'xhigh' so a persisted xhigh survives
restart instead of being silently dropped by .catch(undefined).
2. ModelPicker /effort cycle is driven by getAvailableEffortLevels(model)
instead of a boolean includeMax, so models supporting xhigh
(opus-4-7/4-8, OpenAI/Codex) can actually select it from the picker.
displayEffort clamp now uses the available levels list, so stale
xhigh also clamps to high when the focused model doesn't support it.
3. SDK/control metadata uses getAvailableEffortLevels(model) instead of
the EFFORT_LEVELS fallback that advertised xhigh to every max-capable
model. SDK schema + generated types extended to include 'xhigh'.
Also fixes a latent generator bug: the array case in generate-sdk-types
now parenthesizes union/intersection elements so the trailing [] binds
the whole type, e.g. ("a"|"b")[] rather than "a"|"b[]. Without this,
the regenerated xhigh levels ended up typed as the single-literal
"xhigh"[] and broke the modelInfo assignability check.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore(effort): order xhigh before max in EFFORT_LEVELS
EFFORT_LEVELS now matches getAvailableEffortLevels() output order
(['low', 'medium', 'high', 'xhigh', 'max']), and the order asserted by
the existing effort.codex.test.ts tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore(effort): order xhigh before max in settings + SDK schemas
Matches the EFFORT_LEVELS / getAvailableEffortLevels order from the
previous commit. The Zod enum order doesn't affect runtime validation,
but keeps the source consistent and avoids confusion if anyone reads
the enum literal to infer display order.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(effort): clamp ModelPicker selection and mark xhigh as current
- ModelPicker.handleSelect: clamp the emitted/persisted effort to the
focused model's available levels so a toggled-but-unsupported level
(e.g. 'xhigh' on a model that doesn't support it) is never written
to settings.json or handed to the consumer. Add focusedAvailableLevels
+ focusedDefaultEffort to the memo guard so the function regenerates
when the focused model changes.
- EffortPicker: compare the xhigh option against the persisted 'xhigh'
level directly. The 'max' alias path is kept only for legacy
settings.json values that still hold 'max' from before xhigh was
introduced.
* docs(effort): fix stale EffortPicker comment about xhigh normalization
openAIEffortToStandard is a type cast that passes 'xhigh' through as a
first-class EffortLevel — the shim only converts to 'max' at the
Anthropic request boundary, not here. Update the comment to match.
* docs(effort): update /effort help to match xhigh support matrix
The /effort --help output still described max as "Opus 4.6 only" and
xhigh as an "alias for max", but this PR promotes xhigh to a first-class
EffortLevel and allows it for OpenCode Claude Opus 4.7/4.8 (with max
also allowed for those Opus variants). Update the help so it matches
the picker/runtime behavior:
- max: "(Opus 4.6+)"
- xhigh: "(OpenAI/Codex and Opus 4.7+)"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(sdk): address reviewer P2 — sync xhigh across override union, schemas, CLI
- Add 'xhigh_effort' to ModelCapabilityOverride union so the new
call at effort.ts:93 typechecks (P2 finding 1).
- Add 'xhigh' to AgentDefinition.effort enum (coreSchemas.ts) and
control.applied.effort enum (controlSchemas.ts), then regenerate
coreTypes.generated.ts so the SDK public contract matches the
first-class effort level (P2 finding 2).
- Add 'xhigh' to the --effort CLI flag allowed list and help text
(main.tsx:945-951) so users can actually pass --effort xhigh
instead of hitting "It must be one of: low, medium, high, max".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(effort): narrow allowlist to shim-serialized models; sync max description
Address reviewer findings on PR #1505:
P2: The broad `m.includes('opus-4') || m.includes('sonnet-4')` branch
made older variants (claude-opus-4-1, claude-sonnet-4-5) advertise
effort support, but the Anthropic /messages shim only serializes
low/medium as anthropicBody.effort for the isAdaptive || isOpus45
set (opus-4-5/4-6/4-7/4-8, sonnet-4-6). For other models the shim
only emits thinking for high/max, so low/medium on those models
was silently dropped on the wire. Collapse the two 4-model branches
into one that matches the shim's serialization set; the substring
match still covers prefix variations (claude-, opencode-claude-).
P3: getEffortLevelDescription('max') said "Opus 4.6 only" but
modelSupportsMaxEffort now allows opus-4-6, opus-4-7, opus-4-8.
Update the shared description to "Opus 4.6+" so the picker and
/effort confirmation agree with the new support matrix (matching
the /effort --help text from
|
||
|
|
07c1c56b4f |
Add Azure / Foundry launch support to VS Code extension (#1365)
* Enhance OpenClaude VS Code extension with Microsoft Foundry / Azure OpenAI support. Added configuration options for Azure API key, endpoint, and deployment settings. Updated README and documentation for new features, including a setup wizard for Azure integration. Improved terminal launch environment handling for Azure compatibility. * Fix packaged Windows helper runtime references * Use installed CLI from Windows helper aliases * Scope Windows helper env overrides to invocation * Align Windows alias docs with shipped helper |
||
|
|
9a342b61fa | fix(agent-routing): support API model aliases (#1546) | ||
|
|
73a2833819 |
feat(sponsors): add Atlas Cloud sponsor and sponsored tip (#1536)
Add Atlas Cloud (atlascloud.ai) to the README sponsors table with its banner asset, and add an Atlas Cloud sponsored tip to the tip catalog. Co-authored-by: OpenClaude <openclaude@gitlawb.com> |
||
|
|
3be54de16b |
Make OpenGateway the default startup provider (#1493)
Default fresh installs to the Gitlawb OpenGateway profile, keep validation behavior for saved profiles, and mark OpenGateway as the recommended provider in the picker. Update setup docs and generated integration metadata to reflect the API-key-backed OpenGateway route, and add coverage for the fresh-install startup environment. |
||
|
|
5b1c5a2cef |
Mention Arch AUR (#1286)
* Arch Linux installation instructions * Include Arch Linux installation instructions for OpenClaude * Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * docs: Update installation instructions for Arch Linux * docs: Clarify Arch Linux installation instructions and AUR usage * Grammar fix Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> |
||
|
|
a8632b4cc3 |
fix(agents): route configured agent model overrides (#1390)
* fix(agents): route configured agent model overrides * fix(agents): preserve routed teammate providers * test: isolate attribution provider env * test: harden attribution fixture isolation * fix(agents): load flag settings before teammate routing |
||
|
|
f3d41c6161 |
fix(release): verify npm latest tag and document @latest install (#1378)
* fix(release): verify npm latest tag and document @latest install * fix(auto-updater): use @latest for global installs |
||
|
|
5a22d604f8 |
feat(provider): add OpenCode Zen/Go subscription support (#1350)
* feat(provider): add OpenCode Zen/Go subscription support Add OpenCode as a first-class provider, enabling users to connect their Zen (pay-as-you-go) and Go ($10/mo) subscriptions via the /provider command. New integration descriptors: - vendors/opencode.ts — OpenCode Zen vendor (41 models) - gateways/opencode-go.ts — OpenCode Go gateway (12 models) - brands/opencode.ts — brand descriptor - models/opencode.ts — full model catalog (GPT, Claude, Gemini, Qwen, GLM, Kimi, MiniMax, Grok, DeepSeek, MiMo, Nemotron) Modified files: - integrationArtifacts.generated.ts — register descriptors and presets - providerProfile.ts — add OPENCODE_API_KEY env/secret key, 'opencode' profile type, and buildLaunchEnv handler - providerConfig.ts — add DEFAULT_OPENCODE_BASE_URL constants Auth: OPENCODE_API_KEY env var or interactive key entry in /provider Transport: openai-compatible (chat_completions) Base URLs: https://opencode.ai/zen/v1 (Zen), /zen/go/v1 (Go) * feat(provider): add [Zen]/[Go] tags to OpenCode preset labels Add visual tags in the /provider preset selection to distinguish OpenCode Zen (pay-as-you-go) from OpenCode Go (subscription). * feat(provider): enable dynamic model discovery for OpenCode Switch OpenCode vendor and Go gateway from static to hybrid model catalog with openai-compatible discovery. Models are fetched from /v1/models on startup and cached for 1 hour. Manual refresh is supported via the /provider UI. Static model list is preserved as fallback when discovery fails. * test(provider): add comprehensive OpenCode Zen/Go test suite 97 tests across 2 files covering: Integration tests (72 tests): - Vendor descriptor: id, label, classification, base URL, model, auth, transport, preset, validation, catalog, discovery, usage metadata - Gateway descriptor: id, label, vendorId, category, base URL, model, auth, transport, preset, catalog, discovery - Brand descriptor: id, label, canonicalVendorId, capabilities, modelIds - Model catalog: registration, vendor/gateway associations, required fields, valid classifications, reasoning/coding tags, no duplicates, model counts (41 Zen, 12 Go), modelDescriptorId consistency - Cross-reference: brand↔model, vendor↔model, gateway↔model, shared OPENCODE_API_KEY - Registry validation: no errors, no preset conflicts - Edge cases: unique ids, unique apiNames, non-empty labels, valid contextWindow/maxOutputTokens, valid defaultModel format, validation message content, discovery config Profile tests (25 tests): - Type guard: isProviderProfile('opencode'), rejects invalid values - buildLaunchEnv: persisted env, defaults, process env precedence, OPENCODE_API_KEY mapping, whitespace/null/undefined/empty handling, very long keys, special characters, concurrent access, boundary values, no credential leakage * fix(provider): add per-model endpoint routing (P1) Add endpointPath field to OpenAIShimTransportConfig so catalog entries can specify which API path to use per model. This addresses the maintainer's [P1] finding that all models were routed to /chat/completions regardless of their upstream endpoint. Changes: - descriptors.ts: add endpointPath?: string to OpenAIShimTransportConfig - openaiShim.ts: buildRequestUrl checks shimConfig.endpointPath first - vendors/opencode.ts: add transportOverrides to 31 catalog entries (GPT→/responses, Claude/Qwen→/messages, Gemini→/models/<id>) + switch to source: 'static' to prevent free models from live API - gateways/opencode-go.ts: add transportOverrides to 4 entries (MiniMax/Qwen→/messages) + switch to source: 'static' - opencode.test.ts: update tests for static source, remove discovery tests * refactor(opencode): model OpenCode Zen/Go as gateways (P2) * docs(provider): document OpenCode setup and move badge metadata to descriptors - Add OpenCode Zen/Go rows to README supported providers table - Add OpenCode Zen/Go examples and OPENCODE_API_KEY to advanced-setup.md - Add PresetBadge type to descriptor/manifest with badge propagation in artifact generator - Move 4 hard-coded preset badges ([FREE], [Sponsor], [Zen], [Go]) from ProviderManager.tsx into descriptor preset metadata - Add badge field to providerUiMetadata so UI components read from manifest - Update integration overview docs to recommend preset.badge for future gateways * fix(provider): match request body to endpoint format for OpenCode /messages and /responses (P1) Extend the openaiShim transport so that endpointPath overrides select both the URL and the correct body/response format: - /responses → OpenAI Responses API body (input, max_output_tokens) - /messages → Anthropic Messages API body (content blocks, system, max_tokens) Also fixes: abort listener leak in SSE passthrough, system prompt content-block flattening, and removes [Zen]/[Go] badge entries (P3). Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com> * fix(provider): add Google AI SDK body/response format for OpenCode Zen Gemini models (P1) The three Gemini models in the OpenCode Zen catalog (gemini-3.5-flash, gemini-3.1-pro, gemini-3-flash) were sending chat-completions body to the /models/gemini-* endpoint, which expects Google AI SDK format. - effectiveTransport now detects /models/gemini- endpointPath → 'gemini' - buildGeminiBody() converts Anthropic messages → Google contents[] with role mapping, systemInstruction, generationConfig, functionDeclarations - geminiSseToAnthropic() parses Google SSE frames → Anthropic stream events with text deltas, functionCall tool_use, finishReason mapping - _convertGeminiToAnthropicResponse() for non-streaming responses - Streaming/non-streaming routing via URL detection (/models/gemini-) - serializeBody(), hasToolsPayload, omitGeminiTools all updated * fix: prevent OpenCode model descriptors from shadowing canonical limits P1: Prefix all defaultModel values in opencode.ts with 'opencode-' so the fallback findModelDescriptorForApiName() doesn't match canonical model names. The OpenCode descriptors are still found via catalog entry lookup when the OpenCode route is active. P2: Add 'OpenCode Go' and 'OpenCode Zen' to PRESET_ORDER in ProviderManager.test.tsx between 'OpenAI' and 'OpenRouter' so navigateToPreset() sends the correct number of j keypresses. * fix: align OpenCode Go descriptor metadata with Zen - category: 'hosted' → 'aggregating' (both are aggregating gateways) - add validation block with OPENCODE_API_KEY guidance - update test assertion from 'hosted' to 'aggregating' * fix: accept OPENAI_API_KEY as fallback in OpenCode validation When users set up OpenCode Zen/Go via /provider, the key is saved as OPENAI_API_KEY (via buildCompatibilityProcessEnv). The validation block only checked OPENCODE_API_KEY, causing a startup warning even though the runtime auth header had the key it needed. Add OPENAI_API_KEY to validation.credentialEnvVars for both gateways, matching the pattern used by Hicap and Gitlawb Opengateway. * chore: trigger mergeability recheck --------- Co-authored-by: Gravirei <gravirei@users.noreply.github.com> Co-authored-by: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com> |
||
|
|
7cc8edaa3c |
fix(docs): update Xiaomi MiMo API URL in README. (#1424)
- Reason: https://api.xiaomimimo.com/v1 returns 404 |
||
|
|
2e3f7467f9 |
docs(vertex): clarify Claude on Vertex setup (#1273)
* docs(vertex): clarify Claude on Vertex setup * docs(vertex): point region overrides at env utils * docs(vertex): use cli model selector |
||
|
|
e5535577aa |
docs: add Xiaomi MiMo sponsor (#1213)
* docs: add Xiaomi MiMo sponsor * feat(tips): add Xiaomi MiMo sponsored tips |
||
|
|
13a090162f | fix(gemini): preserve tool calls through opengateway (#1204) | ||
|
|
4d04f5bf4f |
feat(opengateway): add Gemini 3.1 Flash Lite + GLM 5.1 FP8 to catalog (#1194)
* feat(opengateway): add Gemini 3.1 Flash Lite + GLM 5.1 FP8 to catalog Opengateway now routes non-Xiaomi models through GMI Cloud (configured in opengateway/src/providers.ts via modelIds: - google/gemini-3.1-flash-lite-preview - zai-org/GLM-5.1-FP8 Adding both as catalog entries on the gitlawb-opengateway gateway descriptor so openclaude users see them in the model picker when the Opengateway preset is active. Each catalog entry reuses the existing upstream model descriptor (`gemini-3.1-flash-lite-preview`, `GLM-5.1`) for capability metadata; the apiName uses the full vendor-prefixed form the gateway routes on. No new model/brand/vendor descriptors needed — only the gateway catalog gets the new IDs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * update opengateway --------- Co-authored-by: OpenClaude <openclaude@gitlawb.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |