From 0e36457d8fad7cc608f3501a6ce106cfadfcac9c Mon Sep 17 00:00:00 2001 From: hzhang Date: Sat, 23 May 2026 19:35:38 +0100 Subject: [PATCH] =?UTF-8?q?fix(tools):=20execute=20receives=20(callId,=20a?= =?UTF-8?q?rgs),=20not=20(args)=20=E2=80=94=20pre-existing=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenClaw plugin-sdk's registerTool execute signature is: execute: async (_id: string, params) => { ... } Fabric tools were calling it as `(p) => { ... }`, so `p` held the call id (a string) and the real args were silently dropped onto the floor. Every tool that read a required field from `p` failed with the field surfacing as undefined. fabric-guild-list (just added) appeared to work because all its properties are optional — `p.nameFilter` and `p.purposeFilter` both being undefined produced empty filter needles, which let the unfiltered guild list through. The real bug surfaced the moment fabric-channel-list (required: guildNodeId) was invoked: the ctxGuild helper saw `undefined` and reported `agent not a member of guild undefined`. Compare dialectic plugin's tools.ts which has always used the correct `async (_id: string, params) => {...}` shape and worked end-to-end. Aligning the fabric signature to match. Verified end-to-end on sim: - fabric-guild-list returns 1 guild with the purpose set via the new `cli node set-purpose` - fabric-channel-list returns 3 channels including a now-populated `purpose` field on each row - fabric-channel-set-purpose successfully patches a channel and the subsequent fabric-channel-list shows the new purpose --- dist/fabric/src/tools.js | 18 +++++++++--------- src/tools.ts | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/dist/fabric/src/tools.js b/dist/fabric/src/tools.js index a9d3506..adb4f63 100644 --- a/dist/fabric/src/tools.js +++ b/dist/fabric/src/tools.js @@ -48,7 +48,7 @@ export function registerFabricTools(api, client, identity) { }, }, }, - execute: async (p) => { + execute: async (_id, p) => { const agentId = ctx.agentId; if (!agentId) return { ok: false, error: 'no agent context' }; @@ -84,7 +84,7 @@ export function registerFabricTools(api, client, identity) { callbackChannelId: { type: 'string', description: 'optional channel to also post the summary to' }, }, }, - execute: async (p) => { + execute: async (_id, p) => { const agentId = ctx.agentId; if (!agentId) return { ok: false, error: 'no agent context' }; @@ -128,7 +128,7 @@ export function registerFabricTools(api, client, identity) { }, }, }, - execute: async (p) => { + execute: async (_id, p) => { const agentId = ctx.agentId; if (!agentId) return { ok: false, error: 'no agent context' }; @@ -188,7 +188,7 @@ export function registerFabricTools(api, client, identity) { channelId: { type: 'string' }, }, }, - execute: async (p) => { + execute: async (_id, p) => { const agentId = ctx.agentId; if (!agentId) return { ok: false, error: 'no agent context' }; @@ -235,7 +235,7 @@ export function registerFabricTools(api, client, identity) { content: { type: 'string', description: 'Message body (markdown supported by the renderer).' }, }, }, - execute: async (p) => { + execute: async (_id, p) => { const agentId = ctx.agentId; if (!agentId) return { ok: false, error: 'no agent context' }; @@ -270,7 +270,7 @@ export function registerFabricTools(api, client, identity) { includeClosed: { type: 'boolean', description: 'default false — closed channels filtered out' }, }, }, - execute: async (p) => { + execute: async (_id, p) => { const agentId = ctx.agentId; if (!agentId) return { ok: false, error: 'no agent context' }; @@ -330,7 +330,7 @@ export function registerFabricTools(api, client, identity) { }, }, }, - execute: async (p) => { + execute: async (_id, p) => { const agentId = ctx.agentId; if (!agentId) return { ok: false, error: 'no agent context' }; @@ -387,7 +387,7 @@ export function registerFabricTools(api, client, identity) { }, }, }, - execute: async (p) => { + execute: async (_id, p) => { const agentId = ctx.agentId; if (!agentId) return { ok: false, error: 'no agent context' }; @@ -422,7 +422,7 @@ export function registerFabricTools(api, client, identity) { limit: { type: 'integer', minimum: 1, maximum: 200, description: 'default 20' }, }, }, - execute: async (p) => { + execute: async (_id, p) => { const agentId = ctx.agentId; if (!agentId) return { ok: false, error: 'no agent context' }; diff --git a/src/tools.ts b/src/tools.ts index 6377097..d787018 100644 --- a/src/tools.ts +++ b/src/tools.ts @@ -71,7 +71,7 @@ export function registerFabricTools( }, }, }, - execute: async (p: { + execute: async (_id: string, p: { guildNodeId: string; name: string; isPublic?: boolean; @@ -114,7 +114,7 @@ export function registerFabricTools( callbackChannelId: { type: 'string', description: 'optional channel to also post the summary to' }, }, }, - execute: async (p: { + execute: async (_id: string, p: { guildNodeId: string; channelId: string; summary: string; @@ -164,7 +164,7 @@ export function registerFabricTools( }, }, }, - execute: async (p: { + execute: async (_id: string, p: { action: 'read' | 'share' | 'update' | 'close'; guildNodeId: string; channelId: string; @@ -229,7 +229,7 @@ export function registerFabricTools( channelId: { type: 'string' }, }, }, - execute: async (p: { + execute: async (_id: string, p: { action: 'members' | 'join' | 'leave'; guildNodeId: string; channelId: string; @@ -281,7 +281,7 @@ export function registerFabricTools( content: { type: 'string', description: 'Message body (markdown supported by the renderer).' }, }, }, - execute: async (p: { guildNodeId: string; channelId: string; content: string }) => { + execute: async (_id: string, p: { guildNodeId: string; channelId: string; content: string }) => { const agentId = ctx.agentId; if (!agentId) return { ok: false, error: 'no agent context' }; const { session, guild, token } = await ctxGuild(agentId, p.guildNodeId); @@ -323,7 +323,7 @@ export function registerFabricTools( includeClosed: { type: 'boolean', description: 'default false — closed channels filtered out' }, }, }, - execute: async (p: { + execute: async (_id: string, p: { guildNodeId: string; nameFilter?: string; xType?: string; @@ -387,7 +387,7 @@ export function registerFabricTools( }, }, }, - execute: async (p: { nameFilter?: string; purposeFilter?: string }) => { + execute: async (_id: string, p: { nameFilter?: string; purposeFilter?: string }) => { const agentId = ctx.agentId; if (!agentId) return { ok: false, error: 'no agent context' }; const entry = identity.findByAgentId(agentId); @@ -442,7 +442,7 @@ export function registerFabricTools( }, }, }, - execute: async (p: { guildNodeId: string; channelId: string; purpose: string }) => { + execute: async (_id: string, p: { guildNodeId: string; channelId: string; purpose: string }) => { const agentId = ctx.agentId; if (!agentId) return { ok: false, error: 'no agent context' }; const { guild, token } = await ctxGuild(agentId, p.guildNodeId); @@ -483,7 +483,7 @@ export function registerFabricTools( limit: { type: 'integer', minimum: 1, maximum: 200, description: 'default 20' }, }, }, - execute: async (p: { + execute: async (_id: string, p: { guildNodeId: string; channelId: string; seqFrom?: number;