@nuvin/nuvin-core 1.6.0 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/VERSION +2 -2
- package/dist/index.d.ts +38 -6
- package/dist/index.js +247 -39
- package/package.json +1 -1
package/dist/VERSION
CHANGED
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
|
-
|
|
2007
|
-
|
|
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;
|
|
@@ -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
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
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
|
-
|
|
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);
|
|
@@ -3751,7 +3744,7 @@ var AgentManager = class {
|
|
|
3751
3744
|
}
|
|
3752
3745
|
};
|
|
3753
3746
|
}
|
|
3754
|
-
this.eventCallback?.({
|
|
3747
|
+
await this.eventCallback?.({
|
|
3755
3748
|
type: AgentEventTypes.SubAgentStarted,
|
|
3756
3749
|
conversationId: config.conversationId ?? "default",
|
|
3757
3750
|
messageId: config.messageId ?? "",
|
|
@@ -3770,7 +3763,7 @@ var AgentManager = class {
|
|
|
3770
3763
|
events.push(event);
|
|
3771
3764
|
if (event.type === AgentEventTypes.ToolCalls) {
|
|
3772
3765
|
for (const toolCall of event.toolCalls) {
|
|
3773
|
-
this.eventCallback?.({
|
|
3766
|
+
await this.eventCallback?.({
|
|
3774
3767
|
type: AgentEventTypes.SubAgentToolCall,
|
|
3775
3768
|
conversationId: config.conversationId ?? "default",
|
|
3776
3769
|
messageId: config.messageId ?? "",
|
|
@@ -3781,7 +3774,7 @@ var AgentManager = class {
|
|
|
3781
3774
|
});
|
|
3782
3775
|
}
|
|
3783
3776
|
} else if (event.type === AgentEventTypes.ToolResult) {
|
|
3784
|
-
this.eventCallback?.({
|
|
3777
|
+
await this.eventCallback?.({
|
|
3785
3778
|
type: AgentEventTypes.SubAgentToolResult,
|
|
3786
3779
|
conversationId: config.conversationId ?? "default",
|
|
3787
3780
|
messageId: config.messageId ?? "",
|
|
@@ -3845,7 +3838,7 @@ var AgentManager = class {
|
|
|
3845
3838
|
}
|
|
3846
3839
|
}
|
|
3847
3840
|
const snapshot = metricsPort.getSnapshot();
|
|
3848
|
-
this.eventCallback?.({
|
|
3841
|
+
await this.eventCallback?.({
|
|
3849
3842
|
type: AgentEventTypes.SubAgentCompleted,
|
|
3850
3843
|
conversationId: config.conversationId ?? "default",
|
|
3851
3844
|
messageId: config.messageId ?? "",
|
|
@@ -3875,7 +3868,7 @@ var AgentManager = class {
|
|
|
3875
3868
|
const isTimeout = error instanceof Error && error.message.includes("timeout");
|
|
3876
3869
|
const isAborted = error instanceof Error && (error.message.includes("aborted") || error.name === "AbortError");
|
|
3877
3870
|
const status = isTimeout ? "timeout" : isAborted ? "error" : "error";
|
|
3878
|
-
this.eventCallback?.({
|
|
3871
|
+
await this.eventCallback?.({
|
|
3879
3872
|
type: AgentEventTypes.SubAgentCompleted,
|
|
3880
3873
|
conversationId: config.conversationId ?? "default",
|
|
3881
3874
|
messageId: config.messageId ?? "",
|
|
@@ -4634,9 +4627,11 @@ var BaseLLM = class {
|
|
|
4634
4627
|
transport = null;
|
|
4635
4628
|
apiUrl;
|
|
4636
4629
|
enablePromptCaching = false;
|
|
4630
|
+
retryConfig;
|
|
4637
4631
|
constructor(apiUrl, options) {
|
|
4638
4632
|
this.apiUrl = apiUrl;
|
|
4639
4633
|
this.enablePromptCaching = options?.enablePromptCaching ?? false;
|
|
4634
|
+
this.retryConfig = options?.retry;
|
|
4640
4635
|
}
|
|
4641
4636
|
transformUsage(rawUsage) {
|
|
4642
4637
|
if (!rawUsage) return void 0;
|
|
@@ -5299,6 +5294,206 @@ function createTransport(inner, defaultBaseUrl, apiKey, baseUrl, version, custom
|
|
|
5299
5294
|
return new SimpleBearerAuthTransport(inner, defaultBaseUrl, apiKey, baseUrl, version, customHeaders);
|
|
5300
5295
|
}
|
|
5301
5296
|
|
|
5297
|
+
// src/transports/backoff.ts
|
|
5298
|
+
function calculateBackoff(attempt, baseDelayMs, maxDelayMs, multiplier, jitterFactor) {
|
|
5299
|
+
const exponentialDelay = baseDelayMs * multiplier ** attempt;
|
|
5300
|
+
const cappedDelay = Math.min(exponentialDelay, maxDelayMs);
|
|
5301
|
+
const jitterRange = cappedDelay * jitterFactor;
|
|
5302
|
+
const jitter = jitterRange * (Math.random() * 2 - 1);
|
|
5303
|
+
return Math.max(0, Math.round(cappedDelay + jitter));
|
|
5304
|
+
}
|
|
5305
|
+
function parseRetryAfterHeader(header) {
|
|
5306
|
+
if (!header) return null;
|
|
5307
|
+
const seconds = parseInt(header, 10);
|
|
5308
|
+
if (!Number.isNaN(seconds) && seconds >= 0) {
|
|
5309
|
+
return seconds * 1e3;
|
|
5310
|
+
}
|
|
5311
|
+
const date = Date.parse(header);
|
|
5312
|
+
if (!Number.isNaN(date)) {
|
|
5313
|
+
const delayMs = date - Date.now();
|
|
5314
|
+
return delayMs > 0 ? delayMs : null;
|
|
5315
|
+
}
|
|
5316
|
+
return null;
|
|
5317
|
+
}
|
|
5318
|
+
|
|
5319
|
+
// src/transports/error-classification.ts
|
|
5320
|
+
var DEFAULT_RETRYABLE_STATUS_CODES = [429, 500, 502, 503, 504];
|
|
5321
|
+
var RETRYABLE_NETWORK_ERRORS = [
|
|
5322
|
+
"econnrefused",
|
|
5323
|
+
"enotfound",
|
|
5324
|
+
"etimedout",
|
|
5325
|
+
"econnreset",
|
|
5326
|
+
"epipe",
|
|
5327
|
+
"network",
|
|
5328
|
+
"fetch failed",
|
|
5329
|
+
"socket hang up"
|
|
5330
|
+
];
|
|
5331
|
+
var NON_RETRYABLE_PATTERNS = [
|
|
5332
|
+
"invalid",
|
|
5333
|
+
"unauthorized",
|
|
5334
|
+
"forbidden",
|
|
5335
|
+
"not found",
|
|
5336
|
+
"bad request",
|
|
5337
|
+
"api key",
|
|
5338
|
+
"authentication",
|
|
5339
|
+
"permission",
|
|
5340
|
+
"invalid_api_key",
|
|
5341
|
+
"insufficient_quota"
|
|
5342
|
+
];
|
|
5343
|
+
function isRetryableStatusCode(status, retryableStatusCodes = DEFAULT_RETRYABLE_STATUS_CODES) {
|
|
5344
|
+
return retryableStatusCodes.includes(status);
|
|
5345
|
+
}
|
|
5346
|
+
function isRetryableError(error, retryableStatusCodes = DEFAULT_RETRYABLE_STATUS_CODES) {
|
|
5347
|
+
if (!error) return false;
|
|
5348
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
5349
|
+
return false;
|
|
5350
|
+
}
|
|
5351
|
+
if (error instanceof LLMError) {
|
|
5352
|
+
if (error.statusCode) {
|
|
5353
|
+
return isRetryableStatusCode(error.statusCode, retryableStatusCodes);
|
|
5354
|
+
}
|
|
5355
|
+
return error.isRetryable;
|
|
5356
|
+
}
|
|
5357
|
+
const err2 = error;
|
|
5358
|
+
const statusCode = err2.statusCode ?? err2.status;
|
|
5359
|
+
if (statusCode) {
|
|
5360
|
+
return isRetryableStatusCode(statusCode, retryableStatusCodes);
|
|
5361
|
+
}
|
|
5362
|
+
const message = err2.message?.toLowerCase() || "";
|
|
5363
|
+
const code = err2.code?.toLowerCase() || "";
|
|
5364
|
+
for (const pattern of NON_RETRYABLE_PATTERNS) {
|
|
5365
|
+
if (message.includes(pattern) || code.includes(pattern)) {
|
|
5366
|
+
return false;
|
|
5367
|
+
}
|
|
5368
|
+
}
|
|
5369
|
+
for (const networkError of RETRYABLE_NETWORK_ERRORS) {
|
|
5370
|
+
if (message.includes(networkError) || code.includes(networkError)) {
|
|
5371
|
+
return true;
|
|
5372
|
+
}
|
|
5373
|
+
}
|
|
5374
|
+
return false;
|
|
5375
|
+
}
|
|
5376
|
+
|
|
5377
|
+
// src/transports/retry-transport.ts
|
|
5378
|
+
var DEFAULT_RETRY_CONFIG = {
|
|
5379
|
+
maxRetries: 3,
|
|
5380
|
+
baseDelayMs: 1e3,
|
|
5381
|
+
maxDelayMs: 6e4,
|
|
5382
|
+
backoffMultiplier: 2,
|
|
5383
|
+
jitterFactor: 0.2,
|
|
5384
|
+
retryableStatusCodes: [429, 500, 502, 503, 504]
|
|
5385
|
+
};
|
|
5386
|
+
var AbortError = class _AbortError extends Error {
|
|
5387
|
+
constructor(message = "Operation aborted") {
|
|
5388
|
+
super(message);
|
|
5389
|
+
this.name = "AbortError";
|
|
5390
|
+
if (Error.captureStackTrace) {
|
|
5391
|
+
Error.captureStackTrace(this, _AbortError);
|
|
5392
|
+
}
|
|
5393
|
+
}
|
|
5394
|
+
};
|
|
5395
|
+
var sleep = (ms, signal) => {
|
|
5396
|
+
return new Promise((resolve6, reject) => {
|
|
5397
|
+
if (signal?.aborted) {
|
|
5398
|
+
reject(new AbortError("Operation aborted"));
|
|
5399
|
+
return;
|
|
5400
|
+
}
|
|
5401
|
+
const timeout = setTimeout(resolve6, ms);
|
|
5402
|
+
signal?.addEventListener(
|
|
5403
|
+
"abort",
|
|
5404
|
+
() => {
|
|
5405
|
+
clearTimeout(timeout);
|
|
5406
|
+
reject(new AbortError("Operation aborted during retry delay"));
|
|
5407
|
+
},
|
|
5408
|
+
{ once: true }
|
|
5409
|
+
);
|
|
5410
|
+
});
|
|
5411
|
+
};
|
|
5412
|
+
var RetryTransport = class {
|
|
5413
|
+
constructor(inner, config = {}) {
|
|
5414
|
+
this.inner = inner;
|
|
5415
|
+
this.config = { ...DEFAULT_RETRY_CONFIG, ...config };
|
|
5416
|
+
}
|
|
5417
|
+
config;
|
|
5418
|
+
async get(url, headers, signal) {
|
|
5419
|
+
return this.executeWithRetry(() => this.inner.get(url, headers, signal), signal);
|
|
5420
|
+
}
|
|
5421
|
+
async post(url, body, headers, signal) {
|
|
5422
|
+
return this.executeWithRetry(() => this.inner.post(url, body, headers, signal), signal);
|
|
5423
|
+
}
|
|
5424
|
+
async executeWithRetry(fn, signal) {
|
|
5425
|
+
let lastError;
|
|
5426
|
+
let attempt = 0;
|
|
5427
|
+
while (attempt <= this.config.maxRetries) {
|
|
5428
|
+
if (signal?.aborted) {
|
|
5429
|
+
throw new AbortError("Operation aborted before execution");
|
|
5430
|
+
}
|
|
5431
|
+
try {
|
|
5432
|
+
const response = await fn();
|
|
5433
|
+
if (this.isRetryableResponse(response)) {
|
|
5434
|
+
const error = new Error(`HTTP ${response.status}`);
|
|
5435
|
+
error.status = response.status;
|
|
5436
|
+
if (attempt < this.config.maxRetries) {
|
|
5437
|
+
const delayMs = this.getDelayForResponse(response, attempt);
|
|
5438
|
+
this.config.onRetry?.(attempt + 1, error, delayMs);
|
|
5439
|
+
await sleep(delayMs, signal);
|
|
5440
|
+
attempt++;
|
|
5441
|
+
continue;
|
|
5442
|
+
}
|
|
5443
|
+
lastError = error;
|
|
5444
|
+
break;
|
|
5445
|
+
}
|
|
5446
|
+
return response;
|
|
5447
|
+
} catch (error) {
|
|
5448
|
+
if (error instanceof AbortError || error instanceof Error && error.name === "AbortError") {
|
|
5449
|
+
throw error;
|
|
5450
|
+
}
|
|
5451
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
5452
|
+
if (!isRetryableError(lastError, this.config.retryableStatusCodes)) {
|
|
5453
|
+
throw lastError;
|
|
5454
|
+
}
|
|
5455
|
+
if (attempt < this.config.maxRetries) {
|
|
5456
|
+
const delayMs = calculateBackoff(
|
|
5457
|
+
attempt,
|
|
5458
|
+
this.config.baseDelayMs,
|
|
5459
|
+
this.config.maxDelayMs,
|
|
5460
|
+
this.config.backoffMultiplier,
|
|
5461
|
+
this.config.jitterFactor
|
|
5462
|
+
);
|
|
5463
|
+
this.config.onRetry?.(attempt + 1, lastError, delayMs);
|
|
5464
|
+
await sleep(delayMs, signal);
|
|
5465
|
+
attempt++;
|
|
5466
|
+
} else {
|
|
5467
|
+
break;
|
|
5468
|
+
}
|
|
5469
|
+
}
|
|
5470
|
+
}
|
|
5471
|
+
if (lastError) {
|
|
5472
|
+
this.config.onExhausted?.(lastError, attempt + 1);
|
|
5473
|
+
throw lastError;
|
|
5474
|
+
}
|
|
5475
|
+
throw new Error("Retry exhausted without error");
|
|
5476
|
+
}
|
|
5477
|
+
isRetryableResponse(response) {
|
|
5478
|
+
return isRetryableStatusCode(response.status, this.config.retryableStatusCodes);
|
|
5479
|
+
}
|
|
5480
|
+
getDelayForResponse(response, attempt) {
|
|
5481
|
+
const headers = "headers" in response && response.headers instanceof Headers ? response.headers : null;
|
|
5482
|
+
const retryAfter = headers?.get("retry-after") ?? null;
|
|
5483
|
+
const retryAfterMs = parseRetryAfterHeader(retryAfter);
|
|
5484
|
+
if (retryAfterMs !== null) {
|
|
5485
|
+
return Math.min(retryAfterMs, this.config.maxDelayMs);
|
|
5486
|
+
}
|
|
5487
|
+
return calculateBackoff(
|
|
5488
|
+
attempt,
|
|
5489
|
+
this.config.baseDelayMs,
|
|
5490
|
+
this.config.maxDelayMs,
|
|
5491
|
+
this.config.backoffMultiplier,
|
|
5492
|
+
this.config.jitterFactor
|
|
5493
|
+
);
|
|
5494
|
+
}
|
|
5495
|
+
};
|
|
5496
|
+
|
|
5302
5497
|
// src/llm-providers/model-limits.ts
|
|
5303
5498
|
function normalizeModelLimits(provider, model) {
|
|
5304
5499
|
switch (provider.toLowerCase()) {
|
|
@@ -5416,7 +5611,7 @@ function normalizeModelInfo(provider, model) {
|
|
|
5416
5611
|
var GithubLLM = class extends BaseLLM {
|
|
5417
5612
|
opts;
|
|
5418
5613
|
constructor(opts = {}) {
|
|
5419
|
-
super(opts.apiUrl ?? "https://api.individual.githubcopilot.com");
|
|
5614
|
+
super(opts.apiUrl ?? "https://api.individual.githubcopilot.com", { retry: opts.retry });
|
|
5420
5615
|
this.opts = opts;
|
|
5421
5616
|
}
|
|
5422
5617
|
createTransport() {
|
|
@@ -5427,11 +5622,15 @@ var GithubLLM = class extends BaseLLM {
|
|
|
5427
5622
|
maxFileSize: 5 * 1024 * 1024,
|
|
5428
5623
|
captureResponseBody: true
|
|
5429
5624
|
});
|
|
5430
|
-
|
|
5625
|
+
const authTransport = new GithubAuthTransport(base, {
|
|
5431
5626
|
baseUrl: this.opts.apiUrl,
|
|
5432
5627
|
apiKey: this.opts.apiKey,
|
|
5433
5628
|
accessToken: this.opts.accessToken
|
|
5434
5629
|
});
|
|
5630
|
+
if (this.retryConfig) {
|
|
5631
|
+
return new RetryTransport(authTransport, this.retryConfig);
|
|
5632
|
+
}
|
|
5633
|
+
return authTransport;
|
|
5435
5634
|
}
|
|
5436
5635
|
transformUsage(rawUsage) {
|
|
5437
5636
|
if (!rawUsage) return void 0;
|
|
@@ -6050,8 +6249,8 @@ var GenericLLM = class extends BaseLLM {
|
|
|
6050
6249
|
providerName;
|
|
6051
6250
|
customHeaders;
|
|
6052
6251
|
constructor(baseUrl, modelConfig, opts = {}, customHeaders) {
|
|
6053
|
-
const { enablePromptCaching = false, includeUsage = false, providerName = "unknown", ...restOpts } = opts;
|
|
6054
|
-
super(opts.apiUrl || baseUrl, { enablePromptCaching });
|
|
6252
|
+
const { enablePromptCaching = false, includeUsage = false, providerName = "unknown", retry, ...restOpts } = opts;
|
|
6253
|
+
super(opts.apiUrl || baseUrl, { enablePromptCaching, retry });
|
|
6055
6254
|
this.includeUsage = includeUsage;
|
|
6056
6255
|
this.modelConfig = modelConfig;
|
|
6057
6256
|
this.providerName = providerName;
|
|
@@ -6066,7 +6265,7 @@ var GenericLLM = class extends BaseLLM {
|
|
|
6066
6265
|
maxFileSize: 5 * 1024 * 1024,
|
|
6067
6266
|
captureResponseBody: true
|
|
6068
6267
|
});
|
|
6069
|
-
|
|
6268
|
+
const authTransport = createTransport(
|
|
6070
6269
|
base,
|
|
6071
6270
|
this.apiUrl,
|
|
6072
6271
|
this.opts.apiKey,
|
|
@@ -6074,6 +6273,10 @@ var GenericLLM = class extends BaseLLM {
|
|
|
6074
6273
|
this.opts.version,
|
|
6075
6274
|
this.customHeaders
|
|
6076
6275
|
);
|
|
6276
|
+
if (this.retryConfig) {
|
|
6277
|
+
return new RetryTransport(authTransport, this.retryConfig);
|
|
6278
|
+
}
|
|
6279
|
+
return authTransport;
|
|
6077
6280
|
}
|
|
6078
6281
|
async getModels(signal) {
|
|
6079
6282
|
if (this.modelConfig === false) {
|
|
@@ -6464,6 +6667,7 @@ function isValidConfig(value) {
|
|
|
6464
6667
|
}
|
|
6465
6668
|
export {
|
|
6466
6669
|
AGENT_CREATOR_SYSTEM_PROMPT,
|
|
6670
|
+
AbortError,
|
|
6467
6671
|
AgentEventTypes,
|
|
6468
6672
|
AgentFilePersistence,
|
|
6469
6673
|
AgentManager,
|
|
@@ -6476,6 +6680,7 @@ export {
|
|
|
6476
6680
|
ConversationContext,
|
|
6477
6681
|
ConversationStore,
|
|
6478
6682
|
CoreMCPClient,
|
|
6683
|
+
DEFAULT_RETRY_CONFIG,
|
|
6479
6684
|
DefaultDelegationPolicy,
|
|
6480
6685
|
DefaultDelegationResultFormatter,
|
|
6481
6686
|
DefaultDelegationService,
|
|
@@ -6495,6 +6700,7 @@ export {
|
|
|
6495
6700
|
NoopReminders,
|
|
6496
6701
|
PersistedMemory,
|
|
6497
6702
|
PersistingConsoleEventPort,
|
|
6703
|
+
RetryTransport,
|
|
6498
6704
|
RuntimeEnv,
|
|
6499
6705
|
SimpleContextBuilder,
|
|
6500
6706
|
SimpleCost,
|
|
@@ -6533,6 +6739,8 @@ export {
|
|
|
6533
6739
|
isFileReadResult,
|
|
6534
6740
|
isFileReadSuccess,
|
|
6535
6741
|
isJsonResult,
|
|
6742
|
+
isRetryableError,
|
|
6743
|
+
isRetryableStatusCode,
|
|
6536
6744
|
isSuccess,
|
|
6537
6745
|
isSuccessJson,
|
|
6538
6746
|
isSuccessText,
|