build: PaddedCell-style install.mjs + SDK-aligned packaging
install.mjs (--install/--build-only/--uninstall/--openclaw-profile-path), tsconfig outDir dist/fabric, package.json openclaw file dep + main. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
112
dist/fabric/src/tools.js
vendored
Normal file
112
dist/fabric/src/tools.js
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
const X_BY_KIND = {
|
||||
chat: 'general',
|
||||
work: 'work',
|
||||
report: 'report',
|
||||
discussion: 'discuss',
|
||||
};
|
||||
export function registerFabricTools(api, client, identity) {
|
||||
// Resolve the calling agent's Fabric session + a guild's token/endpoint.
|
||||
const ctxGuild = async (agentId, guildNodeId) => {
|
||||
const entry = identity.findByAgentId(agentId);
|
||||
if (!entry)
|
||||
throw new Error(`agent ${agentId} not registered (call fabric-register)`);
|
||||
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;
|
||||
if (!guild || !token)
|
||||
throw new Error(`agent not a member of guild ${guildNodeId}`);
|
||||
return { session, guild, token };
|
||||
};
|
||||
// fabric-register: bind this agent to a Fabric API key.
|
||||
api.registerTool((ctx) => ({
|
||||
name: 'fabric-register',
|
||||
description: "Register this agent's Fabric API key (minted via Center CLI `user apikey`).",
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
required: ['fabricApiKey'],
|
||||
properties: {
|
||||
fabricApiKey: { type: 'string', description: 'Fabric Center API key (fak_…)' },
|
||||
},
|
||||
},
|
||||
handler: async (params) => {
|
||||
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 };
|
||||
},
|
||||
}));
|
||||
const makeCreate = (kind) => api.registerTool((ctx) => ({
|
||||
name: `create-${kind}-channel`,
|
||||
description: `Create a Fabric ${kind} channel (x_type=${X_BY_KIND[kind]}).`,
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
required: ['guildNodeId', 'name'],
|
||||
properties: {
|
||||
guildNodeId: { type: 'string' },
|
||||
name: { type: 'string' },
|
||||
isPublic: { type: 'boolean' },
|
||||
memberUserIds: { type: 'array', items: { type: 'string' } },
|
||||
onDuty: { type: 'string', description: 'required for triage-like flows (unused for these kinds)' },
|
||||
listeners: { type: 'array', items: { type: 'string' } },
|
||||
},
|
||||
},
|
||||
handler: async (p) => {
|
||||
const agentId = ctx.agentId;
|
||||
if (!agentId)
|
||||
return { ok: false, error: 'no agent context' };
|
||||
const { guild, token } = await ctxGuild(agentId, p.guildNodeId);
|
||||
const ch = await client.createChannel(guild.endpoint, token, {
|
||||
guildId: p.guildNodeId,
|
||||
name: p.name,
|
||||
xType: X_BY_KIND[kind],
|
||||
isPublic: p.isPublic ?? false,
|
||||
memberUserIds: p.memberUserIds ?? [],
|
||||
});
|
||||
return { ok: true, channelId: ch.id };
|
||||
},
|
||||
}));
|
||||
makeCreate('chat');
|
||||
makeCreate('work');
|
||||
makeCreate('report');
|
||||
makeCreate('discussion');
|
||||
// discussion-complete: post a summary then close the channel (Guild
|
||||
// /channels/:id/close — history stays readable, new posts -> 409).
|
||||
api.registerTool((ctx) => ({
|
||||
name: 'discussion-complete',
|
||||
description: 'Conclude a discussion: post a summary then close the channel.',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
required: ['guildNodeId', 'channelId', 'summary'],
|
||||
properties: {
|
||||
guildNodeId: { type: 'string' },
|
||||
channelId: { type: 'string' },
|
||||
summary: { type: 'string' },
|
||||
callbackChannelId: { type: 'string', description: 'optional channel to also post the summary to' },
|
||||
},
|
||||
},
|
||||
handler: async (p) => {
|
||||
const agentId = ctx.agentId;
|
||||
if (!agentId)
|
||||
return { ok: false, error: 'no agent context' };
|
||||
const { session, guild, token } = await ctxGuild(agentId, p.guildNodeId);
|
||||
await client.postMessage(guild.endpoint, token, p.channelId, p.summary, session.user.id);
|
||||
if (p.callbackChannelId) {
|
||||
await client
|
||||
.postMessage(guild.endpoint, token, p.callbackChannelId, p.summary, session.user.id)
|
||||
.catch(() => undefined);
|
||||
}
|
||||
await client.closeChannel(guild.endpoint, token, p.channelId);
|
||||
return { ok: true, closed: true };
|
||||
},
|
||||
}));
|
||||
}
|
||||
Reference in New Issue
Block a user