fix(api-server): 修复OPTIONS请求的CORS头部设置
feat(convert): 添加OpenAI流式响应停止块生成函数 refactor(common): 优化流式请求处理逻辑,支持更多协议转换
This commit is contained in:
parent
015a17a3a9
commit
f33cf38b42
3 changed files with 53 additions and 8 deletions
|
|
@ -411,9 +411,15 @@ function createRequestHandler(config) {
|
|||
const apiService = await getApiService(currentConfig);
|
||||
const method = req.method;
|
||||
if (method === 'OPTIONS') {
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
console.log("OPTIONS REQUEST SUCCESS");
|
||||
return res.end("OPTIONS REQUEST SUCCESS");
|
||||
// 设置 CORS 头部,允许所有来源和方法
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
||||
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, x-goog-api-key');
|
||||
|
||||
// OPTIONS 请求通常返回 204 No Content
|
||||
res.writeHead(204);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// Health check endpoint - no authentication required
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { promises as fs } from 'fs';
|
|||
import * as path from 'path';
|
||||
import * as http from 'http'; // Add http for IncomingMessage and ServerResponse types
|
||||
import { ApiServiceAdapter } from './adapter.js'; // Import ApiServiceAdapter
|
||||
import { convertData } from './convert.js';
|
||||
import { convertData, getOpenAIStreamChunkStop } from './convert.js';
|
||||
import { ProviderStrategyFactory } from './provider-strategies.js';
|
||||
|
||||
export const API_ACTIONS = {
|
||||
|
|
@ -207,7 +207,8 @@ export async function handleStreamRequest(res, service, model, requestBody, from
|
|||
// The service returns a stream in its native format (toProvider).
|
||||
const nativeStream = await service.generateContentStream(model, requestBody);
|
||||
const needsConversion = getProtocolPrefix(fromProvider) !== getProtocolPrefix(toProvider);
|
||||
const isClaude = getProtocolPrefix(fromProvider) === MODEL_PROTOCOL_PREFIX.CLAUDE;
|
||||
const addEvent = getProtocolPrefix(fromProvider) === MODEL_PROTOCOL_PREFIX.CLAUDE;
|
||||
const openStop = getProtocolPrefix(fromProvider) === MODEL_PROTOCOL_PREFIX.OPENAI;
|
||||
|
||||
try {
|
||||
for await (const nativeChunk of nativeStream) {
|
||||
|
|
@ -225,7 +226,7 @@ export async function handleStreamRequest(res, service, model, requestBody, from
|
|||
continue;
|
||||
}
|
||||
|
||||
if (isClaude) {
|
||||
if (addEvent) {
|
||||
res.write(`event: ${chunkToSend.type}\n`);
|
||||
// console.log(`event: ${chunkToSend.type}\n`);
|
||||
}
|
||||
|
|
@ -233,6 +234,10 @@ export async function handleStreamRequest(res, service, model, requestBody, from
|
|||
res.write(`data: ${JSON.stringify(chunkToSend)}\n\n`);
|
||||
// console.log(`data: ${JSON.stringify(chunkToSend)}\n`);
|
||||
}
|
||||
if (openStop && needsConversion) {
|
||||
res.write(`data: ${JSON.stringify(getOpenAIStreamChunkStop(model))}\n\n`);
|
||||
// console.log(`data: ${JSON.stringify(getOpenAIStreamChunkStop(model))}\n`);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('\n[Server] Error during stream processing:', error.stack);
|
||||
|
|
|
|||
|
|
@ -407,10 +407,18 @@ export function toOpenAIStreamChunkFromClaude(claudeChunk, model) {
|
|||
object: "chat.completion.chunk",
|
||||
created: Math.floor(Date.now() / 1000),
|
||||
model: model,
|
||||
system_fingerprint: "",
|
||||
choices: [{
|
||||
index: 0,
|
||||
delta: { content: claudeChunk },
|
||||
finish_reason: null,
|
||||
delta: {
|
||||
content: claudeChunk,
|
||||
reasoning_content: ""
|
||||
},
|
||||
finish_reason: !claudeChunk ? 'stop' : null,
|
||||
message: {
|
||||
content: claudeChunk,
|
||||
reasoning_content: ""
|
||||
}
|
||||
}],
|
||||
usage:{
|
||||
prompt_tokens: 0,
|
||||
|
|
@ -420,6 +428,32 @@ export function toOpenAIStreamChunkFromClaude(claudeChunk, model) {
|
|||
};
|
||||
}
|
||||
|
||||
export function getOpenAIStreamChunkStop(model) {
|
||||
return {
|
||||
id: `chatcmpl-${uuidv4()}`, // uuidv4 needs to be imported or handled
|
||||
object: "chat.completion.chunk",
|
||||
created: Math.floor(Date.now() / 1000),
|
||||
model: model,
|
||||
system_fingerprint: "",
|
||||
choices: [{
|
||||
index: 0,
|
||||
delta: {
|
||||
content: "",
|
||||
reasoning_content: ""
|
||||
},
|
||||
finish_reason: 'stop',
|
||||
message: {
|
||||
content: "",
|
||||
reasoning_content: ""
|
||||
}
|
||||
}],
|
||||
usage:{
|
||||
prompt_tokens: 0,
|
||||
completion_tokens: 0,
|
||||
total_tokens: 0,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue