dsh-composer-plus 0.6.2 → 0.7.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.
Files changed (3) hide show
  1. package/README.md +4 -4
  2. package/client.js +25 -10
  3. 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@0.6.2`.
24
+ > dsh's pnpm skips versions younger than 24 hours. Right after a release, add the version: `dsh-composer-plus@0.7.0`.
25
25
 
26
26
  ## Features
27
27
 
@@ -30,13 +30,13 @@ 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 a turn has stopped and the composer is empty, Send turns into **▶**. One click sends `continue`. |
33
+ | **One-click Continue** | When a turn has stopped and the composer is empty, Send turns into **▶**. One click sends “continue” in dsh's language (`continue` / `继续`). |
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
  | **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. |
38
38
 
39
- Labels follow dsh's language (English or Chinese).
39
+ 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.
40
40
 
41
41
  ## Keyboard shortcuts
42
42
 
@@ -63,7 +63,7 @@ Tested on dsh `0.2.0-rc.2` (desktop and web) and `0.2.1-alpha.2` (web). CI runs
63
63
 
64
64
  - **No notifications on macOS:** System Settings → Notifications → DeepSeek Harness → allow. Choose **Alerts** to keep them on screen.
65
65
  - **▶, queue grips, 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).
66
- - **Install fails right after a release:** add the version (`dsh-composer-plus@0.6.2`), see the install note above.
66
+ - **Install fails right after a release:** add the version (`dsh-composer-plus@0.7.0`), see the install note above.
67
67
 
68
68
  ## Limits
69
69
 
package/client.js CHANGED
@@ -196,7 +196,6 @@ window.__ModuleLoader__.load({
196
196
  return React.createElement('span', { ref: anchor, hidden: true });
197
197
  }
198
198
 
199
- const CONTINUE_TEXT = 'continue';
200
199
  /** Dictionary namespace for this plugin's menu copy; dsh ships `en` and `zh`. */
201
200
  const LOCALE_NS = 'dsh-composer-plus';
202
201
  let createPortal;
@@ -212,7 +211,7 @@ window.__ModuleLoader__.load({
212
211
  * Send turns into a play button that submits "continue". Send is not a slot, so the play button is
213
212
  * portaled into Send's row with Send's own class and Send is hidden meanwhile.
214
213
  * Hidden on a blank chat, while running, in subagent views, or as soon as the user types or attaches. */
215
- function ContinueButton({ useSession, useInput, inputActions }) {
214
+ function ContinueButton({ useSession, useInput, inputActions, t }) {
216
215
  const show = useSession((s) => s !== undefined && !s.blank && !s.running && s.subagent === null && !s.removed);
217
216
  const idle = useInput((s) => s !== undefined && s.phase === 'plain' && s.draft.trim() === '' && s.attachmentIds.length === 0);
218
217
  const visible = show && idle && inputActions !== undefined;
@@ -228,15 +227,17 @@ window.__ModuleLoader__.load({
228
227
  const anchor = React.createElement('span', { ref: anchorRef, hidden: true, 'aria-hidden': true });
229
228
  if (!visible || host === null) return anchor;
230
229
  const onClick = () => {
231
- if (React.flushSync !== undefined) React.flushSync(() => inputActions.setDraft(CONTINUE_TEXT));
232
- else inputActions.setDraft(CONTINUE_TEXT);
230
+ // The sent message follows dsh's language, so the model reads it in the user's own language.
231
+ const text = t('continue.message');
232
+ if (React.flushSync !== undefined) React.flushSync(() => inputActions.setDraft(text));
233
+ else inputActions.setDraft(text);
233
234
  inputActions.submit();
234
235
  };
235
236
  const button = React.createElement('button', {
236
237
  type: 'button',
237
238
  className: host.className,
238
- title: 'Continue',
239
- 'aria-label': 'Continue',
239
+ title: t('continue.label'),
240
+ 'aria-label': t('continue.label'),
240
241
  onMouseDown: (event) => event.preventDefault(),
241
242
  onClick,
242
243
  }, React.createElement('svg', { viewBox: '0 0 16 16', width: 16, height: 16, 'aria-hidden': true },
@@ -255,7 +256,7 @@ window.__ModuleLoader__.load({
255
256
  * so nothing is lost or duplicated.
256
257
  * shortcut: grips are portaled into QueueDock rows found in the DOM; if a dsh update changes that markup the
257
258
  * grips just stop appearing — upgrade when dsh exposes a queue row slot or a native move action. */
258
- function QueueReorder({ useSession, useProjection, updateQueue, notify }) {
259
+ function QueueReorder({ useSession, useProjection, updateQueue, notify, t }) {
259
260
  const inbox = useProjection('inbox');
260
261
  const pending = useSession((s) => (s === undefined ? undefined : s.pendingSubmissions));
261
262
  const mutable = useSession((s) => s !== undefined && (s.subagent === null || s.subagent.address.mode === 'continuable'));
@@ -320,7 +321,7 @@ window.__ModuleLoader__.load({
320
321
  }
321
322
  } catch {
322
323
  for (const change of done.reverse()) await edit(change.row, change.prev).catch(() => undefined);
323
- notify('error', 'Reorder failed: a message may have already started sending.');
324
+ notify('error', t('queue.failed'));
324
325
  } finally {
325
326
  setBusy(false);
326
327
  }
@@ -375,8 +376,8 @@ window.__ModuleLoader__.load({
375
376
  const draggable = texts[index] !== null && !busy;
376
377
  const grip = React.createElement('button', {
377
378
  type: 'button',
378
- title: draggable ? 'Drag to reorder (or ↑/↓)' : 'Messages with images/files cannot be moved',
379
- 'aria-label': 'Reorder queued message',
379
+ title: draggable ? t('queue.drag') : t('queue.locked'),
380
+ 'aria-label': t('queue.grip'),
380
381
  disabled: !draggable,
381
382
  onPointerDown: (event) => startDrag(index, event),
382
383
  onKeyDown: (event) => {
@@ -683,6 +684,7 @@ window.__ModuleLoader__.load({
683
684
  name: 'conversation.input.dock',
684
685
  id: 'queue-reorder',
685
686
  order: 21,
687
+ locale: LOCALE_NS,
686
688
  inject: (sessionId) => {
687
689
  const actx = ctx.sessions.scope(sessionId);
688
690
  const conversation = actx === undefined ? undefined : actx.get('conversation');
@@ -713,9 +715,16 @@ window.__ModuleLoader__.load({
713
715
  name: 'conversation.input.right',
714
716
  id: 'composer-continue',
715
717
  order: 1000,
718
+ locale: LOCALE_NS,
716
719
  }, ContinueButton));
717
720
  if (ctx.locale !== undefined) ctx.effect(() => ctx.locale.register(LOCALE_NS, {
718
721
  en: {
722
+ 'continue.label': 'Continue',
723
+ 'continue.message': 'continue',
724
+ 'queue.drag': 'Drag to reorder (or ↑/↓)',
725
+ 'queue.locked': 'Messages with images/files cannot be moved',
726
+ 'queue.grip': 'Reorder queued message',
727
+ 'queue.failed': 'Reorder failed: a message may have already started sending.',
719
728
  copyDeeplink: 'Copy deeplink',
720
729
  allowChat: 'Allow for this chat',
721
730
  allowChatTitle: 'Allow {toolName} without asking for the rest of this chat, with any arguments. If the tool can write, that includes any write.',
@@ -750,6 +759,12 @@ window.__ModuleLoader__.load({
750
759
  'changes.refresh': 'Refresh',
751
760
  },
752
761
  zh: {
762
+ 'continue.label': '继续',
763
+ 'continue.message': '继续',
764
+ 'queue.drag': '拖动以排序(或按 ↑/↓)',
765
+ 'queue.locked': '含图片或文件的消息无法移动',
766
+ 'queue.grip': '调整排队消息顺序',
767
+ 'queue.failed': '排序失败:某条消息可能已开始发送。',
753
768
  copyDeeplink: '复制深层链接',
754
769
  allowChat: '本对话内允许',
755
770
  allowChatTitle: '本对话剩余时间内,{toolName} 的任何参数调用都无需再询问。若该工具可写入,也包括任何写入操作。',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-composer-plus",
3
- "version": "0.6.2",
3
+ "version": "0.7.0",
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",