dsh-rewind-plugin 0.7.5 → 0.9.0-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.
@@ -9,23 +9,22 @@
9
9
  * transcript) is untouched; only the model-visible surface is cut, so the
10
10
  * next request derives its context from the target message onward.
11
11
  *
12
- * Marker shape (v0.3.4+): the marker is an EMPTY `assistant/message` with a
13
- * replace `surfaceOp`, wrapped in its own step frame —
12
+ * Marker shape (v0.1.3/v2): the marker is an EMPTY `user/message` carrying a
13
+ * replace `surfaceOp` — a single event:
14
14
  *
15
- * step/start (turn, step) → assistant/message (marker) → step/end (turn, step)
15
+ * user/message (marker, empty content) → { surfaceOp {replace, start, end} }
16
16
  *
17
- * The step frame exists because the harness token-meter replays the log and
18
- * requires every `assistant/message` to sit inside an OPEN step whose
19
- * `(turn, step)` matches exactly (`token meter: assistant/message at seq N
20
- * has no matching step/start event` otherwise) — a bare marker appended while
21
- * idle (every step already closed) makes every later measure() call throw,
22
- * which disables /compact and automatic compaction. The frame's `turn` is the
23
- * LAST STARTED turn (`markerTurnOf`) and `step` is that turn's next unused
24
- * step number (`markerStepOf`): never a reused one, or the client
25
- * conversation assembler sees a duplicate `step/start` and rejects the log
26
- * with "received more than one start Match". The agent loop numbers its own
27
- * steps from memory (each new turn restarts at 1), so the ghost step can
28
- * never collide with a future real step.
17
+ * v2 reserves surface `replace` to a node that cites every shadowed seq via
18
+ * `sourceEventSeqs`, and `assistant/message` can no longer carry
19
+ * `sourceEventSeqs` (it now embeds its provider stream instead) — so the
20
+ * replacement node must be a `user/message`, exactly as /compact's checkpoint
21
+ * is. No ghost `step/start`…`step/end` frame is needed: the token-meter's
22
+ * step state machine ignores `user/message`, and the session invariant
23
+ * (`invariant.ts`) imposes no open-turn requirement on it, so the marker is
24
+ * appended while idle, outside any turn. The empty content means the marker
25
+ * carries no language; it sits at the surface tail as the model-visible
26
+ * "cut point" (an empty `user/message` derives to itself, so it remains a
27
+ * present-but-empty user turn in derived history).
29
28
  *
30
29
  * @module dsh-rewind/rewind
31
30
  */
@@ -85,48 +84,6 @@ export declare const CANDIDATE_PREVIEW_CHARS = 80;
85
84
  * still pass an explicit `limit`.
86
85
  */
87
86
  export declare const DEFAULT_CANDIDATE_LIMIT = 100;
