mirror of
https://github.com/fancive/obsidian-parallel-reader.git
synced 2026-07-22 06:53:43 +00:00
refactor: extract body builders and types to src/provider-bodies.ts
Move buildAnthropicMessagesBody, buildOpenAiChatBody, buildOpenAiResponsesBody, buildGeminiBody, tokenLimitFieldForOpenAiChat and their type interfaces to a new module. Reduces providers.ts from 494 to 367 lines (under 400 target). Change-Id: Ib124d5cf5f2f66bac03acbf83e1a224cb6325d12
This commit is contained in:
parent
c111865fbd
commit
5eb005f293
3 changed files with 176 additions and 154 deletions
36
main.js
36
main.js
File diff suppressed because one or more lines are too long
143
src/provider-bodies.ts
Normal file
143
src/provider-bodies.ts
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
'use strict';
|
||||
|
||||
import {
|
||||
ANTHROPIC_CARD_TOOL_NAME,
|
||||
anthropicCardTool,
|
||||
cardOutputSchema,
|
||||
openAiJsonSchemaResponseFormat,
|
||||
openAiResponsesTextFormat,
|
||||
} from './schema';
|
||||
import { API_FORMATS, getApiFormat, getApiPreset, modelForApi } from './settings';
|
||||
import type { PluginSettings } from './types';
|
||||
|
||||
/* ---------- Body type interfaces ---------- */
|
||||
|
||||
export interface AnthropicMessagesBody {
|
||||
model: string;
|
||||
max_tokens: number;
|
||||
system: string;
|
||||
messages: Array<{ role: string; content: string }>;
|
||||
tools?: unknown[];
|
||||
tool_choice?: { type: string; name: string };
|
||||
stream?: boolean;
|
||||
}
|
||||
|
||||
export interface OpenAiChatBody {
|
||||
model: string;
|
||||
messages: Array<{ role: string; content: string }>;
|
||||
response_format?: unknown;
|
||||
stream?: boolean;
|
||||
[tokenField: string]: unknown;
|
||||
}
|
||||
|
||||
export interface OpenAiResponsesBody {
|
||||
model: string;
|
||||
instructions: string;
|
||||
input: string;
|
||||
max_output_tokens: number;
|
||||
text?: unknown;
|
||||
stream?: boolean;
|
||||
}
|
||||
|
||||
interface GeminiGenerationConfig {
|
||||
temperature: number;
|
||||
maxOutputTokens: number;
|
||||
responseMimeType?: string;
|
||||
responseJsonSchema?: unknown;
|
||||
}
|
||||
|
||||
export interface GeminiBody {
|
||||
systemInstruction: { parts: Array<{ text: string }> };
|
||||
contents: Array<{ role: string; parts: Array<{ text: string }> }>;
|
||||
generationConfig: GeminiGenerationConfig;
|
||||
}
|
||||
|
||||
/* ---------- Body builders ---------- */
|
||||
|
||||
export function tokenLimitFieldForOpenAiChat(settings: PluginSettings): string {
|
||||
const preset = getApiPreset(settings);
|
||||
const format = API_FORMATS[getApiFormat(settings)];
|
||||
return preset.tokenLimitField || format?.tokenLimitField || 'max_tokens';
|
||||
}
|
||||
|
||||
export function buildAnthropicMessagesBody(
|
||||
system: string,
|
||||
user: string,
|
||||
settings: PluginSettings,
|
||||
options?: { structured?: boolean },
|
||||
): AnthropicMessagesBody {
|
||||
const structured = !options || options.structured !== false;
|
||||
const body: AnthropicMessagesBody = {
|
||||
model: modelForApi(settings),
|
||||
max_tokens: Number(settings.apiMaxTokens) || 4096,
|
||||
system,
|
||||
messages: [{ role: 'user', content: user }],
|
||||
};
|
||||
if (structured) {
|
||||
body.tools = [anthropicCardTool()];
|
||||
body.tool_choice = { type: 'tool', name: ANTHROPIC_CARD_TOOL_NAME };
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
export function buildOpenAiChatBody(
|
||||
system: string,
|
||||
user: string,
|
||||
settings: PluginSettings,
|
||||
options?: { structured?: boolean },
|
||||
): OpenAiChatBody {
|
||||
const structured = !options || options.structured !== false;
|
||||
const body: OpenAiChatBody = {
|
||||
model: modelForApi(settings),
|
||||
messages: [
|
||||
{ role: 'system', content: system },
|
||||
{ role: 'user', content: user },
|
||||
],
|
||||
};
|
||||
body[tokenLimitFieldForOpenAiChat(settings)] = Number(settings.apiMaxTokens) || 4096;
|
||||
if (structured) {
|
||||
body.response_format = openAiJsonSchemaResponseFormat();
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
export function buildOpenAiResponsesBody(
|
||||
system: string,
|
||||
user: string,
|
||||
settings: PluginSettings,
|
||||
options?: { structured?: boolean },
|
||||
): OpenAiResponsesBody {
|
||||
const structured = !options || options.structured !== false;
|
||||
const body: OpenAiResponsesBody = {
|
||||
model: modelForApi(settings),
|
||||
instructions: system,
|
||||
input: user,
|
||||
max_output_tokens: Number(settings.apiMaxTokens) || 4096,
|
||||
};
|
||||
if (structured) {
|
||||
body.text = openAiResponsesTextFormat();
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
export function buildGeminiBody(
|
||||
system: string,
|
||||
user: string,
|
||||
settings: PluginSettings,
|
||||
options?: { structured?: boolean },
|
||||
): GeminiBody {
|
||||
const structured = !options || options.structured !== false;
|
||||
const generationConfig: GeminiGenerationConfig = {
|
||||
temperature: 0,
|
||||
maxOutputTokens: Number(settings.apiMaxTokens) || 4096,
|
||||
};
|
||||
if (structured) {
|
||||
generationConfig.responseMimeType = 'application/json';
|
||||
generationConfig.responseJsonSchema = cardOutputSchema(false);
|
||||
}
|
||||
return {
|
||||
systemInstruction: { parts: [{ text: system }] },
|
||||
contents: [{ role: 'user', parts: [{ text: user }] }],
|
||||
generationConfig,
|
||||
};
|
||||
}
|
||||
151
src/providers.ts
151
src/providers.ts
|
|
@ -1,6 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
import { translate } from './i18n';
|
||||
import {
|
||||
buildAnthropicMessagesBody,
|
||||
buildGeminiBody,
|
||||
buildOpenAiChatBody,
|
||||
buildOpenAiResponsesBody,
|
||||
} from './provider-bodies';
|
||||
import {
|
||||
cardsFromAnthropicToolUse,
|
||||
textFromAnthropicMessagesResponse,
|
||||
|
|
@ -8,14 +14,7 @@ import {
|
|||
textFromOpenAiChatResponse,
|
||||
textFromOpenAiResponsesResponse,
|
||||
} from './provider-parsers';
|
||||
import {
|
||||
ANTHROPIC_CARD_TOOL_NAME,
|
||||
anthropicCardTool,
|
||||
cardOutputSchema,
|
||||
openAiJsonSchemaResponseFormat,
|
||||
openAiResponsesTextFormat,
|
||||
parseCardsJson,
|
||||
} from './schema';
|
||||
import { parseCardsJson } from './schema';
|
||||
import {
|
||||
API_FORMATS,
|
||||
getApiAuthType,
|
||||
|
|
@ -28,6 +27,14 @@ import {
|
|||
import { deltaExtractorForFormat, type StreamProgress, streamingFetch } from './streaming';
|
||||
import type { PluginSettings, RawCard } from './types';
|
||||
|
||||
export {
|
||||
buildAnthropicMessagesBody,
|
||||
buildGeminiBody,
|
||||
buildOpenAiChatBody,
|
||||
buildOpenAiResponsesBody,
|
||||
tokenLimitFieldForOpenAiChat,
|
||||
} from './provider-bodies';
|
||||
|
||||
/* ---------- Typed request/response shapes ---------- */
|
||||
|
||||
type RequestUrlFunction = (params: {
|
||||
|
|
@ -44,46 +51,6 @@ function requiredDeltaExtractor(format: string) {
|
|||
return extractor;
|
||||
}
|
||||
|
||||
interface AnthropicMessagesBody {
|
||||
model: string;
|
||||
max_tokens: number;
|
||||
system: string;
|
||||
messages: Array<{ role: string; content: string }>;
|
||||
tools?: unknown[];
|
||||
tool_choice?: { type: string; name: string };
|
||||
stream?: boolean;
|
||||
}
|
||||
|
||||
interface OpenAiChatBody {
|
||||
model: string;
|
||||
messages: Array<{ role: string; content: string }>;
|
||||
response_format?: unknown;
|
||||
stream?: boolean;
|
||||
[tokenField: string]: unknown;
|
||||
}
|
||||
|
||||
interface OpenAiResponsesBody {
|
||||
model: string;
|
||||
instructions: string;
|
||||
input: string;
|
||||
max_output_tokens: number;
|
||||
text?: unknown;
|
||||
stream?: boolean;
|
||||
}
|
||||
|
||||
interface GeminiGenerationConfig {
|
||||
temperature: number;
|
||||
maxOutputTokens: number;
|
||||
responseMimeType?: string;
|
||||
responseJsonSchema?: unknown;
|
||||
}
|
||||
|
||||
interface GeminiBody {
|
||||
systemInstruction: { parts: Array<{ text: string }> };
|
||||
contents: Array<{ role: string; parts: Array<{ text: string }> }>;
|
||||
generationConfig: GeminiGenerationConfig;
|
||||
}
|
||||
|
||||
/* ---------- Helpers ---------- */
|
||||
|
||||
function endpointUrl(baseUrl: string, suffixes: string[]) {
|
||||
|
|
@ -237,94 +204,6 @@ async function requestJsonBodyWithStructuredFallback(
|
|||
}
|
||||
}
|
||||
|
||||
export function tokenLimitFieldForOpenAiChat(settings: PluginSettings): string {
|
||||
const preset = getApiPreset(settings);
|
||||
const format = API_FORMATS[getApiFormat(settings)];
|
||||
return preset.tokenLimitField || format?.tokenLimitField || 'max_tokens';
|
||||
}
|
||||
|
||||
export function buildAnthropicMessagesBody(
|
||||
system: string,
|
||||
user: string,
|
||||
settings: PluginSettings,
|
||||
options?: { structured?: boolean },
|
||||
): AnthropicMessagesBody {
|
||||
const structured = !options || options.structured !== false;
|
||||
const body: AnthropicMessagesBody = {
|
||||
model: modelForApi(settings),
|
||||
max_tokens: Number(settings.apiMaxTokens) || 4096,
|
||||
system,
|
||||
messages: [{ role: 'user', content: user }],
|
||||
};
|
||||
if (structured) {
|
||||
body.tools = [anthropicCardTool()];
|
||||
body.tool_choice = { type: 'tool', name: ANTHROPIC_CARD_TOOL_NAME };
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
export function buildOpenAiChatBody(
|
||||
system: string,
|
||||
user: string,
|
||||
settings: PluginSettings,
|
||||
options?: { structured?: boolean },
|
||||
): OpenAiChatBody {
|
||||
const structured = !options || options.structured !== false;
|
||||
const body: OpenAiChatBody = {
|
||||
model: modelForApi(settings),
|
||||
messages: [
|
||||
{ role: 'system', content: system },
|
||||
{ role: 'user', content: user },
|
||||
],
|
||||
};
|
||||
body[tokenLimitFieldForOpenAiChat(settings)] = Number(settings.apiMaxTokens) || 4096;
|
||||
if (structured) {
|
||||
body.response_format = openAiJsonSchemaResponseFormat();
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
export function buildOpenAiResponsesBody(
|
||||
system: string,
|
||||
user: string,
|
||||
settings: PluginSettings,
|
||||
options?: { structured?: boolean },
|
||||
): OpenAiResponsesBody {
|
||||
const structured = !options || options.structured !== false;
|
||||
const body: OpenAiResponsesBody = {
|
||||
model: modelForApi(settings),
|
||||
instructions: system,
|
||||
input: user,
|
||||
max_output_tokens: Number(settings.apiMaxTokens) || 4096,
|
||||
};
|
||||
if (structured) {
|
||||
body.text = openAiResponsesTextFormat();
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
export function buildGeminiBody(
|
||||
system: string,
|
||||
user: string,
|
||||
settings: PluginSettings,
|
||||
options?: { structured?: boolean },
|
||||
): GeminiBody {
|
||||
const structured = !options || options.structured !== false;
|
||||
const generationConfig: GeminiGenerationConfig = {
|
||||
temperature: 0,
|
||||
maxOutputTokens: Number(settings.apiMaxTokens) || 4096,
|
||||
};
|
||||
if (structured) {
|
||||
generationConfig.responseMimeType = 'application/json';
|
||||
generationConfig.responseJsonSchema = cardOutputSchema(false);
|
||||
}
|
||||
return {
|
||||
systemInstruction: { parts: [{ text: system }] },
|
||||
contents: [{ role: 'user', parts: [{ text: user }] }],
|
||||
generationConfig,
|
||||
};
|
||||
}
|
||||
|
||||
async function summarizeViaAnthropicMessages(
|
||||
requestUrlImpl: RequestUrlFunction,
|
||||
system: string,
|
||||
|
|
|
|||
Loading…
Reference in a new issue