dsh-composer-plus 1.0.0 → 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 +4 -4
- package/client.js +34 -11
- 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,12 +30,12 @@ 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. |
|
|
37
37
|
| **Project status** | A project row in the sidebar shows the same spinner / waiting / done marker as its chats, so a collapsed project still tells you a chat inside is working or needs you. Hover it for details. |
|
|
38
|
-
| **Active projects first** | When a chat starts running or needs you, its project moves to the top of the sidebar with dsh's own row animation (the same move as dragging it there). Finished projects stay where they are; drag them anywhere as usual. |
|
|
38
|
+
| **Active projects first** | When a chat starts running or needs you, its project moves to the top of the sidebar with dsh's own row animation (the same move as dragging it there). Finished projects stay where they are; drag them anywhere as usual. Moves are saved to dsh's project order, so turning this off keeps the current order. |
|
|
39
39
|
| **Background notifications** | While dsh is in the background you get a notification when a turn finishes (first line of the reply), or when a chat needs an approval (tool name), an answer (the question) or a plan review. The Dock/taskbar badge counts waiting chats. Clicking opens that chat. |
|
|
40
40
|
|
|
41
41
|
All text — buttons, tooltips, notices, notifications and the Continue message — follows the language selected in dsh (English or Chinese, the two languages dsh ships). Switching the language in dsh settings updates it live.
|
|
@@ -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: {
|
|
@@ -887,13 +905,13 @@ window.__ModuleLoader__.load({
|
|
|
887
905
|
'feature.projectStatus': 'Project status',
|
|
888
906
|
'feature.projectStatus.description': 'Show the running / waiting / done marker of a project\'s chats on the project row.',
|
|
889
907
|
'feature.activeProjectsFirst': 'Active projects first',
|
|
890
|
-
'feature.activeProjectsFirst.description': 'Move a project to the top of the sidebar when one of its chats runs or needs you.',
|
|
908
|
+
'feature.activeProjectsFirst.description': 'Move a project to the top of the sidebar when one of its chats runs or needs you. Moves are saved; turning this off keeps the current order.',
|
|
891
909
|
'feature.notifications': 'Background notifications',
|
|
892
910
|
'feature.notifications.description': 'Notify when a chat finishes or needs you while dsh is in the background, with a Dock badge.',
|
|
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',
|
|
@@ -954,13 +972,13 @@ window.__ModuleLoader__.load({
|
|
|
954
972
|
'feature.projectStatus': '项目状态',
|
|
955
973
|
'feature.projectStatus.description': '在项目行上显示其对话的进行中 / 等待 / 完成标记。',
|
|
956
974
|
'feature.activeProjectsFirst': '活跃项目置顶',
|
|
957
|
-
'feature.activeProjectsFirst.description': '
|
|
975
|
+
'feature.activeProjectsFirst.description': '当项目中的对话正在运行或需要你处理时,将该项目移到侧边栏顶部。移动会被保存;关闭此项后保留当前顺序。',
|
|
958
976
|
'feature.notifications': '后台通知',
|
|
959
977
|
'feature.notifications.description': 'dsh 在后台时,对话完成或需要你处理时发出通知,并显示程序坞角标。',
|
|
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 计划模式',
|
|
@@ -1019,7 +1037,12 @@ window.__ModuleLoader__.load({
|
|
|
1019
1037
|
id: 'project-status',
|
|
1020
1038
|
locale: LOCALE_NS,
|
|
1021
1039
|
}, ProjectStatusMarkers))]);
|
|
1022
|
-
|
|
1040
|
+
// ctx.inject returns a Cordis fiber, not a disposer.
|
|
1041
|
+
const injectScope = (deps, setup) => {
|
|
1042
|
+
if (ctx.inject === undefined) return [];
|
|
1043
|
+
const fiber = ctx.inject(deps, setup);
|
|
1044
|
+
return [() => fiber.dispose()];
|
|
1045
|
+
};
|
|
1023
1046
|
feature('notifications', () => injectScope(['uiSession', 'uiWorkspace', 'sessions'], (scope) => {
|
|
1024
1047
|
const t = ctx.locale.bind(LOCALE_NS);
|
|
1025
1048
|
scope.effect(() => watchAttention(scope.uiSession.sessionStatus, scope.sessions.list, t,
|
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",
|