dsh-zen-remote 2.4.0 → 2.4.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.
package/src/share-ops.ts CHANGED
@@ -32,11 +32,92 @@ export interface AgentStatusLike {
32
32
 
33
33
  /** The slice of a DSH session header the share decision reads. Field names
34
34
  * per `validateSessionHeader`: `id` (matches the session id), `origin`
35
- * (only legal value `'subagent'`), `parentSession` (a string when set). */
35
+ * (only legal value `'subagent'`), `parentSession` (a string when set),
36
+ * `isSeeded` (true on a fork). */
36
37
  export interface CreatedSessionHeaderLike {
37
38
  id?: unknown
38
39
  origin?: unknown
39
40
  parentSession?: unknown
41
+ isSeeded?: unknown
42
+ }
43
+
44
+ /** The slice of a DSH Session read to detect an unused blank placeholder
45
+ * reclaimed by `session/create` (`dsh-api-session-controller`'s `claim`
46
+ * resumes persisted blank sessions with `source: 'resume'`). */
47
+ export interface CreatedSessionLike {
48
+ header?: CreatedSessionHeaderLike | null | undefined
49
+ snapshotEvents?: (() => readonly { type?: unknown }[]) | undefined
50
+ }
51
+
52
+ /** The slice of `ctx.agents.turnBoundaryOf(session)` (DSH 0.2+ projection
53
+ * reader, the non-deprecated replacement for `snapshotEvents()`). */
54
+ export interface TurnBoundaryLike {
55
+ openTurnStartSeq?: unknown
56
+ lastTurn?: unknown
57
+ }
58
+
59
+ /**
60
+ * Whether `session` is an unseeded, non-subagent blank session (zero turns
61
+ * ever started). DSH's `createInWorkspace` reuses persisted blank sessions
62
+ * via `session/create` → `agents.resume` (`source: 'resume'`); judging
63
+ * blankness lets `agent/created` auto-share a reclaimed blank placeholder
64
+ * while keeping established conversations closed across reopens.
65
+ *
66
+ * Prefers `turnBoundaryOf(session)` (DSH's `sessionProjections`-backed
67
+ * `ctx.agents.turnBoundaryOf`, the predicate `dsh-api-session-controller`'s
68
+ * own `isBlank` uses: `openTurnStartSeq === null && lastTurn === 0`); falls
69
+ * back to `session.snapshotEvents()` when `turnBoundaryOf` is absent (DSH
70
+ * 0.1.7 compatibility or unit-test mocks; ponytail: remove `snapshotEvents`
71
+ * fallback once 0.1.7 support is dropped and `@deepseek-ai/dsh-session`
72
+ * retires synchronous event-log reads).
73
+ */
74
+ export function isBlankSession(
75
+ session: CreatedSessionLike | undefined | null,
76
+ turnBoundaryOf?: ((session: CreatedSessionLike) => TurnBoundaryLike | undefined) | undefined,
77
+ ): boolean {
78
+ if (session === null || typeof session !== 'object') return false
79
+ const header = session.header
80
+ if (header === null || typeof header !== 'object') return false
81
+ if (header.origin === 'subagent' || header.isSeeded === true) return false
82
+ if (typeof header.id !== 'string' || header.id === '') return false
83
+ if (typeof turnBoundaryOf === 'function') {
84
+ try {
85
+ const boundary = turnBoundaryOf(session)
86
+ if (boundary !== null && typeof boundary === 'object') {
87
+ return boundary.openTurnStartSeq === null && boundary.lastTurn === 0
88
+ }
89
+ } catch {
90
+ // Fall through to snapshotEvents when the projection reader is unavailable.
91
+ }
92
+ }
93
+ if (typeof session.snapshotEvents !== 'function') return false
94
+ try {
95
+ const events = session.snapshotEvents()
96
+ if (!Array.isArray(events)) return false
97
+ return !events.some((event) => event !== null && typeof event === 'object' && event.type === 'turn/start')
98
+ } catch {
99
+ return false
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Whether `event` is the very first `turn/start` (`turn === 1`) of an
105
+ * unseeded non-subagent session. Covers the in-memory `reuseLive` path of
106
+ * `session/create`, where a live blank session (created before
107
+ * `autoShareNewSessions` was enabled, or after its idle window expired in
108
+ * memory) is reused without emitting `agent/created`.
109
+ */
110
+ export function isFirstTurnStart(
111
+ session: { header?: CreatedSessionHeaderLike | null | undefined } | undefined | null,
112
+ event: { type?: unknown; data?: unknown } | undefined | null,
113
+ ): boolean {
114
+ if (event === null || typeof event !== 'object' || event.type !== 'turn/start') return false
115
+ const data = event.data as { turn?: unknown } | null | undefined
116
+ if (data === null || typeof data !== 'object' || data.turn !== 1) return false
117
+ const header = session?.header
118
+ if (header === null || typeof header !== 'object') return false
119
+ if (header.origin === 'subagent' || header.isSeeded === true) return false
120
+ return typeof header.id === 'string' && header.id !== ''
40
121
  }
41
122
 
42
123
  /**