@crazx/dsh-api-session-controller 0.1.6-alpha.1.zw.2 → 0.1.6-alpha.2.zw.1

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.
Files changed (35) hide show
  1. package/README.i18n.yaml +2 -2
  2. package/README.md +15 -3
  3. package/README.zh.md +15 -3
  4. package/lib/client.js +428 -471
  5. package/lib/index.js +16 -47
  6. package/lib/typert.host.js +179 -161
  7. package/lib/typert.remote-client.js +168 -150
  8. package/lib/types/agent.d.ts +1 -1
  9. package/lib/types/agent.js +8 -1
  10. package/lib/types/client/contract/sessions.d.ts +55 -20
  11. package/lib/types/client/contract/snapshot.d.ts +0 -14
  12. package/lib/types/client/index.d.ts +11 -2
  13. package/lib/types/client/index.js +16 -5
  14. package/lib/types/client/scope.d.ts +13 -3
  15. package/lib/types/client/scope.js +15 -22
  16. package/lib/types/client/sessions/lineage.d.ts +1 -4
  17. package/lib/types/client/sessions/lineage.js +1 -3
  18. package/lib/types/client/sessions/manager.d.ts +28 -49
  19. package/lib/types/client/sessions/manager.js +75 -174
  20. package/lib/types/client/sessions/projection-store.d.ts +5 -11
  21. package/lib/types/client/sessions/projection-store.js +6 -14
  22. package/lib/types/client/sessions/service.d.ts +34 -119
  23. package/lib/types/client/sessions/service.js +259 -244
  24. package/lib/types/client/sessions/session.d.ts +7 -20
  25. package/lib/types/client/sessions/session.js +29 -33
  26. package/lib/types/commands.d.ts +2 -2
  27. package/lib/types/commands.js +10 -4
  28. package/lib/types/control.d.ts +1 -1
  29. package/lib/types/control.js +1 -41
  30. package/lib/types/index.d.ts +2 -2
  31. package/lib/types/index.js +1 -1
  32. package/lib/types/types.d.ts +3 -17
  33. package/package.json +70 -70
  34. package/lib/types/client/sessions/queue-mirror.d.ts +0 -26
  35. package/lib/types/client/sessions/queue-mirror.js +0 -61
@@ -1,30 +1,15 @@
1
- /**
2
- * ClientSessions: root sessions service — list snapshot store (manager
3
- * projection; carries `current`, the persisted selection every
4
- * session-scoped surface keys off), Agent scope tree (mintScope pattern: no-op plugin
5
- * Fiber + ctx.extend scope tag; one scope per session, agent id === session
6
- * id), stable SessionBinding cache, breadcrumb-route projection.
7
- *
8
- * Scope lifecycle is stage-driven: a scope is minted lazily on first
9
- * resolution (pure — resolution has no side effects and is render-safe);
10
- * the event window and deferred teardown key off the STAGED session, which
11
- * follows `list.current` exactly. Staging is the open signal: the window
12
- * opens ⟺ the session is on stage (the stage is `current`; the staged
13
- * state can widen to a multi-pane list later). A session leaving the list
14
- * tears its scope down immediately unless it is the staged one, whose scope
15
- * survives frozen (read-only view) until the stage moves on.
16
- */
1
+ /** Client catalog and source-labelled ownership of exact Session generations. */
17
2
  import type { Context } from '@deepseek-ai/cordis';
18
3
  import type { SubagentAddress } from '@deepseek-ai/dsh-subagent/client';
19
4
  import { type SessionId } from '@deepseek-ai/dsh-session/types';
20
5
  import type { WorkspaceId } from '@deepseek-ai/dsh-workspace/types';
21
6
  import type { SessionJob as JobView } from '../../types.ts';
22
7
  import type { SessionProjectionMap } from '@deepseek-ai/dsh-session-projection/types';
23
- import { type SnapshotStore } from '@deepseek-ai/dsh-client-store';
8
+ import { type ObservableSnapshot, type SnapshotStore } from '@deepseek-ai/dsh-client-store';
24
9
  import type { RemoteFailure, RemoteResult } from '@deepseek-ai/dsh-typert-protocol';
25
10
  import type { SessionEventSource } from '../contract/events.ts';
26
11
  import type { SessionFace } from '../contract/session.ts';
