Add Kiro CLI provider with multi-credential support#116
Add Kiro CLI provider with multi-credential support#116ItzMeAyben wants to merge 3 commits intoMirrowel:mainfrom
Conversation
…and documentation
Add comprehensive Kiro CLI (Amazon Q / Kiro) provider implementation with support for multiple authentication methods: - Direct refresh token via environment variables - JSON credentials from Kiro IDE (~/.aws/sso/cache/kiro-auth-token.json) - SQLite database from kiro-cli (macOS and Linux) - Auto-detection with configurable priority Features: - KiroAuthManager with AWS SSO OIDC and Kiro Desktop auth support - Token refresh with automatic expiration handling - HTTP client with retry logic (403, 429, 5xx) - OpenAI message/tool format conversion to Kiro API - AWS Event Stream parsing for streaming responses - Thinking block extraction and formatting - macOS and Linux path support Updates: - credential_manager.py: Add Kiro credential discovery - launcher_tui.py: Add Kiro credential detection in TUI - main.py: Skip JSON parsing for Kiro SQLite credentials - docker-compose.dev.yml: Add Kiro credential volume mounts - .env.example: Document all Kiro auth options - README.md: Add comprehensive Kiro setup documentation Co-authored-by: Cursor <cursoragent@cursor.com>
Add SPDX-License-Identifier and Copyright headers to all new Kiro provider files as required by CONTRIBUTING.md guidelines. Co-authored-by: Cursor <cursoragent@cursor.com>
|
@greptile |
|
@ItzMeAyben I didn't notice before, but the base branch here is main - it should be Dev branch instead. Main is never directly modified and is outdated. |
|
| Filename | Overview |
|---|---|
| src/rotator_library/providers/kiro_auth_base.py | Core authentication manager with token lifecycle, credential loading (JSON/SQLite), automatic refresh, and multi-auth support (Kiro Desktop/AWS SSO OIDC) |
| src/rotator_library/providers/kiro_cli_provider.py | Provider implementation following ProviderInterface pattern, handles model resolution, dynamic model discovery, and streaming/non-streaming responses |
| src/rotator_library/providers/utilities/kiro_converters.py | Message format conversions between OpenAI and Kiro APIs, handles tools, images, thinking tags injection, and schema sanitization for compatibility |
| src/rotator_library/providers/utilities/kiro_streaming.py | AWS Event Stream parser with thinking block extraction, tool call parsing, OpenAI SSE conversion, handles first token timeout and retry logic |
| src/rotator_library/credential_manager.py | Added Kiro CLI credential discovery supporting env tokens, JSON files, and SQLite databases with priority-based detection across platforms |
| src/proxy_app/main.py | Changed default port from 8000 to 7777, added special handling to skip JSON parsing for kiro_cli SQLite credentials during initialization |
| README.md | Added comprehensive Kiro CLI documentation covering three authentication methods, auto-detection paths, configuration options, and examples |
Sequence Diagram
sequenceDiagram
participant Client as API Client
participant Proxy as LLM Proxy
participant Provider as KiroCliProvider
participant Auth as KiroAuthManager
participant Store as Credential Store<br/>(JSON/SQLite)
participant OIDC as AWS SSO/Kiro Auth
participant API as Kiro Bedrock API
Client->>Proxy: POST /v1/chat/completions<br/>model: kiro_cli/claude-sonnet-4.5
Proxy->>Provider: acompletion(messages, tools)
Provider->>Auth: Request authentication
alt Credentials valid (more than 10min remaining)
Auth-->>Provider: Return valid auth header
else Credentials expired or expiring soon
Auth->>Store: Reload from disk
Store-->>Auth: Latest credentials with metadata
alt Still expired after reload
Auth->>OIDC: POST refresh request
OIDC-->>Auth: New credentials with expiry
Auth->>Store: Persist updated credentials
end
Auth-->>Provider: Return fresh auth header
end
Provider->>Provider: Convert OpenAI to Kiro format
Provider->>API: POST /generateAssistantResponse<br/>with Bearer authorization
alt Streaming enabled
API-->>Provider: AWS Event Stream
Provider->>Provider: Parse events, extract thinking
Provider-->>Client: OpenAI SSE chunks
else Non-streaming
API-->>Provider: AWS Event Stream
Provider->>Provider: Collect full response
Provider-->>Client: OpenAI completion
end
Last reviewed commit: 076746c
| await self.auth_manager.force_refresh() | ||
| continue | ||
|
|
||
| if response.status_code in (429,) or 500 <= response.status_code < 600: |
There was a problem hiding this comment.
Single-element tuple (429,) is unnecessarily verbose
| if response.status_code in (429,) or 500 <= response.status_code < 600: | |
| if response.status_code == 429 or 500 <= response.status_code < 600: |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/rotator_library/providers/utilities/kiro_http_client.py
Line: 96
Comment:
Single-element tuple `(429,)` is unnecessarily verbose
```suggestion
if response.status_code == 429 or 500 <= response.status_code < 600:
```
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
|
|
||
| # Special-case: Kiro CLI supports multiple credential sources | ||
| # Priority: REFRESH_TOKEN (env) > KIRO_CREDS_FILE (JSON) > KIRO_CLI_DB_FILE (SQLite) > default paths | ||
| kiro_refresh_token = self.env_vars.get("KIRO_REFRESH_TOKEN") or self.env_vars.get("REFRESH_TOKEN") |
There was a problem hiding this comment.
Consider using only KIRO_REFRESH_TOKEN instead of falling back to generic REFRESH_TOKEN to avoid potential conflicts with other systems
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/rotator_library/credential_manager.py
Line: 129
Comment:
Consider using only `KIRO_REFRESH_TOKEN` instead of falling back to generic `REFRESH_TOKEN` to avoid potential conflicts with other systems
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
|
Starting my review of this Kiro CLI provider implementation. Adding support for Claude models via AWS Bedrock with multi-credential authentication - this looks comprehensive! Analyzing the new provider files now. 🔍 |
There was a problem hiding this comment.
Overall Assessment
Excellent PR implementing comprehensive Kiro CLI provider support! The architecture is well-designed with clean separation of concerns across authentication, HTTP client, streaming, and conversion layers. The code follows the existing provider interface pattern and includes proper LGPL-3.0 licensing on all new files.
Key Strengths
- Multi-credential authentication: Clean implementation supporting environment variables, JSON files, and SQLite databases with auto-detection
- Token lifecycle management: Proper refresh handling with 10-minute safety margin and persistent storage
- AWS Event Stream parsing: Well-implemented parser for streaming responses with thinking block extraction
- Error handling: Good use of exponential backoff and automatic token refresh on 403 errors
- Thread safety: Proper use of
asyncio.Lockfor token refresh to prevent race conditions
Notes
I concur with Greptile's observations regarding:
- The verbose tuple syntax in
kiro_http_client.py:96could be simplified - The
REFRESH_TOKENfallback incredential_manager.py:129could conflict with other systems
Minor Suggestion
The silent JSON parsing failure in extract_tool_uses_from_message() could mask issues with malformed tool arguments. Consider adding logging when json.loads() fails.
Questions for the Author
- Has this been tested with both Kiro Desktop and AWS SSO OIDC authentication flows in production?
- Are there any plans to support Windows paths for the SQLite auto-detection?
Overall, this is high-quality code ready for merge after addressing the minor suggestions.
This review was generated by an AI assistant.
| func = tc.get("function", {}) | ||
| arguments = func.get("arguments", "{}") | ||
| if isinstance(arguments, str): |
There was a problem hiding this comment.
If json.loads() fails here, input_data becomes an empty dict but the code continues silently. Consider logging this parsing failure so malformed tool arguments don't go unnoticed.
Summary
Add Kiro CLI (Amazon Q / Kiro) provider enabling access to Claude models via AWS Bedrock using Kiro CLI authentication.
Port Note: Uses 7777 (project default) vs reference's 8000.
Features
<thinking>block extractionSupported Models
All Claude models available through Kiro API:
Architecture
Authentication Flow
sequenceDiagram participant Client as API Client participant Proxy as LLM Proxy participant Auth as KiroAuthManager participant Store as Credential Store participant OIDC as AWS SSO/Kiro Auth participant API as Kiro Bedrock API Client->>Proxy: POST /v1/chat/completions Proxy->>Auth: get_access_token() Auth->>Store: Load credentials Store-->>Auth: Token + metadata alt Token valid (> 10min remaining) Auth-->>Proxy: Valid access_token else Token expired or expiring Auth->>OIDC: Refresh token request OIDC-->>Auth: New access_token (1hr) Auth->>Store: Save refreshed token Auth-->>Proxy: New access_token end Proxy->>API: Request with Bearer token API-->>Proxy: Event Stream response Proxy-->>Client: OpenAI SSE chunksToken Management
Automatic Refresh
Token Storage Locations
~/Library/Application Support/kiro-cli/data.sqlite3~/.aws/sso/cache/kiro-auth-token.json~/.local/share/kiro-cli/data.sqlite3~/.aws/sso/cache/kiro-auth-token.jsonAuthentication Priority
KIRO_REFRESH_TOKEN/REFRESH_TOKENenvironment variableKIRO_CREDS_FILE)KIRO_CLI_DB_FILE)System Architecture
graph TB subgraph "LLM Proxy Server" A[FastAPI Router] --> B[KiroCliProvider] B --> C[Message Converters] B --> D[Stream Parser] B --> E[HTTP Client] end subgraph "Authentication Layer" F[KiroAuthManager] --> G[(JSON Files)] F --> H[(SQLite DB)] F --> I[Token Refresh] I --> J[AWS SSO OIDC] I --> K[Kiro Desktop Auth] end subgraph "External Services" L[Kiro Bedrock API] end B --> F E -->|Bearer Token| L F -->|Credentials| E L -->|AWS Event Stream| D D -->|OpenAI SSE| A C -->|Kiro Payload| EProject Structure
Testing
Verified working across multiple scenarios:
Implementation Notes
ProviderInterfacepattern fromprovider_interface.pyhas_custom_logic()for direct API handlingChecklist
ProviderInterfacepatternAcknowledgments
Implementation adapted from kiro-gateway by @Jwadow - reference for Kiro API flows, AWS Event Stream parsing, and message format conversions. Integrated into LLM-API-Key-Proxy's provider architecture with LGPL-3.0 licensing.