@mastra/core
Version:
110 lines • 5.45 kB
TypeScript
/**
* Shared helpers for the `streamUntilIdle` wrapper pattern used by both
* the regular `Agent` and `DurableAgent`. Extracted to avoid duplicating
* the state-machine, idle-timer, continuation-loop, and bg-task-event
* plumbing across two files.
*
* The main entry point is `runIdleLoop`, a generic function that drives
* the full idle-wrapper lifecycle. Callers provide:
* - A `firstTurn` callback to run the initial stream/resume
* - A `buildResult` callback to construct the caller-specific return value
* - Optional `postPipeInner` hooks for durable-specific cleanup/abort tracking
*/
import type { BackgroundTaskManager } from '../../background-tasks/manager.js';
import type { MastraMemory } from '../../memory/memory.js';
export declare const TERMINAL_BG_CHUNKS: Set<string>;
export interface ResolvedScope {
threadId: string | undefined;
resourceId: string | undefined;
scopeKey: string | null;
}
/**
* Resolve memory / thread / resource for this call, matching `#execute`
* semantics (RequestContext-scoped keys override caller-supplied memory
* args). Returns `null` when no memory backend is configured — caller
* falls through to a plain stream in that case.
*/
export declare function resolveScope(agent: {
getMemory: (opts?: any) => Promise<MastraMemory | undefined>;
}, mergedOptions: Record<string, any>): Promise<ResolvedScope | null>;
/**
* Build the ephemeral user-prompt text that tells the LLM which tool-call
* IDs just completed / failed / canceled. The directive stops the LLM from (a) re-processing
* results already handled on a prior continuation and (b) mimicking the
* prior assistant ack text ("I'm running it in the background") and
* re-dispatching the same tool.
*/
export declare function buildContinuationDirective(batch: Array<Record<string, unknown>>): string;
/**
* Wrap the continuation directive into a stream-options object suitable for
* a recursive `agent.stream([], ...)` call. `context` messages are visible
* to the LLM but NOT persisted to memory, so the directive doesn't pollute
* future turns.
*/
export declare function buildContinuationOpts(baseContinuationOpts: Record<string, any>, callerContext: any[] | undefined, batch: Array<Record<string, unknown>>): Record<string, any>;
/**
* Register `closer` as the active wrapper for `scopeKey`, aborting any
* prior registered closer first. No-op for null scopes.
*/
export declare function acquireStreamSlot(activeStreams: Map<string, () => void>, scopeKey: string | null, closer: () => void): void;
/**
* Remove `closer` from the active streams map iff it's still the entry for
* `scopeKey`. A later call that took over (and replaced the entry) will not
* get accidentally unregistered.
*/
export declare function releaseStreamSlot(activeStreams: Map<string, () => void>, scopeKey: string | null, closer: () => void): void;
export interface IdleLoopDeps {
activeStreams: Map<string, () => void>;
bgManager: BackgroundTaskManager | undefined;
}
/**
* Called after each inner stream result (first turn + continuations).
* Durable agents use this to track cleanup/abort handles.
*/
export interface PostPipeHooks {
/** Called with each inner result after `firstTurn` or continuation. */
onInnerResult?: (inner: any) => void;
/** Extra teardown to run inside `forceClose`. */
onForceClose?: () => void;
}
/**
* Everything the `buildResult` callback needs to construct the
* caller-specific return type.
*/
export interface IdleLoopContext {
combinedStream: ReadableStream<any>;
forceClose: () => void;
threadId: string | undefined;
resourceId: string | undefined;
}
/**
* Generic idle-loop wrapper. Drives the full lifecycle:
* 1. Merge options + resolve scope (early-return if no bgManager / no memory)
* 2. Acquire stream slot
* 3. Run first turn via `firstTurn(opts)`
* 4. Subscribe to `bgManager.stream()` for bg-task events
* 5. On terminal bg events, queue and process continuations via `streamForContinuation`
* 6. Idle timer fires `forceClose` if nothing happens for `maxIdleMs`
*
* @param agent Must expose `.id`, `.getDefaultOptions(...)`, `.getMemory(...)`.
* @param streamOptions Caller-supplied stream options (may include `maxIdleMs`).
* @param deps `{ activeStreams, bgManager }`.
* @param firstTurn Callback for the initial turn. Returns the first result.
* @param streamForContinuation Callback to create a continuation stream.
* Returns an inner result (any shape); the `.fullStream` field is piped.
* @param buildResult Callback to construct the final return value from the
* first-turn result + idle-loop context.
* @param hooks Optional durable-specific hooks for cleanup/abort tracking.
*/
export declare function runIdleLoop<TAgent extends {
id: string;
getDefaultOptions: (opts?: any) => any | Promise<any>;
getMemory: (opts?: any) => Promise<MastraMemory | undefined>;
}, TFirstResult extends {
fullStream: any;
}, TReturn>(agent: TAgent, streamOptions: (Record<string, any> & {
maxIdleMs?: number;
}) | undefined, deps: IdleLoopDeps, firstTurn: (opts: Record<string, any>) => Promise<TFirstResult>, streamForContinuation: (opts: Record<string, any>) => Promise<{
fullStream: ReadableStream<any>;
}>, buildResult: (first: TFirstResult, ctx: IdleLoopContext) => TReturn, hooks?: PostPipeHooks): Promise<TReturn>;
//# sourceMappingURL=stream-until-idle-helpers.d.ts.map