mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-09-04 10:11:46 +03:00
fix(tui): reduce redundant runtime chrome
This commit is contained in:
+59
-7
@@ -1,5 +1,5 @@
|
||||
import { afterEach, describe, expect, test } from "bun:test"
|
||||
import { CliRenderEvents, TextareaRenderable, TextRenderable } from "@opentui/core"
|
||||
import { BoxRenderable, CliRenderEvents, TextareaRenderable, TextRenderable } from "@opentui/core"
|
||||
import {
|
||||
MockTreeSitterClient,
|
||||
createTestRenderer,
|
||||
@@ -1279,9 +1279,9 @@ describe("NanobotTui layout", () => {
|
||||
expect(setup.renderer.width).toBe(width)
|
||||
expect(setup.renderer.height).toBe(height)
|
||||
expect(frame).not.toContain("undefined")
|
||||
expect(occurrences(frame, "Ask nanobot anything")).toBeLessThanOrEqual(1)
|
||||
expect(occurrences(frame, "Steer this turn…")).toBeLessThanOrEqual(1)
|
||||
if (width >= 30 && height >= 9) {
|
||||
expect(occurrences(frame, "Ask nanobot anything")).toBe(1)
|
||||
expect(occurrences(frame, "Steer this turn…")).toBe(1)
|
||||
}
|
||||
expect(occurrences(frame, "nanobot · test/model")).toBe(height >= 14 ? 1 : 0)
|
||||
}
|
||||
@@ -1774,13 +1774,18 @@ describe("NanobotTui layout", () => {
|
||||
expect(frame).toMatch(/Thinking\s+0s/u)
|
||||
expect(frame).not.toMatch(/[◐◓◑◒⠋⠙⠹⠸]/u)
|
||||
expect(frame).not.toContain("hidden reasoning")
|
||||
const status = (app as unknown as {
|
||||
const ui = app as unknown as {
|
||||
status: {
|
||||
content: { chunks: Array<{ fg?: { toInts(): number[] } }> }
|
||||
plainText: string
|
||||
}
|
||||
}).status
|
||||
composer: TextareaRenderable
|
||||
composerFrame: BoxRenderable
|
||||
}
|
||||
const status = ui.status
|
||||
expect(status.plainText).toMatch(/^Thinking\s+0s/u)
|
||||
expect(ui.composer.placeholder).toBe("Steer this turn…")
|
||||
expect(ui.composerFrame.height).toBe(3)
|
||||
const shimmerColors = new Set(
|
||||
status.content.chunks
|
||||
.slice(0, "Thinking".length)
|
||||
@@ -1803,7 +1808,11 @@ describe("NanobotTui layout", () => {
|
||||
expect(frame).toMatch(/Working\s+0s/u)
|
||||
expect(frame).not.toMatch(/[◐◓◑◒⠋⠙⠹⠸]/u)
|
||||
expect(frame).toContain("› Running pwd")
|
||||
expect(occurrences(frame, "pwd")).toBe(1)
|
||||
expect(status.plainText).not.toContain("pwd")
|
||||
app.accept({ event: "turn_end", chat_id: "chat" })
|
||||
await setup.flush()
|
||||
expect(ui.composer.placeholder).toBe("Ask nanobot anything")
|
||||
})
|
||||
|
||||
test("folds long tool traces without discarding their details", async () => {
|
||||
@@ -1823,8 +1832,9 @@ describe("NanobotTui layout", () => {
|
||||
await setup.renderOnce()
|
||||
let frame = setup.captureCharFrame()
|
||||
|
||||
expect(frame).toContain("5 earlier steps · Ctrl+O expand")
|
||||
expect(frame).toContain("7 earlier steps · Ctrl+O expand")
|
||||
expect(frame).not.toContain("tool_0")
|
||||
expect(frame).toContain("tool_7")
|
||||
expect(frame).toContain("tool_9")
|
||||
|
||||
setup.mockInput.pressKey("O", { ctrl: true })
|
||||
@@ -1860,6 +1870,37 @@ describe("NanobotTui layout", () => {
|
||||
app.accept({ event: "turn_end", chat_id: "chat" })
|
||||
})
|
||||
|
||||
test("groups consecutive file activity only in the collapsed preview", async () => {
|
||||
setup = await createRenderer({ width: 72, height: 20, screenMode: "alternate-screen" })
|
||||
const app = mount(setup)
|
||||
app.accept({
|
||||
event: "message",
|
||||
chat_id: "chat",
|
||||
text: "file progress",
|
||||
kind: "tool_hint",
|
||||
tool_events: Array.from({ length: 6 }, (_, index) => ({
|
||||
phase: "end" as const,
|
||||
call_id: `read-${index}`,
|
||||
name: "read_file",
|
||||
arguments: { path: `/tmp/nanobot-workspace/src/file-${index}.ts` },
|
||||
})),
|
||||
})
|
||||
await setup.renderOnce()
|
||||
let frame = setup.captureCharFrame()
|
||||
|
||||
expect(frame).toContain("6 steps · Ctrl+O expand")
|
||||
expect(frame).toContain("✓ Read 6 files")
|
||||
expect(frame).not.toContain("src/file-0.ts")
|
||||
|
||||
setup.mockInput.pressKey("O", { ctrl: true })
|
||||
await setup.renderOnce()
|
||||
frame = setup.captureCharFrame()
|
||||
|
||||
expect(frame).not.toContain("Read 6 files")
|
||||
expect(frame).toContain("src/file-0.ts")
|
||||
expect(frame).toContain("src/file-5.ts")
|
||||
})
|
||||
|
||||
test("supports keyboard transcript navigation without rebuilding the layout", async () => {
|
||||
setup = await createRenderer({ width: 64, height: 16, screenMode: "alternate-screen" })
|
||||
const app = mount(setup)
|
||||
@@ -2235,6 +2276,10 @@ describe("NanobotTui in a Herdr pane", () => {
|
||||
new MockTreeSitterClient({ autoResolveTimeout: 0 }),
|
||||
host,
|
||||
)
|
||||
const ui = app as unknown as {
|
||||
composer: TextareaRenderable
|
||||
composerFrame: BoxRenderable
|
||||
}
|
||||
|
||||
await setup.mockInput.typeText("/")
|
||||
await setup.flush()
|
||||
@@ -2243,6 +2288,7 @@ describe("NanobotTui in a Herdr pane", () => {
|
||||
expect(commandFrame).toContain("/new-chat")
|
||||
expect(commandFrame).toContain("/branch")
|
||||
setup.mockInput.pressEscape()
|
||||
ui.composer.setText("")
|
||||
|
||||
app.accept({ event: "attached", chat_id: "chat" })
|
||||
app.accept({
|
||||
@@ -2259,6 +2305,12 @@ describe("NanobotTui in a Herdr pane", () => {
|
||||
kind: "tool_hint",
|
||||
tool_events: [{ phase: "end", call_id: "read", name: "read_file", arguments: { path: "app.ts" } }],
|
||||
})
|
||||
await setup.flush()
|
||||
const activeFrame = setup.captureCharFrame()
|
||||
expect(occurrences(activeFrame, "› Ship the Herdr integration")).toBe(1)
|
||||
expect(occurrences(activeFrame, "app.ts")).toBe(1)
|
||||
expect(ui.composer.placeholder).toBe("Steer this turn…")
|
||||
expect(ui.composerFrame.height).toBe(3)
|
||||
app.accept({
|
||||
event: "turn_end",
|
||||
chat_id: "chat",
|
||||
@@ -2273,7 +2325,7 @@ describe("NanobotTui in a Herdr pane", () => {
|
||||
const frame = setup.captureCharFrame()
|
||||
|
||||
expect(sessions).toEqual(["chat"])
|
||||
expect(frame).toContain("› Ship the Herdr integration")
|
||||
expect(occurrences(frame, "› Ship the Herdr integration")).toBe(1)
|
||||
expect(frame).not.toContain(">_ nanobot")
|
||||
expect(frame).not.toContain("test/model")
|
||||
expect(states.some(({ state }) => state === "working")).toBe(true)
|
||||
|
||||
Reference in New Issue
Block a user