@promptbook/ollama 0.100.0-44 → 0.100.0-46
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/esm/index.es.js +100 -5
- package/esm/index.es.js.map +1 -1
- package/esm/typings/src/_packages/components.index.d.ts +14 -0
- package/esm/typings/src/_packages/core.index.d.ts +4 -0
- package/esm/typings/src/_packages/types.index.d.ts +8 -0
- package/esm/typings/src/book-2.0/commitments/_misc/AgentModelRequirements.d.ts +1 -1
- package/esm/typings/src/book-components/AvatarProfile/AvatarProfile/AvatarProfile.d.ts +26 -0
- package/esm/typings/src/book-components/AvatarProfile/AvatarProfile/AvatarProfileFromSource.d.ts +19 -0
- package/esm/typings/src/book-components/BookEditor/BookEditorInner.d.ts +15 -0
- package/esm/typings/src/book-components/Chat/Chat/Chat.d.ts +128 -0
- package/esm/typings/src/book-components/Chat/interfaces/ChatMessage.d.ts +16 -0
- package/esm/typings/src/book-components/Chat/interfaces/ChatParticipant.d.ts +12 -0
- package/esm/typings/src/book-components/Chat/utils/ExportFormat.d.ts +4 -0
- package/esm/typings/src/book-components/Chat/utils/addUtmParamsToUrl.d.ts +7 -0
- package/esm/typings/src/book-components/Chat/utils/createShortLinkForChat.d.ts +7 -0
- package/esm/typings/src/book-components/Chat/utils/downloadFile.d.ts +6 -0
- package/esm/typings/src/book-components/Chat/utils/exportChatHistory.d.ts +11 -0
- package/esm/typings/src/book-components/Chat/utils/generatePdfContent.d.ts +10 -0
- package/esm/typings/src/book-components/Chat/utils/generateQrDataUrl.d.ts +7 -0
- package/esm/typings/src/book-components/Chat/utils/getPromptbookBranding.d.ts +6 -0
- package/esm/typings/src/book-components/Chat/utils/messagesToHtml.d.ts +10 -0
- package/esm/typings/src/book-components/Chat/utils/messagesToJson.d.ts +7 -0
- package/esm/typings/src/book-components/Chat/utils/messagesToMarkdown.d.ts +10 -0
- package/esm/typings/src/book-components/Chat/utils/messagesToText.d.ts +10 -0
- package/esm/typings/src/config.d.ts +13 -0
- package/esm/typings/src/execution/ExecutionTask.d.ts +12 -13
- package/esm/typings/src/llm-providers/openai/OpenAiCompatibleExecutionTools.d.ts +8 -0
- package/esm/typings/src/playground/permanent/error-handling-playground.d.ts +5 -0
- package/esm/typings/src/utils/organization/preserve.d.ts +21 -0
- package/esm/typings/src/version.d.ts +1 -1
- package/package.json +2 -2
- package/umd/index.umd.js +100 -5
- package/umd/index.umd.js.map +1 -1
- package/esm/typings/src/scripting/javascript/utils/preserve.d.ts +0 -14
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode } from 'react';
|
|
2
|
+
import type { Promisable } from 'type-fest';
|
|
3
|
+
import type { ChatMessage } from '../interfaces/ChatMessage';
|
|
4
|
+
import type { ChatParticipant } from '../interfaces/ChatParticipant';
|
|
5
|
+
/**
|
|
6
|
+
* @deprecated use `isComplete` instead
|
|
7
|
+
* @private util of `<Chat />`
|
|
8
|
+
*/
|
|
9
|
+
export declare const LOADING_INTERACTIVE_IMAGE = "Loading...";
|
|
10
|
+
interface ChatProps {
|
|
11
|
+
/**
|
|
12
|
+
* Optional callback to create a new agent from the template.
|
|
13
|
+
* If provided, renders the [Use this template] button.
|
|
14
|
+
*/
|
|
15
|
+
onUseTemplate?(): void;
|
|
16
|
+
/**
|
|
17
|
+
* Messages to render - they are rendered as they are
|
|
18
|
+
*/
|
|
19
|
+
readonly messages: ReadonlyArray<ChatMessage>;
|
|
20
|
+
/**
|
|
21
|
+
* Called every time the user types or dictated a message
|
|
22
|
+
*/
|
|
23
|
+
onChange?(messageContent: string): void;
|
|
24
|
+
/**
|
|
25
|
+
* Called when user sends a message
|
|
26
|
+
*
|
|
27
|
+
* Note: You must handle the message yourself and add it to the `messages` array
|
|
28
|
+
*/
|
|
29
|
+
onMessage(messageContent: string): Promisable<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Optional callback, when set, button for resetting chat will be shown
|
|
32
|
+
*/
|
|
33
|
+
onReset?(): Promisable<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Determines whether the voice recognition button is rendered
|
|
36
|
+
*/
|
|
37
|
+
readonly isVoiceRecognitionButtonShown?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* The language code to use for voice recognition
|
|
40
|
+
*/
|
|
41
|
+
readonly voiceLanguage?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Optional placeholder message for the textarea
|
|
44
|
+
*
|
|
45
|
+
* @default "Write a message"
|
|
46
|
+
*/
|
|
47
|
+
readonly placeholderMessageContent?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Optional preset message in chat
|
|
50
|
+
*/
|
|
51
|
+
readonly defaultMessage?: string;
|
|
52
|
+
/**
|
|
53
|
+
* List of tasks that are currently in progress that should be displayed
|
|
54
|
+
*/
|
|
55
|
+
readonly tasksProgress?: Array<{
|
|
56
|
+
id: string;
|
|
57
|
+
name: string;
|
|
58
|
+
progress?: number;
|
|
59
|
+
}>;
|
|
60
|
+
/**
|
|
61
|
+
* Content to be shown inside the chat bar in head
|
|
62
|
+
* If not provided, the chat bar will not be rendered
|
|
63
|
+
*/
|
|
64
|
+
readonly children?: ReactNode;
|
|
65
|
+
/**
|
|
66
|
+
* Optional CSS class name which will be added to root <div/> element
|
|
67
|
+
*/
|
|
68
|
+
readonly className?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Optional CSS style which will be added to root <div/> element
|
|
71
|
+
*/
|
|
72
|
+
readonly style?: CSSProperties;
|
|
73
|
+
/**
|
|
74
|
+
* Voice call props - when provided, voice call button will be shown
|
|
75
|
+
*/
|
|
76
|
+
readonly voiceCallProps?: {
|
|
77
|
+
selectedModel: string;
|
|
78
|
+
providerClients: Map<string, unknown>;
|
|
79
|
+
currentPersonaContent?: string;
|
|
80
|
+
onVoiceMessage?: (content: string, isVoiceCall: boolean) => void;
|
|
81
|
+
onAssistantVoiceResponse?: (content: string, isVoiceCall: boolean) => void;
|
|
82
|
+
onVoiceCallStateChange?: (isVoiceCalling: boolean) => void;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Indicates whether a voice call is currently active
|
|
86
|
+
*/
|
|
87
|
+
readonly isVoiceCalling?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Whether experimental features are enabled (required for voice calling)
|
|
90
|
+
*/
|
|
91
|
+
readonly isExperimental?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Whether the save button is enabled and shown
|
|
94
|
+
*/
|
|
95
|
+
readonly isSaveButtonEnabled?: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Optional markdown header to include at the top of exported files.
|
|
98
|
+
* Example: "## Discussion Topic\n\nSome topic here"
|
|
99
|
+
*/
|
|
100
|
+
readonly exportHeaderMarkdown?: string;
|
|
101
|
+
/**
|
|
102
|
+
* Optional mapping of participant IDs (message.from) to display metadata for exports.
|
|
103
|
+
* Keys should match ChatMessage.from values (e.g., 'USER', 'AGENT_{id}', etc.)
|
|
104
|
+
*/
|
|
105
|
+
readonly participants?: ReadonlyArray<ChatParticipant>;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Renders a chat with messages and input for new messages
|
|
109
|
+
*
|
|
110
|
+
* Note: 🔇 This component does NOT have speak functionality, it just allows to trigger voice recognition
|
|
111
|
+
*
|
|
112
|
+
* Note: There are multiple chat components:
|
|
113
|
+
* - <Chat/> renders chat as it is without any logic
|
|
114
|
+
* - <SimpleChat/> with callback function after each message 🔵->🟢->🔵->🟢->🔵->🟢->...
|
|
115
|
+
* - <WorkerChat/> with continuously running worker function on background which binds on dialogues queue 🔵->🟢->🔵->🟢->🔵->🟢->...
|
|
116
|
+
* - <SignalChat/> fully controlled by signal that is passed in 🔵->🟢->🟢->🟢->🔵->🟢->...
|
|
117
|
+
* - <LlmChat/> connected to LLM Execution Tools of Promptbook
|
|
118
|
+
* - <AgentChat/> direct OpenAI API integration with streaming responses and model selection
|
|
119
|
+
* - <ChatbotMiniapp/> Fully working chatbot miniapp created from book
|
|
120
|
+
* - <AssistantChatPage/> page for assistant chat with welcome message and avatar
|
|
121
|
+
* - <ModelAwareChat/> wrapper around <Chat/> that provides model-aware avatars
|
|
122
|
+
*
|
|
123
|
+
* Use <WorkerChat/> or <SignalChat/> in most cases.
|
|
124
|
+
*
|
|
125
|
+
* @public exported from `@promptbook/components`
|
|
126
|
+
*/
|
|
127
|
+
export declare function Chat(props: ChatProps): import("react/jsx-runtime").JSX.Element;
|
|
128
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { string_markdown } from '../../../types/typeAliases';
|
|
2
|
+
import type { string_name } from '../../../types/typeAliases';
|
|
3
|
+
/**
|
|
4
|
+
* A message in the chat
|
|
5
|
+
*
|
|
6
|
+
* @public exported from `@promptbook/components`
|
|
7
|
+
*/
|
|
8
|
+
export type ChatMessage = {
|
|
9
|
+
id: string;
|
|
10
|
+
date: Date;
|
|
11
|
+
from: string_name;
|
|
12
|
+
content: string_markdown;
|
|
13
|
+
isComplete?: boolean;
|
|
14
|
+
expectedAnswer?: string;
|
|
15
|
+
isVoiceCall?: boolean;
|
|
16
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { string_name } from '../../../types/typeAliases';
|
|
2
|
+
import type { string_url_image } from '../../../types/typeAliases';
|
|
3
|
+
/**
|
|
4
|
+
* A participant in the chat
|
|
5
|
+
*
|
|
6
|
+
* @public exported from `@promptbook/components`
|
|
7
|
+
*/
|
|
8
|
+
export type ChatParticipant = {
|
|
9
|
+
name: string_name;
|
|
10
|
+
avatarUrl?: string_url_image;
|
|
11
|
+
color: string;
|
|
12
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ChatMessage } from '../interfaces/ChatMessage';
|
|
2
|
+
import type { ExportFormat } from './ExportFormat';
|
|
3
|
+
/**
|
|
4
|
+
* Exports chat messages in the specified format
|
|
5
|
+
*
|
|
6
|
+
* @private utility of `<Chat/>` component
|
|
7
|
+
*/
|
|
8
|
+
export declare function exportChatHistory(messages: ChatMessage[], format: ExportFormat, headerMarkdown?: string, participants?: Record<string, {
|
|
9
|
+
name: string;
|
|
10
|
+
avatarUrl?: string;
|
|
11
|
+
}>): Promise<void>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ChatMessage } from '../interfaces/ChatMessage';
|
|
2
|
+
/**
|
|
3
|
+
* Generates PDF content using HTML and triggers print dialog
|
|
4
|
+
*
|
|
5
|
+
* @private utility of `<Chat/>` component
|
|
6
|
+
*/
|
|
7
|
+
export declare function generatePdfContent(messages: ChatMessage[], shareUrl: string, qrDataUrl?: string | null, headerMarkdown?: string, participants?: Record<string, {
|
|
8
|
+
name: string;
|
|
9
|
+
avatarUrl?: string;
|
|
10
|
+
}>): void;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ChatMessage } from '../interfaces/ChatMessage';
|
|
2
|
+
/**
|
|
3
|
+
* Converts chat messages to HTML format
|
|
4
|
+
*
|
|
5
|
+
* @private utility of `<Chat/>` component
|
|
6
|
+
*/
|
|
7
|
+
export declare function messagesToHtml(messages: ChatMessage[], shareUrl: string, qrDataUrl?: string | null, headerMarkdown?: string, participants?: Record<string, {
|
|
8
|
+
name: string;
|
|
9
|
+
avatarUrl?: string;
|
|
10
|
+
}>): string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ChatMessage } from '../interfaces/ChatMessage';
|
|
2
|
+
/**
|
|
3
|
+
* Converts chat messages to Markdown format
|
|
4
|
+
*
|
|
5
|
+
* @private utility of `<Chat/>` component
|
|
6
|
+
*/
|
|
7
|
+
export declare function messagesToMarkdown(messages: ChatMessage[], shareUrl: string, qrDataUrl?: string | null, headerMarkdown?: string, participants?: Record<string, {
|
|
8
|
+
name: string;
|
|
9
|
+
avatarUrl?: string;
|
|
10
|
+
}>): string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ChatMessage } from '../interfaces/ChatMessage';
|
|
2
|
+
/**
|
|
3
|
+
* Converts chat messages to plain text format
|
|
4
|
+
*
|
|
5
|
+
* @private utility of `<Chat/>` component
|
|
6
|
+
*/
|
|
7
|
+
export declare function messagesToText(messages: ChatMessage[], shareUrl: string, headerMarkdown?: string, participants?: Record<string, {
|
|
8
|
+
name: string;
|
|
9
|
+
avatarUrl?: string;
|
|
10
|
+
}>): string;
|
|
@@ -301,6 +301,19 @@ export declare const DEFAULT_GET_PIPELINE_COLLECTION_FUNCTION_NAME = "getPipelin
|
|
|
301
301
|
* @public exported from `@promptbook/core`
|
|
302
302
|
*/
|
|
303
303
|
export declare const DEFAULT_MAX_REQUESTS_PER_MINUTE = 60;
|
|
304
|
+
/**
|
|
305
|
+
* API request timeout in milliseconds
|
|
306
|
+
* Can be overridden via API_REQUEST_TIMEOUT environment variable
|
|
307
|
+
*
|
|
308
|
+
* @public exported from `@promptbook/core`
|
|
309
|
+
*/
|
|
310
|
+
export declare const API_REQUEST_TIMEOUT: number;
|
|
311
|
+
/**
|
|
312
|
+
* URL of the Promptbook logo
|
|
313
|
+
*
|
|
314
|
+
* @public exported from `@promptbook/core`
|
|
315
|
+
*/
|
|
316
|
+
export declare const PROMPTBOOK_LOGO_URL = "https://promptbook.studio/logos/logo-blue-white-256.png";
|
|
304
317
|
/**
|
|
305
318
|
* Indicates whether pipeline logic validation is enabled. When true, the pipeline logic is checked for consistency.
|
|
306
319
|
*
|
|
@@ -20,7 +20,8 @@ type CreateTaskOptions<TTaskResult extends AbstractTaskResult> = {
|
|
|
20
20
|
readonly title: AbstractTask<TTaskResult>['title'];
|
|
21
21
|
/**
|
|
22
22
|
* Callback that processes the task and updates the ongoing result
|
|
23
|
-
* @param
|
|
23
|
+
* @param updateOngoingResult Function to update the partial result of the task processing
|
|
24
|
+
* @param updateTldr Function to update tldr progress information
|
|
24
25
|
* @returns The final task result
|
|
25
26
|
*/
|
|
26
27
|
taskProcessCallback(updateOngoingResult: (newOngoingResult: PartialDeep<TTaskResult> & {
|
|
@@ -28,20 +29,10 @@ type CreateTaskOptions<TTaskResult extends AbstractTaskResult> = {
|
|
|
28
29
|
* Optional update of the task title
|
|
29
30
|
*/
|
|
30
31
|
readonly title?: AbstractTask<TTaskResult>['title'];
|
|
31
|
-
}) => void
|
|
32
|
-
/**
|
|
33
|
-
* Optional callback to provide custom tldr information
|
|
34
|
-
* @param createdAt When the task was created
|
|
35
|
-
* @param status Current task status
|
|
36
|
-
* @param currentValue Current partial result
|
|
37
|
-
* @param errors Current errors
|
|
38
|
-
* @param warnings Current warnings
|
|
39
|
-
* @returns Custom tldr information
|
|
40
|
-
*/
|
|
41
|
-
tldrProvider?(createdAt: Date, status: task_status, currentValue: PartialDeep<TTaskResult>, errors: Array<Error>, warnings: Array<Error>): {
|
|
32
|
+
}) => void, updateTldr: (tldrInfo: {
|
|
42
33
|
readonly percent: number_percent;
|
|
43
34
|
readonly message: string;
|
|
44
|
-
}
|
|
35
|
+
}) => void): Promise<TTaskResult>;
|
|
45
36
|
};
|
|
46
37
|
/**
|
|
47
38
|
* Helper to create a new task
|
|
@@ -119,6 +110,14 @@ export type AbstractTask<TTaskResult extends AbstractTaskResult> = {
|
|
|
119
110
|
* Gets a promise that resolves with the task result
|
|
120
111
|
*/
|
|
121
112
|
asPromise(options?: {
|
|
113
|
+
/**
|
|
114
|
+
* Do the task throws on error
|
|
115
|
+
*
|
|
116
|
+
* - If `true` when error occurs the returned promise will rejects
|
|
117
|
+
* - If `false` the promise will resolve with object with all listed errors and warnings and partial result
|
|
118
|
+
*
|
|
119
|
+
* @default true
|
|
120
|
+
*/
|
|
122
121
|
readonly isCrashedOnError?: boolean;
|
|
123
122
|
}): Promise<TTaskResult>;
|
|
124
123
|
/**
|
|
@@ -82,6 +82,14 @@ export declare abstract class OpenAiCompatibleExecutionTools implements LlmExecu
|
|
|
82
82
|
* Default model for completion variant.
|
|
83
83
|
*/
|
|
84
84
|
protected abstract getDefaultEmbeddingModel(): AvailableModel;
|
|
85
|
+
/**
|
|
86
|
+
* Makes a request with retry logic for network errors like ECONNRESET
|
|
87
|
+
*/
|
|
88
|
+
private makeRequestWithRetry;
|
|
89
|
+
/**
|
|
90
|
+
* Determines if an error is retryable (network-related errors)
|
|
91
|
+
*/
|
|
92
|
+
private isRetryableNetworkError;
|
|
85
93
|
}
|
|
86
94
|
/**
|
|
87
95
|
* TODO: [🛄] Some way how to re-wrap the errors from `OpenAiCompatibleExecutionTools`
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { really_any } from './really_any';
|
|
2
|
+
/**
|
|
3
|
+
* Does nothing, but preserves the function in the bundle
|
|
4
|
+
* Compiler is tricked into thinking the function is used
|
|
5
|
+
*
|
|
6
|
+
* @param value any function to preserve
|
|
7
|
+
* @returns nothing
|
|
8
|
+
* @private within the repository
|
|
9
|
+
*/
|
|
10
|
+
export declare function $preserve(...value: Array<really_any>): void;
|
|
11
|
+
/**
|
|
12
|
+
* DO NOT USE THIS FUNCTION
|
|
13
|
+
* Only purpose of this function is to trick the compiler and javascript engine
|
|
14
|
+
* that `_preserved` array can be used in the future and should not be garbage collected
|
|
15
|
+
*
|
|
16
|
+
* @private internal for `preserve`
|
|
17
|
+
*/
|
|
18
|
+
export declare function __DO_NOT_USE_getPreserved(): Array<really_any>;
|
|
19
|
+
/**
|
|
20
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
21
|
+
*/
|
|
@@ -15,7 +15,7 @@ export declare const BOOK_LANGUAGE_VERSION: string_semantic_version;
|
|
|
15
15
|
export declare const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version;
|
|
16
16
|
/**
|
|
17
17
|
* Represents the version string of the Promptbook engine.
|
|
18
|
-
* It follows semantic versioning (e.g., `0.100.0-
|
|
18
|
+
* It follows semantic versioning (e.g., `0.100.0-45`).
|
|
19
19
|
*
|
|
20
20
|
* @generated
|
|
21
21
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@promptbook/ollama",
|
|
3
|
-
"version": "0.100.0-
|
|
3
|
+
"version": "0.100.0-46",
|
|
4
4
|
"description": "Promptbook: Run AI apps in plain human language across multiple models and platforms",
|
|
5
5
|
"private": false,
|
|
6
6
|
"sideEffects": false,
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
"module": "./esm/index.es.js",
|
|
95
95
|
"typings": "./esm/typings/src/_packages/ollama.index.d.ts",
|
|
96
96
|
"peerDependencies": {
|
|
97
|
-
"@promptbook/core": "0.100.0-
|
|
97
|
+
"@promptbook/core": "0.100.0-46"
|
|
98
98
|
},
|
|
99
99
|
"dependencies": {
|
|
100
100
|
"bottleneck": "^2.19.5",
|
package/umd/index.umd.js
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* @generated
|
|
26
26
|
* @see https://github.com/webgptorg/promptbook
|
|
27
27
|
*/
|
|
28
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.100.0-
|
|
28
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.100.0-46';
|
|
29
29
|
/**
|
|
30
30
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
31
31
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -229,6 +229,13 @@
|
|
|
229
229
|
* @public exported from `@promptbook/utils`
|
|
230
230
|
*/
|
|
231
231
|
const SMALL_NUMBER = 0.001;
|
|
232
|
+
// <- TODO: [⏳] Standardize timeouts, Make DEFAULT_TIMEOUT_MS as global constant
|
|
233
|
+
/**
|
|
234
|
+
* How many times to retry the connections
|
|
235
|
+
*
|
|
236
|
+
* @private within the repository - too low-level in comparison with other `MAX_...`
|
|
237
|
+
*/
|
|
238
|
+
const CONNECTION_RETRIES_LIMIT = 5;
|
|
232
239
|
// <- TODO: [🧜♂️]
|
|
233
240
|
/**
|
|
234
241
|
* Default settings for parsing and generating CSV files in Promptbook.
|
|
@@ -249,6 +256,13 @@
|
|
|
249
256
|
* @public exported from `@promptbook/core`
|
|
250
257
|
*/
|
|
251
258
|
const DEFAULT_MAX_REQUESTS_PER_MINUTE = 60;
|
|
259
|
+
/**
|
|
260
|
+
* API request timeout in milliseconds
|
|
261
|
+
* Can be overridden via API_REQUEST_TIMEOUT environment variable
|
|
262
|
+
*
|
|
263
|
+
* @public exported from `@promptbook/core`
|
|
264
|
+
*/
|
|
265
|
+
const API_REQUEST_TIMEOUT = parseInt(process.env.API_REQUEST_TIMEOUT || '90000');
|
|
252
266
|
/**
|
|
253
267
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
254
268
|
* TODO: [🧠][🧜♂️] Maybe join remoteServerUrl and path into single value
|
|
@@ -1923,7 +1937,18 @@
|
|
|
1923
1937
|
const openAiOptions = { ...this.options };
|
|
1924
1938
|
delete openAiOptions.isVerbose;
|
|
1925
1939
|
delete openAiOptions.userId;
|
|
1926
|
-
|
|
1940
|
+
// Enhanced configuration for better ECONNRESET handling
|
|
1941
|
+
const enhancedOptions = {
|
|
1942
|
+
...openAiOptions,
|
|
1943
|
+
timeout: API_REQUEST_TIMEOUT,
|
|
1944
|
+
maxRetries: CONNECTION_RETRIES_LIMIT,
|
|
1945
|
+
defaultHeaders: {
|
|
1946
|
+
Connection: 'keep-alive',
|
|
1947
|
+
'Keep-Alive': 'timeout=30, max=100',
|
|
1948
|
+
...openAiOptions.defaultHeaders,
|
|
1949
|
+
},
|
|
1950
|
+
};
|
|
1951
|
+
this.client = new OpenAI__default["default"](enhancedOptions);
|
|
1927
1952
|
}
|
|
1928
1953
|
return this.client;
|
|
1929
1954
|
}
|
|
@@ -2011,7 +2036,7 @@
|
|
|
2011
2036
|
console.info(colors__default["default"].bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
|
2012
2037
|
}
|
|
2013
2038
|
const rawResponse = await this.limiter
|
|
2014
|
-
.schedule(() => client.chat.completions.create(rawRequest))
|
|
2039
|
+
.schedule(() => this.makeRequestWithRetry(() => client.chat.completions.create(rawRequest)))
|
|
2015
2040
|
.catch((error) => {
|
|
2016
2041
|
assertsError(error);
|
|
2017
2042
|
if (this.options.isVerbose) {
|
|
@@ -2087,7 +2112,7 @@
|
|
|
2087
2112
|
console.info(colors__default["default"].bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
|
2088
2113
|
}
|
|
2089
2114
|
const rawResponse = await this.limiter
|
|
2090
|
-
.schedule(() => client.completions.create(rawRequest))
|
|
2115
|
+
.schedule(() => this.makeRequestWithRetry(() => client.completions.create(rawRequest)))
|
|
2091
2116
|
.catch((error) => {
|
|
2092
2117
|
assertsError(error);
|
|
2093
2118
|
if (this.options.isVerbose) {
|
|
@@ -2151,7 +2176,7 @@
|
|
|
2151
2176
|
console.info(colors__default["default"].bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
|
2152
2177
|
}
|
|
2153
2178
|
const rawResponse = await this.limiter
|
|
2154
|
-
.schedule(() => client.embeddings.create(rawRequest))
|
|
2179
|
+
.schedule(() => this.makeRequestWithRetry(() => client.embeddings.create(rawRequest)))
|
|
2155
2180
|
.catch((error) => {
|
|
2156
2181
|
assertsError(error);
|
|
2157
2182
|
if (this.options.isVerbose) {
|
|
@@ -2209,6 +2234,76 @@
|
|
|
2209
2234
|
}
|
|
2210
2235
|
return model;
|
|
2211
2236
|
}
|
|
2237
|
+
// <- Note: [🤖] getDefaultXxxModel
|
|
2238
|
+
/**
|
|
2239
|
+
* Makes a request with retry logic for network errors like ECONNRESET
|
|
2240
|
+
*/
|
|
2241
|
+
async makeRequestWithRetry(requestFn) {
|
|
2242
|
+
let lastError;
|
|
2243
|
+
for (let attempt = 1; attempt <= CONNECTION_RETRIES_LIMIT; attempt++) {
|
|
2244
|
+
try {
|
|
2245
|
+
return await requestFn();
|
|
2246
|
+
}
|
|
2247
|
+
catch (error) {
|
|
2248
|
+
assertsError(error);
|
|
2249
|
+
lastError = error;
|
|
2250
|
+
// Check if this is a retryable network error
|
|
2251
|
+
const isRetryableError = this.isRetryableNetworkError(error);
|
|
2252
|
+
if (!isRetryableError || attempt === CONNECTION_RETRIES_LIMIT) {
|
|
2253
|
+
if (this.options.isVerbose) {
|
|
2254
|
+
console.info(colors__default["default"].bgRed('Final error after retries'), `Attempt ${attempt}/${CONNECTION_RETRIES_LIMIT}:`, error);
|
|
2255
|
+
}
|
|
2256
|
+
throw error;
|
|
2257
|
+
}
|
|
2258
|
+
// Calculate exponential backoff delay
|
|
2259
|
+
const baseDelay = 1000; // 1 second
|
|
2260
|
+
const backoffDelay = baseDelay * Math.pow(2, attempt - 1);
|
|
2261
|
+
const jitterDelay = Math.random() * 500; // Add some randomness
|
|
2262
|
+
const totalDelay = backoffDelay + jitterDelay;
|
|
2263
|
+
if (this.options.isVerbose) {
|
|
2264
|
+
console.info(colors__default["default"].bgYellow('Retrying request'), `Attempt ${attempt}/${CONNECTION_RETRIES_LIMIT}, waiting ${Math.round(totalDelay)}ms:`, error.message);
|
|
2265
|
+
}
|
|
2266
|
+
// Wait before retrying
|
|
2267
|
+
await new Promise((resolve) => setTimeout(resolve, totalDelay));
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
throw lastError;
|
|
2271
|
+
}
|
|
2272
|
+
/**
|
|
2273
|
+
* Determines if an error is retryable (network-related errors)
|
|
2274
|
+
*/
|
|
2275
|
+
isRetryableNetworkError(error) {
|
|
2276
|
+
const errorMessage = error.message.toLowerCase();
|
|
2277
|
+
const errorCode = error.code;
|
|
2278
|
+
// Network connection errors that should be retried
|
|
2279
|
+
const retryableErrors = [
|
|
2280
|
+
'econnreset',
|
|
2281
|
+
'enotfound',
|
|
2282
|
+
'econnrefused',
|
|
2283
|
+
'etimedout',
|
|
2284
|
+
'socket hang up',
|
|
2285
|
+
'network error',
|
|
2286
|
+
'fetch failed',
|
|
2287
|
+
'connection reset',
|
|
2288
|
+
'connection refused',
|
|
2289
|
+
'timeout',
|
|
2290
|
+
];
|
|
2291
|
+
// Check error message
|
|
2292
|
+
if (retryableErrors.some((retryableError) => errorMessage.includes(retryableError))) {
|
|
2293
|
+
return true;
|
|
2294
|
+
}
|
|
2295
|
+
// Check error code
|
|
2296
|
+
if (errorCode && retryableErrors.includes(errorCode.toLowerCase())) {
|
|
2297
|
+
return true;
|
|
2298
|
+
}
|
|
2299
|
+
// Check for specific HTTP status codes that are retryable
|
|
2300
|
+
const errorWithStatus = error;
|
|
2301
|
+
const httpStatus = errorWithStatus.status || errorWithStatus.statusCode;
|
|
2302
|
+
if (httpStatus && [429, 500, 502, 503, 504].includes(httpStatus)) {
|
|
2303
|
+
return true;
|
|
2304
|
+
}
|
|
2305
|
+
return false;
|
|
2306
|
+
}
|
|
2212
2307
|
}
|
|
2213
2308
|
/**
|
|
2214
2309
|
* TODO: [🛄] Some way how to re-wrap the errors from `OpenAiCompatibleExecutionTools`
|