88
- /**
89
- * Turn number for the rewind marker.
90
- *
91
- * The marker MUST NOT reuse the harness's next-turn number. The agent loop
92
- * numbers its next real turn `lastTurn/start + 1` (dsh-agent-loop), so a
93
- * marker numbered `maxTurn + 1` collides: the log then holds an
94
- * `assistant/message` (the marker) BEFORE the `turn/start` of the same turn,
95
- * and the client conversation-context builder rejects that ordering with
96
- * `conversation Context …:turn-tail… received an update before its start
97
- * Match` — history load fails and the whole conversation disappears from the
98
- * UI (reproduced across real sessions).
99
- *
100
- * The marker therefore reuses the LAST STARTED turn's number: the harness has
101
- * already consumed it (its next turn is strictly larger), so it can never be
102
- * reused by a future `turn/start`, and the marker lands as a harmless
103
- * trailing update on that turn's already-closed tail context (its `turn/end`
104
- * is already matched) — no new context, no reordering, nothing rendered, and
105
- * the empty content still derives to `null` in the model context.
106
- *
107
- * @param events - the full session event log.
108
- * @returns a turn number the harness can never reuse for a future `turn/start`.
109
- */
110
- export declare function markerTurnOf(events: readonly SessionEvent[]): number;
111
- /**
112
- * Step number for the rewind marker's ghost step frame.
113
- *
114
- * The marker's `assistant/message` must be wrapped in `step/start` …
115
- * `step/end` of the SAME `(turn, step)` so the harness token-meter replay
116
- * accepts it (see the module doc). The step number MUST be a step this turn
117
- * has never started: the client conversation assembler treats `step/start`
118
- * as the start of an `assistant-step` context keyed `turn:step`, so reusing
119
- * an already-started step number makes the log replay throw "received more
120
- * than one start Match" and the history disappears from the UI. Reusing
121
- * `lastStep + 1` is always safe: the harness numbers a turn's steps from
122
- * memory (each new turn restarts at 1), so the ghost step can never collide
123
- * with a future real step of this turn.
124
- *
125
- * @param events - the full session event log.
126
- * @param turn - the marker's turn (normally `markerTurnOf(events)`).
127
- * @returns the smallest step number this turn has never started (≥ 1).
128
- */
129
- export declare function markerStepOf(events: readonly SessionEvent[], turn: number): number;
130
87
  /** Narrow an event to a user message. */
131
88
  export declare function isUserMessageEvent(event: SessionEvent): event is SessionEvent<'user/message'>;
132
89
  /**
@@ -0,0 +1,57 @@
1
+ import { type SessionEvent } from '@deepseek-ai/dsh-session';
2
+ /** A complete frame's byte range within a buffer. */
3
+ export interface ZstdFrameRange {
4
+ start: number;
5
+ end: number;
6
+ }
7
+ /** Result of scanning a buffer for complete zstd frames. */
8
+ export interface ZstdFrameScan {
9
+ frames: ZstdFrameRange[];
10
+ /** Offset of an incomplete trailing frame, or undefined when the buffer is whole. */
11
+ tornStart?: number;
12
+ }
13
+ /**
14
+ * Scan a buffer for structurally complete Zstandard frames (mirrors DSH
15
+ * `scanZstdFrames`). A trailing incomplete frame is reported as `tornStart`
16
+ * and omitted from `frames`.
17
+ */
18
+ export declare function scanZstdFrames(buffer: Buffer): ZstdFrameScan;
19
+ /**
20
+ * Compress one independently decodable, checksummed Zstandard frame (mirrors DSH
21
+ * `compressZstdFrame`). Async so it runs on libuv's threadpool and does not
22
+ * block the event loop, letting a concurrency pool overlap compression across
23
+ * sessions.
24
+ */
25
+ export declare function compressZstdFrame(input: Buffer | string): Promise<Buffer>;
26
+ /** Decompress one complete Zstandard frame (validates its checksum). Async (threadpool). */
27
+ export declare function decompressZstdFrame(input: Buffer): Promise<Buffer>;
28
+ /** Decode a concatenated multi-frame zstd buffer to plaintext (async, threadpool). Frames are
29
+ * decoded in bounded parallel batches (a large log can have tens of thousands of frames). */
30
+ export declare function decodeZstd(buffer: Buffer): Promise<string>;
31
+ /** One complete session plaintext split into its header line and event body. */
32
+ export interface SplitSession {
33
+ /** The first line (a `type:'session'` record) WITHOUT its trailing newline. */
34
+ headerLine: string;
35
+ /** Every event row, newline-separated, after the header line. */
36
+ body: string;
37
+ }
38
+ /** Split a session plaintext into an independent header line and the event body. */
39
+ export declare function splitSession(plaintext: string): SplitSession;
40
+ /**
41
+ * Decode a JSONL event body into logical {@link SessionEvent}s. Layout-blind:
42
+ * packed chunk rows and per-line rows both decode; range-encoded provenance is
43
+ * expanded. This is the read-side counterpart that consumes the body that
44
+ * `sessionPersistence.readRaw(id)` produced.
45
+ */
46
+ export declare function decodeEventBody(body: string): SessionEvent[];
47
+ export interface EncodeOptions {
48
+ /** Pack delta-chunk runs into storage rows (lossless, ~60% smaller). Default true. */
49
+ readonly packChunks?: boolean;
50
+ }
51
+ /**
52
+ * Encode a header line + events into a 2-frame Zstandard buffer (mirrors DSH
53
+ * `encodePhysicalJsonl`): the header is its OWN frame, the body its own.
54
+ * @param headerLine - the header JSON text, no trailing newline.
55
+ * @param events - the repaired event list in log order.
56
+ */
57
+ export declare function encodeSessionLog(headerLine: string, events: readonly SessionEvent[], options?: EncodeOptions): Promise<Buffer>;
@@ -46,9 +46,9 @@ export declare const CleanupConfigSchema: z<CleanupConfig>;
46
46
  /**
47
47
  * Structural face of the settings scope the host needs for the policy: a
48
48
  * resolved read and a validated write. Kept local (never imports the settings
49
- * contract) so the host bundle links on both 0.1.1-rc.2 and 0.1.2-rc.1 — the
50
- * settings API drift (0.1.2 adds `mutate`, 0.1.1 does not) is confined to the
51
- * seam the host passes in, never to this module.
49
+ * contract) so the host bundle does not type-couple on the client settings
50
+ * API (0.1.2 adds `mutate`; it is unused here), and the seam the host passes
51
+ * in isolates the drift to this module.
52
52
  */
