@nuvin/nuvin-core 1.4.3 → 1.5.1
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 +10 -7
- package/dist/index.js +151 -208
- package/package.json +3 -3
package/dist/VERSION
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -283,6 +283,8 @@ type UsageData = {
|
|
|
283
283
|
cost_details?: {
|
|
284
284
|
upstream_inference_cost?: number;
|
|
285
285
|
};
|
|
286
|
+
cache_creation_input_tokens?: number;
|
|
287
|
+
cache_read_input_tokens?: number;
|
|
286
288
|
};
|
|
287
289
|
type CompletionResult = {
|
|
288
290
|
content: string;
|
|
@@ -833,6 +835,7 @@ type ConversationMetadata = {
|
|
|
833
835
|
toolCallCount?: number;
|
|
834
836
|
totalTimeMs?: number;
|
|
835
837
|
totalPrice?: number;
|
|
838
|
+
summarizedFrom?: string;
|
|
836
839
|
};
|
|
837
840
|
type Conversation = {
|
|
838
841
|
messages: Message[];
|
|
@@ -1217,19 +1220,16 @@ interface TransportResponse {
|
|
|
1217
1220
|
}
|
|
1218
1221
|
interface HttpTransport {
|
|
1219
1222
|
get(url: string, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
|
|
1220
|
-
|
|
1221
|
-
postStream(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<Response>;
|
|
1223
|
+
post(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<Response>;
|
|
1222
1224
|
}
|
|
1223
1225
|
declare class FetchTransport implements HttpTransport {
|
|
1224
1226
|
private opts;
|
|
1225
1227
|
private logger;
|
|
1226
1228
|
constructor(opts?: PersistOptions);
|
|
1227
|
-
private getRequestSize;
|
|
1228
1229
|
private getResponseSize;
|
|
1229
1230
|
private headersToRecord;
|
|
1231
|
+
post(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<Response>;
|
|
1230
1232
|
get(url: string, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
|
|
1231
|
-
postJson(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
|
|
1232
|
-
postStream(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<Response>;
|
|
1233
1233
|
}
|
|
1234
1234
|
|
|
1235
1235
|
declare class GithubAuthTransport implements HttpTransport {
|
|
@@ -1249,9 +1249,8 @@ declare class GithubAuthTransport implements HttpTransport {
|
|
|
1249
1249
|
private makeAuthHeaders;
|
|
1250
1250
|
private determineInitiator;
|
|
1251
1251
|
private generateRequestId;
|
|
1252
|
+
post(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<Response>;
|
|
1252
1253
|
get(url: string, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
|
|
1253
|
-
postJson(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
|
|
1254
|
-
postStream(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<Response>;
|
|
1255
1254
|
}
|
|
1256
1255
|
|
|
1257
1256
|
declare class LLMError extends Error {
|
|
@@ -1267,6 +1266,7 @@ declare abstract class BaseLLM implements LLMPort {
|
|
|
1267
1266
|
enablePromptCaching?: boolean;
|
|
1268
1267
|
});
|
|
1269
1268
|
protected abstract createTransport(): HttpTransport;
|
|
1269
|
+
protected transformUsage(rawUsage: unknown): UsageData | undefined;
|
|
1270
1270
|
protected getTransport(): HttpTransport;
|
|
1271
1271
|
protected applyCacheControl(params: CompletionParams): CompletionParams;
|
|
1272
1272
|
generateCompletion(params: CompletionParams, signal?: AbortSignal): Promise<CompletionResult>;
|
|
@@ -1302,6 +1302,7 @@ declare class GithubLLM extends BaseLLM implements LLMPort {
|
|
|
1302
1302
|
private readonly opts;
|
|
1303
1303
|
constructor(opts?: GithubOptions);
|
|
1304
1304
|
protected createTransport(): GithubAuthTransport;
|
|
1305
|
+
protected transformUsage(rawUsage: unknown): UsageData | undefined;
|
|
1305
1306
|
getModels(signal?: AbortSignal): Promise<ModelInfo[]>;
|
|
1306
1307
|
private handleError;
|
|
1307
1308
|
generateCompletion(params: CompletionParams, signal?: AbortSignal): Promise<CompletionResult>;
|
|
@@ -1343,6 +1344,7 @@ declare class AnthropicAISDKLLM {
|
|
|
1343
1344
|
private transformMessages;
|
|
1344
1345
|
private transformTools;
|
|
1345
1346
|
private transformToolChoice;
|
|
1347
|
+
private transformUsage;
|
|
1346
1348
|
private handleError;
|
|
1347
1349
|
generateCompletion(params: CompletionParams, signal?: AbortSignal): Promise<CompletionResult>;
|
|
1348
1350
|
streamCompletion(params: CompletionParams, handlers?: {
|
|
@@ -1350,6 +1352,7 @@ declare class AnthropicAISDKLLM {
|
|
|
1350
1352
|
onToolCallDelta?: (tc: ToolCall) => void;
|
|
1351
1353
|
onStreamFinish?: (finishReason?: string, usage?: UsageData) => void;
|
|
1352
1354
|
}, signal?: AbortSignal): Promise<CompletionResult>;
|
|
1355
|
+
getModels(signal?: AbortSignal): Promise<ModelInfo[]>;
|
|
1353
1356
|
}
|
|
1354
1357
|
|
|
1355
1358
|
type ModelConfig = false | true | string | string[] | Array<{
|
package/dist/index.js
CHANGED
|
@@ -3958,24 +3958,6 @@ function mergeChoices(choices) {
|
|
|
3958
3958
|
...extraFields
|
|
3959
3959
|
};
|
|
3960
3960
|
}
|
|
3961
|
-
function normalizeUsage(usage) {
|
|
3962
|
-
if (!usage) return void 0;
|
|
3963
|
-
const usageObj = usage;
|
|
3964
|
-
const prompt_tokens = usage.prompt_tokens ?? (typeof usageObj.input_tokens === "number" ? usageObj.input_tokens : void 0);
|
|
3965
|
-
const completion_tokens = usage.completion_tokens ?? (typeof usageObj.output_tokens === "number" ? usageObj.output_tokens : void 0);
|
|
3966
|
-
const total_tokens = usage.total_tokens ?? (prompt_tokens != null && completion_tokens != null ? prompt_tokens + completion_tokens : void 0);
|
|
3967
|
-
const cost = usage.cost ?? (typeof usageObj.estimated_cost === "number" ? usageObj.estimated_cost : void 0);
|
|
3968
|
-
return {
|
|
3969
|
-
prompt_tokens,
|
|
3970
|
-
completion_tokens,
|
|
3971
|
-
total_tokens,
|
|
3972
|
-
...usage.reasoning_tokens !== void 0 && { reasoning_tokens: usage.reasoning_tokens },
|
|
3973
|
-
...usage.prompt_tokens_details && { prompt_tokens_details: usage.prompt_tokens_details },
|
|
3974
|
-
...usage.completion_tokens_details && { completion_tokens_details: usage.completion_tokens_details },
|
|
3975
|
-
...cost !== void 0 && { cost },
|
|
3976
|
-
...usage.cost_details && { cost_details: usage.cost_details }
|
|
3977
|
-
};
|
|
3978
|
-
}
|
|
3979
3961
|
|
|
3980
3962
|
// src/llm-providers/base-llm.ts
|
|
3981
3963
|
var LLMError = class _LLMError extends Error {
|
|
@@ -3997,6 +3979,28 @@ var BaseLLM = class {
|
|
|
3997
3979
|
this.apiUrl = apiUrl;
|
|
3998
3980
|
this.enablePromptCaching = options?.enablePromptCaching ?? false;
|
|
3999
3981
|
}
|
|
3982
|
+
transformUsage(rawUsage) {
|
|
3983
|
+
if (!rawUsage) return void 0;
|
|
3984
|
+
const usage = rawUsage;
|
|
3985
|
+
const promptTokens = usage.prompt_tokens ?? usage.input_tokens;
|
|
3986
|
+
const completionTokens = usage.completion_tokens ?? usage.output_tokens;
|
|
3987
|
+
const totalTokens = usage.total_tokens ?? (promptTokens != null && completionTokens != null ? promptTokens + completionTokens : void 0);
|
|
3988
|
+
const cost = usage.cost ?? usage.estimated_cost;
|
|
3989
|
+
return {
|
|
3990
|
+
prompt_tokens: promptTokens,
|
|
3991
|
+
completion_tokens: completionTokens,
|
|
3992
|
+
total_tokens: totalTokens,
|
|
3993
|
+
...usage.reasoning_tokens !== void 0 && { reasoning_tokens: usage.reasoning_tokens },
|
|
3994
|
+
...usage.prompt_tokens_details && { prompt_tokens_details: usage.prompt_tokens_details },
|
|
3995
|
+
...usage.completion_tokens_details && { completion_tokens_details: usage.completion_tokens_details },
|
|
3996
|
+
...cost !== void 0 && { cost },
|
|
3997
|
+
...usage.cost_details && { cost_details: usage.cost_details },
|
|
3998
|
+
...usage.cache_creation_input_tokens !== void 0 && {
|
|
3999
|
+
cache_creation_input_tokens: usage.cache_creation_input_tokens
|
|
4000
|
+
},
|
|
4001
|
+
...usage.cache_read_input_tokens !== void 0 && { cache_read_input_tokens: usage.cache_read_input_tokens }
|
|
4002
|
+
};
|
|
4003
|
+
}
|
|
4000
4004
|
getTransport() {
|
|
4001
4005
|
if (!this.transport) this.transport = this.createTransport();
|
|
4002
4006
|
return this.transport;
|
|
@@ -4073,7 +4077,7 @@ var BaseLLM = class {
|
|
|
4073
4077
|
if (enhancedParams.tools && enhancedParams.tools.length > 0) body.tools = enhancedParams.tools;
|
|
4074
4078
|
if (enhancedParams.tool_choice && enhancedParams.tools && enhancedParams.tools.length > 0)
|
|
4075
4079
|
body.tool_choice = enhancedParams.tool_choice;
|
|
4076
|
-
const res = await this.getTransport().
|
|
4080
|
+
const res = await this.getTransport().post("/chat/completions", body, void 0, signal);
|
|
4077
4081
|
if (!res.ok) {
|
|
4078
4082
|
const text = await res.text();
|
|
4079
4083
|
const isRetryable = res.status === 429 || res.status >= 500;
|
|
@@ -4081,7 +4085,7 @@ var BaseLLM = class {
|
|
|
4081
4085
|
}
|
|
4082
4086
|
const data = await res.json();
|
|
4083
4087
|
const merged = mergeChoices(data.choices);
|
|
4084
|
-
const usage =
|
|
4088
|
+
const usage = this.transformUsage(data.usage);
|
|
4085
4089
|
return { ...merged, ...usage ? { usage } : {} };
|
|
4086
4090
|
}
|
|
4087
4091
|
async streamCompletion(params, handlers = {}, signal) {
|
|
@@ -4099,12 +4103,7 @@ var BaseLLM = class {
|
|
|
4099
4103
|
if (enhancedParams.tools && enhancedParams.tools.length > 0) body.tools = enhancedParams.tools;
|
|
4100
4104
|
if (enhancedParams.tool_choice && enhancedParams.tools && enhancedParams.tools.length > 0)
|
|
4101
4105
|
body.tool_choice = enhancedParams.tool_choice;
|
|
4102
|
-
const res = await this.getTransport().
|
|
4103
|
-
"/chat/completions",
|
|
4104
|
-
body,
|
|
4105
|
-
{ Accept: "text/event-stream" },
|
|
4106
|
-
signal
|
|
4107
|
-
);
|
|
4106
|
+
const res = await this.getTransport().post("/chat/completions", body, { Accept: "text/event-stream" }, signal);
|
|
4108
4107
|
if (!res.ok) {
|
|
4109
4108
|
const text = await res.text();
|
|
4110
4109
|
const isRetryable = res.status === 429 || res.status >= 500;
|
|
@@ -4137,7 +4136,7 @@ var BaseLLM = class {
|
|
|
4137
4136
|
}
|
|
4138
4137
|
const usageData = evt.usage || choices[0]?.usage;
|
|
4139
4138
|
if (usageData) {
|
|
4140
|
-
usage =
|
|
4139
|
+
usage = this.transformUsage(usageData);
|
|
4141
4140
|
if (lastFinishReason && handlers.onStreamFinish) {
|
|
4142
4141
|
handlers.onStreamFinish(lastFinishReason, usage);
|
|
4143
4142
|
} else {
|
|
@@ -4232,9 +4231,6 @@ var BaseLLM = class {
|
|
|
4232
4231
|
}
|
|
4233
4232
|
};
|
|
4234
4233
|
|
|
4235
|
-
// src/transports/transport.ts
|
|
4236
|
-
import * as crypto2 from "crypto";
|
|
4237
|
-
|
|
4238
4234
|
// src/logger/network.ts
|
|
4239
4235
|
var NetworkLogger = class {
|
|
4240
4236
|
constructor(opts = {}) {
|
|
@@ -4381,10 +4377,6 @@ var FetchTransport = class {
|
|
|
4381
4377
|
this.logger = new NetworkLogger(this.opts);
|
|
4382
4378
|
}
|
|
4383
4379
|
logger;
|
|
4384
|
-
getRequestSize(body) {
|
|
4385
|
-
if (!body) return 0;
|
|
4386
|
-
return new TextEncoder().encode(JSON.stringify(body)).length;
|
|
4387
|
-
}
|
|
4388
4380
|
getResponseSize(headers) {
|
|
4389
4381
|
const contentLength = headers.get("content-length");
|
|
4390
4382
|
return contentLength ? parseInt(contentLength, 10) : 0;
|
|
@@ -4396,6 +4388,17 @@ var FetchTransport = class {
|
|
|
4396
4388
|
});
|
|
4397
4389
|
return record;
|
|
4398
4390
|
}
|
|
4391
|
+
async post(url, body, headers, signal) {
|
|
4392
|
+
if (typeof fetch !== "function") {
|
|
4393
|
+
throw new Error("Global fetch is not available. Use Node 18+ or a compatible runtime.");
|
|
4394
|
+
}
|
|
4395
|
+
return fetch(url, {
|
|
4396
|
+
method: "POST",
|
|
4397
|
+
headers: { "Content-Type": "application/json", ...headers || {} },
|
|
4398
|
+
body: JSON.stringify(body ?? {}),
|
|
4399
|
+
signal
|
|
4400
|
+
});
|
|
4401
|
+
}
|
|
4399
4402
|
async get(url, headers, signal) {
|
|
4400
4403
|
if (typeof fetch !== "function") {
|
|
4401
4404
|
throw new Error("Global fetch is not available. Use Node 18+ or a compatible runtime.");
|
|
@@ -4453,123 +4456,10 @@ var FetchTransport = class {
|
|
|
4453
4456
|
throw error;
|
|
4454
4457
|
}
|
|
4455
4458
|
}
|
|
4456
|
-
async postJson(url, body, headers, signal) {
|
|
4457
|
-
if (typeof fetch !== "function") {
|
|
4458
|
-
throw new Error("Global fetch is not available. Use Node 18+ or a compatible runtime.");
|
|
4459
|
-
}
|
|
4460
|
-
const startTime = performance.now();
|
|
4461
|
-
const reqBody = JSON.stringify(body ?? {});
|
|
4462
|
-
try {
|
|
4463
|
-
const res = await fetch(url, {
|
|
4464
|
-
method: "POST",
|
|
4465
|
-
headers: { "Content-Type": "application/json", ...headers || {} },
|
|
4466
|
-
body: reqBody,
|
|
4467
|
-
signal
|
|
4468
|
-
});
|
|
4469
|
-
const ttfb = performance.now() - startTime;
|
|
4470
|
-
try {
|
|
4471
|
-
const clone = res.clone();
|
|
4472
|
-
const text = await clone.text();
|
|
4473
|
-
let response;
|
|
4474
|
-
try {
|
|
4475
|
-
response = JSON.parse(text);
|
|
4476
|
-
} catch {
|
|
4477
|
-
response = text;
|
|
4478
|
-
}
|
|
4479
|
-
const duration = performance.now() - startTime;
|
|
4480
|
-
await this.logger.logRequest({
|
|
4481
|
-
url,
|
|
4482
|
-
method: "POST",
|
|
4483
|
-
headers: { ...headers || {} },
|
|
4484
|
-
requestBody: body,
|
|
4485
|
-
responseStatus: res.status,
|
|
4486
|
-
responseHeaders: this.headersToRecord(res.headers),
|
|
4487
|
-
ok: res.ok,
|
|
4488
|
-
stream: false,
|
|
4489
|
-
startTime,
|
|
4490
|
-
duration,
|
|
4491
|
-
ttfb,
|
|
4492
|
-
requestSize: this.getRequestSize(body),
|
|
4493
|
-
responseSize: this.getResponseSize(res.headers),
|
|
4494
|
-
response
|
|
4495
|
-
});
|
|
4496
|
-
} catch {
|
|
4497
|
-
}
|
|
4498
|
-
return res;
|
|
4499
|
-
} catch (error) {
|
|
4500
|
-
const duration = performance.now() - startTime;
|
|
4501
|
-
await this.logger.logRequest({
|
|
4502
|
-
url,
|
|
4503
|
-
method: "POST",
|
|
4504
|
-
headers: { ...headers || {} },
|
|
4505
|
-
requestBody: body,
|
|
4506
|
-
responseStatus: 0,
|
|
4507
|
-
ok: false,
|
|
4508
|
-
stream: false,
|
|
4509
|
-
startTime,
|
|
4510
|
-
duration,
|
|
4511
|
-
requestSize: this.getRequestSize(body),
|
|
4512
|
-
error: error instanceof Error ? error.message : String(error)
|
|
4513
|
-
});
|
|
4514
|
-
throw error;
|
|
4515
|
-
}
|
|
4516
|
-
}
|
|
4517
|
-
async postStream(url, body, headers, signal) {
|
|
4518
|
-
if (typeof fetch !== "function") {
|
|
4519
|
-
throw new Error("Global fetch is not available. Use Node 18+ or a compatible runtime.");
|
|
4520
|
-
}
|
|
4521
|
-
const startTime = performance.now();
|
|
4522
|
-
const reqBody = JSON.stringify(body ?? {});
|
|
4523
|
-
try {
|
|
4524
|
-
const res = await fetch(url, {
|
|
4525
|
-
method: "POST",
|
|
4526
|
-
headers: { "Content-Type": "application/json", ...headers || {} },
|
|
4527
|
-
body: reqBody,
|
|
4528
|
-
signal
|
|
4529
|
-
});
|
|
4530
|
-
const ttfb = performance.now() - startTime;
|
|
4531
|
-
const duration = performance.now() - startTime;
|
|
4532
|
-
const logEntryData = {
|
|
4533
|
-
id: crypto2.randomUUID ? crypto2.randomUUID() : Math.random().toString(36).slice(2),
|
|
4534
|
-
timestamp: Date.now().toString(),
|
|
4535
|
-
url,
|
|
4536
|
-
method: "POST",
|
|
4537
|
-
headers: { ...headers || {} },
|
|
4538
|
-
requestBody: body,
|
|
4539
|
-
responseStatus: res.status,
|
|
4540
|
-
responseHeaders: this.headersToRecord(res.headers),
|
|
4541
|
-
ok: res.ok,
|
|
4542
|
-
stream: true,
|
|
4543
|
-
startTime,
|
|
4544
|
-
duration,
|
|
4545
|
-
ttfb,
|
|
4546
|
-
requestSize: this.getRequestSize(body),
|
|
4547
|
-
responseSize: this.getResponseSize(res.headers)
|
|
4548
|
-
};
|
|
4549
|
-
void this.logger.logRequest(logEntryData);
|
|
4550
|
-
return this.logger.createStreamTapper(res, logEntryData);
|
|
4551
|
-
} catch (error) {
|
|
4552
|
-
const duration = performance.now() - startTime;
|
|
4553
|
-
await this.logger.logRequest({
|
|
4554
|
-
url,
|
|
4555
|
-
method: "POST",
|
|
4556
|
-
headers: { ...headers || {} },
|
|
4557
|
-
requestBody: body,
|
|
4558
|
-
responseStatus: 0,
|
|
4559
|
-
ok: false,
|
|
4560
|
-
stream: true,
|
|
4561
|
-
startTime,
|
|
4562
|
-
duration,
|
|
4563
|
-
requestSize: this.getRequestSize(body),
|
|
4564
|
-
error: error instanceof Error ? error.message : String(error)
|
|
4565
|
-
});
|
|
4566
|
-
throw error;
|
|
4567
|
-
}
|
|
4568
|
-
}
|
|
4569
4459
|
};
|
|
4570
4460
|
|
|
4571
4461
|
// src/transports/github-transport.ts
|
|
4572
|
-
import * as
|
|
4462
|
+
import * as crypto2 from "crypto";
|
|
4573
4463
|
var isVisionMessage = (msg) => {
|
|
4574
4464
|
if (!msg) return false;
|
|
4575
4465
|
const content = msg.content;
|
|
@@ -4653,8 +4543,8 @@ var GithubAuthTransport = class {
|
|
|
4653
4543
|
return "agent";
|
|
4654
4544
|
}
|
|
4655
4545
|
generateRequestId() {
|
|
4656
|
-
if (
|
|
4657
|
-
return
|
|
4546
|
+
if (crypto2?.randomUUID) {
|
|
4547
|
+
return crypto2.randomUUID();
|
|
4658
4548
|
}
|
|
4659
4549
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
4660
4550
|
const r = Math.random() * 16 | 0;
|
|
@@ -4662,44 +4552,29 @@ var GithubAuthTransport = class {
|
|
|
4662
4552
|
return v.toString(16);
|
|
4663
4553
|
});
|
|
4664
4554
|
}
|
|
4665
|
-
async
|
|
4555
|
+
async post(url, body, headers, signal) {
|
|
4666
4556
|
if (!this.apiKey && this.accessToken) {
|
|
4667
4557
|
await this.exchangeToken(signal);
|
|
4668
4558
|
}
|
|
4669
4559
|
const fullUrl = this.buildFullUrl(url);
|
|
4670
|
-
let res = await this.inner.
|
|
4560
|
+
let res = await this.inner.post(fullUrl, body, this.makeAuthHeaders(headers, body), signal);
|
|
4671
4561
|
if (res.status === 401 && this.accessToken) {
|
|
4672
4562
|
await this.exchangeToken(signal);
|
|
4673
4563
|
const retryUrl = this.buildFullUrl(url);
|
|
4674
|
-
res = await this.inner.
|
|
4564
|
+
res = await this.inner.post(retryUrl, body, this.makeAuthHeaders(headers, body), signal);
|
|
4675
4565
|
}
|
|
4676
4566
|
return res;
|
|
4677
4567
|
}
|
|
4678
|
-
async
|
|
4568
|
+
async get(url, headers, signal) {
|
|
4679
4569
|
if (!this.apiKey && this.accessToken) {
|
|
4680
4570
|
await this.exchangeToken(signal);
|
|
4681
4571
|
}
|
|
4682
4572
|
const fullUrl = this.buildFullUrl(url);
|
|
4683
|
-
let res = await this.inner.
|
|
4684
|
-
if (res.status === 401 && this.accessToken) {
|
|
4685
|
-
await this.exchangeToken(signal);
|
|
4686
|
-
const retryUrl = this.buildFullUrl(url);
|
|
4687
|
-
res = await this.inner.postJson(retryUrl, body, this.makeAuthHeaders(headers, body), signal);
|
|
4688
|
-
}
|
|
4689
|
-
return res;
|
|
4690
|
-
}
|
|
4691
|
-
async postStream(url, body, headers, signal) {
|
|
4692
|
-
let hdrs = this.makeAuthHeaders({ Accept: "text/event-stream", ...headers || {} }, body);
|
|
4693
|
-
if ((!this.apiKey || !hdrs.Authorization) && this.accessToken) {
|
|
4694
|
-
await this.exchangeToken(signal);
|
|
4695
|
-
hdrs = this.makeAuthHeaders({ Accept: "text/event-stream", ...headers || {} }, body);
|
|
4696
|
-
}
|
|
4697
|
-
const fullUrl = this.buildFullUrl(url);
|
|
4698
|
-
let res = await this.inner.postStream(fullUrl, body, hdrs, signal);
|
|
4573
|
+
let res = await this.inner.get(fullUrl, this.makeAuthHeaders(headers), signal);
|
|
4699
4574
|
if (res.status === 401 && this.accessToken) {
|
|
4700
4575
|
await this.exchangeToken(signal);
|
|
4701
4576
|
const retryUrl = this.buildFullUrl(url);
|
|
4702
|
-
res = await this.inner.
|
|
4577
|
+
res = await this.inner.get(retryUrl, this.makeAuthHeaders(headers), signal);
|
|
4703
4578
|
}
|
|
4704
4579
|
return res;
|
|
4705
4580
|
}
|
|
@@ -4742,13 +4617,9 @@ var BaseBearerAuthTransport = class {
|
|
|
4742
4617
|
const fullUrl = this.buildFullUrl(url);
|
|
4743
4618
|
return this.inner.get(fullUrl, this.makeAuthHeaders(headers), signal);
|
|
4744
4619
|
}
|
|
4745
|
-
async
|
|
4746
|
-
const fullUrl = this.buildFullUrl(url);
|
|
4747
|
-
return this.inner.postJson(fullUrl, body, this.makeAuthHeaders(headers), signal);
|
|
4748
|
-
}
|
|
4749
|
-
async postStream(url, body, headers, signal) {
|
|
4620
|
+
async post(url, body, headers, signal) {
|
|
4750
4621
|
const fullUrl = this.buildFullUrl(url);
|
|
4751
|
-
return this.inner.
|
|
4622
|
+
return this.inner.post(fullUrl, body, this.makeAuthHeaders(headers), signal);
|
|
4752
4623
|
}
|
|
4753
4624
|
};
|
|
4754
4625
|
|
|
@@ -4782,6 +4653,9 @@ function normalizeModelLimits(provider, model) {
|
|
|
4782
4653
|
maxOutput: limits?.max_output_tokens
|
|
4783
4654
|
};
|
|
4784
4655
|
}
|
|
4656
|
+
case "anthropic": {
|
|
4657
|
+
return getFallbackLimits("anthropic", model.id);
|
|
4658
|
+
}
|
|
4785
4659
|
case "deepinfra": {
|
|
4786
4660
|
const metadata = model.metadata;
|
|
4787
4661
|
const contextLength = metadata?.context_length;
|
|
@@ -4846,10 +4720,18 @@ var FALLBACK_LIMITS = {
|
|
|
4846
4720
|
"kimi-k2-turbo-preview": { contextWindow: 262144 }
|
|
4847
4721
|
},
|
|
4848
4722
|
anthropic: {
|
|
4849
|
-
"claude-
|
|
4850
|
-
"claude-
|
|
4723
|
+
"claude-opus-4-5-20251101": { contextWindow: 2e5, maxOutput: 16e3 },
|
|
4724
|
+
"claude-haiku-4-5-20251001": { contextWindow: 2e5, maxOutput: 16e3 },
|
|
4725
|
+
"claude-sonnet-4-5-20250929": { contextWindow: 2e5, maxOutput: 16e3 },
|
|
4726
|
+
"claude-opus-4-1-20250805": { contextWindow: 2e5, maxOutput: 16e3 },
|
|
4727
|
+
"claude-opus-4-20250514": { contextWindow: 2e5, maxOutput: 16e3 },
|
|
4728
|
+
"claude-sonnet-4-20250514": { contextWindow: 2e5, maxOutput: 16e3 },
|
|
4729
|
+
"claude-3-7-sonnet-20250219": { contextWindow: 2e5, maxOutput: 8192 },
|
|
4730
|
+
"claude-3-5-haiku-20241022": { contextWindow: 2e5, maxOutput: 8192 },
|
|
4731
|
+
"claude-3-haiku-20240307": { contextWindow: 2e5, maxOutput: 4096 },
|
|
4851
4732
|
"claude-3-opus-20240229": { contextWindow: 2e5, maxOutput: 4096 },
|
|
4852
|
-
"claude-
|
|
4733
|
+
"claude-sonnet-4-5": { contextWindow: 2e5, maxOutput: 16e3 },
|
|
4734
|
+
"claude-3-5-sonnet-20241022": { contextWindow: 2e5, maxOutput: 8192 }
|
|
4853
4735
|
}
|
|
4854
4736
|
};
|
|
4855
4737
|
function getFallbackLimits(provider, model) {
|
|
@@ -4859,7 +4741,10 @@ function getFallbackLimits(provider, model) {
|
|
|
4859
4741
|
}
|
|
4860
4742
|
function normalizeModelInfo(provider, model) {
|
|
4861
4743
|
const id = model.id;
|
|
4862
|
-
|
|
4744
|
+
let name = model.name ?? id;
|
|
4745
|
+
if (provider.toLowerCase() === "anthropic" && model.display_name) {
|
|
4746
|
+
name = model.display_name;
|
|
4747
|
+
}
|
|
4863
4748
|
const limits = normalizeModelLimits(provider, model);
|
|
4864
4749
|
return {
|
|
4865
4750
|
id,
|
|
@@ -4881,9 +4766,7 @@ var GithubLLM = class extends BaseLLM {
|
|
|
4881
4766
|
logLevel: "INFO",
|
|
4882
4767
|
enableConsoleLog: false,
|
|
4883
4768
|
maxFileSize: 5 * 1024 * 1024,
|
|
4884
|
-
// 5MB before rotation
|
|
4885
4769
|
captureResponseBody: true
|
|
4886
|
-
// Disable for better performance
|
|
4887
4770
|
});
|
|
4888
4771
|
return new GithubAuthTransport(base, {
|
|
4889
4772
|
baseUrl: this.opts.apiUrl,
|
|
@@ -4891,6 +4774,17 @@ var GithubLLM = class extends BaseLLM {
|
|
|
4891
4774
|
accessToken: this.opts.accessToken
|
|
4892
4775
|
});
|
|
4893
4776
|
}
|
|
4777
|
+
transformUsage(rawUsage) {
|
|
4778
|
+
if (!rawUsage) return void 0;
|
|
4779
|
+
const usage = rawUsage;
|
|
4780
|
+
return {
|
|
4781
|
+
prompt_tokens: usage.prompt_tokens,
|
|
4782
|
+
completion_tokens: usage.completion_tokens,
|
|
4783
|
+
total_tokens: usage.total_tokens,
|
|
4784
|
+
prompt_tokens_details: usage.prompt_tokens_details,
|
|
4785
|
+
completion_tokens_details: usage.completion_tokens_details
|
|
4786
|
+
};
|
|
4787
|
+
}
|
|
4894
4788
|
async getModels(signal) {
|
|
4895
4789
|
const res = await this.getTransport().get("/models", void 0, signal);
|
|
4896
4790
|
if (!res.ok) {
|
|
@@ -5229,6 +5123,28 @@ var AnthropicAISDKLLM = class {
|
|
|
5229
5123
|
}
|
|
5230
5124
|
return "auto";
|
|
5231
5125
|
}
|
|
5126
|
+
transformUsage(rawUsage) {
|
|
5127
|
+
if (!rawUsage) {
|
|
5128
|
+
return { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 };
|
|
5129
|
+
}
|
|
5130
|
+
const inputTokens = rawUsage.inputTokens ?? rawUsage.input_tokens ?? 0;
|
|
5131
|
+
const outputTokens = rawUsage.outputTokens ?? rawUsage.output_tokens ?? 0;
|
|
5132
|
+
const cacheCreation = rawUsage.cacheCreationInputTokens ?? rawUsage.cache_creation_input_tokens ?? 0;
|
|
5133
|
+
const cacheRead = rawUsage.cacheReadInputTokens ?? rawUsage.cache_read_input_tokens ?? 0;
|
|
5134
|
+
const cachedTokens = rawUsage.cachedInputTokens ?? cacheCreation + cacheRead;
|
|
5135
|
+
const promptTokens = inputTokens + cachedTokens;
|
|
5136
|
+
const totalTokens = promptTokens + outputTokens;
|
|
5137
|
+
return {
|
|
5138
|
+
prompt_tokens: promptTokens,
|
|
5139
|
+
completion_tokens: outputTokens,
|
|
5140
|
+
total_tokens: totalTokens,
|
|
5141
|
+
prompt_tokens_details: {
|
|
5142
|
+
cached_tokens: cachedTokens
|
|
5143
|
+
},
|
|
5144
|
+
...cacheCreation > 0 && { cache_creation_input_tokens: cacheCreation },
|
|
5145
|
+
...cacheRead > 0 && { cache_read_input_tokens: cacheRead }
|
|
5146
|
+
};
|
|
5147
|
+
}
|
|
5232
5148
|
handleError(error) {
|
|
5233
5149
|
if (error instanceof LLMError) {
|
|
5234
5150
|
throw error;
|
|
@@ -5297,18 +5213,7 @@ var AnthropicAISDKLLM = class {
|
|
|
5297
5213
|
}
|
|
5298
5214
|
})) : void 0;
|
|
5299
5215
|
const rawUsage = result.usage;
|
|
5300
|
-
const usage = rawUsage
|
|
5301
|
-
prompt_tokens: rawUsage.inputTokens || 0,
|
|
5302
|
-
completion_tokens: rawUsage.outputTokens || 0,
|
|
5303
|
-
total_tokens: rawUsage.totalTokens || 0,
|
|
5304
|
-
prompt_tokens_details: {
|
|
5305
|
-
cached_tokens: rawUsage.cachedInputTokens || 0
|
|
5306
|
-
}
|
|
5307
|
-
} : {
|
|
5308
|
-
prompt_tokens: 0,
|
|
5309
|
-
completion_tokens: 0,
|
|
5310
|
-
total_tokens: 0
|
|
5311
|
-
};
|
|
5216
|
+
const usage = this.transformUsage(rawUsage);
|
|
5312
5217
|
return {
|
|
5313
5218
|
content: result.text,
|
|
5314
5219
|
...tool_calls && { tool_calls },
|
|
@@ -5329,9 +5234,10 @@ var AnthropicAISDKLLM = class {
|
|
|
5329
5234
|
messages,
|
|
5330
5235
|
tools,
|
|
5331
5236
|
toolChoice,
|
|
5332
|
-
maxOutputTokens: params.maxTokens
|
|
5237
|
+
maxOutputTokens: params.maxTokens,
|
|
5333
5238
|
temperature: params.temperature,
|
|
5334
5239
|
abortSignal: signal,
|
|
5240
|
+
maxRetries: 10,
|
|
5335
5241
|
onError: (event) => {
|
|
5336
5242
|
streamError = event.error;
|
|
5337
5243
|
},
|
|
@@ -5357,18 +5263,7 @@ var AnthropicAISDKLLM = class {
|
|
|
5357
5263
|
}
|
|
5358
5264
|
})) : void 0;
|
|
5359
5265
|
const rawUsage = await result.usage;
|
|
5360
|
-
const usage = rawUsage
|
|
5361
|
-
prompt_tokens: rawUsage.inputTokens || 0,
|
|
5362
|
-
completion_tokens: rawUsage.outputTokens || 0,
|
|
5363
|
-
total_tokens: rawUsage.totalTokens || 0,
|
|
5364
|
-
prompt_tokens_details: {
|
|
5365
|
-
cached_tokens: rawUsage.cachedInputTokens || 0
|
|
5366
|
-
}
|
|
5367
|
-
} : {
|
|
5368
|
-
prompt_tokens: 0,
|
|
5369
|
-
completion_tokens: 0,
|
|
5370
|
-
total_tokens: 0
|
|
5371
|
-
};
|
|
5266
|
+
const usage = this.transformUsage(rawUsage);
|
|
5372
5267
|
const finishReason = await result.finishReason;
|
|
5373
5268
|
await handlers.onStreamFinish?.(finishReason, usage);
|
|
5374
5269
|
return {
|
|
@@ -5380,6 +5275,54 @@ var AnthropicAISDKLLM = class {
|
|
|
5380
5275
|
this.handleError(error);
|
|
5381
5276
|
}
|
|
5382
5277
|
}
|
|
5278
|
+
async getModels(signal) {
|
|
5279
|
+
const baseURL = this.opts.baseURL || this.opts.apiUrl || "https://api.anthropic.com/v1";
|
|
5280
|
+
const url = `${baseURL}/models`;
|
|
5281
|
+
const headers = {
|
|
5282
|
+
"anthropic-version": "2023-06-01",
|
|
5283
|
+
"anthropic-beta": " oauth-2025-04-20,fine-grained-tool-streaming-2025-05-14"
|
|
5284
|
+
};
|
|
5285
|
+
if (this.opts.oauth) {
|
|
5286
|
+
headers.authorization = `Bearer ${this.opts.oauth.access}`;
|
|
5287
|
+
} else if (this.opts.apiKey) {
|
|
5288
|
+
headers["x-api-key"] = this.opts.apiKey;
|
|
5289
|
+
} else {
|
|
5290
|
+
throw new LLMError("No API key or OAuth credentials provided", 401, false);
|
|
5291
|
+
}
|
|
5292
|
+
try {
|
|
5293
|
+
const response = await fetch(url, {
|
|
5294
|
+
method: "GET",
|
|
5295
|
+
headers,
|
|
5296
|
+
signal
|
|
5297
|
+
});
|
|
5298
|
+
if (!response.ok) {
|
|
5299
|
+
if ((response.status === 401 || response.status === 403) && this.opts.oauth) {
|
|
5300
|
+
await this.ensureValidToken();
|
|
5301
|
+
headers.authorization = `Bearer ${this.opts.oauth.access}`;
|
|
5302
|
+
const retryResponse = await fetch(url, {
|
|
5303
|
+
method: "GET",
|
|
5304
|
+
headers,
|
|
5305
|
+
signal
|
|
5306
|
+
});
|
|
5307
|
+
if (!retryResponse.ok) {
|
|
5308
|
+
const text2 = await retryResponse.text();
|
|
5309
|
+
throw new LLMError(text2 || `Failed to fetch models: ${retryResponse.status}`, retryResponse.status);
|
|
5310
|
+
}
|
|
5311
|
+
const data2 = await retryResponse.json();
|
|
5312
|
+
return data2.data.map((model) => normalizeModelInfo("anthropic", model));
|
|
5313
|
+
}
|
|
5314
|
+
const text = await response.text();
|
|
5315
|
+
throw new LLMError(text || `Failed to fetch models: ${response.status}`, response.status);
|
|
5316
|
+
}
|
|
5317
|
+
const data = await response.json();
|
|
5318
|
+
return data.data.map((model) => normalizeModelInfo("anthropic", model));
|
|
5319
|
+
} catch (error) {
|
|
5320
|
+
if (error instanceof LLMError) {
|
|
5321
|
+
throw error;
|
|
5322
|
+
}
|
|
5323
|
+
throw new LLMError(error instanceof Error ? error.message : "Failed to fetch models", void 0, false, error);
|
|
5324
|
+
}
|
|
5325
|
+
}
|
|
5383
5326
|
};
|
|
5384
5327
|
|
|
5385
5328
|
// src/llm-providers/llm-provider-config.json
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuvin/nuvin-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"private": false,
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"dev": "tsup --watch",
|
|
47
47
|
"build": "node scripts/build.js",
|
|
48
48
|
"clean": "rm -rf dist",
|
|
49
|
-
"test": "vitest run",
|
|
50
|
-
"test:watch": "vitest",
|
|
49
|
+
"test": "vitest --typecheck run",
|
|
50
|
+
"test:watch": "vitest --typecheck",
|
|
51
51
|
"format": "pnpm exec biome format --changed --no-errors-on-unmatched --write ."
|
|
52
52
|
}
|
|
53
53
|
}
|