dsh-gitbash-shell 0.43.3 → 0.44.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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,16 @@
3
3
  > 倒序排列,新版本条目在最上面。条目格式:`## vX.Y.Z — YYYY-MM-DD` + 类型(feat / fix / docs / chore)+ 要点 + 相关链接。
4
4
  > 纪律见 AGENTS.md「变更记录纪律」:发版前先更新本文件并随版本提交;事故复盘、复现与真机验证记录也记在这里。
5
5
 
6
+ ## [0.44.0] — 2026-10-28
7
+
8
+ ### feat:跟随 dsh 0.2.2-alpha.2 的工具执行器架构(executor 行、subagent 模型键、assemble 事件收窄、promoted 文案精简)
9
+
10
+ - **背景**:官方 0.2.2-alpha.2 重做了工具执行架构(`docs/upgrade-guide/v0.2.1-rc.2/tool-executor-plugins/`):`dsh-tools` 的 `mode`/`maxParallelSubCalls` 配置被 `z.never()` 拒绝,执行模式改由显式 `tool-executor-native` / `tool-executor-ptc` 行承载(base 已挂 native,PTC 侧需 preset 级覆盖);`dsh-agent-tool-presentation` 仍支持但已弃用。同期 preset 还有三处形状变化,官方 preset 逐行对齐面因此多了一个代际。
11
+ - **组合跟随(探测门控)**:`probeHostExtras` 增加 `executorPlugin`(`@deepseek-ai/dsh-tool-executor-ptc` 可解析)与 `profileContext`(live 服务读取)。新宿主上:PTC 变体改挂 `tool-executor-ptc`,不再挂 `tool-presentation(mode: ptc)`;`tool-subagent-list-agents` 行删除(list_agents 已并入 `tool-subagent-control` 主行);subagent 配置键 `modelSelectionSettings` → `modelSelection` + `modelDiscovery`;plugin-manager / plugin-market 两行改由 `profileContext` 门控(官方 `!!js "!ctx.get('profileContext')"` 语义,三个变体一致)。旧宿主全部保持原行集不变——组合对齐的向后兼容纪律照旧。
12
+ - **assemble 事件收窄**:0.2.2-alpha.2 的 `system-prompt/assemble` 只带 prompt presentation,不再带 `tools`(`PromptAssembly` 拆分,工具声明改由 provider 持有)。`applyToolRouting` 与 `runCodeHintFor` 因此改为:宿主给了工具列表就用宿主的,否则从 `ctx.get('tools').schemas(agent)` 读回——新老宿主都拿到真实工具面,方言路由与 run_code 提示句不受影响。
13
+ - **promoted 文案精简**:测试钩子 `renderPromoted` 跟随官方简化——只留 `[still running after Nms; moved to background job id]`,跟随指引(读输出/停止)改由官方 `tool:jobs` 段落统一承载,不再重复。
14
+ - **测试(337 项:336 pass + 1 skip)**:`probeHostExtras` 断言扩到新字段(含 live 服务读取与抛错降级);新增 alpha.2 组合形态测试(executor 行/无 list-agents 行/新 subagent 键/profile 门控/旧宿主不变);源码断言与新工具列表回退路径。
15
+
6
16
  ## [0.43.3] — 2026-10-27
7
17
 
8
18
  ### fix:工具面晚于 `agent/created` 落定时,bash 补位永久错过(真机复现;PR #36,致谢 @qiantao448-ux 首次贡献)
package/dsh.plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "dsh-external/dsh-gitbash-shell",
3
- "version": "0.43.3",
3
+ "version": "0.44.0",
4
4
  "main": "./src/index.js",
5
5
  "description": "Windows 全模式 Git Bash:自带 bash 工具(私有 Git Bash 执行器实例,官方 PowerShell 执行器原样保留),官方四个模式经行内工具补位直接获得 Git Bash(v0.35.0 起;v0.39.0 起不再替换宿主执行器),四个 *·Git Bash 变体 preset 可开关;官方 pwsh 工具默认隐藏、开关可见(真 PowerShell);附带 gb_* FastCtx 文件工具,检测到 dsh-ops 自动让位。联动:dsh-ptc-cordis-preset(PTC 创造模式带 Git Bash 行且可去重)+ dsh-better-sidebar(终端标签自动切 Git Bash)。",
