dsh-gitbash-shell 0.40.1 → 0.40.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 +25 -0
- package/README.md +7 -4
- package/dsh.plugin.json +1 -1
- package/package.json +6 -2
- package/src/bash-render.js +10 -5
- package/src/compositions.js +57 -21
- package/src/index.js +35 -16
package/CHANGELOG.md
CHANGED
|
@@ -3,8 +3,33 @@
|
|
|
3
3
|
> 倒序排列,新版本条目在最上面。条目格式:`## vX.Y.Z — YYYY-MM-DD` + 类型(feat / fix / docs / chore)+ 要点 + 相关链接。
|
|
4
4
|
> 纪律见 AGENTS.md「变更记录纪律」:发版前先更新本文件并随版本提交;事故复盘、复现与真机验证记录也记在这里。
|
|
5
5
|
|
|
6
|
+
## v0.40.3 — 2026-10-17
|
|
7
|
+
|
|
8
|
+
### gitBash 能力服务新增 `pwshToolEnabled`(feat,additive——配对 dsh-ptc-cordis-preset v0.20.1)
|
|
9
|
+
|
|
10
|
+
- **背景**:PTC 创造模式(ptc-cordis preset)的 pwsh 可见性矩阵有个残余不一致——gitbash-shell 单独安装且用户开启 `pwshTool` 开关时,官方 PTC/标准模式有 pwsh(遮蔽层放行、翻译层保护),而 ptc-cordis 组合仍禁(v0.20.0 只探测 dsh-ops 的 `opsPresent`,看不到本插件的私有设置)。跨插件没有读对方 config 的通道,唯一干净做法是把判定结果发布在已有的 `gitBash` 能力服务上。
|
|
11
|
+
- **改动**:`gitBashCapability` 新增 `get pwshToolEnabled()` —— 返回 `liveSettings.pwshTool() === true`,与遮蔽层(`src/inline-tools.js` 的 `pwshVisible` 判定)**同一读取器、同一语义**:能力字段回答的就是「pwsh 行此刻对本机 agent 是否可见」。纯 additive(先例:`ok/source` v0.28.0、`inlinePatched` v0.35.1),老消费方忽略新字段。
|
|
12
|
+
- **接线重排**:`const liveSettings = makeLiveReader(ctx, config)` 从能力服务之后提升到之前——getter 共享同一 reader,且声明先于能力对象构造,杜绝任何同步读取路径上的 TDZ。
|
|
13
|
+
- **测试**:smoke 源码断言补 getter 形状 + liveSettings 必须先于 `gitBashCapability` 声明(防 TDZ 复发)。236 tests / 235 pass / 1 skip / 0 fail。
|
|
14
|
+
- **消费方**:dsh-ptc-cordis-preset v0.20.1 起,组合条件从 `gitBashActive && !opsPresent` 扩为再 `&& !peerPwshTool`,「手动开 pwshTool、不装 dsh-ops」场景下 PTC 创造与官方模式一致放行。
|
|
15
|
+
|
|
16
|
+
## v0.40.2 — 2026-10-17
|
|
17
|
+
|
|
18
|
+
### 适配 dsh 0.2.1-alpha.5(0.2.1-rc.1 与其同码):组合对齐重跑 + exit-status 解析器跟齐(feat / fix / test)
|
|
19
|
+
|
|
20
|
+
- **组合行集跟随官方 0.2.1-alpha.3..alpha.5**(行 id 零改名;`tests/align-official.mjs` 重 pin 四枚 SHA256 后全绿):
|
|
21
|
+
- 官方在 alpha.3 **删除**了 subagent/subagent_fork 的 `toolFilter.deny`(`schedule_*` 四项——官方提醒工具重新可达子代理):插件侧 `subagentDeny` 整体删除,任何探针组合都不再产出 deny,与官方逐字节一致。
|
|
22
|
+
- alpha.4 给三个全工具 preset 新增 `tool-plugin-market` 行(紧跟 `tool-plugin-manager`;standard/ptc `disabled: true`,cordis `!!js !ctx.get('profileContext')`):挂新探针 `pluginMarket`(探测 `@deepseek-ai/dsh-plugin-market/tools`),disabled 分法与 manager 相同。
|
|
23
|
+
- alpha.3 给 **minimal** 新增 image-only `tool-fs`(`{read:false, readImage:true, write:false, edit:false}`)与专属 compaction 组(`isolate` 仅 `{compaction:true}`,**无** tool-result-pruner 行):`minimalPluginsFor` 增加 `hostExtras` 参数,挂 `compaction` 探针(探测 `@deepseek-ai/dsh-compaction-basic`)——minimal 不再是「永不加行」。
|
|
24
|
+
- `probeHostExtras` 扩为四探针(新增 plugin-market/tools、compaction-basic),返回 `{ timeContext, toolSchedule, pluginMarket, compaction }`;注册日志行同步;缺包/旧宿主仍保持 0.1.7 逐字节行集。
|
|
25
|
+
- **exit-status 解析器 null 感知(fix)**:`parseExitStatus` 的 exit 正则 `/(\d+)/` → `/(-?\d+|null)/`、`'null'` → `null`。官方 0.2.1-alpha.5 把 `TerminalResultView.exitCode` 放宽为 `number | null`(正常结束但无退出码),客户端卡模型(ui-tool `terminal-card-model.ts`)已解析 `[exit code: null]`,而本插件的移植解析器会把该标记当「未匹配」错落 `exitCode: 0`(读作成功)。本解析喂的是 terminal 卡(镜像 client 侧读法),故对齐 client 实现;官方服务端 `dsh-shell render.ts` 的同名解析器仍为 `(\d+)` 未跟(如实记录,不抄)。生产端 `renderResult` 对 `exitCode: null` 本就打出 `[exit code: null]`(与官方 background 断言一致),bash 工具 schema 早已允许 `integer|null`,均无需改。
|
|
26
|
+
- **测试同步**:`smoke.mjs` era 测试重写(默认无行 + probe-on 官方槽位 + deny **不得再出现** + minimal 四行断言)、`probeHostExtras` deepEqual 四键形状、minimal 接线正则(现在传 `hostExtras`)、`parseExitStatus` 加 null 例;`compatibility-regressions.mjs` 加 producer/parser 的 null 往返;`host-preview.mjs` hostExtras 形状同步。
|
|
27
|
+
- **元数据**:version 0.40.2;`dsh.compatibility.dshReleases` 增 `0.2.1-alpha.3`/`alpha.4`/`alpha.5`/`0.2.1-rc.1`(rc.1 于 2026-10-17 发布,与 alpha.5 同码——全仓 diff 仅 355 个 package.json 版本号 bump,align-official 对 rc.1 树复跑四 SHA 全绿;依据:静态对齐 + 全量回归;**Windows 双端真机验证待做**,发版前按家族纪律补)。
|
|
28
|
+
- 相关:dsh v0.2.1-alpha.3/4/5 Release;`tests/align-official.mjs`(需 dsh checkout,不属于 `npm test`)。
|
|
29
|
+
|
|
6
30
|
## v0.40.1 — 2026-10-15
|
|
7
31
|
|
|
32
|
+
|
|
8
33
|
### 清理 gitbash_native 的两个死配置读取(chore)
|
|
9
34
|
|
|
10
35
|
- 删除 `gitbash_native` 模块对 `config.enableRunInBackground`/`config.promoteOnTimeout` 的读取([v0.40.0 已知项](#v0400--2026-10-15)就此销账):该模块由 inline 接线**手动挂载在 agent scope**(`scope.ctx.plugin({...module})` 无参调用),行/执行器 Config 不可达,两个字段自 v0.40.0 起读到的恒为 undefined、按 `!== false` 恒开——是"没接线的开关面板"而非活门控。清理后行为一个字节不变:`background` 仅由 Jobs 注册表在场决定(这正是实际生效的逻辑),超时转 Job 跟随后台可用性;用户级开关仍是 `experimentalNative` 总闸(要关 native 后台只能整体关闭 native/path,官方 tool-bash 的同名活开关不受影响)。
|
package/README.md
CHANGED
|
@@ -70,10 +70,13 @@ Git Bash 增量;跟随 dsh 升级的对齐由冒烟测试
|
|
|
70
70
|
**preset id 保持 `code-gitbash` 不变**——会话钉在 id 上,dsh 0.1.2 把内置 `code`
|
|
71
71
|
改名 `ptc` 时本插件的变体 id 就没有跟随(改名会让已固定的会话报 preset not found)。
|
|
72
72
|
|
|
73
|
-
**dsh 0.2.1 增量自动随行(v0.34.0)**:官方 0.2.1 给全工具
|
|
74
|
-
(`time-context`)与提醒工具(`schedule_
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
**dsh 0.2.1 增量自动随行(v0.34.0 起,v0.40.2 对齐 alpha.5)**:官方 0.2.1 给全工具
|
|
74
|
+
preset 加了时间上下文(`time-context`)与提醒工具(`schedule_*`);alpha.3 又把这两行
|
|
75
|
+
从 subagent 的 `toolFilter.deny` 里移除(提醒工具重新可达子代理),给极简变体加了
|
|
76
|
+
image-only `tool-fs` 与专属 compaction 组,alpha.4 给全工具 preset 加了插件市场
|
|
77
|
+
(`tool-plugin-market`)。本插件在 0.2.1+ 宿主上探测到对应包即自动把上述行纳入变体
|
|
78
|
+
(全工具三变体随探针取 `time-context`/`tool-schedule`/`tool-plugin-market`,极简
|
|
79
|
+
变体只取 compaction 增量,与官方一致);旧宿主行为逐字节不变,**无需为此升级 dsh**。
|
|
77
80
|
|
|
78
81
|
## 安装(公开 npm 插件,推荐)
|
|
79
82
|
|
package/dsh.plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-external/dsh-gitbash-shell",
|
|
3
|
-
"version": "0.40.
|
|
3
|
+
"version": "0.40.3",
|
|
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.40.
|
|
3
|
+
"version": "0.40.3",
|
|
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": {
|
|
@@ -36,7 +36,11 @@
|
|
|
36
36
|
"dshReleases": {
|
|
37
37
|
"0.2.0-rc.2": "compatible",
|
|
38
38
|
"0.2.1-alpha.1": "compatible",
|
|
39
|
-
"0.2.1-alpha.2": "compatible"
|
|
39
|
+
"0.2.1-alpha.2": "compatible",
|
|
40
|
+
"0.2.1-alpha.3": "compatible",
|
|
41
|
+
"0.2.1-alpha.4": "compatible",
|
|
42
|
+
"0.2.1-alpha.5": "compatible",
|
|
43
|
+
"0.2.1-rc.1": "compatible"
|
|
40
44
|
}
|
|
41
45
|
}
|
|
42
46
|
},
|
package/src/bash-render.js
CHANGED
|
@@ -48,16 +48,21 @@ export function escalationHintMarker(subject) {
|
|
|
48
48
|
export const ESCALATION_TARGETS = Object.freeze(['workspace-write', 'danger-full-access'])
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
|
-
* The official exit-status parse (dsh-shell render.ts
|
|
52
|
-
*
|
|
51
|
+
* The official exit-status parse (the producer twin is dsh-shell render.ts,
|
|
52
|
+
* the reader twin is ui-tool terminal-card-model.ts — the card reader, which
|
|
53
|
+
* is what this parse feeds): the LAST marker line anchors the split between
|
|
54
|
+
* the output body and the exit pill. `null` is the official 0.2.1-alpha.5
|
|
55
|
+
* widening — the process ENDED without reporting a code; the card model reads
|
|
56
|
+
* an explicit null as a failure, while the marker-less fallback below still
|
|
57
|
+
* reads as success.
|
|
53
58
|
* @param {string} text - the rendered result text.
|
|
54
|
-
* @returns {{ body: string, exitCode?: number, signal?: string }}
|
|
59
|
+
* @returns {{ body: string, exitCode?: number | null, signal?: string }}
|
|
55
60
|
*/
|
|
56
61
|
export function parseExitStatus(text) {
|
|
57
62
|
const signal = /\n\[killed by signal: ([^\]\n]+)\]$/.exec(text)
|
|
58
63
|
if (signal && signal[1] !== undefined) return { body: text.slice(0, signal.index), signal: signal[1] }
|
|
59
|
-
const exit = /\n\[exit code: (
|
|
60
|
-
if (exit && exit[1] !== undefined) return { body: text.slice(0, exit.index), exitCode: Number(exit[1]) }
|
|
64
|
+
const exit = /\n\[exit code: (-?\d+|null)\]$/.exec(text)
|
|
65
|
+
if (exit && exit[1] !== undefined) return { body: text.slice(0, exit.index), exitCode: exit[1] === 'null' ? null : Number(exit[1]) }
|
|
61
66
|
return { body: text, exitCode: 0 }
|
|
62
67
|
}
|
|
63
68
|
|
package/src/compositions.js
CHANGED
|
@@ -7,12 +7,14 @@
|
|
|
7
7
|
* of the committed assets/<variant>/agent.cordis*.yml texts the materializer
|
|
8
8
|
* writes on older hosts.
|
|
9
9
|
*
|
|
10
|
-
* Every variant mirrors the official
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
10
|
+
* Every variant mirrors the official preset it replaces (packages/bundle/
|
|
11
|
+
* web-app/presets/{standard,minimal,ptc,cordis}.patch.yml) with the Git Bash
|
|
12
|
+
* routing: full variants keep the official platform-gated shell rows, and the
|
|
13
|
+
* inline patch adds OUR bash over a private executor on Windows. The minimal
|
|
14
|
+
* variant instead keeps its persistent Git Bash terminal rows. On non-Windows
|
|
15
|
+
* hosts the official stack stays native. Host-release deltas ride hostExtras
|
|
16
|
+
* probes (the block below the header rows) — each probe keeps the base set
|
|
17
|
+
* byte-identical to the 0.1.7 mirror. A conditional delta exists while
|
|
16
18
|
* dsh-ptc-cordis-preset reports its experimental-CPython backend ACTIVE: the
|
|
17
19
|
* two workflow rows follow the official Python composition and go off (see
|
|
18
20
|
* `pythonActive` below). While that backend is off — the default, and also
|
|
@@ -82,18 +84,18 @@ export function pluginsFor({ kind, gitBash, skillsDir, pythonActive = false, hos
|
|
|
82
84
|
const bashDisabled = win
|
|
83
85
|
const pwshDisabled = !win
|
|
84
86
|
const workflowOn = kind !== 'ptc' && pythonActive !== true
|
|
85
|
-
// dsh 0.2.1
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
//
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
87
|
+
// dsh 0.2.1 grew the official full-tool presets across releases, all
|
|
88
|
+
// row-id-stable: alpha.2 added time-context (durable clock readings) and
|
|
89
|
+
// tool-schedule (the reminder tools); alpha.3 DELETED the schedule_*
|
|
90
|
+
// toolFilter deny from the subagent/subagent_fork configs (official
|
|
91
|
+
// reminders reach subagents again — the deny was never load-bearing,
|
|
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
|
|
97
99
|
const rows = [
|
|
98
100
|
{
|
|
99
101
|
id: 'persona',
|
|
@@ -170,12 +172,12 @@ export function pluginsFor({ kind, gitBash, skillsDir, pythonActive = false, hos
|
|
|
170
172
|
{
|
|
171
173
|
id: 'tool-subagent',
|
|
172
174
|
name: '@deepseek-ai/dsh-tool-subagent',
|
|
173
|
-
config: { provider: 'spawn', toolName: 'subagent', modelSelectionSettings: true, ...(timeContext ? {} : { backgroundMode: 'continuable' })
|
|
175
|
+
config: { provider: 'spawn', toolName: 'subagent', modelSelectionSettings: true, ...(timeContext ? {} : { backgroundMode: 'continuable' }) },
|
|
174
176
|
},
|
|
175
177
|
{
|
|
176
178
|
id: 'tool-subagent-fork',
|
|
177
179
|
name: '@deepseek-ai/dsh-tool-subagent',
|
|
178
|
-
config: { provider: 'fork', toolName: 'subagent_fork', ...(timeContext ? {} : { backgroundMode: 'continuable' })
|
|
180
|
+
config: { provider: 'fork', toolName: 'subagent_fork', ...(timeContext ? {} : { backgroundMode: 'continuable' }) },
|
|
179
181
|
},
|
|
180
182
|
{
|
|
181
183
|
id: 'workflow-ptc',
|
|
@@ -226,6 +228,14 @@ export function pluginsFor({ kind, gitBash, skillsDir, pythonActive = false, hos
|
|
|
226
228
|
// on wherever a profile context exists (every web deployment does).
|
|
227
229
|
...off(kind !== 'cordis'),
|
|
228
230
|
})
|
|
231
|
+
if (pluginMarket) {
|
|
232
|
+
rows.push({
|
|
233
|
+
// The official 0.2.1-alpha.4 rows: same disabled split as the manager.
|
|
234
|
+
id: 'tool-plugin-market',
|
|
235
|
+
name: '@deepseek-ai/dsh-plugin-market/tools',
|
|
236
|
+
...off(kind !== 'cordis'),
|
|
237
|
+
})
|
|
238
|
+
}
|
|
229
239
|
return rows
|
|
230
240
|
}
|
|
231
241
|
|
|
@@ -241,9 +251,14 @@ export function pluginsFor({ kind, gitBash, skillsDir, pythonActive = false, hos
|
|
|
241
251
|
* pins the historical default, so a missing Git stays a VISIBLE spawn
|
|
242
252
|
* failure — never a substitute shell (issue #15: the hardcoded default
|
|
243
253
|
* broke every PTY spawn where Git lives outside `C:/Program Files/Git`).
|
|
254
|
+
* @param {object} [input.hostExtras] - the host probe (probeHostExtras):
|
|
255
|
+
* `compaction` true adds the official 0.2.1-alpha.3 minimal rows (an
|
|
256
|
+
* image-read-only tool-fs plus the pruner-less compaction group) ahead of
|
|
257
|
+
* the terminal.
|
|
244
258
|
* @returns {object[]} the declarative plugins list.
|
|
245
259
|
*/
|
|
246
|
-
export function minimalPluginsFor({ bashPath } = {}) {
|
|
260
|
+
export function minimalPluginsFor({ bashPath, hostExtras = {} } = {}) {
|
|
261
|
+
const { compaction = false } = hostExtras
|
|
247
262
|
const win = typeof process !== 'undefined' && process.platform === 'win32'
|
|
248
263
|
return [
|
|
249
264
|
{
|
|
@@ -255,6 +270,27 @@ export function minimalPluginsFor({ bashPath } = {}) {
|
|
|
255
270
|
includeRuntimeContext: false,
|
|
256
271
|
},
|
|
257
272
|
},
|
|
273
|
+
...(compaction ? [
|
|
274
|
+
{
|
|
275
|
+
// Official 0.2.1-alpha.3 minimal: image reads ride the fs tool; every
|
|
276
|
+
// other fs verb stays with the persistent terminal.
|
|
277
|
+
id: 'tool-fs',
|
|
278
|
+
name: '@deepseek-ai/dsh-tool-fs',
|
|
279
|
+
config: { read: false, readImage: true, write: false, edit: false },
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
// Official 0.2.1-alpha.3 minimal compaction group: NO pruner row
|
|
283
|
+
// (isolate carries compaction alone, unlike the full presets).
|
|
284
|
+
id: 'compaction',
|
|
285
|
+
name: 'cordis:group',
|
|
286
|
+
group: true,
|
|
287
|
+
isolate: { compaction: true },
|
|
288
|
+
config: [
|
|
289
|
+
{ id: 'compaction-basic', name: '@deepseek-ai/dsh-compaction-basic' },
|
|
290
|
+
{ id: 'command-compact', name: '@deepseek-ai/dsh-command-compact' },
|
|
291
|
+
],
|
|
292
|
+
},
|
|
293
|
+
] : []),
|
|
258
294
|
{
|
|
259
295
|
id: 'persistent-shell',
|
|
260
296
|
name: 'cordis:group',
|
package/src/index.js
CHANGED
|
@@ -1765,14 +1765,16 @@ function cleanupLegacyTrees(presetIds) {
|
|
|
1765
1765
|
* package is absent rejects the WHOLE mount, so the rows ride this probe: each
|
|
1766
1766
|
* is added only when its package resolves from the HOST's module base —
|
|
1767
1767
|
* `ctx.baseUrl`, the exact base `prepareProfileEntries` mounts preset rows
|
|
1768
|
-
* from, so the probe can never disagree with the mounter. On dsh <= 0.2.0
|
|
1768
|
+
* from, so the probe can never disagree with the mounter. On dsh <= 0.2.0 all
|
|
1769
1769
|
* stay false and the row set stays byte-identical to the 0.1.7 mirror. Probed
|
|
1770
1770
|
* once per boot; the profile's package set does not change under a running
|
|
1771
|
-
* host.
|
|
1771
|
+
* host. `compaction` is the one flag minimal consumes (the official
|
|
1772
|
+
* 0.2.1-alpha.3 minimal rows); the rest only shape the full variants.
|
|
1772
1773
|
* @param {object} ctx - cordis context (any fiber of the running host).
|
|
1773
1774
|
* @param {Function} [resolve] - predicate override for tests; receives a
|
|
1774
1775
|
* package specifier, resolves like `require.resolve`, returns boolean.
|
|
1775
|
-
* @returns {Promise<{timeContext: boolean, toolSchedule: boolean
|
|
1776
|
+
* @returns {Promise<{timeContext: boolean, toolSchedule: boolean,
|
|
1777
|
+
* pluginMarket: boolean, compaction: boolean}>}
|
|
1776
1778
|
*/
|
|
1777
1779
|
export async function probeHostExtras(ctx, resolve) {
|
|
1778
1780
|
let ok = resolve
|
|
@@ -1787,11 +1789,13 @@ export async function probeHostExtras(ctx, resolve) {
|
|
|
1787
1789
|
ok = () => false
|
|
1788
1790
|
}
|
|
1789
1791
|
}
|
|
1790
|
-
const [timeContext, toolSchedule] = await Promise.all([
|
|
1792
|
+
const [timeContext, toolSchedule, pluginMarket, compaction] = await Promise.all([
|
|
1791
1793
|
Promise.resolve(safeProbe(ok, '@deepseek-ai/dsh-time-context')).then(Boolean),
|
|
1792
1794
|
Promise.resolve(safeProbe(ok, '@deepseek-ai/dsh-tool-schedule')).then(Boolean),
|
|
1795
|
+
Promise.resolve(safeProbe(ok, '@deepseek-ai/dsh-plugin-market/tools')).then(Boolean),
|
|
1796
|
+
Promise.resolve(safeProbe(ok, '@deepseek-ai/dsh-compaction-basic')).then(Boolean),
|
|
1793
1797
|
])
|
|
1794
|
-
return { timeContext, toolSchedule }
|
|
1798
|
+
return { timeContext, toolSchedule, pluginMarket, compaction }
|
|
1795
1799
|
}
|
|
1796
1800
|
|
|
1797
1801
|
/** Run one probe predicate; ANY failure reads as "absent" (a throwing
|
|
@@ -1871,7 +1875,7 @@ async function registerVariant(ctx, presetId, { gitBashActive, skillsDir, python
|
|
|
1871
1875
|
const meta = PRESET_META[presetId]
|
|
1872
1876
|
if (!meta) return undefined
|
|
1873
1877
|
const plugins = meta.kind === 'minimal'
|
|
1874
|
-
? minimalPluginsFor({ bashPath: minimalPtyBashPath(readBashResolution) })
|
|
1878
|
+
? minimalPluginsFor({ bashPath: minimalPtyBashPath(readBashResolution), hostExtras })
|
|
1875
1879
|
: pluginsFor({ kind: meta.kind, gitBash: gitBashActive, skillsDir, pythonActive, hostExtras })
|
|
1876
1880
|
return ctx.agentPresets.register({
|
|
1877
1881
|
id: presetId,
|
|
@@ -1908,9 +1912,10 @@ async function runDeclarativeEra(ctx, presetIds, readSuppress, readBashResolutio
|
|
|
1908
1912
|
cleanupLegacyTrees(presetIds)
|
|
1909
1913
|
const gitBashActive = process.platform === 'win32'
|
|
1910
1914
|
const skillsDir = await resolveSkillsDir()
|
|
1911
|
-
// The dsh 0.2.1 additions (time-context / tool-schedule
|
|
1912
|
-
//
|
|
1913
|
-
// cannot change under a
|
|
1915
|
+
// The dsh 0.2.1 additions (time-context / tool-schedule / plugin-market /
|
|
1916
|
+
// minimal compaction rows) probe once per boot and ride every
|
|
1917
|
+
// (re-)registration below — the profile's package set cannot change under a
|
|
1918
|
+
// running host.
|
|
1914
1919
|
const hostExtras = await probeHostExtras(ctx)
|
|
1915
1920
|
/** presetId -> unregister, i.e. exactly what is live right now. */
|
|
1916
1921
|
const live = new Map()
|
|
@@ -2007,8 +2012,13 @@ async function runDeclarativeEra(ctx, presetIds, readSuppress, readBashResolutio
|
|
|
2007
2012
|
console.log(TAG + ' registered ' + live.size + ' preset(s) declaratively (' + [...live.keys()].join(', ') + ')'
|
|
2008
2013
|
+ (live.size === 0 ? ' — variantPresets is off: the official presets carry Git Bash through the inline tool patch (see the CHANGELOG)'
|
|
2009
2014
|
: '')
|
|
2010
|
-
+ (hostExtras.timeContext || hostExtras.toolSchedule
|
|
2011
|
-
? ' [dsh 0.2.1 additions: ' +
|
|
2015
|
+
+ (hostExtras.timeContext || hostExtras.toolSchedule || hostExtras.pluginMarket || hostExtras.compaction
|
|
2016
|
+
? ' [dsh 0.2.1 additions: ' + [
|
|
2017
|
+
hostExtras.timeContext ? 'time-context' : '',
|
|
2018
|
+
hostExtras.toolSchedule ? 'tool-schedule' : '',
|
|
2019
|
+
hostExtras.pluginMarket ? 'plugin-market' : '',
|
|
2020
|
+
hostExtras.compaction ? 'minimal compaction' : '',
|
|
2021
|
+
].filter(Boolean).join(' + ') + ']'
|
|
2012
2022
|
: ''))
|
|
2013
2023
|
|
|
2014
2024
|
// The peer's capability: `ctx.inject` makes this independent of row order,
|
|
@@ -2096,6 +2106,13 @@ export async function apply(ctx, config = {}) {
|
|
|
2096
2106
|
console.log(`${TAG} inspect-registry shim wiring failed: ${error?.message ?? error}`)
|
|
2097
2107
|
}
|
|
2098
2108
|
|
|
2109
|
+
// Era-aware live settings: every consumer below re-reads the row Config
|
|
2110
|
+
// refs on every use (volatile), so a flipped knob lands on the next
|
|
2111
|
+
// dispatch with zero wiring. Declared BEFORE the cooperation capability so
|
|
2112
|
+
// its getters share the same reader (v0.40.3 pwshToolEnabled) — the
|
|
2113
|
+
// capability must answer with the exact value the masking layer sees.
|
|
2114
|
+
const liveSettings = makeLiveReader(ctx, config)
|
|
2115
|
+
|
|
2099
2116
|
// ── cooperation capability ────────────────────────────────────────────────
|
|
2100
2117
|
// Publish whether the Git Bash shell stack is active on this host so peer
|
|
2101
2118
|
// plugins (e.g. dsh-ptc-cordis-preset) can adopt it in the presets they
|
|
@@ -2130,6 +2147,13 @@ export async function apply(ctx, config = {}) {
|
|
|
2130
2147
|
// anything — peers reading this flag drop the suffix (dsh-ptc-cordis-preset
|
|
2131
2148
|
// v0.17.3+); older peers ignore it and keep the v0.34 wording.
|
|
2132
2149
|
get inlinePatched() { return process.platform === 'win32' },
|
|
2150
|
+
// Additive (v0.40.3): whether the official pwsh row is VISIBLE for agents
|
|
2151
|
+
// on this host — the exact `pwshTool() === true` verdict the masking layer
|
|
2152
|
+
// reads (src/inline-tools.js hidePwsh), so peers composing the same row
|
|
2153
|
+
// key off one signal instead of re-deriving the switch. Default OFF
|
|
2154
|
+
// (bash-first); the switch is live, so a flip lands on the next read.
|
|
2155
|
+
// Older peers ignore the field and keep the v0.20.0 ops-only behavior.
|
|
2156
|
+
get pwshToolEnabled() { return liveSettings.pwshTool() === true },
|
|
2133
2157
|
// Kept for existing consumers (peer plugins read `bashPath`): the resolved
|
|
2134
2158
|
// interpreter. When resolution failed we report the explicit value (or the
|
|
2135
2159
|
// historical default) so the ENOENT a consumer may hit names a real path —
|
|
@@ -2149,11 +2173,6 @@ export async function apply(ctx, config = {}) {
|
|
|
2149
2173
|
const disposeGitBash = ctx.provide('gitBash', gitBashCapability)
|
|
2150
2174
|
ctx.effect(() => disposeGitBash, 'dsh-gitbash-shell: gitBash capability')
|
|
2151
2175
|
|
|
2152
|
-
// Era-aware live settings: every consumer below re-reads the row Config
|
|
2153
|
-
// refs on every use (volatile), so a flipped knob lands on the next
|
|
2154
|
-
// dispatch with zero wiring.
|
|
2155
|
-
const liveSettings = makeLiveReader(ctx, config)
|
|
2156
|
-
|
|
2157
2176
|
// ── official shell-env fact: DSH_PATH_DIALECT (Windows only, gated; v0.11.0) ──
|
|
2158
2177
|
// dsh-shell-env owns the model-visible $DSH_* facts (host-plane service;
|
|
2159
2178
|
// the web composition injects it and publishes DSH_WEB_URL beside the
|