dsh-gitbash-shell 0.38.1 → 0.38.3

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,23 @@
3
3
  > 倒序排列,新版本条目在最上面。条目格式:`## vX.Y.Z — YYYY-MM-DD` + 类型(feat / fix / docs / chore)+ 要点 + 相关链接。
4
4
  > 纪律见 AGENTS.md「变更记录纪律」:发版前先更新本文件并随版本提交;事故复盘、复现与真机验证记录也记在这里。
5
5
 
6
+ ## v0.38.3 — 2026-10-13
7
+
8
+ **类型**:fix(补位激活的 scope 上下文时序;用户终端日志一锤定音)。
9
+
10
+ - **根因(日志 `official tool-bash activation failed: Cannot read properties of undefined (reading 'shell')`)**:cordis 的 `ctx.plugin()` **只创建 Fiber 就返回,插件的 apply 回调是异步启动的**(`vendor/cordis/lib/index.js:1619`,wrapped fiber 是 thenable)——`createScope` 返回时 `childCtx` 还是 `undefined`,`mod.apply(undefined, {})` 在官方模块第一行 `ctx.shell.sandboxMode` 上炸。此前的解析修复(v0.38.1)已生效:模块拿到了,死在最后一步。
11
+ - **修复**:`createScope` 返回 `{ fiber, get ctx(), dispose }`;`activateOfficialBash` 与 `providePwsh`(同款隐患,此前 pwsh7 开了也会静默发不出)在动手前 `await scope.fiber` 等回调跑完,再校验 `scope.ctx` 就绪。
12
+ - **冒烟**:118 项全绿。
13
+ - **真机判据**:升级重启新建会话 → 工具面出现 `bash`;日志出现 `official bash tool activated for this agent`。若再现 activation failed,错误行会指向官方模块内部的真实原因(而非 ctx undefined)。
14
+
15
+ ## v0.38.2 — 2026-10-13
16
+
17
+ **类型**:fix(v0.38.0 折叠分区在真机上完全失效;用户截图定位)。
18
+
19
+ - **`fold()` helper 签名与调用点不匹配(实锤 bug)**:七个调用点是 `fold("sec.xxx", 行, 行, ...)`,实现却按 `(key, titleKey, ...行)` 解析——**每个分区的第一行内容被吞进标题参数**,`t(<React元素>)` 得到空标题,卡片退化成一列无标题的平铺开关(v0.38.0 的折叠在真机从未生效)。修复:实现改为 `(titleKey, ...行)`,折叠状态键直接用词典键,调用点零改动。
20
+ - 官方用法核对(SystemPromptRow/PresentRow):`DisclosureRow` 的 props 形状(icon/title/open/expandable/expandOnRowClick/onToggle/children)与本插件用法一致,问题只在签名错乱。
21
+ - **冒烟**:118 项全绿;断言改锁 `folds[titleKey]`。
22
+
6
23
  ## v0.38.1 — 2026-10-13
7
24
 
8
25
  **类型**:fix(bash 补位在桌面版宿主解析不到官方包;真机反复确认的最后一个开放问题)。
package/dsh.plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "dsh-external/dsh-gitbash-shell",
3
- "version": "0.38.1",
3
+ "version": "0.38.3",
4
4
  "main": "./src/index.js",
5
5
  "description": "Windows 全模式 Git Bash:用 Git for Windows bash 替换 PowerShell 执行器;官方四个模式经行内工具补位直接获得 Git Bash(v0.35.0,默认),四个 *·Git Bash 变体 preset 可开关;附带 gitbash_pwsh(系统 PowerShell 7)与 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.38.1",
3
+ "version": "0.38.3",
4
4
  "description": "Windows 上让 agent 的每条 shell 命令改经 Git for Windows bash 执行;物化四个内置预设的 Git Bash 变体,统一 MSYS 盘根路径方言,侧栏终端接管可开关。· Run every agent shell command through Git for Windows bash on Windows; materialize Git Bash variants of the built-in presets, unify the MSYS drive-root path dialect, and adopt the sidebar terminal behind a switch.",
5
5
  "type": "module",
