fix(http-scope): allow explicit port numbers in HTTP URL patterns#498
Conversation
📝 WalkthroughWalkthroughAdds explicit port-aware HTTP/HTTPS capability patterns and changes both OpenAI provider adapters to pass an empty string when the API key is missing or falsy. ChangesHTTP scope port patterns
OpenAI API key fallback
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/desktop/src-tauri/capabilities/default.json`:
- Around line 172-179: The capability rules currently allow plaintext HTTP to
arbitrary hosts via the `http://**` and `http://*:*` entries, which is broader
than intended. Update the network allowlist in `default.json` to keep only
loopback-only HTTP patterns for local endpoints, while preserving the
non-default-port handling already covered by the existing `https://*:*` and
other relevant entries. Use the surrounding capability block to locate the HTTP
URL entries and replace the broad wildcards with loopback-specific equivalents.
In
`@apps/desktop/src/services/AgentService/infrastructure/providers/adapters/openai-compatible.ts`:
- Line 31: The OpenAI-compatible adapter is coercing an unset API key to an
empty string, which makes createOpenAICompatible send an unwanted Authorization
header. Update the adapter logic in openai-compatible.ts so the apiKey field
remains undefined when this.apiKey is not configured, and verify the
constructor/config path in the adapter preserves the missing-key case instead of
substituting a default string.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 58246b2c-8f07-4178-8774-d8b8d1ccd17e
📒 Files selected for processing (3)
apps/desktop/src-tauri/capabilities/default.jsonapps/desktop/src/services/AgentService/infrastructure/providers/adapters/openai-compatible.tsapps/desktop/src/services/AgentService/infrastructure/providers/adapters/openai.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (6)
- GitHub Check: Rust Checks
- GitHub Check: Frontend Tests
- GitHub Check: Frontend Quality
- GitHub Check: Desktop E2E Smoke (Windows)
- GitHub Check: CodeQL (javascript-typescript)
- GitHub Check: CodeQL (rust)
⚠️ CI failures not shown inline (2)
GitHub Actions: PR Template Check / 0_Validate PR template.txt: fix(http-scope): allow explicit port numbers in HTTP URL patterns
Conclusion: failure
##[group]Run node apps/desktop/scripts/ci/pr-template-check.js
�[36;1mnode apps/desktop/scripts/ci/pr-template-check.js�[0m
shell: /usr/bin/bash -e {0}
env:
PR_BODY: ## Problem
Configuring an OpenAI-compatible provider on a non-default port (e.g. LM Studio at `http://192.168.3.10:1234`) fails with:
```
url not allowed on the configured scope: http://192.168.3.10:1234/v1/models
```
Additionally, leaving the API key empty for local models throws:
```
OpenAI API key is missing. Pass it using the 'apiKey' parameter.
```
## Root Cause
### Scope issue
Tauri-plugin-http uses the `urlpattern` crate (WHATWG URL Pattern standard) for scope matching. When `http://**` is parsed without an explicit port, urlpattern normalizes the port component to `""` (empty string). A URL with an explicit port like `:1234` produces `port() = "1234"`, which does not match `""`.
### API key issue
`@ai-sdk/openai`'s `createOpenAI()` calls `loadApiKey()`, which throws when `apiKey` is `undefined`. Passing an empty string `""` bypasses the check without sending an Authorization header (for `openai-compatible`) or sending `*** (for `openai`).
## Changes
1. **`capabilities/default.json`** — Add explicit port-aware patterns:
- `http://*` matches `http://host` (no explicit port)
- `http://*:*` matches `http://host:port` (any explicit port)
- Same for `https://*:*`
2. **`openai-compatible.ts`** — Change `***REDACTED*** to `***REDACTED*** || ''`
3. **`openai.ts`** — Same change, allowing empty API key
## Testing
- `curl http://192.168.3.10:1234/v1/models` → ✅ 200
- `curl http://192.168.3.10:1234/v1/chat/completions` (no auth) → ✅ 200
- Before fix: TouchAI rejected the URL with scope error
- After fix: TouchAI release build accepts the URL and works with empty API key
- Pre-commit hooks: rust check ✅, vue-tsc ✅, eslint ✅, prettier ✅
Closes `#496`
PR_HEAD_REF: fix/http-scope-urlpattern-port-matching
PR_HEAD_REPO_FULL_NAME: ARCJ137442/TouchAI
##[endgroup]
Missing required PR template...
GitHub Actions: PR Template Check / Validate PR template: fix(http-scope): allow explicit port numbers in HTTP URL patterns
Conclusion: failure
##[group]Run node apps/desktop/scripts/ci/pr-template-check.js
�[36;1mnode apps/desktop/scripts/ci/pr-template-check.js�[0m
shell: /usr/bin/bash -e {0}
env:
PR_BODY: ## Problem
Configuring an OpenAI-compatible provider on a non-default port (e.g. LM Studio at `http://192.168.3.10:1234`) fails with:
```
url not allowed on the configured scope: http://192.168.3.10:1234/v1/models
```
Additionally, leaving the API key empty for local models throws:
```
OpenAI API key is missing. Pass it using the 'apiKey' parameter.
```
## Root Cause
### Scope issue
Tauri-plugin-http uses the `urlpattern` crate (WHATWG URL Pattern standard) for scope matching. When `http://**` is parsed without an explicit port, urlpattern normalizes the port component to `""` (empty string). A URL with an explicit port like `:1234` produces `port() = "1234"`, which does not match `""`.
### API key issue
`@ai-sdk/openai`'s `createOpenAI()` calls `loadApiKey()`, which throws when `apiKey` is `undefined`. Passing an empty string `""` bypasses the check without sending an Authorization header (for `openai-compatible`) or sending `*** (for `openai`).
## Changes
1. **`capabilities/default.json`** — Add explicit port-aware patterns:
- `http://*` matches `http://host` (no explicit port)
- `http://*:*` matches `http://host:port` (any explicit port)
- Same for `https://*:*`
2. **`openai-compatible.ts`** — Change `***REDACTED*** to `***REDACTED*** || ''`
3. **`openai.ts`** — Same change, allowing empty API key
## Testing
- `curl http://192.168.3.10:1234/v1/models` → ✅ 200
- `curl http://192.168.3.10:1234/v1/chat/completions` (no auth) → ✅ 200
- Before fix: TouchAI rejected the URL with scope error
- After fix: TouchAI release build accepts the URL and works with empty API key
- Pre-commit hooks: rust check ✅, vue-tsc ✅, eslint ✅, prettier ✅
Closes `#496`
PR_HEAD_REF: fix/http-scope-urlpattern-port-matching
PR_HEAD_REPO_FULL_NAME: ARCJ137442/TouchAI
##[endgroup]
Missing required PR template...
🔇 Additional comments (1)
apps/desktop/src/services/AgentService/infrastructure/providers/adapters/openai.ts (1)
27-27: 🎯 Functional CorrectnessNo change needed for
apiKeyfallbackapiKey: ''still falls back toOPENAI_API_KEY, so this change does not alter the missing-key path.> Likely an incorrect or invalid review comment.
Source-level verification of the 3 CodeRabbit review pointsI dug into the actual SDK source to check each claim. 1️⃣ Empty apiKey — issue confirmed
getHeaders = () => ({
Authorization: `Bearer ${loadApiKey({ apiKey: options.apiKey, ... })}`,
})
Root cause chain:
No side effect on OpenAI-Compatible ( Asymmetry is intentional: Alibaba/Anthropic/Google/DeepSeek all pass 2️⃣ HTTP scope too broad — pre-existing, not introduced by this PR
3️⃣ Missing tests — fully confirmed
Summary
|
|
Merged. Thank you for contributing to TouchAI again. 已合并。感谢你再次为 TouchAI 做出贡献。 We appreciate the continued help. |
Summary
Fix two bugs that block using local OpenAI-compatible models (e.g. LM Studio) on non-default ports:
HTTP scope port mismatch —
capabilities/default.jsonusedhttp://**which in urlpattern normalizes port to"", rejecting URLs with explicit ports like:1234. Addedhttp://*:*andhttps://*:*patterns.Empty API key crash —
@ai-sdk/openai'sloadApiKey()throws whenapiKeyisundefined. Changed toapiKey || ''so empty strings pass through without sending an Authorization header.Related issue or RFC
AI assistance disclosure
Testing evidence
curl http://192.168.3.10:1234/v1/models→ 200curl http://192.168.3.10:1234/v1/chat/completions(no auth) → 200(CI only — local tests rely on pre-commit hooks which passed)
Risk notes
AgentService, runtime, MCP, or schema impact: None — only capability file and provider adapter changesScreenshots or recordings
Checklist
[WIP]or similar title prefixes.AgentService, runtime, MCP, or schema boundaries, there is an accepted RFC.pnpm test:prfor this code PR, or this is a docs-only change.pnpm test:coverage:rustor relied on CI coverage evidence.pnpm test:e2elocally or documented why CI is the first valid proof.