refactor(telemetry): read agents via [
{
"id": "main",
"identityName": "霓光 (Neon)",
"identityEmoji": "✨",
"identitySource": "identity",
"workspace": "/root/.openclaw/workspace",
"agentDir": "/root/.openclaw/agents/main/agent",
"model": "minimax-portal/MiniMax-M2.5",
"bindings": 1,
"isDefault": true,
"routes": [
"default (no explicit rules)"
]
},
{
"id": "developer",
"name": "developer",
"identityName": "小智 (Zhi)",
"identityEmoji": "👋",
"identitySource": "identity",
"workspace": "/root/.openclaw/workspace/workspace-developer",
"agentDir": "/root/.openclaw/agents/developer/agent",
"model": "anthropic/claude-opus-4-6",
"bindings": 1,
"isDefault": false
},
{
"id": "dispatcher",
"name": "dispatcher",
"workspace": "/root/.openclaw/workspace/workspace-dispatcher",
"agentDir": "/root/.openclaw/agents/dispatcher/agent",
"model": "minimax-portal/MiniMax-M2.5",
"bindings": 0,
"isDefault": false
},
{
"id": "operator",
"name": "operator",
"identityName": "晨曦 (Orion)",
"identityEmoji": "✨",
"identitySource": "identity",
"workspace": "/root/.openclaw/workspace/workspace-operator",
"agentDir": "/root/.openclaw/agents/operator/agent",
"model": "openai-codex/gpt-5.2-codex",
"bindings": 1,
"isDefault": false
},
{
"id": "manager",
"name": "manager",
"identityName": "指南(Nav)",
"identityEmoji": "🧭",
"identitySource": "identity",
"workspace": "/root/.openclaw/workspace/workspace-manager",
"agentDir": "/root/.openclaw/agents/manager/agent",
"model": "openai-codex/gpt-5.2-codex",
"bindings": 1,
"isDefault": false
},
{
"id": "mentor",
"name": "mentor",
"identityName": "霖 (Lyn)",
"identityEmoji": "🪶",
"identitySource": "identity",
"workspace": "/root/.openclaw/workspace/workspace-mentor",
"agentDir": "/root/.openclaw/agents/mentor/agent",
"model": "minimax-portal/MiniMax-M2.1",
"bindings": 1,
"isDefault": false
},
{
"id": "recruiter",
"name": "recruiter",
"identityName": "沐川(Evan)",
"identityEmoji": "🧩",
"identitySource": "identity",
"workspace": "/root/.openclaw/workspace/workspace-recruiter",
"agentDir": "/root/.openclaw/agents/recruiter/agent",
"model": "minimax-portal/MiniMax-M2.5",
"bindings": 0,
"isDefault": false
},
{
"id": "administrative-secretary",
"name": "administrative-secretary",
"identityName": "映秘(Mirror)",
"identityEmoji": "🪞",
"identitySource": "identity",
"workspace": "/root/.openclaw/workspace/workspace-administrative-secretary",
"agentDir": "/root/.openclaw/agents/administrative-secretary/agent",
"model": "minimax-portal/MiniMax-M2.5",
"bindings": 1,
"isDefault": false
},
{
"id": "agent-resource-director",
"name": "agent-resource-director",
"identityName": "影织(Sherlock)",
"identityEmoji": "🕸️",
"identitySource": "identity",
"workspace": "/root/.openclaw/workspace/workspace-agent-resource-director",
"agentDir": "/root/.openclaw/agents/agent-resource-director/agent",
"model": "kimi-coding/kimi-k2-thinking",
"bindings": 1,
"isDefault": false
}
]
[plugins] memory-lancedb-pro@1.1.0-beta.6: plugin registered (db: /root/.openclaw/memory/lancedb-pro, model: jina-embeddings-v5-text-small)
[plugins] memory-lancedb-pro: diagnostic build tag loaded (memory-lancedb-pro-diag-20260308-0058)
[plugins] self-improvement: integrated hooks registered (agent:bootstrap, command:new, command:reset)
[plugins] session-strategy: using systemSessionMemory (plugin memory-reflection hooks disabled)
[plugins] PaddedCell plugin initializing...
[plugins] PaddedCell plugin initialized
[plugins] dirigent: pluginDir resolved from import.meta.url: /root/.openclaw/plugins/dirigent
[plugins] hook runner initialized with 3 registered hooks
[plugins] hook runner initialized with 3 registered hooks
[plugins] hook runner initialized with 3 registered hooks
[plugins] hook runner initialized with 3 registered hooks
- Prefer OpenClaw CLI as source of truth for agent list
- Parse JSON prefix defensively when plugin logs trail output
- Keep file/directory discovery only as fallback
This commit is contained in:
@@ -185,8 +185,59 @@ async function collectOpenclawStatus() {
|
||||
/**
|
||||
* Get list of OpenClaw agents from local state
|
||||
*/
|
||||
function extractJsonPrefix(text) {
|
||||
const trimmed = text.trim();
|
||||
if (!trimmed) return null;
|
||||
|
||||
const startsWith = trimmed[0];
|
||||
if (startsWith !== '[' && startsWith !== '{') return null;
|
||||
|
||||
let depth = 0;
|
||||
let inString = false;
|
||||
let escape = false;
|
||||
for (let i = 0; i < trimmed.length; i += 1) {
|
||||
const ch = trimmed[i];
|
||||
if (escape) {
|
||||
escape = false;
|
||||
continue;
|
||||
}
|
||||
if (ch === '\\') {
|
||||
escape = true;
|
||||
continue;
|
||||
}
|
||||
if (ch === '"') {
|
||||
inString = !inString;
|
||||
continue;
|
||||
}
|
||||
if (inString) continue;
|
||||
if (ch === '[' || ch === '{') depth += 1;
|
||||
if (ch === ']' || ch === '}') depth -= 1;
|
||||
if (depth === 0) {
|
||||
return trimmed.slice(0, i + 1);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async function getOpenclawAgents() {
|
||||
try {
|
||||
try {
|
||||
const { stdout } = await execAsync('openclaw agents list --json 2>/dev/null');
|
||||
const jsonPrefix = extractJsonPrefix(stdout);
|
||||
if (jsonPrefix) {
|
||||
const agents = JSON.parse(jsonPrefix);
|
||||
if (Array.isArray(agents)) {
|
||||
return agents.map((agent) => ({
|
||||
id: agent.id,
|
||||
name: agent.name || agent.id,
|
||||
status: agent.isDefault ? 'default' : 'configured',
|
||||
}));
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
log.debug('Failed to get agents from `openclaw agents list --json`:', err.message);
|
||||
}
|
||||
|
||||
const agentConfigPath = `${CONFIG.openclawPath}/agents.json`;
|
||||
try {
|
||||
await access(agentConfigPath, constants.R_OK);
|
||||
|
||||
Reference in New Issue
Block a user