refactor(plugin): fabric-register is a script, not a tool

Binding an agent's Fabric API key was an OpenClaw tool; make it a
self-contained Node script installed to ~/.openclaw/bin/fabric-register
instead.

- bin/fabric-register.mjs: no plugin deps; AGENT_ID env wins, else
  --agent-id required; --api-key validated via POST /auth/agent/login;
  on success upserts ~/.openclaw/fabric-identity.json (format matches
  IdentityRegistry). Flags/env for center, identity-file, openclaw-path.
- install.mjs: copy the script to ~/.openclaw/bin (chmod 0755) on
  install, remove on uninstall; Next-steps updated.
- tools.ts: drop the fabric-register tool; ctxGuild error now points to
  the script / static accounts config.
- README updated.

Verified: missing-id -> exit 2; --agent-id and AGENT_ID both bind and
write a valid identity file; bad key -> 401, no write.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
h z
2026-05-16 13:12:48 +01:00
parent 9d0fa1d5c8
commit 26c12533fb
5 changed files with 232 additions and 59 deletions

View File

@@ -25,7 +25,12 @@ export function registerFabricTools(
// Resolve the calling agent's Fabric session + a guild's token/endpoint.
const ctxGuild = async (agentId: string, guildNodeId: string) => {
const entry = identity.findByAgentId(agentId);
if (!entry) throw new Error(`agent ${agentId} not registered (call fabric-register)`);
if (!entry)
throw new Error(
`agent ${agentId} not registered — run: AGENT_ID=${agentId} ` +
`~/.openclaw/bin/fabric-register --api-key <fak_…> (or set ` +
`channels.fabric.accounts.${agentId}); then restart the gateway`,
);
const session = await client.agentLogin(entry.fabricApiKey);
const guild = session.guilds.find((g) => g.nodeId === guildNodeId);
const token = session.guildAccessTokens.find((t) => t.guildNodeId === guildNodeId)?.token;
@@ -33,31 +38,10 @@ export function registerFabricTools(
return { session, guild, token };
};
// fabric-register: bind this agent to a Fabric API key.
api.registerTool((ctx: Ctx) => ({
name: 'fabric-register',
description: "Register this agent's Fabric API key (minted via Center CLI `user apikey`).",
parameters: {
type: 'object',
additionalProperties: false,
required: ['fabricApiKey'],
properties: {
fabricApiKey: { type: 'string', description: 'Fabric Center API key (fak_…)' },
},
},
execute: async (params: { fabricApiKey: string }) => {
const agentId = ctx.agentId;
if (!agentId) return { ok: false, error: 'no agent context' };
const session = await client.agentLogin(params.fabricApiKey);
identity.upsert({
agentId,
fabricApiKey: params.fabricApiKey,
fabricUserId: session.user.id,
displayName: session.user.name,
});
return { ok: true, user: session.user };
},
}));
// NOTE: binding an agent's Fabric API key is intentionally NOT a tool.
// It's a one-time step done out-of-band via the installed script
// ~/.openclaw/bin/fabric-register --api-key <fak_…> (AGENT_ID or --agent-id)
// or via static config (channels.fabric.accounts.<agentId>).
const makeCreate = (kind: 'chat' | 'work' | 'report' | 'discussion') =>
api.registerTool((ctx: Ctx) => ({