@effect/ai-anthropic 0.16.1 → 0.17.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/AnthropicTool/package.json +6 -0
- package/dist/cjs/AnthropicClient.js +286 -190
- package/dist/cjs/AnthropicClient.js.map +1 -1
- package/dist/cjs/AnthropicLanguageModel.js +1026 -311
- package/dist/cjs/AnthropicLanguageModel.js.map +1 -1
- package/dist/cjs/AnthropicTokenizer.js +8 -6
- package/dist/cjs/AnthropicTokenizer.js.map +1 -1
- package/dist/cjs/AnthropicTool.js +461 -0
- package/dist/cjs/AnthropicTool.js.map +1 -0
- package/dist/cjs/Generated.js +3507 -1230
- package/dist/cjs/Generated.js.map +1 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/internal/utilities.js +13 -3
- package/dist/cjs/internal/utilities.js.map +1 -1
- package/dist/dts/AnthropicClient.d.ts +673 -17
- package/dist/dts/AnthropicClient.d.ts.map +1 -1
- package/dist/dts/AnthropicLanguageModel.d.ts +217 -26
- package/dist/dts/AnthropicLanguageModel.d.ts.map +1 -1
- package/dist/dts/AnthropicTokenizer.d.ts +1 -1
- package/dist/dts/AnthropicTokenizer.d.ts.map +1 -1
- package/dist/dts/AnthropicTool.d.ts +523 -0
- package/dist/dts/AnthropicTool.d.ts.map +1 -0
- package/dist/dts/Generated.d.ts +7863 -3496
- package/dist/dts/Generated.d.ts.map +1 -1
- package/dist/dts/index.d.ts +4 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/esm/AnthropicClient.js +269 -188
- package/dist/esm/AnthropicClient.js.map +1 -1
- package/dist/esm/AnthropicLanguageModel.js +1022 -306
- package/dist/esm/AnthropicLanguageModel.js.map +1 -1
- package/dist/esm/AnthropicTokenizer.js +8 -6
- package/dist/esm/AnthropicTokenizer.js.map +1 -1
- package/dist/esm/AnthropicTool.js +452 -0
- package/dist/esm/AnthropicTool.js.map +1 -0
- package/dist/esm/Generated.js +3492 -1063
- package/dist/esm/Generated.js.map +1 -1
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/utilities.js +12 -2
- package/dist/esm/internal/utilities.js.map +1 -1
- package/package.json +11 -3
- package/src/AnthropicClient.ts +713 -369
- package/src/AnthropicLanguageModel.ts +1404 -345
- package/src/AnthropicTokenizer.ts +14 -23
- package/src/AnthropicTool.ts +553 -0
- package/src/Generated.ts +4165 -1681
- package/src/index.ts +5 -0
- package/src/internal/utilities.ts +18 -4
|
@@ -3,32 +3,31 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.withConfigOverride = exports.modelWithTokenizer = exports.model = exports.make = exports.layerWithTokenizer = exports.layer = exports.
|
|
7
|
-
var
|
|
8
|
-
var
|
|
9
|
-
var
|
|
10
|
-
var
|
|
11
|
-
var
|
|
6
|
+
exports.withConfigOverride = exports.prepareTools = exports.modelWithTokenizer = exports.model = exports.make = exports.layerWithTokenizer = exports.layer = exports.Config = void 0;
|
|
7
|
+
var AiError = _interopRequireWildcard(require("@effect/ai/AiError"));
|
|
8
|
+
var IdGenerator = _interopRequireWildcard(require("@effect/ai/IdGenerator"));
|
|
9
|
+
var LanguageModel = _interopRequireWildcard(require("@effect/ai/LanguageModel"));
|
|
10
|
+
var AiModel = _interopRequireWildcard(require("@effect/ai/Model"));
|
|
11
|
+
var _Telemetry = require("@effect/ai/Telemetry");
|
|
12
|
+
var Tool = _interopRequireWildcard(require("@effect/ai/Tool"));
|
|
12
13
|
var Arr = _interopRequireWildcard(require("effect/Array"));
|
|
13
14
|
var Context = _interopRequireWildcard(require("effect/Context"));
|
|
15
|
+
var DateTime = _interopRequireWildcard(require("effect/DateTime"));
|
|
14
16
|
var Effect = _interopRequireWildcard(require("effect/Effect"));
|
|
15
17
|
var Encoding = _interopRequireWildcard(require("effect/Encoding"));
|
|
16
18
|
var _Function = require("effect/Function");
|
|
17
19
|
var Layer = _interopRequireWildcard(require("effect/Layer"));
|
|
18
|
-
var Option = _interopRequireWildcard(require("effect/Option"));
|
|
19
20
|
var Predicate = _interopRequireWildcard(require("effect/Predicate"));
|
|
20
21
|
var Stream = _interopRequireWildcard(require("effect/Stream"));
|
|
21
22
|
var _AnthropicClient = require("./AnthropicClient.js");
|
|
22
23
|
var AnthropicTokenizer = _interopRequireWildcard(require("./AnthropicTokenizer.js"));
|
|
24
|
+
var AnthropicTool = _interopRequireWildcard(require("./AnthropicTool.js"));
|
|
23
25
|
var InternalUtilities = _interopRequireWildcard(require("./internal/utilities.js"));
|
|
24
26
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
25
27
|
/**
|
|
26
28
|
* @since 1.0.0
|
|
27
29
|
*/
|
|
28
30
|
|
|
29
|
-
const constDisableValidation = {
|
|
30
|
-
disableValidation: true
|
|
31
|
-
};
|
|
32
31
|
// =============================================================================
|
|
33
32
|
// Configuration
|
|
34
33
|
// =============================================================================
|
|
@@ -43,32 +42,23 @@ class Config extends /*#__PURE__*/Context.Tag("@effect/ai-anthropic/AnthropicLan
|
|
|
43
42
|
static getOrUndefined = /*#__PURE__*/Effect.map(/*#__PURE__*/Effect.context(), context => context.unsafeMap.get(Config.key));
|
|
44
43
|
}
|
|
45
44
|
// =============================================================================
|
|
46
|
-
// Anthropic Provider Metadata
|
|
47
|
-
// =============================================================================
|
|
48
|
-
/**
|
|
49
|
-
* @since 1.0.0
|
|
50
|
-
* @category Context
|
|
51
|
-
*/
|
|
52
|
-
exports.Config = Config;
|
|
53
|
-
class ProviderMetadata extends /*#__PURE__*/Context.Tag(InternalUtilities.ProviderMetadataKey)() {}
|
|
54
|
-
// =============================================================================
|
|
55
45
|
// Anthropic Language Model
|
|
56
46
|
// =============================================================================
|
|
57
47
|
/**
|
|
58
48
|
* @since 1.0.0
|
|
59
|
-
* @category
|
|
49
|
+
* @category Ai Models
|
|
60
50
|
*/
|
|
61
|
-
exports.
|
|
62
|
-
const model = (model, config) => AiModel.make(layer({
|
|
51
|
+
exports.Config = Config;
|
|
52
|
+
const model = (model, config) => AiModel.make("anthropic", layer({
|
|
63
53
|
model,
|
|
64
54
|
config
|
|
65
55
|
}));
|
|
66
56
|
/**
|
|
67
57
|
* @since 1.0.0
|
|
68
|
-
* @category
|
|
58
|
+
* @category Ai Models
|
|
69
59
|
*/
|
|
70
60
|
exports.model = model;
|
|
71
|
-
const modelWithTokenizer = (model, config) => AiModel.make(layerWithTokenizer({
|
|
61
|
+
const modelWithTokenizer = (model, config) => AiModel.make("anthropic", layerWithTokenizer({
|
|
72
62
|
model,
|
|
73
63
|
config
|
|
74
64
|
}));
|
|
@@ -79,88 +69,86 @@ const modelWithTokenizer = (model, config) => AiModel.make(layerWithTokenizer({
|
|
|
79
69
|
exports.modelWithTokenizer = modelWithTokenizer;
|
|
80
70
|
const make = exports.make = /*#__PURE__*/Effect.fnUntraced(function* (options) {
|
|
81
71
|
const client = yield* _AnthropicClient.AnthropicClient;
|
|
82
|
-
const makeRequest = Effect.fnUntraced(function* (
|
|
83
|
-
prompt,
|
|
84
|
-
system,
|
|
85
|
-
toolChoice,
|
|
86
|
-
tools
|
|
87
|
-
}) {
|
|
72
|
+
const makeRequest = Effect.fnUntraced(function* (providerOptions) {
|
|
88
73
|
const context = yield* Effect.context();
|
|
89
|
-
const
|
|
90
|
-
let tool_choice = undefined;
|
|
91
|
-
if (useStructured) {
|
|
92
|
-
tool_choice = {
|
|
93
|
-
type: "tool",
|
|
94
|
-
name: tools[0].name
|
|
95
|
-
};
|
|
96
|
-
} else if (tools.length > 0) {
|
|
97
|
-
if (toolChoice === "required") {
|
|
98
|
-
tool_choice = {
|
|
99
|
-
type: "any"
|
|
100
|
-
};
|
|
101
|
-
} else if (typeof toolChoice === "object") {
|
|
102
|
-
tool_choice = {
|
|
103
|
-
type: "tool",
|
|
104
|
-
name: toolChoice.tool
|
|
105
|
-
};
|
|
106
|
-
} else {
|
|
107
|
-
tool_choice = {
|
|
108
|
-
type: toolChoice
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
const messages = yield* makeMessages(method, prompt);
|
|
113
|
-
return {
|
|
74
|
+
const config = {
|
|
114
75
|
model: options.model,
|
|
115
|
-
max_tokens: 4096,
|
|
116
76
|
...options.config,
|
|
117
|
-
...context.unsafeMap.get(Config.key)
|
|
118
|
-
|
|
119
|
-
|
|
77
|
+
...context.unsafeMap.get(Config.key)
|
|
78
|
+
};
|
|
79
|
+
const {
|
|
80
|
+
betas: messageBetas,
|
|
120
81
|
messages,
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
82
|
+
system
|
|
83
|
+
} = yield* prepareMessages(providerOptions);
|
|
84
|
+
const {
|
|
85
|
+
betas: toolBetas,
|
|
86
|
+
toolChoice,
|
|
87
|
+
tools
|
|
88
|
+
} = yield* prepareTools(providerOptions, config);
|
|
89
|
+
const responseFormat = providerOptions.responseFormat;
|
|
90
|
+
const request = {
|
|
91
|
+
max_tokens: 4096,
|
|
92
|
+
...config,
|
|
93
|
+
system,
|
|
94
|
+
messages,
|
|
95
|
+
tools: responseFormat.type === "text" ? tools : [{
|
|
96
|
+
name: responseFormat.objectName,
|
|
97
|
+
description: Tool.getDescriptionFromSchemaAst(responseFormat.schema.ast) ?? "Respond with a JSON object",
|
|
98
|
+
input_schema: Tool.getJsonSchemaFromSchemaAst(responseFormat.schema.ast)
|
|
99
|
+
}],
|
|
100
|
+
tool_choice: responseFormat.type === "text" ? toolChoice : {
|
|
101
|
+
type: "tool",
|
|
102
|
+
name: responseFormat.objectName,
|
|
103
|
+
disable_parallel_tool_use: true
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
return {
|
|
107
|
+
betas: new Set([...messageBetas, ...toolBetas]),
|
|
108
|
+
request
|
|
127
109
|
};
|
|
128
110
|
});
|
|
129
|
-
return yield*
|
|
111
|
+
return yield* LanguageModel.make({
|
|
130
112
|
generateText: Effect.fnUntraced(function* (options) {
|
|
131
|
-
const
|
|
113
|
+
const {
|
|
114
|
+
betas,
|
|
115
|
+
request
|
|
116
|
+
} = yield* makeRequest(options);
|
|
132
117
|
annotateRequest(options.span, request);
|
|
133
|
-
const
|
|
134
|
-
|
|
118
|
+
const anthropicBeta = betas.size > 0 ? Array.from(betas).join(",") : undefined;
|
|
119
|
+
const rawResponse = yield* client.createMessage({
|
|
120
|
+
params: {
|
|
121
|
+
"anthropic-beta": anthropicBeta
|
|
122
|
+
},
|
|
135
123
|
payload: request
|
|
136
124
|
});
|
|
137
|
-
|
|
138
|
-
|
|
125
|
+
annotateResponse(options.span, rawResponse);
|
|
126
|
+
return yield* makeResponse(rawResponse, options);
|
|
127
|
+
}),
|
|
128
|
+
streamText: Effect.fnUntraced(function* (options) {
|
|
129
|
+
const {
|
|
130
|
+
betas,
|
|
131
|
+
request
|
|
132
|
+
} = yield* makeRequest(options);
|
|
133
|
+
annotateRequest(options.span, request);
|
|
134
|
+
const anthropicBeta = betas.size > 0 ? Array.from(betas).join(",") : undefined;
|
|
135
|
+
return client.createMessageStream({
|
|
136
|
+
params: {
|
|
137
|
+
"anthropic-beta": anthropicBeta
|
|
138
|
+
},
|
|
139
|
+
payload: request
|
|
140
|
+
});
|
|
141
|
+
}, (effect, options) => effect.pipe(Effect.flatMap(stream => makeStreamResponse(stream, options)), Stream.unwrap, Stream.map(response => {
|
|
142
|
+
annotateStreamResponse(options.span, response);
|
|
139
143
|
return response;
|
|
140
|
-
}
|
|
141
|
-
module: "AnthropicLanguageModel",
|
|
142
|
-
method: "generateText",
|
|
143
|
-
description: "An error occurred",
|
|
144
|
-
cause
|
|
145
|
-
}))),
|
|
146
|
-
streamText(options) {
|
|
147
|
-
return makeRequest("streamText", options).pipe(Effect.tap(request => annotateRequest(options.span, request)), Effect.map(client.stream), Stream.unwrap, Stream.map(response => {
|
|
148
|
-
annotateStreamResponse(options.span, response);
|
|
149
|
-
return response;
|
|
150
|
-
}), Stream.catchAll(cause => _AiError.AiError.is(cause) ? Effect.fail(cause) : Effect.fail(new _AiError.AiError({
|
|
151
|
-
module: "AnthropicLanguageModel",
|
|
152
|
-
method: "streamText",
|
|
153
|
-
description: "An error occurred",
|
|
154
|
-
cause
|
|
155
|
-
}))));
|
|
156
|
-
}
|
|
144
|
+
})))
|
|
157
145
|
});
|
|
158
146
|
});
|
|
159
147
|
/**
|
|
160
148
|
* @since 1.0.0
|
|
161
149
|
* @category Layers
|
|
162
150
|
*/
|
|
163
|
-
const layer = options => Layer.effect(
|
|
151
|
+
const layer = options => Layer.effect(LanguageModel.LanguageModel, make({
|
|
164
152
|
model: options.model,
|
|
165
153
|
config: options.config
|
|
166
154
|
}));
|
|
@@ -179,193 +167,125 @@ const withConfigOverride = exports.withConfigOverride = /*#__PURE__*/(0, _Functi
|
|
|
179
167
|
...config,
|
|
180
168
|
...overrides
|
|
181
169
|
})));
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (current?.type !== "assistant") {
|
|
190
|
-
current = {
|
|
191
|
-
type: "assistant",
|
|
192
|
-
messages: []
|
|
193
|
-
};
|
|
194
|
-
messages.push(current);
|
|
195
|
-
}
|
|
196
|
-
current.messages.push(message);
|
|
197
|
-
break;
|
|
198
|
-
}
|
|
199
|
-
case "ToolMessage":
|
|
200
|
-
case "UserMessage":
|
|
201
|
-
{
|
|
202
|
-
if (current?.type !== "user") {
|
|
203
|
-
current = {
|
|
204
|
-
type: "user",
|
|
205
|
-
messages: []
|
|
206
|
-
};
|
|
207
|
-
messages.push(current);
|
|
208
|
-
}
|
|
209
|
-
current.messages.push(message);
|
|
210
|
-
break;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
return messages;
|
|
215
|
-
};
|
|
216
|
-
const makeMessages = /*#__PURE__*/Effect.fnUntraced(function* (method, prompt) {
|
|
170
|
+
// =============================================================================
|
|
171
|
+
// Prompt Conversion
|
|
172
|
+
// =============================================================================
|
|
173
|
+
const prepareMessages = /*#__PURE__*/Effect.fnUntraced(function* (options) {
|
|
174
|
+
const betas = new Set();
|
|
175
|
+
const groups = groupMessages(options.prompt);
|
|
176
|
+
let system = undefined;
|
|
217
177
|
const messages = [];
|
|
218
|
-
const groups = groupMessages(prompt);
|
|
219
178
|
for (let i = 0; i < groups.length; i++) {
|
|
220
179
|
const group = groups[i];
|
|
221
180
|
const isLastGroup = i === groups.length - 1;
|
|
222
181
|
switch (group.type) {
|
|
223
|
-
case "
|
|
182
|
+
case "system":
|
|
224
183
|
{
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
const part = message.parts[k];
|
|
231
|
-
const isLastPart = k === message.parts.length - 1;
|
|
232
|
-
switch (part._tag) {
|
|
233
|
-
case "ReasoningPart":
|
|
234
|
-
{
|
|
235
|
-
content.push({
|
|
236
|
-
type: "thinking",
|
|
237
|
-
thinking: part.reasoningText,
|
|
238
|
-
signature: part.signature
|
|
239
|
-
});
|
|
240
|
-
break;
|
|
241
|
-
}
|
|
242
|
-
case "RedactedReasoningPart":
|
|
243
|
-
{
|
|
244
|
-
content.push({
|
|
245
|
-
type: "redacted_thinking",
|
|
246
|
-
data: part.redactedText
|
|
247
|
-
});
|
|
248
|
-
break;
|
|
249
|
-
}
|
|
250
|
-
case "TextPart":
|
|
251
|
-
{
|
|
252
|
-
content.push({
|
|
253
|
-
type: "text",
|
|
254
|
-
text:
|
|
255
|
-
// Anthropic does not allow trailing whitespace in assistant
|
|
256
|
-
// content blocks
|
|
257
|
-
isLastGroup && isLastMessage && isLastPart ? part.text.trim() : part.text
|
|
258
|
-
});
|
|
259
|
-
break;
|
|
260
|
-
}
|
|
261
|
-
case "ToolCallPart":
|
|
262
|
-
{
|
|
263
|
-
content.push({
|
|
264
|
-
type: "tool_use",
|
|
265
|
-
id: part.id,
|
|
266
|
-
name: part.name,
|
|
267
|
-
input: part.params
|
|
268
|
-
});
|
|
269
|
-
break;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
messages.push({
|
|
275
|
-
role: "assistant",
|
|
276
|
-
content
|
|
277
|
-
});
|
|
184
|
+
system = group.messages.map(message => ({
|
|
185
|
+
type: "text",
|
|
186
|
+
text: message.content,
|
|
187
|
+
cache_control: getCacheControl(message)
|
|
188
|
+
}));
|
|
278
189
|
break;
|
|
279
190
|
}
|
|
280
191
|
case "user":
|
|
281
192
|
{
|
|
282
193
|
const content = [];
|
|
283
|
-
for (
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
case "ToolMessage":
|
|
194
|
+
for (const message of group.messages) {
|
|
195
|
+
switch (message.role) {
|
|
196
|
+
case "user":
|
|
287
197
|
{
|
|
288
|
-
for (let
|
|
289
|
-
const part = message.
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
}
|
|
299
|
-
case "UserMessage":
|
|
300
|
-
{
|
|
301
|
-
for (let k = 0; k < message.parts.length; k++) {
|
|
302
|
-
const part = message.parts[k];
|
|
303
|
-
switch (part._tag) {
|
|
304
|
-
case "FilePart":
|
|
305
|
-
{
|
|
306
|
-
if (Predicate.isUndefined(part.mediaType) || part.mediaType !== "application/pdf") {
|
|
307
|
-
return yield* new _AiError.AiError({
|
|
308
|
-
module: "AnthropicLanguageModel",
|
|
309
|
-
method,
|
|
310
|
-
description: "AnthropicLanguageModel only supports PDF file inputs"
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
|
-
content.push({
|
|
314
|
-
type: "document",
|
|
315
|
-
source: {
|
|
316
|
-
type: "base64",
|
|
317
|
-
media_type: "application/pdf",
|
|
318
|
-
data: Encoding.encodeBase64(part.data)
|
|
319
|
-
}
|
|
320
|
-
});
|
|
321
|
-
break;
|
|
322
|
-
}
|
|
323
|
-
case "FileUrlPart":
|
|
324
|
-
{
|
|
325
|
-
content.push({
|
|
326
|
-
type: "document",
|
|
327
|
-
source: {
|
|
328
|
-
type: "url",
|
|
329
|
-
url: part.url.toString()
|
|
330
|
-
}
|
|
331
|
-
});
|
|
332
|
-
break;
|
|
333
|
-
}
|
|
334
|
-
case "TextPart":
|
|
198
|
+
for (let j = 0; j < message.content.length; j++) {
|
|
199
|
+
const part = message.content[j];
|
|
200
|
+
const isLastPart = j === message.content.length - 1;
|
|
201
|
+
// Attempt to get the cache control from the part first. If
|
|
202
|
+
// the part does not have cache control defined and we are
|
|
203
|
+
// evaluating the last part for this message, also check the
|
|
204
|
+
// message for cache control.
|
|
205
|
+
const cacheControl = getCacheControl(part) ?? (isLastPart ? getCacheControl(message) : undefined);
|
|
206
|
+
switch (part.type) {
|
|
207
|
+
case "text":
|
|
335
208
|
{
|
|
336
209
|
content.push({
|
|
337
210
|
type: "text",
|
|
338
|
-
text: part.text
|
|
211
|
+
text: part.text,
|
|
212
|
+
cache_control: cacheControl
|
|
339
213
|
});
|
|
340
214
|
break;
|
|
341
215
|
}
|
|
342
|
-
case "
|
|
216
|
+
case "file":
|
|
343
217
|
{
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
218
|
+
if (part.mediaType.startsWith("image/")) {
|
|
219
|
+
const source = part.data instanceof URL ? {
|
|
220
|
+
type: "url",
|
|
221
|
+
url: part.data.toString()
|
|
222
|
+
} : {
|
|
347
223
|
type: "base64",
|
|
348
|
-
media_type: part.mediaType
|
|
349
|
-
data: Encoding.encodeBase64(part.data)
|
|
224
|
+
media_type: part.mediaType === "image/*" ? "image/jpeg" : part.mediaType,
|
|
225
|
+
data: typeof part.data === "string" ? part.data : Encoding.encodeBase64(part.data)
|
|
226
|
+
};
|
|
227
|
+
content.push({
|
|
228
|
+
type: "image",
|
|
229
|
+
source,
|
|
230
|
+
cache_control: cacheControl
|
|
231
|
+
});
|
|
232
|
+
} else if (part.mediaType === "application/pdf" || part.mediaType === "text/plain") {
|
|
233
|
+
if (part.mediaType === "application/pdf") {
|
|
234
|
+
betas.add("pdfs-2024-09-25");
|
|
350
235
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
case "ImageUrlPart":
|
|
355
|
-
{
|
|
356
|
-
content.push({
|
|
357
|
-
type: "image",
|
|
358
|
-
source: {
|
|
236
|
+
const enableCitations = shouldEnableCitations(part);
|
|
237
|
+
const documentOptions = getDocumentMetadata(part);
|
|
238
|
+
const source = part.data instanceof URL ? {
|
|
359
239
|
type: "url",
|
|
360
|
-
url: part.
|
|
361
|
-
}
|
|
362
|
-
|
|
240
|
+
url: part.data.toString()
|
|
241
|
+
} : part.mediaType === "application/pdf" ? {
|
|
242
|
+
type: "base64",
|
|
243
|
+
media_type: "application/pdf",
|
|
244
|
+
data: typeof part.data === "string" ? part.data : Encoding.encodeBase64(part.data)
|
|
245
|
+
} : {
|
|
246
|
+
type: "text",
|
|
247
|
+
media_type: "text/plain",
|
|
248
|
+
data: typeof part.data === "string" ? part.data : Encoding.encodeBase64(part.data)
|
|
249
|
+
};
|
|
250
|
+
content.push({
|
|
251
|
+
type: "document",
|
|
252
|
+
source,
|
|
253
|
+
title: documentOptions?.title ?? part.fileName,
|
|
254
|
+
...(documentOptions?.context ? {
|
|
255
|
+
context: documentOptions.context
|
|
256
|
+
} : undefined),
|
|
257
|
+
...(enableCitations ? {
|
|
258
|
+
citations: {
|
|
259
|
+
enabled: true
|
|
260
|
+
}
|
|
261
|
+
} : undefined),
|
|
262
|
+
cache_control: cacheControl
|
|
263
|
+
});
|
|
264
|
+
} else {
|
|
265
|
+
return yield* new AiError.MalformedInput({
|
|
266
|
+
module: "AnthropicLanguageModel",
|
|
267
|
+
method: "prepareMessages",
|
|
268
|
+
description: `Detected unsupported media type for file: '${part.mediaType}'`
|
|
269
|
+
});
|
|
270
|
+
}
|
|
363
271
|
break;
|
|
364
272
|
}
|
|
365
273
|
}
|
|
366
274
|
}
|
|
367
275
|
break;
|
|
368
276
|
}
|
|
277
|
+
// TODO: advanced tool result content parts
|
|
278
|
+
case "tool":
|
|
279
|
+
{
|
|
280
|
+
for (const part of message.content) {
|
|
281
|
+
content.push({
|
|
282
|
+
type: "tool_result",
|
|
283
|
+
tool_use_id: part.id,
|
|
284
|
+
content: JSON.stringify(part.result)
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
369
289
|
}
|
|
370
290
|
}
|
|
371
291
|
messages.push({
|
|
@@ -374,83 +294,561 @@ const makeMessages = /*#__PURE__*/Effect.fnUntraced(function* (method, prompt) {
|
|
|
374
294
|
});
|
|
375
295
|
break;
|
|
376
296
|
}
|
|
297
|
+
case "assistant":
|
|
298
|
+
{
|
|
299
|
+
const content = [];
|
|
300
|
+
for (let j = 0; j < group.messages.length; j++) {
|
|
301
|
+
const message = group.messages[j];
|
|
302
|
+
const isLastMessage = j === group.messages.length - 1;
|
|
303
|
+
for (let k = 0; k < message.content.length; k++) {
|
|
304
|
+
const part = message.content[k];
|
|
305
|
+
const isLastPart = k === message.content.length - 1;
|
|
306
|
+
// Attempt to get the cache control from the part first. If
|
|
307
|
+
// the part does not have cache control defined and we are
|
|
308
|
+
// evaluating the last part for this message, also check the
|
|
309
|
+
// message for cache control.
|
|
310
|
+
const cacheControl = getCacheControl(part) ?? (isLastPart ? getCacheControl(message) : undefined);
|
|
311
|
+
switch (part.type) {
|
|
312
|
+
case "text":
|
|
313
|
+
{
|
|
314
|
+
content.push({
|
|
315
|
+
type: "text",
|
|
316
|
+
// Anthropic does not allow trailing whitespace in assistant
|
|
317
|
+
// content blocks
|
|
318
|
+
text: isLastGroup && isLastMessage && isLastPart ? part.text.trim() : part.text
|
|
319
|
+
});
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
322
|
+
case "reasoning":
|
|
323
|
+
{
|
|
324
|
+
const options = part.options.anthropic;
|
|
325
|
+
if (Predicate.isNotUndefined(options)) {
|
|
326
|
+
if (options.type === "thinking") {
|
|
327
|
+
content.push({
|
|
328
|
+
type: "thinking",
|
|
329
|
+
thinking: part.text,
|
|
330
|
+
signature: options.signature
|
|
331
|
+
});
|
|
332
|
+
} else {
|
|
333
|
+
content.push({
|
|
334
|
+
type: "redacted_thinking",
|
|
335
|
+
data: options.redactedData
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
break;
|
|
340
|
+
}
|
|
341
|
+
case "tool-call":
|
|
342
|
+
{
|
|
343
|
+
if (part.providerExecuted) {
|
|
344
|
+
if (part.name === "AnthropicWebSearch") {
|
|
345
|
+
content.push({
|
|
346
|
+
type: "server_tool_use",
|
|
347
|
+
id: part.id,
|
|
348
|
+
name: "web_search",
|
|
349
|
+
input: part.params,
|
|
350
|
+
cache_control: cacheControl
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
if (part.name === "AnthropicCodeExecution") {
|
|
354
|
+
content.push({
|
|
355
|
+
type: "server_tool_use",
|
|
356
|
+
id: part.id,
|
|
357
|
+
name: "code_execution",
|
|
358
|
+
input: part.params,
|
|
359
|
+
cache_control: cacheControl
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
} else {
|
|
363
|
+
content.push({
|
|
364
|
+
type: "tool_use",
|
|
365
|
+
id: part.id,
|
|
366
|
+
name: part.name,
|
|
367
|
+
input: part.params,
|
|
368
|
+
cache_control: cacheControl
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
messages.push({
|
|
377
|
+
role: "assistant",
|
|
378
|
+
content
|
|
379
|
+
});
|
|
380
|
+
break;
|
|
381
|
+
}
|
|
377
382
|
}
|
|
378
383
|
}
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
method,
|
|
385
|
-
description: "Prompt contained no messages"
|
|
386
|
-
});
|
|
384
|
+
return {
|
|
385
|
+
system,
|
|
386
|
+
messages,
|
|
387
|
+
betas
|
|
388
|
+
};
|
|
387
389
|
});
|
|
388
|
-
|
|
390
|
+
// =============================================================================
|
|
391
|
+
// Response Conversion
|
|
392
|
+
// =============================================================================
|
|
393
|
+
const makeResponse = /*#__PURE__*/Effect.fnUntraced(function* (response, options) {
|
|
394
|
+
const idGenerator = yield* IdGenerator.IdGenerator;
|
|
389
395
|
const parts = [];
|
|
390
|
-
|
|
396
|
+
const citableDocuments = extractCitableDocuments(options.prompt);
|
|
397
|
+
parts.push({
|
|
398
|
+
type: "response-metadata",
|
|
391
399
|
id: response.id,
|
|
392
|
-
|
|
393
|
-
|
|
400
|
+
modelId: response.model,
|
|
401
|
+
timestamp: DateTime.formatIso(yield* DateTime.now)
|
|
402
|
+
});
|
|
394
403
|
for (const part of response.content) {
|
|
395
404
|
switch (part.type) {
|
|
396
405
|
case "text":
|
|
397
406
|
{
|
|
398
|
-
parts
|
|
399
|
-
|
|
400
|
-
|
|
407
|
+
// The text parts should only be added to the response here if the
|
|
408
|
+
// response format is `"text"`. If the response format is `"json"`,
|
|
409
|
+
// then the text parts must instead be added to the response when a
|
|
410
|
+
// tool call is received.
|
|
411
|
+
if (options.responseFormat.type === "text") {
|
|
412
|
+
parts.push({
|
|
413
|
+
type: "text",
|
|
414
|
+
text: part.text
|
|
415
|
+
});
|
|
416
|
+
if (Predicate.isNotNullable(part.citations)) {
|
|
417
|
+
for (const citation of part.citations) {
|
|
418
|
+
const source = yield* processCitation(citation, citableDocuments, idGenerator);
|
|
419
|
+
if (Predicate.isNotUndefined(source)) {
|
|
420
|
+
parts.push(source);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
break;
|
|
426
|
+
}
|
|
427
|
+
case "thinking":
|
|
428
|
+
{
|
|
429
|
+
parts.push({
|
|
430
|
+
type: "reasoning",
|
|
431
|
+
text: part.thinking,
|
|
432
|
+
metadata: {
|
|
433
|
+
anthropic: {
|
|
434
|
+
type: "thinking",
|
|
435
|
+
signature: part.signature
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
break;
|
|
440
|
+
}
|
|
441
|
+
case "redacted_thinking":
|
|
442
|
+
{
|
|
443
|
+
parts.push({
|
|
444
|
+
type: "reasoning",
|
|
445
|
+
text: "",
|
|
446
|
+
metadata: {
|
|
447
|
+
anthropic: {
|
|
448
|
+
type: "redacted_thinking",
|
|
449
|
+
redactedData: part.data
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
});
|
|
401
453
|
break;
|
|
402
454
|
}
|
|
403
455
|
case "tool_use":
|
|
404
456
|
{
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
457
|
+
// When a `"json"` response format is requested, the JSON that we need
|
|
458
|
+
// will be returned by the tool call injected into the request
|
|
459
|
+
if (options.responseFormat.type === "json") {
|
|
460
|
+
parts.push({
|
|
461
|
+
type: "text",
|
|
462
|
+
text: JSON.stringify(part.input)
|
|
463
|
+
});
|
|
464
|
+
} else {
|
|
465
|
+
const providerTool = AnthropicTool.getProviderDefinedToolName(part.name);
|
|
466
|
+
const name = Predicate.isNotUndefined(providerTool) ? providerTool : part.name;
|
|
467
|
+
const providerName = Predicate.isNotUndefined(providerTool) ? part.name : undefined;
|
|
468
|
+
parts.push({
|
|
469
|
+
type: "tool-call",
|
|
470
|
+
id: part.id,
|
|
471
|
+
name,
|
|
472
|
+
params: part.input,
|
|
473
|
+
providerName,
|
|
474
|
+
providerExecuted: false
|
|
475
|
+
});
|
|
476
|
+
}
|
|
410
477
|
break;
|
|
411
478
|
}
|
|
412
|
-
case "
|
|
479
|
+
case "server_tool_use":
|
|
413
480
|
{
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
481
|
+
const providerTool = AnthropicTool.getProviderDefinedToolName(part.name);
|
|
482
|
+
if (Predicate.isNotUndefined(providerTool)) {
|
|
483
|
+
parts.push({
|
|
484
|
+
type: "tool-call",
|
|
485
|
+
id: part.id,
|
|
486
|
+
name: providerTool,
|
|
487
|
+
params: part.input,
|
|
488
|
+
providerName: part.name,
|
|
489
|
+
providerExecuted: true
|
|
490
|
+
});
|
|
491
|
+
}
|
|
418
492
|
break;
|
|
419
493
|
}
|
|
420
|
-
case "
|
|
494
|
+
case "code_execution_tool_result":
|
|
495
|
+
case "bash_code_execution_tool_result":
|
|
496
|
+
case "text_editor_code_execution_tool_result":
|
|
497
|
+
{
|
|
498
|
+
parts.push({
|
|
499
|
+
type: "tool-result",
|
|
500
|
+
id: part.tool_use_id,
|
|
501
|
+
name: "AnthropicCodeExecution",
|
|
502
|
+
result: part.content,
|
|
503
|
+
providerName: "code_execution",
|
|
504
|
+
providerExecuted: true
|
|
505
|
+
});
|
|
506
|
+
break;
|
|
507
|
+
}
|
|
508
|
+
case "web_search_tool_result":
|
|
421
509
|
{
|
|
422
|
-
parts.push(
|
|
423
|
-
|
|
424
|
-
|
|
510
|
+
parts.push({
|
|
511
|
+
type: "tool-result",
|
|
512
|
+
id: part.tool_use_id,
|
|
513
|
+
name: "AnthropicWebSearch",
|
|
514
|
+
result: part.content,
|
|
515
|
+
providerName: "web_search",
|
|
516
|
+
providerExecuted: true
|
|
517
|
+
});
|
|
425
518
|
break;
|
|
426
519
|
}
|
|
427
520
|
}
|
|
428
521
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
reason: InternalUtilities.resolveFinishReason(response.stop_reason),
|
|
436
|
-
usage: new AiResponse.Usage({
|
|
522
|
+
// Anthropic always returns a non-null `stop_reason` for non-streaming responses
|
|
523
|
+
const finishReason = InternalUtilities.resolveFinishReason(response.stop_reason, options.responseFormat.type === "json");
|
|
524
|
+
parts.push({
|
|
525
|
+
type: "finish",
|
|
526
|
+
reason: finishReason,
|
|
527
|
+
usage: {
|
|
437
528
|
inputTokens: response.usage.input_tokens,
|
|
438
529
|
outputTokens: response.usage.output_tokens,
|
|
439
530
|
totalTokens: response.usage.input_tokens + response.usage.output_tokens,
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
531
|
+
cachedInputTokens: response.usage.cache_read_input_tokens ?? undefined
|
|
532
|
+
},
|
|
533
|
+
metadata: {
|
|
534
|
+
anthropic: {
|
|
535
|
+
usage: response.usage,
|
|
536
|
+
stopSequence: response.stop_sequence ?? undefined
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
return parts;
|
|
541
|
+
});
|
|
542
|
+
const makeStreamResponse = /*#__PURE__*/Effect.fnUntraced(function* (stream, options) {
|
|
543
|
+
const idGenerator = yield* IdGenerator.IdGenerator;
|
|
544
|
+
const citableDocuments = extractCitableDocuments(options.prompt);
|
|
545
|
+
// Setup all requisite state for the streaming response
|
|
546
|
+
let finishReason = "unknown";
|
|
547
|
+
const contentBlocks = {};
|
|
548
|
+
let blockType = undefined;
|
|
549
|
+
const usage = {
|
|
550
|
+
inputTokens: undefined,
|
|
551
|
+
outputTokens: undefined,
|
|
552
|
+
totalTokens: undefined
|
|
553
|
+
};
|
|
554
|
+
let metaUsage = undefined;
|
|
555
|
+
let stopSequence = undefined;
|
|
556
|
+
return stream.pipe(Stream.mapEffect(Effect.fnUntraced(function* (event) {
|
|
557
|
+
const parts = [];
|
|
558
|
+
switch (event.type) {
|
|
559
|
+
case "ping":
|
|
560
|
+
{
|
|
561
|
+
break;
|
|
562
|
+
}
|
|
563
|
+
case "message_start":
|
|
564
|
+
{
|
|
565
|
+
// Track usage metadata
|
|
566
|
+
usage.inputTokens = event.message.usage.input_tokens;
|
|
567
|
+
metaUsage = event.message.usage;
|
|
568
|
+
// Track response metadata
|
|
569
|
+
parts.push({
|
|
570
|
+
type: "response-metadata",
|
|
571
|
+
id: event.message.id,
|
|
572
|
+
modelId: event.message.model,
|
|
573
|
+
timestamp: DateTime.formatIso(yield* DateTime.now)
|
|
574
|
+
});
|
|
575
|
+
break;
|
|
576
|
+
}
|
|
577
|
+
case "message_delta":
|
|
578
|
+
{
|
|
579
|
+
// Track usage metadata
|
|
580
|
+
if (Predicate.isNotNullable(event.usage.output_tokens)) {
|
|
581
|
+
usage.outputTokens = event.usage.output_tokens;
|
|
582
|
+
}
|
|
583
|
+
usage.totalTokens = (usage.inputTokens ?? 0) + (event.usage.output_tokens ?? 0);
|
|
584
|
+
// Track stop sequence metadata
|
|
585
|
+
if (Predicate.isNotNullable(event.delta.stop_sequence)) {
|
|
586
|
+
stopSequence = event.delta.stop_sequence;
|
|
587
|
+
}
|
|
588
|
+
// Track the response finish reason
|
|
589
|
+
if (Predicate.isNotNullable(event.delta.stop_reason)) {
|
|
590
|
+
finishReason = InternalUtilities.resolveFinishReason(event.delta.stop_reason);
|
|
591
|
+
}
|
|
592
|
+
break;
|
|
593
|
+
}
|
|
594
|
+
case "message_stop":
|
|
595
|
+
{
|
|
596
|
+
parts.push({
|
|
597
|
+
type: "finish",
|
|
598
|
+
reason: finishReason,
|
|
599
|
+
usage,
|
|
600
|
+
metadata: {
|
|
601
|
+
anthropic: {
|
|
602
|
+
usage: metaUsage,
|
|
603
|
+
stopSequence
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
});
|
|
607
|
+
break;
|
|
608
|
+
}
|
|
609
|
+
case "content_block_start":
|
|
610
|
+
{
|
|
611
|
+
blockType = event.content_block.type;
|
|
612
|
+
switch (event.content_block.type) {
|
|
613
|
+
case "text":
|
|
614
|
+
{
|
|
615
|
+
contentBlocks[event.index] = {
|
|
616
|
+
type: "text"
|
|
617
|
+
};
|
|
618
|
+
parts.push({
|
|
619
|
+
type: "text-start",
|
|
620
|
+
id: event.index.toString()
|
|
621
|
+
});
|
|
622
|
+
break;
|
|
623
|
+
}
|
|
624
|
+
case "thinking":
|
|
625
|
+
{
|
|
626
|
+
contentBlocks[event.index] = {
|
|
627
|
+
type: "reasoning"
|
|
628
|
+
};
|
|
629
|
+
parts.push({
|
|
630
|
+
type: "reasoning-start",
|
|
631
|
+
id: event.index.toString()
|
|
632
|
+
});
|
|
633
|
+
break;
|
|
634
|
+
}
|
|
635
|
+
case "redacted_thinking":
|
|
636
|
+
{
|
|
637
|
+
contentBlocks[event.index] = {
|
|
638
|
+
type: "reasoning"
|
|
639
|
+
};
|
|
640
|
+
parts.push({
|
|
641
|
+
type: "reasoning-start",
|
|
642
|
+
id: event.index.toString(),
|
|
643
|
+
metadata: {
|
|
644
|
+
anthropic: {
|
|
645
|
+
type: "redacted_thinking",
|
|
646
|
+
redactedData: event.content_block.data
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
});
|
|
650
|
+
break;
|
|
651
|
+
}
|
|
652
|
+
case "tool_use":
|
|
653
|
+
{
|
|
654
|
+
const toolName = event.content_block.name;
|
|
655
|
+
const providerTool = AnthropicTool.getProviderDefinedToolName(toolName);
|
|
656
|
+
const name = Predicate.isNotUndefined(providerTool) ? providerTool : toolName;
|
|
657
|
+
const providerName = Predicate.isNotUndefined(providerTool) ? toolName : undefined;
|
|
658
|
+
contentBlocks[event.index] = {
|
|
659
|
+
type: "tool-call",
|
|
660
|
+
id: event.content_block.id,
|
|
661
|
+
name,
|
|
662
|
+
params: "",
|
|
663
|
+
providerName,
|
|
664
|
+
providerExecuted: false
|
|
665
|
+
};
|
|
666
|
+
parts.push({
|
|
667
|
+
type: "tool-params-start",
|
|
668
|
+
id: event.content_block.id,
|
|
669
|
+
name: toolName,
|
|
670
|
+
providerName,
|
|
671
|
+
providerExecuted: false
|
|
672
|
+
});
|
|
673
|
+
break;
|
|
674
|
+
}
|
|
675
|
+
case "server_tool_use":
|
|
676
|
+
{
|
|
677
|
+
const toolName = event.content_block.name;
|
|
678
|
+
const providerTool = AnthropicTool.getProviderDefinedToolName(toolName);
|
|
679
|
+
if (Predicate.isNotUndefined(providerTool)) {
|
|
680
|
+
contentBlocks[event.index] = {
|
|
681
|
+
type: "tool-call",
|
|
682
|
+
id: event.content_block.id,
|
|
683
|
+
name: providerTool,
|
|
684
|
+
params: "",
|
|
685
|
+
providerName: toolName,
|
|
686
|
+
providerExecuted: true
|
|
687
|
+
};
|
|
688
|
+
parts.push({
|
|
689
|
+
type: "tool-params-start",
|
|
690
|
+
id: event.content_block.id,
|
|
691
|
+
name: providerTool,
|
|
692
|
+
providerName: toolName,
|
|
693
|
+
providerExecuted: true
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
break;
|
|
697
|
+
}
|
|
698
|
+
case "code_execution_tool_result":
|
|
699
|
+
case "bash_code_execution_tool_result":
|
|
700
|
+
case "text_editor_code_execution_tool_result":
|
|
701
|
+
{
|
|
702
|
+
parts.push({
|
|
703
|
+
type: "tool-result",
|
|
704
|
+
id: event.content_block.tool_use_id,
|
|
705
|
+
name: "AnthropicCodeExecution",
|
|
706
|
+
result: event.content_block.content,
|
|
707
|
+
providerName: "code_execution",
|
|
708
|
+
providerExecuted: true
|
|
709
|
+
});
|
|
710
|
+
break;
|
|
711
|
+
}
|
|
712
|
+
case "web_search_tool_result":
|
|
713
|
+
{
|
|
714
|
+
parts.push({
|
|
715
|
+
type: "tool-result",
|
|
716
|
+
id: event.content_block.tool_use_id,
|
|
717
|
+
name: "AnthropicWebSearch",
|
|
718
|
+
result: event.content_block.content,
|
|
719
|
+
providerName: "web_search",
|
|
720
|
+
providerExecuted: true
|
|
721
|
+
});
|
|
722
|
+
break;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
break;
|
|
726
|
+
}
|
|
727
|
+
case "content_block_delta":
|
|
728
|
+
{
|
|
729
|
+
switch (event.delta.type) {
|
|
730
|
+
case "text_delta":
|
|
731
|
+
{
|
|
732
|
+
parts.push({
|
|
733
|
+
type: "text-delta",
|
|
734
|
+
id: event.index.toString(),
|
|
735
|
+
delta: event.delta.text
|
|
736
|
+
});
|
|
737
|
+
break;
|
|
738
|
+
}
|
|
739
|
+
case "thinking_delta":
|
|
740
|
+
{
|
|
741
|
+
parts.push({
|
|
742
|
+
type: "reasoning-delta",
|
|
743
|
+
id: event.index.toString(),
|
|
744
|
+
delta: event.delta.thinking
|
|
745
|
+
});
|
|
746
|
+
break;
|
|
747
|
+
}
|
|
748
|
+
case "signature_delta":
|
|
749
|
+
{
|
|
750
|
+
if (blockType === "thinking") {
|
|
751
|
+
parts.push({
|
|
752
|
+
type: "reasoning-delta",
|
|
753
|
+
id: event.index.toString(),
|
|
754
|
+
delta: "",
|
|
755
|
+
metadata: {
|
|
756
|
+
anthropic: {
|
|
757
|
+
type: "thinking",
|
|
758
|
+
signature: event.delta.signature
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
break;
|
|
764
|
+
}
|
|
765
|
+
case "input_json_delta":
|
|
766
|
+
{
|
|
767
|
+
const contentBlock = contentBlocks[event.index];
|
|
768
|
+
const delta = event.delta.partial_json;
|
|
769
|
+
if (contentBlock.type === "tool-call") {
|
|
770
|
+
parts.push({
|
|
771
|
+
type: "tool-params-delta",
|
|
772
|
+
id: contentBlock.id,
|
|
773
|
+
delta
|
|
774
|
+
});
|
|
775
|
+
contentBlock.params += delta;
|
|
776
|
+
}
|
|
777
|
+
break;
|
|
778
|
+
}
|
|
779
|
+
case "citations_delta":
|
|
780
|
+
{
|
|
781
|
+
const citation = event.delta.citation;
|
|
782
|
+
const source = yield* processCitation(citation, citableDocuments, idGenerator);
|
|
783
|
+
if (Predicate.isNotUndefined(source)) {
|
|
784
|
+
parts.push(source);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
break;
|
|
789
|
+
}
|
|
790
|
+
case "content_block_stop":
|
|
791
|
+
{
|
|
792
|
+
if (Predicate.isNotNullable(contentBlocks[event.index])) {
|
|
793
|
+
const contentBlock = contentBlocks[event.index];
|
|
794
|
+
switch (contentBlock.type) {
|
|
795
|
+
case "text":
|
|
796
|
+
{
|
|
797
|
+
parts.push({
|
|
798
|
+
type: "text-end",
|
|
799
|
+
id: event.index.toString()
|
|
800
|
+
});
|
|
801
|
+
break;
|
|
802
|
+
}
|
|
803
|
+
case "reasoning":
|
|
804
|
+
{
|
|
805
|
+
parts.push({
|
|
806
|
+
type: "reasoning-end",
|
|
807
|
+
id: event.index.toString()
|
|
808
|
+
});
|
|
809
|
+
break;
|
|
810
|
+
}
|
|
811
|
+
case "tool-call":
|
|
812
|
+
{
|
|
813
|
+
parts.push({
|
|
814
|
+
type: "tool-params-end",
|
|
815
|
+
id: contentBlock.id
|
|
816
|
+
});
|
|
817
|
+
// If the tool call has no parameters, an empty string is returned
|
|
818
|
+
const params = contentBlock.params.length === 0 ? "{}" : contentBlock.params;
|
|
819
|
+
parts.push({
|
|
820
|
+
type: "tool-call",
|
|
821
|
+
id: contentBlock.id,
|
|
822
|
+
name: contentBlock.name,
|
|
823
|
+
params: JSON.parse(params),
|
|
824
|
+
providerName: contentBlock.providerName,
|
|
825
|
+
providerExecuted: contentBlock.providerExecuted
|
|
826
|
+
});
|
|
827
|
+
break;
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
delete contentBlocks[event.index];
|
|
831
|
+
}
|
|
832
|
+
blockType = undefined;
|
|
833
|
+
break;
|
|
834
|
+
}
|
|
835
|
+
case "error":
|
|
836
|
+
{
|
|
837
|
+
parts.push({
|
|
838
|
+
type: "error",
|
|
839
|
+
error: event.error
|
|
840
|
+
});
|
|
841
|
+
break;
|
|
842
|
+
}
|
|
446
843
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
parts
|
|
450
|
-
}, constDisableValidation);
|
|
844
|
+
return parts;
|
|
845
|
+
})), Stream.flattenIterables);
|
|
451
846
|
});
|
|
847
|
+
// =============================================================================
|
|
848
|
+
// Telemetry
|
|
849
|
+
// =============================================================================
|
|
452
850
|
const annotateRequest = (span, request) => {
|
|
453
|
-
(0,
|
|
851
|
+
(0, _Telemetry.addGenAIAnnotations)(span, {
|
|
454
852
|
system: "anthropic",
|
|
455
853
|
operation: {
|
|
456
854
|
name: "chat"
|
|
@@ -465,8 +863,8 @@ const annotateRequest = (span, request) => {
|
|
|
465
863
|
}
|
|
466
864
|
});
|
|
467
865
|
};
|
|
468
|
-
const
|
|
469
|
-
(0,
|
|
866
|
+
const annotateResponse = (span, response) => {
|
|
867
|
+
(0, _Telemetry.addGenAIAnnotations)(span, {
|
|
470
868
|
response: {
|
|
471
869
|
id: response.id,
|
|
472
870
|
model: response.model,
|
|
@@ -478,19 +876,336 @@ const annotateChatResponse = (span, response) => {
|
|
|
478
876
|
}
|
|
479
877
|
});
|
|
480
878
|
};
|
|
481
|
-
const annotateStreamResponse = (span,
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
879
|
+
const annotateStreamResponse = (span, part) => {
|
|
880
|
+
if (part.type === "response-metadata") {
|
|
881
|
+
(0, _Telemetry.addGenAIAnnotations)(span, {
|
|
882
|
+
response: {
|
|
883
|
+
id: part.id,
|
|
884
|
+
model: part.modelId
|
|
885
|
+
}
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
if (part.type === "finish") {
|
|
889
|
+
(0, _Telemetry.addGenAIAnnotations)(span, {
|
|
890
|
+
response: {
|
|
891
|
+
finishReasons: [part.reason]
|
|
892
|
+
},
|
|
893
|
+
usage: {
|
|
894
|
+
inputTokens: part.usage.inputTokens,
|
|
895
|
+
outputTokens: part.usage.outputTokens
|
|
896
|
+
}
|
|
897
|
+
});
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
/**
|
|
901
|
+
* A helper method which takes in large language model provider options from
|
|
902
|
+
* the base Effect AI SDK as well as Anthropic request configuration options
|
|
903
|
+
* and returns the prepared tools, tool choice, and Anthropic betas to include
|
|
904
|
+
* in a request.
|
|
905
|
+
*
|
|
906
|
+
* This method is primarily exposed for use by other Effect provider
|
|
907
|
+
* integrations which can utilize Anthropic models (i.e. Amazon Bedrock).
|
|
908
|
+
*
|
|
909
|
+
* @since 1.0.0
|
|
910
|
+
* @category Tool Calling
|
|
911
|
+
*/
|
|
912
|
+
const prepareTools = exports.prepareTools = /*#__PURE__*/Effect.fnUntraced(function* (options, config) {
|
|
913
|
+
// Return immediately if no tools are in the toolkit or a tool choice of
|
|
914
|
+
// "none" was specified
|
|
915
|
+
if (options.tools.length === 0 || options.toolChoice === "none") {
|
|
916
|
+
return {
|
|
917
|
+
betas: new Set(),
|
|
918
|
+
tools: undefined,
|
|
919
|
+
toolChoice: undefined
|
|
920
|
+
};
|
|
921
|
+
}
|
|
922
|
+
const betas = new Set();
|
|
923
|
+
let tools = [];
|
|
924
|
+
let toolChoice = undefined;
|
|
925
|
+
// Convert the tools in the toolkit to the provider-defined format
|
|
926
|
+
for (const tool of options.tools) {
|
|
927
|
+
if (Tool.isUserDefined(tool)) {
|
|
928
|
+
tools.push({
|
|
929
|
+
name: tool.name,
|
|
930
|
+
description: Tool.getDescription(tool),
|
|
931
|
+
input_schema: Tool.getJsonSchema(tool)
|
|
932
|
+
});
|
|
493
933
|
}
|
|
494
|
-
|
|
934
|
+
if (Tool.isProviderDefined(tool)) {
|
|
935
|
+
switch (tool.id) {
|
|
936
|
+
case "anthropic.bash_20241022":
|
|
937
|
+
{
|
|
938
|
+
betas.add("computer-use-2024-10-22");
|
|
939
|
+
tools.push({
|
|
940
|
+
name: "bash",
|
|
941
|
+
type: "bash_20241022"
|
|
942
|
+
});
|
|
943
|
+
break;
|
|
944
|
+
}
|
|
945
|
+
case "anthropic.bash_20250124":
|
|
946
|
+
{
|
|
947
|
+
betas.add("computer-use-2025-01-24");
|
|
948
|
+
tools.push({
|
|
949
|
+
name: "bash",
|
|
950
|
+
type: "bash_20250124"
|
|
951
|
+
});
|
|
952
|
+
break;
|
|
953
|
+
}
|
|
954
|
+
case "anthropic.code_execution_20250522":
|
|
955
|
+
{
|
|
956
|
+
betas.add("code-execution-2025-05-22");
|
|
957
|
+
tools.push({
|
|
958
|
+
...tool.args,
|
|
959
|
+
name: "code_execution",
|
|
960
|
+
type: "code_execution_2025522"
|
|
961
|
+
});
|
|
962
|
+
break;
|
|
963
|
+
}
|
|
964
|
+
case "anthropic.code_execution_20250825":
|
|
965
|
+
{
|
|
966
|
+
betas.add("code-execution-2025-08-25");
|
|
967
|
+
tools.push({
|
|
968
|
+
...tool.args,
|
|
969
|
+
name: "code_execution",
|
|
970
|
+
type: "code_execution_20250825"
|
|
971
|
+
});
|
|
972
|
+
break;
|
|
973
|
+
}
|
|
974
|
+
case "anthropic.computer_use_20241022":
|
|
975
|
+
{
|
|
976
|
+
betas.add("computer-use-2025-10-22");
|
|
977
|
+
tools.push({
|
|
978
|
+
...tool.args,
|
|
979
|
+
name: "computer",
|
|
980
|
+
type: "computer_20241022"
|
|
981
|
+
});
|
|
982
|
+
break;
|
|
983
|
+
}
|
|
984
|
+
case "anthropic.computer_use_20250124":
|
|
985
|
+
{
|
|
986
|
+
betas.add("computer-use-2025-01-24");
|
|
987
|
+
tools.push({
|
|
988
|
+
...tool.args,
|
|
989
|
+
name: "computer",
|
|
990
|
+
type: "computer_20250124"
|
|
991
|
+
});
|
|
992
|
+
break;
|
|
993
|
+
}
|
|
994
|
+
case "anthropic.text_editor_20241022":
|
|
995
|
+
{
|
|
996
|
+
betas.add("computer-use-2024-10-22");
|
|
997
|
+
tools.push({
|
|
998
|
+
name: "str_replace_editor",
|
|
999
|
+
type: "text_editor_20241022"
|
|
1000
|
+
});
|
|
1001
|
+
break;
|
|
1002
|
+
}
|
|
1003
|
+
case "anthropic.text_editor_20250124":
|
|
1004
|
+
{
|
|
1005
|
+
betas.add("computer-use-2025-01-24");
|
|
1006
|
+
tools.push({
|
|
1007
|
+
name: "str_replace_editor",
|
|
1008
|
+
type: "text_editor_20250124"
|
|
1009
|
+
});
|
|
1010
|
+
break;
|
|
1011
|
+
}
|
|
1012
|
+
case "anthropic.text_editor_20250429":
|
|
1013
|
+
{
|
|
1014
|
+
betas.add("computer-use-2025-01-24");
|
|
1015
|
+
tools.push({
|
|
1016
|
+
name: "str_replace_based_edit_tool",
|
|
1017
|
+
type: "text_editor_20250429"
|
|
1018
|
+
});
|
|
1019
|
+
break;
|
|
1020
|
+
}
|
|
1021
|
+
case "anthropic.text_editor_20250728":
|
|
1022
|
+
{
|
|
1023
|
+
tools.push({
|
|
1024
|
+
name: "str_replace_based_edit_tool",
|
|
1025
|
+
type: "text_editor_20250728"
|
|
1026
|
+
});
|
|
1027
|
+
break;
|
|
1028
|
+
}
|
|
1029
|
+
case "anthropic.web_search_20250305":
|
|
1030
|
+
{
|
|
1031
|
+
tools.push({
|
|
1032
|
+
...tool.args,
|
|
1033
|
+
name: "web_search",
|
|
1034
|
+
type: "web_search_20250305"
|
|
1035
|
+
});
|
|
1036
|
+
break;
|
|
1037
|
+
}
|
|
1038
|
+
default:
|
|
1039
|
+
{
|
|
1040
|
+
return yield* new AiError.MalformedInput({
|
|
1041
|
+
module: "AnthropicLanguageModel",
|
|
1042
|
+
method: "prepareTools",
|
|
1043
|
+
description: `Received request to call unknown provider-defined tool '${tool.name}'`
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
// Convert the tool choice to the provider-defined format
|
|
1050
|
+
if (options.toolChoice === "auto") {
|
|
1051
|
+
toolChoice = {
|
|
1052
|
+
type: "auto",
|
|
1053
|
+
disable_parallel_tool_use: config.disableParallelToolCalls
|
|
1054
|
+
};
|
|
1055
|
+
} else if (options.toolChoice === "required") {
|
|
1056
|
+
toolChoice = {
|
|
1057
|
+
type: "any",
|
|
1058
|
+
disable_parallel_tool_use: config.disableParallelToolCalls
|
|
1059
|
+
};
|
|
1060
|
+
} else if ("tool" in options.toolChoice) {
|
|
1061
|
+
toolChoice = {
|
|
1062
|
+
type: "tool",
|
|
1063
|
+
name: options.toolChoice.tool,
|
|
1064
|
+
disable_parallel_tool_use: config.disableParallelToolCalls
|
|
1065
|
+
};
|
|
1066
|
+
} else {
|
|
1067
|
+
const allowedTools = new Set(options.toolChoice.oneOf);
|
|
1068
|
+
tools = tools.filter(tool => allowedTools.has(tool.name));
|
|
1069
|
+
toolChoice = {
|
|
1070
|
+
type: options.toolChoice.mode === "required" ? "any" : "auto",
|
|
1071
|
+
disable_parallel_tool_use: config.disableParallelToolCalls
|
|
1072
|
+
};
|
|
1073
|
+
}
|
|
1074
|
+
return {
|
|
1075
|
+
betas,
|
|
1076
|
+
tools,
|
|
1077
|
+
toolChoice
|
|
1078
|
+
};
|
|
1079
|
+
});
|
|
1080
|
+
const groupMessages = prompt => {
|
|
1081
|
+
const messages = [];
|
|
1082
|
+
let current = undefined;
|
|
1083
|
+
for (const message of prompt.content) {
|
|
1084
|
+
switch (message.role) {
|
|
1085
|
+
case "system":
|
|
1086
|
+
{
|
|
1087
|
+
if (current?.type !== "system") {
|
|
1088
|
+
current = {
|
|
1089
|
+
type: "system",
|
|
1090
|
+
messages: []
|
|
1091
|
+
};
|
|
1092
|
+
messages.push(current);
|
|
1093
|
+
}
|
|
1094
|
+
current.messages.push(message);
|
|
1095
|
+
break;
|
|
1096
|
+
}
|
|
1097
|
+
case "assistant":
|
|
1098
|
+
{
|
|
1099
|
+
if (current?.type !== "assistant") {
|
|
1100
|
+
current = {
|
|
1101
|
+
type: "assistant",
|
|
1102
|
+
messages: []
|
|
1103
|
+
};
|
|
1104
|
+
messages.push(current);
|
|
1105
|
+
}
|
|
1106
|
+
current.messages.push(message);
|
|
1107
|
+
break;
|
|
1108
|
+
}
|
|
1109
|
+
case "tool":
|
|
1110
|
+
case "user":
|
|
1111
|
+
{
|
|
1112
|
+
if (current?.type !== "user") {
|
|
1113
|
+
current = {
|
|
1114
|
+
type: "user",
|
|
1115
|
+
messages: []
|
|
1116
|
+
};
|
|
1117
|
+
messages.push(current);
|
|
1118
|
+
}
|
|
1119
|
+
current.messages.push(message);
|
|
1120
|
+
break;
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
return messages;
|
|
1125
|
+
};
|
|
1126
|
+
const isCitationPart = part => {
|
|
1127
|
+
if (part.type === "file" && (part.mediaType === "application/pdf" || part.mediaType === "text/plain")) {
|
|
1128
|
+
return part.options.anthropic?.citations?.enabled ?? false;
|
|
1129
|
+
}
|
|
1130
|
+
return false;
|
|
1131
|
+
};
|
|
1132
|
+
const extractCitableDocuments = prompt => {
|
|
1133
|
+
const citableDocuments = [];
|
|
1134
|
+
for (const message of prompt.content) {
|
|
1135
|
+
if (message.role === "user") {
|
|
1136
|
+
for (const part of message.content) {
|
|
1137
|
+
if (isCitationPart(part)) {
|
|
1138
|
+
citableDocuments.push({
|
|
1139
|
+
title: part.fileName ?? "Untitled Document",
|
|
1140
|
+
fileName: part.fileName,
|
|
1141
|
+
mediaType: part.mediaType
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
return citableDocuments;
|
|
1148
|
+
};
|
|
1149
|
+
const getCacheControl = part => part.options.anthropic?.cacheControl;
|
|
1150
|
+
const getDocumentMetadata = part => {
|
|
1151
|
+
const options = part.options.anthropic;
|
|
1152
|
+
if (Predicate.isNotUndefined(options)) {
|
|
1153
|
+
return {
|
|
1154
|
+
title: options.documentTitle,
|
|
1155
|
+
context: options.documentContext
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1158
|
+
return undefined;
|
|
495
1159
|
};
|
|
1160
|
+
const shouldEnableCitations = part => part.options.anthropic?.citations?.enabled ?? false;
|
|
1161
|
+
const processCitation = /*#__PURE__*/Effect.fnUntraced(function* (citation, citableDocuments, idGenerator) {
|
|
1162
|
+
if (citation.type === "page_location" || citation.type === "char_location") {
|
|
1163
|
+
const citedDocument = citableDocuments[citation.document_index];
|
|
1164
|
+
if (Predicate.isNotUndefined(citedDocument)) {
|
|
1165
|
+
const id = yield* idGenerator.generateId();
|
|
1166
|
+
const metadata = citation.type === "char_location" ? {
|
|
1167
|
+
source: "document",
|
|
1168
|
+
type: citation.type,
|
|
1169
|
+
citedText: citation.cited_text,
|
|
1170
|
+
startCharIndex: citation.start_char_index,
|
|
1171
|
+
endCharIndex: citation.end_char_index
|
|
1172
|
+
} : {
|
|
1173
|
+
source: "document",
|
|
1174
|
+
type: citation.type,
|
|
1175
|
+
citedText: citation.cited_text,
|
|
1176
|
+
startPageNumber: citation.start_page_number,
|
|
1177
|
+
endPageNumber: citation.end_page_number
|
|
1178
|
+
};
|
|
1179
|
+
return {
|
|
1180
|
+
type: "source",
|
|
1181
|
+
sourceType: "document",
|
|
1182
|
+
id,
|
|
1183
|
+
mediaType: citedDocument.mediaType,
|
|
1184
|
+
title: citation.document_title ?? citedDocument.title,
|
|
1185
|
+
fileName: citedDocument.fileName,
|
|
1186
|
+
metadata: {
|
|
1187
|
+
anthropic: metadata
|
|
1188
|
+
}
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
if (citation.type === "web_search_result_location") {
|
|
1193
|
+
const id = yield* idGenerator.generateId();
|
|
1194
|
+
const metadata = {
|
|
1195
|
+
source: "url",
|
|
1196
|
+
citedText: citation.cited_text,
|
|
1197
|
+
encryptedIndex: citation.encrypted_index
|
|
1198
|
+
};
|
|
1199
|
+
return {
|
|
1200
|
+
type: "source",
|
|
1201
|
+
sourceType: "url",
|
|
1202
|
+
id,
|
|
1203
|
+
url: citation.url,
|
|
1204
|
+
title: citation.title ?? "Untitled",
|
|
1205
|
+
metadata: {
|
|
1206
|
+
anthropic: metadata
|
|
1207
|
+
}
|
|
1208
|
+
};
|
|
1209
|
+
}
|
|
1210
|
+
});
|
|
496
1211
|
//# sourceMappingURL=AnthropicLanguageModel.js.map
|