Merge remote-tracking branch 'origin/master' into feat/web-diff-card
# Conflicts: # packages/client/ui-conversation/README.i18n.yaml # packages/client/ui-conversation/src/client/chat/GenericToolCard.tsx # packages/client/ui-conversation/src/client/chat/ToolRow.tsx # packages/client/ui-conversation/src/client/skeleton/DetailsPanel.tsx # packages/client/ui-primitives/README.i18n.yaml # packages/client/ui-primitives/src/index.ts
This commit is contained in:
@@ -105,10 +105,10 @@ export async function createTuiTestHarness<TerminalType extends Terminal, Exit e
|
||||
await ctx.plugin(UserInteractionService)
|
||||
await ctx.plugin(TuiPromptService)
|
||||
const catalog = options.catalog ?? {
|
||||
providers: [{ id: 'deepseek', name: 'DeepSeek' }],
|
||||
providers: [{ id: 'deepseek-official', name: 'DeepSeek' }],
|
||||
models: [
|
||||
{ provider: 'deepseek', id: 'deepseek-v4-flash', name: 'DeepSeek V4 Flash' },
|
||||
{ provider: 'deepseek', id: 'deepseek-v4-pro', name: 'DeepSeek V4 Pro' },
|
||||
{ provider: 'deepseek-official', id: 'deepseek-v4-flash', name: 'DeepSeek V4 Flash' },
|
||||
{ provider: 'deepseek-official', id: 'deepseek-v4-pro', name: 'DeepSeek V4 Pro' },
|
||||
],
|
||||
}
|
||||
ctx.provide('tokenMeter', {
|
||||
@@ -194,7 +194,7 @@ export async function createTuiTestHarness<TerminalType extends Terminal, Exit e
|
||||
const cancelled: AgentCancelCause[] = []
|
||||
const agent: FakeAgent = {
|
||||
id: sessionId,
|
||||
options: options.agentOptions ?? { provider: 'deepseek', model: 'deepseek-v4-flash' },
|
||||
options: options.agentOptions ?? { provider: 'deepseek-official', model: 'deepseek-v4-flash' },
|
||||
session,
|
||||
status: options.status ?? 'idle',
|
||||
get acceptsNextStep() {
|
||||
|
||||
@@ -152,8 +152,8 @@ describe('TUI prompt values', () => {
|
||||
describe('TUI prompt templates', () => {
|
||||
it('interpolates values and removes separators around unavailable values', () => {
|
||||
const tokens = parseTuiPromptTemplate('${cwd} ${git/worktree} :: ${missing} ${model}')
|
||||
const values = new Map([['cwd', '/work'], ['model', 'deepseek']])
|
||||
expect(renderTuiPromptTemplate(tokens, name => values.get(name))).toBe('/work :: deepseek')
|
||||
const values = new Map([['cwd', '/work'], ['model', 'deepseek-official']])
|
||||
expect(renderTuiPromptTemplate(tokens, name => values.get(name))).toBe('/work :: deepseek-official')
|
||||
})
|
||||
|
||||
it('keeps a trailing literal after the last value', () => {
|
||||
|
||||
@@ -36,9 +36,9 @@ buffer
|
||||
14| " │ │ "
|
||||
style 8-8 fg=bright-magenta
|
||||
style 83-83 fg=bright-magenta
|
||||
15| " │ → deepseek/deepseek-v4-pro DeepSeek V4 Pro │ "
|
||||
15| " │ → deepseek-official/deepseek-v4- DeepSeek V4 Pro │ "
|
||||
style 8-8 fg=bright-magenta
|
||||
style 10-58 fg=bright-magenta inverse
|
||||
style 10-41 fg=bright-magenta inverse
|
||||
style 83-83 fg=bright-magenta
|
||||
16| " │ │ "
|
||||
style 8-8 fg=bright-magenta
|
||||
|
||||
@@ -36,13 +36,13 @@ buffer
|
||||
14| " │ │ "
|
||||
style 8-8 fg=bright-magenta
|
||||
style 83-83 fg=bright-magenta
|
||||
15| " │ → deepseek/deepseek-v4-flash DeepSeek V4 Flash — current │ "
|
||||
15| " │ → deepseek-official/deepseek-v4- DeepSeek V4 Flash — current │ "
|
||||
style 8-8 fg=bright-magenta
|
||||
style 10-70 fg=bright-magenta inverse
|
||||
style 10-41 fg=bright-magenta inverse
|
||||
style 83-83 fg=bright-magenta
|
||||
16| " │ deepseek/deepseek-v4-pro DeepSeek V4 Pro │ "
|
||||
16| " │ deepseek-official/deepseek-v4- DeepSeek V4 Pro │ "
|
||||
style 8-8 fg=bright-magenta
|
||||
style 36-58 dim
|
||||
style 42-58 dim
|
||||
style 83-83 fg=bright-magenta
|
||||
17| " │ │ "
|
||||
style 8-8 fg=bright-magenta
|
||||
|
||||
@@ -16,8 +16,8 @@ buffer
|
||||
5| "Model wait 0.0s "
|
||||
style 0-14 dim
|
||||
6| <blank>
|
||||
7| "Model selected: deepseek/deepseek-v4-pro. New steps will use it. "
|
||||
style 0-63 dim
|
||||
7| "Model selected: deepseek-official/deepseek-v4-pro. New steps will use it. "
|
||||
style 0-72 dim
|
||||
8| <blank>
|
||||
9| "/workspace/project (tui-staging) deepseek-v4-pro ↑0 ↓0 0% context"
|
||||
style 0-17 fg=bright-magenta bold
|
||||
|
||||
@@ -31,15 +31,15 @@ buffer
|
||||
13| " unavailable: current session "
|
||||
style 2-31 fg=yellow
|
||||
14| " Other workspace work "
|
||||
15| " 2024-02-02T00:00:08.000Z · turn 1: completed · deepseek/deepseek-v4-pro "
|
||||
style 2-74 dim
|
||||
15| " 2024-02-02T00:00:08.000Z · turn 1: completed · deepseek-official/deepseek-v4-pro "
|
||||
style 2-83 dim
|
||||
16| " persisted · elsewhere-session "
|
||||
style 2-32 dim
|
||||
17| " workspace /workspace/other "
|
||||
style 2-29 dim
|
||||
18| " Resume selector design "
|
||||
19| " 2024-01-01T00:00:08.000Z · turn 1: completed · deepseek/deepseek-v4-pro "
|
||||
style 2-74 dim
|
||||
19| " 2024-01-01T00:00:08.000Z · turn 1: completed · deepseek-official/deepseek-v4-pro "
|
||||
style 2-83 dim
|
||||
20| " persisted · earlier-session "
|
||||
style 2-30 dim
|
||||
21| " workspace /workspace/project "
|
||||
|
||||
@@ -29,8 +29,8 @@ buffer
|
||||
12| " unavailable: current session "
|
||||
style 2-31 fg=yellow
|
||||
13| " Resume selector design "
|
||||
14| " 2024-01-01T00:00:08.000Z · turn 1: completed · deepseek/deepseek-v4-pro "
|
||||
style 2-74 dim
|
||||
14| " 2024-01-01T00:00:08.000Z · turn 1: completed · deepseek-official/deepseek-v4-pro "
|
||||
style 2-83 dim
|
||||
15| " persisted · earlier-session "
|
||||
style 2-30 dim
|
||||
16| " "
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
terminal 56x36 buffer=normal length=44 base=8 viewport=8
|
||||
terminal 56x36 buffer=normal length=45 base=9 viewport=9
|
||||
lifecycle started=1 stopped=0 progress=inactive
|
||||
title "Inspect session diagnostics — DSH snapshot"
|
||||
cursor hidden column=7 viewportRow=35 bufferRow=43
|
||||
cursor hidden column=7 viewportRow=35 bufferRow=44
|
||||
buffer
|
||||
0| " DEEPSEEK HARNESS"
|
||||
style 1-8 fg=bright-magenta bold
|
||||
@@ -37,84 +37,87 @@ buffer
|
||||
style 0-0 dim
|
||||
style 3-12 dim
|
||||
style 55-55 dim
|
||||
15| "│ Model: deepseek/deepseek-v4-pro (effort │"
|
||||
style 0-0 dim
|
||||
style 3-12 dim
|
||||
style 40-55 dim
|
||||
16| "│ default; reasoning blocks shown) │"
|
||||
style 0-0 dim
|
||||
style 15-46 dim
|
||||
style 55-55 dim
|
||||
17| "│ │"
|
||||
style 0-0 dim
|
||||
style 55-55 dim
|
||||
18| "│ Agent: idle · 8 events · 1 turn · 1 step · 1 │"
|
||||
15| "│ Model: deepseek-official/deepseek-v4-pro │"
|
||||
style 0-0 dim
|
||||
style 3-12 dim
|
||||
style 55-55 dim
|
||||
19| "│ tool call │"
|
||||
16| "│ (effort default; reasoning blocks │"
|
||||
style 0-0 dim
|
||||
style 15-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
|
||||
20| "│ │"
|
||||
style 0-0 dim
|
||||
style 55-55 dim
|
||||
21| "│ Tokens: 1,250 input + 340 output │"
|
||||
19| "│ Agent: idle · 8 events · 1 turn · 1 step · 1 │"
|
||||
style 0-0 dim
|
||||
style 3-12 dim
|
||||
style 55-55 dim
|
||||
22| "│ KV cache: [███████████░░░░░] 67% hit (3,000 read │"
|
||||
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 dim
|
||||
style 55-55 dim
|
||||
23| "│ KV cache: [███████████░░░░░] 67% hit (3,000 read │"
|
||||
style 0-0 dim
|
||||
style 3-12 dim
|
||||
style 15-15 dim
|
||||
style 16-26 fg=bright-magenta
|
||||
style 27-32 dim
|
||||
style 55-55 dim
|
||||
23| "│ + 250 write) │"
|
||||
24| "│ + 250 write) │"
|
||||
style 0-0 dim
|
||||
style 55-55 dim
|
||||
24| "│ Context: [█████░░░░░░░░░░░] 33% used (42,000 / │"
|
||||
25| "│ Context: [█████░░░░░░░░░░░] 33% used (42,000 / │"
|
||||
style 0-0 dim
|
||||
style 3-12 dim
|
||||
style 15-15 dim
|
||||
style 16-20 fg=bright-magenta
|
||||
style 21-32 dim
|
||||
style 55-55 dim
|
||||
25| "│ 128,000) │"
|
||||
26| "│ 128,000) │"
|
||||
style 0-0 dim
|
||||
style 55-55 dim
|
||||
26| "│ │"
|
||||
27| "│ │"
|
||||
style 0-0 dim
|
||||
style 55-55 dim
|
||||
27| "│ Created: 2026-07-22 09:10:11 UTC │"
|
||||
28| "│ Created: 2026-07-22 09:10:11 UTC │"
|
||||
style 0-0 dim
|
||||
style 3-12 dim
|
||||
style 55-55 dim
|
||||
28| "│ Active: 2026-07-22 09:10:11 UTC │"
|
||||
29| "│ Active: 2026-07-22 09:10:11 UTC │"
|
||||
style 0-0 dim
|
||||
style 3-12 dim
|
||||
style 55-55 dim
|
||||
29| "╰──────────────────────────────────────────────────────╯"
|
||||
30| "╰──────────────────────────────────────────────────────╯"
|
||||
style 0-55 dim
|
||||
30| <blank>
|
||||
31| "System prompt "
|
||||
31| <blank>
|
||||
32| "System prompt "
|
||||
style 0-12 fg=bright-magenta bold
|
||||
32| "You are an AI agent powered by the DeepSeek Harness SDK."
|
||||
33| " "
|
||||
34| "Paths prefixed with @ are files explicitly referenced by"
|
||||
35| "the user. Use the read tool when their contents are "
|
||||
36| "needed; do not claim to have inspected a file before "
|
||||
37| "reading it. "
|
||||
38| <blank>
|
||||
39| "Registered tools "
|
||||
33| "You are an AI agent powered by the DeepSeek Harness SDK."
|
||||
34| " "
|
||||
35| "Paths prefixed with @ are files explicitly referenced by"
|
||||
36| "the user. Use the read tool when their contents are "
|
||||
37| "needed; do not claim to have inspected a file before "
|
||||
38| "reading it. "
|
||||
39| <blank>
|
||||
40| "Registered tools "
|
||||
style 0-15 fg=bright-magenta bold
|
||||
40| "read, write "
|
||||
41| <blank>
|
||||
42| "/workspace/project (tui-staging) deepseek-v4-pro ↑1.3k"
|
||||
41| "read, write "
|
||||
42| <blank>
|
||||
43| "/workspace/project (tui-staging) deepseek-v4-pro ↑1.3k"
|
||||
style 0-17 fg=bright-magenta bold
|
||||
style 18-31 dim
|
||||
style 34-48 dim
|
||||
style 51-55 dim
|
||||
43| " dsh > "
|
||||
44| " dsh > "
|
||||
style 1-3 fg=bright-magenta bold
|
||||
style 5-6 dim
|
||||
style 7-7 inverse
|
||||
|
||||
@@ -21,68 +21,68 @@ buffer
|
||||
style 0-2 fg=bright-magenta bold underline
|
||||
9| "inspect this session "
|
||||
10| <blank>
|
||||
11| "╭─ Session status ───────────────────────────────────────────────────────────────╮"
|
||||
11| "╭─ Session status ────────────────────────────────────────────────────────────────────────╮"
|
||||
style 0-2 dim
|
||||
style 3-16 fg=bright-magenta bold
|
||||
style 17-81 dim
|
||||
12| "│ Session: main-session │"
|
||||
style 17-90 dim
|
||||
12| "│ Session: main-session │"
|
||||
style 0-0 dim
|
||||
style 3-12 dim
|
||||
style 81-81 dim
|
||||
13| "│ Title: Inspect session diagnostics │"
|
||||
style 90-90 dim
|
||||
13| "│ Title: Inspect session diagnostics │"
|
||||
style 0-0 dim
|
||||
style 3-12 dim
|
||||
style 81-81 dim
|
||||
14| "│ Directory: /workspace/project │"
|
||||
style 90-90 dim
|
||||
14| "│ Directory: /workspace/project │"
|
||||
style 0-0 dim
|
||||
style 3-12 dim
|
||||
style 81-81 dim
|
||||
15| "│ Model: deepseek/deepseek-v4-pro (effort default; reasoning blocks shown) │"
|
||||
style 90-90 dim
|
||||
15| "│ Model: deepseek-official/deepseek-v4-pro (effort default; reasoning blocks shown) │"
|
||||
style 0-0 dim
|
||||
style 3-12 dim
|
||||
style 40-79 dim
|
||||
style 81-81 dim
|
||||
16| "│ │"
|
||||
style 49-88 dim
|
||||
style 90-90 dim
|
||||
16| "│ │"
|
||||
style 0-0 dim
|
||||
style 81-81 dim
|
||||
17| "│ Agent: idle · 8 events · 1 turn · 1 step · 1 tool call │"
|
||||
style 90-90 dim
|
||||
17| "│ Agent: idle · 8 events · 1 turn · 1 step · 1 tool call │"
|
||||
style 0-0 dim
|
||||
style 3-12 dim
|
||||
style 81-81 dim
|
||||
18| "│ │"
|
||||
style 90-90 dim
|
||||
18| "│ │"
|
||||
style 0-0 dim
|
||||
style 81-81 dim
|
||||
19| "│ Tokens: 1,250 input + 340 output │"
|
||||
style 90-90 dim
|
||||
19| "│ Tokens: 1,250 input + 340 output │"
|
||||
style 0-0 dim
|
||||
style 3-12 dim
|
||||
style 81-81 dim
|
||||
20| "│ KV cache: [███████████░░░░░] 67% hit (3,000 read + 250 write) │"
|
||||
style 90-90 dim
|
||||
20| "│ KV cache: [███████████░░░░░] 67% hit (3,000 read + 250 write) │"
|
||||
style 0-0 dim
|
||||
style 3-12 dim
|
||||
style 15-15 dim
|
||||
style 16-26 fg=bright-magenta
|
||||
style 27-32 dim
|
||||
style 81-81 dim
|
||||
21| "│ Context: [█████░░░░░░░░░░░] 33% used (42,000 / 128,000) │"
|
||||
style 90-90 dim
|
||||
21| "│ Context: [█████░░░░░░░░░░░] 33% used (42,000 / 128,000) │"
|
||||
style 0-0 dim
|
||||
style 3-12 dim
|
||||
style 15-15 dim
|
||||
style 16-20 fg=bright-magenta
|
||||
style 21-32 dim
|
||||
style 81-81 dim
|
||||
22| "│ │"
|
||||
style 90-90 dim
|
||||
22| "│ │"
|
||||
style 0-0 dim
|
||||
style 81-81 dim
|
||||
23| "│ Created: 2026-07-22 09:10:11 UTC │"
|
||||
style 90-90 dim
|
||||
23| "│ Created: 2026-07-22 09:10:11 UTC │"
|
||||
style 0-0 dim
|
||||
style 3-12 dim
|
||||
style 81-81 dim
|
||||
24| "│ Active: 2026-07-22 09:10:11 UTC │"
|
||||
style 90-90 dim
|
||||
24| "│ Active: 2026-07-22 09:10:11 UTC │"
|
||||
style 0-0 dim
|
||||
style 3-12 dim
|
||||
style 81-81 dim
|
||||
25| "╰────────────────────────────────────────────────────────────────────────────────╯"
|
||||
style 0-81 dim
|
||||
style 90-90 dim
|
||||
25| "╰─────────────────────────────────────────────────────────────────────────────────────────╯"
|
||||
style 0-90 dim
|
||||
26| <blank>
|
||||
27| "System prompt "
|
||||
style 0-12 fg=bright-magenta bold
|
||||
|
||||
@@ -554,7 +554,7 @@ describe('TUI terminal-state snapshots', () => {
|
||||
description: 'Audit terminal states from independent angles',
|
||||
phases: [
|
||||
{ title: 'Inspect', detail: 'Map renderer branches' },
|
||||
{ title: 'Verify', detail: 'Challenge missing states', provider: 'deepseek', model: 'deepseek-v4-flash' },
|
||||
{ title: 'Verify', detail: 'Challenge missing states', provider: 'deepseek-official', model: 'deepseek-v4-flash' },
|
||||
],
|
||||
},
|
||||
args: { packages: ['ui/tui', 'workflow/tool-workflow'] },
|
||||
@@ -866,13 +866,13 @@ describe('TUI terminal-state snapshots', () => {
|
||||
{ type: 'turn/start', seq: 0, time: Date.parse(`${day}T00:00:01Z`), data: { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } } },
|
||||
{ type: 'user/message', seq: 1, time: Date.parse(`${day}T00:00:02Z`), data: createUserMessage({ content: [{ type: 'text', text: 'restore the selector' }], source: { kind: 'user' } }), surfaceOp: 'append' },
|
||||
{ type: 'step/start', seq: 2, time: Date.parse(`${day}T00:00:03Z`), data: { turn: 1, step: 1 } },
|
||||
{ type: 'request/header', seq: 3, time: Date.parse(`${day}T00:00:04Z`), data: { header: { config: { provider: 'deepseek', model: 'deepseek-v4-pro' } }, reason: 'initial' } },
|
||||
{ type: 'request/header', seq: 3, time: Date.parse(`${day}T00:00:04Z`), data: { header: { config: { provider: 'deepseek-official', model: 'deepseek-v4-pro' } }, reason: 'initial' } },
|
||||
{ type: 'assistant/message', seq: 4, time: Date.parse(`${day}T00:00:05Z`), data: {
|
||||
turn: 1, step: 1,
|
||||
message: createMessage({
|
||||
role: 'assistant',
|
||||
content: [{ type: 'text', text: 'ready' }],
|
||||
source: { kind: 'model', provider: 'deepseek', model: 'deepseek-v4-pro' },
|
||||
source: { kind: 'model', provider: 'deepseek-official', model: 'deepseek-v4-pro' },
|
||||
}),
|
||||
}, surfaceOp: 'append' },
|
||||
{ type: 'step/end', seq: 5, time: Date.parse(`${day}T00:00:06Z`), data: { turn: 1, step: 1 } },
|
||||
@@ -913,7 +913,7 @@ describe('TUI terminal-state snapshots', () => {
|
||||
const harness = await setupSnapshot({
|
||||
contextWindow: 128_000,
|
||||
contextTokens: 42_000,
|
||||
agentOptions: { provider: 'deepseek', model: 'deepseek-v4-pro' },
|
||||
agentOptions: { provider: 'deepseek-official', model: 'deepseek-v4-pro' },
|
||||
tools: {
|
||||
read: {
|
||||
name: 'read',
|
||||
|
||||
@@ -247,7 +247,7 @@ describe('goodbye message and /resume', () => {
|
||||
({ version: 0, id: SessionId(id), createdAt, cwd })
|
||||
const resumeEvents = (
|
||||
title: string,
|
||||
provider = 'deepseek',
|
||||
provider = 'deepseek-official',
|
||||
time = 100,
|
||||
reason: TurnEndReason = { kind: 'completed' },
|
||||
): SessionEvent[] => [
|
||||
@@ -319,8 +319,8 @@ describe('goodbye message and /resume', () => {
|
||||
sessionPersistence: {
|
||||
list: async () => [older, newer, header('foreign-session', 3000, '/elsewhere')],
|
||||
load: async id => id === newer.id
|
||||
? { meta: newer, events: resumeEvents('Newer product work', 'deepseek', 300) }
|
||||
: { meta: older, events: resumeEvents('Older investigation', 'deepseek', 100) },
|
||||
? { meta: newer, events: resumeEvents('Newer product work', 'deepseek-official', 300) }
|
||||
: { meta: older, events: resumeEvents('Older investigation', 'deepseek-official', 100) },
|
||||
},
|
||||
})
|
||||
result.terminal.send('/resume')
|
||||
@@ -419,7 +419,7 @@ describe('goodbye message and /resume', () => {
|
||||
list: async () => targets,
|
||||
load: async id => ({
|
||||
meta: targets.find(target => target.id === id)!,
|
||||
events: resumeEvents(`Paged ${id.slice('paged-'.length)}`, 'deepseek', 1000 - Number(id.slice('paged-'.length)) * 10),
|
||||
events: resumeEvents(`Paged ${id.slice('paged-'.length)}`, 'deepseek-official', 1000 - Number(id.slice('paged-'.length)) * 10),
|
||||
}),
|
||||
},
|
||||
})
|
||||
@@ -475,7 +475,7 @@ describe('goodbye message and /resume', () => {
|
||||
cwd: '/workspace',
|
||||
sessionPersistence: {
|
||||
list: async () => [target],
|
||||
load: async () => ({ meta: target, events: resumeEvents(`Turn ${label}`, 'deepseek', 100, reason) }),
|
||||
load: async () => ({ meta: target, events: resumeEvents(`Turn ${label}`, 'deepseek-official', 100, reason) }),
|
||||
},
|
||||
})
|
||||
result.terminal.send('/resume')
|
||||
@@ -711,7 +711,7 @@ describe('goodbye message and /resume', () => {
|
||||
it('falls back to assistant provenance and header creation time for sparse logs', async () => {
|
||||
const assistantOnly = header('assistant-route', 20, '/workspace')
|
||||
const empty = header('empty-log', 10, '/workspace')
|
||||
const events = resumeEvents('Assistant route', 'deepseek')
|
||||
const events = resumeEvents('Assistant route', 'deepseek-official')
|
||||
.filter(event => event.type !== 'request/header')
|
||||
.map((event, seq) => ({ ...event, seq })) as SessionEvent[]
|
||||
const result = await setup({
|
||||
@@ -726,7 +726,7 @@ describe('goodbye message and /resume', () => {
|
||||
result.terminal.send('/resume')
|
||||
result.terminal.send('\r')
|
||||
await tick(); await tick()
|
||||
expect(result.terminal.output).toContain('deepseek/model-1')
|
||||
expect(result.terminal.output).toContain('deepseek-official/model-1')
|
||||
expect(result.terminal.output).toContain(new Date(empty.createdAt).toISOString())
|
||||
await dispose(result)
|
||||
})
|
||||
@@ -2397,7 +2397,7 @@ describe('pi-tui chat lifecycle and transcript', () => {
|
||||
contextWindow: 128_000,
|
||||
contextTokens: 42_000,
|
||||
config: { showReasoning: false },
|
||||
agentOptions: { provider: 'deepseek', model: 'deepseek-v4-pro' },
|
||||
agentOptions: { provider: 'deepseek-official', model: 'deepseek-v4-pro' },
|
||||
tools: {
|
||||
read: {
|
||||
name: 'read', description: 'Read a file', parameters: {},
|
||||
@@ -2445,7 +2445,7 @@ describe('pi-tui chat lifecycle and transcript', () => {
|
||||
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 (effort default; reasoning blocks')
|
||||
expect(result.terminal.output).toContain('deepseek-official/deepseek-v4-pro (effort default; reasoning blocks')
|
||||
expect(result.terminal.output).toContain('hidden)')
|
||||
// 6 domain events + the /status invocation's own command/run (open turn: joined directly).
|
||||
expect(result.terminal.output).toContain('running · 7 events · 1 turn · 1 step · 2 tool calls')
|
||||
@@ -3601,7 +3601,7 @@ describe('pi-tui chat lifecycle and transcript', () => {
|
||||
|
||||
const failed = await setup({
|
||||
catalog: {
|
||||
providers: [{ id: 'deepseek', name: 'DeepSeek' }],
|
||||
providers: [{ id: 'deepseek-official', name: 'DeepSeek' }],
|
||||
models: [],
|
||||
listModels: () => Promise.reject(new Error('catalog offline')),
|
||||
resolveModelInfo: () => Promise.reject(new Error('capacity offline')),
|
||||
@@ -3617,8 +3617,8 @@ describe('pi-tui chat lifecycle and transcript', () => {
|
||||
|
||||
const reasoningFailed = await setup({
|
||||
catalog: {
|
||||
providers: [{ id: 'deepseek', name: 'DeepSeek' }],
|
||||
models: [{ provider: 'deepseek', id: 'model-1', name: 'Model One' }],
|
||||
providers: [{ id: 'deepseek-official', name: 'DeepSeek' }],
|
||||
models: [{ provider: 'deepseek-official', id: 'model-1', name: 'Model One' }],
|
||||
resolveModelInfo: () => Promise.reject(new Error('reasoning metadata offline')),
|
||||
},
|
||||
})
|
||||
@@ -3634,7 +3634,7 @@ describe('pi-tui chat lifecycle and transcript', () => {
|
||||
const deferred = Promise.withResolvers<never[]>()
|
||||
const result = await setup({
|
||||
catalog: {
|
||||
providers: [{ id: 'deepseek', name: 'DeepSeek' }],
|
||||
providers: [{ id: 'deepseek-official', name: 'DeepSeek' }],
|
||||
models: [],
|
||||
listModels: () => deferred.promise,
|
||||
},
|
||||
@@ -3650,7 +3650,7 @@ describe('pi-tui chat lifecycle and transcript', () => {
|
||||
const rejected = Promise.withResolvers<never[]>()
|
||||
const rejectedResult = await setup({
|
||||
catalog: {
|
||||
providers: [{ id: 'deepseek', name: 'DeepSeek' }],
|
||||
providers: [{ id: 'deepseek-official', name: 'DeepSeek' }],
|
||||
models: [],
|
||||
listModels: () => rejected.promise,
|
||||
},
|
||||
@@ -3667,7 +3667,7 @@ describe('pi-tui chat lifecycle and transcript', () => {
|
||||
const contextResult = await setup({
|
||||
contextTokens: 99,
|
||||
catalog: {
|
||||
providers: [{ id: 'deepseek', name: 'DeepSeek' }],
|
||||
providers: [{ id: 'deepseek-official', name: 'DeepSeek' }],
|
||||
models: [],
|
||||
resolveModelInfo: () => context.promise.then(value => ({ context: value })),
|
||||
},
|
||||
@@ -4395,6 +4395,14 @@ describe('tool cards and surface replay', () => {
|
||||
name: 'knownXml', description: '', parameters: {}, output: UNUSED_TOOL_OUTPUT, execute: async () => [],
|
||||
presentCall: () => ({ card: 'generic', title: 'Known XML' }),
|
||||
},
|
||||
// A web card carries no `content` copy, so it falls back to the raw result
|
||||
// content, which must still render through the dim Markdown path (bold
|
||||
// markers stripped) rather than as bare text.
|
||||
webCard: {
|
||||
name: 'webCard', description: '', parameters: {}, output: UNUSED_TOOL_OUTPUT, execute: async () => [],
|
||||
presentCall: () => ({ card: 'generic', title: 'Fetch page', kind: 'fetch' }),
|
||||
presentResult: () => ({ card: 'web', kind: 'fetch', title: 'https://a.test', url: 'https://a.test', statusCode: 200, truncated: false }),
|
||||
},
|
||||
}
|
||||
|
||||
it('uses terminal, diff, generic, fallback, and collapsed tool presentations', async () => {
|
||||
@@ -4415,6 +4423,7 @@ describe('tool cards and surface replay', () => {
|
||||
['c11', 'terminalResult', '{}'],
|
||||
['c12', 'symbolic', '{}'],
|
||||
['c13', 'knownXml', '{}'],
|
||||
['c16', 'webCard', '{}'],
|
||||
] as const
|
||||
appendAssistant(result.session, [
|
||||
{ type: 'text', text: 'Calling tools' },
|
||||
@@ -4508,6 +4517,14 @@ describe('tool cards and surface replay', () => {
|
||||
isError: false,
|
||||
}),
|
||||
}, { surfaceOp: 'append' })
|
||||
result.session.append('tool/result', {
|
||||
turn: 1, step: 1,
|
||||
message: createToolResultMessage({
|
||||
callId: 'c16' as never,
|
||||
content: [{ type: 'text', text: 'Fetched **body** text' }],
|
||||
isError: false,
|
||||
}),
|
||||
}, { surfaceOp: 'append' })
|
||||
result.session.append('tool/result', {
|
||||
turn: 1,
|
||||
step: 1,
|
||||
@@ -4557,6 +4574,11 @@ describe('tool cards and surface replay', () => {
|
||||
expect(output).toContain('Empty card')
|
||||
expect(output).toContain('converted terminal')
|
||||
expect(output).toContain('<known><value>literal</value></known>')
|
||||
// A web card carries no `content` copy, so it falls back to the raw result
|
||||
// content, which still renders through the dim Markdown path: the bold
|
||||
// markers are stripped rather than shown literally.
|
||||
expect(output).toContain('Fetched body text')
|
||||
expect(output).not.toContain('Fetched **body** text')
|
||||
expect(output).toContain('path: /tmp/a.txt')
|
||||
expect(output).toContain('line (number="1"): hello')
|
||||
expect(output).not.toContain('<result>')
|
||||
|
||||
Reference in New Issue
Block a user