@nuvin/nuvin-core 1.6.1 → 1.7.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/VERSION +2 -2
- package/dist/index.d.ts +8 -5
- package/dist/index.js +309 -193
- package/package.json +1 -1
package/dist/VERSION
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ type AgentTemplate = {
|
|
|
17
17
|
topP?: number;
|
|
18
18
|
timeoutMs?: number;
|
|
19
19
|
shareContext?: boolean;
|
|
20
|
+
stream?: boolean;
|
|
20
21
|
metadata?: Record<string, unknown>;
|
|
21
22
|
};
|
|
22
23
|
/**
|
|
@@ -40,6 +41,7 @@ type SpecialistAgentConfig = {
|
|
|
40
41
|
topP?: number;
|
|
41
42
|
timeoutMs?: number;
|
|
42
43
|
shareContext?: boolean;
|
|
44
|
+
stream?: boolean;
|
|
43
45
|
delegatingMemory?: Message[];
|
|
44
46
|
delegationDepth: number;
|
|
45
47
|
conversationId?: string;
|
|
@@ -1691,6 +1693,7 @@ type FileNewSuccessResult$1 = {
|
|
|
1691
1693
|
metadata: {
|
|
1692
1694
|
file_path: string;
|
|
1693
1695
|
bytes: number;
|
|
1696
|
+
lines: number;
|
|
1694
1697
|
created: string;
|
|
1695
1698
|
overwritten?: boolean;
|
|
1696
1699
|
};
|
|
@@ -2096,6 +2099,7 @@ type AnthropicAISDKOptions = {
|
|
|
2096
2099
|
apiUrl?: string;
|
|
2097
2100
|
baseURL?: string;
|
|
2098
2101
|
httpLogFile?: string;
|
|
2102
|
+
retry?: Partial<RetryConfig>;
|
|
2099
2103
|
onTokenUpdate?: (newCredentials: {
|
|
2100
2104
|
access: string;
|
|
2101
2105
|
refresh: string;
|
|
@@ -2105,12 +2109,11 @@ type AnthropicAISDKOptions = {
|
|
|
2105
2109
|
declare class AnthropicAISDKLLM {
|
|
2106
2110
|
private readonly opts;
|
|
2107
2111
|
private provider?;
|
|
2108
|
-
private
|
|
2112
|
+
private transport?;
|
|
2113
|
+
private authTransport?;
|
|
2109
2114
|
constructor(opts?: AnthropicAISDKOptions);
|
|
2110
|
-
private
|
|
2111
|
-
private
|
|
2112
|
-
private ensureValidToken;
|
|
2113
|
-
private createFetchWithRetry;
|
|
2115
|
+
private getAuthTransport;
|
|
2116
|
+
private getTransport;
|
|
2114
2117
|
private getProvider;
|
|
2115
2118
|
private getModel;
|
|
2116
2119
|
private transformMessages;
|
package/dist/index.js
CHANGED
|
@@ -964,6 +964,20 @@ var AgentOrchestrator = class {
|
|
|
964
964
|
};
|
|
965
965
|
turnHistory.push(toolMsg);
|
|
966
966
|
toolResultMsgs.push(toolMsg);
|
|
967
|
+
await this.events?.emit({
|
|
968
|
+
type: AgentEventTypes.ToolResult,
|
|
969
|
+
conversationId,
|
|
970
|
+
messageId,
|
|
971
|
+
result: {
|
|
972
|
+
id: toolCall.id,
|
|
973
|
+
name: toolCall.function.name,
|
|
974
|
+
status: "error",
|
|
975
|
+
type: "text",
|
|
976
|
+
result: toolDenialResult,
|
|
977
|
+
durationMs: 0,
|
|
978
|
+
metadata: { errorReason: "denied" /* Denied */ }
|
|
979
|
+
}
|
|
980
|
+
});
|
|
967
981
|
}
|
|
968
982
|
await this.memory.append(conversationId, [assistantMsg, ...toolResultMsgs]);
|
|
969
983
|
await this.events?.emit({
|
|
@@ -1205,7 +1219,10 @@ var AgentOrchestrator = class {
|
|
|
1205
1219
|
content: contentStr,
|
|
1206
1220
|
timestamp: this.clock.iso(),
|
|
1207
1221
|
tool_call_id: tr.id,
|
|
1208
|
-
name: tr.name
|
|
1222
|
+
name: tr.name,
|
|
1223
|
+
status: tr.status,
|
|
1224
|
+
durationMs: tr.durationMs,
|
|
1225
|
+
metadata: tr.metadata
|
|
1209
1226
|
});
|
|
1210
1227
|
this.metrics?.recordToolCall?.();
|
|
1211
1228
|
await this.events?.emit({
|
|
@@ -2648,10 +2665,12 @@ var FileNewTool = class {
|
|
|
2648
2665
|
const existsBefore = await fs4.stat(abs).then(() => true).catch(() => false);
|
|
2649
2666
|
await fs4.mkdir(path4.dirname(abs), { recursive: true });
|
|
2650
2667
|
const bytes = Buffer.from(p.content, "utf8");
|
|
2668
|
+
const lines = p.content.split(/\r?\n/).length;
|
|
2651
2669
|
await this.writeAtomic(abs, bytes);
|
|
2652
2670
|
return okText(`File written at ${p.file_path}.`, {
|
|
2653
2671
|
file_path: p.file_path,
|
|
2654
2672
|
bytes: bytes.length,
|
|
2673
|
+
lines,
|
|
2655
2674
|
created: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2656
2675
|
overwritten: existsBefore
|
|
2657
2676
|
});
|
|
@@ -3671,6 +3690,7 @@ var DefaultSpecialistAgentFactory = class {
|
|
|
3671
3690
|
topP: template.topP,
|
|
3672
3691
|
timeoutMs: template.timeoutMs,
|
|
3673
3692
|
shareContext: template.shareContext ?? false,
|
|
3693
|
+
stream: template.stream ?? true,
|
|
3674
3694
|
delegatingMemory: void 0,
|
|
3675
3695
|
// TODO: provide delegating memory when available
|
|
3676
3696
|
delegationDepth: input.currentDepth + 1,
|
|
@@ -3827,7 +3847,7 @@ var AgentManager = class {
|
|
|
3827
3847
|
this.activeAgents.set(agentId, specialistOrchestrator);
|
|
3828
3848
|
try {
|
|
3829
3849
|
const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
3830
|
-
const response = await this.executeWithTimeout(specialistOrchestrator, config.taskDescription, timeoutMs, signal);
|
|
3850
|
+
const response = await this.executeWithTimeout(specialistOrchestrator, config.taskDescription, timeoutMs, signal, config.stream);
|
|
3831
3851
|
const executionTimeMs = Date.now() - startTime;
|
|
3832
3852
|
const conversationHistory = await memory.get("default");
|
|
3833
3853
|
const toolCallsExecuted = events.filter((e) => e.type === "tool_calls").length;
|
|
@@ -3909,7 +3929,7 @@ var AgentManager = class {
|
|
|
3909
3929
|
/**
|
|
3910
3930
|
* Execute agent task with timeout
|
|
3911
3931
|
*/
|
|
3912
|
-
async executeWithTimeout(orchestrator, taskDescription, timeoutMs, signal) {
|
|
3932
|
+
async executeWithTimeout(orchestrator, taskDescription, timeoutMs, signal, stream) {
|
|
3913
3933
|
const timeoutController = new AbortController();
|
|
3914
3934
|
const combinedSignal = signal ? AbortSignal.any([signal, timeoutController.signal]) : timeoutController.signal;
|
|
3915
3935
|
let timer;
|
|
@@ -3917,7 +3937,8 @@ var AgentManager = class {
|
|
|
3917
3937
|
return await Promise.race([
|
|
3918
3938
|
orchestrator.send(taskDescription, {
|
|
3919
3939
|
conversationId: "default",
|
|
3920
|
-
signal: combinedSignal
|
|
3940
|
+
signal: combinedSignal,
|
|
3941
|
+
stream
|
|
3921
3942
|
}),
|
|
3922
3943
|
new Promise((_, reject) => {
|
|
3923
3944
|
if (signal?.aborted) {
|
|
@@ -4722,9 +4743,9 @@ var BaseLLM = class {
|
|
|
4722
4743
|
model: enhancedParams.model,
|
|
4723
4744
|
messages: enhancedParams.messages,
|
|
4724
4745
|
temperature: enhancedParams.temperature,
|
|
4725
|
-
max_tokens: enhancedParams.maxTokens,
|
|
4726
4746
|
top_p: enhancedParams.topP,
|
|
4727
4747
|
stream: false,
|
|
4748
|
+
...enhancedParams.maxTokens !== void 0 && { max_tokens: enhancedParams.maxTokens },
|
|
4728
4749
|
...enhancedParams.reasoning && { reasoning: enhancedParams.reasoning },
|
|
4729
4750
|
...enhancedParams.usage && { usage: enhancedParams.usage }
|
|
4730
4751
|
};
|
|
@@ -4748,9 +4769,9 @@ var BaseLLM = class {
|
|
|
4748
4769
|
model: enhancedParams.model,
|
|
4749
4770
|
messages: enhancedParams.messages,
|
|
4750
4771
|
temperature: enhancedParams.temperature,
|
|
4751
|
-
max_tokens: enhancedParams.maxTokens,
|
|
4752
4772
|
top_p: enhancedParams.topP,
|
|
4753
4773
|
stream: true,
|
|
4774
|
+
...enhancedParams.maxTokens !== void 0 && { max_tokens: enhancedParams.maxTokens },
|
|
4754
4775
|
...enhancedParams.reasoning && { reasoning: enhancedParams.reasoning },
|
|
4755
4776
|
...enhancedParams.usage && { usage: enhancedParams.usage }
|
|
4756
4777
|
};
|
|
@@ -5234,66 +5255,6 @@ var GithubAuthTransport = class {
|
|
|
5234
5255
|
}
|
|
5235
5256
|
};
|
|
5236
5257
|
|
|
5237
|
-
// src/transports/base-bearer-auth-transport.ts
|
|
5238
|
-
var BaseBearerAuthTransport = class {
|
|
5239
|
-
inner;
|
|
5240
|
-
apiKey;
|
|
5241
|
-
baseUrl;
|
|
5242
|
-
version;
|
|
5243
|
-
customHeaders;
|
|
5244
|
-
constructor(inner, apiKey, baseUrl, version, customHeaders) {
|
|
5245
|
-
this.inner = inner;
|
|
5246
|
-
this.apiKey = apiKey;
|
|
5247
|
-
this.baseUrl = baseUrl ?? this.getDefaultBaseUrl();
|
|
5248
|
-
this.version = version;
|
|
5249
|
-
this.customHeaders = customHeaders;
|
|
5250
|
-
}
|
|
5251
|
-
buildFullUrl(path9) {
|
|
5252
|
-
if (path9.startsWith("/")) {
|
|
5253
|
-
return `${this.baseUrl}${path9}`;
|
|
5254
|
-
}
|
|
5255
|
-
return path9;
|
|
5256
|
-
}
|
|
5257
|
-
makeAuthHeaders(headers) {
|
|
5258
|
-
const base = headers ? { ...headers } : {};
|
|
5259
|
-
if (!base["User-Agent"] && this.version) {
|
|
5260
|
-
base["User-Agent"] = `nuvin-cli/${this.version}`;
|
|
5261
|
-
}
|
|
5262
|
-
if (this.apiKey && this.apiKey.trim() !== "" && !this.customHeaders?.Authorization) {
|
|
5263
|
-
base.Authorization = `Bearer ${this.apiKey}`;
|
|
5264
|
-
}
|
|
5265
|
-
if (this.customHeaders) {
|
|
5266
|
-
Object.assign(base, this.customHeaders);
|
|
5267
|
-
}
|
|
5268
|
-
return base;
|
|
5269
|
-
}
|
|
5270
|
-
async get(url, headers, signal) {
|
|
5271
|
-
const fullUrl = this.buildFullUrl(url);
|
|
5272
|
-
return this.inner.get(fullUrl, this.makeAuthHeaders(headers), signal);
|
|
5273
|
-
}
|
|
5274
|
-
async post(url, body, headers, signal) {
|
|
5275
|
-
const fullUrl = this.buildFullUrl(url);
|
|
5276
|
-
return this.inner.post(fullUrl, body, this.makeAuthHeaders(headers), signal);
|
|
5277
|
-
}
|
|
5278
|
-
};
|
|
5279
|
-
|
|
5280
|
-
// src/transports/simple-bearer-transport.ts
|
|
5281
|
-
var SimpleBearerAuthTransport = class extends BaseBearerAuthTransport {
|
|
5282
|
-
defaultUrl;
|
|
5283
|
-
constructor(inner, defaultBaseUrl, apiKey, baseUrl, version, customHeaders) {
|
|
5284
|
-
super(inner, apiKey, baseUrl ?? defaultBaseUrl, version, customHeaders);
|
|
5285
|
-
this.defaultUrl = defaultBaseUrl;
|
|
5286
|
-
}
|
|
5287
|
-
getDefaultBaseUrl() {
|
|
5288
|
-
return this.defaultUrl;
|
|
5289
|
-
}
|
|
5290
|
-
};
|
|
5291
|
-
|
|
5292
|
-
// src/transports/transport-factory.ts
|
|
5293
|
-
function createTransport(inner, defaultBaseUrl, apiKey, baseUrl, version, customHeaders) {
|
|
5294
|
-
return new SimpleBearerAuthTransport(inner, defaultBaseUrl, apiKey, baseUrl, version, customHeaders);
|
|
5295
|
-
}
|
|
5296
|
-
|
|
5297
5258
|
// src/transports/backoff.ts
|
|
5298
5259
|
function calculateBackoff(attempt, baseDelayMs, maxDelayMs, multiplier, jitterFactor) {
|
|
5299
5260
|
const exponentialDelay = baseDelayMs * multiplier ** attempt;
|
|
@@ -5494,6 +5455,247 @@ var RetryTransport = class {
|
|
|
5494
5455
|
}
|
|
5495
5456
|
};
|
|
5496
5457
|
|
|
5458
|
+
// src/transports/anthropic-transport.ts
|
|
5459
|
+
var CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
|
|
5460
|
+
var DEFAULT_BASE_URL = "https://api.anthropic.com/v1";
|
|
5461
|
+
var AnthropicAuthTransport = class {
|
|
5462
|
+
inner;
|
|
5463
|
+
baseUrl;
|
|
5464
|
+
retryConfig;
|
|
5465
|
+
apiKey;
|
|
5466
|
+
oauth;
|
|
5467
|
+
onTokenUpdate;
|
|
5468
|
+
refreshPromise = null;
|
|
5469
|
+
constructor(inner, opts) {
|
|
5470
|
+
this.inner = inner;
|
|
5471
|
+
this.apiKey = opts.apiKey;
|
|
5472
|
+
this.oauth = opts.oauth;
|
|
5473
|
+
this.baseUrl = opts.baseUrl ?? DEFAULT_BASE_URL;
|
|
5474
|
+
this.onTokenUpdate = opts.onTokenUpdate;
|
|
5475
|
+
this.retryConfig = opts.retry;
|
|
5476
|
+
}
|
|
5477
|
+
async refreshAccessToken() {
|
|
5478
|
+
if (!this.oauth) {
|
|
5479
|
+
return { type: "failed" };
|
|
5480
|
+
}
|
|
5481
|
+
try {
|
|
5482
|
+
const response = await fetch("https://console.anthropic.com/v1/oauth/token", {
|
|
5483
|
+
method: "POST",
|
|
5484
|
+
headers: {
|
|
5485
|
+
"Content-Type": "application/json"
|
|
5486
|
+
},
|
|
5487
|
+
body: JSON.stringify({
|
|
5488
|
+
grant_type: "refresh_token",
|
|
5489
|
+
refresh_token: this.oauth.refresh,
|
|
5490
|
+
client_id: CLIENT_ID
|
|
5491
|
+
})
|
|
5492
|
+
});
|
|
5493
|
+
if (!response.ok) {
|
|
5494
|
+
return { type: "failed" };
|
|
5495
|
+
}
|
|
5496
|
+
const json = await response.json();
|
|
5497
|
+
return {
|
|
5498
|
+
type: "success",
|
|
5499
|
+
access: json.access_token,
|
|
5500
|
+
refresh: json.refresh_token,
|
|
5501
|
+
expires: Date.now() + json.expires_in * 1e3
|
|
5502
|
+
};
|
|
5503
|
+
} catch {
|
|
5504
|
+
return { type: "failed" };
|
|
5505
|
+
}
|
|
5506
|
+
}
|
|
5507
|
+
updateCredentials(result) {
|
|
5508
|
+
if (result.type === "success" && result.access && result.refresh && result.expires) {
|
|
5509
|
+
if (this.oauth) {
|
|
5510
|
+
this.oauth.access = result.access;
|
|
5511
|
+
this.oauth.refresh = result.refresh;
|
|
5512
|
+
this.oauth.expires = result.expires;
|
|
5513
|
+
}
|
|
5514
|
+
this.onTokenUpdate?.({
|
|
5515
|
+
access: result.access,
|
|
5516
|
+
refresh: result.refresh,
|
|
5517
|
+
expires: result.expires
|
|
5518
|
+
});
|
|
5519
|
+
}
|
|
5520
|
+
}
|
|
5521
|
+
async ensureValidToken() {
|
|
5522
|
+
if (!this.oauth) return;
|
|
5523
|
+
if (this.refreshPromise) {
|
|
5524
|
+
const result = await this.refreshPromise;
|
|
5525
|
+
if (result.type === "failed") {
|
|
5526
|
+
throw new Error("Token refresh failed");
|
|
5527
|
+
}
|
|
5528
|
+
return;
|
|
5529
|
+
}
|
|
5530
|
+
this.refreshPromise = this.refreshAccessToken();
|
|
5531
|
+
try {
|
|
5532
|
+
const result = await this.refreshPromise;
|
|
5533
|
+
if (result.type === "success") {
|
|
5534
|
+
this.updateCredentials(result);
|
|
5535
|
+
} else {
|
|
5536
|
+
throw new Error("Token refresh failed");
|
|
5537
|
+
}
|
|
5538
|
+
} finally {
|
|
5539
|
+
this.refreshPromise = null;
|
|
5540
|
+
}
|
|
5541
|
+
}
|
|
5542
|
+
buildFullUrl(path9) {
|
|
5543
|
+
if (path9.startsWith("/")) {
|
|
5544
|
+
return `${this.baseUrl}${path9}`;
|
|
5545
|
+
}
|
|
5546
|
+
return path9;
|
|
5547
|
+
}
|
|
5548
|
+
makeAuthHeaders(headers) {
|
|
5549
|
+
const base = {
|
|
5550
|
+
"anthropic-version": "2023-06-01",
|
|
5551
|
+
"anthropic-beta": "oauth-2025-04-20,fine-grained-tool-streaming-2025-05-14",
|
|
5552
|
+
...headers || {}
|
|
5553
|
+
};
|
|
5554
|
+
if (this.oauth) {
|
|
5555
|
+
base.authorization = `Bearer ${this.oauth.access}`;
|
|
5556
|
+
} else if (this.apiKey) {
|
|
5557
|
+
base["x-api-key"] = this.apiKey;
|
|
5558
|
+
}
|
|
5559
|
+
return base;
|
|
5560
|
+
}
|
|
5561
|
+
async get(url, headers, signal) {
|
|
5562
|
+
const fullUrl = this.buildFullUrl(url);
|
|
5563
|
+
let res = await this.inner.get(fullUrl, this.makeAuthHeaders(headers), signal);
|
|
5564
|
+
if ((res.status === 401 || res.status === 403) && this.oauth) {
|
|
5565
|
+
await this.ensureValidToken();
|
|
5566
|
+
res = await this.inner.get(fullUrl, this.makeAuthHeaders(headers), signal);
|
|
5567
|
+
}
|
|
5568
|
+
return res;
|
|
5569
|
+
}
|
|
5570
|
+
async post(url, body, headers, signal) {
|
|
5571
|
+
const fullUrl = this.buildFullUrl(url);
|
|
5572
|
+
let res = await this.inner.post(fullUrl, body, this.makeAuthHeaders(headers), signal);
|
|
5573
|
+
if ((res.status === 401 || res.status === 403) && this.oauth) {
|
|
5574
|
+
await this.ensureValidToken();
|
|
5575
|
+
res = await this.inner.post(fullUrl, body, this.makeAuthHeaders(headers), signal);
|
|
5576
|
+
}
|
|
5577
|
+
return res;
|
|
5578
|
+
}
|
|
5579
|
+
createRetryTransport() {
|
|
5580
|
+
return new RetryTransport(this, this.retryConfig);
|
|
5581
|
+
}
|
|
5582
|
+
createFetchFunction() {
|
|
5583
|
+
const makeRequest = async (url, init) => {
|
|
5584
|
+
let currentInit = init;
|
|
5585
|
+
if (this.oauth) {
|
|
5586
|
+
const headers = new Headers(currentInit?.headers);
|
|
5587
|
+
headers.delete("x-api-key");
|
|
5588
|
+
headers.set("authorization", `Bearer ${this.oauth.access}`);
|
|
5589
|
+
headers.set("user-agent", "ai-sdk/anthropic/2.0.30 ai-sdk/provider-utils/3.0.12");
|
|
5590
|
+
currentInit = { ...currentInit, headers };
|
|
5591
|
+
}
|
|
5592
|
+
const response = await fetch(url, currentInit);
|
|
5593
|
+
if ((response.status === 401 || response.status === 403) && this.oauth) {
|
|
5594
|
+
await this.ensureValidToken();
|
|
5595
|
+
const headers = new Headers(currentInit?.headers);
|
|
5596
|
+
headers.set("authorization", `Bearer ${this.oauth.access}`);
|
|
5597
|
+
currentInit = { ...currentInit, headers };
|
|
5598
|
+
return fetch(url, currentInit);
|
|
5599
|
+
}
|
|
5600
|
+
return response;
|
|
5601
|
+
};
|
|
5602
|
+
const retryTransport = new RetryTransport(
|
|
5603
|
+
{
|
|
5604
|
+
get: async (url, headers, signal) => {
|
|
5605
|
+
return makeRequest(url, { method: "GET", headers, signal });
|
|
5606
|
+
},
|
|
5607
|
+
post: async (url, body, headers, signal) => {
|
|
5608
|
+
return makeRequest(url, {
|
|
5609
|
+
method: "POST",
|
|
5610
|
+
headers,
|
|
5611
|
+
body: typeof body === "string" ? body : JSON.stringify(body),
|
|
5612
|
+
signal
|
|
5613
|
+
});
|
|
5614
|
+
}
|
|
5615
|
+
},
|
|
5616
|
+
this.retryConfig
|
|
5617
|
+
);
|
|
5618
|
+
return async (url, init) => {
|
|
5619
|
+
const urlStr = typeof url === "string" ? url : url instanceof URL ? url.toString() : url.url;
|
|
5620
|
+
const method = init?.method?.toUpperCase() ?? "GET";
|
|
5621
|
+
const headers = init?.headers ? Object.fromEntries(new Headers(init.headers).entries()) : void 0;
|
|
5622
|
+
if (method === "GET") {
|
|
5623
|
+
return retryTransport.get(urlStr, headers, init?.signal ?? void 0);
|
|
5624
|
+
}
|
|
5625
|
+
return retryTransport.post(urlStr, init?.body, headers, init?.signal ?? void 0);
|
|
5626
|
+
};
|
|
5627
|
+
}
|
|
5628
|
+
getBaseUrl() {
|
|
5629
|
+
return this.baseUrl;
|
|
5630
|
+
}
|
|
5631
|
+
getOAuth() {
|
|
5632
|
+
return this.oauth;
|
|
5633
|
+
}
|
|
5634
|
+
getApiKey() {
|
|
5635
|
+
return this.apiKey;
|
|
5636
|
+
}
|
|
5637
|
+
};
|
|
5638
|
+
|
|
5639
|
+
// src/transports/base-bearer-auth-transport.ts
|
|
5640
|
+
var BaseBearerAuthTransport = class {
|
|
5641
|
+
inner;
|
|
5642
|
+
apiKey;
|
|
5643
|
+
baseUrl;
|
|
5644
|
+
version;
|
|
5645
|
+
customHeaders;
|
|
5646
|
+
constructor(inner, apiKey, baseUrl, version, customHeaders) {
|
|
5647
|
+
this.inner = inner;
|
|
5648
|
+
this.apiKey = apiKey;
|
|
5649
|
+
this.baseUrl = baseUrl ?? this.getDefaultBaseUrl();
|
|
5650
|
+
this.version = version;
|
|
5651
|
+
this.customHeaders = customHeaders;
|
|
5652
|
+
}
|
|
5653
|
+
buildFullUrl(path9) {
|
|
5654
|
+
if (path9.startsWith("/")) {
|
|
5655
|
+
return `${this.baseUrl}${path9}`;
|
|
5656
|
+
}
|
|
5657
|
+
return path9;
|
|
5658
|
+
}
|
|
5659
|
+
makeAuthHeaders(headers) {
|
|
5660
|
+
const base = headers ? { ...headers } : {};
|
|
5661
|
+
if (!base["User-Agent"] && this.version) {
|
|
5662
|
+
base["User-Agent"] = `nuvin-cli/${this.version}`;
|
|
5663
|
+
}
|
|
5664
|
+
if (this.apiKey && this.apiKey.trim() !== "" && !this.customHeaders?.Authorization) {
|
|
5665
|
+
base.Authorization = `Bearer ${this.apiKey}`;
|
|
5666
|
+
}
|
|
5667
|
+
if (this.customHeaders) {
|
|
5668
|
+
Object.assign(base, this.customHeaders);
|
|
5669
|
+
}
|
|
5670
|
+
return base;
|
|
5671
|
+
}
|
|
5672
|
+
async get(url, headers, signal) {
|
|
5673
|
+
const fullUrl = this.buildFullUrl(url);
|
|
5674
|
+
return this.inner.get(fullUrl, this.makeAuthHeaders(headers), signal);
|
|
5675
|
+
}
|
|
5676
|
+
async post(url, body, headers, signal) {
|
|
5677
|
+
const fullUrl = this.buildFullUrl(url);
|
|
5678
|
+
return this.inner.post(fullUrl, body, this.makeAuthHeaders(headers), signal);
|
|
5679
|
+
}
|
|
5680
|
+
};
|
|
5681
|
+
|
|
5682
|
+
// src/transports/simple-bearer-transport.ts
|
|
5683
|
+
var SimpleBearerAuthTransport = class extends BaseBearerAuthTransport {
|
|
5684
|
+
defaultUrl;
|
|
5685
|
+
constructor(inner, defaultBaseUrl, apiKey, baseUrl, version, customHeaders) {
|
|
5686
|
+
super(inner, apiKey, baseUrl ?? defaultBaseUrl, version, customHeaders);
|
|
5687
|
+
this.defaultUrl = defaultBaseUrl;
|
|
5688
|
+
}
|
|
5689
|
+
getDefaultBaseUrl() {
|
|
5690
|
+
return this.defaultUrl;
|
|
5691
|
+
}
|
|
5692
|
+
};
|
|
5693
|
+
|
|
5694
|
+
// src/transports/transport-factory.ts
|
|
5695
|
+
function createTransport(inner, defaultBaseUrl, apiKey, baseUrl, version, customHeaders) {
|
|
5696
|
+
return new SimpleBearerAuthTransport(inner, defaultBaseUrl, apiKey, baseUrl, version, customHeaders);
|
|
5697
|
+
}
|
|
5698
|
+
|
|
5497
5699
|
// src/llm-providers/model-limits.ts
|
|
5498
5700
|
function normalizeModelLimits(provider, model) {
|
|
5499
5701
|
switch (provider.toLowerCase()) {
|
|
@@ -5696,126 +5898,68 @@ import {
|
|
|
5696
5898
|
jsonSchema,
|
|
5697
5899
|
APICallError
|
|
5698
5900
|
} from "ai";
|
|
5699
|
-
var CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
|
|
5700
5901
|
var AnthropicAISDKLLM = class {
|
|
5701
5902
|
opts;
|
|
5702
5903
|
provider;
|
|
5703
|
-
|
|
5904
|
+
transport;
|
|
5905
|
+
authTransport;
|
|
5704
5906
|
constructor(opts = {}) {
|
|
5705
5907
|
this.opts = opts;
|
|
5706
5908
|
}
|
|
5707
|
-
|
|
5708
|
-
if (!this.
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
"Content-Type": "application/json"
|
|
5716
|
-
},
|
|
5717
|
-
body: JSON.stringify({
|
|
5718
|
-
grant_type: "refresh_token",
|
|
5719
|
-
refresh_token: this.opts.oauth.refresh,
|
|
5720
|
-
client_id: CLIENT_ID
|
|
5721
|
-
})
|
|
5909
|
+
getAuthTransport() {
|
|
5910
|
+
if (!this.authTransport) {
|
|
5911
|
+
const base = new FetchTransport({
|
|
5912
|
+
persistFile: this.opts.httpLogFile,
|
|
5913
|
+
logLevel: "INFO",
|
|
5914
|
+
enableConsoleLog: false,
|
|
5915
|
+
maxFileSize: 5 * 1024 * 1024,
|
|
5916
|
+
captureResponseBody: true
|
|
5722
5917
|
});
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
} catch (_error) {
|
|
5734
|
-
return { type: "failed" };
|
|
5735
|
-
}
|
|
5736
|
-
}
|
|
5737
|
-
updateCredentials(result) {
|
|
5738
|
-
if (result.type === "success" && result.access && result.refresh && result.expires) {
|
|
5739
|
-
if (this.opts.oauth) {
|
|
5740
|
-
this.opts.oauth.access = result.access;
|
|
5741
|
-
this.opts.oauth.refresh = result.refresh;
|
|
5742
|
-
this.opts.oauth.expires = result.expires;
|
|
5743
|
-
}
|
|
5744
|
-
this.opts.onTokenUpdate?.({
|
|
5745
|
-
access: result.access,
|
|
5746
|
-
refresh: result.refresh,
|
|
5747
|
-
expires: result.expires
|
|
5918
|
+
this.authTransport = new AnthropicAuthTransport(base, {
|
|
5919
|
+
apiKey: this.opts.apiKey,
|
|
5920
|
+
oauth: this.opts.oauth ? {
|
|
5921
|
+
access: this.opts.oauth.access,
|
|
5922
|
+
refresh: this.opts.oauth.refresh,
|
|
5923
|
+
expires: this.opts.oauth.expires
|
|
5924
|
+
} : void 0,
|
|
5925
|
+
baseUrl: this.opts.baseURL || this.opts.apiUrl,
|
|
5926
|
+
retry: this.opts.retry,
|
|
5927
|
+
onTokenUpdate: this.opts.onTokenUpdate
|
|
5748
5928
|
});
|
|
5749
5929
|
}
|
|
5930
|
+
return this.authTransport;
|
|
5750
5931
|
}
|
|
5751
|
-
|
|
5752
|
-
if (!this.
|
|
5753
|
-
|
|
5754
|
-
const result = await this.refreshPromise;
|
|
5755
|
-
if (result.type === "failed") {
|
|
5756
|
-
throw new Error("Token refresh failed");
|
|
5757
|
-
}
|
|
5758
|
-
return;
|
|
5759
|
-
}
|
|
5760
|
-
this.refreshPromise = this.refreshAccessToken();
|
|
5761
|
-
try {
|
|
5762
|
-
const result = await this.refreshPromise;
|
|
5763
|
-
if (result.type === "success") {
|
|
5764
|
-
this.updateCredentials(result);
|
|
5765
|
-
this.provider = void 0;
|
|
5766
|
-
} else {
|
|
5767
|
-
throw new Error("Token refresh failed");
|
|
5768
|
-
}
|
|
5769
|
-
} finally {
|
|
5770
|
-
this.refreshPromise = null;
|
|
5932
|
+
getTransport() {
|
|
5933
|
+
if (!this.transport) {
|
|
5934
|
+
this.transport = this.getAuthTransport().createRetryTransport();
|
|
5771
5935
|
}
|
|
5936
|
+
return this.transport;
|
|
5772
5937
|
}
|
|
5773
|
-
|
|
5774
|
-
return async (url, init) => {
|
|
5775
|
-
if (init?.headers && this.opts.oauth) {
|
|
5776
|
-
const headers = new Headers(init.headers);
|
|
5777
|
-
headers.delete("x-api-key");
|
|
5778
|
-
headers.set("authorization", `Bearer ${this.opts.oauth.access}`);
|
|
5779
|
-
headers.set("user-agent", "ai-sdk/anthropic/2.0.30 ai-sdk/provider-utils/3.0.12");
|
|
5780
|
-
init = { ...init, headers };
|
|
5781
|
-
}
|
|
5782
|
-
const response = await fetch(url, init);
|
|
5783
|
-
if ((response.status === 401 || response.status === 403) && this.opts.oauth) {
|
|
5784
|
-
await this.ensureValidToken();
|
|
5785
|
-
if (init?.headers) {
|
|
5786
|
-
const headers = new Headers(init.headers);
|
|
5787
|
-
headers.set("authorization", `Bearer ${this.opts.oauth.access}`);
|
|
5788
|
-
init = { ...init, headers };
|
|
5789
|
-
}
|
|
5790
|
-
return fetch(url, init);
|
|
5791
|
-
}
|
|
5792
|
-
return response;
|
|
5793
|
-
};
|
|
5794
|
-
}
|
|
5795
|
-
async getProvider() {
|
|
5938
|
+
getProvider() {
|
|
5796
5939
|
if (this.provider) {
|
|
5797
5940
|
return this.provider;
|
|
5798
5941
|
}
|
|
5942
|
+
const authTransport = this.getAuthTransport();
|
|
5799
5943
|
if (this.opts.oauth) {
|
|
5800
5944
|
this.provider = createAnthropic({
|
|
5801
5945
|
apiKey: "sk-ant-oauth-placeholder",
|
|
5802
|
-
baseURL:
|
|
5946
|
+
baseURL: authTransport.getBaseUrl(),
|
|
5803
5947
|
headers: {
|
|
5804
5948
|
authorization: `Bearer ${this.opts.oauth.access}`,
|
|
5805
5949
|
"anthropic-beta": "oauth-2025-04-20,claude-code-20250219,interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14"
|
|
5806
5950
|
},
|
|
5807
|
-
fetch:
|
|
5951
|
+
fetch: authTransport.createFetchFunction()
|
|
5808
5952
|
});
|
|
5809
5953
|
} else {
|
|
5810
5954
|
this.provider = createAnthropic({
|
|
5811
5955
|
apiKey: this.opts.apiKey,
|
|
5812
|
-
baseURL:
|
|
5956
|
+
baseURL: authTransport.getBaseUrl()
|
|
5813
5957
|
});
|
|
5814
5958
|
}
|
|
5815
5959
|
return this.provider;
|
|
5816
5960
|
}
|
|
5817
|
-
|
|
5818
|
-
const provider =
|
|
5961
|
+
getModel(modelName) {
|
|
5962
|
+
const provider = this.getProvider();
|
|
5819
5963
|
return provider(modelName);
|
|
5820
5964
|
}
|
|
5821
5965
|
transformMessages(messages) {
|
|
@@ -6049,7 +6193,7 @@ var AnthropicAISDKLLM = class {
|
|
|
6049
6193
|
}
|
|
6050
6194
|
async generateCompletion(params, signal) {
|
|
6051
6195
|
try {
|
|
6052
|
-
const model =
|
|
6196
|
+
const model = this.getModel(params.model);
|
|
6053
6197
|
const messages = this.transformMessages(params.messages);
|
|
6054
6198
|
const tools = this.transformTools(params.tools);
|
|
6055
6199
|
const toolChoice = tools ? this.transformToolChoice(params.tool_choice) : void 0;
|
|
@@ -6083,7 +6227,7 @@ var AnthropicAISDKLLM = class {
|
|
|
6083
6227
|
}
|
|
6084
6228
|
async streamCompletion(params, handlers = {}, signal) {
|
|
6085
6229
|
let streamError = null;
|
|
6086
|
-
const model =
|
|
6230
|
+
const model = this.getModel(params.model);
|
|
6087
6231
|
const messages = this.transformMessages(params.messages);
|
|
6088
6232
|
const tools = this.transformTools(params.tools);
|
|
6089
6233
|
const toolChoice = tools ? this.transformToolChoice(params.tool_choice) : void 0;
|
|
@@ -6134,45 +6278,17 @@ var AnthropicAISDKLLM = class {
|
|
|
6134
6278
|
}
|
|
6135
6279
|
}
|
|
6136
6280
|
async getModels(signal) {
|
|
6137
|
-
const
|
|
6138
|
-
|
|
6139
|
-
const headers = {
|
|
6140
|
-
"anthropic-version": "2023-06-01",
|
|
6141
|
-
"anthropic-beta": " oauth-2025-04-20,fine-grained-tool-streaming-2025-05-14"
|
|
6142
|
-
};
|
|
6143
|
-
if (this.opts.oauth) {
|
|
6144
|
-
headers.authorization = `Bearer ${this.opts.oauth.access}`;
|
|
6145
|
-
} else if (this.opts.apiKey) {
|
|
6146
|
-
headers["x-api-key"] = this.opts.apiKey;
|
|
6147
|
-
} else {
|
|
6281
|
+
const authTransport = this.getAuthTransport();
|
|
6282
|
+
if (!authTransport.getApiKey() && !authTransport.getOAuth()) {
|
|
6148
6283
|
throw new LLMError("No API key or OAuth credentials provided", 401, false);
|
|
6149
6284
|
}
|
|
6150
6285
|
try {
|
|
6151
|
-
const
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
});
|
|
6156
|
-
if (!response.ok) {
|
|
6157
|
-
if ((response.status === 401 || response.status === 403) && this.opts.oauth) {
|
|
6158
|
-
await this.ensureValidToken();
|
|
6159
|
-
headers.authorization = `Bearer ${this.opts.oauth.access}`;
|
|
6160
|
-
const retryResponse = await fetch(url, {
|
|
6161
|
-
method: "GET",
|
|
6162
|
-
headers,
|
|
6163
|
-
signal
|
|
6164
|
-
});
|
|
6165
|
-
if (!retryResponse.ok) {
|
|
6166
|
-
const text2 = await retryResponse.text();
|
|
6167
|
-
throw new LLMError(text2 || `Failed to fetch models: ${retryResponse.status}`, retryResponse.status);
|
|
6168
|
-
}
|
|
6169
|
-
const data2 = await retryResponse.json();
|
|
6170
|
-
return data2.data.map((model) => normalizeModelInfo("anthropic", model));
|
|
6171
|
-
}
|
|
6172
|
-
const text = await response.text();
|
|
6173
|
-
throw new LLMError(text || `Failed to fetch models: ${response.status}`, response.status);
|
|
6286
|
+
const res = await this.getTransport().get("/models", void 0, signal);
|
|
6287
|
+
if (!res.ok) {
|
|
6288
|
+
const text = await res.text();
|
|
6289
|
+
throw new LLMError(text || `Failed to fetch models: ${res.status}`, res.status);
|
|
6174
6290
|
}
|
|
6175
|
-
const data = await
|
|
6291
|
+
const data = await res.json();
|
|
6176
6292
|
return data.data.map((model) => normalizeModelInfo("anthropic", model));
|
|
6177
6293
|
} catch (error) {
|
|
6178
6294
|
if (error instanceof LLMError) {
|