dsh-deepseek-import 0.1.1 → 0.2.0

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/README.md CHANGED
@@ -1,228 +1,230 @@
1
- # DSH chat migration
2
-
3
- English | [中文](README.zh.md)
4
-
5
- Capture conversations from **Edge** on `chat.deepseek.com` (one or many), export them as JSON, then rebuild them as resumable **DeepSeek Harness** sessions.
6
-
7
- ```
8
- Edge extension ──export──▶ dsh-deepseek-*.json ──dsh-import.cmd──▶ ~/.dsh/sessions + workspace.json
9
- ```
10
-
11
- ## Install
12
-
13
- Requires **Node.js 22+** (session compression uses built-in zstd).
14
-
15
- ```powershell
16
- # from npm (once published)
17
- npm i -g dsh-deepseek-import
18
- dsh-import --list
19
-
20
- # or run straight from source
21
- git clone https://github.com/Hungry-M/dsh-deepseek-import.git
22
- cd dsh-deepseek-import
23
- node dsh-import.mjs --list
24
- ```
25
-
26
- The Edge extension must be loaded separately (next section) — a browser extension cannot ship inside an npm package.
27
-
28
- ## 1. Install the extension (once)
29
-
30
- 1. Open `edge://extensions/` in Edge
31
- 2. Turn on **Developer mode**
32
- 3. Click **Load unpacked** and pick the `edge-extension` folder
33
- 4. Pin it to the toolbar (optional)
34
-
35
- ## 2. Capture a conversation
36
-
37
- 1. Open any conversation on `chat.deepseek.com` and let it finish loading
38
- 2. Open the extension; the conversation appears once it has been captured
39
- 3. To capture more, open them one by one — the list accumulates
40
- 4. Tick what you need → **Export selected**
41
-
42
- > If a conversation never shows up, open it and click **Capture chat**. It tries three sources in order: the browser's local cache (IndexedDB), a screen-by-screen backfill, then only the visible screen.
43
-
44
- ### Capturing very long conversations
45
-
46
- DeepSeek loads long conversations page by page. The extension does two things:
47
-
48
- 1. **Merge by message identity** — each message carries `message_id`; the extension unions them by id, so scrolling up or capturing twice only ever *adds* messages, never overwrites what was already captured.
49
- 2. **Capture chat** reads `deepseek-chat / history-message` straight from IndexedDB first. For most conversations that is the whole history in one read, with no scrolling at all.
50
-
51
- ## 3. Import into DSH
52
-
53
- Double-click **`dsh-import.cmd`** in the workspace (or drop JSON files onto it). With no arguments it uses the newest `dsh-deepseek-*.json` found in your download folder.
54
-
55
- - Lists your DSH workspaces; pick one by number
56
- - Each conversation becomes one session: title, order and body (including code blocks and tables) are preserved
57
- - **Attachments** (images, txt, pdf, docx…) that can be downloaded are saved under `<workspace>/.dsh-imported/<sessionId>/` with their original names; anything that cannot be downloaded degrades to `[附件未下载:name (size) 原链接]`
58
- - **Thinking** goes to `thinking.md` in the same folder (never injected into the context)
59
- - **Edited / regenerated versions**: only the selected branch stays in the body, all versions go to `revisions.md`
60
- - **Interrupted outputs** keep only a numbered placeholder (`[中断输出 #27:未产生完整正文…]`); add `--keep-interrupted` to keep the partial text
61
- - `workspace.json` is backed up before it is modified
62
- - Everything is mirrored to `import.log`
63
-
64
- ### Important: restart DSH after importing
65
-
66
- The sidebar list comes from `~/.dsh/storages/workspace.json`, which DSH **only reads at startup**. Quit DSH completely and reopen it.
67
-
68
- If the session still does not show up, use this order instead: **quit DSH → run `dsh-import.cmd` → start DSH**. A running DSH can overwrite `workspace.json` with its in-memory list.
69
-
70
- ### Configuration (shared by CLI / TUI / extension)
71
-
72
- `import.config.json`, next to this file:
73
-
74
- ```json
75
- { "downloadDir": "D:\\Downloads", "subdir": "dsh-import", "lang": "zh" }
76
- ```
77
-
78
- | Key | Meaning |
79
- |---|---|
80
- | `downloadDir` | Where to look for exports (defaults to the real system download folder) |
81
- | `subdir` | Subfolder convention: the extension saves to `<downloadDir>/<subdir>/`, the importer scans it too |
82
- | `lang` | `zh` / `en`, affects the TUI and the extension UI |
83
- | `autoTrim` | Default `true`: auto-trim conversations above the threshold |
84
- | `autoTrimChars` | Trigger threshold, default `120000` chars |
85
- | `autoTrimTurns` | Max turns kept, default `20` |
86
- | `autoTrimBudget` | Char budget for the kept part, default `60000` (walks backwards from the end) |
87
-
88
- The same four auto-trim values live in the extension's ⚙ settings (checkbox + a collapsed "Advanced" section). They travel inside the export's `options`, and the importer resolves them in this order:
89
-
90
- ```
91
- CLI flags > export options (extension settings) > import.config.json > built-in defaults
92
- ```
93
-
94
- Sidecar location is also selectable in the extension (**Write sidecars to DSH home**), which equals `--no-sidecar`.
95
-
96
- ### CLI (for AI / scripts)
97
-
98
- ```powershell
99
- node dsh-import.mjs --list # list workspaces
100
- node dsh-import.mjs # newest export in the download folder
101
- node dsh-import.mjs export.json -w "D:\proj" # explicit workspace
102
- node dsh-import.mjs export.json --dry-run # parse only
103
- node dsh-import.mjs export.json --thinking # also inline thinking (default: thinking.md only)
104
- node dsh-import.mjs export.json --json # machine-readable: {ok, workspace, created[]}
105
- node dsh-import.mjs export.json --keep-versions # keep pre-edit versions (default: current branch only)
106
- node dsh-import.mjs export.json --keep-interrupted # keep partial interrupted output
107
- node dsh-import.mjs export.json --tail 20 # only the last 20 turns
108
- node dsh-import.mjs export.json --no-auto-trim # disable auto trimming
109
- node dsh-import.mjs export.json --no-sidecar # sidecars to ~/.dsh/import-archive/
110
- node dsh-import.mjs export.json --sidecar-dir "E:\arch"
111
- ```
112
-
113
- `dsh-import.mjs` is also a module:
114
-
115
- ```js
116
- import { runImport, getWorkspaces, listExports, peekExport } from './dsh-import.mjs';
117
- await runImport({ files: ['x.json'], workspacePath: 'D:\\proj', only: ['<conversation id>'] });
118
- ```
119
-
120
- ### Interactive UI
121
-
122
- ```powershell
123
- node dsh-import-tui.mjs
124
- ```
125
-
126
- Pick an export (size/time shown) → preview conversations (messages/chars/thinking/attachments) → select (`all`, `1,3`, `1-2`) → **pick a branch point** → pick workspace → confirm.
127
-
128
- ### Branching from a specific message
129
-
130
- To start a session at a chosen point instead of "the last N turns":
131
-
132
- ```powershell
133
- node dsh-import.mjs export.json --from-match "some text you typed"
134
- node dsh-import.mjs export.json --from-index 157
135
- ```
136
-
137
- ### Auditing imported sessions
138
-
139
- DSH session format v4 requires the first model-visible node to be a `system/message`.
140
- Imports from `0.1.0` predate that fix and would break the moment you kept chatting in them.
141
- `0.1.1` writes the head on import, and this command repairs sessions created earlier:
142
-
143
- ```powershell
144
- node dsh-import.mjs --audit # report only
145
- node dsh-import.mjs --repair # insert/move the head, resequence, drop the projection cache
146
- ```
147
-
148
- - `--from-match` does a case-insensitive substring match over **user messages**, first hit wins
149
- - If the same text was edited and appears several times, the TUI lists them chronologically and you pick by number
150
- - Choosing a branch point disables auto-trim (your choice wins); the full text still goes to `transcript.md`
151
-
152
- ### How sidecar files are found later
153
-
154
- The first user message ends with an index line:
155
-
156
- ```
157
- [导入存档(需要时可直接读取):思考 2 段 → .dsh-imported/<sessionId>/thinking.md;附件 → …]
158
- ```
159
-
160
- Those files sit inside the workspace, so the model can read them on demand with ordinary file tools (nothing is pushed into the context automatically).
161
-
162
- ## Don't import very long conversations in one piece
163
-
164
- A 227-message / 520k-char conversation is roughly 250–350k tokens. DSH compacts automatically (`dsh-compaction-basic`), but after compaction only ~16% of recent history stays verbatim and the rest becomes a summary — the import is effectively wasted.
165
-
166
- ```powershell
167
- node dsh-import.mjs export.json --tail 20
168
- ```
169
-
170
- - Only the last 20 turns are imported; the full text goes to `.dsh-imported/<sessionId>/transcript.md`
171
- - The first message carries a note plus the sidecar index, so the model can grep the transcript when it needs old details
172
- - Conversations over 150k chars always get a `transcript.md`, even without `--tail`
173
- - `transcript.md` starts with an index (`#N role chars — first line`), and each section is headed `## #N`, so `grep "## #123"` jumps straight to a message
174
-
175
- ## FAQ
176
-
177
- **Double-clicking the cmd closes instantly?**
178
- Older builds had LF line endings, which `cmd.exe` mis-parses. Current builds use CRLF, always stop at `pause`, and write `import.log`.
179
-
180
- **"Node.js not found"?**
181
- Lookup order: `node-path.txt` → PATH → `Program Files\nodejs` → `Program Files (x86)\nodejs` → `%LOCALAPPDATA%\Programs\nodejs` → `%APPDATA%\npm` → `node.exe` next to the script.
182
-
183
- **Which file does the cmd import?**
184
- Without arguments: the newest `dsh-deepseek-*.json` in the download folder. You can also drop files/folders onto it.
185
-
186
- **Body is only a fragment?**
187
- Open the conversation and click **Capture chat**; then check the "来源" (source) tag in the list.
188
-
189
- ## Known limitations
190
-
191
- - **Thinking is archived, not inlined**: DSH reasoning blocks carry provider signatures; faking them would poison later requests. Read `thinking.md`, or force inline with `--thinking`.
192
- - **Attachments are not added to DSH's attachment store**: they are written to disk and referenced by path. When no download URL is available only the name and size survive.
193
- - **Web-search citations**: the cache record has no `references` table, so `[reference:N]` markers stay as plain text with no links.
194
- - **Only text and attachments** are migrated; tool calls and search results have no structured export.
195
- - **Session format is DSH internals** (v4 JSONL + zstd, multi-frame). A future DSH change may require an update here.
196
- - The extension relies on DeepSeek's own responses; if a redesign breaks capture, use **Capture chat** as the fallback.
197
-
198
- ## 4. Moving an imported session to another workspace
199
-
200
- ```powershell
201
- node move-session.mjs --list # sessions per workspace
202
- node move-session.mjs <session-id> --to "D:\other" # move
203
- node move-session.mjs <session-id> --to "D:\other" --dry-run # preview
204
- ```
205
-
206
- It updates four things: `cwd` in the session log, the project folder that holds the session, `sessionIds` in `workspace.json`, and the `.dsh-imported/<id>` folder. Restart DSH afterwards.
207
-
208
- ## Rollback
209
-
210
- - Delete a session folder: `~/.dsh/sessions/--<workspace>--/session-<uuid>/`
211
- - Restore the list: copy the matching `workspace.json.bak-*` over `workspace.json`
212
- - Single session: `node remove-session.mjs <session-id>`
213
-
214
- ## Layout
215
-
216
- ```
217
- edge-extension/
218
- manifest.json MV3 manifest
219
- merge.js window merging by message id / overlap
220
- inject.js main world: read-only sniffing of fetch/XHR responses
221
- stream-parser.js streaming patch protocol parser
222
- content.js isolated world: normalize, cache reader, DOM fallback
223
- background.js capture storage, attachment fetching
224
- popup.html/js/css selection and export UI
225
- dsh-import.mjs export JSON → DSH sessions
226
- dsh-import-tui.mjs interactive importer
227
- dsh-import.cmd double-click entry
228
- ```
1
+ # DSH chat migration
2
+
3
+ English | [中文](README.zh.md)
4
+
5
+ Capture conversations from **Edge** on `chat.deepseek.com` (one or many), export them as JSON, then rebuild them as resumable **DeepSeek Harness** sessions.
6
+
7
+ ```
8
+ Edge extension ──export──▶ dsh-deepseek-*.json ──dsh-import.cmd──▶ ~/.dsh/sessions + workspace.json
9
+ ```
10
+
11
+ ## Install
12
+
13
+ Requires **Node.js 22+** (session compression uses built-in zstd).
14
+
15
+ ```powershell
16
+ # from npm (once published)
17
+ npm i -g dsh-deepseek-import
18
+ dsh-import --list
19
+
20
+ # or run straight from source
21
+ git clone https://github.com/Hungry-M/dsh-deepseek-import.git
22
+ cd dsh-deepseek-import
23
+ node dsh-import.mjs --list
24
+ ```
25
+
26
+ The Edge extension must be loaded separately (next section) — a browser extension cannot ship inside an npm package.
27
+
28
+ ## 1. Install the extension (once)
29
+
30
+ 1. Open `edge://extensions/` in Edge
31
+ 2. Turn on **Developer mode**
32
+ 3. Click **Load unpacked** and pick the `edge-extension` folder
33
+ 4. Pin it to the toolbar (optional)
34
+
35
+ ## 2. Capture a conversation
36
+
37
+ 1. Open any conversation on `chat.deepseek.com` and let it finish loading
38
+ 2. Open the extension; the conversation appears once it has been captured
39
+ 3. To capture more, open them one by one — the list accumulates
40
+ 4. Tick what you need → **Export selected**
41
+
42
+ > If a conversation never shows up, open it and click **Capture chat**. It tries three sources in order: the browser's local cache (IndexedDB), a screen-by-screen backfill, then only the visible screen.
43
+
44
+ ### Capturing very long conversations
45
+
46
+ DeepSeek loads long conversations page by page. The extension does two things:
47
+
48
+ 1. **Merge by message identity** — each message carries `message_id`; the extension unions them by id, so scrolling up or capturing twice only ever *adds* messages, never overwrites what was already captured.
49
+ 2. **Capture chat** reads `deepseek-chat / history-message` straight from IndexedDB first. For most conversations that is the whole history in one read, with no scrolling at all.
50
+
51
+ ## 3. Import into DSH
52
+
53
+ Double-click **`dsh-import.cmd`** in the workspace (or drop JSON files onto it). With no arguments it uses the newest `dsh-deepseek-*.json` found in your download folder.
54
+
55
+ - Lists your DSH workspaces; pick one by number
56
+ - Each conversation becomes one session: title, order and body (including code blocks and tables) are preserved
57
+ - **Attachments** (images, txt, pdf, docx…): saved under `<workspace>/.dsh-imported/<sessionId>/` with their original names **only when the data source carries them**; anything that cannot be downloaded degrades to `[附件未下载:name (size) 原链接]`. DeepSeek's IndexedDB cache copy usually carries no attachments
58
+ - **Thinking** goes to `thinking.md` in the same folder (never injected into the context)
59
+ - **Edited / regenerated versions**: only the selected branch stays in the body, all versions go to `revisions.md`
60
+ - **Interrupted outputs** keep only a numbered placeholder (`[中断输出 #27:未产生完整正文…]`); add `--keep-interrupted` to keep the partial text
61
+ - `workspace.json` is backed up before it is modified
62
+ - Everything is mirrored to `import.log`
63
+
64
+ ### Important: restart DSH after importing
65
+
66
+ The sidebar list comes from `~/.dsh/storages/workspace.json`, which DSH **only reads at startup**. Quit DSH completely and reopen it.
67
+
68
+ If the session still does not show up, use this order instead: **quit DSH → run `dsh-import.cmd` → start DSH**. A running DSH can overwrite `workspace.json` with its in-memory list.
69
+
70
+ ### Configuration (shared by CLI / TUI / extension)
71
+
72
+ `import.config.json`, next to this file:
73
+
74
+ ```json
75
+ { "downloadDir": "D:\\Downloads", "subdir": "dsh-import", "lang": "zh" }
76
+ ```
77
+
78
+ | Key | Meaning |
79
+ |---|---|
80
+ | `downloadDir` | Where to look for exports (defaults to the real system download folder) |
81
+ | `subdir` | Subfolder convention: the extension saves to `<downloadDir>/<subdir>/`, the importer scans it too |
82
+ | `lang` | `zh` / `en`, affects the TUI and the extension UI |
83
+ | `autoTrim` | Default `true`: auto-trim conversations above the threshold |
84
+ | `autoTrimChars` | Trigger threshold, default `120000` chars |
85
+ | `autoTrimTurns` | Max turns kept, default `20` |
86
+ | `autoTrimBudget` | Char budget for the kept part, default `60000` (walks backwards from the end) |
87
+
88
+ The same four auto-trim values live in the extension's ⚙ settings (checkbox + a collapsed "Advanced" section). They travel inside the export's `options`, and the importer resolves them in this order:
89
+
90
+ ```
91
+ CLI flags > export options (extension settings) > import.config.json > built-in defaults
92
+ ```
93
+
94
+ Sidecar location is also selectable in the extension (**Write sidecars to DSH home**), which equals `--no-sidecar`.
95
+
96
+ ### CLI (for AI / scripts)
97
+
98
+ ```powershell
99
+ node dsh-import.mjs --list # list workspaces
100
+ node dsh-import.mjs # newest export in the download folder
101
+ node dsh-import.mjs export.json -w "D:\proj" # explicit workspace
102
+ node dsh-import.mjs export.json --dry-run # parse only
103
+ node dsh-import.mjs export.json --thinking # also inline thinking (default: thinking.md only)
104
+ node dsh-import.mjs export.json --json # machine-readable: {ok, workspace, created[]}
105
+ node dsh-import.mjs export.json --keep-versions # keep pre-edit versions (default: current branch only)
106
+ node dsh-import.mjs export.json --keep-interrupted # keep partial interrupted output
107
+ node dsh-import.mjs export.json --tail 20 # only the last 20 turns
108
+ node dsh-import.mjs export.json --no-auto-trim # disable auto trimming
109
+ node dsh-import.mjs export.json --no-sidecar # sidecars to ~/.dsh/import-archive/
110
+ node dsh-import.mjs export.json --sidecar-dir "E:\arch"
111
+ ```
112
+
113
+ `dsh-import.mjs` is also a module:
114
+
115
+ ```js
116
+ import { runImport, getWorkspaces, listExports, peekExport } from './dsh-import.mjs';
117
+ await runImport({ files: ['x.json'], workspacePath: 'D:\\proj', only: ['<conversation id>'] });
118
+ ```
119
+
120
+ ### Interactive UI
121
+
122
+ ```powershell
123
+ node dsh-import-tui.mjs
124
+ ```
125
+
126
+ Pick an export (size/time shown) → preview conversations (messages/chars/thinking/attachments) → select (`all`, `1,3`, `1-2`) → **pick a branch point** → pick workspace → confirm.
127
+
128
+ ### Branching from a specific message
129
+
130
+ To start a session at a chosen point instead of "the last N turns":
131
+
132
+ ```powershell
133
+ node dsh-import.mjs export.json --from-match "some text you typed"
134
+ node dsh-import.mjs export.json --from-index 157
135
+ ```
136
+
137
+ ### Auditing imported sessions
138
+
139
+ DSH session format v4 requires the first model-visible node to be a `system/message`.
140
+ Imports from `0.1.0` predate that fix and would break the moment you kept chatting in them.
141
+ `0.1.1` writes the head on import, and this command repairs sessions created earlier:
142
+
143
+ ```powershell
144
+ node dsh-import.mjs --audit # report only
145
+ node dsh-import.mjs --repair # insert/move the head, resequence, drop the projection cache
146
+ ```
147
+
148
+ - `--from-match` does a case-insensitive substring match over **user messages**, first hit wins
149
+ - If the same text was edited and appears several times, the TUI lists them chronologically and you pick by number
150
+ - Choosing a branch point disables auto-trim (your choice wins); the full text still goes to `transcript.md`
151
+
152
+ ### How sidecar files are found later
153
+
154
+ The first user message ends with an index line:
155
+
156
+ ```
157
+ [导入存档(需要时可直接读取):思考 2 段 → .dsh-imported/<sessionId>/thinking.md;附件 → …]
158
+ ```
159
+
160
+ Those files sit inside the workspace, so the model can read them on demand with ordinary file tools (nothing is pushed into the context automatically).
161
+
162
+ ## Don't import very long conversations in one piece
163
+
164
+ A 227-message / 520k-char conversation is roughly 250–350k tokens. DSH compacts automatically (`dsh-compaction-basic`), but after compaction only ~16% of recent history stays verbatim and the rest becomes a summary — the import is effectively wasted.
165
+
166
+ ```powershell
167
+ node dsh-import.mjs export.json --tail 20
168
+ ```
169
+
170
+ - Only the last 20 turns are imported; the full text goes to `.dsh-imported/<sessionId>/transcript.md`
171
+ - The first message carries a note plus the sidecar index, so the model can grep the transcript when it needs old details
172
+ - Conversations over 150k chars always get a `transcript.md`, even without `--tail`
173
+ - `transcript.md` starts with an index (`#N role chars — first line`), and each section is headed `## #N`, so `grep "## #123"` jumps straight to a message
174
+
175
+ ## FAQ
176
+
177
+ **Double-clicking the cmd closes instantly?**
178
+ Older builds had LF line endings, which `cmd.exe` mis-parses. Current builds use CRLF, always stop at `pause`, and write `import.log`.
179
+
180
+ **"Node.js not found"?**
181
+ Lookup order: `node-path.txt` → PATH → `Program Files\nodejs` → `Program Files (x86)\nodejs` → `%LOCALAPPDATA%\Programs\nodejs` → `%APPDATA%\npm` → `node.exe` next to the script.
182
+
183
+ **Which file does the cmd import?**
184
+ Without arguments: the newest `dsh-deepseek-*.json` in the download folder. You can also drop files/folders onto it.
185
+
186
+ **Body is only a fragment?**
187
+ Open the conversation and click **Capture chat**; then check the "来源" (source) tag in the list.
188
+
189
+ ## Known limitations
190
+
191
+ - **Citations and attachments depend on the data source**: DeepSeek's IndexedDB cache copy keeps the body and thinking only; the `references` table and `files` field are usually absent. `references.md` and the attachment folder are therefore created **only when the source carries them** — their absence is a normal result, not a failure.
192
+
193
+ - **Thinking is archived, not inlined**: DSH reasoning blocks carry provider signatures; faking them would poison later requests. Read `thinking.md`, or force inline with `--thinking`.
194
+ - **Attachments are not added to DSH's attachment store**: they are written to disk and referenced by path. When no download URL is available only the name and size survive.
195
+ - **Web-search citations**: the cache record has no `references` table, so `[reference:N]` markers stay as plain text with no links.
196
+ - **Only text and attachments** are migrated; tool calls and search results have no structured export.
197
+ - **Session format is DSH internals** (v4 JSONL + zstd, multi-frame). A future DSH change may require an update here.
198
+ - The extension relies on DeepSeek's own responses; if a redesign breaks capture, use **Capture chat** as the fallback.
199
+
200
+ ## 4. Moving an imported session to another workspace
201
+
202
+ ```powershell
203
+ node move-session.mjs --list # sessions per workspace
204
+ node move-session.mjs <session-id> --to "D:\other" # move
205
+ node move-session.mjs <session-id> --to "D:\other" --dry-run # preview
206
+ ```
207
+
208
+ It updates four things: `cwd` in the session log, the project folder that holds the session, `sessionIds` in `workspace.json`, and the `.dsh-imported/<id>` folder. Restart DSH afterwards.
209
+
210
+ ## Rollback
211
+
212
+ - Delete a session folder: `~/.dsh/sessions/--<workspace>--/session-<uuid>/`
213
+ - Restore the list: copy the matching `workspace.json.bak-*` over `workspace.json`
214
+ - Single session: `node remove-session.mjs <session-id>`
215
+
216
+ ## Layout
217
+
218
+ ```
219
+ edge-extension/
220
+ manifest.json MV3 manifest
221
+ merge.js window merging by message id / overlap
222
+ inject.js main world: read-only sniffing of fetch/XHR responses
223
+ stream-parser.js streaming patch protocol parser
224
+ content.js isolated world: normalize, cache reader, DOM fallback
225
+ background.js capture storage, attachment fetching
226
+ popup.html/js/css selection and export UI
227
+ dsh-import.mjs export JSON → DSH sessions
228
+ dsh-import-tui.mjs interactive importer
229
+ dsh-import.cmd double-click entry
230
+ ```