@nuvin/nuvin-core 1.4.4 → 1.5.2
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 +9 -7
- package/dist/index.js +183 -231
- 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;
|
|
@@ -1218,19 +1220,16 @@ interface TransportResponse {
|
|
|
1218
1220
|
}
|
|
1219
1221
|
interface HttpTransport {
|
|
1220
1222
|
get(url: string, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
|
|
1221
|
-
|
|
1222
|
-
postStream(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<Response>;
|
|
1223
|
+
post(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<Response>;
|
|
1223
1224
|
}
|
|
1224
1225
|
declare class FetchTransport implements HttpTransport {
|
|
1225
1226
|
private opts;
|
|
1226
1227
|
private logger;
|
|
1227
1228
|
constructor(opts?: PersistOptions);
|
|
1228
|
-
private getRequestSize;
|
|
1229
1229
|
private getResponseSize;
|
|
1230
1230
|
private headersToRecord;
|
|
1231
|
+
post(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<Response>;
|
|
1231
1232
|
get(url: string, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
|
|
1232
|
-
postJson(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
|
|
1233
|
-
postStream(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<Response>;
|
|
1234
1233
|
}
|
|
1235
1234
|
|
|
1236
1235
|
declare class GithubAuthTransport implements HttpTransport {
|
|
@@ -1250,9 +1249,8 @@ declare class GithubAuthTransport implements HttpTransport {
|
|
|
1250
1249
|
private makeAuthHeaders;
|
|
1251
1250
|
private determineInitiator;
|
|
1252
1251
|
private generateRequestId;
|
|
1252
|
+
post(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<Response>;
|
|
1253
1253
|
get(url: string, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
|
|
1254
|
-
postJson(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
|
|
1255
|
-
postStream(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<Response>;
|
|
1256
1254
|
}
|
|
1257
1255
|
|
|
1258
1256
|
declare class LLMError extends Error {
|
|
@@ -1268,6 +1266,7 @@ declare abstract class BaseLLM implements LLMPort {
|
|
|
1268
1266
|
enablePromptCaching?: boolean;
|
|
1269
1267
|
});
|
|
1270
1268
|
protected abstract createTransport(): HttpTransport;
|
|
1269
|
+
protected transformUsage(rawUsage: unknown): UsageData | undefined;
|
|
1271
1270
|
protected getTransport(): HttpTransport;
|
|
1272
1271
|
protected applyCacheControl(params: CompletionParams): CompletionParams;
|
|
1273
1272
|
generateCompletion(params: CompletionParams, signal?: AbortSignal): Promise<CompletionResult>;
|
|
@@ -1303,6 +1302,7 @@ declare class GithubLLM extends BaseLLM implements LLMPort {
|
|
|
1303
1302
|
private readonly opts;
|
|
1304
1303
|
constructor(opts?: GithubOptions);
|
|
1305
1304
|
protected createTransport(): GithubAuthTransport;
|
|
1305
|
+
protected transformUsage(rawUsage: unknown): UsageData | undefined;
|
|
1306
1306
|
getModels(signal?: AbortSignal): Promise<ModelInfo[]>;
|
|
1307
1307
|
private handleError;
|
|
1308
1308
|
generateCompletion(params: CompletionParams, signal?: AbortSignal): Promise<CompletionResult>;
|
|
@@ -1344,6 +1344,7 @@ declare class AnthropicAISDKLLM {
|
|
|
1344
1344
|
private transformMessages;
|
|
1345
1345
|
private transformTools;
|
|
1346
1346
|
private transformToolChoice;
|
|
1347
|
+
private transformUsage;
|
|
1347
1348
|
private handleError;
|
|
1348
1349
|
generateCompletion(params: CompletionParams, signal?: AbortSignal): Promise<CompletionResult>;
|
|
1349
1350
|
streamCompletion(params: CompletionParams, handlers?: {
|
|
@@ -1351,6 +1352,7 @@ declare class AnthropicAISDKLLM {
|
|
|
1351
1352
|
onToolCallDelta?: (tc: ToolCall) => void;
|
|
1352
1353
|
onStreamFinish?: (finishReason?: string, usage?: UsageData) => void;
|
|
1353
1354
|
}, signal?: AbortSignal): Promise<CompletionResult>;
|
|
1355
|
+
getModels(signal?: AbortSignal): Promise<ModelInfo[]>;
|
|
1354
1356
|
}
|
|
1355
1357
|
|
|
1356
1358
|
type ModelConfig = false | true | string | string[] | Array<{
|
package/dist/index.js
CHANGED
|
@@ -3048,7 +3048,7 @@ var AssignTool = class {
|
|
|
3048
3048
|
properties: {
|
|
3049
3049
|
description: {
|
|
3050
3050
|
type: "string",
|
|
3051
|
-
description:
|
|
3051
|
+
description: "A summary of the task to be performed by the delegated agent. Be specific about the desired outcome. From 5-10 words."
|
|
3052
3052
|
},
|
|
3053
3053
|
agent: {
|
|
3054
3054
|
type: "string",
|
|
@@ -3056,10 +3056,10 @@ var AssignTool = class {
|
|
|
3056
3056
|
},
|
|
3057
3057
|
task: {
|
|
3058
3058
|
type: "string",
|
|
3059
|
-
description: "
|
|
3059
|
+
description: "Detailed description of the task to be performed by the agent."
|
|
3060
3060
|
}
|
|
3061
3061
|
},
|
|
3062
|
-
required: ["agent", "task"]
|
|
3062
|
+
required: ["agent", "task", "description"]
|
|
3063
3063
|
};
|
|
3064
3064
|
/**
|
|
3065
3065
|
* Update the enabled agents configuration
|
|
@@ -3196,7 +3196,7 @@ var LLMResolver = class {
|
|
|
3196
3196
|
};
|
|
3197
3197
|
|
|
3198
3198
|
// src/agent-manager.ts
|
|
3199
|
-
var DEFAULT_TIMEOUT_MS =
|
|
3199
|
+
var DEFAULT_TIMEOUT_MS = 3e6;
|
|
3200
3200
|
var MAX_DELEGATION_DEPTH = 3;
|
|
3201
3201
|
var AgentManager = class {
|
|
3202
3202
|
constructor(delegatingConfig, delegatingTools, llmFactory, eventCallback, configResolver) {
|
|
@@ -3394,25 +3394,34 @@ var AgentManager = class {
|
|
|
3394
3394
|
* Execute agent task with timeout
|
|
3395
3395
|
*/
|
|
3396
3396
|
async executeWithTimeout(orchestrator, taskDescription, timeoutMs, signal) {
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3397
|
+
const timeoutController = new AbortController();
|
|
3398
|
+
const combinedSignal = signal ? AbortSignal.any([signal, timeoutController.signal]) : timeoutController.signal;
|
|
3399
|
+
let timer;
|
|
3400
|
+
try {
|
|
3401
|
+
return await Promise.race([
|
|
3402
|
+
orchestrator.send(taskDescription, {
|
|
3403
|
+
conversationId: "default",
|
|
3404
|
+
signal: combinedSignal
|
|
3405
|
+
}),
|
|
3406
|
+
new Promise((_, reject) => {
|
|
3407
|
+
if (signal?.aborted) {
|
|
3408
|
+
reject(new Error("Sub-agent execution aborted by user"));
|
|
3409
|
+
return;
|
|
3410
|
+
}
|
|
3411
|
+
signal?.addEventListener("abort", () => reject(new Error("Sub-agent execution aborted by user")), {
|
|
3412
|
+
once: true
|
|
3413
|
+
});
|
|
3414
|
+
}),
|
|
3415
|
+
new Promise((_, reject) => {
|
|
3416
|
+
timer = setTimeout(() => {
|
|
3417
|
+
timeoutController.abort();
|
|
3418
|
+
reject(new Error(`Task execution timeout after ${timeoutMs}ms`));
|
|
3419
|
+
}, timeoutMs);
|
|
3420
|
+
})
|
|
3421
|
+
]);
|
|
3422
|
+
} finally {
|
|
3423
|
+
if (timer) clearTimeout(timer);
|
|
3424
|
+
}
|
|
3416
3425
|
}
|
|
3417
3426
|
/**
|
|
3418
3427
|
* Get active specialist agent count
|
|
@@ -3958,24 +3967,6 @@ function mergeChoices(choices) {
|
|
|
3958
3967
|
...extraFields
|
|
3959
3968
|
};
|
|
3960
3969
|
}
|
|
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
3970
|
|
|
3980
3971
|
// src/llm-providers/base-llm.ts
|
|
3981
3972
|
var LLMError = class _LLMError extends Error {
|
|
@@ -3997,6 +3988,28 @@ var BaseLLM = class {
|
|
|
3997
3988
|
this.apiUrl = apiUrl;
|
|
3998
3989
|
this.enablePromptCaching = options?.enablePromptCaching ?? false;
|
|
3999
3990
|
}
|
|
3991
|
+
transformUsage(rawUsage) {
|
|
3992
|
+
if (!rawUsage) return void 0;
|
|
3993
|
+
const usage = rawUsage;
|
|
3994
|
+
const promptTokens = usage.prompt_tokens ?? usage.input_tokens;
|
|
3995
|
+
const completionTokens = usage.completion_tokens ?? usage.output_tokens;
|
|
3996
|
+
const totalTokens = usage.total_tokens ?? (promptTokens != null && completionTokens != null ? promptTokens + completionTokens : void 0);
|
|
3997
|
+
const cost = usage.cost ?? usage.estimated_cost;
|
|
3998
|
+
return {
|
|
3999
|
+
prompt_tokens: promptTokens,
|
|
4000
|
+
completion_tokens: completionTokens,
|
|
4001
|
+
total_tokens: totalTokens,
|
|
4002
|
+
...usage.reasoning_tokens !== void 0 && { reasoning_tokens: usage.reasoning_tokens },
|
|
4003
|
+
...usage.prompt_tokens_details && { prompt_tokens_details: usage.prompt_tokens_details },
|
|
4004
|
+
...usage.completion_tokens_details && { completion_tokens_details: usage.completion_tokens_details },
|
|
4005
|
+
...cost !== void 0 && { cost },
|
|
4006
|
+
...usage.cost_details && { cost_details: usage.cost_details },
|
|
4007
|
+
...usage.cache_creation_input_tokens !== void 0 && {
|
|
4008
|
+
cache_creation_input_tokens: usage.cache_creation_input_tokens
|
|
4009
|
+
},
|
|
4010
|
+
...usage.cache_read_input_tokens !== void 0 && { cache_read_input_tokens: usage.cache_read_input_tokens }
|
|
4011
|
+
};
|
|
4012
|
+
}
|
|
4000
4013
|
getTransport() {
|
|
4001
4014
|
if (!this.transport) this.transport = this.createTransport();
|
|
4002
4015
|
return this.transport;
|
|
@@ -4073,7 +4086,7 @@ var BaseLLM = class {
|
|
|
4073
4086
|
if (enhancedParams.tools && enhancedParams.tools.length > 0) body.tools = enhancedParams.tools;
|
|
4074
4087
|
if (enhancedParams.tool_choice && enhancedParams.tools && enhancedParams.tools.length > 0)
|
|
4075
4088
|
body.tool_choice = enhancedParams.tool_choice;
|
|
4076
|
-
const res = await this.getTransport().
|
|
4089
|
+
const res = await this.getTransport().post("/chat/completions", body, void 0, signal);
|
|
4077
4090
|
if (!res.ok) {
|
|
4078
4091
|
const text = await res.text();
|
|
4079
4092
|
const isRetryable = res.status === 429 || res.status >= 500;
|
|
@@ -4081,7 +4094,7 @@ var BaseLLM = class {
|
|
|
4081
4094
|
}
|
|
4082
4095
|
const data = await res.json();
|
|
4083
4096
|
const merged = mergeChoices(data.choices);
|
|
4084
|
-
const usage =
|
|
4097
|
+
const usage = this.transformUsage(data.usage);
|
|
4085
4098
|
return { ...merged, ...usage ? { usage } : {} };
|
|
4086
4099
|
}
|
|
4087
4100
|
async streamCompletion(params, handlers = {}, signal) {
|
|
@@ -4099,12 +4112,7 @@ var BaseLLM = class {
|
|
|
4099
4112
|
if (enhancedParams.tools && enhancedParams.tools.length > 0) body.tools = enhancedParams.tools;
|
|
4100
4113
|
if (enhancedParams.tool_choice && enhancedParams.tools && enhancedParams.tools.length > 0)
|
|
4101
4114
|
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
|
-
);
|
|
4115
|
+
const res = await this.getTransport().post("/chat/completions", body, { Accept: "text/event-stream" }, signal);
|
|
4108
4116
|
if (!res.ok) {
|
|
4109
4117
|
const text = await res.text();
|
|
4110
4118
|
const isRetryable = res.status === 429 || res.status >= 500;
|
|
@@ -4137,7 +4145,7 @@ var BaseLLM = class {
|
|
|
4137
4145
|
}
|
|
4138
4146
|
const usageData = evt.usage || choices[0]?.usage;
|
|
4139
4147
|
if (usageData) {
|
|
4140
|
-
usage =
|
|
4148
|
+
usage = this.transformUsage(usageData);
|
|
4141
4149
|
if (lastFinishReason && handlers.onStreamFinish) {
|
|
4142
4150
|
handlers.onStreamFinish(lastFinishReason, usage);
|
|
4143
4151
|
} else {
|
|
@@ -4232,9 +4240,6 @@ var BaseLLM = class {
|
|
|
4232
4240
|
}
|
|
4233
4241
|
};
|
|
4234
4242
|
|
|
4235
|
-
// src/transports/transport.ts
|
|
4236
|
-
import * as crypto2 from "crypto";
|
|
4237
|
-
|
|
4238
4243
|
// src/logger/network.ts
|
|
4239
4244
|
var NetworkLogger = class {
|
|
4240
4245
|
constructor(opts = {}) {
|
|
@@ -4381,10 +4386,6 @@ var FetchTransport = class {
|
|
|
4381
4386
|
this.logger = new NetworkLogger(this.opts);
|
|
4382
4387
|
}
|
|
4383
4388
|
logger;
|
|
4384
|
-
getRequestSize(body) {
|
|
4385
|
-
if (!body) return 0;
|
|
4386
|
-
return new TextEncoder().encode(JSON.stringify(body)).length;
|
|
4387
|
-
}
|
|
4388
4389
|
getResponseSize(headers) {
|
|
4389
4390
|
const contentLength = headers.get("content-length");
|
|
4390
4391
|
return contentLength ? parseInt(contentLength, 10) : 0;
|
|
@@ -4396,6 +4397,17 @@ var FetchTransport = class {
|
|
|
4396
4397
|
});
|
|
4397
4398
|
return record;
|
|
4398
4399
|
}
|
|
4400
|
+
async post(url, body, headers, signal) {
|
|
4401
|
+
if (typeof fetch !== "function") {
|
|
4402
|
+
throw new Error("Global fetch is not available. Use Node 18+ or a compatible runtime.");
|
|
4403
|
+
}
|
|
4404
|
+
return fetch(url, {
|
|
4405
|
+
method: "POST",
|
|
4406
|
+
headers: { "Content-Type": "application/json", ...headers || {} },
|
|
4407
|
+
body: JSON.stringify(body ?? {}),
|
|
4408
|
+
signal
|
|
4409
|
+
});
|
|
4410
|
+
}
|
|
4399
4411
|
async get(url, headers, signal) {
|
|
4400
4412
|
if (typeof fetch !== "function") {
|
|
4401
4413
|
throw new Error("Global fetch is not available. Use Node 18+ or a compatible runtime.");
|
|
@@ -4453,123 +4465,10 @@ var FetchTransport = class {
|
|
|
4453
4465
|
throw error;
|
|
4454
4466
|
}
|
|
4455
4467
|
}
|
|
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
4468
|
};
|
|
4570
4469
|
|
|
4571
4470
|
// src/transports/github-transport.ts
|
|
4572
|
-
import * as
|
|
4471
|
+
import * as crypto2 from "crypto";
|
|
4573
4472
|
var isVisionMessage = (msg) => {
|
|
4574
4473
|
if (!msg) return false;
|
|
4575
4474
|
const content = msg.content;
|
|
@@ -4653,8 +4552,8 @@ var GithubAuthTransport = class {
|
|
|
4653
4552
|
return "agent";
|
|
4654
4553
|
}
|
|
4655
4554
|
generateRequestId() {
|
|
4656
|
-
if (
|
|
4657
|
-
return
|
|
4555
|
+
if (crypto2?.randomUUID) {
|
|
4556
|
+
return crypto2.randomUUID();
|
|
4658
4557
|
}
|
|
4659
4558
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
4660
4559
|
const r = Math.random() * 16 | 0;
|
|
@@ -4662,44 +4561,29 @@ var GithubAuthTransport = class {
|
|
|
4662
4561
|
return v.toString(16);
|
|
4663
4562
|
});
|
|
4664
4563
|
}
|
|
4665
|
-
async
|
|
4564
|
+
async post(url, body, headers, signal) {
|
|
4666
4565
|
if (!this.apiKey && this.accessToken) {
|
|
4667
4566
|
await this.exchangeToken(signal);
|
|
4668
4567
|
}
|
|
4669
4568
|
const fullUrl = this.buildFullUrl(url);
|
|
4670
|
-
let res = await this.inner.
|
|
4569
|
+
let res = await this.inner.post(fullUrl, body, this.makeAuthHeaders(headers, body), signal);
|
|
4671
4570
|
if (res.status === 401 && this.accessToken) {
|
|
4672
4571
|
await this.exchangeToken(signal);
|
|
4673
4572
|
const retryUrl = this.buildFullUrl(url);
|
|
4674
|
-
res = await this.inner.
|
|
4573
|
+
res = await this.inner.post(retryUrl, body, this.makeAuthHeaders(headers, body), signal);
|
|
4675
4574
|
}
|
|
4676
4575
|
return res;
|
|
4677
4576
|
}
|
|
4678
|
-
async
|
|
4577
|
+
async get(url, headers, signal) {
|
|
4679
4578
|
if (!this.apiKey && this.accessToken) {
|
|
4680
4579
|
await this.exchangeToken(signal);
|
|
4681
4580
|
}
|
|
4682
4581
|
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);
|
|
4582
|
+
let res = await this.inner.get(fullUrl, this.makeAuthHeaders(headers), signal);
|
|
4699
4583
|
if (res.status === 401 && this.accessToken) {
|
|
4700
4584
|
await this.exchangeToken(signal);
|
|
4701
4585
|
const retryUrl = this.buildFullUrl(url);
|
|
4702
|
-
res = await this.inner.
|
|
4586
|
+
res = await this.inner.get(retryUrl, this.makeAuthHeaders(headers), signal);
|
|
4703
4587
|
}
|
|
4704
4588
|
return res;
|
|
4705
4589
|
}
|
|
@@ -4742,13 +4626,9 @@ var BaseBearerAuthTransport = class {
|
|
|
4742
4626
|
const fullUrl = this.buildFullUrl(url);
|
|
4743
4627
|
return this.inner.get(fullUrl, this.makeAuthHeaders(headers), signal);
|
|
4744
4628
|
}
|
|
4745
|
-
async
|
|
4629
|
+
async post(url, body, headers, signal) {
|
|
4746
4630
|
const fullUrl = this.buildFullUrl(url);
|
|
4747
|
-
return this.inner.
|
|
4748
|
-
}
|
|
4749
|
-
async postStream(url, body, headers, signal) {
|
|
4750
|
-
const fullUrl = this.buildFullUrl(url);
|
|
4751
|
-
return this.inner.postStream(fullUrl, body, this.makeAuthHeaders(headers), signal);
|
|
4631
|
+
return this.inner.post(fullUrl, body, this.makeAuthHeaders(headers), signal);
|
|
4752
4632
|
}
|
|
4753
4633
|
};
|
|
4754
4634
|
|
|
@@ -4782,6 +4662,9 @@ function normalizeModelLimits(provider, model) {
|
|
|
4782
4662
|
maxOutput: limits?.max_output_tokens
|
|
4783
4663
|
};
|
|
4784
4664
|
}
|
|
4665
|
+
case "anthropic": {
|
|
4666
|
+
return getFallbackLimits("anthropic", model.id);
|
|
4667
|
+
}
|
|
4785
4668
|
case "deepinfra": {
|
|
4786
4669
|
const metadata = model.metadata;
|
|
4787
4670
|
const contextLength = metadata?.context_length;
|
|
@@ -4846,10 +4729,18 @@ var FALLBACK_LIMITS = {
|
|
|
4846
4729
|
"kimi-k2-turbo-preview": { contextWindow: 262144 }
|
|
4847
4730
|
},
|
|
4848
4731
|
anthropic: {
|
|
4849
|
-
"claude-
|
|
4850
|
-
"claude-
|
|
4732
|
+
"claude-opus-4-5-20251101": { contextWindow: 2e5, maxOutput: 16e3 },
|
|
4733
|
+
"claude-haiku-4-5-20251001": { contextWindow: 2e5, maxOutput: 16e3 },
|
|
4734
|
+
"claude-sonnet-4-5-20250929": { contextWindow: 2e5, maxOutput: 16e3 },
|
|
4735
|
+
"claude-opus-4-1-20250805": { contextWindow: 2e5, maxOutput: 16e3 },
|
|
4736
|
+
"claude-opus-4-20250514": { contextWindow: 2e5, maxOutput: 16e3 },
|
|
4737
|
+
"claude-sonnet-4-20250514": { contextWindow: 2e5, maxOutput: 16e3 },
|
|
4738
|
+
"claude-3-7-sonnet-20250219": { contextWindow: 2e5, maxOutput: 8192 },
|
|
4739
|
+
"claude-3-5-haiku-20241022": { contextWindow: 2e5, maxOutput: 8192 },
|
|
4740
|
+
"claude-3-haiku-20240307": { contextWindow: 2e5, maxOutput: 4096 },
|
|
4851
4741
|
"claude-3-opus-20240229": { contextWindow: 2e5, maxOutput: 4096 },
|
|
4852
|
-
"claude-
|
|
4742
|
+
"claude-sonnet-4-5": { contextWindow: 2e5, maxOutput: 16e3 },
|
|
4743
|
+
"claude-3-5-sonnet-20241022": { contextWindow: 2e5, maxOutput: 8192 }
|
|
4853
4744
|
}
|
|
4854
4745
|
};
|
|
4855
4746
|
function getFallbackLimits(provider, model) {
|
|
@@ -4859,7 +4750,10 @@ function getFallbackLimits(provider, model) {
|
|
|
4859
4750
|
}
|
|
4860
4751
|
function normalizeModelInfo(provider, model) {
|
|
4861
4752
|
const id = model.id;
|
|
4862
|
-
|
|
4753
|
+
let name = model.name ?? id;
|
|
4754
|
+
if (provider.toLowerCase() === "anthropic" && model.display_name) {
|
|
4755
|
+
name = model.display_name;
|
|
4756
|
+
}
|
|
4863
4757
|
const limits = normalizeModelLimits(provider, model);
|
|
4864
4758
|
return {
|
|
4865
4759
|
id,
|
|
@@ -4881,9 +4775,7 @@ var GithubLLM = class extends BaseLLM {
|
|
|
4881
4775
|
logLevel: "INFO",
|
|
4882
4776
|
enableConsoleLog: false,
|
|
4883
4777
|
maxFileSize: 5 * 1024 * 1024,
|
|
4884
|
-
// 5MB before rotation
|
|
4885
4778
|
captureResponseBody: true
|
|
4886
|
-
// Disable for better performance
|
|
4887
4779
|
});
|
|
4888
4780
|
return new GithubAuthTransport(base, {
|
|
4889
4781
|
baseUrl: this.opts.apiUrl,
|
|
@@ -4891,6 +4783,17 @@ var GithubLLM = class extends BaseLLM {
|
|
|
4891
4783
|
accessToken: this.opts.accessToken
|
|
4892
4784
|
});
|
|
4893
4785
|
}
|
|
4786
|
+
transformUsage(rawUsage) {
|
|
4787
|
+
if (!rawUsage) return void 0;
|
|
4788
|
+
const usage = rawUsage;
|
|
4789
|
+
return {
|
|
4790
|
+
prompt_tokens: usage.prompt_tokens,
|
|
4791
|
+
completion_tokens: usage.completion_tokens,
|
|
4792
|
+
total_tokens: usage.total_tokens,
|
|
4793
|
+
prompt_tokens_details: usage.prompt_tokens_details,
|
|
4794
|
+
completion_tokens_details: usage.completion_tokens_details
|
|
4795
|
+
};
|
|
4796
|
+
}
|
|
4894
4797
|
async getModels(signal) {
|
|
4895
4798
|
const res = await this.getTransport().get("/models", void 0, signal);
|
|
4896
4799
|
if (!res.ok) {
|
|
@@ -5229,6 +5132,28 @@ var AnthropicAISDKLLM = class {
|
|
|
5229
5132
|
}
|
|
5230
5133
|
return "auto";
|
|
5231
5134
|
}
|
|
5135
|
+
transformUsage(rawUsage) {
|
|
5136
|
+
if (!rawUsage) {
|
|
5137
|
+
return { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 };
|
|
5138
|
+
}
|
|
5139
|
+
const inputTokens = rawUsage.inputTokens ?? rawUsage.input_tokens ?? 0;
|
|
5140
|
+
const outputTokens = rawUsage.outputTokens ?? rawUsage.output_tokens ?? 0;
|
|
5141
|
+
const cacheCreation = rawUsage.cacheCreationInputTokens ?? rawUsage.cache_creation_input_tokens ?? 0;
|
|
5142
|
+
const cacheRead = rawUsage.cacheReadInputTokens ?? rawUsage.cache_read_input_tokens ?? 0;
|
|
5143
|
+
const cachedTokens = rawUsage.cachedInputTokens ?? cacheCreation + cacheRead;
|
|
5144
|
+
const promptTokens = inputTokens + cachedTokens;
|
|
5145
|
+
const totalTokens = promptTokens + outputTokens;
|
|
5146
|
+
return {
|
|
5147
|
+
prompt_tokens: promptTokens,
|
|
5148
|
+
completion_tokens: outputTokens,
|
|
5149
|
+
total_tokens: totalTokens,
|
|
5150
|
+
prompt_tokens_details: {
|
|
5151
|
+
cached_tokens: cachedTokens
|
|
5152
|
+
},
|
|
5153
|
+
...cacheCreation > 0 && { cache_creation_input_tokens: cacheCreation },
|
|
5154
|
+
...cacheRead > 0 && { cache_read_input_tokens: cacheRead }
|
|
5155
|
+
};
|
|
5156
|
+
}
|
|
5232
5157
|
handleError(error) {
|
|
5233
5158
|
if (error instanceof LLMError) {
|
|
5234
5159
|
throw error;
|
|
@@ -5297,18 +5222,7 @@ var AnthropicAISDKLLM = class {
|
|
|
5297
5222
|
}
|
|
5298
5223
|
})) : void 0;
|
|
5299
5224
|
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
|
-
};
|
|
5225
|
+
const usage = this.transformUsage(rawUsage);
|
|
5312
5226
|
return {
|
|
5313
5227
|
content: result.text,
|
|
5314
5228
|
...tool_calls && { tool_calls },
|
|
@@ -5329,9 +5243,10 @@ var AnthropicAISDKLLM = class {
|
|
|
5329
5243
|
messages,
|
|
5330
5244
|
tools,
|
|
5331
5245
|
toolChoice,
|
|
5332
|
-
maxOutputTokens: params.maxTokens
|
|
5246
|
+
maxOutputTokens: params.maxTokens,
|
|
5333
5247
|
temperature: params.temperature,
|
|
5334
5248
|
abortSignal: signal,
|
|
5249
|
+
maxRetries: 10,
|
|
5335
5250
|
onError: (event) => {
|
|
5336
5251
|
streamError = event.error;
|
|
5337
5252
|
},
|
|
@@ -5357,18 +5272,7 @@ var AnthropicAISDKLLM = class {
|
|
|
5357
5272
|
}
|
|
5358
5273
|
})) : void 0;
|
|
5359
5274
|
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
|
-
};
|
|
5275
|
+
const usage = this.transformUsage(rawUsage);
|
|
5372
5276
|
const finishReason = await result.finishReason;
|
|
5373
5277
|
await handlers.onStreamFinish?.(finishReason, usage);
|
|
5374
5278
|
return {
|
|
@@ -5380,6 +5284,54 @@ var AnthropicAISDKLLM = class {
|
|
|
5380
5284
|
this.handleError(error);
|
|
5381
5285
|
}
|
|
5382
5286
|
}
|
|
5287
|
+
async getModels(signal) {
|
|
5288
|
+
const baseURL = this.opts.baseURL || this.opts.apiUrl || "https://api.anthropic.com/v1";
|
|
5289
|
+
const url = `${baseURL}/models`;
|
|
5290
|
+
const headers = {
|
|
5291
|
+
"anthropic-version": "2023-06-01",
|
|
5292
|
+
"anthropic-beta": " oauth-2025-04-20,fine-grained-tool-streaming-2025-05-14"
|
|
5293
|
+
};
|
|
5294
|
+
if (this.opts.oauth) {
|
|
5295
|
+
headers.authorization = `Bearer ${this.opts.oauth.access}`;
|
|
5296
|
+
} else if (this.opts.apiKey) {
|
|
5297
|
+
headers["x-api-key"] = this.opts.apiKey;
|
|
5298
|
+
} else {
|
|
5299
|
+
throw new LLMError("No API key or OAuth credentials provided", 401, false);
|
|
5300
|
+
}
|
|
5301
|
+
try {
|
|
5302
|
+
const response = await fetch(url, {
|
|
5303
|
+
method: "GET",
|
|
5304
|
+
headers,
|
|
5305
|
+
signal
|
|
5306
|
+
});
|
|
5307
|
+
if (!response.ok) {
|
|
5308
|
+
if ((response.status === 401 || response.status === 403) && this.opts.oauth) {
|
|
5309
|
+
await this.ensureValidToken();
|
|
5310
|
+
headers.authorization = `Bearer ${this.opts.oauth.access}`;
|
|
5311
|
+
const retryResponse = await fetch(url, {
|
|
5312
|
+
method: "GET",
|
|
5313
|
+
headers,
|
|
5314
|
+
signal
|
|
5315
|
+
});
|
|
5316
|
+
if (!retryResponse.ok) {
|
|
5317
|
+
const text2 = await retryResponse.text();
|
|
5318
|
+
throw new LLMError(text2 || `Failed to fetch models: ${retryResponse.status}`, retryResponse.status);
|
|
5319
|
+
}
|
|
5320
|
+
const data2 = await retryResponse.json();
|
|
5321
|
+
return data2.data.map((model) => normalizeModelInfo("anthropic", model));
|
|
5322
|
+
}
|
|
5323
|
+
const text = await response.text();
|
|
5324
|
+
throw new LLMError(text || `Failed to fetch models: ${response.status}`, response.status);
|
|
5325
|
+
}
|
|
5326
|
+
const data = await response.json();
|
|
5327
|
+
return data.data.map((model) => normalizeModelInfo("anthropic", model));
|
|
5328
|
+
} catch (error) {
|
|
5329
|
+
if (error instanceof LLMError) {
|
|
5330
|
+
throw error;
|
|
5331
|
+
}
|
|
5332
|
+
throw new LLMError(error instanceof Error ? error.message : "Failed to fetch models", void 0, false, error);
|
|
5333
|
+
}
|
|
5334
|
+
}
|
|
5383
5335
|
};
|
|
5384
5336
|
|
|
5385
5337
|
// 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.2",
|
|
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
|
}
|