mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-08 06:54:24 +00:00
Auto-reply: normalize stop matching and add multilingual triggers (#25103)
* Auto-reply tests: cover multilingual abort triggers * Auto-reply: normalize multilingual abort triggers * Gateway: route chat stop matching through abort parser * Gateway tests: cover chat stop parsing variants * Auto-reply tests: cover Russian and German stop words * Auto-reply: add Russian and German abort triggers * Gateway tests: include Russian and German stop forms * Telegram tests: route Russian and German stop forms to control lane * Changelog: note multilingual abort stop coverage * Changelog: add shared credit for abort shortcut update
This commit is contained in:
@@ -13,7 +13,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
- Subagents/Sessions: add `agents.defaults.subagents.runTimeoutSeconds` so `sessions_spawn` can inherit a configurable default timeout when the tool call omits `runTimeoutSeconds` (unset remains `0`, meaning no timeout). (#24594) Thanks @mitchmcalister.
|
||||
- Config/Kilo Gateway: Kilo provider flow now surfaces an updated list of models. (#24921) thanks @gumadeiras.
|
||||
- Auto-reply/Abort shortcuts: expand standalone stop phrases (`stop openclaw`, `stop action`, `stop run`, `stop agent`, `please stop`, and related variants) and accept trailing punctuation (for example `STOP OPENCLAW!!!`) so emergency stop messages are caught more reliably.
|
||||
- Auto-reply/Abort shortcuts: expand standalone stop phrases (`stop openclaw`, `stop action`, `stop run`, `stop agent`, `please stop`, and related variants), accept trailing punctuation (for example `STOP OPENCLAW!!!`), and add multilingual stop keywords (including ES/FR/ZH/HI/AR/JP/DE/PT/RU forms) so emergency stop messages are caught more reliably. Thanks @steipete and @vincentkoc.
|
||||
|
||||
### Fixes
|
||||
|
||||
|
||||
@@ -147,6 +147,25 @@ describe("abort detection", () => {
|
||||
"STOP OPENCLAW",
|
||||
"stop openclaw!!!",
|
||||
"stop don’t do anything",
|
||||
"detente",
|
||||
"detén",
|
||||
"arrête",
|
||||
"停止",
|
||||
"やめて",
|
||||
"止めて",
|
||||
"रुको",
|
||||
"توقف",
|
||||
"стоп",
|
||||
"остановись",
|
||||
"останови",
|
||||
"остановить",
|
||||
"прекрати",
|
||||
"halt",
|
||||
"anhalten",
|
||||
"aufhören",
|
||||
"hoer auf",
|
||||
"stopp",
|
||||
"pare",
|
||||
];
|
||||
for (const candidate of positives) {
|
||||
expect(isAbortTrigger(candidate)).toBe(true);
|
||||
@@ -164,6 +183,12 @@ describe("abort detection", () => {
|
||||
expect(isAbortRequestText("stop")).toBe(true);
|
||||
expect(isAbortRequestText("stop action")).toBe(true);
|
||||
expect(isAbortRequestText("stop openclaw!!!")).toBe(true);
|
||||
expect(isAbortRequestText("やめて")).toBe(true);
|
||||
expect(isAbortRequestText("остановись")).toBe(true);
|
||||
expect(isAbortRequestText("halt")).toBe(true);
|
||||
expect(isAbortRequestText("stopp")).toBe(true);
|
||||
expect(isAbortRequestText("pare")).toBe(true);
|
||||
expect(isAbortRequestText(" توقف ")).toBe(true);
|
||||
expect(isAbortRequestText("/stop@openclaw_bot", { botUsername: "openclaw_bot" })).toBe(true);
|
||||
|
||||
expect(isAbortRequestText("/status")).toBe(false);
|
||||
|
||||
@@ -30,6 +30,27 @@ const ABORT_TRIGGERS = new Set([
|
||||
"wait",
|
||||
"exit",
|
||||
"interrupt",
|
||||
"detente",
|
||||
"deten",
|
||||
"detén",
|
||||
"arrete",
|
||||
"arrête",
|
||||
"停止",
|
||||
"やめて",
|
||||
"止めて",
|
||||
"रुको",
|
||||
"توقف",
|
||||
"стоп",
|
||||
"остановись",
|
||||
"останови",
|
||||
"остановить",
|
||||
"прекрати",
|
||||
"halt",
|
||||
"anhalten",
|
||||
"aufhören",
|
||||
"hoer auf",
|
||||
"stopp",
|
||||
"pare",
|
||||
"stop openclaw",
|
||||
"openclaw stop",
|
||||
"stop action",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
abortChatRunById,
|
||||
isChatStopCommandText,
|
||||
type ChatAbortOps,
|
||||
type ChatAbortControllerEntry,
|
||||
} from "./chat-abort.js";
|
||||
@@ -42,6 +43,22 @@ function createOps(params: {
|
||||
};
|
||||
}
|
||||
|
||||
describe("isChatStopCommandText", () => {
|
||||
it("matches slash and standalone multilingual stop forms", () => {
|
||||
expect(isChatStopCommandText(" /STOP!!! ")).toBe(true);
|
||||
expect(isChatStopCommandText("stop please")).toBe(true);
|
||||
expect(isChatStopCommandText("停止")).toBe(true);
|
||||
expect(isChatStopCommandText("やめて")).toBe(true);
|
||||
expect(isChatStopCommandText("توقف")).toBe(true);
|
||||
expect(isChatStopCommandText("остановись")).toBe(true);
|
||||
expect(isChatStopCommandText("halt")).toBe(true);
|
||||
expect(isChatStopCommandText("stopp")).toBe(true);
|
||||
expect(isChatStopCommandText("pare")).toBe(true);
|
||||
expect(isChatStopCommandText("/status")).toBe(false);
|
||||
expect(isChatStopCommandText("keep going")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("abortChatRunById", () => {
|
||||
it("broadcasts aborted payload with partial message when buffered text exists", () => {
|
||||
const runId = "run-1";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { isAbortTrigger } from "../auto-reply/reply/abort.js";
|
||||
import { isAbortRequestText } from "../auto-reply/reply/abort.js";
|
||||
|
||||
export type ChatAbortControllerEntry = {
|
||||
controller: AbortController;
|
||||
@@ -9,11 +9,7 @@ export type ChatAbortControllerEntry = {
|
||||
};
|
||||
|
||||
export function isChatStopCommandText(text: string): boolean {
|
||||
const trimmed = text.trim();
|
||||
if (!trimmed) {
|
||||
return false;
|
||||
}
|
||||
return trimmed.toLowerCase() === "/stop" || isAbortTrigger(trimmed);
|
||||
return isAbortRequestText(text);
|
||||
}
|
||||
|
||||
export function resolveChatRunExpiresAtMs(params: {
|
||||
|
||||
@@ -184,6 +184,16 @@ describe("createTelegramBot", () => {
|
||||
message: mockMessage({ chat: mockChat({ id: 123 }), text: "stop please" }),
|
||||
}),
|
||||
).toBe("telegram:123:control");
|
||||
expect(
|
||||
getTelegramSequentialKey({
|
||||
message: mockMessage({ chat: mockChat({ id: 123 }), text: "остановись" }),
|
||||
}),
|
||||
).toBe("telegram:123:control");
|
||||
expect(
|
||||
getTelegramSequentialKey({
|
||||
message: mockMessage({ chat: mockChat({ id: 123 }), text: "halt" }),
|
||||
}),
|
||||
).toBe("telegram:123:control");
|
||||
expect(
|
||||
getTelegramSequentialKey({
|
||||
message: mockMessage({ chat: mockChat({ id: 123 }), text: "/abort" }),
|
||||
|
||||
Reference in New Issue
Block a user