From 5e635c96564af35e9c834aef8177e266d851262f Mon Sep 17 00:00:00 2001 From: Manik Vahsith <49544491+manikv12@users.noreply.github.com> Date: Fri, 30 Jan 2026 00:17:42 -0600 Subject: [PATCH 1/4] feat: add Kimi K2.5 model to synthetic catalog (#4407) * feat: add Kimi K2.5 model to synthetic catalog Add hf:moonshotai/Kimi-K2.5 to the synthetic model catalog. This model is available via dev.synthetic.new API. - 256k context window - 8192 max tokens - Supports reasoning * chore: fix formatting in onboard-helpers.ts * fix: update config candidate ordering test (#4407) (thanks @manikv12) --------- Co-authored-by: Peter Steinberger --- CHANGELOG.md | 1 + src/agents/synthetic-models.ts | 8 ++++++++ src/commands/onboard-helpers.ts | 12 ++++++------ src/config/paths.test.ts | 8 ++++++-- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d09635740..10bcda92f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Status: stable. - Routing: precompile session key regexes. (#1697) Thanks @Ray0907. - CLI: use Node's module compile cache for faster startup. (#2808) Thanks @pi0. - Auth: show copyable Google auth URL after ASCII prompt. (#1787) Thanks @robbyczgw-cla. +- Agents: add Kimi K2.5 to the synthetic model catalog. (#4407) Thanks @manikv12. - TUI: avoid width overflow when rendering selection lists. (#1686) Thanks @mossein. - macOS: finish OpenClaw app rename for macOS sources, bundle identifiers, and shared kit paths. (#2844) Thanks @fal3. - Branding: update launchd labels, mobile bundle IDs, and logging subsystems to bot.molt (legacy com.clawdbot migrations). Thanks @thewilloftheshadow. diff --git a/src/agents/synthetic-models.ts b/src/agents/synthetic-models.ts index e31f3c795..9b9247805 100644 --- a/src/agents/synthetic-models.ts +++ b/src/agents/synthetic-models.ts @@ -99,6 +99,14 @@ export const SYNTHETIC_MODEL_CATALOG = [ contextWindow: 256000, maxTokens: 8192, }, + { + id: "hf:moonshotai/Kimi-K2.5", + name: "Kimi K2.5", + reasoning: true, + input: ["text"], + contextWindow: 256000, + maxTokens: 8192, + }, { id: "hf:openai/gpt-oss-120b", name: "GPT OSS 120B", diff --git a/src/commands/onboard-helpers.ts b/src/commands/onboard-helpers.ts index f56da78e9..774893213 100644 --- a/src/commands/onboard-helpers.ts +++ b/src/commands/onboard-helpers.ts @@ -64,12 +64,12 @@ export function randomToken(): string { export function printWizardHeader(runtime: RuntimeEnv) { const header = [ - "▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄", - "██░▄▄▄░██░▄▄░██░▄▄▄██░▀██░██░▄▄▀██░████░▄▄▀██░███░██", - "██░███░██░▀▀░██░▄▄▄██░█░█░██░█████░████░▀▀░██░█░█░██", - "██░▀▀▀░██░█████░▀▀▀██░██▄░██░▀▀▄██░▀▀░█░██░██▄▀▄▀▄██", - "▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀", - " 🦞 OPENCLAW 🦞 ", + "▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄", + "██░▄▄▄░██░▄▄░██░▄▄▄██░▀██░██░▄▄▀██░████░▄▄▀██░███░██", + "██░███░██░▀▀░██░▄▄▄██░█░█░██░█████░████░▀▀░██░█░█░██", + "██░▀▀▀░██░█████░▀▀▀██░██▄░██░▀▀▄██░▀▀░█░██░██▄▀▄▀▄██", + "▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀", + " 🦞 OPENCLAW 🦞 ", " ", ].join("\n"); runtime.log(header); diff --git a/src/config/paths.test.ts b/src/config/paths.test.ts index 06cd26444..f25e5b000 100644 --- a/src/config/paths.test.ts +++ b/src/config/paths.test.ts @@ -48,8 +48,12 @@ describe("state + config path candidates", () => { it("orders default config candidates in a stable order", () => { const home = "/home/test"; const candidates = resolveDefaultConfigCandidates({} as NodeJS.ProcessEnv, () => home); - expect(candidates[0]).toBe(path.join(home, ".openclaw", "openclaw.json")); - expect(candidates).toHaveLength(1); + const expectedDirs = [".openclaw", ".clawdbot", ".moltbot", ".moldbot"]; + const expectedFiles = ["openclaw.json", "clawdbot.json", "moltbot.json", "moldbot.json"]; + const expected = expectedDirs.flatMap((dir) => + expectedFiles.map((file) => path.join(home, dir, file)), + ); + expect(candidates).toEqual(expected); }); it("prefers ~/.openclaw when it exists and legacy dir is missing", async () => { From 28f8d00e9f075f9fa11e8242e1acf392b78d39ac Mon Sep 17 00:00:00 2001 From: Nate Date: Thu, 29 Jan 2026 23:15:42 -0700 Subject: [PATCH 2/4] fix: update install URLs from clawd.bot to openclaw.ai --- .github/workflows/install-smoke.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/install-smoke.yml b/.github/workflows/install-smoke.yml index 0347c7810..d5d2ef515 100644 --- a/.github/workflows/install-smoke.yml +++ b/.github/workflows/install-smoke.yml @@ -32,8 +32,8 @@ jobs: - name: Run installer docker tests env: - CLAWDBOT_INSTALL_URL: https://clawd.bot/install.sh - CLAWDBOT_INSTALL_CLI_URL: https://clawd.bot/install-cli.sh + CLAWDBOT_INSTALL_URL: https://openclaw.ai/install.sh + CLAWDBOT_INSTALL_CLI_URL: https://openclaw.ai/install-cli.sh CLAWDBOT_NO_ONBOARD: "1" CLAWDBOT_INSTALL_SMOKE_SKIP_CLI: "1" CLAWDBOT_INSTALL_SMOKE_SKIP_NONROOT: ${{ github.event_name == 'pull_request' && '1' || '0' }} From c6ddc95fc0d514758087ca1020c04c49caeee63f Mon Sep 17 00:00:00 2001 From: robhparker Date: Thu, 29 Jan 2026 23:15:33 -0500 Subject: [PATCH 3/4] fix(telegram): scope skill commands to bound agent per bot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit registerTelegramNativeCommands() calls listSkillCommandsForAgents() without passing agentIds, causing ALL agents' skill commands to be registered on EVERY Telegram bot. When multiple agents share skill names (e.g. two agents both have a "butler" skill), the shared `used` Set in listSkillCommandsForAgents causes de-duplication suffixes (_2, _3) and all commands appear on every bot regardless of agent binding. This fix uses the existing resolveAgentRoute() (already imported) to find the bound agent for the current Telegram accountId, then passes that agentId to listSkillCommandsForAgents(). The function already accepts an optional agentIds parameter — it just wasn't wired from the Telegram registration path. Before: All agents' skill commands registered on every Telegram bot, causing /butler_2, /housekeeper_2 dedup suffixes and potential BOT_COMMANDS_TOO_MUCH errors when total exceeds 100. After: Each Telegram bot only registers skill commands for its own bound agent. No cross-agent dedup, no command limit overflow. Co-Authored-By: Claude Opus 4.5 --- src/telegram/bot-native-commands.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/telegram/bot-native-commands.ts b/src/telegram/bot-native-commands.ts index 5f37b81dc..c4b78a09a 100644 --- a/src/telegram/bot-native-commands.ts +++ b/src/telegram/bot-native-commands.ts @@ -257,8 +257,12 @@ export const registerTelegramNativeCommands = ({ shouldSkipUpdate, opts, }: RegisterTelegramNativeCommandsParams) => { + const boundRoute = resolveAgentRoute({ cfg, channel: "telegram", accountId }); + const boundAgentIds = boundRoute?.agentId ? [boundRoute.agentId] : undefined; const skillCommands = - nativeEnabled && nativeSkillsEnabled ? listSkillCommandsForAgents({ cfg }) : []; + nativeEnabled && nativeSkillsEnabled + ? listSkillCommandsForAgents({ cfg, agentIds: boundAgentIds }) + : []; const nativeCommands = nativeEnabled ? listNativeCommandSpecsForConfig(cfg, { skillCommands, provider: "telegram" }) : []; From 9025da2296c11829bf48f0f38c434d6a0ce82fa3 Mon Sep 17 00:00:00 2001 From: Ayaan Zaidi Date: Fri, 30 Jan 2026 11:57:25 +0530 Subject: [PATCH 4/4] fix: scope telegram skill commands per bot (#4360) (thanks @robhparker) --- CHANGELOG.md | 1 + src/telegram/bot-native-commands.test.ts | 82 ++++++++++++++++++++++++ src/telegram/bot-native-commands.ts | 10 ++- 3 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 src/telegram/bot-native-commands.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 10bcda92f..4c0549c16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,6 +73,7 @@ Status: stable. ### Fixes - Telegram: avoid silent empty replies by tracking normalization skips before fallback. (#3796) +- Telegram: scope native skill commands to bound agent per bot. (#4360) Thanks @robhparker. - Mentions: honor mentionPatterns even when explicit mentions are present. (#3303) Thanks @HirokiKobayashi-R. - Discord: restore username directory lookup in target resolution. (#3131) Thanks @bonald. - Agents: align MiniMax base URL test expectation with default provider config. (#3131) Thanks @bonald. diff --git a/src/telegram/bot-native-commands.test.ts b/src/telegram/bot-native-commands.test.ts new file mode 100644 index 000000000..dc6b94dcc --- /dev/null +++ b/src/telegram/bot-native-commands.test.ts @@ -0,0 +1,82 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; + +import type { OpenClawConfig } from "../config/config.js"; +import type { TelegramAccountConfig } from "../config/types.js"; +import type { RuntimeEnv } from "../runtime.js"; +import { registerTelegramNativeCommands } from "./bot-native-commands.js"; + +const { listSkillCommandsForAgents } = vi.hoisted(() => ({ + listSkillCommandsForAgents: vi.fn(() => []), +})); + +vi.mock("../auto-reply/skill-commands.js", () => ({ + listSkillCommandsForAgents, +})); + +describe("registerTelegramNativeCommands", () => { + beforeEach(() => { + listSkillCommandsForAgents.mockReset(); + }); + + const buildParams = (cfg: OpenClawConfig, accountId = "default") => ({ + bot: { + api: { + setMyCommands: vi.fn().mockResolvedValue(undefined), + sendMessage: vi.fn().mockResolvedValue(undefined), + }, + command: vi.fn(), + } as unknown as Parameters[0]["bot"], + cfg, + runtime: {} as RuntimeEnv, + accountId, + telegramCfg: {} as TelegramAccountConfig, + allowFrom: [], + groupAllowFrom: [], + replyToMode: "off" as const, + textLimit: 4096, + useAccessGroups: false, + nativeEnabled: true, + nativeSkillsEnabled: true, + nativeDisabledExplicit: false, + resolveGroupPolicy: () => ({ allowlistEnabled: false, allowed: true }), + resolveTelegramGroupConfig: () => ({ + groupConfig: undefined, + topicConfig: undefined, + }), + shouldSkipUpdate: () => false, + opts: { token: "token" }, + }); + + it("scopes skill commands when account binding exists", () => { + const cfg: OpenClawConfig = { + agents: { + list: [{ id: "main", default: true }, { id: "butler" }], + }, + bindings: [ + { + agentId: "butler", + match: { channel: "telegram", accountId: "bot-a" }, + }, + ], + }; + + registerTelegramNativeCommands(buildParams(cfg, "bot-a")); + + expect(listSkillCommandsForAgents).toHaveBeenCalledWith({ + cfg, + agentIds: ["butler"], + }); + }); + + it("keeps skill commands unscoped without a matching binding", () => { + const cfg: OpenClawConfig = { + agents: { + list: [{ id: "main", default: true }, { id: "butler" }], + }, + }; + + registerTelegramNativeCommands(buildParams(cfg, "bot-a")); + + expect(listSkillCommandsForAgents).toHaveBeenCalledWith({ cfg }); + }); +}); diff --git a/src/telegram/bot-native-commands.ts b/src/telegram/bot-native-commands.ts index c4b78a09a..cd53459e6 100644 --- a/src/telegram/bot-native-commands.ts +++ b/src/telegram/bot-native-commands.ts @@ -257,11 +257,15 @@ export const registerTelegramNativeCommands = ({ shouldSkipUpdate, opts, }: RegisterTelegramNativeCommandsParams) => { - const boundRoute = resolveAgentRoute({ cfg, channel: "telegram", accountId }); - const boundAgentIds = boundRoute?.agentId ? [boundRoute.agentId] : undefined; + const boundRoute = + nativeEnabled && nativeSkillsEnabled + ? resolveAgentRoute({ cfg, channel: "telegram", accountId }) + : null; + const boundAgentIds = + boundRoute && boundRoute.matchedBy.startsWith("binding.") ? [boundRoute.agentId] : null; const skillCommands = nativeEnabled && nativeSkillsEnabled - ? listSkillCommandsForAgents({ cfg, agentIds: boundAgentIds }) + ? listSkillCommandsForAgents(boundAgentIds ? { cfg, agentIds: boundAgentIds } : { cfg }) : []; const nativeCommands = nativeEnabled ? listNativeCommandSpecsForConfig(cfg, { skillCommands, provider: "telegram" })