@prysm-ai/llm 0.3.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/CHANGELOG.md +47 -0
- package/dist/base.d.ts +17 -0
- package/dist/base.d.ts.map +1 -0
- package/dist/base.js +26 -0
- package/dist/base.js.map +1 -0
- package/dist/constants.d.ts +12 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +12 -0
- package/dist/constants.js.map +1 -0
- package/dist/content.d.ts +18 -0
- package/dist/content.d.ts.map +1 -0
- package/dist/content.js +18 -0
- package/dist/content.js.map +1 -0
- package/dist/factory/createModel.d.ts +38 -0
- package/dist/factory/createModel.d.ts.map +1 -0
- package/dist/factory/createModel.js +44 -0
- package/dist/factory/createModel.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/provider/anthropic.d.ts +45 -0
- package/dist/provider/anthropic.d.ts.map +1 -0
- package/dist/provider/anthropic.js +290 -0
- package/dist/provider/anthropic.js.map +1 -0
- package/dist/provider/openai.d.ts +84 -0
- package/dist/provider/openai.d.ts.map +1 -0
- package/dist/provider/openai.js +234 -0
- package/dist/provider/openai.js.map +1 -0
- package/dist/provider/proxy.d.ts +53 -0
- package/dist/provider/proxy.d.ts.map +1 -0
- package/dist/provider/proxy.js +113 -0
- package/dist/provider/proxy.js.map +1 -0
- package/dist/router.d.ts +21 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +86 -0
- package/dist/router.js.map +1 -0
- package/dist/types.d.ts +71 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +46 -0
- package/src/base.ts +43 -0
- package/src/constants.ts +13 -0
- package/src/content.ts +36 -0
- package/src/factory/createModel.ts +64 -0
- package/src/index.ts +9 -0
- package/src/provider/anthropic.ts +359 -0
- package/src/provider/openai.ts +280 -0
- package/src/provider/proxy.ts +171 -0
- package/src/router.ts +113 -0
- package/src/types.ts +77 -0
- package/tsconfig.json +9 -0
- package/vitest.config.ts +14 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# @prysm-ai/llm
|
|
2
|
+
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 发布 0.2.0 版本
|
|
8
|
+
|
|
9
|
+
核心变更:
|
|
10
|
+
- 重构 @prysm-ai/core 为统一入口包,导出所有子包
|
|
11
|
+
- @prysm-ai/agent 新增 types.ts 定义核心类型
|
|
12
|
+
- 删除 core 包自有类型定义,改为纯 re-export
|
|
13
|
+
- 新增 createModel 工厂函数
|
|
14
|
+
- 支持流式输出 chatStream
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Updated dependencies
|
|
19
|
+
- @prysm-ai/core@0.3.0
|
|
20
|
+
- @prysm-ai/utils@0.3.0
|
|
21
|
+
|
|
22
|
+
## 0.2.0
|
|
23
|
+
|
|
24
|
+
### Minor Changes
|
|
25
|
+
|
|
26
|
+
- 发布第一个版本,包含核心功能:
|
|
27
|
+
- core: 核心抽象类(Agent、Context、Storage 等)
|
|
28
|
+
- llm: LLM 抽象层,支持 OpenAI/Anthropic 提供商,新增 createModel 工厂函数
|
|
29
|
+
- agent: Agent 框架核心实现
|
|
30
|
+
- tools: 工具系统
|
|
31
|
+
- memory: 记忆系统
|
|
32
|
+
- prompts: 提示词模板管理
|
|
33
|
+
- logger: 日志系统
|
|
34
|
+
- metrics: 指标系统
|
|
35
|
+
- tracing: 链路追踪
|
|
36
|
+
- enterprise: 企业级功能
|
|
37
|
+
- mcp: Model Context Protocol
|
|
38
|
+
- skills: 技能系统
|
|
39
|
+
- multiagent: 多 Agent 协作
|
|
40
|
+
- rag: 检索增强生成
|
|
41
|
+
- utils: 工具函数库
|
|
42
|
+
|
|
43
|
+
### Patch Changes
|
|
44
|
+
|
|
45
|
+
- Updated dependencies
|
|
46
|
+
- @prysm-ai/core@0.2.0
|
|
47
|
+
- @prysm-ai/utils@0.2.0
|
package/dist/base.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ChatMessage, LLMResponse, LLMRequestOptions, ModelInfo, EmbedRequest, EmbedResponse, LLMProvider } from './types';
|
|
2
|
+
import type { StreamingOptions } from './provider/openai';
|
|
3
|
+
export declare abstract class BaseLLMProvider {
|
|
4
|
+
abstract readonly provider: LLMProvider;
|
|
5
|
+
abstract readonly defaultModel: string;
|
|
6
|
+
protected apiKey: string | undefined;
|
|
7
|
+
protected baseUrl: string | undefined;
|
|
8
|
+
constructor(apiKey?: string, baseUrl?: string);
|
|
9
|
+
abstract chat(messages: ChatMessage[], options?: LLMRequestOptions): Promise<LLMResponse>;
|
|
10
|
+
abstract chatStream(messages: ChatMessage[], options: StreamingOptions): Promise<void>;
|
|
11
|
+
abstract listModels(): Promise<ModelInfo[]>;
|
|
12
|
+
abstract validateKey(): Promise<boolean>;
|
|
13
|
+
embed(_request: EmbedRequest): Promise<EmbedResponse>;
|
|
14
|
+
getProvider(): LLMProvider;
|
|
15
|
+
protected applyRequestOptions(requestBody: Record<string, unknown>, options: LLMRequestOptions): void;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAChI,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,8BAAsB,eAAe;IACnC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IACxC,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAEvC,SAAS,CAAC,MAAM,EAAG,MAAM,GAAG,SAAS,CAAC;IACtC,SAAS,CAAC,OAAO,EAAG,MAAM,GAAG,SAAS,CAAC;gBAE3B,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;IAK7C,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC;IAEzF,QAAQ,CAAC,UAAU,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAEtF,QAAQ,CAAC,UAAU,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAE3C,QAAQ,CAAC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAElC,KAAK,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;IAI3D,WAAW,IAAI,WAAW;IAI1B,SAAS,CAAC,mBAAmB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI;CAWtG"}
|
package/dist/base.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export class BaseLLMProvider {
|
|
2
|
+
apiKey;
|
|
3
|
+
baseUrl;
|
|
4
|
+
constructor(apiKey, baseUrl) {
|
|
5
|
+
this.apiKey = apiKey;
|
|
6
|
+
this.baseUrl = baseUrl;
|
|
7
|
+
}
|
|
8
|
+
async embed(_request) {
|
|
9
|
+
throw new Error('Embed not supported by this provider');
|
|
10
|
+
}
|
|
11
|
+
getProvider() {
|
|
12
|
+
return this.provider;
|
|
13
|
+
}
|
|
14
|
+
applyRequestOptions(requestBody, options) {
|
|
15
|
+
if (options.temperature !== undefined) {
|
|
16
|
+
requestBody.temperature = options.temperature;
|
|
17
|
+
}
|
|
18
|
+
if (options.maxTokens !== undefined) {
|
|
19
|
+
requestBody.max_tokens = options.maxTokens;
|
|
20
|
+
}
|
|
21
|
+
if (options.stop !== undefined) {
|
|
22
|
+
requestBody.stop = options.stop;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=base.js.map
|
package/dist/base.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":"AAGA,MAAM,OAAgB,eAAe;IAIzB,MAAM,CAAsB;IAC5B,OAAO,CAAsB;IAEvC,YAAY,MAAe,EAAE,OAAgB;QAC3C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAUD,KAAK,CAAC,KAAK,CAAC,QAAsB;QAChC,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAES,mBAAmB,CAAC,WAAoC,EAAE,OAA0B;QAC5F,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACtC,WAAW,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QAChD,CAAC;QACD,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACpC,WAAW,CAAC,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC;QAC7C,CAAC;QACD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC/B,WAAW,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QAClC,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const MessageRole: {
|
|
2
|
+
readonly System: "system";
|
|
3
|
+
readonly User: "user";
|
|
4
|
+
readonly Assistant: "assistant";
|
|
5
|
+
readonly Tool: "tool";
|
|
6
|
+
};
|
|
7
|
+
export type MessageRole = (typeof MessageRole)[keyof typeof MessageRole];
|
|
8
|
+
export declare enum LLMProviderType {
|
|
9
|
+
OpenAI = "openai",
|
|
10
|
+
Anthropic = "anthropic"
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW;;;;;CAKd,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAEzE,oBAAY,eAAe;IACzB,MAAM,WAAW;IACjB,SAAS,cAAc;CACxB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const MessageRole = {
|
|
2
|
+
System: 'system',
|
|
3
|
+
User: 'user',
|
|
4
|
+
Assistant: 'assistant',
|
|
5
|
+
Tool: 'tool',
|
|
6
|
+
};
|
|
7
|
+
export var LLMProviderType;
|
|
8
|
+
(function (LLMProviderType) {
|
|
9
|
+
LLMProviderType["OpenAI"] = "openai";
|
|
10
|
+
LLMProviderType["Anthropic"] = "anthropic";
|
|
11
|
+
})(LLMProviderType || (LLMProviderType = {}));
|
|
12
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;IACZ,SAAS,EAAE,WAAW;IACtB,IAAI,EAAE,MAAM;CACJ,CAAC;AAIX,MAAM,CAAN,IAAY,eAGX;AAHD,WAAY,eAAe;IACzB,oCAAiB,CAAA;IACjB,0CAAuB,CAAA;AACzB,CAAC,EAHW,eAAe,KAAf,eAAe,QAG1B"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type MessageContent = string | MessagePart[];
|
|
2
|
+
export interface TextPart {
|
|
3
|
+
type: 'text';
|
|
4
|
+
text: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ImagePart {
|
|
7
|
+
type: 'image_url';
|
|
8
|
+
image_url: {
|
|
9
|
+
url: string;
|
|
10
|
+
detail?: 'low' | 'high' | 'auto';
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export type MessagePart = TextPart | ImagePart;
|
|
14
|
+
export declare function isTextPart(part: MessagePart): part is TextPart;
|
|
15
|
+
export declare function isImagePart(part: MessagePart): part is ImagePart;
|
|
16
|
+
export declare function hasImages(content: MessageContent): boolean;
|
|
17
|
+
export declare function getTextContent(content: MessageContent): string;
|
|
18
|
+
//# sourceMappingURL=content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,WAAW,EAAE,CAAC;AAEpD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE;QACT,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;KAClC,CAAC;CACH;AAED,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE/C,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,IAAI,QAAQ,CAE9D;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,IAAI,SAAS,CAEhE;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAG1D;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAG9D"}
|
package/dist/content.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Message content types for multimodal support
|
|
2
|
+
export function isTextPart(part) {
|
|
3
|
+
return part.type === 'text';
|
|
4
|
+
}
|
|
5
|
+
export function isImagePart(part) {
|
|
6
|
+
return part.type === 'image_url';
|
|
7
|
+
}
|
|
8
|
+
export function hasImages(content) {
|
|
9
|
+
if (typeof content === 'string')
|
|
10
|
+
return false;
|
|
11
|
+
return content.some(part => part.type === 'image_url');
|
|
12
|
+
}
|
|
13
|
+
export function getTextContent(content) {
|
|
14
|
+
if (typeof content === 'string')
|
|
15
|
+
return content;
|
|
16
|
+
return content.filter(isTextPart).map(p => p.text).join('\n');
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAmB/C,MAAM,UAAU,UAAU,CAAC,IAAiB;IAC1C,OAAO,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAiB;IAC3C,OAAO,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAuB;IAC/C,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC9C,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAuB;IACpD,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,OAAO,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { BaseLLMProvider } from '../base';
|
|
2
|
+
/**
|
|
3
|
+
* createModel 配置选项
|
|
4
|
+
*/
|
|
5
|
+
export interface CreateModelOptions {
|
|
6
|
+
/** 接口类型: openai | anthropic */
|
|
7
|
+
type: 'openai' | 'anthropic';
|
|
8
|
+
/** 模型接口地址 */
|
|
9
|
+
baseUrl: string;
|
|
10
|
+
/** API 密钥 */
|
|
11
|
+
apiKey: string;
|
|
12
|
+
/** 模型名称 */
|
|
13
|
+
model: string;
|
|
14
|
+
/** 可选: API 路径 */
|
|
15
|
+
apiPath?: string;
|
|
16
|
+
/** 可选: 超时时间(毫秒) */
|
|
17
|
+
timeoutMs?: number;
|
|
18
|
+
/** 可选: 默认 temperature */
|
|
19
|
+
temperature?: number;
|
|
20
|
+
/** 可选: 默认 maxTokens */
|
|
21
|
+
maxTokens?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 创建模型实例工厂函数
|
|
25
|
+
* 根据 type 创建对应的 Provider 实例,返回可直接使用的模型
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* const model = createModel({
|
|
29
|
+
* type: 'openai',
|
|
30
|
+
* baseUrl: 'https://api.moonshot.cn/v1',
|
|
31
|
+
* apiKey: process.env.MOONSHOT_API_KEY,
|
|
32
|
+
* model: 'kimi-k2.6',
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* const response = await model.chat(messages);
|
|
36
|
+
*/
|
|
37
|
+
export declare function createModel(options: CreateModelOptions): BaseLLMProvider;
|
|
38
|
+
//# sourceMappingURL=createModel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createModel.d.ts","sourceRoot":"","sources":["../../src/factory/createModel.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,+BAA+B;IAC/B,IAAI,EAAE,QAAQ,GAAG,WAAW,CAAC;IAC7B,aAAa;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW;IACX,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,eAAe,CAuBxE"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { OpenAIProvider } from '../provider/openai';
|
|
2
|
+
import { AnthropicProvider } from '../provider/anthropic';
|
|
3
|
+
/**
|
|
4
|
+
* 创建模型实例工厂函数
|
|
5
|
+
* 根据 type 创建对应的 Provider 实例,返回可直接使用的模型
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* const model = createModel({
|
|
9
|
+
* type: 'openai',
|
|
10
|
+
* baseUrl: 'https://api.moonshot.cn/v1',
|
|
11
|
+
* apiKey: process.env.MOONSHOT_API_KEY,
|
|
12
|
+
* model: 'kimi-k2.6',
|
|
13
|
+
* });
|
|
14
|
+
*
|
|
15
|
+
* const response = await model.chat(messages);
|
|
16
|
+
*/
|
|
17
|
+
export function createModel(options) {
|
|
18
|
+
const { type, baseUrl, apiKey, apiPath, timeoutMs } = options;
|
|
19
|
+
switch (type) {
|
|
20
|
+
case 'openai': {
|
|
21
|
+
const config = { apiKey };
|
|
22
|
+
if (baseUrl)
|
|
23
|
+
config.baseUrl = baseUrl;
|
|
24
|
+
if (apiPath)
|
|
25
|
+
config.apiPath = apiPath;
|
|
26
|
+
if (timeoutMs)
|
|
27
|
+
config.timeoutMs = timeoutMs;
|
|
28
|
+
return new OpenAIProvider(config);
|
|
29
|
+
}
|
|
30
|
+
case 'anthropic': {
|
|
31
|
+
const config = { apiKey };
|
|
32
|
+
if (baseUrl)
|
|
33
|
+
config.baseUrl = baseUrl;
|
|
34
|
+
if (apiPath)
|
|
35
|
+
config.apiPath = apiPath;
|
|
36
|
+
if (timeoutMs)
|
|
37
|
+
config.timeoutMs = timeoutMs;
|
|
38
|
+
return new AnthropicProvider(config);
|
|
39
|
+
}
|
|
40
|
+
default:
|
|
41
|
+
throw new Error(`Unsupported provider type: ${type}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=createModel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createModel.js","sourceRoot":"","sources":["../../src/factory/createModel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAwB,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAA2B,MAAM,uBAAuB,CAAC;AAyBnF;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,WAAW,CAAC,OAA2B;IACrD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAE9D,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,MAAM,GAAyB,EAAE,MAAM,EAAE,CAAC;YAChD,IAAI,OAAO;gBAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;YACtC,IAAI,OAAO;gBAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;YACtC,IAAI,SAAS;gBAAE,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;YAC5C,OAAO,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;QACpC,CAAC;QAED,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,MAAM,GAA4B,EAAE,MAAM,EAAE,CAAC;YACnD,IAAI,OAAO;gBAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;YACtC,IAAI,OAAO;gBAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;YACtC,IAAI,SAAS;gBAAE,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;YAC5C,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC;QAED;YACE,MAAM,IAAI,KAAK,CAAC,8BAA8B,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './types';
|
|
2
|
+
export * from './base';
|
|
3
|
+
export * from './provider/openai';
|
|
4
|
+
export * from './provider/anthropic';
|
|
5
|
+
export * from './provider/proxy';
|
|
6
|
+
export * from './router';
|
|
7
|
+
export * from './content';
|
|
8
|
+
export * from './constants';
|
|
9
|
+
export * from './factory/createModel';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './types';
|
|
2
|
+
export * from './base';
|
|
3
|
+
export * from './provider/openai';
|
|
4
|
+
export * from './provider/anthropic';
|
|
5
|
+
export * from './provider/proxy';
|
|
6
|
+
export * from './router';
|
|
7
|
+
export * from './content';
|
|
8
|
+
export * from './constants';
|
|
9
|
+
export * from './factory/createModel';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ChatMessage, LLMResponse, LLMRequestOptions, ModelInfo } from '../types';
|
|
2
|
+
import { BaseLLMProvider } from '../base';
|
|
3
|
+
export interface AnthropicStreamingOptions extends Omit<LLMRequestOptions, 'stream'> {
|
|
4
|
+
stream: true;
|
|
5
|
+
onChunk?: (chunk: string) => void;
|
|
6
|
+
onComplete?: (fullContent: string) => void;
|
|
7
|
+
onError?: (error: Error) => void;
|
|
8
|
+
}
|
|
9
|
+
export interface AnthropicProviderConfig {
|
|
10
|
+
apiKey: string;
|
|
11
|
+
baseUrl?: string;
|
|
12
|
+
apiPath?: string;
|
|
13
|
+
timeoutMs?: number;
|
|
14
|
+
}
|
|
15
|
+
export declare class AnthropicProvider extends BaseLLMProvider {
|
|
16
|
+
readonly provider: 'anthropic';
|
|
17
|
+
readonly defaultModel = "claude-3-5-sonnet-20241022";
|
|
18
|
+
private authToken;
|
|
19
|
+
private timeoutMs;
|
|
20
|
+
private apiUrl;
|
|
21
|
+
constructor(config: AnthropicProviderConfig);
|
|
22
|
+
chat(messages: ChatMessage[], options?: LLMRequestOptions): Promise<LLMResponse>;
|
|
23
|
+
chatStream(messages: ChatMessage[], options: AnthropicStreamingOptions): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* 将消息内容规范化为 Anthropic 格式
|
|
26
|
+
* @param content - MessageContent 类型: string | MessagePart[]
|
|
27
|
+
* - string: 纯文本内容,直接返回
|
|
28
|
+
* - MessagePart[]: 文本/图片部分数组,转换为 Anthropic 内容块
|
|
29
|
+
* @returns 纯文本返回 string,多模态内容返回 AnthropicContent[]
|
|
30
|
+
*/
|
|
31
|
+
private normalizeContent;
|
|
32
|
+
/**
|
|
33
|
+
* 将单个消息部分规范化为 Anthropic 内容块
|
|
34
|
+
* @param part - MessagePart 类型: TextPart | ImagePart
|
|
35
|
+
* - TextPart: { type: 'text', text: string }
|
|
36
|
+
* - ImagePart: { type: 'image_url', image_url: { url: string, detail?: 'low'|'high'|'auto' } }
|
|
37
|
+
* @returns AnthropicContent: { type: 'text', text: string } | { type: 'image', source: {...} }
|
|
38
|
+
*/
|
|
39
|
+
private normalizePart;
|
|
40
|
+
private getTextContent;
|
|
41
|
+
protected applyRequestOptions(requestBody: Record<string, unknown>, options: LLMRequestOptions): void;
|
|
42
|
+
listModels(): Promise<ModelInfo[]>;
|
|
43
|
+
validateKey(): Promise<boolean>;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=anthropic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/provider/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEvF,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAI1C,MAAM,WAAW,yBAA0B,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IAClF,MAAM,EAAE,IAAI,CAAC;IACb,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,UAAU,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkBD,qBAAa,iBAAkB,SAAQ,eAAe;IACpD,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAe;IAC7C,SAAkB,YAAY,gCAAgC;IAE9D,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,uBAAuB;IASrC,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,OAAO,GAAE,iBAAgD,GAAG,OAAO,CAAC,WAAW,CAAC;IAkF9G,UAAU,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC;IAgG5F;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB;IASxB;;;;;;OAMG;IACH,OAAO,CAAC,aAAa;IAqCrB,OAAO,CAAC,cAAc;cAOH,mBAAmB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAqBxG,UAAU,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAQlC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAqBtC"}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { BaseLLMProvider } from '../base';
|
|
2
|
+
import { isTextPart } from '../content';
|
|
3
|
+
import { MessageRole } from '../constants';
|
|
4
|
+
export class AnthropicProvider extends BaseLLMProvider {
|
|
5
|
+
provider = 'anthropic';
|
|
6
|
+
defaultModel = 'claude-3-5-sonnet-20241022';
|
|
7
|
+
authToken;
|
|
8
|
+
timeoutMs;
|
|
9
|
+
apiUrl;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
super(config.apiKey, config.baseUrl);
|
|
12
|
+
this.authToken = config.apiKey;
|
|
13
|
+
this.timeoutMs = config.timeoutMs ?? 60000;
|
|
14
|
+
const base = config.baseUrl ?? 'https://api.anthropic.com';
|
|
15
|
+
const path = config.apiPath ?? '/v1/messages';
|
|
16
|
+
this.apiUrl = `${base}${path}`;
|
|
17
|
+
}
|
|
18
|
+
async chat(messages, options = { model: this.defaultModel }) {
|
|
19
|
+
const systemMessage = messages.find(m => m.role === MessageRole.System);
|
|
20
|
+
const conversationMessages = messages.filter(m => m.role !== MessageRole.System);
|
|
21
|
+
const requestBody = {
|
|
22
|
+
model: options.model,
|
|
23
|
+
messages: conversationMessages.map(msg => ({
|
|
24
|
+
role: msg.role,
|
|
25
|
+
content: this.normalizeContent(msg.content),
|
|
26
|
+
})),
|
|
27
|
+
};
|
|
28
|
+
if (systemMessage) {
|
|
29
|
+
requestBody.system = this.getTextContent(systemMessage.content);
|
|
30
|
+
}
|
|
31
|
+
this.applyRequestOptions(requestBody, options);
|
|
32
|
+
const controller = new AbortController();
|
|
33
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
34
|
+
try {
|
|
35
|
+
const response = await fetch(this.apiUrl, {
|
|
36
|
+
method: 'POST',
|
|
37
|
+
headers: {
|
|
38
|
+
'Content-Type': 'application/json',
|
|
39
|
+
'x-api-key': this.authToken,
|
|
40
|
+
'anthropic-version': '2023-06-01',
|
|
41
|
+
'anthropic-dangerous-direct-browser-access': 'true',
|
|
42
|
+
},
|
|
43
|
+
body: JSON.stringify(requestBody),
|
|
44
|
+
signal: controller.signal,
|
|
45
|
+
});
|
|
46
|
+
clearTimeout(timeoutId);
|
|
47
|
+
if (!response.ok) {
|
|
48
|
+
const error = await response.text();
|
|
49
|
+
throw new Error(`Anthropic API error: ${response.status} - ${error}`);
|
|
50
|
+
}
|
|
51
|
+
const data = await response.json();
|
|
52
|
+
const responseMessage = data.content.find(c => c.type === 'text');
|
|
53
|
+
const toolCalls = data.content
|
|
54
|
+
.filter(c => c.type === 'tool_use')
|
|
55
|
+
.map(c => ({
|
|
56
|
+
id: c.id ?? '',
|
|
57
|
+
type: 'function',
|
|
58
|
+
function: {
|
|
59
|
+
name: c.name ?? '',
|
|
60
|
+
arguments: JSON.stringify(c.input ?? {}),
|
|
61
|
+
},
|
|
62
|
+
}));
|
|
63
|
+
const result = {
|
|
64
|
+
id: data.id,
|
|
65
|
+
model: data.model,
|
|
66
|
+
role: 'assistant',
|
|
67
|
+
content: responseMessage?.text ?? '',
|
|
68
|
+
finishReason: mapFinishReason(data.stop_reason),
|
|
69
|
+
usage: {
|
|
70
|
+
promptTokens: data.usage.input_tokens,
|
|
71
|
+
completionTokens: data.usage.output_tokens,
|
|
72
|
+
totalTokens: data.usage.input_tokens + data.usage.output_tokens,
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
if (toolCalls.length > 0) {
|
|
76
|
+
result.toolCalls = toolCalls;
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
clearTimeout(timeoutId);
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async chatStream(messages, options) {
|
|
86
|
+
const systemMessage = messages.find(m => m.role === MessageRole.System);
|
|
87
|
+
const conversationMessages = messages.filter(m => m.role !== MessageRole.System);
|
|
88
|
+
const requestBody = {
|
|
89
|
+
model: options.model,
|
|
90
|
+
messages: conversationMessages.map(msg => ({
|
|
91
|
+
role: msg.role,
|
|
92
|
+
content: this.normalizeContent(msg.content),
|
|
93
|
+
})),
|
|
94
|
+
stream: true,
|
|
95
|
+
};
|
|
96
|
+
if (systemMessage) {
|
|
97
|
+
requestBody.system = this.getTextContent(systemMessage.content);
|
|
98
|
+
}
|
|
99
|
+
if (options.temperature !== undefined) {
|
|
100
|
+
requestBody.temperature = options.temperature;
|
|
101
|
+
}
|
|
102
|
+
if (options.maxTokens !== undefined) {
|
|
103
|
+
requestBody.max_tokens = options.maxTokens;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
requestBody.max_tokens = 4096;
|
|
107
|
+
}
|
|
108
|
+
this.applyRequestOptions(requestBody, options);
|
|
109
|
+
const controller = new AbortController();
|
|
110
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
111
|
+
try {
|
|
112
|
+
const response = await fetch(this.apiUrl, {
|
|
113
|
+
method: 'POST',
|
|
114
|
+
headers: {
|
|
115
|
+
'Content-Type': 'application/json',
|
|
116
|
+
'x-api-key': this.authToken,
|
|
117
|
+
'anthropic-version': '2023-06-01',
|
|
118
|
+
'anthropic-dangerous-direct-browser-access': 'true',
|
|
119
|
+
},
|
|
120
|
+
body: JSON.stringify(requestBody),
|
|
121
|
+
signal: controller.signal,
|
|
122
|
+
});
|
|
123
|
+
clearTimeout(timeoutId);
|
|
124
|
+
if (!response.ok) {
|
|
125
|
+
const error = await response.text();
|
|
126
|
+
throw new Error(`Anthropic API error: ${response.status} - ${error}`);
|
|
127
|
+
}
|
|
128
|
+
// SSE streaming response
|
|
129
|
+
const reader = response.body?.getReader();
|
|
130
|
+
if (!reader) {
|
|
131
|
+
throw new Error('No response body');
|
|
132
|
+
}
|
|
133
|
+
const decoder = new TextDecoder();
|
|
134
|
+
let fullContent = '';
|
|
135
|
+
let buffer = '';
|
|
136
|
+
while (true) {
|
|
137
|
+
const { done, value } = await reader.read();
|
|
138
|
+
if (done)
|
|
139
|
+
break;
|
|
140
|
+
buffer += decoder.decode(value, { stream: true });
|
|
141
|
+
const lines = buffer.split('\n');
|
|
142
|
+
buffer = lines.pop() ?? '';
|
|
143
|
+
for (const line of lines) {
|
|
144
|
+
if (line.startsWith('data: ')) {
|
|
145
|
+
const data = line.slice(6);
|
|
146
|
+
if (data === '[DONE]')
|
|
147
|
+
continue;
|
|
148
|
+
try {
|
|
149
|
+
const event = JSON.parse(data);
|
|
150
|
+
if (event.type === 'content_block_delta' && event.delta?.type === 'text_delta') {
|
|
151
|
+
const text = event.delta.text;
|
|
152
|
+
fullContent += text;
|
|
153
|
+
options.onChunk?.(text);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
// Ignore parse errors for partial lines
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
options.onComplete?.(fullContent);
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
options.onError?.(error instanceof Error ? error : new Error(String(error)));
|
|
166
|
+
throw error;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* 将消息内容规范化为 Anthropic 格式
|
|
171
|
+
* @param content - MessageContent 类型: string | MessagePart[]
|
|
172
|
+
* - string: 纯文本内容,直接返回
|
|
173
|
+
* - MessagePart[]: 文本/图片部分数组,转换为 Anthropic 内容块
|
|
174
|
+
* @returns 纯文本返回 string,多模态内容返回 AnthropicContent[]
|
|
175
|
+
*/
|
|
176
|
+
normalizeContent(content) {
|
|
177
|
+
// 步骤1: 如果内容是纯字符串,直接返回(Anthropic 接受字符串格式)
|
|
178
|
+
if (typeof content === 'string') {
|
|
179
|
+
return content;
|
|
180
|
+
}
|
|
181
|
+
// 步骤2: 如果内容是数组,规范化每个部分
|
|
182
|
+
return content.map(part => this.normalizePart(part));
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* 将单个消息部分规范化为 Anthropic 内容块
|
|
186
|
+
* @param part - MessagePart 类型: TextPart | ImagePart
|
|
187
|
+
* - TextPart: { type: 'text', text: string }
|
|
188
|
+
* - ImagePart: { type: 'image_url', image_url: { url: string, detail?: 'low'|'high'|'auto' } }
|
|
189
|
+
* @returns AnthropicContent: { type: 'text', text: string } | { type: 'image', source: {...} }
|
|
190
|
+
*/
|
|
191
|
+
normalizePart(part) {
|
|
192
|
+
// 步骤1: 处理文本部分 - 转换为 Anthropic 文本块
|
|
193
|
+
if (part.type === 'text') {
|
|
194
|
+
return { type: 'text', text: part.text };
|
|
195
|
+
}
|
|
196
|
+
// 步骤2: 处理图片部分 - 转换为 Anthropic 图片块
|
|
197
|
+
if (part.type === 'image_url') {
|
|
198
|
+
const urlOrData = part.image_url.url;
|
|
199
|
+
// 步骤2a: 如果是 data URI(base64),解析并转换为 Anthropic base64 格式
|
|
200
|
+
if (urlOrData.startsWith('data:')) {
|
|
201
|
+
// 解析 data URI 格式: data:image/png;base64,<编码数据>
|
|
202
|
+
const match = urlOrData.match(/^data:(\w+\/\w+);base64,(.+)$/);
|
|
203
|
+
if (match) {
|
|
204
|
+
return {
|
|
205
|
+
type: 'image',
|
|
206
|
+
source: {
|
|
207
|
+
type: 'base64',
|
|
208
|
+
media_type: match[1], // 例如 'image/png'
|
|
209
|
+
data: match[2], // base64 编码内容
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// 步骤2b: 如果是普通 URL,转换为 Anthropic URL 格式
|
|
215
|
+
return {
|
|
216
|
+
type: 'image',
|
|
217
|
+
source: {
|
|
218
|
+
type: 'url',
|
|
219
|
+
media_type: 'image/png', // URL 默认假设为 PNG
|
|
220
|
+
data: urlOrData,
|
|
221
|
+
},
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
// 降级处理: 未知类型返回空文本块
|
|
225
|
+
return { type: 'text', text: '' };
|
|
226
|
+
}
|
|
227
|
+
getTextContent(content) {
|
|
228
|
+
if (typeof content === 'string') {
|
|
229
|
+
return content;
|
|
230
|
+
}
|
|
231
|
+
return content.filter(isTextPart).map(p => p.text).join('\n');
|
|
232
|
+
}
|
|
233
|
+
applyRequestOptions(requestBody, options) {
|
|
234
|
+
super.applyRequestOptions(requestBody, options);
|
|
235
|
+
if (options.temperature !== undefined) {
|
|
236
|
+
requestBody.temperature = options.temperature;
|
|
237
|
+
}
|
|
238
|
+
if (options.maxTokens !== undefined) {
|
|
239
|
+
requestBody.max_tokens = options.maxTokens;
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
requestBody.max_tokens = 4096;
|
|
243
|
+
}
|
|
244
|
+
if (options.stop !== undefined) {
|
|
245
|
+
requestBody.stop_sequences = options.stop;
|
|
246
|
+
}
|
|
247
|
+
if (options.tools !== undefined) {
|
|
248
|
+
requestBody.tools = options.tools;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
async listModels() {
|
|
252
|
+
return [
|
|
253
|
+
{ provider: 'anthropic', model: 'claude-3-5-sonnet-20241022', displayName: 'Claude 3.5 Sonnet', contextWindow: 200000, supportsTools: true, supportsVision: true },
|
|
254
|
+
{ provider: 'anthropic', model: 'claude-3-opus-20240229', displayName: 'Claude 3 Opus', contextWindow: 200000, supportsTools: true, supportsVision: true },
|
|
255
|
+
{ provider: 'anthropic', model: 'claude-3-haiku-20240307', displayName: 'Claude 3 Haiku', contextWindow: 200000, supportsTools: true, supportsVision: true },
|
|
256
|
+
];
|
|
257
|
+
}
|
|
258
|
+
async validateKey() {
|
|
259
|
+
try {
|
|
260
|
+
const response = await fetch(this.apiUrl, {
|
|
261
|
+
method: 'POST',
|
|
262
|
+
headers: {
|
|
263
|
+
'Content-Type': 'application/json',
|
|
264
|
+
'x-api-key': this.authToken,
|
|
265
|
+
'anthropic-version': '2023-06-01',
|
|
266
|
+
'anthropic-dangerous-direct-browser-access': 'true',
|
|
267
|
+
},
|
|
268
|
+
body: JSON.stringify({
|
|
269
|
+
model: this.defaultModel,
|
|
270
|
+
messages: [{ role: 'user', content: 'test' }],
|
|
271
|
+
max_tokens: 1,
|
|
272
|
+
}),
|
|
273
|
+
});
|
|
274
|
+
return response.ok || response.status === 400;
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
function mapFinishReason(reason) {
|
|
282
|
+
switch (reason) {
|
|
283
|
+
case 'end_turn': return 'stop';
|
|
284
|
+
case 'max_tokens': return 'length';
|
|
285
|
+
case 'stop_sequence': return 'stop';
|
|
286
|
+
case 'tool_use': return 'tool_calls';
|
|
287
|
+
default: return 'stop';
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
//# sourceMappingURL=anthropic.js.map
|