@nuvin/nuvin-core 1.6.1 → 1.7.0

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