Files
fusion/packages/core/src/ai-engine-loader.ts
gsxdsm 4dbd72d54f feat(core,engine): add interactive AI session seam for plugin routes (U4)
Expose createInteractiveAiSession on route/loader PluginContext alongside the
one-shot createAiSession. The prompt->parse->retry->pause->resume loop is
reimplemented in an engine seam modeled on planning.ts (no engine await-input
primitive exists). Reuses PlanningQuestion/PlanningResponse; stays generic with
no plugin-specific concepts. Injected on route contexts only; tool/runtime
contexts omit it (parity with createAiSession).
2026-06-02 18:46:33 -07:00

81 lines
2.8 KiB
TypeScript

/**
* Shared lazy accessor for `@fusion/engine`'s `createFnAgent`.
*
* Core can't import engine statically (engine depends on core, so a static
* import would create a cycle). Instead, engine wires its `createFnAgent` in
* via `setCreateFnAgent` when its module loads, and consumers in core read it
* back through `getFnAgent`.
*
* If engine never loads (e.g. tests that only import core), `getFnAgent`
* returns `undefined` and callers degrade gracefully.
*/
import type { CreateAiSessionFactory, CreateInteractiveAiSessionFactory } from "./plugin-types.js";
// Engine exports a function type we intentionally don't pull in here — importing
// the type would reintroduce the cycle this module is designed to avoid.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type CreateFnAgent = any;
let createFnAgent: CreateFnAgent | undefined;
let createAiSessionFactory: CreateAiSessionFactory | undefined;
let createInteractiveAiSessionFactory: CreateInteractiveAiSessionFactory | undefined;
/** Shape of a message in an agent session's state. */
export interface AgentMessage {
role: string;
content?: string | Array<{ type: string; text: string }>;
}
/**
* Wire engine's `createFnAgent` into core. Called by `@fusion/engine` at module
* load. Tests can also call this with a stub.
*/
export function setCreateFnAgent(fn: CreateFnAgent | undefined): void {
createFnAgent = fn;
}
/**
* Returns `createFnAgent` from `@fusion/engine`, or `undefined` if engine has
* not registered itself yet (typical in tests).
*/
export async function getFnAgent(): Promise<CreateFnAgent> {
return createFnAgent;
}
/**
* Wire engine's plugin-facing AI session factory into core.
* Called by `@fusion/engine` at module load; tests may register stubs.
*/
export function setCreateAiSessionFactory(fn: CreateAiSessionFactory | undefined): void {
createAiSessionFactory = fn;
}
/**
* Returns engine-registered plugin AI session factory, or `undefined` when
* engine hasn't registered it (common in isolated core tests).
*/
export async function getCreateAiSessionFactory(): Promise<CreateAiSessionFactory | undefined> {
return createAiSessionFactory;
}
/**
* Wire engine's plugin-facing interactive AI session factory into core.
* Called by `@fusion/engine` at module load; tests may register stubs.
*/
export function setCreateInteractiveAiSessionFactory(
fn: CreateInteractiveAiSessionFactory | undefined,
): void {
createInteractiveAiSessionFactory = fn;
}
/**
* Returns engine-registered plugin interactive AI session factory, or
* `undefined` when engine hasn't registered it (common in isolated core tests).
*/
export async function getCreateInteractiveAiSessionFactory(): Promise<
CreateInteractiveAiSessionFactory | undefined
> {
return createInteractiveAiSessionFactory;
}