Files
fusion/packages/core/src/ai-engine-loader.ts
gsxdsm 69d9b67ca1 fix(dashboard,core,engine): statically import @fusion/engine to fix createFnAgent undefined in published CLI
The dashboard modules used a variable-specifier dynamic import
(`const m = "@fusion/engine"; await import(m)`) to defeat bundler static
analysis. tsup honored that and left the dynamic import in dist/bin.js,
so the published `@runfusion/fusion` package failed at runtime with
"createFnAgent2 is not a function" — `@fusion/engine` isn't on npm and
the silent catch set the binding to undefined. Replaces the trick with
static imports across planning, chat, subtask-breakdown, mission-interview,
agent-generation, ai-refine, roadmap-suggestions, milestone-slice-interview,
and routes. Core can't statically import engine (cycle), so it now exposes
setCreateFnAgent and engine wires itself in at module load. Documents the
pattern in AGENTS.md.

Fixes Runfusion/Fusion#9.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 14:43:03 -07:00

41 lines
1.4 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.
*/
// 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;
/** 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;
}