refactor(tui): simplify mini footer status line (#38112)
This commit is contained in:
parent
592ef7433a
commit
dd50d457b0
15 changed files with 111 additions and 102 deletions
|
|
@ -81,6 +81,9 @@ describe("run catalog shared", () => {
|
|||
cost: {
|
||||
input: 0,
|
||||
},
|
||||
limit: {
|
||||
context: 128_000,
|
||||
},
|
||||
status: "active",
|
||||
variants: {
|
||||
high: {},
|
||||
|
|
|
|||
|
|
@ -259,15 +259,9 @@ function footerComposerFrame(root: BoxRenderable | RootRenderable) {
|
|||
|
||||
function footerStatusline(root: BoxRenderable | RootRenderable) {
|
||||
const status = (RUN_THEME_FALLBACK.footer.status as RGBA).toInts()
|
||||
const accent = (RUN_THEME_FALLBACK.footer.statusAccent as RGBA).toInts()
|
||||
const boxes = root.getChildren().filter((item): item is BoxRenderable => item instanceof BoxRenderable)
|
||||
for (const box of boxes) {
|
||||
const first = box.getChildren().find((item): item is BoxRenderable => item instanceof BoxRenderable)
|
||||
if (
|
||||
box.backgroundColor?.toInts().every((value, index) => value === status[index]) &&
|
||||
first?.backgroundColor?.toInts().every((value, index) => value === accent[index])
|
||||
)
|
||||
return box
|
||||
if (box.backgroundColor?.toInts().every((value, index) => value === status[index])) return box
|
||||
boxes.push(...box.getChildren().filter((item): item is BoxRenderable => item instanceof BoxRenderable))
|
||||
}
|
||||
throw new Error("Footer statusline not found")
|
||||
|
|
@ -1076,30 +1070,25 @@ test("direct footer shows authoritative pending work while running", async () =>
|
|||
const frame = app.captureCharFrame()
|
||||
const transparent = RGBA.fromValues(0, 0, 0, 0).toInts()
|
||||
const tinted = (RUN_THEME_FALLBACK.footer.status as RGBA).toInts()
|
||||
const accent = (RUN_THEME_FALLBACK.footer.statusAccent as RGBA).toInts()
|
||||
const statusline = footerStatusline(app.renderer.root)
|
||||
const statusItems = statusline.getChildren().filter((item): item is BoxRenderable => item instanceof BoxRenderable)
|
||||
const mode = statusItems[0]
|
||||
const main = statusItems[1]
|
||||
const main = statusItems[0]
|
||||
const spinner = main.getChildren()[0]
|
||||
const model = statusItems[2]
|
||||
const queued = statusItems[3]
|
||||
const background = statusItems[1]
|
||||
const queued = statusItems[2]
|
||||
const hint = statusItems.at(-1)!
|
||||
|
||||
expect(spinner).toBeDefined()
|
||||
expect(frame).toContain("a-model-name-long-enough-to-force-responsive-truncation")
|
||||
expect(frame).toContain("1 pending")
|
||||
expect(frame).toContain("ctrl+b background")
|
||||
expect(frame).toContain("ctrl+x q 1 pending")
|
||||
expect(frame).toContain("↓ subagents")
|
||||
expect(frame).toContain("ctrl+p cmd")
|
||||
expect(frame).toContain("a-model-name-long-enough-to-force-responsive-truncation")
|
||||
expect(frame).toContain("subagents · ctrl+p cmd")
|
||||
expect(frame).not.toContain("1 agent")
|
||||
expect(statusline.backgroundColor.toInts()).toEqual(tinted)
|
||||
expect(mode.backgroundColor.toInts()).toEqual(accent)
|
||||
expect(main.backgroundColor.toInts()).toEqual(transparent)
|
||||
expect(model.backgroundColor.toInts()).toEqual(transparent)
|
||||
expect(background.backgroundColor.toInts()).toEqual(transparent)
|
||||
expect(queued.backgroundColor.toInts()).toEqual(transparent)
|
||||
expect(hint.backgroundColor.toInts()).toEqual(transparent)
|
||||
} finally {
|
||||
|
|
@ -1127,9 +1116,7 @@ test("direct footer always offers backgrounding for a foreground subagent", asyn
|
|||
await app.renderOnce()
|
||||
const frame = app.captureCharFrame()
|
||||
|
||||
expect(frame).toContain("GPT-5")
|
||||
expect(frame).toContain("xhigh · ctrl+b background · ↓ subagents · ctrl+p cmd")
|
||||
expect(frame).toContain("ctrl+b background")
|
||||
expect(frame).toContain("ctrl+b background · ↓ subagents · ctrl+p cmd")
|
||||
expect(frame).not.toContain("queued")
|
||||
} finally {
|
||||
app.cleanup()
|
||||
|
|
@ -1154,8 +1141,7 @@ test("direct footer hides the subagent hint when only completed subagents remain
|
|||
await app.renderOnce()
|
||||
const frame = app.captureCharFrame()
|
||||
|
||||
expect(frame).toContain("GPT-5")
|
||||
expect(frame).toContain("xhigh · ctrl+p cmd")
|
||||
expect(frame).toContain("ctrl+p cmd")
|
||||
expect(frame).not.toContain("↓ subagents")
|
||||
} finally {
|
||||
app.cleanup()
|
||||
|
|
@ -1194,7 +1180,7 @@ test("direct footer shows full usage metadata when room is available", async ()
|
|||
}
|
||||
})
|
||||
|
||||
test("direct footer mode label keeps left padding without a status pill", async () => {
|
||||
test("direct footer does not label normal mode as build", async () => {
|
||||
const app = await renderFooter()
|
||||
|
||||
try {
|
||||
|
|
@ -1202,10 +1188,10 @@ test("direct footer mode label keeps left padding without a status pill", async
|
|||
const statusline = app
|
||||
.captureCharFrame()
|
||||
.split("\n")
|
||||
.find((line) => line.includes("BUILD") && line.includes("cmd"))
|
||||
.find((line) => line.includes("cmd"))
|
||||
|
||||
expect(statusline).toBeDefined()
|
||||
expect(statusline?.startsWith(" BUILD ")).toBe(true)
|
||||
expect(statusline).not.toContain("BUILD")
|
||||
} finally {
|
||||
app.cleanup()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ describe("run footer width", () => {
|
|||
expect(narrow.statusline.showCommandHint).toBe(true)
|
||||
expect(narrow.statusline.showContextHints).toBe(false)
|
||||
expect(narrow.statusline.contextHintLimit).toBe(0)
|
||||
expect(narrow.statusline.showModel).toBe(false)
|
||||
|
||||
const command = footerWidthPolicy(65)
|
||||
expect(command.statusline.showCommandHint).toBe(false)
|
||||
|
|
@ -22,14 +21,11 @@ describe("run footer width", () => {
|
|||
expect(compact.statusline.showActivityMeta).toBe(true)
|
||||
expect(compact.statusline.showContextHints).toBe(true)
|
||||
expect(compact.statusline.contextHintLimit).toBe(1)
|
||||
expect(compact.statusline.showModel).toBe(false)
|
||||
|
||||
const model = footerWidthPolicy(120)
|
||||
expect(model.statusline.contextHintLimit).toBe(2)
|
||||
expect(model.statusline.showModel).toBe(true)
|
||||
const context = footerWidthPolicy(120)
|
||||
expect(context.statusline.contextHintLimit).toBe(2)
|
||||
|
||||
const spacious = footerWidthPolicy(150)
|
||||
expect(spacious.statusline.contextHintLimit).toBeUndefined()
|
||||
expect(spacious.statusline.showModel).toBe(true)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -128,6 +128,9 @@ describe("run runtime boot", () => {
|
|||
cost: {
|
||||
input: 0,
|
||||
},
|
||||
limit: {
|
||||
context: 128_000,
|
||||
},
|
||||
status: "active",
|
||||
variants: {
|
||||
high: {},
|
||||
|
|
|
|||
|
|
@ -200,6 +200,50 @@ afterEach(() => {
|
|||
})
|
||||
|
||||
describe("V2 mini transport", () => {
|
||||
test("formats footer usage with compact tokens and context percentage", async () => {
|
||||
const events = feed()
|
||||
events.push(connected())
|
||||
const ui = footer()
|
||||
const transport = await createSessionTransport({
|
||||
sdk: sdk({ streams: [events] }),
|
||||
sessionID: "ses_1",
|
||||
thinking: false,
|
||||
footer: ui.api,
|
||||
contextLimit: (model) =>
|
||||
model.providerID === "test" && model.modelID === "model" ? 160_000 : undefined,
|
||||
})
|
||||
|
||||
events.push({
|
||||
id: "evt_step_started",
|
||||
created: 1,
|
||||
type: "session.step.started",
|
||||
durable: durable("ses_1", 1),
|
||||
data: {
|
||||
sessionID: "ses_1",
|
||||
assistantMessageID: "msg_assistant",
|
||||
agent: "build",
|
||||
model: { providerID: "test", id: "model" },
|
||||
},
|
||||
})
|
||||
events.push({
|
||||
id: "evt_step_ended",
|
||||
created: 2,
|
||||
type: "session.step.ended",
|
||||
durable: durable("ses_1", 2),
|
||||
data: {
|
||||
sessionID: "ses_1",
|
||||
assistantMessageID: "msg_assistant",
|
||||
finish: "stop",
|
||||
cost: 0,
|
||||
tokens: { input: 7_000, output: 500, reasoning: 8, cache: { read: 0, write: 0 } },
|
||||
},
|
||||
})
|
||||
|
||||
while (!ui.events.some((event) => event.type === "stream.patch" && event.patch.usage)) await Bun.sleep(0)
|
||||
expect(ui.events).toContainEqual({ type: "stream.patch", patch: { usage: "7.5K (5%)" } })
|
||||
await transport.close()
|
||||
})
|
||||
|
||||
test("recursively hydrates blockers for direct and transitive descendants", async () => {
|
||||
const events = feed()
|
||||
events.push(connected())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue