dsh-gitbash-shell 0.35.1 → 0.35.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 +11 -0
- package/dsh.plugin.json +1 -1
- package/package.json +1 -1
- package/src/index.js +1 -0
- package/src/inline-tools.js +42 -16
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
> 倒序排列,新版本条目在最上面。条目格式:`## vX.Y.Z — YYYY-MM-DD` + 类型(feat / fix / docs / chore)+ 要点 + 相关链接。
|
|
4
4
|
> 纪律见 AGENTS.md「变更记录纪律」:发版前先更新本文件并随版本提交;事故复盘、复现与真机验证记录也记在这里。
|
|
5
5
|
|
|
6
|
+
## v0.35.2 — 2026-10-12
|
|
7
|
+
|
|
8
|
+
**类型**:fix(Windows 真机报告;行内补位的时序洞 + 调用层兜底)。
|
|
9
|
+
|
|
10
|
+
- **修复:已存在的 agent 拿不到补位(用户 Windows 真机报告)**。症状:AI 调 `pwsh` 工具收到 `/usr/bin/bash: line 1: Select-String: command not found`——假 pwsh 的执行器在本机就是 `ctx.shell`(Git Bash),PowerShell 命令进了 bash。根因:补位判定此前**只挂在 `agent/created`** 上,本插件行**激活晚于 agent 存在**时(插件热重载、宿主先恢复会话后本 bundle 行才挂完),全部已存在的 agent 保持假 pwsh 且没有 bash,且永不再触发判定。修复为 **dsh-ops 验证过的双重独立层**(`installHostShellDenial` 同款形态):
|
|
11
|
+
- **层 1 — 挂载时补扫**:`mountInlineTools` 新增 `agents(ctx)` 依赖(index.js 传入 `ctx.get('agents')`),挂载那一刻对 `agents.list()` 里的每个**已存活 agent** 跑一遍 `reconcile`——与 created 事件同一条路径,250ms×5 有界重试等同样生效;
|
|
12
|
+
- **层 2 — 调用层守卫**:新增 `tools/pre-execute` 监听,凡 `pwsh` 调用到达分发层一律 deny,理由句直接指路替换品(bash 工具 / `gitbash_pwsh`)。两层层层独立:即便 per-agent 的 `restrict({ deny })` 输了竞态,谎工具也到不了执行器。
|
|
13
|
+
- **顺手修复:重名声明 SyntaxError**。v0.35.2 开发中引入的 `agents` 依赖与 `mountInlineTools` 内部的 agent 状态 Map 同名(`const` 重复声明,模块整体加载失败)。内部 Map 改名 `tracked`;冒烟加防回归断言(源码不得再现 `const agents = new Map()`)。
|
|
14
|
+
- **冒烟**:新增「inline tools: the mount-time sweep and the call-layer guard exist (v0.35.2)」;「…wires the patch…」补 `agents` 依赖接线断言。合计 114 项(113 过 + 1 跳)。
|
|
15
|
+
- **Windows 真机复验清单(升级后)**:①官方模式新会话有 bash 工具;②假 pwsh 调用被拒(deny 理由指路);③`gitbash_pwsh` 跑真 pwsh 7;④`gb_grep` 出参 /c/ 方言。v0.35.0 的真机验证项(见该条目)顺延至此版一起验。
|
|
16
|
+
|
|
6
17
|
## v0.35.1 — 2026-10-12
|
|
7
18
|
|
|
8
19
|
**类型**:fix(dsh-ptc-cordis-preset 联动显示;真机反馈)。
|
package/dsh.plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-external/dsh-gitbash-shell",
|
|
3
|
-
"version": "0.35.
|
|
3
|
+
"version": "0.35.2",
|
|
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.35.
|
|
3
|
+
"version": "0.35.2",
|
|
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/index.js
CHANGED
|
@@ -2608,6 +2608,7 @@ export async function apply(ctx, config = {}) {
|
|
|
2608
2608
|
try {
|
|
2609
2609
|
mountInlineTools(ctx, {
|
|
2610
2610
|
tools: (c) => { try { return c.get('tools') } catch { return undefined } },
|
|
2611
|
+
agents: (c) => { try { return c.get('agents') } catch { return undefined } },
|
|
2611
2612
|
createScope: (agentCtx) => {
|
|
2612
2613
|
let childCtx
|
|
2613
2614
|
const fiber = agentCtx.plugin((c) => { childCtx = c })
|
package/src/inline-tools.js
CHANGED
|
@@ -223,6 +223,7 @@ export async function activateOfficialBash(agent, toolBashHref, createScopeFn, l
|
|
|
223
223
|
/**
|
|
224
224
|
* Mount the per-agent reconcile. `deps`:
|
|
225
225
|
* - tools(ctx) -> the host tool registry (or undefined)
|
|
226
|
+
* - agents(ctx) -> the host agents service (or undefined)
|
|
226
227
|
* - createScope(fn) -> cordis createScope
|
|
227
228
|
* - allowed(session) -> danger-full-access verdict for the pwsh channel
|
|
228
229
|
* - echo(text) -> result dialect echo (Windows -> MSYS), or undefined
|
|
@@ -231,15 +232,20 @@ export async function activateOfficialBash(agent, toolBashHref, createScopeFn, l
|
|
|
231
232
|
* - pwshEnabled() -> the row switch for publishing the pwsh tool
|
|
232
233
|
* - log(message) -> the plugin's tagged logger
|
|
233
234
|
*
|
|
234
|
-
* Registration decisions re-run on EVERY agent creation
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
*
|
|
235
|
+
* Registration decisions re-run on EVERY agent creation AND once at mount
|
|
236
|
+
* time for every ALREADY-LIVE agent (the dsh-ops-proven shape,
|
|
237
|
+
* `installHostShellDenial`): this row can activate long after agents exist —
|
|
238
|
+
* a plugin hot-reload, or a host whose sessions resumed before this bundle
|
|
239
|
+
* row finished mounting — and an agent/created-only listener leaves every
|
|
240
|
+
* such agent with the fake pwsh and no bash, which is exactly the Windows
|
|
241
|
+
* field report behind this block. A second, INDEPENDENT layer guards the
|
|
242
|
+
* call itself through `tools/pre-execute`: visibility restriction can lose a
|
|
243
|
+
* race, and a lying pwsh that reaches its executor still runs Git Bash.
|
|
238
244
|
*/
|
|
239
245
|
export function mountInlineTools(ctx, deps) {
|
|
240
|
-
const { tools, createScope, allowed, spawn, pwshPath, echo, log } = deps
|
|
241
|
-
/** agent -> { timer, scope, denyPwsh } */
|
|
242
|
-
const
|
|
246
|
+
const { tools, agents, createScope, allowed, spawn, pwshPath, echo, log } = deps
|
|
247
|
+
/** agent -> { timer, scope, denyPwsh }; named `tracked` because `agents` above is the host service */
|
|
248
|
+
const tracked = new Map()
|
|
243
249
|
let pwshPublished = false
|
|
244
250
|
let pwshDisposer = undefined
|
|
245
251
|
let toolBashHrefPromise
|
|
@@ -287,17 +293,17 @@ export function mountInlineTools(ctx, deps) {
|
|
|
287
293
|
if (attempt < 5 && !names.includes('bash') && !names.includes('pwsh')) {
|
|
288
294
|
const timer = setTimeout(() => { try { reconcile(agent, { attempt: attempt + 1 }) } catch { /* never crash on a timer */ } }, 250)
|
|
289
295
|
timer.unref?.()
|
|
290
|
-
const state =
|
|
296
|
+
const state = tracked.get(agent)
|
|
291
297
|
if (state) state.timer = timer
|
|
292
|
-
else
|
|
298
|
+
else tracked.set(agent, { timer, scope: undefined, denyPwsh: undefined })
|
|
293
299
|
return
|
|
294
300
|
}
|
|
295
301
|
const needs = inlineNeeds(names)
|
|
296
|
-
let state =
|
|
302
|
+
let state = tracked.get(agent)
|
|
297
303
|
if (state?.timer) { clearTimeout(state.timer); state.timer = undefined }
|
|
298
304
|
if (!state) {
|
|
299
305
|
state = { timer: undefined, scope: undefined, denyPwsh: undefined }
|
|
300
|
-
|
|
306
|
+
tracked.set(agent, state)
|
|
301
307
|
}
|
|
302
308
|
if (needs.denyPwsh && !state.denyPwsh) {
|
|
303
309
|
// Deny the fake pwsh first: restrict is per-agent and idempotent, and
|
|
@@ -318,7 +324,7 @@ export function mountInlineTools(ctx, deps) {
|
|
|
318
324
|
return
|
|
319
325
|
}
|
|
320
326
|
const scope = await activateOfficialBash(agent, href, createScope, log)
|
|
321
|
-
if (scope &&
|
|
327
|
+
if (scope && tracked.get(agent) === state) {
|
|
322
328
|
state.scope = scope
|
|
323
329
|
log('official bash tool activated for this agent (Git Bash host; fake pwsh denied)')
|
|
324
330
|
}
|
|
@@ -334,9 +340,9 @@ export function mountInlineTools(ctx, deps) {
|
|
|
334
340
|
}
|
|
335
341
|
|
|
336
342
|
const teardown = (agent) => {
|
|
337
|
-
const state =
|
|
343
|
+
const state = tracked.get(agent)
|
|
338
344
|
if (!state) return
|
|
339
|
-
|
|
345
|
+
tracked.delete(agent)
|
|
340
346
|
if (state.timer) clearTimeout(state.timer)
|
|
341
347
|
if (state.denyPwsh) { try { state.denyPwsh() } catch { /* already lifted */ } }
|
|
342
348
|
if (state.scope) { void state.scope.dispose().catch(() => {}) }
|
|
@@ -345,14 +351,34 @@ export function mountInlineTools(ctx, deps) {
|
|
|
345
351
|
try {
|
|
346
352
|
ctx.on('agent/created', ({ agent } = {}) => { try { reconcile(agent) } catch { /* never break agent creation */ } })
|
|
347
353
|
ctx.on('agent/disposed', ({ agent } = {}) => { try { teardown(agent) } catch { /* never break disposal */ } })
|
|
354
|
+
// MOUNT-TIME SWEEP (v0.35.2, the Windows field report): agents that
|
|
355
|
+
// already exist when this row mounts never fire agent/created — a plugin
|
|
356
|
+
// hot-reload or a host that resumed sessions before this bundle row
|
|
357
|
+
// finished mounting would otherwise keep the fake pwsh and no bash on
|
|
358
|
+
// every live agent. Same shape the proven dsh-ops denial uses.
|
|
359
|
+
for (const agent of agents?.(ctx)?.list?.() ?? []) {
|
|
360
|
+
try { reconcile(agent) } catch { /* one broken agent never blocks the rest */ }
|
|
361
|
+
}
|
|
362
|
+
// CALL-LAYER GUARD (v0.35.2, second independent layer): even when the
|
|
363
|
+
// per-agent visibility restriction loses a race, a `pwsh` call that
|
|
364
|
+
// reaches its executor runs Git Bash (ctx.shell IS Git Bash on this
|
|
365
|
+
// host). Deny at dispatch and name the replacements.
|
|
366
|
+
ctx.on('tools/pre-execute', (exec, next) => {
|
|
367
|
+
try {
|
|
368
|
+
if (exec?.name === 'pwsh') {
|
|
369
|
+
return { kind: 'deny', reason: 'the host pwsh tool would run Git Bash on this host (its executor was replaced). Use the bash tool for commands, or gitbash_pwsh for Windows-native work (registry, services, WMI).' }
|
|
370
|
+
}
|
|
371
|
+
} catch { /* never block the waterfall */ }
|
|
372
|
+
return next()
|
|
373
|
+
})
|
|
348
374
|
} catch (error) {
|
|
349
375
|
log(`agent lifecycle wiring failed: ${error?.message ?? error}`)
|
|
350
376
|
return
|
|
351
377
|
}
|
|
352
378
|
|
|
353
379
|
ctx.effect(() => () => {
|
|
354
|
-
for (const agent of [...
|
|
355
|
-
|
|
380
|
+
for (const agent of [...tracked.keys()]) teardown(agent)
|
|
381
|
+
tracked.clear()
|
|
356
382
|
unpublishPwsh()
|
|
357
383
|
}, 'dsh-gitbash-shell: inline tool patching')
|
|
358
384
|
}
|