| <!DOCTYPE html> |
| <html lang="zh-CN"> |
|
|
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Cursor2API - 强大的AI模型API代理</title> |
| <style> |
| * { |
| margin: 0; |
| padding: 0; |
| box-sizing: border-box; |
| } |
| |
| body { |
| font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; |
| line-height: 1.6; |
| color: #333; |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| min-height: 100vh; |
| } |
| |
| .container { |
| max-width: 1200px; |
| margin: 0 auto; |
| padding: 20px; |
| } |
| |
| .header { |
| text-align: center; |
| color: white; |
| margin-bottom: 40px; |
| } |
| |
| .header h1 { |
| font-size: 3rem; |
| font-weight: 700; |
| margin-bottom: 10px; |
| text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3); |
| } |
| |
| .header .subtitle { |
| font-size: 1.2rem; |
| opacity: 0.9; |
| } |
| |
| .main-content { |
| background: white; |
| border-radius: 20px; |
| box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); |
| overflow: hidden; |
| } |
| |
| .nav-tabs { |
| display: flex; |
| background: #f8f9fa; |
| border-bottom: 1px solid #e9ecef; |
| } |
| |
| .nav-tab { |
| flex: 1; |
| padding: 20px; |
| text-align: center; |
| cursor: pointer; |
| font-weight: 600; |
| color: #6c757d; |
| transition: all 0.3s ease; |
| border: none; |
| background: none; |
| } |
| |
| .nav-tab:hover { |
| background: #e9ecef; |
| color: #495057; |
| } |
| |
| .nav-tab.active { |
| background: #007bff; |
| color: white; |
| } |
| |
| .tab-content { |
| display: none; |
| padding: 40px; |
| } |
| |
| .tab-content.active { |
| display: block; |
| } |
| |
| .status-card { |
| background: linear-gradient(135deg, #28a745, #20c997); |
| color: white; |
| padding: 30px; |
| border-radius: 15px; |
| margin-bottom: 30px; |
| text-align: center; |
| } |
| |
| .api-info { |
| display: grid; |
| grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); |
| gap: 20px; |
| margin-bottom: 30px; |
| } |
| |
| .info-card { |
| background: #f8f9fa; |
| padding: 25px; |
| border-radius: 15px; |
| border-left: 4px solid #007bff; |
| } |
| |
| .info-card h3 { |
| color: #007bff; |
| margin-bottom: 15px; |
| } |
| |
| .info-card .value { |
| font-family: Monaco, monospace; |
| background: white; |
| padding: 10px; |
| border-radius: 8px; |
| font-weight: bold; |
| } |
| |
| .models-grid { |
| display: grid; |
| grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); |
| gap: 20px; |
| margin-bottom: 30px; |
| } |
| |
| .model-card { |
| background: white; |
| border: 2px solid #e9ecef; |
| border-radius: 15px; |
| padding: 20px; |
| cursor: pointer; |
| transition: all 0.3s ease; |
| text-align: center; |
| } |
| |
| .model-card:hover { |
| border-color: #007bff; |
| transform: translateY(-5px); |
| box-shadow: 0 10px 25px rgba(0, 123, 255, 0.2); |
| } |
| |
| .model-card.selected { |
| border-color: #007bff; |
| background: #f8f9ff; |
| } |
| |
| .model-card .model-name { |
| font-size: 1.2rem; |
| font-weight: bold; |
| color: #007bff; |
| margin-bottom: 8px; |
| } |
| |
| .model-card .provider { |
| font-size: 0.9rem; |
| color: #6c757d; |
| opacity: 0.8; |
| } |
| |
| .code-block { |
| background: #f8f9fa; |
| border: 1px solid #e9ecef; |
| border-radius: 10px; |
| padding: 20px; |
| margin: 20px 0; |
| position: relative; |
| } |
| |
| .copy-btn { |
| position: absolute; |
| top: 10px; |
| right: 10px; |
| background: #007bff; |
| color: white; |
| border: none; |
| padding: 8px 15px; |
| border-radius: 6px; |
| cursor: pointer; |
| font-size: 0.9rem; |
| transition: background 0.3s ease; |
| } |
| |
| .copy-btn:hover { |
| background: #0056b3; |
| } |
| |
| .code-block code { |
| font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; |
| font-size: 0.9rem; |
| line-height: 1.5; |
| display: block; |
| white-space: pre-wrap; |
| word-break: break-all; |
| } |
| |
| .endpoint-card { |
| background: #f8f9fa; |
| border-radius: 10px; |
| padding: 20px; |
| margin: 15px 0; |
| border-left: 4px solid #007bff; |
| } |
| |
| .method-badge { |
| display: inline-block; |
| padding: 4px 12px; |
| border-radius: 20px; |
| font-size: 0.8rem; |
| font-weight: bold; |
| margin-right: 10px; |
| } |
| |
| .method-get { |
| background: #28a745; |
| color: white; |
| } |
| |
| .method-post { |
| background: #007bff; |
| color: white; |
| } |
| |
| .footer { |
| text-align: center; |
| padding: 30px; |
| color: #6c757d; |
| background: rgba(255, 255, 255, 0.9); |
| margin-top: 40px; |
| border-radius: 15px; |
| } |
| |
| @media (max-width: 768px) { |
| .header h1 { |
| font-size: 2rem; |
| } |
| |
| .models-grid { |
| grid-template-columns: 1fr; |
| } |
| |
| .api-info { |
| grid-template-columns: 1fr; |
| } |
| } |
| </style> |
| </head> |
|
|
| <body> |
| <div class="container"> |
| <div class="header"> |
| <h1>🚀 Cursor2API</h1> |
| <p class="subtitle">强大的AI模型API代理服务 - OpenAI兼容接口</p> |
| </div> |
|
|
| <div class="main-content"> |
| |
| <div class="nav-tabs"> |
| <button class="nav-tab active" onclick="showTab('overview')">概览</button> |
| <button class="nav-tab" onclick="showTab('models')">模型列表</button> |
| <button class="nav-tab" onclick="showTab('api')">API文档</button> |
| </div> |
|
|
| |
| <div id="overview" class="tab-content active"> |
| <div class="status-card"> |
| <h2>✅ 服务运行正常</h2> |
| <p> Cursor2API已成功启动并运行中</p> |
| </div> |
|
|
| <div class="api-info"> |
| <div class="info-card"> |
| <h3>📍 服务地址</h3> |
| <div class="value">http://localhost:8002</div> |
| </div> |
| <div class="info-card"> |
| <h3>🔑 API密钥</h3> |
| <div class="value">0000 (默认)</div> |
| </div> |
| <div class="info-card"> |
| <h3>🎯 兼容性</h3> |
| <div class="value">OpenAI API 标准</div> |
| </div> |
| <div class="info-card"> |
| <h3>🌊 流式支持</h3> |
| <div class="value">支持 SSE 流式响应</div> |
| </div> |
| <div class="info-card"> |
| <h3>🧰 Tool Calls</h3> |
| <div class="value">支持 tools / tool_choice / tool_calls</div> |
| </div> |
| <div class="info-card"> |
| <h3>🧠 Thinking</h3> |
| <div class="value">自动暴露 -thinking 模型(thinking 不对外透出)</div> |
| </div> |
| </div> |
|
|
| <div style="margin-top: 30px;"> |
| <h3>🚀 快速开始</h3> |
|
|
| <div class="code-block"> |
| <button class="copy-btn" onclick="copyCode(this)">复制</button> |
| <code># 获取模型列表 |
| curl -H "Authorization: Bearer 0000" http://localhost:8002/v1/models</code> |
| </div> |
|
|
| <h4 style="margin-top: 15px; color: #555;">非流式聊天 (Non-Streaming)</h4> |
| <div class="code-block"> |
| <button class="copy-btn" onclick="copyCode(this)">复制</button> |
| <code>curl -X POST http://localhost:8002/v1/chat/completions \ |
| -H "Content-Type: application/json" \ |
| -H "Authorization: Bearer 0000" \ |
| -d '{ |
| "model": "claude-sonnet-4.6", |
| "messages": [{"role": "user", "content": "Hello!"}], |
| "stream": false |
| }'</code> |
| </div> |
|
|
| <h4 style="margin-top: 15px; color: #555;">流式聊天 (Streaming)</h4> |
| <div class="code-block"> |
| <button class="copy-btn" onclick="copyCode(this)">复制</button> |
| <code>curl -X POST http://localhost:8002/v1/chat/completions \ |
| -H "Content-Type: application/json" \ |
| -H "Authorization: Bearer 0000" \ |
| -d '{ |
| "model": "claude-sonnet-4.6", |
| "messages": [{"role": "user", "content": "Hello!"}], |
| "stream": true |
| }'</code> |
| </div> |
|
|
| <h4 style="margin-top: 15px; color: #555;">工具调用 (Tool Calls)</h4> |
| <div class="code-block"> |
| <button class="copy-btn" onclick="copyCode(this)">复制</button> |
| <code>curl -X POST http://localhost:8002/v1/chat/completions \ |
| -H "Content-Type: application/json" \ |
| -H "Authorization: Bearer 0000" \ |
| -d '{ |
| "model": "claude-sonnet-4.6", |
| "messages": [{"role": "user", "content": "What is 2+2? Use the calculator tool."}], |
| "tools": [ |
| { |
| "type": "function", |
| "function": { |
| "name": "calculator", |
| "description": "Evaluate a simple arithmetic expression.", |
| "parameters": { |
| "type": "object", |
| "properties": { |
| "expression": {"type": "string"} |
| }, |
| "required": ["expression"] |
| } |
| } |
| } |
| ], |
| "tool_choice": {"type": "function", "function": {"name": "calculator"}}, |
| "stream": false |
| }'</code> |
| </div> |
|
|
| <h4 style="margin-top: 15px; color: #555;">Kilo Code 兼容(可选)</h4> |
| <div class="code-block"> |
| <button class="copy-btn" onclick="copyCode(this)">复制</button> |
| <code># 当上层强制“必须用工具”时,可在 .env 开启 |
| KILO_TOOL_STRICT=true |
|
|
| # 非流式请求:若要求用工具但本轮未产出 tool_calls,会自动重试 1 次(流式不重试)</code> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="models" class="tab-content"> |
| <h2>🤖 支持的AI模型</h2> |
| <p>点击模型卡片可查看详细信息和使用示例</p> |
|
|
| <div class="models-grid" id="modelsGrid"> |
| <div class="model-card" onclick="selectModel('claude-sonnet-4.6')"> |
| <div class="model-name">claude-sonnet-4.6</div> |
| <div class="provider">Anthropic Claude</div> |
| </div> |
| <div class="model-card" onclick="selectModel('claude-sonnet-4.6-thinking')"> |
| <div class="model-name">claude-sonnet-4.6-thinking</div> |
| <div class="provider">Anthropic Claude + Thinking</div> |
| </div> |
| </div> |
|
|
| <div id="selectedModelInfo" style="display: none; margin-top: 30px;"> |
| <h3>使用选中的模型</h3> |
| <div class="code-block"> |
| <button class="copy-btn" onclick="copyCode(this)">复制</button> |
| <code id="modelExample"></code> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="api" class="tab-content"> |
| <h2>📡 API端点文档</h2> |
|
|
| <div class="endpoint-card"> |
| <div class="method-badge method-get">GET</div> |
| <strong>/v1/models</strong> |
| <p>获取所有可用的AI模型列表</p> |
| <div class="code-block" style="margin-top: 15px;"> |
| <button class="copy-btn" onclick="copyCode(this)">复制</button> |
| <code>curl -H "Authorization: Bearer 0000" http://localhost:8002/v1/models</code> |
| </div> |
| </div> |
|
|
| <div class="endpoint-card"> |
| <div class="method-badge method-post">POST</div> |
| <strong>/v1/chat/completions</strong> |
| <p>创建聊天完成请求,支持流式、非流式和 OpenAI 兼容 tool_calls</p> |
| <div class="code-block" style="margin-top: 15px;"> |
| <button class="copy-btn" onclick="copyCode(this)">复制</button> |
| <code>curl -X POST http://localhost:8002/v1/chat/completions \ |
| -H "Content-Type: application/json" \ |
| -H "Authorization: Bearer 0000" \ |
| -d '{ |
| "model": "claude-sonnet-4.6", |
| "messages": [ |
| {"role": "user", "content": "你好"} |
| ], |
| "stream": false |
| }'</code> |
| </div> |
| <p style="margin-top: 10px; color: #555;"> |
| 说明:当响应包含工具调用时,非流式会返回 <code>message.tool_calls</code> 且 <code>finish_reason="tool_calls"</code>; |
| 流式会在 <code>delta.tool_calls</code> 中输出,并在最后一个 chunk 以 <code>finish_reason="tool_calls"</code> 收尾。 |
| </p> |
| </div> |
|
|
| <div class="endpoint-card"> |
| <div class="method-badge method-post">POST</div> |
| <strong>/v1/responses</strong> |
| <p>Responses API 兼容端点,支持输入项、工具调用与流式输出</p> |
| <div class="code-block" style="margin-top: 15px;"> |
| <button class="copy-btn" onclick="copyCode(this)">复制</button> |
| <code>curl -X POST http://localhost:8002/v1/responses \ |
| -H "Content-Type: application/json" \ |
| -H "Authorization: Bearer 0000" \ |
| -d '{ |
| "model": "claude-sonnet-4.6", |
| "input": "你好", |
| "stream": false |
| }'</code> |
| </div> |
| <p style="margin-top: 10px; color: #555;"> |
| 说明:当响应包含工具调用时,会返回 <code>output</code> 数组中的 <code>function_call</code>、 |
| <code>apply_patch_call</code>、<code>shell_call</code> 或 <code>local_shell_call</code> 等输出项。 |
| </p> |
| </div> |
|
|
| <div class="endpoint-card"> |
| <div class="method-badge method-get">GET</div> |
| <strong>/health</strong> |
| <p>健康检查端点</p> |
| <div class="code-block" style="margin-top: 15px;"> |
| <button class="copy-btn" onclick="copyCode(this)">复制</button> |
| <code>curl http://localhost:8002/health</code> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="footer"> |
| <p>©2025 Cursor2API | 强大的AI模型API代理服务</p> |
| </div> |
| </div> |
|
|
| <script> |
| |
| function showTab(tabName) { |
| const tabContents = document.getElementsByClassName('tab-content'); |
| for (let i = 0; i < tabContents.length; i++) { |
| tabContents[i].classList.remove('active'); |
| } |
| |
| const tabBtns = document.getElementsByClassName('nav-tab'); |
| for (let i = 0; i < tabBtns.length; i++) { |
| tabBtns[i].classList.remove('active'); |
| } |
| |
| document.getElementById(tabName).classList.add('active'); |
| event.target.classList.add('active'); |
| } |
| |
| |
| function selectModel(modelId) { |
| const prevSelected = document.querySelector('.model-card.selected'); |
| if (prevSelected) { |
| prevSelected.classList.remove('selected'); |
| } |
| |
| const modelCards = document.querySelectorAll('.model-card'); |
| modelCards.forEach(card => { |
| if (card.onclick.toString().includes(modelId)) { |
| card.classList.add('selected'); |
| } |
| }); |
| |
| const exampleCode = `curl -X POST http://localhost:8002/v1/chat/completions \\ |
| -H "Content-Type: application/json" \\ |
| -H "Authorization: Bearer 0000" \\ |
| -d '{ |
| "model": "${modelId}", |
| "messages": [ |
| { |
| "role": "user", |
| "content": "你好,请用中文回答问题" |
| } |
| ], |
| "stream": false |
| }'`; |
| |
| document.getElementById('modelExample').textContent = exampleCode; |
| document.getElementById('selectedModelInfo').style.display = 'block'; |
| } |
| |
| |
| function copyCode(btn) { |
| const codeBlock = btn.nextElementSibling; |
| const code = codeBlock.textContent; |
| |
| navigator.clipboard.writeText(code).then(() => { |
| const originalText = btn.textContent; |
| btn.textContent = '已复制!'; |
| btn.style.background = '#28a745'; |
| setTimeout(() => { |
| btn.textContent = originalText; |
| btn.style.background = '#007bff'; |
| }, 2000); |
| }).catch(() => { |
| alert('复制失败,请手动复制代码'); |
| }); |
| } |
| </script> |
| </body> |
|
|
| </html> |
|
|