OpenClaw channel plugin: defineChannelPluginEntry + createChatChannelPlugin.
Inbound via channel-turn kernel (wakeup -> admission: true=dispatch,
else drop+recordHistory). One Fabric socket per agent identity in the
plugin runtime (no sidecar). Center API-key agent auth. Tools:
fabric-register, create-{chat,work,report,discussion}-channel,
discussion-complete (post summary + close channel).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
64 lines
2.1 KiB
TypeScript
64 lines
2.1 KiB
TypeScript
import {
|
|
createChatChannelPlugin,
|
|
createChannelPluginBase,
|
|
} from 'openclaw/plugin-sdk/channel-core';
|
|
import type { OpenClawConfig } from 'openclaw/plugin-sdk/channel-core';
|
|
|
|
export type ResolvedFabricAccount = {
|
|
accountId: string | null;
|
|
centerApiBase: string;
|
|
allowFrom: string[];
|
|
dmPolicy: string | undefined;
|
|
};
|
|
|
|
export function resolveFabricAccount(
|
|
cfg: OpenClawConfig,
|
|
accountId?: string | null,
|
|
): ResolvedFabricAccount {
|
|
const section = (cfg.channels as Record<string, any>)?.['fabric'];
|
|
const centerApiBase: string | undefined = section?.centerApiBase;
|
|
if (!centerApiBase) throw new Error('fabric: channels.fabric.centerApiBase is required');
|
|
return {
|
|
accountId: accountId ?? null,
|
|
centerApiBase,
|
|
allowFrom: section?.allowFrom ?? [],
|
|
dmPolicy: section?.dmSecurity,
|
|
};
|
|
}
|
|
|
|
// Outbound is wired by the entry (it needs the identity registry + client to
|
|
// post as the right agent). Channel-turn visible replies go through the
|
|
// inbound adapter's delivery callback; this object owns config/security only.
|
|
export function buildFabricChannelPlugin(
|
|
sendText: (params: { accountId?: string | null; to: string; text: string }) => Promise<{ messageId?: string }>,
|
|
) {
|
|
return createChatChannelPlugin<ResolvedFabricAccount>({
|
|
base: createChannelPluginBase({
|
|
id: 'fabric',
|
|
setup: {
|
|
resolveAccount: resolveFabricAccount,
|
|
inspectAccount(cfg, accountId) {
|
|
const section = (cfg.channels as Record<string, any>)?.['fabric'];
|
|
const ok = Boolean(section?.centerApiBase);
|
|
return { enabled: ok, configured: ok, tokenStatus: ok ? 'available' : 'missing' };
|
|
},
|
|
},
|
|
}),
|
|
security: {
|
|
dm: {
|
|
channelKey: 'fabric',
|
|
resolvePolicy: (a) => a.dmPolicy,
|
|
resolveAllowFrom: (a) => a.allowFrom,
|
|
defaultPolicy: 'allowlist',
|
|
},
|
|
},
|
|
// Fabric replies thread by being posted into the same channel.
|
|
threading: { topLevelReplyToMode: 'channel' },
|
|
outbound: {
|
|
attachedResults: {
|
|
sendText: async (params) => sendText(params),
|
|
},
|
|
},
|
|
});
|
|
}
|