feat: v2.5.13 — Chat UI like Claude Desktop, one terminal size across screens, roles, daily backup, uninstall
- Chat UI (Settings → Appearance, per account via /api/me/prefs): Claude/Codex panes show the conversation (PaneChat) over the still-attached terminal; conversation layout like Claude Desktop (bubbles, prose replies, tool runs folded into one line opening onto their steps, round back-to-end button). - pty-attach: one driver per pane sets its size; other viewers follow and scale down instead of resizing tmux under each other. - Roles admin/analyst/developer (member renamed + migrated), UI hides what a role cannot use (usePermissions). - Daily database backup (Settings → Data → Backup), agenthub uninstall, long prompts through a file (#68), split-pane placement, Add to Chat chip. Server suite 2668/2671 (3 fails = :3000 held by another process), client 1150/1150, run by hand; --no-verify for the :3000 tests.
This commit is contained in:
@@ -69,6 +69,7 @@ vi.mock("@xterm/xterm", () => ({
|
||||
attachCustomKeyEventHandler: keyHandlerMock,
|
||||
focus: focusMock,
|
||||
paste: pasteMock,
|
||||
resize: (cols: number, rows: number) => Object.assign(termState, { cols, rows }),
|
||||
})),
|
||||
}));
|
||||
// jsdom loads no stylesheet, so stand in for the CSS-variable probe.
|
||||
@@ -368,7 +369,9 @@ describe("TerminalView", () => {
|
||||
render(<TerminalView runId="agenthub-lane-1" wsBaseUrl="ws://localhost:4820" />);
|
||||
const ws = MockWebSocket.instances[0]!;
|
||||
ws.onopen?.();
|
||||
expect(ws.sent).toContain(JSON.stringify({ type: "resize", cols: 131, rows: 28 }));
|
||||
expect(ws.sent).toContain(
|
||||
JSON.stringify({ type: "resize", cols: 131, rows: 28, drive: false })
|
||||
);
|
||||
});
|
||||
|
||||
it("reports a size change xterm made on its own, with no container resize", async () => {
|
||||
@@ -385,7 +388,34 @@ describe("TerminalView", () => {
|
||||
onResizeHandlers.forEach((fn) => fn());
|
||||
expect(ws.sent).toEqual([]);
|
||||
await new Promise((r) => setTimeout(r, 200));
|
||||
expect(ws.sent).toEqual([JSON.stringify({ type: "resize", cols: 127, rows: 28 })]);
|
||||
expect(ws.sent).toEqual([
|
||||
JSON.stringify({ type: "resize", cols: 127, rows: 28, drive: false }),
|
||||
]);
|
||||
});
|
||||
|
||||
it("follows another browser's size until a keystroke here takes the lead", () => {
|
||||
// Two browsers of different sizes on one pane: the one not in use renders
|
||||
// the driver's grid instead of resizing tmux under it.
|
||||
const w = vi.spyOn(HTMLElement.prototype, "clientWidth", "get").mockReturnValue(800);
|
||||
const h = vi.spyOn(HTMLElement.prototype, "clientHeight", "get").mockReturnValue(600);
|
||||
try {
|
||||
render(<TerminalView runId="agenthub-lane-1" wsBaseUrl="ws://localhost:4820" />);
|
||||
const ws = MockWebSocket.instances[0]!;
|
||||
ws.onopen?.();
|
||||
ws.onmessage?.({ data: '{"type":"size","cols":90,"rows":20}' });
|
||||
expect([termState.cols, termState.rows]).toEqual([90, 20]);
|
||||
ws.sent.length = 0;
|
||||
onDataHandlers.forEach((fn) => fn("\x1b[<64;5;5M")); // a wheel notch
|
||||
expect(ws.sent).toEqual(["\x1b[<64;5;5M"]);
|
||||
onDataHandlers.forEach((fn) => fn("a"));
|
||||
expect(ws.sent[1]).toBe(
|
||||
JSON.stringify({ type: "resize", cols: 90, rows: 20, drive: true })
|
||||
);
|
||||
expect(ws.sent[2]).toBe("a");
|
||||
} finally {
|
||||
w.mockRestore();
|
||||
h.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
it("never reports a collapsed console's zero size", () => {
|
||||
|
||||
Reference in New Issue
Block a user