@@ -9,7 +9,6 @@ import { useCharacterOrchestratorStore } from '@proj-airi/stage-ui/stores/charac
99import { useChatSessionStore } from ' @proj-airi/stage-ui/stores/chat/session-store'
1010import { usePluginHostInspectorStore } from ' @proj-airi/stage-ui/stores/devtools/plugin-host-debug'
1111import { useDisplayModelsStore } from ' @proj-airi/stage-ui/stores/display-models'
12- import { clearMcpToolBridge , setMcpToolBridge } from ' @proj-airi/stage-ui/stores/mcp-tool-bridge'
1312import { useModsServerChannelStore } from ' @proj-airi/stage-ui/stores/mods/api/channel-server'
1413import { useContextBridgeStore } from ' @proj-airi/stage-ui/stores/mods/api/context-bridge'
1514import { useAiriCardStore } from ' @proj-airi/stage-ui/stores/modules/airi-card'
@@ -27,12 +26,11 @@ import ResizeHandler from './components/ResizeHandler.vue'
2726
2827import {
2928 electronGetServerChannelConfig ,
30- electronMcpCallTool ,
31- electronMcpListTools ,
3229 electronPluginInspect ,
3330 electronPluginList ,
3431 electronPluginLoad ,
3532 electronPluginLoadEnabled ,
33+ electronPluginSetAutoReload ,
3634 electronPluginSetEnabled ,
3735 electronPluginUnload ,
3836 electronPluginUpdateCapability ,
@@ -44,6 +42,8 @@ import {
4442} from ' ../shared/eventa'
4543import { initializeElectronAuthCallbackBridge } from ' ./bridges/electron-auth-callback'
4644import { initializeStageThreeRuntimeTraceBridge } from ' ./bridges/stage-three-runtime-trace'
45+ import { useTamagotchiMcpToolsStore } from ' ./stores/mcp-tools'
46+ import { useTamagotchiPluginToolsStore } from ' ./stores/plugin-tools'
4747import { useServerChannelSettingsStore } from ' ./stores/settings/server-channel'
4848import { useStageWindowLifecycleStore } from ' ./stores/stage-window-lifecycle'
4949
@@ -63,6 +63,8 @@ const characterOrchestratorStore = useCharacterOrchestratorStore()
6363const analyticsStore = useSharedAnalyticsStore ()
6464const inferencePreload = useInferencePreload ()
6565const pluginHostInspectorStore = usePluginHostInspectorStore ()
66+ const mcpToolsStore = useTamagotchiMcpToolsStore ()
67+ const pluginToolsStore = useTamagotchiPluginToolsStore ()
6668const stageWindowLifecycleStore = useStageWindowLifecycleStore ()
6769const settingsAudioDeviceStore = useSettingsAudioDevice ()
6870const context = useElectronEventaContext ()
@@ -73,33 +75,63 @@ void stageWindowLifecycleStore.initializeWindowLifecycleBridge()
7375const getServerChannelConfig = useElectronEventaInvoke (electronGetServerChannelConfig )
7476const listPlugins = useElectronEventaInvoke (electronPluginList )
7577const setPluginEnabled = useElectronEventaInvoke (electronPluginSetEnabled )
78+ const setPluginAutoReload = useElectronEventaInvoke (electronPluginSetAutoReload )
7679const loadEnabledPlugins = useElectronEventaInvoke (electronPluginLoadEnabled )
7780const loadPlugin = useElectronEventaInvoke (electronPluginLoad )
7881const unloadPlugin = useElectronEventaInvoke (electronPluginUnload )
7982const inspectPluginHost = useElectronEventaInvoke (electronPluginInspect )
8083const startTrackingCursorPoint = useElectronEventaInvoke (electronStartTrackMousePosition )
8184const reportPluginCapability = useElectronEventaInvoke (electronPluginUpdateCapability )
82- const listMcpTools = useElectronEventaInvoke (electronMcpListTools )
83- const callMcpTool = useElectronEventaInvoke (electronMcpCallTool )
8485const setLocale = useElectronEventaInvoke (i18nSetLocale )
8586const isChatWindowRoute = () => route .path === ' /chat'
87+ const isWidgetsWindowRoute = () => route .path === ' /widgets'
88+
89+ async function refreshPluginRuntimeTools() {
90+ try {
91+ await pluginToolsStore .refresh ()
92+ }
93+ catch (error ) {
94+ console .warn (' [App] Failed to refresh plugin runtime tools:' , error )
95+ }
96+ }
97+
98+ watch (() => route .path , () => {
99+ contextBridgeStore .setSparkNotifyHostRole (isWidgetsWindowRoute () ? ' client' : ' main' )
100+ }, { immediate: true })
86101
87102// NOTICE: register plugin host bridge during setup to avoid race with pages using it in immediate watchers.
88103pluginHostInspectorStore .setBridge ({
89104 list : () => listPlugins (),
90- setEnabled : payload => setPluginEnabled (payload ),
91- loadEnabled : () => loadEnabledPlugins (),
92- load : payload => loadPlugin (payload ),
93- unload : payload => unloadPlugin (payload ),
105+ setEnabled : async (payload ) => {
106+ const result = await setPluginEnabled (payload )
107+ await refreshPluginRuntimeTools ()
108+ return result
109+ },
110+ setAutoReload : payload => setPluginAutoReload (payload ),
111+ loadEnabled : async () => {
112+ const result = await loadEnabledPlugins ()
113+ await refreshPluginRuntimeTools ()
114+ return result
115+ },
116+ load : async (payload ) => {
117+ const result = await loadPlugin (payload )
118+ await refreshPluginRuntimeTools ()
119+ return result
120+ },
121+ unload : async (payload ) => {
122+ const result = await unloadPlugin (payload )
123+ await refreshPluginRuntimeTools ()
124+ return result
125+ },
94126 inspect : () => inspectPluginHost (),
95127})
96128
97- // NOTICE: MCP tools are declared from stage-ui and executed during model streaming.
98- // Register runtime bridge during setup to avoid missing bridge in early tool invocations.
99- setMcpToolBridge ({
100- listTools : () => listMcpTools (),
101- callTool : payload => callMcpTool (payload ),
129+ // NOTICE: Runtime tool stores must register during setup so renderer consumers can see them
130+ // before `onMounted()` finishes the rest of the startup flow.
131+ void mcpToolsStore .refresh ().catch ((error ) => {
132+ console .warn (' [App] Failed to refresh MCP runtime tools:' , error )
102133})
134+ void refreshPluginRuntimeTools ()
103135
104136watch (language , () => {
105137 i18n .locale .value = language .value
@@ -143,8 +175,10 @@ onMounted(async () => {
143175 }).catch (err => console .error (' Failed to initialize Mods Server Channel in App.vue:' , err ))
144176 if (! isChatWindowRoute ()) {
145177 contextBridgeStore .initialize ()
146- characterOrchestratorStore .initialize ()
147- await startTrackingCursorPoint ()
178+ if (! isWidgetsWindowRoute ()) {
179+ characterOrchestratorStore .initialize ()
180+ await startTrackingCursorPoint ()
181+ }
148182 }
149183
150184 // Expose stage provider definitions to plugin host APIs.
@@ -176,7 +210,8 @@ onUnmounted(() => {
176210 if (! isChatWindowRoute ()) {
177211 contextBridgeStore .dispose ()
178212 }
179- clearMcpToolBridge ()
213+ mcpToolsStore .dispose ()
214+ pluginToolsStore .dispose ()
180215})
181216 </script >
182217
0 commit comments