@deepseek-ai/dsh-api-session-controller 0.1.6-alpha.1 → 0.1.7-alpha.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 (44) hide show
  1. package/README.i18n.yaml +2 -2
  2. package/README.md +42 -7
  3. package/README.zh.md +42 -7
  4. package/lib/client.js +1037 -992
  5. package/lib/index.js +314 -183
  6. package/lib/typert.host.js +539 -331
  7. package/lib/typert.remote-client.d.ts +10 -5
  8. package/lib/typert.remote-client.js +374 -264
  9. package/lib/types/agent.d.ts +1 -1
  10. package/lib/types/agent.js +8 -1
  11. package/lib/types/archived-session-gate.d.ts +30 -0
  12. package/lib/types/archived-session-gate.js +52 -0
  13. package/lib/types/client/contract/session.d.ts +2 -0
  14. package/lib/types/client/contract/sessions.d.ts +65 -35
  15. package/lib/types/client/contract/snapshot.d.ts +0 -14
  16. package/lib/types/client/index.d.ts +12 -3
  17. package/lib/types/client/index.js +16 -5
  18. package/lib/types/client/scope.d.ts +13 -3
  19. package/lib/types/client/scope.js +15 -22
  20. package/lib/types/client/sessions/lineage.d.ts +5 -5
  21. package/lib/types/client/sessions/lineage.js +3 -4
  22. package/lib/types/client/sessions/manager.d.ts +91 -105
  23. package/lib/types/client/sessions/manager.js +307 -434
  24. package/lib/types/client/sessions/projection-store.d.ts +34 -21
  25. package/lib/types/client/sessions/projection-store.js +48 -24
  26. package/lib/types/client/sessions/remotes.d.ts +1 -2
  27. package/lib/types/client/sessions/service.d.ts +53 -150
  28. package/lib/types/client/sessions/service.js +267 -264
  29. package/lib/types/client/sessions/session.d.ts +24 -35
  30. package/lib/types/client/sessions/session.js +131 -73
  31. package/lib/types/commands.d.ts +6 -4
  32. package/lib/types/commands.js +82 -40
  33. package/lib/types/control.d.ts +2 -4
  34. package/lib/types/control.js +2 -84
  35. package/lib/types/history.js +1 -1
  36. package/lib/types/index.d.ts +34 -7
  37. package/lib/types/index.js +118 -14
  38. package/lib/types/list.js +24 -15
  39. package/lib/types/skill-catalog.js +60 -50
  40. package/lib/types/types.d.ts +40 -40
  41. package/lib/types/types.js +0 -1
  42. package/package.json +71 -76
  43. package/lib/types/client/sessions/queue-mirror.d.ts +0 -26
  44. package/lib/types/client/sessions/queue-mirror.js +0 -61
@@ -1,10 +1,14 @@
1
1
  /**
2
2
  * Generic per-session projection value store (push model; see the
3
3
  * session-projection subsystem page, docs/subsystems/session-projection.md):
4
- * the host is the only computation site; the client holds finished
5
- * whole values per key — `key → { value, seq }` — seeded by a follow opening
6
- * baseline and updated by Session Controller `projection` frames,
7
- * under the single rule **higher seq wins**. No client-side domain folding
4
+ * the host is the only computation site; the client holds finished whole
5
+ * values per key in one of two row kinds. A `sequenced` row
6
+ * (`{ value, seq }`) comes from the connected Host — a follow opening
7
+ * baseline, a Session Controller `projection` frame, a list block the Host
8
+ * computed for an attached Session — and merges under **higher seq wins**
9
+ * against other sequenced rows. A `cached` row (`{ value }`) comes from the
10
+ * session list's view of the persisted checkpoint, carries no comparable
11
+ * seq, and yields to every sequenced write. No client-side domain folding
8
12
  * exists: a domain ships projection support with zero client code. Per-key
9
13
  * bare observable faces feed `useProjection` (ui-renderer binds them).
10
14
  */
@@ -38,10 +42,14 @@ export interface ProjectionsBaseline {
38
42
  }