27
- import type { AgentContext, ISessions } from '../contract/sessions.ts';
12
+ import type { AgentContext, ISessions, SessionReference, SessionRetainInfo, SessionRetainOptions, SessionTarget } from '../contract/sessions.ts';
28
13
  import { SessionManager } from './manager.ts';
29
14
  import type { SessionRemotes } from './remotes.ts';
30
15
  import type { SessionListPhase, SessionSearchResultItem, SubagentCatalogSnapshot } from './manager.ts';
@@ -40,8 +25,8 @@ export interface SessionSummary {
40
25
  /** Coarse durable origin for navigation filtering; not a continuation capability. */
41
26
  origin?: 'subagent';
42
27
  running: boolean;
43
- /** Finished while not selected and not yet opened — the sidebar's green "done" reminder. Absent = false. */
44
- completed?: boolean;
28
+ /** Local ownership counts; Host metadata refreshes cannot overwrite them. */
29
+ readonly retainedBy: SessionRetainInfo['retainedBy'];
45
30
  /**
46
31
  * Empty-log bit (host summary derivation mirror). New Session reuses a blank
47
32
  * one targeting the same workspace. Filtering stays with the consumer: the
@@ -53,17 +38,12 @@ export interface SessionSummary {
53
38
  /** Current host-computed projection values retained by the object layer. */
54
39
  projectionValues?: Readonly<Partial<SessionProjectionMap>>;
55
40
  }
