mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 08:50:15 +01:00
🧵 feat: Implement Request Executor Pattern for Actions (#4566)
* chore: actions typing * fix(actions): implement request executor pattern to prevent concurrent execution issues BREAKING CHANGE: ActionRequest now uses a RequestExecutor pattern for isolated request state - Introduce RequestConfig class to store immutable configuration - Add RequestExecutor class to handle isolated request state for each execution - Modify ActionRequest to act as a facade creating new executors for each operation - Maintain backward compatibility through delegation and getters - Add TypeScript types for better type safety - Fix race conditions in concurrent executions with auth and params This change prevents state mutation issues when the same action is called multiple times concurrently, particularly when using authentication. Each request now gets its own isolated state through a new executor instance, solving race conditions while maintaining the existing API interface. * ci: test isolation/immutatability * chore: Update version to 0.7.51 in data-provider package * refactor(actions): refactor createActionTool to use request executor pattern
This commit is contained in:
parent
262176fec4
commit
1526b429c9
5 changed files with 414 additions and 74 deletions
|
|
@ -119,18 +119,24 @@ async function loadActionSets(searchParams) {
|
|||
* @param {string | undefined} [params.name] - The name of the tool.
|
||||
* @param {string | undefined} [params.description] - The description for the tool.
|
||||
* @param {import('zod').ZodTypeAny | undefined} [params.zodSchema] - The Zod schema for tool input validation/definition
|
||||
* @returns { Promsie<typeof tool | { _call: (toolInput: Object | string) => unknown}> } An object with `_call` method to execute the tool input.
|
||||
* @returns { Promise<typeof tool | { _call: (toolInput: Object | string) => unknown}> } An object with `_call` method to execute the tool input.
|
||||
*/
|
||||
async function createActionTool({ action, requestBuilder, zodSchema, name, description }) {
|
||||
action.metadata = await decryptMetadata(action.metadata);
|
||||
/** @type {(toolInput: Object | string) => Promise<unknown>} */
|
||||
const _call = async (toolInput) => {
|
||||
try {
|
||||
requestBuilder.setParams(toolInput);
|
||||
const executor = requestBuilder.createExecutor();
|
||||
|
||||
// Chain the operations
|
||||
const preparedExecutor = executor.setParams(toolInput);
|
||||
|
||||
if (action.metadata.auth && action.metadata.auth.type !== AuthTypeEnum.None) {
|
||||
await requestBuilder.setAuth(action.metadata);
|
||||
await preparedExecutor.setAuth(action.metadata);
|
||||
}
|
||||
const res = await requestBuilder.execute();
|
||||
|
||||
const res = await preparedExecutor.execute();
|
||||
|
||||
if (typeof res.data === 'object') {
|
||||
return JSON.stringify(res.data);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue