dsh-mini-remote 0.1.8 → 0.1.9

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/CHANGELOG.md CHANGED
@@ -2,6 +2,42 @@
2
2
 
3
3
  本文件记录每个版本改了什么。格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
4
4
 
5
+ ## [0.1.9] - 2026-10-05
6
+
7
+ 这一版跨了三天、74 笔改动,主体是**设置页整屏化与插件页**、**「完整」显示模式与执行轨迹**,以及一串观感与读取速度的修补。
8
+
9
+ ### 新加的
10
+
11
+ - **设置页从「贴底抽屉」改成整屏。** 内容越加越多,那张最高只占 86% 屏高的抽屉不够用了。页眉跟着收矮(65 → 约 51 像素);底色仍是毛玻璃,因为页眉挪到了滚动区**外面**,往上滚时它不跟着跑。四个面板(设置、统一操作、子智能体、插件)的「关闭」按钮统一收小一号。
12
+
13
+ - **多了「插件」这一页。** 从设置页进去,列出官方插件和已安装的插件,分组可折叠、默认收起。内置插件按 DSH 自己的 Loader 条目表列,不再按包名——那才是「一切皆插件」的粒度。会话插件那一组的预设名走中文词条表,不再露 `standard` 这类代号;标题后面原来跟着的括号说明也去掉了。
14
+
15
+ - **显示模式多了「完整」,把执行轨迹画出来。** 原来只有两种看聊天的模式,现在多了「完整」:执行轨迹**穿插在对话里的原位**(和电脑端同一套长相),带三层折叠,可以一层层点开看「这一步读了什么文件」。已加载的轨迹可以搜——**搜不到时如实说「已加载的这批里没有」**,不说成「不存在」,因为实际只搜了已加载的那部分。跑着的那一行有一道扫光扫过去,和电脑端一样。思考正文、工具卡的「输入 / 输出」、自动审查的文案都对齐了电脑端。
16
+
17
+ - **字体大小可以调了。** 设置页里三档:小 / 标准 / 大。
18
+
19
+ - **新建会话可以选 Agent 模式。** 照电脑端的词条表,模式名走中文;自己起的名字不翻译。
20
+
21
+ - **手机上「添加文件」和「调用指令」并成了一个入口。** 原来这两件事各有各的门(回形针直接开文件选择器、打一个斜杠才弹指令菜单),手机上没人知道打斜杠还能调指令。现在是输入框旁边**一个**入口,点开是一张面板:上面「添加文件」、下面「调用指令」。选文件支持**多选**,选完直接回主页面,不必自己再按一下关闭。
22
+
23
+ - **设置页多了「繁忙时的发送行为」。** 照电脑端那一条做的,两边共用同一个值:智能体运行时按发送键,是**排队发送**还是**插话发送**。位置在权限档位下面。
24
+
25
+ - **附件按钮的图标换成了电脑端那只鲸鱼。** 填色跟着主题走,深浅两套各自适配。上传文件时它会**原地游动**——原来那个转圈是「物件在转」的语汇(齿轮、加载器),用在活物身上像标本被转着看。用户要「减少动效」时它就不动,而忙碌的表示没丢(按钮此时是禁用态)。
26
+
27
+ - **浅色主题成为默认。** 之前默认深色。
28
+
29
+ - **导航和子智能体的读取更快了。** 服务端多了一层**会话元数据缓存**,导航缓存跟着会话事件增量更新,子智能体列表和运行状态也改成增量刷新;子智能体面板首次点开会预取,不再等那一下。
30
+
31
+ ### 修了的
32
+
33
+ - **权限档位那三处观感问题。** 那一块下面缺一条分割线(照其他线的做法补上,位置和其他板块一致);那排按钮没填满它的框,最右「自动审查」那一格的背景空出一条;上缘那条线偏粗——是标签那行的下边线和按钮框的上边框**叠在一起**了,去掉前者。
34
+ - **子智能体面板的空态文字贴着屏边。** 那三处漏了左留白。
35
+ - **「调用指令」紧贴着上面的按钮。** 那条留白规则其实写着 20 像素,但被更具体的选择器盖掉了,**从来没生效过**。
36
+ - **导航栏会卡在「正在读取…」不走。** 刷新时清了数据、没清展开态。
37
+ - **「完整」模式的一串问题。** 已结束的轮次组头全写着「进行中」(一排跑完的轮在假转圈);往上滑放不出更早的一屏;正在想的片段不逐字顺出来;跑着的空组要等步骤跑完才一次性冒出来;实时帧里的旁白被画成「工具调用」空壳。
38
+ - **切会话时权限档位不跟着走**,以及权限档位那一块会因为一次读失败就整个消失。
39
+ - **设置页两处实测出来的毛病**:DSH 版本号一直显示 `unknown`、会话插件那一组的行数虚报。
40
+
5
41
  ## [0.1.8] - 2026-10-02
6
42
 
7
43
  ### 改了的
