diff --git a/apps/ui-server-auth/tsconfig.json b/apps/ui-server-auth/tsconfig.json
index 9f7359641..06fe74adc 100644
--- a/apps/ui-server-auth/tsconfig.json
+++ b/apps/ui-server-auth/tsconfig.json
@@ -8,6 +8,7 @@
"DOM.Iterable",
"DOM.AsyncIterable"
],
+ "useDefineForClassFields": true,
"paths": {
"@proj-airi/stage-ui/*": [
"../../packages/stage-ui/src/*"
diff --git a/packages/stage-pages/src/pages/devtools/plugin-host.vue b/packages/stage-pages/src/pages/devtools/plugin-host.vue
index 7e8d4fe4e..ac5f00d0c 100644
--- a/packages/stage-pages/src/pages/devtools/plugin-host.vue
+++ b/packages/stage-pages/src/pages/devtools/plugin-host.vue
@@ -106,6 +106,18 @@ async function loadEnabled() {
}
}
+async function setAutoReload(plugin: PluginManifestSummary, enabled: boolean) {
+ try {
+ await store.setAutoReload({
+ name: plugin.name,
+ enabled,
+ })
+ }
+ catch (error) {
+ toast.error(error instanceof Error ? error.message : `Failed to update auto-reload state for ${plugin.name}.`)
+ }
+}
+
async function setEnabled(plugin: PluginManifestSummary, enabled: boolean) {
try {
await store.setEnabled({
@@ -173,7 +185,7 @@ onMounted(async () => {
:description="store.error"
/>
-
+
Discovered
@@ -206,6 +218,14 @@ onMounted(async () => {
{{ readyCapabilitiesCount }} / {{ store.capabilities.length }}
+
+
+ Kits
+
+
+ {{ store.kits.length }}
+
+
@@ -272,6 +292,9 @@ onMounted(async () => {
{{ plugin.enabled ? 'enabled' : 'disabled' }}
+
+ {{ plugin.autoReload ? 'auto reload on' : 'auto reload off' }}
+
{{ plugin.loaded ? 'loaded' : 'not loaded' }}
@@ -280,6 +303,14 @@ onMounted(async () => {
+
+
+
+ No kits registered.
+
+
+
+
+ {{ kit.kitId }}
+
+ v{{ kit.version }}
+
+
+
+ runtimes: {{ kit.runtimes.join(', ') || '-' }}
+
+
{{ JSON.stringify(kit.capabilities, null, 2) }}
+
+
+
+
path: string
enabled: boolean
+ autoReload: boolean
loaded: boolean
isNew: boolean
}
@@ -32,9 +33,36 @@ export interface PluginHostSessionSummary {
moduleId: string
}
+export interface PluginHostKitCapabilitySummary {
+ key: string
+ actions: string[]
+}
+
+export interface PluginHostKitSummary {
+ kitId: string
+ version: string
+ capabilities: PluginHostKitCapabilitySummary[]
+ runtimes: Array<'electron' | 'node' | 'web'>
+}
+
+export interface PluginHostModuleSummary {
+ moduleId: string
+ ownerSessionId: string
+ ownerPluginId: string
+ kitId: string
+ kitModuleType: string
+ state: 'announced' | 'active' | 'degraded' | 'withdrawn'
+ runtime: 'electron' | 'node' | 'web'
+ revision: number
+ updatedAt: number
+ config: Record
+}
+
export interface PluginHostDebugSnapshot {
registry: PluginRegistrySnapshot
sessions: PluginHostSessionSummary[]
+ kits: PluginHostKitSummary[]
+ modules: PluginHostModuleSummary[]
capabilities: PluginCapabilityState[]
refreshedAt: number
}
@@ -42,6 +70,7 @@ export interface PluginHostDebugSnapshot {
interface PluginHostDebugBridge {
list: () => Promise
setEnabled: (payload: { name: string, enabled: boolean, path?: string }) => Promise
+ setAutoReload: (payload: { name: string, enabled: boolean }) => Promise
loadEnabled: () => Promise
load: (payload: { name: string }) => Promise
unload: (payload: { name: string }) => Promise
@@ -60,6 +89,7 @@ export const usePluginHostInspectorStore = defineStore('devtools:plugin-host-deb
const bridge = ref()
const registry = ref()
const sessions = ref([])
+ const kits = ref([])
const capabilities = ref([])
const refreshedAt = ref()
const error = ref()
@@ -87,6 +117,7 @@ export const usePluginHostInspectorStore = defineStore('devtools:plugin-host-deb
function assignInspection(snapshot: PluginHostDebugSnapshot) {
assignRegistry(snapshot.registry)
sessions.value = snapshot.sessions
+ kits.value = snapshot.kits
capabilities.value = snapshot.capabilities
refreshedAt.value = snapshot.refreshedAt
}
@@ -146,6 +177,13 @@ export const usePluginHostInspectorStore = defineStore('devtools:plugin-host-deb
return nextRegistry
}
+ async function setAutoReload(payload: { name: string, enabled: boolean }) {
+ const nextRegistry = await withBridge(activeBridge => activeBridge.setAutoReload(payload))
+ assignRegistry(nextRegistry)
+ await refreshInspection()
+ return nextRegistry
+ }
+
async function loadEnabled() {
const nextRegistry = await withBridge(activeBridge => activeBridge.loadEnabled())
assignRegistry(nextRegistry)
@@ -170,6 +208,7 @@ export const usePluginHostInspectorStore = defineStore('devtools:plugin-host-deb
return {
registry,
sessions,
+ kits,
capabilities,
refreshedAt,
loading,
@@ -185,6 +224,7 @@ export const usePluginHostInspectorStore = defineStore('devtools:plugin-host-deb
refreshInspection,
refreshAll,
setEnabled,
+ setAutoReload,
loadEnabled,
load,
unload,
diff --git a/packages/stage-ui/src/stores/mods/api/context-bridge.ts b/packages/stage-ui/src/stores/mods/api/context-bridge.ts
index 264c6ec54..e318bd43f 100644
--- a/packages/stage-ui/src/stores/mods/api/context-bridge.ts
+++ b/packages/stage-ui/src/stores/mods/api/context-bridge.ts
@@ -55,11 +55,16 @@ export const useContextBridgeStore = defineStore('mods:api:context-bridge', () =
const { post: broadcastContext, data: incomingContext } = useBroadcastChannel({ name: CONTEXT_CHANNEL_NAME })
const { post: broadcastStreamEvent, data: incomingStreamEvent } = useBroadcastChannel({ name: CHAT_STREAM_CHANNEL_NAME })
+ const sparkNotifyHostRole = ref<'main' | 'client'>('client')
const disposeHookFns = ref void>>([])
let remoteStreamGuard: { sessionId: string, generation: number } | null = null
let initialized = false
+ function setSparkNotifyHostRole(role: 'main' | 'client') {
+ sparkNotifyHostRole.value = role
+ }
+
async function initialize() {
await mutex.acquire()
@@ -525,5 +530,6 @@ export const useContextBridgeStore = defineStore('mods:api:context-bridge', () =
return {
initialize,
dispose,
+ setSparkNotifyHostRole,
}
})