refactor: apply repository naming contract

Apply the accepted pre-release package, service, type, directory, and role renames as one repository-wide change.
This commit is contained in:
Tianyi Cui
2026-08-13 00:36:22 +08:00
parent 101df7cf58
commit a2d0f7f411
3281 changed files with 21730 additions and 21592 deletions

View File

@@ -1,7 +1,7 @@
import { Context } from '@deepseek-ai/cordis'
import { describe, expect, it, vi } from 'vitest'
import { SlotsService } from '@deepseek-ai/dsh-client-runtime/client'
import { LocaleService } from '@deepseek-ai/dsh-client-locale/client'
import { SlotRegistry } from '@deepseek-ai/dsh-client-runtime/client'
import { LocaleRuntime } from '@deepseek-ai/dsh-client-locale/client'
import { usePinnedBrowserLanguages } from '@deepseek-ai/dsh-client-test-runtime'
import { apply, inject } from '@deepseek-ai/dsh-client-ui-workspace/client'
import type { WorkspaceBrowserInjected, WorkspacePickerInjected } from '@deepseek-ai/dsh-client-ui-workspace/client'
@@ -14,7 +14,7 @@ usePinnedBrowserLanguages('zh-CN')
async function bench() {
const ctx = new Context()
await ctx.plugin(SlotsService).await()
await ctx.plugin(SlotRegistry).await()
const create = vi.fn(async (input: { name: string } | { path: string }) => ({
workspaceId: 'ws-new' as never,
path: 'name' in input ? `/projects/${input.name}` : input.path,
@@ -36,10 +36,10 @@ async function bench() {
create, startSession, rename, insertSessionBefore,
} as never)
ctx.provide('sessions', { open, clear, search, searchResultLimit: 20, binding, fork } as never)
const locale = new LocaleService(ctx)
const locale = new LocaleRuntime(ctx)
ctx.provide('locale', locale)
return {
ctx, slots: ctx.get('slots') as SlotsService, locale, create, startSession, rename,
ctx, slots: ctx.get('slots') as SlotRegistry, locale, create, startSession, rename,
insertSessionBefore, open, clear, search, renameSession, binding, fork,
}
}
@@ -47,7 +47,7 @@ async function bench() {
type HoleName = 'sidebar.workspaces' | 'conversation.hero.workspace' | 'conversation.empty.workspace'
/** Declare any subset of the holes with a single root registration ('root' is a single slot). */
function declare(slots: SlotsService, ...names: HoleName[]): () => void {
function declare(slots: SlotRegistry, ...names: HoleName[]): () => void {
const children = Object.fromEntries(names.map(name => [name, { kind: 'single', scope: 'root' }]))
return slots.register({ name: 'root', children } as never, () => null)
}

View File

@@ -1,12 +1,12 @@
import { describe, expect, it } from 'vitest'
import { Context } from '@deepseek-ai/cordis'
import * as WorkspaceInvariant from '@deepseek-ai/dsh-client-ui-workspace/invariant'
import InvariantService from '@deepseek-ai/dsh-invariants'
import InvariantRegistry from '@deepseek-ai/dsh-invariants'
describe('invariant companion', () => {
it('registers under the package name with an empty installer', async () => {
const ctx = new Context()
await ctx.plugin(InvariantService, { enabled: true })
await ctx.plugin(InvariantRegistry, { enabled: true })
await expect(ctx.plugin(WorkspaceInvariant).await()).resolves.toBeDefined()
})

View File

@@ -16,7 +16,7 @@ import { cleanup, fireEvent, waitFor, within } from '@testing-library/react'
import type { ISession, SessionId, WorkspaceId } from '@deepseek-ai/dsh-client-runtime/client'
import type { PropsRenderSlots } from '@deepseek-ai/dsh-client-ui-slots'
import { SlotTestRuntime, usePinnedBrowserLanguages } from '@deepseek-ai/dsh-client-test-runtime'
import { LocaleService } from '@deepseek-ai/dsh-client-locale/client'
import { LocaleRuntime } from '@deepseek-ai/dsh-client-locale/client'
import { apply, inject } from '@deepseek-ai/dsh-client-ui-workspace/client'
// The service reads its initial locale from the browser; these specs assert
@@ -31,7 +31,7 @@ beforeEach(() => { localStorage.clear() })
/** Runtime with the locale face installed (the browser entry declares `locale:` — zh default backs the t seat). */
async function createRuntime(): Promise<SlotTestRuntime> {
const runtime = await SlotTestRuntime.create()
const locale = new LocaleService(runtime.ctx)
const locale = new LocaleRuntime(runtime.ctx)
runtime.provide('locale', locale)
runtime.slots.installLocale(locale)
return runtime

View File

@@ -3,7 +3,7 @@ import type {
SessionId, SessionListState, SessionSummary, WorkspaceId, WorkspaceView,
} from '@deepseek-ai/dsh-client-runtime/client'
import {
deriveFlat, deriveGroups, deriveSearchResults, projectLabel, relativeTime,
deriveFlat, deriveGroups, deriveSearchResults, workspaceLabel, relativeTime,
UNGROUPED_KEY, UNGROUPED_LABEL,
} from '../src/client/tree.ts'
import { createWorkspaceViewStore } from '../src/client/stores.ts'
@@ -18,14 +18,14 @@ const list = (...items: SessionSummary[]): SessionListState => ({
ids: items.map(item => item.id),
byId: Object.fromEntries(items.map(item => [item.id, item])),
current: undefined,
phase: 'ready', subagentsByParent: {}, tasksBySession: {}, currentAddress: undefined,
phase: 'ready', subagentsByParent: {}, jobsBySession: {}, currentAddress: undefined,
})
const workspace = (id: string, sessionIds: string[], title = id): WorkspaceView => ({
workspaceId: wid(id), path: `/projects/${id}`, title,
sessionIds: sessionIds.map(sid), createdAt: '2026-01-01T00:00:00.000Z', updatedAt: '2026-01-01T00:00:00.000Z',
})
const view = (expandedProjects: readonly string[] = [], ungroupedOrder?: readonly string[]) => ({
expandedProjects,
const view = (expandedGroups: readonly string[] = [], ungroupedOrder?: readonly string[]) => ({
expandedGroups,
...(ungroupedOrder === undefined ? {} : { ungroupedOrder }),
})
const noArchive: readonly SessionId[] = []
@@ -155,7 +155,7 @@ describe('deriveGroups', () => {
list(parent, oldChild, newChild, tieB, tieA, self, orphan, cycleA, cycleB),
[],
noArchive,
{ expandedProjects: [UNGROUPED_KEY] },
{ expandedGroups: [UNGROUPED_KEY] },
)
expect(groups).toHaveLength(1)
@@ -398,42 +398,42 @@ describe('createWorkspaceViewStore', () => {
expect(store.getSnapshot().orderBy).toBe('manual')
store.actions.setGroupBy('flat')
store.actions.setOrderBy('updated')
store.actions.setWorkspaceExpanded('alpha', true)
store.actions.syncRecentSessions('alpha', ['two', 'one'], { one: 1, two: 2 })
store.actions.setRecentSessionOrder('alpha', ['one', 'two'])
store.actions.setGroupExpanded('alpha', true)
store.actions.syncSessionOrderAccount('alpha', ['two', 'one'], { one: 1, two: 2 })
store.actions.setSessionOrder('alpha', ['one', 'two'])
expect(store.getSnapshot().groupBy).toBe('flat')
expect(store.getSnapshot()).toMatchObject({
orderBy: 'updated',
workspaceExpansion: { alpha: true },
recentSessionOrder: { alpha: ['one', 'two'] },
recentSessionUpdatedAt: { alpha: { one: 1, two: 2 } },
groupExpansion: { alpha: true },
sessionOrderByAccount: { alpha: ['one', 'two'] },
sessionUpdatedAtByAccount: { alpha: { one: 1, two: 2 } },
})
})
it('removes view state outside the retained Workspace key set', () => {
const store = createWorkspaceViewStore().create()
store.actions.setWorkspaceExpanded('', true)
store.actions.setWorkspaceExpanded('alpha', true)
store.actions.setWorkspaceExpanded('deleted', true)
store.actions.syncRecentSessions('alpha', ['alpha-session'], { 'alpha-session': 2 })
store.actions.syncRecentSessions('deleted', ['deleted-session'], { 'deleted-session': 1 })
store.actions.setGroupExpanded('', true)
store.actions.setGroupExpanded('alpha', true)
store.actions.setGroupExpanded('deleted', true)
store.actions.syncSessionOrderAccount('alpha', ['alpha-session'], { 'alpha-session': 2 })
store.actions.syncSessionOrderAccount('deleted', ['deleted-session'], { 'deleted-session': 1 })
store.actions.retainWorkspaceKeys(['', 'alpha'])
store.actions.retainAccountKeys(['', 'alpha'])
const snapshot = store.getSnapshot()
expect(snapshot.workspaceExpansion).toEqual({ '': true, alpha: true })
expect(snapshot.recentSessionOrder).toEqual({ alpha: ['alpha-session'] })
expect(snapshot.recentSessionUpdatedAt).toEqual({ alpha: { 'alpha-session': 2 } })
expect(snapshot.groupExpansion).toEqual({ '': true, alpha: true })
expect(snapshot.sessionOrderByAccount).toEqual({ alpha: ['alpha-session'] })
expect(snapshot.sessionUpdatedAtByAccount).toEqual({ alpha: { 'alpha-session': 2 } })
})
})
describe('projectLabel', () => {
describe('workspaceLabel', () => {
it('uses the Ungrouped fallback and extracts POSIX and Windows basenames', () => {
expect(projectLabel(undefined)).toBe(UNGROUPED_LABEL)
expect(projectLabel('')).toBe(UNGROUPED_LABEL)
expect(projectLabel('/projects/demo/')).toBe('demo')
expect(projectLabel('C:\\projects\\demo\\')).toBe('demo')
expect(projectLabel('/')).toBe('/')
expect(workspaceLabel(undefined)).toBe(UNGROUPED_LABEL)
expect(workspaceLabel('')).toBe(UNGROUPED_LABEL)
expect(workspaceLabel('/projects/demo/')).toBe('demo')
expect(workspaceLabel('C:\\projects\\demo\\')).toBe('demo')
expect(workspaceLabel('/')).toBe('/')
})
})

View File

@@ -30,7 +30,7 @@ const sessionState = (items: readonly SessionSummary[], overrides: Partial<Sessi
byId: Object.fromEntries(items.map(item => [item.id, item])),
current: undefined,
phase: 'ready',
subagentsByParent: {}, tasksBySession: {},
subagentsByParent: {}, jobsBySession: {},
currentAddress: undefined,
...overrides,
})
@@ -104,16 +104,16 @@ describe('WorkspaceBrowser', () => {
}
const b = mount({ useWorkspaces: hook(pending) })
act(() => {
b.store.actions.setWorkspaceExpanded('deleted', true)
b.store.actions.syncRecentSessions('deleted', ['session'], { session: 1 })
b.store.actions.setGroupExpanded('deleted', true)
b.store.actions.syncSessionOrderAccount('deleted', ['session'], { session: 1 })
})
expect(b.store.getSnapshot().workspaceExpansion).toEqual({ deleted: true })
expect(b.store.getSnapshot().groupExpansion).toEqual({ deleted: true })
rerender(b, { useWorkspaces: hook(workspaceState([])) })
await waitFor(() => {
expect(b.store.getSnapshot().workspaceExpansion).toEqual({})
expect(b.store.getSnapshot().recentSessionOrder).toEqual({ [UNGROUPED_KEY]: [] })
expect(b.store.getSnapshot().recentSessionUpdatedAt).toEqual({ [UNGROUPED_KEY]: {} })
expect(b.store.getSnapshot().groupExpansion).toEqual({})
expect(b.store.getSnapshot().sessionOrderByAccount).toEqual({ [UNGROUPED_KEY]: [] })
expect(b.store.getSnapshot().sessionUpdatedAtByAccount).toEqual({ [UNGROUPED_KEY]: {} })
})
})
@@ -173,7 +173,7 @@ describe('WorkspaceBrowser', () => {
fireEvent.click(screen.getByRole('button', { name: '视图选项' }))
fireEvent.click(screen.getByRole('menuitem', { name: '单列表' }))
await waitFor(() => {
expect(b.store.getSnapshot().recentSessionOrder[FLAT_SESSION_ORDER_KEY])
expect(b.store.getSnapshot().sessionOrderByAccount[FLAT_SESSION_ORDER_KEY])
.toEqual(['one', 'two', 'three'])
})
@@ -185,14 +185,14 @@ describe('WorkspaceBrowser', () => {
})
fireEvent.dragStart(one, { dataTransfer: dragData() })
fireDrag(three, 'drop', 180)
expect(b.store.getSnapshot().recentSessionOrder[FLAT_SESSION_ORDER_KEY])
expect(b.store.getSnapshot().sessionOrderByAccount[FLAT_SESSION_ORDER_KEY])
.toEqual(['two', 'three', 'one'])
expect(insertSessionBefore).not.toHaveBeenCalled()
fireEvent.click(screen.getByRole('button', { name: '视图选项' }))
fireEvent.click(screen.getByRole('menuitem', { name: '最近更新' }))
await waitFor(() => {
expect(b.store.getSnapshot().recentSessionOrder[FLAT_SESSION_ORDER_KEY])
expect(b.store.getSnapshot().sessionOrderByAccount[FLAT_SESSION_ORDER_KEY])
.toEqual(['one', 'two', 'three'])
})
@@ -244,9 +244,9 @@ describe('WorkspaceBrowser', () => {
expect(screen.getByRole('button', { name: '收起' })).toBeTruthy()
fireEvent.click(screen.getByText('alpha'))
expect(b.store.getSnapshot().workspaceExpansion).toEqual({ alpha: false })
expect(b.store.getSnapshot().groupExpansion).toEqual({ alpha: false })
fireEvent.click(screen.getByText('alpha'))
expect(b.store.getSnapshot().workspaceExpansion).toEqual({ alpha: true })
expect(b.store.getSnapshot().groupExpansion).toEqual({ alpha: true })
expect(screen.queryByText('session-6')).toBeNull()
expect(screen.getByRole('button', { name: '展开其余 2 个会话' })).toBeTruthy()
})
@@ -272,7 +272,7 @@ describe('WorkspaceBrowser', () => {
})
fireEvent.dragStart(one, { dataTransfer: dragData() })
fireDrag(two, 'drop', 180)
expect(b.store.getSnapshot().recentSessionOrder.alpha).toEqual(['two', 'one'])
expect(b.store.getSnapshot().sessionOrderByAccount.alpha).toEqual(['two', 'one'])
fireEvent.click(screen.getByRole('button', { name: '视图选项' }))
fireEvent.click(screen.getByRole('menuitem', { name: '手动排序' }))
@@ -283,16 +283,16 @@ describe('WorkspaceBrowser', () => {
const updated = sessionState([summary('one', 4), summary('two', 2)])
rerender(b, { useSessions: hook(updated) })
await waitFor(() => {
expect(b.store.getSnapshot().recentSessionUpdatedAt.alpha).toEqual({ one: 4, two: 2 })
expect(b.store.getSnapshot().sessionUpdatedAtByAccount.alpha).toEqual({ one: 4, two: 2 })
})
expect(b.store.getSnapshot().recentSessionOrder.alpha).toEqual(['two', 'one'])
expect(b.store.getSnapshot().sessionOrderByAccount.alpha).toEqual(['two', 'one'])
expect(screen.getAllByRole('treeitem').slice(1)[0]?.textContent).toContain('two')
// Entering Last updated performs one complete recency sort.
fireEvent.click(screen.getByRole('button', { name: '视图选项' }))
fireEvent.click(screen.getByRole('menuitem', { name: '最近更新' }))
await waitFor(() => {
expect(b.store.getSnapshot().recentSessionOrder.alpha).toEqual(['one', 'two'])
expect(b.store.getSnapshot().sessionOrderByAccount.alpha).toEqual(['one', 'two'])
expect(screen.getAllByRole('treeitem').slice(1)[0]?.textContent).toContain('one')
})
@@ -301,7 +301,7 @@ describe('WorkspaceBrowser', () => {
const promoted = sessionState([summary('one', 4), summary('two', 5)])
rerender(b, { useSessions: hook(promoted) })
await waitFor(() => {
expect(b.store.getSnapshot().recentSessionOrder.alpha).toEqual(['two', 'one'])
expect(b.store.getSnapshot().sessionOrderByAccount.alpha).toEqual(['two', 'one'])
expect(screen.getAllByRole('treeitem').slice(1)[0]?.textContent).toContain('two')
})
@@ -310,7 +310,7 @@ describe('WorkspaceBrowser', () => {
useSessions: hook(promoted),
useWorkspaces: hook(workspaceState([workspace('alpha', ['two', 'one'])])),
})
expect(restored.store.getSnapshot().recentSessionOrder.alpha).toEqual(['two', 'one'])
expect(restored.store.getSnapshot().sessionOrderByAccount.alpha).toEqual(['two', 'one'])
expect(screen.getAllByRole('treeitem').slice(1)[0]?.textContent).toContain('two')
})
@@ -378,11 +378,11 @@ describe('WorkspaceBrowser', () => {
startSession,
})
startSession.mockImplementation(() => {
expect(b.store.getSnapshot().workspaceExpansion).toEqual({ alpha: true })
expect(b.store.getSnapshot().groupExpansion).toEqual({ alpha: true })
})
expect(screen.queryByText('alpha-s')).toBeNull()
fireEvent.click(screen.getByRole('button', { name: '在“alpha”中新建会话' }))
expect(b.store.getSnapshot().workspaceExpansion).toEqual({ alpha: true })
expect(b.store.getSnapshot().groupExpansion).toEqual({ alpha: true })
expect(screen.getByText('alpha-s')).toBeTruthy()
expect(startSession).toHaveBeenCalledWith(wid('alpha'))
})
@@ -858,18 +858,18 @@ describe('WorkspaceBrowser', () => {
}
dragAfter('one', 'three')
expect(b.store.getSnapshot().recentSessionOrder[UNGROUPED_KEY]).toEqual(['two', 'three', 'one'])
expect(b.store.getSnapshot().sessionOrderByAccount[UNGROUPED_KEY]).toEqual(['two', 'three', 'one'])
dragAfter('two', 'one')
expect(b.store.getSnapshot().recentSessionOrder[UNGROUPED_KEY]).toEqual(['three', 'one', 'two'])
expect(b.store.getSnapshot().sessionOrderByAccount[UNGROUPED_KEY]).toEqual(['three', 'one', 'two'])
expect(insertSessionBefore).not.toHaveBeenCalled()
fireEvent.click(screen.getByRole('button', { name: '视图选项' }))
fireEvent.click(screen.getByRole('menuitem', { name: '最近更新' }))
await waitFor(() => {
expect(b.store.getSnapshot().recentSessionOrder[UNGROUPED_KEY]).toEqual(['one', 'two', 'three'])
expect(b.store.getSnapshot().sessionOrderByAccount[UNGROUPED_KEY]).toEqual(['one', 'two', 'three'])
})
dragAfter('one', 'three')
expect(b.store.getSnapshot().recentSessionOrder[UNGROUPED_KEY]).toEqual(['two', 'three', 'one'])
expect(b.store.getSnapshot().sessionOrderByAccount[UNGROUPED_KEY]).toEqual(['two', 'three', 'one'])
expect(insertSessionBefore).not.toHaveBeenCalled()
b.view.unmount()
@@ -878,7 +878,7 @@ describe('WorkspaceBrowser', () => {
useWorkspaces: hook(workspaceState([])),
insertSessionBefore,
})
expect(restored.store.getSnapshot().recentSessionOrder[UNGROUPED_KEY]).toEqual(['two', 'three', 'one'])
expect(restored.store.getSnapshot().sessionOrderByAccount[UNGROUPED_KEY]).toEqual(['two', 'three', 'one'])
expect(screen.getAllByRole('treeitem').slice(1).map(row => row.textContent)).toEqual([
expect.stringContaining('two'),
expect.stringContaining('three'),

View File

@@ -28,7 +28,7 @@ function hook<T>(snapshot: T) {
return function select<S>(selector: (state: T) => S): S { return selector(snapshot) }
}
const sessions: SessionListState = {
ids: [], byId: {}, current: undefined, phase: 'ready', subagentsByParent: {}, tasksBySession: {}, currentAddress: undefined,
ids: [], byId: {}, current: undefined, phase: 'ready', subagentsByParent: {}, jobsBySession: {}, currentAddress: undefined,
}
const workspaceState = (items: readonly WorkspaceView[]): WorkspaceListState => ({
items, archivedSessionIds: [], state: 'idle', phase: 'ready', error: null, baselinesReady: true,