@prismshadow/mmsp 0.5.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/README.md +121 -0
- package/dist/ant_messages/client.d.ts +59 -0
- package/dist/ant_messages/client.d.ts.map +1 -0
- package/dist/ant_messages/client.js +419 -0
- package/dist/ant_messages/index.d.ts +2 -0
- package/dist/ant_messages/index.d.ts.map +1 -0
- package/dist/ant_messages/index.js +18 -0
- package/dist/anthropic_official/client.d.ts +63 -0
- package/dist/anthropic_official/client.d.ts.map +1 -0
- package/dist/anthropic_official/client.js +540 -0
- package/dist/anthropic_official/index.d.ts +2 -0
- package/dist/anthropic_official/index.d.ts.map +1 -0
- package/dist/anthropic_official/index.js +18 -0
- package/dist/autoClient.d.ts +96 -0
- package/dist/autoClient.d.ts.map +1 -0
- package/dist/autoClient.js +258 -0
- package/dist/baseClient.d.ts +111 -0
- package/dist/baseClient.d.ts.map +1 -0
- package/dist/baseClient.js +284 -0
- package/dist/deepseek_official/client.d.ts +60 -0
- package/dist/deepseek_official/client.d.ts.map +1 -0
- package/dist/deepseek_official/client.js +407 -0
- package/dist/deepseek_official/index.d.ts +2 -0
- package/dist/deepseek_official/index.d.ts.map +1 -0
- package/dist/deepseek_official/index.js +18 -0
- package/dist/errors.d.ts +84 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +140 -0
- package/dist/gemini_generate_content/client.d.ts +86 -0
- package/dist/gemini_generate_content/client.d.ts.map +1 -0
- package/dist/gemini_generate_content/client.js +809 -0
- package/dist/gemini_generate_content/index.d.ts +2 -0
- package/dist/gemini_generate_content/index.d.ts.map +1 -0
- package/dist/gemini_generate_content/index.js +18 -0
- package/dist/gemini_official/client.d.ts +87 -0
- package/dist/gemini_official/client.d.ts.map +1 -0
- package/dist/gemini_official/client.js +780 -0
- package/dist/gemini_official/index.d.ts +2 -0
- package/dist/gemini_official/index.d.ts.map +1 -0
- package/dist/gemini_official/index.js +18 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/integration/index.d.ts +1 -0
- package/dist/integration/index.d.ts.map +1 -0
- package/dist/integration/index.js +14 -0
- package/dist/integration/playground.d.ts +17 -0
- package/dist/integration/playground.d.ts.map +1 -0
- package/dist/integration/playground.js +3246 -0
- package/dist/integration/tracer.d.ts +188 -0
- package/dist/integration/tracer.d.ts.map +1 -0
- package/dist/integration/tracer.js +1928 -0
- package/dist/legacy.d.ts +13 -0
- package/dist/legacy.d.ts.map +1 -0
- package/dist/legacy.js +59 -0
- package/dist/minimax_official/client.d.ts +43 -0
- package/dist/minimax_official/client.d.ts.map +1 -0
- package/dist/minimax_official/client.js +346 -0
- package/dist/minimax_official/index.d.ts +2 -0
- package/dist/minimax_official/index.d.ts.map +1 -0
- package/dist/minimax_official/index.js +18 -0
- package/dist/moonshot_official/client.d.ts +73 -0
- package/dist/moonshot_official/client.d.ts.map +1 -0
- package/dist/moonshot_official/client.js +477 -0
- package/dist/moonshot_official/index.d.ts +2 -0
- package/dist/moonshot_official/index.d.ts.map +1 -0
- package/dist/moonshot_official/index.js +18 -0
- package/dist/openai_chat/client.d.ts +67 -0
- package/dist/openai_chat/client.d.ts.map +1 -0
- package/dist/openai_chat/client.js +419 -0
- package/dist/openai_chat/index.d.ts +2 -0
- package/dist/openai_chat/index.d.ts.map +1 -0
- package/dist/openai_chat/index.js +18 -0
- package/dist/openai_chat_vllm_adapter/client.d.ts +15 -0
- package/dist/openai_chat_vllm_adapter/client.d.ts.map +1 -0
- package/dist/openai_chat_vllm_adapter/client.js +118 -0
- package/dist/openai_chat_vllm_adapter/index.d.ts +2 -0
- package/dist/openai_chat_vllm_adapter/index.d.ts.map +1 -0
- package/dist/openai_chat_vllm_adapter/index.js +5 -0
- package/dist/openai_embedding/client.d.ts +46 -0
- package/dist/openai_embedding/client.d.ts.map +1 -0
- package/dist/openai_embedding/client.js +124 -0
- package/dist/openai_embedding/index.d.ts +2 -0
- package/dist/openai_embedding/index.d.ts.map +1 -0
- package/dist/openai_embedding/index.js +18 -0
- package/dist/openai_official/client.d.ts +61 -0
- package/dist/openai_official/client.d.ts.map +1 -0
- package/dist/openai_official/client.js +464 -0
- package/dist/openai_official/index.d.ts +2 -0
- package/dist/openai_official/index.d.ts.map +1 -0
- package/dist/openai_official/index.js +18 -0
- package/dist/openai_responses/client.d.ts +61 -0
- package/dist/openai_responses/client.d.ts.map +1 -0
- package/dist/openai_responses/client.js +449 -0
- package/dist/openai_responses/index.d.ts +2 -0
- package/dist/openai_responses/index.d.ts.map +1 -0
- package/dist/openai_responses/index.js +18 -0
- package/dist/registry.d.ts +49 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +798 -0
- package/dist/streamItems.d.ts +36 -0
- package/dist/streamItems.d.ts.map +1 -0
- package/dist/streamItems.js +183 -0
- package/dist/types.d.ts +190 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +37 -0
- package/dist/utils.d.ts +99 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +312 -0
- package/dist/zai_official/client.d.ts +78 -0
- package/dist/zai_official/client.d.ts.map +1 -0
- package/dist/zai_official/client.js +420 -0
- package/dist/zai_official/index.d.ts +2 -0
- package/dist/zai_official/index.d.ts.map +1 -0
- package/dist/zai_official/index.js +18 -0
- package/package.json +68 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { BetaMessageParam, BetaRawMessageStreamEvent } from "@anthropic-ai/sdk/resources/beta/messages";
|
|
2
|
+
import { LLMClient } from "../baseClient";
|
|
3
|
+
import { UniConfig, UniEvent, UniMessage } from "../types";
|
|
4
|
+
/**
|
|
5
|
+
* Claude 5-specific LLM client implementation (also serves Claude 4.6 through 4.8).
|
|
6
|
+
*/
|
|
7
|
+
export declare class AnthropicOfficialClient extends LLMClient {
|
|
8
|
+
protected _model: string;
|
|
9
|
+
private _client;
|
|
10
|
+
private _use_bedrock;
|
|
11
|
+
/**
|
|
12
|
+
* Initialize Claude 5 client with model and API key.
|
|
13
|
+
*/
|
|
14
|
+
constructor(options: {
|
|
15
|
+
model: string;
|
|
16
|
+
apiKey?: string;
|
|
17
|
+
baseUrl?: string | null;
|
|
18
|
+
defaultHeaders?: Record<string, string>;
|
|
19
|
+
});
|
|
20
|
+
/**
|
|
21
|
+
* Convert image URL to image source.
|
|
22
|
+
*
|
|
23
|
+
* Bedrock does not support image url sources, so we need to fetch the image bytes and encode them.
|
|
24
|
+
*/
|
|
25
|
+
private _convertImageUrlToSource;
|
|
26
|
+
/**
|
|
27
|
+
* Convert ThinkingLevel enum to Claude's adaptive thinking config.
|
|
28
|
+
*/
|
|
29
|
+
private _generation;
|
|
30
|
+
private _convertThinkingLevelToThinkingConfig;
|
|
31
|
+
/**
|
|
32
|
+
* Convert ToolChoice to Claude's tool_choice format.
|
|
33
|
+
*/
|
|
34
|
+
private _convertToolChoice;
|
|
35
|
+
/**
|
|
36
|
+
* Transform universal configuration to Claude-specific configuration.
|
|
37
|
+
*/
|
|
38
|
+
transformUniConfigToModelConfig(config: UniConfig): any;
|
|
39
|
+
/**
|
|
40
|
+
* Transform universal message format to Claude's MessageParam format.
|
|
41
|
+
*/
|
|
42
|
+
transformUniMessageToModelInput(messages: UniMessage[], signal?: AbortSignal): Promise<BetaMessageParam[]>;
|
|
43
|
+
/**
|
|
44
|
+
* Transform one Claude stream event into a universal event, identifying items by content
|
|
45
|
+
* block index.
|
|
46
|
+
*/
|
|
47
|
+
transformModelOutputToUniEvent(modelOutput: BetaRawMessageStreamEvent): UniEvent;
|
|
48
|
+
/**
|
|
49
|
+
* Stream generate using Claude SDK with unified conversion methods.
|
|
50
|
+
*/
|
|
51
|
+
_streamingResponseInternal(options: {
|
|
52
|
+
messages: UniMessage[];
|
|
53
|
+
config: UniConfig;
|
|
54
|
+
signal?: AbortSignal;
|
|
55
|
+
}): AsyncGenerator<UniEvent>;
|
|
56
|
+
/**
|
|
57
|
+
* List the model ids the configured endpoint serves.
|
|
58
|
+
*
|
|
59
|
+
* @returns The model ids, in the order the endpoint returned them.
|
|
60
|
+
*/
|
|
61
|
+
listModels(): Promise<string[]>;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/anthropic_official/client.ts"],"names":[],"mappings":"AAgBA,OAAO,EACL,gBAAgB,EAChB,yBAAyB,EAC1B,MAAM,2CAA2C,CAAC;AAEnD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAK1C,OAAO,EAOL,SAAS,EACT,QAAQ,EACR,UAAU,EAEX,MAAM,UAAU,CAAC;AAelB;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,SAAS;IACpD,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,YAAY,CAAU;IAE9B;;OAEG;gBACS,OAAO,EAAE;QACnB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACzC;IAuCD;;;;OAIG;YACW,wBAAwB;IA8CtC;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,qCAAqC;IA6C7C;;OAEG;IAEH,OAAO,CAAC,kBAAkB;IA6B1B;;OAEG;IAEH,+BAA+B,CAAC,MAAM,EAAE,SAAS,GAAG,GAAG;IAoGvD;;OAEG;IACG,+BAA+B,CACnC,QAAQ,EAAE,UAAU,EAAE,EACtB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAqE9B;;;OAGG;IACH,8BAA8B,CAC5B,WAAW,EAAE,yBAAyB,GACrC,QAAQ;IAwHX;;OAEG;IACI,0BAA0B,CAAC,OAAO,EAAE;QACzC,QAAQ,EAAE,UAAU,EAAE,CAAC;QACvB,MAAM,EAAE,SAAS,CAAC;QAClB,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,GAAG,cAAc,CAAC,QAAQ,CAAC;IAmD5B;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CAgBtC"}
|
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright 2025 Prism Shadow. and/or its affiliates
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// you may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
//
|
|
8
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
16
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
17
|
+
};
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.AnthropicOfficialClient = void 0;
|
|
20
|
+
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
21
|
+
const bedrock_sdk_1 = __importDefault(require("@anthropic-ai/bedrock-sdk"));
|
|
22
|
+
const baseClient_1 = require("../baseClient");
|
|
23
|
+
const errors_1 = require("../errors");
|
|
24
|
+
const types_1 = require("../types");
|
|
25
|
+
const utils_1 = require("../utils");
|
|
26
|
+
const REDACTED_THINKING = "_REDACTED_THINKING";
|
|
27
|
+
// Generations told apart by explicit version, matched anywhere in the id so Bedrock's
|
|
28
|
+
// anthropic.claude-opus-5-5 counts too. Opus 5.5 and Fable 5.1 always think: "disabled" and
|
|
29
|
+
// "between_tools" return 400. Sonnet 5.5 drops only up-front thinking, with "between_tools".
|
|
30
|
+
const ALWAYS_THINKING = ["opus-5-5", "fable-5-1"];
|
|
31
|
+
const BETWEEN_TOOLS = ["sonnet-5-5"];
|
|
32
|
+
// The 2026-09 generation returns 400 for tool_choice "any" and "tool".
|
|
33
|
+
const NO_FORCED_TOOL_CHOICE = ["opus-5-5", "sonnet-5-5", "fable-5-1"];
|
|
34
|
+
// These reject the speed parameter ("does not support the `speed` parameter").
|
|
35
|
+
const NO_FAST_MODE = ["4-6", "sonnet-5-5", "fable-5-1"];
|
|
36
|
+
/**
|
|
37
|
+
* Claude 5-specific LLM client implementation (also serves Claude 4.6 through 4.8).
|
|
38
|
+
*/
|
|
39
|
+
class AnthropicOfficialClient extends baseClient_1.LLMClient {
|
|
40
|
+
/**
|
|
41
|
+
* Initialize Claude 5 client with model and API key.
|
|
42
|
+
*/
|
|
43
|
+
constructor(options) {
|
|
44
|
+
super();
|
|
45
|
+
this._model = options.model;
|
|
46
|
+
const { apiKey: key, baseUrl: url } = (0, utils_1.resolveCredentials)(this.constructor.name, options, { key: "ANTHROPIC_API_KEY", baseUrl: "ANTHROPIC_BASE_URL" });
|
|
47
|
+
if (url && url.startsWith("bedrock://")) {
|
|
48
|
+
// example: bedrock://us-east-1
|
|
49
|
+
const region = url.replace("bedrock://", "");
|
|
50
|
+
const [accessKey, secretKey] = (key || "").split(",");
|
|
51
|
+
const bedrock = new bedrock_sdk_1.default({
|
|
52
|
+
awsSecretKey: secretKey,
|
|
53
|
+
awsAccessKey: accessKey,
|
|
54
|
+
awsRegion: region,
|
|
55
|
+
defaultHeaders: options.defaultHeaders,
|
|
56
|
+
});
|
|
57
|
+
// AnthropicBedrock's options type leaves out apiKey and authToken, yet the Anthropic client
|
|
58
|
+
// it extends still fills both from ANTHROPIC_API_KEY and ANTHROPIC_AUTH_TOKEN and sends them
|
|
59
|
+
// to AWS beside the SigV4 signature, so clear them: the AWS credentials sign alone.
|
|
60
|
+
bedrock.apiKey = null;
|
|
61
|
+
bedrock.authToken = null;
|
|
62
|
+
this._client = bedrock;
|
|
63
|
+
this._use_bedrock = true;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
this._client = new sdk_1.default({
|
|
67
|
+
apiKey: key,
|
|
68
|
+
// null, not undefined: the SDK fills an undefined authToken from ANTHROPIC_AUTH_TOKEN and
|
|
69
|
+
// sends it as Authorization: Bearer beside the key, to whatever base URL this client uses
|
|
70
|
+
authToken: null,
|
|
71
|
+
baseURL: url,
|
|
72
|
+
defaultHeaders: options.defaultHeaders,
|
|
73
|
+
});
|
|
74
|
+
this._use_bedrock = false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Convert image URL to image source.
|
|
79
|
+
*
|
|
80
|
+
* Bedrock does not support image url sources, so we need to fetch the image bytes and encode them.
|
|
81
|
+
*/
|
|
82
|
+
async _convertImageUrlToSource(url, signal) {
|
|
83
|
+
if (url.startsWith("data:")) {
|
|
84
|
+
const match = url.match(/data:([^;]+);base64,(.+)/);
|
|
85
|
+
if (match) {
|
|
86
|
+
const mediaType = match[1];
|
|
87
|
+
const base64Data = match[2];
|
|
88
|
+
return {
|
|
89
|
+
type: "image",
|
|
90
|
+
source: {
|
|
91
|
+
type: "base64",
|
|
92
|
+
media_type: mediaType,
|
|
93
|
+
data: base64Data,
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
throw new Error(`Invalid base64 image: ${url}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else if (this._use_bedrock) {
|
|
102
|
+
const response = await fetch(url, { signal });
|
|
103
|
+
if (!response.ok) {
|
|
104
|
+
throw new Error(`Failed to fetch image: ${response.status} ${response.statusText}`);
|
|
105
|
+
}
|
|
106
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
107
|
+
const buffer = Buffer.from(arrayBuffer);
|
|
108
|
+
const mime_type = response.headers.get("content-type") || "image/jpeg";
|
|
109
|
+
return {
|
|
110
|
+
type: "image",
|
|
111
|
+
source: {
|
|
112
|
+
type: "base64",
|
|
113
|
+
media_type: mime_type,
|
|
114
|
+
data: buffer.toString("base64"),
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
return { type: "image", source: { type: "url", url } };
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Convert ThinkingLevel enum to Claude's adaptive thinking config.
|
|
124
|
+
*/
|
|
125
|
+
_generation(versions) {
|
|
126
|
+
return versions.some((version) => this._model.includes(version));
|
|
127
|
+
}
|
|
128
|
+
_convertThinkingLevelToThinkingConfig(thinkingLevel) {
|
|
129
|
+
// nothing turns thinking off on ALWAYS_THINKING, so NONE takes the least of it
|
|
130
|
+
const none = this._generation(ALWAYS_THINKING)
|
|
131
|
+
? { thinking: { type: "adaptive" }, output_config: { effort: "low" } }
|
|
132
|
+
: this._generation(BETWEEN_TOOLS)
|
|
133
|
+
? { thinking: { type: "between_tools" } }
|
|
134
|
+
: {}; // omit thinking config
|
|
135
|
+
const mapping = {
|
|
136
|
+
[types_1.ThinkingLevel.NONE]: none,
|
|
137
|
+
[types_1.ThinkingLevel.LOW]: {
|
|
138
|
+
thinking: { type: "adaptive" },
|
|
139
|
+
output_config: { effort: "low" },
|
|
140
|
+
},
|
|
141
|
+
[types_1.ThinkingLevel.MEDIUM]: {
|
|
142
|
+
thinking: { type: "adaptive" },
|
|
143
|
+
output_config: { effort: "medium" },
|
|
144
|
+
},
|
|
145
|
+
[types_1.ThinkingLevel.HIGH]: {
|
|
146
|
+
thinking: { type: "adaptive" },
|
|
147
|
+
output_config: { effort: "high" },
|
|
148
|
+
},
|
|
149
|
+
// Claude 4.6 has no xhigh effort, so XHIGH degrades to the closest supported level
|
|
150
|
+
[types_1.ThinkingLevel.XHIGH]: {
|
|
151
|
+
thinking: { type: "adaptive" },
|
|
152
|
+
output_config: {
|
|
153
|
+
effort: this._model.includes("4-6") ? "high" : "xhigh",
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
// every model this client serves is 4.6 or later, and max spans that whole range
|
|
157
|
+
[types_1.ThinkingLevel.MAX]: {
|
|
158
|
+
thinking: { type: "adaptive" },
|
|
159
|
+
output_config: { effort: "max" },
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
return mapping[thinkingLevel];
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Convert ToolChoice to Claude's tool_choice format.
|
|
166
|
+
*/
|
|
167
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
168
|
+
_convertToolChoice(toolChoice) {
|
|
169
|
+
if ((toolChoice === "required" || Array.isArray(toolChoice)) &&
|
|
170
|
+
this._generation(NO_FORCED_TOOL_CHOICE)) {
|
|
171
|
+
throw new errors_1.UnsupportedParameterError({
|
|
172
|
+
client: this.constructor.name,
|
|
173
|
+
parameter: "tool_choice",
|
|
174
|
+
message: `${this._model} does not support forcing a tool call; use auto and name the tool in the prompt.`,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
if (Array.isArray(toolChoice)) {
|
|
178
|
+
if (toolChoice.length > 1) {
|
|
179
|
+
throw new errors_1.UnsupportedParameterError({
|
|
180
|
+
client: this.constructor.name,
|
|
181
|
+
parameter: "tool_choice",
|
|
182
|
+
message: "Claude supports only one tool choice.",
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
return { type: "any", name: toolChoice[0] };
|
|
186
|
+
}
|
|
187
|
+
else if (toolChoice === "none") {
|
|
188
|
+
return { type: "none" };
|
|
189
|
+
}
|
|
190
|
+
else if (toolChoice === "auto") {
|
|
191
|
+
return { type: "auto" };
|
|
192
|
+
}
|
|
193
|
+
else if (toolChoice === "required") {
|
|
194
|
+
return { type: "any" };
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Transform universal configuration to Claude-specific configuration.
|
|
199
|
+
*/
|
|
200
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
201
|
+
transformUniConfigToModelConfig(config) {
|
|
202
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
203
|
+
const claudeConfig = {
|
|
204
|
+
model: this._model,
|
|
205
|
+
stream: true,
|
|
206
|
+
};
|
|
207
|
+
if (config.system_prompt !== undefined) {
|
|
208
|
+
claudeConfig.system = config.system_prompt;
|
|
209
|
+
}
|
|
210
|
+
if (config.max_tokens !== undefined) {
|
|
211
|
+
claudeConfig.max_tokens = config.max_tokens;
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
claudeConfig.max_tokens = 64000;
|
|
215
|
+
}
|
|
216
|
+
if (config.temperature !== undefined && config.temperature !== 1.0) {
|
|
217
|
+
throw new errors_1.UnsupportedParameterError({
|
|
218
|
+
client: this.constructor.name,
|
|
219
|
+
parameter: "temperature",
|
|
220
|
+
message: "Claude models do not support setting temperature; the API dropped it " +
|
|
221
|
+
"starting with the 4.7 generation and the unified client rejects it for the whole family.",
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
if (config.thinking_level !== undefined) {
|
|
225
|
+
Object.assign(claudeConfig, this._convertThinkingLevelToThinkingConfig(config.thinking_level));
|
|
226
|
+
}
|
|
227
|
+
if (config.thinking_summary !== undefined) {
|
|
228
|
+
// display lives on the thinking block, so a summary asked for on its own selects
|
|
229
|
+
// adaptive thinking, which is what this family runs by default anyway; a block
|
|
230
|
+
// carrying display but no output_config is accepted on 4.6 through 5 (verified
|
|
231
|
+
// live 2026-09-03). NONE omits the block, so the request lands on that default.
|
|
232
|
+
claudeConfig.thinking = claudeConfig.thinking ?? { type: "adaptive" };
|
|
233
|
+
// between_tools takes no display: its updates between tool calls always carry their text
|
|
234
|
+
if (claudeConfig.thinking.type !== "between_tools") {
|
|
235
|
+
claudeConfig.thinking.display = config.thinking_summary
|
|
236
|
+
? "summarized"
|
|
237
|
+
: "omitted";
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (config.tools !== undefined) {
|
|
241
|
+
const claudeTools = [];
|
|
242
|
+
for (const tool of config.tools) {
|
|
243
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
244
|
+
const claudeTool = {};
|
|
245
|
+
for (const [key, value] of Object.entries(tool)) {
|
|
246
|
+
claudeTool[key.replace("parameters", "input_schema")] = value;
|
|
247
|
+
}
|
|
248
|
+
claudeTools.push(claudeTool);
|
|
249
|
+
}
|
|
250
|
+
claudeConfig.tools = claudeTools;
|
|
251
|
+
}
|
|
252
|
+
if (config.tool_choice !== undefined) {
|
|
253
|
+
claudeConfig.tool_choice = this._convertToolChoice(config.tool_choice);
|
|
254
|
+
}
|
|
255
|
+
if (config.fast_mode) {
|
|
256
|
+
if (this._use_bedrock) {
|
|
257
|
+
throw new errors_1.UnsupportedParameterError({
|
|
258
|
+
client: this.constructor.name,
|
|
259
|
+
parameter: "fast_mode",
|
|
260
|
+
message: "Bedrock does not support fast mode.",
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
if (this._generation(NO_FAST_MODE)) {
|
|
264
|
+
throw new errors_1.UnsupportedParameterError({
|
|
265
|
+
client: this.constructor.name,
|
|
266
|
+
parameter: "fast_mode",
|
|
267
|
+
message: `${this._model} does not support fast mode.`,
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
claudeConfig.speed = "fast";
|
|
271
|
+
claudeConfig.betas = ["fast-mode-2026-02-01"];
|
|
272
|
+
}
|
|
273
|
+
// Add cache_control if prompt caching is enabled
|
|
274
|
+
// TODO: wait for bedrock to support cache_control in config
|
|
275
|
+
if (!this._use_bedrock) {
|
|
276
|
+
const promptCaching = config.prompt_caching || types_1.PromptCaching.ENABLE;
|
|
277
|
+
if (promptCaching === types_1.PromptCaching.ENABLE) {
|
|
278
|
+
claudeConfig.cache_control = { type: "ephemeral" };
|
|
279
|
+
}
|
|
280
|
+
else if (promptCaching === types_1.PromptCaching.ENHANCE) {
|
|
281
|
+
claudeConfig.cache_control = { type: "ephemeral", ttl: "1h" };
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return claudeConfig;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Transform universal message format to Claude's MessageParam format.
|
|
288
|
+
*/
|
|
289
|
+
async transformUniMessageToModelInput(messages, signal) {
|
|
290
|
+
const claudeMessages = [];
|
|
291
|
+
for (const msg of messages) {
|
|
292
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
293
|
+
const contentBlocks = [];
|
|
294
|
+
for (const item of msg.content_items) {
|
|
295
|
+
if (item.type === "text.done") {
|
|
296
|
+
contentBlocks.push({ type: "text", text: item.text });
|
|
297
|
+
}
|
|
298
|
+
else if (item.type === "image_url.done") {
|
|
299
|
+
const imageUrl = item.image_url;
|
|
300
|
+
contentBlocks.push(await this._convertImageUrlToSource(imageUrl, signal));
|
|
301
|
+
}
|
|
302
|
+
else if (item.type === "thinking.done") {
|
|
303
|
+
if (item.thinking === REDACTED_THINKING) {
|
|
304
|
+
contentBlocks.push({
|
|
305
|
+
type: "redacted_thinking",
|
|
306
|
+
data: item.fidelity?.signature,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
contentBlocks.push({
|
|
311
|
+
type: "thinking",
|
|
312
|
+
thinking: item.thinking,
|
|
313
|
+
signature: item.fidelity?.signature,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
else if (item.type === "tool_call.done") {
|
|
318
|
+
contentBlocks.push({
|
|
319
|
+
type: "tool_use",
|
|
320
|
+
id: item.tool_call_id,
|
|
321
|
+
name: item.name,
|
|
322
|
+
input: item.arguments,
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
else if (item.type === "tool_result.done") {
|
|
326
|
+
if (!item.tool_call_id) {
|
|
327
|
+
throw new Error("tool_call_id is required for tool result.");
|
|
328
|
+
}
|
|
329
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
330
|
+
const toolResult = [{ type: "text", text: item.text }];
|
|
331
|
+
if (item.images) {
|
|
332
|
+
for (const imageUrl of item.images) {
|
|
333
|
+
toolResult.push(await this._convertImageUrlToSource(imageUrl, signal));
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
contentBlocks.push({
|
|
337
|
+
type: "tool_result",
|
|
338
|
+
content: toolResult,
|
|
339
|
+
tool_use_id: item.tool_call_id,
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
throw new Error(`Unknown item: ${JSON.stringify(item)}`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
claudeMessages.push({
|
|
347
|
+
role: msg.role,
|
|
348
|
+
content: contentBlocks,
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
return claudeMessages;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Transform one Claude stream event into a universal event, identifying items by content
|
|
355
|
+
* block index.
|
|
356
|
+
*/
|
|
357
|
+
transformModelOutputToUniEvent(modelOutput) {
|
|
358
|
+
let eventType = "delta";
|
|
359
|
+
const contentItems = [];
|
|
360
|
+
let usageMetadata = null;
|
|
361
|
+
let finishReason = null;
|
|
362
|
+
const claudeEventType = modelOutput.type;
|
|
363
|
+
if (claudeEventType === "content_block_start") {
|
|
364
|
+
const itemId = String(modelOutput.index);
|
|
365
|
+
const block = modelOutput.content_block;
|
|
366
|
+
if (block.type === "tool_use") {
|
|
367
|
+
contentItems.push({
|
|
368
|
+
type: "tool_call.delta",
|
|
369
|
+
name: block.name,
|
|
370
|
+
arguments: "",
|
|
371
|
+
tool_call_id: block.id,
|
|
372
|
+
fidelity: { item_id: itemId },
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
else if (block.type === "redacted_thinking") {
|
|
376
|
+
contentItems.push({
|
|
377
|
+
type: "thinking.delta",
|
|
378
|
+
thinking: REDACTED_THINKING,
|
|
379
|
+
fidelity: { item_id: itemId, signature: block.data },
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
else if (claudeEventType === "content_block_delta") {
|
|
384
|
+
const itemId = String(modelOutput.index);
|
|
385
|
+
const delta = modelOutput.delta;
|
|
386
|
+
if (delta.type === "thinking_delta") {
|
|
387
|
+
contentItems.push({
|
|
388
|
+
type: "thinking.delta",
|
|
389
|
+
thinking: delta.thinking,
|
|
390
|
+
fidelity: { item_id: itemId },
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
else if (delta.type === "text_delta") {
|
|
394
|
+
contentItems.push({
|
|
395
|
+
type: "text.delta",
|
|
396
|
+
text: delta.text,
|
|
397
|
+
fidelity: { item_id: itemId },
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
else if (delta.type === "input_json_delta") {
|
|
401
|
+
contentItems.push({
|
|
402
|
+
type: "tool_call.delta",
|
|
403
|
+
name: "",
|
|
404
|
+
arguments: delta.partial_json,
|
|
405
|
+
tool_call_id: "",
|
|
406
|
+
fidelity: { item_id: itemId },
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
else if (delta.type === "signature_delta") {
|
|
410
|
+
// the last delta of a thinking block: its signature
|
|
411
|
+
contentItems.push({
|
|
412
|
+
type: "thinking.delta",
|
|
413
|
+
thinking: "",
|
|
414
|
+
fidelity: { item_id: itemId, signature: delta.signature },
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
else if (claudeEventType === "message_start") {
|
|
419
|
+
eventType = "stop";
|
|
420
|
+
const usage = modelOutput.message.usage;
|
|
421
|
+
if (usage) {
|
|
422
|
+
const cacheCreationTokens = usage.cache_creation_input_tokens || 0;
|
|
423
|
+
usageMetadata = {
|
|
424
|
+
cached_tokens: usage.cache_read_input_tokens || null,
|
|
425
|
+
prompt_tokens: usage.input_tokens + cacheCreationTokens,
|
|
426
|
+
thoughts_tokens: null,
|
|
427
|
+
response_tokens: null,
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
else if (claudeEventType === "message_delta") {
|
|
432
|
+
eventType = "stop";
|
|
433
|
+
const stopReasonMapping = {
|
|
434
|
+
end_turn: "stop",
|
|
435
|
+
max_tokens: "length",
|
|
436
|
+
stop_sequence: "stop",
|
|
437
|
+
tool_use: "tool_call",
|
|
438
|
+
};
|
|
439
|
+
const stopReason = modelOutput.delta.stop_reason;
|
|
440
|
+
if (stopReason) {
|
|
441
|
+
finishReason = stopReasonMapping[stopReason] || "unknown";
|
|
442
|
+
}
|
|
443
|
+
if (modelOutput.usage) {
|
|
444
|
+
// message_delta reports the output tokens; the input side came with message_start
|
|
445
|
+
usageMetadata = {
|
|
446
|
+
cached_tokens: null,
|
|
447
|
+
prompt_tokens: null,
|
|
448
|
+
thoughts_tokens: null,
|
|
449
|
+
response_tokens: modelOutput.usage.output_tokens,
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
else if ([
|
|
454
|
+
"content_block_stop",
|
|
455
|
+
"message_stop",
|
|
456
|
+
"text",
|
|
457
|
+
"thinking",
|
|
458
|
+
"signature",
|
|
459
|
+
"input_json",
|
|
460
|
+
"ping",
|
|
461
|
+
].includes(claudeEventType)) {
|
|
462
|
+
// a block needs no stop: it is done when the next one begins or the stream ends. The SDK
|
|
463
|
+
// drops the "ping" heartbeat at the SSE layer; it reaches here only from gateways that
|
|
464
|
+
// relabel it onto another event
|
|
465
|
+
}
|
|
466
|
+
else if ((0, utils_1.isDebugEnabled)()) {
|
|
467
|
+
throw new Error(`Unknown output: ${JSON.stringify(modelOutput)}`);
|
|
468
|
+
}
|
|
469
|
+
else {
|
|
470
|
+
// a gateway injects its own events (heartbeats, cost tickers) into the stream, and
|
|
471
|
+
// killing a long generation over one costs more than dropping it
|
|
472
|
+
}
|
|
473
|
+
return {
|
|
474
|
+
role: "assistant",
|
|
475
|
+
event_type: eventType,
|
|
476
|
+
content_items: contentItems,
|
|
477
|
+
usage_metadata: usageMetadata,
|
|
478
|
+
finish_reason: finishReason,
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Stream generate using Claude SDK with unified conversion methods.
|
|
483
|
+
*/
|
|
484
|
+
async *_streamingResponseInternal(options) {
|
|
485
|
+
const claudeConfig = this.transformUniConfigToModelConfig(options.config);
|
|
486
|
+
const claudeMessages = await this.transformUniMessageToModelInput(options.messages, options.signal);
|
|
487
|
+
// Add cache_control to last user message's last item if enabled
|
|
488
|
+
// TODO: remove after bedrock supports cache_control in config
|
|
489
|
+
if (this._use_bedrock) {
|
|
490
|
+
const promptCaching = options.config.prompt_caching || types_1.PromptCaching.ENABLE;
|
|
491
|
+
if (promptCaching !== types_1.PromptCaching.DISABLE &&
|
|
492
|
+
claudeMessages.length > 0) {
|
|
493
|
+
try {
|
|
494
|
+
const reversedMessages = [...claudeMessages].reverse();
|
|
495
|
+
const lastUserMessage = reversedMessages.find((x) => x.role === "user");
|
|
496
|
+
if (lastUserMessage && Array.isArray(lastUserMessage.content)) {
|
|
497
|
+
const lastContentItem = lastUserMessage.content[lastUserMessage.content.length - 1];
|
|
498
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
499
|
+
lastContentItem.cache_control = {
|
|
500
|
+
type: "ephemeral",
|
|
501
|
+
ttl: promptCaching === types_1.PromptCaching.ENHANCE ? "1h" : "5m",
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
catch {
|
|
506
|
+
// Ignore errors in cache_control setup
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
const stream = (await this._client.beta.messages.create({
|
|
511
|
+
...claudeConfig,
|
|
512
|
+
messages: claudeMessages,
|
|
513
|
+
}, {
|
|
514
|
+
signal: options.signal,
|
|
515
|
+
}));
|
|
516
|
+
for await (const event of stream) {
|
|
517
|
+
yield this.transformModelOutputToUniEvent(event);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* List the model ids the configured endpoint serves.
|
|
522
|
+
*
|
|
523
|
+
* @returns The model ids, in the order the endpoint returned them.
|
|
524
|
+
*/
|
|
525
|
+
async listModels() {
|
|
526
|
+
if (this._use_bedrock) {
|
|
527
|
+
throw new errors_1.UnsupportedOperationError({
|
|
528
|
+
client: this.constructor.name,
|
|
529
|
+
operation: "list_models",
|
|
530
|
+
message: "Bedrock does not support listing models.",
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
const models = [];
|
|
534
|
+
for await (const model of this._client.models.list()) {
|
|
535
|
+
models.push(model.id);
|
|
536
|
+
}
|
|
537
|
+
return models;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
exports.AnthropicOfficialClient = AnthropicOfficialClient;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/anthropic_official/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright 2025 Prism Shadow. and/or its affiliates
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// you may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
//
|
|
8
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.AnthropicOfficialClient = void 0;
|
|
17
|
+
var client_1 = require("./client");
|
|
18
|
+
Object.defineProperty(exports, "AnthropicOfficialClient", { enumerable: true, get: function () { return client_1.AnthropicOfficialClient; } });
|