Merge branch 'can1357:main' into main

This commit is contained in:
Daniel Young
2026-08-18 12:10:24 -04:00
committed by GitHub
3 changed files with 19 additions and 5 deletions
+7 -2
View File
@@ -279,7 +279,11 @@ describe("Agent", () => {
});
it("keeps follow-up ownership when the deadline expires during a dequeue hook", async () => {
const mock = createMockModel({ responses: [{ content: ["done"] }] });
const agent = new Agent({ streamFn: mock.stream, deadline: Date.now() + 25 });
// Generous budget: the loop checks the deadline before invoking dequeue
// hooks, so the mock roundtrip must beat it even on starved CI runners.
// The hook itself parks until the deadline timer aborts the loop signal,
// so the expiry-during-hook branch stays exercised.
const agent = new Agent({ streamFn: mock.stream, deadline: Date.now() + 1_000 });
let hookSignal: AbortSignal | undefined;
agent.addBeforeQueuedMessageDequeueHook(async signal => {
if (!signal) throw new Error("Expected the active loop signal");
@@ -297,7 +301,8 @@ describe("Agent", () => {
expect(agent.peekFollowUpQueue()).toHaveLength(1);
});
it("keeps queued work when continue() reaches its deadline inside a dequeue hook", async () => {
const agent = new Agent({ deadline: Date.now() + 25 });
// Same starvation guard as above: hook entry must precede expiry.
const agent = new Agent({ deadline: Date.now() + 1_000 });
agent.replaceMessages([createAssistantMessage([{ type: "text", text: "ready" }])]);
agent.addBeforeQueuedMessageDequeueHook(async signal => {
if (!signal) throw new Error("Expected the deadline-aware dequeue signal");
+1 -1
View File
@@ -1025,7 +1025,7 @@ describe("Editor component", () => {
await terminal.waitForRender();
for (const char of "ast") editor.handleInput(char);
tui.requestRender();
await terminal.waitForRender();
await terminal.waitForRender(() => terminal.getViewport()[1]?.includes("ast") === true);
const beforePreedit = terminal.getViewport().map(row => row.trimEnd());
expect(beforePreedit.slice(0, 3)).toEqual(["+------------------+", "| ast", "+------------------+"]);
+11 -2
View File
@@ -280,12 +280,21 @@ export class VirtualTerminal implements Terminal {
// --- Test-only helpers ---------------------------------------------------
/** Wait for TUI's throttled render pipeline to settle (matches the ~33ms frame budget). */
async waitForRender(): Promise<void> {
/**
* Wait for TUI's throttled render pipeline to settle (matches the ~33ms
* frame budget). Fixed sleeps race starved CI timers, so callers asserting
* on a specific frame pass `until`; polling continues (10ms slices, ~2s
* cap) until the predicate observes the expected viewport.
*/
async waitForRender(until?: () => boolean): Promise<void> {
const nextTick = Promise.withResolvers<void>();
process.nextTick(nextTick.resolve);
await nextTick.promise;
await Bun.sleep(40);
if (until) {
const deadline = Date.now() + 2_000;
while (!until() && Date.now() < deadline) await Bun.sleep(10);
}
await this.flush();
}