package/lib/commands.js CHANGED
@@ -83,6 +83,12 @@ export function describeCommands(descriptors) {
83
83
  if (!name) continue
84
84
  const hint = typeof d?.input?.hint === 'string' && d.input.hint ? d.input.hint : null
85
85
  rows.push({
86
+ // 这条指令的**身份**:DSH 自己的 `CommandDefinitionId`(例如
87
+ // `@deepseek-ai/dsh-command-compact`)。桌面端靠它选本地化标题、图标和内置别名。
88
+ // 手机这一版还拿不到那份本地化文案——它长在浏览器端那个包里(dsh-client-ui-commands
89
+ // 自己的 zh/en 词典加 React 图标),宿主服务只给 name / description——所以界面照旧
90
+ // 显示注册名;但标识不能再丢:丢了就永远接不上那一层。
91
+ definitionId: typeof d?.definitionId === 'string' && d.definitionId ? d.definitionId : null,
86
92
  name,
87
93
  description: typeof d?.description === 'string' ? d.description : '',
88
94
  hint,
package/lib/events.js CHANGED
@@ -140,8 +140,12 @@ export function createTurnTracker() {
140
140
  return {
141
141
  /**
142
142
  * 喂入一条会话事件。
143
- * @returns {{kind:'user', text:string}|{kind:'notice', text:string, summary:string, senderSessionId:string}|{kind:'reply', text:string, reason:string, userText:string, userMessageId:string, interrupted:boolean}|null}
143
+ * @returns {{kind:'user', text:string, id?:string, turn:number|null}|{kind:'notice', text:string, summary:string, senderSessionId:string, turn:number|null}|{kind:'reply', text:string, reason:string, userText:string, userMessageId:string, interrupted:boolean, turn:number|null}|null}
144
144
  * 需要推送到手机时返回动作,否则返回 null。
145
+ *
146
+ * 每个动作都带 `turn`(这条动作发生在第几轮):完整模式要把每一轮的轨迹块
147
+ * 插回它那轮对话的原位(指令之后、回答之前),对号靠它——轮号本来就在
148
+ * turn/start 时记在 s.turn 上,这里只是随动作带出来。
145
149
  */
146
150
  feed(sessionId, event) {
147
151
  if (!event || typeof event.type !== 'string') return null
@@ -174,6 +178,7 @@ export function createTurnTracker() {
174
178
  text: notice,
175
179
  summary: typeof event.data.source.summary === 'string' ? event.data.source.summary : '',
176
180
  senderSessionId: String(event.data.source.senderSessionId ?? ''),
181
+ turn: s.turn,
177
182
  }
178
183
  }
179
184
  // 只认人发的;agent.inject() 的合成上下文(文件变更通知、skill 内容等)
@@ -187,7 +192,7 @@ export function createTurnTracker() {
187
192
  s.userMessageId = event.data?.id ?? ''
188
193
  // 带上 id:手机自己发出去的指令,注入后也会以这条事件回来,
189
194
  // 调用方要靠 id 把它认出来、不要记第二笔(见 index.js 的 injectedIds)。
190
- return { kind: 'user', text, id: event.data?.id }
195
+ return { kind: 'user', text, id: event.data?.id, turn: s.turn }
191
196
  }
192
197
 
193
198
  case 'assistant/message': {
@@ -227,7 +232,7 @@ export function createTurnTracker() {
227
232
  s.interrupted = false
228
233
  // 被取消/出错的轮次,以及卡在工具里没跑出回答的轮次,都没有什么可推的。
229
234
  if (!text) return null
230
- return { kind: 'reply', text, reason, userText, userMessageId, interrupted }
235
+ return { kind: 'reply', text, reason, userText, userMessageId, interrupted, turn: s.turn }
231
236
  }
232
237
 
233
238
  default:
package/lib/history.js CHANGED
@@ -20,7 +20,10 @@ import { foldCommandEvent } from './commands.js'
20
20
  * @returns {Array<{role:'user'|'assistant'|'command'|'notice', text?:string|null, timestamp:number|null,
21
21
  * id?:string|null, reason?:string, interrupted?:boolean,
22
22
  * commandId?:string, name?:string, args?:string, kind?:string,
23
- * summary?:string, senderSessionId?:string}>}
23
+ * summary?:string, senderSessionId?:string,
24
+ * turn?:number|null}>}
25
+ * turn=这条消息发生在第几轮(指令行没有轮号,留空)。完整模式靠它把
26
+ * 每轮的轨迹块插回对话原位。
24
27
  */
25
28
  export function replayHistory(events) {
26
29
  const tracker = createTurnTracker()
@@ -43,16 +46,18 @@ export function replayHistory(events) {
43
46
  text: action.text,
44
47
  summary: action.summary,
45
48
  senderSessionId: action.senderSessionId,
49
+ turn: action.turn ?? null,
46
50
  timestamp,
47
51
  })
48
52
  continue
49
53
  }
50
54
  if (action.kind === 'user') {
51
- out.push({ role: 'user', text: action.text, id: action.id ?? null, timestamp })
55
+ out.push({ role: 'user', text: action.text, id: action.id ?? null, turn: action.turn ?? null, timestamp })
52
56
  } else {
53
57
  out.push({
54
58
  role: 'assistant',
55
59
  text: action.text,
60
+ turn: action.turn ?? null,
56
61
  timestamp,
57
62
  reason: action.reason,
58
63
  interrupted: action.interrupted === true,