@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 CHANGED
@@ -1,4 +1,4 @@
1
1
  {
2
- "version": "1.4.4",
3
- "commit": "a070d52"
2
+ "version": "1.5.2",
3
+ "commit": "f0799f5"
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
@@ -3048,7 +3048,7 @@ var AssignTool = class {
3048
3048
  properties: {
3049
3049
  description: {
3050
3050
  type: "string",
3051
- description: 'Explanation of why this task is being delegated (e.g., "Delegate code review to specialist agent")'
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: "Task description (3-4 sentences explaining what to do)"
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 = 3e5;
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
- return new Promise((resolve6, reject) => {
3398
- const timer = setTimeout(() => {
3399
- reject(new Error(`Task execution timeout after ${timeoutMs}ms`));
3400
- }, timeoutMs);
3401
- const abortHandler = () => {
3402
- clearTimeout(timer);
3403
- reject(new Error("Sub-agent execution aborted by user"));
3404
- };
3405
- signal?.addEventListener("abort", abortHandler);
3406
- orchestrator.send(taskDescription, { conversationId: "default", signal }).then((response) => {
3407
- clearTimeout(timer);
3408
- signal?.removeEventListener("abort", abortHandler);
3409
- resolve6(response);
3410
- }).catch((error) => {
3411
- clearTimeout(timer);
3412
- signal?.removeEventListener("abort", abortHandler);
3413
- reject(error);
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().postJson("/chat/completions", body, void 0, signal);
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 = normalizeUsage(data.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().postStream(
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 = normalizeUsage(usageData);
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 crypto3 from "crypto";
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 (crypto3?.randomUUID) {
4657
- return crypto3.randomUUID();
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 get(url, headers, signal) {
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.get(fullUrl, this.makeAuthHeaders(headers), signal);
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.get(retryUrl, this.makeAuthHeaders(headers), signal);
4573
+ res = await this.inner.post(retryUrl, body, this.makeAuthHeaders(headers, body), signal);
4675
4574
  }
4676
4575
  return res;
4677
4576
  }
4678
- async postJson(url, body, headers, signal) {
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.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);
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.postStream(retryUrl, body, this.makeAuthHeaders(hdrs, body), signal);
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 postJson(url, body, headers, signal) {
4629
+ async post(url, body, headers, signal) {
4746
4630
  const fullUrl = this.buildFullUrl(url);
4747
- return this.inner.postJson(fullUrl, body, this.makeAuthHeaders(headers), signal);
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-sonnet-4-5": { contextWindow: 2e5, maxOutput: 16e3 },
4850
- "claude-3-5-sonnet-20241022": { contextWindow: 2e5, maxOutput: 8192 },
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-3-haiku-20240307": { contextWindow: 2e5, maxOutput: 4096 }
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
- const name = model.name ?? id;
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 ?? 10240,
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.4.4",
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
  }