Merge refreshed schema DSL into canonical tool output

# Conflicts:
#	docs/config-catalog.md
#	examples/headless-agent/tests/snapshots/advanced-toolchain/session.1.jsonl
#	examples/headless-agent/tests/snapshots/advanced-toolchain/session.2.jsonl
#	examples/headless-agent/tests/snapshots/advanced-toolchain/session.jsonl
#	packages/context/workspace-context/tests/workspace-context.spec.ts
#	packages/core/tools/tests/tools.spec.ts
#	packages/ui/tui/src/index.ts
#	packages/ui/tui/tests/tui.snapshot.ts
This commit is contained in:
Tianyi Cui
2026-07-22 21:31:16 +08:00
390 changed files with 16442 additions and 2975 deletions
+41 -22
View File
@@ -8,7 +8,7 @@ import AgentRegistry, {
} from '@deepseek-ai/dsh-agent'
import type { ContentBlock, LlmModelContext, LlmModelInfo, LlmProviderInfo } from '@deepseek-ai/dsh-llm'
import CommandService from '@deepseek-ai/dsh-commands'
import SessionStore, { SessionId, type Session } from '@deepseek-ai/dsh-session'
import SessionStore, { SessionId, type Session, type SessionHeader } from '@deepseek-ai/dsh-session'
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
import type { ToolDefinition } from '@deepseek-ai/dsh-tools'
import UserInteractionService from '@deepseek-ai/dsh-user-interaction'
@@ -24,11 +24,16 @@ interface FakeAgent extends Agent {
export interface TuiHarnessOptions {
status?: AgentStatus
config?: Config
/** Leave the session event log empty instead of seeding one turn and step. */
omitInitialLifecycle?: boolean
/** Omit the harness's default `welcome`, exercising the banner sweep-reveal path. */
omitWelcome?: boolean
tools?: Record<string, ToolDefinition>
configureContext?: (ctx: Context) => Promise<void>
beforeMount?: (session: Session) => void
cwd?: string | null
formatCwd?: TuiRuntime['formatCwd']
/** Fake-agent creation options (`provider`/`model` seed the model selector's initial target). */
agentOptions?: AgentOptions
contextWindow?: number
contextTokens?: number
@@ -39,6 +44,8 @@ export interface TuiHarnessOptions {
listModels?: (provider: string) => Promise<LlmModelInfo[]>
resolveModelContext?: (provider: string, model: string) => Promise<LlmModelContext | undefined>
}
/** Provide a fake `sessionPersistence` service so resume surfaces can list sessions. */
sessionPersistence?: { list(): Promise<SessionHeader[]> }
}
export interface TuiHarness<TerminalType extends Terminal, Exit extends (code: number) => void> {
@@ -74,19 +81,6 @@ export async function createTuiTestHarness<TerminalType extends Terminal, Exit e
{ provider: 'deepseek', id: 'deepseek-v4-pro', name: 'DeepSeek V4 Pro' },
],
}
ctx.provide('llm', {
listProviders() {
return catalog.providers.map(provider => ({ ...provider }))
},
listModels(provider: string) {
return catalog.listModels?.(provider)
?? Promise.resolve(catalog.models.filter(model => model.provider === provider).map(model => ({ ...model })))
},
resolveModelContext(provider: string, model: string) {
return catalog.resolveModelContext?.(provider, model)
?? Promise.resolve({ contextWindow: options.contextWindow ?? 128_000 })
},
} as never)
ctx.provide('tokenMeter', {
measure() {
return { totalTokens: options.contextTokens ?? 0 }
@@ -102,17 +96,39 @@ export async function createTuiTestHarness<TerminalType extends Terminal, Exit e
} else {
await options.configureContext(ctx)
}
// A configureContext may mount the real LlmService; only fill the
// advisory-catalog stub when none was provided.
if (ctx.get('llm') === undefined) {
ctx.provide('llm', {
listProviders() {
return catalog.providers.map(provider => ({ ...provider }))
},
listModels(provider: string) {
return catalog.listModels?.(provider)
?? Promise.resolve(catalog.models.filter(model => model.provider === provider).map(model => ({ ...model })))
},
resolveModelContext(provider: string, model: string) {
return catalog.resolveModelContext?.(provider, model)
?? Promise.resolve({ contextWindow: options.contextWindow ?? 128_000 })
},
} as never)
}
if (ctx.get('systemPrompt') === undefined) await ctx.plugin(SystemPrompt)
if (options.sessionPersistence !== undefined) {
ctx.provide('sessionPersistence', options.sessionPersistence as never)
}
const sessionId = SessionId('main-session')
const session = ctx.sessions.create(
sessionId,
options.cwd === null ? undefined : { meta: { cwd: options.cwd ?? '/workspace' } },
)
session.append('turn/start', {
turn: 1,
trigger: { kind: 'message', source: { kind: 'user' } },
})
session.append('step/start', { turn: 1, step: 1 })
if (options.omitInitialLifecycle !== true) {
session.append('turn/start', {
turn: 1,
trigger: { kind: 'message', source: { kind: 'user' } },
})
session.append('step/start', { turn: 1, step: 1 })
}
options.beforeMount?.(session)
const sent: ContentBlock[][] = []
const steered: ContentBlock[][] = []
@@ -142,13 +158,16 @@ export async function createTuiTestHarness<TerminalType extends Terminal, Exit e
}
ctx.agents.register(agent)
const controller = createTuiChat(ctx, Object.assign({
welcome: 'Coding agent ready.',
...options.omitWelcome === true ? {} : { welcome: 'Coding agent ready.' },
sessionId,
color: false,
}, options.config), {
terminal,
exit,
now: options.now ?? (() => 0),
// Default to the real clock (runtime.now falls back to Date.now) so the
// elapsed-status suites can drive time via timers or Date.now spies; a
// test pins the clock only by passing `now` explicitly.
...(options.now === undefined ? {} : { now: options.now }),
...(options.formatCwd === undefined ? {} : { formatCwd: options.formatCwd }),
})
return { ctx, session, agent, terminal, exit, controller }
@@ -174,7 +193,7 @@ export function appendUser(session: Session, text: string): void {
export function appendAssistant(
session: Session,
content: ContentBlock[],
usage?: { inputTokens: number; outputTokens: number },
usage?: { inputTokens: number; outputTokens: number; cacheReadTokens?: number; cacheWriteTokens?: number },
position: { turn: number; step: number } = { turn: 1, step: 1 },
): void {
session.append('assistant/message', {
@@ -1,108 +1,99 @@
terminal 100x40 buffer=normal length=41 base=1 viewport=1
terminal 100x40 buffer=normal length=40 base=0 viewport=0
lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=1 viewportRow=37 bufferRow=38
cursor hidden column=1 viewportRow=36 bufferRow=36
buffer
0| "╭──────────────────────────────────────────────────────────────────────────────────────────────────╮"
style 0-99 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 99-99 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 99-99 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 99-99 fg=bright-blue
4| "╰──────────────────────────────────────────────────────────────────────────────────────────────────╯"
style 0-99 fg=bright-blue
5| <blank>
6| "▌ "
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| <blank>
4| "▌ "
style 0-0 fg=green
7| "▌ ✓ pnpm run test:coverage "
5| "▌ ✓ pnpm run test:coverage "
style 0-0 fg=green
style 2-2 fg=green bold
style 3-25 bold
8| "▌ Run the coverage gate "
6| "▌ Run the coverage gate "
style 0-0 fg=green
style 2-22 fg=bright-black
9| "▌ /workspace/project "
7| "▌ /workspace/project "
style 0-0 fg=green
style 2-19 dim
10| "▌ … +4 lines (Ctrl+O to expand) "
8| "▌ … +4 lines (Ctrl+O to expand) "
style 0-0 fg=green
style 2-30 dim
11| "▌ [exit 0] "
9| "▌ [exit 0] "
style 0-0 fg=green
style 2-9 dim
10| "▌ "
style 0-0 fg=green
11| <blank>
12| "▌ "
style 0-0 fg=green
13| <blank>
14| "▌ "
style 0-0 fg=green
15| "▌ ✓ Edit renderer "
13| "▌ ✓ Edit renderer "
style 0-0 fg=green
style 2-2 fg=green bold
style 3-16 bold
16| "▌ src/view.ts "
14| "▌ src/view.ts "
style 0-0 fg=green
style 2-12 bold
17| "▌ - old line "
15| "▌ - old line "
style 0-0 fg=green
style 2-11 fg=red
18| "▌ … +5 lines (Ctrl+O to expand) "
16| "▌ … +5 lines (Ctrl+O to expand) "
style 0-0 fg=green
style 2-30 dim
19| "▌ + expect(screen).toMatchSnapshot() "
17| "▌ + expect(screen).toMatchSnapshot() "
style 0-0 fg=green
style 2-35 fg=green
18| "▌ "
style 0-0 fg=green
19| <blank>
20| "▌ "
style 0-0 fg=green
21| <blank>
22| "▌ "
style 0-0 fg=green
23| "▌ ✓ Delegate renderer audit "
21| "▌ ✓ Delegate renderer audit "
style 0-0 fg=green
style 2-2 fg=green bold
style 3-26 bold
24| "▌ The renderer has explicit lifecycle ownership. "
22| "▌ The renderer has explicit lifecycle ownership. "
style 0-0 fg=green
23| "▌ "
style 0-0 fg=green
24| <blank>
25| "▌ "
style 0-0 fg=green
26| <blank>
27| "▌ "
style 0-0 fg=green
28| "▌ ✓ Read output from background task subagent-7 "
26| "▌ ✓ Read output from background task subagent-7 "
style 0-0 fg=green
style 2-2 fg=green bold
style 3-46 bold
29| "▌ audit complete "
27| "▌ audit complete "
style 0-0 fg=green
30| "▌ [status: completed] "
28| "▌ [status: completed] "
style 0-0 fg=green
29| "▌ "
style 0-0 fg=green
30| <blank>
31| "▌ "
style 0-0 fg=green
32| <blank>
33| "▌ "
style 0-0 fg=green
34| "▌ ✓ Load skill dsh-code-review "
32| "▌ ✓ Load skill dsh-code-review "
style 0-0 fg=green
style 2-2 fg=green bold
style 3-29 bold
35| "▌ Loaded review instructions. "
33| "▌ Loaded review instructions. "
style 0-0 fg=green
36| "▌ "
34| "▌ "
style 0-0 fg=green
35| "────────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-99 dim
36| " "
style 1-1 inverse
37| "────────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-99 dim
38| " "
style 1-1 inverse
39| "────────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-99 dim
40| "/workspace/project ↑0 ↓0 0% context tools:compact deepseek-v4-flash(reasoning:on)"
style 0-24 dim
style 42-99 dim
38| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context tools:collapsed"
style 0-43 dim
style 73-99 dim
39| <blank>
@@ -1,127 +1,117 @@
terminal 100x40 buffer=normal length=50 base=10 viewport=10
terminal 100x40 buffer=normal length=48 base=8 viewport=8
lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=1 viewportRow=37 bufferRow=47
cursor hidden column=1 viewportRow=37 bufferRow=45
buffer
0| "╭──────────────────────────────────────────────────────────────────────────────────────────────────╮"
style 0-99 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 99-99 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 99-99 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 99-99 fg=bright-blue
4| "╰──────────────────────────────────────────────────────────────────────────────────────────────────╯"
style 0-99 fg=bright-blue
5| <blank>
6| "▌ "
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| <blank>
4| "▌ "
style 0-0 fg=green
7| "▌ ✓ pnpm run test:coverage "
5| "▌ ✓ pnpm run test:coverage "
style 0-0 fg=green
style 2-2 fg=green bold
style 3-25 bold
8| "▌ Run the coverage gate "
6| "▌ Run the coverage gate "
style 0-0 fg=green
style 2-22 fg=bright-black
9| "▌ /workspace/project "
7| "▌ /workspace/project "
style 0-0 fg=green
style 2-19 dim
10| "▌ packages/ui/tui 100% "
8| "▌ packages/ui/tui 100% "
style 0-0 fg=green
11| "▌ 4016 tests passed "
9| "▌ 4016 tests passed "
style 0-0 fg=green
12| "▌ 1 test skipped "
10| "▌ 1 test skipped "
style 0-0 fg=green
13| "▌ coverage complete "
11| "▌ coverage complete "
style 0-0 fg=green
14| "▌ [exit 0] "
12| "▌ [exit 0] "
style 0-0 fg=green
style 2-9 dim
13| "▌ "
style 0-0 fg=green
14| <blank>
15| "▌ "
style 0-0 fg=green
16| <blank>
17| "▌ "
style 0-0 fg=green
18| "▌ ✓ Edit renderer "
16| "▌ ✓ Edit renderer "
style 0-0 fg=green
style 2-2 fg=green bold
style 3-16 bold
19| "▌ src/view.ts "
17| "▌ src/view.ts "
style 0-0 fg=green
style 2-12 bold
20| "▌ - old line "
18| "▌ - old line "
style 0-0 fg=green
style 2-11 fg=red
21| "▌ - keep "
19| "▌ - keep "
style 0-0 fg=green
style 2-7 fg=red
22| "▌ + new line "
20| "▌ + new line "
style 0-0 fg=green
style 2-11 fg=green
23| "▌ + keep "
21| "▌ + keep "
style 0-0 fg=green
style 2-7 fg=green
24| "▌ "
22| "▌ "
style 0-0 fg=green
25| "▌ tests/view.spec.ts "
23| "▌ tests/view.spec.ts "
style 0-0 fg=green
style 2-19 bold
26| "▌ + expect(screen).toMatchSnapshot() "
24| "▌ + expect(screen).toMatchSnapshot() "
style 0-0 fg=green
style 2-35 fg=green
25| "▌ "
style 0-0 fg=green
26| <blank>
27| "▌ "
style 0-0 fg=green
28| <blank>
29| "▌ "
style 0-0 fg=green
30| "▌ ✓ Delegate renderer audit "
28| "▌ ✓ Delegate renderer audit "
style 0-0 fg=green
style 2-2 fg=green bold
style 3-26 bold
31| "▌ The renderer has explicit lifecycle ownership. "
29| "▌ The renderer has explicit lifecycle ownership. "
style 0-0 fg=green
30| "▌ "
style 0-0 fg=green
31| <blank>
32| "▌ "
style 0-0 fg=green
33| <blank>
34| "▌ "
style 0-0 fg=green
35| "▌ ✓ Read output from background task subagent-7 "
33| "▌ ✓ Read output from background task subagent-7 "
style 0-0 fg=green
style 2-2 fg=green bold
style 3-46 bold
36| "▌ audit complete "
34| "▌ audit complete "
style 0-0 fg=green
37| "▌ [status: completed] "
35| "▌ [status: completed] "
style 0-0 fg=green
36| "▌ "
style 0-0 fg=green
37| <blank>
38| "▌ "
style 0-0 fg=green
39| <blank>
40| "▌ "
style 0-0 fg=green
41| "▌ ✓ Load skill dsh-code-review "
39| "▌ ✓ Load skill dsh-code-review "
style 0-0 fg=green
style 2-2 fg=green bold
style 3-29 bold
42| "▌ Loaded review instructions. "
40| "▌ Loaded review instructions. "
style 0-0 fg=green
43| "▌ "
41| "▌ "
style 0-0 fg=green
44| <blank>
45| " Tool cards expanded. "
42| <blank>
43| " Tool cards expanded. "
style 1-20 fg=bright-black
44| "────────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-99 dim
45| " "
style 1-1 inverse
46| "────────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-99 dim
47| " "
style 1-1 inverse
48| "────────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-99 dim
49| "/workspace/project ↑0 ↓0 0% context tools:expanded deepseek-v4-flash(reasoning:on)"
style 0-24 dim
style 41-99 dim
47| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context tools:expanded"
style 0-43 dim
style 74-99 dim
@@ -0,0 +1,29 @@
terminal 96x36 buffer=normal length=36 base=0 viewport=0
lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=1 viewportRow=4 bufferRow=4
viewport
0| " DEEPSEEK HARNESS"
style 1-1 fg=#4d6bfe bold
style 2-2 fg=#4772fe bold
style 3-3 fg=#4278ff bold
style 4-4 fg=#3c7fff bold
style 5-5 fg=#3685ff bold
style 6-6 fg=#308bff bold
style 7-7 fg=#2a92ff bold
style 8-8 fg=#2498ff bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
4| " "
style 1-1 inverse
5| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
6| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context tools:collapsed"
style 0-43 dim
style 69-95 dim
7-35| <blank>
@@ -1,52 +1,42 @@
terminal 96x36 buffer=normal length=36 base=0 viewport=0
lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=1 viewportRow=15 bufferRow=15
cursor hidden column=1 viewportRow=13 bufferRow=13
buffer
0| "╭──────────────────────────────────────────────────────────────────────────────────────────────╮"
style 0-95 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 95-95 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 95-95 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 95-95 fg=bright-blue
4| "╰──────────────────────────────────────────────────────────────────────────────────────────────╯"
style 0-95 fg=bright-blue
5| <blank>
6| "▌ "
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| <blank>
4| "▌ "
style 0-0 fg=yellow
7| "▌ ◌ const first = await tools.bash({ command: 'echo CODE_ONE' }) "
5| "▌ ◌ const first = await tools.bash({ command: 'echo CODE_ONE' }) "
style 0-0 fg=yellow
style 2-2 fg=yellow bold
style 3-95 bold
8| "▌ const second = await tools.bas "
6| "▌ const second = await tools.bas "
style 0-0 fg=yellow
style 2-31 bold
9| "▌ const first = await tools.bash({ command: 'echo CODE_ONE' }) "
7| "▌ const first = await tools.bash({ command: 'echo CODE_ONE' }) "
style 0-0 fg=yellow
10| "▌ const second = await tools.bash({ command: 'echo CODE_TWO' }) "
8| "▌ const second = await tools.bash({ command: 'echo CODE_TWO' }) "
style 0-0 fg=yellow
11| "▌ console.log(first, second) "
9| "▌ console.log(first, second) "
style 0-0 fg=yellow
12| "▌ return `${first}+${second}` "
10| "▌ return `${first}+${second}` "
style 0-0 fg=yellow
13| "▌ "
11| "▌ "
style 0-0 fg=yellow
12| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
13| " "
style 1-1 inverse
14| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
15| " "
style 1-1 inverse
16| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
17| "/workspace/project ↑0 ↓0 0% context tools:compact deepseek-v4-flash(reasoning:on)"
style 0-24 dim
style 38-95 dim
18-35| <blank>
15| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context tools:collapsed"
style 0-43 dim
style 69-95 dim
16-35| <blank>
@@ -3,50 +3,44 @@ lifecycle started=1 stopped=0 progress=active
title "DSH snapshot"
cursor hidden column=1 viewportRow=17 bufferRow=17
viewport
0| "╭──────────────────────────────────────────────────────────────────────────────────────────────╮"
style 0-95 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| <blank>
4| "▌ "
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 95-95 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 95-95 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 95-95 fg=bright-blue
4| "╰──────────────────────────────────────────────────────────────────────────────────────────────╯"
style 0-95 fg=bright-blue
5| <blank>
6| "▌ "
style 0-0 fg=bright-blue
7| "▌ You "
5| "▌ You "
style 0-0 fg=bright-blue
style 2-4 fg=bright-blue bold
8| "▌ Show the live update. "
6| "▌ Show the live update. "
style 0-0 fg=bright-blue
9| "▌ "
7| "▌ "
style 0-0 fg=bright-blue
10| <blank>
11| " Reasoning "
8| <blank>
9| " Reasoning "
style 1-9 fg=bright-black italic
12| " Inspecting width and styles. "
10| " Inspecting width and styles. "
style 1-28 fg=bright-black italic
13| <blank>
14| " Assistant "
11| <blank>
12| " Assistant "
style 1-9 fg=bright-magenta bold
15| " Streaming visible state… "
13| " Streaming visible state… "
style 11-23 bold
14| <blank>
15| " ⠋ Responding 0s · total 0s — Enter sends steering, Esc cancels "
style 1-1 fg=bright-blue
style 3-62 fg=bright-black
16| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 fg=bright-blue
17| " "
style 1-1 inverse
18| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 fg=bright-blue
19| "◒ Working · 0s esc interrupt"
style 0-13 fg=bright-blue
style 83-95 dim
19| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context tools:collapsed"
style 0-43 dim
style 69-95 dim
20-35| <blank>
@@ -1,59 +1,49 @@
terminal 96x36 buffer=normal length=36 base=0 viewport=0
lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=1 viewportRow=18 bufferRow=18
cursor hidden column=1 viewportRow=16 bufferRow=16
buffer
0| "╭──────────────────────────────────────────────────────────────────────────────────────────────╮"
style 0-95 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 95-95 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 95-95 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 95-95 fg=bright-blue
4| "╰──────────────────────────────────────────────────────────────────────────────────────────────╯"
style 0-95 fg=bright-blue
5| <blank>
6| "▌ ◌ Inspect cordis runtime: tools "
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| <blank>
4| "▌ ◌ Inspect cordis runtime: tools "
style 0-0 fg=yellow
style 2-2 fg=yellow bold
style 3-32 bold
7| <blank>
8| "▌ "
5| <blank>
6| "▌ "
style 0-0 fg=yellow
9| "▌ ◌ Mount plugin into live cordis runtime "
7| "▌ ◌ Mount plugin into live cordis runtime "
style 0-0 fg=yellow
style 2-2 fg=yellow bold
style 3-40 bold
10| "▌ { "
8| "▌ { "
style 0-0 fg=yellow
11| "▌ \"code\": \"return { name: 'snapshot-marker', apply(ctx) { ctx.provide('snapshotMarker', { "
9| "▌ \"code\": \"return { name: 'snapshot-marker', apply(ctx) { ctx.provide('snapshotMarker', { "
style 0-0 fg=yellow
12| "▌ ready: true }) } }\" "
10| "▌ ready: true }) } }\" "
style 0-0 fg=yellow
13| "▌ } "
11| "▌ } "
style 0-0 fg=yellow
14| "▌ "
12| "▌ "
style 0-0 fg=yellow
15| <blank>
16| "▌ ◌ Unmount dyn-1 "
13| <blank>
14| "▌ ◌ Unmount dyn-1 "
style 0-0 fg=yellow
style 2-2 fg=yellow bold
style 3-16 bold
15| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
16| " "
style 1-1 inverse
17| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
18| " "
style 1-1 inverse
19| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
20| "/workspace/project ↑0 ↓0 0% context tools:compact deepseek-v4-flash(reasoning:on)"
style 0-24 dim
style 38-95 dim
21-35| <blank>
18| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context tools:collapsed"
style 0-43 dim
style 69-95 dim
19-35| <blank>
@@ -1,67 +1,63 @@
terminal 92x32 buffer=normal length=32 base=0 viewport=0
lifecycle started=1 stopped=1 progress=inactive
title "DSH snapshot"
cursor visible column=0 viewportRow=30 bufferRow=30
cursor visible column=0 viewportRow=31 bufferRow=31
buffer
0| "╭──────────────────────────────────────────────────────────────────────────────────────────╮"
style 0-91 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 91-91 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 91-91 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 91-91 fg=bright-blue
4| "╰──────────────────────────────────────────────────────────────────────────────────────────╯"
style 0-91 fg=bright-blue
5| <blank>
6| " Keyboard shortcuts "
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| <blank>
4| " Keyboard shortcuts "
style 1-18 fg=bright-blue bold
7| " Enter send • Shift/Alt+Enter newline • Up/Down prompt history "
5| " Enter send • Shift/Alt+Enter newline • Up/Down prompt history "
style 1-61 fg=bright-black
8| " Esc cancel active turn • Ctrl+O toggle tool cards • Ctrl+R toggle reasoning "
6| " Esc cancel active turn • Ctrl+O toggle tool cards • Ctrl+R toggle reasoning "
style 1-75 fg=bright-black
9| " Ctrl+C cancel while running; clear input or exit while idle • Ctrl+D exit "
7| " Ctrl+C cancel while running; clear input or exit while idle • Ctrl+D exit "
style 1-73 fg=bright-black
10| " "
11| " /cancel — Cancel the active turn "
style 1-32 fg=bright-black
12| " /clear — Clear the transcript view (session history is unchanged) "
8| " "
9| " /clear — Clear the transcript view (session history is unchanged) "
style 1-65 fg=bright-black
13| " /exit — Exit after the active turn reaches idle "
10| " /exit — Exit after the active turn reaches idle "
style 1-47 fg=bright-black
14| " /help — Show keyboard shortcuts and commands "
11| " /help — Show keyboard shortcuts and commands "
style 1-44 fg=bright-black
15| " /model [[provider/]model] — Show or switch this session's model "
12| " /model [[provider/]model] — Show or switch this session's model "
style 1-63 fg=bright-black
16| " /reasoning — Toggle reasoning blocks "
13| " /reasoning — Toggle reasoning blocks "
style 1-36 fg=bright-black
17| " /redraw — Invalidate components and redraw the terminal "
14| " /redraw — Invalidate components and redraw the terminal "
style 1-55 fg=bright-black
15| " /reload — EXPERIMENTAL (dev): re-read loader config files and apply the diff (idle only) "
style 1-88 fg=bright-black
16| " /resume — List this workspace's resumable sessions "
style 1-50 fg=bright-black
17| " /status — Show detailed session diagnostics "
style 1-43 fg=bright-black
18| " /tools — Expand or collapse all tool cards "
style 1-42 fg=bright-black
19| <blank>
20| " provider stream failed after partial output "
19| " /skill:<name> [instructions] — load a skill into the conversation "
style 1-65 fg=bright-black
20| <blank>
21| " provider stream failed after partial output "
style 1-43 fg=red
21| <blank>
22| " The previous process ended during this turn. "
22| <blank>
23| " The previous process ended during this turn. "
style 1-44 fg=yellow
23| <blank>
24| " Unknown command: /unknown-advanced-command "
24| <blank>
25| " Unknown command: /unknown-advanced-command "
style 1-42 fg=yellow
25| "────────────────────────────────────────────────────────────────────────────────────────────"
26| "────────────────────────────────────────────────────────────────────────────────────────────"
style 0-91 dim
26| " "
27| " "
style 1-1 inverse
27| "────────────────────────────────────────────────────────────────────────────────────────────"
28| "────────────────────────────────────────────────────────────────────────────────────────────"
style 0-91 dim
28| "/workspace/project ↑0 ↓0 0% context tools:compact deepseek-v4-flash(reasoning:on)"
style 0-24 dim
style 34-91 dim
29-31| <blank>
29| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context tools:collapsed"
style 0-43 dim
style 65-91 dim
30-31| <blank>
@@ -1,56 +1,46 @@
terminal 96x36 buffer=normal length=36 base=0 viewport=0
lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=1 viewportRow=17 bufferRow=17
cursor hidden column=1 viewportRow=15 bufferRow=15
buffer
0| "╭──────────────────────────────────────────────────────────────────────────────────────────────╮"
style 0-95 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 95-95 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 95-95 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 95-95 fg=bright-blue
4| "╰──────────────────────────────────────────────────────────────────────────────────────────────╯"
style 0-95 fg=bright-blue
5| <blank>
6| "▌ "
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| <blank>
4| "▌ "
style 0-0 fg=yellow
7| "▌ ◌ workflow: tui-matrix "
5| "▌ ◌ workflow: tui-matrix "
style 0-0 fg=yellow
style 2-2 fg=yellow bold
style 3-23 bold
8| "▌ phase('Inspect') "
6| "▌ phase('Inspect') "
style 0-0 fg=yellow
9| "▌ const reports = await parallel([ "
7| "▌ const reports = await parallel([ "
style 0-0 fg=yellow
10| "▌ () => agent('Audit layout', { label: 'layout', phase: 'Inspect' }), "
8| "▌ () => agent('Audit layout', { label: 'layout', phase: 'Inspect' }), "
style 0-0 fg=yellow
11| "▌ … +1 lines (Ctrl+O to expand) "
9| "▌ … +1 lines (Ctrl+O to expand) "
style 0-0 fg=yellow
style 2-30 dim
12| "▌ ]) "
10| "▌ ]) "
style 0-0 fg=yellow
13| "▌ phase('Verify') "
11| "▌ phase('Verify') "
style 0-0 fg=yellow
14| "▌ return { reports, verdict: 'covered' } "
12| "▌ return { reports, verdict: 'covered' } "
style 0-0 fg=yellow
15| "▌ "
13| "▌ "
style 0-0 fg=yellow
14| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
15| " "
style 1-1 inverse
16| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
17| " "
style 1-1 inverse
18| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
19| "/workspace/project ↑0 ↓0 0% context tools:compact deepseek-v4-flash(reasoning:on)"
style 0-24 dim
style 38-95 dim
20-35| <blank>
17| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context tools:collapsed"
style 0-43 dim
style 69-95 dim
18-35| <blank>
@@ -1,67 +1,63 @@
terminal 92x32 buffer=normal length=32 base=0 viewport=0
lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=1 viewportRow=26 bufferRow=26
cursor hidden column=1 viewportRow=27 bufferRow=27
buffer
0| "╭──────────────────────────────────────────────────────────────────────────────────────────╮"
style 0-91 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 91-91 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 91-91 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 91-91 fg=bright-blue
4| "╰──────────────────────────────────────────────────────────────────────────────────────────╯"
style 0-91 fg=bright-blue
5| <blank>
6| " Keyboard shortcuts "
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| <blank>
4| " Keyboard shortcuts "
style 1-18 fg=bright-blue bold
7| " Enter send • Shift/Alt+Enter newline • Up/Down prompt history "
5| " Enter send • Shift/Alt+Enter newline • Up/Down prompt history "
style 1-61 fg=bright-black
8| " Esc cancel active turn • Ctrl+O toggle tool cards • Ctrl+R toggle reasoning "
6| " Esc cancel active turn • Ctrl+O toggle tool cards • Ctrl+R toggle reasoning "
style 1-75 fg=bright-black
9| " Ctrl+C cancel while running; clear input or exit while idle • Ctrl+D exit "
7| " Ctrl+C cancel while running; clear input or exit while idle • Ctrl+D exit "
style 1-73 fg=bright-black
10| " "
11| " /cancel — Cancel the active turn "
style 1-32 fg=bright-black
12| " /clear — Clear the transcript view (session history is unchanged) "
8| " "
9| " /clear — Clear the transcript view (session history is unchanged) "
style 1-65 fg=bright-black
13| " /exit — Exit after the active turn reaches idle "
10| " /exit — Exit after the active turn reaches idle "
style 1-47 fg=bright-black
14| " /help — Show keyboard shortcuts and commands "
11| " /help — Show keyboard shortcuts and commands "
style 1-44 fg=bright-black
15| " /model [[provider/]model] — Show or switch this session's model "
12| " /model [[provider/]model] — Show or switch this session's model "
style 1-63 fg=bright-black
16| " /reasoning — Toggle reasoning blocks "
13| " /reasoning — Toggle reasoning blocks "
style 1-36 fg=bright-black
17| " /redraw — Invalidate components and redraw the terminal "
14| " /redraw — Invalidate components and redraw the terminal "
style 1-55 fg=bright-black
15| " /reload — EXPERIMENTAL (dev): re-read loader config files and apply the diff (idle only) "
style 1-88 fg=bright-black
16| " /resume — List this workspace's resumable sessions "
style 1-50 fg=bright-black
17| " /status — Show detailed session diagnostics "
style 1-43 fg=bright-black
18| " /tools — Expand or collapse all tool cards "
style 1-42 fg=bright-black
19| <blank>
20| " provider stream failed after partial output "
19| " /skill:<name> [instructions] — load a skill into the conversation "
style 1-65 fg=bright-black
20| <blank>
21| " provider stream failed after partial output "
style 1-43 fg=red
21| <blank>
22| " The previous process ended during this turn. "
22| <blank>
23| " The previous process ended during this turn. "
style 1-44 fg=yellow
23| <blank>
24| " Unknown command: /unknown-advanced-command "
24| <blank>
25| " Unknown command: /unknown-advanced-command "
style 1-42 fg=yellow
25| "────────────────────────────────────────────────────────────────────────────────────────────"
26| "────────────────────────────────────────────────────────────────────────────────────────────"
style 0-91 dim
26| " "
27| " "
style 1-1 inverse
27| "────────────────────────────────────────────────────────────────────────────────────────────"
28| "────────────────────────────────────────────────────────────────────────────────────────────"
style 0-91 dim
28| "/workspace/project ↑0 ↓0 0% context tools:compact deepseek-v4-flash(reasoning:on)"
style 0-24 dim
style 34-91 dim
29-31| <blank>
29| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context tools:collapsed"
style 0-43 dim
style 65-91 dim
30-31| <blank>
@@ -3,33 +3,23 @@ lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=0 viewportRow=31 bufferRow=31
buffer
0| "╭──────────────────────────────────────────────────────────────────────────────────────────╮"
style 0-91 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 91-91 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 91-91 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 91-91 fg=bright-blue
4| "╰──────────────────────────────────────────────────────────────────────────────────────────╯"
style 0-91 fg=bright-blue
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| "────────────────────────────────────────────────────────────────────────────────────────────"
style 0-91 dim
4| " "
style 1-1 inverse
5| "────────────────────────────────────────────────────────────────────────────────────────────"
style 0-91 dim
6| " "
style 1-1 inverse
7| "────────────────────────────────────────────────────────────────────────────────────────────"
style 0-91 dim
8| "/workspace/project ↑0 ↓0 0% context tools:compact deepseek-v4-flash(reasoning:on)"
style 0-24 dim
style 34-91 dim
9-12| <blank>
6| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context tools:collapsed"
style 0-43 dim
style 65-91 dim
7-12| <blank>
13| " ╭ Select model ────────────────────────────────────────────────────────╮ "
style 10-81 fg=bright-blue
14| " │ → deepseek/deepseek-v4-flash DeepSeek V4 Flash — current │ "
@@ -1,35 +1,25 @@
terminal 92x32 buffer=normal length=32 base=0 viewport=0
lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=1 viewportRow=8 bufferRow=8
cursor hidden column=1 viewportRow=6 bufferRow=6
buffer
0| "╭──────────────────────────────────────────────────────────────────────────────────────────╮"
style 0-91 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 91-91 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 91-91 fg=bright-blue
3| "│ deepseek-v4-pro • main-session │"
style 0-0 fg=bright-blue
style 2-33 dim
style 91-91 fg=bright-blue
4| "╰──────────────────────────────────────────────────────────────────────────────────────────╯"
style 0-91 fg=bright-blue
5| <blank>
6| " Model selected: deepseek/deepseek-v4-pro. New steps will use it. "
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-pro • main-session"
style 1-32 dim
3| <blank>
4| " Model selected: deepseek/deepseek-v4-pro. New steps will use it. "
style 1-64 fg=bright-black
5| "────────────────────────────────────────────────────────────────────────────────────────────"
style 0-91 dim
6| " "
style 1-1 inverse
7| "────────────────────────────────────────────────────────────────────────────────────────────"
style 0-91 dim
8| " "
style 1-1 inverse
9| "────────────────────────────────────────────────────────────────────────────────────────────"
style 0-91 dim
10| "/workspace/project ↑0 ↓0 0% context tools:compact deepseek-v4-pro(reasoning:on)"
style 0-24 dim
style 36-91 dim
11-31| <blank>
8| "deepseek-v4-pro /workspace/project ↑0 ↓0 0% context tools:collapsed"
style 0-41 dim
style 65-91 dim
9-31| <blank>
@@ -3,23 +3,17 @@ lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=56 viewportRow=17 bufferRow=17
viewport
0| "╭──────────────────────────────────────────────────────╮"
style 0-55 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 55-55 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 55-55 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 55-55 fg=bright-blue
4| "╰──────────────────────────────────────────────────────╯"
style 0-55 fg=bright-blue
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| "────────────────────────────────────────────────────────"
style 0-55 dim
4| " "
style 1-1 inverse
5| " "
6| " Question 1/3 (3 unanswered) · Coverage "
style 2-39 fg=bright-black
@@ -3,27 +3,22 @@ lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=0 viewportRow=19 bufferRow=19
viewport
0| "╭──────────────────────────────────────────────────────╮"
style 0-55 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 55-55 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 55-55 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 55-55 fg=bright-blue
4| "╰──────────────────────────────────────────────────────╯"
style 0-55 fg=bright-blue
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| "────────────────────────────────────────────────────────"
style 0-55 dim
4| " "
style 1-1 inverse
5| "────────────────────────────────────────────────────────"
style 0-55 dim
6| " "
style 1-1 inverse
6| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context"
style 0-43 dim
style 46-55 dim
7| " "
8| " Question 1/3 (3 unanswered) · Coverage "
style 2-39 fg=bright-black
@@ -0,0 +1,32 @@
terminal 92x32 buffer=normal length=32 base=0 viewport=0
lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=1 viewportRow=10 bufferRow=10
buffer
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| <blank>
4| " Resumable sessions "
style 1-18 fg=bright-blue bold
5| " 2024-01-02 03:04 (current) "
style 1-16 fg=bright-black
style 17-26 fg=green
6| " RESUME_SESSION_ID=main-session dsh "
7| " 2024-01-01 00:00 "
style 1-16 fg=bright-black
8| " RESUME_SESSION_ID=earlier-session dsh "
9| "────────────────────────────────────────────────────────────────────────────────────────────"
style 0-91 dim
10| " "
style 1-1 inverse
11| "────────────────────────────────────────────────────────────────────────────────────────────"
style 0-91 dim
12| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context tools:collapsed"
style 0-43 dim
style 65-91 dim
13-31| <blank>
@@ -1,48 +1,38 @@
terminal 96x36 buffer=normal length=36 base=0 viewport=0
lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=1 viewportRow=15 bufferRow=15
cursor hidden column=1 viewportRow=13 bufferRow=13
buffer
0| "╭──────────────────────────────────────────────────────────────────────────────────────────────╮"
style 0-95 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| <blank>
4| "▌ "
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 95-95 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 95-95 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 95-95 fg=bright-blue
4| "╰──────────────────────────────────────────────────────────────────────────────────────────────╯"
style 0-95 fg=bright-blue
5| <blank>
6| "▌ "
style 0-0 fg=bright-blue
7| "▌ You "
5| "▌ You "
style 0-0 fg=bright-blue
style 2-4 fg=bright-blue bold
8| "▌ Start then cancel. "
6| "▌ Start then cancel. "
style 0-0 fg=bright-blue
9| "▌ "
7| "▌ "
style 0-0 fg=bright-blue
10| <blank>
11| " Retrying model request (1/2) in 1000ms: temporary transport failure "
8| <blank>
9| " Retrying model request (1/2) in 1000ms: temporary transport failure "
style 1-67 fg=yellow
12| <blank>
13| " Turn cancelled. "
10| <blank>
11| " Turn cancelled. "
style 1-15 fg=yellow
12| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
13| " "
style 1-1 inverse
14| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
15| " "
style 1-1 inverse
16| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
17| "/workspace/project ↑0 ↓0 0% context tools:compact deepseek-v4-flash(reasoning:on)"
style 0-24 dim
style 38-95 dim
18-35| <blank>
15| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context tools:collapsed"
style 0-43 dim
style 69-95 dim
16-35| <blank>
@@ -1,45 +1,35 @@
terminal 96x36 buffer=normal length=36 base=0 viewport=0
lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=1 viewportRow=13 bufferRow=13
cursor hidden column=1 viewportRow=11 bufferRow=11
buffer
0| "╭──────────────────────────────────────────────────────────────────────────────────────────────╮"
style 0-95 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| <blank>
4| "▌ "
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 95-95 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 95-95 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 95-95 fg=bright-blue
4| "╰──────────────────────────────────────────────────────────────────────────────────────────────╯"
style 0-95 fg=bright-blue
5| <blank>
6| "▌ "
style 0-0 fg=bright-blue
7| "▌ You "
5| "▌ You "
style 0-0 fg=bright-blue
style 2-4 fg=bright-blue bold
8| "▌ Let the bounded policy exhaust. "
6| "▌ Let the bounded policy exhaust. "
style 0-0 fg=bright-blue
9| "▌ "
7| "▌ "
style 0-0 fg=bright-blue
10| <blank>
11| " provider still unavailable "
8| <blank>
9| " provider still unavailable "
style 1-26 fg=red
10| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
11| " "
style 1-1 inverse
12| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
13| " "
style 1-1 inverse
14| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
15| "/workspace/project ↑0 ↓0 0% context tools:compact deepseek-v4-flash(reasoning:on)"
style 0-24 dim
style 38-95 dim
16-35| <blank>
13| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context tools:collapsed"
style 0-43 dim
style 69-95 dim
14-35| <blank>
@@ -1,49 +1,39 @@
terminal 96x36 buffer=normal length=36 base=0 viewport=0
lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=1 viewportRow=16 bufferRow=16
cursor hidden column=1 viewportRow=14 bufferRow=14
buffer
0| "╭──────────────────────────────────────────────────────────────────────────────────────────────╮"
style 0-95 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| <blank>
4| "▌ "
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 95-95 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 95-95 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 95-95 fg=bright-blue
4| "╰──────────────────────────────────────────────────────────────────────────────────────────────╯"
style 0-95 fg=bright-blue
5| <blank>
6| "▌ "
style 0-0 fg=bright-blue
7| "▌ You "
5| "▌ You "
style 0-0 fg=bright-blue
style 2-4 fg=bright-blue bold
8| "▌ Recover this request. "
6| "▌ Recover this request. "
style 0-0 fg=bright-blue
9| "▌ "
7| "▌ "
style 0-0 fg=bright-blue
10| <blank>
11| " Retrying model request (1/2) in 500ms: provider rate limit "
8| <blank>
9| " Retrying model request (1/2) in 500ms: provider rate limit "
style 1-58 fg=yellow
12| <blank>
13| " Assistant "
10| <blank>
11| " Assistant "
style 1-9 fg=bright-magenta bold
14| " Recovered on the next bounded attempt. "
12| " Recovered on the next bounded attempt. "
13| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
14| " "
style 1-1 inverse
15| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
16| " "
style 1-1 inverse
17| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
18| "/workspace/project ↑0 ↓0 0% context tools:compact deepseek-v4-flash(reasoning:on)"
style 0-24 dim
style 38-95 dim
19-35| <blank>
16| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context tools:collapsed"
style 0-43 dim
style 69-95 dim
17-35| <blank>
@@ -1,45 +1,35 @@
terminal 96x36 buffer=normal length=36 base=0 viewport=0
lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=1 viewportRow=13 bufferRow=13
cursor hidden column=1 viewportRow=11 bufferRow=11
buffer
0| "╭──────────────────────────────────────────────────────────────────────────────────────────────╮"
style 0-95 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| <blank>
4| "▌ "
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 95-95 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 95-95 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 95-95 fg=bright-blue
4| "╰──────────────────────────────────────────────────────────────────────────────────────────────╯"
style 0-95 fg=bright-blue
5| <blank>
6| "▌ "
style 0-0 fg=bright-blue
7| "▌ You "
5| "▌ You "
style 0-0 fg=bright-blue
style 2-4 fg=bright-blue bold
8| "▌ Recover this request. "
6| "▌ Recover this request. "
style 0-0 fg=bright-blue
9| "▌ "
7| "▌ "
style 0-0 fg=bright-blue
10| <blank>
11| " Retrying model request (1/2) in 500ms: provider rate limit "
8| <blank>
9| " Retrying model request (1/2) in 500ms: provider rate limit "
style 1-58 fg=yellow
10| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
11| " "
style 1-1 inverse
12| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
13| " "
style 1-1 inverse
14| "────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-95 dim
15| "/workspace/project ↑0 ↓0 0% context tools:compact deepseek-v4-flash(reasoning:on)"
style 0-24 dim
style 38-95 dim
16-35| <blank>
13| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context tools:collapsed"
style 0-43 dim
style 69-95 dim
14-35| <blank>
@@ -0,0 +1,110 @@
terminal 56x36 buffer=normal length=36 base=0 viewport=0
lifecycle started=1 stopped=0 progress=inactive
title "Inspect session diagnostics — DSH snapshot"
cursor hidden column=1 viewportRow=32 bufferRow=32
buffer
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Inspect session diagnostics"
style 1-27 fg=bright-black
2| " deepseek-v4-pro • main-session"
style 1-32 dim
3| <blank>
4| "▌ "
style 0-0 fg=bright-blue
5| "▌ You "
style 0-0 fg=bright-blue
style 2-4 fg=bright-blue bold
6| "▌ inspect this session "
style 0-0 fg=bright-blue
7| "▌ "
style 0-0 fg=bright-blue
8| <blank>
9| " Assistant "
style 1-9 fg=bright-magenta bold
10| " Session inspected. "
11| <blank>
12| "╭─ Session status ─────────────────────────────────────╮"
style 0-2 dim
style 3-16 fg=bright-blue bold
style 17-55 dim
13| "│ Session: main-session │"
style 0-0 dim
style 3-12 fg=bright-black
style 55-55 dim
14| "│ Title: Inspect session diagnostics │"
style 0-0 dim
style 3-12 fg=bright-black
style 55-55 dim
15| "│ Directory: /workspace/project │"
style 0-0 dim
style 3-12 fg=bright-black
style 55-55 dim
16| "│ Model: deepseek/deepseek-v4-pro (reasoning │"
style 0-0 dim
style 3-12 fg=bright-black
style 40-55 dim
17| "│ shown) │"
style 0-0 dim
style 15-20 dim
style 55-55 dim
18| "│ │"
style 0-0 dim
style 55-55 dim
19| "│ Agent: idle · 6 events · 1 turn · 1 step · 1 │"
style 0-0 dim
style 3-12 fg=bright-black
style 55-55 dim
20| "│ tool call │"
style 0-0 dim
style 55-55 dim
21| "│ │"
style 0-0 dim
style 55-55 dim
22| "│ Tokens: 1,250 input + 340 output │"
style 0-0 dim
style 3-12 fg=bright-black
style 55-55 dim
23| "│ KV cache: [███████████░░░░░] 67% hit (3,000 read │"
style 0-0 dim
style 3-12 fg=bright-black
style 15-15 dim
style 16-26 fg=bright-blue
style 27-32 dim
style 55-55 dim
24| "│ + 250 write) │"
style 0-0 dim
style 55-55 dim
25| "│ Context: [█████░░░░░░░░░░░] 33% used (42,000 / │"
style 0-0 dim
style 3-12 fg=bright-black
style 15-15 dim
style 16-20 fg=bright-blue
style 21-32 dim
style 55-55 dim
26| "│ 128,000) │"
style 0-0 dim
style 55-55 dim
27| "│ │"
style 0-0 dim
style 55-55 dim
28| "│ Created: 2026-07-22 09:10:11 UTC │"
style 0-0 dim
style 3-12 fg=bright-black
style 55-55 dim
29| "│ Active: 2026-07-22 09:10:11 UTC │"
style 0-0 dim
style 3-12 fg=bright-black
style 55-55 dim
30| "╰──────────────────────────────────────────────────────╯"
style 0-55 dim
31| "────────────────────────────────────────────────────────"
style 0-55 dim
32| " "
style 1-1 inverse
33| "────────────────────────────────────────────────────────"
style 0-55 dim
34| "deepseek-v4-pro /workspace/project ↑1.3k ↓340 cache 6"
style 0-55 dim
35| <blank>
@@ -0,0 +1,99 @@
terminal 92x32 buffer=normal length=32 base=0 viewport=0
lifecycle started=1 stopped=0 progress=inactive
title "Inspect session diagnostics — DSH snapshot"
cursor hidden column=1 viewportRow=28 bufferRow=28
buffer
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Inspect session diagnostics"
style 1-27 fg=bright-black
2| " deepseek-v4-pro • main-session"
style 1-32 dim
3| <blank>
4| "▌ "
style 0-0 fg=bright-blue
5| "▌ You "
style 0-0 fg=bright-blue
style 2-4 fg=bright-blue bold
6| "▌ inspect this session "
style 0-0 fg=bright-blue
7| "▌ "
style 0-0 fg=bright-blue
8| <blank>
9| " Assistant "
style 1-9 fg=bright-magenta bold
10| " Session inspected. "
11| <blank>
12| "╭─ Session status ─────────────────────────────────────────────────╮"
style 0-2 dim
style 3-16 fg=bright-blue bold
style 17-67 dim
13| "│ Session: main-session │"
style 0-0 dim
style 3-12 fg=bright-black
style 67-67 dim
14| "│ Title: Inspect session diagnostics │"
style 0-0 dim
style 3-12 fg=bright-black
style 67-67 dim
15| "│ Directory: /workspace/project │"
style 0-0 dim
style 3-12 fg=bright-black
style 67-67 dim
16| "│ Model: deepseek/deepseek-v4-pro (reasoning shown) │"
style 0-0 dim
style 3-12 fg=bright-black
style 40-56 dim
style 67-67 dim
17| "│ │"
style 0-0 dim
style 67-67 dim
18| "│ Agent: idle · 6 events · 1 turn · 1 step · 1 tool call │"
style 0-0 dim
style 3-12 fg=bright-black
style 67-67 dim
19| "│ │"
style 0-0 dim
style 67-67 dim
20| "│ Tokens: 1,250 input + 340 output │"
style 0-0 dim
style 3-12 fg=bright-black
style 67-67 dim
21| "│ KV cache: [███████████░░░░░] 67% hit (3,000 read + 250 write) │"
style 0-0 dim
style 3-12 fg=bright-black
style 15-15 dim
style 16-26 fg=bright-blue
style 27-32 dim
style 67-67 dim
22| "│ Context: [█████░░░░░░░░░░░] 33% used (42,000 / 128,000) │"
style 0-0 dim
style 3-12 fg=bright-black
style 15-15 dim
style 16-20 fg=bright-blue
style 21-32 dim
style 67-67 dim
23| "│ │"
style 0-0 dim
style 67-67 dim
24| "│ Created: 2026-07-22 09:10:11 UTC │"
style 0-0 dim
style 3-12 fg=bright-black
style 67-67 dim
25| "│ Active: 2026-07-22 09:10:11 UTC │"
style 0-0 dim
style 3-12 fg=bright-black
style 67-67 dim
26| "╰──────────────────────────────────────────────────────────────────╯"
style 0-67 dim
27| "────────────────────────────────────────────────────────────────────────────────────────────"
style 0-91 dim
28| " "
style 1-1 inverse
29| "────────────────────────────────────────────────────────────────────────────────────────────"
style 0-91 dim
30| "deepseek-v4-pro /workspace/project ↑1.3k ↓340 cache 67% 33% context tools:collapsed"
style 0-57 dim
style 64-91 dim
31| <blank>
@@ -1,40 +1,30 @@
terminal 44x18 buffer=normal length=18 base=0 viewport=0
lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=1 viewportRow=11 bufferRow=11
cursor hidden column=1 viewportRow=9 bufferRow=9
buffer
0| "╭──────────────────────────────────────────╮"
style 0-43 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 43-43 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 43-43 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 43-43 fg=bright-blue
4| "╰──────────────────────────────────────────╯"
style 0-43 fg=bright-blue
5| <blank>
6| " Context · compact "
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| <blank>
4| " Context · compact "
style 1-17 dim
7| " Compacted summary: the prior command "
5| " Compacted summary: the prior command "
style 1-43 fg=bright-black
8| " completed and its details were retired "
6| " completed and its details were retired "
style 1-43 fg=bright-black
9| " from the active surface. "
7| " from the active surface. "
style 1-24 fg=bright-black
8| "────────────────────────────────────────────"
style 0-43 dim
9| " "
style 1-1 inverse
10| "────────────────────────────────────────────"
style 0-43 dim
11| " "
style 1-1 inverse
12| "────────────────────────────────────────────"
11| "deepseek-v4-flash /workspace/project ↑0 ↓0"
style 0-43 dim
13| " 0% context deepseek-v4-flash(reasoning:on)"
style 1-43 dim
14-17| <blank>
12-17| <blank>
@@ -1,37 +1,27 @@
terminal 104x30 buffer=normal length=30 base=0 viewport=0
lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=1 viewportRow=9 bufferRow=9
cursor hidden column=1 viewportRow=7 bufferRow=7
buffer
0| "╭──────────────────────────────────────────────────────────────────────────────────────────────────────╮"
style 0-103 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 103-103 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 103-103 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 103-103 fg=bright-blue
4| "╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯"
style 0-103 fg=bright-blue
5| <blank>
6| " Context · compact "
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| <blank>
4| " Context · compact "
style 1-17 dim
7| " Compacted summary: the prior command completed and its details were retired from the active surface. "
5| " Compacted summary: the prior command completed and its details were retired from the active surface. "
style 1-100 fg=bright-black
6| "────────────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-103 dim
7| " "
style 1-1 inverse
8| "────────────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-103 dim
9| " "
style 1-1 inverse
10| "────────────────────────────────────────────────────────────────────────────────────────────────────────"
style 0-103 dim
11| "/workspace/project ↑0 ↓0 0% context tools:compact deepseek-v4-flash(reasoning:on)"
style 0-24 dim
style 46-103 dim
12-29| <blank>
9| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context tools:collapsed"
style 0-43 dim
style 77-103 dim
10-29| <blank>
@@ -1,68 +1,59 @@
terminal 80x24 buffer=normal length=25 base=1 viewport=1
terminal 80x24 buffer=normal length=24 base=0 viewport=0
lifecycle started=1 stopped=0 progress=inactive
title "DSH snapshot"
cursor hidden column=1 viewportRow=21 bufferRow=22
cursor hidden column=1 viewportRow=20 bufferRow=20
buffer
0| "╭──────────────────────────────────────────────────────────────────────────────╮"
style 0-79 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Snapshot agent ready."
style 1-21 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| <blank>
4| "▌ "
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 79-79 fg=bright-blue
2| "│ Snapshot agent ready. │"
style 0-0 fg=bright-blue
style 2-22 fg=bright-black
style 79-79 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 79-79 fg=bright-blue
4| "╰──────────────────────────────────────────────────────────────────────────────╯"
style 0-79 fg=bright-blue
5| <blank>
6| "▌ "
style 0-0 fg=bright-blue
7| "▌ You "
5| "▌ You "
style 0-0 fg=bright-blue
style 2-4 fg=bright-blue bold
8| "▌ Old prompt with a long line that exercises wrapping before compaction. "
6| "▌ Old prompt with a long line that exercises wrapping before compaction. "
style 0-0 fg=bright-blue
7| "▌ "
style 0-0 fg=bright-blue
8| <blank>
9| "▌ "
style 0-0 fg=bright-blue
10| <blank>
11| "▌ "
style 0-0 fg=green
12| "▌ ✓ pnpm run test:coverage "
10| "▌ ✓ pnpm run test:coverage "
style 0-0 fg=green
style 2-2 fg=green bold
style 3-25 bold
13| "▌ Run the coverage gate "
11| "▌ Run the coverage gate "
style 0-0 fg=green
style 2-22 fg=bright-black
14| "▌ /workspace/project "
12| "▌ /workspace/project "
style 0-0 fg=green
style 2-19 dim
15| "▌ packages/ui/tui 100% "
13| "▌ packages/ui/tui 100% "
style 0-0 fg=green
16| "▌ … +1 lines (Ctrl+O to expand) "
14| "▌ … +1 lines (Ctrl+O to expand) "
style 0-0 fg=green
style 2-30 dim
17| "▌ 1 test skipped "
15| "▌ 1 test skipped "
style 0-0 fg=green
18| "▌ coverage complete "
16| "▌ coverage complete "
style 0-0 fg=green
19| "▌ [exit 0] "
17| "▌ [exit 0] "
style 0-0 fg=green
style 2-9 dim
20| "▌ "
18| "▌ "
style 0-0 fg=green
19| "────────────────────────────────────────────────────────────────────────────────"
style 0-79 dim
20| " "
style 1-1 inverse
21| "────────────────────────────────────────────────────────────────────────────────"
style 0-79 dim
22| " "
style 1-1 inverse
23| "────────────────────────────────────────────────────────────────────────────────"
style 0-79 dim
24| "/workspace/pro ↑0 ↓0 0% context tools:compact deepseek-v4-flash(reasoning:on)"
style 0-13 dim
style 22-79 dim
22| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context tools:collapsed"
style 0-43 dim
style 53-79 dim
23| <blank>
@@ -1,87 +1,77 @@
terminal 100x34 buffer=normal length=40 base=6 viewport=6
terminal 100x34 buffer=normal length=38 base=4 viewport=4
lifecycle started=1 stopped=0 progress=inactive
title "Unsafe terminal title \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m"
cursor hidden column=100 viewportRow=33 bufferRow=39
cursor hidden column=100 viewportRow=33 bufferRow=37
buffer
0| "╭──────────────────────────────────────────────────────────────────────────────────────────────────╮"
style 0-99 fg=bright-blue
1| "│ DEEPSEEK HARNESS │"
0| " DEEPSEEK HARNESS"
style 1-8 fg=bright-blue bold
style 10-16 bold
1| " Unsafe welcome \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m"
style 1-60 fg=bright-black
2| " deepseek-v4-flash • main-session"
style 1-34 dim
3| <blank>
4| "▌ "
style 0-0 fg=bright-blue
style 2-9 fg=bright-blue bold
style 11-17 bold
style 99-99 fg=bright-blue
2| "│ Unsafe welcome \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m │"
style 0-0 fg=bright-blue
style 2-61 fg=bright-black
style 99-99 fg=bright-blue
3| "│ deepseek-v4-flash • main-session │"
style 0-0 fg=bright-blue
style 2-35 dim
style 99-99 fg=bright-blue
4| "╰──────────────────────────────────────────────────────────────────────────────────────────────────╯"
style 0-99 fg=bright-blue
5| <blank>
6| "▌ "
style 0-0 fg=bright-blue
7| "▌ You "
5| "▌ You "
style 0-0 fg=bright-blue
style 2-4 fg=bright-blue bold
8| "▌ Unsafe user \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
6| "▌ Unsafe user \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
style 0-0 fg=bright-blue
9| "▌ "
7| "▌ "
style 0-0 fg=bright-blue
10| <blank>
11| " Reasoning "
8| <blank>
9| " Reasoning "
style 1-9 fg=bright-black italic
12| " Unsafe reasoning \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
10| " Unsafe reasoning \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
style 1-62 fg=bright-black italic
13| <blank>
14| " Assistant "
11| <blank>
12| " Assistant "
style 1-9 fg=bright-magenta bold
15| " Unsafe assistant \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
16| <blank>
17| "▌ "
13| " Unsafe assistant \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
14| <blank>
15| "▌ "
style 0-0 fg=green
18| "▌ ✓ Unsafe title \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
16| "▌ ✓ Unsafe title \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
style 0-0 fg=green
style 2-2 fg=green bold
style 3-61 bold
19| "▌ Unsafe description \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
17| "▌ Unsafe description \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
style 0-0 fg=green
style 2-65 fg=bright-black
20| "▌ /unsafe/\\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
18| "▌ /unsafe/\\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
style 0-0 fg=green
style 2-54 dim
21| "▌ Unsafe output \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
19| "▌ Unsafe output \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
style 0-0 fg=green
22| "▌ [signal SIG\\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m] "
20| "▌ [signal SIG\\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m] "
style 0-0 fg=green
style 2-58 fg=red
23| "▌ "
21| "▌ "
style 0-0 fg=green
24| <blank>
25| " Context · unsafe-\\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
22| <blank>
23| " Context · unsafe-\\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
style 1-62 dim
26| " Unsafe context \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
24| " Unsafe context \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
style 1-60 fg=bright-black
27| <blank>
28| " Prompt blocked: Unsafe policy \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
25| <blank>
26| " Prompt blocked: Unsafe policy \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
style 1-75 fg=yellow
29| <blank>
30| " Unsafe turn error \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
27| <blank>
28| " Unsafe turn error \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
style 1-63 fg=red
31| <blank>
32| " "
33| " Question 1/1 (1 unanswered) · Unsafe header \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
29| <blank>
30| " "
31| " Question 1/1 (1 unanswered) · Unsafe header \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
style 2-90 fg=bright-black
34| " Unsafe question \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
35| " "
36| " › 1. Unsafe option \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m Unsafe detail \\x1b]2;snapshot-c "
32| " Unsafe question \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m "
33| " "
34| " › 1. Unsafe option \\x1b]2;snapshot-controlled\\x07\\x09\\x7f\\x9b31m Unsafe detail \\x1b]2;snapshot-c "
style 2-65 fg=bright-blue bold
style 67-97 fg=bright-black
37| " Tab custom answer • ↑/↓ navigate • Enter submit • Esc interrupt "
35| " Tab custom answer • ↑/↓ navigate • Enter submit • Esc interrupt "
style 2-64 dim
38| " "
39| "/workspace/project ↑0 ↓0 0% context tools:compact deepseek-v4-flash(reasoning:on)"
style 0-24 dim
style 42-99 dim
36| " "
37| "deepseek-v4-flash /workspace/project ↑0 ↓0 0% context tools:collapsed"
style 0-43 dim
style 73-99 dim
+84 -3
View File
@@ -1,12 +1,12 @@
import { mkdir, readdir, writeFile } from 'node:fs/promises'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
import { afterAll, describe, expect, it } from 'vitest'
import { afterAll, describe, expect, it, vi } from 'vitest'
import type { Context } from 'cordis'
import { agentEvents } from '@deepseek-ai/dsh-agent'
import { CallId, type ContentBlock } from '@deepseek-ai/dsh-llm'
import type {} from '@deepseek-ai/dsh-llm-retry'
import type { JsonValue, Session } from '@deepseek-ai/dsh-session'
import { SessionId, type JsonValue, type Session } from '@deepseek-ai/dsh-session'
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
import ToolRegistry, { type ToolDefinition, type ToolResultView } from '@deepseek-ai/dsh-tools'
import * as ToolCordis from '@deepseek-ai/dsh-tool-cordis'
@@ -30,6 +30,7 @@ const CHECKPOINTS = [
'retry-recovered',
'retry-cancelled',
'retry-exhausted',
'banner-gradient',
'code-mode-pending',
'dynamic-workflow-pending',
'cordis-tools-pending',
@@ -45,6 +46,9 @@ const CHECKPOINTS = [
'model-switching',
'errors-and-help',
'disposed-terminal',
'resume-sessions',
'status-diagnostics',
'status-diagnostics-narrow',
] as const
type Checkpoint = typeof CHECKPOINTS[number]
@@ -56,9 +60,23 @@ async function checkpoint(
name: Checkpoint,
terminal: HeadlessTerminal,
options: TerminalSnapshotOptions = {},
bannerGradient = false,
): Promise<void> {
observedCheckpoints.add(name)
expect(terminal.themeViolations(), `${name} must remain theme-agnostic`).toEqual([])
const violations = terminal.themeViolations()
if (bannerGradient) {
// The banner paints its product name in the DeepSeek brand gradient with
// 24-bit foreground codes: the sole sanctioned truecolor. Require it to be
// present and to never leak a background or extended-palette color into the
// otherwise theme-agnostic UI.
expect(violations, `${name} must render the banner gradient`).not.toEqual([])
expect(
violations.every(entry => entry.endsWith('rgb-fg')),
`${name} must confine truecolor to the banner foreground`,
).toBe(true)
} else {
expect(violations, `${name} must remain theme-agnostic`).toEqual([])
}
const snapshot = await terminal.snapshot(options)
const path = join(SNAPSHOTS_DIR, `${name}.expected.txt`)
if (REFRESHING) {
@@ -309,6 +327,12 @@ describe('TUI terminal-state snapshots', () => {
await disposeSnapshot(harness)
})
it('paints the startup banner product name in the DeepSeek brand gradient on truecolor terminals', async () => {
const harness = await setupSnapshot({ config: { truecolor: true } })
await checkpoint('banner-gradient', harness.terminal, {}, true)
await disposeSnapshot(harness)
})
it('pins Code Mode run_code with its production presenter', async () => {
const harness = await setupSnapshot({ configureContext: configureAdvancedTools })
const call = {
@@ -597,6 +621,63 @@ describe('TUI terminal-state snapshots', () => {
await checkpoint('model-switching', harness.terminal, { includeScrollback: true })
await disposeSnapshot(harness)
})
it('lists this workspace\'s resumable sessions with their commands', async () => {
const harness = await setupSnapshot({
config: { resumeCommand: 'RESUME_SESSION_ID={session} dsh' },
sessionPersistence: { list: async () => [
{ version: 0, id: SessionId('main-session'), createdAt: Date.parse('2024-01-02T03:04:00Z'), cwd: '/workspace/project' },
{ version: 0, id: SessionId('earlier-session'), createdAt: Date.parse('2024-01-01T00:00:00Z'), cwd: '/workspace/project' },
] },
}, { columns: 92, rows: 32 })
harness.terminal.send('/resume')
harness.terminal.send('\r')
// `/resume` scans persistence asynchronously, so the listing renders a tick
// after submit (the unit suite waits the same way); settle, then flush.
await new Promise(resolve => setTimeout(resolve, 60))
await harness.terminal.flush()
await checkpoint('resume-sessions', harness.terminal, { includeScrollback: true })
await disposeSnapshot(harness)
})
it('pins the detailed session diagnostics card', async () => {
const dateNow = vi.spyOn(Date, 'now').mockReturnValue(Date.parse('2026-07-22T09:10:11.000Z'))
const harness = await setupSnapshot({
contextWindow: 128_000,
contextTokens: 42_000,
agentOptions: { provider: 'deepseek', model: 'deepseek-v4-pro' },
beforeMount(session) {
appendUser(session, 'inspect this session')
appendAssistant(session, [{ type: 'text', text: 'Session inspected.' }], {
inputTokens: 1_250,
outputTokens: 340,
cacheReadTokens: 3_000,
cacheWriteTokens: 250,
})
session.append('tool/call', {
turn: 1,
step: 1,
callId: CallId('status-call'),
name: 'read',
arguments: '{"path":"README.md"}',
})
session.append('session/title', {
title: 'Inspect session diagnostics',
messageSeqs: [1],
source: { kind: 'fallback' },
})
},
}, { columns: 92, rows: 32 })
await renderAfter(harness, () => {
harness.terminal.send('/status')
harness.terminal.send('\r')
})
await checkpoint('status-diagnostics', harness.terminal, { includeScrollback: true })
await renderAfter(harness, () => { harness.terminal.resize(56, 36) })
await checkpoint('status-diagnostics-narrow', harness.terminal, { includeScrollback: true })
await disposeSnapshot(harness)
dateNow.mockRestore()
})
})
afterAll(async () => {
+793 -19
View File
@@ -4,9 +4,10 @@ import { describe, expect, it, vi } from 'vitest'
import { Context } from 'cordis'
import type { Terminal } from '@earendil-works/pi-tui'
import AgentRegistry, { agentEvents, assembleContextFor, type Agent } from '@deepseek-ai/dsh-agent'
import type { LlmCallConfig } from '@deepseek-ai/dsh-llm'
import { type LlmCallConfig } from '@deepseek-ai/dsh-llm'
import CommandService, { type CommandInvocation } from '@deepseek-ai/dsh-commands'
import SessionStore, { SessionId } from '@deepseek-ai/dsh-session'
import SessionStore, { SessionId, type SessionHeader } from '@deepseek-ai/dsh-session'
import SkillService, { type SkillDefinition, type SkillSummary } from '@deepseek-ai/dsh-skill'
import type {} from '@deepseek-ai/dsh-session-title'
import type { ToolDefinition } from '@deepseek-ai/dsh-tools'
import UserInteractionService from '@deepseek-ai/dsh-user-interaction'
@@ -14,6 +15,7 @@ import type {} from '@deepseek-ai/dsh-llm-retry'
import {
createTuiChat,
mountTui,
renderSkillInvocation,
resolveTuiConfig,
type TuiRuntime,
} from '../src/index.ts'
@@ -127,6 +129,15 @@ function provideTokenMeter(ctx: Context): void {
} as never)
}
/** Minimal advisory-catalog llm stub for tests composing their own context. */
function provideLlmCatalog(ctx: Context): void {
ctx.provide('llm', {
listProviders: () => [],
listModels: () => Promise.resolve([]),
resolveModelContext: () => Promise.resolve(undefined),
} as never)
}
describe('TUI config', () => {
it('defaults every direct-call TUI option', () => {
expect(resolveTuiConfig(undefined)).toEqual({
@@ -140,6 +151,7 @@ describe('TUI config', () => {
modelDialogMaxHeight: 20,
showHardwareCursor: false,
color: true,
truecolor: false,
title: 'DeepSeek Harness',
})
expect(resolveTuiConfig({
@@ -153,6 +165,7 @@ describe('TUI config', () => {
modelDialogMaxHeight: 16,
showHardwareCursor: true,
color: false,
truecolor: true,
title: 'DSH',
})).toEqual({
showReasoning: false,
@@ -165,11 +178,121 @@ describe('TUI config', () => {
modelDialogMaxHeight: 16,
showHardwareCursor: true,
color: false,
truecolor: true,
title: 'DSH',
})
})
})
describe('resume command and /resume', () => {
const RESUME = 'RESUME_SESSION_ID={session} dsh'
const header = (id: string, createdAt: number, cwd: string): SessionHeader =>
({ version: 0, id: SessionId(id), createdAt, cwd })
it('prints the resume command on exit once the session is persisted', async () => {
const result = await setup({
cwd: '/workspace',
config: { resumeCommand: RESUME },
sessionPersistence: { list: async () => [header('main-session', 1000, '/workspace')] },
})
result.terminal.send('/exit')
result.terminal.send('\r')
await tick()
expect(result.terminal.output).toContain('To resume this session: RESUME_SESSION_ID=main-session dsh')
expect(result.exit).toHaveBeenCalledWith(0)
await dispose(result)
})
it('omits the exit hint when the session is not yet persisted', async () => {
const result = await setup({ cwd: '/workspace', config: { resumeCommand: RESUME } })
result.terminal.send('/exit')
result.terminal.send('\r')
await tick()
expect(result.terminal.output).not.toContain('To resume this session')
expect(result.exit).toHaveBeenCalledWith(0)
await dispose(result)
})
it('omits the exit hint when the session listing fails', async () => {
const result = await setup({
cwd: '/workspace',
config: { resumeCommand: RESUME },
sessionPersistence: { list: () => Promise.reject(new Error('disk gone')) },
})
result.terminal.send('/exit')
result.terminal.send('\r')
await tick()
expect(result.terminal.output).not.toContain('To resume this session')
expect(result.exit).toHaveBeenCalledWith(0)
await dispose(result)
})
it('lists this workspace\'s sessions newest-first and marks the current one', async () => {
const result = await setup({
cwd: '/workspace',
config: { resumeCommand: RESUME },
sessionPersistence: {
list: async () => [
header('main-session', 1000, '/workspace'),
header('older-session', 500, '/workspace'),
header('newer-session', 2000, '/workspace'),
header('foreign-session', 3000, '/elsewhere'),
],
},
})
result.terminal.send('/resume')
result.terminal.send('\r')
await tick()
const output = result.terminal.output
expect(output).toContain('Resumable sessions')
expect(output).toContain('RESUME_SESSION_ID=main-session dsh')
expect(output).toContain('(current)')
expect(output).toContain('RESUME_SESSION_ID=newer-session dsh')
expect(output).not.toContain('foreign-session')
// Newest-first: the newer session's command precedes the current session's.
// Match the full resume command, not the bare id: the banner detail line
// echoes the current session id (`main-session`) above the listing.
expect(output.indexOf('RESUME_SESSION_ID=newer-session')).toBeLessThan(
output.indexOf('RESUME_SESSION_ID=main-session'),
)
expect(output.indexOf('RESUME_SESSION_ID=main-session')).toBeLessThan(
output.indexOf('RESUME_SESSION_ID=older-session'),
)
await dispose(result)
})
it('warns from /resume when resume is not configured', async () => {
const result = await setup({ cwd: '/workspace' })
result.terminal.send('/resume')
result.terminal.send('\r')
await tick()
expect(result.terminal.output).toContain('Resume is not configured')
await dispose(result)
})
it('warns from /resume when no persistence backend is mounted', async () => {
const result = await setup({ cwd: '/workspace', config: { resumeCommand: RESUME } })
result.terminal.send('/resume')
result.terminal.send('\r')
await tick()
expect(result.terminal.output).toContain('no persistence backend is mounted')
await dispose(result)
})
it('notes from /resume when no workspace sessions are persisted yet', async () => {
const result = await setup({
cwd: '/workspace',
config: { resumeCommand: RESUME },
sessionPersistence: { list: async () => [header('foreign-session', 10, '/elsewhere')] },
})
result.terminal.send('/resume')
result.terminal.send('\r')
await tick()
expect(result.terminal.output).toContain('No resumable sessions found')
await dispose(result)
})
})
describe('pi-tui chat lifecycle and transcript', () => {
it('uses the latest log-backed title for the header subtitle and terminal window', async () => {
const result = await setup({
@@ -208,6 +331,9 @@ describe('pi-tui chat lifecycle and transcript', () => {
const result = await setup({
contextWindow: 100,
contextTokens: 42,
// Short cwd: the footer clips its right (context/tools) segment first,
// and the default worktree path would swallow it at 88 columns.
cwd: '/opt',
now: () => now,
beforeMount(session) {
appendUser(session, 'restored prompt')
@@ -234,13 +360,14 @@ describe('pi-tui chat lifecycle and transcript', () => {
expect(result.terminal.output).toContain('restored answer')
expect(result.terminal.output).toContain('write tests')
expect(result.terminal.output).toContain('↑1.3k ↓42')
expect(result.terminal.output).toContain('42% context tools:compact deepseek-v4-flash(reasoning:on)')
// Context resolution is async (resolveModelContext); settle before reading.
await tick()
expect(result.terminal.output).toContain('42% context tools:collapsed')
// Narrow terminals clip the right-hand context/tools segment first; the
// model-led left segment stays.
result.terminal.resize(52)
await tick()
expect(result.terminal.output).toContain('42% context deepseek-v4-flash(reasoning:on)')
result.terminal.resize(65)
await tick()
expect(result.terminal.output).toContain('↑1.3k ↓42 42% context deepseek-v4-flash(reasoning:on)')
expect(result.terminal.output).toContain('deepseek-v4-flash')
result.terminal.resize(88)
await tick()
@@ -329,8 +456,7 @@ describe('pi-tui chat lifecycle and transcript', () => {
expect(result.terminal.output).toContain('final live answer')
})
expect(result.terminal.output).toContain('◒ Working · 8s')
expect(result.terminal.output).toContain('esc interrupt')
expect(result.terminal.output).toContain('Enter sends steering, Esc cancels')
expect(result.terminal.output).toContain('Steering')
expect(result.terminal.output).toContain('user context')
expect(result.terminal.output).toContain('Prompt blocked')
@@ -352,7 +478,7 @@ describe('pi-tui chat lifecycle and transcript', () => {
agentEvents(result.ctx, result.agent).emit('agent/status', 'idle')
await tick()
expect(result.terminal.output).toContain('↑1.8k ↓50')
expect(result.terminal.output).toContain('deepseek-v4-flash(reasoning:off)')
expect(result.terminal.output).toContain('deepseek-v4-flash')
expect(result.terminal.progress.at(-1)).toBe(false)
await dispose(result)
expect(result.terminal.stopped).toBe(1)
@@ -421,6 +547,170 @@ describe('pi-tui chat lifecycle and transcript', () => {
await dispose(result)
})
it('badges queued steering on the running status line and clears it as each drains', async () => {
// Pin a cwd free of the substring under test; the footer renders the path.
const result = await setup({ status: 'running', cwd: '/workspace' })
// Running with nothing queued: the plain steering hint, no badge.
expect(result.terminal.output).toContain('— Enter sends steering, Esc cancels')
expect(result.terminal.output).not.toContain('queued')
const queueSteering = (text: string): void => {
result.ctx.emit('agent/queued', result.agent, [{ type: 'text', text }], { source: { kind: 'user' }, steering: true })
}
const drainSteering = (text: string): void => {
result.session.append('steering/message', { turn: 1, content: [{ type: 'text', text }], source: { kind: 'user' } }, { surfaceOp: 'append' })
}
// A steering queue for a different agent never touches this status line.
const other = { ...result.agent, id: SessionId('other') } as Agent
result.terminal.output = ''
result.ctx.emit('agent/queued', other, [{ type: 'text', text: 'elsewhere' }], { source: { kind: 'user' }, steering: true })
await tick()
expect(result.terminal.output).not.toContain('queued')
// Two steering messages queue while the turn runs.
queueSteering('first')
result.terminal.output = ''
queueSteering('second')
await tick()
expect(result.terminal.output).toContain('2 queued · Enter sends steering, Esc cancels')
// A non-steering queue (an idle-style send) leaves the badge untouched.
result.terminal.output = ''
result.ctx.emit('agent/queued', result.agent, [{ type: 'text', text: 'sent' }], { source: { kind: 'user' }, steering: false })
drainSteering('first')
await tick()
expect(result.terminal.output).toContain('1 queued')
expect(result.terminal.output).not.toContain('2 queued')
// Draining the last queued message returns the plain hint.
result.terminal.output = ''
drainSteering('second')
await tick()
expect(result.terminal.output).toContain('— Enter sends steering, Esc cancels')
expect(result.terminal.output).not.toContain('queued')
// A drain with no matching queued entry is ignored rather than underflowing.
result.terminal.output = ''
drainSteering('continuation')
queueSteering('after')
await tick()
expect(result.terminal.output).toContain('1 queued')
// A loop-authored steering event (plugin source, no matching agent/queued)
// cannot consume a pending user slot, even when it drains first.
result.terminal.output = ''
result.session.append('steering/message', {
turn: 1,
content: [{ type: 'text', text: 'continue: goal not reached' }],
source: { kind: 'plugin', plugin: 'hooks' },
}, { surfaceOp: 'append' })
await tick()
expect(result.terminal.output).toContain('1 queued')
result.terminal.output = ''
drainSteering('after')
await tick()
expect(result.terminal.output).not.toContain('queued')
// The turn ending resets the badge, so the next running turn starts clean.
result.agent.status = 'idle'
result.ctx.emit('agent/status', result.agent, 'idle')
result.agent.status = 'running'
result.terminal.output = ''
result.ctx.emit('agent/status', result.agent, 'running')
await tick()
expect(result.terminal.output).toContain('— Enter sends steering, Esc cancels')
expect(result.terminal.output).not.toContain('queued')
await dispose(result)
})
it('derives the fine-grained turn phase from session lifecycle events', async () => {
// A live event before the turn runs has no status controller to move.
const idle = await setup()
// A steering queue arriving while idle has no status line to badge, so the
// refresh is a no-op beyond requesting a render.
idle.ctx.emit('agent/queued', idle.agent, [{ type: 'text', text: 'early' }], { source: { kind: 'user' }, steering: true })
idle.session.append('tool/call', { turn: 1, step: 0, callId: 'pre' as never, name: 'bash', arguments: '{}' })
await tick()
expect(idle.terminal.output).not.toContain('Executing tools')
expect(idle.terminal.output).not.toContain('queued')
await dispose(idle)
const result = await setup({ status: 'running' })
expect(result.terminal.output).toContain('Waiting for the first token')
result.terminal.output = ''
result.session.append('assistant/chunk', { turn: 1, step: 0, chunk: { type: 'block-start', index: 0, blockType: 'reasoning' } })
result.session.append('assistant/chunk', { turn: 1, step: 0, chunk: { type: 'reasoning-delta', index: 0, text: 'mull it over' } })
await tick()
expect(result.terminal.output).toContain('Thinking')
result.terminal.output = ''
result.session.append('assistant/chunk', { turn: 1, step: 0, chunk: { type: 'block-start', index: 1, blockType: 'text' } })
result.session.append('assistant/chunk', { turn: 1, step: 0, chunk: { type: 'text-delta', index: 1, text: 'answering' } })
await tick()
expect(result.terminal.output).toContain('Responding')
result.terminal.output = ''
result.session.append('tool/call', { turn: 1, step: 0, callId: 'c1' as never, name: 'bash', arguments: '{}' })
await tick()
expect(result.terminal.output).toContain('Executing tools')
// The next step reopens the wait window and resets the executing label.
result.terminal.output = ''
result.session.append('step/start', { turn: 1, step: 1 })
await tick()
expect(result.terminal.output).toContain('Waiting for the first token')
expect(result.terminal.output).not.toContain('Executing tools')
await dispose(result)
})
it('refreshes the running status elapsed time on its own timer', async () => {
const result = await setup({ status: 'running' })
result.terminal.output = ''
// The loader repaints "0s" until the controller's own interval fires; a
// non-zero elapsed proves the refresh, not just the loader's animation.
await new Promise(resolve => setTimeout(resolve, 1_300))
expect(result.terminal.output).toMatch(/Waiting for the first token [1-9]s/)
await dispose(result)
})
it('shows minutes and seconds once a step passes a minute', async () => {
const result = await setup({ status: 'running' })
const base = Date.now()
const nowSpy = vi.spyOn(Date, 'now').mockReturnValue(base + 95_000)
result.terminal.output = ''
result.session.append('assistant/chunk', { turn: 1, step: 0, chunk: { type: 'text-delta', index: 0, text: 'hi' } })
await tick()
expect(result.terminal.output).toContain('total 1m')
nowSpy.mockRestore()
await dispose(result)
})
it('preserves the turn phase and elapsed time across a mid-turn color-scheme change', async () => {
const result = await setup({ status: 'running' })
const base = Date.now()
const nowSpy = vi.spyOn(Date, 'now').mockReturnValue(base)
// Advance into `responding`, anchoring the phase clock at `base`.
result.session.append('assistant/chunk', { turn: 1, step: 0, chunk: { type: 'text-delta', index: 0, text: 'answering' } })
await tick()
// Four seconds later the terminal reports a light color scheme, rebuilding
// the status loader; the phase and its elapsed time must survive the rebuild.
nowSpy.mockReturnValue(base + 4_000)
result.terminal.output = ''
result.terminal.send('\x1b[?997;2n')
await tick()
await tick()
expect(result.terminal.output).toContain('Responding 4s')
expect(result.terminal.output).not.toContain('Waiting for the first token')
nowSpy.mockRestore()
await dispose(result)
})
it('renders the ANSI palette and every markdown/content style', async () => {
const result = await setup({
cwd: '/workspace',
@@ -524,6 +814,126 @@ describe('pi-tui chat lifecycle and transcript', () => {
await dispose(logicalResult)
})
it('shows the session cache hit rate in the footer and updates it live', async () => {
// Empty session: no input billed yet, so the cache segment is hidden.
// A cwd without "cache" in it keeps the negative assertion unambiguous.
const empty = await setup({ cwd: '/opt' })
expect(empty.terminal.output).toContain('↑0 ↓0')
expect(empty.terminal.output).not.toContain('cache')
await dispose(empty)
const result = await setup({
// Pin a short cwd so the footer never clips the cache segment: the
// default is process.cwd(), and a deep worktree path truncates
// `cache 60%` at the terminal width.
cwd: '/opt',
beforeMount(session) {
// Cold call: 10 billed input tokens, none served from cache.
appendAssistant(session, [{ type: 'text', text: 'cold' }], { inputTokens: 10, outputTokens: 5 })
},
})
expect(result.terminal.output).toContain('cache 0%')
result.terminal.output = ''
// Warm call lands live on the next step (same-step usage replaces rather
// than accumulates): 5 uncached + 30 cache-read + 5 cache-write billed
// input, so 30 of the 50 total prompt tokens are hits → 60%.
appendAssistant(result.session, [{ type: 'text', text: 'warm' }], {
inputTokens: 5,
outputTokens: 5,
cacheReadTokens: 30,
cacheWriteTokens: 5,
}, { turn: 1, step: 2 })
await tick()
expect(result.terminal.output).toContain('cache 60%')
expect(result.terminal.output).not.toContain('cache 0%')
await dispose(result)
})
it('shows detailed session diagnostics while the agent is running', async () => {
const timestamp = Date.parse('2026-07-22T09:10:11.000Z')
const dateNow = vi.spyOn(Date, 'now').mockReturnValue(timestamp)
const result = await setup({
cwd: '/workspace/status',
contextWindow: 128_000,
contextTokens: 42_000,
config: { showReasoning: false },
agentOptions: { provider: 'deepseek', model: 'deepseek-v4-pro' },
beforeMount(session) {
session.append('session/title', {
title: 'Inspect status \u001B]2;unsafe\u0007',
messageSeqs: [1],
source: { kind: 'fallback' },
})
appendAssistant(session, [{ type: 'text', text: 'measured' }], {
inputTokens: 1_250,
outputTokens: 340,
cacheReadTokens: 3_000,
cacheWriteTokens: 250,
})
session.append('tool/call', {
turn: 1, step: 1, callId: 'status-call-1' as never, name: 'read', arguments: '{}',
})
session.append('tool/call', {
turn: 1, step: 1, callId: 'status-call-2' as never, name: 'write', arguments: '{}',
})
},
})
result.agent.status = 'running'
agentEvents(result.ctx, result.agent).emit('agent/status', 'running')
result.terminal.send('/status')
result.terminal.send('\r')
await tick()
expect(result.terminal.output).toContain('Session status')
expect(result.terminal.output).toContain('main-session')
expect(result.terminal.output).toContain('Inspect status \\x1b]2;unsafe\\x07')
expect(result.terminal.output).toContain('/workspace/status')
expect(result.terminal.output).toContain('deepseek/deepseek-v4-pro (reasoning hidden)')
expect(result.terminal.output).toContain('running · 6 events · 1 turn · 1 step · 2 tool calls')
expect(result.terminal.output).toContain('1,250 input + 340 output')
expect(result.terminal.output).toContain('[███████████░░░░░] 67% hit (3,000 read + 250 write)')
expect(result.terminal.output).toContain('[█████░░░░░░░░░░░] 33% used (42,000 / 128,000)')
expect(result.terminal.output).toContain('2026-07-22 09:10:11 UTC')
expect(result.terminal.output).not.toContain('\u001B]2;unsafe\u0007')
result.terminal.resize(56)
result.terminal.send('/redraw')
result.terminal.send('\r')
await tick()
await dispose(result)
dateNow.mockRestore()
})
it('labels unavailable status diagnostics without inventing values', async () => {
const timestamp = Date.parse('2026-07-22T10:11:12.000Z')
const dateNow = vi.spyOn(Date, 'now').mockReturnValue(timestamp)
const result = await setup({
cwd: null,
omitInitialLifecycle: true,
contextTokens: 7,
agentOptions: {},
catalog: {
providers: [],
models: [],
resolveModelContext: () => Promise.resolve(undefined),
},
})
result.terminal.send('/status')
result.terminal.send('\r')
await tick()
expect(result.terminal.output).toContain('untitled')
expect(result.terminal.output).toContain('unset (reasoning shown)')
expect(result.terminal.output).toContain('idle · 0 events · 0 turns · 0 steps · 0 tool calls')
expect(result.terminal.output).toContain('n/a (0 read + 0 write)')
expect(result.terminal.output).toContain('7 used · capacity unknown')
expect(result.terminal.output).toContain('2026-07-22 10:11:12 UTC')
await dispose(result)
dateNow.mockRestore()
})
it('sends, steers, handles commands, global keys, and disposed-agent input', async () => {
const result = await setup()
@@ -545,17 +955,15 @@ describe('pi-tui chat lifecycle and transcript', () => {
result.terminal.send('\x03')
result.terminal.send('\x12')
result.terminal.send('\x0f')
result.terminal.send('/cancel')
result.terminal.send('\r')
expect(result.agent.cancelled).toContainEqual({ kind: 'user' })
result.agent.status = 'idle'
for (const command of ['/help', '/reasoning', '/tools', '/redraw']) {
for (const command of ['/help', '/reasoning', '/tools', '/redraw', '/reload']) {
result.terminal.send(command)
result.terminal.send('\r')
await tick()
}
for (const command of ['/clear', '/cancel', '/wat']) {
for (const command of ['/clear', '/wat']) {
result.terminal.send(command)
result.terminal.send('\r')
}
@@ -568,8 +976,9 @@ describe('pi-tui chat lifecycle and transcript', () => {
expect(result.terminal.output).toContain('Keyboard shortcuts')
expect(result.terminal.output).toContain('Reasoning blocks')
expect(result.terminal.output).toContain('Tool cards')
expect(result.terminal.output).toContain('already idle')
expect(result.terminal.output).toContain('Unknown command')
// /reload without a Loader in the context degrades to a warning.
expect(result.terminal.output).toContain('/reload needs the cordis Loader')
expect(result.exit).toHaveBeenCalledWith(0)
await result.controller.dispose()
await result.ctx.fiber.dispose()
@@ -635,7 +1044,7 @@ describe('pi-tui chat lifecycle and transcript', () => {
expect(result.agent.steered).toEqual([])
initialContext.resolve({ contextWindow: 100 })
await tick()
expect(result.terminal.output).not.toContain('50% context tools:compact b1(reasoning:on)')
expect(result.terminal.output).not.toContain('50% context tools:collapsed')
result.terminal.send('/model')
result.terminal.send('\r')
@@ -646,7 +1055,8 @@ describe('pi-tui chat lifecycle and transcript', () => {
result.agent.status = 'idle'
result.ctx.emit('agent/status', result.agent, 'idle')
await tick()
expect(result.terminal.output).toContain('25% context tools:compact b1(reasoning:on)')
expect(result.terminal.output).toContain('b1 ')
expect(result.terminal.output).toContain('25% context tools:collapsed')
const assembly = await result.ctx.systemPrompt.assemble(assembleContextFor(result.agent))
expect(assembly.variables).toMatchObject({ provider: 'beta', model: 'b1' })
@@ -691,7 +1101,8 @@ describe('pi-tui chat lifecycle and transcript', () => {
unset.terminal.send('\r')
await tick()
expect(unset.terminal.output).toContain('Model selected: alpha/a1')
expect(unset.terminal.output).toContain('context unknown tools:compact a1(reasoning:on)')
expect(unset.terminal.output).toContain('a1 ')
expect(unset.terminal.output).not.toContain('% context')
await dispose(unset)
const empty = await setup({ agentOptions: {}, catalog: { providers: [], models: [] } })
@@ -790,6 +1201,11 @@ describe('pi-tui chat lifecycle and transcript', () => {
description: 'Fail a plugin command',
handler: () => { throw new Error('plugin command exploded') },
})
result.ctx.commands.register({
name: 'plugin-error',
description: 'Return an error result',
handler: () => ({ kind: 'error' as const, text: 'plugin error result' }),
})
result.terminal.send('/plugin-check value ')
result.terminal.send('\r')
@@ -806,6 +1222,10 @@ describe('pi-tui chat lifecycle and transcript', () => {
result.terminal.send('\r')
await tick()
expect(result.terminal.output).toContain('Command failed: plugin command exploded')
result.terminal.send('/plugin-error')
result.terminal.send('\r')
await tick()
expect(result.terminal.output).toContain('plugin error result')
result.terminal.send('/help')
result.terminal.send('\r')
await tick()
@@ -815,6 +1235,7 @@ describe('pi-tui chat lifecycle and transcript', () => {
await result.controller.dispose()
expect(result.ctx.commands.list(result.agent).map(command => command.name)).toEqual([
'plugin-check',
'plugin-error',
'plugin-fail',
])
await result.ctx.fiber.dispose()
@@ -923,6 +1344,153 @@ describe('pi-tui chat lifecycle and transcript', () => {
})
})
describe('skill slash command', () => {
const withSkills = async (ctx: Context): Promise<void> => {
ctx.provide('tools', { get() { return undefined } } as never)
await ctx.plugin(SkillService)
const skills = ctx.get('skills')
if (skills === undefined) throw new Error('skills service not mounted')
skills.register({ name: 'demo-skill', description: 'Demo skill for tests', source: 'runtime', provider: 'runtime', content: 'Demo instructions body.' })
skills.register({ name: 'hidden-skill', description: 'Model-hidden skill', source: 'runtime', provider: 'runtime', content: 'Hidden instructions body.', disableModelInvocation: true })
}
it('offers non-hidden skills as slash completions and hides model-disabled ones', async () => {
const result = await setup({ configureContext: withSkills })
result.terminal.send('/skill')
await tick()
expect(result.terminal.output).toContain('demo-skill')
expect(result.terminal.output).not.toContain('hidden-skill')
await dispose(result)
})
it('loads a skill as a user turn, appending typed instructions', async () => {
const result = await setup({ configureContext: withSkills })
result.terminal.send('/skill:demo-skill')
result.terminal.send('\r')
await tick()
expect(result.agent.sent).toEqual([[{ type: 'text', text: '<skill name="demo-skill">\nDemo instructions body.\n</skill>' }]])
result.agent.status = 'running'
result.terminal.send('/skill:demo-skill focus on tests')
result.terminal.send('\r')
await tick()
expect(result.agent.steered).toEqual([[{ type: 'text', text: '<skill name="demo-skill">\nDemo instructions body.\n</skill>\n\nfocus on tests' }]])
await dispose(result)
})
it('invokes a model-disabled skill by its exact name', async () => {
const result = await setup({ configureContext: withSkills })
result.terminal.send('/skill:hidden-skill')
result.terminal.send('\r')
await tick()
expect(result.agent.sent).toEqual([[{ type: 'text', text: '<skill name="hidden-skill">\nHidden instructions body.\n</skill>' }]])
await dispose(result)
})
it('reports an unknown skill and an empty skill name without sending', async () => {
const result = await setup({ configureContext: withSkills })
result.terminal.send('/skill:does-not-exist')
result.terminal.send('\r')
await tick()
result.terminal.send('/skill:')
result.terminal.send('\r')
await tick()
// A space right after the colon parses to an empty name, not a name of
// "focus"; the documented syntax puts the name immediately after the colon.
result.terminal.send('/skill: focus')
result.terminal.send('\r')
await tick()
expect(result.terminal.output).toContain('Unknown skill: does-not-exist')
expect(result.terminal.output).toContain('Usage: /skill:<name>')
expect(result.agent.sent).toEqual([])
await dispose(result)
})
it('warns when no skill service is mounted', async () => {
const result = await setup()
result.terminal.send('/skill:demo-skill')
result.terminal.send('\r')
await tick()
expect(result.terminal.output).toContain('Skills are not available')
expect(result.agent.sent).toEqual([])
await dispose(result)
})
it('surfaces skill lookup failures as an error notice', async () => {
const result = await setup({
configureContext: async (ctx) => {
ctx.provide('tools', { get() { return undefined } } as never)
ctx.provide('skills', {
list: () => Promise.reject(new Error('list boom')),
get: () => Promise.reject(new Error('get boom')),
} as never)
},
})
result.terminal.send('/skill:demo-skill')
result.terminal.send('\r')
await tick()
expect(result.terminal.output).toContain('failed to load')
expect(result.terminal.output).toContain('get boom')
await dispose(result)
})
it('drops skill list and lookup results that settle after disposal', async () => {
const pendingList: Array<(value: SkillSummary[]) => void> = []
const pendingGet: Array<{ resolve: (value: SkillDefinition | undefined) => void; reject: (error: unknown) => void }> = []
const result = await setup({
configureContext: async (ctx) => {
ctx.provide('tools', { get() { return undefined } } as never)
ctx.provide('skills', {
list: () => new Promise<SkillSummary[]>((resolve) => { pendingList.push(resolve) }),
get: () => new Promise<SkillDefinition | undefined>((resolve, reject) => { pendingGet.push({ resolve, reject }) }),
} as never)
},
})
result.terminal.send('/skill:demo-skill')
result.terminal.send('\r')
await tick()
result.terminal.send('/skill:other-skill')
result.terminal.send('\r')
await tick()
await dispose(result)
for (const resolve of pendingList) resolve([{ name: 'late', description: 'late', source: 'runtime', provider: 'runtime' }])
pendingGet[0]?.resolve({ name: 'demo-skill', description: 'late', source: 'runtime', provider: 'runtime', content: 'late body' })
pendingGet[1]?.reject(new Error('late failure'))
await tick()
expect(result.agent.sent).toEqual([])
expect(result.terminal.output).not.toContain('late failure')
expect(result.terminal.output).not.toContain('late body')
})
})
describe('renderSkillInvocation', () => {
const skill: SkillDefinition = {
name: 'demo-skill',
description: 'Demo skill',
source: 'runtime',
provider: 'runtime',
content: 'Body text.',
}
it('renders directory, url, opaque, and absent resource bases', () => {
expect(renderSkillInvocation({ ...skill, resourceBase: { kind: 'directory', path: '/skills/demo' } }, '')).toBe(
'<skill name="demo-skill">\nReferences in this skill are relative to /skills/demo.\n\nBody text.\n</skill>',
)
expect(renderSkillInvocation({ ...skill, resourceBase: { kind: 'url', url: 'https://x/y' } }, 'go')).toBe(
'<skill name="demo-skill">\nReferences in this skill are relative to https://x/y.\n\nBody text.\n</skill>\n\ngo',
)
expect(renderSkillInvocation({ ...skill, resourceBase: { kind: 'opaque', description: 'held in memory' } }, '')).toBe(
'<skill name="demo-skill">\nheld in memory\n\nBody text.\n</skill>',
)
expect(renderSkillInvocation(skill, '')).toBe('<skill name="demo-skill">\nBody text.\n</skill>')
})
it('throws on an unknown resource base kind', () => {
expect(() => renderSkillInvocation({ ...skill, resourceBase: { kind: 'future' } as never }, '')).toThrow('unreachable variant')
})
})
describe('tool cards and surface replay', () => {
const tools: Record<string, ToolDefinition> = {
bash: {
@@ -1125,12 +1693,13 @@ describe('TUI user-interaction dialogs', () => {
const single = result.ctx.userInteraction.ask({
questions: [{
id: 'mode', header: 'Mode', question: 'Choose a mode',
id: 'mode', header: 'Mode', question: 'Choose a mode', detail: 'This choice controls the next turn.',
options: [{ label: 'Safe', description: 'Use checks' }, { label: 'Fast' }],
}],
})
await tick()
expect(result.terminal.output).toContain('Choose a mode')
expect(result.terminal.output).toContain('This choice controls the next turn.')
expect(result.terminal.output).toContain('Question 1/1 (1 unanswered) · Mode')
expect(result.terminal.output).toContain('1/2')
result.terminal.send('\x1b[B')
@@ -1295,6 +1864,40 @@ describe('terminal mounting', () => {
await ctx.fiber.dispose()
})
it('degrades /reload to a warning when mounted as a real plugin without a Loader', async () => {
// Production shape: the TUI runs inside a plugin fiber, where a bare
// `ctx.loader` proxy read would THROW `cannot get property without
// inject` — only the non-throwing `ctx.get` lookup degrades gracefully.
const ctx = new Context()
provideTokenMeter(ctx)
provideLlmCatalog(ctx)
await ctx.plugin(SessionStore)
await ctx.plugin(AgentRegistry)
await ctx.plugin(CommandService)
await ctx.plugin(UserInteractionService)
ctx.provide('tools', { get: () => undefined } as never)
const session = ctx.sessions.create(SessionId('main'))
ctx.agents.register({
id: session.id, options: {}, session, status: 'idle', ctx,
send() {}, steer() {}, inject() {}, cancel() {}, whenIdle: () => Promise.resolve(),
})
const terminal = new FakeTerminal()
// Mirror dsh-tui's own inject (minus loader, the absence under test).
await ctx.plugin({
inject: ['agents', 'commands', 'userInteraction', 'tools', 'llm', 'tokenMeter'],
apply: (pluginCtx: Context) => {
mountTui(pluginCtx, { color: false }, { terminal, exit: vi.fn() })
},
})
await tick()
expect(terminal.started).toBe(1)
terminal.send('/reload')
terminal.send('\r')
await tick()
expect(terminal.output).toContain('/reload needs the cordis Loader')
await ctx.fiber.dispose()
})
it('waits for its configured agent before starting the TUI', async () => {
const ctx = new Context()
provideTokenMeter(ctx)
@@ -1476,4 +2079,175 @@ describe('terminal mounting', () => {
expect(terminal.output).toContain('\x1b[2mdeepseek-v4-flash')
await disposeTuiTestHarness(result)
})
it('runs /reload against every file-backed loader subtree, reports completion, and rejects re-entry while in flight', async () => {
const refreshed: string[] = []
let releaseRefresh!: () => void
const gate = new Promise<void>((resolve) => { releaseRefresh = resolve })
const result = await setup({
configureContext: async (ctx) => {
ctx.provide('tools', { get: () => undefined } as never)
// A structural Loader: two file-backed subtrees and one plain entry.
// The first subtree blocks on a gate so re-entry can be probed
// deterministically mid-flight.
ctx.provide('loader', {
entries: () => [
{ subtree: { refresh: async () => { refreshed.push('root'); await gate } } },
{},
{ subtree: { refresh: async () => { refreshed.push('nested') } } },
],
} as never)
},
})
result.terminal.send('/reload')
result.terminal.send('\r')
await tick()
expect(result.terminal.output).toContain('Reloading 2 config tree(s)')
// Second /reload while the first is gated: refused, no extra refreshes.
result.terminal.send('/reload')
result.terminal.send('\r')
await tick()
expect(result.terminal.output).toContain('A config reload is already running.')
expect(refreshed.sort()).toEqual(['nested', 'root'])
releaseRefresh()
await tick()
expect(result.terminal.output).toContain('Config reload complete.')
// The guard released: a third /reload runs again.
result.terminal.send('/reload')
result.terminal.send('\r')
await tick()
expect(refreshed).toHaveLength(4)
await dispose(result)
})
it('reports a /reload failure if a refresh ever rejects', async () => {
const result = await setup({
configureContext: async (ctx) => {
ctx.provide('tools', { get: () => undefined } as never)
ctx.provide('loader', {
entries: () => [{ subtree: { refresh: () => Promise.reject(new Error('disk gone')) } }],
} as never)
},
})
result.terminal.send('/reload')
result.terminal.send('\r')
await tick()
expect(result.terminal.output).toContain('Config reload failed: disk gone')
// The failure arm also releases the re-entrancy guard.
result.terminal.send('/reload')
result.terminal.send('\r')
await tick()
expect(result.terminal.output).not.toContain('A config reload is already running.')
await dispose(result)
})
it('refuses /reload while the agent is running and allows it back at idle', async () => {
const refreshed: string[] = []
const result = await setup({
status: 'running',
configureContext: async (ctx) => {
ctx.provide('tools', { get: () => undefined } as never)
ctx.provide('loader', {
entries: () => [{ subtree: { refresh: async () => { refreshed.push('tree') } } }],
} as never)
},
})
result.terminal.send('/reload')
result.terminal.send('\r')
await tick()
expect(result.terminal.output).toContain('/reload requires an idle agent (status: running).')
expect(refreshed).toHaveLength(0)
// Back at idle the same command runs.
result.agent.status = 'idle'
result.terminal.send('/reload')
result.terminal.send('\r')
await tick()
expect(refreshed).toHaveLength(1)
expect(result.terminal.output).toContain('Config reload complete.')
await dispose(result)
})
})
describe('banner sweep reveal', () => {
it('renders the product name through the brand-gradient path when truecolor is enabled', async () => {
// The product name carries a per-letter 24-bit gradient from the brand
// indigo to light blue; the per-letter layout is pinned by the
// `banner-gradient` terminal snapshot.
const result = await setup({ config: { color: true, truecolor: true } })
expect(result.terminal.output).toContain('\x1b[38;2;77;107;254m')
expect(result.terminal.output).toContain('\x1b[38;2;36;152;255m')
expect(result.terminal.output).toContain('HARNESS')
await dispose(result)
})
it('sweeps the whole borderless banner in when no welcome is configured, ending complete', async () => {
const intervals = vi.spyOn(globalThis, 'setInterval')
const cleared = vi.spyOn(globalThis, 'clearInterval')
const result = await setup({ omitWelcome: true })
const revealHandle = intervals.mock.results.at(-1)?.value as ReturnType<typeof setInterval>
// Run the sweep to natural completion — it clears its own timer at the end.
const done = (): boolean => cleared.mock.calls.some(call => call[0] === revealHandle)
const deadline = Date.now() + 5000
while (!done() && Date.now() < deadline) await tick()
intervals.mockRestore()
cleared.mockRestore()
// The finished banner carries the title and the model • session detail.
expect(result.terminal.output).toContain('DEEPSEEK')
expect(result.terminal.output).toContain('HARNESS')
expect(result.terminal.output).toContain('main-session')
// Borderless: no box-drawing frame around the banner.
expect(result.terminal.output).not.toContain('╭')
expect(result.terminal.output).not.toContain('╮')
// A mid-sweep frame rendered a clipped title: `DEEPSEEK` with no `HARNESS`
// on the same line.
const clipped = result.terminal.output
.split('\n')
.some(line => line.includes('DEEPSEEK') && !line.includes('HARNESS'))
expect(clipped).toBe(true)
await dispose(result)
})
it('renders a configured welcome verbatim in a complete banner with no sweep', async () => {
const result = await setup()
await tick()
expect(result.terminal.output).toContain('Coding agent ready.')
expect(result.terminal.output).toContain('DEEPSEEK')
expect(result.terminal.output).not.toContain('╭')
// No reveal frames: the banner is drawn whole from the first render, so no
// clipped-title frame ever appears.
const clipped = result.terminal.output
.split('\n')
.some(line => line.includes('DEEPSEEK') && !line.includes('HARNESS'))
expect(clipped).toBe(false)
await dispose(result)
})
it('omits the subtitle line entirely when no welcome is configured', async () => {
const result = await setup({ omitWelcome: true })
const deadline = Date.now() + 5000
while (!result.terminal.output.includes('main-session') && Date.now() < deadline) await tick()
// Banner is title + detail only — no subtitle between them.
expect(result.terminal.output).toContain('deepseek-v4-flash')
expect(result.terminal.output).not.toContain('ready.')
await dispose(result)
})
it('stops a mid-sweep animation on dispose', async () => {
// The output-stability probe alone is insensitive to a leaked interval
// (pi-tui's stopped guard silences post-stop renders), so capture the
// reveal's own interval handle and assert dispose clears exactly it.
const intervals = vi.spyOn(globalThis, 'setInterval')
const result = await setup({ omitWelcome: true })
const revealHandle = intervals.mock.results.at(-1)?.value as ReturnType<typeof setInterval>
expect(revealHandle).toBeDefined()
const cleared = vi.spyOn(globalThis, 'clearInterval')
await dispose(result)
expect(cleared.mock.calls.some(call => call[0] === revealHandle)).toBe(true)
intervals.mockRestore()
cleared.mockRestore()
const settled = result.terminal.output.length
await tick()
await tick()
expect(result.terminal.output.length).toBe(settled)
})
})