@zmainer/dsh-wx-bridge 1.1.0 → 1.1.1
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/README.md +13 -8
- package/lib/kernel/acp-overlay-chat.yml +4 -5
- package/lib/kernel/acp-overlay.yml +4 -5
- package/lib/kernel/bridge.mjs +8 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -74,7 +74,7 @@ dsh plugin --profile <profile> add @zmainer/dsh-wx-bridge
|
|
|
74
74
|
"preset": "<预设 id,留空跟随 DSH 默认预设>",
|
|
75
75
|
"enabled": true,
|
|
76
76
|
"permPolicy": "ask",
|
|
77
|
-
"permPreset": "
|
|
77
|
+
"permPreset": "workspace-write",
|
|
78
78
|
"approvalTimeoutMs": 120000
|
|
79
79
|
}
|
|
80
80
|
}
|
|
@@ -95,7 +95,7 @@ dsh plugin --profile <profile> add @zmainer/dsh-wx-bridge
|
|
|
95
95
|
| `acp.dshBin` | ACP 用的 dsh 入口(默认跟随宿主运行时,schema 才一致) | 自动 |
|
|
96
96
|
| `acp.patch` | 覆盖叠层文件路径(预设档自动生成) | 插件内置 |
|
|
97
97
|
| `acp.permPolicy` | 审批策略:`ask`(默认,推到微信等回复)/ `allow`(自动批准)/ `reject`(一律拒绝) | ask |
|
|
98
|
-
| `acp.permPreset` | 手机通道权限预设(写进 ACP 叠层):`
|
|
98
|
+
| `acp.permPreset` | 手机通道权限预设(写进 ACP 叠层):`workspace-write`(默认)/ `read-only` / `danger-full-access`。越界的写与提权会在微信里弹审批卡 | workspace-write |
|
|
99
99
|
| `acp.approvalTimeoutMs` | 审批卡等待时长(超时按拒绝) | 120000 |
|
|
100
100
|
| `acp.patchAcp` | 是否允许给已装 `dsh-acp` 打预设补丁 | true |
|
|
101
101
|
|
|
@@ -127,10 +127,10 @@ dsh plugin --profile <profile> add @zmainer/dsh-wx-bridge
|
|
|
127
127
|
|
|
128
128
|
## 安全基线
|
|
129
129
|
|
|
130
|
-
- **权限预设(`acp.permPreset`,默认 `
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
130
|
+
- **权限预设(`acp.permPreset`,默认 `workspace-write`)**:手机任务默认只能写工作区;**越界的写与提权会变成
|
|
131
|
+
审批卡推到微信**,回「批准 / 拒绝」即可(1.1.0 起)。这正是默认从 `danger-full-access` 收紧的原因——
|
|
132
|
+
手机可应答审批后,不必再用"最宽权限"来绕开"无人可答"。要更严:`read-only`;要旧行为(免审批全权,
|
|
133
|
+
适合 `mvn` 写 `~/.m2` 这类高频越界任务):`danger-full-access`。
|
|
134
134
|
- **审批默认 `ask`**:需要审批的操作会把卡片推到微信等回复;**120 秒未回按拒绝**(fail-closed),
|
|
135
135
|
也可发 `/审批 自动` 恢复"自动批准"、`/审批 拒绝` 变成一律拒绝。找不到归属联系人的审批一律拒绝。
|
|
136
136
|
- **准入默认 `strict`**(TOFU 白名单 + 一次性登记 token):未登记的发送者**不执行**,但只回一次可操作提示
|
|
@@ -166,8 +166,8 @@ ACP 的 `session/request_permission` 请求**必须被应答**。早先版本只
|
|
|
166
166
|
- 同一时刻每个人只留一张卡:新卡到达会作废旧卡(避免"批准"批到过期的那张)。
|
|
167
167
|
- 开关:`/审批` 看策略、`/审批 询问|自动|拒绝` 改;面板/HTTP 侧用 `POST /wxbridge/approval`。
|
|
168
168
|
|
|
169
|
-
>
|
|
170
|
-
>
|
|
169
|
+
> 什么时候会真的看到审批卡?**当通道权限预设被收紧时**——默认的 `workspace-write` 就意味着
|
|
170
|
+
> "工作区之外的写 / 提权"会先问你;若不想要这种打扰,把 `acp.permPreset` 改成 `danger-full-access`。
|
|
171
171
|
|
|
172
172
|
## 主动推送(1.1.0)
|
|
173
173
|
|
|
@@ -266,6 +266,11 @@ ode_modules\@zmainer\dsh-wx-bridge` → 改名成 `...dsh-wx-bridge.bak` 更稳
|
|
|
266
266
|
|
|
267
267
|
## 最近变更
|
|
268
268
|
|
|
269
|
+
- **1.1.1**:**默认权限预设从 `danger-full-access` 收紧为 `workspace-write`**——审批能在微信里答了以后,
|
|
270
|
+
"手机端无人可答审批"就不再是把通道放到最宽的理由。行为变化:工作区之外的写与提权会先在微信里弹审批卡
|
|
271
|
+
(回「批准 / 拒绝」),要旧行为就把 `acp.permPreset` 设回 `danger-full-access`,要更严设 `read-only`。
|
|
272
|
+
同时把子进程 home 的 `settings.yaml` / headless profile 补丁里写死的 `workspace-write` 接到同一个配置项,
|
|
273
|
+
并修好「对话模式」生成叠层的 `defaultPreset` 替换(此前只在模板写死旧值时才替换)。
|
|
269
274
|
- **1.1.0**:**微信内审批应答 + 主动推送**(两条都是用户要求)——
|
|
270
275
|
① **审批**:ACP 的 `session/request_permission` 不再由桥按固定策略静默回答,而是把卡片推到微信
|
|
271
276
|
(选项带编号),回「批准 / 拒绝 / 1 / 2」即映射成 ACP 的 `optionId` 回去;**超时 120 秒按拒绝**
|
|
@@ -8,13 +8,12 @@
|
|
|
8
8
|
- id: dsh-computer-use
|
|
9
9
|
disabled: true
|
|
10
10
|
|
|
11
|
-
# 通道权限预设(config.acp.permPreset,默认
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
# 默认留在最宽,是因为 ~/.m2 之类的写操作会被 workspace-write 拦掉(maven 编译直接失败)。
|
|
11
|
+
# 通道权限预设(config.acp.permPreset,默认 workspace-write):
|
|
12
|
+
# 越界(工作区之外)的写与提权会把审批卡推到微信——回「批准 / 拒绝」(或 1 / 2)即可,
|
|
13
|
+
# 120 秒未回按拒绝处理(fail-closed)。要更严:read-only;要旧行为(免审批全权):danger-full-access。
|
|
15
14
|
- id: permission
|
|
16
15
|
config:
|
|
17
|
-
defaultPreset:
|
|
16
|
+
defaultPreset: workspace-write
|
|
18
17
|
- id: skill-filesystem
|
|
19
18
|
disabled: true
|
|
20
19
|
- id: tool-skill
|
|
@@ -8,13 +8,12 @@
|
|
|
8
8
|
- id: dsh-computer-use
|
|
9
9
|
disabled: true
|
|
10
10
|
|
|
11
|
-
# 通道权限预设(config.acp.permPreset,默认
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
# 默认留在最宽,是因为 ~/.m2 之类的写操作会被 workspace-write 拦掉(maven 编译直接失败)。
|
|
11
|
+
# 通道权限预设(config.acp.permPreset,默认 workspace-write):
|
|
12
|
+
# 越界(工作区之外)的写与提权会把审批卡推到微信——回「批准 / 拒绝」(或 1 / 2)即可,
|
|
13
|
+
# 120 秒未回按拒绝处理(fail-closed)。要更严:read-only;要旧行为(免审批全权):danger-full-access。
|
|
15
14
|
- id: permission
|
|
16
15
|
config:
|
|
17
|
-
defaultPreset:
|
|
16
|
+
defaultPreset: workspace-write
|
|
18
17
|
#
|
|
19
18
|
# 备注(2026-09-21 实测,别重复踩):**模型目录不随行配置走**。
|
|
20
19
|
# 本文件曾试在两处放 llm-deepseek 目录(改行 config;停用 base 行 + 换行 id 插副本),
|
package/lib/kernel/bridge.mjs
CHANGED
|
@@ -236,10 +236,11 @@ const PERM_MODES = ['ask', 'allow', 'reject']
|
|
|
236
236
|
function normPermMode(v, d = 'ask') { const s = String(v ?? '').toLowerCase(); return PERM_MODES.includes(s) ? s : d }
|
|
237
237
|
let ACP_PERM = normPermMode(ACP_CFG.permPolicy, 'ask')
|
|
238
238
|
const APPROVAL_TIMEOUT_MS = Number(process.env.WXBRIDGE_APPROVAL_TIMEOUT_MS || ACP_CFG.approvalTimeoutMs || 120000)
|
|
239
|
-
// 手机通道的权限预设(ACP 叠层里 permission.defaultPreset
|
|
240
|
-
//
|
|
241
|
-
//
|
|
242
|
-
|
|
239
|
+
// 手机通道的权限预设(ACP 叠层里 permission.defaultPreset)。默认 workspace-write:
|
|
240
|
+
// 越界(工作区之外)的写与提权会变成审批卡推到微信,回「批准 / 拒绝」即可 —— 手机可应答后,
|
|
241
|
+
// 不必再用"最宽权限"绕开审批。要回到旧行为:config.json 的 acp.permPreset 设 danger-full-access;
|
|
242
|
+
// 要更严:read-only(连写工作区都要批,maven 写 ~/.m2 也会拦)。
|
|
243
|
+
const ACP_PERM_PRESET = String(ACP_CFG.permPreset || 'workspace-write')
|
|
243
244
|
// 主动推送:外部往 outbox 丢 JSON,桥轮询代发(见 outbox.mjs / wxpush.mjs)
|
|
244
245
|
const OUTBOX_DIR = join(STATE_DIR, 'outbox')
|
|
245
246
|
const OUTBOX_SENT_DIR = join(OUTBOX_DIR, 'sent')
|
|
@@ -407,7 +408,7 @@ function prepareChildHome() {
|
|
|
407
408
|
writeFileSync(join(prof, 'cordis.yml'), '# dsh profile root (managed by wxbridge)' + NL + '[]' + NL)
|
|
408
409
|
writeFileSync(join(prof, 'cordis.patch.yml'),
|
|
409
410
|
'# wxbridge: keep headless permissions narrow without touching the host settings.yaml' + NL
|
|
410
|
-
+ '- id: permission' + NL + ' config:' + NL + ' defaultPreset:
|
|
411
|
+
+ '- id: permission' + NL + ' config:' + NL + ' defaultPreset: ' + ACP_PERM_PRESET + NL)
|
|
411
412
|
return { refs: Object.keys(refs), home: HOST_HOME, shared: true }
|
|
412
413
|
}
|
|
413
414
|
|
|
@@ -415,7 +416,7 @@ function prepareChildHome() {
|
|
|
415
416
|
writeFileSync(target, ['version: 1', 'refs:'].concat(Object.keys(refs).map((k) => ' ' + k + ': ' + refs[k])).join(NL) + NL)
|
|
416
417
|
// 默认预设**不写死**:预设由用户自己的 DSH 决定(ACP 会话本就不加入预设;写死某个人的预设
|
|
417
418
|
// 等于把插件产品绑到某个人的环境上)。
|
|
418
|
-
writeFileSync(join(CHILD_HOME, 'settings.yaml'), 'permission:' + NL + ' defaultPreset:
|
|
419
|
+
writeFileSync(join(CHILD_HOME, 'settings.yaml'), 'permission:' + NL + ' defaultPreset: ' + ACP_PERM_PRESET + NL)
|
|
419
420
|
try { spawn('cmd.exe', ['/c', 'icacls "' + target + '" /inheritance:r /grant:r "' + process.env.USERNAME + ':R"'], { windowsHide: true, stdio: 'ignore' }).unref() } catch {}
|
|
420
421
|
return { refs: Object.keys(refs), home: CHILD_HOME, shared: false }
|
|
421
422
|
}
|
|
@@ -871,7 +872,7 @@ function ensureChatOverlay() {
|
|
|
871
872
|
const lines = text.split(NL)
|
|
872
873
|
while (lines.length && !String(lines[lines.length - 1]).trim()) lines.pop()
|
|
873
874
|
const indent = (String(lines[lines.length - 1] || '').match(/^\s*/) || [''])[0]
|
|
874
|
-
const body = lines.map((l) => (/^(\s*
|
|
875
|
+
const body = lines.map((l) => (/^(\s*defaultPreset:\s*)\S+\s*$/.test(l) ? l.replace(/^(\s*defaultPreset:\s*)\S+\s*$/, '$1' + ACP_PERM_PRESET) : l))
|
|
875
876
|
const out = body.concat(pushHintLines().map((h) => indent + h)).join(NL) + NL
|
|
876
877
|
try {
|
|
877
878
|
const f = join(STATE_DIR, 'acp-overlay-chat.gen.yml')
|