@deepseek-ai/dsh-client-test-runtime 0.1.1-rc.2 → 0.1.2-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,9 @@
1
- /** Session/workspace fixture shapes and snapshot defaults for the test runtime. */
2
- import type { ConversationSnapshot, ISession, SessionId, SessionSummary, WorkspaceListState } from '@deepseek-ai/dsh-client-runtime/client';
1
+ /** Controller and UI-domain fixture shapes for the client test runtime. */
2
+ import type { ISession, SessionEventLikeEntry, SessionSnapshot, SessionSummary } from '@deepseek-ai/dsh-api-session-controller/client';
3
+ import type { WorkspaceSnapshot } from '@deepseek-ai/dsh-api-workspace-controller/client';
4
+ import type { SessionId } from '@deepseek-ai/dsh-session/types';
5
+ import { type ConversationSnapshot } from '@deepseek-ai/dsh-client-ui-conversation/client';
6
+ import { type ChatSnapshot } from '@deepseek-ai/dsh-client-ui-chat/client';
3
7
  /**
4
8
  * Fixture overrides for the session behavior face: any subset of the
5
9
  * production ISession verbs (typed against it, so a face change surfaces
@@ -16,6 +20,12 @@ export type SessionBehaviorOverrides = Partial<ISession> & Record<string, unknow
16
20
  * React act themselves.
17
21
  */
18
22
  export type Stabilizer = (fn: () => void | Promise<void>) => Promise<void>;
23
+ /** Mutable top-level snapshot fields accepted by fixture update callbacks. */
24
+ export type FixtureSnapshot<T> = {
25
+ -readonly [Key in keyof T]: T[Key];
26
+ };
27
+ /** Writable test representation of the immutable Session Controller snapshot. */
28
+ export type SessionFixtureSnapshot = FixtureSnapshot<SessionSnapshot>;
19
29
  /**
20
30
  * Session fixture accepted by {@link TestSessions.add}: identity plus optional
21
31
  * snapshot/list-row overrides and the session behavior face the feature under
@@ -24,23 +34,38 @@ export type Stabilizer = (fn: () => void | Promise<void>) => Promise<void>;
24
34
  */
25
35
  export interface SessionFixture {
26
36
  id: string;
27
- /** Overrides merged over {@link conversationSnapshot} (sessionId comes from `id`). */
28
- snapshot?: Partial<Omit<ConversationSnapshot, 'sessionId'>>;
37
+ /** Overrides merged over {@link sessionSnapshot}; Conversation data arrives through the event feed. */
38
+ snapshot?: Partial<Omit<SessionSnapshot, 'sessionId'>>;
29
39
  /** List-row overrides merged over the defaults derived from `id`. */
30
40
  summary?: Partial<Omit<SessionSummary, 'id'>>;
31
41
  /** Session behavior face: exactly the methods the feature under test calls (ISession subset + extras). */
32
42
  session?: SessionBehaviorOverrides;
43
+ /** Initial contiguous event window consumed by Conversation assembly. */
44
+ events?: readonly SessionEventLikeEntry[];
45
+ /** Whether the initial event window has an older page. */
46
+ hasMore?: boolean;
33
47
  }
34
48
  /**
35
- * A complete quiescent conversation snapshot (open window, no traffic).
49
+ * A complete quiescent Session Controller snapshot.
36
50
  * @param sessionId - owning session id.
37
51
  * @returns the snapshot; spread fixture overrides on top.
38
52
  */
39
- export declare function conversationSnapshot(sessionId: SessionId): ConversationSnapshot;
53
+ export declare function sessionSnapshot(sessionId: SessionId): SessionSnapshot;
40
54
  /**
41
- * A ready workspace list with no workspaces (the shape WorkspaceRuntime
42
- * projects after both baselines land).
43
- * @returns the initial state of the test workspaces store.
55
+ * A target-neutral Conversation snapshot.
56
+ * @param overrides - target roster or activity overrides.
57
+ * @returns an immutable fixture value.
44
58
  */
45
- export declare function workspaceListState(): WorkspaceListState;
59
+ export declare function conversationSnapshot(overrides?: Partial<ConversationSnapshot>): ConversationSnapshot;
60
+ /**
61
+ * A Chat target snapshot.
62
+ * @param overrides - Chat target overrides.
63
+ * @returns an immutable fixture value.
64
+ */
65
+ export declare function chatSnapshot(overrides?: Partial<ChatSnapshot>): ChatSnapshot;
66
+ /**
67
+ * A ready Workspace Controller snapshot with no Workspace rows.
68
+ * @returns the initial state of the test Workspace source.
69
+ */
70
+ export declare function workspaceSnapshot(): WorkspaceSnapshot;
46
71
  //# sourceMappingURL=fixtures.d.ts.map
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * jsdom slot test runtime: a real small runtime — Cordis `Context`, the
3
- * runtime `SlotRegistry`, and the UI renderer — assembled around
3
+ * renderer-owned `SlotRegistry`, the `ui-session` adapter, and the UI renderer — assembled around
4
4
  * test-owned session/workspace doubles, so feature specs exercise
