dsh-loadout 0.13.0 → 0.13.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/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  「装备栏」是一个 DeepSeek Harness 插件:给每个对话选一套工具(套装),只把用得上的工具投给模型。
4
4
 
5
+ ## 0.13.1
6
+
7
+ - 只改文档:README(中英)删掉从讨论过程里带进来的内容——为什么某句话放在底部而不是悬停里、某个 `span` 的透明度如何叠加、上一版修错了什么、0.4.0 那次崩溃的来龙去脉。留下的仍然是有用的那部分:缓存按前缀命中所以切换的代价跟着上下文长度走、行上为什么报 token 而不是钱、价格是估算、`auto` 标记与草稿的语义、链接安装与拷贝安装的区别。行为与 0.13.0 完全相同。
8
+
5
9
  ## 0.13.0
6
10
 
7
11
  - **默认套装是「借来的」,不是「选过的」**:新建对话时宿主会把当时的默认套装写进这个对话的绑定,于是它看起来像用户自己选的——之后在设置页把默认改掉,欢迎区仍然显示旧套装(而列表里 `全部(默认)` 已经打上标记、却没有勾),两张嘴说两套话。现在这类绑定带 `auto` 标记(落盘),读取时不算「已选」,胶囊显示当前默认;欢迎区发现「借来的套装 ≠ 现在的默认」时发一次 `bind { follow: true }` 让宿主补上(不写草稿、仍是借来的),所以下一次改默认它还会跟着走。第一轮对话结束后标记消失,绑定才真正属于这个对话。设置页改默认本身仍然不碰任何对话——这条承诺没有变。
package/README.en.md CHANGED
@@ -47,9 +47,9 @@ Without the dsh CLI you can use `scripts/install.ps1`: it creates the junction l
47
47
 
48
48
  Restart the app afterwards: host plugins have no hot reload, and the UI needs at least a refresh.
49
49
 
50
- ### Why not copy the files
50
+ ### Link installs, not copies
51
51
 
52
- That is exactly how 0.4.0 broke startup: `install.ps1` copied files into the profile, so after the source was fixed the profile still ran the old bundle. A link cannot drift.
52
+ A **link** install, not a copy. A copy lands in the profile and keeps running the old bundle after the source changes — that is how 0.4.0 broke startup. A link cannot drift, and `preflight` reports whether the install has.
53
53
 
54
54
  ### Self-checks
55
55
 
@@ -119,7 +119,7 @@ Each row states **how many tokens of tool definitions it would put in the prompt
119
119
 
120
120
  > 本对话上下文(约 150k tokens),下一条未命中价≈¥0.23,之后恢复至缓存价。
121
121
 
122
- It lives there rather than in a per-row tooltip because the reminder block is the paragraph people read; a tooltip has to be found first. The number comes from the host token meter's `contextPressure` projection (the provider-reported size of the last request plus whatever the surface has grown by since), not from guessing at the session file. The ¥2 / ¥0.5 per million tokens (miss / hit) are fixed estimates: they only feed the hint, and no setting changes what a switch does. The settings page's `全部` and `仅内置` cards state their token counts too, like every kit card.
122
+ The number comes from the host token meter's `contextPressure` projection (the provider-reported size of the last request plus whatever the surface has grown by since), not from guessing at the session file. The ¥2 / ¥0.5 per million tokens (miss / hit) are fixed estimates: they only feed the hint, and no setting changes what a switch does. The settings page's `全部` and `仅内置` cards state their token counts too, like every kit card.
123
123
 
124
124
  The `加挂` group counts `in this conversation / plugins there are at all` (e.g. `加挂(1/5)`), so under the `全部` base it reads `6/6`: all six plugins are already in, and there is nothing left to attach. Its tooltip only explains the verb ("在当前选择上临时加开插件,不新建套装。已经包含的插件不能再加。"); the bill is stated once, at the bottom.
125
125
 
@@ -127,7 +127,7 @@ The last line of the conversation menu's footer is the one that matters most: **
127
127
 
128
128
  Configuring is not the same as using: in the conversation menu, "+ 新建套装" offers **保存** (store it, keep the current tools) and **保存并启用** (store it and switch to it — the hover text says the next message is billed once at the miss price). "保存" in Settings only ever saves.
