mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-26 03:31:24 +08:00
* fix(apiServer): use 127.0.0.1 instead of localhost for better compatibility - Change default host from localhost to 127.0.0.1 in config and settings - Add buildApiServerUrl helper to properly construct API server URLs - Update OpenAPI documentation server URL - Update test files to use 127.0.0.1 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix(migration): migrate existing localhost config to 127.0.0.1 - Add migration 180 to automatically update localhost to 127.0.0.1 - Handle both plain host and hosts with http/https protocol - Increment store version to 180 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(apiServer): simplify buildApiServerUrl implementation - Remove complex URL parsing and protocol handling - Use simple string concatenation for URL building - Assume http protocol since API server is local 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor: remove buildApiServerUrl helper and simplify migration - Remove buildApiServerUrl helper function - Use 127.0.0.1 directly in URL construction - Simplify migration 180 to unconditionally set host to 127.0.0.1 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(apiServer): fix critical bugs and improve code structure 🔴 Critical Fixes: - Fix config.ts to use stored host value instead of ignoring it - Fix hardcoded 127.0.0.1 URLs to use apiServerConfig.host 🟡 Improvements: - Extract API_SERVER_DEFAULTS to shared constants in packages/shared/config/constant.ts - Apply consistent fallback pattern using API_SERVER_DEFAULTS.HOST and API_SERVER_DEFAULTS.PORT - Update all imports to use shared constants across main and renderer processes Files changed: - packages/shared/config/constant.ts: Add API_SERVER_DEFAULTS constants - src/main/apiServer/config.ts: Use stored host with fallback - src/main/apiServer/middleware/openapi.ts: Use constants - src/renderer/src/pages/settings/ToolSettings/ApiServerSettings/ApiServerSettings.tsx: Use config host and constants - src/renderer/src/store/settings.ts: Use constants in initial state - src/renderer/src/store/migrate.ts: Use constants in migration 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * update * fix(apiServer): use relative URL in OpenAPI spec for better compatibility - Change server URL from hardcoded defaults to relative path '/' - This ensures Swagger UI "Try it out" works correctly regardless of configured host/port - Remove unused API_SERVER_DEFAULTS import 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
208 lines
5.5 KiB
TypeScript
208 lines
5.5 KiB
TypeScript
import type { Express } from 'express'
|
|
import swaggerJSDoc from 'swagger-jsdoc'
|
|
import swaggerUi from 'swagger-ui-express'
|
|
|
|
import { loggerService } from '../../services/LoggerService'
|
|
|
|
const logger = loggerService.withContext('OpenAPIMiddleware')
|
|
|
|
const swaggerOptions: swaggerJSDoc.Options = {
|
|
definition: {
|
|
openapi: '3.0.0',
|
|
info: {
|
|
title: 'Cherry Studio API',
|
|
version: '1.0.0',
|
|
description: 'OpenAI-compatible API for Cherry Studio with additional Cherry-specific endpoints',
|
|
contact: {
|
|
name: 'Cherry Studio',
|
|
url: 'https://github.com/CherryHQ/cherry-studio'
|
|
}
|
|
},
|
|
servers: [
|
|
{
|
|
url: '/',
|
|
description: 'Current server'
|
|
}
|
|
],
|
|
components: {
|
|
securitySchemes: {
|
|
BearerAuth: {
|
|
type: 'http',
|
|
scheme: 'bearer',
|
|
bearerFormat: 'JWT',
|
|
description: 'Use the API key from Cherry Studio settings'
|
|
}
|
|
},
|
|
schemas: {
|
|
Error: {
|
|
type: 'object',
|
|
properties: {
|
|
error: {
|
|
type: 'object',
|
|
properties: {
|
|
message: { type: 'string' },
|
|
type: { type: 'string' },
|
|
code: { type: 'string' }
|
|
}
|
|
}
|
|
}
|
|
},
|
|
ChatMessage: {
|
|
type: 'object',
|
|
properties: {
|
|
role: {
|
|
type: 'string',
|
|
enum: ['system', 'user', 'assistant', 'tool']
|
|
},
|
|
content: {
|
|
oneOf: [
|
|
{ type: 'string' },
|
|
{
|
|
type: 'array',
|
|
items: {
|
|
type: 'object',
|
|
properties: {
|
|
type: { type: 'string' },
|
|
text: { type: 'string' },
|
|
image_url: {
|
|
type: 'object',
|
|
properties: {
|
|
url: { type: 'string' }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
},
|
|
name: { type: 'string' },
|
|
tool_calls: {
|
|
type: 'array',
|
|
items: {
|
|
type: 'object',
|
|
properties: {
|
|
id: { type: 'string' },
|
|
type: { type: 'string' },
|
|
function: {
|
|
type: 'object',
|
|
properties: {
|
|
name: { type: 'string' },
|
|
arguments: { type: 'string' }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
ChatCompletionRequest: {
|
|
type: 'object',
|
|
required: ['model', 'messages'],
|
|
properties: {
|
|
model: {
|
|
type: 'string',
|
|
description: 'The model to use for completion, in format provider:model-id'
|
|
},
|
|
messages: {
|
|
type: 'array',
|
|
items: { $ref: '#/components/schemas/ChatMessage' }
|
|
},
|
|
temperature: {
|
|
type: 'number',
|
|
minimum: 0,
|
|
maximum: 2,
|
|
default: 1
|
|
},
|
|
max_tokens: {
|
|
type: 'integer',
|
|
minimum: 1
|
|
},
|
|
stream: {
|
|
type: 'boolean',
|
|
default: false
|
|
},
|
|
tools: {
|
|
type: 'array',
|
|
items: {
|
|
type: 'object',
|
|
properties: {
|
|
type: { type: 'string' },
|
|
function: {
|
|
type: 'object',
|
|
properties: {
|
|
name: { type: 'string' },
|
|
description: { type: 'string' },
|
|
parameters: { type: 'object' }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
Model: {
|
|
type: 'object',
|
|
properties: {
|
|
id: { type: 'string' },
|
|
object: { type: 'string', enum: ['model'] },
|
|
created: { type: 'integer' },
|
|
owned_by: { type: 'string' }
|
|
}
|
|
},
|
|
MCPServer: {
|
|
type: 'object',
|
|
properties: {
|
|
id: { type: 'string' },
|
|
name: { type: 'string' },
|
|
command: { type: 'string' },
|
|
args: {
|
|
type: 'array',
|
|
items: { type: 'string' }
|
|
},
|
|
env: { type: 'object' },
|
|
disabled: { type: 'boolean' }
|
|
}
|
|
}
|
|
}
|
|
},
|
|
security: [
|
|
{
|
|
BearerAuth: []
|
|
}
|
|
]
|
|
},
|
|
apis: ['./src/main/apiServer/routes/**/*.ts', './src/main/apiServer/app.ts']
|
|
}
|
|
|
|
export function setupOpenAPIDocumentation(app: Express) {
|
|
try {
|
|
const specs = swaggerJSDoc(swaggerOptions)
|
|
|
|
// Serve OpenAPI JSON
|
|
app.get('/api-docs.json', (_req, res) => {
|
|
res.setHeader('Content-Type', 'application/json')
|
|
res.send(specs)
|
|
})
|
|
|
|
// Serve Swagger UI
|
|
app.use(
|
|
'/api-docs',
|
|
swaggerUi.serve,
|
|
swaggerUi.setup(specs, {
|
|
customCss: `
|
|
.swagger-ui .topbar { display: none; }
|
|
.swagger-ui .info .title { color: #1890ff; }
|
|
`,
|
|
customSiteTitle: 'Cherry Studio API Documentation'
|
|
})
|
|
)
|
|
|
|
logger.info('OpenAPI documentation ready', {
|
|
docsPath: '/api-docs',
|
|
specPath: '/api-docs.json'
|
|
})
|
|
} catch (error) {
|
|
logger.error('Failed to setup OpenAPI documentation', { error })
|
|
}
|
|
}
|