5
5
  * declaration, registration, scope, store, inject, rendering, updates, and
6
6
  * disposal without hand-building the machinery per suite.
@@ -15,20 +15,22 @@ import type { Fiber, Plugin } from '@deepseek-ai/cordis';
15
15
  import type { RenderResult } from '@testing-library/react';
16
16
  import type { queries } from '@testing-library/dom';
17
17
  import type { BoundFunctions } from '@testing-library/dom';
18
- import { SlotRegistry } from '@deepseek-ai/dsh-client-runtime/client';
18
+ import { SlotRegistry } from '@deepseek-ai/dsh-client-ui-renderer/client';
19
19
  import type { ChildrenDecl, ComposedProps, HostObservable, OwnerOf, SlotComponent, SlotMap, SlotRenderer, SnapshotSelectorHook, StoreInstanceLike } from '@deepseek-ai/dsh-client-ui-slots';
20
20
  import { TestSessions } from './sessions.ts';
21
21
  import { TestWorkspaces } from './workspaces.ts';
22
22
  import type { Stabilizer } from './fixtures.ts';
23
- export type { UseSession } from '@deepseek-ai/dsh-client-ui-renderer/client';
23
+ export type { UseSession } from '@deepseek-ai/dsh-client-ui-session/client';
24
24
  export { domSnapshotSerializer, registerDomSnapshotSerializer } from './snapshot.ts';
25
25
  export { FixtureSession, TestSessions } from './sessions.ts';
26
26
  export { stubSettingsScope } from './settings-scope.ts';
27
27
  export type { StubSettingsScope } from './settings-scope.ts';
28
+ export { scriptedSettingsRemote } from './settings-remote.ts';
29
+ export type { ScriptedNamespace, ScriptedSettingsRemote } from './settings-remote.ts';
28
30
  export { TestWorkspaces } from './workspaces.ts';
29
- export { TestRemote } from './remote.ts';
30
- export { conversationSnapshot, workspaceListState } from './fixtures.ts';
31
- export type { SessionBehaviorOverrides, SessionFixture, Stabilizer } from './fixtures.ts';
31
+ export { RemoteError, TestRemote } from './remote.ts';
32
+ export { chatSnapshot, conversationSnapshot, sessionSnapshot, workspaceSnapshot, } from './fixtures.ts';
33
+ export type { FixtureSnapshot, SessionBehaviorOverrides, SessionFixture, SessionFixtureSnapshot, Stabilizer, } from './fixtures.ts';
32
34
  export { makeTranslate } from './translate.ts';
33
35
  export { usePinnedBrowserLanguages } from './locale-env.ts';
34
36
  /**
@@ -108,7 +110,7 @@ export declare class TestRoot {
108
110
  * batching or React act themselves.
109
111
  */
