From e89c255a01738e83ffbd5b54d1c0fe8288f26b92 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sat, 20 Jun 2026 12:00:03 +0800 Subject: [PATCH] fix(sdk): require session key for effective tools --- packages/sdk/src/client.ts | 17 +++++++++++++++-- packages/sdk/src/index.test.ts | 17 +++++++++++++++++ packages/sdk/src/index.ts | 1 + packages/sdk/src/types.ts | 5 +++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/packages/sdk/src/client.ts b/packages/sdk/src/client.ts index abfb6d246a6e..5abdcc8be73f 100644 --- a/packages/sdk/src/client.ts +++ b/packages/sdk/src/client.ts @@ -29,6 +29,7 @@ import type { TasksGetResult, TasksListParams, TasksListResult, + ToolsEffectiveParams, ToolInvokeParams, ToolInvokeResult, } from "./types.js"; @@ -238,6 +239,18 @@ function requireArtifactQueryScope(api: string, params: unknown): ArtifactQuery return params; } +function hasToolsEffectiveSessionKey(params: unknown): params is ToolsEffectiveParams { + const record = asRecord(params); + return typeof record.sessionKey === "string" && record.sessionKey.trim().length > 0; +} + +function requireToolsEffectiveSessionKey(params: unknown): ToolsEffectiveParams { + if (!hasToolsEffectiveSessionKey(params)) { + throw new Error("oc.tools.effective requires sessionKey"); + } + return params; +} + function readChatProjection(event: OpenClawEvent): ChatProjection | undefined { const raw = event.raw; if (event.type !== "raw" || raw?.event !== "chat") { @@ -861,8 +874,8 @@ export class ToolsNamespace extends RpcNamespace { return await this.call("catalog", params === undefined ? {} : params); } - async effective(params?: unknown): Promise { - return await this.call("effective", params); + async effective(params: ToolsEffectiveParams): Promise { + return await this.call("effective", requireToolsEffectiveSessionKey(params)); } async invoke(name: string, params?: ToolInvokeParams): Promise { diff --git a/packages/sdk/src/index.test.ts b/packages/sdk/src/index.test.ts index 7fae96a7eb00..876a1803c8e1 100644 --- a/packages/sdk/src/index.test.ts +++ b/packages/sdk/src/index.test.ts @@ -739,6 +739,23 @@ describe("OpenClaw SDK", () => { ]); }); + it("rejects tools.effective without a session key before RPC", async () => { + type EffectiveMethod = (this: unknown, params?: unknown) => Promise; + const transport = new FakeTransport({ + "tools.effective": { tools: [] }, + }); + const oc = new OpenClaw({ transport }); + + await expect((oc.tools.effective as unknown as EffectiveMethod).call(oc.tools)).rejects.toThrow( + "oc.tools.effective requires sessionKey", + ); + await expect( + (oc.tools.effective as unknown as EffectiveMethod).call(oc.tools, {}), + ).rejects.toThrow("oc.tools.effective requires sessionKey"); + + expect(transport.calls).toEqual([]); + }); + it("keeps close terminal when it races a pending connect", async () => { const transport = new DelayedConnectTransport({ "agents.list": { agents: [] }, diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index b6d41c1238ad..ea58b15db745 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -56,6 +56,7 @@ export type { TasksGetResult, TasksListParams, TasksListResult, + ToolsEffectiveParams, ToolInvokeParams, ToolInvokeResult, WorkspaceSelection, diff --git a/packages/sdk/src/types.ts b/packages/sdk/src/types.ts index 315c16915f1f..98ced6aa481c 100644 --- a/packages/sdk/src/types.ts +++ b/packages/sdk/src/types.ts @@ -192,6 +192,11 @@ export type SDKError = { }; /** Parameters for direct tool invocation through the SDK. */ +export type ToolsEffectiveParams = { + sessionKey: string; + agentId?: string; +}; + export type ToolInvokeParams = { args?: JsonObject; sessionKey?: string;