129
129
 
130
- If you do not want to pay it now, do not switch here: choosing the default kit is not a conversation-level action. It lives in Settings → 装备栏 (the "设为默认" button on each card), and it only changes what *new* conversations start from — this conversation keeps its kit and its cache.
130
+ Choosing the default kit is not a conversation-level action. It lives in Settings → 装备栏 (the "设为默认" button on each card), and it only changes what *new* conversations start from — this conversation keeps its kit and its cache.
131
131
 
132
132
  Three surfaces, three scopes: **Settings** owns the global half (the default kit, creating / editing / deleting kits); **the new-conversation pill** owns only the conversation that has not started yet (which kit, no default, no create/edit); **the conversation menu** owns only the current conversation (switch, create a kit).
133
133
 
@@ -141,7 +141,7 @@ The pick binds this conversation only; it does not change the default for new co
141
141
 
142
142
  A pick made before the first message is a **draft**: leave the screen without sending anything (switch to another conversation, reload the page) and it is discarded, so the next new conversation starts at the default again — the same reset the host applies to its own mode. The marker is stored in `loadout.json` under `drafts`, so restarting DSH cannot turn "the kit I clicked once on the welcome screen" into a decision for that conversation. Once a message has actually run, the kit becomes this conversation's fixed binding.
143
143
 
144
- The pill also follows Settings: change the default kit and the welcome screen shows the new one without reopening the conversation (it listens to `dsh-loadout:changed` and window `focus`). What it shows is the default, not "what was chosen here": a binding written from a default at creation time is marked `auto` in `loadout.json` and never counts as this conversation's pick, so moving the default from `idea` to `全部` immediately answers `全部` on a new screen. When the borrowed kit no longer matches the current default, the welcome screen asks the host to catch up (`bind { follow: true }`) — still a loan, still free, and still no draft. The first finished turn clears the marker and the kit belongs to the conversation from then on. Changing the default itself never rewrites an existing conversation; only the welcome screen moves, and only because nothing has been sent yet.
144
+ The pill follows Settings: change the default kit and the welcome screen shows the new one without reopening the conversation. What it shows is the default, not "what was chosen here": a binding written from a default at creation time is marked `auto` in `loadout.json` and never counts as this conversation's pick, so moving the default from `idea` to `全部` answers `全部` on a new screen. While the borrowed kit still differs from the default, the welcome screen asks the host to catch up (`bind { follow: true }`) — still a loan, still free, and still no draft. The first finished turn clears the marker and the kit belongs to the conversation from then on. Changing the default never rewrites an existing conversation.
145
145
 
146
146
  ## Files
147
147
 
package/README.md CHANGED
@@ -48,9 +48,9 @@ plugin_manager action=install_bundle target=<本目录绝对路径>
48
48
 
49
49
  装完重启应用:宿主插件没有热重载,界面至少刷新一次。
50
50
 
51
- ### 为什么不能复制文件
51
+ ### 链接安装,不要拷贝
52
52
 
53
- 0.4.0 的启动崩溃就是这么来的:`install.ps1` 把文件拷进 profile,源码修好后 profile 里还是旧拷贝,启动时跑的是旧 bundle。链接安装没有这个问题。
53
+ 拷贝安装会把文件复制进 profile,之后源码再改,profile 里仍是旧副本,启动时跑的也是旧 bundle——0.4.0 的启动崩溃就是这样产生的。链接安装(junction)没有这个问题,`preflight` 会检查副本来是否漂移。
54
54
 
55
55
  自检:
56
56
 
@@ -66,7 +66,9 @@ node scripts/client-smoke.mjs # 浏览器 bundle:菜单与设置页渲染
66
66
  - 设置 → 装备栏:管理套装、改备注、选新对话默认套装。
67
67
  - `/kit <名字>`:在对话里直接切换。
68
68
 