6
6
  "engines": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-gitbash-shell",
3
- "version": "0.43.3",
3
+ "version": "0.44.0",
4
4
  "description": "Windows 上给 agent 一个真正的 Git Bash 命令工具:私有 Git Bash 执行器实例(官方 PowerShell 执行器原样保留),统一 MSYS 盘根路径方言,官方 pwsh 工具默认隐藏可开关,物化四个内置预设的 Git Bash 变体,侧栏终端接管可开关。· Give agents a real Git Bash tool on Windows: a private Git Bash executor instance (the official PowerShell executor stays untouched), a unified MSYS drive-root path dialect, an opt-in official pwsh tool, and four Git Bash preset variants.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -119,7 +119,11 @@ export function renderResult(result, escalationModes = []) {
119
119
 
120
120
  /**
121
121
  * Shape a foreground call that stopped waiting into the text the model sees.
122
- * Mirrors the official `renderPromoted` (tool-bash render.ts:77).
122
+ * Mirrors the official `renderPromoted` (tool-bash render.ts:77) as of dsh
123
+ * 0.2.2-alpha.2: the marker alone — the follow-up guidance now lives in the
124
+ * shared `tool:jobs` system-prompt section, so the older "read newer output
125
+ * with job_output, stop it with job_kill" sentence would duplicate it
126
+ * (upstream simplified this in 0.2.2-alpha.2).
123
127
  * @param {{ jobId: string, timeoutMs: number, output: string, sandbox?: object }} promoted
124
128
  * @param {string[]} [escalationModes]
125
129
  * @returns {string}
@@ -128,9 +132,7 @@ export function renderPromoted(promoted, escalationModes = []) {
128
132
  const body = promoted.output.length > 0
129
133
  ? (promoted.output.endsWith('\n') ? promoted.output : `${promoted.output}\n`)
130
134
  : ''
131
- const text = `${body}[still running after ${promoted.timeoutMs}ms; moved to background job ${promoted.jobId}]\n`
132
- + 'The command keeps running in the background. You will be notified when it finishes; '
133
- + 'read newer output with job_output, stop it with job_kill.'
135
+ const text = `${body}[still running after ${promoted.timeoutMs}ms; moved to background job ${promoted.jobId}]`
134
136
  const notes = sandboxNotes(promoted.sandbox, escalationModes)
135
137
  return notes.length > 0 ? `${text}\n${notes.join('\n')}` : text
136
138
  }
@@ -90,12 +90,19 @@ export function pluginsFor({ kind, gitBash, skillsDir, pythonActive = false, hos
90
90
  // toolFilter deny from the subagent/subagent_fork configs (official
91
91
  // reminders reach subagents again — the deny was never load-bearing,
92
92
  // nothing replaces it); alpha.4 added a tool-plugin-market row to every
93
- // full preset. A preset row whose package is absent rejects the WHOLE
94
- // mount, so these ride a host probe (index.js probeHostExtras, resolved
95
- // from ctx.baseUrl — the base rows mount from); absent/older hosts keep
96
- // the byte-identical 0.1.7 row set. The minimal variant carries its own
97
- // 0.2.1-alpha.3 delta (tool-fs + compaction) behind the compaction flag.
98
- const { timeContext = false, toolSchedule = false, pluginMarket = false, compaction = false } = hostExtras
93
+ // full preset. 0.2.2-alpha.2 then reworked the tool execution architecture
94
+ // (`executorPlugin`): the official executors moved into explicit
95
+ // tool-executor-native/-ptc rows, the subagent config renamed
96
+ // `modelSelectionSettings` to `modelSelection` + opt-in `modelDiscovery`,
97
+ // list-agents folded into the tool-subagent-control row itself (its
98
+ // separate row is gone), and the manager/market rows enable under a
99
+ // profile context instead of staying off outside cordis. A preset row whose
100
+ // package is absent rejects the WHOLE mount, so these ride a host probe
101
+ // (index.js probeHostExtras, resolved from ctx.baseUrl — the base rows
102
+ // mount from); absent/older hosts keep the byte-identical earlier row set.
103
+ // The minimal variant carries its own 0.2.1-alpha.3 delta (tool-fs +
104
+ // compaction) behind the compaction flag.
105
+ const { timeContext = false, toolSchedule = false, pluginMarket = false, compaction = false, executorPlugin = false, profileContext = false } = hostExtras
99
106
  const rows = [
100
107
  {
101
108
  id: 'persona',
@@ -168,11 +175,15 @@ export function pluginsFor({ kind, gitBash, skillsDir, pythonActive = false, hos
168
175
  isolate: { workflowEngine: true },
169
176
  config: [
170
177
  { id: 'tool-subagent-control', name: '@deepseek-ai/dsh-tool-subagent-control' },
171
- { id: 'tool-subagent-list-agents', name: '@deepseek-ai/dsh-tool-subagent-control/list-agents' },
178
+ // 0.2.2-alpha.2 folded list_agents into the control row itself; the
179
+ // separate child row is gone, so alpha.2+ hosts must not mount it.
180
+ ...(executorPlugin ? [] : [{ id: 'tool-subagent-list-agents', name: '@deepseek-ai/dsh-tool-subagent-control/list-agents' }]),
172
181
  {
173
182
  id: 'tool-subagent',
174
183
  name: '@deepseek-ai/dsh-tool-subagent',
175
- config: { provider: 'spawn', toolName: 'subagent', modelSelectionSettings: true, ...(timeContext ? {} : { backgroundMode: 'continuable' }) },
184
+ config: executorPlugin
185
+ ? { provider: 'spawn', toolName: 'subagent', modelSelection: true, modelDiscovery: true, ...(timeContext ? {} : { backgroundMode: 'continuable' }) }
186
+ : { provider: 'spawn', toolName: 'subagent', modelSelectionSettings: true, ...(timeContext ? {} : { backgroundMode: 'continuable' }) },
176
187
  },
177
188
  {
178
189
  id: 'tool-subagent-fork',
@@ -207,11 +218,13 @@ export function pluginsFor({ kind, gitBash, skillsDir, pythonActive = false, hos
207
218
  },
208
219
  ]
209
220
  if (kind === 'ptc') {
210
- rows.push({
211
- id: 'tool-presentation',
212
- name: '@deepseek-ai/dsh-agent-tool-presentation',
213
- config: { mode: 'ptc' },
214
- })
221
+ // 0.2.2-alpha.2 replaced the deprecated presentation selector with the
222
+ // explicit PTC executor row (the base deployment keeps
223
+ // tool-executor-native; a scoped executor row overrides it for this
224
+ // agent). Older hosts keep the presentation row they ship.
225
+ rows.push(executorPlugin
226
+ ? { id: 'tool-executor-ptc', name: '@deepseek-ai/dsh-tool-executor-ptc' }
227
+ : { id: 'tool-presentation', name: '@deepseek-ai/dsh-agent-tool-presentation', config: { mode: 'ptc' } })
215
228
  }
216
229
  if (kind === 'cordis') {
217
230
  rows.push({ id: 'tool-cordis', name: '@deepseek-ai/dsh-tool-cordis' })
@@ -224,16 +237,20 @@ export function pluginsFor({ kind, gitBash, skillsDir, pythonActive = false, hos
224
237
  rows.push({
225
238
  id: 'tool-plugin-manager',
226
239
  name: '@deepseek-ai/dsh-plugin-manager/tools',
227
- // The official 0.1.7 rows: ptc/standard ship it disabled, cordis keeps it
228
- // on wherever a profile context exists (every web deployment does).
229
- ...off(kind !== 'cordis'),
240
+ // The official rows: before 0.2.2-alpha.2 ptc/standard ship it disabled and
241
+ // cordis keeps it on (every web deployment has a profile context). From
242
+ // 0.2.2-alpha.2 on every preset enables it exactly when a profile context
243
+ // exists, so the probe decides for all three variants.
244
+ ...(executorPlugin ? off(!profileContext) : off(kind !== 'cordis')),
230
245
  })
231
246
  if (pluginMarket) {
232
247
  rows.push({
233
- // The official 0.2.1-alpha.4 rows: same disabled split as the manager.
248
+ // The official 0.2.1-alpha.4 rows, following the manager's split on
249
+ // both architectures (alpha.4: disabled on standard/ptc, profile-gated
250
+ // on cordis; alpha.2 of 0.2.2: profile-gated everywhere).
234
251
  id: 'tool-plugin-market',
235
252
  name: '@deepseek-ai/dsh-plugin-market/tools',
236
- ...off(kind !== 'cordis'),
253
+ ...(executorPlugin ? off(!profileContext) : off(kind !== 'cordis')),
237
254
  })
238
255
  }
239
256
  return rows
package/src/index.js CHANGED
@@ -1791,22 +1791,32 @@ function cleanupLegacyTrees(presetIds) {
1791
1791
  }
1792
1792
 
1793
1793
  /**
1794
- * Probe the dsh 0.2.1 host additions for the variant compositions: every
1795
- * full-tool official preset gained a `time-context` row (durable clock
1796
- * readings) and a `tool-schedule` row (the reminder tools). A preset row whose
1797
- * package is absent rejects the WHOLE mount, so the rows ride this probe: each
1798
- * is added only when its package resolves from the HOST's module base —
1799
- * `ctx.baseUrl`, the exact base `prepareProfileEntries` mounts preset rows
1800
- * from, so the probe can never disagree with the mounter. On dsh <= 0.2.0 all
1801
- * stay false and the row set stays byte-identical to the 0.1.7 mirror. Probed
1802
- * once per boot; the profile's package set does not change under a running
1803
- * host. `compaction` is the one flag minimal consumes (the official
1804
- * 0.2.1-alpha.3 minimal rows); the rest only shape the full variants.
1794
+ * Probe the dsh host additions for the variant compositions.
1795
+ *
1796
+ * `timeContext` / `toolSchedule` / `pluginMarket` / `compaction` are the
1797
+ * 0.2.1 rows (durable clock readings, reminder tools, the plugin market row,
1798
+ * the minimal tool-fs + compaction delta). `executorPlugin` marks the
1799
+ * 0.2.2-alpha.2 tool-execution architecture: the packages tool-executor-native
1800
+ * and tool-executor-ptc exist, the official presets mount the latter for PTC,
1801
+ * the subagent config renamed `modelSelectionSettings` to
1802
+ * `modelSelection` + `modelDiscovery`, and list-agents folded into the control
1803
+ * row. `profileContext` is the host fact the manager/market rows gate on since
1804
+ * alpha.2 (`!!js "!ctx.get('profileContext')"`) — computed from the live
1805
+ * service, not the package set.
1806
+ *
1807
+ * A preset row whose package is absent rejects the WHOLE mount, so every row
1808
+ * rides this probe: each is added only when its package resolves from the
1809
+ * HOST's module base — `ctx.baseUrl`, the exact base `prepareProfileEntries`
1810
+ * mounts preset rows from, so the probe can never disagree with the mounter.
1811
+ * On older hosts all stay false and the row set stays byte-identical to the
1812
+ * earlier mirror. Probed once per boot; the profile's package set does not
1813
+ * change under a running host.
1805
1814
  * @param {object} ctx - cordis context (any fiber of the running host).
1806
1815
  * @param {Function} [resolve] - predicate override for tests; receives a
1807
1816
  * package specifier, resolves like `require.resolve`, returns boolean.
1808
1817
  * @returns {Promise<{timeContext: boolean, toolSchedule: boolean,
1809
- * pluginMarket: boolean, compaction: boolean}>}
1818
+ * pluginMarket: boolean, compaction: boolean, executorPlugin: boolean,
1819
+ * profileContext: boolean}>}
1810
1820
  */
