fix: credential detection and provider auth status (#120)

## Summary

Fix credential detection bugs and add credential availability status to the API. Consolidate Claude fallback models and add `sonnet` alias.

Builds on #109 (OAuth token support).

Related issues:
- Fixes #117 (Claude, Codex not showing up in gigacode)
- Related to #113 (Default agent should be Claude Code)

## Changes

### Credential detection fixes
- **`agent-credentials/src/lib.rs`**: Fix `?` operator bug in `extract_claude_credentials` - now continues to next config path if one is missing instead of returning early

### API credential status
- **`sandbox-agent/src/router.rs`**: Add `credentialsAvailable` field to `AgentInfo` struct
- **`/v1/agents`** endpoint now reports whether each agent has valid credentials

### OpenCode provider improvements
- **`sandbox-agent/src/opencode_compat.rs`**: Build `connected` array based on actual credential availability, not just model presence
- Check provider-specific credentials for OpenCode groups (e.g., `opencode:anthropic` only connected if Anthropic creds available)
- Add logging when credential extraction fails in model cache building

### Fallback model consolidation
- Renamed `claude_oauth_fallback_models()` → `claude_fallback_models()` (used for all fallback cases, not just OAuth)
- Added `sonnet` to fallback models (confirmed working via headless CLI test)
- Added `codex_fallback_models()` for Codex when credentials missing
- Added comment explaining aliases work for both API and OAuth users

### Documentation
- **`docs/credentials.mdx`**: New reference doc covering credential sources, extraction behavior, and error handling
- Documents that extraction failures are silent (not errors)
- Documents that agents spawn without credential pre-validation

### Inspector UI
- **`AgentsTab.tsx`**: Added credential status pill showing "Authenticated" or "No Credentials"

## Error Handling Philosophy

- **Extraction failures are silent**: Missing/malformed config files don't error, just continue to next source
- **Agents spawn without credential validation**: No pre-flight auth check; agent's native error surfaces if credentials are missing
- **Fallback models for UI**: When credentials missing, show alias-based models so users can still configure sessions

## Validation

- Tested Claude Code model aliases via headless CLI:
  - `claude --model default --print "say hi"` ✓
  - `claude --model sonnet --print "say hi"` ✓
  - `claude --model haiku --print "say hi"` ✓
- Build passes
- TypeScript types regenerated with `credentialsAvailable` field
This commit is contained in:
NathanFlurry 2026-02-07 07:56:06 +00:00
parent 915d484845
commit c54f83e1a6
No known key found for this signature in database
GPG key ID: 6A5F43A4F3241BCA
13 changed files with 807 additions and 9 deletions

View file

@ -585,6 +585,60 @@ const response = await client.provider.list();
When an OpenCode server is running, call `GET /provider` on its HTTP port. Returns full model metadata including capabilities, costs, context limits, and modalities.
## Command Execution & Process Management
### Agent Tool Execution
The agent executes commands via internal tools (not exposed in the HTTP API). The agent's tool calls are synchronous within its turn. Tool parts have states: `pending`, `running`, `completed`, `error`.
### PTY System (`/pty/*`) - User-Facing Terminals
Separate from the agent's command execution. PTYs are server-scoped interactive terminals for the user:
- `POST /pty` - Create PTY (command, args, cwd, title, env)
- `GET /pty` - List all PTYs
- `GET /pty/{ptyID}` - Get PTY info
- `PUT /pty/{ptyID}` - Update PTY (title, resize via `size: {rows, cols}`)
- `DELETE /pty/{ptyID}` - Kill and remove PTY
- `GET /pty/{ptyID}/connect` - WebSocket for bidirectional I/O
PTY events (globally broadcast via SSE): `pty.created`, `pty.updated`, `pty.exited`, `pty.deleted`.
The agent does NOT use the PTY system. PTYs are for the user's interactive terminal panel, independent of any AI session.
### Session Commands (`/session/{id}/command`, `/session/{id}/shell`) - Context Injection
External clients can inject command results into an AI session's conversation context:
- `POST /session/{sessionID}/command` - Executes a command and records the result as an `AssistantMessage` in the session. Required fields: `command`, `arguments`. The output becomes part of the AI's context for subsequent turns.
- `POST /session/{sessionID}/shell` - Similar but wraps in `sh -c`. Required fields: `command`, `agent`.
- `GET /command` - Lists available command definitions (metadata, not execution).
Session commands emit `command.executed` events with `sessionID` + `messageID`.
**Key distinction**: These endpoints execute commands directly (not via the AI), then inject the output into the session as if the AI produced it. The AI doesn't actively run the command - it just finds the output in its conversation history on the next turn.
### Three Separate Execution Mechanisms
| Mechanism | Who uses it | Scoped to | AI sees output? |
|-----------|-------------|-----------|----------------|
| Agent tools (internal) | AI agent | Session turn | Yes (immediate) |
| PTY (`/pty/*`) | User/frontend | Server (global) | No |
| Session commands (`/session/{id}/*`) | Frontend/SDK client | Session | Yes (next turn) |
The agent has no tool to interact with PTYs and cannot access the session command endpoints. When the agent needs to run a background process, it uses its internal bash-equivalent tool with shell backgrounding (`&`).
### Comparison
| Capability | Supported? | Notes |
|-----------|-----------|-------|
| Agent runs commands | Yes (internal tools) | Synchronous, blocks agent turn |
| User runs commands → agent sees output | Yes (`/session/{id}/command`) | HTTP API, first-class |
| External API for command injection | Yes | Session-scoped endpoints |
| Command source tracking | Implicit | Endpoint implies source (no enum) |
| Background process management | No | Shell `&` only for agent |
| PTY / interactive terminal | Yes (`/pty/*`) | Server-scoped, WebSocket I/O |
## Notes
- OpenCode is the most feature-rich runtime (streaming, questions, permissions)