6
6
  "repository": {
package/src/client.js CHANGED
@@ -2107,7 +2107,11 @@ window.__ModuleLoader__.load({
2107
2107
  and expands the one theme they recognise. A stripped-down host
2108
2108
  without the export degrades to the static title+stack card. */
2109
2109
  var DisclosureRowComponent = icon("DisclosureRow");
2110
- function fold(key, titleKey) {
2110
+ /* v0.38.2 BUGFIX: the call sites are `fold("sec.xxx", row, row, ...)`
2111
+ — one dictionary key followed by the section's rows. The previous
2112
+ draft parsed (key, titleKey, ...) and ATE the first row into the
2113
+ title slot (t(<element>) → empty header, nothing folded). */
2114
+ function fold(titleKey) {
2111
2115
  var body = [];
2112
2116
  for (var i = 1; i < arguments.length; i++) body.push(arguments[i]);
2113
2117
  if (!DisclosureRowComponent || typeof DisclosureRowComponent !== "function") {
@@ -2120,10 +2124,10 @@ window.__ModuleLoader__.load({
2120
2124
  className: "gb-fold",
2121
2125
  icon: null,
2122
2126
  title: t(titleKey),
2123
- open: folds[key] === true,
2127
+ open: folds[titleKey] === true,
2124
2128
  expandable: true,
2125
2129
  expandOnRowClick: true,
2126
- onToggle: function () { toggleFold(key); },
2130
+ onToggle: function () { toggleFold(titleKey); },
2127
2131
  }, E("div", { className: "gb-stack" }, body));
2128
2132
  }
2129
2133
 
package/src/index.js CHANGED
@@ -2618,7 +2618,14 @@ export async function apply(ctx, config = {}) {
2618
2618
  let childCtx
2619
2619
  const fiber = agentCtx.plugin((c) => { childCtx = c })
2620
2620
  return {
2621
- ctx: childCtx,
2621
+ // cordis plugin() starts the fiber ASYNCHRONOUSLY — the apply
2622
+ // callback that captures childCtx has NOT run when plugin()
2623
+ // returns. The wrapped fiber is a thenable (`fiber.await()`):
2624
+ // awaiting it is the only way to observe childCtx being set
2625
+ // (v0.38.3, real machine: apply(undefined) crashed with
2626
+ // "Cannot read properties of undefined (reading 'shell')").
2627
+ fiber,
2628
+ get ctx() { return childCtx },
2622
2629
  dispose: async () => { try { await fiber?.dispose?.() } catch { /* already gone */ } },
2623
2630
  }
2624
2631
  },
@@ -279,6 +279,20 @@ export async function activateOfficialBash(agent, resolved, createScopeFn, log)
279
279
  return undefined
280
280
  }
281
281
  const scope = createScopeFn(agent.ctx)
282
+ // plugin() starts the fiber asynchronously; awaiting the wrapped thenable
283
+ // guarantees the apply callback has captured scope.ctx before we hand it
284
+ // to the official module (v0.38.2-and-earlier passed undefined here and
285
+ // crashed inside `ctx.shell`).
286
+ if (scope.fiber) {
287
+ try { await scope.fiber } catch (error) {
288
+ log(`official tool-bash scope fiber failed to start: ${error?.message ?? error}`)
289
+ return undefined
290
+ }
291
+ }
292
+ if (!scope.ctx) {
293
+ log('official tool-bash scope context did not initialize; activation skipped')
294
+ return undefined
295
+ }
282
296
  try {
283
297
  await mod.apply(scope.ctx, {})
284
298
  return scope
@@ -332,12 +346,15 @@ export function mountInlineTools(ctx, deps) {
332
346
  * pure ADDITION — it shadows nothing and requires no deny juggling. The
333
347
  * scope keeps the registration revertible at agent disposal.
334
348
  */
335
- const providePwsh = (agent, state) => {
349
+ const providePwsh = async (agent, state) => {
336
350
  if (state.pwshScope) return
337
351
  if (typeof spawn !== 'function' || !pwshPath) return
338
352
  if (!createScope) return
339
353
  try {
340
354
  const scope = createScope(agent.ctx)
355
+ // Same asynchronous-fiber shape as activateOfficialBash: wait for the
356
+ // apply callback to capture scope.ctx before touching its tools.
357
+ if (scope.fiber) { try { await scope.fiber } catch { /* disposed */ } }
341
358
  const registry = scope.ctx?.tools
342
359
  if (!registry || typeof registry.register !== 'function') {
343
360
  void scope.dispose().catch(() => {})
@@ -400,7 +417,7 @@ export function mountInlineTools(ctx, deps) {
400
417
  log(`fake-pwsh deny failed: ${error?.message ?? error}`)
401
418
  }
402
419
  }
403
- if (deps.pwshEnabled && deps.pwshEnabled() === true) providePwsh(agent, state)
420
+ if (deps.pwshEnabled && deps.pwshEnabled() === true) void providePwsh(agent, state)
404
421
  }
405
422
  }
406
423
  if (needs.needsBash && !state.scope) {