dsh-browser-playwright-codex 0.7.0 → 0.7.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/CHANGELOG.md +19 -1
- package/README.md +2 -1
- package/lib/client.js +29 -7
- package/lib/gates-patch.d.ts +6 -3
- package/lib/gates-patch.js +18 -8
- package/lib/runtime-state.d.ts +2 -0
- package/lib/runtime-state.js +5 -1
- package/lib/settings-card.js +9 -2
- package/lib/tool.js +5 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,24 @@
|
|
|
3
3
|
Bilingual by intent: the version headings and the summary of each release are given in both
|
|
4
4
|
languages, the individual entries follow the language the surrounding code and docs use.
|
|
5
5
|
|
|
6
|
+
## 0.7.1 — 2026-10-19
|
|
7
|
+
|
|
8
|
+
一句话摘要:**只修文档与一处口径** —— 外部评分(8.9/10)点名的问题:CHANGELOG 的数字手写写错、对比表把五个闸门写成三个、有头模式的 viewport 仍然不生效却没标注。行为零变化。
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **设置卡新增第三个工具开关:诊断工具**(`browser_console_messages` / `browser_network_requests`)。与 `evaluate` / `cdp` 同一套机制:`POST /api/browser-playwright/gates` 现在接受 `diagnostics`,home 补丁块的整行 config 一并写入,`tool.ts` 把**实际生效值**(而不是猜的)发布给卡片;卡片上显示"当前:N 个开着"也把这一项算进去。
|
|
13
|
+
- **「已登录的站点」默认折叠**:标题行直接给出「N 个域 · M 个 cookie · 点击展开」,点开才渲染说明与名单(分组仍各自折叠)。设置页不再被这份名单占掉大半屏。
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **CHANGELOG 0.7.0 的数字按实测改正**:常驻是 **16 工具 / 11,179 字符**(此前手写成 11,005 字符,token 数也跟着漂),对比基线 18 工具 / 12,755 字符保持不变,字符降幅 **−1,576(−12.4%)**。这是连续第三个版本出现"主文档被守卫钉住、CHANGELOG 叙事手写漂移"——本轮起新增加一条守卫:**最新一节 CHANGELOG 不许出现手写的 `≈ N token/轮` 数字**,要写就写实测命令与结果表。
|
|
18
|
+
- **对比与优势.md 的闸门清单**:"五个闸门"此前只列了 `evaluate` / `cdp` / `extract` 三个名字,补上 `console_messages` / `network_requests`,并把它与全量注册的字符差从旧的 2,853 更正为实测 4,603 字符(token 换算见 README 成本表)。
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- **有头模式的 `viewport` 标注**:`browser-lifecycle.ts:44` 用 `viewport: null` 跟随真实窗口,所以 `launch.viewport` 只在 `headless: true` 时生效;README 配置示例与 Known Limitations 现在明写这一点(此前"配了也不生效"没有任何提示,被外部评分连续四次点出)。
|
|
23
|
+
|
|
6
24
|
## 0.7.0 — 2026-10-19
|
|
7
25
|
|
|
8
26
|
一句话摘要:**两个插件合成一个** —— 设置卡片并入本包;加载行从三行收成一行(这是 `dsh-client-modules` 允许本包带 client 模块的前提),独立的 `dsh-browser-toggle` 退役。
|
|
@@ -19,7 +37,7 @@ languages, the individual entries follow the language the surrounding code and d
|
|
|
19
37
|
|
|
20
38
|
### Changed
|
|
21
39
|
|
|
22
|
-
- **两个诊断工具改为门控**:`browser_console_messages` / `browser_network_requests` 不再常驻 —— 新增 `tool.diagnostics: false`(默认关),开启后才注册。常驻成本 **18 工具 12,755 字符 ≈ 3,543 token/轮 → 16 工具 11,
|
|
40
|
+
- **两个诊断工具改为门控**:`browser_console_messages` / `browser_network_requests` 不再常驻 —— 新增 `tool.diagnostics: false`(默认关),开启后才注册。常驻成本 **18 工具 12,755 字符 ≈ 3,543 token/轮 → 16 工具 11,179 字符 ≈ 3,105 token/轮(−438,−12.4%)**;全量注册仍是 21 工具 15,782 字符 ≈ 4,384。
|
|
23
41
|
- **快照瘦身(运行时大头)**:无名无状态的 `generic` 包装层不再逐层输出(真实页面常把一个链接包在 7~8 层 div 里),显示用 `href` 去掉追踪参数(`utm_*` / `gclid` / `rsv_*` / `sa` 等)并截到 160 字符。百度结果页形状的样本:**6,169 → 2,557 字符(−58.6%)**,行数 108 → 24。refs 与点击行为不变 —— 省的是模型读到的东西。
|
|
24
42
|
- 闸门写入块改为**整行 config**(新标记 `# >>> dsh-browser:`),并兼容旧的 `dsh-browser-toggle` 标记就地替换 —— 避免同一个 id 被两段 patch 争抢。
|
|
25
43
|
- `scripts/shipped-gates.mjs` 按新行名读取出厂闸门;`scripts/build-client.mjs` 把 `client/client.js` 复制进 `lib/`。
|
package/README.md
CHANGED
|
@@ -227,7 +227,7 @@ All tunables are patchable through the profile's `cordis.patch.yml` (later layer
|
|
|
227
227
|
headless: false # visible window you can watch and rescue
|
|
228
228
|
persistent: true # profile-backed window, login survives close
|
|
229
229
|
# profileDir: ~/.dsh/browser-profiles/playwright by default
|
|
230
|
-
viewport: { width: 1280, height: 800 }
|
|
230
|
+
viewport: { width: 1280, height: 800 } # headful: IGNORED (the window tracks the desktop; only headless: true pins it)
|
|
231
231
|
navigationTimeoutMs: 30000
|
|
232
232
|
ignoreHTTPSErrors: false
|
|
233
233
|
allowedDomains: [] # e.g. ['github.com'] restricts navigation
|
|
@@ -431,6 +431,7 @@ links below go to GitHub rather than to files inside the package:
|
|
|
431
431
|
registerDisabledTools: false
|
|
432
432
|
maxWaitMs: 60000
|
|
433
433
|
```
|
|
434
|
+
- **`launch.viewport` only applies headless** — the visible window is a real window: it tracks the desktop size (`browser-lifecycle.ts` passes `viewport: null` in headful), so setting 1280×800 there changes nothing. Pin the size by running `headless: true`, or resize the window itself.
|
|
434
435
|
- **Chromium family only** — Firefox/WebKit channels are not probed; providers are swappable if another engine is needed.
|
|
435
436
|
- **Extract needs a dedicated model route** — it does not reuse the main request's route; misconfiguration fails loudly at call time.
|
|
436
437
|
- **JS-driven navigations are not statically checkable** — `allowedDomains` covers `browser_navigate`, `browser_open_tab`, every navigating click (`browser_click`: `ref`, `text`, `precise` and raw-coordinate modes) and `browser_switch_tab`; `mode: "hover"` reveals content without activating anything, so it is not checked against the URL policy. A button whose handler runs `location.href = …` can still leave the allowed hosts, and so can a `<form>` whose `action` points at another host (pressing its submit button is a navigation this check does not statically see), and a tab that is already sitting on a disallowed host stays open (the agent simply refuses to drive it); deploy an external network guard for hard isolation.
|
package/lib/client.js
CHANGED
|
@@ -176,6 +176,11 @@ window.__ModuleLoader__.load({
|
|
|
176
176
|
label: '允许在页面里执行任意 JavaScript',
|
|
177
177
|
hint: '打开后 AI 能在任意网页里运行脚本:能读走页面上的任何内容,也能用你的登录状态去点、去填、去提交。真正需要时才打开。',
|
|
178
178
|
},
|
|
179
|
+
{
|
|
180
|
+
key: 'diagnostics',
|
|
181
|
+
label: '诊断工具:控制台消息与网络请求',
|
|
182
|
+
hint: '给排障用:能读出页面控制台的报错和最近的网络请求(URL、状态、失败原因)。平时用不到;遇到"点了没反应"或"背后的请求失败了"再打开。',
|
|
183
|
+
},
|
|
179
184
|
{
|
|
180
185
|
key: 'allowCdp',
|
|
181
186
|
label: '允许原始 CDP 调试协议',
|
|
@@ -224,13 +229,14 @@ window.__ModuleLoader__.load({
|
|
|
224
229
|
const [enabled, setEnabled] = useState(null);
|
|
225
230
|
const [engine, setEngine] = useState(null);
|
|
226
231
|
const [engineUserChosen, setEngineUserChosen] = useState(false);
|
|
227
|
-
const [gates, setGates] = useState({ allowEvaluate: null, allowCdp: null });
|
|
232
|
+
const [gates, setGates] = useState({ allowEvaluate: null, allowCdp: null, diagnostics: null });
|
|
228
233
|
const [busy, setBusy] = useState(false);
|
|
229
234
|
const [msg, setMsg] = useState('');
|
|
230
235
|
const [logins, setLogins] = useState(null);
|
|
231
236
|
const [showAll, setShowAll] = useState(false);
|
|
232
237
|
const [openGroups, setOpenGroups] = useState([]);
|
|
233
238
|
const [hiddenDomains, setHiddenDomains] = useState(readHiddenDomains());
|
|
239
|
+
const [loginsOpen, setLoginsOpen] = useState(false);
|
|
234
240
|
const mountedRef = useRef(true);
|
|
235
241
|
|
|
236
242
|
const refresh = async () => {
|
|
@@ -245,6 +251,7 @@ window.__ModuleLoader__.load({
|
|
|
245
251
|
setGates({
|
|
246
252
|
allowEvaluate: typeof s.allowEvaluate === 'boolean' ? s.allowEvaluate : null,
|
|
247
253
|
allowCdp: typeof s.allowCdp === 'boolean' ? s.allowCdp : null,
|
|
254
|
+
diagnostics: typeof s.diagnostics === 'boolean' ? s.diagnostics : null,
|
|
248
255
|
});
|
|
249
256
|
}
|
|
250
257
|
catch (error) {
|
|
@@ -333,16 +340,21 @@ window.__ModuleLoader__.load({
|
|
|
333
340
|
const payload = {
|
|
334
341
|
allowEvaluate: gates.allowEvaluate === true,
|
|
335
342
|
allowCdp: gates.allowCdp === true,
|
|
343
|
+
diagnostics: gates.diagnostics === true,
|
|
336
344
|
};
|
|
337
345
|
payload[key] = next;
|
|
338
346
|
try {
|
|
339
347
|
const r = await api('/gates', 'POST', payload);
|
|
340
348
|
if (r && r.error)
|
|
341
349
|
throw new Error(r.error.message || r.error.code || 'unknown');
|
|
342
|
-
setGates({
|
|
350
|
+
setGates({
|
|
351
|
+
allowEvaluate: r.allowEvaluate === true,
|
|
352
|
+
allowCdp: r.allowCdp === true,
|
|
353
|
+
diagnostics: r.diagnostics === true,
|
|
354
|
+
});
|
|
343
355
|
setMsg(r.changed
|
|
344
356
|
? (next
|
|
345
|
-
? '已打开:' + (key ===
|
|
357
|
+
? '已打开:' + ((GATE_ROWS.find((row) => row.key === key) || {}).label || key) + '。工具会在热重载后出现(约 1-2 秒);若一直没出现,重启一次 DSH。'
|
|
346
358
|
: '已关闭。工具会在热重载后消失;若还在,重启一次 DSH。')
|
|
347
359
|
: '状态未变化');
|
|
348
360
|
}
|
|
@@ -425,15 +437,25 @@ window.__ModuleLoader__.load({
|
|
|
425
437
|
gates.allowEvaluate === null && gates.allowCdp === null
|
|
426
438
|
? h('span', { key: 'unknown', style: S.tip }, '当前:读取不到(这个 profile 里的插件版本还没上报闸门状态)')
|
|
427
439
|
: h('span', { key: 'sum', style: S.tip }, '当前:' + (gatesOn === 0 ? '都关着' : gatesOn + ' 个开着'))),
|
|
428
|
-
h('div', {
|
|
429
|
-
|
|
440
|
+
h('div', {
|
|
441
|
+
key: 'loginsGroup',
|
|
442
|
+
style: { ...S.group, cursor: 'pointer', userSelect: 'none' },
|
|
443
|
+
onClick: () => setLoginsOpen((open) => !open),
|
|
444
|
+
}, '已登录的站点(只给你自己看)'
|
|
445
|
+
+ (logins === null || logins.sites === undefined
|
|
446
|
+
? ''
|
|
447
|
+
: ' · ' + logins.sites.length + ' 个域 · ' + logins.sites.reduce((acc, site) => acc + site.cookies, 0) + ' 个 cookie')
|
|
448
|
+
+ (loginsOpen ? ' ▾ 点击收起' : ' ▸ 点击展开')),
|
|
449
|
+
loginsOpen ? h(Notes, { key: 'loginsNotes', title: '说明' },
|
|
430
450
|
h('p', { style: S.note },
|
|
431
451
|
'只列**这台浏览器真的访问过**的域(你在 DSH 里打开过的页面),第三方统计/广告域已排除 ——'
|
|
432
452
|
+ '别人的 cookie 属于你当时浏览的那个站,不代表你登录了它。判据是 OWASP 的会话特征:'
|
|
433
453
|
+ 'httpOnly 且(会话级 或 值像令牌),名字不作为依据。'
|
|
434
454
|
+ '每一行的说明来自网页自己的标题,或一份离线对照表(认不出的就直接显示域名,不编)。'
|
|
435
|
-
+ '这里不显示 cookie 的名字和值;名单只存在于本机内存、不写磁盘;也没有任何工具能让 AI 看到它。')),
|
|
436
|
-
|
|
455
|
+
+ '这里不显示 cookie 的名字和值;名单只存在于本机内存、不写磁盘;也没有任何工具能让 AI 看到它。')) : null,
|
|
456
|
+
loginsOpen === false
|
|
457
|
+
? null
|
|
458
|
+
: logins === null
|
|
437
459
|
? h('div', { key: 'loginsUnknown', style: S.tip },
|
|
438
460
|
'读取不到:这个 profile 里的插件版本还没上报,或还没打开过浏览器。')
|
|
439
461
|
: (() => {
|
package/lib/gates-patch.d.ts
CHANGED
|
@@ -16,15 +16,17 @@ export declare function homePatchPath(env?: NodeJS.ProcessEnv): string;
|
|
|
16
16
|
*
|
|
17
17
|
* @param allowEvaluate - register browser_evaluate
|
|
18
18
|
* @param allowCdp - register browser_cdp
|
|
19
|
+
* @param diagnostics - register the two diagnostics tools
|
|
19
20
|
* @returns the YAML block, markers included
|
|
20
21
|
*/
|
|
21
|
-
export declare function renderBrowserBlock(allowEvaluate: boolean, allowCdp: boolean): string;
|
|
22
|
+
export declare function renderBrowserBlock(allowEvaluate: boolean, allowCdp: boolean, diagnostics: boolean): string;
|
|
22
23
|
/** Merge the managed block into `original`, replacing an existing one in place. */
|
|
23
|
-
export declare function mergeBrowserBlock(original: string, allowEvaluate: boolean, allowCdp: boolean): string;
|
|
24
|
+
export declare function mergeBrowserBlock(original: string, allowEvaluate: boolean, allowCdp: boolean, diagnostics: boolean): string;
|
|
24
25
|
/** Read the current managed block, or undefined when there is none. */
|
|
25
26
|
export declare function parseBrowserBlock(text: string): {
|
|
26
27
|
allowEvaluate: boolean;
|
|
27
28
|
allowCdp: boolean;
|
|
29
|
+
diagnostics: boolean;
|
|
28
30
|
} | undefined;
|
|
29
31
|
/** Back-compat aliases used by the absorbed settings-card host half. */
|
|
30
32
|
export declare const parseGatesBlock: typeof parseBrowserBlock;
|
|
@@ -39,8 +41,9 @@ export declare const mergeGatesBlock: typeof mergeBrowserBlock;
|
|
|
39
41
|
* @param env - environment (DSH_HOME override for tests)
|
|
40
42
|
* @returns the file written and the values it now carries
|
|
41
43
|
*/
|
|
42
|
-
export declare function writeGates(allowEvaluate: boolean, allowCdp: boolean, env?: NodeJS.ProcessEnv): Promise<{
|
|
44
|
+
export declare function writeGates(allowEvaluate: boolean, allowCdp: boolean, diagnostics: boolean, env?: NodeJS.ProcessEnv): Promise<{
|
|
43
45
|
patch: string;
|
|
44
46
|
allowEvaluate: boolean;
|
|
45
47
|
allowCdp: boolean;
|
|
48
|
+
diagnostics: boolean;
|
|
46
49
|
}>;
|
package/lib/gates-patch.js
CHANGED
|
@@ -41,9 +41,10 @@ export function homePatchPath(env = process.env) {
|
|
|
41
41
|
*
|
|
42
42
|
* @param allowEvaluate - register browser_evaluate
|
|
43
43
|
* @param allowCdp - register browser_cdp
|
|
44
|
+
* @param diagnostics - register the two diagnostics tools
|
|
44
45
|
* @returns the YAML block, markers included
|
|
45
46
|
*/
|
|
46
|
-
export function renderBrowserBlock(allowEvaluate, allowCdp) {
|
|
47
|
+
export function renderBrowserBlock(allowEvaluate, allowCdp, diagnostics) {
|
|
47
48
|
return [
|
|
48
49
|
BEGIN,
|
|
49
50
|
'# allowEvaluate: 注册 browser_evaluate(页面任意 JS,能用你的登录态操作网站)',
|
|
@@ -72,6 +73,7 @@ export function renderBrowserBlock(allowEvaluate, allowCdp) {
|
|
|
72
73
|
' toolPrefix: "browser_"',
|
|
73
74
|
' allowEvaluate: ' + (allowEvaluate ? 'true' : 'false'),
|
|
74
75
|
' allowCdp: ' + (allowCdp ? 'true' : 'false'),
|
|
76
|
+
' diagnostics: ' + (diagnostics ? 'true' : 'false'),
|
|
75
77
|
' registerDisabledTools: false',
|
|
76
78
|
' diagnostics: false',
|
|
77
79
|
' maxWaitMs: 60000',
|
|
@@ -98,8 +100,8 @@ function findBlock(original) {
|
|
|
98
100
|
return undefined;
|
|
99
101
|
}
|
|
100
102
|
/** Merge the managed block into `original`, replacing an existing one in place. */
|
|
101
|
-
export function mergeBrowserBlock(original, allowEvaluate, allowCdp) {
|
|
102
|
-
const block = renderBrowserBlock(allowEvaluate, allowCdp);
|
|
103
|
+
export function mergeBrowserBlock(original, allowEvaluate, allowCdp, diagnostics) {
|
|
104
|
+
const block = renderBrowserBlock(allowEvaluate, allowCdp, diagnostics);
|
|
103
105
|
const found = findBlock(original);
|
|
104
106
|
if (found !== undefined)
|
|
105
107
|
return original.slice(0, found.start) + block + original.slice(found.after);
|
|
@@ -115,7 +117,12 @@ export function parseBrowserBlock(text) {
|
|
|
115
117
|
const cdp = /allowCdp:\s*(true|false)/.exec(body);
|
|
116
118
|
if (evaluate === null || cdp === null)
|
|
117
119
|
return undefined;
|
|
118
|
-
|
|
120
|
+
const diag = /diagnostics:\s*(true|false)/.exec(body);
|
|
121
|
+
return {
|
|
122
|
+
allowEvaluate: evaluate[1] === 'true',
|
|
123
|
+
allowCdp: cdp[1] === 'true',
|
|
124
|
+
diagnostics: diag === null ? false : diag[1] === 'true',
|
|
125
|
+
};
|
|
119
126
|
}
|
|
120
127
|
/** Back-compat aliases used by the absorbed settings-card host half. */
|
|
121
128
|
export const parseGatesBlock = parseBrowserBlock;
|
|
@@ -130,7 +137,7 @@ export const mergeGatesBlock = mergeBrowserBlock;
|
|
|
130
137
|
* @param env - environment (DSH_HOME override for tests)
|
|
131
138
|
* @returns the file written and the values it now carries
|
|
132
139
|
*/
|
|
133
|
-
export async function writeGates(allowEvaluate, allowCdp, env = process.env) {
|
|
140
|
+
export async function writeGates(allowEvaluate, allowCdp, diagnostics, env = process.env) {
|
|
134
141
|
const file = homePatchPath(env);
|
|
135
142
|
let original = '';
|
|
136
143
|
try {
|
|
@@ -139,7 +146,7 @@ export async function writeGates(allowEvaluate, allowCdp, env = process.env) {
|
|
|
139
146
|
catch {
|
|
140
147
|
original = '';
|
|
141
148
|
}
|
|
142
|
-
const next = mergeBrowserBlock(original, allowEvaluate, allowCdp);
|
|
149
|
+
const next = mergeBrowserBlock(original, allowEvaluate, allowCdp, diagnostics);
|
|
143
150
|
if (original !== '')
|
|
144
151
|
await copyFile(file, file + '.bak-browser-toggle').catch(() => { });
|
|
145
152
|
const tmp = file + '.tmp-browser-toggle';
|
|
@@ -147,12 +154,15 @@ export async function writeGates(allowEvaluate, allowCdp, env = process.env) {
|
|
|
147
154
|
await rename(tmp, file);
|
|
148
155
|
const check = await readFile(file, 'utf8');
|
|
149
156
|
const parsed = parseBrowserBlock(check);
|
|
150
|
-
if (parsed === undefined ||
|
|
157
|
+
if (parsed === undefined ||
|
|
158
|
+
parsed.allowEvaluate !== allowEvaluate ||
|
|
159
|
+
parsed.allowCdp !== allowCdp ||
|
|
160
|
+
parsed.diagnostics !== diagnostics) {
|
|
151
161
|
if (original !== '') {
|
|
152
162
|
await writeFile(file, original, 'utf8');
|
|
153
163
|
throw new Error('patch self-check failed after write; previous content restored');
|
|
154
164
|
}
|
|
155
165
|
throw new Error('patch self-check failed after write');
|
|
156
166
|
}
|
|
157
|
-
return { patch: file, allowEvaluate, allowCdp };
|
|
167
|
+
return { patch: file, allowEvaluate, allowCdp, diagnostics };
|
|
158
168
|
}
|
package/lib/runtime-state.d.ts
CHANGED
|
@@ -64,11 +64,13 @@ export declare function isEngineUserChosen(): boolean;
|
|
|
64
64
|
export declare function publishGates(gates: {
|
|
65
65
|
allowEvaluate: boolean;
|
|
66
66
|
allowCdp: boolean;
|
|
67
|
+
diagnostics: boolean;
|
|
67
68
|
}): void;
|
|
68
69
|
/** The published gates, or undefined while the tool family has not been applied. */
|
|
69
70
|
export declare function getGates(): {
|
|
70
71
|
allowEvaluate: boolean;
|
|
71
72
|
allowCdp: boolean;
|
|
73
|
+
diagnostics: boolean;
|
|
72
74
|
} | undefined;
|
|
73
75
|
/**
|
|
74
76
|
* The last computed "which sites look logged in" summary, or undefined before anything
|
package/lib/runtime-state.js
CHANGED
|
@@ -149,7 +149,11 @@ export function isEngineUserChosen() {
|
|
|
149
149
|
* @param gates - whether browser_evaluate / browser_cdp are registered.
|
|
150
150
|
*/
|
|
151
151
|
export function publishGates(gates) {
|
|
152
|
-
_gates = {
|
|
152
|
+
_gates = {
|
|
153
|
+
allowEvaluate: gates.allowEvaluate === true,
|
|
154
|
+
allowCdp: gates.allowCdp === true,
|
|
155
|
+
diagnostics: gates.diagnostics === true,
|
|
156
|
+
};
|
|
153
157
|
}
|
|
154
158
|
/** The published gates, or undefined while the tool family has not been applied. */
|
|
155
159
|
export function getGates() {
|
package/lib/settings-card.js
CHANGED
|
@@ -135,6 +135,7 @@ export function apply(ctx) {
|
|
|
135
135
|
// provider build in this profile is too old to report them.
|
|
136
136
|
allowEvaluate: gates ? gates.allowEvaluate : null,
|
|
137
137
|
allowCdp: gates ? gates.allowCdp : null,
|
|
138
|
+
diagnostics: gates ? gates.diagnostics : null,
|
|
138
139
|
// What the user's own layer says right now. Differs from the above
|
|
139
140
|
// between a write and the live reload that applies it.
|
|
140
141
|
patchGates: managedBlockGates() ?? null,
|
|
@@ -209,6 +210,8 @@ export function apply(ctx) {
|
|
|
209
210
|
catch {
|
|
210
211
|
return sendJson(res, 400, { error: { code: 'INVALID_JSON', message: 'body must be JSON' } });
|
|
211
212
|
}
|
|
213
|
+
if (typeof payload.diagnostics !== 'boolean')
|
|
214
|
+
payload.diagnostics = false;
|
|
212
215
|
if (typeof payload.allowEvaluate !== 'boolean' || typeof payload.allowCdp !== 'boolean')
|
|
213
216
|
return sendJson(res, 400, {
|
|
214
217
|
error: {
|
|
@@ -217,16 +220,20 @@ export function apply(ctx) {
|
|
|
217
220
|
},
|
|
218
221
|
});
|
|
219
222
|
const before = readGates();
|
|
220
|
-
if (before &&
|
|
223
|
+
if (before &&
|
|
224
|
+
before.allowEvaluate === payload.allowEvaluate &&
|
|
225
|
+
before.allowCdp === payload.allowCdp &&
|
|
226
|
+
before.diagnostics === payload.diagnostics)
|
|
221
227
|
return sendJson(res, 200, { ...before, changed: false, patch: null });
|
|
222
228
|
try {
|
|
223
|
-
const written = await writeGates(payload.allowEvaluate, payload.allowCdp);
|
|
229
|
+
const written = await writeGates(payload.allowEvaluate, payload.allowCdp, payload.diagnostics);
|
|
224
230
|
// The effective values only move once the loader re-applies the tree
|
|
225
231
|
// (profile patchReload: live); report what was written, and let the
|
|
226
232
|
// panel's next /state poll show whether it took effect.
|
|
227
233
|
sendJson(res, 200, {
|
|
228
234
|
allowEvaluate: written.allowEvaluate,
|
|
229
235
|
allowCdp: written.allowCdp,
|
|
236
|
+
diagnostics: written.diagnostics,
|
|
230
237
|
changed: true,
|
|
231
238
|
patch: written.patch,
|
|
232
239
|
});
|
package/lib/tool.js
CHANGED
|
@@ -60,7 +60,11 @@ export function apply(ctx, config) {
|
|
|
60
60
|
// home-level patch), so the tool family publishes it at registration and the
|
|
61
61
|
// switch shows the truth instead of a guess. Driven by the same values that
|
|
62
62
|
// decided which tools register, so the two can never disagree.
|
|
63
|
-
publishGates({
|
|
63
|
+
publishGates({
|
|
64
|
+
allowEvaluate: registered.has('evaluate'),
|
|
65
|
+
allowCdp: registered.has('cdp'),
|
|
66
|
+
diagnostics: registered.has('console_messages'),
|
|
67
|
+
});
|
|
64
68
|
/** Register one gated tool only when this configuration keeps it live. */
|
|
65
69
|
const registerMaybe = (suffix, definition) => {
|
|
66
70
|
if (registered.has(suffix))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-browser-playwright-codex",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "Browser automation for DeepSeek Harness, one plugin: fill in forms, scrape lists and work across tabs in real pages, using the logins you already have. Runs in a visible window that stays quiet when minimised; native dialogs are parked instead of confirmed, CAPTCHA pages are flagged with a note that says stop and hand the page back, password / one-time-code / card fields are refused by browser_fill, and the Settings card (enable/disable, page-reading mode, capability gates) now lives inside this package.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|