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
|
// Track wakes already dispatched for a slot in the current sync
|
||||||
// window — the simplified inline scheduler does not PATCH slot
|
// window — the simplified inline scheduler does not PATCH slot
|
||||||
// status server-side, so without dedupe the check loop re-wakes
|
// status server-side, so without dedupe the check loop re-wakes
|
||||||
|
|||||||
Reference in New Issue
Block a user