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:
h z
2026-05-15 17:30:37 +01:00
parent 9221664428
commit 7fed6d07f6
537 changed files with 536836 additions and 3 deletions

112
dist/fabric/src/tools.js vendored Normal file
View 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 };
},
}));
}