[PR #49] [CLOSED] feat: add Cursor compatibility and improve tool_results handling #67

Closed
opened 2026-02-27 07:17:48 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/jwadow/kiro-gateway/pull/49
Author: @somehow-paul
Created: 1/21/2026
Status: Closed

Base: mainHead: feat/cursor-compatibility


📝 Commits (1)

  • 4fdc7e6 feat: add Cursor compatibility and improve tool_results handling

📊 Changes

7 files changed (+228 additions, -57 deletions)

View changed files

📝 kiro/converters_core.py (+28 -14)
📝 kiro/converters_openai.py (+22 -5)
📝 kiro/model_resolver.py (+18 -0)
📝 kiro/models_openai.py (+17 -2)
📝 tests/unit/test_converters_core.py (+41 -27)
📝 tests/unit/test_converters_openai.py (+68 -0)
📝 tests/unit/test_models_openai.py (+34 -9)

📄 Description

PR Description

Summary

Add Cursor IDE compatibility and improve tool_results handling for better client support.

Changes

1. Cursor-style Flat Tool Format Support

Cursor IDE sends tools in a flat format instead of the standard OpenAI nested format:

// Standard OpenAI format
{"type": "function", "function": {"name": "...", "description": "...", "parameters": {...}}}

// Cursor flat format (now supported)
{"type": "function", "name": "...", "description": "...", "input_schema": {...}}

Files changed:

  • kiro/models_openai.py - Extended Tool model to accept both formats
  • kiro/converters_openai.py - Added conversion logic for flat format

2. Orphaned tool_results Handling Improvement

Previously, when a message contained tool_results without a preceding assistant message with tool_calls, the tool_results were silently stripped. Now they are converted to text representation and appended to the message content, preserving context for the model.

Files changed:

  • kiro/converters_core.py - Convert orphaned tool_results to text instead of stripping

3. Inverted Model Name Normalization

Added support for inverted model name format used by some clients:

claude-4.5-opus-high -> claude-opus-4.5
claude-4.5-sonnet-low -> claude-sonnet-4.5

Files changed:

  • kiro/model_resolver.py - Added pattern matching for inverted format

Testing

  • All 392 existing tests pass
  • Added new tests for Cursor flat tool format
  • Added tests for inverted model name normalization

Kiro Gateway - Cursor IDE API Compatibility Test Report

Report Date: January 21, 2026
Gateway Version: Kiro Gateway (AGPL-3.0)
Test Client: Cursor IDE
API Standard: OpenAI Chat Completions API


Executive Summary

This report evaluates the compatibility between Kiro Gateway and Cursor IDE's AI agent functionality. The gateway acts as a proxy that translates OpenAI-compatible API requests to the Kiro (AWS CodeWhisperer) backend, enabling Cursor to use Claude models through the Kiro infrastructure.

Category Status Notes
Overall Compatibility Compatible Full support for Cursor's agent mode
Streaming Supported SSE streaming with text/event-stream
Tool Calling Supported Both OpenAI and Cursor-style formats
Vision/Images Supported Base64 and URL image formats
Extended Thinking Supported Automatic injection

1. API Endpoint Compatibility

1.1 Supported Endpoints

Endpoint Method Cursor Usage Status
/v1/chat/completions POST Primary agent endpoint Fully Supported
/v1/models GET Model listing Fully Supported
/health GET Health check Supported
/ GET Root health check Supported

1.2 Authentication

Method Status Notes
Authorization: Bearer {key} Supported Standard OpenAI format
x-api-key header Supported Anthropic format (alternative)

2. Request Format Analysis

2.1 Captured Cursor Request Structure

Based on the captured request_body.json, Cursor sends requests with the following structure:

{
"model": "claude-4.5-opus-high",
"messages": [...],
"tools": [...],
"max_tokens": 4096,
"system": [...],
"metadata": {"user_id": "..."},
"tool_choice": {"type": "auto"},
"stream": true,
"stream_options": {"include_usage": true}
}

There is still an unresolved problem: when using Cursor, the connection occasionally drops / the stream gets interrupted.
I’m not sure whether this is related to my FRP setup.
Since using the API in Cursor requires forwarding traffic through a public IP, FRP is involved in the network path.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/jwadow/kiro-gateway/pull/49 **Author:** [@somehow-paul](https://github.com/somehow-paul) **Created:** 1/21/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `feat/cursor-compatibility` --- ### 📝 Commits (1) - [`4fdc7e6`](https://github.com/jwadow/kiro-gateway/commit/4fdc7e6a71cffff34e84080548ea5ea724e3423f) feat: add Cursor compatibility and improve tool_results handling ### 📊 Changes **7 files changed** (+228 additions, -57 deletions) <details> <summary>View changed files</summary> 📝 `kiro/converters_core.py` (+28 -14) 📝 `kiro/converters_openai.py` (+22 -5) 📝 `kiro/model_resolver.py` (+18 -0) 📝 `kiro/models_openai.py` (+17 -2) 📝 `tests/unit/test_converters_core.py` (+41 -27) 📝 `tests/unit/test_converters_openai.py` (+68 -0) 📝 `tests/unit/test_models_openai.py` (+34 -9) </details> ### 📄 Description ## PR Description ### Summary Add Cursor IDE compatibility and improve tool_results handling for better client support. ### Changes #### 1. Cursor-style Flat Tool Format Support Cursor IDE sends tools in a flat format instead of the standard OpenAI nested format: ```json // Standard OpenAI format {"type": "function", "function": {"name": "...", "description": "...", "parameters": {...}}} // Cursor flat format (now supported) {"type": "function", "name": "...", "description": "...", "input_schema": {...}} ``` **Files changed:** - `kiro/models_openai.py` - Extended `Tool` model to accept both formats - `kiro/converters_openai.py` - Added conversion logic for flat format #### 2. Orphaned tool_results Handling Improvement Previously, when a message contained `tool_results` without a preceding assistant message with `tool_calls`, the tool_results were silently stripped. Now they are converted to text representation and appended to the message content, preserving context for the model. **Files changed:** - `kiro/converters_core.py` - Convert orphaned tool_results to text instead of stripping #### 3. Inverted Model Name Normalization Added support for inverted model name format used by some clients: ``` claude-4.5-opus-high -> claude-opus-4.5 claude-4.5-sonnet-low -> claude-sonnet-4.5 ``` **Files changed:** - `kiro/model_resolver.py` - Added pattern matching for inverted format ### Testing - All 392 existing tests pass - Added new tests for Cursor flat tool format - Added tests for inverted model name normalization # Kiro Gateway - Cursor IDE API Compatibility Test Report **Report Date:** January 21, 2026 **Gateway Version:** Kiro Gateway (AGPL-3.0) **Test Client:** Cursor IDE **API Standard:** OpenAI Chat Completions API --- ## Executive Summary This report evaluates the compatibility between **Kiro Gateway** and **Cursor IDE**'s AI agent functionality. The gateway acts as a proxy that translates OpenAI-compatible API requests to the Kiro (AWS CodeWhisperer) backend, enabling Cursor to use Claude models through the Kiro infrastructure. | Category | Status | Notes | |----------|--------|-------| | **Overall Compatibility** | ✅ **Compatible** | Full support for Cursor's agent mode | | **Streaming** | ✅ Supported | SSE streaming with `text/event-stream` | | **Tool Calling** | ✅ Supported | Both OpenAI and Cursor-style formats | | **Vision/Images** | ✅ Supported | Base64 and URL image formats | | **Extended Thinking** | ✅ Supported | Automatic injection | --- ## 1. API Endpoint Compatibility ### 1.1 Supported Endpoints | Endpoint | Method | Cursor Usage | Status | |----------|--------|--------------|--------| | `/v1/chat/completions` | POST | Primary agent endpoint | ✅ Fully Supported | | `/v1/models` | GET | Model listing | ✅ Fully Supported | | `/health` | GET | Health check | ✅ Supported | | `/` | GET | Root health check | ✅ Supported | ### 1.2 Authentication | Method | Status | Notes | |--------|--------|-------| | `Authorization: Bearer {key}` | ✅ Supported | Standard OpenAI format | | `x-api-key` header | ✅ Supported | Anthropic format (alternative) | --- ## 2. Request Format Analysis ### 2.1 Captured Cursor Request Structure Based on the captured `request_body.json`, Cursor sends requests with the following structure: { "model": "claude-4.5-opus-high", "messages": [...], "tools": [...], "max_tokens": 4096, "system": [...], "metadata": {"user_id": "..."}, "tool_choice": {"type": "auto"}, "stream": true, "stream_options": {"include_usage": true} } There is still an unresolved problem: when using Cursor, the connection occasionally drops / the stream gets interrupted. I’m not sure whether this is related to my FRP setup. Since using the API in Cursor requires forwarding traffic through a public IP, FRP is involved in the network path. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
kerem 2026-02-27 07:17:48 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/kiro-gateway-jwadow#67
No description provided.