dashboard(cli): reset plugin state to installed before autoload
PluginStore.updatePluginState rejects same-state transitions, so the autoload at startup error'd with "Invalid state transition from started to started" for every plugin whose persisted state was "started" from a previous container generation. The new process has no in-memory instance yet, so the right thing is to flip the persisted state back to "installed" before loadAllPlugins() walks the registry; loadPlugin() then drives the state machine forward to "started" cleanly. This unblocks the plugin route mount for telemetry-watcher.
This commit is contained in:
@@ -1394,7 +1394,24 @@ export async function runDashboard(port: number, opts: { paused?: boolean; dev?:
|
||||
// can't be added after listen(). Loading them up-front is the cheap
|
||||
// path that mirrors how runtime-providing plugins (paperclip etc.)
|
||||
// expect to be available immediately.
|
||||
//
|
||||
// Reset persisted state for enabled plugins back to "installed" before
|
||||
// loadAllPlugins runs. PluginStore.updatePluginState rejects no-op
|
||||
// transitions ("started" → "started"), and the persisted state from
|
||||
// the previous container generation is "started" for any plugin that
|
||||
// had been enabled — without this reset, autoload errors on every
|
||||
// restart for already-enabled plugins.
|
||||
try {
|
||||
const persisted = await pluginStore.listPlugins();
|
||||
for (const p of persisted) {
|
||||
if (p.enabled && p.state === "started") {
|
||||
try {
|
||||
await pluginStore.updatePluginState(p.id, "installed");
|
||||
} catch {
|
||||
// Best effort — loader will surface the real failure if any.
|
||||
}
|
||||
}
|
||||
}
|
||||
const result = await pluginLoader.loadAllPlugins();
|
||||
logSink.log(
|
||||
`Autoloaded ${result.loaded} plugin(s), ${result.errors} error(s)`,
|
||||
|
||||
Reference in New Issue
Block a user