@voltagent/core 0.1.71 → 0.1.72
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/index.d.ts +39 -9
- package/dist/index.js +74 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +74 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -344,10 +344,13 @@ type InternalAnyWorkflowStep<INPUT, DATA = DangerouslyAllowAny, RESULT = Dangero
|
|
|
344
344
|
* Infer the result type from a list of steps
|
|
345
345
|
* @private - INTERNAL USE ONLY
|
|
346
346
|
*/
|
|
347
|
-
type InternalInferWorkflowStepsResult<STEPS extends ReadonlyArray<InternalAnyWorkflowStep<
|
|
348
|
-
[K in keyof STEPS]:
|
|
347
|
+
type InternalInferWorkflowStepsResult<STEPS extends ReadonlyArray<InternalAnyWorkflowStep<any, any, any, any, any>>> = {
|
|
348
|
+
[K in keyof STEPS]: ExtractExecuteResult<STEPS[K]>;
|
|
349
349
|
};
|
|
350
350
|
type InternalExtractWorkflowInputData<T> = TF.IsUnknown<T> extends true ? BaseMessage | BaseMessage[] | string : TF.IsAny<T> extends true ? BaseMessage | BaseMessage[] | string : T extends z.ZodType ? z.infer<T> : T;
|
|
351
|
+
type ExtractExecuteResult<T> = T extends {
|
|
352
|
+
execute: (...args: any[]) => infer R;
|
|
353
|
+
} ? R extends Promise<infer U> ? U : R : never;
|
|
351
354
|
|
|
352
355
|
type WorkflowStateStatus = "pending" | "running" | "completed" | "failed" | "suspended";
|
|
353
356
|
type WorkflowState<INPUT, RESULT> = {
|
|
@@ -3545,6 +3548,17 @@ interface LibSQLStorageOptions extends MemoryOptions {
|
|
|
3545
3548
|
* @default 100
|
|
3546
3549
|
*/
|
|
3547
3550
|
storageLimit?: number;
|
|
3551
|
+
/**
|
|
3552
|
+
* Number of retry attempts for database operations when encountering busy/locked errors
|
|
3553
|
+
* @default 3
|
|
3554
|
+
*/
|
|
3555
|
+
retryAttempts?: number;
|
|
3556
|
+
/**
|
|
3557
|
+
* Base delay in milliseconds before retrying a failed operation
|
|
3558
|
+
* Uses a jittered exponential backoff strategy for better load distribution
|
|
3559
|
+
* @default 50
|
|
3560
|
+
*/
|
|
3561
|
+
baseDelayMs?: number;
|
|
3548
3562
|
}
|
|
3549
3563
|
/**
|
|
3550
3564
|
* A LibSQL storage implementation of the Memory and WorkflowMemory interfaces
|
|
@@ -3560,6 +3574,8 @@ declare class LibSQLStorage implements Memory {
|
|
|
3560
3574
|
private initialized;
|
|
3561
3575
|
private workflowExtension;
|
|
3562
3576
|
private logger;
|
|
3577
|
+
private retryAttempts;
|
|
3578
|
+
private baseDelayMs;
|
|
3563
3579
|
/**
|
|
3564
3580
|
* Create a new LibSQL storage
|
|
3565
3581
|
* @param options Configuration options
|
|
@@ -3577,6 +3593,20 @@ declare class LibSQLStorage implements Memory {
|
|
|
3577
3593
|
* @param data Additional data to log
|
|
3578
3594
|
*/
|
|
3579
3595
|
private debug;
|
|
3596
|
+
/**
|
|
3597
|
+
* Calculate delay with jitter for better load distribution
|
|
3598
|
+
* @param attempt Current retry attempt number
|
|
3599
|
+
* @returns Delay in milliseconds
|
|
3600
|
+
*/
|
|
3601
|
+
private calculateRetryDelay;
|
|
3602
|
+
/**
|
|
3603
|
+
* Execute a database operation with retry strategy
|
|
3604
|
+
* Implements jittered exponential backoff
|
|
3605
|
+
* @param operationFn The operation function to execute
|
|
3606
|
+
* @param operationName Operation name for logging
|
|
3607
|
+
* @returns The result of the operation
|
|
3608
|
+
*/
|
|
3609
|
+
private executeWithRetryStrategy;
|
|
3580
3610
|
/**
|
|
3581
3611
|
* Initialize workflow tables
|
|
3582
3612
|
*/
|
|
@@ -3619,7 +3649,7 @@ declare class LibSQLStorage implements Memory {
|
|
|
3619
3649
|
/**
|
|
3620
3650
|
* Close the database connection
|
|
3621
3651
|
*/
|
|
3622
|
-
close(): void
|
|
3652
|
+
close(): Promise<void>;
|
|
3623
3653
|
/**
|
|
3624
3654
|
* Add or update a history entry
|
|
3625
3655
|
* @param key Entry ID
|
|
@@ -4989,10 +5019,10 @@ declare function andWhen<INPUT, DATA, RESULT>({ condition, step, inputSchema, ou
|
|
|
4989
5019
|
* @param config - Configuration object with steps array and metadata
|
|
4990
5020
|
* @returns A workflow step that executes all steps simultaneously and returns their results as an array
|
|
4991
5021
|
*/
|
|
4992
|
-
declare function andAll<INPUT, DATA, RESULT, STEPS extends ReadonlyArray<InternalAnyWorkflowStep<INPUT, DATA, RESULT
|
|
5022
|
+
declare function andAll<INPUT, DATA, RESULT, STEPS extends ReadonlyArray<InternalAnyWorkflowStep<INPUT, DATA, RESULT>>>({ steps, ...config }: WorkflowStepParallelAllConfig<STEPS>): {
|
|
4993
5023
|
type: "parallel-all";
|
|
4994
|
-
steps: InternalAnyWorkflowStep<INPUT, DATA,
|
|
4995
|
-
execute: (context: WorkflowExecuteContext<INPUT, DATA, any, any>) => Promise<
|
|
5024
|
+
steps: InternalAnyWorkflowStep<INPUT, DATA, InternalInferWorkflowStepsResult<STEPS>>[];
|
|
5025
|
+
execute: (context: WorkflowExecuteContext<INPUT, DATA, any, any>) => Promise<InternalInferWorkflowStepsResult<STEPS>>;
|
|
4996
5026
|
id: string;
|
|
4997
5027
|
name: string;
|
|
4998
5028
|
purpose: string;
|
|
@@ -5043,12 +5073,12 @@ declare function andAll<INPUT, DATA, RESULT, STEPS extends ReadonlyArray<Interna
|
|
|
5043
5073
|
* @param config - Configuration object with steps array and metadata
|
|
5044
5074
|
* @returns A workflow step that executes all steps simultaneously and returns the result from the first step to complete
|
|
5045
5075
|
*/
|
|
5046
|
-
declare function andRace<INPUT, DATA, RESULT, STEPS extends ReadonlyArray<InternalAnyWorkflowStep<INPUT, DATA, RESULT
|
|
5076
|
+
declare function andRace<INPUT, DATA, RESULT, STEPS extends ReadonlyArray<InternalAnyWorkflowStep<INPUT, DATA, RESULT>>>({ steps, ...config }: InternalWorkflowStepConfig<{
|
|
5047
5077
|
steps: STEPS;
|
|
5048
5078
|
}>): {
|
|
5049
5079
|
type: "parallel-race";
|
|
5050
|
-
steps: InternalAnyWorkflowStep<INPUT, DATA,
|
|
5051
|
-
execute: (context: WorkflowExecuteContext<INPUT, DATA, any, any>) => Promise<
|
|
5080
|
+
steps: InternalAnyWorkflowStep<INPUT, DATA, InternalInferWorkflowStepsResult<STEPS>[number]>[];
|
|
5081
|
+
execute: (context: WorkflowExecuteContext<INPUT, DATA, any, any>) => Promise<InternalInferWorkflowStepsResult<STEPS>[number]>;
|
|
5052
5082
|
id: string;
|
|
5053
5083
|
name: string;
|
|
5054
5084
|
purpose: string;
|
package/dist/index.js
CHANGED
|
@@ -4669,18 +4669,24 @@ var LibSQLStorage = class {
|
|
|
4669
4669
|
initialized;
|
|
4670
4670
|
workflowExtension;
|
|
4671
4671
|
logger;
|
|
4672
|
+
retryAttempts;
|
|
4673
|
+
baseDelayMs;
|
|
4672
4674
|
/**
|
|
4673
4675
|
* Create a new LibSQL storage
|
|
4674
4676
|
* @param options Configuration options
|
|
4675
4677
|
*/
|
|
4676
4678
|
constructor(options) {
|
|
4677
4679
|
this.logger = new LoggerProxy({ component: "libsql-storage" });
|
|
4680
|
+
this.retryAttempts = options.retryAttempts ?? 3;
|
|
4681
|
+
this.baseDelayMs = options.baseDelayMs ?? 50;
|
|
4678
4682
|
this.options = {
|
|
4679
4683
|
storageLimit: options.storageLimit || 100,
|
|
4680
4684
|
tablePrefix: options.tablePrefix || "voltagent_memory",
|
|
4681
4685
|
debug: options.debug || false,
|
|
4682
4686
|
url: this.normalizeUrl(options.url),
|
|
4683
|
-
authToken: options.authToken
|
|
4687
|
+
authToken: options.authToken,
|
|
4688
|
+
retryAttempts: this.retryAttempts,
|
|
4689
|
+
baseDelayMs: this.baseDelayMs
|
|
4684
4690
|
};
|
|
4685
4691
|
this.client = (0, import_client.createClient)({
|
|
4686
4692
|
url: this.options.url,
|
|
@@ -4726,6 +4732,50 @@ var LibSQLStorage = class {
|
|
|
4726
4732
|
this.logger.debug(`${message}`, data || "");
|
|
4727
4733
|
}
|
|
4728
4734
|
}
|
|
4735
|
+
/**
|
|
4736
|
+
* Calculate delay with jitter for better load distribution
|
|
4737
|
+
* @param attempt Current retry attempt number
|
|
4738
|
+
* @returns Delay in milliseconds
|
|
4739
|
+
*/
|
|
4740
|
+
calculateRetryDelay(attempt) {
|
|
4741
|
+
const exponentialDelay = this.baseDelayMs * 2 ** (attempt - 1);
|
|
4742
|
+
const jitterFactor = 0.2 + Math.random() * 0.2;
|
|
4743
|
+
const delayWithJitter = exponentialDelay * (1 + jitterFactor);
|
|
4744
|
+
return Math.min(delayWithJitter, 2e3);
|
|
4745
|
+
}
|
|
4746
|
+
/**
|
|
4747
|
+
* Execute a database operation with retry strategy
|
|
4748
|
+
* Implements jittered exponential backoff
|
|
4749
|
+
* @param operationFn The operation function to execute
|
|
4750
|
+
* @param operationName Operation name for logging
|
|
4751
|
+
* @returns The result of the operation
|
|
4752
|
+
*/
|
|
4753
|
+
async executeWithRetryStrategy(operationFn, operationName) {
|
|
4754
|
+
let attempt = 0;
|
|
4755
|
+
while (attempt < this.retryAttempts) {
|
|
4756
|
+
attempt++;
|
|
4757
|
+
try {
|
|
4758
|
+
return await operationFn();
|
|
4759
|
+
} catch (error) {
|
|
4760
|
+
const isBusyError = error.message && (error.message.includes("SQLITE_BUSY") || error.message.includes("database is locked") || error.code === "SQLITE_BUSY");
|
|
4761
|
+
if (!isBusyError || attempt >= this.retryAttempts) {
|
|
4762
|
+
this.debug(`Operation failed: ${operationName}`, {
|
|
4763
|
+
attempt,
|
|
4764
|
+
error: error.message
|
|
4765
|
+
});
|
|
4766
|
+
throw error;
|
|
4767
|
+
}
|
|
4768
|
+
const delay = this.calculateRetryDelay(attempt);
|
|
4769
|
+
this.debug(`Retrying ${operationName}`, {
|
|
4770
|
+
attempt,
|
|
4771
|
+
remainingAttempts: this.retryAttempts - attempt,
|
|
4772
|
+
delay
|
|
4773
|
+
});
|
|
4774
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
4775
|
+
}
|
|
4776
|
+
}
|
|
4777
|
+
throw new Error(`Max retry attempts (${this.retryAttempts}) exceeded for ${operationName}`);
|
|
4778
|
+
}
|
|
4729
4779
|
/**
|
|
4730
4780
|
* Initialize workflow tables
|
|
4731
4781
|
*/
|
|
@@ -4744,6 +4794,20 @@ var LibSQLStorage = class {
|
|
|
4744
4794
|
* @returns Promise that resolves when initialization is complete
|
|
4745
4795
|
*/
|
|
4746
4796
|
async initializeDatabase() {
|
|
4797
|
+
if (this.options.url.startsWith("file:") || this.options.url.includes(":memory:")) {
|
|
4798
|
+
try {
|
|
4799
|
+
await this.client.execute("PRAGMA journal_mode=WAL;");
|
|
4800
|
+
this.debug("PRAGMA journal_mode=WAL set.");
|
|
4801
|
+
} catch (err) {
|
|
4802
|
+
this.debug("Failed to set PRAGMA journal_mode=WAL.", err);
|
|
4803
|
+
}
|
|
4804
|
+
try {
|
|
4805
|
+
await this.client.execute("PRAGMA busy_timeout = 5000;");
|
|
4806
|
+
this.debug("PRAGMA busy_timeout=5000 set.");
|
|
4807
|
+
} catch (err) {
|
|
4808
|
+
this.debug("Failed to set PRAGMA busy_timeout.", err);
|
|
4809
|
+
}
|
|
4810
|
+
}
|
|
4747
4811
|
const conversationsTableName = `${this.options.tablePrefix}_conversations`;
|
|
4748
4812
|
await this.client.execute(`
|
|
4749
4813
|
CREATE TABLE IF NOT EXISTS ${conversationsTableName} (
|
|
@@ -5015,7 +5079,7 @@ var LibSQLStorage = class {
|
|
|
5015
5079
|
await debugDelay();
|
|
5016
5080
|
const tableName = `${this.options.tablePrefix}_messages`;
|
|
5017
5081
|
const contentString = JSON.stringify(message.content);
|
|
5018
|
-
|
|
5082
|
+
await this.executeWithRetryStrategy(async () => {
|
|
5019
5083
|
await this.client.execute({
|
|
5020
5084
|
sql: `INSERT INTO ${tableName} (conversation_id, message_id, role, content, type, created_at)
|
|
5021
5085
|
VALUES (?, ?, ?, ?, ?, ?)`,
|
|
@@ -5034,10 +5098,7 @@ var LibSQLStorage = class {
|
|
|
5034
5098
|
} catch (pruneError) {
|
|
5035
5099
|
this.debug("Error pruning old messages:", pruneError);
|
|
5036
5100
|
}
|
|
5037
|
-
}
|
|
5038
|
-
this.debug("Error adding message:", error);
|
|
5039
|
-
throw new Error("Failed to add message to LibSQL database");
|
|
5040
|
-
}
|
|
5101
|
+
}, `addMessage[${message.id}]`);
|
|
5041
5102
|
}
|
|
5042
5103
|
/**
|
|
5043
5104
|
* Prune old messages to respect storage limit
|
|
@@ -5110,7 +5171,11 @@ var LibSQLStorage = class {
|
|
|
5110
5171
|
/**
|
|
5111
5172
|
* Close the database connection
|
|
5112
5173
|
*/
|
|
5113
|
-
close() {
|
|
5174
|
+
async close() {
|
|
5175
|
+
try {
|
|
5176
|
+
await this.initialized;
|
|
5177
|
+
} catch {
|
|
5178
|
+
}
|
|
5114
5179
|
this.client.close();
|
|
5115
5180
|
}
|
|
5116
5181
|
/**
|
|
@@ -5370,7 +5435,7 @@ var LibSQLStorage = class {
|
|
|
5370
5435
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5371
5436
|
const metadataString = JSON.stringify(conversation.metadata);
|
|
5372
5437
|
const tableName = `${this.options.tablePrefix}_conversations`;
|
|
5373
|
-
|
|
5438
|
+
return await this.executeWithRetryStrategy(async () => {
|
|
5374
5439
|
await this.client.execute({
|
|
5375
5440
|
sql: `INSERT INTO ${tableName} (id, resource_id, user_id, title, metadata, created_at, updated_at)
|
|
5376
5441
|
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
@@ -5393,10 +5458,7 @@ var LibSQLStorage = class {
|
|
|
5393
5458
|
createdAt: now,
|
|
5394
5459
|
updatedAt: now
|
|
5395
5460
|
};
|
|
5396
|
-
}
|
|
5397
|
-
this.debug("Error creating conversation:", error);
|
|
5398
|
-
throw new Error("Failed to create conversation in LibSQL database");
|
|
5399
|
-
}
|
|
5461
|
+
}, `createConversation[${conversation.id}]`);
|
|
5400
5462
|
}
|
|
5401
5463
|
async getConversation(id) {
|
|
5402
5464
|
await this.initialized;
|