69
- 设置页没有自己的对话,所以它只管「新对话从哪套开始」,不切换当前对话——当前对话请在标题栏里切,还没开始的对话可以在欢迎区直接选。页面顶部就这么写着:「设置页不绑定具体会话,上面的数字来自最近活跃的那个对话。」下面「新对话默认套装」一节把提醒并进同一行标题:`新对话默认套装只影响新建对话`(一个文本节点、同一字号同一颜色、无间隙——拆成两个 `span` 时第二段自带 0.6 透明度,叠加标题的 0.6 后比标题更淡,看着像换了字体),下一行再补「当前对话在「装备栏」切换;新建时也可选套装。」默认列表里「全部 / 仅内置」和套装是同一种卡片:都能「复制切换命令」或「设为默认」;「我的套装」默认折叠,只显示当前默认的那一个(这一行下面始终留着「+ 新建套装」),点开才列出全部。已经保存的套装可以在卡片上「编辑」:改动就在那张卡片下面展开,「覆盖保存」(正在用它的对话立刻按新工具集走)或「另存为新套装」。
69
+ 设置页只管「新对话从哪套开始」,不切换当前对话。当前对话在标题栏「装备栏」里切,还没开始的对话可以直接在欢迎区选。页面顶部有一行说明:「设置页不绑定具体会话,上面的数字来自最近活跃的那个对话。」
70
+
71
+ 「新对话默认套装」列表里,「全部 / 仅内置」与套装是同一种卡片:都能「复制切换命令」或「设为默认」。「我的套装」默认折叠,只显示当前默认的那一个(这一行下面始终留着「+ 新建套装」),点开才列出全部。已保存的套装可以在卡片上「编辑」:改动在那张卡片下面展开,可选「覆盖保存」(正在用它的对话立刻按新工具集走)或「另存为新套装」。
70
72
 
71
73
  ### 预置套装(五套,只读)
72
74
 
@@ -97,10 +99,10 @@ node scripts/client-smoke.mjs # 浏览器 bundle:菜单与设置页渲染
97
99
  `null` 就是「全部」。规则:
98
100
 
99
101
  - 对话第一次出现时写入一次:有新默认就记默认,从别的对话分叉出来就继承父对话,升级前就存在的旧对话记 `null`(保持当时的实际状态)。
100
- - **「记了默认」和「选了套装」是两回事**:按默认写下的绑定同时记进 `auto`,读的时候不算「这个对话选过它」。所以在设置页把默认从 `idea` 改成 `全部` 之后,新建对话的胶囊立刻显示「全部」,而不是还挂着 `idea`——欢迎区发现「借来的套装 ≠ 现在的默认」时会补一次请求,让宿主把工具集换过去(免费,还没发出第一条消息)。第一轮对话结束后 `auto` 标记消失,绑定才真正属于这个对话。
101
- - **空白对话一律以胶囊为准**:只要一个对话还没发出第一条消息,欢迎区就不争论——胶囊显示什么,下一条消息就用什么;需要时补一次 `follow` 请求把工具集对齐(不写草稿,仍算「借来的」)。这条也覆盖本次修复之前创建的对话:它们把当时的默认(比如 `idea`)写成了真实绑定、没有 `auto` 标记,只要还没发过消息,下次打开欢迎区就会被纠正到当前默认。
102
- - 以后只有显式切换(标题栏、`/kit`、`kit_apply`、`kit_assign`)才改它,显式选择会清掉 `auto` 标记。
103
- - 改「新对话默认套装」只影响之后新建的对话,已有对话各自保留(宿主不遍历、不改写任何已有绑定;跟着走的是欢迎区自己)。
102
+ - 由默认写下的绑定同时记进 `auto`,读取时不算「这个对话选过它」,胶囊显示当前默认;第一轮对话结束后标记消失,绑定才真正属于这个对话。
103
+ - 只要对话还没发出第一条消息,欢迎区以胶囊为准:胶囊显示什么,下一条消息就用什么;不一致时由宿主把工具集对齐(不写草稿,仍算「借来的」)。
104
+ - 只有显式切换(标题栏、`/kit`、`kit_apply`、`kit_assign`)才改绑定,显式选择会清掉 `auto` 标记。
105
+ - 改「新对话默认套装」只影响之后新建的对话,已有对话各自保留。
104
106
  - 子代理不记录绑定:它的父对话已经决定了它能看见什么。
105
107
 
