@nuvin/nuvin-core 1.4.4 → 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 CHANGED
@@ -1,4 +1,4 @@
1
1
  {
2
- "version": "1.4.4",
3
- "commit": "a070d52"
2
+ "version": "1.5.1",
3
+ "commit": "c15f31a"
4
4
  }
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
- postJson(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
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
@@ -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().postJson("/chat/completions", body, void 0, signal);
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 = normalizeUsage(data.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().postStream(
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 = normalizeUsage(usageData);
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 crypto3 from "crypto";
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 (crypto3?.randomUUID) {
4657
- return crypto3.randomUUID();
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 get(url, headers, signal) {
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.get(fullUrl, this.makeAuthHeaders(headers), signal);
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.get(retryUrl, this.makeAuthHeaders(headers), signal);
4564
+ res = await this.inner.post(retryUrl, body, this.makeAuthHeaders(headers, body), signal);
4675
4565
  }
4676
4566
  return res;
4677
4567
  }
4678
- async postJson(url, body, headers, signal) {
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.postJson(fullUrl, body, this.makeAuthHeaders(headers, body), signal);
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.postStream(retryUrl, body, this.makeAuthHeaders(hdrs, body), signal);
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 postJson(url, body, headers, signal) {
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.postStream(fullUrl, body, this.makeAuthHeaders(headers), signal);
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-sonnet-4-5": { contextWindow: 2e5, maxOutput: 16e3 },
4850
- "claude-3-5-sonnet-20241022": { contextWindow: 2e5, maxOutput: 8192 },
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-3-haiku-20240307": { contextWindow: 2e5, maxOutput: 4096 }
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
- const name = model.name ?? id;
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 ?? 10240,
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.4.4",
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
  }