* feat(auth): add multi-account types and storage layer
Add foundation for multi-account Google Antigravity auth:
- ModelFamily, AccountTier, RateLimitState types for rate limit tracking
- AccountMetadata, AccountStorage, ManagedAccount interfaces
- Cross-platform storage module with XDG_DATA_HOME/APPDATA support
- Comprehensive test coverage for storage operations
🤖 Generated with [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
* feat(auth): implement AccountManager for multi-account rotation
Add AccountManager class with automatic account rotation:
- Per-family rate limit tracking (claude, gemini-flash, gemini-pro)
- Paid tier prioritization in rotation logic
- Round-robin account selection within tier pools
- Account add/remove operations with index management
- Storage persistence integration
🤖 Generated with [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
* feat(auth): add CLI prompts for multi-account setup
Add @clack/prompts-based CLI utilities:
- promptAddAnotherAccount() for multi-account flow
- promptAccountTier() for free/paid tier selection
- Non-TTY environment handling (graceful skip)
🤖 Generated with [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
* feat(auth): integrate multi-account OAuth flow into plugin
Enhance OAuth flow for multi-account support:
- Prompt for additional accounts after first OAuth (up to 10)
- Collect email and tier for each account
- Save accounts to storage via AccountManager
- Load AccountManager in loader() from stored accounts
- Toast notifications for account authentication success
- Backward compatible with single-account flow
🤖 Generated with [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
* feat(auth): add rate limit rotation to fetch interceptor
Integrate AccountManager into fetch for automatic rotation:
- Model family detection from URL (claude/gemini-flash/gemini-pro)
- Rate limit detection (429 with retry-after > 5s, 5xx errors)
- Mark rate-limited accounts and rotate to next available
- Recursive retry with new account on rotation
- Lazy load accounts from storage on first request
- Debug logging for account switches
🤖 Generated with [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
* feat(cli): add auth account management commands
Add CLI commands for managing Google Antigravity accounts:
- `auth list`: Show all accounts with email, tier, rate limit status
- `auth remove <index|email>`: Remove account by index or email
- Help text with usage examples
- Active account indicator and remaining rate limit display
🤖 Generated with [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
* refactor(auth): address review feedback - remove duplicate ManagedAccount and reuse fetch function
- Remove unused ManagedAccount interface from types.ts (duplicate of accounts.ts)
- Reuse fetchFn in rate limit retry instead of creating new fetch closure
Preserves cachedTokens, cachedProjectId, fetchInstanceId, accountsLoaded state
* fix(auth): address Cubic review feedback (8 issues)
P1 fixes:
- storage.ts: Use mode 0o600 for OAuth credentials file (security)
- fetch.ts: Return original 5xx status instead of synthesized 429
- accounts.ts: Adjust activeIndex/currentIndex in removeAccount
- plugin.ts: Fix multi-account migration to split on ||| not |
P2 fixes:
- cli.ts: Remove confusing cancel message when returning default
- auth.ts: Use strict parseInt check to prevent partial matches
- storage.test.ts: Use try/finally for env var cleanup
* refactor(test): import ManagedAccount from accounts.ts instead of duplicating
* fix(auth): address Oracle review findings (P1/P2)
P1 fixes:
- Clear cachedProjectId on account change to prevent stale project IDs
- Continue endpoint fallback for single-account users on rate limit
- Restore access/expires tokens from storage for non-active accounts
- Re-throw non-ENOENT filesystem errors (keep returning null for parse errors)
- Use atomic write (temp file + rename) for account storage
P2 fixes:
- Derive RateLimitState type from ModelFamily using mapped type
- Add MODEL_FAMILIES constant and use dynamic iteration in clearExpiredRateLimits
- Add missing else branch in storage.test.ts env cleanup
- Handle open() errors gracefully with user-friendly toast message
Tests updated to reflect correct behavior for token restoration.
* fix(auth): address Cubic review round 2 (5 issues)
P1: Return original 429/5xx response on last endpoint instead of generic 503
P2: Use unique temp filename (pid+timestamp) and cleanup on rename failure
P2: Clear cachedProjectId when first account introduced (lastAccountIndex null)
P3: Add console.error logging to open() catch block
* test(auth): add AccountManager removeAccount index tests
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* test(auth): add storage layer security and atomicity tests
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
* fix(auth): address Cubic review round 3 (4 issues)
P1 Fixes:
- plugin.ts: Validate refresh_token before constructing first account
- plugin.ts: Validate additionalTokens.refresh_token before pushing accounts
- fetch.ts: Reset cachedTokens when switching accounts during rotation
P2 Fixes:
- fetch.ts: Improve model-family detection (parse model from body, fallback to URL)
* fix(auth): address Cubic review round 4 (3 issues)
P1 Fixes:
- plugin.ts: Close serverHandle before early return on missing refresh_token
- plugin.ts: Close additionalServerHandle before continue on missing refresh_token
P2 Fixes:
- fetch.ts: Remove overly broad 'pro' matching in getModelFamilyFromModelName
* fix(auth): address Cubic review round 5 (9 issues)
P1 Fixes:
- plugin.ts: Close additionalServerHandle after successful account auth
- fetch.ts: Cancel response body on 429/5xx to prevent connection leaks
P2 Fixes:
- plugin.ts: Close additionalServerHandle on OAuth error/missing code
- plugin.ts: Close additionalServerHandle on verifier mismatch
- auth.ts: Set activeIndex to -1 when all accounts removed
- storage.ts: Use shared getDataDir utility for consistent paths
- fetch.ts: Catch loadAccounts IO errors with graceful fallback
- storage.test.ts: Improve test assertions with proper error tracking
* feat(antigravity): add system prompt and thinking config constants
* feat(antigravity): add reasoning_effort and Gemini 3 thinkingLevel support
* feat(antigravity): inject system prompt into all requests
* feat(antigravity): integrate thinking config and system prompt in fetch layer
* feat(auth): auto-open browser for OAuth login on all platforms
* fix(auth): add alias2ModelName for Antigravity Claude models
Root cause: Antigravity API expects 'claude-sonnet-4-5-thinking' but we were
sending 'gemini-claude-sonnet-4-5-thinking'. Ported alias mapping from
CLIProxyAPI antigravity_executor.go:1328-1347.
Transforms:
- gemini-claude-sonnet-4-5-thinking → claude-sonnet-4-5-thinking
- gemini-claude-opus-4-5-thinking → claude-opus-4-5-thinking
- gemini-3-pro-preview → gemini-3-pro-high
- gemini-3-flash-preview → gemini-3-flash
* fix(auth): add requestType and toolConfig for Antigravity API
Missing required fields from CLIProxyAPI implementation:
- requestType: 'agent'
- request.toolConfig.functionCallingConfig.mode: 'VALIDATED'
- Delete request.safetySettings
Also strip 'antigravity-' prefix before alias transformation.
* fix(auth): remove broken alias2ModelName transformations for Gemini 3
CLIProxyAPI's alias mappings don't work with public Antigravity API:
- gemini-3-pro-preview → gemini-3-pro-high (404!)
- gemini-3-flash-preview → gemini-3-flash (404!)
Tested: -preview suffix names work, transformed names return 404.
Keep only gemini-claude-* prefix stripping for future Claude support.
* fix(auth): implement correct alias2ModelName transformations for Antigravity API
Implements explicit switch-based model name mappings for Antigravity API.
Updates SANDBOX endpoint constants to clarify quota/availability behavior.
Fixes test expectations to match new transformation logic.
🤖 Generated with assistance of OhMyOpenCode
---------
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Previously, the install command would delete the entire 'agents' object
from the user's oh-my-opencode config before merging new install settings.
This caused all user customizations to be lost on reinstall.
Fixed by removing the 'delete existing.agents' line and relying on the
existing deepMerge function to properly merge configs, preserving user
customizations while updating only the fields specified by the installer.
Fixes#556
All Gemini model references now use the `antigravity-` prefix to ensure explicit
routing to Antigravity quota pools instead of relying on legacy `-preview` suffix
disambiguation. This approach prevents potential breakage if Google removes the
`-preview` suffix in future versions.
Updates include:
- config-manager: Updated Gemini model assignments with antigravity- prefix
- config-manager.test.ts: Updated test assertions to match new naming convention
- install.ts: Updated config summary display to show antigravity-prefixed model name
Migration follows opencode-antigravity-auth plugin v1.2.7+ guidance for explicit
quota routing configuration.
🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
- Remove gemini-3-pro-medium and gemini-3-flash-lite (deprecated in antigravity v1.2.7)
- Remove CHATGPT_HOTFIX_REPO variable and setupChatGPTHotfix() function
- Update CODEX_PROVIDER_CONFIG to modern variants system
🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
The installer now dynamically detects and uses the appropriate config
directory based on whether opencode CLI or opencode-desktop (Tauri) is
being used:
- opencode CLI: ~/.config/opencode/ (all platforms)
- opencode-desktop on Linux: ~/.config/ai.opencode.desktop/
- opencode-desktop on macOS: ~/Library/Application Support/ai.opencode.desktop/
- opencode-desktop on Windows: %APPDATA%/ai.opencode.desktop/
Key changes:
- Add new opencode-config-dir.ts module with platform-specific path resolution
- Support dev builds with ai.opencode.desktop.dev identifier
- Backward compatibility: checks legacy ~/.config/opencode/ first
- Refactor config-manager.ts to use dynamic paths via config context
- Update doctor plugin check to use shared path utilities
Fixes#440
Co-authored-by: sisyphus-dev-ai <sisyphus-dev-ai@users.noreply.github.com>
- Regenerated root AGENTS.md with overview, structure, and complexity hotspots
- Regenerated all 7 subdirectory AGENTS.md files: hooks, tools, features, agents, cli, auth, shared
- Used 11 background explore agents for comprehensive feature and architecture analysis
- All files within size limits (root: 112 lines, subdirs: 57-68 lines)
- Includes where-to-look guide, conventions, anti-patterns, and agent model information
🤖 Generated with assistance of oh-my-opencode
- Add "🪄 The Magic Word: ultrawork" section to all READMEs (EN, KO, JA, ZH-CN)
- Add Skill-Embedded MCP Support feature documentation
- Update installer to show ultrawork tip and star request after completion
🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
Add doctor check for GitHub CLI (gh) that verifies:
- Binary installation status
- Authentication status with GitHub
- Account details and token scopes when authenticated
Closes#374
Co-authored-by: sisyphus-dev-ai <sisyphus-dev-ai@users.noreply.github.com>
- Add error classification helpers for permission, file-not-found, and filesystem errors
- Handle empty/corrupt config files gracefully with recovery suggestions
- Add 60-second timeout to runBunInstall() to prevent hanging forever
- Improve error messages with specific recovery suggestions for each error type
- Export BunInstallResult type with detailed error info (success, timedOut, error)
- Handle SyntaxError in JSON parsing with user-friendly suggestions
- Add validation for config file contents (empty, whitespace-only, non-object)
Fixes#338
Co-authored-by: sisyphus-dev-ai <sisyphus-dev-ai@users.noreply.github.com>
Implements a comprehensive 'doctor' command that diagnoses oh-my-opencode
installation health with a beautiful TUI output.
Checks performed:
- OpenCode installation (version, path, binary)
- Plugin registration in opencode.json
- Configuration file validity (oh-my-opencode.json)
- Auth providers (Anthropic, OpenAI, Google)
- Dependencies (ast-grep CLI/NAPI, comment-checker)
- LSP servers availability
- MCP servers (builtin and user)
- Version status and updates
Features:
- Beautiful TUI with symbols and colors
- --verbose flag for detailed output
- --json flag for machine-readable output
- --category flag for running specific checks
- Exit code 1 on failures for CI integration
Closes#333
Co-authored-by: sisyphus-dev-ai <sisyphus-dev-ai@users.noreply.github.com>
- Only log tool invocation state changes, not text streaming
- Remove redundant preview logging for message.part text events
- Reduce verbose output noise by filtering partial message updates
🤖 Generated with assistance of OhMyOpenCode
* feat(cli): librarian uses gemini-3-flash when hasGemini (antigravity auth)
Closes#294
* feat(cli): add explore to gemini-3-flash when hasGemini + update docs
* feat(cli): fix explore agent fallback logic to use haiku for max20 Claude users
- Use gemini-3-flash for both librarian and explore when hasGemini
- Use haiku for explore when Claude max20 is available (hasClaude && isMax20)
- Fall back to big-pickle for both when other models unavailable
- Updated all README files to document the fallback precedence
🤖 Generated with assistance of [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
- Add process.exit(0) in runner.ts for immediate termination
- Fix Timer type to ReturnType<typeof setInterval> in manager.ts
- Add .unref() to BackgroundManager polling interval
- Add cleanup() method to BackgroundManager
🤖 Generated with assistance of [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
- Add new CLI command 'get-local-version' to display current version and check for updates
- Reuses existing version checking infrastructure from auto-update-checker
- Supports both human-readable and JSON output formats
- Handles edge cases: local dev mode, pinned versions, network errors
- Provides colored terminal output with picocolors
- Closes#260
Co-authored-by: sisyphus-dev-ai <sisyphus-dev-ai@users.noreply.github.com>
When session.error occurs with incomplete todos, the run command now:
- Captures the error via handleSessionError()
- Exits with code 1 instead of waiting indefinitely
- Shows clear error message to user
Previously, run command ignored session.error events, causing infinite
'Waiting: N todos remaining' loop when agent errors occurred.
🤖 Generated with assistance of OhMyOpenCode
https://github.com/code-yeongyu/oh-my-opencode
- logEventVerbose() logs all event types including message content, tool calls, and results
- Session tags distinguish main vs child sessions for multi-session tracking
- completion.ts error logging instead of silently swallowing API errors
- Helps diagnose realtime streaming behavior in CI environments
🤖 Generated with assistance of OhMyOpenCode (https://github.com/code-yeongyu/oh-my-opencode)
- Remove DEFAULT_TIMEOUT_MS (set to 0) to allow CI agent runs to complete without timeout
- Add stdbuf -oL -eL for unbuffered realtime output in GitHub Actions
- Update timeout logic to only set timeout when value > 0
This fixes CI agent runs that were timing out after 30 minutes and not showing realtime output.
🤖 Generated with assistance of OhMyOpenCode
The SDK yields events directly as the payload without wrapping in { payload: ... }.
Changed processEvents to treat event as the payload directly instead of looking
for event.payload. This fixes the 'Waiting for completion...' hang in GitHub
Actions where all events were being silently skipped.
🤖 Generated with assistance of [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
- Added message.part.updated event handling for incremental text streaming
- Added tool.execute event to display tool calls with input previews
- Added tool.result event to show truncated tool result outputs
- Enhanced EventState with lastPartText and currentTool tracking
- Defined MessagePartUpdatedProps, ToolExecuteProps, ToolResultProps types
- Updated event tests to cover new state fields
This enables the CLI run command to display real-time agent output similar to the native opencode run command, improving user experience with immediate feedback on tool execution.
🤖 Generated with assistance of OhMyOpenCode (https://github.com/code-yeongyu/oh-my-opencode)
- Add new 'run' command using @opencode-ai/sdk to manage agent sessions
- Implement recursive descendant session checking (waits for ALL nested child sessions)
- Add completion conditions: all todos done + all descendant sessions idle
- Add SSE event processing for session state tracking
- Fix todo-continuation-enforcer to clean up session tracking
- Comprehensive test coverage with memory-safe test patterns
Unlike 'opencode run', this command ensures the agent completes all tasks
by recursively waiting for nested background agent sessions before exiting.
🤖 Generated with assistance of OhMyOpenCode (https://github.com/code-yeongyu/oh-my-opencode)
The api: "antigravity" field being added to opencode.json causes
authentication failures with the antigravity plugin.
Fixes: NoeFabris/opencode-antigravity-auth#49
- Add user reviews section to READMEs (EN, KO, JA, ZH-CN)
- Update Antigravity request.ts: change default model from gemini-3-pro-preview to gemini-3-pro-high
- Enhance config-manager.ts: add full model specs (name, limit, modalities) to provider config
- Add comprehensive test suite for config-manager (config-manager.test.ts)
🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)