feat(aimlapi): add guided top-up and key provisioning - #1886
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📜 Recent review details🧰 Additional context used📓 Path-based instructions (4)docs/**/*.{md,mdx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*📄 CodeRabbit inference engine (CONTRIBUTING.md)
Files:
⚙️ CodeRabbit configuration file
Files:
**⚙️ CodeRabbit configuration file
Files:
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}⚙️ CodeRabbit configuration file
Files:
🔇 Additional comments (1)
📝 WalkthroughWalkthroughThis PR adds an AI/ML API top-up and provisioning flow: a new HTTP client and config module for checkout/auth/exchange, CLI prompt helpers, a ChangesAI/ML API top-up feature
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related issues
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 6 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (6 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: 5
🤖 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 `@src/components/ProviderManager.test.tsx`:
- Around line 924-1000: This ProviderManager top-up test is relying on the
email/password prompts, but renderAimlapiApiKeyChoice will bypass them if
AIMLAPI_EMAIL and AIMLAPI_PASSWORD are already set. Update the test to save the
current env values, clear both before mounting ProviderManager and running the
flow, then restore them afterward so the prompts are rendered consistently and
the test cannot hang.
In `@src/integrations/aimlapi/client.ts`:
- Around line 184-194: Add a timeout to the shared fetch wrapper in AIMLAPI
client so stalled requests can’t hang indefinitely. Update the request path in
the fetch call used by `getSession`, `signup`, `pay`, and `exchange` to pass an
`AbortSignal.timeout(...)` signal, and make sure the existing `AimlapiApiError`
handling in the same block still reports timeout/network failures cleanly.
In `@src/integrations/aimlapi/topup.ts`:
- Around line 331-338: The retry logic in the polling loop is too narrow: in the
catch block it only retries AimlapiApiError responses with status >= 500, so
transient network failures surfaced by client.request as status 0 still abort
the in-progress payment wait. Update the retry condition in the polling code
around the catch block to also treat status 0 as transient, and keep the
existing sleep/continue behavior for those errors.
- Line 187: The console output in the session handling path is leaking a
sensitive capability token, so remove the use of session.sessionToken from the
log in topup.ts and replace it with a non-sensitive identifier or a generic
session message. Update the logging in the code that prints the session details
so it does not expose one-time tokens while still preserving any useful
operational context.
In `@src/main.tsx`:
- Line 4019: The CLI help text for the `--amount` option is hardcoded instead of
using the AIMLAPI limit constants, so it can drift from the validation rules.
Update the option definition in `main.tsx` to derive the displayed minimum and
maximum from the AIMLAPI bounds exported by `integrations/aimlapi/config.ts`,
keeping the help text aligned with the values enforced by the validation logic.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 872e4f18-a0bb-4e3d-93c3-3d9ff98fe1a8
⛔ Files ignored due to path filters (1)
src/integrations/generated/integrationManifest.generated.tsis excluded by!**/generated/**,!src/integrations/generated/**
📒 Files selected for processing (15)
src/cli/handlers/aimlapi.tssrc/components/ProviderManager.test.tsxsrc/components/ProviderManager.tsxsrc/integrations/aimlapi/client.tssrc/integrations/aimlapi/config.tssrc/integrations/aimlapi/index.tssrc/integrations/aimlapi/prompt.tssrc/integrations/aimlapi/topup.tssrc/integrations/artifactGenerator.tssrc/integrations/discoveryService.test.tssrc/integrations/gateways/aimlapi.tssrc/integrations/gateways/gitlawb-opengateway.tssrc/main.tsxsrc/services/api/bootstrap.test.tssrc/services/api/client.test.ts
💤 Files with no reviewable changes (1)
- src/integrations/gateways/gitlawb-opengateway.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript with strict mode and ESM imports in source and test files.
Files:
src/cli/handlers/aimlapi.tssrc/integrations/aimlapi/index.tssrc/integrations/gateways/aimlapi.tssrc/main.tsxsrc/integrations/aimlapi/prompt.tssrc/integrations/artifactGenerator.tssrc/services/api/client.test.tssrc/services/api/bootstrap.test.tssrc/integrations/aimlapi/client.tssrc/integrations/discoveryService.test.tssrc/integrations/aimlapi/config.tssrc/integrations/aimlapi/topup.tssrc/components/ProviderManager.test.tsxsrc/components/ProviderManager.tsx
**/*
📄 CodeRabbit inference engine (CONTRIBUTING.md)
In the files you touch, preserve the existing code style.
Files:
src/cli/handlers/aimlapi.tssrc/integrations/aimlapi/index.tssrc/integrations/gateways/aimlapi.tssrc/main.tsxsrc/integrations/aimlapi/prompt.tssrc/integrations/artifactGenerator.tssrc/services/api/client.test.tssrc/services/api/bootstrap.test.tssrc/integrations/aimlapi/client.tssrc/integrations/discoveryService.test.tssrc/integrations/aimlapi/config.tssrc/integrations/aimlapi/topup.tssrc/components/ProviderManager.test.tsxsrc/components/ProviderManager.tsx
⚙️ CodeRabbit configuration file
**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.
Files:
src/cli/handlers/aimlapi.tssrc/integrations/aimlapi/index.tssrc/integrations/gateways/aimlapi.tssrc/main.tsxsrc/integrations/aimlapi/prompt.tssrc/integrations/artifactGenerator.tssrc/services/api/client.test.tssrc/services/api/bootstrap.test.tssrc/integrations/aimlapi/client.tssrc/integrations/discoveryService.test.tssrc/integrations/aimlapi/config.tssrc/integrations/aimlapi/topup.tssrc/components/ProviderManager.test.tsxsrc/components/ProviderManager.tsx
**
⚙️ CodeRabbit configuration file
**: # AGENTS.md - AI Agent Coding GuideThis guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.
Project Snapshot
OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.
The installed CLI runs on Node.js
>=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.Work Style
- Keep changes focused on one problem.
- Prefer existing patterns in the file or nearby module.
- Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
- Add or update tests when behavior changes.
- Update docs when setup, commands, provider behavior, or user-facing behavior changes.
- For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.
Stack And Conventions
- TypeScript with strict mode and ESM imports.
- React + Ink for terminal UI.
- Bun lockfile and Bun scripts for development workflows.
- Node runtime for the built CLI.
Common libraries and patterns:
chalkfor terminal color.commanderfor CLI argument parsing.execafor child processes.- Existing service, provider, settings, permission, and UI patterns over new abstractions.
Repository Map
src/commands/- slash and CLI command implementations.src/components/- React/Ink UI components.src/services/- API, MCP, OAuth, wiki, voice, and other service integrations.src/tools/- tool implementations.src/utils/- shared utilities.src/integrations/- provider and model integration metadata.src/entrypoints/- CLI, MCP, SDK, and generated public types.src/tasks/- local, remote, workflow, and monitor tas...
Files:
src/cli/handlers/aimlapi.tssrc/integrations/aimlapi/index.tssrc/integrations/gateways/aimlapi.tssrc/main.tsxsrc/integrations/aimlapi/prompt.tssrc/integrations/artifactGenerator.tssrc/services/api/client.test.tssrc/services/api/bootstrap.test.tssrc/integrations/aimlapi/client.tssrc/integrations/discoveryService.test.tssrc/integrations/aimlapi/config.tssrc/integrations/aimlapi/topup.tssrc/components/ProviderManager.test.tsxsrc/components/ProviderManager.tsx
src/{commands,components,services,tools,utils,integrations,entrypoints,tasks}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Prefer the existing service, provider, settings, permission, and UI patterns over introducing new abstractions.
Files:
src/integrations/aimlapi/index.tssrc/integrations/gateways/aimlapi.tssrc/integrations/aimlapi/prompt.tssrc/integrations/artifactGenerator.tssrc/services/api/client.test.tssrc/services/api/bootstrap.test.tssrc/integrations/aimlapi/client.tssrc/integrations/discoveryService.test.tssrc/integrations/aimlapi/config.tssrc/integrations/aimlapi/topup.tssrc/components/ProviderManager.test.tsxsrc/components/ProviderManager.tsx
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}
⚙️ CodeRabbit configuration file
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}: Review provider routing, model selection, env precedence, auth/token handling, OpenAI-compatible shims, retries, proxy behavior, and outbound HTTP behavior with high scrutiny. Block on silent default changes, hidden fallback expansion, credential reuse mistakes, hardcoded provider assumptions, or new network reach that is not intentional and documented.
Files:
src/integrations/aimlapi/index.tssrc/integrations/gateways/aimlapi.tssrc/integrations/aimlapi/prompt.tssrc/integrations/artifactGenerator.tssrc/services/api/client.test.tssrc/services/api/bootstrap.test.tssrc/integrations/aimlapi/client.tssrc/integrations/discoveryService.test.tssrc/integrations/aimlapi/config.tssrc/integrations/aimlapi/topup.ts
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}
⚙️ CodeRabbit configuration file
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}: Review install, launcher, build, packaging, startup, and entrypoint changes for cross-platform compatibility, tracked-source rewrites, env/config precedence, and release safety. Block on changes that can break Windows/macOS/Linux startup or publish unexpected artifacts.
Files:
src/main.tsx
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}
⚙️ CodeRabbit configuration file
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.
Files:
src/services/api/client.test.tssrc/services/api/bootstrap.test.tssrc/integrations/discoveryService.test.tssrc/components/ProviderManager.test.tsx
src/components/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use React + Ink patterns for terminal UI components under
src/components/.
Files:
src/components/ProviderManager.test.tsxsrc/components/ProviderManager.tsx
🪛 ast-grep (0.44.1)
src/integrations/aimlapi/topup.ts
[warning] 186-186: Avoid logging sensitive data
Context: console.log(chalk.dim( -> Session ${session.sessionToken}))
Note: [CWE-532] Insertion of Sensitive Information into Log File.
(log-sensitive-data-typescript)
[warning] 238-238: Avoid logging sensitive data
Context: console.log( key ${chalk.dim(maskKey(apiKey))} (id ${apiKeyId}))
Note: [CWE-532] Insertion of Sensitive Information into Log File.
(log-sensitive-data-typescript)
🔇 Additional comments (19)
src/integrations/artifactGenerator.ts (1)
226-278: LGTM!src/integrations/gateways/aimlapi.ts (1)
77-77: LGTM!Partner ID value matches
DEFAULT_PARTNER_IDinsrc/integrations/aimlapi/config.ts, and the description/badge changes align with the PR's intent to surface aimlapi as the recommended preset.Also applies to: 90-91
src/integrations/discoveryService.test.ts (1)
463-467: LGTM!src/services/api/bootstrap.test.ts (1)
220-220: LGTM!src/services/api/client.test.ts (1)
642-642: LGTM!src/integrations/aimlapi/client.ts (1)
15-166: LGTM!src/integrations/aimlapi/config.ts (1)
13-75: LGTM!src/integrations/aimlapi/prompt.ts (1)
9-63: LGTM!src/integrations/aimlapi/topup.ts (2)
92-153: LGTM!Also applies to: 155-320
238-238: LGTM!src/integrations/aimlapi/index.ts (1)
1-12: LGTM!src/main.tsx (2)
4020-4020:--methodhas no.choices()guard.An invalid value (e.g. a typo) silently falls back to
'card'with no error, since the action handler doesopts.method === 'crypto' ? 'crypto' : 'card'. Low-impact since the fallback is safe, but a one-line.choices(['card', 'crypto'])would surface user typos instead of masking them.Also applies to: 4038-4038
4012-4044: LGTM on the subcommand wiring (dynamic import,--no-opennegation viaopts.open === false, option →AimlapiTopupOptionsmapping) — no cross-platform/startup-path concerns for this new subcommand registration.src/components/ProviderManager.tsx (4)
2374-2446: Amount validation duplicated between here andrenderAimlapiTopupAmount.The finite/min/max checks in
startAimlapiTopupre-implement the same logic already enforced when the user submits the amount screen (lines 2551-2599). It's harmless (defensive re-check before firing the network call) but the two copies can drift over time.
48-57: LGTM!Also applies to: 125-130, 827-837, 1578-1584
1972-2048: LGTM! Verified the full bidirectional screen graph:aimlapi-api-key-choice → email → password → amount → method → progress. EveryhandleBackFrom*mirrors its corresponding forward transition (cursor offsets included), and cancel is correctly blocked whileisAimlapiTopupRunningis true.Also applies to: 2288-2292
2448-2717: LGTM! Status-label map is aRecord<AimlapiTopupStatus, string>, so TypeScript guarantees exhaustive coverage of all eight statuses fromtopup.ts, and the render switch wiring is correct.Also applies to: 3145-3162
src/cli/handlers/aimlapi.ts (1)
1-26: LGTM!src/components/ProviderManager.test.tsx (1)
111-121: LGTM!Also applies to: 328-328, 443-450, 890-901
| test('ProviderManager can top up AI/ML API and save the issued key', async () => { | ||
| const addProviderProfile = mock((payload: any) => ({ | ||
| id: 'aimlapi_profile', | ||
| ...payload, | ||
| })) | ||
| const provisionAimlapiKey = mock(async (options: any) => { | ||
| options.onStatus?.('creating-session') | ||
| options.onStatus?.('opening-checkout', 'https://app.aimlapi.com/checkout/test') | ||
| options.onStatus?.('waiting-payment') | ||
| options.onStatus?.('provisioning-key') | ||
| return { | ||
| apiKey: 'aimlapi-issued-key', | ||
| apiKeyId: 'key_test', | ||
| baseUrl: 'https://api.aimlapi.com/v1', | ||
| model: 'gpt-4o', | ||
| } | ||
| }) | ||
|
|
||
| mockProviderManagerDependencies(() => undefined, async () => undefined, { | ||
| addProviderProfile, | ||
| provisionAimlapiKey, | ||
| }) | ||
|
|
||
| const nonce = `${Date.now()}-${Math.random()}` | ||
| const { ProviderManager } = await import(`./ProviderManager.js?ts=${nonce}`) | ||
| const mounted = await mountProviderManager(ProviderManager) | ||
|
|
||
| try { | ||
| await waitForFrameOutput(mounted.getOutput, frame => | ||
| frame.includes('Provider manager'), | ||
| ) | ||
|
|
||
| mounted.stdin.write('\r') | ||
| await waitForFrameOutput(mounted.getOutput, frame => | ||
| frame.includes('Choose provider preset'), | ||
| ) | ||
|
|
||
| await navigateToPreset(mounted.stdin, 'AI/ML API') | ||
| mounted.stdin.write('\r') | ||
| await waitForFrameOutput(mounted.getOutput, frame => | ||
| frame.includes('Step 1 of 2: Default model'), | ||
| ) | ||
|
|
||
| mounted.stdin.write('\r') | ||
| await waitForFrameOutput(mounted.getOutput, frame => | ||
| frame.includes('Top up and get API key'), | ||
| ) | ||
|
|
||
| mounted.stdin.write('\r') | ||
| await waitForFrameOutput(mounted.getOutput, frame => | ||
| frame.includes('Enter your AI/ML API account email'), | ||
| ) | ||
| mounted.stdin.write('user@example.com') | ||
| await Bun.sleep(25) | ||
| mounted.stdin.write('\r') | ||
|
|
||
| await waitForFrameOutput(mounted.getOutput, frame => | ||
| frame.includes('Enter your AI/ML API password'), | ||
| ) | ||
| mounted.stdin.write('secret-password') | ||
| await Bun.sleep(25) | ||
| mounted.stdin.write('\r') | ||
|
|
||
| await waitForFrameOutput(mounted.getOutput, frame => | ||
| frame.includes('Choose a top-up amount in USD') && | ||
| frame.includes('25'), | ||
| ) | ||
| mounted.stdin.write('\r') | ||
|
|
||
| await waitForFrameOutput(mounted.getOutput, frame => | ||
| frame.includes('Payment method') && | ||
| frame.includes('Card') && | ||
| frame.includes('Crypto'), | ||
| ) | ||
| mounted.stdin.write('j') | ||
| await Bun.sleep(25) | ||
| mounted.stdin.write('\r') |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Map the relevant files and locate the AI/ML API top-up path.
git ls-files 'src/components/ProviderManager.test.tsx' 'src/components/ProviderManager.tsx' 'src/**/aimlapi*' 'src/**/ProviderManager*' | sort
echo '--- outline ProviderManager.test.tsx ---'
ast-grep outline src/components/ProviderManager.test.tsx --view expanded || true
echo '--- outline ProviderManager.tsx ---'
ast-grep outline src/components/ProviderManager.tsx --view expanded || true
echo '--- search for AIMLAPI env usage ---'
rg -n "AIMLAPI_EMAIL|AIMLAPI_PASSWORD|renderAimlapiApiKeyChoice|topup" src/components src/services src/utils src/commands src/integrations | sed -n '1,240p'Repository: Gitlawb/openclaude
Length of output: 7084
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Read the implementation around the top-up branch.
file=src/components/ProviderManager.tsx
line=$(rg -n "renderAimlapiApiKeyChoice|AIMLAPI_EMAIL|AIMLAPI_PASSWORD" "$file" | head -n 1 | cut -d: -f1 || true)
if [ -n "${line:-}" ]; then
start=$((line-80)); [ "$start" -lt 1 ] && start=1
end=$((line+180))
sed -n "${start},${end}p" "$file" | cat -n
fi
echo '--- relevant test section ---'
sed -n '924,1000p' src/components/ProviderManager.test.tsx | cat -n
echo '--- existing env isolation patterns in tests ---'
rg -n "delete process\.env\.AIMLAPI_|originalAimlapi|process\.env\.[A-Z_]+ =|delete process\.env\." src/components/ProviderManager.test.tsx src/**/*.test.tsx src/**/*.test.ts | sed -n '1,240p'Repository: Gitlawb/openclaude
Length of output: 34052
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Check whether the test suite or nearby tests rely on these vars being present.
rg -n "AIMLAPI_EMAIL|AIMLAPI_PASSWORD" . --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' | sed -n '1,240p'Repository: Gitlawb/openclaude
Length of output: 1244
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Probe the exact branch logic with a read-only script snippet extracted from the file.
python3 - <<'PY'
from pathlib import Path
import re
text = Path('src/components/ProviderManager.tsx').read_text()
for pat in ['AIMLAPI_EMAIL', 'AIMLAPI_PASSWORD', 'topup', 'renderAimlapiApiKeyChoice']:
print(f'--- {pat} ---')
for m in re.finditer(pat, text):
s = max(0, m.start()-260)
e = min(len(text), m.end()+520)
print(text[s:e])
print('====')
break
PYRepository: Gitlawb/openclaude
Length of output: 3454
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- ProviderManager env-branch implementation ---'
rg -n -A40 -B40 "AIMLAPI_EMAIL|AIMLAPI_PASSWORD|renderAimlapiApiKeyChoice|topup" src/components/ProviderManager.tsx | sed -n '1,240p'
echo '--- targeted test snippet ---'
sed -n '924,1000p' src/components/ProviderManager.test.tsx | cat -n
echo '--- all repo env references ---'
rg -n "AIMLAPI_EMAIL|AIMLAPI_PASSWORD" src tests . --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' | sed -n '1,240p'Repository: Gitlawb/openclaude
Length of output: 13508
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
text = Path('src/components/ProviderManager.tsx').read_text()
needles = ['AIMLAPI_EMAIL', 'AIMLAPI_PASSWORD', 'renderAimlapiApiKeyChoice', 'topup']
for needle in needles:
idx = text.find(needle)
print(f'=== {needle} @ {idx} ===')
if idx != -1:
start = max(0, idx - 900)
end = min(len(text), idx + 1600)
print(text[start:end])
print()
PYRepository: Gitlawb/openclaude
Length of output: 10290
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Try a narrow search around the topup branch in the component file.
file='src/components/ProviderManager.tsx'
match_line=$(rg -n "AIMLAPI_EMAIL|AIMLAPI_PASSWORD|topup" "$file" | head -n 1 | cut -d: -f1)
echo "match_line=${match_line:-none}"
if [ -n "${match_line:-}" ]; then
start=$((match_line-120)); [ "$start" -lt 1 ] && start=1
end=$((match_line+240))
sed -n "${start},${end}p" "$file" | cat -n
fiRepository: Gitlawb/openclaude
Length of output: 13544
Clear AIMLAPI_EMAIL/AIMLAPI_PASSWORD in this test.
renderAimlapiApiKeyChoice skips the email/password prompts when both are set, so this case can hang waiting for a screen that never renders. Save and restore both env vars around the test.
🤖 Prompt for 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.
In `@src/components/ProviderManager.test.tsx` around lines 924 - 1000, This
ProviderManager top-up test is relying on the email/password prompts, but
renderAimlapiApiKeyChoice will bypass them if AIMLAPI_EMAIL and AIMLAPI_PASSWORD
are already set. Update the test to save the current env values, clear both
before mounting ProviderManager and running the flow, then restore them
afterward so the prompts are rendered consistently and the test cannot hang.
Source: Path instructions
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/integrations/aimlapi/client.ts (1)
186-206: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winWrap
response.text()in the timeout guard
AbortSignal.timeout(...)can also fire while the body is being consumed. If headers arrive but the body stalls,response.text()rejects outside thistry/catch, so the error escapes as a raw abort instead ofAimlapiApiError(status=0). That bypasses the retry inpollUntilPaid()and can abort an in-progress top-up.🤖 Prompt for 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. In `@src/integrations/aimlapi/client.ts` around lines 186 - 206, The timeout handling around the fetch in Aimlapi client is incomplete because response.text() can still be aborted after headers arrive, escaping as a raw abort instead of AimlapiApiError. Update the request flow in client.ts around the fetch/response handling so the body read is covered by the same try/catch used for the network call, and convert any abort or body-consumption failure into AimlapiApiError with status 0. Keep the existing error path in the AimlapiApiError construction and the request logic in the fetch/response.text sequence.Source: Path instructions
🤖 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 `@src/main.tsx`:
- Line 4021: The `--method` option currently accepts any string and later falls
back to `card`, which hides typos instead of failing fast. Update the command
definitions in `main.tsx` (and the matching option in `topup.ts`) to use
`.choices()` for the payment method so only valid values like `card` and
`crypto` are accepted. Make sure the parsing logic in the `method` handling path
no longer performs a silent default for invalid input.
---
Outside diff comments:
In `@src/integrations/aimlapi/client.ts`:
- Around line 186-206: The timeout handling around the fetch in Aimlapi client
is incomplete because response.text() can still be aborted after headers arrive,
escaping as a raw abort instead of AimlapiApiError. Update the request flow in
client.ts around the fetch/response handling so the body read is covered by the
same try/catch used for the network call, and convert any abort or
body-consumption failure into AimlapiApiError with status 0. Keep the existing
error path in the AimlapiApiError construction and the request logic in the
fetch/response.text sequence.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 0f21f2b9-a542-4b0e-916b-7ca236f97f8b
⛔ Files ignored due to path filters (1)
src/integrations/generated/integrationManifest.generated.tsis excluded by!**/generated/**,!src/integrations/generated/**
📒 Files selected for processing (4)
src/components/ProviderManager.test.tsxsrc/integrations/aimlapi/client.tssrc/integrations/aimlapi/topup.tssrc/main.tsx
📜 Review details
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript with strict mode and ESM imports in source and test files.
Files:
src/main.tsxsrc/integrations/aimlapi/client.tssrc/components/ProviderManager.test.tsxsrc/integrations/aimlapi/topup.ts
**/*
📄 CodeRabbit inference engine (CONTRIBUTING.md)
In the files you touch, preserve the existing code style.
Files:
src/main.tsxsrc/integrations/aimlapi/client.tssrc/components/ProviderManager.test.tsxsrc/integrations/aimlapi/topup.ts
⚙️ CodeRabbit configuration file
**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.
Files:
src/main.tsxsrc/integrations/aimlapi/client.tssrc/components/ProviderManager.test.tsxsrc/integrations/aimlapi/topup.ts
**
⚙️ CodeRabbit configuration file
**: # AGENTS.md - AI Agent Coding GuideThis guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.
Project Snapshot
OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.
The installed CLI runs on Node.js
>=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.Work Style
- Keep changes focused on one problem.
- Prefer existing patterns in the file or nearby module.
- Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
- Add or update tests when behavior changes.
- Update docs when setup, commands, provider behavior, or user-facing behavior changes.
- For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.
Stack And Conventions
- TypeScript with strict mode and ESM imports.
- React + Ink for terminal UI.
- Bun lockfile and Bun scripts for development workflows.
- Node runtime for the built CLI.
Common libraries and patterns:
chalkfor terminal color.commanderfor CLI argument parsing.execafor child processes.- Existing service, provider, settings, permission, and UI patterns over new abstractions.
Repository Map
src/commands/- slash and CLI command implementations.src/components/- React/Ink UI components.src/services/- API, MCP, OAuth, wiki, voice, and other service integrations.src/tools/- tool implementations.src/utils/- shared utilities.src/integrations/- provider and model integration metadata.src/entrypoints/- CLI, MCP, SDK, and generated public types.src/tasks/- local, remote, workflow, and monitor tas...
Files:
src/main.tsxsrc/integrations/aimlapi/client.tssrc/components/ProviderManager.test.tsxsrc/integrations/aimlapi/topup.ts
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}
⚙️ CodeRabbit configuration file
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}: Review install, launcher, build, packaging, startup, and entrypoint changes for cross-platform compatibility, tracked-source rewrites, env/config precedence, and release safety. Block on changes that can break Windows/macOS/Linux startup or publish unexpected artifacts.
Files:
src/main.tsx
src/{commands,components,services,tools,utils,integrations,entrypoints,tasks}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Prefer the existing service, provider, settings, permission, and UI patterns over introducing new abstractions.
Files:
src/integrations/aimlapi/client.tssrc/components/ProviderManager.test.tsxsrc/integrations/aimlapi/topup.ts
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}
⚙️ CodeRabbit configuration file
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}: Review provider routing, model selection, env precedence, auth/token handling, OpenAI-compatible shims, retries, proxy behavior, and outbound HTTP behavior with high scrutiny. Block on silent default changes, hidden fallback expansion, credential reuse mistakes, hardcoded provider assumptions, or new network reach that is not intentional and documented.
Files:
src/integrations/aimlapi/client.tssrc/integrations/aimlapi/topup.ts
src/components/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use React + Ink patterns for terminal UI components under
src/components/.
Files:
src/components/ProviderManager.test.tsx
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}
⚙️ CodeRabbit configuration file
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.
Files:
src/components/ProviderManager.test.tsx
🔇 Additional comments (4)
src/main.tsx (1)
39-39: LGTM!Resolves the earlier feedback to source
--amountbounds fromMIN_AMOUNT_USD_MINOR/MAX_AMOUNT_USD_MINORinstead of hardcoding$20/$10000.Also applies to: 4020-4020
src/components/ProviderManager.test.tsx (1)
29-30: LGTM! This resolves the previously flagged hang risk —AIMLAPI_EMAIL/AIMLAPI_PASSWORDare now cleared before the top-up test runs and captured in the env snapshot for restore, so the email/password prompt screens are reliably exercised. As per path instructions, tests touching env state should isolate it, and this now does.Also applies to: 927-929
src/integrations/aimlapi/client.ts (1)
55-55: LGTM!Also applies to: 191-191
src/integrations/aimlapi/topup.ts (1)
187-187: LGTM!Also applies to: 333-334
|
Fixed — reverted the "pin AI/ML API first" rule in artifactGenerator.ts and regenerated the manifest. Preset order is back to gitlawb-opengateway → anthropic → aimlapi → ..., same as main. Also addressed all 5 CodeRabbit findings (fetch timeout, no longer logging the session token, retry on network errors during poll, cleared env vars in the new test, --amount help text sourced from config bounds). @jatmn could you please re-review? |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@src/main.tsx`:
- Line 4019: The password CLI option on the command definition exposes
credentials in shell history and process listings, so remove the value-accepting
`--password <password>` flag from `src/main.tsx` and rely on `AIMLAPI_PASSWORD`
plus the existing hidden prompt flow. Update the related command setup and any
password-handling logic to use the `promptHidden` helper from `prompt.ts` for
interactive entry instead of accepting the password as a CLI argument.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 4c11b41b-99a3-4dca-9da7-bad87573bf5a
📒 Files selected for processing (1)
src/main.tsx
📜 Review details
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript with strict mode and ESM imports in source and test files.
Files:
src/main.tsx
**/*
📄 CodeRabbit inference engine (CONTRIBUTING.md)
In the files you touch, preserve the existing code style.
Files:
src/main.tsx
⚙️ CodeRabbit configuration file
**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.
Files:
src/main.tsx
**
⚙️ CodeRabbit configuration file
**: # AGENTS.md - AI Agent Coding GuideThis guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.
Project Snapshot
OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.
The installed CLI runs on Node.js
>=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.Work Style
- Keep changes focused on one problem.
- Prefer existing patterns in the file or nearby module.
- Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
- Add or update tests when behavior changes.
- Update docs when setup, commands, provider behavior, or user-facing behavior changes.
- For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.
Stack And Conventions
- TypeScript with strict mode and ESM imports.
- React + Ink for terminal UI.
- Bun lockfile and Bun scripts for development workflows.
- Node runtime for the built CLI.
Common libraries and patterns:
chalkfor terminal color.commanderfor CLI argument parsing.execafor child processes.- Existing service, provider, settings, permission, and UI patterns over new abstractions.
Repository Map
src/commands/- slash and CLI command implementations.src/components/- React/Ink UI components.src/services/- API, MCP, OAuth, wiki, voice, and other service integrations.src/tools/- tool implementations.src/utils/- shared utilities.src/integrations/- provider and model integration metadata.src/entrypoints/- CLI, MCP, SDK, and generated public types.src/tasks/- local, remote, workflow, and monitor tas...
Files:
src/main.tsx
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}
⚙️ CodeRabbit configuration file
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}: Review install, launcher, build, packaging, startup, and entrypoint changes for cross-platform compatibility, tracked-source rewrites, env/config precedence, and release safety. Block on changes that can break Windows/macOS/Linux startup or publish unexpected artifacts.
Files:
src/main.tsx
🔇 Additional comments (1)
src/main.tsx (1)
4013-4018: LGTM!Also applies to: 4020-4020, 4022-4045
jatmn
left a comment
There was a problem hiding this comment.
I found a few issues that need to be addressed before this is ready.
Findings
-
[P1] Fix the failing AI/ML API ProviderManager tests
src/components/ProviderManager.test.tsx:120
The new AI/ML API tests now fail in a fresh checkout becausePRESET_ORDERstill pinsAI/ML APIfirst, but the current manifest restoredGitlawb Opengatewayas the first preset after the maintainer request. As a result,navigateToPreset(mounted.stdin, 'AI/ML API')selects the wrong mocked preset,ProviderManager saves AI/ML API preset...seesMock providerinstead ofAI/ML API, andProviderManager can top up AI/ML API...times out before the top-up screen. Please realign the test helper with the actual preset order or make it derive the target from rendered labels so the changed tests exercise the AI/ML API path again. -
[P2] Complete CodeRabbit's request to normalize body-read aborts
src/integrations/aimlapi/client.ts:199
CodeRabbit's timeout follow-up is still valid: thefetch()call is inside thetry/catch, butresponse.text()is awaited after that block. If headers arrive and the body stalls or the timeout fires while consuming the body, the abort escapes as a raw error instead ofAimlapiApiError(status=0), sopollUntilPaid()cannot use its transient retry path and an in-progress checkout wait can abort. Please keep the body read inside the same normalized error handling. -
[P2] Complete CodeRabbit's request to avoid argv password exposure
src/main.tsx:4019
The CLI still accepts--password <password>and forwards it into the top-up flow. That puts the AI/ML API account password in shell history and process listings while the command runs, even though this PR already hasAIMLAPI_PASSWORDand the hiddenpromptHidden()path for non-echoed interactive entry. Please remove the value-taking password flag and rely on env/hidden prompt instead.
|
Fixed all three: PRESET_ORDER in the test helper now matches the restored order (Gitlawb Opengateway, Anthropic, AI/ML API, ...) — verified against ORDERED_PROVIDER_PRESETS directly. Body read (response.text()) is now inside the same try/catch as fetch(), so a timeout/abort mid-body normalizes to AimlapiApiError(status=0) and pollUntilPaid can retry it. Removed the value-taking --password CLI flag; only AIMLAPI_PASSWORD env / hidden prompt remain. @jatmn ready for re-review, please |
jatmn
left a comment
There was a problem hiding this comment.
Thanks for the update. I rechecked the current branch and found issues that still need to be addressed.
Findings
-
[P1] Fix the failing smoke-and-tests check
src/integrations/aimlapi/client.ts:192
The current GitHubsmoke-and-tests (22)job fails inbun run checkbecausescripts/no-raw-abort-signal-timeout.test.tsrejects this newAbortSignal.timeout(REQUEST_TIMEOUT_MS)call. The repository has a guard for this because rawAbortSignal.timeout()leaks native memory under Bun; timeout fetches should use the cleanup-safe helper pattern, such ascreateCombinedAbortSignal(..., { timeoutMs }), and callcleanup()after the fetch/body read completes. Please replace the raw timeout signal so the smoke job can pass again. -
[P3] Remove the stale
--passwordguidance from non-interactive top-up errors
src/integrations/aimlapi/prompt.ts:12
The CLI correctly no longer registers a value-taking--passwordoption, but the non-TTY guard still tells users to provide credentials via--email/--password. Runningopenclaude aimlapi topup --helpconfirms there is no password flag, while a non-interactive run withoutAIMLAPI_PASSWORDprints this impossible instruction. Please update this message to point users atAIMLAPI_PASSWORDor an interactive hidden prompt instead of the removed flag.
|
Fixed both — smoke check should pass now (AbortSignal.timeout replaced with createCombinedAbortSignal + cleanup()), and the non-interactive error message no longer mentions the removed --password flag. @jatmn could you please re-review? |
jatmn
left a comment
There was a problem hiding this comment.
Thanks for the update. I rechecked the current branch and found one issue that still needs to be addressed.
Findings
- [P2] Update the AI/ML API setup guide for guided top-up
docs/aimlapi-setup.md:11
The README still links this file as the AI/ML API setup guide, but the guide now drifts from the feature added in this PR: it says users must already have an AI/ML API account and API key from the dashboard, and the/providerinstructions only tell them to paste an existing key. The linked issue and this implementation specifically remove that blocker by adding “Top up and get API key” plusopenclaude aimlapi topup, so users following the documented setup path will still think they need to leave OpenClaude and manually create a key. Please update the setup guide to describe both supported paths: guided top-up/key provisioning and entering an existing key.
|
Fixed — updated the setup guide to document both paths (guided top-up via /provider or openclaude aimlapi topup, plus entering an existing key), so it no longer implies users must create a key manually on the dashboard first. Ready for re-review, please. (@jatmn ) |
jatmn
left a comment
There was a problem hiding this comment.
Thanks for the update. I rechecked the previously discussed paths and do not see any remaining actionable issues from my side.
@kevincodex1 LGTM
|
Thanks a lot for the thorough review and all the feedback throughout this process. I really appreciate the time and effort you put into it—it was a great learning experience for me. Glad we got everything sorted out! |
|
Thanks for the contribution :) |
| baseUrlEnvVars: ['OPENGATEWAY_BASE_URL', 'OPENAI_BASE_URL'], | ||
| fallbackBaseUrl: 'https://opengateway.gitlawb.com/v1', | ||
| fallbackModel: 'mimo-v2.5-pro', | ||
| badge: { text: 'Recommended', color: 'success' }, |
There was a problem hiding this comment.
please dont remove this . OpenGateway is our own gateway so it will be always on top and AIML will be below it but still recommended
There was a problem hiding this comment.
was format change, its still there :)
Summary
Adds a guided AI/ML API top-up path to provider setup and the CLI.
Related to #1885.
Follow-up to #835 / #863.
This PR includes one prerequisite cleanup commit that updates the AI/ML API checkout/inference attribution partner id before adding the guided checkout flow.
What changed
Provider setup
AI/ML API top-up
CLI
openclaude aimlapi topup.--no-open.Why
AI/ML API is already available as a first-class provider, but first-run setup still assumes the user has an API key. This completes the onboarding path for users who need to top up and receive a key during setup.
Impact
User-facing
/providerwithout already having an API key.Maintainer
Verification
bun run typecheckbun run buildbun run integrations:checkgit diff --checkKnown local test issue:
bun test src/components/ProviderManager.test.tsxcurrently fails before running tests withCannot find package 'bundle' from src/state/AppState.tsx.Summary by CodeRabbit
aimlapi topupCLI command with guided payment and API key provisioning.