refactor(llm-deepseek)!: rename the provider route to deepseek-official

The native adapter's route was named deepseek, colliding with pi-ai's
catalog provider of the same name, so the two DeepSeek paths could never
be mounted side by side. The web settings page needs both configurable at
once. Compositions, fixtures, goldens, scaffolding defaults, and docs all
move together (pre-release, no shim); TUI/session-query-spill/
missing-credential goldens re-recorded through their keyless refresh
modes because provider-name length shifts box padding and spill
truncation points.
This commit is contained in:
Yichen Jiang
2026-07-29 16:36:07 +08:00
parent 7f1496c996
commit fee12f1af0
239 changed files with 823 additions and 820 deletions

View File

@@ -6,7 +6,7 @@ The `jsonrpc` plugin serves newline-delimited JSON-RPC over stdio so out-of-proc
## Wiring
`inject: ['agents']`. The server gets or creates one agent per `sessionId`. It forwards subagent completions only when the service-snapshotted lifecycle `local` flag is true; provider names, child ids, and durable lineage never establish locality. A registered adapter wins, an unowned `deepseek` route mounts `dsh-llm-deepseek`, and any other unowned provider fails initialization. Other capabilities come from the surrounding `cordis.yml`.
`inject: ['agents']`. The server gets or creates one agent per `sessionId`. It forwards subagent completions only when the service-snapshotted lifecycle `local` flag is true; provider names, child ids, and durable lineage never establish locality. A registered adapter wins, an unowned `deepseek-official` route mounts `dsh-llm-deepseek`, and any other unowned provider fails initialization. Other capabilities come from the surrounding `cordis.yml`.
## Config

View File

@@ -6,7 +6,7 @@
## 组装
`inject: ['agents']`。服务器按 `sessionId` 获取或创建一个 agent。只有服务建立快照时的生命周期 `local` 标志为 true服务器才会转发 subagent 完成事件;提供方名称、子级 id 和持久化谱系均不能证明本地性。已注册的适配器优先;未被持有的 `deepseek` 路由会挂载 `dsh-llm-deepseek`,任何其他未被持有的提供方都会导致初始化失败。其他功能由外围 `cordis.yml` 提供。
`inject: ['agents']`。服务器按 `sessionId` 获取或创建一个 agent。只有服务建立快照时的生命周期 `local` 标志为 true服务器才会转发 subagent 完成事件;提供方名称、子级 id 和持久化谱系均不能证明本地性。已注册的适配器优先;未被持有的 `deepseek-official` 路由会挂载 `dsh-llm-deepseek`,任何其他未被持有的提供方都会导致初始化失败。其他功能由外围 `cordis.yml` 提供。
## 配置

View File

