fix(coding-agent): detect non-English questions in todo reminder guard

The isAwaitingUserAnswer guard that suppresses the todo completion reminder while the agent waits on a user question only recognized English question words and pronouns. A '?'/'?'-terminated Chinese, Japanese, Korean, or Spanish prompt went undetected, so the <system-reminder> interrupted the pause and the model misread it as the user's answer.

isQuestionPromptLine now also treats a question-mark-terminated line containing any non-ASCII character as a pending user question.

Fixes #7803
This commit is contained in:
roboomp
2026-08-06 06:47:27 +00:00
parent 1e492d6ff9
commit 181f63ebc0
3 changed files with 26 additions and 1 deletions
+4
View File
@@ -2,6 +2,10 @@
## [Unreleased]
### Fixed
- Fixed the todo completion reminder still firing while the agent was waiting on a user question asked in a non-English language. The `isAwaitingUserAnswer` guard only recognized English question words and pronouns, so a `?`/`?`-terminated Chinese, Japanese, Korean, or Spanish prompt (e.g. `我应该继续吗?`) went undetected and the `<system-reminder>` interrupted the pause — which the model then misread as the user's answer and acted on. A trailing question mark plus any non-ASCII character in the line now counts as a pending question ([#7803](https://github.com/can1357/oh-my-pi/issues/7803)).
## [17.2.9] - 2026-08-05
### Breaking Changes
@@ -27,6 +27,15 @@ const QUESTION_PROMPT_RE =
const USER_DIRECTED_PROMPT_RE = /\b(?:you|your|we|our)\b/i;
const USER_RESPONSE_CUE_RE =
/^(?:please\s+)?(?:confirm|reply|choose|pick|decide|advise)\b|^(?:please\s+)?answer\b|^(?:please\s+)?(?:let\s+me\s+know|tell\s+me)\b/i;
/**
* A trailing question mark is the universal signal that a line is a question, but
* the English word/pronoun gates above exist to filter incidental "?" out of prose
* (e.g. a TypeScript `foo?: string` tail). Non-English text has no cheap word list,
* yet any non-ASCII character in a "?"/"?"-terminated line reliably marks it as
* genuine prose — CJK/Japanese/Korean, Spanish `¿…?`, accented Latin — so treat it
* as a real user-directed question. Fixes non-Latin prompts going undetected (#7803).
*/
const NON_ASCII_TEXT_RE = /[^\x00-\x7F]/;
interface PromptLine {
text: string;
@@ -361,7 +370,8 @@ function isQuestionPromptLine(line: string): boolean {
return (
candidate.hadPromptLabel ||
QUESTION_PROMPT_RE.test(candidate.text) ||
USER_DIRECTED_PROMPT_RE.test(candidate.text)
USER_DIRECTED_PROMPT_RE.test(candidate.text) ||
NON_ASCII_TEXT_RE.test(candidate.text)
);
}
@@ -186,6 +186,17 @@ describe("AgentSession todo reminder self-continuation suppression", () => {
expect(continueSpy).not.toHaveBeenCalled();
});
it("does not remind or continue when the assistant yields with a non-English (Chinese) question", async () => {
const continueSpy = vi.spyOn(session.agent, "continue").mockResolvedValue();
emitTextOnlyStop("我遇到一个需要你决定的问题:是否应该继续删除旧的配置文件?");
await session.waitForIdle();
expect(reminderAttempts).toEqual([]);
expect(todoReminderTranscriptEntry()).toBeUndefined();
expect(continueSpy).not.toHaveBeenCalled();
});
it("still reminds when the assistant answers its own prompt-shaped question", async () => {
const continueSpy = vi.spyOn(session.agent, "continue").mockResolvedValue();