dsh-side-chat-plus 0.3.2 → 0.3.4
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 +327 -326
- package/README.zh.md +269 -268
- package/dsh.plugin.json +3 -3
- package/lib/client-registry.js +397 -181
- package/lib/client-registry.js.map +1 -1
- package/lib/client.js +397 -181
- package/lib/client.js.map +1 -1
- package/lib/index.js +22 -7
- package/lib/types/client/locales.d.ts +18 -0
- package/lib/types/context-types.d.ts +36 -4
- package/lib/types/settings-shared.d.ts +4 -0
- package/package.json +37 -37
- package/src/client/attachments/AttachmentRail.module.css +89 -89
- package/src/client/attachments/AttachmentRail.tsx +173 -173
- package/src/client/attachments/DropOverlay.module.css +38 -38
- package/src/client/attachments/DropOverlay.tsx +62 -62
- package/src/client/attachments/ImageLightbox.module.css +44 -44
- package/src/client/attachments/ImageLightbox.tsx +58 -58
- package/src/client/attachments/MessageImage.module.css +61 -61
- package/src/client/attachments/MessageImage.tsx +120 -120
- package/src/client/attachments/index.ts +19 -19
- package/src/client/client.module.css +1051 -1032
- package/src/client/index.tsx +2209 -1966
- package/src/client/locales.ts +191 -173
- package/src/context-types.ts +415 -384
- package/src/index.ts +29 -9
- package/src/settings-shared.ts +6 -0
package/README.md
CHANGED
|
@@ -1,326 +1,327 @@
|
|
|
1
|
-
# dsh-side-chat — 侧边聊天 (Side chat)
|
|
2
|
-
|
|
3
|
-
An **enhanced version of a Codex-style side chat** for
|
|
4
|
-
[DSH](https://www.deepseek.com): a dedicated, agentic chat in a right-side
|
|
5
|
-
panel, scoped to the conversation it was started from and aware of its
|
|
6
|
-
workspace. Select part of a conversation and ask about it in the side chat; the
|
|
7
|
-
side chat inherits the main conversation's toolset, model, and permission
|
|
8
|
-
preset, and its AI replies can be **brought back to the main conversation**
|
|
9
|
-
(directly or as a summary, into the composer draft or as a collapsed context
|
|
10
|
-
row).
|
|
11
|
-
|
|
12
|
-
On top of the Codex-style base, it adds one extra capability: when the main
|
|
13
|
-
agent asks you a **question dialog**, you can side-chat about the question and
|
|
14
|
-
its options **without interrupting the flow** — let the AI help you think it
|
|
15
|
-
through first, then bring the answer back and answer the dialog.
|
|
16
|
-
|
|
17
|
-
> 中文文档见 [README.zh.md](./README.zh.md).
|
|
18
|
-
|
|
19
|
-
## What it does
|
|
20
|
-
|
|
21
|
-
- **Select text → ask in a side chat.** Select any part of a message and a
|
|
22
|
-
floating button *"Ask in side chat"* appears. The selected text is carried
|
|
23
|
-
into the side chat automatically.
|
|
24
|
-
- **Per-conversation isolation.** Each side chat is a hidden ordinary DSH
|
|
25
|
-
session (`meta.parentSession` links it to the conversation that started it,
|
|
26
|
-
and the session is archived so it never appears in the main session list).
|
|
27
|
-
Every conversation gets its own side chat.
|
|
28
|
-
- **Inherits main-conversation context.** The side chat is aware of the
|
|
29
|
-
conversation it was started from and its working directory, and inherits the
|
|
30
|
-
main conversation's toolset, model, thinking effort, and permission preset by
|
|
31
|
-
default — so it can act on the same workspace as the main conversation.
|
|
32
|
-
- **Model / effort / permission are adjustable.** A two-level model menu
|
|
33
|
-
(provider → model → effort) and a permission menu are copied from the main
|
|
34
|
-
conversation, so each side chat can be tuned independently.
|
|
35
|
-
- **"Look up workspace / parent when needed" switch** (default off). When on,
|
|
36
|
-
the side chat may read files from the workspace and the parent conversation
|
|
37
|
-
when it needs more information.
|
|
38
|
-
- **Normal conversation capabilities.** Markdown replies, thinking/reasoning
|
|
39
|
-
display, image attachments (paste / drag-and-drop), send/stop controls, and
|
|
40
|
-
thinking-duration display — all reuse the same UI primitives as the main
|
|
41
|
-
conversation.
|
|
42
|
-
- **Bring AI replies back to the main conversation.** Every assistant reply in
|
|
43
|
-
the side chat can be brought into the current main conversation: select part
|
|
44
|
-
of it with the mouse, or insert the whole reply in one click. Either way you
|
|
45
|
-
can choose **"Insert directly"** (verbatim) or **"Summarize & insert"** (the
|
|
46
|
-
side chat's inherited model summarizes it first). Where it lands is
|
|
47
|
-
configurable: **into the composer draft**, or **as a collapsed context row**
|
|
48
|
-
(injected as context — not into the composer, never sent).
|
|
49
|
-
- **Ask about the current question dialog — without interrupting the flow.**
|
|
50
|
-
When the main conversation shows a question dialog (the agent asking you
|
|
51
|
-
something), the side panel automatically lists the question and each option
|
|
52
|
-
(no manual text selection needed). Each question has "Bring all" and each
|
|
53
|
-
option has "Bring", both offering to **continue an existing side chat** or
|
|
54
|
-
**start a new one**. The list can be **collapsed / expanded**, and items can
|
|
55
|
-
be **deleted individually or all at once** (deleted items stay gone).
|
|
56
|
-
- **Deletable side chats.** Each entry in the side-chat list can be deleted
|
|
57
|
-
individually, or all of them at once via "Delete all".
|
|
58
|
-
- **Resolution-aware, resizable, collapsible panel.** Drag to resize
|
|
59
|
-
(280–720 px); the width is automatically capped to keep the panel within
|
|
60
|
-
~40% of the window and to leave the main chat usable, re-adapts when the
|
|
61
|
-
window is resized (different monitor, zoom), and is remembered across
|
|
62
|
-
reloads. Collapse and expand; no close button.
|
|
63
|
-
- **Language-aware.** The plugin follows DSH's language setting (Chinese /
|
|
64
|
-
English).
|
|
65
|
-
|
|
66
|
-
## Codex-style side chat, enhanced
|
|
67
|
-
|
|
68
|
-
This plugin is an **enhanced version of a Codex-style side chat**: a second,
|
|
69
|
-
agentic chat that works beside the main conversation — plus an extra capability
|
|
70
|
-
on top of the Codex-style base: side-chatting about the current **question
|
|
71
|
-
dialog** without interrupting the flow.
|
|
72
|
-
|
|
73
|
-
**The Codex-style base.** The side chat is a real DSH agent session, not a
|
|
74
|
-
scratchpad:
|
|
75
|
-
|
|
76
|
-
- It **inherits the main conversation's setup** — toolset, permission preset,
|
|
77
|
-
model / thinking effort, and working directory — so it can read and work with
|
|
78
|
-
the same workspace as the main conversation, subject to the permission preset
|
|
79
|
-
you choose for it.
|
|
80
|
-
- The **"Look up workspace / parent when needed"** switch (default off) lets it
|
|
81
|
-
read workspace files and the parent conversation's records when the task needs
|
|
82
|
-
more context.
|
|
83
|
-
- **Model / thinking effort / permission preset are adjustable per chat**, so a
|
|
84
|
-
hard task can be handed to a stronger model without touching the main
|
|
85
|
-
conversation.
|
|
86
|
-
- The final reply (or a summary of it) can be **brought back** into the main
|
|
87
|
-
conversation — into the composer draft or as a collapsed context row — the
|
|
88
|
-
Codex-style "hand the result over" without copy-pasting.
|
|
89
|
-
|
|
90
|
-
**The enhancement: question-dialog side chat, no flow interruption.** When the
|
|
91
|
-
main agent asks you something, the flow normally stops until you answer. This
|
|
92
|
-
plugin lets you keep moving: the side panel automatically lists the question and
|
|
93
|
-
every option; bring the whole question or any single option into a side chat
|
|
94
|
-
(new or existing), let the AI analyze it for you, then bring the answer back and
|
|
95
|
-
answer the dialog. The main conversation simply waits — nothing is interrupted,
|
|
96
|
-
and you never have to answer before you're ready.
|
|
97
|
-
|
|
98
|
-
## Requirements
|
|
99
|
-
|
|
100
|
-
- [Node.js](https://nodejs.org) ≥ 20
|
|
101
|
-
- [pnpm](https://pnpm.io)
|
|
102
|
-
- DSH ≥ `0.1.0-rc.6` (the harness `engines.dsh` constraint)
|
|
103
|
-
|
|
104
|
-
## Build
|
|
105
|
-
|
|
106
|
-
```bash
|
|
107
|
-
pnpm install
|
|
108
|
-
pnpm build
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
`pnpm build` clears `lib/`, runs `tsc -p tsconfig.build.json` for type
|
|
112
|
-
declarations, then bundles the host (`lib/index.js`) and client
|
|
113
|
-
(`lib/client.js` + `lib/client-registry.js`) with tsdown.
|
|
114
|
-
|
|
115
|
-
## CI and publishing
|
|
116
|
-
|
|
117
|
-
[GitHub Actions](.github/workflows) covers two jobs:
|
|
118
|
-
|
|
119
|
-
- **[`ci.yml`](.github/workflows/ci.yml)** runs on every push to `main` and on
|
|
120
|
-
pull requests: it installs dependencies, typechecks, builds, runs the test
|
|
121
|
-
script, and packs the tarball (uploaded as an artifact) for Node 20 and 22.
|
|
122
|
-
- **[`publish.yml`](.github/workflows/publish.yml)** fires when a `v*` tag is
|
|
123
|
-
pushed: it builds and publishes the package to **npm** as
|
|
124
|
-
[`dsh-side-chat-plus`](https://www.npmjs.com/package/dsh-side-chat-plus),
|
|
125
|
-
authenticated with the `NPM_TOKEN` repository secret.
|
|
126
|
-
|
|
127
|
-
The package name is `dsh-side-chat-plus` (the plain `dsh-side-chat` name on npm
|
|
128
|
-
belongs to a different maintainer, so the release is published under the
|
|
129
|
-
`-plus` name).
|
|
130
|
-
|
|
131
|
-
> **Registry dependencies.** The harness packages this plugin targets (the DSH
|
|
132
|
-
> `0.1.2` API line) are published to npm as prereleases (`0.1.2-rc.1`) and, in a
|
|
133
|
-
> few cases, declare internal dependencies with a plain `>=0.1.2` range that
|
|
134
|
-
> npm/pnpm refuses to match against a prerelease. The developer `pnpm-workspace.yaml`
|
|
135
|
-
> therefore points the `@deepseek-ai/dsh-*` packages at a local harness checkout
|
|
136
|
-
> (absolute `D:/code/...` paths that exist only on the maintainer's machine). CI
|
|
137
|
-
> swaps that file for one whose overrides pin every `@deepseek-ai/dsh-*`
|
|
138
|
-
> dependency to `0.1.2-rc.1`, so installs resolve from the registry. On another
|
|
139
|
-
> machine, point the overrides at your own harness clone or use the CI workspace
|
|
140
|
-
> file as a template.
|
|
141
|
-
|
|
142
|
-
## Deploy
|
|
143
|
-
|
|
144
|
-
DSH web loads external plugins from the active profile. This package is a
|
|
145
|
-
**bundle**: its `package.json` declares `dsh.bundle.patch` →
|
|
146
|
-
[`cordis.patch.yml`](./cordis.patch.yml), whose `insert` row mounts the plugin.
|
|
147
|
-
That declaration is what lets `dsh plugin add` install the package *and*
|
|
148
|
-
activate it in one step.
|
|
149
|
-
|
|
150
|
-
> **Recommended: install from npm.** The package is published to
|
|
151
|
-
> [npm](https://www.npmjs.com/package/dsh-side-chat-plus) as
|
|
152
|
-
> `dsh-side-chat-plus`, so `dsh plugin add` needs no source checkout — the
|
|
153
|
-
> tarball ships the prebuilt `lib/` and is activated in one go.
|
|
154
|
-
|
|
155
|
-
### Install from npm
|
|
156
|
-
|
|
157
|
-
The built package is published to npm as [`dsh-side-chat-plus`](https://www.npmjs.com/package/dsh-side-chat-plus). Installed from the registry, the tarball ships the prebuilt `lib/` (plus `cordis.patch.yml` and `dsh.plugin.json`), so no source build is needed:
|
|
158
|
-
|
|
159
|
-
```bash
|
|
160
|
-
npx -p @deepseek-ai/dsh dsh plugin --profile web add dsh-side-chat-plus
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
`dsh plugin` reconciles the bundle into the profile's `dsh.profile.bundles`
|
|
164
|
-
layer list; the prebuilt `lib/` means nothing extra runs at install time.
|
|
165
|
-
Version falls out of the tagged release (see [CI and publishing](#ci-and-publishing)).
|
|
166
|
-
|
|
167
|
-
Restart `dsh web`, then hard-refresh the page (Ctrl/Cmd+Shift+R).
|
|
168
|
-
|
|
169
|
-
### Install from GitHub
|
|
170
|
-
|
|
171
|
-
```bash
|
|
172
|
-
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:heartmove/dsh-side-chat-plus
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
`dsh plugin` forwards to pnpm inside `~/.dsh/profiles/web/`, then reconciles the
|
|
176
|
-
bundle into the profile's `dsh.profile.bundles` layer list. A git install
|
|
177
|
-
fetches sources, so pnpm runs the package's `prepare` script (`tsdown`) to build
|
|
178
|
-
`lib/` from `src/` after checkout.
|
|
179
|
-
|
|
180
|
-
pnpm ≥ 10 refuses to run a git dependency's `prepare` script until it is
|
|
181
|
-
allowlisted, so the first `add` fails with an "Ignored build scripts" hint. Copy
|
|
182
|
-
the exact package key pnpm printed into the profile's `pnpm-workspace.yaml`
|
|
183
|
-
(`~/.dsh/profiles/web/pnpm-workspace.yaml`):
|
|
184
|
-
|
|
185
|
-
```yaml
|
|
186
|
-
allowBuilds:
|
|
187
|
-
dsh-side-chat-plus: true
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
then re-run the `add`. That allowance means "run this package's code on my
|
|
191
|
-
machine at install time" — only allow packages whose source you trust, and pin a
|
|
192
|
-
commit (`github:heartmove/dsh-side-chat-plus#<sha>`) so a later push cannot
|
|
193
|
-
silently change what runs.
|
|
194
|
-
|
|
195
|
-
Restart `dsh web`, then hard-refresh the page (Ctrl/Cmd+Shift+R).
|
|
196
|
-
|
|
197
|
-
### Install from a local checkout
|
|
198
|
-
|
|
199
|
-
From the directory that contains this checkout:
|
|
200
|
-
|
|
201
|
-
```bash
|
|
202
|
-
npx -p @deepseek-ai/dsh dsh plugin --profile web add ./dsh-side-chat-plus
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
pnpm links the checkout and `dsh` activates the bundle the same way.
|
|
206
|
-
|
|
207
|
-
### Manual link
|
|
208
|
-
|
|
209
|
-
To manage the profile by hand, link the package and list it as a bundle in
|
|
210
|
-
`~/.dsh/profiles/web/package.json` (the bundle's own `cordis.patch.yml` supplies
|
|
211
|
-
the loader row, so no `insert` entry is needed):
|
|
212
|
-
|
|
213
|
-
```json
|
|
214
|
-
{
|
|
215
|
-
"dependencies": {
|
|
216
|
-
"dsh-side-chat-plus": "link:D:\\path\\to\\dsh-side-chat-plus"
|
|
217
|
-
},
|
|
218
|
-
"dsh": {
|
|
219
|
-
"profile": {
|
|
220
|
-
"bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-side-chat-plus"]
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
(On POSIX systems use `link:/path/to/dsh-side-chat-plus`.) Then run `pnpm install`
|
|
227
|
-
in the profile directory and restart `dsh web`.
|
|
228
|
-
|
|
229
|
-
## Usage
|
|
230
|
-
|
|
231
|
-
1. Select part of any message in the main conversation.
|
|
232
|
-
2. A floating **"Ask in side chat"** button appears — click it.
|
|
233
|
-
- If a side chat already exists for this conversation, you'll also see
|
|
234
|
-
**"Continue active side chat"**.
|
|
235
|
-
3. The right-side panel opens (or expands) with the selected text staged in the
|
|
236
|
-
composer.
|
|
237
|
-
4. Adjust **model / effort** and **permission**, and toggle **"Look up workspace
|
|
238
|
-
/ parent when needed"** as desired.
|
|
239
|
-
5. Send. The reply streams back with markdown rendering and, where applicable,
|
|
240
|
-
a "Think" row for the model's reasoning.
|
|
241
|
-
6. Drag the panel's left edge to resize, or use the collapse/expand control.
|
|
242
|
-
|
|
243
|
-
### Sending behavior
|
|
244
|
-
|
|
245
|
-
By default (`sendImmediately` on), selecting text **sends it immediately** and
|
|
246
|
-
appends your configured **default prompt**. Turn `sendImmediately` off in
|
|
247
|
-
settings to stage the selection as an attachment instead, so you can review and
|
|
248
|
-
edit before sending.
|
|
249
|
-
|
|
250
|
-
### Bring replies back to the main conversation
|
|
251
|
-
|
|
252
|
-
Assistant replies in the side chat can be brought into the current main
|
|
253
|
-
conversation (**never sent**):
|
|
254
|
-
|
|
255
|
-
1. **Bring a selection.** Select part of an assistant reply in the side chat,
|
|
256
|
-
then choose **"Insert directly"** (verbatim) or **"Summarize & insert"** (the
|
|
257
|
-
side chat's inherited model summarizes it first) from the floating menu.
|
|
258
|
-
2. **Bring the whole reply.** Each assistant reply has **"Insert directly"** and
|
|
259
|
-
**"Summarize & insert"** buttons under its text, for inserting the full reply
|
|
260
|
-
(or its summary) in one click.
|
|
261
|
-
3. Per the **bring-back target** setting, the content is either **appended to
|
|
262
|
-
the main composer draft** (edit before sending) or **injected as a collapsed
|
|
263
|
-
context row** (source-tagged, not into the composer; the model sees it next
|
|
264
|
-
turn).
|
|
265
|
-
|
|
266
|
-

|
|
267
|
-
|
|
268
|
-
### Ask about the current question dialog
|
|
269
|
-
|
|
270
|
-
When the main conversation shows a question dialog, the side panel automatically
|
|
271
|
-
lists the question and its options:
|
|
272
|
-
|
|
273
|
-
1. While the panel is closed, a **floating entry** appears beside the dialog's
|
|
274
|
-
header — click it to open the panel.
|
|
275
|
-
2. Each question has "Bring all" and each option has "Bring", both offering to
|
|
276
|
-
**continue an existing side chat** or **start a new one**.
|
|
277
|
-
3. The list can be **collapsed / expanded**, and items can be **deleted
|
|
278
|
-
individually or all at once** (deleted items stay gone).
|
|
279
|
-
|
|
280
|
-
The main conversation keeps waiting on the dialog — nothing is interrupted; do
|
|
281
|
-
the research in the side chat first, then bring the answer back and answer the
|
|
282
|
-
dialog.
|
|
283
|
-
|
|
284
|
-

|
|
285
|
-
|
|
286
|
-
### Delete side chats
|
|
287
|
-
|
|
288
|
-
Each entry in the side-chat list has a "×" delete button; "Delete all" at the
|
|
289
|
-
top-right removes every side chat of the current conversation.
|
|
290
|
-
|
|
291
|
-
## Settings
|
|
292
|
-
|
|
293
|
-
Open DSH **Settings → 侧边聊天 (Side chat)** to configure:
|
|
294
|
-
|
|
295
|
-
| Setting | Default | Description |
|
|
296
|
-
| --- | --- | --- |
|
|
297
|
-
| `lookupDefault` | off | Whether the "look up workspace / parent" switch is on by default for new side chats. |
|
|
298
|
-
| `sendImmediately` | on | Whether selecting text sends it immediately, or stages it as an attachment. |
|
|
299
|
-
| `defaultPrompt` | *(empty)* | Extra prompt appended when the selection is sent immediately. |
|
|
300
|
-
| `bringMode` | `draft` | Where brought-back content lands: `draft` into the composer, or `context` as a collapsed context row. |
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
1
|
+
# dsh-side-chat — 侧边聊天 (Side chat)
|
|
2
|
+
|
|
3
|
+
An **enhanced version of a Codex-style side chat** for
|
|
4
|
+
[DSH](https://www.deepseek.com): a dedicated, agentic chat in a right-side
|
|
5
|
+
panel, scoped to the conversation it was started from and aware of its
|
|
6
|
+
workspace. Select part of a conversation and ask about it in the side chat; the
|
|
7
|
+
side chat inherits the main conversation's toolset, model, and permission
|
|
8
|
+
preset, and its AI replies can be **brought back to the main conversation**
|
|
9
|
+
(directly or as a summary, into the composer draft or as a collapsed context
|
|
10
|
+
row).
|
|
11
|
+
|
|
12
|
+
On top of the Codex-style base, it adds one extra capability: when the main
|
|
13
|
+
agent asks you a **question dialog**, you can side-chat about the question and
|
|
14
|
+
its options **without interrupting the flow** — let the AI help you think it
|
|
15
|
+
through first, then bring the answer back and answer the dialog.
|
|
16
|
+
|
|
17
|
+
> 中文文档见 [README.zh.md](./README.zh.md).
|
|
18
|
+
|
|
19
|
+
## What it does
|
|
20
|
+
|
|
21
|
+
- **Select text → ask in a side chat.** Select any part of a message and a
|
|
22
|
+
floating button *"Ask in side chat"* appears. The selected text is carried
|
|
23
|
+
into the side chat automatically.
|
|
24
|
+
- **Per-conversation isolation.** Each side chat is a hidden ordinary DSH
|
|
25
|
+
session (`meta.parentSession` links it to the conversation that started it,
|
|
26
|
+
and the session is archived so it never appears in the main session list).
|
|
27
|
+
Every conversation gets its own side chat.
|
|
28
|
+
- **Inherits main-conversation context.** The side chat is aware of the
|
|
29
|
+
conversation it was started from and its working directory, and inherits the
|
|
30
|
+
main conversation's toolset, model, thinking effort, and permission preset by
|
|
31
|
+
default — so it can act on the same workspace as the main conversation.
|
|
32
|
+
- **Model / effort / permission are adjustable.** A two-level model menu
|
|
33
|
+
(provider → model → effort) and a permission menu are copied from the main
|
|
34
|
+
conversation, so each side chat can be tuned independently.
|
|
35
|
+
- **"Look up workspace / parent when needed" switch** (default off). When on,
|
|
36
|
+
the side chat may read files from the workspace and the parent conversation
|
|
37
|
+
when it needs more information.
|
|
38
|
+
- **Normal conversation capabilities.** Markdown replies, thinking/reasoning
|
|
39
|
+
display, image attachments (paste / drag-and-drop), send/stop controls, and
|
|
40
|
+
thinking-duration display — all reuse the same UI primitives as the main
|
|
41
|
+
conversation.
|
|
42
|
+
- **Bring AI replies back to the main conversation.** Every assistant reply in
|
|
43
|
+
the side chat can be brought into the current main conversation: select part
|
|
44
|
+
of it with the mouse, or insert the whole reply in one click. Either way you
|
|
45
|
+
can choose **"Insert directly"** (verbatim) or **"Summarize & insert"** (the
|
|
46
|
+
side chat's inherited model summarizes it first). Where it lands is
|
|
47
|
+
configurable: **into the composer draft**, or **as a collapsed context row**
|
|
48
|
+
(injected as context — not into the composer, never sent).
|
|
49
|
+
- **Ask about the current question dialog — without interrupting the flow.**
|
|
50
|
+
When the main conversation shows a question dialog (the agent asking you
|
|
51
|
+
something), the side panel automatically lists the question and each option
|
|
52
|
+
(no manual text selection needed). Each question has "Bring all" and each
|
|
53
|
+
option has "Bring", both offering to **continue an existing side chat** or
|
|
54
|
+
**start a new one**. The list can be **collapsed / expanded**, and items can
|
|
55
|
+
be **deleted individually or all at once** (deleted items stay gone).
|
|
56
|
+
- **Deletable side chats.** Each entry in the side-chat list can be deleted
|
|
57
|
+
individually, or all of them at once via "Delete all".
|
|
58
|
+
- **Resolution-aware, resizable, collapsible panel.** Drag to resize
|
|
59
|
+
(280–720 px); the width is automatically capped to keep the panel within
|
|
60
|
+
~40% of the window and to leave the main chat usable, re-adapts when the
|
|
61
|
+
window is resized (different monitor, zoom), and is remembered across
|
|
62
|
+
reloads. Collapse and expand; no close button.
|
|
63
|
+
- **Language-aware.** The plugin follows DSH's language setting (Chinese /
|
|
64
|
+
English).
|
|
65
|
+
|
|
66
|
+
## Codex-style side chat, enhanced
|
|
67
|
+
|
|
68
|
+
This plugin is an **enhanced version of a Codex-style side chat**: a second,
|
|
69
|
+
agentic chat that works beside the main conversation — plus an extra capability
|
|
70
|
+
on top of the Codex-style base: side-chatting about the current **question
|
|
71
|
+
dialog** without interrupting the flow.
|
|
72
|
+
|
|
73
|
+
**The Codex-style base.** The side chat is a real DSH agent session, not a
|
|
74
|
+
scratchpad:
|
|
75
|
+
|
|
76
|
+
- It **inherits the main conversation's setup** — toolset, permission preset,
|
|
77
|
+
model / thinking effort, and working directory — so it can read and work with
|
|
78
|
+
the same workspace as the main conversation, subject to the permission preset
|
|
79
|
+
you choose for it.
|
|
80
|
+
- The **"Look up workspace / parent when needed"** switch (default off) lets it
|
|
81
|
+
read workspace files and the parent conversation's records when the task needs
|
|
82
|
+
more context.
|
|
83
|
+
- **Model / thinking effort / permission preset are adjustable per chat**, so a
|
|
84
|
+
hard task can be handed to a stronger model without touching the main
|
|
85
|
+
conversation.
|
|
86
|
+
- The final reply (or a summary of it) can be **brought back** into the main
|
|
87
|
+
conversation — into the composer draft or as a collapsed context row — the
|
|
88
|
+
Codex-style "hand the result over" without copy-pasting.
|
|
89
|
+
|
|
90
|
+
**The enhancement: question-dialog side chat, no flow interruption.** When the
|
|
91
|
+
main agent asks you something, the flow normally stops until you answer. This
|
|
92
|
+
plugin lets you keep moving: the side panel automatically lists the question and
|
|
93
|
+
every option; bring the whole question or any single option into a side chat
|
|
94
|
+
(new or existing), let the AI analyze it for you, then bring the answer back and
|
|
95
|
+
answer the dialog. The main conversation simply waits — nothing is interrupted,
|
|
96
|
+
and you never have to answer before you're ready.
|
|
97
|
+
|
|
98
|
+
## Requirements
|
|
99
|
+
|
|
100
|
+
- [Node.js](https://nodejs.org) ≥ 20
|
|
101
|
+
- [pnpm](https://pnpm.io)
|
|
102
|
+
- DSH ≥ `0.1.0-rc.6` (the harness `engines.dsh` constraint)
|
|
103
|
+
|
|
104
|
+
## Build
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
pnpm install
|
|
108
|
+
pnpm build
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`pnpm build` clears `lib/`, runs `tsc -p tsconfig.build.json` for type
|
|
112
|
+
declarations, then bundles the host (`lib/index.js`) and client
|
|
113
|
+
(`lib/client.js` + `lib/client-registry.js`) with tsdown.
|
|
114
|
+
|
|
115
|
+
## CI and publishing
|
|
116
|
+
|
|
117
|
+
[GitHub Actions](.github/workflows) covers two jobs:
|
|
118
|
+
|
|
119
|
+
- **[`ci.yml`](.github/workflows/ci.yml)** runs on every push to `main` and on
|
|
120
|
+
pull requests: it installs dependencies, typechecks, builds, runs the test
|
|
121
|
+
script, and packs the tarball (uploaded as an artifact) for Node 20 and 22.
|
|
122
|
+
- **[`publish.yml`](.github/workflows/publish.yml)** fires when a `v*` tag is
|
|
123
|
+
pushed: it builds and publishes the package to **npm** as
|
|
124
|
+
[`dsh-side-chat-plus`](https://www.npmjs.com/package/dsh-side-chat-plus),
|
|
125
|
+
authenticated with the `NPM_TOKEN` repository secret.
|
|
126
|
+
|
|
127
|
+
The package name is `dsh-side-chat-plus` (the plain `dsh-side-chat` name on npm
|
|
128
|
+
belongs to a different maintainer, so the release is published under the
|
|
129
|
+
`-plus` name).
|
|
130
|
+
|
|
131
|
+
> **Registry dependencies.** The harness packages this plugin targets (the DSH
|
|
132
|
+
> `0.1.2` API line) are published to npm as prereleases (`0.1.2-rc.1`) and, in a
|
|
133
|
+
> few cases, declare internal dependencies with a plain `>=0.1.2` range that
|
|
134
|
+
> npm/pnpm refuses to match against a prerelease. The developer `pnpm-workspace.yaml`
|
|
135
|
+
> therefore points the `@deepseek-ai/dsh-*` packages at a local harness checkout
|
|
136
|
+
> (absolute `D:/code/...` paths that exist only on the maintainer's machine). CI
|
|
137
|
+
> swaps that file for one whose overrides pin every `@deepseek-ai/dsh-*`
|
|
138
|
+
> dependency to `0.1.2-rc.1`, so installs resolve from the registry. On another
|
|
139
|
+
> machine, point the overrides at your own harness clone or use the CI workspace
|
|
140
|
+
> file as a template.
|
|
141
|
+
|
|
142
|
+
## Deploy
|
|
143
|
+
|
|
144
|
+
DSH web loads external plugins from the active profile. This package is a
|
|
145
|
+
**bundle**: its `package.json` declares `dsh.bundle.patch` →
|
|
146
|
+
[`cordis.patch.yml`](./cordis.patch.yml), whose `insert` row mounts the plugin.
|
|
147
|
+
That declaration is what lets `dsh plugin add` install the package *and*
|
|
148
|
+
activate it in one step.
|
|
149
|
+
|
|
150
|
+
> **Recommended: install from npm.** The package is published to
|
|
151
|
+
> [npm](https://www.npmjs.com/package/dsh-side-chat-plus) as
|
|
152
|
+
> `dsh-side-chat-plus`, so `dsh plugin add` needs no source checkout — the
|
|
153
|
+
> tarball ships the prebuilt `lib/` and is activated in one go.
|
|
154
|
+
|
|
155
|
+
### Install from npm
|
|
156
|
+
|
|
157
|
+
The built package is published to npm as [`dsh-side-chat-plus`](https://www.npmjs.com/package/dsh-side-chat-plus). Installed from the registry, the tarball ships the prebuilt `lib/` (plus `cordis.patch.yml` and `dsh.plugin.json`), so no source build is needed:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
npx -p @deepseek-ai/dsh dsh plugin --profile web add dsh-side-chat-plus
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`dsh plugin` reconciles the bundle into the profile's `dsh.profile.bundles`
|
|
164
|
+
layer list; the prebuilt `lib/` means nothing extra runs at install time.
|
|
165
|
+
Version falls out of the tagged release (see [CI and publishing](#ci-and-publishing)).
|
|
166
|
+
|
|
167
|
+
Restart `dsh web`, then hard-refresh the page (Ctrl/Cmd+Shift+R).
|
|
168
|
+
|
|
169
|
+
### Install from GitHub
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:heartmove/dsh-side-chat-plus
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
`dsh plugin` forwards to pnpm inside `~/.dsh/profiles/web/`, then reconciles the
|
|
176
|
+
bundle into the profile's `dsh.profile.bundles` layer list. A git install
|
|
177
|
+
fetches sources, so pnpm runs the package's `prepare` script (`tsdown`) to build
|
|
178
|
+
`lib/` from `src/` after checkout.
|
|
179
|
+
|
|
180
|
+
pnpm ≥ 10 refuses to run a git dependency's `prepare` script until it is
|
|
181
|
+
allowlisted, so the first `add` fails with an "Ignored build scripts" hint. Copy
|
|
182
|
+
the exact package key pnpm printed into the profile's `pnpm-workspace.yaml`
|
|
183
|
+
(`~/.dsh/profiles/web/pnpm-workspace.yaml`):
|
|
184
|
+
|
|
185
|
+
```yaml
|
|
186
|
+
allowBuilds:
|
|
187
|
+
dsh-side-chat-plus: true
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
then re-run the `add`. That allowance means "run this package's code on my
|
|
191
|
+
machine at install time" — only allow packages whose source you trust, and pin a
|
|
192
|
+
commit (`github:heartmove/dsh-side-chat-plus#<sha>`) so a later push cannot
|
|
193
|
+
silently change what runs.
|
|
194
|
+
|
|
195
|
+
Restart `dsh web`, then hard-refresh the page (Ctrl/Cmd+Shift+R).
|
|
196
|
+
|
|
197
|
+
### Install from a local checkout
|
|
198
|
+
|
|
199
|
+
From the directory that contains this checkout:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
npx -p @deepseek-ai/dsh dsh plugin --profile web add ./dsh-side-chat-plus
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
pnpm links the checkout and `dsh` activates the bundle the same way.
|
|
206
|
+
|
|
207
|
+
### Manual link
|
|
208
|
+
|
|
209
|
+
To manage the profile by hand, link the package and list it as a bundle in
|
|
210
|
+
`~/.dsh/profiles/web/package.json` (the bundle's own `cordis.patch.yml` supplies
|
|
211
|
+
the loader row, so no `insert` entry is needed):
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
{
|
|
215
|
+
"dependencies": {
|
|
216
|
+
"dsh-side-chat-plus": "link:D:\\path\\to\\dsh-side-chat-plus"
|
|
217
|
+
},
|
|
218
|
+
"dsh": {
|
|
219
|
+
"profile": {
|
|
220
|
+
"bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-side-chat-plus"]
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
(On POSIX systems use `link:/path/to/dsh-side-chat-plus`.) Then run `pnpm install`
|
|
227
|
+
in the profile directory and restart `dsh web`.
|
|
228
|
+
|
|
229
|
+
## Usage
|
|
230
|
+
|
|
231
|
+
1. Select part of any message in the main conversation.
|
|
232
|
+
2. A floating **"Ask in side chat"** button appears — click it.
|
|
233
|
+
- If a side chat already exists for this conversation, you'll also see
|
|
234
|
+
**"Continue active side chat"**.
|
|
235
|
+
3. The right-side panel opens (or expands) with the selected text staged in the
|
|
236
|
+
composer.
|
|
237
|
+
4. Adjust **model / effort** and **permission**, and toggle **"Look up workspace
|
|
238
|
+
/ parent when needed"** as desired.
|
|
239
|
+
5. Send. The reply streams back with markdown rendering and, where applicable,
|
|
240
|
+
a "Think" row for the model's reasoning.
|
|
241
|
+
6. Drag the panel's left edge to resize, or use the collapse/expand control.
|
|
242
|
+
|
|
243
|
+
### Sending behavior
|
|
244
|
+
|
|
245
|
+
By default (`sendImmediately` on), selecting text **sends it immediately** and
|
|
246
|
+
appends your configured **default prompt**. Turn `sendImmediately` off in
|
|
247
|
+
settings to stage the selection as an attachment instead, so you can review and
|
|
248
|
+
edit before sending.
|
|
249
|
+
|
|
250
|
+
### Bring replies back to the main conversation
|
|
251
|
+
|
|
252
|
+
Assistant replies in the side chat can be brought into the current main
|
|
253
|
+
conversation (**never sent**):
|
|
254
|
+
|
|
255
|
+
1. **Bring a selection.** Select part of an assistant reply in the side chat,
|
|
256
|
+
then choose **"Insert directly"** (verbatim) or **"Summarize & insert"** (the
|
|
257
|
+
side chat's inherited model summarizes it first) from the floating menu.
|
|
258
|
+
2. **Bring the whole reply.** Each assistant reply has **"Insert directly"** and
|
|
259
|
+
**"Summarize & insert"** buttons under its text, for inserting the full reply
|
|
260
|
+
(or its summary) in one click.
|
|
261
|
+
3. Per the **bring-back target** setting, the content is either **appended to
|
|
262
|
+
the main composer draft** (edit before sending) or **injected as a collapsed
|
|
263
|
+
context row** (source-tagged, not into the composer; the model sees it next
|
|
264
|
+
turn).
|
|
265
|
+
|
|
266
|
+

|
|
267
|
+
|
|
268
|
+
### Ask about the current question dialog
|
|
269
|
+
|
|
270
|
+
When the main conversation shows a question dialog, the side panel automatically
|
|
271
|
+
lists the question and its options:
|
|
272
|
+
|
|
273
|
+
1. While the panel is closed, a **floating entry** appears beside the dialog's
|
|
274
|
+
header — click it to open the panel.
|
|
275
|
+
2. Each question has "Bring all" and each option has "Bring", both offering to
|
|
276
|
+
**continue an existing side chat** or **start a new one**.
|
|
277
|
+
3. The list can be **collapsed / expanded**, and items can be **deleted
|
|
278
|
+
individually or all at once** (deleted items stay gone).
|
|
279
|
+
|
|
280
|
+
The main conversation keeps waiting on the dialog — nothing is interrupted; do
|
|
281
|
+
the research in the side chat first, then bring the answer back and answer the
|
|
282
|
+
dialog.
|
|
283
|
+
|
|
284
|
+

|
|
285
|
+
|
|
286
|
+
### Delete side chats
|
|
287
|
+
|
|
288
|
+
Each entry in the side-chat list has a "×" delete button; "Delete all" at the
|
|
289
|
+
top-right removes every side chat of the current conversation.
|
|
290
|
+
|
|
291
|
+
## Settings
|
|
292
|
+
|
|
293
|
+
Open DSH **Settings → 侧边聊天 (Side chat)** to configure:
|
|
294
|
+
|
|
295
|
+
| Setting | Default | Description |
|
|
296
|
+
| --- | --- | --- |
|
|
297
|
+
| `lookupDefault` | off | Whether the "look up workspace / parent" switch is on by default for new side chats. |
|
|
298
|
+
| `sendImmediately` | on | Whether selecting text sends it immediately, or stages it as an attachment. |
|
|
299
|
+
| `defaultPrompt` | *(empty)* | Extra prompt appended when the selection is sent immediately. |
|
|
300
|
+
| `bringMode` | `draft` | Where brought-back content lands: `draft` into the composer, or `context` as a collapsed context row. |
|
|
301
|
+
| `panelHome` | `sidebar-right` | Where the panel lives: `sidebar-right` docks it into the new built-in right sidebar as a "Side chat" tab (same rail as document previews, default); `floating` is the classic drag-resizable right-edge panel. In floating mode the side chat yields automatically while the built-in sidebar is open (docked, fullscreen or floated), so the two never cover each other. |
|
|
302
|
+
|
|
303
|
+
Preferences are stored in the DSH settings namespace `dsh-side-chat`.
|
|
304
|
+
|
|
305
|
+
## Project layout
|
|
306
|
+
|
|
307
|
+
```
|
|
308
|
+
src/
|
|
309
|
+
index.ts host plugin (routes, session/agent lifecycle, transcript folding)
|
|
310
|
+
wire.ts request/response helpers
|
|
311
|
+
trust-fence.ts loopback / trusted-API request guard
|
|
312
|
+
settings-shared.ts preference vocabulary shared by host and client
|
|
313
|
+
context-types.ts Cordis Context type augmentation
|
|
314
|
+
client/
|
|
315
|
+
index.tsx client plugin (panel, composer, settings section, floating buttons)
|
|
316
|
+
api.ts client↔host API types
|
|
317
|
+
locales.ts zh/en dictionaries
|
|
318
|
+
client.module.css panel/composer/settings styles
|
|
319
|
+
layout.css #root margin-right driven by panel width
|
|
320
|
+
cordis.patch.yml bundle patch layer (inserts the loader row; dsh.bundle.patch)
|
|
321
|
+
dsh.plugin.json external plugin manifest
|
|
322
|
+
tsdown.config.ts bundle config (client externals + CSS inlining)
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## License
|
|
326
|
+
|
|
327
|
+
[MIT](./LICENSE)
|