feat(hf-plugin): expose globalThis.__hfAgentStatus.get(agentId)
Cross-plugin agent-status accessor for use by Fabric.OpenclawPlugin's presence-sync loop (and any future plugin needing 'is agent X busy right now'). Backed by CalendarBridgeClient.getAgentStatus() with a 30s in-memory TTL cache to avoid hammering the HF backend. Returns one of 'idle' | 'on_call' | 'busy' | 'exhausted' | 'offline' or undefined when the agent isn't known to HF. Cache miss + bridge failure returns the last cached value (stale-data better than no data for delivery-decision use cases). Part of DIALECTIC-V2 Phase 1 (Fabric announce channel + busy-discard). See /home/hzhang/arch/DIALECTIC-V2-DESIGN.md sections 7+8.
This commit is contained in:
@@ -396,6 +396,36 @@ function register(api: PluginAPI): void {
|
||||
}
|
||||
}
|
||||
|
||||
// Cross-plugin exposure: agent status lookup for other plugins
|
||||
// (currently Fabric.OpenclawPlugin uses this to skip delivering
|
||||
// `announce` channel messages to busy agents — see DIALECTIC-V2
|
||||
// design doc, Phase 1). Backed by calendarBridge.getAgentStatus
|
||||
// with a small TTL cache to avoid hammering the HF backend.
|
||||
type HfStatus = 'idle' | 'on_call' | 'busy' | 'exhausted' | 'offline';
|
||||
const HF_STATUS_CACHE_TTL_MS = 30_000;
|
||||
const hfStatusCache = new Map<string, { status: HfStatus; at: number }>();
|
||||
const _G = globalThis as Record<string, unknown>;
|
||||
_G['__hfAgentStatus'] = {
|
||||
async get(agentId: string): Promise<HfStatus | undefined> {
|
||||
if (!agentId) return undefined;
|
||||
const cached = hfStatusCache.get(agentId);
|
||||
if (cached && Date.now() - cached.at < HF_STATUS_CACHE_TTL_MS) {
|
||||
return cached.status;
|
||||
}
|
||||
try {
|
||||
const status = await calendarBridge.getAgentStatus(agentId);
|
||||
if (status) {
|
||||
const typed = status as HfStatus;
|
||||
hfStatusCache.set(agentId, { status: typed, at: Date.now() });
|
||||
return typed;
|
||||
}
|
||||
} catch {
|
||||
/* fall through to cached-or-undefined */
|
||||
}
|
||||
return cached?.status;
|
||||
},
|
||||
};
|
||||
|
||||
// Track wakes already dispatched for a slot in the current sync
|
||||
// window — the simplified inline scheduler does not PATCH slot
|
||||
// status server-side, so without dedupe the check loop re-wakes
|
||||
|
||||
Reference in New Issue
Block a user