Repository navigation
feat(providers): add LLMTR as a built-in provider - #540
Merged
Sun-sunshine06 merged 8 commits intoNov 10, 2026
Merged
Conversation
Signed-off-by: knowhy <194148385+knowhycodata@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Findings
- [Nit] Default model/base-URL literal is duplicated across packages —
'qwen/qwen3.8-27b-free'is hardcoded inpackages/shared/src/config.ts:337(BUILTIN_PROVIDERS.llmtr.defaultModel),packages/shared/src/config.ts:615(PROVIDER_SHORTLIST.llmtr.defaultPrimary), andpackages/providers/src/validate.ts:71(chat probe), and the validator also hardcodes the root'https://llmtr.com'instead of the built-in base URL. If the default model is ever changed or retired, the validator can silently probe a stale model while the rest of the app uses a different one.
Suggested fix: import the shared constant invalidate.ts(it already imports from@open-codesign/shared) and useBUILTIN_PROVIDERS.llmtr.defaultModelfor the probe, e.g.model: BUILTIN_PROVIDERS.llmtr.defaultModel, and derive the root fromBUILTIN_PROVIDERS.llmtr.baseUrlrather than a second literal.
Questions
pingProvider('llmtr', ...)returns{ ok: true, modelCount: 0 }(packages/providers/src/validate.ts:164) even thoughBUILTIN_PROVIDERS.llmtr.capabilitiesdeclaressupportsModelsEndpoint: true/modelDiscoveryMode: 'models'. Can you confirm the onboarding model picker is populated fromPROVIDER_SHORTLIST/GET /v1/modelsdiscovery and not from the validate result, so a successful key check does not leave users with an empty model list?- Validation now depends on the specific free model
qwen/qwen3.8-27b-free. If that model is rate-limited (HTTP 429) or renamed/retired (404), a still-valid key will surface as a genericnetworkerror (the added test for 500→networkcodifies this). Is that acceptable, or would a clearer retry hint for 429 / a fallback be worth adding? - The PR says
Closes #539, but the issue body and acceptance criteria were not part of the provided public review context, so I could not validate the closure claim. Can you confirm the diff covers everything #539 asks for (e.g. provider selection, diagnostics, and any title-generation path), rather than a single onboarding path?
Summary
- Review mode: initial
- Directionally sound and additive: the change mirrors the existing Atlas Cloud built-in pattern (enum,
BUILTIN_PROVIDERS,PROVIDER_SHORTLIST,detectProviderFromKey, error key-help URL, model-discovery host, README/zh + changeset). The exhaustiveRecord<SupportedOnboardingProvider, ...>maps force the new entries, and the added Vitest coverage (detection, validation success/204/401/403/500/transport/custom base, config, model discovery, base URL, onboarding IPC forwarding) is proportional to the change. - No blocking issues found. Main residual risk is the validation probe's dependence on a single hardcoded free model; otherwise this is mergeable after the nit/question above.
Testing
- Not run (automation). Added tests look adequate for the change.
Open-CoDesign Bot
Reduce routine dependency PR churn by checking npm and GitHub Actions monthly, with at most two npm and one Actions version-update PRs open at a time. Batch development tools and Actions while keeping related Electron, pi, React, Radix, and Tailwind updates together. Specific groups precede the development-tools catch-all. Existing major-version ignores remain; grouping applies only to version updates, leaving security updates on their own cadence. Explicitly disable Renovate so Dependabot is the sole updater, and point the review prompt to Dependabot policy. Existing CI checks and actual Electron dependency versions remain unchanged; the retired Renovate Electron 41 exclusion already contradicted the checked-in 41.10.6 dependency. Validation: dependabot.yml parsed with PyYAML; git diff --check passed. No application code or dependency versions changed. --------- Co-authored-by: Sun-sunshine06 <Sun-sunshine06@users.noreply.github.com>
…ion (OpenCoworkAI#542) Release manifest synchronization pushes a `[skip ci]` commit to protected main, then silently succeeds when the fallback PR cannot be created. Intel verification targets the retired macos-13 runner and does not gate publishing. - Generate a dedicated manifest PR without skipping CI or pushing main. Use a lease when refreshing its branch, reuse an open PR, and fail on credential, PR creation, or auto-merge errors. - Require RELEASE_BOT_TOKEN instead of GITHUB_TOKEN so PR events trigger required checks. Document minimum permissions and recovery of existing skipped-CI PRs. - Move native Intel packaging to macos-15-intel, verify runner architecture, run it on related PRs, and reuse it as a publication gate. Suppress the additional DMG artifact during release calls. - Add local-Git integration tests with mocked gh calls to CI, covering no-op, missing credentials, creation, reruns and denied PR creation. Validation: actionlint 1.7.12 on all three changed workflows; bash syntax; local and CI manifest integration tests; git diff --check. Cloud CI (lint/typecheck/tests/Electron build), Linux packaging smoke, CodeQL, Dependency Review and automated PR review passed for 79dc6ab. Native Intel validation also passed on attempt 2 (3m37s): https://github.com/OpenCoworkAI/open-codesign/actions/runs/41869077136/job/126721621301 . Verified x86_64 runner architecture, x64 DMG packaging, packaged app architecture, native application smoke test, and artifact upload. Attempt 1 failed because no hosted runner acquired the job; it executed no steps. Rerunning the failed job passed without code changes. All 8 current PR checks pass for 79dc6ab. Maintainer setup: configure repository secret RELEASE_BOT_TOKEN using a repository-scoped fine-grained PAT with Contents and Pull requests read/write, with organization approval if required. Keep required checks and auto-merge enabled; no protection bypass is needed. No settings or secrets were changed. Actual release publication and token-backed manifest PR creation are not exercised by this PR. Leaves OpenCoworkAI#541 and OpenCoworkAI#534 untouched. Co-authored-by: Sun-sunshine06 <Sun-sunshine06@users.noreply.github.com>
Bumps [undici](https://github.com/nodejs/undici) from 7.29.1 to 7.30.1. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/nodejs/undici/releases">undici's releases</a>.</em></p> <blockquote> <h2>v7.30.1</h2> <h2>Security fixes</h2> <h3>High severity</h3> <h4>Denial of service via TLS 1.2 certificate-changing renegotiation</h4> <p><strong>CVE-2026-87018 · <a href="https://github.com/nodejs/undici/security/advisories/GHSA-qrxm-fqhp-jwvm">GHSA-qrxm-fqhp-jwvm</a></strong></p> <p>A malicious or compromised HTTPS server could crash the Node.js process by initiating TLS 1.2 renegotiation and presenting a different, CA-trusted certificate whose hostname did not match the requested host. The resulting socket error reached an assertion in undici's HTTP/1.1 and HTTP/2 connection handling. This release handles post-connect certificate errors without terminating the process.</p> <h4>TLS certificate validation bypass through dropped <code>Agent</code> options</h4> <p><strong>CVE-2026-109383 · <a href="https://github.com/nodejs/undici/security/advisories/GHSA-2m5v-pch6-74hx">GHSA-2m5v-pch6-74hx</a></strong></p> <p><code>Agent</code> used a JSON-based clone for constructor options, which silently removed function-valued TLS options such as <code>checkServerIdentity</code>. Applications relying on custom certificate or public-key verification could therefore accept a certificate that the callback was intended to reject. This release preserves TLS options when creating per-origin dispatchers.</p> <h4>Cache poisoning and cross-user disclosure through cross-origin redirects</h4> <p><strong>CVE-2026-109829 · <a href="https://github.com/nodejs/undici/security/advisories/GHSA-4w7w-5xrc-9h26">GHSA-4w7w-5xrc-9h26</a></strong></p> <p>When an originless <code>Agent</code> combined redirect and shared-cache interceptors as <code>compose(redirect(), cache())</code>, a response from a cross-origin redirect could be stored under the original URL. This could allow persistent cache poisoning or disclosure of user-specific responses to later callers. This release verifies the response origin before caching and preserves redirect-hop cache-control policy.</p> <h4>Denial of service through excessive <code>Content-Encoding</code> values</h4> <p><strong>CVE-2026-109869 · <a href="https://github.com/nodejs/undici/security/advisories/GHSA-xjj6-f33q-929c">GHSA-xjj6-f33q-929c</a></strong></p> <p>A malicious HTTP server could crash the Node.js process by returning more than five content codings and closing the connection before sending the body. Although <code>fetch()</code> rejected the response, an error from an orphaned internal stream could remain unhandled. This release validates the content-encoding chain before creating the body stream and aborts oversized chains safely.</p> <h3>Medium severity</h3> <h4>Denial of service through the <code>decompress</code> interceptor</h4> <p><strong>CVE-2026-87029 · <a href="https://github.com/nodejs/undici/security/advisories/GHSA-55wc-3pg8-jfw6">GHSA-55wc-3pg8-jfw6</a></strong></p> <p>An exception thrown by a downstream response handler from an asynchronous decompression callback could escape as an uncaught exception. A server could trigger this when <code>decompress</code> was composed with a handler such as <code>dump</code> with a size limit. This release converts downstream handler exceptions into per-request errors.</p> <h4>Subresource Integrity bypass with non-lowercase algorithm tokens</h4> <p><strong>CVE-2026-109841 · <a href="https://github.com/nodejs/undici/security/advisories/GHSA-f72v-6w45-q472">GHSA-f72v-6w45-q472</a></strong></p> <p><code>fetch()</code> treated valid mixed-case or uppercase SRI algorithm tokens, such as <code>SHA256</code>, as unknown and could accept a response whose body did not match the configured digest. This release normalizes algorithm tokens before validation and digest selection.</p> <h4>Denial of service through unbounded EventSource parser state</h4> <p><strong>CVE-2026-109924 · <a href="https://github.com/nodejs/undici/security/advisories/GHSA-4qv8-2p9j-2685">GHSA-4qv8-2p9j-2685</a></strong></p> <p>A malicious Server-Sent Events endpoint could exhaust process memory by sending many tiny <code>data:</code> fields without completing an event, or by splitting an unfinished line across many chunks. This release bounds retained EventSource parser state, including field counts, buffered chunks, unfinished-line length, and retained field data.</p> <h4>Denial of service through unbounded automatic WebSocket PONG buffering</h4> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/nodejs/undici/commit/7507102a675b082a71437f0a00681e537875556c"><code>7507102</code></a> Bumped v7.30.1 (<a href="https://redirect.github.com/nodejs/undici/issues/6022">#6022</a>)</li> <li><a href="https://github.com/nodejs/undici/commit/7d60c7b6ee342d3b5489beef02a88e3da72d6463"><code>7d60c7b</code></a> [v7.x] fix(cookies): backport <a href="https://redirect.github.com/nodejs/undici/issues/5663">#5663</a>, <a href="https://redirect.github.com/nodejs/undici/issues/5808">#5808</a> and <a href="https://redirect.github.com/nodejs/undici/issues/5832">#5832</a> (<a href="https://redirect.github.com/nodejs/undici/issues/6019">#6019</a>)</li> <li><a href="https://github.com/nodejs/undici/commit/0227d5de51ed14d88a95e2cd4c01abddfce9b5fc"><code>0227d5d</code></a> fix: avoid unbounded recursion in Set-Cookie attribute parser (<a href="https://redirect.github.com/nodejs/undici/issues/5757">#5757</a>) (<a href="https://redirect.github.com/nodejs/undici/issues/5997">#5997</a>)</li> <li><a href="https://github.com/nodejs/undici/commit/53944624462b6797560288c55dbd8c66857bb495"><code>5394462</code></a> fix(websocket): bound automatic PONG writes under backpressure</li> <li><a href="https://github.com/nodejs/undici/commit/299162740d5f39120092277e70efacb4d151c1c6"><code>2991627</code></a> fix(eventsource): bound retained SSE parser state</li> <li><a href="https://github.com/nodejs/undici/commit/18bc8a1e09d15bc45815154a289dcf6fd5254d00"><code>18bc8a1</code></a> fix(sri): accept non-lowercase algorithm tokens</li> <li><a href="https://github.com/nodejs/undici/commit/63cba7712ca012b2603c6aeeb4c72d8692332cd0"><code>63cba77</code></a> fix(decompress): converge downstream handler throws to per-request errors</li> <li><a href="https://github.com/nodejs/undici/commit/07ded4941b1e72afec862958c3b8ddf468f3b429"><code>07ded49</code></a> fix(fetch): abort excessive content encoding responses</li> <li><a href="https://github.com/nodejs/undici/commit/b20b82ad80a405a12b6ce1f341bcd418de390aa0"><code>b20b82a</code></a> fix(cache): prevent cross-origin redirect cache confusion</li> <li><a href="https://github.com/nodejs/undici/commit/04cb74b1db131ff8f5b4557dce811cbf5f4664b4"><code>04cb74b</code></a> fix: preserve Agent connection options</li> <li>Additional commits viewable in <a href="https://github.com/nodejs/undici/compare/v7.29.1...v7.30.1">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/OpenCoworkAI/open-codesign/network/alerts). </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Upgrade the test-only happy-dom dependency from 20.9.0 to 21.0.4, including the security fixes for ESM compilation, redirects and cross-origin isolation. Keep the hardened default that disables external CSS and iframe loading; no loading opt-ins are introduced. Refresh the lockfile against current main, including the merged Undici security update OpenCoworkAI#531. The required full pre-push run exposed an existing Chromium source-edit test race unrelated to happy-dom: the periodic selection refresh could replace a transient save-error message before the assertion observed it. Assert the retained real iframe validation response with a changed field, the disabled Save control and its explanation instead. The checks for zero apply requests, unchanged source bytes and the runtime-mutated preview remain. No product behavior or source-edit authorization is changed. Validation: full repository typecheck, lint and all 11 package test tasks passed through the normal pre-push hook. Desktop: 211 test files and 3,043 tests passed; 2 opt-in integration files / 12 tests skipped. UI tests passed with happy-dom 21.0.4. Current remote checks are attached to the latest head. --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sun-sunshine06 <Sun-sunshine06@users.noreply.github.com>
Migrate all three pi packages together to the maintained `@earendil-works` namespace (0.79.10), preserving existing sessions, provider integration and native hosted web search. Integrate current main and refresh the native-event/message-replay patch against the new SDK. Keep the current monthly Dependabot groups and disabled Renovate configuration. Align the desktop and nested pi Undici runtime at 8.12.4 with a scoped 8.x security floor, addressing advisories affecting the earlier 8.10.2 pin. Require Node >=22.19.0. The transitive OpenTelemetry API packages do not add an SDK or exporter. Existing lifecycle guards handle only the exact internal halt error; unrelated observer exceptions still propagate. Validation on the updated tree: repository typechecks and lint, core/provider tests (including hosted-search protocol and patched SDK hook tests), HTTP runtime version/dispatcher regressions, and desktop production build passed. Production audit reports no remaining Undici advisories; unrelated baseline advisories remain. Full pre-push and remote integration checks are tracked on the latest head. Supersedes the deprecated-namespace update in OpenCoworkAI#544. The independent Undici 7.x security update OpenCoworkAI#531 is already merged; this migration retains its security intent on the SDK-required 8.x line. --------- Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: Sun-sunshine06 <Sun-sunshine06@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sun-sunshine06 <Sun-sunshine06@users.noreply.github.com>
## Summary Adds Opper as a proxy preset, next to the OpenRouter and Requesty presets. Opper is an EU-hosted, OpenAI-compatible gateway: base URL `https://api.opper.ai/v3/compat`, `GET /models` for model discovery, bare model ids such as `claude-sonnet-4-6`. Same three files as the Requesty preset in OpenCoworkAI#397. The base URL already has a version segment, so `canonicalBaseUrl` keeps it and does not append `/v1`. Disclosure: Opper is my startup. ## Type of change - [ ] Bug fix - [x] New feature - [ ] Refactor (no behavior change) - [ ] Documentation - [ ] Build / CI / tooling - [ ] Breaking change ## Linked issue Refs #<issue> ## Checklist - [x] I checked the linked issue / relevant context before starting - [ ] `pnpm lint && pnpm typecheck && pnpm test` passes locally (not run locally; CI will run it) - [x] Added/updated tests for the change - [x] Added a changeset (`pnpm changeset`) if user-visible - [ ] Updated docs if behavior changed (not needed) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Findings
- [Nit] The PR diff against
maincovers far more than the LLMTR provider —gh pr diffincludes the pi 0.79 namespace migration, theundici8.12.4 /enginesbump, a release-pipeline rewrite (.github/workflows/release.yml:79-90,.github/scripts/sync-release-manifests.sh:1), dependency-policy changes (.github/dependabot.yml:1,renovate.json:1) and lifecycle changes inpackages/core/src/agent.ts:1388-1540— 89 files for a provider addition. The PR body saysmainwas integrated; if so those commits are already on the base and a rebase would reduce this to the provider change, making the release-path edits separately reviewable.
Suggested fix / next action:git fetch origin && git rebase origin/mainand force-push; if any of those files are new work rather than merged-inmain, split them into their own PR.
Questions
enginesis nownode: ">=22.19.0"(package.json:15-17) and CI installs Node from.nvmrc(node-version-file: .nvmrcin.github/workflows/ci.yml:31-33). Was.nvmrcbumped to at least 22.19.0, so local installs and CI do not disagree with the new engine requirement (the installed pi 0.79 packages declarenode >=22.19.0inpnpm-lock.yaml)?
Summary
- Review mode: follow-up after new commits
- The earlier nit is resolved:
packages/providers/src/validate.ts:62-75now derives both the endpoint root and the probe model fromBUILTIN_PROVIDERS.llmtr(.baseUrl/.defaultModel), so changing the default model can no longer desync the validator from generation. - The earlier
modelCount: 0question is answered by the PR body and by the provider config: discovery stays on the shortlist /GET /v1/modelspath (modelDiscoveryMode: 'models',supportsModelsEndpoint: trueinpackages/shared/src/config.ts:332-347), covered bypackages/shared/src/config.test.ts,model-discovery.test.ts,base-url.test.ts. - The LLMTR wiring is complete and mirrors the Atlas Cloud precedent: both
ProviderIdenums (packages/shared/src/config.ts:10,packages/shared/src/index.ts:40),SUPPORTED_ONBOARDING_PROVIDERS,BUILTIN_PROVIDERS,PROVIDER_SHORTLIST(packages/shared/src/config.ts:613-619), key detection (packages/providers/src/index.ts:601), key-help rewrite (packages/core/src/errors.ts:25),LISTING_CAPABLE_OFFICIAL_HOSTS(packages/shared/src/model-discovery.ts:131), onboarding parser messages, README/README.zh-CN and a changeset. Vitest coverage is proportional (probe shape, 204, 401/403, 500, transport failure, custom base URL, IPC forwarding, key detection, error rewrite). - Residual risk (non-blocking, unchanged from the prior review): the probe depends on a single free model, so a 429 on that model still surfaces as a generic
networkerror with no retry hint.Closes #539could not be validated against the issue body/acceptance criteria in this run — only the public PR body enumerates the covered paths. - No blocking issues found in the provider change itself.
Testing
- Not run (automation). Added unit coverage looks adequate for the provider paths; no live provider call was made.
Open-CoDesign Bot
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add LLMTR as an optional built-in OpenAI-compatible provider across onboarding, provider configuration, model discovery, key detection and help links. Users supply their own API key; no new dependency or hosted account is introduced.
The key check uses a minimal chat request because the public model catalog does not validate credentials. Derive its endpoint and model from BUILTIN_PROVIDERS.llmtr so probe defaults stay aligned with generation. Existing 401/403, credit and rate-limit diagnostics remain in use; model discovery remains separate from the validation result.
Integrated current main, including the pi namespace/security migration. Provider tests and all repository typechecks passed locally; full pre-push and current remote CI are tracked on the latest head. The earlier CI failure was in the unrelated workspace-rename coordination test. No paid live model call was made during this maintainer pass; the contributor's original PR reported live generation and invalid-key checks.
Contributor disclosure: the original author works on LLMTR. Closes #539.
Final validation: full local pre-push lint, typecheck and all 11 test tasks passed (desktop: 3,046 passed, 12 skipped); required remote CI and security/dependency checks passed on 867afce. The follow-up review used a stale base SHA (5daa34e); GitHub compare against current main and local merge-base comparison show only the 18 LLMTR-related files. The pi/security/release changes are already merged on main. CI resolves .nvmrc 22 to the current Node 22 release and its install/typecheck/tests passed with the >=22.19.0 engine requirement. Issue #539 acceptance criteria were checked against the implementation.