106
108
  ## 升级
@@ -135,17 +137,17 @@ node scripts/client-smoke.mjs # 浏览器 bundle:菜单与设置页渲染
135
137
  - 15 万 token 的对话中途切一次:约等于「整段上下文未命中一次」的钱(本机实测 ¥0.2 量级),之后要靠每轮省下的那 1.9k 慢慢还。
136
138
  - 空闲很久、刚重启、刚压缩过:缓存本来已经冷了,这时候切基本免费。
137
139
 
138
- 菜单里每一行右边显示的是**这一行会往提示词里放多少工具定义**(`≈3.1k tokens`、`全部` 是 `≈5.6k tokens`、`仅内置` 是 `≈4.1k tokens`),套装的默认标记跟在名字后面(`全部(默认)`、`idea(默认)`);状态行带 `· 上下文 ~150k`。行上不写钱:换任何一套,被作废的都是同一段历史,那个数字对每一行都一样,写出来反而看不出区别——区别在「这套装进多少工具」。钱只在**菜单底部「重要提醒」下面那一行**出现,加粗:
140
+ 菜单里每一行右边显示的是**这一行会往提示词里放多少工具定义**(`≈3.1k tokens`、`全部` 是 `≈5.6k tokens`、`仅内置` 是 `≈4.1k tokens`),套装的默认标记跟在名字后面(`全部(默认)`、`idea(默认)`);状态行带 `· 上下文 ~150k`。行上不写钱:换任何一套,被作废的都是同一段历史,那个数字对每一行都一样,区别在「这套装进多少工具」。钱只在**菜单底部「重要提醒」下面那一行**出现,加粗:
139
141
 
140
142
  > 本对话上下文(约 150k tokens),下一条未命中价≈¥0.23,之后恢复至缓存价。
141
143
 
142
- 把这句话放在底部而不是每一行的悬停里,是因为提醒那块本来就醒目、用户会读,而悬停要先找到。这个数字来自宿主 token meter 的 `contextPressure` 投影(提供方报告的上一次请求规模,加上之后新增的表面增量),不是按会话文件大小猜的。价格按 ¥2 / ¥0.5 每百万 token(未命中 / 命中)估算——只用于提示,不影响切换本身。设置页里 `全部` 与 `仅内置` 两张卡片也写着各自的 token 数,和套装卡片一样。
144
+ 这个数字来自宿主 token meter 的 `contextPressure` 投影(提供方报告的上一次请求规模,加上之后新增的表面增量)。价格按 ¥2 / ¥0.5 每百万 token(未命中 / 命中)估算——只用于提示,不影响切换本身。设置页里 `全部` 与 `仅内置` 两张卡片也写着各自的 token 数,和套装卡片一样。
143
145
 
144
146
  `加挂` 分组的数量写成 `已在对话中 / 插件总数`(例如 `加挂(1/5)`)——所以在「全部」底座下它是 `6/6`:六个插件都已经在对话里,没有可再加的。分组标题的悬停提示只说加挂的语义(「在当前选择上临时加开插件,不新建套装。已经包含的插件不能再加。」),账在底部那一行。
145
147
 
146
148
  对话页菜单底部那段说明的最后一条是**重要提醒**:建议新建对话时就直接选好套装;对话中途切换会改变插件清单,下一条消息按未命中价重算一次,之后恢复。长对话影响较大,短对话基本无影响;空闲很久、刚压缩过、刚重启之后再切,基本免费。
147
149
 
148
- 不想现在付这笔钱,就别在这里切:选默认套装不在对话页——它属于全局决定,在 设置 → 装备栏 里改(每张卡片的「设为默认」),改完之后新建的对话从这套开始,当前对话不受影响,也不会触发任何重算。
150
+ 选默认套装不在对话页——它属于全局决定,在 设置 → 装备栏 里改(每张卡片的「设为默认」),改完之后新建的对话从这套开始,当前对话不受影响,也不会触发任何重算。
149
151
 
150
152
  三个入口各管一段,互不越界:**设置页**管全局(默认套装、新建 / 编辑 / 删除套装);**新对话的胶囊**只管这一条还没开始的对话(选哪套,不碰默认,也不建不改);**对话页菜单**只管当前对话(切换、新建套装)。
