mirror of
https://github.com/xmanrui/OpenClaw-bot-review.git
synced 2026-07-27 22:25:52 +00:00
125 lines
3.9 KiB
TypeScript
125 lines
3.9 KiB
TypeScript
import { OfficeState } from './engine/officeState'
|
|
|
|
export interface SubagentInfo {
|
|
toolId: string
|
|
label: string
|
|
sessionKey?: string
|
|
childSessionKey?: string
|
|
activityEvents?: Array<{ key: string; text: string; at: number }>
|
|
}
|
|
|
|
export interface AgentActivity {
|
|
agentId: string
|
|
name: string
|
|
emoji: string
|
|
state: 'idle' | 'working' | 'waiting' | 'offline'
|
|
currentTool?: string
|
|
toolStatus?: string
|
|
lastActive: number
|
|
subagents?: SubagentInfo[]
|
|
}
|
|
|
|
/** Track which subagent keys were active last sync, per parent agent */
|
|
const prevSubagentKeys = new Map<string, Set<string>>()
|
|
|
|
/** Track previous agent states to detect offline→working transitions */
|
|
const prevAgentStates = new Map<string, string>()
|
|
|
|
export function syncAgentsToOffice(
|
|
activities: AgentActivity[],
|
|
office: OfficeState,
|
|
agentIdMap: Map<string, number>,
|
|
nextIdRef: { current: number },
|
|
): void {
|
|
const currentAgentIds = new Set(activities.map(a => a.agentId))
|
|
|
|
// Remove agents that are no longer present
|
|
for (const [agentId, charId] of agentIdMap) {
|
|
if (!currentAgentIds.has(agentId)) {
|
|
office.removeAllSubagents(charId)
|
|
office.removeAgent(charId)
|
|
agentIdMap.delete(agentId)
|
|
prevSubagentKeys.delete(agentId)
|
|
}
|
|
}
|
|
|
|
for (const activity of activities) {
|
|
if (activity.state === 'offline') {
|
|
if (agentIdMap.has(activity.agentId)) {
|
|
const charId = agentIdMap.get(activity.agentId)!
|
|
office.removeAllSubagents(charId)
|
|
office.removeAgent(charId)
|
|
agentIdMap.delete(activity.agentId)
|
|
prevSubagentKeys.delete(activity.agentId)
|
|
}
|
|
prevAgentStates.set(activity.agentId, 'offline')
|
|
continue
|
|
}
|
|
|
|
let charId = agentIdMap.get(activity.agentId)
|
|
if (charId === undefined) {
|
|
charId = nextIdRef.current++
|
|
agentIdMap.set(activity.agentId, charId)
|
|
// Spawn at door if agent was previously offline or is brand new
|
|
const wasOffline = prevAgentStates.get(activity.agentId) === 'offline'
|
|
const isNew = !prevAgentStates.has(activity.agentId)
|
|
office.addAgent(charId, undefined, undefined, undefined, undefined, wasOffline || isNew)
|
|
}
|
|
|
|
// Set label (agent name with id in parentheses)
|
|
const ch = office.characters.get(charId)
|
|
if (ch) {
|
|
ch.label = activity.name ? `${activity.name} (${activity.agentId})` : activity.agentId
|
|
}
|
|
|
|
switch (activity.state) {
|
|
case 'working':
|
|
office.setAgentActive(charId, true)
|
|
office.setAgentTool(charId, activity.currentTool || null)
|
|
break
|
|
case 'idle':
|
|
office.setAgentActive(charId, false)
|
|
office.setAgentTool(charId, null)
|
|
break
|
|
case 'waiting':
|
|
office.setAgentActive(charId, true)
|
|
office.showWaitingBubble(charId)
|
|
break
|
|
}
|
|
|
|
// Sync subagents
|
|
const currentSubKeys = new Set<string>()
|
|
if (activity.subagents) {
|
|
for (const sub of activity.subagents) {
|
|
const subKey = sub.sessionKey ? `${sub.sessionKey}::${sub.toolId}` : sub.toolId
|
|
currentSubKeys.add(subKey)
|
|
const existingSubId = office.getSubagentId(charId, subKey)
|
|
if (existingSubId === null) {
|
|
const subId = office.addSubagent(charId, subKey)
|
|
office.setAgentActive(subId, true)
|
|
const subCh = office.characters.get(subId)
|
|
if (subCh) subCh.label = office.getTempWorkerLabel()
|
|
} else {
|
|
const subCh = office.characters.get(existingSubId)
|
|
if (subCh) {
|
|
subCh.label = office.getTempWorkerLabel()
|
|
office.setAgentActive(existingSubId, true)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove subagents that are no longer active
|
|
const prevKeys = prevSubagentKeys.get(activity.agentId)
|
|
if (prevKeys) {
|
|
for (const subKey of prevKeys) {
|
|
if (!currentSubKeys.has(subKey)) {
|
|
office.removeSubagent(charId, subKey)
|
|
}
|
|
}
|
|
}
|
|
prevSubagentKeys.set(activity.agentId, currentSubKeys)
|
|
prevAgentStates.set(activity.agentId, activity.state)
|
|
}
|
|
}
|