@angelky7/dsh-browser-control 1.2.0 → 1.3.0
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.en.md +3 -3
- package/README.md +3 -3
- package/lib/index.js +31 -5
- package/lib/types/index.js +31 -2
- package/package.json +2 -2
package/README.en.md
CHANGED
|
@@ -64,8 +64,8 @@ In one line: **for "use MY browser" tasks (logged-in Bilibili, Zhihu, admin pane
|
|
|
64
64
|
|
|
65
65
|
| File | Purpose |
|
|
66
66
|
|---|---|
|
|
67
|
-
| [DSH-Browser-Control-v1.
|
|
68
|
-
| [dsh-browser-control-plugin-v1.
|
|
67
|
+
| [DSH-Browser-Control-v1.3.0.zip](https://github.com/angelky7/dsh-browser-control/releases/download/v1.3.0/DSH-Browser-Control-v1.3.0.zip) | Chrome extension (unzip and load; extension code is unchanged since 1.2.0 — no reinstall needed) |
|
|
68
|
+
| [dsh-browser-control-plugin-v1.3.0.zip](https://github.com/angelky7/dsh-browser-control/releases/download/v1.3.0/dsh-browser-control-plugin-v1.3.0.zip) | dsh plugin (offline fallback; online installs use Option A/B) |
|
|
69
69
|
|
|
70
70
|
## Install the Chrome extension (30 seconds)
|
|
71
71
|
|
|
@@ -104,7 +104,7 @@ npm install @angelky7/dsh-browser-control
|
|
|
104
104
|
|
|
105
105
|
```bash
|
|
106
106
|
# Straight from GitHub
|
|
107
|
-
dsh plugin --profile web add "github:angelky7/dsh-browser-control#v1.
|
|
107
|
+
dsh plugin --profile web add "github:angelky7/dsh-browser-control#v1.3.0"
|
|
108
108
|
|
|
109
109
|
# Local checkout for debugging (note: the explicit file: prefix is required)
|
|
110
110
|
dsh plugin --profile web add "file:D:\path\to\dsh-browser-control"
|
package/README.md
CHANGED
|
@@ -64,8 +64,8 @@ Chrome 扩展(CDP 驱动)
|
|
|
64
64
|
|
|
65
65
|
| 文件 | 说明 |
|
|
66
66
|
|---|---|
|
|
67
|
-
| [DSH-Browser-Control-v1.
|
|
68
|
-
| [dsh-browser-control-plugin-v1.
|
|
67
|
+
| [DSH-Browser-Control-v1.3.0.zip](https://github.com/angelky7/dsh-browser-control/releases/download/v1.3.0/DSH-Browser-Control-v1.3.0.zip) | Chrome 扩展(解压后加载;与 1.2.0 相比扩展代码无改动,已装 1.2.0 不必重装) |
|
|
68
|
+
| [dsh-browser-control-plugin-v1.3.0.zip](https://github.com/angelky7/dsh-browser-control/releases/download/v1.3.0/dsh-browser-control-plugin-v1.3.0.zip) | dsh 插件(离线兜底,在线装直接用方式 A/B) |
|
|
69
69
|
|
|
70
70
|
## 安装 Chrome 扩展(30 秒)
|
|
71
71
|
|
|
@@ -104,7 +104,7 @@ npm install @angelky7/dsh-browser-control
|
|
|
104
104
|
|
|
105
105
|
```bash
|
|
106
106
|
# 直接从 GitHub 安装
|
|
107
|
-
dsh plugin --profile web add "github:angelky7/dsh-browser-control#v1.
|
|
107
|
+
dsh plugin --profile web add "github:angelky7/dsh-browser-control#v1.3.0"
|
|
108
108
|
|
|
109
109
|
# 本地目录调试(注意:必须显式 file: 前缀)
|
|
110
110
|
dsh plugin --profile web add "file:D:\path\to\dsh-browser-control"
|
package/lib/index.js
CHANGED
|
@@ -939,6 +939,15 @@ function policyRefusal(command, flags, params) {
|
|
|
939
939
|
* fix, so the model can tell the user what to do instead of hanging.
|
|
940
940
|
* @module @deepseek-ai/dsh-browser-bridge
|
|
941
941
|
*/
|
|
942
|
+
/** Navigation wait ceiling (same as browser_wait); the bridge gets this plus BRIDGE_MARGIN_MS. */
|
|
943
|
+
const NAV_MAX_MS = 12e4;
|
|
944
|
+
/**
|
|
945
|
+
* Extra time handed to the bridge on top of the navigation budget. Without it a
|
|
946
|
+
* caller-requested budget longer than the bridge default (60s) would be beaten by
|
|
947
|
+
* the bridge, and the model would get `command_timeout` (effect unknown) instead
|
|
948
|
+
* of a navigation timeout (nothing was touched) - two very different next steps.
|
|
949
|
+
*/
|
|
950
|
+
const BRIDGE_MARGIN_MS = 2e3;
|
|
942
951
|
/** Cordis plugin name used by loader diagnostics. */
|
|
943
952
|
const name = "browser-bridge";
|
|
944
953
|
/** The tool registry this plugin contributes `browser_*` tools to. */
|
|
@@ -1236,6 +1245,10 @@ function applyBrowserTools(ctx, controller) {
|
|
|
1236
1245
|
tabId: {
|
|
1237
1246
|
type: "number",
|
|
1238
1247
|
description: "Target tab; defaults to the active tab."
|
|
1248
|
+
},
|
|
1249
|
+
timeoutMs: {
|
|
1250
|
+
type: "number",
|
|
1251
|
+
description: `How long to wait for the page load to settle: defaults to 15000, capped at ${NAV_MAX_MS}. Raise it for slow pages instead of retrying; drop it to 3000-5000 when you do not need the page to finish loading and will read/wait afterwards.`
|
|
1239
1252
|
}
|
|
1240
1253
|
},
|
|
1241
1254
|
output: {
|
|
@@ -1287,7 +1300,9 @@ function applyBrowserTools(ctx, controller) {
|
|
|
1287
1300
|
async execute(args, exec) {
|
|
1288
1301
|
const params = { url: args.url };
|
|
1289
1302
|
if (args.tabId !== void 0) params.tabId = args.tabId;
|
|
1290
|
-
const
|
|
1303
|
+
const budgetMs = typeof args.timeoutMs === "number" && Number.isFinite(args.timeoutMs) ? Math.min(NAV_MAX_MS, Math.max(100, Math.trunc(args.timeoutMs))) : 15e3;
|
|
1304
|
+
params.timeoutMs = budgetMs;
|
|
1305
|
+
const raw = await controller.execute("nav", params, exec.signal, budgetMs + BRIDGE_MARGIN_MS);
|
|
1291
1306
|
const out = { tabId: raw.tabId };
|
|
1292
1307
|
if (typeof raw.url === "string") out.url = raw.url;
|
|
1293
1308
|
if (typeof raw.title === "string") out.title = raw.title;
|
|
@@ -2041,6 +2056,8 @@ function applyBrowserTools(ctx, controller) {
|
|
|
2041
2056
|
}
|
|
2042
2057
|
}
|
|
2043
2058
|
}));
|
|
2059
|
+
/** Page-side ceiling of the eval race in the extension; the bridge budget adds slack on top. */
|
|
2060
|
+
const EVAL_MAX_MS = 12e4;
|
|
2044
2061
|
ctx.tools.register(defineTool({
|
|
2045
2062
|
name: "browser_evaluate",
|
|
2046
2063
|
description: "Run JavaScript in the page and get the JSON result back as a string. Prefer read-only inspection.",
|
|
@@ -2053,6 +2070,10 @@ function applyBrowserTools(ctx, controller) {
|
|
|
2053
2070
|
tabId: {
|
|
2054
2071
|
type: "number",
|
|
2055
2072
|
description: "Target tab; defaults to the active tab."
|
|
2073
|
+
},
|
|
2074
|
+
timeoutMs: {
|
|
2075
|
+
type: "number",
|
|
2076
|
+
description: `Give up after this many milliseconds; defaults to 60000, capped at ${EVAL_MAX_MS}.`
|
|
2056
2077
|
}
|
|
2057
2078
|
},
|
|
2058
2079
|
output: {
|
|
@@ -2081,10 +2102,15 @@ function applyBrowserTools(ctx, controller) {
|
|
|
2081
2102
|
kind: "other"
|
|
2082
2103
|
}),
|
|
2083
2104
|
async execute(args, exec) {
|
|
2084
|
-
const
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2105
|
+
const params = { expression: args.expression };
|
|
2106
|
+
if (args.tabId !== void 0) params.tabId = args.tabId;
|
|
2107
|
+
let bridgeCeiling;
|
|
2108
|
+
if (typeof args.timeoutMs === "number" && Number.isFinite(args.timeoutMs)) {
|
|
2109
|
+
const evalBudget = Math.min(EVAL_MAX_MS, Math.max(100, Math.trunc(args.timeoutMs)));
|
|
2110
|
+
params.timeoutMs = evalBudget;
|
|
2111
|
+
bridgeCeiling = evalBudget + 2e3;
|
|
2112
|
+
}
|
|
2113
|
+
const raw = await controller.execute("eval", params, exec.signal, bridgeCeiling);
|
|
2088
2114
|
let json;
|
|
2089
2115
|
try {
|
|
2090
2116
|
json = JSON.stringify(raw.value) ?? String(raw.value);
|
package/lib/types/index.js
CHANGED
|
@@ -24,6 +24,15 @@ import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
|
24
24
|
import { BridgeServer, cleanupArtifacts } from "./server.js";
|
|
25
25
|
import { BridgeError, classify } from "./errors.js";
|
|
26
26
|
import { policyRefusal } from "./policy.js";
|
|
27
|
+
/** Navigation wait ceiling (same as browser_wait); the bridge gets this plus BRIDGE_MARGIN_MS. */
|
|
28
|
+
const NAV_MAX_MS = 120_000;
|
|
29
|
+
/**
|
|
30
|
+
* Extra time handed to the bridge on top of the navigation budget. Without it a
|
|
31
|
+
* caller-requested budget longer than the bridge default (60s) would be beaten by
|
|
32
|
+
* the bridge, and the model would get `command_timeout` (effect unknown) instead
|
|
33
|
+
* of a navigation timeout (nothing was touched) - two very different next steps.
|
|
34
|
+
*/
|
|
35
|
+
const BRIDGE_MARGIN_MS = 2_000;
|
|
27
36
|
// Re-exported so the policy tables stay testable from the published bundle
|
|
28
37
|
// (verify/verify_policy.mjs reconciles them against the extension's COMMANDS).
|
|
29
38
|
export { LOCAL_DESTRUCTIVE_COMMANDS, PAGE_MUTATING_COMMANDS, READ_ONLY_ALLOWED, SCRIPT_COMMANDS, policyRefusal } from "./policy.js";
|
|
@@ -358,6 +367,7 @@ function applyBrowserTools(ctx, controller) {
|
|
|
358
367
|
parameters: {
|
|
359
368
|
url: { type: 'string', required: true, description: 'Absolute URL to open in the tab.' },
|
|
360
369
|
tabId: { type: 'number', description: 'Target tab; defaults to the active tab.' },
|
|
370
|
+
timeoutMs: { type: 'number', description: `How long to wait for the page load to settle: defaults to 15000, capped at ${NAV_MAX_MS}. Raise it for slow pages instead of retrying; drop it to 3000-5000 when you do not need the page to finish loading and will read/wait afterwards.` },
|
|
361
371
|
},
|
|
362
372
|
output: {
|
|
363
373
|
schema: {
|
|
@@ -397,7 +407,11 @@ function applyBrowserTools(ctx, controller) {
|
|
|
397
407
|
const params = { url: args.url };
|
|
398
408
|
if (args.tabId !== undefined)
|
|
399
409
|
params.tabId = args.tabId;
|
|
400
|
-
const
|
|
410
|
+
const budgetMs = typeof args.timeoutMs === 'number' && Number.isFinite(args.timeoutMs)
|
|
411
|
+
? Math.min(NAV_MAX_MS, Math.max(100, Math.trunc(args.timeoutMs)))
|
|
412
|
+
: 15_000;
|
|
413
|
+
params.timeoutMs = budgetMs;
|
|
414
|
+
const raw = await controller.execute('nav', params, exec.signal, budgetMs + BRIDGE_MARGIN_MS);
|
|
401
415
|
// The declared schema is closed, so the fields describing a navigation that did
|
|
402
416
|
// not arrive have to be carried over on purpose. The old shape check
|
|
403
417
|
// (`siteUnreachable === true`) also missed the object the extension really
|
|
@@ -866,12 +880,15 @@ function applyBrowserTools(ctx, controller) {
|
|
|
866
880
|
}
|
|
867
881
|
},
|
|
868
882
|
}));
|
|
883
|
+
/** Page-side ceiling of the eval race in the extension; the bridge budget adds slack on top. */
|
|
884
|
+
const EVAL_MAX_MS = 120_000;
|
|
869
885
|
ctx.tools.register(defineTool({
|
|
870
886
|
name: 'browser_evaluate',
|
|
871
887
|
description: 'Run JavaScript in the page and get the JSON result back as a string. Prefer read-only inspection.',
|
|
872
888
|
parameters: {
|
|
873
889
|
expression: { type: 'string', required: true, description: 'JavaScript expression or statement sequence; awaited like a promise body.' },
|
|
874
890
|
tabId: { type: 'number', description: 'Target tab; defaults to the active tab.' },
|
|
891
|
+
timeoutMs: { type: 'number', description: `Give up after this many milliseconds; defaults to 60000, capped at ${EVAL_MAX_MS}.` },
|
|
875
892
|
},
|
|
876
893
|
output: {
|
|
877
894
|
schema: {
|
|
@@ -886,7 +903,19 @@ function applyBrowserTools(ctx, controller) {
|
|
|
886
903
|
},
|
|
887
904
|
presentCall: () => ({ card: 'generic', title: 'Evaluate in page', kind: 'other' }),
|
|
888
905
|
async execute(args, exec) {
|
|
889
|
-
const
|
|
906
|
+
const params = { expression: args.expression };
|
|
907
|
+
if (args.tabId !== undefined)
|
|
908
|
+
params.tabId = args.tabId;
|
|
909
|
+
// The extension races the evaluation at this budget; give the bridge 2s of
|
|
910
|
+
// slack so the page-side timeout reports first. Omitted → send nothing and
|
|
911
|
+
// let the bridge default (60s) govern, exactly as before the knob existed.
|
|
912
|
+
let bridgeCeiling;
|
|
913
|
+
if (typeof args.timeoutMs === 'number' && Number.isFinite(args.timeoutMs)) {
|
|
914
|
+
const evalBudget = Math.min(EVAL_MAX_MS, Math.max(100, Math.trunc(args.timeoutMs)));
|
|
915
|
+
params.timeoutMs = evalBudget;
|
|
916
|
+
bridgeCeiling = evalBudget + 2_000;
|
|
917
|
+
}
|
|
918
|
+
const raw = await controller.execute('eval', params, exec.signal, bridgeCeiling);
|
|
890
919
|
let json;
|
|
891
920
|
try {
|
|
892
921
|
json = JSON.stringify(raw.value) ?? String(raw.value);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angelky7/dsh-browser-control",
|
|
3
3
|
"description": "Local WebSocket bridge between dsh and the DSH Browser Control browser extension, with model-facing browser_* tools and a Settings-managed on/off switch",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.3.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"types": "lib/types/index.d.ts",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"build": "tsc -p tsconfig.json && tsdown",
|
|
38
38
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
39
39
|
"check": "npm run typecheck && npm run build && publint",
|
|
40
|
-
"verify": "node verify/verify_config_patch.mjs && node verify/verify_peers.mjs && node verify/verify_surface.mjs && node verify/verify_tab_groups.mjs && node verify/verify_tabs_close_many.mjs && node verify/verify_cdp_retry.mjs && node verify/verify_snapshot_ax.mjs && node verify/verify_hard_lock.mjs && node verify/verify_policy.mjs && node verify/verify_cookies.mjs && node verify/verify_extension_e2e.mjs && node verify/verify_plugin.mjs legacy && node verify/verify_plugin.mjs conflict && node verify/verify_plugin.mjs new && node verify/verify_http.mjs && node verify/verify_errors.mjs && node verify/verify_hold.mjs && node verify/verify_protocol.mjs && node verify/verify_bundle_http.mjs && node verify/verify_nav_report.mjs && node verify/verify_nav_landing.mjs && node verify/verify_render_contract.mjs && node verify/verify_press_events.mjs"
|
|
40
|
+
"verify": "node verify/verify_config_patch.mjs && node verify/verify_peers.mjs && node verify/verify_surface.mjs && node verify/verify_tab_groups.mjs && node verify/verify_tabs_close_many.mjs && node verify/verify_cdp_retry.mjs && node verify/verify_snapshot_ax.mjs && node verify/verify_hard_lock.mjs && node verify/verify_policy.mjs && node verify/verify_cookies.mjs && node verify/verify_extension_e2e.mjs && node verify/verify_plugin.mjs legacy && node verify/verify_plugin.mjs conflict && node verify/verify_plugin.mjs new && node verify/verify_http.mjs && node verify/verify_errors.mjs && node verify/verify_hold.mjs && node verify/verify_protocol.mjs && node verify/verify_bundle_http.mjs && node verify/verify_nav_report.mjs && node verify/verify_nav_landing.mjs && node verify/verify_render_contract.mjs && node verify/verify_press_events.mjs && node verify/verify_nav_timeout.mjs"
|
|
41
41
|
},
|
|
42
42
|
"publishConfig": {
|
|
43
43
|
"access": "public",
|