39
43
  /**
40
44
  * One session's projection values. Framework semantics, uniform across every
41
- * key: a baseline seeds rows at its cut, a push frame updates one row, and in
42
- * both paths a lower-or-equal seq loses — a replayed frame cannot regress a
43
- * value, a stale baseline cannot overwrite a newer frame. A key the store has
44
- * never seen reads `undefined` (capability absent). Faces are identity-stable
45
+ * key. Sequenced writes (a baseline seeds rows at its cut, a push frame
46
+ * updates one row) compare seqs among themselves: a lower-or-equal seq within
47
+ * the Host generation loses, so a replayed frame cannot regress a value and a
48
+ * stale baseline cannot overwrite a newer frame. Cached writes (the session
49
+ * list's zero-I/O block) only fill keys no sequenced row holds, and a baseline
50
+ * discards every cached row before it seeds, regardless of seq: the connected
51
+ * Session is the truth and a cached value never outranks it. A key the store
52
+ * has never seen reads `undefined` (capability absent). Faces are identity-stable
45
53
  * per key (create-on-demand, cached) so the React side binds each exactly
46
54
  * once; the store-level channel (`subscribeAny`) serves coarse consumers (the
47
55
  * manager's list projection reads the `title` key).
@@ -87,22 +95,27 @@ export declare class ProjectionValueStore {
87
95
  */
88
96
  apply(key: string, value: unknown, seq: SessionSeqCursor): void;
89
97
  /**
90
- * Seed from a history tail page's projections block: every carried key
91
- * lands under the same seq rule as frames; a key the block omits is
92
- * capability-absent as of the cut — its row clears unless a newer frame
93
- * already superseded the cut (a stale baseline can neither overwrite nor
94
- * clear newer values).
95
- * @param baseline - the response's projections block.
98
+ * Fill keys from a session-list block the Host labeled `cached`: a zero-I/O
99
+ * view of the persisted checkpoint. A cached value lands only where no
100
+ * sequenced row exists: a connected Session has already answered for such
101
+ * a key, and the list's view of the persisted checkpoint cannot be newer
102
+ * than it.
103
+ * @param values - whole values by key viewed from the persisted checkpoint.
96
104
  */
97
- seed(baseline: ProjectionsBaseline): void;
105
+ applyCached(values: Readonly<Record<string, unknown>>): void;
98
106
  /**
99
- * Drop rows beyond a replacement control baseline. Such rows describe
100
- * process state the Host lost before persisting it and would otherwise
101
- * outrank recomputed lower-seq values forever. The caller seeds the new
102
- * baseline immediately afterward.
103
- * @param lastSeq - highest durable sequence reflected by the baseline.
107
+ * Seed from a history tail page's projections block. Every cached row is
108
+ * discarded first, regardless of seq: the block comes from the connected
109
+ * Session, and a value viewed from the persisted checkpoint never outranks
110
+ * it. Then every carried key lands under the same seq rule as frames, and a
111
+ * key the block omits is capability-absent as of the cut — its row clears
112
+ * unless a newer frame already superseded the cut (a stale baseline can
113
+ * neither overwrite nor clear newer sequenced values).
114
+ * @param baseline - the response's projections block.
104
115
  */
105
- truncate(lastSeq: SessionSeqCursor): void;
116
+ seed(baseline: ProjectionsBaseline): void;
117
+ /** Discard one Host generation's values and watermarks while preserving subscribed faces. */
118
+ clear(): void;
106
119
  private changed;
107
120
  private channel;
108
121
  }
@@ -1,10 +1,14 @@
1
1
  import { Notifier } from "./notifier.js";
2
2
  /**
3
3
  * One session's projection values. Framework semantics, uniform across every
4
- * key: a baseline seeds rows at its cut, a push frame updates one row, and in
5
- * both paths a lower-or-equal seq loses — a replayed frame cannot regress a
6
- * value, a stale baseline cannot overwrite a newer frame. A key the store has
7
- * never seen reads `undefined` (capability absent). Faces are identity-stable
4
+ * key. Sequenced writes (a baseline seeds rows at its cut, a push frame
5
+ * updates one row) compare seqs among themselves: a lower-or-equal seq within
6
+ * the Host generation loses, so a replayed frame cannot regress a value and a
7
+ * stale baseline cannot overwrite a newer frame. Cached writes (the session
8
+ * list's zero-I/O block) only fill keys no sequenced row holds, and a baseline
9
+ * discards every cached row before it seeds, regardless of seq: the connected
10
+ * Session is the truth and a cached value never outranks it. A key the store
11
+ * has never seen reads `undefined` (capability absent). Faces are identity-stable
8
12
  * per key (create-on-demand, cached) so the React side binds each exactly
9
13
  * once; the store-level channel (`subscribeAny`) serves coarse consumers (the
10
14
  * manager's list projection reads the `title` key).
@@ -61,20 +65,46 @@ export class ProjectionValueStore {
61
65
  */
