@@ -126,6 +126,11 @@ function tryResolve(id: string): string | undefined {
126126const capacitorKeyboardEntry = tryResolve ( "@capacitor/keyboard" ) ;
127127const capacitorPreferencesEntry = tryResolve ( "@capacitor/preferences" ) ;
128128const capacitorAppEntry = tryResolve ( "@capacitor/app" ) ;
129+ const reactEntry = requireResolve ( "react" ) ;
130+ const reactJsxRuntimeEntry = requireResolve ( "react/jsx-runtime" ) ;
131+ const reactJsxDevRuntimeEntry = requireResolve ( "react/jsx-dev-runtime" ) ;
132+ const reactDomEntry = requireResolve ( "react-dom" ) ;
133+ const reactDomClientEntry = requireResolve ( "react-dom/client" ) ;
129134// `@elizaos/app-core` is always real. `@elizaos/app-wallet` is required by
130135// onboarding callbacks + AppContext (useWalletState), so resolve it real
131136// when present. `app-hyperscape` is real when its package is present.
@@ -241,6 +246,15 @@ function resolveLocalUiAliases(): Alias[] {
241246 find : / ^ @ e l i z a o s \/ u i $ / ,
242247 replacement : path . join ( uiPkgRoot , "src/index.ts" ) ,
243248 } ,
249+ {
250+ find : / ^ @ e l i z a o s \/ u i \/ a p i $ / ,
251+ replacement : path . join ( uiPkgRoot , "src/api/index.ts" ) ,
252+ } ,
253+ {
254+ find : / ^ @ e l i z a o s \/ u i \/ a p i \/ ( .* ) $ / ,
255+ replacement : `${ uiPkgRoot } /src/api/$1.ts` ,
256+ customResolver : resolveExistingUiSourceModule ,
257+ } ,
244258 {
245259 find : / ^ @ e l i z a o s \/ u i \/ c o m p o n e n t s \/ u i \/ ( .* ) $ / ,
246260 replacement : `${ uiPkgRoot } /src/components/ui/$1.tsx` ,
@@ -280,10 +294,20 @@ function resolveLocalUiAliases(): Alias[] {
280294 find : / ^ @ e l i z a o s \/ u i \/ l a y o u t s \/ ( .+ ) \/ ( [ ^ / ] + ) $ / ,
281295 replacement : `${ uiPkgRoot } /src/layouts/$1/$2.tsx` ,
282296 } ,
297+ {
298+ find : / ^ @ e l i z a o s \/ u i \/ p l a t f o r m \/ ( .* ) $ / ,
299+ replacement : `${ uiPkgRoot } /src/platform/$1.ts` ,
300+ customResolver : resolveExistingUiSourceModule ,
301+ } ,
283302 {
284303 find : / ^ @ e l i z a o s \/ u i \/ l i b \/ ( .* ) $ / ,
285304 replacement : `${ uiPkgRoot } /src/lib/$1.ts` ,
286305 } ,
306+ {
307+ find : / ^ @ e l i z a o s \/ u i \/ ( .+ ) $ / ,
308+ replacement : `${ uiPkgRoot } /src/$1` ,
309+ customResolver : resolveExistingUiSourceModule ,
310+ } ,
287311 ] ;
288312}
289313
@@ -353,16 +377,16 @@ function resolveLocalElizaAppAliases(): Alias[] {
353377 for ( const [ key , value ] of Object . entries ( pkg . exports || { } ) ) {
354378 const exportTarget = resolveExportTarget ( value ) ;
355379 if ( ! exportTarget ) continue ;
356- const resolvedTarget = path . resolve ( pkgDir , exportTarget ) ;
357- // Only create an alias when the target file actually exists on disk .
358- // In a fresh local clone, dist/ may not be built yet. Skipping the
359- // alias lets the import fall through to the stub or npm package .
360- if ( ! fs . existsSync ( resolvedTarget ) ) continue ;
380+ const runtimeTarget = resolveRuntimeTarget ( pkgDir , exportTarget ) ;
381+ // Prefer local source targets when the package export points at dist/ .
382+ // Fresh local clones often have src/ but no dist/ yet; checking dist
383+ // first lets imports fall through to stale npm/Bun-store packages .
384+ if ( ! fs . existsSync ( runtimeTarget ) ) continue ;
361385 const aliasKey =
362386 key === "." ? pkgName : `${ pkgName } /${ key . replace ( / ^ \. \/ / , "" ) } ` ;
363387 aliases . push ( {
364388 find : new RegExp ( `^${ escapeRegExp ( aliasKey ) } $` ) ,
365- replacement : resolveRuntimeTarget ( pkgDir , exportTarget ) ,
389+ replacement : runtimeTarget ,
366390 } ) ;
367391 }
368392
@@ -488,21 +512,21 @@ function resolveLocalAppCoreAliases(): Alias[] {
488512
489513 for ( const [ key , value ] of Object . entries ( appCorePkg . exports || { } ) ) {
490514 if ( key === "." ) continue ; // handled by the explicit bare alias above
491- if ( typeof value !== "string" ) continue ;
492- const aliasKey =
493- key === "."
494- ? "@elizaos/app-core"
495- : `@elizaos/app-core/${ key . replace ( / ^ \. \/ / , "" ) } ` ;
496-
497- // Resolve the string value, handling both plain strings and conditional exports.
498515 const resolvedValue : string | null =
499516 typeof value === "string"
500517 ? value
501518 : typeof value === "object" && value !== null
502- ? ( ( value as Record < string , string > ) . import ??
519+ ? ( ( value as Record < string , string > ) . source ??
520+ ( value as Record < string , string > ) . import ??
503521 ( value as Record < string , string > ) . default ??
504522 null )
505523 : null ;
524+ if ( ! resolvedValue ) continue ;
525+
526+ const aliasKey =
527+ key === "."
528+ ? "@elizaos/app-core"
529+ : `@elizaos/app-core/${ key . replace ( / ^ \. \/ / , "" ) } ` ;
506530
507531 // CSS files in app-core exports point to dist paths (e.g. ./styles/styles.css).
508532 // In Wave A these moved to @elizaos /ui. If the dist path doesn't exist locally,
@@ -549,6 +573,49 @@ function resolveLocalAppCoreAliases(): Alias[] {
549573
550574 const uiSource = path . join ( appCoreSrcRoot , "ui" ) ;
551575 const uiPkgSrcRoot = uiPkgRoot ? path . join ( uiPkgRoot , "src" ) : null ;
576+ // Wave A moved styles from @elizaos /app-core to @elizaos/ui. Keep an
577+ // explicit redirect ahead of the catch-all so local-source builds do not
578+ // resolve CSS requests to missing app-core source files.
579+ const uiStylesSourceDir = uiPkgRoot
580+ ? path . join ( uiPkgRoot , "src/styles" )
581+ : null ;
582+ const appCoreStylesLocalDir = path . join ( appCoreSrcRoot , "styles" ) ;
583+ const cssRedirectAlias : Alias [ ] =
584+ uiStylesSourceDir &&
585+ fs . existsSync ( path . join ( uiStylesSourceDir , "styles.css" ) ) &&
586+ ! fs . existsSync ( path . join ( appCoreStylesLocalDir , "styles.css" ) )
587+ ? [
588+ {
589+ find : / ^ @ e l i z a o s \/ a p p - c o r e \/ s t y l e s \/ ( .+ \. c s s ) $ / ,
590+ replacement : `${ uiStylesSourceDir } /$1` ,
591+ } ,
592+ ]
593+ : [ ] ;
594+ const uiComponentsSourceDir = uiPkgRoot ? path . join ( uiPkgRoot , "src" ) : null ;
595+
596+ function resolveAppCoreWithUiFallback ( id : string ) : string {
597+ if ( fs . existsSync ( id ) ) return id ;
598+ const withTsx = id . endsWith ( ".tsx" ) ? id : `${ id } .tsx` ;
599+ if ( fs . existsSync ( withTsx ) ) return withTsx ;
600+ const withTs = id . endsWith ( ".ts" ) ? id : `${ id } .ts` ;
601+ if ( fs . existsSync ( withTs ) ) return withTs ;
602+
603+ if ( uiComponentsSourceDir && id . startsWith ( `${ appCoreSrcRoot } ${ path . sep } ` ) ) {
604+ const relativeToAppCoreSrc = id . slice ( appCoreSrcRoot . length + 1 ) ;
605+ const uiEquivalent = path . join (
606+ uiComponentsSourceDir ,
607+ relativeToAppCoreSrc ,
608+ ) ;
609+ if ( fs . existsSync ( uiEquivalent ) ) return uiEquivalent ;
610+ const uiEquivalentTsx = `${ uiEquivalent } .tsx` ;
611+ if ( fs . existsSync ( uiEquivalentTsx ) ) return uiEquivalentTsx ;
612+ const uiEquivalentTs = `${ uiEquivalent } .ts` ;
613+ if ( fs . existsSync ( uiEquivalentTs ) ) return uiEquivalentTs ;
614+ }
615+
616+ return id ;
617+ }
618+
552619 const legacyAppCoreUiAliases : Alias [ ] = uiPkgSrcRoot
553620 ? [
554621 {
@@ -840,7 +907,7 @@ function resolveExistingUiSourceModule(id: string) {
840907 }
841908
842909 for ( const candidate of candidates ) {
843- if ( fs . existsSync ( candidate ) ) {
910+ if ( fs . existsSync ( candidate ) && fs . statSync ( candidate ) . isFile ( ) ) {
844911 return candidate ;
845912 }
846913 }
@@ -1310,7 +1377,7 @@ function generateNodeBuiltinStub(moduleId: string, req = _require): string {
13101377 // * mutation traps (set / defineProperty) don't throw under strict mode
13111378 // * `instanceof`, `default`, `__esModule` resolve sensibly for ESM<->CJS
13121379 "function noopFn() { return noop; }" ,
1313- "const handler = { get(t, p) { if (typeof p === 'symbol') return undefined; if ( p === '__esModule ') return true ; if (p === 'default ') return noop ; if (p === 'prototype ') return {} ; if (p in t) return t[p]; return noop; }, set(t, p, v) { try { t[p] = v; } catch {} return true; }, has() { return true; }, ownKeys() { return [] ; }, getOwnPropertyDescriptor() { return { configurable: true, enumerable: true }; }, apply() { return noop; }, construct() { return noop; }, defineProperty(t, p, d) { try { Object.defineProperty(t, p, { configurable: true, writable: true, enumerable: true, ...d }); } catch {} return true; } };" ,
1380+ "const handler = { get(t, p) { if (p === 'prototype' || p === 'name' || p === 'length' || typeof p === 'symbol ') return Reflect.get(t, p) ; if (p === '__esModule ') return true ; if (p === 'default ') return noop ; if (p in t) return t[p]; return noop; }, set(t, p, v) { try { t[p] = v; } catch {} return true; }, has() { return true; }, ownKeys(t ) { return Reflect.ownKeys(t) ; }, getOwnPropertyDescriptor(t, p ) { return Reflect.getOwnPropertyDescriptor(t, p) ?? { configurable: true, enumerable: true, writable: true, value: noop }; }, apply() { return noop; }, construct() { return noop; }, defineProperty(t, p, d) { try { Object.defineProperty(t, p, { configurable: true, writable: true, enumerable: true, ...d }); } catch {} return true; } };" ,
13141381 "const noop = new Proxy(noopFn, handler);" ,
13151382 "const stub = noop;" ,
13161383 "const asyncNoop = () => Promise.resolve();" ,
@@ -1754,6 +1821,7 @@ function generatePluginElizacloudStub(): string {
17541821// agent runtime modules. The renderer never enters those code paths; the
17551822// stub satisfies Rollup's static analysis and trees away at module init.
17561823const PLUGIN_LOCAL_INFERENCE_STUB_NAMES = [
1824+ "detectEmbeddingPreset" ,
17571825 "getLocalInferenceActiveModelId" ,
17581826 "getLocalInferenceActiveSnapshot" ,
17591827 "getLocalInferenceChatStatus" ,
@@ -1765,6 +1833,53 @@ function generatePluginLocalInferenceStub(): string {
17651833 return generateNamedExportStub ( PLUGIN_LOCAL_INFERENCE_STUB_NAMES ) ;
17661834}
17671835
1836+ function generatePluginAgentSkillsStub ( ) : string {
1837+ return generateNamedExportStub ( [
1838+ "discoverSkills" ,
1839+ "handleCuratedSkillsRoutes" ,
1840+ "handleSkillsRoutes" ,
1841+ ] ) ;
1842+ }
1843+
1844+ function generatePluginAppManagerStub ( ) : string {
1845+ return [
1846+ "const noop = () => undefined;" ,
1847+ "const asyncFalse = async () => false;" ,
1848+ "export class AppManager {}" ,
1849+ "export const handleAppsRoutes = asyncFalse;" ,
1850+ "export const readAppRunStore = () => [];" ,
1851+ "export const resolveAppRunStoreFilePath = () => '';" ,
1852+ "export const resolveLegacyAppRunStoreFilePath = () => '';" ,
1853+ "export const writeAppRunStore = noop;" ,
1854+ "export default new Proxy(noop, { get: () => noop, apply: () => undefined });" ,
1855+ ] . join ( "\n" ) ;
1856+ }
1857+
1858+ function generatePluginRegistryStub ( ) : string {
1859+ return [
1860+ "const noop = () => undefined;" ,
1861+ "const asyncFalse = async () => false;" ,
1862+ "const emptyPluginList = () => ({ plugins: [], categories: [], installed: [] });" ,
1863+ "export const buildPluginListResponse = emptyPluginList;" ,
1864+ "export const handlePluginRoutes = asyncFalse;" ,
1865+ "export const handlePluginsCompatRoutes = asyncFalse;" ,
1866+ "export const installAndRestart = noop;" ,
1867+ "export const installPlugin = noop;" ,
1868+ "export const listInstalledPlugins = () => [];" ,
1869+ "export const uninstallAndRestart = noop;" ,
1870+ "export const uninstallPlugin = noop;" ,
1871+ "export default new Proxy(noop, { get: () => noop, apply: () => undefined });" ,
1872+ ] . join ( "\n" ) ;
1873+ }
1874+
1875+ function generatePluginWalletStub ( ) : string {
1876+ return generateNamedExportStub ( [ "handleWalletRoutes" ] ) ;
1877+ }
1878+
1879+ function generatePluginX402Stub ( ) : string {
1880+ return generateNamedExportStub ( [ "validateX402Startup" ] ) ;
1881+ }
1882+
17681883function generateAgentPluginAutoEnableStub ( ) : string {
17691884 return [
17701885 "export const CONNECTOR_PLUGINS = {};" ,
@@ -1982,6 +2097,11 @@ const NATIVE_MODULE_STUB_GENERATORS = new Map<
19822097 [ "async_hooks" , generateAsyncHooksStub ] ,
19832098 [ "@elizaos/plugin-elizacloud" , generatePluginElizacloudStub ] ,
19842099 [ "@elizaos/plugin-local-inference" , generatePluginLocalInferenceStub ] ,
2100+ [ "@elizaos/plugin-agent-skills" , generatePluginAgentSkillsStub ] ,
2101+ [ "@elizaos/plugin-app-manager" , generatePluginAppManagerStub ] ,
2102+ [ "@elizaos/plugin-registry" , generatePluginRegistryStub ] ,
2103+ [ "@elizaos/plugin-wallet" , generatePluginWalletStub ] ,
2104+ [ "@elizaos/plugin-x402" , generatePluginX402Stub ] ,
19852105 [ "esbuild" , generateEsbuildStub ] ,
19862106 // @node -rs/argon2's server-side Rust binding is referenced by
19872107 // app-core's password-hashing helpers. Renderer never executes them
@@ -2091,6 +2211,7 @@ function nativeModuleStubPlugin(): Plugin {
20912211 "@elizaos/plugin-sql" ,
20922212 "@elizaos/plugin-agent-skills" ,
20932213 "@elizaos/plugin-agent-orchestrator" ,
2214+ "@elizaos/plugin-app-manager" ,
20942215 // The agent runtime is server-only — it lives in the API child
20952216 // process, not in the renderer. app-core/dist code can leak agent
20962217 // imports (account-pool etc.); stub them so Rollup doesn't try to
@@ -2100,6 +2221,11 @@ function nativeModuleStubPlugin(): Plugin {
21002221 // tts proxy routes). Renderer references the exported names but
21012222 // never executes the code; named-export stub registered above.
21022223 "@elizaos/plugin-elizacloud" ,
2224+ // Server-side plugin install/discovery routes. The renderer only needs
2225+ // static named exports to resolve when app-core server barrels leak in.
2226+ "@elizaos/plugin-registry" ,
2227+ "@elizaos/plugin-wallet" ,
2228+ "@elizaos/plugin-x402" ,
21032229 // @node -rs/argon2 has a wasm32-wasi variant that browser builds
21042230 // surface via dynamic import. The browser can't resolve the bare
21052231 // specifier at runtime; stub it so the bundle loads. Real hashing
@@ -2544,6 +2670,11 @@ export default defineConfig({
25442670 alias : [
25452671 // Bare Node built-in polyfills for browser — pathe provides ESM path,
25462672 // events is pre-bundled via optimizeDeps.
2673+ { find : / ^ r e a c t $ / , replacement : reactEntry } ,
2674+ { find : / ^ r e a c t \/ j s x - r u n t i m e $ / , replacement : reactJsxRuntimeEntry } ,
2675+ { find : / ^ r e a c t \/ j s x - d e v - r u n t i m e $ / , replacement : reactJsxDevRuntimeEntry } ,
2676+ { find : / ^ r e a c t - d o m $ / , replacement : reactDomEntry } ,
2677+ { find : / ^ r e a c t - d o m \/ c l i e n t $ / , replacement : reactDomClientEntry } ,
25472678 { find : / ^ p a t h $ / , replacement : patheEntry } ,
25482679 { find : / ^ @ c a p a c i t o r \/ c o r e $ / , replacement : capacitorCoreEntry } ,
25492680 // Aliases for Capacitor packages that may not be hoisted to root node_modules
0 commit comments