151
153
 
@@ -153,15 +155,15 @@ node scripts/client-smoke.mjs # 浏览器 bundle:菜单与设置页渲染
153
155
 
154
156
  ## 新建对话时选套装
155
157
 
156
- 空白对话的输入框工具行里、`标准模式`选择栏右侧,多一个 `选择对话套装 <当前选择> ▾` 的小胶囊。鼠标停上去显示「这个新对话会用「X」套装」;选过之后显示「这个对话会用「X」套装,下一条消息生效」。点开是一个向上浮出的折叠列表:`全部`、`仅内置`、`预设套装`、`我的套装`——后两组默认收起,点开才列出条目;收起时仍会显示「当前默认的那一套」(名字后面标 `(默认)`,与标题栏一致),否则空白屏幕上会答成「什么都没选」。列表里的 `全部` / `仅内置` / 每套套装都按标题栏的规则标 `(默认)`;胶囊本身不标,它说的是「这个对话实际用哪套」。收起时胶囊上的名字就是「这个对话实际会用哪套」:设过默认就显示那套,没设过就显示「全部」。选中的那套从第一条消息起生效;发出第一条消息后整个胶囊不再出现。
158
+ 空白对话的输入框工具行里、`标准模式`选择栏右侧,多一个 `选择对话套装 <当前选择> ▾` 的小胶囊。鼠标停上去显示「这个新对话会用「X」套装」;选过之后显示「这个对话会用「X」套装,下一条消息生效」。点开是一个向上浮出的折叠列表:`全部`、`仅内置`、`预设套装`、`我的套装`——后两组默认收起,点开才列出条目;收起时仍会显示「当前默认的那一套」(名字后面标 `(默认)`,与标题栏一致)。列表里的 `全部` / `仅内置` / 每套套装都按标题栏的规则标 `(默认)`;胶囊本身不标,它说的是「这个对话实际用哪套」。设过默认就显示那套,没设过就显示「全部」。选中的那套从第一条消息起生效;发出第一条消息后整个胶囊不再出现。
157
159
 
158
160
  这是唯一真正免费的切换——此时还没有 agent,也就没有任何请求前缀被建起来,工具定义怎么写都不影响缓存。所以在这里挑,比发完第一条消息再切便宜。
159
161
 
160
162
  选择只绑在当前这条对话上,不动「新对话默认套装」;想改默认仍然去设置页。如果宿主版本没有这个插槽(比如更早的 DSH),这一行不会出现,其余功能不受影响。
161
163
 
162
- 还没有发出第一条消息就离开这个新对话(点了别的对话、或刷新页面),这个选择会被当作**草稿**丢掉:下次再进新对话回到默认套装,和 DSH 自己把模式重置回「标准模式」是同一件事。草稿标记存在 `loadout.json` 的 `drafts` 里,所以重启 DSH 也不会把「上次随手选的」误当成这条对话的决定。真正发过一条消息之后,它才成为这个对话的固定套装。
164
+ 还没有发出第一条消息就离开这个新对话(点了别的对话、或刷新页面),这个选择会被当作**草稿**丢掉:下次再进新对话回到默认套装,和 DSH 自己把模式重置回「标准模式」是同一件事。草稿标记存在 `loadout.json` 的 `drafts` 里,所以重启 DSH 不会把「上次随手选的」误当成这条对话的决定。真正发过一条消息之后,它才成为这个对话的固定套装。
163
165
 
164
- 胶囊会跟着设置页走:在设置里改了默认套装,回到欢迎区显示的就是新的默认(它监听 `dsh-loadout:changed` 与窗口 `focus`,不需要重新打开对话)。
166
+ 在设置里改了默认套装,回到欢迎区显示的就是新的默认,不需要重新打开对话。
165
167
 
166
168
  ## 文件
167
169
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-loadout",
3
- "version": "0.13.0",
3
+ "version": "0.13.1",
4
4
  "description": "Loadout for DeepSeek Harness: group tools into kits, keep only the current kit's tools visible in each conversation, and manage everything from a settings panel.",
5
5
  "type": "module",
6
6
  "main": "./index.js",