62
66
  apply(key, value, seq) {
63
67
  const row = this.rows.get(key);
64
- if (row !== undefined && seq <= row.seq)
65
- return; // higher seq wins; replays and stale frames drop
66
- this.rows.set(key, { value, seq });
68
+ // higher seq wins among sequenced rows; replays and stale frames drop. A
69
+ // cached row has no comparable seq and always yields.
70
+ if (row?.kind === 'sequenced' && seq <= row.seq)
71
+ return;
72
+ this.rows.set(key, { kind: 'sequenced', value, seq });
67
73
  this.changed(key);
68
74
  }
69
75
  /**
70
- * Seed from a history tail page's projections block: every carried key
71
- * lands under the same seq rule as frames; a key the block omits is
72
- * capability-absent as of the cut — its row clears unless a newer frame
73
- * already superseded the cut (a stale baseline can neither overwrite nor
74
- * clear newer values).
76
+ * Fill keys from a session-list block the Host labeled `cached`: a zero-I/O
77
+ * view of the persisted checkpoint. A cached value lands only where no
78
+ * sequenced row exists: a connected Session has already answered for such
79
+ * a key, and the list's view of the persisted checkpoint cannot be newer
80
+ * than it.
81
+ * @param values - whole values by key viewed from the persisted checkpoint.
82
+ */
83
+ applyCached(values) {
84
+ for (const key of Object.keys(values)) {
85
+ if (this.rows.get(key)?.kind === 'sequenced')
86
+ continue;
87
+ this.rows.set(key, { kind: 'cached', value: values[key] });
88
+ this.changed(key);
89
+ }
90
+ }
91
+ /**
92
+ * Seed from a history tail page's projections block. Every cached row is
93
+ * discarded first, regardless of seq: the block comes from the connected
94
+ * Session, and a value viewed from the persisted checkpoint never outranks
95
+ * it. Then every carried key lands under the same seq rule as frames, and a
96
+ * key the block omits is capability-absent as of the cut — its row clears
97
+ * unless a newer frame already superseded the cut (a stale baseline can
98
+ * neither overwrite nor clear newer sequenced values).
75
99
  * @param baseline - the response's projections block.
76
100
  */