110
112
  export declare class SlotTestRuntime {
111
- /** The runtime's Cordis root (escape hatch: extra services via `ctx.provide`, raw `ctx.plugin` mounts). */
113
+ /** The runtime's Cordis root for owner APIs and explicit test-only services. */
112
114
  readonly ctx: Context;
113
115
  /** The production SlotRegistry mounted on {@link SlotTestRuntime.ctx}. */
114
116
  readonly slots: SlotRegistry;
@@ -127,6 +129,7 @@ export declare class SlotTestRuntime {
127
129
  private readonly ownerCell;
128
130
  private readonly autoDeclared;
129
131
  private autoRootView;
132
+ private readonly disposeWorkspaceSource;
130
133
  private constructor();
131
134
  /**
132
135
  * Assemble a runtime: real Context, mounted SlotRegistry, installed
@@ -134,17 +137,6 @@ export declare class SlotTestRuntime {
134
137
  * @returns the ready runtime.
135
138
  */
136
139
  static create(): Promise<SlotTestRuntime>;
137
- /**
138
- * Provide an extra service the feature under test injects (e.g. a layout
139
- * fake). Sugar over `ctx.provide`, typed against the Context declaration
140
- * merge: for a declared service name the fake must be a subset of that
141
- * service's outward face (Partial — supply only what the feature calls),
142
- * so a production face change breaks the fake at compile time. Undeclared
143
- * names stay unchecked (ad-hoc test services).
144
- * @param name - service name.
145
- * @param value - service implementation (test double).
146
- */
147
- provide<K extends string>(name: K, value: K extends keyof Context ? Partial<Context[K]> : unknown): void;
148
140
  /**
149
141
  * Mount a feature plugin on a real fiber. Required services are prechecked
150
142
  * so a missing provider fails loud instead of suspending the fiber forever
@@ -153,6 +145,8 @@ export declare class SlotTestRuntime {
153
145
  * @returns handle owning the fiber's explicit disposal.
154
146
  */
155
147
  mount(plugin: Plugin): Promise<FeatureHandle>;
148
+ /** Release the default Workspace hook before mounting its production owner. */
149
+ releaseWorkspaceSource(): void;
156
150
  /**
157
151
  * Render the root slot tree through the ctx-level entry (the shell's own
158
152
  * entry point): `ctx.slots.renderSlot('root', {})` under Testing Library.
@@ -1,18 +1,17 @@
1
- /** Test-owned Remote face: `$on` subscriptions driven by the internal forwarded-event plumbing. */
1
+ /** Test-owned Remote face: `$on` subscriptions with an explicit test event driver. */
2
2
  import type { Context } from '@deepseek-ai/cordis';
3
+ export { RemoteError } from '@deepseek-ai/dsh-typert-protocol';
3
4
  /**
4
5
  * Remote service test double for the forwarded-event path. Feature specs need
5
6
  * `ctx.remote.$on` to exist (their plugins inject `remote`) and need forwarded
6
- * host events to reach those subscribers, but not the generated namespaces or
7
- * the wire so this double implements subscription and dispatch only.
7
+ * Host events to reach those subscribers, but not the wire so this double
8
+ * implements subscription plus an explicit `emit` driver available only on the
9
+ * concrete test object. A spec that also calls one namespace scripts it through
10
+ * the constructor rather than reaching the real Client Remote service.
8
11
  *
9
- * Dispatch is driven the same way production drives it: `client/runtime` owns the
10
- * host frame sink and hands each decoded `host/remote-event` frame to
11
- * `$dispatch`. A spec therefore exercises its refresh chains by calling
12
- * `$dispatch(name, args)` on this double.
13
- *
14
- * `$mount` rejects: a spec that reaches a generated namespace through this
15
- * double has outgrown it and needs the real Client Remote service.
12
+ * `$mount` rejects: a spec that needs a real generated contribution installed
13
+ * codecs, descriptors, and the wire has outgrown this double and needs the
14
+ * real Client Remote service.
16
15
  *
17
16
  * One deliberate asymmetry with production: a throwing listener propagates out
18
17
  * of the emit instead of being contained and logged, so a spec cannot lean on
@@ -22,17 +21,27 @@ import type { Context } from '@deepseek-ai/cordis';
22
21
  export declare class TestRemote {
23
22
  private readonly subscriptions;
24
23
  /**
25
- * Register the double as `ctx.remote`.
24
+ * Fixed Host facts mirrored from the production `ctx.remote.$host`. Plain
25
+ * mutable field: a spec assigns it to script a non-loopback or homed Host.
26
+ */
27
+ $host: {
28
+ home: string | undefined;
29
+ isLoopback: boolean;
30
+ };
31
+ /**
32
+ * Register the double as `ctx.remote`, plus one service per scripted
33
+ * namespace so a plugin injecting `remote.<name>` also unparks.
26
34
  * @param ctx - the spec's root Context.
35
+ * @param namespaces - scripted namespace faces reached as `ctx.remote.<name>`.
27
36
  */
28
- constructor(ctx: Context);
37
+ constructor(ctx: Context, namespaces?: Readonly<Record<string, object>>);
29
38
  /**
30
39
  * Deliver one forwarded host event to its subscribers, standing in for the
31
40
  * carrier that owns the frame sink.
32
41
  * @param event - forwarded host event name.
33
42
  * @param args - the Host argument list, verbatim.
34
43
  */
35
- $dispatch(event: string, args: readonly unknown[]): void;
44
+ emit(event: string, args: readonly unknown[]): void;
36
45
  /**
37
46
  * Subscribe to one forwarded host event.
38
47
  * @param event - forwarded host event name.
@@ -1,12 +1,15 @@
1
- /** Test-owned sessions face: the SlotRegistry host contract over declarative fixtures. */
1
+ /** Test-owned Session Controller faces over declarative fixtures. */
2
2
  import type { Context } from '@deepseek-ai/cordis';
3
3
  import type { AttachmentIdType } from '@deepseek-ai/dsh-attachment';
4
- import type { AgentContext, ConversationSnapshot, ISessions, ProjectionsFace, SessionFace, SessionId, SessionListState, SessionProvideDescriptor, SessionSearchResultItem, SessionSummary, SnapshotStore, SubagentAddress } from '@deepseek-ai/dsh-client-runtime/client';
5
- import type { HostObservable, SessionMaybeProvideInfo, SessionProvideInfo } from '@deepseek-ai/dsh-client-ui-slots';
6
- import type { SessionFixture, Stabilizer } from './fixtures.ts';
4
+ import { MutableSessionEventSource } from '@deepseek-ai/dsh-api-session-controller/client';
5
+ import type { AgentContext, ISessions, ProjectionsFace, SessionBinding, SessionFace, SessionListState, SessionEventLikeEntry, SessionLiveEventEntry, SessionSearchResultItem, SessionSnapshot, SessionSummary, SubmissionHandle } from '@deepseek-ai/dsh-api-session-controller/client';
6
+ import type { SubagentAddress } from '@deepseek-ai/dsh-subagent/client';
7
+ import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
8
+ import type { SessionId } from '@deepseek-ai/dsh-session/types';
9
+ import type { SessionFixture, SessionFixtureSnapshot, Stabilizer } from './fixtures.ts';
7
10
  /**
8
- * The fixture-backed session face: conversation reads delegate to the
9
- * fixture's snapshot store; ISession verbs are fail-loud stubs unless the
11
+ * The fixture-backed session face: lifecycle reads delegate to the fixture's
12
+ * snapshot store; Session verbs are fail-loud stubs unless the
10
13
  * fixture supplies them (the runtime never fakes behavior a test did not
11
14
  * declare — an unstubbed call names itself instead of half-working). Extra
12
15
  * fixture methods are grafted verbatim for feature-side casts.
@@ -14,21 +17,22 @@ import type { SessionFixture, Stabilizer } from './fixtures.ts';
14
17
  export declare class FixtureSession implements SessionFace {
15
18
  readonly sessionId: SessionId;
16
19
  private readonly store;
20
+ /** Mutable event source consumed only by Conversation assembly. */
21
+ readonly eventSource: MutableSessionEventSource;
17
22
  /**
18
- * The useProjection seat: identity-stable per-key faces over the fixture's
19
- * projection values (set via {@link TestSessions.setProjection}).
23
+ * Identity-stable per-key faces over fixture-controlled projection values.
20
24
  */
21
25
  readonly projections: ProjectionsFace & {
22
26
  set(key: string, value: unknown): void;
23
27
  };
24
28
  /**
25
29
  * @param sessionId - host identity (branded view of the fixture id).
26
- * @param store - conversation snapshot store (updateSnapshot writes it).
30
+ * @param store - Session Controller snapshot store.
27
31
  * @param overrides - fixture-declared behavior face, grafted over the stubs.
28
32
  */
29
- constructor(sessionId: SessionId, store: SnapshotStore<ConversationSnapshot>, overrides: Record<string, unknown>);
30
- /** @returns the fixture conversation snapshot (useSession read side). */
31
- getSnapshot(): ConversationSnapshot;
33
+ constructor(sessionId: SessionId, store: SnapshotStore<SessionFixtureSnapshot>, overrides: Record<string, unknown>);
34
+ /** @returns the fixture Session Controller snapshot (useSession read side). */
35
+ getSnapshot(): SessionSnapshot;
32
36
  /**
33
37
  * Subscribe to fixture snapshot changes.
34
38
  * @param fn - change callback.
@@ -40,6 +44,14 @@ export declare class FixtureSession implements SessionFace {
40
44
  * @returns never — always throws.
41
45
  */
42
46
  prompt(): never;
47
+ /**
48
+ * Minimal local-echo registration: mints an identity without touching the
49
+ * fixture snapshot (submission echoes are client-only presentation state).
50
+ * Supply `beginSubmission` on the fixture's session face to observe echoes.
51
+ * @returns a handle whose abandon is a no-op.
52
+ */
53
+ beginSubmission(): SubmissionHandle;
54
+ private submissionSeq;
43
55
  /**
44
56
  * Fail-loud stub; supply `readAttachment` on the fixture's session face to exercise it.
45
57
  * @param _attachmentId - opaque durable attachment id.
@@ -72,47 +84,33 @@ export declare class FixtureSession implements SessionFace {
72
84
  */
73
85
  rename(): never;
74
86
  }
75
- /** Test binding shape handed to provider resolvers and feature injects (a SessionBinding whose session is the fixture face). */
76
- export interface TestSessionBinding {
77
- readonly sessionId: SessionId;
78
- readonly session: FixtureSession;
79
- readonly ctx: AgentContext;
80
- }
81
87
  /**
82
88
  * Sessions test double behind the renderer host and feature injects: owns the
83
- * list/current observable, the standard-props provide channel (the runtime's
84
- * `useSession` contribution included), scope minting through the production
85
- * `createScope`, and the session behavior face supplied per fixture.
89
+ * list/current observable, scope minting through the production `createScope`,
90
+ * stable Controller bindings, and the session behavior face supplied per
91
+ * fixture. `ui-session` owns standard-source materialization.
86
92
  *
87
93
  * Implements the same ISessions face features receive as `ctx.sessions`, so
88
94
  * a production face change breaks this double at compile time; the extra
89
- * members (add/updateSnapshot/setCurrent/remove/behavior/calls/stubSearch and
90
- * the legacy provideInfo/maybeProvideInfo lookups) are bench-only surface.
95
+ * members (add/updateSessionSnapshot/event-window drivers/setCurrent/remove/
96
+ * behavior/calls/stubs) are bench-only surface.
91
97
  */
92
98
  export declare class TestSessions implements ISessions {
93
99
  private readonly stabilize;
94
100
  private readonly rootCtx;
95
101
  /** The useSessions standard feed (list rows + current selection). */
96
102
  readonly list: SnapshotStore<SessionListState>;
97
- /**
98
- * Atomic current-session provide projection (production SessionRuntime
99
- * mirror): selection changes and provider-roster changes publish through
100
- * this one source — the member the SlotRegistry host face hands the
101
- * renderer's SessionProvider.
102
- */
103
- readonly currentProvideInfo: HostObservable<SessionMaybeProvideInfo>;
104
103
  private readonly records;
105
- /** The production provide channel (roster, materialization rules, current projection) — no test-side mirror. */
106
- private readonly channel;
107
104
  /** Calls observed on the service-level face, newest last. */
108
105
  readonly calls: {
109
- method: 'open' | 'openSubagent' | 'setSubagentCatalogOpen' | 'refreshSubagents' | 'clear' | 'search' | 'fork';
106
+ method: 'create' | 'open' | 'openSubagent' | 'setSubagentCatalogOpen' | 'refreshSubagents' | 'clear' | 'refresh' | 'search' | 'fork';
110
107
  args: unknown[];
111
108
  }[];
112
109
  /** The wire schema's `session.search` result bound (production parity). */
113
110
  readonly searchResultLimit = 20;
114
111
  /** Replaceable search behavior (see {@link TestSessions.stubSearch}). */
115
112
  private searchStub;
113
+ private createStub;
116
114
  /**
117
115
  * @param stabilize - the owning runtime's act wrapper.
118
116
  * @param rootCtx - the runtime's Cordis root; scope fibers mount under it.
@@ -128,12 +126,31 @@ export declare class TestSessions implements ISessions {
128
126
  current?: boolean;
129
127
  }): Promise<SessionId>;
130
128
  /**
131
- * Update a session's conversation snapshot through an immer draft (the
132
- * live-stream stand-in: components subscribed via useSession re-render).
129
+ * Update Session Controller lifecycle state through an immer draft.
133
130
  * @param id - session id.
134
131
  * @param mutate - draft mutator.
135
132
  */
136
- updateSnapshot(id: string, mutate: (draft: ConversationSnapshot) => void): Promise<void>;
133
+ updateSessionSnapshot(id: string, mutate: (draft: SessionFixtureSnapshot) => void): Promise<void>;
134
+ /**
135
+ * Replace a Session's complete contiguous event window.
136
+ * @param id - Session identity.
137
+ * @param entries - complete event window.
138
+ * @param hasMore - whether older history remains.
139
+ */
140
+ replaceEvents(id: string, entries: readonly SessionEventLikeEntry[], hasMore?: boolean): Promise<void>;
141
+ /**
142
+ * Prepend one older contiguous event page.
143
+ * @param id - Session identity.
144
+ * @param entries - older entries.
145
+ * @param hasMore - whether another older page remains.
146
+ */
147
+ prependEvents(id: string, entries: readonly SessionEventLikeEntry[], hasMore?: boolean): Promise<void>;
148
+ /**
149
+ * Append one live event to a Session's contiguous window.
150
+ * @param id - Session identity.
151
+ * @param entry - live event entry.
152
+ */
153
+ appendEvent(id: string, entry: SessionLiveEventEntry): Promise<void>;
137
154
  /**
138
155
  * Update a session's list row (the wire-echo stand-in: title settles,
139
156
  * running flips — components subscribed via useSessions re-render).
@@ -149,31 +166,10 @@ export declare class TestSessions implements ISessions {
149
166
  /**
150
167
  * Remove a session: list row, scope fiber, and per-session store instances
151
168
  * (with persisted state) die together — the same single lifecycle axis the
152
- * production SessionRuntime drives on session death, minus staging.
169
+ * production Client Sessions service drives on session death, minus staging.
153
170
  * @param id - session id.
154
171
  */
155
172
  remove(id: string): Promise<void>;
156
- /**
157
- * Register a per-session standard-props provider (production `provide`
158
- * contract: hooks become `use<Name>` selector hooks on the render side,
159
- * props spread verbatim; duplicate names fail loud at materialization).
160
- * @param descriptor - static member roster plus per-session resolver.
161
- * @returns disposer removing the provider.
162
- */
163
- provide(descriptor: SessionProvideDescriptor): () => void;
164
- /**
165
- * Resolve the definite per-session standard-props bundle (host face member).
166
- * @param id - session id.
167
- * @returns the identity-stable bundle, or undefined for unknown sessions.
168
- */
169
- provideInfo(id: string): SessionProvideInfo | undefined;
170
- /**
171
- * Resolve the current-session-optional standard kit (host face member):
172
- * unknown or absent ids return the static no-session projection.
173
- * @param id - current session id, when selected.
174
- * @returns a definite or no-session provide bundle.
175
- */
176
- maybeProvideInfo(id: string | undefined): SessionMaybeProvideInfo;
177
173
  /**
178
174
  * Resolve (mint on first touch) the session-scoped Cordis context through
179
175
  * the production `createScope`, so real `scopeOf`/scope-addressed services
@@ -187,7 +183,7 @@ export declare class TestSessions implements ISessions {
187
183
  * @param id - session id.
188
184
  * @returns sessionId + behavior face + scoped ctx, or undefined when unknown.
189
185
  */
190
- binding(id: string): TestSessionBinding | undefined;
186
+ binding(id: string): SessionBinding | undefined;
191
187
  /**
192
188
  * Read the session scope tag off a context (service-method boundary mirror).
193
189
  * @param ctx - any client context.
@@ -201,6 +197,13 @@ export declare class TestSessions implements ISessions {
201
197
  * @returns the fixture session face, or undefined off-scope.
202
198
  */
203
199
  sessionOf(ctx: Context): SessionFace | undefined;
200
+ /**
201
+ * Install Session creation behavior for navigation tests.
202
+ * @param impl - implementation that must return an already-added fixture id.
203
+ */
204
+ stubCreate(impl: (opts: Parameters<ISessions['create']>[0]) => Promise<SessionId>): void;
205
+ /** Create through the installed test behavior and require an addressable binding. */
206
+ create(opts?: Parameters<ISessions['create']>[0]): Promise<SessionId>;
204
207
  /**
205
208
  * Service-level selection call (recorded, then applied to the list store
206
209
  * synchronously — inject callbacks call this outside any act window; the
@@ -216,10 +219,10 @@ export declare class TestSessions implements ISessions {
216
219
  setSubagentCatalogOpen(parentSessionId: SessionId, open: boolean): void;
217
220
  /** Record a catalog refresh; fixture callers drive snapshots explicitly. */
218
221
  refreshSubagents(parentSessionId: SessionId): Promise<void>;
219
- /** Apply a confirmed preset switch into the fixture list, as production does. */
220
- noteAgentPreset(sessionId: SessionId, agentPreset: string): void;
221
222
  /** Clear the current selection (recorded; the production no-session flow). */
222
223
  clear(): void;
224
+ /** Record a list refresh; fixture callers publish list state explicitly. */
225
+ refresh(): Promise<void>;
223
226
  /**
224
227
  * Replace the sidebar-search result page (the call is still recorded).
225
228
  * @param impl - hits for a query, as the Host would rank them.
@@ -252,7 +255,7 @@ export declare class TestSessions implements ISessions {
252
255
  * The session face of a fixture (typed view for assertions; fixture
253
256
  * behavior methods are grafted onto it).
254
257
  * @param id - session id.
255
- * @returns the FixtureSession the binding and provide channel carry.
258
+ * @returns the FixtureSession carried by the Controller binding.
256
259
  */
257
260
  behavior(id: string): FixtureSession;
258
261
  /** Dispose minted scope fibers (runtime dispose path). */
@@ -0,0 +1,83 @@
1
+ /** Test double for the `settings` Remote namespace a bench's plugins inject. */
2
+ import { vi } from 'vitest';
3
+ /** The minimum a scripted namespace view carries for the double's own bookkeeping. */
4
+ export interface ScriptedNamespace {
5
+ /** Namespace key the write addresses. */
6
+ ns: string;
7
+ }
8
+ /** One scripted `settings` namespace face plus the controls a bench drives it with. */
9
+ export interface ScriptedSettingsRemote<View extends ScriptedNamespace> {
10
+ /**
11
+ * The namespace face handed to `TestRemote` as `settings`. A plugin injecting
12
+ * `remote.settings` unparks on it, which is what most benches need; the
13
+ * describe answer is the same one the shared mirror would read.
14
+ */
15
+ settings: {
16
+ describe(): Promise<{
17
+ ok: true;
18
+ value: {
19
+ writable: boolean;
20
+ hasDocument: boolean;
21
+ namespaces: readonly View[];
22
+ };
23
+ }>;
24
+ update(ns: string, patch: unknown, expectedRevision: number | undefined): Promise<{
25
+ ok: true;
26
+ value: View;
27
+ } | {
28
+ ok: false;
29
+ error: {
30
+ code: string;
31
+ message: string;
32
+ details: object;
33
+ };
34
+ }>;
35
+ replace(ns: string, section: unknown, expectedRevision: number | undefined): Promise<{
36
+ ok: true;
37
+ value: View;
38
+ } | {
39
+ ok: false;
40
+ error: {
41
+ code: string;
42
+ message: string;
43
+ details: object;
44
+ };
45
+ }>;
46
+ mutate(ns: string, ops: unknown, expectedRevision: number | undefined): Promise<{
47
+ ok: true;
48
+ value: View;
49
+ } | {
50
+ ok: false;
51
+ error: {
52
+ code: string;
53
+ message: string;
54
+ details: object;
55
+ };
56
+ }>;
57
+ };
58
+ /** Spy behind `settings.update`, for argument assertions. */
59
+ update: ReturnType<typeof vi.fn>;
60
+ /** Spy behind `settings.replace`, for argument assertions. */
61
+ replace: ReturnType<typeof vi.fn>;
62
+ /** Spy behind `settings.mutate`, for argument assertions. */
63
+ mutate: ReturnType<typeof vi.fn>;
64
+ /**
65
+ * Replace what the next describe answers with, as a Host commit would.
66
+ * @param namespaces - the namespace views to serve from now on.
67
+ */
68
+ publish(namespaces: readonly View[]): void;
69
+ }
70
+ /**
71
+ * Build a scripted `settings` Remote namespace for a bench. Each write answers
72
+ * with the addressed namespace unchanged, so a bench that only needs its
73
+ * plugins to activate scripts nothing; one asserting a write reads the
74
+ * corresponding spy or replaces the face.
75
+ * @param namespaces - namespace views the first describe answers with.
76
+ * @param options - deployment facts the describe answer reports.
77
+ * @returns the face and its controls.
78
+ */
79
+ export declare function scriptedSettingsRemote<View extends ScriptedNamespace>(namespaces?: readonly View[], options?: {
80
+ writable?: boolean;
81
+ hasDocument?: boolean;
82
+ }): ScriptedSettingsRemote<View>;
83
+ //# sourceMappingURL=settings-remote.d.ts.map
@@ -1,12 +1,14 @@
1
1
  /** Test double for the client settings-scope seam. */
2
2
  import { vi } from 'vitest';
3
- import type { SettingsScope, SettingsScopeSnapshot } from '@deepseek-ai/dsh-client-runtime/client';
3
+ import type { SettingsScope, SettingsScopeSnapshot } from '@deepseek-ai/dsh-client-ui-settings/client';
4
4
  /** Handle over one stubbed scope: the scope, its write spy, and publication controls. */
5
5
  export interface StubSettingsScope<T> {
6
6
  /** The scope face handed to the service under test. */
7
7
  scope: SettingsScope<T>;
8
8
  /** Spy behind `scope.set`; resolves immediately. */
9
9
  set: ReturnType<typeof vi.fn>;
10
+ /** Spy behind `scope.mutate`; resolves immediately. */
11
+ mutate: ReturnType<typeof vi.fn>;
10
12
  /** Spy behind `scope.unset`; resolves immediately. */
11
13
  unset: ReturnType<typeof vi.fn>;
12
14
  /** @returns how many listeners are currently subscribed (disposal assertions). */
@@ -1,5 +1,15 @@
1
- import type { DirectoryListing, IWorkspaces, SessionId, SnapshotStore, WorkspaceId, WorkspaceListState, WorkspaceView } from '@deepseek-ai/dsh-client-runtime/client';
2
- import type { Stabilizer } from './fixtures.ts';
1
+ import type { IWorkspaces, WorkspaceId, WorkspaceSnapshot, WorkspaceView } from '@deepseek-ai/dsh-api-workspace-controller/client';
2
+ import type { SessionId } from '@deepseek-ai/dsh-session/types';
3
+ import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
4
+ import type { FixtureSnapshot, Stabilizer } from './fixtures.ts';
5
+ /** Writable test representation of the immutable Workspace Controller snapshot. */
6
+ type WorkspaceFixtureSnapshot = FixtureSnapshot<WorkspaceSnapshot>;
7
+ /** Callable command names on the production Workspace Controller face. */
8
+ type WorkspaceAction = {
9
+ [Key in keyof IWorkspaces]: IWorkspaces[Key] extends (...args: never[]) => unknown ? Key : never;
10
+ }[keyof IWorkspaces];
11
+ /** Test replacement retaining one Controller command's parameters and result. */
12
+ type WorkspaceStub<Key extends WorkspaceAction> = (...args: Parameters<IWorkspaces[Key]>) => ReturnType<IWorkspaces[Key]>;
3
13
  /**
4
14
  * Workspaces test double. Implements the same IWorkspaces face features
5
15
  * receive as `ctx.workspaces`, so a production face change breaks this
@@ -10,7 +20,7 @@ import type { Stabilizer } from './fixtures.ts';
10
20
  export declare class TestWorkspaces implements IWorkspaces {
11
21
  private readonly stabilize;
12
22
  /** The useWorkspaces standard feed. */
13
- readonly list: SnapshotStore<WorkspaceListState>;
23
+ readonly list: SnapshotStore<WorkspaceFixtureSnapshot>;
14
24
  /** Calls observed on the action face, newest last. */
15
25
  readonly calls: {
16
26
  method: string;
@@ -26,26 +36,13 @@ export declare class TestWorkspaces implements IWorkspaces {
26
36
  * Update the workspace list state through an immer draft.
27
37
  * @param mutate - draft mutator.
28
38
  */
29
- update(mutate: (draft: WorkspaceListState) => void): Promise<void>;
39
+ update(mutate: (draft: WorkspaceFixtureSnapshot) => void): Promise<void>;
30
40
  /**
31
41
  * Replace an action's behavior (the recorded call is still appended first).
32
- * @param method - action name (e.g. 'connectWorkspace').
42
+ * @param method - Controller action name (e.g. 'create').
33
43
  * @param impl - replacement behavior.
34
44
  */
35
- stub(method: string, impl: (...args: unknown[]) => unknown): void;
36
- /**
37
- * Connect a workspace to its reusable/new blank session (recorded). The
38
- * default resolves the workspace id back as the session id; stub for
39
- * cross-session flows.
40
- * @param workspaceId - target workspace.
41
- * @returns the connected session id.
42
- */
43
- connectWorkspace(workspaceId: WorkspaceId): Promise<SessionId>;
44
- /**
45
- * New-session flow (recorded; stubbed behavior runs when installed).
46
- * @param workspaceId - optional explicit workspace target.
47
- */
48
- startSession(workspaceId?: WorkspaceId): void;
45
+ stub<Key extends WorkspaceAction>(method: Key, impl: WorkspaceStub<Key>): void;
49
46
  /**
50
47
  * Create a Workspace (recorded). The default echoes a view derived from
51
48
  * the input; stub for failure or list-coupled flows.
@@ -55,30 +52,6 @@ export declare class TestWorkspaces implements IWorkspaces {
55
52
  create(input: {
56
53
  path: string;
57
54
  }): Promise<WorkspaceView>;
58
- /**
59
- * Open a path with the host OS default application (recorded; default no-op).
60
- * @param path - host-resolvable path.
61
- */
62
- openPath(path: string): Promise<void>;
63
- /**
64
- * Directory picker (recorded). The default cancels (null); stub to select.
65
- * @returns the picked path, or null.
66
- */
67
- pickDirectory(): Promise<string | null>;
68
- /**
69
- * Browse listing (recorded). The default serves an empty home level; stub
70
- * to shape a tree.
71
- * @param path - absolute directory to list; absent lists the home level.
72
- * @returns the level's listing.
73
- */
74
- listDirectory(path?: string, signal?: AbortSignal): Promise<DirectoryListing>;
75
- /**
76
- * Browse child creation (recorded). The default joins parent and name.
77
- * @param path - absolute existing parent directory.
78
- * @param name - single path segment.
79
- * @returns the created directory's absolute path.
80
- */
81
- createDirectory(path: string, name: string): Promise<string>;
82
55
  /**
83
56
  * Rename a Workspace (recorded). The default echoes a minimal view.
84
57
  * @param workspaceId - target workspace.
@@ -112,4 +85,5 @@ export declare class TestWorkspaces implements IWorkspaces {
112
85
  */
113
86
  archiveSession(sessionId: SessionId): Promise<void>;
114
87
  }
88
+ export {};
115
89
  //# sourceMappingURL=workspaces.d.ts.map