initial commits
This commit is contained in:
217
docs/REQUIREMENTS_DESIGN.md
Normal file
217
docs/REQUIREMENTS_DESIGN.md
Normal file
@@ -0,0 +1,217 @@
|
||||
# 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
|
||||
```
|
||||
|
||||
Options:
|
||||
|
||||
- `--host`: default `127.0.0.1`
|
||||
- `--port`, `-p`: default `4141`
|
||||
- `--endpoint-url`: default `https://genai-nexus.api.corpinter.net`
|
||||
- `--api-key`: optional; fallback to ignored local config, `NEXUS_API_KEY`, then `AWS_BEARER_TOKEN_BEDROCK`
|
||||
- `--model`: default `claude-sonnet-4.6`
|
||||
- `--small-model`: default `claude-haiku-4.5`
|
||||
- `--claude-code`: print Claude Code launch command
|
||||
- `--verbose`, `-v`: debug logging without secrets
|
||||
|
||||
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`, ignored local `nexus-claude-api.local.json`, `NEXUS_API_KEY`, or `AWS_BEARER_TOKEN_BEDROCK`.
|
||||
|
||||
## Model Mapping
|
||||
|
||||
Public local model IDs:
|
||||
|
||||
- `claude-sonnet-4.6`
|
||||
- `claude-opus-4.6`
|
||||
- `claude-haiku-4.5`
|
||||
|
||||
Backend IDs are resolved through a mapping table. The initial default mapping keeps the same IDs, except common short aliases are supported:
|
||||
|
||||
- `claude-sonnet-4` -> `claude-sonnet-4.6`
|
||||
- `claude-opus-4` -> `claude-opus-4.6`
|
||||
- `claude-haiku-4` -> `claude-haiku-4.5`
|
||||
|
||||
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 local 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.
|
||||
Reference in New Issue
Block a user