@@ -55,8 +55,8 @@ function successStatus(reason: string, options: HarnessSdkServerOptions): 'ok' |
*/
export class HarnessSdkServer {
private cwd = process.cwd()
private provider = 'deepseek'
private model = 'deepseek'
private provider = 'deepseek-official'
private model = 'deepseek-official'
private maxTokens: number | undefined
private llmFiber: { dispose(): Promise<void> } | undefined
private readonly sessions = new Map<string, SessionRecord>()
@@ -124,7 +124,7 @@ export class HarnessSdkServer {
this.model = params.model
this.maxTokens = params.maxTokens
if (!this.hasAdapterFor(this.provider)) {
if (this.provider !== 'deepseek') throw new Error(`no adapter registered for provider "${this.provider}"`)
if (this.provider !== 'deepseek-official') throw new Error(`no adapter registered for provider "${this.provider}"`)
this.llmFiber = await this.ctx.plugin(LlmDeepSeek, {})
}
return { serverInfo: { name: 'deepseek-harness-sdk-runtime', version: '0.0.1' } }

View File

@@ -153,7 +153,7 @@ describe('dsh-jsonrpc plugin apply', () => {
vi.stubEnv('DEEPSEEK_API_KEY', 'test-key')
const harness = await mountPlugin(storageDir)
try {
harness.send({ jsonrpc: '2.0', id: 'init-1', method: 'initialize', params: { cwd: storageDir, provider: 'deepseek', model: 'apply-model' } })
harness.send({ jsonrpc: '2.0', id: 'init-1', method: 'initialize', params: { cwd: storageDir, provider: 'deepseek-official', model: 'apply-model' } })
const response = await harness.waitForFrame(frame => frame.id === 'init-1', 'initialize response')
expect(response).toEqual({
@@ -175,7 +175,7 @@ describe('dsh-jsonrpc plugin apply', () => {
vi.stubEnv('DEEPSEEK_BASE_URL', llmServer.url)
const harness = await mountPlugin(storageDir)
try {
harness.send({ jsonrpc: '2.0', id: 1, method: 'initialize', params: { cwd: storageDir, provider: 'deepseek', model: 'dsagent-model' } })
harness.send({ jsonrpc: '2.0', id: 1, method: 'initialize', params: { cwd: storageDir, provider: 'deepseek-official', model: 'dsagent-model' } })
await harness.waitForFrame(frame => frame.id === 1, 'initialize response')
harness.send({
@@ -236,7 +236,7 @@ describe('dsh-jsonrpc plugin apply', () => {
expect(harness.exits()).toEqual([0])
const before = harness.frames().length
harness.send({ jsonrpc: '2.0', id: 'after-exit', method: 'initialize', params: { cwd: storageDir, provider: 'deepseek', model: 'x' } })
harness.send({ jsonrpc: '2.0', id: 'after-exit', method: 'initialize', params: { cwd: storageDir, provider: 'deepseek-official', model: 'x' } })
await settle()
expect(harness.frames().length).toBe(before)
} finally {
@@ -257,7 +257,7 @@ describe('dsh-jsonrpc plugin apply', () => {
expect(harness.outputErrors.map(error => error.message)).toEqual(['flush callback failed'])
const before = harness.frames().length
harness.send({ jsonrpc: '2.0', id: 'after-flush-failure', method: 'initialize', params: { cwd: storageDir, provider: 'deepseek', model: 'x' } })
harness.send({ jsonrpc: '2.0', id: 'after-flush-failure', method: 'initialize', params: { cwd: storageDir, provider: 'deepseek-official', model: 'x' } })
await settle()
expect(harness.frames().length).toBe(before)
} finally {
@@ -281,7 +281,7 @@ describe('dsh-jsonrpc plugin apply', () => {
await harness.fiber.dispose()
const before = harness.frames().length
harness.send({ jsonrpc: '2.0', id: 'probe-2', method: 'initialize', params: { cwd: storageDir, provider: 'deepseek', model: 'x' } })
harness.send({ jsonrpc: '2.0', id: 'probe-2', method: 'initialize', params: { cwd: storageDir, provider: 'deepseek-official', model: 'x' } })
await settle()
expect(harness.frames().length).toBe(before)
expect(harness.exits()).toEqual([])

View File

@@ -121,7 +121,7 @@ describe('HarnessSdkServer', () => {
const init = await server.handleRequest('initialize', {
cwd: storageDir,
provider: 'deepseek',
provider: 'deepseek-official',
model: 'dsagent-model',
maxTokens: 321,
}) as { serverInfo: { name: string } }
@@ -154,7 +154,7 @@ describe('HarnessSdkServer', () => {
const orphanHandle = await ctx.agents.create({
sessionId: SessionId('orphan-session'),
meta: { cwd: storageDir },
agentOptions: { provider: 'deepseek', model: 'dsagent-model' },
agentOptions: { provider: 'deepseek-official', model: 'dsagent-model' },
})
orphanHandle.agent.followup(createUserMessage({ content: [{ type: 'text', text: 'outside the sdk session map' }], source: { kind: 'user' } }))
await orphanHandle.agent.whenIdle()
@@ -352,7 +352,7 @@ describe('HarnessSdkServer', () => {
try {
const server = new HarnessSdkServer(ctx, new FakeTransport())
await server.initialize({ cwd: storageDir, provider: 'deepseek', model: 'plain-model' })
await server.initialize({ cwd: storageDir, provider: 'deepseek-official', model: 'plain-model' })
await server.prompt({
sessionId: 'plain',
contentBlocks: [{ type: 'text', text: 'hello' }],
@@ -376,20 +376,20 @@ describe('HarnessSdkServer', () => {
const parentHandle = await ctx.agents.create({
sessionId: SessionId('main'),
meta: { cwd: storageDir },
agentOptions: { provider: 'deepseek', model: 'deepseek' },
agentOptions: { provider: 'deepseek-official', model: 'deepseek-official' },
})
// A custom in-process provider may own its child at the provider/root
// scope while preserving durable parent lineage.
const handle = await ctx.agents.create({
sessionId: SessionId('child-session'),
meta: { cwd: storageDir, parentSession: SessionId('main') },
agentOptions: { provider: 'deepseek', model: 'deepseek' },
agentOptions: { provider: 'deepseek-official', model: 'deepseek-official' },
})
expect(ctx.agents.roots()).toContain(handle.agent)
const parentlessHandle = await parentHandle.agent.ctx.agents.create({
sessionId: SessionId('parentless-child-session'),
meta: { cwd: storageDir },
agentOptions: { model: 'deepseek' },
agentOptions: { model: 'deepseek-official' },
})
await settleSubagent(ctx, parentHandle.agent, {
provider: 'spawn',
@@ -446,12 +446,12 @@ describe('HarnessSdkServer', () => {
const parentHandle = await ctx.agents.create({
sessionId: SessionId('collision-parent'),
meta: { cwd: storageDir },
agentOptions: { model: 'deepseek' },
agentOptions: { model: 'deepseek-official' },
})
const collidingChild = await parentHandle.agent.ctx.agents.create({
sessionId: SessionId('remote-run-id'),
meta: { cwd: storageDir, parentSession: SessionId('collision-parent') },
agentOptions: { model: 'deepseek' },
agentOptions: { model: 'deepseek-official' },
})
await settleSubagent(ctx, parentHandle.agent, {
@@ -485,12 +485,12 @@ describe('HarnessSdkServer', () => {
const parentHandle = await ctx.agents.create({
sessionId: SessionId('continuation-parent'),
meta: { cwd: storageDir },
agentOptions: { model: 'deepseek' },
agentOptions: { model: 'deepseek-official' },
})
const childHandle = await parentHandle.agent.ctx.agents.create({
sessionId: SessionId('continuation-child'),
meta: { cwd: storageDir, parentSession: SessionId('continuation-parent') },
agentOptions: { model: 'deepseek' },
agentOptions: { model: 'deepseek-official' },
})
await settleSubagent(ctx, parentHandle.agent, {
@@ -530,12 +530,12 @@ describe('HarnessSdkServer', () => {
const oldParent = await ctx.agents.create({
sessionId: SessionId('old-parent'),
meta: { cwd: storageDir },
agentOptions: { model: 'deepseek' },
agentOptions: { model: 'deepseek-official' },
})
const oldChild = await oldParent.agent.ctx.agents.create({
sessionId: SessionId('reused-child'),
meta: { cwd: storageDir, parentSession: SessionId('old-parent') },
agentOptions: { model: 'deepseek' },
agentOptions: { model: 'deepseek-official' },
})
const first = Promise.withResolvers<SubagentResult>()
const sameLifetime = Promise.withResolvers<SubagentResult>()
@@ -571,12 +571,12 @@ describe('HarnessSdkServer', () => {
const newParent = await ctx.agents.create({
sessionId: SessionId('new-parent'),
meta: { cwd: storageDir },
agentOptions: { model: 'deepseek' },
agentOptions: { model: 'deepseek-official' },
})
const newChild = await newParent.agent.ctx.agents.create({
sessionId: SessionId('reused-child'),
meta: { cwd: storageDir, parentSession: SessionId('new-parent') },
agentOptions: { model: 'deepseek' },
agentOptions: { model: 'deepseek-official' },
})
currentLocalAgent = newChild.agent
const secondRun = await ctx.subagents.start('reused', {
@@ -629,12 +629,12 @@ describe('HarnessSdkServer', () => {
const parent = await ctx.agents.create({
sessionId: SessionId('provider-reuse-parent'),
meta: { cwd: storageDir },
agentOptions: { model: 'deepseek' },
agentOptions: { model: 'deepseek-official' },
})
const child = await parent.agent.ctx.agents.create({
sessionId: SessionId('provider-reuse-child'),
meta: { cwd: storageDir, parentSession: SessionId('provider-reuse-parent') },
agentOptions: { model: 'deepseek' },
agentOptions: { model: 'deepseek-official' },
})
const localResult = Promise.withResolvers<SubagentResult>()
const remoteResult = Promise.withResolvers<SubagentResult>()
@@ -722,18 +722,18 @@ describe('HarnessSdkServer', () => {
parentHandle = await ctx.agents.create({
sessionId: SessionId('fallback-parent'),
meta: { cwd: storageDir },
agentOptions: { provider: 'deepseek', model: 'deepseek' },
agentOptions: { provider: 'deepseek-official', model: 'deepseek-official' },
})
handle = await parentHandle.agent.ctx.agents.create({
sessionId: SessionId('fallback-child-session'),
meta: { cwd: storageDir, parentSession: SessionId('fallback-parent') },
agentOptions: { provider: 'deepseek', model: 'deepseek' },
agentOptions: { provider: 'deepseek-official', model: 'deepseek-official' },
})
const fallbackChild = handle.agent
failedHandle = await parentHandle.agent.ctx.agents.create({
sessionId: SessionId('failed-child-session'),
meta: { cwd: storageDir },
agentOptions: { provider: 'deepseek', model: 'deepseek' },
agentOptions: { provider: 'deepseek-official', model: 'deepseek-official' },
})
const missedStartResult = Promise.withResolvers<SubagentResult>()
const disposeMissedStartProvider = ctx.subagents.registerProvider({
@@ -831,11 +831,11 @@ describe('HarnessSdkServer', () => {
const server = new HarnessSdkServer(ctx, new FakeTransport())
const inspect = server as unknown as { hasAdapterFor(provider: string): boolean }
expect(inspect.hasAdapterFor('deepseek')).toBe(true)
expect(inspect.hasAdapterFor('deepseek-official')).toBe(true)
expect(inspect.hasAdapterFor('missing-provider')).toBe(false)
await server.initialize({ cwd: storageDir, provider: 'deepseek', model: 'preinstalled-model' })
await server.initialize({ cwd: storageDir, provider: 'deepseek-official', model: 'preinstalled-model' })
expect(ctx.get('llm')?.listProviders().filter(provider => provider.id === 'deepseek')).toEqual([{ id: 'deepseek', name: 'DeepSeek' }])
expect(ctx.get('llm')?.listProviders().filter(provider => provider.id === 'deepseek-official')).toEqual([{ id: 'deepseek-official', name: 'DeepSeek' }])
await server.shutdown()
} finally {
await ctx.fiber.dispose()
@@ -854,7 +854,7 @@ describe('HarnessSdkServer', () => {
await expect(server.initialize({ cwd: storageDir, provider: 'private', model: 'new-model' }))
.rejects.toThrow('no adapter registered for provider "private"')
expect(ctx.get('llm')?.listProviders()).toEqual([{ id: 'deepseek', name: 'DeepSeek' }])
expect(ctx.get('llm')?.listProviders()).toEqual([{ id: 'deepseek-official', name: 'DeepSeek' }])
await server.shutdown()
} finally {
await ctx.fiber.dispose()
@@ -871,7 +871,7 @@ describe('HarnessSdkServer', () => {
const server = new HarnessSdkServer(ctx, new FakeTransport())
await expect(server.initialize({
cwd: storageDir,
provider: 'deepseek',
provider: 'deepseek-official',
model: 'model',
maxTokens,
})).rejects.toThrow('initialize maxTokens must be a positive safe integer')

View File

@@ -103,10 +103,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', {
@@ -192,7 +192,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() {

View File

@@ -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', () => {

View File

@@ -29,13 +29,13 @@ buffer
9-12| <blank>
13| " ╭ Select model ────────────────────────────────────────────────────────────╮ "
style 8-83 fg=bright-blue
14| " │ → deepseek/deepseek-v4-flash DeepSeek V4 Flash — current │ "
14| " │ → deepseek-official/deepseek-v4- DeepSeek V4 Flash — current │ "
style 8-8 fg=bright-blue
style 10-70 fg=bright-blue inverse
style 10-41 fg=bright-blue inverse
style 83-83 fg=bright-blue
15| " │ deepseek/deepseek-v4-pro DeepSeek V4 Pro │ "
15| " │ deepseek-official/deepseek-v4- DeepSeek V4 Pro │ "
style 8-8 fg=bright-blue
style 36-58 fg=bright-black
style 42-58 fg=bright-black
style 83-83 fg=bright-blue
16| " │ │ "
style 8-8 fg=bright-blue

View File

@@ -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 fg=bright-black
7| "Model selected: deepseek-official/deepseek-v4-pro. New steps will use it. "
style 0-72 fg=bright-black
8| <blank>
9| "/workspace/project (tui-staging) deepseek-v4-pro ↑0 ↓0 0% context"
style 0-17 fg=bright-blue bold

View File

@@ -28,8 +28,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 fg=bright-black
14| " 2024-01-01T00:00:08.000Z · turn 1: completed · deepseek-official/deepseek-v4-pro "
style 2-83 fg=bright-black
15| " persisted · earlier-session "
style 2-30 dim
16| " "

View File

@@ -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-blue bold
@@ -37,84 +37,87 @@ buffer
style 0-0 dim
style 3-12 fg=bright-black
style 55-55 dim
15| "│ Model: deepseek/deepseek-v4-pro (effort │"
style 0-0 dim
style 3-12 fg=bright-black
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 · 7 events · 1 turn · 1 step · 1 │"
15| "│ Model: deepseek-official/deepseek-v4-pro │"
style 0-0 dim
style 3-12 fg=bright-black
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 · 7 events · 1 turn · 1 step · 1 │"
style 0-0 dim
style 3-12 fg=bright-black
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 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
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 fg=bright-black
style 15-15 dim
style 16-20 fg=bright-blue
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 fg=bright-black
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 fg=bright-black
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-blue 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-blue 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-blue bold
style 18-31 fg=bright-black
style 34-48 fg=bright-black
style 51-55 fg=bright-black
43| " dsh > "
44| " dsh > "
style 1-3 fg=bright-blue bold
style 5-6 fg=bright-black
style 7-7 inverse

View File

@@ -21,68 +21,68 @@ buffer
style 0-2 fg=bright-blue bold underline
9| "inspect this session "
10| <blank>
11| "╭─ Session status ───────────────────────────────────────────────────────────────╮"
11| "╭─ Session status ────────────────────────────────────────────────────────────────────────╮"
style 0-2 dim
style 3-16 fg=bright-blue bold
style 17-81 dim
12| "│ Session: main-session │"
style 17-90 dim
12| "│ Session: main-session │"
style 0-0 dim
style 3-12 fg=bright-black
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 fg=bright-black
style 81-81 dim
14| "│ Directory: /workspace/project │"
style 90-90 dim
14| "│ Directory: /workspace/project │"
style 0-0 dim
style 3-12 fg=bright-black
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 fg=bright-black
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 · 7 events · 1 turn · 1 step · 1 tool call │"
style 90-90 dim
17| "│ Agent: idle · 7 events · 1 turn · 1 step · 1 tool call │"
style 0-0 dim
style 3-12 fg=bright-black
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 fg=bright-black
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 fg=bright-black
style 15-15 dim
style 16-26 fg=bright-blue
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 fg=bright-black
style 15-15 dim
style 16-20 fg=bright-blue
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 fg=bright-black
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 fg=bright-black
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-blue bold

View File

@@ -489,7 +489,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'] },
@@ -824,7 +824,7 @@ describe('TUI terminal-state snapshots', () => {
content: [{ type: 'text', text: 'restore the selector' }], source: { kind: 'user' },
}), surfaceOp: 'append' },
{ type: 'step/start', seq: 2, time: Date.parse('2024-01-01T00:00:03Z'), data: { turn: 1, step: 1 } },
{ type: 'request/header', seq: 3, time: Date.parse('2024-01-01T00:00:04Z'), data: { header: { config: { provider: 'deepseek', model: 'deepseek-v4-pro' } }, reason: 'initial' } },
{ type: 'request/header', seq: 3, time: Date.parse('2024-01-01T00:00:04Z'), data: { header: { config: { provider: 'deepseek-official', model: 'deepseek-v4-pro' } }, reason: 'initial' } },
{ type: 'assistant/message', seq: 4, time: Date.parse('2024-01-01T00:00:05Z'), data: {
turn: 1, step: 1,
message: createMessage({
@@ -832,7 +832,7 @@ describe('TUI terminal-state snapshots', () => {
content: [{ type: 'text', text: 'ready' }],
source: {
kind: 'model',
...{ provider: 'deepseek', model: 'deepseek-v4-pro' },
...{ provider: 'deepseek-official', model: 'deepseek-v4-pro' },
},
}),
}, surfaceOp: 'append' },
@@ -859,7 +859,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',

View File

@@ -235,7 +235,7 @@ describe('resume command 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[] => [
@@ -310,8 +310,8 @@ describe('resume command 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')
@@ -405,7 +405,7 @@ describe('resume command 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),
}),
},
})
@@ -461,7 +461,7 @@ describe('resume command 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')
@@ -663,7 +663,7 @@ describe('resume command 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({
@@ -678,7 +678,7 @@ describe('resume command 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)
})
@@ -2167,7 +2167,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: {},
@@ -2215,7 +2215,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')
@@ -3355,7 +3355,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')),
@@ -3371,8 +3371,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')),
},
})
@@ -3388,7 +3388,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,
},
@@ -3404,7 +3404,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,
},
@@ -3421,7 +3421,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 })),
},