fix(ask): preserve prior answer when custom editor dismissed in single-select
This commit is contained in:
@@ -331,12 +331,12 @@ async function askSingleQuestion(
|
||||
} else if (choice === OTHER_OPTION) {
|
||||
if (!selectTimedOut) {
|
||||
const customResult = await promptForCustomInput();
|
||||
if (customResult.input === undefined) {
|
||||
return { selectedOptions, customInput, timedOut, cancelled: true };
|
||||
if (customResult.input !== undefined) {
|
||||
customInput = customResult.input;
|
||||
selectedOptions = [];
|
||||
}
|
||||
customInput = customResult.input;
|
||||
// If editor was dismissed (undefined), keep prior selectedOptions/customInput intact
|
||||
}
|
||||
selectedOptions = [];
|
||||
} else {
|
||||
selectedOptions = [stripRecommendedSuffix(choice)];
|
||||
customInput = undefined;
|
||||
|
||||
@@ -411,7 +411,7 @@ describe("AskTool custom input", () => {
|
||||
expect(abort).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("aborts when editor is cancelled after choosing Other in multi-question flow", async () => {
|
||||
it("continues multi-question flow when editor is dismissed on a fresh question", async () => {
|
||||
const tool = new AskTool(createSession());
|
||||
const abort = vi.fn();
|
||||
const editor = vi.fn(async () => undefined);
|
||||
@@ -437,11 +437,14 @@ describe("AskTool custom input", () => {
|
||||
abort,
|
||||
});
|
||||
|
||||
await expect(
|
||||
tool.execute("call-editor-multi-cancel", { questions }, undefined, undefined, context),
|
||||
).rejects.toBeInstanceOf(ToolAbortError);
|
||||
const result = await tool.execute("call-editor-multi-dismiss", { questions }, undefined, undefined, context);
|
||||
|
||||
// Editor dismissed on "Details?" — flow continues with empty answer, not abort
|
||||
expect(result.details?.results?.[0]?.selectedOptions).toEqual(["one"]);
|
||||
expect(result.details?.results?.[1]?.selectedOptions).toEqual([]);
|
||||
expect(result.details?.results?.[1]?.customInput).toBeUndefined();
|
||||
expect(editor).toHaveBeenCalledTimes(1);
|
||||
expect(abort).toHaveBeenCalledTimes(1);
|
||||
expect(abort).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("surfaces external abort during editor mode as ToolAbortError", async () => {
|
||||
@@ -895,4 +898,53 @@ describe("AskTool multi-question navigation", () => {
|
||||
expect(result.details?.results?.[1]?.selectedOptions).toEqual(["two"]);
|
||||
expect(editor).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("preserves prior single-select answer when custom editor is dismissed during navigation", async () => {
|
||||
const tool = new AskTool(createSession());
|
||||
let detailVisits = 0;
|
||||
const editor = vi.fn(async () => undefined);
|
||||
const questions = [
|
||||
{
|
||||
id: "details",
|
||||
question: "Details?",
|
||||
options: [{ label: "short" }, { label: "long" }],
|
||||
},
|
||||
{
|
||||
id: "summary",
|
||||
question: "Summary?",
|
||||
options: [{ label: "one" }, { label: "two" }],
|
||||
},
|
||||
];
|
||||
const context = createContext({
|
||||
select: async (prompt, _options, dialogOptions) => {
|
||||
if (prompt.includes("Details?")) {
|
||||
detailVisits += 1;
|
||||
if (detailVisits === 1) return "short";
|
||||
// Second visit: try Other then dismiss editor, then forward
|
||||
if (detailVisits === 2) return "Other (type your own)";
|
||||
dialogOptions?.onRight?.();
|
||||
return undefined;
|
||||
}
|
||||
if (prompt.includes("Summary?")) {
|
||||
const summaryVisit = detailVisits;
|
||||
if (summaryVisit <= 2) {
|
||||
// Navigate back to re-visit details
|
||||
dialogOptions?.onLeft?.();
|
||||
return undefined;
|
||||
}
|
||||
return "two";
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
editor,
|
||||
});
|
||||
|
||||
const result = await tool.execute("call-nav-single-dismiss", { questions }, undefined, undefined, context);
|
||||
|
||||
// The prior selection "short" should survive the editor dismiss
|
||||
expect(result.details?.results?.[0]?.selectedOptions).toEqual(["short"]);
|
||||
expect(result.details?.results?.[0]?.customInput).toBeUndefined();
|
||||
expect(result.details?.results?.[1]?.selectedOptions).toEqual(["two"]);
|
||||
expect(editor).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user