diff --git a/packages/client/runtime/src/client/contract/workspaces.ts b/packages/client/runtime/src/client/contract/workspaces.ts index cd32cbf56f..bb50b43277 100644 --- a/packages/client/runtime/src/client/contract/workspaces.ts +++ b/packages/client/runtime/src/client/contract/workspaces.ts @@ -6,7 +6,7 @@ * the concrete class. Widening this interface is the explicit act of * widening what features may do to the workspaces domain. */ -import type { SessionId, WorkspaceId, WorkspaceView } from '@deepseek-ai/dsh-client-connection/client' +import type { DirectoryListing, SessionId, WorkspaceId, WorkspaceView } from '@deepseek-ai/dsh-client-connection/client' import type { WorkspaceListState } from '../workspaces/service.ts' import type { ObservableSnapshot } from './store.ts' @@ -37,6 +37,19 @@ export interface IWorkspaces { * @returns the selected path, or null when the user cancelled. */ pickDirectory(): Promise + /** + * List one directory level through the Host's `browse` capability. + * @param path - absolute directory to list; absent lists the Host home directory. + * @returns the level's listing with breadcrumb ancestry. + */ + listDirectory(path?: string): Promise + /** + * Create one child directory through the Host's `browse` capability. + * @param path - absolute existing parent directory. + * @param name - single non-blank path segment. + * @returns the created directory's absolute path. + */ + createDirectory(path: string, name: string): Promise /** * Open a filesystem path with the Host operating system's default application. * @param path - absolute or host-resolvable path. diff --git a/packages/client/test-runtime/src/workspaces.ts b/packages/client/test-runtime/src/workspaces.ts index 32c9bff36e..ee635a5fd8 100644 --- a/packages/client/test-runtime/src/workspaces.ts +++ b/packages/client/test-runtime/src/workspaces.ts @@ -1,7 +1,7 @@ /** Test-owned workspaces face: the renderer standard-kit observable plus recorded actions. */ import { createSnapshotStore } from '@deepseek-ai/dsh-client-runtime/client' import type { - IWorkspaces, SessionId, SnapshotStore, WorkspaceId, WorkspaceListState, WorkspaceView, + DirectoryListing, IWorkspaces, SessionId, SnapshotStore, WorkspaceId, WorkspaceListState, WorkspaceView, } from '@deepseek-ai/dsh-client-runtime/client' import { workspaceListState } from './fixtures.ts' import type { Stabilizer } from './fixtures.ts' @@ -109,6 +109,32 @@ export class TestWorkspaces implements IWorkspaces { return null } + /** + * Browse listing (recorded). The default serves an empty home level; stub + * to shape a tree. + * @param path - absolute directory to list; absent lists the home level. + * @returns the level's listing. + */ + async listDirectory(path?: string): Promise { + this.calls.push({ method: 'listDirectory', args: [path] }) + const stub = this.stubs.get('listDirectory') + if (stub !== undefined) return await (stub(path) as Promise) + return { path: '/home/test', home: '/home/test', crumbs: [{ name: '/', path: '/', hidden: false }], entries: [] } + } + + /** + * Browse child creation (recorded). The default joins parent and name. + * @param path - absolute existing parent directory. + * @param name - single path segment. + * @returns the created directory's absolute path. + */ + async createDirectory(path: string, name: string): Promise { + this.calls.push({ method: 'createDirectory', args: [path, name] }) + const stub = this.stubs.get('createDirectory') + if (stub !== undefined) return await (stub(path, name) as Promise) + return `${path}/${name}` + } + /** * Rename a Workspace (recorded). The default echoes a minimal view. * @param workspaceId - target workspace.