dsh-loadout 0.12.1 → 0.12.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/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  「装备栏」是一个 DeepSeek Harness 插件:给每个对话选一套工具(套装),只把用得上的工具投给模型。
4
4
 
5
+ ## 0.12.2
6
+
7
+ - **修「绑定到已不存在的套装」**:如果某个对话绑的套装在应用关着的时候被删掉(旧版本、手改 loadout.json、或别的机器同步过来的文件),启动后它会被当成「空套装」套用——等于把这对话的工具连同内置工具一起裁光,只剩 kit_*。现在这种绑定在第一次被读到时回退到「全部」,并把 ssignments 里那个失效名字改成
8
+ ull,日志里留一行说明。回归断言: binding to a deleted kit falls back to 全部(用第二个模块实例模拟重启)。
5
9
  ## 0.12.1
6
10
 
7
11
  - **修卡死**:编辑(覆盖保存)、重命名或删除一个正在被对话使用的套装时,宿主会遍历「正在用它的对话」并逐个重新套用工具;这个遍历边改边往 `Map` 里重写条目,迭代器被塞回一个已经走过的键,于是永远走不完——表现是界面点下去没有任何反应、进程占满一个核。现在遍历快照(`[...state]`),编辑与删除都会立刻返回。
package/index.js CHANGED
@@ -1132,8 +1132,19 @@ export function apply(ctx, config = {}) {
1132
1132
  */
1133
1133
  function ensureBindingApplied(agent) {
1134
1134
  if (agent === undefined || agent === null) return
1135
- const value = ensureBinding(agent)
1135
+ let value = ensureBinding(agent)
1136
1136
  if (value === undefined) return
1137
+ // A stored binding can name a kit that no longer exists — an older build, a
1138
+ // hand-edited store, or a kit deleted while the app was closed. Applying it
1139
+ // would compute an empty allow list and strip the conversation down to the
1140
+ // kit_* tools, so such a conversation falls back to 全部 and the dangling
1141
+ // name is rewritten to stop it resurfacing on every read.
1142
+ if (value !== null && value !== DEFAULT_DSH && resolveKit(lastAgent, value) === undefined) {
1143
+ book.assignments[sessionIdOf(agent)] = null
1144
+ save()
1145
+ ctx.logger?.warn(`dsh-loadout: 套装「${value}」已不存在,这个对话回到「全部」`)
1146
+ value = null
1147
+ }
1137
1148
  const selection = selectionForBinding(value)
1138
1149
  const current = state.get(agent)?.selection
1139
1150
  if (current !== undefined && sameSelection(current, selection)) return
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-loadout",
3
- "version": "0.12.1",
3
+ "version": "0.12.2",
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",
@@ -846,6 +846,24 @@ try {
846
846
  check('a preset name cannot be taken by a user kit',
847
847
  /预置/u.test(presetClashError ?? ''), presetClashError)
848
848
 
849
+ // T22: a binding that names a kit removed outside the app falls back to 全部.
850
+ // Simulated the way it really happens: the kit is gone from the store file when
851
+ // the app starts again, so a fresh module instance has to cope with it.
852
+ await ctxV2.registered.get('kit_create').execute(
853
+ { name: 'ghost-kit', title: '已删除的', builtins: ['read'], plugins: [] }, exec(agentB))
854
+ await ctxV2.registered.get('kit_assign').execute({ sessionId: 'session-ghost', kit: 'ghost-kit' }, exec(agentB))
855
+ const storeWithGhost = storeOf()
856
+ storeWithGhost.kits = storeWithGhost.kits.filter((kit) => kit.name !== 'ghost-kit')
857
+ writeFileSync(join(v2Home, '.dsh', 'loadout.json'), JSON.stringify(storeWithGhost), 'utf8')
858
+ const v2b = await import('../index.js?v2=2')
859
+ const ctxV2b = makeCtx()
860
+ v2b.apply(ctxV2b, { defaultKit: '', kits: config.kits })
861
+ const agentGhost = makeAgent(undefined, { id: 'session-ghost' })
862
+ for (const handler of ctxV2b.handlers.get('agent/created') ?? []) handler(agentGhost)
863
+ check('a binding to a deleted kit falls back to 全部',
864
+ storeOf().assignments['session-ghost'] === null && keptOf(agentGhost).includes('web_search'),
865
+ JSON.stringify({ assignments: storeOf().assignments, kept: keptOf(agentGhost) }))
866
+
849
867
  // T03/T05: the default changes again; conversations that already answered keep theirs.
850
868
  const agentC = makeAgent(undefined, { id: 'session-c' })
851
869
  await ctxV2.registered.get('kit_set_default').execute({ name: 'chat' }, exec(agentB))