refactor(client): carve outward interfaces for the session, workspace, layout, slash, and conversation services

Feature packages now reach these domains through interface types only:
ISession/SessionFace (identity + prompt/cancel/loadOlder + the useSession
snapshot source), ISessions, IWorkspaces, ILayout, IConversation, and the
existing SlashServiceContract now actually mounted on Context.slash. The
concrete services implement their face; wire-pump and assembly entry
points stay on the classes. The provide-channel materialization and
current-projection logic moves into SessionProvideChannel so the
production service and the client test runtime share one implementation.
The workspaces service consumes sessions through the narrow SessionsPort.
This commit is contained in:
imccyu
2026-07-28 23:03:56 +08:00
parent eb38a365dc
commit 0efc7f045e
19 changed files with 556 additions and 179 deletions

View File

@@ -17,14 +17,16 @@ import { ThemePresenter } from './theme-presenter.ts'
// Contract surface only (export-convergence rule: cross-package consumers
// keep a symbol exported; test-only/package-internal symbols live off /src).
// LayoutService: the ctx.layout service class (consumers type against it).
// ILayout: the ctx.layout face consumers and test fakes type against.
// OwnerShare contracts below are the render-side halves registrants compose
// against; the frame components and the store factory are package-internal.
export { LayoutService } from './service.ts'
export type { ILayout } from './service.ts'
declare module 'cordis' {
interface Context {
layout: LayoutService
/** The outward face only; the concrete service stays inside this plugin. */
layout: import('./service.ts').ILayout
}
}

View File

@@ -14,8 +14,23 @@ import type { createLayoutStore } from './stores.ts'
/** The layout store's bound action set (framework-baked, draft params peeled). */
export type PanelActions = BoundActions<ReturnType<typeof createLayoutStore>>
/**
* The outward layout face (`ctx.layout`): the panel transitions other
* plugins may trigger — and exactly what a test fake must supply. The
* attachPanels wiring hook stays on the concrete class (root-entry assembly
* only).
*/
export interface ILayout {
/** Toggle the sidebar panel (closed ⟷ contract default width). */
toggleSidebar(): void
/** Open the details panel (no-op when already open). */
openDetails(): void
/** Close the details panel. */
closeDetails(): void
}
/** Cross-plugin panel-action face (ctx.layout). */
export class LayoutService {
export class LayoutService implements ILayout {
#panels: PanelActions | undefined
/**