diff --git a/DEVLOG.md b/DEVLOG.md index 3701fba..0e8519e 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -30,11 +30,19 @@ - All Chinese text in the initial directory selection page translated to English - Includes: title, description, labels, placeholders, error messages, button text +### Bug Fixes + +**Agent tree: sub-agents not grouped under main (old config format)** +- **Symptom**: On machines with openclaw.json created before OCM v0.6 multi-bot support, all sub-agents displayed as independent cards instead of nested under main +- **Root cause**: Old-format bindings lack `accountId` field in sub-agent entries. The tree builder relied on `parentAccountId` to match sub-agents to roots, but old bindings only had `channel` + `peer` — no `accountId`. So `parentAccountId` was null and no parent match was found +- **Fix**: Fallback inference — if a sub-agent has a peer binding but no `accountId`, automatically infer `parentAccountId` from main's binding (`accountId`) or fall back to `'default'` + ### Technical Notes - **CPU usage measurement:** Two `os.cpus()` snapshots 200ms apart, calculating idle-to-total ratio across all cores - **Gauge rendering:** Pure SVG arcs with `stroke-dasharray` animation, no external libraries. 270° arc (gap at bottom), colour transitions via `gaugeColor()` function - **allowFrom auto-config:** `POST /api/agents` now accepts optional `telegramUserId` field (numeric string), appends to `channels.telegram.allowFrom[]` if not already present +- **Old-config compatibility:** Sub-agent bindings without `accountId` are now auto-assigned to the main agent's bot, maintaining backward compatibility with configs created before multi-bot support --- diff --git a/openclaw-manager.js b/openclaw-manager.js index 313e647..9339c48 100644 --- a/openclaw-manager.js +++ b/openclaw-manager.js @@ -365,7 +365,20 @@ async function handleApi(req, res, urlObj, body) { const accountId = botBinding?.match?.accountId || (isMain ? mainInferredAccountId : null); // For sub-agents (with peer match), find which accountId they belong to const parentBinding = bindings.find(b => b.agentId === a.id && b.match?.accountId); - const parentAccountId = parentBinding?.match?.accountId || null; + // Fallback: if sub-agent has peer binding but no accountId, AND there's only one bot (old single-bot config), + // infer parentAccountId from main. If multiple bots exist, leave as orphan (can't guess which bot it belongs to). + let parentAccountId = parentBinding?.match?.accountId || null; + if (!parentAccountId && !hasOwnBot) { + const hasPeerBinding = bindings.find(b => b.agentId === a.id && b.match?.peer); + if (hasPeerBinding) { + const rootBindings = bindings.filter(b => b.match?.accountId && !b.match?.peer); + const rootCount = rootBindings.length + (list.some(x => x.id === 'main') && !rootBindings.some(b => b.agentId === 'main') ? 1 : 0); + if (rootCount <= 1) { + const mainBinding = rootBindings.find(b => b.agentId === 'main') || rootBindings[0]; + parentAccountId = mainBinding?.match?.accountId || mainInferredAccountId || 'default'; + } + } + } // Workspace: explicit per-agent, or defaults.workspace for main const workspace = a.workspace || (isMain ? defaultWorkspace : null); return { ...a, workspace, groupId, requireMention: groupId ? (groups[groupId]?.requireMention ?? true) : null,