53
53
  export interface CleanupSettingsScope {
54
54
  /** The resolved policy: schema defaults, then base, then the user layer. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-rewind-plugin",
3
- "version": "0.7.5",
3
+ "version": "0.9.0-alpha.1",
4
4
  "description": "DSH 插件:真正便捷无感的同窗口内对话回退,从不新建分支;自带轻量工作区备份,可一并还原文件(完整 Claude Code /rewind 语义)。 · DSH plugin: genuinely effortless in-window conversation rewind — never forking a new session; ships a lightweight workspace backup that restores files together with the rewind (full Claude Code /rewind semantics).",
5
5
  "keywords": [
6
6
  "deepseek-harness",
@@ -52,7 +52,6 @@
52
52
  "client": {
53
53
  "inject": [
54
54
  "@deepseek-ai/dsh-client-locale",
55
- "@deepseek-ai/dsh-client-runtime",
56
55
  "@deepseek-ai/dsh-client-ui-commands",
57
56
  "@deepseek-ai/dsh-client-ui-conversation",
58
57
  "@deepseek-ai/dsh-client-ui-settings"
@@ -74,19 +73,18 @@
74
73
  "peerDependencies": {
75
74
  "@deepseek-ai/cordis": "^4.0.1",
76
75
  "@deepseek-ai/schemastery": "^3.18.1",
77
- "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
78
- "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6 || ^0.1.1-rc.2",
79
- "@deepseek-ai/dsh-client-ui-commands": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
80
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
81
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
82
- "@deepseek-ai/dsh-commands": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
83
- "@deepseek-ai/dsh-fs": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
84
- "@deepseek-ai/dsh-home-paths": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
85
- "@deepseek-ai/dsh-llm": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
86
- "@deepseek-ai/dsh-sandbox": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
87
- "@deepseek-ai/dsh-session": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
88
- "@deepseek-ai/dsh-settings": "^0.1.0-rc.8 || ^0.1.1-rc.2 || ^0.1.2-alpha.2",
89
- "@deepseek-ai/dsh-tools": "^0.1.0-rc.6 || ^0.1.1-rc.2 || ^0.1.2-alpha.2"
76
+ "@deepseek-ai/dsh-client-locale": "^0.1.2-rc.1",
77
+ "@deepseek-ai/dsh-client-ui-commands": "^0.1.2-rc.1",
78
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.2-rc.1",
79
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-rc.1",
80
+ "@deepseek-ai/dsh-commands": "^0.1.2-rc.1",
81
+ "@deepseek-ai/dsh-fs": "^0.1.2-rc.1",
82
+ "@deepseek-ai/dsh-home-paths": "^0.1.2-rc.1",
83
+ "@deepseek-ai/dsh-llm": "^0.1.2-rc.1",
84
+ "@deepseek-ai/dsh-sandbox": "^0.1.2-rc.1",
85
+ "@deepseek-ai/dsh-session": "^0.1.2-rc.1",
86
+ "@deepseek-ai/dsh-settings": "^0.1.2-rc.1",
87
+ "@deepseek-ai/dsh-tools": "^0.1.2-rc.1"
90
88
  },
91
89
  "peerDependenciesMeta": {
92
90
  "@deepseek-ai/cordis": {
@@ -98,9 +96,6 @@
98
96
  "@deepseek-ai/dsh-client-locale": {
99
97
  "optional": true
100
98
  },
101
- "@deepseek-ai/dsh-client-runtime": {
102
- "optional": true
103
- },
104
99
  "@deepseek-ai/dsh-client-ui-commands": {
105
100
  "optional": true
106
101
  },
@@ -138,29 +133,37 @@
138
133
  "devDependencies": {
139
134
  "@deepseek-ai/cordis": "^4.0.1",
140
135
  "@deepseek-ai/schemastery": "^3.18.1",
141
- "@deepseek-ai/dsh-agent": "^0.1.1-rc.2",
142
- "@deepseek-ai/dsh-client-locale": "^0.1.1-rc.2",
143
- "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
144
- "@deepseek-ai/dsh-client-ui-commands": "^0.1.1-rc.2",
145
- "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.1-rc.2",
146
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.1-rc.2",
147
- "@deepseek-ai/dsh-command-compact": "^0.1.1-rc.2",
148
- "@deepseek-ai/dsh-commands": "^0.1.1-rc.2",
149
- "@deepseek-ai/dsh-compaction": "^0.1.1-rc.2",
150
- "@deepseek-ai/dsh-compaction-basic": "^0.1.1-rc.2",
151
- "@deepseek-ai/dsh-fs": "^0.1.1-rc.2",
152
- "@deepseek-ai/dsh-goal": "^0.1.1-rc.2",
153
- "@deepseek-ai/dsh-home-paths": "^0.1.1-rc.2",
154
- "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
155
- "@deepseek-ai/dsh-plan-mode": "^0.1.1-rc.2",
156
- "@deepseek-ai/dsh-sandbox": "^0.1.1-rc.2",
157
- "@deepseek-ai/dsh-session": "^0.1.1-rc.2",
158
- "@deepseek-ai/dsh-session-projection": "^0.1.1-rc.2",
159
- "@deepseek-ai/dsh-session-stats": "^0.1.1-rc.2",
160
- "@deepseek-ai/dsh-session-title": "^0.1.1-rc.2",
161
- "@deepseek-ai/dsh-settings": "^0.1.1-rc.2",
162
- "@deepseek-ai/dsh-token-meter": "^0.1.1-rc.2",
163
- "@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
136
+ "@deepseek-ai/dsh-agent": "^0.1.2-rc.1",
137
+ "@deepseek-ai/dsh-attachment": "^0.1.2-rc.1",
138
+ "@deepseek-ai/dsh-client-locale": "^0.1.2-rc.1",
139
+ "@deepseek-ai/dsh-client-connection": "^0.1.2-rc.1",
140
+ "@deepseek-ai/dsh-client-store": "^0.1.2-rc.1",
141
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.2-rc.1",
142
+ "@deepseek-ai/dsh-api-session-controller": "^0.1.2-rc.1",
143
+ "@deepseek-ai/dsh-client-ui-conversation": "^0.1.2-rc.1",
144
+ "@deepseek-ai/dsh-scope": "^0.1.2-rc.1",
145
+ "@deepseek-ai/dsh-typert-protocol": "^0.1.2-rc.1",
146
+ "@deepseek-ai/dsh-user-questions": "^0.1.2-rc.1",
147
+ "@deepseek-ai/dsh-client-ui-commands": "^0.1.2-rc.1",
148
+ "@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.2-rc.1",
149
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-rc.1",
150
+ "@deepseek-ai/dsh-command-compact": "^0.1.2-rc.1",
151
+ "@deepseek-ai/dsh-commands": "^0.1.2-rc.1",
152
+ "@deepseek-ai/dsh-compaction": "^0.1.2-rc.1",
153
+ "@deepseek-ai/dsh-compaction-basic": "^0.1.2-rc.1",
154
+ "@deepseek-ai/dsh-fs": "^0.1.2-rc.1",
155
+ "@deepseek-ai/dsh-goal": "^0.1.2-rc.1",
156
+ "@deepseek-ai/dsh-home-paths": "^0.1.2-rc.1",
157
+ "@deepseek-ai/dsh-llm": "^0.1.2-rc.1",
158
+ "@deepseek-ai/dsh-plan-mode": "^0.1.2-rc.1",
159
+ "@deepseek-ai/dsh-sandbox": "^0.1.2-rc.1",
160
+ "@deepseek-ai/dsh-session": "^0.1.2-rc.1",
161
+ "@deepseek-ai/dsh-session-projection": "^0.1.2-rc.1",
162
+ "@deepseek-ai/dsh-session-stats": "^0.1.2-rc.1",
163
+ "@deepseek-ai/dsh-session-title": "^0.1.2-rc.1",
164
+ "@deepseek-ai/dsh-settings": "^0.1.2-rc.1",
165
+ "@deepseek-ai/dsh-token-meter": "^0.1.2-rc.1",
166
+ "@deepseek-ai/dsh-tools": "^0.1.2-rc.1",
164
167
  "@types/node": "^24.0.0",
165
168
  "@types/react": "^18.3.31",
166
169
  "@types/react-dom": "^18.3.7",
@@ -1,41 +0,0 @@
1
- # Troubleshooting
2
-
3
- [简体中文](troubleshooting.zh.md)
4
-
5
- ## History load failure: `…turn-tail… received an update before its start Match`
6
-
7
- Rewinds from `≤ 0.2.4` collided with the next real turn's `turn/start`, so reopening the session showed
8
-
9
- ```
10
- Failed to load history: conversation Context …:turn-tail… received an update before its start Match (internal)
11
- ```
12
-
13
- and the history vanished. Rewinds from `0.2.5` on no longer collide; already-corrupted sessions need an offline repair (the log is append-only). The repair tool (`dsh-rewind-repair`) is no longer shipped from v0.4.0 — install a pre-v0.4.0 release to get it (fully quit dsh web / host first, then):
14
-
15
- ```sh
16
- npm exec --yes --package=dsh-rewind-plugin@0.3.3 -- dsh-rewind-repair
17
- npm exec --yes --package=dsh-rewind-plugin@0.3.3 -- dsh-rewind-repair -- --dry-run # preview only
18
- ```
19
-
20
- It only rewrites the marker events' `data.turn` (seqs, order, and zstd frame structure intact) and backs up the original file before writing — safe to run repeatedly. From a source checkout of a pre-v0.4.0 tag: `node scripts/repair-markers.mjs` (identical flags).
21
-
22
- ## Known compatibility boundaries
23
-
24
- Behavioral notes — none of these is a crash — verified by the compatibility
25
- probe suites; the audit [audit.md](audit.md) is the source of truth and lists
26
- the probes that pin each one:
27
-
28
- - Session stats / telemetry do **not** roll back with a rewind.
29
- - Withdrawn messages stay **searchable and exported** (`/export` and full-text
30
- search read the raw log).
31
- - Session titles may **regenerate** (title derives from the current surface).
32
- - Files written by a **cancelled tool call** (write happened, no snapshot
33
- commit) cannot be restored by "conversation and code".
34
-
35
- **R-OPENSTEP** (harness-side, plugin does not guard): a session log carrying an
36
- *unclosed* `step/start` (a crash before the agent loop's `finally` closed the
37
- step) makes later step activity break token-meter replay, so `/compact` can
38
- fail after a rewind. Harness `0.1.1-rc.2` fixes the crash path on load
39
- (`interruptedTurnClosers`); a plugin-side up-front rejection was tried and
40
- **reverted** (`177ec14`, false positives on real logs). Deep analysis:
41
- [audit.md](audit.md) → R-OPENSTEP.
@@ -1,29 +0,0 @@
1
- # 故障修复
2
-
3
- [English](troubleshooting.md)
4
-
5
- ## 历史加载失败:`…turn-tail… received an update before its start Match`
6
-
7
- 0.2.4 及之前版本的回退与下一条真实回合的 `turn/start` 撞号,重开会话时历史整段消失。0.2.5 起的新回退不再产生该冲突;**已损坏的旧会话需离线修复**(日志是 append-only 的)。修复工具(`dsh-rewind-repair`)v0.4.0 起不再随包提供——安装 v0.4.0 之前的版本即可获取(先完全退出 dsh web / host,然后):
8
-
9
- ```sh
10
- npm exec --yes --package=dsh-rewind-plugin@0.3.3 -- dsh-rewind-repair
11
- npm exec --yes --package=dsh-rewind-plugin@0.3.3 -- dsh-rewind-repair -- --dry-run # 只预览不写盘
12
- ```
13
-
14
- 工具只改写标记事件的 `data.turn`(保持 seq / 顺序 / zstd 帧结构不变),改前自动备份原文件——可安全重复运行。源码方式:v0.4.0 之前的 tag 下 `node scripts/repair-markers.mjs`(参数相同)。
15
-
16
- ## 已知兼容边界
17
-
18
- 以下均为**预期行为而非崩溃**(探针钉住,完整依据见 [audit.md](audit.md) 事实源):
19
-
20
- - 会话统计 / 遥测**不回退**(折叠的是完整日志);
21
- - 被撤回的消息**仍可搜索、可导出**(`/export` 与全文搜索基于原始日志);
22
- - 会话标题可能**重新生成**(标题由当前 surface 派生);
23
- - 被**取消的工具调用**写入的文件(无快照提交)无法由「回退对话和代码」恢复。
24
-
25
- **R-OPENSTEP**(harness 侧,插件不设守卫):日志中存在*未闭合* `step/start`
26
- (agent 循环的 `finally` 闭合 step 前崩溃)时,后续 step 活动会破坏 token-meter
27
- 重放,回退后 `/compact` 可能报错。harness `0.1.1-rc.2` 已在加载时自动闭合
28
- (`interruptedTurnClosers`);插件曾实现前置拒绝但已回退(`177ec14`,真实日志
29
- 误判)。深入分析:[audit.md](audit.md) → R-OPENSTEP。
@@ -1,37 +0,0 @@
1
- /**
2
- * Cross-channel session event-log reader.
3
- *
4
- * This is a "0.1.1-rc.2 ↔ 0.1.2-rc.1" dual-channel reader. Harness 0.1.1-rc.2
5
- * exposes the full log as `Session.events` (`get events(): readonly
6
- * SessionEvent[]`); the 0.1.2 line (alpha.4+, now 0.1.2-rc.1) removed that
7
- * member and replaced it with the on-demand APIs `snapshotEvents(from?, to?)`
8
- * (half-open range, internally cached), `eventAt(seq)`, `ownEvents()` and
9
- * `seq`. This module reads the full log through whichever channel the host
10
- * exposes, so the plugin keeps one code path across both endpoints.
11
- *
12
- * `snapshotEvents()` is deliberately preferred over `ownEvents()`:
13
- * `snapshotEvents()` defaults to the whole log (including any fork-inherited
14
- * prefix), which is exactly what `Session.events` returned on 0.1.1-rc.2 — the
15
- * rewind semantics are preserved for fork-seeded sessions. `ownEvents()`
16
- * would drop the inherited prefix and change behaviour.
17
- *
18
- * @module dsh-rewind/session-events
19
- */
20
- import type { Session, SessionEvent } from '@deepseek-ai/dsh-session';
21
- /**
22
- * Read the full event log of a session, transparently across harness channels:
23
- * - 0.1.1-rc.2 (`Session.events`): the live immutable log array.
24
- * - 0.1.2-rc.1 (`Session.snapshotEvents()`): a deep-frozen snapshot, cached
25
- * by the session until the next append. This is the single 0.1.2-line
26
- * channel (alpha.2/3 still exposed `events` and thus fall into the
27
- * 0.1.1-rc.2 branch below).
28
- *
29
- * Falls back to an empty log when the session exposes neither member (a future
30
- * harness shape) rather than throwing — callers already treat the empty log as
31
- * "no candidates".
32
- *
33
- * @param session - the session to read.
34
- * @returns the full event log in log order (the same shape 0.1.1-rc.2's `events`
35
- * returned, so existing consumers are unchanged).
36
- */
37
- export declare function eventsOf(session: Session): readonly SessionEvent[];
@@ -1,33 +0,0 @@
1
- /**
2
- * Version-neutral settings-namespace reading for the host half.
3
- *
4
- * This is a "0.1.1-rc.2 ↔ 0.1.2-rc.1" dual channel. DSH 0.1.1-rc.2 exposes a
5
- * `settingsNamespace(value)` brand helper, and `settings.get` is typed to
6
- * require a branded `SettingsNamespace`. The 0.1.2 line (0.1.2-rc.1) removed
7
- * that helper (the `SettingsNamespace` *type* remains) and `settings.get`
8
- * accepts the raw namespace string. This module collapses both into one runtime
9
- * call: on 0.1.1-rc.2 the brand is a compile-time marker erased at runtime (so
10
- * `settingsNamespace(ns)` returns `ns`), on 0.1.2-rc.1 the brand helper is
11
- * absent and the raw `ns` string is used directly. That is what lets a single
12
- * compiled host bundle link and run on both harness generations.
13
- *
14
- * @module dsh-rewind/settings-locale
15
- */
16
- /** Minimal structural face of the settings provider the host reads from. */
17
- export interface SettingsProviderLike {
18
- /**
19
- * Read one registered settings section by namespace. Accepts whatever the
20
- * running DSH generation passes: a branded `SettingsNamespace` (0.1.1-rc.2,
21
- * brand erased) or the raw namespace string (0.1.2-rc.1).
22
- */
23
- get(ns: string): unknown;
24
- }
25
- /** The `settingsNamespace(ns)` brand helper, or `undefined` when removed (0.1.2-rc.1). */
26
- export type SettingsNamespaceBrand = ((value: string) => string) | undefined;
27
- /**
28
- * Read one settings section keyed by `ns`, tolerant of the settings-namespace
29
- * brand across DSH generations. Pass the brand helper when available (the
30
- * 0.1.1-rc.2 path); it is `undefined` on 0.1.2-rc.1, where the raw `ns` string
31
- * is used directly. Never throws: an absent section simply returns `undefined`.
32
- */
33
- export declare function readSettingsSection(provider: SettingsProviderLike, ns: string, brand: SettingsNamespaceBrand): unknown;