diff --git a/extensions/feishu/src/channel.test.ts b/extensions/feishu/src/channel.test.ts index 96bf0d03ed3..2b0a04028e0 100644 --- a/extensions/feishu/src/channel.test.ts +++ b/extensions/feishu/src/channel.test.ts @@ -576,17 +576,6 @@ describe("feishuPlugin actions", () => { ).rejects.toThrow("Feishu thread-reply requires messageId."); }); - it("declares card as optional in the tool schema", () => { - const discovery = feishuPlugin.actions?.describeMessageTool?.({ cfg }); - const schema = Array.isArray(discovery?.schema) ? discovery.schema[0] : discovery?.schema; - const cardSchema = schema?.properties?.card; - expect(cardSchema).toBeDefined(); - // TypeBox marks Optional schemas with Symbol(TypeBox.Optional) = "Optional". - expect( - (cardSchema as unknown as Record)?.[Symbol.for("TypeBox.Optional")], - ).toBe("Optional"); - }); - it("sends media-only messages without requiring card", async () => { feishuOutboundSendMediaMock.mockResolvedValueOnce({ channel: "feishu", diff --git a/src/agents/pi-embedded-runner/model.test.ts b/src/agents/pi-embedded-runner/model.test.ts index 5cd1ef7c09b..eb5ea440680 100644 --- a/src/agents/pi-embedded-runner/model.test.ts +++ b/src/agents/pi-embedded-runner/model.test.ts @@ -294,7 +294,7 @@ describe("resolveModel", () => { }, }, }, - } as OpenClawConfig; + } as unknown as OpenClawConfig; const result = resolveModelForTest("custom", "missing-model", "/tmp/agent", cfg); @@ -314,7 +314,7 @@ describe("resolveModel", () => { }, }, }, - } as OpenClawConfig; + } as unknown as OpenClawConfig; const result = resolveModelForTest("google-paid", "missing-model", "/tmp/agent", cfg); @@ -362,7 +362,7 @@ describe("resolveModel", () => { }, }, }, - } as OpenClawConfig; + } as unknown as OpenClawConfig; // Requesting a non-listed model forces the providerCfg fallback branch. const result = resolveModelForTest("custom", "missing-model", "/tmp/agent", cfg); @@ -388,7 +388,7 @@ describe("resolveModel", () => { }, }, }, - } as OpenClawConfig; + } as unknown as OpenClawConfig; const result = resolveModelForTest("custom", "missing-model", "/tmp/agent", cfg); @@ -442,7 +442,7 @@ describe("resolveModel", () => { }, }, }, - } as OpenClawConfig; + } as unknown as OpenClawConfig; const result = resolveModelForTest("custom", "model-b", "/tmp/agent", cfg); @@ -469,7 +469,7 @@ describe("resolveModel", () => { }, }, }, - } as OpenClawConfig; + } as unknown as OpenClawConfig; const result = resolveModelForTest("custom", "model-b", "/tmp/agent", cfg); @@ -495,7 +495,7 @@ describe("resolveModel", () => { }, }, }, - } as OpenClawConfig; + } as unknown as OpenClawConfig; const models = buildInlineProviderModels(cfg.models?.providers ?? {}); expect(models).toEqual( @@ -661,7 +661,7 @@ describe("resolveModel", () => { }, }, }, - } as OpenClawConfig; + } as unknown as OpenClawConfig; const result = resolveModelForTest("onehub", "glm-5", "/tmp/agent", cfg); @@ -720,7 +720,7 @@ describe("resolveModel", () => { }, }, }, - } as OpenClawConfig; + } as unknown as OpenClawConfig; const result = resolveModelForTest("qwen", "qwen3-coder-plus", "/tmp/agent", cfg); @@ -869,7 +869,7 @@ describe("resolveModel", () => { }, }, }, - } as OpenClawConfig; + } as unknown as OpenClawConfig; const result = resolveModelForTest("github-copilot", "gpt-5.4-mini", "/tmp/agent", cfg); diff --git a/src/agents/tools/message-tool.test.ts b/src/agents/tools/message-tool.test.ts index 02369744d9b..8e75c5bc393 100644 --- a/src/agents/tools/message-tool.test.ts +++ b/src/agents/tools/message-tool.test.ts @@ -37,6 +37,24 @@ function createTelegramPollExtraToolSchemas() { }; } +function createCardSchemaPlugin(params: { + id: string; + label: string; + docsPath: string; + blurb: string; +}) { + return createChannelPlugin({ + ...params, + actions: ["send"], + capabilities: ["cards"], + toolSchema: () => ({ + properties: { + card: createMessageToolCardSchema(), + }, + }), + }); +} + const mocks = vi.hoisted(() => ({ runMessageAction: vi.fn(), loadConfig: vi.fn(() => ({})), @@ -421,37 +439,45 @@ describe("message tool schema scoping", () => { expect(actionEnum).toContain("poll"); }); - it("keeps provider card schema optional after merging into the message tool schema", () => { - const feishuPlugin = createChannelPlugin({ - id: "feishu", - label: "Feishu", - docsPath: "/channels/feishu", - blurb: "Feishu test plugin.", - actions: ["send"], - capabilities: ["cards"], - toolSchema: () => ({ - properties: { - card: createMessageToolCardSchema(), - }, + it.each([ + { + provider: "feishu", + plugin: createCardSchemaPlugin({ + id: "feishu", + label: "Feishu", + docsPath: "/channels/feishu", + blurb: "Feishu test plugin.", }), - }); + }, + { + provider: "msteams", + plugin: createCardSchemaPlugin({ + id: "msteams", + label: "MSTeams", + docsPath: "/channels/msteams", + blurb: "MSTeams test plugin.", + }), + }, + ])( + "keeps $provider card schema optional after merging into the message tool schema", + ({ plugin }) => { + setActivePluginRegistry( + createTestRegistry([{ pluginId: plugin.id, source: "test", plugin }]), + ); - setActivePluginRegistry( - createTestRegistry([{ pluginId: "feishu", source: "test", plugin: feishuPlugin }]), - ); + const tool = createMessageTool({ + config: {} as never, + currentChannelProvider: plugin.id, + }); + const schema = tool.parameters as { + properties?: Record; + required?: string[]; + }; - const tool = createMessageTool({ - config: {} as never, - currentChannelProvider: "feishu", - }); - const schema = tool.parameters as { - properties?: Record; - required?: string[]; - }; - - expect(schema.properties?.card).toBeDefined(); - expect(schema.required ?? []).not.toContain("card"); - }); + expect(schema.properties?.card).toBeDefined(); + expect(schema.required ?? []).not.toContain("card"); + }, + ); it("hides telegram poll extras when telegram polls are disabled in scoped mode", () => { const telegramPluginWithConfig = createChannelPlugin({