77
101
  seed(baseline) {
102
+ for (const [key, row] of this.rows) {
103
+ if (row.kind !== 'cached')
104
+ continue;
105
+ this.rows.delete(key);
106
+ this.changed(key);
107
+ }
78
108
  // Erased walk: the framework crosses the open key space; per-key typing
79
109
  // is re-established at the consumer (useProjection's map lookup).
80
110
  const values = baseline.values;
@@ -83,23 +113,17 @@ export class ProjectionValueStore {
83
113
  for (const [key, row] of this.rows) {
84
114
  if (Object.hasOwn(values, key))
85
115
  continue;
86
- if (row.seq > baseline.asOfSeq)
116
+ // Every cached row was deleted above; the kind test only narrows the
117
+ // type so `row.seq` is readable.
118
+ if (row.kind === 'sequenced' && row.seq > baseline.asOfSeq)
87
119
  continue;
88
120
  this.rows.delete(key);
89
121
  this.changed(key);
90
122
  }
91
123
  }
92
- /**
93
- * Drop rows beyond a replacement control baseline. Such rows describe
94
- * process state the Host lost before persisting it and would otherwise
95
- * outrank recomputed lower-seq values forever. The caller seeds the new
96
- * baseline immediately afterward.
97
- * @param lastSeq - highest durable sequence reflected by the baseline.
98
- */
99
- truncate(lastSeq) {
100
- for (const [key, row] of this.rows) {
101
- if (row.seq <= lastSeq)
102
- continue;
124
+ /** Discard one Host generation's values and watermarks while preserving subscribed faces. */
125
+ clear() {
126
+ for (const key of this.rows.keys()) {
103
127
  this.rows.delete(key);
104
128
  this.changed(key);
105
129
  }
@@ -7,7 +7,7 @@
7
7
  import type { ClientRemote } from '@deepseek-ai/dsh-api-gateway/client';
8
8
  import type { CommandSubmitAttachment } from '@deepseek-ai/dsh-commands/types';
9
9
  import type { SessionId } from '@deepseek-ai/dsh-session/types';
10
- import type { SubagentCatalog, SubagentInterruptReceipt, SubagentPromptReceipt, SubagentPromptRequest } from '@deepseek-ai/dsh-subagent/client';
10
+ import type { SubagentInterruptReceipt, SubagentPromptReceipt, SubagentPromptRequest } from '@deepseek-ai/dsh-subagent/client';
11
11
  import type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol';
12
12
  import type { SessionRemote } from '../transport.ts';
13
13
  /** Narrow Commands namespace consumed by a Client Session. */
@@ -16,7 +16,6 @@ export interface SessionCommandsRemote {
16
16
  }
17
17
  /** Narrow subagent namespace consumed by a Client Session and its manager. */
18
18
  export interface SessionSubagentsRemote {
19
- list(parentSessionId: SessionId, signal?: AbortSignal): Promise<RemoteResult<SubagentCatalog>>;
20
19
  prompt(request: SubagentPromptRequest, signal?: AbortSignal): Promise<RemoteResult<SubagentPromptReceipt>>;
21
20
  interruptByParent(childSessionId: SessionId, parentSessionId: SessionId, mode: 'continuable'): Promise<RemoteResult<SubagentInterruptReceipt>>;
22
21
  }
@@ -1,33 +1,17 @@
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
- import type { SessionJob as JobView } from '../../types.ts';
22
6
  import type { SessionProjectionMap } from '@deepseek-ai/dsh-session-projection/types';
23
- import { type SnapshotStore } from '@deepseek-ai/dsh-client-store';
7
+ import { type ObservableSnapshot, type SnapshotStore } from '@deepseek-ai/dsh-client-store';
24
8
  import type { RemoteFailure, RemoteResult } from '@deepseek-ai/dsh-typert-protocol';
25
9
  import type { SessionEventSource } from '../contract/events.ts';
26
10
  import type { SessionFace } from '../contract/session.ts';
27
- import type { AgentContext, ISessions } from '../contract/sessions.ts';
11
+ import type { AgentContext, ISessions, SessionReference, SessionRetainInfo, SessionRetainOptions, SessionTarget } from '../contract/sessions.ts';
28
12
  import { SessionManager } from './manager.ts';
29
13
  import type { SessionRemotes } from './remotes.ts';
30
- import type { SessionListPhase, SessionSearchResultItem, SubagentCatalogSnapshot } from './manager.ts';
14
+ import type { SessionListPhase, SessionSearchResultItem, SessionProjectionSnapshot } from './manager.ts';
31
15
  /** Session list row projected from the host list RPC plus live stream increments. */
32
16
  export interface SessionSummary {
33
17
  id: SessionId;
@@ -39,43 +23,32 @@ export interface SessionSummary {
39
23
  parentId?: SessionId;
40
24
  /** Coarse durable origin for navigation filtering; not a continuation capability. */
41
25
  origin?: 'subagent';
26
+ /** Host running state for `ids` members; a display fallback for other rows. */
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
- * Empty-log bit (host summary derivation mirror). New Session reuses a blank
47
- * one targeting the same workspace. Filtering stays with the consumer: the
48
- * store carries every row, while the Workspace browser shows only the
49
- * selected blank entry.
31
+ * New Session presentation and reuse eligibility, derived from the Host
32
+ * summary, `sessionListMetadata`, and client acceptance/running observations.
33
+ * New Session reuses a blank one targeting the same workspace. Filtering
34
+ * stays with the consumer: the store carries every row, while the Workspace
35
+ * browser shows only the selected blank entry.
50
36
  */
51
37
  blank: boolean;
52
38
  updatedAt: number;
53
39
  /** Current host-computed projection values retained by the object layer. */
54
40
  projectionValues?: Readonly<Partial<SessionProjectionMap>>;
55
41
  }
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
- */
42
+ /** Catalog metadata and local source counts; catalog membership owns no Client generation. */
61
43
  export interface SessionListState {
62
- /** Host-list order; addressed breadcrumb-only rows are excluded. */
44
+ /** Host list order; every id has a matching byId row in the same snapshot. */
63
45
  ids: SessionId[];
64
- /** Host rows plus the current addressed subagent route used by navigation. */
46
+ /** Host/catalog rows plus retained subagent fallbacks; only `ids` expresses Host-list membership. */
65
47
  byId: Record<SessionId, SessionSummary>;
66
- current: SessionId | undefined;
67
48
  /** Arrival lifecycle projected 1:1 from the manager snapshot (see SessionListPhase): empty-with-ready means "truly no sessions". */
68
49
  phase: SessionListPhase;
69
- /** Direct durable catalogs keyed by their selected parent address. */
70
- subagentsByParent: Readonly<Record<SessionId, SubagentCatalogSnapshot>>;
71
- /**
72
- * Background jobs each session can see, mirrored last-wins from Session
73
- * Controller's control baseline and `jobs` frames. A missing key is an empty
74
- * set, so consumers read absence rather than a sentinel.
75
- */
76
- jobsBySession: Readonly<Record<SessionId, readonly JobView[]>>;
77
- /** Current session's catalog-derived address, absent on ordinary navigation. */
78
- currentAddress: SubagentAddress | undefined;
50
+ /** Shared projection values and explicit-read state, including unopened Sessions. */
51
+ projectionsBySession: Readonly<Record<SessionId, SessionProjectionSnapshot>>;
79
52
  }
80
53
  /** Structured session-create failure. */
81
54
  export declare class SessionCreateError extends Error {
@@ -109,7 +82,7 @@ export interface SessionBinding {
109
82
  readonly ctx: AgentContext;
110
83
  }
111
84
  export { scopeOf } from '../scope.ts';
112
- /** Root sessions service: list store, current selection, object-layer manager, scope tree, bindings, and breadcrumb routes. */
85
+ /** Host catalog and local reference allocator; view selection remains outside the Controller. */
113
86
  export declare class ClientSessions implements ISessions {
114
87
  private readonly rootCtx;
115
88
  /**
@@ -119,72 +92,35 @@ export declare class ClientSessions implements ISessions {
119
92
  * reports the same number.
120
93
  */
121
94
  readonly searchResultLimit = 20;
122
- /** List snapshot store (list RPC + host stream increments; re-pulled on reconnect) — the useSessions standard feed, current included. */
95
+ /** Catalog metadata and local reference-source projection. */
123
96
  readonly list: SnapshotStore<SessionListState>;
124
97
  /** The object-layer instance cluster and frame dispatch entry. */
125
98
  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
99
  private readonly scopes;
136
- /** In-flight scope drops remain here after records leave `scopes`, so root disposal can await quiescence. */
100
+ /** Stable per-id sources retained for the Client root lifetime, including across generation replacement. */
101
+ private readonly retainObservers;
137
102
  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;
103
+ private closed;
147
104
  /**
148
105
  * @param ctx - client root context (scope fibers mount under it).
149
106
  * @param remote - generated Remote namespaces shared with every Session.
150
107
  */
151
108
  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;
109
+ retain(target: SessionTarget, options: SessionRetainOptions): SessionReference;
110
+ using<T>(target: SessionTarget, options: SessionRetainOptions, operation: (reference: SessionReference) => T | Promise<T>): Promise<T>;
111
+ retainInfo(id: SessionId): ObservableSnapshot<SessionRetainInfo>;
162
112
  /**
163
113
  * Resolve an already discovered direct-parent address without opening it.
164
114
  * Feature plugins use this to avoid Agent-bound RPCs in persisted child views.
165
115
  * @param id - possible addressed child id.
166
- * @returns The retained address, when present.
116
+ * @returns A retained or loaded-catalog address, without retaining a new selection or scope.
167
117
  */
168
118
  subagentAddress(id: SessionId): SubagentAddress | undefined;
169
119
  /**
170
- * Inform the Session Controller whether a catalog menu is consuming membership updates.
171
- * @param parentSessionId - selected parent.
172
- * @param open - menu state.
120
+ * Load all Session projections once per connection; retry an unsuccessful initial read.
121
+ * @param sessionId - Session to inspect without opening its conversation.
173
122
  */
174
- setSubagentCatalogOpen(parentSessionId: SessionId, open: boolean): void;
175
- /**
176
- * Refresh one direct-child catalog.
177
- * @param parentSessionId - catalog owner.
178
- */
179
- 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;
123
+ refreshProjections(sessionId: SessionId): Promise<void>;
188
124
  /**
189
125
  * Refresh the real Session baseline, reusing an in-flight pull.
190
126
  * @returns completion of the current or newly started baseline pull.
@@ -234,12 +170,8 @@ export declare class ClientSessions implements ISessions {
234
170
  /** Rebuild the Session baseline and every opened window after connection. */
235
171
  handleConnected(): void;
236
172
  /**
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.
173
+ * Create a Host Session and publish its catalog row before resolving.
174
+ * Callers retain the returned identity before borrowing its binding.
243
175
  * @param opts - target workspace or directory and an optional preallocated id.
244
176
  * @returns the new session id.
245
177
  * @throws {SessionCreateError} with the requested id.
@@ -250,16 +182,14 @@ export declare class ClientSessions implements ISessions {
250
182
  sessionId?: SessionId;
251
183
  }): Promise<SessionId>;
252
184
  /**
253
- * Fork a session from a completed-turn prefix of the source (same
185
+ * Fork a session from an exact inclusive prefix of the source (same
254
186
  * synchronous-addressability guarantee as {@link ClientSessions.create}:
255
- * on resolution the child is in the list store and open() can target it).
256
- * @param opts - source session id, the optional event seq anchoring the
257
- * cut (the boundary is the first turn/end at or after it; an in-log
258
- * anchor in an open turn is unavailable rather than clipped backward),
259
- * and whether to increment an inherited durable title before resolving.
260
- * A fractional anchor floors to a real event seq: the frozen nodes of an
261
- * interrupted turn carry flow-ordering seqs between two events, and the
262
- * wire takes integers only.
187
+ * on resolution the child is catalogued and may be explicitly retained).
188
+ * @param opts - source session id, the optional exact inclusive boundary
189
+ * seq (a real event seq the caller already knows; a cut inside an open
190
+ * turn is balanced Host-side with synthetic closers, and omission selects
191
+ * the latest completed-turn prefix), and whether to increment an
192
+ * inherited durable title before resolving.
263
193
  * @returns the child session id.
264
194
  * @throws {SessionForkError} with the source id.
265
195
  * @throws {Error} when a requested child-title rename fails after creation.
@@ -270,20 +200,17 @@ export declare class ClientSessions implements ISessions {
270
200
  increaseTitle?: boolean;
271
201
  }): Promise<SessionId>;
272
202
  /**
273
- * Resolve an Agent-scoped context view (use-and-discard).
203
+ * Borrow an already-retained Agent-scoped Context.
274
204
  * @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.
205
+ * @returns the scoped Context, or undefined without a retained generation.
276
206
  */
277
207
  scope(id: SessionId): AgentContext | undefined;
278
208
  /**
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.
209
+ * Retain a validated Gateway identity synchronously, without history or catalog I/O.
210
+ * @param id - Host-projected Session identity, possibly not yet catalogued.
211
+ * @returns a Gateway-source reference owned by the invocation.
285
212
  */
286
- resolveAgentScope(id: SessionId): AgentContext;
213
+ retainAgentScope(id: SessionId): SessionReference;
287
214
  /**
288
215
  * Read the Agent scope tag off a context. Service-method boundary: fetch
289
216
  * bundles must reach scope resolution through ctx.sessions — a cross-bundle
@@ -300,50 +227,26 @@ export declare class ClientSessions implements ISessions {
300
227
  * `agent.session`). Same service-method boundary as
301
228
  * {@link ClientSessions.scopeOf}.
302
229
  * @param ctx - an Agent-scoped context.
303
- * @returns the session face, or undefined when the ctx is untagged or its scope was pruned.
230
+ * @returns the matching live Session, or undefined for an untagged or ended generation.
304
231
  */
305
232
  sessionOf(ctx: Context): SessionFace | undefined;
306
233
  /**
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.
234
+ * Borrow an already-retained binding without extending its lifetime.
235
+ * @param id - Session identity.
236
+ * @returns the live binding, or undefined without a retained generation.
311
237
  */
312
238
  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;
239
+ private retainScope;
240
+ private retentionSnapshot;
241
+ private publishRetention;
242
+ private retireScope;
328
243
  /** Materialize one scope after its caller establishes that the id may be addressed. */
329
244
  private materializeScope;
330
- /** The one aliveness predicate shared by scope mint and prune: host-listed or currently addressed. */
331
- private eligible;
332
245
  /** Project the manager's list snapshot into the store (title derivation is display-only). */
333
246
  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
247
  private startScopeDrop;
337
248
  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
- */
249
+ /** Await the already-withdrawn Session and scoped cleanup to quiescence. */
345
250
  private dropScope;
346
- /** Run deferred teardowns whose session is no longer staged (called when the stage moves). */
347
- private sweepDeferred;
348
251
  }
349
252
  //# sourceMappingURL=service.d.ts.map