diff --git a/CHANGELOG.md b/CHANGELOG.md index b0b6e8a729f..a587626e608 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- Model directives/Auth profiles: split `/model` profile suffixes at the first `@` after the last slash so email-based auth profile IDs (for example OAuth profile IDs) resolve correctly. Landed from contributor PR #30932 by @haosenwang1018. Thanks @haosenwang1018. - Windows/Plugin install: avoid `spawn EINVAL` on Windows npm/npx invocations by resolving to `node` + npm CLI scripts instead of spawning `.cmd` directly. Landed from contributor PR #31147 by @codertony. Thanks @codertony. - LINE/Voice transcription: classify M4A voice media as `audio/mp4` (not `video/mp4`) by checking the MPEG-4 `ftyp` major brand (`M4A ` / `M4B `), restoring voice transcription for LINE voice messages. Landed from contributor PR #31151 by @scoootscooob. Thanks @scoootscooob. - Cron/Delivery mode none: send explicit `delivery: { mode: "none" }` from cron editor for both add and update flows so previous announce delivery is actually cleared. Landed from contributor PR #31145 by @byungsker. Thanks @byungsker. diff --git a/src/agents/model-ref-profile.test.ts b/src/agents/model-ref-profile.test.ts index 68ba917c2c1..92c2211eff7 100644 --- a/src/agents/model-ref-profile.test.ts +++ b/src/agents/model-ref-profile.test.ts @@ -46,4 +46,11 @@ describe("splitTrailingAuthProfile", () => { model: "provider/foo@bar/baz", }); }); + + it("uses first @ after last slash for email-based auth profiles", () => { + expect(splitTrailingAuthProfile("flash@google-gemini-cli:test@gmail.com")).toEqual({ + model: "flash", + profile: "google-gemini-cli:test@gmail.com", + }); + }); }); diff --git a/src/agents/model-ref-profile.ts b/src/agents/model-ref-profile.ts index 76f8108ddf2..54ec79f905f 100644 --- a/src/agents/model-ref-profile.ts +++ b/src/agents/model-ref-profile.ts @@ -7,9 +7,9 @@ export function splitTrailingAuthProfile(raw: string): { return { model: "" }; } - const profileDelimiter = trimmed.lastIndexOf("@"); const lastSlash = trimmed.lastIndexOf("/"); - if (profileDelimiter <= 0 || profileDelimiter <= lastSlash) { + const profileDelimiter = trimmed.indexOf("@", lastSlash + 1); + if (profileDelimiter <= 0) { return { model: trimmed }; } diff --git a/src/telegram/bot.create-telegram-bot.test.ts b/src/telegram/bot.create-telegram-bot.test.ts index fbaed5fc651..4196b1c9851 100644 --- a/src/telegram/bot.create-telegram-bot.test.ts +++ b/src/telegram/bot.create-telegram-bot.test.ts @@ -1775,10 +1775,14 @@ describe("createTelegramBot", () => { }); expect(sendMessageSpy.mock.calls.length).toBeGreaterThan(1); - for (const call of sendMessageSpy.mock.calls) { - expect((call[2] as { reply_to_message_id?: number } | undefined)?.reply_to_message_id).toBe( - messageId, - ); + for (const [index, call] of sendMessageSpy.mock.calls.entries()) { + const actual = (call[2] as { reply_to_message_id?: number } | undefined) + ?.reply_to_message_id; + if (mode === "all" || index === 0) { + expect(actual).toBe(messageId); + } else { + expect(actual).toBeUndefined(); + } } } }); diff --git a/src/telegram/bot/delivery.ts b/src/telegram/bot/delivery.ts index dce22202d4a..62e5f01ea3c 100644 --- a/src/telegram/bot/delivery.ts +++ b/src/telegram/bot/delivery.ts @@ -294,7 +294,7 @@ export async function deliverReplies(params: { replyMarkup, }); } - if (replyToMessageIdForPayload && !hasReplied) { + if (replyToMessageId && !hasReplied) { hasReplied = true; } continue;