@charming_groot/providers 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/auth-resolver.d.ts +9 -0
- package/dist/auth/auth-resolver.d.ts.map +1 -0
- package/dist/auth/auth-resolver.js +200 -0
- package/dist/auth/auth-resolver.js.map +1 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +2 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/base-provider.d.ts +10 -0
- package/dist/base-provider.d.ts.map +1 -0
- package/dist/base-provider.js +8 -0
- package/dist/base-provider.js.map +1 -0
- package/dist/circuit-breaker.d.ts +42 -0
- package/dist/circuit-breaker.d.ts.map +1 -0
- package/dist/circuit-breaker.js +116 -0
- package/dist/circuit-breaker.js.map +1 -0
- package/dist/claude-provider.d.ts +15 -0
- package/dist/claude-provider.d.ts.map +1 -0
- package/dist/claude-provider.js +171 -0
- package/dist/claude-provider.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/openai-provider.d.ts +16 -0
- package/dist/openai-provider.d.ts.map +1 -0
- package/dist/openai-provider.js +196 -0
- package/dist/openai-provider.js.map +1 -0
- package/dist/provider-factory.d.ts +17 -0
- package/dist/provider-factory.d.ts.map +1 -0
- package/dist/provider-factory.js +36 -0
- package/dist/provider-factory.js.map +1 -0
- package/dist/retry-provider.d.ts +25 -0
- package/dist/retry-provider.d.ts.map +1 -0
- package/dist/retry-provider.js +92 -0
- package/dist/retry-provider.js.map +1 -0
- package/dist/thinking-parser.d.ts +28 -0
- package/dist/thinking-parser.d.ts.map +1 -0
- package/dist/thinking-parser.js +40 -0
- package/dist/thinking-parser.js.map +1 -0
- package/package.json +34 -0
- package/src/auth/auth-resolver.ts +261 -0
- package/src/auth/index.ts +1 -0
- package/src/base-provider.ts +28 -0
- package/src/circuit-breaker.ts +157 -0
- package/src/claude-provider.ts +215 -0
- package/src/index.ts +13 -0
- package/src/openai-provider.ts +239 -0
- package/src/provider-factory.ts +48 -0
- package/src/retry-provider.ts +135 -0
- package/src/thinking-parser.ts +50 -0
- package/tests/auth-resolver.test.ts +204 -0
- package/tests/circuit-breaker.test.ts +220 -0
- package/tests/claude-provider.test.ts +35 -0
- package/tests/openai-provider.test.ts +35 -0
- package/tests/provider-factory.test.ts +73 -0
- package/tests/retry-provider-new.test.ts +166 -0
- package/tests/retry-provider.test.ts +118 -0
- package/tests/thinking-parser.test.ts +73 -0
- package/tsconfig.json +10 -0
- package/vitest.config.ts +15 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AuthConfig, ResolvedCredential } from '@charming_groot/core';
|
|
2
|
+
/**
|
|
3
|
+
* Synchronously extract a token/apiKey from an AuthConfig.
|
|
4
|
+
* For auth types that require async token exchange (OAuth client_credentials, Azure AD),
|
|
5
|
+
* the caller should use resolveAuth() first and pass the accessToken.
|
|
6
|
+
*/
|
|
7
|
+
export declare function extractToken(auth: AuthConfig): string;
|
|
8
|
+
export declare function resolveAuth(auth: AuthConfig): Promise<ResolvedCredential>;
|
|
9
|
+
//# sourceMappingURL=auth-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-resolver.d.ts","sourceRoot":"","sources":["../../src/auth/auth-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG3E;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAiBrD;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAmB/E"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { ProviderError } from '@charming_groot/core';
|
|
2
|
+
/**
|
|
3
|
+
* Synchronously extract a token/apiKey from an AuthConfig.
|
|
4
|
+
* For auth types that require async token exchange (OAuth client_credentials, Azure AD),
|
|
5
|
+
* the caller should use resolveAuth() first and pass the accessToken.
|
|
6
|
+
*/
|
|
7
|
+
export function extractToken(auth) {
|
|
8
|
+
switch (auth.type) {
|
|
9
|
+
case 'no-auth':
|
|
10
|
+
return 'no-auth';
|
|
11
|
+
case 'api-key':
|
|
12
|
+
return auth.apiKey;
|
|
13
|
+
case 'oauth':
|
|
14
|
+
return auth.accessToken ?? '';
|
|
15
|
+
case 'azure-ad':
|
|
16
|
+
return auth.accessToken ?? '';
|
|
17
|
+
case 'aws-iam':
|
|
18
|
+
return auth.accessKeyId ?? '';
|
|
19
|
+
case 'gcp-service-account':
|
|
20
|
+
return auth.accessToken ?? '';
|
|
21
|
+
case 'credential-file':
|
|
22
|
+
return '';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export async function resolveAuth(auth) {
|
|
26
|
+
switch (auth.type) {
|
|
27
|
+
case 'no-auth':
|
|
28
|
+
return { type: 'no-auth', headers: {}, token: undefined };
|
|
29
|
+
case 'api-key':
|
|
30
|
+
return resolveApiKey(auth);
|
|
31
|
+
case 'oauth':
|
|
32
|
+
return resolveOAuth(auth);
|
|
33
|
+
case 'azure-ad':
|
|
34
|
+
return resolveAzureAd(auth);
|
|
35
|
+
case 'aws-iam':
|
|
36
|
+
return resolveAwsIam(auth);
|
|
37
|
+
case 'gcp-service-account':
|
|
38
|
+
return resolveGcp(auth);
|
|
39
|
+
case 'credential-file':
|
|
40
|
+
return resolveCredentialFile(auth);
|
|
41
|
+
default:
|
|
42
|
+
throw new ProviderError(`Unsupported auth type: ${auth.type}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function resolveApiKey(auth) {
|
|
46
|
+
return {
|
|
47
|
+
type: 'api-key',
|
|
48
|
+
headers: { Authorization: `Bearer ${auth.apiKey}` },
|
|
49
|
+
token: auth.apiKey,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
async function resolveOAuth(auth) {
|
|
53
|
+
// If we already have a valid access token, use it
|
|
54
|
+
if (auth.accessToken) {
|
|
55
|
+
return {
|
|
56
|
+
type: 'oauth',
|
|
57
|
+
headers: { Authorization: `Bearer ${auth.accessToken}` },
|
|
58
|
+
token: auth.accessToken,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// Client credentials flow
|
|
62
|
+
const params = new URLSearchParams({
|
|
63
|
+
grant_type: auth.refreshToken ? 'refresh_token' : 'client_credentials',
|
|
64
|
+
client_id: auth.clientId,
|
|
65
|
+
client_secret: auth.clientSecret,
|
|
66
|
+
});
|
|
67
|
+
if (auth.refreshToken) {
|
|
68
|
+
params.set('refresh_token', auth.refreshToken);
|
|
69
|
+
}
|
|
70
|
+
if (auth.scopes && auth.scopes.length > 0) {
|
|
71
|
+
params.set('scope', auth.scopes.join(' '));
|
|
72
|
+
}
|
|
73
|
+
const response = await fetch(auth.tokenUrl, {
|
|
74
|
+
method: 'POST',
|
|
75
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
76
|
+
body: params.toString(),
|
|
77
|
+
});
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
const body = await response.text();
|
|
80
|
+
throw new ProviderError(`OAuth token request failed (${response.status}): ${body}`);
|
|
81
|
+
}
|
|
82
|
+
const data = await response.json();
|
|
83
|
+
const expiresAt = data.expires_in
|
|
84
|
+
? new Date(Date.now() + data.expires_in * 1000)
|
|
85
|
+
: undefined;
|
|
86
|
+
return {
|
|
87
|
+
type: 'oauth',
|
|
88
|
+
headers: { Authorization: `Bearer ${data.access_token}` },
|
|
89
|
+
token: data.access_token,
|
|
90
|
+
expiresAt,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
async function resolveAzureAd(auth) {
|
|
94
|
+
if (auth.accessToken) {
|
|
95
|
+
return {
|
|
96
|
+
type: 'azure-ad',
|
|
97
|
+
headers: { Authorization: `Bearer ${auth.accessToken}` },
|
|
98
|
+
token: auth.accessToken,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (!auth.clientSecret) {
|
|
102
|
+
throw new ProviderError('Azure AD auth requires either accessToken or clientSecret');
|
|
103
|
+
}
|
|
104
|
+
const tokenUrl = `https://login.microsoftonline.com/${auth.tenantId}/oauth2/v2.0/token`;
|
|
105
|
+
const params = new URLSearchParams({
|
|
106
|
+
grant_type: 'client_credentials',
|
|
107
|
+
client_id: auth.clientId,
|
|
108
|
+
client_secret: auth.clientSecret,
|
|
109
|
+
scope: 'https://cognitiveservices.azure.com/.default',
|
|
110
|
+
});
|
|
111
|
+
const response = await fetch(tokenUrl, {
|
|
112
|
+
method: 'POST',
|
|
113
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
114
|
+
body: params.toString(),
|
|
115
|
+
});
|
|
116
|
+
if (!response.ok) {
|
|
117
|
+
const body = await response.text();
|
|
118
|
+
throw new ProviderError(`Azure AD token request failed (${response.status}): ${body}`);
|
|
119
|
+
}
|
|
120
|
+
const data = await response.json();
|
|
121
|
+
const expiresAt = data.expires_in
|
|
122
|
+
? new Date(Date.now() + data.expires_in * 1000)
|
|
123
|
+
: undefined;
|
|
124
|
+
return {
|
|
125
|
+
type: 'azure-ad',
|
|
126
|
+
headers: {
|
|
127
|
+
Authorization: `Bearer ${data.access_token}`,
|
|
128
|
+
'api-key': data.access_token,
|
|
129
|
+
},
|
|
130
|
+
token: data.access_token,
|
|
131
|
+
expiresAt,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
async function resolveAwsIam(auth) {
|
|
135
|
+
// If explicit credentials provided, use them directly
|
|
136
|
+
// Real AWS Bedrock signing would use AWS SDK's SigV4
|
|
137
|
+
// This provides the credential structure for consumers to use
|
|
138
|
+
const headers = {};
|
|
139
|
+
if (auth.accessKeyId && auth.secretAccessKey) {
|
|
140
|
+
headers['x-aws-access-key-id'] = auth.accessKeyId;
|
|
141
|
+
headers['x-aws-region'] = auth.region;
|
|
142
|
+
if (auth.sessionToken) {
|
|
143
|
+
headers['x-aws-session-token'] = auth.sessionToken;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
type: 'aws-iam',
|
|
148
|
+
headers,
|
|
149
|
+
token: auth.accessKeyId,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
async function resolveGcp(auth) {
|
|
153
|
+
if (auth.accessToken) {
|
|
154
|
+
return {
|
|
155
|
+
type: 'gcp-service-account',
|
|
156
|
+
headers: { Authorization: `Bearer ${auth.accessToken}` },
|
|
157
|
+
token: auth.accessToken,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
// When keyFilePath is provided, consumers should use Google Auth Library
|
|
161
|
+
// This returns a placeholder that signals ADC should be used
|
|
162
|
+
return {
|
|
163
|
+
type: 'gcp-service-account',
|
|
164
|
+
headers: {},
|
|
165
|
+
token: undefined,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
async function resolveCredentialFile(auth) {
|
|
169
|
+
const { readFile } = await import('node:fs/promises');
|
|
170
|
+
let content;
|
|
171
|
+
try {
|
|
172
|
+
content = await readFile(auth.filePath, 'utf-8');
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
throw new ProviderError(`Failed to read credential file: ${auth.filePath}`, error instanceof Error ? error : undefined);
|
|
176
|
+
}
|
|
177
|
+
try {
|
|
178
|
+
const credentials = JSON.parse(content);
|
|
179
|
+
const profile = auth.profile ?? 'default';
|
|
180
|
+
const entry = credentials[profile];
|
|
181
|
+
if (!entry) {
|
|
182
|
+
throw new ProviderError(`Profile '${profile}' not found in credential file`);
|
|
183
|
+
}
|
|
184
|
+
const apiKey = entry['api_key'] ?? entry['apiKey'] ?? entry['token'];
|
|
185
|
+
if (!apiKey) {
|
|
186
|
+
throw new ProviderError(`No api_key/apiKey/token found in profile '${profile}'`);
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
type: 'credential-file',
|
|
190
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
191
|
+
token: apiKey,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
if (error instanceof ProviderError)
|
|
196
|
+
throw error;
|
|
197
|
+
throw new ProviderError(`Failed to parse credential file: ${auth.filePath}`, error instanceof Error ? error : undefined);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=auth-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-resolver.js","sourceRoot":"","sources":["../../src/auth/auth-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ILlmProvider, Message, LlmResponse, StreamEvent, ToolDescription } from '@charming_groot/core';
|
|
2
|
+
import type { AgentLogger } from '@charming_groot/core';
|
|
3
|
+
export declare abstract class BaseProvider implements ILlmProvider {
|
|
4
|
+
abstract readonly providerId: string;
|
|
5
|
+
protected readonly logger: AgentLogger;
|
|
6
|
+
constructor(loggerName: string);
|
|
7
|
+
abstract chat(messages: readonly Message[], tools?: readonly ToolDescription[]): Promise<LlmResponse>;
|
|
8
|
+
abstract stream(messages: readonly Message[], tools?: readonly ToolDescription[]): AsyncIterable<StreamEvent>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=base-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-provider.d.ts","sourceRoot":"","sources":["../src/base-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,OAAO,EACP,WAAW,EACX,WAAW,EACX,eAAe,EAChB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,8BAAsB,YAAa,YAAW,YAAY;IACxD,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IACrC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;gBAE3B,UAAU,EAAE,MAAM;IAI9B,QAAQ,CAAC,IAAI,CACX,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,KAAK,CAAC,EAAE,SAAS,eAAe,EAAE,GACjC,OAAO,CAAC,WAAW,CAAC;IAEvB,QAAQ,CAAC,MAAM,CACb,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,KAAK,CAAC,EAAE,SAAS,eAAe,EAAE,GACjC,aAAa,CAAC,WAAW,CAAC;CAC9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-provider.js","sourceRoot":"","sources":["../src/base-provider.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAGzD,MAAM,OAAgB,YAAY;IAEb,MAAM,CAAc;IAEvC,YAAY,UAAkB;QAC5B,IAAI,CAAC,MAAM,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;IAC9C,CAAC;CAWF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ILlmProvider, Message, LlmResponse, StreamEvent, ToolDescription } from '@charming_groot/core';
|
|
2
|
+
export interface CircuitBreakerConfig {
|
|
3
|
+
/** Consecutive failures before opening the circuit (default: 5) */
|
|
4
|
+
failureThreshold?: number;
|
|
5
|
+
/** Consecutive successes in HALF_OPEN to close the circuit (default: 2) */
|
|
6
|
+
successThreshold?: number;
|
|
7
|
+
/** Ms to stay OPEN before allowing a probe request (default: 60_000) */
|
|
8
|
+
openTimeoutMs?: number;
|
|
9
|
+
}
|
|
10
|
+
type State = 'CLOSED' | 'OPEN' | 'HALF_OPEN';
|
|
11
|
+
/**
|
|
12
|
+
* Circuit breaker wrapping an ILlmProvider.
|
|
13
|
+
*
|
|
14
|
+
* CLOSED → normal operation, counts failures
|
|
15
|
+
* OPEN → rejects immediately, waits openTimeoutMs then probes
|
|
16
|
+
* HALF_OPEN → allows one request; success → CLOSED, failure → OPEN
|
|
17
|
+
*
|
|
18
|
+
* Wrap inside RetryProvider for best results:
|
|
19
|
+
* createProvider() → RetryProvider → CircuitBreakerProvider
|
|
20
|
+
*/
|
|
21
|
+
export declare class CircuitBreakerProvider implements ILlmProvider {
|
|
22
|
+
readonly providerId: string;
|
|
23
|
+
private readonly inner;
|
|
24
|
+
private readonly failureThreshold;
|
|
25
|
+
private readonly successThreshold;
|
|
26
|
+
private readonly openTimeoutMs;
|
|
27
|
+
private readonly logger;
|
|
28
|
+
private state;
|
|
29
|
+
private failureCount;
|
|
30
|
+
private successCount;
|
|
31
|
+
private openedAt;
|
|
32
|
+
constructor(provider: ILlmProvider, config?: CircuitBreakerConfig);
|
|
33
|
+
get currentState(): State;
|
|
34
|
+
chat(messages: readonly Message[], tools?: readonly ToolDescription[]): Promise<LlmResponse>;
|
|
35
|
+
stream(messages: readonly Message[], tools?: readonly ToolDescription[]): AsyncIterable<StreamEvent>;
|
|
36
|
+
private guardOrThrow;
|
|
37
|
+
private onSuccess;
|
|
38
|
+
private onFailure;
|
|
39
|
+
private transitionTo;
|
|
40
|
+
}
|
|
41
|
+
export {};
|
|
42
|
+
//# sourceMappingURL=circuit-breaker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circuit-breaker.d.ts","sourceRoot":"","sources":["../src/circuit-breaker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,OAAO,EACP,WAAW,EACX,WAAW,EACX,eAAe,EAEhB,MAAM,sBAAsB,CAAC;AAG9B,MAAM,WAAW,oBAAoB;IACnC,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,KAAK,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;AAE7C;;;;;;;;;GASG;AACH,qBAAa,sBAAuB,YAAW,YAAY;IACzD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IAErC,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,QAAQ,CAAU;gBAEd,QAAQ,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,oBAAoB;IASjE,IAAI,YAAY,IAAI,KAAK,CAExB;IAEK,IAAI,CACR,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,KAAK,CAAC,EAAE,SAAS,eAAe,EAAE,GACjC,OAAO,CAAC,WAAW,CAAC;IAYhB,MAAM,CACX,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,KAAK,CAAC,EAAE,SAAS,eAAe,EAAE,GACjC,aAAa,CAAC,WAAW,CAAC;IAa7B,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,SAAS;IAgBjB,OAAO,CAAC,YAAY;CAwBrB"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { ProviderError, createChildLogger } from '@charming_groot/core';
|
|
2
|
+
/**
|
|
3
|
+
* Circuit breaker wrapping an ILlmProvider.
|
|
4
|
+
*
|
|
5
|
+
* CLOSED → normal operation, counts failures
|
|
6
|
+
* OPEN → rejects immediately, waits openTimeoutMs then probes
|
|
7
|
+
* HALF_OPEN → allows one request; success → CLOSED, failure → OPEN
|
|
8
|
+
*
|
|
9
|
+
* Wrap inside RetryProvider for best results:
|
|
10
|
+
* createProvider() → RetryProvider → CircuitBreakerProvider
|
|
11
|
+
*/
|
|
12
|
+
export class CircuitBreakerProvider {
|
|
13
|
+
providerId;
|
|
14
|
+
inner;
|
|
15
|
+
failureThreshold;
|
|
16
|
+
successThreshold;
|
|
17
|
+
openTimeoutMs;
|
|
18
|
+
logger;
|
|
19
|
+
state = 'CLOSED';
|
|
20
|
+
failureCount = 0;
|
|
21
|
+
successCount = 0;
|
|
22
|
+
openedAt = 0;
|
|
23
|
+
constructor(provider, config) {
|
|
24
|
+
this.inner = provider;
|
|
25
|
+
this.providerId = provider.providerId;
|
|
26
|
+
this.failureThreshold = config?.failureThreshold ?? 5;
|
|
27
|
+
this.successThreshold = config?.successThreshold ?? 2;
|
|
28
|
+
this.openTimeoutMs = config?.openTimeoutMs ?? 60_000;
|
|
29
|
+
this.logger = createChildLogger('circuit-breaker');
|
|
30
|
+
}
|
|
31
|
+
get currentState() {
|
|
32
|
+
return this.state;
|
|
33
|
+
}
|
|
34
|
+
async chat(messages, tools) {
|
|
35
|
+
this.guardOrThrow();
|
|
36
|
+
try {
|
|
37
|
+
const result = await this.inner.chat(messages, tools);
|
|
38
|
+
this.onSuccess();
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
this.onFailure(error);
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async *stream(messages, tools) {
|
|
47
|
+
this.guardOrThrow();
|
|
48
|
+
try {
|
|
49
|
+
yield* this.inner.stream(messages, tools);
|
|
50
|
+
this.onSuccess();
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
this.onFailure(error);
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// ── Internal state machine ───────────────────────────────────────────────
|
|
58
|
+
guardOrThrow() {
|
|
59
|
+
if (this.state === 'CLOSED' || this.state === 'HALF_OPEN')
|
|
60
|
+
return;
|
|
61
|
+
// OPEN: check if timeout has elapsed
|
|
62
|
+
const elapsed = Date.now() - this.openedAt;
|
|
63
|
+
if (elapsed >= this.openTimeoutMs) {
|
|
64
|
+
this.transitionTo('HALF_OPEN');
|
|
65
|
+
return; // allow this probe request through
|
|
66
|
+
}
|
|
67
|
+
const remaining = Math.ceil((this.openTimeoutMs - elapsed) / 1000);
|
|
68
|
+
throw new ProviderError(`Circuit breaker OPEN for provider '${this.providerId}' — retry in ${remaining}s`);
|
|
69
|
+
}
|
|
70
|
+
onSuccess() {
|
|
71
|
+
if (this.state === 'HALF_OPEN') {
|
|
72
|
+
this.successCount++;
|
|
73
|
+
if (this.successCount >= this.successThreshold) {
|
|
74
|
+
this.transitionTo('CLOSED');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
this.failureCount = 0; // reset on any success in CLOSED
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
onFailure(error) {
|
|
82
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
83
|
+
this.logger.warn({ state: this.state, error: msg }, 'Circuit breaker recorded failure');
|
|
84
|
+
if (this.state === 'HALF_OPEN') {
|
|
85
|
+
// Probe failed → back to OPEN
|
|
86
|
+
this.transitionTo('OPEN');
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
this.failureCount++;
|
|
90
|
+
if (this.failureCount >= this.failureThreshold) {
|
|
91
|
+
this.transitionTo('OPEN');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
transitionTo(next) {
|
|
95
|
+
const prev = this.state;
|
|
96
|
+
this.state = next;
|
|
97
|
+
if (next === 'OPEN') {
|
|
98
|
+
this.openedAt = Date.now();
|
|
99
|
+
this.successCount = 0;
|
|
100
|
+
this.logger.error({ failureCount: this.failureCount, openTimeoutMs: this.openTimeoutMs }, `Circuit breaker OPENED for provider '${this.providerId}'`);
|
|
101
|
+
}
|
|
102
|
+
else if (next === 'HALF_OPEN') {
|
|
103
|
+
this.successCount = 0;
|
|
104
|
+
this.logger.warn({}, `Circuit breaker HALF_OPEN — probing provider '${this.providerId}'`);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
this.failureCount = 0;
|
|
108
|
+
this.logger.info({}, `Circuit breaker CLOSED for provider '${this.providerId}'`);
|
|
109
|
+
}
|
|
110
|
+
if (prev !== next) {
|
|
111
|
+
// Allow external inspection of state transitions
|
|
112
|
+
this.logger.debug({ from: prev, to: next }, 'Circuit breaker state transition');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=circuit-breaker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circuit-breaker.js","sourceRoot":"","sources":["../src/circuit-breaker.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAaxE;;;;;;;;;GASG;AACH,MAAM,OAAO,sBAAsB;IACxB,UAAU,CAAS;IAEX,KAAK,CAAe;IACpB,gBAAgB,CAAS;IACzB,gBAAgB,CAAS;IACzB,aAAa,CAAS;IACtB,MAAM,CAAc;IAE7B,KAAK,GAAU,QAAQ,CAAC;IACxB,YAAY,GAAI,CAAC,CAAC;IAClB,YAAY,GAAI,CAAC,CAAC;IAClB,QAAQ,GAAQ,CAAC,CAAC;IAE1B,YAAY,QAAsB,EAAE,MAA6B;QAC/D,IAAI,CAAC,KAAK,GAAc,QAAQ,CAAC;QACjC,IAAI,CAAC,UAAU,GAAS,QAAQ,CAAC,UAAU,CAAC;QAC5C,IAAI,CAAC,gBAAgB,GAAG,MAAM,EAAE,gBAAgB,IAAI,CAAC,CAAC;QACtD,IAAI,CAAC,gBAAgB,GAAG,MAAM,EAAE,gBAAgB,IAAI,CAAC,CAAC;QACtD,IAAI,CAAC,aAAa,GAAM,MAAM,EAAE,aAAa,IAAO,MAAM,CAAC;QAC3D,IAAI,CAAC,MAAM,GAAa,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;IAC/D,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,IAAI,CACR,QAA4B,EAC5B,KAAkC;QAElC,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACtD,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACtB,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,CAAC,MAAM,CACX,QAA4B,EAC5B,KAAkC;QAElC,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,IAAI,CAAC;YACH,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAC1C,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACtB,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,4EAA4E;IAEpE,YAAY;QAClB,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,KAAK,WAAW;YAAE,OAAO;QAElE,qCAAqC;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC3C,IAAI,OAAO,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YAClC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;YAC/B,OAAO,CAAC,mCAAmC;QAC7C,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QACnE,MAAM,IAAI,aAAa,CACrB,sCAAsC,IAAI,CAAC,UAAU,gBAAgB,SAAS,GAAG,CAClF,CAAC;IACJ,CAAC;IAEO,SAAS;QACf,IAAI,IAAI,CAAC,KAAK,KAAK,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,YAAY,EAAE,CAAC;YACpB,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC/C,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,iCAAiC;QAC1D,CAAC;IACH,CAAC;IAEO,SAAS,CAAC,KAAc;QAC9B,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,kCAAkC,CAAC,CAAC;QAExF,IAAI,IAAI,CAAC,KAAK,KAAK,WAAW,EAAE,CAAC;YAC/B,8BAA8B;YAC9B,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YAC1B,OAAO;QACT,CAAC;QAED,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC/C,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAEO,YAAY,CAAC,IAAW;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAElB,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,IAAI,CAAC,QAAQ,GAAO,IAAI,CAAC,GAAG,EAAE,CAAC;YAC/B,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;YACtB,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,EACtE,wCAAwC,IAAI,CAAC,UAAU,GAAG,CAC3D,CAAC;QACJ,CAAC;aAAM,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;YAChC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;YACtB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,iDAAiD,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QAC5F,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;YACtB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,wCAAwC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACnF,CAAC;QAED,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,iDAAiD;YACjD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,kCAAkC,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Message, LlmResponse, StreamEvent, ToolDescription, ProviderConfig } from '@charming_groot/core';
|
|
2
|
+
import { BaseProvider } from './base-provider.js';
|
|
3
|
+
export declare class ClaudeProvider extends BaseProvider {
|
|
4
|
+
readonly providerId = "claude";
|
|
5
|
+
private readonly client;
|
|
6
|
+
private readonly model;
|
|
7
|
+
private readonly maxTokens;
|
|
8
|
+
constructor(config: ProviderConfig);
|
|
9
|
+
chat(messages: readonly Message[], tools?: readonly ToolDescription[]): Promise<LlmResponse>;
|
|
10
|
+
stream(messages: readonly Message[], tools?: readonly ToolDescription[]): AsyncIterable<StreamEvent>;
|
|
11
|
+
private toAnthropicMessages;
|
|
12
|
+
private toAnthropicTools;
|
|
13
|
+
private parseResponse;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=claude-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-provider.d.ts","sourceRoot":"","sources":["../src/claude-provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EACP,WAAW,EACX,WAAW,EACX,eAAe,EAEf,cAAc,EACf,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAclD,qBAAa,cAAe,SAAQ,YAAY;IAC9C,QAAQ,CAAC,UAAU,YAAY;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,MAAM,EAAE,cAAc;IAQ5B,IAAI,CACR,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,KAAK,CAAC,EAAE,SAAS,eAAe,EAAE,GACjC,OAAO,CAAC,WAAW,CAAC;IAsBhB,MAAM,CACX,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,KAAK,CAAC,EAAE,SAAS,eAAe,EAAE,GACjC,aAAa,CAAC,WAAW,CAAC;IA0C7B,OAAO,CAAC,mBAAmB;IAsC3B,OAAO,CAAC,gBAAgB;IAmBxB,OAAO,CAAC,aAAa;CAiDtB"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
2
|
+
import { ProviderError } from '@charming_groot/core';
|
|
3
|
+
import { BaseProvider } from './base-provider.js';
|
|
4
|
+
import { extractToken } from './auth/auth-resolver.js';
|
|
5
|
+
import { extractThinkTag, estimateThinkingMs } from './thinking-parser.js';
|
|
6
|
+
export class ClaudeProvider extends BaseProvider {
|
|
7
|
+
providerId = 'claude';
|
|
8
|
+
client;
|
|
9
|
+
model;
|
|
10
|
+
maxTokens;
|
|
11
|
+
constructor(config) {
|
|
12
|
+
super('claude-provider');
|
|
13
|
+
const apiKey = extractToken(config.auth);
|
|
14
|
+
this.client = new Anthropic({ apiKey, baseURL: config.baseUrl });
|
|
15
|
+
this.model = config.model;
|
|
16
|
+
this.maxTokens = config.maxTokens;
|
|
17
|
+
}
|
|
18
|
+
async chat(messages, tools) {
|
|
19
|
+
try {
|
|
20
|
+
const systemMsg = messages.find((m) => m.role === 'system');
|
|
21
|
+
const nonSystemMsgs = messages.filter((m) => m.role !== 'system');
|
|
22
|
+
const response = await this.client.messages.create({
|
|
23
|
+
model: this.model,
|
|
24
|
+
max_tokens: this.maxTokens,
|
|
25
|
+
system: systemMsg?.content,
|
|
26
|
+
messages: this.toAnthropicMessages(nonSystemMsgs),
|
|
27
|
+
tools: tools ? this.toAnthropicTools(tools) : undefined,
|
|
28
|
+
});
|
|
29
|
+
return this.parseResponse(response);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
throw new ProviderError(`Claude API error: ${error instanceof Error ? error.message : String(error)}`, error instanceof Error ? error : undefined);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async *stream(messages, tools) {
|
|
36
|
+
try {
|
|
37
|
+
const systemMsg = messages.find((m) => m.role === 'system');
|
|
38
|
+
const nonSystemMsgs = messages.filter((m) => m.role !== 'system');
|
|
39
|
+
const stream = this.client.messages.stream({
|
|
40
|
+
model: this.model,
|
|
41
|
+
max_tokens: this.maxTokens,
|
|
42
|
+
system: systemMsg?.content,
|
|
43
|
+
messages: this.toAnthropicMessages(nonSystemMsgs),
|
|
44
|
+
tools: tools ? this.toAnthropicTools(tools) : undefined,
|
|
45
|
+
});
|
|
46
|
+
for await (const event of stream) {
|
|
47
|
+
if (event.type === 'content_block_delta') {
|
|
48
|
+
const delta = event.delta;
|
|
49
|
+
if (delta.type === 'text_delta' && delta.text) {
|
|
50
|
+
yield { type: 'text_delta', content: delta.text };
|
|
51
|
+
}
|
|
52
|
+
else if (delta.type === 'input_json_delta' && delta.partial_json) {
|
|
53
|
+
yield { type: 'tool_call_delta', content: delta.partial_json };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else if (event.type === 'content_block_start') {
|
|
57
|
+
const block = event.content_block;
|
|
58
|
+
if (block.type === 'tool_use') {
|
|
59
|
+
yield {
|
|
60
|
+
type: 'tool_call_start',
|
|
61
|
+
toolCall: { id: block.id, name: block.name },
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else if (event.type === 'message_stop') {
|
|
66
|
+
const finalMessage = await stream.finalMessage();
|
|
67
|
+
yield { type: 'done', response: this.parseResponse(finalMessage) };
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
throw new ProviderError(`Claude stream error: ${error instanceof Error ? error.message : String(error)}`, error instanceof Error ? error : undefined);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
toAnthropicMessages(messages) {
|
|
76
|
+
return messages.map((msg) => {
|
|
77
|
+
if (msg.toolResults && msg.toolResults.length > 0) {
|
|
78
|
+
return {
|
|
79
|
+
role: 'user',
|
|
80
|
+
content: msg.toolResults.map((tr) => ({
|
|
81
|
+
type: 'tool_result',
|
|
82
|
+
tool_use_id: tr.toolCallId,
|
|
83
|
+
content: tr.content,
|
|
84
|
+
})),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
if (msg.toolCalls && msg.toolCalls.length > 0) {
|
|
88
|
+
const content = [];
|
|
89
|
+
if (msg.content) {
|
|
90
|
+
content.push({ type: 'text', text: msg.content });
|
|
91
|
+
}
|
|
92
|
+
for (const tc of msg.toolCalls) {
|
|
93
|
+
content.push({
|
|
94
|
+
type: 'tool_use',
|
|
95
|
+
id: tc.id,
|
|
96
|
+
name: tc.name,
|
|
97
|
+
input: JSON.parse(tc.arguments),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return { role: 'assistant', content };
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
role: msg.role,
|
|
104
|
+
content: msg.content,
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
toAnthropicTools(tools) {
|
|
109
|
+
return tools.map((tool) => ({
|
|
110
|
+
name: tool.name,
|
|
111
|
+
description: tool.description,
|
|
112
|
+
input_schema: {
|
|
113
|
+
type: 'object',
|
|
114
|
+
properties: Object.fromEntries(tool.parameters.map((p) => [
|
|
115
|
+
p.name,
|
|
116
|
+
{ type: p.type, description: p.description },
|
|
117
|
+
])),
|
|
118
|
+
required: tool.parameters
|
|
119
|
+
.filter((p) => p.required)
|
|
120
|
+
.map((p) => p.name),
|
|
121
|
+
},
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
parseResponse(response) {
|
|
125
|
+
let content = '';
|
|
126
|
+
const toolCalls = [];
|
|
127
|
+
let thinkingMs;
|
|
128
|
+
for (const block of response.content) {
|
|
129
|
+
if (block.type === 'thinking') {
|
|
130
|
+
// Anthropic extended thinking block — estimate duration from token count
|
|
131
|
+
// (no direct timing from API, but the block existing means thinking occurred)
|
|
132
|
+
const thinkingBlock = block;
|
|
133
|
+
thinkingMs = estimateThinkingMs(thinkingBlock.thinking);
|
|
134
|
+
}
|
|
135
|
+
else if (block.type === 'text') {
|
|
136
|
+
content += block.text;
|
|
137
|
+
}
|
|
138
|
+
else if (block.type === 'tool_use') {
|
|
139
|
+
toolCalls.push({
|
|
140
|
+
id: block.id,
|
|
141
|
+
name: block.name,
|
|
142
|
+
arguments: JSON.stringify(block.input),
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Fallback: parse <think>...</think> tags from text content (DeepSeek, etc.)
|
|
147
|
+
const parsed = extractThinkTag(content);
|
|
148
|
+
if (parsed.thinkContent) {
|
|
149
|
+
content = parsed.cleanContent;
|
|
150
|
+
if (!thinkingMs) {
|
|
151
|
+
thinkingMs = estimateThinkingMs(parsed.thinkContent);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const stopReason = response.stop_reason === 'tool_use'
|
|
155
|
+
? 'tool_use'
|
|
156
|
+
: response.stop_reason === 'max_tokens'
|
|
157
|
+
? 'max_tokens'
|
|
158
|
+
: 'end_turn';
|
|
159
|
+
return {
|
|
160
|
+
content,
|
|
161
|
+
stopReason,
|
|
162
|
+
toolCalls,
|
|
163
|
+
usage: {
|
|
164
|
+
inputTokens: response.usage.input_tokens,
|
|
165
|
+
outputTokens: response.usage.output_tokens,
|
|
166
|
+
thinkingMs,
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=claude-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-provider.js","sourceRoot":"","sources":["../src/claude-provider.ts"],"names":[],"mappings":"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"}
|