@nuvin/nuvin-core 1.6.0 → 1.6.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.6.0",
3
- "commit": "ec1e31a"
2
+ "version": "1.6.2",
3
+ "commit": "43b45f7"
4
4
  }
package/dist/index.d.ts CHANGED
@@ -540,7 +540,6 @@ type SendMessageOptions = {
540
540
  conversationId?: string;
541
541
  stream?: boolean;
542
542
  signal?: AbortSignal;
543
- retry?: boolean;
544
543
  };
545
544
  type UserAttachment = ImageContentPart & {
546
545
  token?: string;
@@ -1994,6 +1993,38 @@ declare class GithubAuthTransport implements HttpTransport {
1994
1993
  get(url: string, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
1995
1994
  }
1996
1995
 
1996
+ interface RetryConfig {
1997
+ maxRetries: number;
1998
+ baseDelayMs: number;
1999
+ maxDelayMs: number;
2000
+ backoffMultiplier: number;
2001
+ jitterFactor: number;
2002
+ retryableStatusCodes: number[];
2003
+ onRetry?: (attempt: number, error: Error, delayMs: number) => void;
2004
+ onExhausted?: (error: Error, attempts: number) => void;
2005
+ }
2006
+ declare const DEFAULT_RETRY_CONFIG: RetryConfig;
2007
+ declare class AbortError extends Error {
2008
+ constructor(message?: string);
2009
+ }
2010
+ declare class RetryTransport implements HttpTransport {
2011
+ private inner;
2012
+ private config;
2013
+ constructor(inner: HttpTransport, config?: Partial<RetryConfig>);
2014
+ get(url: string, headers?: HttpHeaders, signal?: AbortSignal): Promise<TransportResponse>;
2015
+ post(url: string, body: unknown, headers?: HttpHeaders, signal?: AbortSignal): Promise<Response>;
2016
+ private executeWithRetry;
2017
+ private isRetryableResponse;
2018
+ private getDelayForResponse;
2019
+ }
2020
+
2021
+ declare function isRetryableStatusCode(status: number, retryableStatusCodes?: number[]): boolean;
2022
+ declare function isRetryableError(error: unknown, retryableStatusCodes?: number[]): boolean;
2023
+
2024
+ interface BaseLLMOptions {
2025
+ enablePromptCaching?: boolean;
2026
+ retry?: Partial<RetryConfig>;
2027
+ }
1997
2028
  declare class LLMError extends Error {
1998
2029
  readonly statusCode?: number | undefined;
1999
2030
  readonly isRetryable: boolean;
@@ -2003,9 +2034,8 @@ declare abstract class BaseLLM implements LLMPort {
2003
2034
  protected transport: HttpTransport | null;
2004
2035
  protected apiUrl: string;
2005
2036
  protected enablePromptCaching: boolean;
2006
- constructor(apiUrl: string, options?: {
2007
- enablePromptCaching?: boolean;
2008
- });
2037
+ protected retryConfig?: Partial<RetryConfig>;
2038
+ constructor(apiUrl: string, options?: BaseLLMOptions);
2009
2039
  protected abstract createTransport(): HttpTransport;
2010
2040
  protected transformUsage(rawUsage: unknown): UsageData | undefined;
2011
2041
  protected getTransport(): HttpTransport;
@@ -2038,11 +2068,12 @@ type GithubOptions = {
2038
2068
  accessToken?: string;
2039
2069
  apiUrl?: string;
2040
2070
  httpLogFile?: string;
2071
+ retry?: Partial<RetryConfig>;
2041
2072
  };
2042
2073
  declare class GithubLLM extends BaseLLM implements LLMPort {
2043
2074
  private readonly opts;
2044
2075
  constructor(opts?: GithubOptions);
2045
- protected createTransport(): GithubAuthTransport;
2076
+ protected createTransport(): GithubAuthTransport | RetryTransport;
2046
2077
  protected transformUsage(rawUsage: unknown): UsageData | undefined;
2047
2078
  getModels(signal?: AbortSignal): Promise<ModelInfo[]>;
2048
2079
  private handleError;
@@ -2065,6 +2096,7 @@ type AnthropicAISDKOptions = {
2065
2096
  apiUrl?: string;
2066
2097
  baseURL?: string;
2067
2098
  httpLogFile?: string;
2099
+ retry?: Partial<RetryConfig>;
2068
2100
  onTokenUpdate?: (newCredentials: {
2069
2101
  access: string;
2070
2102
  refresh: string;
@@ -2074,12 +2106,11 @@ type AnthropicAISDKOptions = {
2074
2106
  declare class AnthropicAISDKLLM {
2075
2107
  private readonly opts;
2076
2108
  private provider?;
2077
- private refreshPromise;
2109
+ private transport?;
2110
+ private authTransport?;
2078
2111
  constructor(opts?: AnthropicAISDKOptions);
2079
- private refreshAccessToken;
2080
- private updateCredentials;
2081
- private ensureValidToken;
2082
- private createFetchWithRetry;
2112
+ private getAuthTransport;
2113
+ private getTransport;
2083
2114
  private getProvider;
2084
2115
  private getModel;
2085
2116
  private transformMessages;
@@ -2109,6 +2140,7 @@ interface LLMOptions {
2109
2140
  includeUsage?: boolean;
2110
2141
  version?: string;
2111
2142
  providerName?: string;
2143
+ retry?: Partial<RetryConfig>;
2112
2144
  }
2113
2145
  interface CustomProviderDefinition {
2114
2146
  type?: 'openai-compat' | 'anthropic';
@@ -2211,4 +2243,4 @@ declare function resolveBackspaces(s: string): string;
2211
2243
  declare function stripAnsiAndControls(s: string): string;
2212
2244
  declare function canonicalizeTerminalPaste(raw: string): string;
2213
2245
 
2214
- export { AGENT_CREATOR_SYSTEM_PROMPT, type AgentAwareToolPort, type AgentCatalog, type AgentConfig, type AgentEvent, AgentEventTypes, AgentFilePersistence, AgentManager, AgentManagerCommandRunner, AgentOrchestrator, AgentRegistry, type AgentTemplate, AnthropicAISDKLLM, type AssignErrorResult, type AssignParams, type AssignResult, type AssignSuccessResult$1 as AssignSuccessResult, type AssignTaskArgs, type AssignTaskMetadata, type BashErrorResult, type BashParams, type BashResult, type BashSuccessResult$1 as BashSuccessResult, BashTool, type BashToolArgs, type BashToolMetadata, type CommandMetadata, type CompleteAgent, CompositeToolPort, type Conversation, ConversationContext, type ConversationMetadata, type ConversationSnapshot, ConversationStore, CoreMCPClient, DefaultDelegationPolicy, DefaultDelegationResultFormatter, DefaultDelegationService, DefaultSpecialistAgentFactory, type DelegationMetadata, type DelegationService, type DelegationServiceConfig, DelegationServiceFactory, type DirEntry, type DirLsArgs, type DirLsMetadata, type DirLsParams, type DirLsResult, type DirLsSuccessResult$1 as DirLsSuccessResult, type ErrorMetadata, ErrorReason, type ExecResult, type ExecResultError, type ExecResultSuccess, type FileEditArgs, type FileEditMetadata, type FileEditResult, type FileEditSuccessResult$1 as FileEditSuccessResult, type FileMetadata, type FileNewArgs, type FileNewMetadata, type FileNewParams, type FileNewResult, type FileNewSuccessResult$1 as FileNewSuccessResult, type FileReadArgs, type FileReadErrorResult, type FileReadMetadata, type FileReadParams, type FileReadResult, type FileReadSuccessResult$1 as FileReadSuccessResult, type FolderTreeOptions, type FunctionTool, GithubLLM, InMemoryMemory, InMemoryMetadata, InMemoryMetricsPort, JsonFileMemoryPersistence, type LLMConfig, LLMError, type LLMFactory, type LLMOptions, type LLMPort, LLMResolver, type LineRangeMetadata, type MCPConfig, type MCPServerConfig, MCPToolPort, type MemoryPort, MemoryPortMetadataAdapter, type Message, type MessageContent, type MessageContentPart, type MetadataPort, type MetricsChangeHandler, type MetricsPort, type MetricsSnapshot, type ModelInfo, type ModelLimits, NoopMetricsPort, NoopReminders, type OrchestratorAwareToolPort, type ParseResult, PersistedMemory, PersistingConsoleEventPort, RuntimeEnv, type SendMessageOptions, SimpleContextBuilder, SimpleCost, SimpleId, type SpecialistAgentConfig, type SpecialistAgentResult, type SubAgentState, type SubAgentToolCall, SystemClock, type TodoWriteArgs, type TodoWriteMetadata, type TodoWriteResult, type TodoWriteSuccessResult$1 as TodoWriteSuccessResult, type ToolApprovalDecision, type ToolArguments, type ToolCall, type ToolCallValidation, type ToolErrorMetadata, type ToolExecutionContext, type ToolExecutionResult, type ToolMetadataMap, type ToolName, type ToolParameterMap, type ToolPort, ToolRegistry, type ToolValidator, type TypedToolInvocation, type UsageData, type UserAttachment, type UserMessagePayload, type ValidationResult, type WebFetchArgs, type WebFetchMetadata, type WebFetchParams, type WebFetchResult, type WebFetchSuccessResult$1 as WebFetchSuccessResult, type WebSearchArgs, type WebSearchMetadata, type WebSearchParams, type WebSearchResult, type WebSearchSuccessResult$1 as WebSearchSuccessResult, type WebSearchToolResult, buildAgentCreationPrompt, buildInjectedSystem, canonicalizeTerminalPaste, convertToolCall, convertToolCalls, createEmptySnapshot, createLLM, err, generateFolderTree, getAvailableProviders, getFallbackLimits, getProviderLabel, isAssignResult, isAssignSuccess, isAssignTaskArgs, isBashResult, isBashSuccess, isBashToolArgs, isDirLsArgs, isDirLsResult, isDirLsSuccess, isError, isFileEditArgs, isFileEditResult, isFileEditSuccess, isFileNewArgs, isFileNewResult, isFileNewSuccess, isFileReadArgs, isFileReadResult, isFileReadSuccess, isJsonResult, isSuccess, isSuccessJson, isSuccessText, isTextResult, isTodoWriteArgs, isTodoWriteResult, isTodoWriteSuccess, isWebFetchArgs, isWebFetchResult, isWebFetchSuccess, isWebSearchArgs, isWebSearchResult, isWebSearchSuccess, loadMCPConfig, normalizeModelInfo, normalizeModelLimits, normalizeNewlines, okJson, okText, parseJSON, parseSubAgentToolCallArguments, parseToolArguments, renderTemplate, resolveBackspaces, resolveCarriageReturns, stripAnsiAndControls, supportsGetModels, toolValidators };
2246
+ export { AGENT_CREATOR_SYSTEM_PROMPT, AbortError, type AgentAwareToolPort, type AgentCatalog, type AgentConfig, type AgentEvent, AgentEventTypes, AgentFilePersistence, AgentManager, AgentManagerCommandRunner, AgentOrchestrator, AgentRegistry, type AgentTemplate, AnthropicAISDKLLM, type AssignErrorResult, type AssignParams, type AssignResult, type AssignSuccessResult$1 as AssignSuccessResult, type AssignTaskArgs, type AssignTaskMetadata, type BaseLLMOptions, type BashErrorResult, type BashParams, type BashResult, type BashSuccessResult$1 as BashSuccessResult, BashTool, type BashToolArgs, type BashToolMetadata, type CommandMetadata, type CompleteAgent, CompositeToolPort, type Conversation, ConversationContext, type ConversationMetadata, type ConversationSnapshot, ConversationStore, CoreMCPClient, DEFAULT_RETRY_CONFIG, DefaultDelegationPolicy, DefaultDelegationResultFormatter, DefaultDelegationService, DefaultSpecialistAgentFactory, type DelegationMetadata, type DelegationService, type DelegationServiceConfig, DelegationServiceFactory, type DirEntry, type DirLsArgs, type DirLsMetadata, type DirLsParams, type DirLsResult, type DirLsSuccessResult$1 as DirLsSuccessResult, type ErrorMetadata, ErrorReason, type ExecResult, type ExecResultError, type ExecResultSuccess, type FileEditArgs, type FileEditMetadata, type FileEditResult, type FileEditSuccessResult$1 as FileEditSuccessResult, type FileMetadata, type FileNewArgs, type FileNewMetadata, type FileNewParams, type FileNewResult, type FileNewSuccessResult$1 as FileNewSuccessResult, type FileReadArgs, type FileReadErrorResult, type FileReadMetadata, type FileReadParams, type FileReadResult, type FileReadSuccessResult$1 as FileReadSuccessResult, type FolderTreeOptions, type FunctionTool, GithubLLM, InMemoryMemory, InMemoryMetadata, InMemoryMetricsPort, JsonFileMemoryPersistence, type LLMConfig, LLMError, type LLMFactory, type LLMOptions, type LLMPort, LLMResolver, type LineRangeMetadata, type MCPConfig, type MCPServerConfig, MCPToolPort, type MemoryPort, MemoryPortMetadataAdapter, type Message, type MessageContent, type MessageContentPart, type MetadataPort, type MetricsChangeHandler, type MetricsPort, type MetricsSnapshot, type ModelInfo, type ModelLimits, NoopMetricsPort, NoopReminders, type OrchestratorAwareToolPort, type ParseResult, PersistedMemory, PersistingConsoleEventPort, type RetryConfig, RetryTransport, RuntimeEnv, type SendMessageOptions, SimpleContextBuilder, SimpleCost, SimpleId, type SpecialistAgentConfig, type SpecialistAgentResult, type SubAgentState, type SubAgentToolCall, SystemClock, type TodoWriteArgs, type TodoWriteMetadata, type TodoWriteResult, type TodoWriteSuccessResult$1 as TodoWriteSuccessResult, type ToolApprovalDecision, type ToolArguments, type ToolCall, type ToolCallValidation, type ToolErrorMetadata, type ToolExecutionContext, type ToolExecutionResult, type ToolMetadataMap, type ToolName, type ToolParameterMap, type ToolPort, ToolRegistry, type ToolValidator, type TypedToolInvocation, type UsageData, type UserAttachment, type UserMessagePayload, type ValidationResult, type WebFetchArgs, type WebFetchMetadata, type WebFetchParams, type WebFetchResult, type WebFetchSuccessResult$1 as WebFetchSuccessResult, type WebSearchArgs, type WebSearchMetadata, type WebSearchParams, type WebSearchResult, type WebSearchSuccessResult$1 as WebSearchSuccessResult, type WebSearchToolResult, buildAgentCreationPrompt, buildInjectedSystem, canonicalizeTerminalPaste, convertToolCall, convertToolCalls, createEmptySnapshot, createLLM, err, generateFolderTree, getAvailableProviders, getFallbackLimits, getProviderLabel, isAssignResult, isAssignSuccess, isAssignTaskArgs, isBashResult, isBashSuccess, isBashToolArgs, isDirLsArgs, isDirLsResult, isDirLsSuccess, isError, isFileEditArgs, isFileEditResult, isFileEditSuccess, isFileNewArgs, isFileNewResult, isFileNewSuccess, isFileReadArgs, isFileReadResult, isFileReadSuccess, isJsonResult, isRetryableError, isRetryableStatusCode, isSuccess, isSuccessJson, isSuccessText, isTextResult, isTodoWriteArgs, isTodoWriteResult, isTodoWriteSuccess, isWebFetchArgs, isWebFetchResult, isWebFetchSuccess, isWebSearchArgs, isWebSearchResult, isWebSearchSuccess, loadMCPConfig, normalizeModelInfo, normalizeModelLimits, normalizeNewlines, okJson, okText, parseJSON, parseSubAgentToolCallArguments, parseToolArguments, renderTemplate, resolveBackspaces, resolveCarriageReturns, stripAnsiAndControls, supportsGetModels, toolValidators };
package/dist/index.js CHANGED
@@ -1015,37 +1015,30 @@ var AgentOrchestrator = class {
1015
1015
  if (!_llm) {
1016
1016
  throw new Error("LLM provider not set");
1017
1017
  }
1018
- if (opts.retry) {
1019
- providerMsgs = this.context.toProviderMessages(history, this.cfg.systemPrompt, []);
1020
- userMessages = [];
1021
- userDisplay = "[Retry]";
1022
- enhanced = [];
1018
+ const normalized = typeof content === "string" ? { text: content, displayText: content, attachments: [] } : {
1019
+ text: content.text ?? "",
1020
+ displayText: content.displayText,
1021
+ attachments: Array.isArray(content.attachments) ? content.attachments : []
1022
+ };
1023
+ const attachments = normalized.attachments;
1024
+ enhanced = this.reminders.enhance(normalized.text, { conversationId: convo });
1025
+ const enhancedCombined = enhanced.join("\n");
1026
+ const messageParts = buildMessageParts(enhancedCombined, attachments);
1027
+ let userContent;
1028
+ if (attachments.length > 0 || messageParts.some((part) => part.type === "image")) {
1029
+ userContent = { type: "parts", parts: messageParts };
1030
+ } else if (messageParts.length === 1 && messageParts[0]?.type === "text") {
1031
+ userContent = messageParts[0].text;
1032
+ } else if (messageParts.length > 0) {
1033
+ userContent = { type: "parts", parts: messageParts };
1023
1034
  } else {
1024
- const normalized = typeof content === "string" ? { text: content, displayText: content, attachments: [] } : {
1025
- text: content.text ?? "",
1026
- displayText: content.displayText,
1027
- attachments: Array.isArray(content.attachments) ? content.attachments : []
1028
- };
1029
- const attachments = normalized.attachments;
1030
- enhanced = this.reminders.enhance(normalized.text, { conversationId: convo });
1031
- const enhancedCombined = enhanced.join("\n");
1032
- const messageParts = buildMessageParts(enhancedCombined, attachments);
1033
- let userContent;
1034
- if (attachments.length > 0 || messageParts.some((part) => part.type === "image")) {
1035
- userContent = { type: "parts", parts: messageParts };
1036
- } else if (messageParts.length === 1 && messageParts[0]?.type === "text") {
1037
- userContent = messageParts[0].text;
1038
- } else if (messageParts.length > 0) {
1039
- userContent = { type: "parts", parts: messageParts };
1040
- } else {
1041
- userContent = enhancedCombined;
1042
- }
1043
- providerMsgs = this.context.toProviderMessages(history, this.cfg.systemPrompt, [userContent]);
1044
- userDisplay = resolveDisplayText(normalized.text, attachments, normalized.displayText);
1045
- const userTimestamp = this.clock.iso();
1046
- userMessages = [{ id: this.ids.uuid(), role: "user", content: userContent, timestamp: userTimestamp }];
1047
- await this.memory.append(convo, userMessages);
1035
+ userContent = enhancedCombined;
1048
1036
  }
1037
+ providerMsgs = this.context.toProviderMessages(history, this.cfg.systemPrompt, [userContent]);
1038
+ userDisplay = resolveDisplayText(normalized.text, attachments, normalized.displayText);
1039
+ const userTimestamp = this.clock.iso();
1040
+ userMessages = [{ id: this.ids.uuid(), role: "user", content: userContent, timestamp: userTimestamp }];
1041
+ await this.memory.append(convo, userMessages);
1049
1042
  if (opts.signal?.aborted) throw new Error("Aborted");
1050
1043
  const toolDefs = this.tools.getToolDefinitions(this.cfg.enabledTools ?? []);
1051
1044
  const toolNames = toolDefs.map((t) => t.function.name);
@@ -1212,7 +1205,10 @@ var AgentOrchestrator = class {
1212
1205
  content: contentStr,
1213
1206
  timestamp: this.clock.iso(),
1214
1207
  tool_call_id: tr.id,
1215
- name: tr.name
1208
+ name: tr.name,
1209
+ status: tr.status,
1210
+ durationMs: tr.durationMs,
1211
+ metadata: tr.metadata
1216
1212
  });
1217
1213
  this.metrics?.recordToolCall?.();
1218
1214
  await this.events?.emit({
@@ -3751,7 +3747,7 @@ var AgentManager = class {
3751
3747
  }
3752
3748
  };
3753
3749
  }
3754
- this.eventCallback?.({
3750
+ await this.eventCallback?.({
3755
3751
  type: AgentEventTypes.SubAgentStarted,
3756
3752
  conversationId: config.conversationId ?? "default",
3757
3753
  messageId: config.messageId ?? "",
@@ -3770,7 +3766,7 @@ var AgentManager = class {
3770
3766
  events.push(event);
3771
3767
  if (event.type === AgentEventTypes.ToolCalls) {
3772
3768
  for (const toolCall of event.toolCalls) {
3773
- this.eventCallback?.({
3769
+ await this.eventCallback?.({
3774
3770
  type: AgentEventTypes.SubAgentToolCall,
3775
3771
  conversationId: config.conversationId ?? "default",
3776
3772
  messageId: config.messageId ?? "",
@@ -3781,7 +3777,7 @@ var AgentManager = class {
3781
3777
  });
3782
3778
  }
3783
3779
  } else if (event.type === AgentEventTypes.ToolResult) {
3784
- this.eventCallback?.({
3780
+ await this.eventCallback?.({
3785
3781
  type: AgentEventTypes.SubAgentToolResult,
3786
3782
  conversationId: config.conversationId ?? "default",
3787
3783
  messageId: config.messageId ?? "",
@@ -3845,7 +3841,7 @@ var AgentManager = class {
3845
3841
  }
3846
3842
  }
3847
3843
  const snapshot = metricsPort.getSnapshot();
3848
- this.eventCallback?.({
3844
+ await this.eventCallback?.({
3849
3845
  type: AgentEventTypes.SubAgentCompleted,
3850
3846
  conversationId: config.conversationId ?? "default",
3851
3847
  messageId: config.messageId ?? "",
@@ -3875,7 +3871,7 @@ var AgentManager = class {
3875
3871
  const isTimeout = error instanceof Error && error.message.includes("timeout");
3876
3872
  const isAborted = error instanceof Error && (error.message.includes("aborted") || error.name === "AbortError");
3877
3873
  const status = isTimeout ? "timeout" : isAborted ? "error" : "error";
3878
- this.eventCallback?.({
3874
+ await this.eventCallback?.({
3879
3875
  type: AgentEventTypes.SubAgentCompleted,
3880
3876
  conversationId: config.conversationId ?? "default",
3881
3877
  messageId: config.messageId ?? "",
@@ -4634,9 +4630,11 @@ var BaseLLM = class {
4634
4630
  transport = null;
4635
4631
  apiUrl;
4636
4632
  enablePromptCaching = false;
4633
+ retryConfig;
4637
4634
  constructor(apiUrl, options) {
4638
4635
  this.apiUrl = apiUrl;
4639
4636
  this.enablePromptCaching = options?.enablePromptCaching ?? false;
4637
+ this.retryConfig = options?.retry;
4640
4638
  }
4641
4639
  transformUsage(rawUsage) {
4642
4640
  if (!rawUsage) return void 0;
@@ -5239,6 +5237,387 @@ var GithubAuthTransport = class {
5239
5237
  }
5240
5238
  };
5241
5239
 
5240
+ // src/transports/backoff.ts
5241
+ function calculateBackoff(attempt, baseDelayMs, maxDelayMs, multiplier, jitterFactor) {
5242
+ const exponentialDelay = baseDelayMs * multiplier ** attempt;
5243
+ const cappedDelay = Math.min(exponentialDelay, maxDelayMs);
5244
+ const jitterRange = cappedDelay * jitterFactor;
5245
+ const jitter = jitterRange * (Math.random() * 2 - 1);
5246
+ return Math.max(0, Math.round(cappedDelay + jitter));
5247
+ }
5248
+ function parseRetryAfterHeader(header) {
5249
+ if (!header) return null;
5250
+ const seconds = parseInt(header, 10);
5251
+ if (!Number.isNaN(seconds) && seconds >= 0) {
5252
+ return seconds * 1e3;
5253
+ }
5254
+ const date = Date.parse(header);
5255
+ if (!Number.isNaN(date)) {
5256
+ const delayMs = date - Date.now();
5257
+ return delayMs > 0 ? delayMs : null;
5258
+ }
5259
+ return null;
5260
+ }
5261
+
5262
+ // src/transports/error-classification.ts
5263
+ var DEFAULT_RETRYABLE_STATUS_CODES = [429, 500, 502, 503, 504];
5264
+ var RETRYABLE_NETWORK_ERRORS = [
5265
+ "econnrefused",
5266
+ "enotfound",
5267
+ "etimedout",
5268
+ "econnreset",
5269
+ "epipe",
5270
+ "network",
5271
+ "fetch failed",
5272
+ "socket hang up"
5273
+ ];
5274
+ var NON_RETRYABLE_PATTERNS = [
5275
+ "invalid",
5276
+ "unauthorized",
5277
+ "forbidden",
5278
+ "not found",
5279
+ "bad request",
5280
+ "api key",
5281
+ "authentication",
5282
+ "permission",
5283
+ "invalid_api_key",
5284
+ "insufficient_quota"
5285
+ ];
5286
+ function isRetryableStatusCode(status, retryableStatusCodes = DEFAULT_RETRYABLE_STATUS_CODES) {
5287
+ return retryableStatusCodes.includes(status);
5288
+ }
5289
+ function isRetryableError(error, retryableStatusCodes = DEFAULT_RETRYABLE_STATUS_CODES) {
5290
+ if (!error) return false;
5291
+ if (error instanceof Error && error.name === "AbortError") {
5292
+ return false;
5293
+ }
5294
+ if (error instanceof LLMError) {
5295
+ if (error.statusCode) {
5296
+ return isRetryableStatusCode(error.statusCode, retryableStatusCodes);
5297
+ }
5298
+ return error.isRetryable;
5299
+ }
5300
+ const err2 = error;
5301
+ const statusCode = err2.statusCode ?? err2.status;
5302
+ if (statusCode) {
5303
+ return isRetryableStatusCode(statusCode, retryableStatusCodes);
5304
+ }
5305
+ const message = err2.message?.toLowerCase() || "";
5306
+ const code = err2.code?.toLowerCase() || "";
5307
+ for (const pattern of NON_RETRYABLE_PATTERNS) {
5308
+ if (message.includes(pattern) || code.includes(pattern)) {
5309
+ return false;
5310
+ }
5311
+ }
5312
+ for (const networkError of RETRYABLE_NETWORK_ERRORS) {
5313
+ if (message.includes(networkError) || code.includes(networkError)) {
5314
+ return true;
5315
+ }
5316
+ }
5317
+ return false;
5318
+ }
5319
+
5320
+ // src/transports/retry-transport.ts
5321
+ var DEFAULT_RETRY_CONFIG = {
5322
+ maxRetries: 3,
5323
+ baseDelayMs: 1e3,
5324
+ maxDelayMs: 6e4,
5325
+ backoffMultiplier: 2,
5326
+ jitterFactor: 0.2,
5327
+ retryableStatusCodes: [429, 500, 502, 503, 504]
5328
+ };
5329
+ var AbortError = class _AbortError extends Error {
5330
+ constructor(message = "Operation aborted") {
5331
+ super(message);
5332
+ this.name = "AbortError";
5333
+ if (Error.captureStackTrace) {
5334
+ Error.captureStackTrace(this, _AbortError);
5335
+ }
5336
+ }
5337
+ };
5338
+ var sleep = (ms, signal) => {
5339
+ return new Promise((resolve6, reject) => {
5340
+ if (signal?.aborted) {
5341
+ reject(new AbortError("Operation aborted"));
5342
+ return;
5343
+ }
5344
+ const timeout = setTimeout(resolve6, ms);
5345
+ signal?.addEventListener(
5346
+ "abort",
5347
+ () => {
5348
+ clearTimeout(timeout);
5349
+ reject(new AbortError("Operation aborted during retry delay"));
5350
+ },
5351
+ { once: true }
5352
+ );
5353
+ });
5354
+ };
5355
+ var RetryTransport = class {
5356
+ constructor(inner, config = {}) {
5357
+ this.inner = inner;
5358
+ this.config = { ...DEFAULT_RETRY_CONFIG, ...config };
5359
+ }
5360
+ config;
5361
+ async get(url, headers, signal) {
5362
+ return this.executeWithRetry(() => this.inner.get(url, headers, signal), signal);
5363
+ }
5364
+ async post(url, body, headers, signal) {
5365
+ return this.executeWithRetry(() => this.inner.post(url, body, headers, signal), signal);
5366
+ }
5367
+ async executeWithRetry(fn, signal) {
5368
+ let lastError;
5369
+ let attempt = 0;
5370
+ while (attempt <= this.config.maxRetries) {
5371
+ if (signal?.aborted) {
5372
+ throw new AbortError("Operation aborted before execution");
5373
+ }
5374
+ try {
5375
+ const response = await fn();
5376
+ if (this.isRetryableResponse(response)) {
5377
+ const error = new Error(`HTTP ${response.status}`);
5378
+ error.status = response.status;
5379
+ if (attempt < this.config.maxRetries) {
5380
+ const delayMs = this.getDelayForResponse(response, attempt);
5381
+ this.config.onRetry?.(attempt + 1, error, delayMs);
5382
+ await sleep(delayMs, signal);
5383
+ attempt++;
5384
+ continue;
5385
+ }
5386
+ lastError = error;
5387
+ break;
5388
+ }
5389
+ return response;
5390
+ } catch (error) {
5391
+ if (error instanceof AbortError || error instanceof Error && error.name === "AbortError") {
5392
+ throw error;
5393
+ }
5394
+ lastError = error instanceof Error ? error : new Error(String(error));
5395
+ if (!isRetryableError(lastError, this.config.retryableStatusCodes)) {
5396
+ throw lastError;
5397
+ }
5398
+ if (attempt < this.config.maxRetries) {
5399
+ const delayMs = calculateBackoff(
5400
+ attempt,
5401
+ this.config.baseDelayMs,
5402
+ this.config.maxDelayMs,
5403
+ this.config.backoffMultiplier,
5404
+ this.config.jitterFactor
5405
+ );
5406
+ this.config.onRetry?.(attempt + 1, lastError, delayMs);
5407
+ await sleep(delayMs, signal);
5408
+ attempt++;
5409
+ } else {
5410
+ break;
5411
+ }
5412
+ }
5413
+ }
5414
+ if (lastError) {
5415
+ this.config.onExhausted?.(lastError, attempt + 1);
5416
+ throw lastError;
5417
+ }
5418
+ throw new Error("Retry exhausted without error");
5419
+ }
5420
+ isRetryableResponse(response) {
5421
+ return isRetryableStatusCode(response.status, this.config.retryableStatusCodes);
5422
+ }
5423
+ getDelayForResponse(response, attempt) {
5424
+ const headers = "headers" in response && response.headers instanceof Headers ? response.headers : null;
5425
+ const retryAfter = headers?.get("retry-after") ?? null;
5426
+ const retryAfterMs = parseRetryAfterHeader(retryAfter);
5427
+ if (retryAfterMs !== null) {
5428
+ return Math.min(retryAfterMs, this.config.maxDelayMs);
5429
+ }
5430
+ return calculateBackoff(
5431
+ attempt,
5432
+ this.config.baseDelayMs,
5433
+ this.config.maxDelayMs,
5434
+ this.config.backoffMultiplier,
5435
+ this.config.jitterFactor
5436
+ );
5437
+ }
5438
+ };
5439
+
5440
+ // src/transports/anthropic-transport.ts
5441
+ var CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
5442
+ var DEFAULT_BASE_URL = "https://api.anthropic.com/v1";
5443
+ var AnthropicAuthTransport = class {
5444
+ inner;
5445
+ baseUrl;
5446
+ retryConfig;
5447
+ apiKey;
5448
+ oauth;
5449
+ onTokenUpdate;
5450
+ refreshPromise = null;
5451
+ constructor(inner, opts) {
5452
+ this.inner = inner;
5453
+ this.apiKey = opts.apiKey;
5454
+ this.oauth = opts.oauth;
5455
+ this.baseUrl = opts.baseUrl ?? DEFAULT_BASE_URL;
5456
+ this.onTokenUpdate = opts.onTokenUpdate;
5457
+ this.retryConfig = opts.retry;
5458
+ }
5459
+ async refreshAccessToken() {
5460
+ if (!this.oauth) {
5461
+ return { type: "failed" };
5462
+ }
5463
+ try {
5464
+ const response = await fetch("https://console.anthropic.com/v1/oauth/token", {
5465
+ method: "POST",
5466
+ headers: {
5467
+ "Content-Type": "application/json"
5468
+ },
5469
+ body: JSON.stringify({
5470
+ grant_type: "refresh_token",
5471
+ refresh_token: this.oauth.refresh,
5472
+ client_id: CLIENT_ID
5473
+ })
5474
+ });
5475
+ if (!response.ok) {
5476
+ return { type: "failed" };
5477
+ }
5478
+ const json = await response.json();
5479
+ return {
5480
+ type: "success",
5481
+ access: json.access_token,
5482
+ refresh: json.refresh_token,
5483
+ expires: Date.now() + json.expires_in * 1e3
5484
+ };
5485
+ } catch {
5486
+ return { type: "failed" };
5487
+ }
5488
+ }
5489
+ updateCredentials(result) {
5490
+ if (result.type === "success" && result.access && result.refresh && result.expires) {
5491
+ if (this.oauth) {
5492
+ this.oauth.access = result.access;
5493
+ this.oauth.refresh = result.refresh;
5494
+ this.oauth.expires = result.expires;
5495
+ }
5496
+ this.onTokenUpdate?.({
5497
+ access: result.access,
5498
+ refresh: result.refresh,
5499
+ expires: result.expires
5500
+ });
5501
+ }
5502
+ }
5503
+ async ensureValidToken() {
5504
+ if (!this.oauth) return;
5505
+ if (this.refreshPromise) {
5506
+ const result = await this.refreshPromise;
5507
+ if (result.type === "failed") {
5508
+ throw new Error("Token refresh failed");
5509
+ }
5510
+ return;
5511
+ }
5512
+ this.refreshPromise = this.refreshAccessToken();
5513
+ try {
5514
+ const result = await this.refreshPromise;
5515
+ if (result.type === "success") {
5516
+ this.updateCredentials(result);
5517
+ } else {
5518
+ throw new Error("Token refresh failed");
5519
+ }
5520
+ } finally {
5521
+ this.refreshPromise = null;
5522
+ }
5523
+ }
5524
+ buildFullUrl(path9) {
5525
+ if (path9.startsWith("/")) {
5526
+ return `${this.baseUrl}${path9}`;
5527
+ }
5528
+ return path9;
5529
+ }
5530
+ makeAuthHeaders(headers) {
5531
+ const base = {
5532
+ "anthropic-version": "2023-06-01",
5533
+ "anthropic-beta": "oauth-2025-04-20,fine-grained-tool-streaming-2025-05-14",
5534
+ ...headers || {}
5535
+ };
5536
+ if (this.oauth) {
5537
+ base.authorization = `Bearer ${this.oauth.access}`;
5538
+ } else if (this.apiKey) {
5539
+ base["x-api-key"] = this.apiKey;
5540
+ }
5541
+ return base;
5542
+ }
5543
+ async get(url, headers, signal) {
5544
+ const fullUrl = this.buildFullUrl(url);
5545
+ let res = await this.inner.get(fullUrl, this.makeAuthHeaders(headers), signal);
5546
+ if ((res.status === 401 || res.status === 403) && this.oauth) {
5547
+ await this.ensureValidToken();
5548
+ res = await this.inner.get(fullUrl, this.makeAuthHeaders(headers), signal);
5549
+ }
5550
+ return res;
5551
+ }
5552
+ async post(url, body, headers, signal) {
5553
+ const fullUrl = this.buildFullUrl(url);
5554
+ let res = await this.inner.post(fullUrl, body, this.makeAuthHeaders(headers), signal);
5555
+ if ((res.status === 401 || res.status === 403) && this.oauth) {
5556
+ await this.ensureValidToken();
5557
+ res = await this.inner.post(fullUrl, body, this.makeAuthHeaders(headers), signal);
5558
+ }
5559
+ return res;
5560
+ }
5561
+ createRetryTransport() {
5562
+ return new RetryTransport(this, this.retryConfig);
5563
+ }
5564
+ createFetchFunction() {
5565
+ const makeRequest = async (url, init) => {
5566
+ let currentInit = init;
5567
+ if (this.oauth) {
5568
+ const headers = new Headers(currentInit?.headers);
5569
+ headers.delete("x-api-key");
5570
+ headers.set("authorization", `Bearer ${this.oauth.access}`);
5571
+ headers.set("user-agent", "ai-sdk/anthropic/2.0.30 ai-sdk/provider-utils/3.0.12");
5572
+ currentInit = { ...currentInit, headers };
5573
+ }
5574
+ const response = await fetch(url, currentInit);
5575
+ if ((response.status === 401 || response.status === 403) && this.oauth) {
5576
+ await this.ensureValidToken();
5577
+ const headers = new Headers(currentInit?.headers);
5578
+ headers.set("authorization", `Bearer ${this.oauth.access}`);
5579
+ currentInit = { ...currentInit, headers };
5580
+ return fetch(url, currentInit);
5581
+ }
5582
+ return response;
5583
+ };
5584
+ const retryTransport = new RetryTransport(
5585
+ {
5586
+ get: async (url, headers, signal) => {
5587
+ return makeRequest(url, { method: "GET", headers, signal });
5588
+ },
5589
+ post: async (url, body, headers, signal) => {
5590
+ return makeRequest(url, {
5591
+ method: "POST",
5592
+ headers,
5593
+ body: typeof body === "string" ? body : JSON.stringify(body),
5594
+ signal
5595
+ });
5596
+ }
5597
+ },
5598
+ this.retryConfig
5599
+ );
5600
+ return async (url, init) => {
5601
+ const urlStr = typeof url === "string" ? url : url instanceof URL ? url.toString() : url.url;
5602
+ const method = init?.method?.toUpperCase() ?? "GET";
5603
+ const headers = init?.headers ? Object.fromEntries(new Headers(init.headers).entries()) : void 0;
5604
+ if (method === "GET") {
5605
+ return retryTransport.get(urlStr, headers, init?.signal ?? void 0);
5606
+ }
5607
+ return retryTransport.post(urlStr, init?.body, headers, init?.signal ?? void 0);
5608
+ };
5609
+ }
5610
+ getBaseUrl() {
5611
+ return this.baseUrl;
5612
+ }
5613
+ getOAuth() {
5614
+ return this.oauth;
5615
+ }
5616
+ getApiKey() {
5617
+ return this.apiKey;
5618
+ }
5619
+ };
5620
+
5242
5621
  // src/transports/base-bearer-auth-transport.ts
5243
5622
  var BaseBearerAuthTransport = class {
5244
5623
  inner;
@@ -5416,7 +5795,7 @@ function normalizeModelInfo(provider, model) {
5416
5795
  var GithubLLM = class extends BaseLLM {
5417
5796
  opts;
5418
5797
  constructor(opts = {}) {
5419
- super(opts.apiUrl ?? "https://api.individual.githubcopilot.com");
5798
+ super(opts.apiUrl ?? "https://api.individual.githubcopilot.com", { retry: opts.retry });
5420
5799
  this.opts = opts;
5421
5800
  }
5422
5801
  createTransport() {
@@ -5427,11 +5806,15 @@ var GithubLLM = class extends BaseLLM {
5427
5806
  maxFileSize: 5 * 1024 * 1024,
5428
5807
  captureResponseBody: true
5429
5808
  });
5430
- return new GithubAuthTransport(base, {
5809
+ const authTransport = new GithubAuthTransport(base, {
5431
5810
  baseUrl: this.opts.apiUrl,
5432
5811
  apiKey: this.opts.apiKey,
5433
5812
  accessToken: this.opts.accessToken
5434
5813
  });
5814
+ if (this.retryConfig) {
5815
+ return new RetryTransport(authTransport, this.retryConfig);
5816
+ }
5817
+ return authTransport;
5435
5818
  }
5436
5819
  transformUsage(rawUsage) {
5437
5820
  if (!rawUsage) return void 0;
@@ -5497,126 +5880,68 @@ import {
5497
5880
  jsonSchema,
5498
5881
  APICallError
5499
5882
  } from "ai";
5500
- var CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
5501
5883
  var AnthropicAISDKLLM = class {
5502
5884
  opts;
5503
5885
  provider;
5504
- refreshPromise = null;
5886
+ transport;
5887
+ authTransport;
5505
5888
  constructor(opts = {}) {
5506
5889
  this.opts = opts;
5507
5890
  }
5508
- async refreshAccessToken() {
5509
- if (!this.opts.oauth) {
5510
- return { type: "failed" };
5511
- }
5512
- try {
5513
- const response = await fetch("https://console.anthropic.com/v1/oauth/token", {
5514
- method: "POST",
5515
- headers: {
5516
- "Content-Type": "application/json"
5517
- },
5518
- body: JSON.stringify({
5519
- grant_type: "refresh_token",
5520
- refresh_token: this.opts.oauth.refresh,
5521
- client_id: CLIENT_ID
5522
- })
5891
+ getAuthTransport() {
5892
+ if (!this.authTransport) {
5893
+ const base = new FetchTransport({
5894
+ persistFile: this.opts.httpLogFile,
5895
+ logLevel: "INFO",
5896
+ enableConsoleLog: false,
5897
+ maxFileSize: 5 * 1024 * 1024,
5898
+ captureResponseBody: true
5523
5899
  });
5524
- if (!response.ok) {
5525
- return { type: "failed" };
5526
- }
5527
- const json = await response.json();
5528
- return {
5529
- type: "success",
5530
- access: json.access_token,
5531
- refresh: json.refresh_token,
5532
- expires: Date.now() + json.expires_in * 1e3
5533
- };
5534
- } catch (_error) {
5535
- return { type: "failed" };
5536
- }
5537
- }
5538
- updateCredentials(result) {
5539
- if (result.type === "success" && result.access && result.refresh && result.expires) {
5540
- if (this.opts.oauth) {
5541
- this.opts.oauth.access = result.access;
5542
- this.opts.oauth.refresh = result.refresh;
5543
- this.opts.oauth.expires = result.expires;
5544
- }
5545
- this.opts.onTokenUpdate?.({
5546
- access: result.access,
5547
- refresh: result.refresh,
5548
- expires: result.expires
5900
+ this.authTransport = new AnthropicAuthTransport(base, {
5901
+ apiKey: this.opts.apiKey,
5902
+ oauth: this.opts.oauth ? {
5903
+ access: this.opts.oauth.access,
5904
+ refresh: this.opts.oauth.refresh,
5905
+ expires: this.opts.oauth.expires
5906
+ } : void 0,
5907
+ baseUrl: this.opts.baseURL || this.opts.apiUrl,
5908
+ retry: this.opts.retry,
5909
+ onTokenUpdate: this.opts.onTokenUpdate
5549
5910
  });
5550
5911
  }
5912
+ return this.authTransport;
5551
5913
  }
5552
- async ensureValidToken() {
5553
- if (!this.opts.oauth) return;
5554
- if (this.refreshPromise) {
5555
- const result = await this.refreshPromise;
5556
- if (result.type === "failed") {
5557
- throw new Error("Token refresh failed");
5558
- }
5559
- return;
5560
- }
5561
- this.refreshPromise = this.refreshAccessToken();
5562
- try {
5563
- const result = await this.refreshPromise;
5564
- if (result.type === "success") {
5565
- this.updateCredentials(result);
5566
- this.provider = void 0;
5567
- } else {
5568
- throw new Error("Token refresh failed");
5569
- }
5570
- } finally {
5571
- this.refreshPromise = null;
5914
+ getTransport() {
5915
+ if (!this.transport) {
5916
+ this.transport = this.getAuthTransport().createRetryTransport();
5572
5917
  }
5918
+ return this.transport;
5573
5919
  }
5574
- createFetchWithRetry() {
5575
- return async (url, init) => {
5576
- if (init?.headers && this.opts.oauth) {
5577
- const headers = new Headers(init.headers);
5578
- headers.delete("x-api-key");
5579
- headers.set("authorization", `Bearer ${this.opts.oauth.access}`);
5580
- headers.set("user-agent", "ai-sdk/anthropic/2.0.30 ai-sdk/provider-utils/3.0.12");
5581
- init = { ...init, headers };
5582
- }
5583
- const response = await fetch(url, init);
5584
- if ((response.status === 401 || response.status === 403) && this.opts.oauth) {
5585
- await this.ensureValidToken();
5586
- if (init?.headers) {
5587
- const headers = new Headers(init.headers);
5588
- headers.set("authorization", `Bearer ${this.opts.oauth.access}`);
5589
- init = { ...init, headers };
5590
- }
5591
- return fetch(url, init);
5592
- }
5593
- return response;
5594
- };
5595
- }
5596
- async getProvider() {
5920
+ getProvider() {
5597
5921
  if (this.provider) {
5598
5922
  return this.provider;
5599
5923
  }
5924
+ const authTransport = this.getAuthTransport();
5600
5925
  if (this.opts.oauth) {
5601
5926
  this.provider = createAnthropic({
5602
5927
  apiKey: "sk-ant-oauth-placeholder",
5603
- baseURL: this.opts.baseURL || this.opts.apiUrl,
5928
+ baseURL: authTransport.getBaseUrl(),
5604
5929
  headers: {
5605
5930
  authorization: `Bearer ${this.opts.oauth.access}`,
5606
5931
  "anthropic-beta": "oauth-2025-04-20,claude-code-20250219,interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14"
5607
5932
  },
5608
- fetch: this.createFetchWithRetry()
5933
+ fetch: authTransport.createFetchFunction()
5609
5934
  });
5610
5935
  } else {
5611
5936
  this.provider = createAnthropic({
5612
5937
  apiKey: this.opts.apiKey,
5613
- baseURL: this.opts.baseURL || this.opts.apiUrl
5938
+ baseURL: authTransport.getBaseUrl()
5614
5939
  });
5615
5940
  }
5616
5941
  return this.provider;
5617
5942
  }
5618
- async getModel(modelName) {
5619
- const provider = await this.getProvider();
5943
+ getModel(modelName) {
5944
+ const provider = this.getProvider();
5620
5945
  return provider(modelName);
5621
5946
  }
5622
5947
  transformMessages(messages) {
@@ -5850,7 +6175,7 @@ var AnthropicAISDKLLM = class {
5850
6175
  }
5851
6176
  async generateCompletion(params, signal) {
5852
6177
  try {
5853
- const model = await this.getModel(params.model);
6178
+ const model = this.getModel(params.model);
5854
6179
  const messages = this.transformMessages(params.messages);
5855
6180
  const tools = this.transformTools(params.tools);
5856
6181
  const toolChoice = tools ? this.transformToolChoice(params.tool_choice) : void 0;
@@ -5884,7 +6209,7 @@ var AnthropicAISDKLLM = class {
5884
6209
  }
5885
6210
  async streamCompletion(params, handlers = {}, signal) {
5886
6211
  let streamError = null;
5887
- const model = await this.getModel(params.model);
6212
+ const model = this.getModel(params.model);
5888
6213
  const messages = this.transformMessages(params.messages);
5889
6214
  const tools = this.transformTools(params.tools);
5890
6215
  const toolChoice = tools ? this.transformToolChoice(params.tool_choice) : void 0;
@@ -5935,45 +6260,17 @@ var AnthropicAISDKLLM = class {
5935
6260
  }
5936
6261
  }
5937
6262
  async getModels(signal) {
5938
- const baseURL = this.opts.baseURL || this.opts.apiUrl || "https://api.anthropic.com/v1";
5939
- const url = `${baseURL}/models`;
5940
- const headers = {
5941
- "anthropic-version": "2023-06-01",
5942
- "anthropic-beta": " oauth-2025-04-20,fine-grained-tool-streaming-2025-05-14"
5943
- };
5944
- if (this.opts.oauth) {
5945
- headers.authorization = `Bearer ${this.opts.oauth.access}`;
5946
- } else if (this.opts.apiKey) {
5947
- headers["x-api-key"] = this.opts.apiKey;
5948
- } else {
6263
+ const authTransport = this.getAuthTransport();
6264
+ if (!authTransport.getApiKey() && !authTransport.getOAuth()) {
5949
6265
  throw new LLMError("No API key or OAuth credentials provided", 401, false);
5950
6266
  }
5951
6267
  try {
5952
- const response = await fetch(url, {
5953
- method: "GET",
5954
- headers,
5955
- signal
5956
- });
5957
- if (!response.ok) {
5958
- if ((response.status === 401 || response.status === 403) && this.opts.oauth) {
5959
- await this.ensureValidToken();
5960
- headers.authorization = `Bearer ${this.opts.oauth.access}`;
5961
- const retryResponse = await fetch(url, {
5962
- method: "GET",
5963
- headers,
5964
- signal
5965
- });
5966
- if (!retryResponse.ok) {
5967
- const text2 = await retryResponse.text();
5968
- throw new LLMError(text2 || `Failed to fetch models: ${retryResponse.status}`, retryResponse.status);
5969
- }
5970
- const data2 = await retryResponse.json();
5971
- return data2.data.map((model) => normalizeModelInfo("anthropic", model));
5972
- }
5973
- const text = await response.text();
5974
- throw new LLMError(text || `Failed to fetch models: ${response.status}`, response.status);
6268
+ const res = await this.getTransport().get("/models", void 0, signal);
6269
+ if (!res.ok) {
6270
+ const text = await res.text();
6271
+ throw new LLMError(text || `Failed to fetch models: ${res.status}`, res.status);
5975
6272
  }
5976
- const data = await response.json();
6273
+ const data = await res.json();
5977
6274
  return data.data.map((model) => normalizeModelInfo("anthropic", model));
5978
6275
  } catch (error) {
5979
6276
  if (error instanceof LLMError) {
@@ -6050,8 +6347,8 @@ var GenericLLM = class extends BaseLLM {
6050
6347
  providerName;
6051
6348
  customHeaders;
6052
6349
  constructor(baseUrl, modelConfig, opts = {}, customHeaders) {
6053
- const { enablePromptCaching = false, includeUsage = false, providerName = "unknown", ...restOpts } = opts;
6054
- super(opts.apiUrl || baseUrl, { enablePromptCaching });
6350
+ const { enablePromptCaching = false, includeUsage = false, providerName = "unknown", retry, ...restOpts } = opts;
6351
+ super(opts.apiUrl || baseUrl, { enablePromptCaching, retry });
6055
6352
  this.includeUsage = includeUsage;
6056
6353
  this.modelConfig = modelConfig;
6057
6354
  this.providerName = providerName;
@@ -6066,7 +6363,7 @@ var GenericLLM = class extends BaseLLM {
6066
6363
  maxFileSize: 5 * 1024 * 1024,
6067
6364
  captureResponseBody: true
6068
6365
  });
6069
- return createTransport(
6366
+ const authTransport = createTransport(
6070
6367
  base,
6071
6368
  this.apiUrl,
6072
6369
  this.opts.apiKey,
@@ -6074,6 +6371,10 @@ var GenericLLM = class extends BaseLLM {
6074
6371
  this.opts.version,
6075
6372
  this.customHeaders
6076
6373
  );
6374
+ if (this.retryConfig) {
6375
+ return new RetryTransport(authTransport, this.retryConfig);
6376
+ }
6377
+ return authTransport;
6077
6378
  }
6078
6379
  async getModels(signal) {
6079
6380
  if (this.modelConfig === false) {
@@ -6464,6 +6765,7 @@ function isValidConfig(value) {
6464
6765
  }
6465
6766
  export {
6466
6767
  AGENT_CREATOR_SYSTEM_PROMPT,
6768
+ AbortError,
6467
6769
  AgentEventTypes,
6468
6770
  AgentFilePersistence,
6469
6771
  AgentManager,
@@ -6476,6 +6778,7 @@ export {
6476
6778
  ConversationContext,
6477
6779
  ConversationStore,
6478
6780
  CoreMCPClient,
6781
+ DEFAULT_RETRY_CONFIG,
6479
6782
  DefaultDelegationPolicy,
6480
6783
  DefaultDelegationResultFormatter,
6481
6784
  DefaultDelegationService,
@@ -6495,6 +6798,7 @@ export {
6495
6798
  NoopReminders,
6496
6799
  PersistedMemory,
6497
6800
  PersistingConsoleEventPort,
6801
+ RetryTransport,
6498
6802
  RuntimeEnv,
6499
6803
  SimpleContextBuilder,
6500
6804
  SimpleCost,
@@ -6533,6 +6837,8 @@ export {
6533
6837
  isFileReadResult,
6534
6838
  isFileReadSuccess,
6535
6839
  isJsonResult,
6840
+ isRetryableError,
6841
+ isRetryableStatusCode,
6536
6842
  isSuccess,
6537
6843
  isSuccessJson,
6538
6844
  isSuccessText,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuvin/nuvin-core",
3
- "version": "1.6.0",
3
+ "version": "1.6.2",
4
4
  "description": "",
5
5
  "private": false,
6
6
  "main": "dist/index.js",