clawport-ui 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/agents-registry.ts +101 -3
- package/package.json +1 -1
package/lib/agents-registry.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readFileSync, existsSync, readdirSync } from 'fs'
|
|
2
|
+
import { execSync } from 'child_process'
|
|
2
3
|
import { join, basename } from 'path'
|
|
3
4
|
import bundledRegistry from '@/lib/agents.json'
|
|
4
5
|
import type { Agent } from '@/lib/types'
|
|
@@ -295,16 +296,100 @@ function discoverAgents(workspacePath: string): AgentEntry[] | null {
|
|
|
295
296
|
return discovered.length > 0 ? discovered : null
|
|
296
297
|
}
|
|
297
298
|
|
|
299
|
+
// ---------------------------------------------------------------------------
|
|
300
|
+
// CLI-based discovery (openclaw agents list)
|
|
301
|
+
// ---------------------------------------------------------------------------
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Discover agents via `openclaw agents list --json`.
|
|
305
|
+
* Returns AgentEntry[] for any agents found, or null on failure.
|
|
306
|
+
* This catches agents defined in openclaw.json that don't have
|
|
307
|
+
* filesystem directories under agents/.
|
|
308
|
+
*/
|
|
309
|
+
function discoverAgentsViaCli(openclawBin: string): AgentEntry[] | null {
|
|
310
|
+
try {
|
|
311
|
+
const raw = execSync(`${openclawBin} agents list --json`, {
|
|
312
|
+
encoding: 'utf-8',
|
|
313
|
+
timeout: 10000,
|
|
314
|
+
})
|
|
315
|
+
const parsed = JSON.parse(raw)
|
|
316
|
+
const agents: unknown[] = Array.isArray(parsed)
|
|
317
|
+
? parsed
|
|
318
|
+
: parsed.agents ?? parsed.data ?? []
|
|
319
|
+
|
|
320
|
+
if (agents.length === 0) return null
|
|
321
|
+
|
|
322
|
+
let colorIndex = 0
|
|
323
|
+
return agents.map((entry) => {
|
|
324
|
+
const a = entry as Record<string, unknown>
|
|
325
|
+
const id = String(a.id ?? a.name ?? a.slug ?? '')
|
|
326
|
+
const name = String(a.name ?? a.displayName ?? slugToName(id))
|
|
327
|
+
const title = String(a.title ?? a.role ?? 'Agent')
|
|
328
|
+
const reportsTo = a.reportsTo != null ? String(a.reportsTo) : null
|
|
329
|
+
const directReports = Array.isArray(a.directReports)
|
|
330
|
+
? a.directReports.map(String)
|
|
331
|
+
: []
|
|
332
|
+
const tools = Array.isArray(a.tools) ? a.tools.map(String) : ['read', 'write']
|
|
333
|
+
|
|
334
|
+
return {
|
|
335
|
+
id,
|
|
336
|
+
name,
|
|
337
|
+
title,
|
|
338
|
+
reportsTo,
|
|
339
|
+
directReports,
|
|
340
|
+
soulPath: typeof a.soulPath === 'string' ? a.soulPath : null,
|
|
341
|
+
voiceId: typeof a.voiceId === 'string' ? a.voiceId : null,
|
|
342
|
+
color: typeof a.color === 'string' ? a.color : DISCOVER_COLORS[colorIndex++ % DISCOVER_COLORS.length],
|
|
343
|
+
emoji: typeof a.emoji === 'string' ? a.emoji : name.charAt(0).toUpperCase(),
|
|
344
|
+
tools,
|
|
345
|
+
memoryPath: typeof a.memoryPath === 'string' ? a.memoryPath : null,
|
|
346
|
+
description: typeof a.description === 'string' ? a.description : `${name} agent.`,
|
|
347
|
+
}
|
|
348
|
+
})
|
|
349
|
+
} catch {
|
|
350
|
+
return null
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Merge CLI-discovered agents into an existing registry.
|
|
356
|
+
* Only adds agents whose IDs are not already present.
|
|
357
|
+
* Also patches directReports on existing agents to include new CLI agents.
|
|
358
|
+
*/
|
|
359
|
+
function mergeCliAgents(existing: AgentEntry[], cliAgents: AgentEntry[]): AgentEntry[] {
|
|
360
|
+
const existingIds = new Set(existing.map(a => a.id))
|
|
361
|
+
const added: AgentEntry[] = []
|
|
362
|
+
|
|
363
|
+
for (const ca of cliAgents) {
|
|
364
|
+
if (existingIds.has(ca.id)) continue
|
|
365
|
+
added.push(ca)
|
|
366
|
+
existingIds.add(ca.id)
|
|
367
|
+
|
|
368
|
+
// If the CLI agent reports to an existing agent, add it to that agent's directReports
|
|
369
|
+
if (ca.reportsTo) {
|
|
370
|
+
const parent = existing.find(a => a.id === ca.reportsTo)
|
|
371
|
+
if (parent && !parent.directReports.includes(ca.id)) {
|
|
372
|
+
parent.directReports.push(ca.id)
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return [...existing, ...added]
|
|
378
|
+
}
|
|
379
|
+
|
|
298
380
|
/**
|
|
299
381
|
* Load the agent registry.
|
|
300
382
|
*
|
|
301
383
|
* Resolution order:
|
|
302
384
|
* 1. $WORKSPACE_PATH/clawport/agents.json (user's own config)
|
|
303
385
|
* 2. Auto-discovered from $WORKSPACE_PATH (agents/ directory scan)
|
|
304
|
-
*
|
|
386
|
+
* + merged with `openclaw agents list --json` (catches config-only agents)
|
|
387
|
+
* 3. CLI-only discovery via `openclaw agents list --json`
|
|
388
|
+
* 4. Bundled lib/agents.json (default example registry)
|
|
305
389
|
*/
|
|
306
390
|
export function loadRegistry(): AgentEntry[] {
|
|
307
391
|
const workspacePath = process.env.WORKSPACE_PATH
|
|
392
|
+
const openclawBin = process.env.OPENCLAW_BIN
|
|
308
393
|
|
|
309
394
|
if (workspacePath) {
|
|
310
395
|
// 1. User-provided override
|
|
@@ -318,11 +403,24 @@ export function loadRegistry(): AgentEntry[] {
|
|
|
318
403
|
}
|
|
319
404
|
}
|
|
320
405
|
|
|
321
|
-
// 2. Auto-discover from workspace
|
|
406
|
+
// 2. Auto-discover from workspace filesystem
|
|
322
407
|
const discovered = discoverAgents(workspacePath)
|
|
408
|
+
|
|
409
|
+
// 2b. Merge in any agents known to OpenClaw CLI but missing from filesystem
|
|
410
|
+
if (discovered && openclawBin) {
|
|
411
|
+
const cliAgents = discoverAgentsViaCli(openclawBin)
|
|
412
|
+
if (cliAgents) return mergeCliAgents(discovered, cliAgents)
|
|
413
|
+
return discovered
|
|
414
|
+
}
|
|
323
415
|
if (discovered) return discovered
|
|
416
|
+
|
|
417
|
+
// 3. CLI-only discovery (no workspace agents/ dir, but CLI knows about agents)
|
|
418
|
+
if (openclawBin) {
|
|
419
|
+
const cliAgents = discoverAgentsViaCli(openclawBin)
|
|
420
|
+
if (cliAgents) return cliAgents
|
|
421
|
+
}
|
|
324
422
|
}
|
|
325
423
|
|
|
326
|
-
//
|
|
424
|
+
// 4. Bundled fallback
|
|
327
425
|
return bundledRegistry as AgentEntry[]
|
|
328
426
|
}
|