diff --git a/dist/fabric/src/channel.js b/dist/fabric/src/channel.js index bca9610..a5f841d 100644 --- a/dist/fabric/src/channel.js +++ b/dist/fabric/src/channel.js @@ -117,6 +117,19 @@ export const fabricChannelPlugin = createChatChannelPlugin({ resolveAccount: (cfg, accountId) => resolveFabricAccount(cfg, accountId), defaultAccountId: (cfg) => resolveDefaultFabricAccountId(cfg), isConfigured: (account) => Boolean(account.fabricApiKey), + // openclaw's channelManager.getRuntimeSnapshot() — called every minute + // by the channel-health-monitor — defaults `configured: true` when the + // plugin doesn't expose describeAccount (see applyDescribedAccountFields + // in server-channels). Without this, fabric's synthetic 'default' + // account (returned by listFabricAccountIds when channels.fabric.accounts + // is empty — the prod shape) gets snapshot {enabled:true, configured:true, + // running:false} → isManagedAccount=true → not-running → restart loop + // every ~10 min, logging `[fabric:default] health-monitor: restarting`. + // Mirror isConfigured here so the snapshot truthfully reports false for + // any account without a fabricApiKey. + describeAccount: (account) => ({ + configured: Boolean(account.fabricApiKey), + }), }, // Minimal setup adapter: Fabric is configured directly under // channels.fabric.* (no interactive wizard). applyAccountConfig is the diff --git a/src/channel.ts b/src/channel.ts index 8fb58c0..09ef50c 100644 --- a/src/channel.ts +++ b/src/channel.ts @@ -153,6 +153,19 @@ export const fabricChannelPlugin = createChatChannelPlugin resolveFabricAccount(cfg as never, accountId), defaultAccountId: (cfg) => resolveDefaultFabricAccountId(cfg as never), isConfigured: (account: ResolvedFabricAccount) => Boolean(account.fabricApiKey), + // openclaw's channelManager.getRuntimeSnapshot() — called every minute + // by the channel-health-monitor — defaults `configured: true` when the + // plugin doesn't expose describeAccount (see applyDescribedAccountFields + // in server-channels). Without this, fabric's synthetic 'default' + // account (returned by listFabricAccountIds when channels.fabric.accounts + // is empty — the prod shape) gets snapshot {enabled:true, configured:true, + // running:false} → isManagedAccount=true → not-running → restart loop + // every ~10 min, logging `[fabric:default] health-monitor: restarting`. + // Mirror isConfigured here so the snapshot truthfully reports false for + // any account without a fabricApiKey. + describeAccount: (account: ResolvedFabricAccount) => ({ + configured: Boolean(account.fabricApiKey), + }), }, // Minimal setup adapter: Fabric is configured directly under // channels.fabric.* (no interactive wizard). applyAccountConfig is the