mirror of
https://github.com/earendil-works/pi.git
synced 2026-06-18 15:54:04 +08:00
Merge pull request #5195 from yzhg1983/private/fix-startup-input-queue
fix(coding-agent): buffer early input before prompt loop
This commit is contained in:
@@ -277,6 +277,7 @@ export class InteractiveMode {
|
||||
private version: string;
|
||||
private isInitialized = false;
|
||||
private onInputCallback?: (text: string) => void;
|
||||
private pendingUserInputs: string[] = [];
|
||||
private loadingAnimation: Loader | undefined = undefined;
|
||||
private workingMessage: string | undefined = undefined;
|
||||
private workingVisible = true;
|
||||
@@ -2660,6 +2661,8 @@ export class InteractiveMode {
|
||||
|
||||
if (this.onInputCallback) {
|
||||
this.onInputCallback(text);
|
||||
} else {
|
||||
this.pendingUserInputs.push(text);
|
||||
}
|
||||
this.editor.addToHistory?.(text);
|
||||
};
|
||||
@@ -3231,6 +3234,11 @@ export class InteractiveMode {
|
||||
}
|
||||
|
||||
async getUserInput(): Promise<string> {
|
||||
const queuedInput = this.pendingUserInputs.shift();
|
||||
if (queuedInput !== undefined) {
|
||||
return queuedInput;
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.onInputCallback = (text: string) => {
|
||||
this.onInputCallback = undefined;
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { InteractiveMode } from "../src/modes/interactive/interactive-mode.ts";
|
||||
|
||||
type SubmitContext = {
|
||||
defaultEditor: { onSubmit?: (text: string) => void };
|
||||
editor: {
|
||||
addToHistory?: (text: string) => void;
|
||||
setText: (text: string) => void;
|
||||
};
|
||||
session: {
|
||||
isCompacting: boolean;
|
||||
isStreaming: boolean;
|
||||
isBashRunning: boolean;
|
||||
prompt: (text: string, options?: unknown) => Promise<void>;
|
||||
};
|
||||
flushPendingBashComponents: () => void;
|
||||
onInputCallback?: (text: string) => void;
|
||||
pendingUserInputs: string[];
|
||||
};
|
||||
|
||||
type InputContext = {
|
||||
onInputCallback?: (text: string) => void;
|
||||
pendingUserInputs: string[];
|
||||
};
|
||||
|
||||
type InteractiveModePrivate = {
|
||||
setupEditorSubmitHandler(this: SubmitContext): void;
|
||||
getUserInput(this: InputContext): Promise<string>;
|
||||
};
|
||||
|
||||
const interactiveModePrototype = InteractiveMode.prototype as unknown as InteractiveModePrivate;
|
||||
|
||||
function createSubmitContext(): SubmitContext {
|
||||
return {
|
||||
defaultEditor: {},
|
||||
editor: {
|
||||
addToHistory: vi.fn(),
|
||||
setText: vi.fn(),
|
||||
},
|
||||
session: {
|
||||
isCompacting: false,
|
||||
isStreaming: false,
|
||||
isBashRunning: false,
|
||||
prompt: vi.fn(async () => {}),
|
||||
},
|
||||
flushPendingBashComponents: vi.fn(),
|
||||
pendingUserInputs: [],
|
||||
};
|
||||
}
|
||||
|
||||
describe("InteractiveMode startup input", () => {
|
||||
it("queues a normal prompt submitted before the input callback is installed", async () => {
|
||||
const context = createSubmitContext();
|
||||
interactiveModePrototype.setupEditorSubmitHandler.call(context);
|
||||
|
||||
await context.defaultEditor.onSubmit?.(" early prompt ");
|
||||
|
||||
expect(context.pendingUserInputs).toEqual(["early prompt"]);
|
||||
expect(context.flushPendingBashComponents).toHaveBeenCalledTimes(1);
|
||||
expect(context.editor.addToHistory).toHaveBeenCalledWith("early prompt");
|
||||
});
|
||||
|
||||
it("returns queued startup input before installing a new input callback", async () => {
|
||||
const context: InputContext = {
|
||||
pendingUserInputs: ["queued prompt"],
|
||||
};
|
||||
|
||||
await expect(interactiveModePrototype.getUserInput.call(context)).resolves.toBe("queued prompt");
|
||||
expect(context.onInputCallback).toBeUndefined();
|
||||
expect(context.pendingUserInputs).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user