Merge remote-tracking branch 'origin/master' into worktree/web-background-tasks-display-258f7e

# Conflicts:
#	docs/subsystems/tasks.i18n.yaml
#	docs/subsystems/tasks.md
#	docs/subsystems/tasks.zh.md
#	packages/host/apiproxy/README.i18n.yaml
#	packages/host/apiproxy/README.md
#	packages/host/apiproxy/README.zh.md
#	packages/host/apiproxy/src/api-proxy.ts
#	packages/tasks/tasks-local/src/index.ts
#	packages/tasks/tasks/README.i18n.yaml
#	packages/tasks/tasks/README.md
#	packages/tasks/tasks/README.zh.md
#	packages/tasks/tasks/src/index.ts
This commit is contained in:
Yichen Jiang
2026-08-11 11:57:33 +08:00
2697 changed files with 39978 additions and 18500 deletions

View File

@@ -68,6 +68,7 @@ const LAYOUT_CHILDREN = {
async function bench(nodes: ToolResultNode[]) {
const runtime = await SlotTestRuntime.create()
runtime.provide('connection', { api: { settings: {} }, isLoopback: false } as never)
runtime.provide('layout', { openDetails: vi.fn(), closeDetails: vi.fn() })
const locale = new LocaleService(runtime.ctx)
runtime.provide('locale', locale)

View File

@@ -8,11 +8,12 @@
// and a file sub-row click opens the host path. Running parents
// (runningCalls) nest their so-far dispatches the same way.
import { Context } from 'cordis'
import { Context } from '@deepseek-ai/cordis'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { cleanup, fireEvent, render } from '@testing-library/react'
import {
ConversationEventRegistry, ConversationViewRegistry, createSnapshotStore, SlotsService,
ConversationEventRegistry, ConversationViewRegistry, createSnapshotStore,
EMPTY_CONVERSATION_VIEWS, SlotsService,
} from '@deepseek-ai/dsh-client-runtime/client'
import type {
ConversationSnapshot, RunningToolCall, SessionId, SessionListState,
@@ -78,7 +79,8 @@ function snapshotWith(
const nestedNodes = nodes.map(node => ({ ...node, subCalls }))
const nestedRunningCalls = runningCalls.map(call => ({ ...call, subCalls }))
return {
sessionId: SID, chat: toolChatSnapshot(nestedNodes, nestedRunningCalls),
sessionId: SID, views: EMPTY_CONVERSATION_VIEWS,
chat: toolChatSnapshot(nestedNodes, nestedRunningCalls),
nodes: nestedNodes, turnTimings: new Map(), turnEnds: new Map(), partial: null,
runningCalls: nestedRunningCalls,
pending: [], queue: [], running: runningCalls.length > 0, composerPhase: 'active', removed: false,
@@ -155,6 +157,7 @@ async function bench(snapshot: ConversationSnapshot) {
}
ctx.provide('workspaces', workspaces)
ctx.provide('layout', layout)
ctx.provide('connection', { api: { settings: {} }, isLoopback: false } as never)
const locale = new LocaleService(ctx)
ctx.provide('locale', locale)
slots.installLocale(locale)

View File

@@ -7,7 +7,9 @@
import { afterEach, describe, expect, it, vi } from 'vitest'
import { cleanup, fireEvent, render } from '@testing-library/react'
import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react'
import { createSnapshotStore } from '@deepseek-ai/dsh-client-runtime/client'
import {
createSnapshotStore, EMPTY_CONVERSATION_VIEWS,
} from '@deepseek-ai/dsh-client-runtime/client'
import type {
ConversationSnapshot, RunningToolCall, SessionId, SessionListState, ToolResultNode, WorkspaceListState,
} from '@deepseek-ai/dsh-client-runtime/client'
@@ -331,7 +333,13 @@ describe('DetailsPanel diff Output section', () => {
useSessions={bindSnapshotSelector(sessions)}
useWorkspaces={bindSnapshotSelector(workspaces)}
useInput={(() => { throw new Error('unused') })}
inputActions={{ setDraft: () => {}, submit: () => {} }}
inputActions={{
setDraft: () => {},
addImages: () => true,
removeImage: () => {},
pruneImages: () => {},
submit: () => {},
}}
useProjection={(() => undefined)}
useStore={bindSnapshotSelector(chat)}
actions={chat.actions}
@@ -345,7 +353,8 @@ describe('DetailsPanel diff Output section', () => {
const nodes = over.nodes ?? []
const runningCalls = over.runningCalls ?? []
return {
sessionId: SID, chat: over.chat ?? toolChatSnapshot(nodes, runningCalls),
sessionId: SID, views: EMPTY_CONVERSATION_VIEWS,
chat: over.chat ?? toolChatSnapshot(nodes, runningCalls),
nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [],
pending: [], queue: [], running: false, composerPhase: 'active', removed: false,
openState: 'open', openError: null, hasMore: false, loadingOlder: false,

View File

@@ -8,9 +8,11 @@
import { afterEach, describe, expect, it, vi } from 'vitest'
import { cleanup, fireEvent, render } from '@testing-library/react'
import { Context } from 'cordis'
import { Context } from '@deepseek-ai/cordis'
import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react'
import { createSnapshotStore } from '@deepseek-ai/dsh-client-runtime/client'
import {
createSnapshotStore, EMPTY_CONVERSATION_VIEWS,
} from '@deepseek-ai/dsh-client-runtime/client'
import { makeTranslate } from '@deepseek-ai/dsh-client-test-runtime'
import { zh as commonZh } from '@deepseek-ai/dsh-client-locale/src/locales/zh.ts'
import type {
@@ -278,7 +280,13 @@ describe('DetailsPanel Output section (read)', () => {
useSessions={bindSnapshotSelector(sessions)}
useWorkspaces={bindSnapshotSelector(workspaces)}
useInput={(() => { throw new Error('unused') })}
inputActions={{ setDraft: () => {}, submit: () => {} }}
inputActions={{
setDraft: () => {},
addImages: () => true,
removeImage: () => {},
pruneImages: () => {},
submit: () => {},
}}
useProjection={(() => undefined)}
useStore={bindSnapshotSelector(chat)}
actions={chat.actions}
@@ -291,7 +299,8 @@ describe('DetailsPanel Output section (read)', () => {
const nodes = over.nodes ?? []
const runningCalls = over.runningCalls ?? []
return {
sessionId: SID, chat: over.chat ?? toolChatSnapshot(nodes, runningCalls),
sessionId: SID, views: EMPTY_CONVERSATION_VIEWS,
chat: over.chat ?? toolChatSnapshot(nodes, runningCalls),
nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [],
pending: [], queue: [], running: false, composerPhase: 'active', removed: false,
openState: 'open', openError: null, hasMore: false, loadingOlder: false,

View File

@@ -9,7 +9,9 @@
import { afterEach, describe, expect, it, vi } from 'vitest'
import { cleanup, fireEvent, render } from '@testing-library/react'
import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react'
import { createSnapshotStore } from '@deepseek-ai/dsh-client-runtime/client'
import {
createSnapshotStore, EMPTY_CONVERSATION_VIEWS,
} from '@deepseek-ai/dsh-client-runtime/client'
import type {
ConversationSnapshot, RunningToolCall, SessionId, SessionListState, ToolResultNode, WorkspaceListState,
} from '@deepseek-ai/dsh-client-runtime/client'
@@ -393,7 +395,13 @@ describe('DetailsPanel Output section (search)', () => {
useSessions={bindSnapshotSelector(sessions)}
useWorkspaces={bindSnapshotSelector(workspaces)}
useInput={(() => { throw new Error('unused') })}
inputActions={{ setDraft: () => {}, submit: () => {} }}
inputActions={{
setDraft: () => {},
addImages: () => true,
removeImage: () => {},
pruneImages: () => {},
submit: () => {},
}}
useProjection={(() => undefined)}
useStore={bindSnapshotSelector(chat)}
actions={chat.actions}
@@ -407,7 +415,8 @@ describe('DetailsPanel Output section (search)', () => {
const nodes = over.nodes ?? []
const runningCalls = over.runningCalls ?? []
return {
sessionId: SID, chat: over.chat ?? toolChatSnapshot(nodes, runningCalls),
sessionId: SID, views: EMPTY_CONVERSATION_VIEWS,
chat: over.chat ?? toolChatSnapshot(nodes, runningCalls),
nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [],
pending: [], queue: [], running: false, composerPhase: 'active', removed: false,
openState: 'open', openError: null, hasMore: false, loadingOlder: false,

View File

@@ -7,7 +7,9 @@
import { afterEach, describe, expect, it, vi } from 'vitest'
import { cleanup, fireEvent, render } from '@testing-library/react'
import { bindSnapshotSelector } from '@deepseek-ai/dsh-client-web-react'
import { createSnapshotStore } from '@deepseek-ai/dsh-client-runtime/client'
import {
createSnapshotStore, EMPTY_CONVERSATION_VIEWS,
} from '@deepseek-ai/dsh-client-runtime/client'
import type {
ConversationSnapshot, RunningToolCall, SessionId, SessionListState, ToolResultNode, WorkspaceListState,
} from '@deepseek-ai/dsh-client-runtime/client'
@@ -468,7 +470,7 @@ describe('DetailsPanel Output section', () => {
useSessions={bindSnapshotSelector(sessions)}
useWorkspaces={bindSnapshotSelector(workspaces)}
useInput={(() => { throw new Error('unused') })}
inputActions={{ setDraft: () => {}, submit: () => {} }}
inputActions={{ setDraft: () => {}, addImages: () => true, removeImage: () => {}, pruneImages: () => {}, submit: () => {} }}
useProjection={(() => undefined)}
useStore={bindSnapshotSelector(chat)}
actions={chat.actions}
@@ -482,7 +484,8 @@ describe('DetailsPanel Output section', () => {
const nodes = over.nodes ?? []
const runningCalls = over.runningCalls ?? []
return {
sessionId: SID, chat: over.chat ?? toolChatSnapshot(nodes, runningCalls),
sessionId: SID, views: EMPTY_CONVERSATION_VIEWS,
chat: over.chat ?? toolChatSnapshot(nodes, runningCalls),
nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [],
pending: [], queue: [], running: false, composerPhase: 'active', removed: false,
openState: 'open', openError: null, hasMore: false, loadingOlder: false,
@@ -653,7 +656,7 @@ describe('DetailsPanel Output section', () => {
baselinesReady: true, recentWorkspaceId: undefined,
}))}
useInput={(() => { throw new Error('unused') })}
inputActions={{ setDraft: () => {}, submit: () => {} }}
inputActions={{ setDraft: () => {}, addImages: () => true, removeImage: () => {}, pruneImages: () => {}, submit: () => {} }}
useProjection={(() => undefined)}
useStore={bindSnapshotSelector(chat)}
actions={chat.actions}

View File

@@ -64,6 +64,7 @@ const LAYOUT_CHILDREN = {
*/
async function bench(nodes: ToolResultNode[]) {
const runtime = await SlotTestRuntime.create()
runtime.provide('connection', { api: { settings: {} }, isLoopback: false } as never)
const layout = { openDetails: vi.fn(), closeDetails: vi.fn() }
runtime.provide('layout', layout)
const locale = new LocaleService(runtime.ctx)
@@ -196,6 +197,7 @@ describe('keyed toolview hole through the real machinery', () => {
describe('registrant declaration injection', () => {
it('runs a registrant before ui-tool and waits on the actual toolview declaration', async () => {
const runtime = await SlotTestRuntime.create()
runtime.provide('connection', { api: { settings: {} }, isLoopback: false } as never)
runtime.provide('layout', { openDetails: vi.fn(), closeDetails: vi.fn() })
const locale = new LocaleService(runtime.ctx)
runtime.provide('locale', locale)

View File

@@ -10,7 +10,9 @@
import { afterEach, describe, expect, it, vi } from 'vitest'
import { cleanup, fireEvent, render } from '@testing-library/react'
import { createSnapshotStore } from '@deepseek-ai/dsh-client-runtime/client'
import {
createSnapshotStore, EMPTY_CONVERSATION_VIEWS,
} from '@deepseek-ai/dsh-client-runtime/client'
import type {
ConversationSnapshot, RunningToolCall, SessionId, SessionListState, ToolResultNode, WorkspaceListState,
} from '@deepseek-ai/dsh-client-runtime/client'
@@ -223,7 +225,13 @@ describe('DetailsPanel web Output section', () => {
useSessions={bindSnapshotSelector(sessions)}
useWorkspaces={bindSnapshotSelector(workspaces)}
useInput={(() => { throw new Error('unused') })}
inputActions={{ setDraft: () => {}, submit: () => {} }}
inputActions={{
setDraft: () => {},
addImages: () => true,
removeImage: () => {},
pruneImages: () => {},
submit: () => {},
}}
useProjection={(() => undefined)}
useStore={bindSnapshotSelector(chat)}
actions={chat.actions}
@@ -237,7 +245,8 @@ describe('DetailsPanel web Output section', () => {
const nodes = over.nodes ?? []
const runningCalls = over.runningCalls ?? []
return {
sessionId: SID, chat: over.chat ?? toolChatSnapshot(nodes, runningCalls),
sessionId: SID, views: EMPTY_CONVERSATION_VIEWS,
chat: over.chat ?? toolChatSnapshot(nodes, runningCalls),
nodes: [], turnTimings: new Map(), turnEnds: new Map(), partial: null, runningCalls: [],
pending: [], queue: [], running: false, composerPhase: 'active', removed: false,
openState: 'open', openError: null, hasMore: false, loadingOlder: false,
@@ -288,7 +297,7 @@ describe('web toolview registration', () => {
return () => {}
},
},
} as unknown as import('cordis').Context
} as unknown as import('@deepseek-ai/cordis').Context
webToolview.apply(ctx)
expect(registered.map(r => r.key)).toEqual(['web_search', 'web_fetch'])
// Both keys claim the conversation locale seat ToolRow's body copy needs.