@simulacra-ai/anthropic 0.0.2 → 0.0.4
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 +23 -6
- package/dist/index.cjs +522 -0
- package/dist/index.cjs.map +1 -0
- package/dist/{anthropic-provider.d.ts → index.d.cts} +9 -5
- package/dist/index.d.ts +64 -2
- package/dist/index.js +494 -1
- package/dist/index.js.map +1 -1
- package/package.json +11 -5
- package/dist/anthropic-provider.d.ts.map +0 -1
- package/dist/anthropic-provider.js +0 -415
- package/dist/anthropic-provider.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Simulacra Anthropic Provider
|
|
2
2
|
|
|
3
|
-
Anthropic Claude
|
|
3
|
+
The Anthropic provider allows Simulacra to use Claude models via the Anthropic API, with support for extended thinking and prompt caching.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -15,8 +15,9 @@ import { Conversation } from "@simulacra-ai/core";
|
|
|
15
15
|
import { AnthropicProvider } from "@simulacra-ai/anthropic";
|
|
16
16
|
import Anthropic from "@anthropic-ai/sdk";
|
|
17
17
|
|
|
18
|
+
// create a provider and conversation
|
|
18
19
|
const provider = new AnthropicProvider(new Anthropic(), { model: MODEL_NAME });
|
|
19
|
-
|
|
20
|
+
using conversation = new Conversation(provider);
|
|
20
21
|
```
|
|
21
22
|
|
|
22
23
|
### AnthropicProviderConfig
|
|
@@ -27,14 +28,30 @@ interface AnthropicProviderConfig {
|
|
|
27
28
|
max_tokens?: number;
|
|
28
29
|
thinking?: { enable: boolean; budget_tokens?: number };
|
|
29
30
|
prompt_caching?: { system_prompt?: boolean; toolkit?: boolean };
|
|
31
|
+
claude_code_auth?: boolean;
|
|
30
32
|
}
|
|
31
33
|
```
|
|
32
34
|
|
|
33
35
|
Additional properties (`temperature`, `top_p`, etc.) spread into the API request.
|
|
34
36
|
|
|
37
|
+
If `max_tokens` is not set, it defaults to 8192.
|
|
38
|
+
|
|
39
|
+
## Claude Code Auth
|
|
40
|
+
|
|
41
|
+
When Claude Code is installed and authenticated, its stored credentials can be used instead of managing API keys. Setting `claude_code_auth: true` causes the provider to use tokens from Claude Code's stored credentials, automatically managing token lifetime and renewal.
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
const provider = new AnthropicProvider(new Anthropic(), {
|
|
45
|
+
model,
|
|
46
|
+
claude_code_auth: true,
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Claude Code auth is well-suited for local development and personal tooling where a Claude subscription is already active. Production systems should use API key authentication.
|
|
51
|
+
|
|
35
52
|
## Extended Thinking
|
|
36
53
|
|
|
37
|
-
|
|
54
|
+
Extended thinking captures the model's chain-of-thought reasoning as `ThinkingMessageContent` blocks in the conversation history. This makes the model's reasoning process visible and accessible alongside its regular output.
|
|
38
55
|
|
|
39
56
|
```typescript
|
|
40
57
|
const provider = new AnthropicProvider(new Anthropic(), {
|
|
@@ -44,11 +61,11 @@ const provider = new AnthropicProvider(new Anthropic(), {
|
|
|
44
61
|
});
|
|
45
62
|
```
|
|
46
63
|
|
|
47
|
-
Both `thinking` and `redacted_thinking` blocks from the API are converted to Simulacra's `ThinkingMessageContent` type.
|
|
64
|
+
Both `thinking` and `redacted_thinking` blocks from the API are converted to Simulacra's `ThinkingMessageContent` type.
|
|
48
65
|
|
|
49
66
|
## Prompt Caching
|
|
50
67
|
|
|
51
|
-
Prompt caching is enabled by default. The provider adds `cache_control` markers to the system prompt and tool definitions, avoiding re-processing static content on every turn.
|
|
68
|
+
Prompt caching is enabled by default. The provider adds `cache_control` markers to the system prompt and tool definitions, avoiding re-processing static content on every turn. Multi-turn conversations benefit because subsequent turns read from the cache at a reduced rate.
|
|
52
69
|
|
|
53
70
|
```typescript
|
|
54
71
|
const provider = new AnthropicProvider(new Anthropic(), {
|
|
@@ -61,7 +78,7 @@ const provider = new AnthropicProvider(new Anthropic(), {
|
|
|
61
78
|
});
|
|
62
79
|
```
|
|
63
80
|
|
|
64
|
-
Cache writes cost slightly more per token than standard requests.
|
|
81
|
+
Cache writes cost slightly more per token than standard requests. Caching can be disabled by setting both flags to `false`.
|
|
65
82
|
|
|
66
83
|
## License
|
|
67
84
|
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AnthropicProvider: () => AnthropicProvider
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/anthropic-provider.ts
|
|
28
|
+
var import_node_fs = require("fs");
|
|
29
|
+
var import_node_os = require("os");
|
|
30
|
+
var import_node_path = require("path");
|
|
31
|
+
var claude_oauth = null;
|
|
32
|
+
var claude_creds_path = null;
|
|
33
|
+
var claude_request_options_promise = null;
|
|
34
|
+
var AnthropicProvider = class _AnthropicProvider {
|
|
35
|
+
#sdk;
|
|
36
|
+
#config;
|
|
37
|
+
context_transformers;
|
|
38
|
+
/**
|
|
39
|
+
* Creates a new Anthropic provider instance.
|
|
40
|
+
*
|
|
41
|
+
* @param sdk - The initialized Anthropic SDK client.
|
|
42
|
+
* @param config - Configuration options for the provider.
|
|
43
|
+
* @param context_transformers - Provider-level context transformers.
|
|
44
|
+
*/
|
|
45
|
+
constructor(sdk, config, context_transformers = []) {
|
|
46
|
+
this.#sdk = sdk;
|
|
47
|
+
this.#config = config;
|
|
48
|
+
this.context_transformers = context_transformers;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Executes a model request and streams the response through the provided receiver.
|
|
52
|
+
*
|
|
53
|
+
* @param request - The request containing messages, tools, and system prompt.
|
|
54
|
+
* @param receiver - The receiver that handles streaming events.
|
|
55
|
+
* @param cancellation - Token to signal cancellation of the request.
|
|
56
|
+
* @returns A promise that resolves when the request completes.
|
|
57
|
+
*/
|
|
58
|
+
async execute_request(request, receiver, cancellation) {
|
|
59
|
+
const {
|
|
60
|
+
model,
|
|
61
|
+
max_tokens,
|
|
62
|
+
thinking,
|
|
63
|
+
prompt_caching,
|
|
64
|
+
claude_code_auth: _,
|
|
65
|
+
...api_extras
|
|
66
|
+
} = this.#config;
|
|
67
|
+
const cache_system = prompt_caching?.system_prompt !== false;
|
|
68
|
+
const cache_tools = prompt_caching?.toolkit !== false;
|
|
69
|
+
const tools = request.tools.map((t) => to_anthropic_tool(t));
|
|
70
|
+
if (cache_tools && tools.length > 0) {
|
|
71
|
+
const last = tools.length - 1;
|
|
72
|
+
tools[last].cache_control = { type: "ephemeral" };
|
|
73
|
+
}
|
|
74
|
+
const system = cache_system && request.system ? [{ type: "text", text: request.system, cache_control: { type: "ephemeral" } }] : request.system;
|
|
75
|
+
const params = {
|
|
76
|
+
...api_extras,
|
|
77
|
+
model,
|
|
78
|
+
stream: true,
|
|
79
|
+
system,
|
|
80
|
+
max_tokens: max_tokens ?? 8192,
|
|
81
|
+
thinking: thinking?.enable && thinking?.budget_tokens ? {
|
|
82
|
+
type: "enabled",
|
|
83
|
+
budget_tokens: thinking.budget_tokens
|
|
84
|
+
} : {
|
|
85
|
+
type: "disabled"
|
|
86
|
+
},
|
|
87
|
+
tools,
|
|
88
|
+
messages: request.messages.map((m) => to_anthropic_message(m))
|
|
89
|
+
};
|
|
90
|
+
receiver.before_request({ params });
|
|
91
|
+
receiver.request_raw(params);
|
|
92
|
+
const response = await this.#sdk.messages.create(
|
|
93
|
+
params,
|
|
94
|
+
this.#config.claude_code_auth ? await ensure_claude_request_options() : void 0
|
|
95
|
+
);
|
|
96
|
+
this.#stream_response(response, receiver, cancellation);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Creates a clone of this provider with the same configuration.
|
|
100
|
+
*
|
|
101
|
+
* @returns A new provider instance with identical configuration.
|
|
102
|
+
*/
|
|
103
|
+
clone() {
|
|
104
|
+
return new _AnthropicProvider(this.#sdk, this.#config, this.context_transformers);
|
|
105
|
+
}
|
|
106
|
+
async #stream_response(stream, receiver, cancellation) {
|
|
107
|
+
try {
|
|
108
|
+
let usage = {};
|
|
109
|
+
let message = {
|
|
110
|
+
content: []
|
|
111
|
+
};
|
|
112
|
+
const json = [];
|
|
113
|
+
for await (const chunk of stream) {
|
|
114
|
+
if (cancellation.is_cancellation_requested) {
|
|
115
|
+
receiver.cancel();
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
receiver.stream_raw(chunk);
|
|
119
|
+
switch (chunk.type) {
|
|
120
|
+
case "message_start": {
|
|
121
|
+
usage = Object.fromEntries(
|
|
122
|
+
Object.entries(chunk.message.usage).filter(([, v]) => typeof v === "number")
|
|
123
|
+
);
|
|
124
|
+
message = chunk.message;
|
|
125
|
+
receiver.start_message({
|
|
126
|
+
usage,
|
|
127
|
+
message: from_anthropic_message(message)
|
|
128
|
+
});
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
case "message_delta": {
|
|
132
|
+
usage = {
|
|
133
|
+
...usage,
|
|
134
|
+
...Object.fromEntries(
|
|
135
|
+
Object.entries(chunk.usage).filter(([, v]) => typeof v === "number")
|
|
136
|
+
)
|
|
137
|
+
};
|
|
138
|
+
message = { ...message, ...chunk.delta };
|
|
139
|
+
receiver.update_message({
|
|
140
|
+
usage,
|
|
141
|
+
message: from_anthropic_message(message)
|
|
142
|
+
});
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
case "message_stop": {
|
|
146
|
+
const raw_stop = message.stop_reason ?? "end_turn";
|
|
147
|
+
const stop_reason = ["tool_use", "stop_sequence", "end_turn", "max_tokens", "error"].includes(raw_stop) ? raw_stop : "other";
|
|
148
|
+
receiver.complete_message({
|
|
149
|
+
usage,
|
|
150
|
+
stop_reason,
|
|
151
|
+
message: from_anthropic_message(message)
|
|
152
|
+
});
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
case "content_block_start": {
|
|
156
|
+
message.content[chunk.index] = chunk.content_block;
|
|
157
|
+
receiver.start_content({
|
|
158
|
+
usage,
|
|
159
|
+
message: from_anthropic_message(message),
|
|
160
|
+
content: from_anthropic_content(chunk.content_block)
|
|
161
|
+
});
|
|
162
|
+
receiver.update_message({
|
|
163
|
+
usage,
|
|
164
|
+
message: from_anthropic_message(message)
|
|
165
|
+
});
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
case "content_block_delta": {
|
|
169
|
+
switch (chunk.delta.type) {
|
|
170
|
+
case "text_delta": {
|
|
171
|
+
const content = message.content[chunk.index];
|
|
172
|
+
content.text += chunk.delta.text;
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
case "citations_delta": {
|
|
176
|
+
const content = message.content[chunk.index];
|
|
177
|
+
content.citations = [...content.citations ?? [], chunk.delta.citation];
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
case "thinking_delta": {
|
|
181
|
+
const content = message.content[chunk.index];
|
|
182
|
+
content.thinking += chunk.delta.thinking;
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
case "input_json_delta": {
|
|
186
|
+
if (!json[chunk.index]) {
|
|
187
|
+
json[chunk.index] = "";
|
|
188
|
+
}
|
|
189
|
+
json[chunk.index] += chunk.delta.partial_json;
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
case "signature_delta": {
|
|
193
|
+
const content = message.content[chunk.index];
|
|
194
|
+
content.signature = (content.signature ?? "") + chunk.delta.signature;
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
receiver.update_content({
|
|
199
|
+
usage,
|
|
200
|
+
message: from_anthropic_message(message),
|
|
201
|
+
content: from_anthropic_content(message.content[chunk.index])
|
|
202
|
+
});
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
case "content_block_stop": {
|
|
206
|
+
const content_block = message.content[chunk.index];
|
|
207
|
+
if (content_block.type === "tool_use" && json[chunk.index]) {
|
|
208
|
+
content_block.input = {
|
|
209
|
+
...content_block.input ?? {},
|
|
210
|
+
...JSON.parse(json[chunk.index])
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
receiver.complete_content({
|
|
214
|
+
usage,
|
|
215
|
+
message: from_anthropic_message(message),
|
|
216
|
+
content: from_anthropic_content(content_block)
|
|
217
|
+
});
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
receiver.response_raw(message);
|
|
223
|
+
} catch (error) {
|
|
224
|
+
receiver.error(error);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
function parameter_to_json_schema(param) {
|
|
229
|
+
switch (param.type) {
|
|
230
|
+
case "object": {
|
|
231
|
+
const properties = {};
|
|
232
|
+
const required = [];
|
|
233
|
+
for (const [key, child] of Object.entries(param.properties)) {
|
|
234
|
+
properties[key] = parameter_to_json_schema(child);
|
|
235
|
+
if (child.required) {
|
|
236
|
+
required.push(key);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return {
|
|
240
|
+
type: "object",
|
|
241
|
+
...param.description ? { description: param.description } : {},
|
|
242
|
+
...Object.keys(properties).length ? { properties } : {},
|
|
243
|
+
...required.length ? { required } : {}
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
case "array":
|
|
247
|
+
return {
|
|
248
|
+
type: "array",
|
|
249
|
+
...param.description ? { description: param.description } : {},
|
|
250
|
+
items: parameter_to_json_schema(param.items)
|
|
251
|
+
};
|
|
252
|
+
case "number":
|
|
253
|
+
return {
|
|
254
|
+
type: "number",
|
|
255
|
+
...param.description ? { description: param.description } : {}
|
|
256
|
+
};
|
|
257
|
+
case "boolean":
|
|
258
|
+
return {
|
|
259
|
+
type: "boolean",
|
|
260
|
+
...param.description ? { description: param.description } : {}
|
|
261
|
+
};
|
|
262
|
+
case "string":
|
|
263
|
+
return "enum" in param && param.enum ? {
|
|
264
|
+
type: "string",
|
|
265
|
+
enum: param.enum,
|
|
266
|
+
...param.description ? { description: param.description } : {}
|
|
267
|
+
} : { type: "string", ...param.description ? { description: param.description } : {} };
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
function to_anthropic_tool(tool) {
|
|
271
|
+
const properties = {};
|
|
272
|
+
const required = [];
|
|
273
|
+
for (const param of tool.parameters) {
|
|
274
|
+
const schema = parameter_to_json_schema(param);
|
|
275
|
+
if (param.description) {
|
|
276
|
+
schema.description = param.description;
|
|
277
|
+
}
|
|
278
|
+
properties[param.name] = schema;
|
|
279
|
+
if (param.required) {
|
|
280
|
+
required.push(param.name);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
name: tool.name,
|
|
285
|
+
description: tool.description,
|
|
286
|
+
input_schema: {
|
|
287
|
+
type: "object",
|
|
288
|
+
...Object.keys(properties).length ? { properties } : {},
|
|
289
|
+
...required.length ? { required } : {}
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
function from_anthropic_message(message) {
|
|
294
|
+
if (typeof message.content === "string") {
|
|
295
|
+
return {
|
|
296
|
+
role: message.role,
|
|
297
|
+
content: [
|
|
298
|
+
{
|
|
299
|
+
type: "text",
|
|
300
|
+
text: message.content
|
|
301
|
+
}
|
|
302
|
+
]
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
return {
|
|
306
|
+
role: message.role,
|
|
307
|
+
content: (message.content ?? []).map(
|
|
308
|
+
(c) => from_anthropic_content(c, Array.isArray(message.content) ? message.content : void 0)
|
|
309
|
+
)
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
function from_anthropic_content(content, allContent) {
|
|
313
|
+
switch (content.type) {
|
|
314
|
+
case "text": {
|
|
315
|
+
const { type: _, text, ...extended } = content;
|
|
316
|
+
return {
|
|
317
|
+
type: "text",
|
|
318
|
+
text,
|
|
319
|
+
extended
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
case "tool_use": {
|
|
323
|
+
const { type: _, id, name, input, ...extended } = content;
|
|
324
|
+
return {
|
|
325
|
+
type: "tool",
|
|
326
|
+
tool_request_id: id,
|
|
327
|
+
tool: name,
|
|
328
|
+
params: input,
|
|
329
|
+
extended
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
case "tool_result": {
|
|
333
|
+
const { type: _, tool_use_id, content: tool_content, ...extended } = content;
|
|
334
|
+
let tool_name = "";
|
|
335
|
+
if (allContent) {
|
|
336
|
+
const matching = allContent.find(
|
|
337
|
+
(c) => c.type === "tool_use" && "id" in c && c.id === tool_use_id
|
|
338
|
+
);
|
|
339
|
+
if (matching) {
|
|
340
|
+
tool_name = matching.name ?? "";
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return {
|
|
344
|
+
type: "tool_result",
|
|
345
|
+
tool_request_id: tool_use_id,
|
|
346
|
+
tool: tool_name,
|
|
347
|
+
result: typeof tool_content === "string" ? (() => {
|
|
348
|
+
try {
|
|
349
|
+
return JSON.parse(tool_content);
|
|
350
|
+
} catch {
|
|
351
|
+
return { text: tool_content };
|
|
352
|
+
}
|
|
353
|
+
})() : tool_content,
|
|
354
|
+
extended
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
case "thinking": {
|
|
358
|
+
const { type: _, thinking, ...extended } = content;
|
|
359
|
+
return {
|
|
360
|
+
type: "thinking",
|
|
361
|
+
thought: thinking,
|
|
362
|
+
extended
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
case "redacted_thinking": {
|
|
366
|
+
const { type: _, ...extended } = content;
|
|
367
|
+
return {
|
|
368
|
+
type: "thinking",
|
|
369
|
+
thought: extended.data,
|
|
370
|
+
extended
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
default:
|
|
374
|
+
return {
|
|
375
|
+
type: "raw",
|
|
376
|
+
model_kind: "anthropic",
|
|
377
|
+
data: JSON.stringify(content)
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
function to_anthropic_message(message) {
|
|
382
|
+
return {
|
|
383
|
+
role: message.role,
|
|
384
|
+
content: message.content.length === 1 && message.content[0].type === "text" ? message.content[0].text : message.content.map((c) => to_anthropic_content(c))
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
function to_anthropic_content(content) {
|
|
388
|
+
switch (content.type) {
|
|
389
|
+
case "text":
|
|
390
|
+
return {
|
|
391
|
+
type: "text",
|
|
392
|
+
text: content.text,
|
|
393
|
+
citations: Array.isArray(content.extended?.citations) ? content.extended.citations : []
|
|
394
|
+
};
|
|
395
|
+
case "tool":
|
|
396
|
+
return {
|
|
397
|
+
type: "tool_use",
|
|
398
|
+
id: content.tool_request_id,
|
|
399
|
+
name: content.tool,
|
|
400
|
+
input: content.params
|
|
401
|
+
};
|
|
402
|
+
case "raw":
|
|
403
|
+
if (content.model_kind !== "anthropic") {
|
|
404
|
+
return {
|
|
405
|
+
type: "text",
|
|
406
|
+
text: content.data
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
try {
|
|
410
|
+
return {
|
|
411
|
+
...JSON.parse(content.data)
|
|
412
|
+
};
|
|
413
|
+
} catch {
|
|
414
|
+
return {
|
|
415
|
+
data: content.data
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
case "tool_result":
|
|
419
|
+
return {
|
|
420
|
+
type: "tool_result",
|
|
421
|
+
tool_use_id: content.tool_request_id,
|
|
422
|
+
is_error: content.result.result === false ? true : void 0,
|
|
423
|
+
content: JSON.stringify(content.result)
|
|
424
|
+
};
|
|
425
|
+
case "thinking":
|
|
426
|
+
if (!content.extended?.signature) {
|
|
427
|
+
return {
|
|
428
|
+
type: "text",
|
|
429
|
+
text: content.thought
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
return {
|
|
433
|
+
type: "thinking",
|
|
434
|
+
thinking: content.thought,
|
|
435
|
+
signature: content.extended?.signature
|
|
436
|
+
};
|
|
437
|
+
default:
|
|
438
|
+
throw new Error("unexpected content type");
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
function ensure_claude_request_options() {
|
|
442
|
+
if (!claude_oauth || !claude_creds_path) {
|
|
443
|
+
const { path: credsPath, oauth } = read_claude_credentials();
|
|
444
|
+
claude_oauth = oauth;
|
|
445
|
+
claude_creds_path = credsPath;
|
|
446
|
+
}
|
|
447
|
+
if (!claude_request_options_promise) {
|
|
448
|
+
claude_request_options_promise = refresh_claude_token(claude_creds_path, claude_oauth).then(
|
|
449
|
+
(token) => ({
|
|
450
|
+
headers: {
|
|
451
|
+
"x-api-key": null,
|
|
452
|
+
authorization: `Bearer ${token}`,
|
|
453
|
+
"anthropic-beta": "oauth-2025-04-20"
|
|
454
|
+
}
|
|
455
|
+
})
|
|
456
|
+
).finally(() => {
|
|
457
|
+
claude_request_options_promise = null;
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
return claude_request_options_promise;
|
|
461
|
+
}
|
|
462
|
+
function get_claude_config_dir() {
|
|
463
|
+
return process.env["CLAUDE_CONFIG_DIR"] || (0, import_node_path.join)((0, import_node_os.homedir)(), ".claude");
|
|
464
|
+
}
|
|
465
|
+
function read_claude_credentials() {
|
|
466
|
+
const configDir = get_claude_config_dir();
|
|
467
|
+
const credsPath = (0, import_node_path.join)(configDir, ".credentials.json");
|
|
468
|
+
let raw;
|
|
469
|
+
try {
|
|
470
|
+
raw = (0, import_node_fs.readFileSync)(credsPath, "utf8");
|
|
471
|
+
} catch (e) {
|
|
472
|
+
throw new Error(
|
|
473
|
+
`Could not read Claude Code credentials at ${credsPath}. Make sure Claude Code is installed and authenticated. (${e.message})`
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
let creds;
|
|
477
|
+
try {
|
|
478
|
+
creds = JSON.parse(raw);
|
|
479
|
+
} catch (e) {
|
|
480
|
+
throw new Error(
|
|
481
|
+
`Invalid JSON in Claude Code credentials at ${credsPath}. (${e.message})`
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
if (!creds.claudeAiOauth) {
|
|
485
|
+
throw new Error(`No OAuth credentials found in ${credsPath}.`);
|
|
486
|
+
}
|
|
487
|
+
return { path: credsPath, oauth: creds.claudeAiOauth };
|
|
488
|
+
}
|
|
489
|
+
async function refresh_claude_token(credsPath, oauth) {
|
|
490
|
+
if (oauth.expiresAt > Date.now() + 6e4) {
|
|
491
|
+
return oauth.accessToken;
|
|
492
|
+
}
|
|
493
|
+
const res = await fetch("https://api.anthropic.com/v1/oauth/token", {
|
|
494
|
+
method: "POST",
|
|
495
|
+
headers: { "Content-Type": "application/json" },
|
|
496
|
+
body: JSON.stringify({
|
|
497
|
+
grant_type: "refresh_token",
|
|
498
|
+
refresh_token: oauth.refreshToken
|
|
499
|
+
})
|
|
500
|
+
});
|
|
501
|
+
if (!res.ok) {
|
|
502
|
+
const body = await res.text();
|
|
503
|
+
throw new Error(`Claude Code OAuth token refresh failed (${res.status}): ${body}`);
|
|
504
|
+
}
|
|
505
|
+
const data = await res.json();
|
|
506
|
+
oauth.accessToken = data.access_token;
|
|
507
|
+
oauth.refreshToken = data.refresh_token || oauth.refreshToken;
|
|
508
|
+
oauth.expiresAt = Date.now() + data.expires_in * 1e3;
|
|
509
|
+
try {
|
|
510
|
+
(0, import_node_fs.copyFileSync)(credsPath, `${credsPath}.${Date.now()}.bak`);
|
|
511
|
+
const creds = JSON.parse((0, import_node_fs.readFileSync)(credsPath, "utf8"));
|
|
512
|
+
creds.claudeAiOauth = { ...oauth };
|
|
513
|
+
(0, import_node_fs.writeFileSync)(credsPath, JSON.stringify(creds, null, 2));
|
|
514
|
+
} catch {
|
|
515
|
+
}
|
|
516
|
+
return data.access_token;
|
|
517
|
+
}
|
|
518
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
519
|
+
0 && (module.exports = {
|
|
520
|
+
AnthropicProvider
|
|
521
|
+
});
|
|
522
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/anthropic-provider.ts"],"sourcesContent":["export { AnthropicProvider, type AnthropicProviderConfig } from \"./anthropic-provider.ts\";\n","import Anthropic from \"@anthropic-ai/sdk\";\nimport { readFileSync, writeFileSync, copyFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport type {\n AssistantContent,\n AssistantMessage,\n CancellationToken,\n Content,\n Message,\n ModelProvider,\n ModelRequest,\n ParameterType,\n ProviderContextTransformer,\n StreamReceiver,\n ToolDefinition,\n} from \"@simulacra-ai/core\";\n\n/**\n * Configuration options for the Anthropic provider.\n */\nexport interface AnthropicProviderConfig extends Record<string, unknown> {\n /** The model identifier to use. */\n model: string;\n /** The maximum number of tokens to generate in the response. */\n max_tokens?: number;\n /** Configuration for extended thinking mode. */\n thinking?: {\n /** Whether to enable extended thinking. */\n enable: boolean;\n /** The token budget allocated for thinking. */\n budget_tokens?: number;\n };\n /** Configuration for prompt caching. Enabled by default when omitted. Cache writes cost more per token than standard requests, but cache reads on subsequent turns cost less. */\n prompt_caching?: {\n /** Whether to cache the system prompt. */\n system_prompt?: boolean;\n /** Whether to cache the tool definitions. */\n toolkit?: boolean;\n };\n /** Use Claude Code's stored OAuth credentials for authentication. When true, the provider reads tokens from Claude Code's credentials file and refreshes them automatically. */\n claude_code_auth?: boolean;\n}\n\ninterface ClaudeCodeOAuth {\n accessToken: string;\n refreshToken: string;\n expiresAt: number;\n [key: string]: unknown;\n}\n\nlet claude_oauth: ClaudeCodeOAuth | null = null;\nlet claude_creds_path: string | null = null;\nlet claude_request_options_promise: Promise<Anthropic.RequestOptions> | null = null;\n\n/**\n * Model provider implementation for Anthropic's Claude models.\n *\n * This provider wraps the Anthropic SDK to provide streaming completions with support\n * for tool use, extended thinking, and prompt caching. It handles message formatting,\n * content streaming, and usage tracking according to the ModelProvider interface.\n */\nexport class AnthropicProvider implements ModelProvider {\n readonly #sdk: Anthropic;\n readonly #config: AnthropicProviderConfig;\n readonly context_transformers: ProviderContextTransformer[];\n\n /**\n * Creates a new Anthropic provider instance.\n *\n * @param sdk - The initialized Anthropic SDK client.\n * @param config - Configuration options for the provider.\n * @param context_transformers - Provider-level context transformers.\n */\n constructor(\n sdk: Anthropic,\n config: AnthropicProviderConfig,\n context_transformers: ProviderContextTransformer[] = [],\n ) {\n this.#sdk = sdk;\n this.#config = config;\n this.context_transformers = context_transformers;\n }\n\n /**\n * Executes a model request and streams the response through the provided receiver.\n *\n * @param request - The request containing messages, tools, and system prompt.\n * @param receiver - The receiver that handles streaming events.\n * @param cancellation - Token to signal cancellation of the request.\n * @returns A promise that resolves when the request completes.\n */\n async execute_request(\n request: ModelRequest,\n receiver: StreamReceiver,\n cancellation: CancellationToken,\n ): Promise<void> {\n const {\n model,\n max_tokens,\n thinking,\n prompt_caching,\n claude_code_auth: _,\n ...api_extras\n } = this.#config;\n const cache_system = prompt_caching?.system_prompt !== false;\n const cache_tools = prompt_caching?.toolkit !== false;\n\n const tools = request.tools.map((t) => to_anthropic_tool(t));\n\n if (cache_tools && tools.length > 0) {\n const last = tools.length - 1;\n (tools[last] as Anthropic.Messages.Tool).cache_control = { type: \"ephemeral\" };\n }\n\n const system: Anthropic.MessageCreateParamsStreaming[\"system\"] =\n cache_system && request.system\n ? [{ type: \"text\", text: request.system, cache_control: { type: \"ephemeral\" } }]\n : request.system;\n\n const params: Anthropic.MessageCreateParamsStreaming = {\n ...api_extras,\n model,\n stream: true,\n system,\n max_tokens: max_tokens ?? 8_192,\n thinking:\n thinking?.enable && thinking?.budget_tokens\n ? {\n type: \"enabled\",\n budget_tokens: thinking.budget_tokens,\n }\n : {\n type: \"disabled\",\n },\n tools,\n messages: request.messages.map((m) => to_anthropic_message(m)),\n };\n receiver.before_request({ params });\n receiver.request_raw(params);\n\n const response = await this.#sdk.messages.create(\n params,\n this.#config.claude_code_auth ? await ensure_claude_request_options() : undefined,\n );\n\n // Intentionally not awaited. Streaming is event-driven through the receiver.\n // The policy wraps only connection establishment; chunk processing flows\n // asynchronously via StreamListener events back to the conversation.\n this.#stream_response(response, receiver, cancellation);\n }\n\n /**\n * Creates a clone of this provider with the same configuration.\n *\n * @returns A new provider instance with identical configuration.\n */\n clone(): ModelProvider {\n return new AnthropicProvider(this.#sdk, this.#config, this.context_transformers);\n }\n\n async #stream_response(\n stream: AsyncIterable<Anthropic.Messages.RawMessageStreamEvent>,\n receiver: StreamReceiver,\n cancellation: CancellationToken,\n ) {\n try {\n let usage: Record<string, number> = {};\n let message: Partial<Anthropic.Message> & { content: Anthropic.ContentBlock[] } = {\n content: [],\n };\n const json: string[] = [];\n for await (const chunk of stream) {\n if (cancellation.is_cancellation_requested) {\n receiver.cancel();\n return;\n }\n receiver.stream_raw(chunk);\n switch (chunk.type) {\n case \"message_start\": {\n usage = Object.fromEntries(\n Object.entries(chunk.message.usage).filter(([, v]) => typeof v === \"number\"),\n ) as Record<string, number>;\n message = chunk.message;\n receiver.start_message({\n usage,\n message: from_anthropic_message(message) as AssistantMessage,\n });\n break;\n }\n case \"message_delta\": {\n usage = {\n ...usage,\n ...Object.fromEntries(\n Object.entries(chunk.usage).filter(([, v]) => typeof v === \"number\"),\n ),\n };\n message = { ...message, ...chunk.delta };\n receiver.update_message({\n usage,\n message: from_anthropic_message(message) as AssistantMessage,\n });\n break;\n }\n case \"message_stop\": {\n const raw_stop = message.stop_reason ?? \"end_turn\";\n const stop_reason = (\n [\"tool_use\", \"stop_sequence\", \"end_turn\", \"max_tokens\", \"error\"].includes(raw_stop)\n ? raw_stop\n : \"other\"\n ) as \"tool_use\" | \"stop_sequence\" | \"end_turn\" | \"max_tokens\" | \"error\" | \"other\";\n receiver.complete_message({\n usage,\n stop_reason,\n message: from_anthropic_message(message) as AssistantMessage,\n });\n break;\n }\n case \"content_block_start\": {\n message.content[chunk.index] = chunk.content_block;\n receiver.start_content({\n usage,\n message: from_anthropic_message(message) as AssistantMessage,\n content: from_anthropic_content(chunk.content_block) as Partial<AssistantContent>,\n });\n receiver.update_message({\n usage,\n message: from_anthropic_message(message) as AssistantMessage,\n });\n break;\n }\n case \"content_block_delta\": {\n switch (chunk.delta.type) {\n case \"text_delta\": {\n const content = message.content[chunk.index] as Anthropic.TextBlock;\n content.text += chunk.delta.text;\n break;\n }\n case \"citations_delta\": {\n const content = message.content[chunk.index] as Anthropic.TextBlock;\n content.citations = [...(content.citations ?? []), chunk.delta.citation];\n break;\n }\n case \"thinking_delta\": {\n const content = message.content[chunk.index] as Anthropic.ThinkingBlock;\n content.thinking += chunk.delta.thinking;\n break;\n }\n case \"input_json_delta\": {\n if (!json[chunk.index]) {\n json[chunk.index] = \"\";\n }\n json[chunk.index] += chunk.delta.partial_json;\n break;\n }\n case \"signature_delta\": {\n const content = message.content[chunk.index] as Anthropic.ThinkingBlock;\n content.signature = (content.signature ?? \"\") + chunk.delta.signature;\n break;\n }\n }\n receiver.update_content({\n usage,\n message: from_anthropic_message(message) as AssistantMessage,\n content: from_anthropic_content(message.content[chunk.index]) as AssistantContent,\n });\n break;\n }\n case \"content_block_stop\": {\n const content_block = message.content[chunk.index];\n if (content_block.type === \"tool_use\" && json[chunk.index]) {\n content_block.input = {\n ...(content_block.input ?? {}),\n ...JSON.parse(json[chunk.index]),\n };\n }\n receiver.complete_content({\n usage,\n message: from_anthropic_message(message) as AssistantMessage,\n content: from_anthropic_content(content_block) as AssistantContent,\n });\n break;\n }\n }\n }\n receiver.response_raw(message);\n } catch (error) {\n receiver.error(error);\n }\n }\n}\n\nfunction parameter_to_json_schema(param: ParameterType): Record<string, unknown> {\n switch (param.type) {\n case \"object\": {\n const properties: Record<string, Record<string, unknown>> = {};\n const required: string[] = [];\n for (const [key, child] of Object.entries(param.properties)) {\n properties[key] = parameter_to_json_schema(child);\n if (child.required) {\n required.push(key);\n }\n }\n return {\n type: \"object\",\n ...(param.description ? { description: param.description } : {}),\n ...(Object.keys(properties).length ? { properties } : {}),\n ...(required.length ? { required } : {}),\n };\n }\n case \"array\":\n return {\n type: \"array\",\n ...(param.description ? { description: param.description } : {}),\n items: parameter_to_json_schema(param.items),\n };\n case \"number\":\n return {\n type: \"number\",\n ...(param.description ? { description: param.description } : {}),\n };\n case \"boolean\":\n return {\n type: \"boolean\",\n ...(param.description ? { description: param.description } : {}),\n };\n case \"string\":\n return \"enum\" in param && param.enum\n ? {\n type: \"string\",\n enum: param.enum,\n ...(param.description ? { description: param.description } : {}),\n }\n : { type: \"string\", ...(param.description ? { description: param.description } : {}) };\n }\n}\n\nfunction to_anthropic_tool(tool: ToolDefinition): Anthropic.Messages.ToolUnion {\n const properties: Record<string, Record<string, unknown>> = {};\n const required: string[] = [];\n\n for (const param of tool.parameters) {\n const schema = parameter_to_json_schema(param);\n if (param.description) {\n schema.description = param.description;\n }\n properties[param.name] = schema;\n if (param.required) {\n required.push(param.name);\n }\n }\n\n return {\n name: tool.name,\n description: tool.description,\n input_schema: {\n type: \"object\",\n ...(Object.keys(properties).length ? { properties } : {}),\n ...(required.length ? { required } : {}),\n },\n };\n}\n\nfunction from_anthropic_message(message: Partial<Anthropic.MessageParam>) {\n if (typeof message.content === \"string\") {\n return {\n role: message.role,\n content: [\n {\n type: \"text\",\n text: message.content,\n },\n ],\n } as Message;\n }\n return {\n role: message.role,\n content: (message.content ?? []).map((c) =>\n from_anthropic_content(c, Array.isArray(message.content) ? message.content : undefined),\n ),\n } as Message;\n}\n\nfunction from_anthropic_content(\n content: Partial<Anthropic.ContentBlockParam>,\n allContent?: Partial<Anthropic.ContentBlockParam>[],\n) {\n switch (content.type) {\n case \"text\": {\n const { type: _, text, ...extended } = content;\n return {\n type: \"text\",\n text,\n extended,\n };\n }\n case \"tool_use\": {\n const { type: _, id, name, input, ...extended } = content;\n return {\n type: \"tool\",\n tool_request_id: id,\n tool: name,\n params: input as Record<string, unknown>,\n extended,\n };\n }\n case \"tool_result\": {\n const { type: _, tool_use_id, content: tool_content, ...extended } = content;\n let tool_name = \"\";\n if (allContent) {\n const matching = allContent.find(\n (c): c is Partial<Anthropic.Messages.ToolUseBlockParam> =>\n c.type === \"tool_use\" && \"id\" in c && c.id === tool_use_id,\n );\n if (matching) {\n tool_name = matching.name ?? \"\";\n }\n }\n return {\n type: \"tool_result\",\n tool_request_id: tool_use_id,\n tool: tool_name,\n result:\n typeof tool_content === \"string\"\n ? (() => {\n try {\n return JSON.parse(tool_content as string);\n } catch {\n return { text: tool_content };\n }\n })()\n : tool_content,\n extended,\n };\n }\n case \"thinking\": {\n const { type: _, thinking, ...extended } = content;\n return {\n type: \"thinking\",\n thought: thinking,\n extended,\n };\n }\n case \"redacted_thinking\": {\n const { type: _, ...extended } = content;\n return {\n type: \"thinking\",\n thought: extended.data,\n extended,\n };\n }\n default:\n return {\n type: \"raw\",\n model_kind: \"anthropic\",\n data: JSON.stringify(content),\n };\n }\n}\n\nfunction to_anthropic_message(message: Readonly<Message>) {\n return {\n role: message.role,\n content:\n message.content.length === 1 && message.content[0].type === \"text\"\n ? message.content[0].text\n : message.content.map((c) => to_anthropic_content(c)),\n };\n}\n\nfunction to_anthropic_content(content: Readonly<Content>) {\n switch (content.type) {\n case \"text\":\n return {\n type: \"text\",\n text: content.text,\n citations: Array.isArray(content.extended?.citations) ? content.extended.citations : [],\n };\n case \"tool\":\n return {\n type: \"tool_use\",\n id: content.tool_request_id,\n name: content.tool,\n input: content.params,\n };\n case \"raw\":\n if (content.model_kind !== \"anthropic\") {\n return {\n type: \"text\",\n text: content.data,\n };\n }\n try {\n return {\n ...JSON.parse(content.data),\n };\n } catch {\n return {\n data: content.data,\n };\n }\n case \"tool_result\":\n return {\n type: \"tool_result\",\n tool_use_id: content.tool_request_id,\n is_error: content.result.result === false ? true : undefined,\n content: JSON.stringify(content.result),\n };\n case \"thinking\":\n if (!content.extended?.signature) {\n return {\n type: \"text\",\n text: content.thought,\n };\n }\n return {\n type: \"thinking\",\n thinking: content.thought,\n signature: content.extended?.signature,\n };\n default:\n throw new Error(\"unexpected content type\");\n }\n}\n\nfunction ensure_claude_request_options(): Promise<Anthropic.RequestOptions> {\n if (!claude_oauth || !claude_creds_path) {\n const { path: credsPath, oauth } = read_claude_credentials();\n claude_oauth = oauth;\n claude_creds_path = credsPath;\n }\n if (!claude_request_options_promise) {\n claude_request_options_promise = refresh_claude_token(claude_creds_path, claude_oauth)\n .then(\n (token) =>\n ({\n headers: {\n \"x-api-key\": null,\n authorization: `Bearer ${token}`,\n \"anthropic-beta\": \"oauth-2025-04-20\",\n },\n }) as Anthropic.RequestOptions,\n )\n .finally(() => {\n claude_request_options_promise = null;\n });\n }\n return claude_request_options_promise;\n}\n\nfunction get_claude_config_dir(): string {\n return process.env[\"CLAUDE_CONFIG_DIR\"] || join(homedir(), \".claude\");\n}\n\nfunction read_claude_credentials(): { path: string; oauth: ClaudeCodeOAuth } {\n const configDir = get_claude_config_dir();\n const credsPath = join(configDir, \".credentials.json\");\n\n let raw: string;\n try {\n raw = readFileSync(credsPath, \"utf8\");\n } catch (e) {\n throw new Error(\n `Could not read Claude Code credentials at ${credsPath}. ` +\n `Make sure Claude Code is installed and authenticated. ` +\n `(${(e as Error).message})`,\n );\n }\n\n let creds: Record<string, unknown>;\n try {\n creds = JSON.parse(raw);\n } catch (e) {\n throw new Error(\n `Invalid JSON in Claude Code credentials at ${credsPath}. (${(e as Error).message})`,\n );\n }\n if (!creds.claudeAiOauth) {\n throw new Error(`No OAuth credentials found in ${credsPath}.`);\n }\n\n return { path: credsPath, oauth: creds.claudeAiOauth as ClaudeCodeOAuth };\n}\n\nasync function refresh_claude_token(credsPath: string, oauth: ClaudeCodeOAuth): Promise<string> {\n if (oauth.expiresAt > Date.now() + 60_000) {\n return oauth.accessToken;\n }\n\n const res = await fetch(\"https://api.anthropic.com/v1/oauth/token\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n grant_type: \"refresh_token\",\n refresh_token: oauth.refreshToken,\n }),\n });\n\n if (!res.ok) {\n const body = await res.text();\n throw new Error(`Claude Code OAuth token refresh failed (${res.status}): ${body}`);\n }\n\n const data = (await res.json()) as {\n access_token: string;\n refresh_token?: string;\n expires_in: number;\n };\n\n // Update in-memory state first so the token is usable even if file ops fail\n oauth.accessToken = data.access_token;\n oauth.refreshToken = data.refresh_token || oauth.refreshToken;\n oauth.expiresAt = Date.now() + data.expires_in * 1000;\n\n try {\n copyFileSync(credsPath, `${credsPath}.${Date.now()}.bak`);\n const creds = JSON.parse(readFileSync(credsPath, \"utf8\"));\n creds.claudeAiOauth = { ...oauth };\n writeFileSync(credsPath, JSON.stringify(creds, null, 2));\n } catch {\n // File persistence is best-effort; in-memory state is already updated\n }\n\n return data.access_token;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,qBAA0D;AAC1D,qBAAwB;AACxB,uBAAqB;AAiDrB,IAAI,eAAuC;AAC3C,IAAI,oBAAmC;AACvC,IAAI,iCAA2E;AASxE,IAAM,oBAAN,MAAM,mBAA2C;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAST,YACE,KACA,QACA,uBAAqD,CAAC,GACtD;AACA,SAAK,OAAO;AACZ,SAAK,UAAU;AACf,SAAK,uBAAuB;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,gBACJ,SACA,UACA,cACe;AACf,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,kBAAkB;AAAA,MAClB,GAAG;AAAA,IACL,IAAI,KAAK;AACT,UAAM,eAAe,gBAAgB,kBAAkB;AACvD,UAAM,cAAc,gBAAgB,YAAY;AAEhD,UAAM,QAAQ,QAAQ,MAAM,IAAI,CAAC,MAAM,kBAAkB,CAAC,CAAC;AAE3D,QAAI,eAAe,MAAM,SAAS,GAAG;AACnC,YAAM,OAAO,MAAM,SAAS;AAC5B,MAAC,MAAM,IAAI,EAA8B,gBAAgB,EAAE,MAAM,YAAY;AAAA,IAC/E;AAEA,UAAM,SACJ,gBAAgB,QAAQ,SACpB,CAAC,EAAE,MAAM,QAAQ,MAAM,QAAQ,QAAQ,eAAe,EAAE,MAAM,YAAY,EAAE,CAAC,IAC7E,QAAQ;AAEd,UAAM,SAAiD;AAAA,MACrD,GAAG;AAAA,MACH;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA,YAAY,cAAc;AAAA,MAC1B,UACE,UAAU,UAAU,UAAU,gBAC1B;AAAA,QACE,MAAM;AAAA,QACN,eAAe,SAAS;AAAA,MAC1B,IACA;AAAA,QACE,MAAM;AAAA,MACR;AAAA,MACN;AAAA,MACA,UAAU,QAAQ,SAAS,IAAI,CAAC,MAAM,qBAAqB,CAAC,CAAC;AAAA,IAC/D;AACA,aAAS,eAAe,EAAE,OAAO,CAAC;AAClC,aAAS,YAAY,MAAM;AAE3B,UAAM,WAAW,MAAM,KAAK,KAAK,SAAS;AAAA,MACxC;AAAA,MACA,KAAK,QAAQ,mBAAmB,MAAM,8BAA8B,IAAI;AAAA,IAC1E;AAKA,SAAK,iBAAiB,UAAU,UAAU,YAAY;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAuB;AACrB,WAAO,IAAI,mBAAkB,KAAK,MAAM,KAAK,SAAS,KAAK,oBAAoB;AAAA,EACjF;AAAA,EAEA,MAAM,iBACJ,QACA,UACA,cACA;AACA,QAAI;AACF,UAAI,QAAgC,CAAC;AACrC,UAAI,UAA8E;AAAA,QAChF,SAAS,CAAC;AAAA,MACZ;AACA,YAAM,OAAiB,CAAC;AACxB,uBAAiB,SAAS,QAAQ;AAChC,YAAI,aAAa,2BAA2B;AAC1C,mBAAS,OAAO;AAChB;AAAA,QACF;AACA,iBAAS,WAAW,KAAK;AACzB,gBAAQ,MAAM,MAAM;AAAA,UAClB,KAAK,iBAAiB;AACpB,oBAAQ,OAAO;AAAA,cACb,OAAO,QAAQ,MAAM,QAAQ,KAAK,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,OAAO,MAAM,QAAQ;AAAA,YAC7E;AACA,sBAAU,MAAM;AAChB,qBAAS,cAAc;AAAA,cACrB;AAAA,cACA,SAAS,uBAAuB,OAAO;AAAA,YACzC,CAAC;AACD;AAAA,UACF;AAAA,UACA,KAAK,iBAAiB;AACpB,oBAAQ;AAAA,cACN,GAAG;AAAA,cACH,GAAG,OAAO;AAAA,gBACR,OAAO,QAAQ,MAAM,KAAK,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,OAAO,MAAM,QAAQ;AAAA,cACrE;AAAA,YACF;AACA,sBAAU,EAAE,GAAG,SAAS,GAAG,MAAM,MAAM;AACvC,qBAAS,eAAe;AAAA,cACtB;AAAA,cACA,SAAS,uBAAuB,OAAO;AAAA,YACzC,CAAC;AACD;AAAA,UACF;AAAA,UACA,KAAK,gBAAgB;AACnB,kBAAM,WAAW,QAAQ,eAAe;AACxC,kBAAM,cACJ,CAAC,YAAY,iBAAiB,YAAY,cAAc,OAAO,EAAE,SAAS,QAAQ,IAC9E,WACA;AAEN,qBAAS,iBAAiB;AAAA,cACxB;AAAA,cACA;AAAA,cACA,SAAS,uBAAuB,OAAO;AAAA,YACzC,CAAC;AACD;AAAA,UACF;AAAA,UACA,KAAK,uBAAuB;AAC1B,oBAAQ,QAAQ,MAAM,KAAK,IAAI,MAAM;AACrC,qBAAS,cAAc;AAAA,cACrB;AAAA,cACA,SAAS,uBAAuB,OAAO;AAAA,cACvC,SAAS,uBAAuB,MAAM,aAAa;AAAA,YACrD,CAAC;AACD,qBAAS,eAAe;AAAA,cACtB;AAAA,cACA,SAAS,uBAAuB,OAAO;AAAA,YACzC,CAAC;AACD;AAAA,UACF;AAAA,UACA,KAAK,uBAAuB;AAC1B,oBAAQ,MAAM,MAAM,MAAM;AAAA,cACxB,KAAK,cAAc;AACjB,sBAAM,UAAU,QAAQ,QAAQ,MAAM,KAAK;AAC3C,wBAAQ,QAAQ,MAAM,MAAM;AAC5B;AAAA,cACF;AAAA,cACA,KAAK,mBAAmB;AACtB,sBAAM,UAAU,QAAQ,QAAQ,MAAM,KAAK;AAC3C,wBAAQ,YAAY,CAAC,GAAI,QAAQ,aAAa,CAAC,GAAI,MAAM,MAAM,QAAQ;AACvE;AAAA,cACF;AAAA,cACA,KAAK,kBAAkB;AACrB,sBAAM,UAAU,QAAQ,QAAQ,MAAM,KAAK;AAC3C,wBAAQ,YAAY,MAAM,MAAM;AAChC;AAAA,cACF;AAAA,cACA,KAAK,oBAAoB;AACvB,oBAAI,CAAC,KAAK,MAAM,KAAK,GAAG;AACtB,uBAAK,MAAM,KAAK,IAAI;AAAA,gBACtB;AACA,qBAAK,MAAM,KAAK,KAAK,MAAM,MAAM;AACjC;AAAA,cACF;AAAA,cACA,KAAK,mBAAmB;AACtB,sBAAM,UAAU,QAAQ,QAAQ,MAAM,KAAK;AAC3C,wBAAQ,aAAa,QAAQ,aAAa,MAAM,MAAM,MAAM;AAC5D;AAAA,cACF;AAAA,YACF;AACA,qBAAS,eAAe;AAAA,cACtB;AAAA,cACA,SAAS,uBAAuB,OAAO;AAAA,cACvC,SAAS,uBAAuB,QAAQ,QAAQ,MAAM,KAAK,CAAC;AAAA,YAC9D,CAAC;AACD;AAAA,UACF;AAAA,UACA,KAAK,sBAAsB;AACzB,kBAAM,gBAAgB,QAAQ,QAAQ,MAAM,KAAK;AACjD,gBAAI,cAAc,SAAS,cAAc,KAAK,MAAM,KAAK,GAAG;AAC1D,4BAAc,QAAQ;AAAA,gBACpB,GAAI,cAAc,SAAS,CAAC;AAAA,gBAC5B,GAAG,KAAK,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,cACjC;AAAA,YACF;AACA,qBAAS,iBAAiB;AAAA,cACxB;AAAA,cACA,SAAS,uBAAuB,OAAO;AAAA,cACvC,SAAS,uBAAuB,aAAa;AAAA,YAC/C,CAAC;AACD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,eAAS,aAAa,OAAO;AAAA,IAC/B,SAAS,OAAO;AACd,eAAS,MAAM,KAAK;AAAA,IACtB;AAAA,EACF;AACF;AAEA,SAAS,yBAAyB,OAA+C;AAC/E,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK,UAAU;AACb,YAAM,aAAsD,CAAC;AAC7D,YAAM,WAAqB,CAAC;AAC5B,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,UAAU,GAAG;AAC3D,mBAAW,GAAG,IAAI,yBAAyB,KAAK;AAChD,YAAI,MAAM,UAAU;AAClB,mBAAS,KAAK,GAAG;AAAA,QACnB;AAAA,MACF;AACA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,GAAI,MAAM,cAAc,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;AAAA,QAC9D,GAAI,OAAO,KAAK,UAAU,EAAE,SAAS,EAAE,WAAW,IAAI,CAAC;AAAA,QACvD,GAAI,SAAS,SAAS,EAAE,SAAS,IAAI,CAAC;AAAA,MACxC;AAAA,IACF;AAAA,IACA,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,GAAI,MAAM,cAAc,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;AAAA,QAC9D,OAAO,yBAAyB,MAAM,KAAK;AAAA,MAC7C;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,GAAI,MAAM,cAAc,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;AAAA,MAChE;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,GAAI,MAAM,cAAc,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;AAAA,MAChE;AAAA,IACF,KAAK;AACH,aAAO,UAAU,SAAS,MAAM,OAC5B;AAAA,QACE,MAAM;AAAA,QACN,MAAM,MAAM;AAAA,QACZ,GAAI,MAAM,cAAc,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;AAAA,MAChE,IACA,EAAE,MAAM,UAAU,GAAI,MAAM,cAAc,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC,EAAG;AAAA,EAC3F;AACF;AAEA,SAAS,kBAAkB,MAAoD;AAC7E,QAAM,aAAsD,CAAC;AAC7D,QAAM,WAAqB,CAAC;AAE5B,aAAW,SAAS,KAAK,YAAY;AACnC,UAAM,SAAS,yBAAyB,KAAK;AAC7C,QAAI,MAAM,aAAa;AACrB,aAAO,cAAc,MAAM;AAAA,IAC7B;AACA,eAAW,MAAM,IAAI,IAAI;AACzB,QAAI,MAAM,UAAU;AAClB,eAAS,KAAK,MAAM,IAAI;AAAA,IAC1B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM,KAAK;AAAA,IACX,aAAa,KAAK;AAAA,IAClB,cAAc;AAAA,MACZ,MAAM;AAAA,MACN,GAAI,OAAO,KAAK,UAAU,EAAE,SAAS,EAAE,WAAW,IAAI,CAAC;AAAA,MACvD,GAAI,SAAS,SAAS,EAAE,SAAS,IAAI,CAAC;AAAA,IACxC;AAAA,EACF;AACF;AAEA,SAAS,uBAAuB,SAA0C;AACxE,MAAI,OAAO,QAAQ,YAAY,UAAU;AACvC,WAAO;AAAA,MACL,MAAM,QAAQ;AAAA,MACd,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM,QAAQ;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AAAA,IACL,MAAM,QAAQ;AAAA,IACd,UAAU,QAAQ,WAAW,CAAC,GAAG;AAAA,MAAI,CAAC,MACpC,uBAAuB,GAAG,MAAM,QAAQ,QAAQ,OAAO,IAAI,QAAQ,UAAU,MAAS;AAAA,IACxF;AAAA,EACF;AACF;AAEA,SAAS,uBACP,SACA,YACA;AACA,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK,QAAQ;AACX,YAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,IAAI;AACvC,aAAO;AAAA,QACL,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,IACA,KAAK,YAAY;AACf,YAAM,EAAE,MAAM,GAAG,IAAI,MAAM,OAAO,GAAG,SAAS,IAAI;AAClD,aAAO;AAAA,QACL,MAAM;AAAA,QACN,iBAAiB;AAAA,QACjB,MAAM;AAAA,QACN,QAAQ;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,IACA,KAAK,eAAe;AAClB,YAAM,EAAE,MAAM,GAAG,aAAa,SAAS,cAAc,GAAG,SAAS,IAAI;AACrE,UAAI,YAAY;AAChB,UAAI,YAAY;AACd,cAAM,WAAW,WAAW;AAAA,UAC1B,CAAC,MACC,EAAE,SAAS,cAAc,QAAQ,KAAK,EAAE,OAAO;AAAA,QACnD;AACA,YAAI,UAAU;AACZ,sBAAY,SAAS,QAAQ;AAAA,QAC/B;AAAA,MACF;AACA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,iBAAiB;AAAA,QACjB,MAAM;AAAA,QACN,QACE,OAAO,iBAAiB,YACnB,MAAM;AACL,cAAI;AACF,mBAAO,KAAK,MAAM,YAAsB;AAAA,UAC1C,QAAQ;AACN,mBAAO,EAAE,MAAM,aAAa;AAAA,UAC9B;AAAA,QACF,GAAG,IACH;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAAA,IACA,KAAK,YAAY;AACf,YAAM,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,IAAI;AAC3C,aAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,IACA,KAAK,qBAAqB;AACxB,YAAM,EAAE,MAAM,GAAG,GAAG,SAAS,IAAI;AACjC,aAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,SAAS;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAAA,IACA;AACE,aAAO;AAAA,QACL,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,MAAM,KAAK,UAAU,OAAO;AAAA,MAC9B;AAAA,EACJ;AACF;AAEA,SAAS,qBAAqB,SAA4B;AACxD,SAAO;AAAA,IACL,MAAM,QAAQ;AAAA,IACd,SACE,QAAQ,QAAQ,WAAW,KAAK,QAAQ,QAAQ,CAAC,EAAE,SAAS,SACxD,QAAQ,QAAQ,CAAC,EAAE,OACnB,QAAQ,QAAQ,IAAI,CAAC,MAAM,qBAAqB,CAAC,CAAC;AAAA,EAC1D;AACF;AAEA,SAAS,qBAAqB,SAA4B;AACxD,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,MAAM,QAAQ;AAAA,QACd,WAAW,MAAM,QAAQ,QAAQ,UAAU,SAAS,IAAI,QAAQ,SAAS,YAAY,CAAC;AAAA,MACxF;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,IAAI,QAAQ;AAAA,QACZ,MAAM,QAAQ;AAAA,QACd,OAAO,QAAQ;AAAA,MACjB;AAAA,IACF,KAAK;AACH,UAAI,QAAQ,eAAe,aAAa;AACtC,eAAO;AAAA,UACL,MAAM;AAAA,UACN,MAAM,QAAQ;AAAA,QAChB;AAAA,MACF;AACA,UAAI;AACF,eAAO;AAAA,UACL,GAAG,KAAK,MAAM,QAAQ,IAAI;AAAA,QAC5B;AAAA,MACF,QAAQ;AACN,eAAO;AAAA,UACL,MAAM,QAAQ;AAAA,QAChB;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,aAAa,QAAQ;AAAA,QACrB,UAAU,QAAQ,OAAO,WAAW,QAAQ,OAAO;AAAA,QACnD,SAAS,KAAK,UAAU,QAAQ,MAAM;AAAA,MACxC;AAAA,IACF,KAAK;AACH,UAAI,CAAC,QAAQ,UAAU,WAAW;AAChC,eAAO;AAAA,UACL,MAAM;AAAA,UACN,MAAM,QAAQ;AAAA,QAChB;AAAA,MACF;AACA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,UAAU,QAAQ;AAAA,QAClB,WAAW,QAAQ,UAAU;AAAA,MAC/B;AAAA,IACF;AACE,YAAM,IAAI,MAAM,yBAAyB;AAAA,EAC7C;AACF;AAEA,SAAS,gCAAmE;AAC1E,MAAI,CAAC,gBAAgB,CAAC,mBAAmB;AACvC,UAAM,EAAE,MAAM,WAAW,MAAM,IAAI,wBAAwB;AAC3D,mBAAe;AACf,wBAAoB;AAAA,EACtB;AACA,MAAI,CAAC,gCAAgC;AACnC,qCAAiC,qBAAqB,mBAAmB,YAAY,EAClF;AAAA,MACC,CAAC,WACE;AAAA,QACC,SAAS;AAAA,UACP,aAAa;AAAA,UACb,eAAe,UAAU,KAAK;AAAA,UAC9B,kBAAkB;AAAA,QACpB;AAAA,MACF;AAAA,IACJ,EACC,QAAQ,MAAM;AACb,uCAAiC;AAAA,IACnC,CAAC;AAAA,EACL;AACA,SAAO;AACT;AAEA,SAAS,wBAAgC;AACvC,SAAO,QAAQ,IAAI,mBAAmB,SAAK,2BAAK,wBAAQ,GAAG,SAAS;AACtE;AAEA,SAAS,0BAAoE;AAC3E,QAAM,YAAY,sBAAsB;AACxC,QAAM,gBAAY,uBAAK,WAAW,mBAAmB;AAErD,MAAI;AACJ,MAAI;AACF,cAAM,6BAAa,WAAW,MAAM;AAAA,EACtC,SAAS,GAAG;AACV,UAAM,IAAI;AAAA,MACR,6CAA6C,SAAS,4DAE/C,EAAY,OAAO;AAAA,IAC5B;AAAA,EACF;AAEA,MAAI;AACJ,MAAI;AACF,YAAQ,KAAK,MAAM,GAAG;AAAA,EACxB,SAAS,GAAG;AACV,UAAM,IAAI;AAAA,MACR,8CAA8C,SAAS,MAAO,EAAY,OAAO;AAAA,IACnF;AAAA,EACF;AACA,MAAI,CAAC,MAAM,eAAe;AACxB,UAAM,IAAI,MAAM,iCAAiC,SAAS,GAAG;AAAA,EAC/D;AAEA,SAAO,EAAE,MAAM,WAAW,OAAO,MAAM,cAAiC;AAC1E;AAEA,eAAe,qBAAqB,WAAmB,OAAyC;AAC9F,MAAI,MAAM,YAAY,KAAK,IAAI,IAAI,KAAQ;AACzC,WAAO,MAAM;AAAA,EACf;AAEA,QAAM,MAAM,MAAM,MAAM,4CAA4C;AAAA,IAClE,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU;AAAA,MACnB,YAAY;AAAA,MACZ,eAAe,MAAM;AAAA,IACvB,CAAC;AAAA,EACH,CAAC;AAED,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,UAAM,IAAI,MAAM,2CAA2C,IAAI,MAAM,MAAM,IAAI,EAAE;AAAA,EACnF;AAEA,QAAM,OAAQ,MAAM,IAAI,KAAK;AAO7B,QAAM,cAAc,KAAK;AACzB,QAAM,eAAe,KAAK,iBAAiB,MAAM;AACjD,QAAM,YAAY,KAAK,IAAI,IAAI,KAAK,aAAa;AAEjD,MAAI;AACF,qCAAa,WAAW,GAAG,SAAS,IAAI,KAAK,IAAI,CAAC,MAAM;AACxD,UAAM,QAAQ,KAAK,UAAM,6BAAa,WAAW,MAAM,CAAC;AACxD,UAAM,gBAAgB,EAAE,GAAG,MAAM;AACjC,sCAAc,WAAW,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,EACzD,QAAQ;AAAA,EAER;AAEA,SAAO,KAAK;AACd;","names":[]}
|