- Introduced user configuration command to set API key. - Updated README and documentation for user config and logging paths. - Refactored logging to support user-specific log files. - Added tests for user configuration and logging behavior.
254 lines
6.7 KiB
Markdown
254 lines
6.7 KiB
Markdown
# nexus-claude-api Requirements Design
|
|
|
|
## Technical Stack
|
|
|
|
- Python `>=3.11`
|
|
- Package manager: `uv`
|
|
- Web framework: FastAPI
|
|
- ASGI server: Uvicorn
|
|
- Nexus client: boto3 Bedrock Runtime client
|
|
- Validation: Pydantic
|
|
- CLI: standard library `argparse`
|
|
- Tests: pytest
|
|
|
|
All project dependencies must be managed by `uv` and the project virtual environment. Do not install global Python dependencies.
|
|
|
|
## Project Structure
|
|
|
|
```text
|
|
nexus-claude-api/
|
|
pyproject.toml
|
|
README.md
|
|
docs/
|
|
AI_NEXUS_CLAUDE.md
|
|
PRD.md
|
|
REQUIREMENTS_DESIGN.md
|
|
src/
|
|
nexus_claude_api/
|
|
__init__.py
|
|
__main__.py
|
|
cli.py
|
|
config.py
|
|
errors.py
|
|
models.py
|
|
nexus_client.py
|
|
server.py
|
|
shell.py
|
|
tokens.py
|
|
routes/
|
|
health.py
|
|
messages.py
|
|
models.py
|
|
translators/
|
|
anthropic_to_bedrock.py
|
|
bedrock_to_anthropic.py
|
|
stream.py
|
|
tests/
|
|
```
|
|
|
|
## CLI Contract
|
|
|
|
Primary command:
|
|
|
|
```powershell
|
|
uv run nexus-claude-api start --port 4141 --claude-code
|
|
```
|
|
|
|
User configuration command:
|
|
|
|
```powershell
|
|
nexus-claude-api config set --api-key <key>
|
|
```
|
|
|
|
Options:
|
|
|
|
- `--host`: default `127.0.0.1`
|
|
- `--port`, `-p`: default `4141`
|
|
- `--endpoint-url`: default `https://genai-nexus.api.corpinter.net`
|
|
- `--api-key`: optional; overrides config files and environment variables
|
|
- `--model`: default `claude-opus-4.6`
|
|
- `--small-model`: default `claude-opus-4.6`
|
|
- `--claude-code`: print Claude Code launch command
|
|
- `--verbose`, `-v`: debug logging without secrets
|
|
- `--dev`: use current-directory development config and logs
|
|
- `--dry-run`: validate config and print helper output without starting the server
|
|
|
|
Credential lookup order:
|
|
|
|
1. `--api-key`
|
|
2. Current-mode config file
|
|
3. `NEXUS_API_KEY`
|
|
4. `AWS_BEARER_TOKEN_BEDROCK`
|
|
|
|
Config file paths:
|
|
|
|
- Default mode: `~/.config/nexus-claude-api/config.json`
|
|
- Development mode with `--dev`: current-directory `nexus-claude-api.local.json`
|
|
|
|
Log file paths:
|
|
|
|
- Default mode: `~/.config/nexus-claude-api/logs/nexus-claude-api.log`
|
|
- Development mode with `--dev`: current-directory `logs/nexus-claude-api.log`
|
|
|
|
When `--claude-code` is used, print a PowerShell command that sets:
|
|
|
|
- `ANTHROPIC_BASE_URL`
|
|
- `ANTHROPIC_AUTH_TOKEN`
|
|
- `ANTHROPIC_MODEL`
|
|
- `ANTHROPIC_DEFAULT_SONNET_MODEL`
|
|
- `ANTHROPIC_DEFAULT_OPUS_MODEL`
|
|
- `ANTHROPIC_SMALL_FAST_MODEL`
|
|
- `ANTHROPIC_DEFAULT_HAIKU_MODEL`
|
|
- `DISABLE_NON_ESSENTIAL_MODEL_CALLS`
|
|
- `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`
|
|
|
|
## HTTP API Contract
|
|
|
|
Expose:
|
|
|
|
- `GET /`
|
|
- `GET /health`
|
|
- `GET /v1/models`
|
|
- `POST /v1/messages`
|
|
- `POST /v1/messages/count_tokens`
|
|
|
|
`ANTHROPIC_AUTH_TOKEN` is printed as `dummy` because Claude Code expects an Anthropic auth token variable to exist. This local proxy does not validate that inbound token by default. It is not the Nexus key.
|
|
|
|
Inbound authentication headers are accepted for compatibility but not validated by default because the service is local. Outbound Nexus authentication uses `--api-key`, the current-mode config file, `NEXUS_API_KEY`, or `AWS_BEARER_TOKEN_BEDROCK`.
|
|
|
|
## Model Mapping
|
|
|
|
Public local model IDs:
|
|
|
|
- `claude-opus-4.6`
|
|
|
|
Backend IDs are resolved through a mapping table. This deployment exposes Opus and maps common Sonnet/Haiku aliases to Opus for users whose Nexus access is limited to `claude-opus-4.6`:
|
|
|
|
- `claude-sonnet-4.6` -> `claude-opus-4.6`
|
|
- `claude-haiku-4.5` -> `claude-opus-4.6`
|
|
- `claude-sonnet-4` -> `claude-opus-4.6`
|
|
- `claude-opus-4` -> `claude-opus-4.6`
|
|
- `claude-haiku-4` -> `claude-opus-4.6`
|
|
|
|
If Nexus requires different backend IDs, update the mapping without changing Claude Code-facing model IDs.
|
|
|
|
## Request Translation
|
|
|
|
Anthropic to Bedrock:
|
|
|
|
- `model` -> `modelId`
|
|
- `messages[].role` -> `role`
|
|
- string content -> `{ "text": "..." }`
|
|
- `{ "type": "text", "text": "..." }` -> `{ "text": "..." }`
|
|
- Anthropic image block -> Bedrock image block
|
|
- assistant `tool_use` -> Bedrock `toolUse`
|
|
- user `tool_result` -> Bedrock `toolResult`
|
|
- `system` -> Bedrock `system`
|
|
- `max_tokens`, `temperature`, `top_p` -> `inferenceConfig`
|
|
- `stop_sequences` -> `stopSequences`
|
|
- `tools` and `tool_choice` -> `toolConfig`
|
|
|
|
Unsupported content blocks should return `400 invalid_request_error`.
|
|
|
|
## Response Translation
|
|
|
|
Bedrock to Anthropic:
|
|
|
|
- Bedrock text content -> Anthropic text block.
|
|
- Bedrock `toolUse` -> Anthropic `tool_use`.
|
|
- Bedrock usage -> Anthropic `usage`.
|
|
- Bedrock stop reason maps to Anthropic stop reason.
|
|
|
|
Stop reason mapping:
|
|
|
|
- `end_turn` -> `end_turn`
|
|
- `max_tokens` -> `max_tokens`
|
|
- `stop_sequence` -> `stop_sequence`
|
|
- `tool_use` -> `tool_use`
|
|
- unknown -> `end_turn`
|
|
|
|
## Streaming Translation
|
|
|
|
Use `converse_stream`.
|
|
|
|
Translate Bedrock stream events to Anthropic SSE events:
|
|
|
|
- `messageStart` -> `message_start`
|
|
- `contentBlockStart` -> `content_block_start`
|
|
- `contentBlockDelta.delta.text` -> `content_block_delta` with `text_delta`
|
|
- tool input deltas -> `content_block_delta` with `input_json_delta`
|
|
- `contentBlockStop` -> `content_block_stop`
|
|
- `messageStop` -> `message_delta`, then `message_stop`
|
|
- `metadata.usage` -> usage update on final `message_delta`
|
|
- backend error -> `error`
|
|
|
|
SSE frame format:
|
|
|
|
```text
|
|
event: <event_type>
|
|
data: <json>
|
|
|
|
```
|
|
|
|
## Error Handling
|
|
|
|
Return Anthropic-compatible errors:
|
|
|
|
```json
|
|
{
|
|
"type": "error",
|
|
"error": {
|
|
"type": "invalid_request_error",
|
|
"message": "..."
|
|
}
|
|
}
|
|
```
|
|
|
|
Status mapping:
|
|
|
|
- invalid request: `400`
|
|
- missing Nexus credential: startup failure
|
|
- Nexus auth failure: `401` or `403`
|
|
- Nexus throttling: `429`
|
|
- Nexus network/timeout: `502` or `504`
|
|
- unexpected server error: `500`
|
|
|
|
## Testing
|
|
|
|
Unit tests:
|
|
|
|
- Minimal Anthropic text request -> Bedrock payload.
|
|
- System prompt conversion.
|
|
- Image block conversion.
|
|
- Tool config conversion.
|
|
- Tool use and tool result conversion.
|
|
- Bedrock text response -> Anthropic response.
|
|
- Bedrock tool response -> Anthropic tool response.
|
|
- Bedrock streaming events -> Anthropic SSE sequence.
|
|
- Token counting approximation.
|
|
|
|
Route tests:
|
|
|
|
- `GET /health`
|
|
- `GET /v1/models`
|
|
- `POST /v1/messages` non-stream
|
|
- `POST /v1/messages` stream
|
|
- `POST /v1/messages/count_tokens`
|
|
|
|
CLI tests:
|
|
|
|
- `nexus-claude-api --help`
|
|
- Claude Code command generation.
|
|
- Missing API key validation.
|
|
- User config writing with `nexus-claude-api config set --api-key <key>`.
|
|
- Default-mode user config lookup from `~/.config/nexus-claude-api/config.json`.
|
|
- Default mode ignores current-directory `nexus-claude-api.local.json`.
|
|
- Development mode uses current-directory `nexus-claude-api.local.json`.
|
|
- `--api-key` overrides config files and config files override environment variables.
|
|
|
|
Logging tests:
|
|
|
|
- Default-mode log path resolves to `~/.config/nexus-claude-api/logs/nexus-claude-api.log`.
|
|
- Development-mode log path resolves to current-directory `logs/nexus-claude-api.log`.
|
|
- Verbose logging enables debug details without logging secrets.
|