dsh-composer-plus 1.8.0 → 1.9.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.
- package/README.md +19 -3
- package/assets/features/deleteChat.webp +0 -0
- package/assets/features/projectName.webp +0 -0
- package/assets/features/turnRollback.webp +0 -0
- package/client.js +364 -7
- package/index.js +444 -7
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ dsh plugin --profile web add dsh-composer-plus
|
|
|
25
25
|
|
|
26
26
|
Then restart dsh. (The CLI can't install into the desktop profile; the app manages it.)
|
|
27
27
|
|
|
28
|
-
> dsh's pnpm skips versions younger than 24 hours. Right after a release, add the version: `dsh-composer-plus@1.
|
|
28
|
+
> dsh's pnpm skips versions younger than 24 hours. Right after a release, add the version: `dsh-composer-plus@1.9.1`.
|
|
29
29
|
|
|
30
30
|
## Features
|
|
31
31
|
|
|
@@ -34,6 +34,9 @@ Then restart dsh. (The CLI can't install into the desktop profile; the app manag
|
|
|
34
34
|
| **Changes panel** | Right sidebar → `+` → **Changes**. Pick **Uncommitted**, **Unstaged**, **Staged** or **Branch** to see changed files with `+/-` counts; click a file for its diff. **Last Turn** opens dsh's own review of the latest turn. | <a href="assets/features/changesPanel.webp"><img src="assets/features/changesPanel.webp" width="160" alt="Changes panel screenshot"></a> |
|
|
35
35
|
| **Feature ideas** | Right sidebar → `+` → **Feature ideas** → **Suggest features**. The chat's own model reads a short summary of the chat's project (top-level files, the README and manifest heads, the last 15 commits) and suggests up to 8 features, shown as a stack of cards in dsh's UI language. Swipe a card right (or click **✓**, or press `→`; the card flies off to its side in each case) to start a new chat in the same project: it starts in plan mode with the idea as the request, so nothing changes before you approve the plan. Swipe left (or **✕**, or `←`) to skip; **Undo** (or `Z`) brings a skipped card back. Click **↓** (or press `↓`) to save a good idea for later: it goes to the project's **Later** list, which every chat in the same project folder shows (also after a restart). **Later (N)** opens the list; **Plan** starts the same plan-mode chat for the idea and takes it off the list, **Remove from the list** deletes it. **More ideas** adds cards. The model runs only when you click. | <a href="assets/features/featureIdeas.webp"><img src="assets/features/featureIdeas.webp" width="160" alt="Feature ideas screenshot"></a> |
|
|
36
36
|
| **Content search** | dsh's own sidebar search (the magnifier next to **Workspaces**; `Cmd+K` in the desktop app, `Cmd+Alt+K` in a browser) also finds chats by the words in your messages and in the replies, not only by title, and shows the matching text under the chat. dsh already has this search, but ships it switched off; this feature switches it on with a search index file on your computer. The index is made at the first search after a start (about 15 s for 250 chats, see Limits) and is kept for the next starts. On by default; a change applies after you restart dsh. | <a href="assets/features/contentSearch.webp"><img src="assets/features/contentSearch.webp" width="160" alt="Content search screenshot"></a> |
|
|
37
|
+
| **Turn rollback** | Hover one of your messages and click **↶** (next to Copy). **Chat only** takes that message and everything after it (replies, tool calls) out of the chat and out of the model's context, and puts the message back in the composer: change it and send it again. **Chat and files** first lists the project files that changed since that message, then also puts them back as they were, including changes made by commands (`bash`), not only by dsh's edit tools. A running turn stops first. The chat log is never rewritten: one hidden marker hides the withdrawn part, the same way dsh's own `/compact` hides old messages. When [dsh-rewind-plugin](https://www.npmjs.com/package/dsh-rewind-plugin) is installed, it does this job and Composer Plus shows no second button. | <a href="assets/features/turnRollback.webp"><img src="assets/features/turnRollback.webp" width="160" alt="Turn rollback screenshot"></a> |
|
|
38
|
+
| **Delete chat** | Sidebar → a chat's **…** menu (or right-click) → **Delete…** → **Delete**. dsh itself can only archive. The chat stops (its turn, jobs, subagents and schedules, like dsh's own archive) and its saved history, with its subagent chats, moves to the macOS Trash (on other systems: `$DSH_HOME/trash`). To get it back, put the folder back and restart dsh: it shows in the sidebar's **Archived only** view. | <a href="assets/features/deleteChat.webp"><img src="assets/features/deleteChat.webp" width="160" alt="Delete chat screenshot"></a> |
|
|
39
|
+
| **Project name in the composer** | The row under the composer (turns, tokens, cache hit, context) starts with the chat's project name, so you always see which project a chat works in. It is dsh's own project title, or the folder name when the project has no title. Hover it to see the full folder path. | <a href="assets/features/projectName.webp"><img src="assets/features/projectName.webp" width="160" alt="Project name in the composer screenshot"></a> |
|
|
37
40
|
| **Input history** | In an empty composer, press `↑` / `↓` to walk through messages you sent, like a terminal. | <a href="assets/features/inputHistory.webp"><img src="assets/features/inputHistory.webp" width="160" alt="Input history screenshot"></a> |
|
|
38
41
|
| **Plan mode shortcut** | `Shift+Tab` adds `/plan ` to the start of the draft (press again to remove it). If the chat is already in plan mode, `Shift+Tab` leaves it. | <a href="assets/features/planToggle.webp"><img src="assets/features/planToggle.webp" width="160" alt="Plan mode shortcut screenshot"></a> |
|
|
39
42
|
| **Keep composer focus** | After you send a `/` command or skill, the cursor stays in the composer, and you can type again at once. This also works for keyboard macros that type a command and press `Enter`. dsh makes the composer read-only while it resolves the command, and the browser then removes the focus. This feature puts the focus back, unless a menu, a dialog or another field has it. | <a href="assets/features/keepFocus.webp"><img src="assets/features/keepFocus.webp" width="160" alt="Keep composer focus screenshot"></a> |
|
|
@@ -57,7 +60,7 @@ Buttons, tooltips, notices and notifications follow the selected dsh language (s
|
|
|
57
60
|
|
|
58
61
|
## Settings
|
|
59
62
|
|
|
60
|
-
Every feature can be switched on or off on its own: dsh **Settings → Composer Plus**. Each row has a small screenshot: hover it for a larger preview, click it to open it full size (`Esc` closes). The **Search features** box at the top filters the page by name or description (any language, case- and accent-insensitive); `Esc` clears it. Each row has a switch and a short description; changes apply immediately, without a restart, and are remembered on that device. Everything is on by default, except **Mobile connect** and **Resume after restart**. dsh's Host keeps the switches of these two and of **Content search**, so they apply to every window and survive a restart. **Content search** changes only after a dsh restart (dsh reads it at start); until then its row says **Restart dsh to apply this change.**
|
|
63
|
+
Every feature can be switched on or off on its own: dsh **Settings → Composer Plus**. Each row has a small screenshot: hover it for a larger preview, click it to open it full size (`Esc` closes). The **Search features** box at the top filters the page by name or description (any language, case- and accent-insensitive); `Esc` clears it. Each row has a switch and a short description; changes apply immediately, without a restart, and are remembered on that device. Everything is on by default, except **Mobile connect** and **Resume after restart**. dsh's Host keeps the switches of these two and of **Content search** and **Turn rollback**, so they apply to every window and survive a restart. **Content search** changes only after a dsh restart (dsh reads it at start); until then its row says **Restart dsh to apply this change.**
|
|
61
64
|
|
|
62
65
|
<p align="center"><img src="docs/images/settings.webp" width="720" alt="Settings → Composer Plus: feature search, language picker, update row and a switch per feature, with a screenshot preview on hover"></p>
|
|
63
66
|
|
|
@@ -99,6 +102,8 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
|
|
|
99
102
|
- **Changes panel:** git runs read-only on your machine, in the chat's own folder, through dsh's authenticated `/api` channel. It never commits, stages or fetches, and only shows paths git itself listed.
|
|
100
103
|
- **Feature ideas:** nothing runs until you click **Suggest features**. Then the Host half reads only the chat's own folder (the browser never sends a path): the names of the top-level entries, the first 6 kB of the README, AGENTS.md and the manifest (`package.json`, `pyproject.toml`, `Cargo.toml`, `go.mod`, …) and `git log --oneline -15`, at most 16 kB in total. It skips `.env*`, key files and folders such as `node_modules`, and it reads only regular files that stay inside the folder: a symlink that points out of the folder, a FIFO or a device is skipped. This summary goes to the model that the chat uses, through dsh's own provider settings, as one request; it is not added to any chat. Nothing in the project is written. A swiped-right idea starts a new chat in plan mode, so approvals and plan review apply as usual. Ideas saved for later (title, summary, why, effort) are kept with the project's folder path in `storages/dsh-composer-plus/later.json` under the dsh home (owner-only file); nothing goes into the project.
|
|
101
104
|
- **Content search:** no new code searches your chats: the plugin only switches on dsh's own message index (SQLite FTS5, `dsh-session-query-sqlite`) and gives it a file, `$DSH_HOME/cache/composer-plus/session-search.db` (owner-only file and folder). The file holds the text of your user and assistant messages, so it is as private as the chat logs in `$DSH_HOME/sessions`. Nothing leaves your machine. It is a copy that dsh can make again: you can delete it while dsh is closed. The switch is in `$DSH_HOME/storages/dsh-composer-plus/content-search.json`.
|
|
105
|
+
- **Turn rollback:** before each of your messages, the Host takes a git snapshot of the chat's folder in its own store, `$DSH_HOME/cache/composer-plus/rollback/<chat>.git` (owner-only folder). It holds copies of the files in that folder that git sees (not ignored files), so it is as private as the project. It reads your repository's objects (no copy of what git already has) and never writes your repository's index, `HEAD`, branches, tags, stash or config; the only change git makes there is a newer time stamp on object files it reuses (this delays their cleanup by `git gc`). A rollback with files writes only regular files inside the chat's folder; it skips symlinks, pipes and anything outside the folder. Nothing leaves your machine. You can delete the store while dsh is closed (rollback then works for the chat only, until new messages). **Delete chat** deletes a chat's store too. The switch is in `$DSH_HOME/storages/dsh-composer-plus/rollback.json`.
|
|
106
|
+
- **Delete chat:** moves the chat's own log folders (`$DSH_HOME/sessions/<project>/<chat>`) to the Trash. It does not touch the project folder.
|
|
102
107
|
- **Allow for this chat:** grants are stored in `$DSH_HOME/storages/dsh-composer-plus/grants.json` (owner-only permissions). A grant covers **one exact tool in one chat**. If that tool can write, the grant covers any write too. Revoke it from the header chip.
|
|
103
108
|
- Auto Review still runs on every call; review failures are never auto-allowed.
|
|
104
109
|
- **Mobile connect:** off until you switch it on. While it is on, the Host half runs the Tether gateway: HTTPS on port 19390 that accepts only your Wi-Fi subnet and your tailnet (100.64.0.0/10), and a pairing page on `127.0.0.1:19391` (this Mac only). A phone needs a one-time code from the QR code (5 minutes) and your **Approve** on the Mac. The phone pins the gateway's certificate. The Mac keeps only a hash of each phone's token (30 days, renewed while used); **Revoke** closes that phone's connections at once. Phones can call only an allowlist of dsh methods (chats, prompts, attachments, slash commands, approvals, questions, models, agents, goals), not settings, credentials, the file browser or the terminal. Data: `$DSH_HOME/storages/dsh-composer-plus/mobile/`. Details: [tether/README.md](tether/README.md).
|
|
@@ -112,8 +117,11 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
|
|
|
112
117
|
- **Mobile connect says the gateway is not running:** "no IPv4 address on en0" means this Mac has no Wi-Fi/Ethernet address; "EADDRINUSE" means another dsh (or app) uses port 19390 or 19391. Only one dsh can run Mobile connect at a time.
|
|
113
118
|
- **Mobile connect, Resume after restart or Content search says "Restart dsh":** the plugin was updated while dsh was running (or, for Content search, you changed the switch); the new state loads after a restart.
|
|
114
119
|
- **The search finds only titles:** Content search is off, dsh has not restarted since you switched it on or installed the plugin, or the word is only in a tool output (see Limits).
|
|
120
|
+
- **No ↶ button on my messages:** Turn rollback is off, the chat is a subagent chat, or dsh-rewind-plugin is installed (use its ↶ button). After an update, restart dsh.
|
|
121
|
+
- **Chat and files is greyed out:** the project is not a git repository, there is no snapshot from before that message (the message is older than the plugin, or one of the 50 newest snapshots replaced it), or no file changed.
|
|
122
|
+
- **Delete says another dsh has this chat open:** a second dsh on the same dsh home holds the chat's lock. Close that window or dsh, then delete again. The chat stays archived meanwhile.
|
|
115
123
|
- **A chat did not continue after a restart:** Resume after restart was off when dsh quit, you stopped that turn yourself, the turn had ended (done or failed), the chat was archived, or more than 20 chats were running (the newest 20 continue).
|
|
116
|
-
- **Install fails right after a release:** add the version (`dsh-composer-plus@1.
|
|
124
|
+
- **Install fails right after a release:** add the version (`dsh-composer-plus@1.9.1`), see the install note above.
|
|
117
125
|
|
|
118
126
|
## Limits
|
|
119
127
|
|
|
@@ -124,6 +132,8 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
|
|
|
124
132
|
- **Content search** is dsh's own search, so it has dsh's limits. It searches only user and assistant messages: not tool output (commands, file contents, results), not reasoning, and it has no filter for user, assistant or tool messages. It matches whole words, not parts of a word (`deploy` does not find `deployment`); letters with accents match without them (`seker` finds `şeker`). One row per chat, with dsh's 240-character snippet, at most 20 rows.
|
|
125
133
|
- **Content search** cost, measured on a copy of 247 real chat logs (159 MB, dsh 0.2.1-rc.2, Apple Silicon, 32 GB): the first search after a start builds the index in about 15 s. During that time dsh's Host answers nothing for about 7 s, so other chats stop streaming for that moment (the page itself does not freeze). The Host's memory grows by about 1.1 GB at the peak; one minute later it is still about 0.5–0.6 GB above the start, until dsh quits. The index file is about 165 MB. Later searches take about 0.5 s. After a restart, the first search takes about 1 s (only new or changed chats are added) and adds about 70 MB. Switch it off if your computer has little memory.
|
|
126
134
|
- **Content search** applies only after a dsh restart, and the index file is shared by every dsh that uses the same dsh home: run only one such dsh at a time (dsh allows one owner per index file).
|
|
135
|
+
- **Turn rollback** puts files back only in a git repository, and only in the chat's folder. It keeps the 50 newest snapshots per chat. Ignored files (`.gitignore`, `info/exclude`, your global ignore file), empty folders, symlinks and submodules are not put back; a file that was ignored when the snapshot was taken is never deleted, even when the turn changed the ignore rules. A file that git cannot read is left out of the snapshot. Each of your messages runs one `git add --all` of the chat's folder into the private store: in a very large folder with many untracked files this can take a few seconds, and the next tool call waits for it (at most 10 s; the snapshot then finishes in the background). If your repository's `git gc` removes an object that an old snapshot needs, that file is listed as not put back. Only the text of the message comes back into the composer: add its images or files again. Subagent chats have no ↶ (a subagent's file changes count as changes of the chat that started it). The exported chat (`/export`) still has the withdrawn messages. The idea of one hidden marker that withdraws part of a chat comes from [dsh-rewind-plugin](https://github.com/SiriLee/dsh-rewind) by SiriLee (MIT); Composer Plus uses no code from it.
|
|
136
|
+
- **Delete chat** needs dsh's archive (dsh 0.2.0 and later). A chat (or one of its subagent chats) that does not stop within 15 s, or that another dsh holds, stays archived and nothing moves. On other systems than macOS the trash folder must be on the same disk as the chat history. An open chat that you delete stays in dsh's memory, archived and hidden, until dsh restarts. Empty the Trash yourself; dsh does not.
|
|
127
137
|
- dsh's queue has no `move` action, so a reorder rewrites the affected rows' text. If the agent picks up a row mid-move, the move is undone and nothing is lost. Messages with images or files can't be moved.
|
|
128
138
|
- An update needs a dsh restart to take effect; the plugin never restarts dsh for you. Web/CLI profiles without dsh's plugin manager only report a new version.
|
|
129
139
|
- **Keep composer focus** gives the focus back only after a `/` command or skill. While dsh resolves the command, the composer stays read-only for a few milliseconds, so keys pressed in that time are lost. If dsh's `/` menu is still open, `Enter` picks the highlighted row and does not send.
|
|
@@ -143,6 +153,10 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-rc.2` (web). CI runs the
|
|
|
143
153
|
|
|
144
154
|
**Can the dsh sidebar search find a chat by a word in its messages, not only its title?** Yes, with **Content search** (on by default): restart dsh once after you install the plugin, then use the magnifier next to **Workspaces**. Matching chats show the text around the word.
|
|
145
155
|
|
|
156
|
+
**Can I undo a turn and edit my prompt, like in OpenCode or Claude Code?** Yes, with **Turn rollback**: click **↶** on the message, choose **Chat and files**, edit the text that comes back in the composer and send it.
|
|
157
|
+
|
|
158
|
+
**Can I delete a chat instead of archiving it?** Yes, with **Delete chat**: **…** → **Delete…**. The history goes to the Trash, so a mistake can be undone.
|
|
159
|
+
|
|
146
160
|
**How do I get ↑/↓ message history in the dsh composer?** Install this plugin; in an empty composer `↑` / `↓` walk through messages you sent.
|
|
147
161
|
|
|
148
162
|
**How do I continue a stopped or failed dsh turn without typing "continue"?** With this plugin the Send button becomes **▶** after a stopped, failed or cut-off turn; one click resumes it.
|
|
@@ -191,6 +205,8 @@ SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-resume-restart.mjs /path
|
|
|
191
205
|
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-feature-ideas.mjs /path/to/dsh/lib/bin.js
|
|
192
206
|
# Content search (fake model, made-up chats): a message-only word finds its chat with the snippet, switch off + restart = titles only + its thumbnail
|
|
193
207
|
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-content-search.mjs /path/to/dsh/lib/bin.js
|
|
208
|
+
# Turn rollback + Delete chat (fake model, made-up git project): bash edit → ↶ Chat and files → files back, .git unchanged; Delete… → Trash + its thumbnails
|
|
209
|
+
SHOT=1 PLAYWRIGHT=/path/to/playwright node test/browser-turn-rollback.mjs /path/to/dsh/lib/bin.js
|
|
194
210
|
```
|
|
195
211
|
|
|
196
212
|
```sh
|
|
Binary file
|
|
Binary file
|
|
Binary file
|