dsh-bash-guard 0.1.0 → 0.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 +36 -12
- package/client.js +172 -76
- package/cordis.patch.yml +1 -1
- package/lib/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
<p align="center">4 个范围 × 3 种权限。12 个开关,一个原生菜单。</p>
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
6
|
+
<a href="https://www.npmjs.com/package/dsh-bash-guard"><img alt="npm version" src="https://img.shields.io/npm/v/dsh-bash-guard"></a>
|
|
6
7
|
<a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-blue"></a>
|
|
7
8
|
<img alt="DSH Web plugin" src="https://img.shields.io/badge/DSH-Web_plugin-555">
|
|
8
9
|
<img alt="TypeScript" src="https://img.shields.io/badge/TypeScript-policy_classifier-3178C6?logo=typescript&logoColor=white">
|
|
@@ -18,7 +19,7 @@
|
|
|
18
19
|
|
|
19
20
|
**DSH Bash Guard 是 DeepSeek Harness 的独立 Web 插件。** 它把 Bash Agent / Bash Guard 的四位权限思路带进 DSH 原生权限菜单,让你按范围控制工具操作,而不必在“只读”和“全部放开”之间二选一。
|
|
20
21
|
|
|
21
|
-
不改宿主源码,不增加一排数字预设,也不用记斜杠命令。展开 `
|
|
22
|
+
不改宿主源码,不增加一排数字预设,也不用记斜杠命令。展开 `Bash Guard 自定义`,直接调整系统、外部、网络和工作区的读、写、执行权限。
|
|
22
23
|
|
|
23
24
|
> **它是额外的工具权限检查,不是沙箱替代品。** 即使设为 `7777`,DSH 原生沙箱和审批仍然适用。
|
|
24
25
|
|
|
@@ -32,9 +33,34 @@
|
|
|
32
33
|
|
|
33
34
|
## 快速开始
|
|
34
35
|
|
|
35
|
-
###
|
|
36
|
+
### 从 npm 安装(推荐)
|
|
36
37
|
|
|
37
|
-
需要
|
|
38
|
+
需要 DSH `0.2.0-rc.2` 或更新版本;兼容范围说明见下文。插件安装到 DSH 的 `web` profile,无需全局安装 npm 包,也无需克隆或手动构建。
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
dsh plugin --profile web add dsh-bash-guard
|
|
42
|
+
dsh --profile web
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
安装后重新启动对应的 DSH Web 实例,在权限菜单中选择 **Bash Guard 自定义**。
|
|
46
|
+
|
|
47
|
+
[npm 包页面](https://www.npmjs.com/package/dsh-bash-guard) · 当前发布版本:`0.1.0`
|
|
48
|
+
|
|
49
|
+
升级到最新发布版本:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
dsh plugin --profile web add dsh-bash-guard@latest
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
如果 npm 镜像尚未同步新版本,可以显式使用官方 registry:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
dsh plugin --profile web add dsh-bash-guard@latest --registry=https://registry.npmjs.org
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 从源码安装(开发者)
|
|
62
|
+
|
|
63
|
+
需要 Git、Node.js / npm,以及上述版本的 DSH。
|
|
38
64
|
|
|
39
65
|
```bash
|
|
40
66
|
git clone https://github.com/lloydzhou/dsh-bash-guard.git
|
|
@@ -46,14 +72,10 @@ dsh plugin --profile web add .
|
|
|
46
72
|
dsh --profile web
|
|
47
73
|
```
|
|
48
74
|
|
|
49
|
-
在输入框附近打开权限菜单,选择 **
|
|
75
|
+
在输入框附近打开权限菜单,选择 **Bash Guard 自定义**。
|
|
50
76
|
|
|
51
77
|
目录安装采用链接。更新插件后重新构建;宿主入口或插件配置变化时,重启对应的 DSH 实例。
|
|
52
78
|
|
|
53
|
-
### npm 发布状态
|
|
54
|
-
|
|
55
|
-
包名为 `dsh-bash-guard`。本仓库已准备 npm 打包配置,但本说明不表示该包已经发布;发布前请使用上面的源码安装方式。
|
|
56
|
-
|
|
57
79
|
## 在菜单中操作
|
|
58
80
|
|
|
59
81
|
| 入口 | 行为 |
|
|
@@ -61,12 +83,14 @@ dsh --profile web
|
|
|
61
83
|
| 单个权限格 | 独立切换该范围的读、写或执行位 |
|
|
62
84
|
| 系统 / 外部 / 网络 / 工作区 | 已全选则清空该行,否则全选该行 |
|
|
63
85
|
| 全选 | 当前不是 `7777` 时显示,点击将全部 Guard 位设为 `7777` |
|
|
64
|
-
| 默认 | 当前是 `7777` 时显示,点击恢复 `
|
|
86
|
+
| 默认 | 当前是 `7777` 时显示,点击恢复 `4667` |
|
|
65
87
|
| 原生权限预设 | 停用 Guard,保留记忆的四位值 |
|
|
66
88
|
|
|
67
89
|
方向键在矩阵中移动焦点,不修改权限;空格切换当前按钮,Escape 关闭菜单。状态由服务端确认,保存时不插入提示行或改变菜单高度。
|
|
68
90
|
|
|
69
|
-
|
|
91
|
+
**统一默认值为 `4667`:** 系统只读、外部读写、网络读写、工作区全部。新会话初始记忆值和菜单“默认”按钮的恢复值一致,Guard 初始不激活;已有会话不会因升级自动重置。
|
|
92
|
+
|
|
93
|
+
界面支持中文和英文,跟随 DSH 的语言设置,无需单独配置。品牌名统一显示为 **Bash Guard**。
|
|
70
94
|
|
|
71
95
|
## 权限怎么读
|
|
72
96
|
|
|
@@ -108,7 +132,7 @@ dsh --profile web
|
|
|
108
132
|
| 模式 | 表达的策略 |
|
|
109
133
|
| :---: | :--- |
|
|
110
134
|
| `0467` | 系统关闭;外部只读;网络读写;工作区全部 |
|
|
111
|
-
| `
|
|
135
|
+
| `4667` | 默认:系统只读;外部与网络读写;工作区全部 |
|
|
112
136
|
| `4447` | 系统、外部、网络只读;工作区全部 |
|
|
113
137
|
| `0007` | 仅开放工作区的三个权限位 |
|
|
114
138
|
| `7777` | Guard 全部位开放,**不等于原生完全权限** |
|
|
@@ -175,7 +199,7 @@ npm pack --dry-run
|
|
|
175
199
|
- [矩阵编辑器](src/GuardEditor.js):单格、整行及全局开关。
|
|
176
200
|
- [测试](tests/):分类器、RPC、原生菜单和矩阵交互。
|
|
177
201
|
|
|
178
|
-
当前回归测试共
|
|
202
|
+
当前回归测试共 177 项,包括全部 4096 种模式的客户端校验。测试覆盖不代表对任意 Shell 程序的安全证明。npm 打包前会自动构建;构建产物与依赖目录不提交到 Git。
|
|
179
203
|
|
|
180
204
|
## 来源与致谢
|
|
181
205
|
|
package/client.js
CHANGED
|
@@ -7,77 +7,71 @@ exports.commandResult = commandResult;
|
|
|
7
7
|
exports.decodeGuardState = decodeGuardState;
|
|
8
8
|
exports.createGuardTransport = createGuardTransport;
|
|
9
9
|
exports.createPermissionControl = createPermissionControl;
|
|
10
|
+
exports.createGuardRemoteContribution = createGuardRemoteContribution;
|
|
10
11
|
exports.apply = apply;
|
|
11
12
|
const GuardEditor_js_1 = require("./GuardEditor.js");
|
|
13
|
+
const locales_js_1 = require("./locales.js");
|
|
12
14
|
// A missing guard service must never hide the host's native permission choices.
|
|
13
|
-
exports.inject = ['sessions', 'slots', 'remote', 'remote.permissionPresets'];
|
|
14
|
-
function commandResult(reply) {
|
|
15
|
+
exports.inject = ['sessions', 'slots', 'locale', 'remote', 'remote.permissionPresets'];
|
|
16
|
+
function commandResult(reply, t = locales_js_1.defaultT) {
|
|
15
17
|
if (!reply?.ok)
|
|
16
|
-
throw new Error(reply?.error?.message
|
|
18
|
+
throw (reply?.error?.message ? new Error(reply?.error?.message) : (0, locales_js_1.localeError)(t, 'error.permissionRequest'));
|
|
17
19
|
if (!reply.value?.matched)
|
|
18
|
-
throw
|
|
20
|
+
throw (0, locales_js_1.localeError)(t, 'error.permissionCommand');
|
|
19
21
|
const result = reply.value.result;
|
|
20
22
|
if (result?.kind === 'error')
|
|
21
|
-
throw new Error(result.text
|
|
23
|
+
throw (result.text ? new Error(result.text) : (0, locales_js_1.localeError)(t, 'error.permissionRequest'));
|
|
22
24
|
return result;
|
|
23
25
|
}
|
|
24
|
-
function decodeGuardState(reply) {
|
|
26
|
+
function decodeGuardState(reply, t = locales_js_1.defaultT) {
|
|
25
27
|
if (!reply?.ok)
|
|
26
|
-
throw new Error(reply?.error?.message
|
|
28
|
+
throw (reply?.error?.message ? new Error(reply?.error?.message) : (0, locales_js_1.localeError)(t, 'error.unavailable'));
|
|
27
29
|
const state = reply.value;
|
|
28
30
|
if (!/^[0-7]{4}$(?![\s\S])/.test(state?.mode) || typeof state.active !== 'boolean' || !Number.isSafeInteger(state.revision) || state.revision < 0) {
|
|
29
|
-
throw
|
|
31
|
+
throw (0, locales_js_1.localeError)(t, 'error.invalidState');
|
|
30
32
|
}
|
|
31
33
|
return { mode: state.mode, active: state.active, revision: state.revision };
|
|
32
34
|
}
|
|
33
|
-
function createGuardTransport(remote, sessionId, sessionFor) {
|
|
35
|
+
function createGuardTransport(remote, sessionId, sessionFor, t = locales_js_1.defaultT) {
|
|
34
36
|
const guard = () => {
|
|
35
37
|
if (!remote.bashGuard)
|
|
36
|
-
throw
|
|
38
|
+
throw (0, locales_js_1.localeError)(t, 'error.unavailable');
|
|
37
39
|
return remote.bashGuard;
|
|
38
40
|
};
|
|
39
41
|
return {
|
|
40
|
-
get: async () => decodeGuardState(await guard().get(sessionId)),
|
|
42
|
+
get: async () => decodeGuardState(await guard().get(sessionId), t),
|
|
41
43
|
write: async (action, state, mode) => decodeGuardState(await guard().update(sessionId, {
|
|
42
44
|
action, revision: state.revision, ...(mode === undefined ? {} : { mode }),
|
|
43
|
-
})),
|
|
45
|
+
}), t),
|
|
44
46
|
// Deliberately independent of guard reads, readiness, and failures.
|
|
45
47
|
preset: async (id) => {
|
|
46
48
|
const live = sessionFor();
|
|
47
49
|
if (!live)
|
|
48
|
-
throw
|
|
49
|
-
return commandResult(await live.command(`/permission ${id}`));
|
|
50
|
+
throw (0, locales_js_1.localeError)(t, 'error.sessionNotReady');
|
|
51
|
+
return commandResult(await live.command(`/permission ${id}`), t);
|
|
50
52
|
},
|
|
51
53
|
catalog: async () => {
|
|
52
54
|
const reply = await remote.permissionPresets.catalog();
|
|
53
55
|
if (!reply?.ok)
|
|
54
|
-
throw new Error(reply?.error?.message
|
|
56
|
+
throw (reply?.error?.message ? new Error(reply?.error?.message) : (0, locales_js_1.localeError)(t, 'error.catalogUnavailable'));
|
|
55
57
|
if (!Array.isArray(reply.value?.options))
|
|
56
|
-
throw
|
|
58
|
+
throw (0, locales_js_1.localeError)(t, 'error.invalidCatalog');
|
|
57
59
|
return reply.value;
|
|
58
60
|
},
|
|
59
61
|
subscribeCatalog: callback => remote.$on?.('permission-presets/catalog-changed', callback),
|
|
60
62
|
};
|
|
61
63
|
}
|
|
62
|
-
const copy = {
|
|
63
|
-
'preset.readOnly': '仅可查看', 'preset.workspaceWrite': '工作区内修改', 'preset.fullAccess': '完全权限',
|
|
64
|
-
'close': '关闭', 'confirm.cancel': '取消',
|
|
65
|
-
'confirm.title': '确认启用完全权限?',
|
|
66
|
-
'confirm.description': '启用完全权限后,智能体将减少确认步骤,并且可以直接执行更多操作,包括敏感操作、文件修改或外部命令。仅建议在你信任当前任务时使用。',
|
|
67
|
-
'confirm.acknowledge': '我已了解风险,并愿意继续', 'confirm.enable': '启用完全权限',
|
|
68
|
-
'auto.label': 'Auto review', 'auto.badge': 'EXP',
|
|
69
|
-
'auto.description': '无沙箱运行;每次原生工具调用和 PTC 内层调用前由同一模型进行实验性审查。',
|
|
70
|
-
'auto.confirm.title': '确认启用 Auto review(实验)?',
|
|
71
|
-
'auto.confirm.description': 'Auto review 不使用沙箱。每次原生工具调用和 PTC 内层调用前,都会由与当前 agent 相同的模型进行审查;审查拒绝的调用由你批准或拒绝。此功能仍属实验性,可能误放行或误拒绝,并会消耗额外 token。',
|
|
72
|
-
'auto.confirm.acknowledge': '我已了解这些风险,并愿意继续', 'auto.confirm.enable': '启用 Auto review',
|
|
73
|
-
};
|
|
74
64
|
const labels = { 'read-only': ['preset.readOnly', 'Read Only'], 'workspace-write': ['preset.workspaceWrite', 'Workspace Write'], 'danger-full-access': ['preset.fullAccess', 'Full access'] };
|
|
75
65
|
function createPermissionControl(React, primitives) {
|
|
76
66
|
const h = React.createElement;
|
|
77
|
-
const { Menu, RiskConfirmation, PermissionIconReadOnlyRegular, PermissionIconWorkspaceWriteRegular, PermissionIconFullAccessRegular, IconChevronDownOutlineRegular,
|
|
78
|
-
|
|
67
|
+
const { Menu, RiskConfirmation, PermissionIconReadOnlyRegular, PermissionIconWorkspaceWriteRegular, PermissionIconFullAccessRegular, IconChevronDownOutlineRegular, IconShieldOutlineRegular } = primitives;
|
|
68
|
+
// Keep the host shield artwork; only the inner adjustment marks are plugin-owned.
|
|
69
|
+
function GuardPermissionIcon() {
|
|
70
|
+
return h('span', { className: 'dsh-bg-guard-icon', 'aria-hidden': true }, h(IconShieldOutlineRegular), h('svg', { className: 'dsh-bg-guard-marks', viewBox: '0 0 16 16', fill: 'none', stroke: 'currentColor', strokeWidth: 1 }, h('path', { d: 'M5 6.5h6M5 9.5h6M7 5.5v2M9.5 8.5v2', strokeLinecap: 'round' })));
|
|
71
|
+
}
|
|
72
|
+
const icons = { 'read-only': PermissionIconReadOnlyRegular, 'workspace-write': PermissionIconWorkspaceWriteRegular, 'danger-full-access': PermissionIconFullAccessRegular, 'bash-guard': GuardPermissionIcon };
|
|
79
73
|
const GuardEditor = (0, GuardEditor_js_1.createGuardEditor)(React, primitives.IconCheckOutlineRegular);
|
|
80
|
-
return function PermissionControl({ sessionId, transport, locked, useProjection, t =
|
|
74
|
+
return function PermissionControl({ sessionId, transport, locked, useProjection, t = locales_js_1.defaultT }) {
|
|
81
75
|
const selection = useProjection('permissions');
|
|
82
76
|
const [state, setState] = React.useState(null);
|
|
83
77
|
const [catalog, setCatalog] = React.useState(null);
|
|
@@ -93,7 +87,7 @@ function createPermissionControl(React, primitives) {
|
|
|
93
87
|
const stateRef = React.useRef(null), api = React.useRef(transport);
|
|
94
88
|
api.current = transport;
|
|
95
89
|
const publish = next => { stateRef.current = next; setState(next); };
|
|
96
|
-
const message = cause => cause instanceof Error ? cause.message : String(cause);
|
|
90
|
+
const message = cause => cause?.localeKey ? t(cause.localeKey) : cause instanceof Error ? cause.message : String(cause);
|
|
97
91
|
const read = async () => {
|
|
98
92
|
if (writing.current)
|
|
99
93
|
return;
|
|
@@ -109,7 +103,7 @@ function createPermissionControl(React, primitives) {
|
|
|
109
103
|
catch (cause) {
|
|
110
104
|
if (generation === epoch.current && ticket === request.current) {
|
|
111
105
|
publish(null);
|
|
112
|
-
setError(
|
|
106
|
+
setError(cause);
|
|
113
107
|
}
|
|
114
108
|
}
|
|
115
109
|
finally {
|
|
@@ -128,7 +122,7 @@ function createPermissionControl(React, primitives) {
|
|
|
128
122
|
}
|
|
129
123
|
catch (cause) {
|
|
130
124
|
if (generation === epoch.current && ticket === catalogRequest.current)
|
|
131
|
-
setNativeError(
|
|
125
|
+
setNativeError(cause);
|
|
132
126
|
}
|
|
133
127
|
};
|
|
134
128
|
React.useEffect(() => {
|
|
@@ -170,7 +164,7 @@ function createPermissionControl(React, primitives) {
|
|
|
170
164
|
}
|
|
171
165
|
catch (cause) {
|
|
172
166
|
if (generation === epoch.current) {
|
|
173
|
-
setError(
|
|
167
|
+
setError(cause);
|
|
174
168
|
try {
|
|
175
169
|
const next = await api.current.get();
|
|
176
170
|
if (generation === epoch.current)
|
|
@@ -211,7 +205,7 @@ function createPermissionControl(React, primitives) {
|
|
|
211
205
|
}
|
|
212
206
|
catch (cause) {
|
|
213
207
|
if (generation === epoch.current)
|
|
214
|
-
setNativeError(
|
|
208
|
+
setNativeError(cause);
|
|
215
209
|
}
|
|
216
210
|
finally {
|
|
217
211
|
if (generation === epoch.current) {
|
|
@@ -251,7 +245,7 @@ function createPermissionControl(React, primitives) {
|
|
|
251
245
|
const icon = id => icons[id] ? h(icons[id]) : undefined;
|
|
252
246
|
const current = state?.active ? 'bash-guard' : selection?.currentValue;
|
|
253
247
|
const option = catalog?.options.find(item => item.value === current);
|
|
254
|
-
const label = current === 'bash-guard' ? `
|
|
248
|
+
const label = current === 'bash-guard' ? `Bash Guard ${state.mode}` : (current ? labelFor(current, option?.name) : t('permission'));
|
|
255
249
|
const items = (catalog?.options || []).map(option => ({
|
|
256
250
|
id: option.value, icon: icon(option.value),
|
|
257
251
|
label: option.value === 'auto' ? h('span', { className: 'dsh-bg-option-label', 'aria-label': `${t('auto.label')} ${t('auto.badge')}` }, t('auto.label'), h('sup', { className: 'dsh-bg-badge' }, t('auto.badge'))) : labelFor(option.value, option.name),
|
|
@@ -259,19 +253,19 @@ function createPermissionControl(React, primitives) {
|
|
|
259
253
|
}));
|
|
260
254
|
items.push({ id: 'guard-separator', type: 'separator' }, {
|
|
261
255
|
id: 'bash-guard', icon: icon('bash-guard'), disabled: !!locked || !state,
|
|
262
|
-
label: h('span', null, '
|
|
256
|
+
label: h('span', null, t('guard.custom'), state && h('span', { className: 'dsh-bg-mode' }, ` ${state.mode}`)),
|
|
263
257
|
});
|
|
264
258
|
const closeConfirmation = () => { setConfirmation(null); setAcknowledged(false); };
|
|
265
259
|
const riskPrefix = confirmation === 'auto' ? 'auto.confirm.' : 'confirm.';
|
|
266
260
|
return h(React.Fragment, null, h(Menu, { open, items, selectedId: current, onSelect: choose, onClose: () => setOpen(false), side: 'top', portal: true,
|
|
267
261
|
anchor: h('button', { type: 'button', className: 'dsh-bg-trigger', disabled: !!locked || picking || confirmation !== null,
|
|
268
|
-
'aria-label':
|
|
262
|
+
'aria-label': t('mode', { name: label }), 'aria-haspopup': 'menu', 'aria-expanded': open,
|
|
269
263
|
title: current === 'auto' ? t('auto.description') : option?.description, onClick: () => setOpen(!open),
|
|
270
264
|
}, icon(current) && h('span', { className: 'dsh-bg-trigger-icon', 'aria-hidden': true }, icon(current)), h('span', { className: 'dsh-bg-trigger-label' }, label), current === 'auto' && h('sup', { className: 'dsh-bg-badge' }, t('auto.badge')), h('span', { className: `dsh-bg-chevron${open ? ' dsh-bg-chevron-open' : ''}`, 'aria-hidden': true }, h(IconChevronDownOutlineRegular))),
|
|
271
|
-
}, state && h(GuardEditor, { mode: state.mode, active: state.active, pending, locked,
|
|
265
|
+
}, state && h(GuardEditor, { mode: state.mode, active: state.active, pending, locked, t,
|
|
272
266
|
onModeChange: mode => submit('mode', mode),
|
|
273
267
|
onChange: (row, digit) => submit('mode', stateRef.current.mode.slice(0, row) + digit + stateRef.current.mode.slice(row + 1)),
|
|
274
|
-
}), h('span', { className: 'dsh-bg-sr-only', role: 'status' }, pending ? '
|
|
268
|
+
}), h('span', { className: 'dsh-bg-sr-only', role: 'status' }, pending ? t('syncing') : ''), error && h('div', { className: 'dsh-bg-error', role: 'alert' }, message(error), h('button', { type: 'button', disabled: pending, onClick: read }, t('retry'))), nativeError && h('div', { className: 'dsh-bg-error', role: 'alert' }, message(nativeError), h('button', { type: 'button', onClick: readCatalog }, t('retry')))), confirmation !== null && h(RiskConfirmation, { open: true, title: t(`${riskPrefix}title`), description: t(`${riskPrefix}description`),
|
|
275
269
|
acknowledgeLabel: t(`${riskPrefix}acknowledge`), cancelLabel: t('confirm.cancel'), closeLabel: t('close'), confirmLabel: t(`${riskPrefix}enable`),
|
|
276
270
|
acknowledged, disabled: !!locked || picking, onAcknowledgedChange: setAcknowledged, onCancel: closeConfirmation,
|
|
277
271
|
onConfirm: () => { if (!acknowledged || locked || picking)
|
|
@@ -281,27 +275,32 @@ function createPermissionControl(React, primitives) {
|
|
|
281
275
|
}
|
|
282
276
|
// Client-owned Typert contribution: mount the namespace before rendering the seat.
|
|
283
277
|
// Structural schemas keep this artifact on host modules (no bundled Zod/React).
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}
|
|
278
|
+
function createGuardRemoteContribution(t = key => key === 'error.sessionId' || key === 'error.invalidUpdate' ? locales_js_1.en[key] : (0, locales_js_1.defaultT)(key)) {
|
|
279
|
+
return {
|
|
280
|
+
package: 'dsh-bash-guard',
|
|
281
|
+
descriptors: ['get', 'update'].map(method => ({
|
|
282
|
+
id: `dsh-bash-guard#bashGuard/${method}`, service: 'bashGuard', namespace: 'bashGuard', method,
|
|
283
|
+
invocation: { kind: 'direct' },
|
|
284
|
+
parameters: [
|
|
285
|
+
{ name: 'sessionId', wire: 'sessionId', source: 'json', codec: { mode: 'strict', typeSymbol: 'dsh-bash-guard#SessionId', create: () => ({ parse(value) {
|
|
286
|
+
if (typeof value !== 'string' || !value.trim())
|
|
287
|
+
throw (0, locales_js_1.localeError)(t, 'error.sessionId');
|
|
288
|
+
return value;
|
|
289
|
+
} }) } },
|
|
290
|
+
...(method === 'update' ? [{ name: 'request', wire: 'request', source: 'json', codec: { mode: 'strict', typeSymbol: 'dsh-bash-guard#GuardUpdate', create: () => ({ parse(value) {
|
|
291
|
+
if (!value || !['activate', 'mode', 'deactivate'].includes(value.action) || !Number.isSafeInteger(value.revision) || value.revision < 0 || (value.mode !== undefined && !/^[0-7]{4}$(?![\s\S])/.test(value.mode)) || (value.action === 'mode' && value.mode === undefined))
|
|
292
|
+
throw (0, locales_js_1.localeError)(t, 'error.invalidUpdate');
|
|
293
|
+
return { action: value.action, revision: value.revision, ...(value.mode === undefined ? {} : { mode: value.mode }) };
|
|
294
|
+
} }) } }] : []),
|
|
295
|
+
],
|
|
296
|
+
result: { mode: 'strict', typeSymbol: 'dsh-bash-guard#GuardRecord', create: () => ({ parse: value => decodeGuardState({ ok: true, value }, t) }) },
|
|
297
|
+
})),
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
exports.guardRemoteContribution = createGuardRemoteContribution();
|
|
304
301
|
async function apply(ctx) {
|
|
302
|
+
ctx.effect(() => ctx.locale.register(locales_js_1.BASH_GUARD_NS, { zh: locales_js_1.zh, en: locales_js_1.en }), 'bash-guard: dictionaries');
|
|
303
|
+
const t = ctx.locale.bind(locales_js_1.BASH_GUARD_NS);
|
|
305
304
|
// Resolve host modules inside apply: the browser loader owns React and styles.
|
|
306
305
|
const React = require('react');
|
|
307
306
|
const primitives = require('@deepseek-ai/dsh-client-ui-primitives');
|
|
@@ -315,17 +314,17 @@ async function apply(ctx) {
|
|
|
315
314
|
$on: (event, listener) => scope.remote.$on(event, listener),
|
|
316
315
|
};
|
|
317
316
|
scope.slots.inject('conversation.input.permission', () => scope.slots.register({
|
|
318
|
-
name: 'conversation.input.permission', priority: -100, locale:
|
|
319
|
-
inject: sessionId => ({ sessionId, transport: createGuardTransport(remote, sessionId, () => scope.sessions.binding(sessionId)?.session) }),
|
|
317
|
+
name: 'conversation.input.permission', priority: -100, locale: locales_js_1.BASH_GUARD_NS,
|
|
318
|
+
inject: sessionId => ({ sessionId, transport: createGuardTransport(remote, sessionId, () => scope.sessions.binding(sessionId)?.session, t) }),
|
|
320
319
|
}, Control));
|
|
321
320
|
};
|
|
322
321
|
// Leave the host seat intact while the injected guard namespace resolves.
|
|
323
322
|
// On mount failure, native choices still work through the guard-free adapter.
|
|
324
323
|
try {
|
|
325
|
-
await ctx.remote.$mount(
|
|
324
|
+
await ctx.remote.$mount(createGuardRemoteContribution(t));
|
|
326
325
|
}
|
|
327
326
|
catch (error) {
|
|
328
|
-
console.warn('
|
|
327
|
+
console.warn(t('error.rpcUnavailable'), error);
|
|
329
328
|
register(ctx, undefined);
|
|
330
329
|
return;
|
|
331
330
|
}
|
|
@@ -337,12 +336,13 @@ async function apply(ctx) {
|
|
|
337
336
|
"use strict";
|
|
338
337
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
339
338
|
exports.createGuardEditor = createGuardEditor;
|
|
339
|
+
const locales_js_1 = require("./locales.js");
|
|
340
340
|
// Independent permission bits; the host owns React and the check glyph.
|
|
341
|
-
const scopes = ['
|
|
342
|
-
const permissions = [{
|
|
341
|
+
const scopes = ['system', 'external', 'network', 'workspace'];
|
|
342
|
+
const permissions = [{ key: 'read', bit: 4 }, { key: 'write', bit: 2 }, { key: 'execute', bit: 1 }];
|
|
343
343
|
function createGuardEditor(React, CheckIcon) {
|
|
344
344
|
const h = React.createElement;
|
|
345
|
-
return function GuardEditor({ mode, active, pending = false, locked = false, error, onChange, onModeChange }) {
|
|
345
|
+
return function GuardEditor({ mode, active, pending = false, locked = false, error, onChange, onModeChange, t = locales_js_1.defaultT }) {
|
|
346
346
|
if (!active)
|
|
347
347
|
return null;
|
|
348
348
|
const disabled = pending || locked;
|
|
@@ -355,24 +355,24 @@ function createGuardEditor(React, CheckIcon) {
|
|
|
355
355
|
const root = event.currentTarget.closest('[data-guard-editor]');
|
|
356
356
|
root?.querySelector(`[data-cell="${Math.max(0, Math.min(3, row + delta[0]))}-${Math.max(0, Math.min(2, col + delta[1]))}"]`)?.focus();
|
|
357
357
|
};
|
|
358
|
-
return h('div', { className: 'dsh-bg-editor'
|
|
358
|
+
return h('div', { className: `dsh-bg-editor${t('scope.workspace') === 'Workspace' ? ' dsh-bg-editor-en' : ''}`, 'data-guard-editor': '', 'aria-busy': pending }, h('div', { className: 'dsh-bg-scope dsh-bg-head' }, h('button', {
|
|
359
359
|
type: 'button', className: 'dsh-bg-scope-label dsh-bg-all-toggle dsh-bg-scope-toggle',
|
|
360
360
|
disabled: locked, 'aria-disabled': disabled,
|
|
361
|
-
title: mode === '7777' ? '
|
|
361
|
+
title: t(mode === '7777' ? 'restoreDefaults' : 'enableAll'),
|
|
362
362
|
onClick: event => { event.stopPropagation(); if (!disabled)
|
|
363
|
-
onModeChange(mode === '7777' ? '
|
|
364
|
-
}, mode === '7777' ? '
|
|
363
|
+
onModeChange(mode === '7777' ? '4667' : '7777'); },
|
|
364
|
+
}, t(mode === '7777' ? 'defaults' : 'selectAll')), ...permissions.map(p => h('span', { className: 'dsh-bg-column', key: p.bit }, t(`bit.${p.key}`)))), ...scopes.map(key => t(`scope.${key}`)).map((scope, row) => h('div', { className: 'dsh-bg-scope', key: row, role: 'group', 'aria-label': t('scope.permissions', { scope }) }, h('button', {
|
|
365
365
|
type: 'button', className: 'dsh-bg-scope-label dsh-bg-scope-toggle',
|
|
366
366
|
disabled: locked, 'aria-disabled': disabled,
|
|
367
|
-
'aria-label':
|
|
368
|
-
title: mode[row] === '7' ? '
|
|
367
|
+
'aria-label': t('scope.toggle', { scope, action: t(mode[row] === '7' ? 'clearAll' : 'selectAll') }),
|
|
368
|
+
title: t(mode[row] === '7' ? 'scope.clearAll' : 'scope.enableAll'),
|
|
369
369
|
onClick: event => { event.stopPropagation(); if (!disabled)
|
|
370
370
|
onChange(row, mode[row] === '7' ? 0 : 7); },
|
|
371
371
|
}, scope), ...permissions.map((permission, col) => {
|
|
372
372
|
const checked = (Number(mode[row]) & permission.bit) !== 0;
|
|
373
373
|
return h('button', {
|
|
374
374
|
type: 'button', key: permission.bit, role: 'checkbox', 'aria-checked': checked,
|
|
375
|
-
'aria-label':
|
|
375
|
+
'aria-label': t('bit.label', { scope, permission: t(`bit.${permission.key}`) }), title: t('bit.status', { scope, permission: t(`bit.${permission.key}`), status: t(checked ? 'enabled' : 'disabled') }),
|
|
376
376
|
'data-cell': `${row}-${col}`, disabled: locked, 'aria-disabled': disabled, className: 'dsh-bg-level',
|
|
377
377
|
onClick: event => { event.stopPropagation(); if (!disabled)
|
|
378
378
|
onChange(row, Number(mode[row]) ^ permission.bit); },
|
|
@@ -382,5 +382,101 @@ function createGuardEditor(React, CheckIcon) {
|
|
|
382
382
|
};
|
|
383
383
|
}
|
|
384
384
|
|
|
385
|
+
},
|
|
386
|
+
"./locales.js": (module,exports,require) => {
|
|
387
|
+
"use strict";
|
|
388
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
389
|
+
exports.en = exports.zh = exports.BASH_GUARD_NS = void 0;
|
|
390
|
+
exports.defaultT = defaultT;
|
|
391
|
+
exports.localeError = localeError;
|
|
392
|
+
// Plugin-owned dictionaries: the host locale service is the only language setting.
|
|
393
|
+
exports.BASH_GUARD_NS = 'bash-guard';
|
|
394
|
+
exports.zh = {
|
|
395
|
+
'permission': '权限',
|
|
396
|
+
'mode': '访问模式,当前:{name}',
|
|
397
|
+
'guard.custom': 'Bash Guard 自定义',
|
|
398
|
+
'syncing': '正在同步权限',
|
|
399
|
+
'retry': '重试',
|
|
400
|
+
'scope.system': '系统', 'scope.external': '外部', 'scope.network': '网络', 'scope.workspace': '工作区',
|
|
401
|
+
'bit.read': '读', 'bit.write': '写', 'bit.execute': '执行',
|
|
402
|
+
'scope.permissions': '{scope}权限',
|
|
403
|
+
'scope.toggle': '{scope}:{action}',
|
|
404
|
+
'scope.enableAll': '开启该范围全部权限',
|
|
405
|
+
'scope.clearAll': '取消该范围全部权限',
|
|
406
|
+
'bit.label': '{scope} · {permission}权限',
|
|
407
|
+
'bit.status': '{scope} · {permission}权限:{status}',
|
|
408
|
+
'enabled': '开启', 'disabled': '关闭',
|
|
409
|
+
'selectAll': '全选', 'clearAll': '取消全选', 'defaults': '默认',
|
|
410
|
+
'restoreDefaults': '恢复默认权限 4667',
|
|
411
|
+
'enableAll': '开启全部 Guard 权限',
|
|
412
|
+
'error.permissionRequest': '权限请求失败',
|
|
413
|
+
'error.permissionCommand': '宿主未提供此权限命令',
|
|
414
|
+
'error.unavailable': 'Bash Guard 不可用',
|
|
415
|
+
'error.invalidState': 'Bash Guard 返回了无效状态',
|
|
416
|
+
'error.sessionNotReady': '会话尚未就绪,请稍后重试',
|
|
417
|
+
'error.catalogUnavailable': '权限列表不可用',
|
|
418
|
+
'error.invalidCatalog': '权限列表无效',
|
|
419
|
+
'error.sessionId': '必须提供会话 ID',
|
|
420
|
+
'error.invalidUpdate': '无效的 Bash Guard 更新',
|
|
421
|
+
'error.rpcUnavailable': 'Bash Guard RPC 不可用',
|
|
422
|
+
'preset.readOnly': '仅可查看', 'preset.workspaceWrite': '工作区内修改', 'preset.fullAccess': '完全权限',
|
|
423
|
+
'close': '关闭', 'confirm.cancel': '取消',
|
|
424
|
+
'confirm.title': '确认启用完全权限?',
|
|
425
|
+
'confirm.description': '启用完全权限后,智能体将减少确认步骤,并且可以直接执行更多操作,包括敏感操作、文件修改或外部命令。仅建议在你信任当前任务时使用。',
|
|
426
|
+
'confirm.acknowledge': '我已了解风险,并愿意继续', 'confirm.enable': '启用完全权限',
|
|
427
|
+
'auto.label': 'Auto review', 'auto.badge': 'EXP',
|
|
428
|
+
'auto.description': '无沙箱运行;每次原生工具调用和 PTC 内层调用前由同一模型进行实验性审查。',
|
|
429
|
+
'auto.confirm.title': '确认启用 Auto review(实验)?',
|
|
430
|
+
'auto.confirm.description': 'Auto review 不使用沙箱。每次原生工具调用和 PTC 内层调用前,都会由与当前 agent 相同的模型进行审查;审查拒绝的调用由你批准或拒绝。此功能仍属实验性,可能误放行或误拒绝,并会消耗额外 token。',
|
|
431
|
+
'auto.confirm.acknowledge': '我已了解这些风险,并愿意继续', 'auto.confirm.enable': '启用 Auto review',
|
|
432
|
+
};
|
|
433
|
+
exports.en = {
|
|
434
|
+
'permission': 'Permission',
|
|
435
|
+
'mode': 'Access mode, current: {name}',
|
|
436
|
+
'guard.custom': 'Bash Guard Custom',
|
|
437
|
+
'syncing': 'Syncing permissions',
|
|
438
|
+
'retry': 'Retry',
|
|
439
|
+
'scope.system': 'System', 'scope.external': 'External', 'scope.network': 'Network', 'scope.workspace': 'Workspace',
|
|
440
|
+
'bit.read': 'Read', 'bit.write': 'Write', 'bit.execute': 'Execute',
|
|
441
|
+
'scope.permissions': '{scope} permissions',
|
|
442
|
+
'scope.toggle': '{scope}: {action}',
|
|
443
|
+
'scope.enableAll': 'Enable all permissions in this scope',
|
|
444
|
+
'scope.clearAll': 'Clear all permissions in this scope',
|
|
445
|
+
'bit.label': '{scope} · {permission} permission',
|
|
446
|
+
'bit.status': '{scope} · {permission} permission: {status}',
|
|
447
|
+
'enabled': 'On', 'disabled': 'Off',
|
|
448
|
+
'selectAll': 'Select all', 'clearAll': 'Clear all', 'defaults': 'Default',
|
|
449
|
+
'restoreDefaults': 'Restore default permissions 4667',
|
|
450
|
+
'enableAll': 'Enable all Guard permissions',
|
|
451
|
+
'error.permissionRequest': 'Permission request failed',
|
|
452
|
+
'error.permissionCommand': 'The host does not provide this permission command',
|
|
453
|
+
'error.unavailable': 'Bash Guard is unavailable',
|
|
454
|
+
'error.invalidState': 'Bash Guard returned an invalid state',
|
|
455
|
+
'error.sessionNotReady': 'The session is not ready yet. Please try again later',
|
|
456
|
+
'error.catalogUnavailable': 'Permission catalog is unavailable',
|
|
457
|
+
'error.invalidCatalog': 'Invalid permission catalog',
|
|
458
|
+
'error.sessionId': 'A session ID is required',
|
|
459
|
+
'error.invalidUpdate': 'Invalid Bash Guard update',
|
|
460
|
+
'error.rpcUnavailable': 'Bash Guard RPC unavailable',
|
|
461
|
+
'preset.readOnly': 'Read Only', 'preset.workspaceWrite': 'Workspace Write', 'preset.fullAccess': 'Full access',
|
|
462
|
+
'close': 'Close', 'confirm.cancel': 'Cancel',
|
|
463
|
+
'confirm.title': 'Enable Full access?',
|
|
464
|
+
'confirm.description': 'Full access reduces confirmation steps and lets the agent perform more actions directly, including sensitive operations, file changes, or external commands. Only use it when you trust the current task.',
|
|
465
|
+
'confirm.acknowledge': 'I understand the risks and want to continue', 'confirm.enable': 'Enable Full access',
|
|
466
|
+
'auto.label': 'Auto review', 'auto.badge': 'EXP',
|
|
467
|
+
'auto.description': 'Run without a sandbox after an experimental same-model review of every native tool call and PTC inner call.',
|
|
468
|
+
'auto.confirm.title': 'Enable Auto review (experimental)?',
|
|
469
|
+
'auto.confirm.description': 'Auto review runs without a sandbox. Before every native tool call and PTC inner call, the same model as the current agent reviews whether to allow it; you approve or reject each call it denies. This feature is experimental, can falsely allow or deny actions, and uses additional tokens.',
|
|
470
|
+
'auto.confirm.acknowledge': 'I understand these risks and want to continue', 'auto.confirm.enable': 'Enable Auto review',
|
|
471
|
+
};
|
|
472
|
+
// Keep the historical Chinese defaults for standalone helpers and editor consumers.
|
|
473
|
+
function defaultT(key, values = {}) {
|
|
474
|
+
return (exports.zh[key] ?? key).replace(/\{(\w+)\}/g, (match, name) => values[name] ?? match);
|
|
475
|
+
}
|
|
476
|
+
// Retain the key so an already-visible local error follows reactive slot language changes.
|
|
477
|
+
function localeError(t, key) {
|
|
478
|
+
return Object.assign(new Error(t(key)), { localeKey: key });
|
|
479
|
+
}
|
|
480
|
+
|
|
385
481
|
}};const cache={};function require(id){if(!factories[id])return hostRequire(id);if(cache[id])return cache[id].exports;const module={exports:{}};cache[id]=module;factories[id](module,module.exports,require);return module.exports;}
|
|
386
|
-
const api=require('./client.js');const original=api.apply;api.apply=(ctx)=>{ctx.effect(()=>{const style=document.createElement('style');style.dataset.plugin='dsh-bash-guard';style.textContent="/* Native permission trigger declarations, namespaced; Menu owns all menu chrome. */\n.dsh-bg-trigger { border-radius: var(--dsw-radius-sm); min-width: 0; max-width: 220px; height: 28px; color: var(--dsw-alias-label-secondary); cursor: pointer; background: transparent; border: none; outline: none; align-items: center; gap: 4px; padding: 0 4px 0 8px; font-size: 13px; font-weight: 500; line-height: 20px; display: inline-flex; }\n.dsh-bg-trigger:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }\n.dsh-bg-trigger:focus-visible { box-shadow: 0 0 0 2px var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary)); }\n.dsh-bg-trigger:disabled { color: var(--dsw-alias-label-dimmed); cursor: default; }\n.dsh-bg-trigger-icon { flex: none; display: inline-flex; }\n.dsh-bg-trigger-icon svg { width: 14px; height: 14px; }\n.dsh-bg-trigger-label { text-overflow: ellipsis; white-space: nowrap; min-width: 0; overflow: hidden; }\n.dsh-bg-option-label { align-items: baseline; gap: 4px; min-width: 0; max-width: 100%; display: inline-flex; }\n.dsh-bg-badge { color: var(--dsw-alias-label-tertiary); letter-spacing: .2px; flex: none; align-self: flex-start; margin-top: -1px; font-size: 8px; font-weight: 600; line-height: 10px; }\n.dsh-bg-chevron { color: var(--dsw-alias-label-caption); flex: none; transition: transform .12s; display: inline-flex; }\n.dsh-bg-chevron-open { transform: rotate(180deg); }\n@container (width <= 460px) { .dsh-bg-trigger:has(.dsh-bg-trigger-icon) .dsh-bg-trigger-label { display: none; } }\n.dsh-bg-editor { padding: 0 8px 4px 32px; color: var(--dsw-alias-label-primary); }\n.dsh-bg-scope { display: grid; grid-template-columns: 48px repeat(3, 32px); align-items: center; gap: 8px; min-height: 32px; }\n.dsh-bg-head { min-height: 26px; }\n.dsh-bg-column { text-align: center; font-size: 12px; color: var(--dsw-alias-label-secondary); }\n.dsh-bg-level svg { width: 16px; height: 16px; }\n.dsh-bg-scope-label { width: 42px; flex: 0 0 42px; color: var(--dsw-alias-label-secondary); font-size: 12px; }\n.dsh-bg-scope-toggle { appearance: none; border: 0; background: transparent; border-radius: var(--dsw-radius-sm); box-sizing: border-box; width: max-content; max-width: none; justify-self: start; height: 24px; margin-left: -6px; padding: 0 6px; text-align: left; white-space: nowrap; font-family: inherit; cursor: pointer; }\n.dsh-bg-scope-toggle:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); color: var(--dsw-alias-label-primary); }\n.dsh-bg-level { appearance: none; border: 1px solid var(--dsw-alias-border-l1); background: transparent; color: var(--dsw-alias-label-secondary); border-radius: var(--dsw-radius-sm); width: 32px; height: 24px; padding: 0; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }\n.dsh-bg-sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }\n.dsh-bg-level:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); color: var(--dsw-alias-label-primary); }\n.dsh-bg-level[aria-checked=\"true\"] { background: var(--dsw-alias-interactive-bg-hover-solid); color: var(--dsw-alias-label-primary); }\n.dsh-bg-editor button:focus-visible, .dsh-bg-error button:focus-visible { outline: 2px solid var(--dsw-focus-ring-color, var(--dsw-alias-label-secondary)); outline-offset: 1px; }\n.dsh-bg-editor button:disabled { cursor: default; color: var(--dsw-alias-label-tertiary); }\n.dsh-bg-error, .dsh-bg-status { color: var(--dsw-alias-label-secondary); font-size: 12px; line-height: 18px; padding: 6px 8px; overflow-wrap: anywhere; max-width: 300px; }\n.dsh-bg-error button { margin-left: 8px; padding: 2px 6px; border: 1px solid var(--dsw-alias-border-l1); border-radius: var(--dsw-radius-sm); background: transparent; color: inherit; font: inherit; cursor: pointer; }\n.dsh-bg-mode { font: 12px var(--ds-font-family-code, monospace); color: var(--dsw-alias-label-secondary); font-variant-numeric: tabular-nums; }\n@media (max-width: 360px) { .dsh-bg-editor { padding-left: 24px; } .dsh-bg-level { padding-inline: 4px; } }\n@media (prefers-reduced-motion: reduce) { .dsh-bg-chevron { transition: none; } }\n";document.head.append(style);return ()=>style.remove()});return original(ctx)};return api;}});
|
|
482
|
+
const api=require('./client.js');const original=api.apply;api.apply=(ctx)=>{ctx.effect(()=>{const style=document.createElement('style');style.dataset.plugin='dsh-bash-guard';style.textContent="/* Native permission trigger declarations, namespaced; Menu owns all menu chrome. */\n.dsh-bg-trigger { border-radius: var(--dsw-radius-sm); min-width: 0; max-width: 220px; height: 28px; color: var(--dsw-alias-label-secondary); cursor: pointer; background: transparent; border: none; outline: none; align-items: center; gap: 4px; padding: 0 4px 0 8px; font-size: 13px; font-weight: 500; line-height: 20px; display: inline-flex; }\n.dsh-bg-trigger:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }\n.dsh-bg-trigger:focus-visible { box-shadow: 0 0 0 2px var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary)); }\n.dsh-bg-trigger:disabled { color: var(--dsw-alias-label-dimmed); cursor: default; }\n.dsh-bg-trigger-icon { flex: none; display: inline-flex; }\n.dsh-bg-trigger-icon svg { width: 14px; height: 14px; }\n.dsh-bg-guard-icon { position: relative; display: inline-flex; width: 16px; height: 16px; flex: none; }\n.dsh-bg-guard-icon > svg { width: 100%; height: 100%; }\n.dsh-bg-guard-marks { position: absolute; inset: 0; pointer-events: none; }\n.dsh-bg-trigger-icon .dsh-bg-guard-icon { width: 14px; height: 14px; }\n.dsh-bg-trigger-label { text-overflow: ellipsis; white-space: nowrap; min-width: 0; overflow: hidden; }\n.dsh-bg-option-label { align-items: baseline; gap: 4px; min-width: 0; max-width: 100%; display: inline-flex; }\n.dsh-bg-badge { color: var(--dsw-alias-label-tertiary); letter-spacing: .2px; flex: none; align-self: flex-start; margin-top: -1px; font-size: 8px; font-weight: 600; line-height: 10px; }\n.dsh-bg-chevron { color: var(--dsw-alias-label-caption); flex: none; transition: transform .12s; display: inline-flex; }\n.dsh-bg-chevron-open { transform: rotate(180deg); }\n@container (width <= 460px) { .dsh-bg-trigger:has(.dsh-bg-trigger-icon) .dsh-bg-trigger-label { display: none; } }\n.dsh-bg-editor { padding: 0 8px 4px 32px; color: var(--dsw-alias-label-primary); }\n.dsh-bg-scope { display: grid; grid-template-columns: 48px repeat(3, 32px); align-items: center; gap: 8px; min-height: 32px; }\n.dsh-bg-head { min-height: 26px; }\n.dsh-bg-editor-en .dsh-bg-scope { grid-template-columns: 72px repeat(3, 44px); }\n.dsh-bg-editor-en .dsh-bg-level { justify-self: center; }\n.dsh-bg-column { text-align: center; font-size: 12px; color: var(--dsw-alias-label-secondary); }\n.dsh-bg-level svg { width: 16px; height: 16px; }\n.dsh-bg-scope-label { width: 42px; flex: 0 0 42px; color: var(--dsw-alias-label-secondary); font-size: 12px; }\n.dsh-bg-scope-toggle { appearance: none; border: 0; background: transparent; border-radius: var(--dsw-radius-sm); box-sizing: border-box; width: max-content; max-width: none; justify-self: start; height: 24px; margin-left: -6px; padding: 0 6px; text-align: left; white-space: nowrap; font-family: inherit; cursor: pointer; }\n.dsh-bg-scope-toggle:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); color: var(--dsw-alias-label-primary); }\n.dsh-bg-level { appearance: none; border: 1px solid var(--dsw-alias-border-l1); background: transparent; color: var(--dsw-alias-label-secondary); border-radius: var(--dsw-radius-sm); width: 32px; height: 24px; padding: 0; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }\n.dsh-bg-sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }\n.dsh-bg-level:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); color: var(--dsw-alias-label-primary); }\n.dsh-bg-level[aria-checked=\"true\"] { background: var(--dsw-alias-interactive-bg-hover-solid); color: var(--dsw-alias-label-primary); }\n.dsh-bg-editor button:focus-visible, .dsh-bg-error button:focus-visible { outline: 2px solid var(--dsw-focus-ring-color, var(--dsw-alias-label-secondary)); outline-offset: 1px; }\n.dsh-bg-editor button:disabled { cursor: default; color: var(--dsw-alias-label-tertiary); }\n.dsh-bg-error, .dsh-bg-status { color: var(--dsw-alias-label-secondary); font-size: 12px; line-height: 18px; padding: 6px 8px; overflow-wrap: anywhere; max-width: 300px; }\n.dsh-bg-error button { margin-left: 8px; padding: 2px 6px; border: 1px solid var(--dsw-alias-border-l1); border-radius: var(--dsw-radius-sm); background: transparent; color: inherit; font: inherit; cursor: pointer; }\n.dsh-bg-mode { font: 12px var(--ds-font-family-code, monospace); color: var(--dsw-alias-label-secondary); font-variant-numeric: tabular-nums; }\n@media (max-width: 360px) { .dsh-bg-editor { padding-left: 24px; } .dsh-bg-level { padding-inline: 4px; } }\n@media (prefers-reduced-motion: reduce) { .dsh-bg-chevron { transition: none; } }\n";document.head.append(style);return ()=>style.remove()});return original(ctx)};return api;}});
|
package/cordis.patch.yml
CHANGED
package/lib/index.js
CHANGED
|
@@ -48,7 +48,7 @@ export class BashGuardService extends TypertRemoteService {
|
|
|
48
48
|
update(sessionId, request) { return this.mutate(sessionId, request); }
|
|
49
49
|
}
|
|
50
50
|
export async function apply(ctx, config = {}) {
|
|
51
|
-
const fallback = config.mode ?? '
|
|
51
|
+
const fallback = config.mode ?? '4667';
|
|
52
52
|
if (!valid(fallback))
|
|
53
53
|
throw new Error('bash-guard: expected four octal digits');
|
|
54
54
|
const domain = await ctx.storageDomain.open({ name: 'bash_guard', version: 1, layout: 'per-record', tables: { sessions: { valueSchema: recordSchema } } });
|