1811
1821
  export async function probeHostExtras(ctx, resolve) {
1812
1822
  let ok = resolve
@@ -1821,13 +1831,20 @@ export async function probeHostExtras(ctx, resolve) {
1821
1831
  ok = () => false
1822
1832
  }
1823
1833
  }
1824
- const [timeContext, toolSchedule, pluginMarket, compaction] = await Promise.all([
1834
+ const [timeContext, toolSchedule, pluginMarket, compaction, executorPlugin] = await Promise.all([
1825
1835
  Promise.resolve(safeProbe(ok, '@deepseek-ai/dsh-time-context')).then(Boolean),
1826
1836
  Promise.resolve(safeProbe(ok, '@deepseek-ai/dsh-tool-schedule')).then(Boolean),
1827
1837
  Promise.resolve(safeProbe(ok, '@deepseek-ai/dsh-plugin-market/tools')).then(Boolean),
1828
1838
  Promise.resolve(safeProbe(ok, '@deepseek-ai/dsh-compaction-basic')).then(Boolean),
1839
+ Promise.resolve(safeProbe(ok, '@deepseek-ai/dsh-tool-executor-ptc')).then(Boolean),
1829
1840
  ])
1830
- return { timeContext, toolSchedule, pluginMarket, compaction }
1841
+ let profileContext = false
1842
+ try {
1843
+ profileContext = ctx?.get?.('profileContext') !== undefined
1844
+ } catch {
1845
+ profileContext = false
1846
+ }
1847
+ return { timeContext, toolSchedule, pluginMarket, compaction, executorPlugin, profileContext }
1831
1848
  }
1832
1849
 
1833
1850
  /** Run one probe predicate; ANY failure reads as "absent" (a throwing
@@ -2274,12 +2291,25 @@ export async function apply(ctx, config = {}) {
2274
2291
  no run_code hint — so they meet the shell they were composed for. */
2275
2292
  const dialect = liveSettings.dialect()
2276
2293
  const applies = dialectApplies(dialect, assembleContext && assembleContext.agent)
2294
+ // dsh 0.2.2-alpha.2 narrowed this event to prompt PRESENTATION: it no
2295
+ // longer carries `tools` ("tool declarations remain provider-owned"),
2296
+ // so read the same list back from the tools service; older hosts keep
2297
+ // handing it over on the assembly.
2298
+ const offeredTools = Array.isArray(assembly && assembly.tools)
2299
+ ? assembly.tools
2300
+ : (() => {
2301
+ try {
2302
+ return ctx.get('tools')?.schemas?.(assembleContext && assembleContext.agent) ?? []
2303
+ } catch {
2304
+ return []
2305
+ }
2306
+ })()
2277
2307
  // Routing is dialect-independent and follows actual offered tools.
2278
2308
  // PTC may expose only run_code here: its generic SDK decision rule
2279
2309
  // relies on the registered bindings' own descriptions, not guessed
2280
2310
  // hidden names. Replace our block on reassembly/visibility changes.
2281
2311
  if (assembly && typeof assembly === 'object') {
2282
- applyToolRouting(assembly.tools, {
2312
+ applyToolRouting(offeredTools, {
2283
2313
  pwshVisible: liveSettings.pwshTool() === true,
2284
2314
  msys: applies && dialect.posixPaths === true,
2285
2315
  terminalGitBash: terminalDialect.gitBash === true,
@@ -2302,7 +2332,7 @@ export async function apply(ctx, config = {}) {
2302
2332
  // v0.20.1: the run_code sentence rides the SAME context entry, but
2303
2333
  // only when this assembly actually offers the tool (see
2304
2334
  // runCodeHintFor) — every other mode stays quiet.
2305
- const hint = runCodeHintFor(assembly.tools, dialect.codePaths === true)
2335
+ const hint = runCodeHintFor(offeredTools, dialect.codePaths === true)
2306
2336
  if (hint !== '') {
2307
2337
  for (const assembled of Array.isArray(assembly.contexts) ? assembly.contexts : []) {
2308
2338
  if (assembled && assembled.name === 'gitbash-shell:posix-paths' && typeof assembled.text === 'string') {