Recruitment's register-agent step is a plain shell step (no LLM turn), so it cannot invoke the `fabric-register` TOOL (tool only fires inside an agent turn) and there is no `openclaw tools call` CLI. It previously fell back to the standalone bootstrap binary, which writes fabric-identity.json but cannot notify the running plugin -> the new agent's inbound socket only came up after a gateway restart. This adds an in-process gateway method `fabric.register` (scope: operator.write) whose handler runs inbound.addAccount: validates the key, persists identity, and brings the inbound socket up immediately. The script now calls `openclaw gateway call fabric.register --params ...` and only falls back to the bootstrap binary if the method is unavailable. Also resyncs committed dist/ to source (sub-discussion-hook/store + tools/ inbound were source-committed but their dist artifacts were stale). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
60 lines
2.6 KiB
JavaScript
60 lines
2.6 KiB
JavaScript
// Plugin-local before_prompt_build hook that injects per-(agent, channel)
|
|
// guides for sub-discussion channels created via the `create-sub-discussion`
|
|
// tool. Mirrors the pattern used by ClawPrompts' fabric-chat-injector
|
|
// (channelId-aware injection) but with content dynamically supplied at
|
|
// channel-creation time instead of read from static files via PrismFacet's
|
|
// router/rule registry.
|
|
//
|
|
// Match logic per turn:
|
|
// ctx.channelId → store.find() → sub-discussion entry
|
|
// ctx.agentId → identity.findByAgentId().fabricUserId
|
|
// ─ matches entry.hostUserId → inject hostGuide
|
|
// ─ matches entry.guestUserIds → inject guestGuide
|
|
// ─ neither → no injection
|
|
//
|
|
// Fail-closed on unknown agentId/channelId — we never inject "the wrong"
|
|
// guide, only the right one or nothing.
|
|
const _G = globalThis;
|
|
const DEDUP_KEY = '_fabricSubDiscussionHookDedup';
|
|
export function registerSubDiscussionHook(api, store, identity) {
|
|
if (!(_G[DEDUP_KEY] instanceof WeakSet))
|
|
_G[DEDUP_KEY] = new WeakSet();
|
|
const dedup = _G[DEDUP_KEY];
|
|
api.on('before_prompt_build', async (...args) => {
|
|
const event = args[0];
|
|
const ctx = (args[1] ?? {});
|
|
// The hook fires both for fabric-driven turns (channelId set) and
|
|
// for other triggers (HF wake, exec-event, etc.) — drop those.
|
|
if (typeof event === 'object' && event !== null) {
|
|
if (dedup.has(event))
|
|
return undefined;
|
|
dedup.add(event);
|
|
}
|
|
const agentId = (ctx.agentId ?? '').trim();
|
|
const channelId = (ctx.channelId ?? '').trim();
|
|
if (!agentId || !channelId)
|
|
return undefined;
|
|
const provider = (ctx.messageProvider ?? '').toLowerCase();
|
|
if (provider && provider !== 'fabric')
|
|
return undefined;
|
|
const entry = store.find(channelId);
|
|
if (!entry)
|
|
return undefined;
|
|
const ident = identity.findByAgentId(agentId);
|
|
const myUserId = (ident?.fabricUserId ?? '').trim();
|
|
if (!myUserId) {
|
|
// identity registry caches fabricUserId after the first agentLogin
|
|
// in inbound.ts. If it's missing here, the agent likely hasn't
|
|
// completed login yet — skip rather than guess.
|
|
return undefined;
|
|
}
|
|
if (myUserId === entry.hostUserId) {
|
|
return { appendSystemContext: entry.hostGuide };
|
|
}
|
|
if (entry.guestUserIds.includes(myUserId)) {
|
|
return { appendSystemContext: entry.guestGuide };
|
|
}
|
|
return undefined;
|
|
});
|
|
}
|