重构Kiro服务从openai迁移至claude模块,更新相关文档和测试 修复Claude策略中内容提取逻辑,支持input_json_delta类型 优化系统提示词处理,当无系统消息时使用首个用户消息 更新README文档,添加健康检查端点和最新模型支持说明
183 lines
6.6 KiB
JavaScript
183 lines
6.6 KiB
JavaScript
import { GeminiApiService } from './gemini/gemini-core.js'; // 导入geminiApiService
|
|
import { OpenAIApiService } from './openai/openai-core.js'; // 导入OpenAIApiService
|
|
import { ClaudeApiService } from './claude/claude-core.js'; // 导入ClaudeApiService
|
|
import { KiroApiService } from './claude/claude-kiro.js'; // 导入KiroApiService
|
|
import { MODEL_PROVIDER } from './common.js'; // 导入 MODEL_PROVIDER
|
|
|
|
// 定义AI服务适配器接口
|
|
// 所有的服务适配器都应该实现这些方法
|
|
export class ApiServiceAdapter {
|
|
constructor() {
|
|
if (new.target === ApiServiceAdapter) {
|
|
throw new TypeError("Cannot construct ApiServiceAdapter instances directly");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 生成内容
|
|
* @param {string} model - 模型名称
|
|
* @param {object} requestBody - 请求体
|
|
* @returns {Promise<object>} - API响应
|
|
*/
|
|
async generateContent(model, requestBody) {
|
|
throw new Error("Method 'generateContent()' must be implemented.");
|
|
}
|
|
|
|
/**
|
|
* 流式生成内容
|
|
* @param {string} model - 模型名称
|
|
* @param {object} requestBody - 请求体
|
|
* @returns {AsyncIterable<object>} - API响应流
|
|
*/
|
|
async *generateContentStream(model, requestBody) {
|
|
throw new Error("Method 'generateContentStream()' must be implemented.");
|
|
}
|
|
|
|
/**
|
|
* 列出可用模型
|
|
* @returns {Promise<object>} - 模型列表
|
|
*/
|
|
async listModels() {
|
|
throw new Error("Method 'listModels()' must be implemented.");
|
|
}
|
|
}
|
|
|
|
// Gemini API 服务适配器
|
|
export class GeminiApiServiceAdapter extends ApiServiceAdapter {
|
|
constructor(config) {
|
|
super();
|
|
this.geminiApiService = new GeminiApiService(config);
|
|
this.geminiApiService.initialize().catch(error => {
|
|
console.error("Failed to initialize geminiApiService:", error);
|
|
});
|
|
}
|
|
|
|
async generateContent(model, requestBody) {
|
|
if (!this.geminiApiService.isInitialized) {
|
|
console.warn("geminiApiService not initialized, attempting to re-initialize...");
|
|
await this.geminiApiService.initialize();
|
|
}
|
|
return this.geminiApiService.generateContent(model, requestBody);
|
|
}
|
|
|
|
async *generateContentStream(model, requestBody) {
|
|
if (!this.geminiApiService.isInitialized) {
|
|
console.warn("geminiApiService not initialized, attempting to re-initialize...");
|
|
await this.geminiApiService.initialize();
|
|
}
|
|
yield* this.geminiApiService.generateContentStream(model, requestBody);
|
|
}
|
|
|
|
async listModels() {
|
|
if (!this.geminiApiService.isInitialized) {
|
|
console.warn("geminiApiService not initialized, attempting to re-initialize...");
|
|
await this.geminiApiService.initialize();
|
|
}
|
|
// Gemini Core API 的 listModels 已经返回符合 Gemini 格式的数据,所以不需要额外转换
|
|
return this.geminiApiService.listModels();
|
|
}
|
|
}
|
|
|
|
// OpenAI API 服务适配器
|
|
export class OpenAIApiServiceAdapter extends ApiServiceAdapter {
|
|
constructor(config) {
|
|
super();
|
|
this.openAIApiService = new OpenAIApiService(config);
|
|
}
|
|
|
|
async generateContent(model, requestBody) {
|
|
// The adapter now expects the requestBody to be in the native OpenAI format.
|
|
// The conversion logic is handled upstream in the server.
|
|
return this.openAIApiService.generateContent(model, requestBody);
|
|
}
|
|
|
|
async *generateContentStream(model, requestBody) {
|
|
// The adapter now expects the requestBody to be in the native OpenAI format.
|
|
const stream = this.openAIApiService.generateContentStream(model, requestBody);
|
|
// The stream is yielded directly without conversion.
|
|
yield* stream;
|
|
}
|
|
|
|
async listModels() {
|
|
// The adapter now returns the native model list from the underlying service.
|
|
return this.openAIApiService.listModels();
|
|
}
|
|
}
|
|
|
|
// Claude API 服务适配器
|
|
export class ClaudeApiServiceAdapter extends ApiServiceAdapter {
|
|
constructor(config) {
|
|
super();
|
|
this.claudeApiService = new ClaudeApiService(config);
|
|
}
|
|
|
|
async generateContent(model, requestBody) {
|
|
// The adapter now expects the requestBody to be in the native Claude format.
|
|
return this.claudeApiService.generateContent(model, requestBody);
|
|
}
|
|
|
|
async *generateContentStream(model, requestBody) {
|
|
// The adapter now expects the requestBody to be in the native Claude format.
|
|
const stream = this.claudeApiService.generateContentStream(model, requestBody);
|
|
yield* stream;
|
|
}
|
|
|
|
async listModels() {
|
|
// The adapter now returns the native model list from the underlying service.
|
|
return this.claudeApiService.listModels();
|
|
}
|
|
}
|
|
|
|
// Kiro API 服务适配器
|
|
export class KiroApiServiceAdapter extends ApiServiceAdapter {
|
|
constructor(config) {
|
|
super();
|
|
this.kiroApiService = new KiroApiService(config);
|
|
this.kiroApiService.initialize().catch(error => {
|
|
console.error("Failed to initialize kiroApiService:", error);
|
|
});
|
|
}
|
|
|
|
async generateContent(model, requestBody) {
|
|
// The adapter expects the requestBody to be in OpenAI format for Kiro API
|
|
return this.kiroApiService.generateContent(model, requestBody);
|
|
}
|
|
|
|
async *generateContentStream(model, requestBody) {
|
|
// The adapter expects the requestBody to be in OpenAI format for Kiro API
|
|
const stream = this.kiroApiService.generateContentStream(model, requestBody);
|
|
yield* stream;
|
|
}
|
|
|
|
async listModels() {
|
|
// Returns the native model list from the Kiro service
|
|
return this.kiroApiService.listModels();
|
|
}
|
|
}
|
|
|
|
// 用于存储服务适配器单例的映射
|
|
const serviceInstances = {};
|
|
|
|
// 服务适配器工厂
|
|
export function getServiceAdapter(config) {
|
|
const provider = config.MODEL_PROVIDER;
|
|
if (!serviceInstances[provider]) {
|
|
switch (provider) {
|
|
case MODEL_PROVIDER.OPENAI_CUSTOM:
|
|
serviceInstances[provider] = new OpenAIApiServiceAdapter(config);
|
|
break;
|
|
case MODEL_PROVIDER.GEMINI_CLI:
|
|
serviceInstances[provider] = new GeminiApiServiceAdapter(config);
|
|
break;
|
|
case MODEL_PROVIDER.CLAUDE_CUSTOM:
|
|
serviceInstances[provider] = new ClaudeApiServiceAdapter(config);
|
|
break;
|
|
case MODEL_PROVIDER.KIRO_API:
|
|
serviceInstances[provider] = new KiroApiServiceAdapter(config);
|
|
break;
|
|
default:
|
|
throw new Error(`Unsupported model provider: ${provider}`);
|
|
}
|
|
}
|
|
return serviceInstances[provider];
|
|
}
|