From c3a7f74b1f7605c55a0ff7f534e5b03fb825c870 Mon Sep 17 00:00:00 2001 From: AskaEth Date: Sun, 6 Sep 2026 11:11:45 +0800 Subject: [PATCH] =?UTF-8?q?fix(cli):=20=E8=87=AA=E5=8A=A8=E6=8B=89?= =?UTF-8?q?=E8=B5=B7=20daemon=20=E8=B5=B0=20boot.js=EF=BC=88=E5=B8=A6=20Br?= =?UTF-8?q?owserManager=EF=BC=89=EF=BC=8C=E4=BF=AE=E5=A4=8D=20open/list/ge?= =?UTF-8?q?t=20=E5=85=A8=20not=20found=EF=BC=9Bdaemon=20=E5=A2=9E=20vision?= =?UTF-8?q?l-daemon=20bin=20+=20start=20=E6=8C=87=E5=90=91=20boot=EF=BC=9B?= =?UTF-8?q?docs=20=E5=90=8C=E6=AD=A5=E5=BD=93=E5=89=8D=20CLI=EF=BC=88?= =?UTF-8?q?=E6=97=A0=20daemon/page=20=E5=AD=90=E5=91=BD=E4=BB=A4=EF=BC=8CB?= =?UTF-8?q?ing=20=E6=98=93=E5=8F=8D=E7=88=AC=E8=AF=B7=E7=94=A8=E7=99=BE?= =?UTF-8?q?=E5=BA=A6=E7=AD=89=E5=9B=BD=E5=86=85=E6=BA=90=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/development/cli.md | 27 +++++++++++++++------------ packages/cli/src/auto-daemon.ts | 5 ++++- packages/daemon/package.json | 5 ++++- packages/daemon/src/boot.ts | 27 +++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 14 deletions(-) create mode 100644 packages/daemon/src/boot.ts diff --git a/docs/development/cli.md b/docs/development/cli.md index 5bb9286..e535d8a 100644 --- a/docs/development/cli.md +++ b/docs/development/cli.md @@ -206,26 +206,29 @@ visionl profiles ## Daemon 管理 -### `visionl daemon start` +> 当前 CLI **没有 `daemon start/stop` 子命令**。首条页面命令会自动拉起**带反检测浏览器**的 daemon(`boot.js`);手动启动可选如下方式。 -手动启动 daemon。 +### 手动启动浏览器 daemon ```bash -visionl daemon start [--port ] +# 方式一:daemon 包 start 脚本(= node ./dist/boot.js) +cd packages/daemon && npm run start -# 默认端口 9527 -visionl daemon start -# 指定端口 -visionl daemon start --port 8080 +# 方式二:直接节点 +node packages/daemon/dist/boot.js + +# 方式三:全局 bin(构建后安装) +visionl-daemon + +# 指定端口:VISIONL_PORT 环境变量,默认 9527 +VISIONL_PORT=8080 node packages/daemon/dist/boot.js ``` -### `visionl daemon stop` +> 注意:必须走 `boot.js`(它初始化 `BrowserManager` 并把它传给 `startServer`)。若直接 `node packages/daemon/dist/server.js`,daemon 会**没有浏览器**,页面路由不注册,`open/list/...` 一律 `not found`(这是已修复的坑)。 -优雅关闭 daemon(不杀死已打开的页面)。 +### 重启 / 停止 daemon -```bash -visionl daemon stop -``` +没有 `daemon stop` 子命令;结束方式为 `kill `(含浏览器常驻进程)即可。 ### `visionl daemon status` diff --git a/packages/cli/src/auto-daemon.ts b/packages/cli/src/auto-daemon.ts index 99fc48b..ede15d4 100644 --- a/packages/cli/src/auto-daemon.ts +++ b/packages/cli/src/auto-daemon.ts @@ -20,7 +20,10 @@ export async function ensureDaemonRunning(port: number): Promise } } - const daemonEntryPath = path.resolve(__dirname, '../../daemon/dist/server.js'); + // Spawn the browser-enabled daemon entry (boot.js) so that page/content/ + // action routes are registered. Spawning server.js directly would start a + // browser-less daemon that only serves /health. + const daemonEntryPath = path.resolve(__dirname, '../../daemon/dist/boot.js'); spawn('node', [daemonEntryPath], { env: { ...process.env, VISIONL_PORT: String(port) }, stdio: 'ignore', diff --git a/packages/daemon/package.json b/packages/daemon/package.json index e0fa0a2..19708d5 100644 --- a/packages/daemon/package.json +++ b/packages/daemon/package.json @@ -3,10 +3,13 @@ "version": "0.1.0", "private": true, "main": "./dist/index.js", + "bin": { + "visionl-daemon": "./dist/boot.js" + }, "scripts": { "typecheck": "tsc -b", "build": "tsc -b", - "start": "node ./dist/index.js" + "start": "node ./dist/boot.js" }, "dependencies": { "@visionl/core": "*", diff --git a/packages/daemon/src/boot.ts b/packages/daemon/src/boot.ts new file mode 100644 index 0000000..b8e5e08 --- /dev/null +++ b/packages/daemon/src/boot.ts @@ -0,0 +1,27 @@ +import { startServer } from './server.js'; +import { BrowserManager } from './browser-manager.js'; + +/** + * boot is the browser-enabled daemon entry: it initializes a persistent + * BrowserManager (anti-detection Chromium) and starts the HTTP+WS server with + * it. Startup via the CLI must go through this entry so page/content/action + * routes are actually registered (spawning server.js alone skips them). + */ +export async function boot(port: number, profile = 'desktop-chrome') { + const bm = new BrowserManager(profile); + await bm.init(); + console.log('[daemon] Browser initialized'); + const server = await startServer(port, bm); + console.log('[daemon] Ready on port', port); + return { bm, server }; +} + +// Direct start when run as a script — the correct browser-enabled daemon entry. +if (process.argv[1] && (process.argv[1].endsWith('boot.js') || process.argv[1].endsWith('boot.ts'))) { + const port = parseInt(process.env.VISIONL_PORT || '9527', 10); + const profile = process.env.VISIONL_PROFILE || 'desktop-chrome'; + boot(port, profile).catch((err) => { + console.error('[daemon] Fatal:', err); + process.exit(1); + }); +}