56
- /**
57
- * Session list store shape. `current` rides the same snapshot (arbitrated:
58
- * the single useSessions standard hook reads list and selection together —
59
- * sidebar highlighting and current-session consumers share one fact source).
60
- */
41
+ /** Catalog metadata and local source counts; catalog membership owns no Client generation. */
61
42
  export interface SessionListState {
62
43
  /** Host-list order; addressed breadcrumb-only rows are excluded. */
63
44
  ids: SessionId[];
64
- /** Host rows plus the current addressed subagent route used by navigation. */
45
+ /** Host/catalog rows plus local fallback rows for live Client generations; only `ids` expresses Host-list membership. */
65
46
  byId: Record<SessionId, SessionSummary>;
66
- current: SessionId | undefined;
67
47
  /** Arrival lifecycle projected 1:1 from the manager snapshot (see SessionListPhase): empty-with-ready means "truly no sessions". */
68
48
  phase: SessionListPhase;
69
49
  /** Direct durable catalogs keyed by their selected parent address. */
@@ -74,8 +54,6 @@ export interface SessionListState {
74
54
  * set, so consumers read absence rather than a sentinel.
75
55
  */
76
56
  jobsBySession: Readonly<Record<SessionId, readonly JobView[]>>;
77
- /** Current session's catalog-derived address, absent on ordinary navigation. */
78
- currentAddress: SubagentAddress | undefined;
79
57
  }
80
58
  /** Structured session-create failure. */
81
59
  export declare class SessionCreateError extends Error {
@@ -109,7 +87,7 @@ export interface SessionBinding {
109
87
  readonly ctx: AgentContext;
110
88
  }
111
89
  export { scopeOf } from '../scope.ts';
112
- /** Root sessions service: list store, current selection, object-layer manager, scope tree, bindings, and breadcrumb routes. */
90
+ /** Host catalog and local reference allocator; view selection remains outside the Controller. */
113
91
  export declare class ClientSessions implements ISessions {
114
92
  private readonly rootCtx;
115
93
  /**
@@ -119,46 +97,23 @@ export declare class ClientSessions implements ISessions {
119
97
  * reports the same number.
120
98
  */
121
99
  readonly searchResultLimit = 20;
122
- /** List snapshot store (list RPC + host stream increments; re-pulled on reconnect) — the useSessions standard feed, current included. */
100
+ /** Catalog metadata and local reference-source projection. */
123
101
  readonly list: SnapshotStore<SessionListState>;
124
102
  /** The object-layer instance cluster and frame dispatch entry. */
125
103
  private readonly manager;
126
- /**
127
- * Persisted selection cell (the durable half of `list.current`). Private on
128
- * purpose: reads go through the list snapshot; writes through {@link
129
- * ClientSessions.open} / {@link ClientSessions.clear}. Projection
130
- * validates it against the live list instead of destructively pruning, so a
131
- * selection survives transient list states (reconnect re-pull) and
132
- * resurfaces when its session returns.
133
- */
134
- private readonly selection;
135
104
  private readonly scopes;
136
- /** In-flight scope drops remain here after records leave `scopes`, so root disposal can await quiescence. */
105
+ /** Stable per-id sources retained for the Client root lifetime, including across generation replacement. */
106
+ private readonly retainObservers;
137
107
  private readonly scopeDrops;
138
- /**
139
- * The staged session id — follows `list.current` exactly, holding its last
140
- * defined value across masked gaps (a transiently absent selection blanks
141
- * `current` without moving the stage, so reconnect re-pulls and removals
142
- * keep the staged scope's frozen view alive until the stage moves on).
143
- */
144
- private watched;
145
- /** Removed-while-staged sessions whose teardown waits for the stage to move away. */
146
- private readonly deferredRemovals;
108
+ private closed;
147
109
  /**
148
110
  * @param ctx - client root context (scope fibers mount under it).
149
111
  * @param remote - generated Remote namespaces shared with every Session.
150
112
  */
151
113
  constructor(rootCtx: Context, remote: SessionRemotes);
152
- /**
153
- * Select a listed or retained catalog-addressed session as current.
154
- * @param id - listed or addressed session id.
155
- */
156
- open(id: SessionId): void;
157
- /**
158
- * Open a healthy catalog child through its direct-parent address.
159
- * @param address - catalog-derived parent and child ids.
160
- */
161
- openSubagent(address: SubagentAddress): void;
114
+ retain(target: SessionTarget, options: SessionRetainOptions): SessionReference;
115
+ using<T>(target: SessionTarget, options: SessionRetainOptions, operation: (reference: SessionReference) => T | Promise<T>): Promise<T>;
116
+ retainInfo(id: SessionId): ObservableSnapshot<SessionRetainInfo>;
162
117
  /**
163
118
  * Resolve an already discovered direct-parent address without opening it.
164
119
  * Feature plugins use this to avoid Agent-bound RPCs in persisted child views.
@@ -177,14 +132,6 @@ export declare class ClientSessions implements ISessions {
177
132
  * @param parentSessionId - catalog owner.
178
133
  */
179
134
  refreshSubagents(parentSessionId: SessionId): Promise<void>;
180
- /**
181
- * Clear the current selection so the layout shows the no-session empty
182
- * state (new-session affordance and the workspace preselection flow).
183
- * Wipes the persisted selection too — a reload stays on empty until the
184
- * user opens or starts a session. The staged scope keeps its frozen view
185
- * per the masked-gap contract until the next open() moves the stage.
186
- */
187
- clear(): void;
188
135
  /**
189
136
  * Refresh the real Session baseline, reusing an in-flight pull.
190
137
  * @returns completion of the current or newly started baseline pull.
@@ -234,12 +181,8 @@ export declare class ClientSessions implements ISessions {
234
181
  /** Rebuild the Session baseline and every opened window after connection. */
235
182
  handleConnected(): void;
236
183
  /**
237
- * Create a session on the host. Resolution guarantee: by the time the
238
- * promise resolves, the created session is in the list store and
239
- * {@link ClientSessions.binding} resolves it — callers (New Session
240
- * draft hand-off) may address the scope synchronously, without waiting a
241
- * notifier flush. The synchronous projection below makes this structural
242
- * rather than an accident of microtask ordering.
184
+ * Create a Host Session and publish its catalog row before resolving.
185
+ * Callers retain the returned identity before borrowing its binding.
243
186
  * @param opts - target workspace or directory and an optional preallocated id.
244
187
  * @returns the new session id.
245
188
  * @throws {SessionCreateError} with the requested id.
@@ -250,9 +193,8 @@ export declare class ClientSessions implements ISessions {
250
193
  sessionId?: SessionId;
251
194
  }): Promise<SessionId>;
252
195
  /**
253
- * Fork a session from a completed-turn prefix of the source (same
254
- * synchronous-addressability guarantee as {@link ClientSessions.create}:
255
- * on resolution the child is in the list store and open() can target it).
196
+ * Fork a Session from a completed-turn prefix of the source and publish
197
+ * the child in the catalog before resolving.
256
198
  * @param opts - source session id, the optional event seq anchoring the
257
199
  * cut (the boundary is the first turn/end at or after it; an in-log
258
200
  * anchor in an open turn is unavailable rather than clipped backward),
@@ -270,20 +212,17 @@ export declare class ClientSessions implements ISessions {
270
212
  increaseTitle?: boolean;
271
213
  }): Promise<SessionId>;
272
214
  /**
273
- * Resolve an Agent-scoped context view (use-and-discard).
215
+ * Borrow an already-retained Agent-scoped Context.
274
216
  * @param id - session id (the agent identity — 1:1 same axis).
275
- * @returns scoped ctx, or undefined for a session neither listed nor already scoped.
217
+ * @returns the scoped Context, or undefined without a retained generation.
276
218
  */
277
219
  scope(id: SessionId): AgentContext | undefined;
278
220
  /**
279
- * Materialize the Agent scope named by a validated Host Remote Event.
280
- * The first successful Session-list baseline becomes authoritative for its
281
- * lifetime; until then, transport streams may address the scope in either
282
- * arrival order.
283
- * @param id - Host-projected Agent identity (the matching Session id).
284
- * @returns the identity-stable Agent Context.
221
+ * Retain a validated Gateway identity synchronously, without history or catalog I/O.
222
+ * @param id - Host-projected Session identity, possibly not yet catalogued.
223
+ * @returns a Gateway-source reference owned by the invocation.
285
224
  */
286
- resolveAgentScope(id: SessionId): AgentContext;
225
+ retainAgentScope(id: SessionId): SessionReference;
287
226
  /**
288
227
  * Read the Agent scope tag off a context. Service-method boundary: fetch
289
228
  * bundles must reach scope resolution through ctx.sessions — a cross-bundle
@@ -300,50 +239,26 @@ export declare class ClientSessions implements ISessions {
300
239
  * `agent.session`). Same service-method boundary as
301
240
  * {@link ClientSessions.scopeOf}.
302
241
  * @param ctx - an Agent-scoped context.
303
- * @returns the session face, or undefined when the ctx is untagged or its scope was pruned.
242
+ * @returns the matching live Session, or undefined for an untagged or ended generation.
304
243
  */
305
244
  sessionOf(ctx: Context): SessionFace | undefined;
306
245
  /**
307
- * Resolve the stable session binding (scope-addressed assembly feed). Pure
308
- * resolution — no staging, no window side effects.
309
- * @param id - session id.
310
- * @returns binding, or undefined for a session neither listed nor already scoped.
246
+ * Borrow an already-retained binding without extending its lifetime.
247
+ * @param id - Session identity.
248
+ * @returns the live binding, or undefined without a retained generation.
311
249
  */
312
250
  binding(id: SessionId): SessionBinding | undefined;
313
- /**
314
- * Move the stage to the list's current session: sweep teardowns deferred
315
- * behind the previous occupant and pull the new occupant's history window.
316
- * Staging IS the open signal — the window opens ⟺ the session is on stage
317
- * — and open() is idempotent (an in-flight or completed open no-ops; a
318
- * failed one retries the next time current is touched).
319
- */
320
- private followCurrent;
321
- /**
322
- * Lazily mint the scope + binding for an eligible session. Eligibility and
323
- * prune share one predicate: listed on the host or selected
324
- * through a retained subagent address. Breadcrumb-only ancestors remain
325
- * summary data and do not keep scopes alive.
326
- */
327
- private resolve;
251
+ private retainScope;
252
+ private retentionSnapshot;
253
+ private publishRetention;
254
+ private retireScope;
328
255
  /** Materialize one scope after its caller establishes that the id may be addressed. */
329
256
  private materializeScope;
330
- /** The one aliveness predicate shared by scope mint and prune: host-listed or currently addressed. */
331
- private eligible;
332
257
  /** Project the manager's list snapshot into the store (title derivation is display-only). */
333
258
  private projectList;
334
- /** Tear down scope + instance for no-longer-eligible sessions off stage; the staged one defers until the stage moves. */
335
- private pruneScopes;
336
259
  private startScopeDrop;
337
260
  private drainScopeDrops;
338
- /**
339
- * One teardown for the whole per-session axis: the scope
340
- * fiber (cascading every actx-registered effect: input shell, slash
341
- * controller, popup, plugin stores, listeners), the session-keyed slot
342
- * registrations and the Session instance itself — the host session log is the
343
- * durable truth, a reopen lazily rebuilds and backfills via open().
344
- */
261
+ /** Await the already-withdrawn Session and scoped cleanup to quiescence. */
345
262
  private dropScope;
346
- /** Run deferred teardowns whose session is no longer staged (called when the stage moves). */
347
- private sweepDeferred;
348
263
  }
349
264
  //# sourceMappingURL=service.d.ts.map