dsh-composer-plus 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/client.js +26 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ dsh plugin --profile web add dsh-composer-plus
|
|
|
21
21
|
|
|
22
22
|
Then restart dsh. (The CLI can't install into the desktop profile; the app manages it.)
|
|
23
23
|
|
|
24
|
-
> dsh's pnpm skips versions younger than 24 hours. Right after a release, add the version: `dsh-composer-plus@1.0.
|
|
24
|
+
> dsh's pnpm skips versions younger than 24 hours. Right after a release, add the version: `dsh-composer-plus@1.0.2`.
|
|
25
25
|
|
|
26
26
|
## Features
|
|
27
27
|
|
|
@@ -30,7 +30,7 @@ Then restart dsh. (The CLI can't install into the desktop profile; the app manag
|
|
|
30
30
|
| **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. |
|
|
31
31
|
| **Input history** | In an empty composer, press `↑` / `↓` to walk through messages you sent, like a terminal. |
|
|
32
32
|
| **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. |
|
|
33
|
-
| **One-click Continue** | When
|
|
33
|
+
| **One-click Continue** | When the last turn was stopped, failed or cut off and the composer is empty, Send turns into **▶**. One click sends “continue” in dsh's language (`continue` / `继续`). A turn that finished normally keeps the regular Send button. |
|
|
34
34
|
| **Queue drag-and-drop** | Queued messages get a grip (⠿). Drag to reorder, or focus the grip and press `↑` / `↓`. `Esc` cancels. |
|
|
35
35
|
| **Copy deeplink** | Right-click a chat in the sidebar → **Copy deeplink**. Paste the `dsh-session:…` link into another chat to attach that chat as read-only context. |
|
|
36
36
|
| **Allow for this chat** | When Auto Review asks you, the approval card gets **Allow for this chat**: the same tool in the same chat is allowed from then on, with any arguments. A header chip lists the grants and revokes them. Grants survive a restart. |
|
|
@@ -69,7 +69,7 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-alpha.2` (web). CI runs
|
|
|
69
69
|
|
|
70
70
|
- **No notifications on macOS:** System Settings → Notifications → DeepSeek Harness → allow. Choose **Alerts** to keep them on screen.
|
|
71
71
|
- **▶, queue grips, project status, Allow for this chat or right-click missing after a dsh update:** these attach to dsh's current HTML because dsh has no slot for them yet. If dsh changes that markup they hide themselves; nothing else breaks. Please open an [issue](https://github.com/furkancak1r/dsh-composer-plus/issues).
|
|
72
|
-
- **Install fails right after a release:** add the version (`dsh-composer-plus@1.0.
|
|
72
|
+
- **Install fails right after a release:** add the version (`dsh-composer-plus@1.0.2`), see the install note above.
|
|
73
73
|
|
|
74
74
|
## Limits
|
|
75
75
|
|
package/client.js
CHANGED
|
@@ -207,12 +207,25 @@ window.__ModuleLoader__.load({
|
|
|
207
207
|
const buttons = [...seat.querySelectorAll('button')].filter((b) => /(^|\s)\w+_primary(\s|$)/.test(b.className));
|
|
208
208
|
return buttons.length === 0 ? null : buttons[buttons.length - 1];
|
|
209
209
|
}
|
|
210
|
-
/**
|
|
211
|
-
*
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
210
|
+
/** True when the newest turn in the loaded window did not finish normally: stopped, failed, cut by a token
|
|
211
|
+
* limit, or still open without a running agent (lost connection). A completed turn needs no resume. */
|
|
212
|
+
function needsResume(entries) {
|
|
213
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
214
|
+
const event = entries[i].event;
|
|
215
|
+
if (event.type === 'turn/end') return event.data?.reason?.kind !== 'completed';
|
|
216
|
+
if (event.type === 'turn/start') return true;
|
|
217
|
+
}
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
/** Codex-style resume: when the last turn was stopped or failed, the composer is empty and the chat has
|
|
221
|
+
* history, Send turns into a play button that submits "continue". A normally completed turn keeps dsh's
|
|
222
|
+
* own Send. Send is not a slot, so the play button is portaled into Send's row with Send's own class and
|
|
223
|
+
* Send is hidden meanwhile. Hidden on a blank chat, while running, in subagent views, or as soon as the
|
|
224
|
+
* user types or attaches. */
|
|
225
|
+
function ContinueButton({ useSession, useInput, useTurnEnd, inputActions, t }) {
|
|
226
|
+
const ended = typeof useTurnEnd === 'function' ? useTurnEnd((window) => window !== undefined && needsResume(window.entries)) : false;
|
|
227
|
+
const failed = useSession((s) => s !== undefined && (s.lastAgentError != null || s.promptError != null));
|
|
228
|
+
const show = useSession((s) => s !== undefined && !s.blank && !s.running && s.subagent === null && !s.removed) && (ended || failed);
|
|
216
229
|
const idle = useInput((s) => s !== undefined && s.phase === 'plain' && s.draft.trim() === '' && s.attachmentIds.length === 0);
|
|
217
230
|
const visible = show && idle && inputActions !== undefined;
|
|
218
231
|
const anchorRef = React.useRef(null);
|
|
@@ -877,6 +890,11 @@ window.__ModuleLoader__.load({
|
|
|
877
890
|
id: 'composer-continue',
|
|
878
891
|
order: 1000,
|
|
879
892
|
locale: LOCALE_NS,
|
|
893
|
+
inject: (sessionId) => {
|
|
894
|
+
// The session's loaded event window; its newest turn/end says how the last turn finished.
|
|
895
|
+
const source = ctx.sessions?.binding?.(sessionId)?.eventSource;
|
|
896
|
+
return source === undefined ? {} : { hooks: { turnEnd: source } };
|
|
897
|
+
},
|
|
880
898
|
}, ContinueButton))]);
|
|
881
899
|
if (ctx.locale !== undefined) ctx.effect(() => ctx.locale.register(LOCALE_NS, {
|
|
882
900
|
en: {
|
|
@@ -893,7 +911,7 @@ window.__ModuleLoader__.load({
|
|
|
893
911
|
'feature.allowForChat': 'Allow for this chat',
|
|
894
912
|
'feature.allowForChat.description': 'Add “Allow for this chat” to Auto Review approvals and auto-allow granted tools.',
|
|
895
913
|
'feature.continueButton': 'One-click Continue',
|
|
896
|
-
'feature.continueButton.description': 'Turn Send into ▶ after a stopped turn; one click sends “continue”.',
|
|
914
|
+
'feature.continueButton.description': 'Turn Send into ▶ after a stopped or failed turn; one click sends “continue”.',
|
|
897
915
|
'feature.inputHistory': 'Input history',
|
|
898
916
|
'feature.inputHistory.description': 'Use ↑ / ↓ in an empty composer to reuse messages you sent.',
|
|
899
917
|
'feature.planToggle': 'Shift+Tab plan mode',
|
|
@@ -960,7 +978,7 @@ window.__ModuleLoader__.load({
|
|
|
960
978
|
'feature.allowForChat': '本对话内允许',
|
|
961
979
|
'feature.allowForChat.description': '在 Auto Review 审批中添加“本对话内允许”,并自动允许已授权的工具。',
|
|
962
980
|
'feature.continueButton': '一键继续',
|
|
963
|
-
'feature.continueButton.description': '
|
|
981
|
+
'feature.continueButton.description': '回合被停止或出错后,发送按钮变为 ▶,点击即发送“继续”。',
|
|
964
982
|
'feature.inputHistory': '输入历史',
|
|
965
983
|
'feature.inputHistory.description': '在空输入框中按 ↑ / ↓ 复用已发送的消息。',
|
|
966
984
|
'feature.planToggle': 'Shift+Tab 计划模式',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-composer-plus",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "DeepSeek Harness helpers: Codex-style Changes panel, input history, Shift+Tab /plan, one-click Continue, queue drag-and-drop, Copy deeplink, Auto Review allow-for-chat, background notifications",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|