mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-22 19:30:15 +01:00
⚙️ refactor: OAuth Flow Signal, Type Safety, Tool Progress & Updated Packages (#6752)
* chore: bump @librechat/agents and related packages * refactor: update message state for tool calls run step, in case no tool call chunks are received * fix: avoid combining finalized args createContentAggregator for tool calls * chore: bump @librechat/agents to version 2.3.99 * feat: add support for aborting flows with AbortSignal in createFlow methods * fix: improve handling of tool call arguments in useStepHandler * chore: bump @librechat/agents to version 2.4.0 * fix: update flow identifier format for OAuth login in createActionTool to allow uniqueness per run * fix: improve error message handling for aborted flows in FlowStateManager * refactor: allow possible multi-agent cross-over for oauth login * fix: add type safety for Sandpack files in ArtifactCodeEditor
This commit is contained in:
parent
ac35b8490c
commit
9b0678da16
6 changed files with 953 additions and 981 deletions
|
|
@ -55,13 +55,18 @@ export class FlowStateManager<T = unknown> {
|
|||
/**
|
||||
* Creates a new flow and waits for its completion
|
||||
*/
|
||||
async createFlow(flowId: string, type: string, metadata: FlowMetadata = {}): Promise<T> {
|
||||
async createFlow(
|
||||
flowId: string,
|
||||
type: string,
|
||||
metadata: FlowMetadata = {},
|
||||
signal?: AbortSignal,
|
||||
): Promise<T> {
|
||||
const flowKey = this.getFlowKey(flowId, type);
|
||||
|
||||
let existingState = (await this.keyv.get(flowKey)) as FlowState<T> | undefined;
|
||||
if (existingState) {
|
||||
this.logger.debug(`[${flowKey}] Flow already exists`);
|
||||
return this.monitorFlow(flowKey, type);
|
||||
return this.monitorFlow(flowKey, type, signal);
|
||||
}
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 250));
|
||||
|
|
@ -69,7 +74,7 @@ export class FlowStateManager<T = unknown> {
|
|||
existingState = (await this.keyv.get(flowKey)) as FlowState<T> | undefined;
|
||||
if (existingState) {
|
||||
this.logger.debug(`[${flowKey}] Flow exists on 2nd check`);
|
||||
return this.monitorFlow(flowKey, type);
|
||||
return this.monitorFlow(flowKey, type, signal);
|
||||
}
|
||||
|
||||
const initialState: FlowState = {
|
||||
|
|
@ -81,10 +86,10 @@ export class FlowStateManager<T = unknown> {
|
|||
|
||||
this.logger.debug('Creating initial flow state:', flowKey);
|
||||
await this.keyv.set(flowKey, initialState, this.ttl);
|
||||
return this.monitorFlow(flowKey, type);
|
||||
return this.monitorFlow(flowKey, type, signal);
|
||||
}
|
||||
|
||||
private monitorFlow(flowKey: string, type: string): Promise<T> {
|
||||
private monitorFlow(flowKey: string, type: string, signal?: AbortSignal): Promise<T> {
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
const checkInterval = 2000;
|
||||
let elapsedTime = 0;
|
||||
|
|
@ -101,6 +106,16 @@ export class FlowStateManager<T = unknown> {
|
|||
return;
|
||||
}
|
||||
|
||||
if (signal?.aborted) {
|
||||
clearInterval(intervalId);
|
||||
this.intervals.delete(intervalId);
|
||||
this.logger.warn(`[${flowKey}] Flow aborted`);
|
||||
const message = `${type} flow aborted`;
|
||||
await this.keyv.delete(flowKey);
|
||||
reject(new Error(message));
|
||||
return;
|
||||
}
|
||||
|
||||
if (flowState.status !== 'PENDING') {
|
||||
clearInterval(intervalId);
|
||||
this.intervals.delete(intervalId);
|
||||
|
|
@ -197,19 +212,19 @@ export class FlowStateManager<T = unknown> {
|
|||
* @param flowId - The ID of the flow
|
||||
* @param type - The type of flow
|
||||
* @param handler - Async function to execute if no existing flow is found
|
||||
* @param metadata - Optional metadata for the flow
|
||||
* @param signal - Optional AbortSignal to cancel the flow
|
||||
*/
|
||||
async createFlowWithHandler(
|
||||
flowId: string,
|
||||
type: string,
|
||||
handler: () => Promise<T>,
|
||||
metadata: FlowMetadata = {},
|
||||
signal?: AbortSignal,
|
||||
): Promise<T> {
|
||||
const flowKey = this.getFlowKey(flowId, type);
|
||||
let existingState = (await this.keyv.get(flowKey)) as FlowState<T> | undefined;
|
||||
if (existingState) {
|
||||
this.logger.debug(`[${flowKey}] Flow already exists`);
|
||||
return this.monitorFlow(flowKey, type);
|
||||
return this.monitorFlow(flowKey, type, signal);
|
||||
}
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 250));
|
||||
|
|
@ -217,13 +232,13 @@ export class FlowStateManager<T = unknown> {
|
|||
existingState = (await this.keyv.get(flowKey)) as FlowState<T> | undefined;
|
||||
if (existingState) {
|
||||
this.logger.debug(`[${flowKey}] Flow exists on 2nd check`);
|
||||
return this.monitorFlow(flowKey, type);
|
||||
return this.monitorFlow(flowKey, type, signal);
|
||||
}
|
||||
|
||||
const initialState: FlowState = {
|
||||
type,
|
||||
status: 'PENDING',
|
||||
metadata,
|
||||
metadata: {},
|
||||
createdAt: Date.now(),
|
||||
};
|
||||
this.logger.debug(`[${flowKey}] Creating initial flow state`);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue