fix: event-loop freezes, plugin-install boot crash, tmux attach/scrollbar, Codex transcripts
- GET /api/workflows: one LEAD() window pass in a read worker (read-pool.js, workflow-stats.js); idx_events_session restored, idx_events_tool added - compat-sqlite gains function/pluck/readonly so a plugin install without a better-sqlite3 build boots again; antigravity-usage uses db.js's Database - install-hooks adds no checkout hooks while the agenthub plugin is enabled (events were doubled) - terminal attach runs the live tmux server's own binary; the pane scrollbar gets a visible 2-column style, and claude panes start with CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN=1 so tmux keeps history to scroll - Codex sessions' conversation in GET /api/sessions/:id/transcript - Codex/Antigravity sessions claimed by their workspace without hooks - UI-audit follow-ups, docs and OpenAPI
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @file runWorktree.test.ts
|
||||
* @description The Changes panel's worktree session for a `?run=` pane survives
|
||||
* a poll that misses the run, and follows every real answer.
|
||||
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
||||
*/
|
||||
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { runWorktreeSession } from "../runWorktree";
|
||||
|
||||
const wt = { worktree: true, sessionId: "s1" };
|
||||
|
||||
describe("runWorktreeSession", () => {
|
||||
it("follows the listed run's worktree session", () => {
|
||||
expect(runWorktreeSession(null, "r1", wt)).toEqual({ run: "r1", session: "s1" });
|
||||
expect(runWorktreeSession(null, "r1", { worktree: false, sessionId: "s1" })).toBeNull();
|
||||
});
|
||||
|
||||
it("keeps the last answer through a poll that misses the run", () => {
|
||||
const prev = runWorktreeSession(null, "r1", wt);
|
||||
expect(runWorktreeSession(prev, "r1", undefined)).toEqual({ run: "r1", session: "s1" });
|
||||
});
|
||||
|
||||
it("drops it for another run or no run", () => {
|
||||
const prev = runWorktreeSession(null, "r1", wt);
|
||||
expect(runWorktreeSession(prev, "r2", undefined)).toBeNull();
|
||||
expect(runWorktreeSession(prev, null, undefined)).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @file toast.test.ts
|
||||
* @description The toast queue: at most four on screen, and an error — which
|
||||
* stays until dismissed — is never the one pushed out by newer toasts.
|
||||
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
||||
*/
|
||||
|
||||
import { describe, it, expect, afterEach } from "vitest";
|
||||
import { toast, subscribeToasts, dismissToast, type ToastItem } from "../toast";
|
||||
|
||||
let current: ToastItem[] = [];
|
||||
const unsubscribe = subscribeToasts((items) => (current = items));
|
||||
|
||||
afterEach(() => {
|
||||
for (const t of current) dismissToast(t.id);
|
||||
});
|
||||
|
||||
describe("toast queue", () => {
|
||||
it("keeps an unread error when newer toasts overflow the queue", () => {
|
||||
toast.error("save failed");
|
||||
for (let i = 0; i < 5; i++) toast.success(`copied ${i}`);
|
||||
expect(current).toHaveLength(4);
|
||||
expect(current.map((t) => t.message)).toContain("save failed");
|
||||
expect(current[current.length - 1]?.message).toBe("copied 4");
|
||||
});
|
||||
|
||||
it("still shows the newest toast when only errors are queued", () => {
|
||||
for (let i = 0; i < 4; i++) toast.error(`error ${i}`);
|
||||
toast.info("hello");
|
||||
expect(current).toHaveLength(4);
|
||||
expect(current[current.length - 1]?.message).toBe("hello");
|
||||
});
|
||||
});
|
||||
|
||||
void unsubscribe;
|
||||
Reference in New Issue
Block a user