@bbclaw/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/anthropic/index.d.ts +44 -0
- package/dist/providers/anthropic/index.d.ts.map +1 -0
- package/dist/providers/anthropic/index.js +75 -0
- package/dist/providers/anthropic/index.js.map +1 -0
- package/dist/providers/index.d.ts +8 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +8 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/openai-compat/index.d.ts +59 -0
- package/dist/providers/openai-compat/index.d.ts.map +1 -0
- package/dist/providers/openai-compat/index.js +175 -0
- package/dist/providers/openai-compat/index.js.map +1 -0
- package/dist/providers/openai-compat/presets.d.ts +22 -0
- package/dist/providers/openai-compat/presets.d.ts.map +1 -0
- package/dist/providers/openai-compat/presets.js +73 -0
- package/dist/providers/openai-compat/presets.js.map +1 -0
- package/dist/providers/openai-compat/requestTranslate.d.ts +39 -0
- package/dist/providers/openai-compat/requestTranslate.d.ts.map +1 -0
- package/dist/providers/openai-compat/requestTranslate.js +228 -0
- package/dist/providers/openai-compat/requestTranslate.js.map +1 -0
- package/dist/providers/openai-compat/sseParser.d.ts +29 -0
- package/dist/providers/openai-compat/sseParser.d.ts.map +1 -0
- package/dist/providers/openai-compat/sseParser.js +139 -0
- package/dist/providers/openai-compat/sseParser.js.map +1 -0
- package/dist/providers/openai-compat/streamAdapter.d.ts +45 -0
- package/dist/providers/openai-compat/streamAdapter.d.ts.map +1 -0
- package/dist/providers/openai-compat/streamAdapter.js +233 -0
- package/dist/providers/openai-compat/streamAdapter.js.map +1 -0
- package/dist/providers/openai-compat/types.d.ts +126 -0
- package/dist/providers/openai-compat/types.d.ts.map +1 -0
- package/dist/providers/openai-compat/types.js +11 -0
- package/dist/providers/openai-compat/types.js.map +1 -0
- package/dist/providers/selector.d.ts +52 -0
- package/dist/providers/selector.d.ts.map +1 -0
- package/dist/providers/selector.js +101 -0
- package/dist/providers/selector.js.map +1 -0
- package/dist/providers/types.d.ts +114 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +152 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/providers/web-bridge/deepseek/spec.d.ts +22 -0
- package/dist/providers/web-bridge/deepseek/spec.d.ts.map +1 -0
- package/dist/providers/web-bridge/deepseek/spec.js +70 -0
- package/dist/providers/web-bridge/deepseek/spec.js.map +1 -0
- package/dist/providers/web-bridge/historySerializer.d.ts +49 -0
- package/dist/providers/web-bridge/historySerializer.d.ts.map +1 -0
- package/dist/providers/web-bridge/historySerializer.js +152 -0
- package/dist/providers/web-bridge/historySerializer.js.map +1 -0
- package/dist/providers/web-bridge/index.d.ts +10 -0
- package/dist/providers/web-bridge/index.d.ts.map +1 -0
- package/dist/providers/web-bridge/index.js +10 -0
- package/dist/providers/web-bridge/index.js.map +1 -0
- package/dist/providers/web-bridge/promptInjector.d.ts +63 -0
- package/dist/providers/web-bridge/promptInjector.d.ts.map +1 -0
- package/dist/providers/web-bridge/promptInjector.js +189 -0
- package/dist/providers/web-bridge/promptInjector.js.map +1 -0
- package/dist/providers/web-bridge/provider.d.ts +59 -0
- package/dist/providers/web-bridge/provider.d.ts.map +1 -0
- package/dist/providers/web-bridge/provider.js +176 -0
- package/dist/providers/web-bridge/provider.js.map +1 -0
- package/dist/providers/web-bridge/shared/BrowserSession.d.ts +51 -0
- package/dist/providers/web-bridge/shared/BrowserSession.d.ts.map +1 -0
- package/dist/providers/web-bridge/shared/BrowserSession.js +88 -0
- package/dist/providers/web-bridge/shared/BrowserSession.js.map +1 -0
- package/dist/providers/web-bridge/shared/WebBridgeAdapter.d.ts +97 -0
- package/dist/providers/web-bridge/shared/WebBridgeAdapter.d.ts.map +1 -0
- package/dist/providers/web-bridge/shared/WebBridgeAdapter.js +359 -0
- package/dist/providers/web-bridge/shared/WebBridgeAdapter.js.map +1 -0
- package/dist/providers/web-bridge/shared/observerScript.d.ts +41 -0
- package/dist/providers/web-bridge/shared/observerScript.d.ts.map +1 -0
- package/dist/providers/web-bridge/shared/observerScript.js +138 -0
- package/dist/providers/web-bridge/shared/observerScript.js.map +1 -0
- package/dist/providers/web-bridge/shared/types.d.ts +94 -0
- package/dist/providers/web-bridge/shared/types.d.ts.map +1 -0
- package/dist/providers/web-bridge/shared/types.js +25 -0
- package/dist/providers/web-bridge/shared/types.js.map +1 -0
- package/dist/providers/web-bridge/toolUseParser.d.ts +70 -0
- package/dist/providers/web-bridge/toolUseParser.d.ts.map +1 -0
- package/dist/providers/web-bridge/toolUseParser.js +360 -0
- package/dist/providers/web-bridge/toolUseParser.js.map +1 -0
- package/package.json +36 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,sBAAsB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,sBAAsB,CAAA"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AnthropicProvider — thin transparent wrapper around the official SDK.
|
|
3
|
+
*
|
|
4
|
+
* This is the simplest possible Provider: forward params verbatim, stream
|
|
5
|
+
* events back verbatim. It exists as:
|
|
6
|
+
* 1. A reference implementation showing the "happy path" with zero translation.
|
|
7
|
+
* 2. The baseline anyone with an ANTHROPIC_API_KEY can fall back to.
|
|
8
|
+
* 3. A correctness oracle for the other providers — if openai-compat or
|
|
9
|
+
* web-bridge ever diverge in behavior, this is what they should match.
|
|
10
|
+
*/
|
|
11
|
+
import type { Message, MessageCreateParamsStreaming, MessageStreamParams, RawMessageStreamEvent } from '@anthropic-ai/sdk/resources/messages/messages.js';
|
|
12
|
+
import type { Logger } from '@bbclaw/shared';
|
|
13
|
+
import { BaseProvider, type HealthCheckResult, type ProviderCapabilities } from '../types.js';
|
|
14
|
+
export interface AnthropicProviderOptions {
|
|
15
|
+
apiKey?: string;
|
|
16
|
+
/** Override the API endpoint, e.g. for a local proxy or self-hosted gateway. */
|
|
17
|
+
baseURL?: string;
|
|
18
|
+
/** Defaults to 2. */
|
|
19
|
+
maxRetries?: number;
|
|
20
|
+
/** Custom fetch (for tests / electron net). */
|
|
21
|
+
fetch?: typeof fetch;
|
|
22
|
+
/** Stable instance id. Defaults to 'anthropic'. */
|
|
23
|
+
id?: string;
|
|
24
|
+
displayName?: string;
|
|
25
|
+
/** Probe model — kept small/cheap to make healthCheck() fast. */
|
|
26
|
+
probeModel?: string;
|
|
27
|
+
/** Default model used when a caller doesn't specify one (e.g. `bbclaw ask`). */
|
|
28
|
+
defaultModel?: string;
|
|
29
|
+
logger?: Logger;
|
|
30
|
+
}
|
|
31
|
+
export declare class AnthropicProvider extends BaseProvider {
|
|
32
|
+
readonly kind: "anthropic";
|
|
33
|
+
readonly id: string;
|
|
34
|
+
readonly displayName: string;
|
|
35
|
+
readonly defaultModel: string;
|
|
36
|
+
readonly capabilities: ProviderCapabilities;
|
|
37
|
+
private readonly client;
|
|
38
|
+
private readonly probeModel;
|
|
39
|
+
constructor(opts?: AnthropicProviderOptions);
|
|
40
|
+
streamMessage(params: MessageStreamParams | MessageCreateParamsStreaming): Promise<AsyncIterable<RawMessageStreamEvent>>;
|
|
41
|
+
createMessage(params: MessageStreamParams): Promise<Message>;
|
|
42
|
+
healthCheck(): Promise<HealthCheckResult>;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/anthropic/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EACV,OAAO,EACP,4BAA4B,EAC5B,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,kDAAkD,CAAA;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EACL,YAAY,EACZ,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAC1B,MAAM,aAAa,CAAA;AAEpB,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,qBAAqB;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,+CAA+C;IAC/C,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IACpB,mDAAmD;IACnD,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gFAAgF;IAChF,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAID,qBAAa,iBAAkB,SAAQ,YAAY;IACjD,QAAQ,CAAC,IAAI,EAAG,WAAW,CAAS;IACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,SAAkB,YAAY,EAAE,MAAM,CAAA;IACtC,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAQ1C;IAED,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAW;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;gBAEvB,IAAI,GAAE,wBAA6B;IAczC,aAAa,CACjB,MAAM,EAAE,mBAAmB,GAAG,4BAA4B,GACzD,OAAO,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAC;IASjC,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;IAIrE,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC;CAmBhD"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AnthropicProvider — thin transparent wrapper around the official SDK.
|
|
3
|
+
*
|
|
4
|
+
* This is the simplest possible Provider: forward params verbatim, stream
|
|
5
|
+
* events back verbatim. It exists as:
|
|
6
|
+
* 1. A reference implementation showing the "happy path" with zero translation.
|
|
7
|
+
* 2. The baseline anyone with an ANTHROPIC_API_KEY can fall back to.
|
|
8
|
+
* 3. A correctness oracle for the other providers — if openai-compat or
|
|
9
|
+
* web-bridge ever diverge in behavior, this is what they should match.
|
|
10
|
+
*/
|
|
11
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
12
|
+
import { BaseProvider, } from '../types.js';
|
|
13
|
+
const DEFAULT_PROBE_MODEL = 'claude-3-5-haiku-latest';
|
|
14
|
+
export class AnthropicProvider extends BaseProvider {
|
|
15
|
+
kind = 'anthropic';
|
|
16
|
+
id;
|
|
17
|
+
displayName;
|
|
18
|
+
defaultModel;
|
|
19
|
+
capabilities = {
|
|
20
|
+
nativeTools: true,
|
|
21
|
+
promptCaching: true,
|
|
22
|
+
extendedThinking: true,
|
|
23
|
+
vision: true,
|
|
24
|
+
contextWindow: 200_000,
|
|
25
|
+
maxOutputTokens: 16_384,
|
|
26
|
+
streaming: true,
|
|
27
|
+
};
|
|
28
|
+
client;
|
|
29
|
+
probeModel;
|
|
30
|
+
constructor(opts = {}) {
|
|
31
|
+
super(opts.logger ?? { debug: () => { }, info: () => { }, warn: () => { }, error: () => { } });
|
|
32
|
+
this.id = opts.id ?? 'anthropic';
|
|
33
|
+
this.displayName = opts.displayName ?? 'Anthropic';
|
|
34
|
+
this.probeModel = opts.probeModel ?? DEFAULT_PROBE_MODEL;
|
|
35
|
+
this.defaultModel = opts.defaultModel ?? 'claude-3-5-sonnet-latest';
|
|
36
|
+
this.client = new Anthropic({
|
|
37
|
+
apiKey: opts.apiKey,
|
|
38
|
+
baseURL: opts.baseURL,
|
|
39
|
+
maxRetries: opts.maxRetries ?? 2,
|
|
40
|
+
fetch: opts.fetch,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
async streamMessage(params) {
|
|
44
|
+
// The SDK's `create` with stream:true returns Stream<RawMessageStreamEvent>,
|
|
45
|
+
// which already satisfies AsyncIterable.
|
|
46
|
+
return this.client.messages.create({
|
|
47
|
+
...params,
|
|
48
|
+
stream: true,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
async createMessage(params) {
|
|
52
|
+
return this.client.messages.create({ ...params, stream: false });
|
|
53
|
+
}
|
|
54
|
+
async healthCheck() {
|
|
55
|
+
const start = Date.now();
|
|
56
|
+
try {
|
|
57
|
+
// 1-token probe. Cheaper than countTokens since some endpoints don't
|
|
58
|
+
// implement countTokens at all.
|
|
59
|
+
await this.client.messages.create({
|
|
60
|
+
model: this.probeModel,
|
|
61
|
+
max_tokens: 1,
|
|
62
|
+
messages: [{ role: 'user', content: 'ping' }],
|
|
63
|
+
});
|
|
64
|
+
return { ok: true, latencyMs: Date.now() - start };
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
return {
|
|
68
|
+
ok: false,
|
|
69
|
+
latencyMs: Date.now() - start,
|
|
70
|
+
reason: e instanceof Error ? e.message : String(e),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/providers/anthropic/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Public surface of the providers subsystem. */
|
|
2
|
+
export * from './types.js';
|
|
3
|
+
export { ProviderRegistry } from './selector.js';
|
|
4
|
+
export { AnthropicProvider, type AnthropicProviderOptions } from './anthropic/index.js';
|
|
5
|
+
export { OpenAICompatProvider, type OpenAICompatProviderOptions, } from './openai-compat/index.js';
|
|
6
|
+
export { OPENAI_COMPAT_PRESETS, getPreset, type ProviderPreset, } from './openai-compat/presets.js';
|
|
7
|
+
export * from './web-bridge/index.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,iDAAiD;AAEjD,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,MAAM,sBAAsB,CAAA;AACvF,OAAO,EACL,oBAAoB,EACpB,KAAK,2BAA2B,GACjC,MAAM,0BAA0B,CAAA;AACjC,OAAO,EACL,qBAAqB,EACrB,SAAS,EACT,KAAK,cAAc,GACpB,MAAM,4BAA4B,CAAA;AACnC,cAAc,uBAAuB,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Public surface of the providers subsystem. */
|
|
2
|
+
export * from './types.js';
|
|
3
|
+
export { ProviderRegistry } from './selector.js';
|
|
4
|
+
export { AnthropicProvider } from './anthropic/index.js';
|
|
5
|
+
export { OpenAICompatProvider, } from './openai-compat/index.js';
|
|
6
|
+
export { OPENAI_COMPAT_PRESETS, getPreset, } from './openai-compat/presets.js';
|
|
7
|
+
export * from './web-bridge/index.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,iDAAiD;AAEjD,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAiC,MAAM,sBAAsB,CAAA;AACvF,OAAO,EACL,oBAAoB,GAErB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EACL,qBAAqB,EACrB,SAAS,GAEV,MAAM,4BAA4B,CAAA;AACnC,cAAc,uBAAuB,CAAA"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAICompatProvider — speaks the OpenAI chat/completions wire format.
|
|
3
|
+
*
|
|
4
|
+
* Compatible with: OpenAI, DeepSeek (official API), Groq, OpenRouter,
|
|
5
|
+
* Together, Mistral, Ollama, LM Studio, and any other server that implements
|
|
6
|
+
* the same schema.
|
|
7
|
+
*
|
|
8
|
+
* Translation responsibilities:
|
|
9
|
+
* - Anthropic-shaped request → OpenAI request: see requestTranslate.ts
|
|
10
|
+
* - OpenAI SSE response → Anthropic stream events: see streamAdapter.ts
|
|
11
|
+
* - Capability advertisement based on the preset (overridable per instance).
|
|
12
|
+
*/
|
|
13
|
+
import type { Message, MessageCreateParamsStreaming, MessageStreamParams, RawMessageStreamEvent } from '@anthropic-ai/sdk/resources/messages/messages.js';
|
|
14
|
+
import type { Logger } from '@bbclaw/shared';
|
|
15
|
+
import { BaseProvider, type HealthCheckResult, type ProviderCapabilities } from '../types.js';
|
|
16
|
+
export interface OpenAICompatProviderOptions {
|
|
17
|
+
id: string;
|
|
18
|
+
displayName?: string;
|
|
19
|
+
/** Either pass a preset id (resolved internally) or supply baseURL directly. */
|
|
20
|
+
preset?: string;
|
|
21
|
+
baseURL?: string;
|
|
22
|
+
/** API key. Some local backends (Ollama, LM Studio) don't require one. */
|
|
23
|
+
apiKey?: string;
|
|
24
|
+
/** Default model used when params.model is empty / unrecognized. */
|
|
25
|
+
defaultModel?: string;
|
|
26
|
+
/** Probe model used by healthCheck. Should be cheapest available. */
|
|
27
|
+
probeModel?: string;
|
|
28
|
+
/** Map an Anthropic model id to a provider-specific one. */
|
|
29
|
+
modelMap?: (anthropicModel: string) => string;
|
|
30
|
+
/** Provider-specific extra body fields. */
|
|
31
|
+
extraBody?: Record<string, unknown>;
|
|
32
|
+
/** Custom fetch (useful for testing or proxying). */
|
|
33
|
+
fetch?: typeof fetch;
|
|
34
|
+
/** Capability overrides — pass partial to override the preset defaults. */
|
|
35
|
+
capabilities?: Partial<ProviderCapabilities>;
|
|
36
|
+
/** Request timeout in ms (whole stream). Default 600s. */
|
|
37
|
+
timeoutMs?: number;
|
|
38
|
+
logger?: Logger;
|
|
39
|
+
}
|
|
40
|
+
export declare class OpenAICompatProvider extends BaseProvider {
|
|
41
|
+
readonly kind: "openai-compat";
|
|
42
|
+
readonly id: string;
|
|
43
|
+
readonly displayName: string;
|
|
44
|
+
readonly capabilities: ProviderCapabilities;
|
|
45
|
+
readonly defaultModel: string | undefined;
|
|
46
|
+
private readonly baseURL;
|
|
47
|
+
private readonly apiKey;
|
|
48
|
+
private readonly probeModel;
|
|
49
|
+
private readonly modelMap;
|
|
50
|
+
private readonly extraBody;
|
|
51
|
+
private readonly fetchImpl;
|
|
52
|
+
private readonly timeoutMs;
|
|
53
|
+
constructor(opts: OpenAICompatProviderOptions);
|
|
54
|
+
streamMessage(params: MessageStreamParams | MessageCreateParamsStreaming): Promise<AsyncIterable<RawMessageStreamEvent>>;
|
|
55
|
+
createMessage(params: MessageStreamParams): Promise<Message>;
|
|
56
|
+
healthCheck(): Promise<HealthCheckResult>;
|
|
57
|
+
private buildHeaders;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/openai-compat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,OAAO,EACP,4BAA4B,EAC5B,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,kDAAkD,CAAA;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EACL,YAAY,EAEZ,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAC1B,MAAM,aAAa,CAAA;AAMpB,MAAM,WAAW,2BAA2B;IAC1C,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,MAAM,CAAA;IAC7C,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACnC,qDAAqD;IACrD,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IACpB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAA;IAC5C,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAeD,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,QAAQ,CAAC,IAAI,EAAG,eAAe,CAAS;IACxC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAAA;IAC3C,SAAkB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;IAElD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAC3C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAC9D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqC;IAC/D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;gBAEtB,IAAI,EAAE,2BAA2B;IA+BvC,aAAa,CACjB,MAAM,EAAE,mBAAmB,GAAG,4BAA4B,GACzD,OAAO,CAAC,aAAa,CAAC,qBAAqB,CAAC,CAAC;IA4CjC,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;IAKrE,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC;IA0B/C,OAAO,CAAC,YAAY;CAQrB"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAICompatProvider — speaks the OpenAI chat/completions wire format.
|
|
3
|
+
*
|
|
4
|
+
* Compatible with: OpenAI, DeepSeek (official API), Groq, OpenRouter,
|
|
5
|
+
* Together, Mistral, Ollama, LM Studio, and any other server that implements
|
|
6
|
+
* the same schema.
|
|
7
|
+
*
|
|
8
|
+
* Translation responsibilities:
|
|
9
|
+
* - Anthropic-shaped request → OpenAI request: see requestTranslate.ts
|
|
10
|
+
* - OpenAI SSE response → Anthropic stream events: see streamAdapter.ts
|
|
11
|
+
* - Capability advertisement based on the preset (overridable per instance).
|
|
12
|
+
*/
|
|
13
|
+
import { BaseProvider, collectStreamToMessage, } from '../types.js';
|
|
14
|
+
import { getPreset } from './presets.js';
|
|
15
|
+
import { translateRequest } from './requestTranslate.js';
|
|
16
|
+
import { parseSSEStream, SSEParseError } from './sseParser.js';
|
|
17
|
+
import { adaptOpenAIStream } from './streamAdapter.js';
|
|
18
|
+
const DEFAULT_TIMEOUT_MS = 600_000;
|
|
19
|
+
/** Sensible defaults for the "modern OpenAI-compatible" baseline. */
|
|
20
|
+
const DEFAULT_OPENAI_COMPAT_CAPABILITIES = {
|
|
21
|
+
nativeTools: true,
|
|
22
|
+
promptCaching: false, // most providers don't honor cache_control on the wire
|
|
23
|
+
extendedThinking: false,
|
|
24
|
+
vision: true,
|
|
25
|
+
contextWindow: 128_000,
|
|
26
|
+
maxOutputTokens: 8_192,
|
|
27
|
+
streaming: true,
|
|
28
|
+
};
|
|
29
|
+
export class OpenAICompatProvider extends BaseProvider {
|
|
30
|
+
kind = 'openai-compat';
|
|
31
|
+
id;
|
|
32
|
+
displayName;
|
|
33
|
+
capabilities;
|
|
34
|
+
defaultModel;
|
|
35
|
+
baseURL;
|
|
36
|
+
apiKey;
|
|
37
|
+
probeModel;
|
|
38
|
+
modelMap;
|
|
39
|
+
extraBody;
|
|
40
|
+
fetchImpl;
|
|
41
|
+
timeoutMs;
|
|
42
|
+
constructor(opts) {
|
|
43
|
+
super(opts.logger ?? { debug: () => { }, info: () => { }, warn: () => { }, error: () => { } });
|
|
44
|
+
let preset;
|
|
45
|
+
if (opts.preset) {
|
|
46
|
+
preset = getPreset(opts.preset);
|
|
47
|
+
if (!preset)
|
|
48
|
+
throw new Error(`Unknown openai-compat preset: ${opts.preset}`);
|
|
49
|
+
}
|
|
50
|
+
const baseURL = (opts.baseURL ?? preset?.baseURL ?? '').replace(/\/+$/, '');
|
|
51
|
+
if (!baseURL) {
|
|
52
|
+
throw new Error('OpenAICompatProvider: baseURL is required (either directly or via preset).');
|
|
53
|
+
}
|
|
54
|
+
this.id = opts.id;
|
|
55
|
+
this.displayName = opts.displayName ?? preset?.label ?? opts.id;
|
|
56
|
+
this.baseURL = baseURL;
|
|
57
|
+
this.apiKey = opts.apiKey;
|
|
58
|
+
this.defaultModel = opts.defaultModel ?? preset?.defaultModel;
|
|
59
|
+
this.probeModel = opts.probeModel ?? preset?.defaultProbeModel ?? this.defaultModel;
|
|
60
|
+
this.modelMap = opts.modelMap;
|
|
61
|
+
this.extraBody = { ...preset?.extraBody, ...opts.extraBody };
|
|
62
|
+
this.fetchImpl = opts.fetch ?? globalThis.fetch;
|
|
63
|
+
this.timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
64
|
+
this.capabilities = {
|
|
65
|
+
...DEFAULT_OPENAI_COMPAT_CAPABILITIES,
|
|
66
|
+
...opts.capabilities,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
async streamMessage(params) {
|
|
70
|
+
const translateOpts = {
|
|
71
|
+
modelMap: this.modelMap ?? (this.defaultModel ? () => this.defaultModel : undefined),
|
|
72
|
+
includeUsage: true,
|
|
73
|
+
extraBody: this.extraBody,
|
|
74
|
+
};
|
|
75
|
+
const body = translateRequest(params, translateOpts);
|
|
76
|
+
const url = `${this.baseURL}/chat/completions`;
|
|
77
|
+
const ac = new AbortController();
|
|
78
|
+
const timeoutHandle = setTimeout(() => ac.abort(), this.timeoutMs);
|
|
79
|
+
let response;
|
|
80
|
+
try {
|
|
81
|
+
response = await this.fetchImpl(url, {
|
|
82
|
+
method: 'POST',
|
|
83
|
+
headers: this.buildHeaders(),
|
|
84
|
+
body: JSON.stringify(body),
|
|
85
|
+
signal: ac.signal,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
clearTimeout(timeoutHandle);
|
|
90
|
+
throw new Error(`OpenAICompatProvider: fetch failed (${e instanceof Error ? e.message : String(e)})`);
|
|
91
|
+
}
|
|
92
|
+
if (!response.ok) {
|
|
93
|
+
clearTimeout(timeoutHandle);
|
|
94
|
+
const detail = await response.text().catch(() => '');
|
|
95
|
+
throw new Error(`OpenAICompatProvider: HTTP ${response.status} — ${detail || response.statusText}`);
|
|
96
|
+
}
|
|
97
|
+
if (!response.body) {
|
|
98
|
+
clearTimeout(timeoutHandle);
|
|
99
|
+
throw new Error('OpenAICompatProvider: empty response body');
|
|
100
|
+
}
|
|
101
|
+
// Wrap the SSE → Anthropic adapter to clear the timeout when the stream ends.
|
|
102
|
+
const upstream = parseSSEStreamSafely(response.body, this.logger.warn.bind(this.logger));
|
|
103
|
+
const adapted = adaptOpenAIStream(upstream, { model: body.model });
|
|
104
|
+
return cleanupOnFinish(adapted, () => clearTimeout(timeoutHandle));
|
|
105
|
+
}
|
|
106
|
+
async createMessage(params) {
|
|
107
|
+
const stream = await this.streamMessage(params);
|
|
108
|
+
return collectStreamToMessage(stream);
|
|
109
|
+
}
|
|
110
|
+
async healthCheck() {
|
|
111
|
+
if (!this.probeModel) {
|
|
112
|
+
return { ok: false, reason: 'no probe model configured' };
|
|
113
|
+
}
|
|
114
|
+
const start = Date.now();
|
|
115
|
+
try {
|
|
116
|
+
const stream = await this.streamMessage({
|
|
117
|
+
model: this.probeModel,
|
|
118
|
+
max_tokens: 1,
|
|
119
|
+
messages: [{ role: 'user', content: 'ping' }],
|
|
120
|
+
});
|
|
121
|
+
// Drain at least one event to confirm the stream is alive.
|
|
122
|
+
for await (const _ev of stream) {
|
|
123
|
+
// first event is enough
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
return { ok: true, latencyMs: Date.now() - start };
|
|
127
|
+
}
|
|
128
|
+
catch (e) {
|
|
129
|
+
return {
|
|
130
|
+
ok: false,
|
|
131
|
+
latencyMs: Date.now() - start,
|
|
132
|
+
reason: e instanceof Error ? e.message : String(e),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
buildHeaders() {
|
|
137
|
+
const headers = {
|
|
138
|
+
'Content-Type': 'application/json',
|
|
139
|
+
Accept: 'text/event-stream',
|
|
140
|
+
};
|
|
141
|
+
if (this.apiKey)
|
|
142
|
+
headers.Authorization = `Bearer ${this.apiKey}`;
|
|
143
|
+
return headers;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Wrap parseSSEStream so that SSE-level parse errors don't abort the entire
|
|
148
|
+
* stream — we log and skip individual malformed events. (Hard errors like
|
|
149
|
+
* network drops still propagate.)
|
|
150
|
+
*/
|
|
151
|
+
async function* parseSSEStreamSafely(body, warn) {
|
|
152
|
+
try {
|
|
153
|
+
for await (const chunk of parseSSEStream(body)) {
|
|
154
|
+
yield chunk;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
catch (e) {
|
|
158
|
+
if (e instanceof SSEParseError) {
|
|
159
|
+
warn('[openai-compat] dropped malformed SSE event:', e.message, e.raw.slice(0, 200));
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
throw e;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/** Run a cleanup callback once the wrapped iterable is exhausted or aborted. */
|
|
166
|
+
async function* cleanupOnFinish(iter, cleanup) {
|
|
167
|
+
try {
|
|
168
|
+
for await (const item of iter)
|
|
169
|
+
yield item;
|
|
170
|
+
}
|
|
171
|
+
finally {
|
|
172
|
+
cleanup();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/providers/openai-compat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AASH,OAAO,EACL,YAAY,EACZ,sBAAsB,GAGvB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,SAAS,EAAuB,MAAM,cAAc,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAgC,MAAM,uBAAuB,CAAA;AACtF,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AA2BtD,MAAM,kBAAkB,GAAG,OAAO,CAAA;AAElC,qEAAqE;AACrE,MAAM,kCAAkC,GAAyB;IAC/D,WAAW,EAAE,IAAI;IACjB,aAAa,EAAE,KAAK,EAAE,uDAAuD;IAC7E,gBAAgB,EAAE,KAAK;IACvB,MAAM,EAAE,IAAI;IACZ,aAAa,EAAE,OAAO;IACtB,eAAe,EAAE,KAAK;IACtB,SAAS,EAAE,IAAI;CAChB,CAAA;AAED,MAAM,OAAO,oBAAqB,SAAQ,YAAY;IAC3C,IAAI,GAAG,eAAwB,CAAA;IAC/B,EAAE,CAAQ;IACV,WAAW,CAAQ;IACnB,YAAY,CAAsB;IACzB,YAAY,CAAoB;IAEjC,OAAO,CAAQ;IACf,MAAM,CAAoB;IAC1B,UAAU,CAAoB;IAC9B,QAAQ,CAAqC;IAC7C,SAAS,CAAqC;IAC9C,SAAS,CAAc;IACvB,SAAS,CAAQ;IAElC,YAAY,IAAiC;QAC3C,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC,CAAA;QAE1F,IAAI,MAAkC,CAAA;QACtC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YAC/B,IAAI,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAA;QAC9E,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,MAAM,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;QAC3E,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,4EAA4E,CAAC,CAAA;QAC/F,CAAC;QAED,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAA;QACjB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,MAAM,EAAE,KAAK,IAAI,IAAI,CAAC,EAAE,CAAA;QAC/D,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QACzB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,MAAM,EAAE,YAAY,CAAA;QAC7D,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,MAAM,EAAE,iBAAiB,IAAI,IAAI,CAAC,YAAY,CAAA;QACnF,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAA;QAC7B,IAAI,CAAC,SAAS,GAAG,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAA;QAC5D,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAA;QAC/C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,kBAAkB,CAAA;QAErD,IAAI,CAAC,YAAY,GAAG;YAClB,GAAG,kCAAkC;YACrC,GAAG,IAAI,CAAC,YAAY;SACrB,CAAA;IACH,CAAC;IAED,KAAK,CAAC,aAAa,CACjB,MAA0D;QAE1D,MAAM,aAAa,GAA4B;YAC7C,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,YAAa,CAAC,CAAC,CAAC,SAAS,CAAC;YACrF,YAAY,EAAE,IAAI;YAClB,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAA;QACD,MAAM,IAAI,GAAG,gBAAgB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;QACpD,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,mBAAmB,CAAA;QAE9C,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAA;QAChC,MAAM,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;QAElE,IAAI,QAAkB,CAAA;QACtB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE;gBACnC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE;gBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBAC1B,MAAM,EAAE,EAAE,CAAC,MAAM;aAClB,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,YAAY,CAAC,aAAa,CAAC,CAAA;YAC3B,MAAM,IAAI,KAAK,CACb,uCAAuC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CACrF,CAAA;QACH,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,YAAY,CAAC,aAAa,CAAC,CAAA;YAC3B,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;YACpD,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,CAAC,MAAM,MAAM,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA;QACrG,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnB,YAAY,CAAC,aAAa,CAAC,CAAA;YAC3B,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;QAC9D,CAAC;QAED,8EAA8E;QAC9E,MAAM,QAAQ,GAAG,oBAAoB,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;QACxF,MAAM,OAAO,GAAG,iBAAiB,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;QAElE,OAAO,eAAe,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAA;IACpE,CAAC;IAEQ,KAAK,CAAC,aAAa,CAAC,MAA2B;QACtD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;QAC/C,OAAO,sBAAsB,CAAC,MAAM,CAAC,CAAA;IACvC,CAAC;IAED,KAAK,CAAC,WAAW;QACf,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAA;QAC3D,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACxB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC;gBACtC,KAAK,EAAE,IAAI,CAAC,UAAU;gBACtB,UAAU,EAAE,CAAC;gBACb,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;aAC9C,CAAC,CAAA;YACF,2DAA2D;YAC3D,IAAI,KAAK,EAAE,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;gBAC/B,wBAAwB;gBACxB,MAAK;YACP,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE,CAAA;QACpD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;gBAC7B,MAAM,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;aACnD,CAAA;QACH,CAAC;IACH,CAAC;IAEO,YAAY;QAClB,MAAM,OAAO,GAA2B;YACtC,cAAc,EAAE,kBAAkB;YAClC,MAAM,EAAE,mBAAmB;SAC5B,CAAA;QACD,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,aAAa,GAAG,UAAU,IAAI,CAAC,MAAM,EAAE,CAAA;QAChE,OAAO,OAAO,CAAA;IAChB,CAAC;CACF;AAED;;;;GAIG;AACH,KAAK,SAAS,CAAC,CAAC,oBAAoB,CAClC,IAAgC,EAChC,IAAkC;IAElC,IAAI,CAAC;QACH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/C,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,YAAY,aAAa,EAAE,CAAC;YAC/B,IAAI,CAAC,8CAA8C,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;YACpF,OAAM;QACR,CAAC;QACD,MAAM,CAAC,CAAA;IACT,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,KAAK,SAAS,CAAC,CAAC,eAAe,CAC7B,IAAsB,EACtB,OAAmB;IAEnB,IAAI,CAAC;QACH,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,IAAI;YAAE,MAAM,IAAI,CAAA;IAC3C,CAAC;YAAS,CAAC;QACT,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Curated presets for known OpenAI-compatible providers. Users select by
|
|
3
|
+
* preset name in the UI; preset values just pre-fill defaults that the user
|
|
4
|
+
* can still override (apiKey is never preset).
|
|
5
|
+
*/
|
|
6
|
+
export interface ProviderPreset {
|
|
7
|
+
/** Stable identifier, used in config files and CLI flags. */
|
|
8
|
+
id: string;
|
|
9
|
+
/** UI label. */
|
|
10
|
+
label: string;
|
|
11
|
+
baseURL: string;
|
|
12
|
+
defaultModel?: string;
|
|
13
|
+
/** A "Haiku-class" small/cheap model used by healthCheck. */
|
|
14
|
+
defaultProbeModel?: string;
|
|
15
|
+
/** Free-form note shown next to the preset in UI. */
|
|
16
|
+
notes?: string;
|
|
17
|
+
/** Some providers wedge extra fields into the request body. */
|
|
18
|
+
extraBody?: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
export declare const OPENAI_COMPAT_PRESETS: ProviderPreset[];
|
|
21
|
+
export declare function getPreset(id: string): ProviderPreset | undefined;
|
|
22
|
+
//# sourceMappingURL=presets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../../src/providers/openai-compat/presets.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,EAAE,EAAE,MAAM,CAAA;IACV,gBAAgB;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,6DAA6D;IAC7D,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACpC;AAED,eAAO,MAAM,qBAAqB,EAAE,cAAc,EA+DjD,CAAA;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEhE"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Curated presets for known OpenAI-compatible providers. Users select by
|
|
3
|
+
* preset name in the UI; preset values just pre-fill defaults that the user
|
|
4
|
+
* can still override (apiKey is never preset).
|
|
5
|
+
*/
|
|
6
|
+
export const OPENAI_COMPAT_PRESETS = [
|
|
7
|
+
{
|
|
8
|
+
id: 'openai',
|
|
9
|
+
label: 'OpenAI',
|
|
10
|
+
baseURL: 'https://api.openai.com/v1',
|
|
11
|
+
defaultModel: 'gpt-4o',
|
|
12
|
+
defaultProbeModel: 'gpt-4o-mini',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
id: 'deepseek-api',
|
|
16
|
+
label: 'DeepSeek (official API)',
|
|
17
|
+
baseURL: 'https://api.deepseek.com/v1',
|
|
18
|
+
defaultModel: 'deepseek-chat',
|
|
19
|
+
defaultProbeModel: 'deepseek-chat',
|
|
20
|
+
notes: 'Cheap, compliant, pay-as-you-go.',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: 'groq',
|
|
24
|
+
label: 'Groq',
|
|
25
|
+
baseURL: 'https://api.groq.com/openai/v1',
|
|
26
|
+
defaultModel: 'llama-3.3-70b-versatile',
|
|
27
|
+
defaultProbeModel: 'llama-3.1-8b-instant',
|
|
28
|
+
notes: 'Very fast inference.',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: 'openrouter',
|
|
32
|
+
label: 'OpenRouter',
|
|
33
|
+
baseURL: 'https://openrouter.ai/api/v1',
|
|
34
|
+
defaultModel: 'anthropic/claude-3.5-sonnet',
|
|
35
|
+
notes: 'One key, many models.',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: 'together',
|
|
39
|
+
label: 'Together AI',
|
|
40
|
+
baseURL: 'https://api.together.xyz/v1',
|
|
41
|
+
defaultModel: 'meta-llama/Llama-3.3-70B-Instruct-Turbo',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: 'mistral',
|
|
45
|
+
label: 'Mistral',
|
|
46
|
+
baseURL: 'https://api.mistral.ai/v1',
|
|
47
|
+
defaultModel: 'mistral-large-latest',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: 'ollama',
|
|
51
|
+
label: 'Ollama (local)',
|
|
52
|
+
baseURL: 'http://localhost:11434/v1',
|
|
53
|
+
defaultModel: 'qwen2.5:7b',
|
|
54
|
+
defaultProbeModel: 'qwen2.5:7b',
|
|
55
|
+
notes: 'Fully offline. No API key required.',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'lm-studio',
|
|
59
|
+
label: 'LM Studio (local)',
|
|
60
|
+
baseURL: 'http://localhost:1234/v1',
|
|
61
|
+
notes: 'Fully offline.',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: 'custom',
|
|
65
|
+
label: 'Custom (OpenAI-compatible)',
|
|
66
|
+
baseURL: '',
|
|
67
|
+
notes: 'Bring your own base URL.',
|
|
68
|
+
},
|
|
69
|
+
];
|
|
70
|
+
export function getPreset(id) {
|
|
71
|
+
return OPENAI_COMPAT_PRESETS.find((p) => p.id === id);
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=presets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../../../src/providers/openai-compat/presets.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAiBH,MAAM,CAAC,MAAM,qBAAqB,GAAqB;IACrD;QACE,EAAE,EAAE,QAAQ;QACZ,KAAK,EAAE,QAAQ;QACf,OAAO,EAAE,2BAA2B;QACpC,YAAY,EAAE,QAAQ;QACtB,iBAAiB,EAAE,aAAa;KACjC;IACD;QACE,EAAE,EAAE,cAAc;QAClB,KAAK,EAAE,yBAAyB;QAChC,OAAO,EAAE,6BAA6B;QACtC,YAAY,EAAE,eAAe;QAC7B,iBAAiB,EAAE,eAAe;QAClC,KAAK,EAAE,kCAAkC;KAC1C;IACD;QACE,EAAE,EAAE,MAAM;QACV,KAAK,EAAE,MAAM;QACb,OAAO,EAAE,gCAAgC;QACzC,YAAY,EAAE,yBAAyB;QACvC,iBAAiB,EAAE,sBAAsB;QACzC,KAAK,EAAE,sBAAsB;KAC9B;IACD;QACE,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,YAAY;QACnB,OAAO,EAAE,8BAA8B;QACvC,YAAY,EAAE,6BAA6B;QAC3C,KAAK,EAAE,uBAAuB;KAC/B;IACD;QACE,EAAE,EAAE,UAAU;QACd,KAAK,EAAE,aAAa;QACpB,OAAO,EAAE,6BAA6B;QACtC,YAAY,EAAE,yCAAyC;KACxD;IACD;QACE,EAAE,EAAE,SAAS;QACb,KAAK,EAAE,SAAS;QAChB,OAAO,EAAE,2BAA2B;QACpC,YAAY,EAAE,sBAAsB;KACrC;IACD;QACE,EAAE,EAAE,QAAQ;QACZ,KAAK,EAAE,gBAAgB;QACvB,OAAO,EAAE,2BAA2B;QACpC,YAAY,EAAE,YAAY;QAC1B,iBAAiB,EAAE,YAAY;QAC/B,KAAK,EAAE,qCAAqC;KAC7C;IACD;QACE,EAAE,EAAE,WAAW;QACf,KAAK,EAAE,mBAAmB;QAC1B,OAAO,EAAE,0BAA0B;QACnC,KAAK,EAAE,gBAAgB;KACxB;IACD;QACE,EAAE,EAAE,QAAQ;QACZ,KAAK,EAAE,4BAA4B;QACnC,OAAO,EAAE,EAAE;QACX,KAAK,EAAE,0BAA0B;KAClC;CACF,CAAA;AAED,MAAM,UAAU,SAAS,CAAC,EAAU;IAClC,OAAO,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;AACvD,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Translate an Anthropic-style request to OpenAI chat/completions wire format.
|
|
3
|
+
*
|
|
4
|
+
* Mapping decisions documented inline. The big ones:
|
|
5
|
+
*
|
|
6
|
+
* - Anthropic `system` is a TextBlockParam[] (each block can carry cache_control
|
|
7
|
+
* hints). OpenAI has no equivalent; we concatenate the blocks with \n\n and
|
|
8
|
+
* drop cache hints. The caller can strip them upstream if it wants stronger
|
|
9
|
+
* guarantees (e.g. removing redundant boundary markers).
|
|
10
|
+
*
|
|
11
|
+
* - Anthropic tool_use/tool_result are content blocks inside a message.
|
|
12
|
+
* OpenAI splits them: assistant messages carry `tool_calls`, and tool
|
|
13
|
+
* results live in a separate `role: tool` message keyed by tool_call_id.
|
|
14
|
+
* We expand one Anthropic message into 1+N OpenAI messages as needed.
|
|
15
|
+
*
|
|
16
|
+
* - Anthropic input is structured JSON (already an object). OpenAI sends it
|
|
17
|
+
* serialized as a string in `function.arguments`. We JSON.stringify on the
|
|
18
|
+
* way out and JSON.parse on the way back (in streamAdapter).
|
|
19
|
+
*
|
|
20
|
+
* - Thinking blocks are model-private CoT — they have no business in the
|
|
21
|
+
* request side, so we drop them silently. (Some providers like DeepSeek-R1
|
|
22
|
+
* echo reasoning back via `reasoning_content`; we'd render that on the
|
|
23
|
+
* response side, not the request side.)
|
|
24
|
+
*
|
|
25
|
+
* - Images: Anthropic accepts base64 `source` or URL; OpenAI accepts URL or
|
|
26
|
+
* base64 data URI. We convert base64 sources into `data:` URIs.
|
|
27
|
+
*/
|
|
28
|
+
import type { MessageCreateParamsBase } from '@anthropic-ai/sdk/resources/messages/messages.js';
|
|
29
|
+
import type { OpenAIRequest } from './types.js';
|
|
30
|
+
export interface TranslateRequestOptions {
|
|
31
|
+
/** Override or map the Anthropic model name to the provider's model name. */
|
|
32
|
+
modelMap?: (anthropicModel: string) => string;
|
|
33
|
+
/** Inject `stream_options: { include_usage: true }`. Default true. */
|
|
34
|
+
includeUsage?: boolean;
|
|
35
|
+
/** Extra fields to merge into the final request (provider-specific). */
|
|
36
|
+
extraBody?: Record<string, unknown>;
|
|
37
|
+
}
|
|
38
|
+
export declare function translateRequest(params: MessageCreateParamsBase, opts?: TranslateRequestOptions): OpenAIRequest;
|
|
39
|
+
//# sourceMappingURL=requestTranslate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requestTranslate.d.ts","sourceRoot":"","sources":["../../../src/providers/openai-compat/requestTranslate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAGV,uBAAuB,EAOxB,MAAM,kDAAkD,CAAA;AACzD,OAAO,KAAK,EAIV,aAAa,EAGd,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,uBAAuB;IACtC,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,MAAM,CAAA;IAC7C,sEAAsE;IACtE,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACpC;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,uBAAuB,EAC/B,IAAI,GAAE,uBAA4B,GACjC,aAAa,CAyCf"}
|