@jackwener/opencli 1.5.6 → 1.5.7
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 +26 -0
- package/README.md +4 -2
- package/README.zh-CN.md +4 -1
- package/SKILL.md +879 -0
- package/dist/browser/cdp.d.ts +1 -0
- package/dist/browser/cdp.js +30 -27
- package/dist/browser/daemon-client.d.ts +7 -1
- package/dist/browser/daemon-client.js +3 -0
- package/dist/browser/dom-helpers.js +1 -0
- package/dist/browser/dom-helpers.test.js +14 -1
- package/dist/browser/mcp.js +18 -13
- package/dist/browser/page.js +22 -2
- package/dist/browser/page.test.d.ts +1 -0
- package/dist/browser/page.test.js +44 -0
- package/dist/browser/stealth.js +198 -0
- package/dist/browser/stealth.test.d.ts +1 -0
- package/dist/browser/stealth.test.js +134 -0
- package/dist/browser.test.js +1 -1
- package/dist/build-manifest.d.ts +1 -0
- package/dist/build-manifest.js +5 -1
- package/dist/build-manifest.test.js +2 -0
- package/dist/cli-manifest.json +544 -137
- package/dist/cli.js +20 -3
- package/dist/clis/antigravity/serve.d.ts +1 -1
- package/dist/clis/antigravity/serve.js +5 -8
- package/dist/clis/bilibili/subtitle.js +4 -0
- package/dist/clis/bilibili/subtitle.test.d.ts +1 -0
- package/dist/clis/bilibili/subtitle.test.js +48 -0
- package/dist/clis/chatwise/ask.js +0 -2
- package/dist/clis/chatwise/export.js +0 -2
- package/dist/clis/chatwise/history.js +0 -2
- package/dist/clis/chatwise/model.js +0 -2
- package/dist/clis/chatwise/new.js +1 -2
- package/dist/clis/chatwise/read.js +0 -2
- package/dist/clis/chatwise/screenshot.js +1 -2
- package/dist/clis/chatwise/send.js +0 -2
- package/dist/clis/chatwise/status.js +1 -2
- package/dist/clis/ctrip/search.d.ts +13 -0
- package/dist/clis/ctrip/search.js +73 -48
- package/dist/clis/ctrip/search.test.d.ts +1 -0
- package/dist/clis/ctrip/search.test.js +64 -0
- package/dist/clis/douyin/_shared/sts2.js +8 -2
- package/dist/clis/douyin/_shared/sts2.test.d.ts +1 -0
- package/dist/clis/douyin/_shared/sts2.test.js +27 -0
- package/dist/clis/douyin/activities.js +4 -2
- package/dist/clis/douyin/activities.test.js +34 -1
- package/dist/clis/douyin/collections.js +1 -1
- package/dist/clis/douyin/collections.test.js +24 -2
- package/dist/clis/douyin/draft.d.ts +8 -11
- package/dist/clis/douyin/draft.js +302 -185
- package/dist/clis/douyin/draft.test.d.ts +1 -1
- package/dist/clis/douyin/draft.test.js +357 -2
- package/dist/clis/douyin/hashtag.js +9 -2
- package/dist/clis/douyin/hashtag.test.js +35 -2
- package/dist/clis/douyin/profile.js +1 -1
- package/dist/clis/douyin/profile.test.js +36 -1
- package/dist/clis/douyin/videos.js +22 -5
- package/dist/clis/douyin/videos.test.js +45 -2
- package/dist/clis/facebook/search.test.d.ts +5 -0
- package/dist/clis/facebook/search.test.js +60 -0
- package/dist/clis/facebook/search.yaml +4 -3
- package/dist/clis/instagram/download.d.ts +16 -0
- package/dist/clis/instagram/download.js +225 -0
- package/dist/clis/instagram/download.test.d.ts +1 -0
- package/dist/clis/instagram/download.test.js +118 -0
- package/dist/clis/notebooklm/bind-current.d.ts +1 -0
- package/dist/clis/notebooklm/bind-current.js +29 -0
- package/dist/clis/notebooklm/bind-current.test.d.ts +1 -0
- package/dist/clis/notebooklm/bind-current.test.js +35 -0
- package/dist/clis/notebooklm/binding.test.d.ts +1 -0
- package/dist/clis/notebooklm/binding.test.js +44 -0
- package/dist/clis/notebooklm/compat.test.d.ts +3 -0
- package/dist/clis/notebooklm/compat.test.js +16 -0
- package/dist/clis/notebooklm/current.d.ts +1 -0
- package/dist/clis/notebooklm/current.js +28 -0
- package/dist/clis/notebooklm/get.d.ts +1 -0
- package/dist/clis/notebooklm/get.js +37 -0
- package/dist/clis/notebooklm/history.d.ts +1 -0
- package/dist/clis/notebooklm/history.js +25 -0
- package/dist/clis/notebooklm/history.test.d.ts +1 -0
- package/dist/clis/notebooklm/history.test.js +58 -0
- package/dist/clis/notebooklm/list.d.ts +1 -0
- package/dist/clis/notebooklm/list.js +35 -0
- package/dist/clis/notebooklm/note-list.d.ts +1 -0
- package/dist/clis/notebooklm/note-list.js +28 -0
- package/dist/clis/notebooklm/note-list.test.d.ts +1 -0
- package/dist/clis/notebooklm/note-list.test.js +56 -0
- package/dist/clis/notebooklm/notes-get.d.ts +1 -0
- package/dist/clis/notebooklm/notes-get.js +47 -0
- package/dist/clis/notebooklm/notes-get.test.d.ts +1 -0
- package/dist/clis/notebooklm/notes-get.test.js +72 -0
- package/dist/clis/notebooklm/rpc.d.ts +36 -0
- package/dist/clis/notebooklm/rpc.js +189 -0
- package/dist/clis/notebooklm/rpc.test.d.ts +1 -0
- package/dist/clis/notebooklm/rpc.test.js +105 -0
- package/dist/clis/notebooklm/shared.d.ts +87 -0
- package/dist/clis/notebooklm/shared.js +3 -0
- package/dist/clis/notebooklm/source-fulltext.d.ts +1 -0
- package/dist/clis/notebooklm/source-fulltext.js +44 -0
- package/dist/clis/notebooklm/source-fulltext.test.d.ts +1 -0
- package/dist/clis/notebooklm/source-fulltext.test.js +106 -0
- package/dist/clis/notebooklm/source-get.d.ts +1 -0
- package/dist/clis/notebooklm/source-get.js +40 -0
- package/dist/clis/notebooklm/source-get.test.d.ts +1 -0
- package/dist/clis/notebooklm/source-get.test.js +84 -0
- package/dist/clis/notebooklm/source-guide.d.ts +1 -0
- package/dist/clis/notebooklm/source-guide.js +44 -0
- package/dist/clis/notebooklm/source-guide.test.d.ts +1 -0
- package/dist/clis/notebooklm/source-guide.test.js +104 -0
- package/dist/clis/notebooklm/source-list.d.ts +1 -0
- package/dist/clis/notebooklm/source-list.js +30 -0
- package/dist/clis/notebooklm/status.d.ts +1 -0
- package/dist/clis/notebooklm/status.js +31 -0
- package/dist/clis/notebooklm/summary.d.ts +1 -0
- package/dist/clis/notebooklm/summary.js +30 -0
- package/dist/clis/notebooklm/summary.test.d.ts +1 -0
- package/dist/clis/notebooklm/summary.test.js +78 -0
- package/dist/clis/notebooklm/utils.d.ts +37 -0
- package/dist/clis/notebooklm/utils.js +739 -0
- package/dist/clis/notebooklm/utils.test.d.ts +1 -0
- package/dist/clis/notebooklm/utils.test.js +390 -0
- package/dist/clis/substack/utils.d.ts +4 -0
- package/dist/clis/substack/utils.js +8 -2
- package/dist/clis/substack/utils.test.d.ts +1 -0
- package/dist/clis/substack/utils.test.js +46 -0
- package/dist/clis/v2ex/hot.yaml +4 -1
- package/dist/clis/v2ex/latest.yaml +4 -1
- package/dist/clis/v2ex/topic.yaml +6 -1
- package/dist/clis/weixin/download.d.ts +9 -0
- package/dist/clis/weixin/download.js +76 -6
- package/dist/clis/weread/book.js +108 -2
- package/dist/clis/weread/commands.test.js +262 -152
- package/dist/clis/weread/utils.d.ts +10 -0
- package/dist/clis/weread/utils.js +27 -7
- package/dist/clis/xiaohongshu/comments.d.ts +3 -0
- package/dist/clis/xiaohongshu/comments.js +76 -17
- package/dist/clis/xiaohongshu/comments.test.js +70 -9
- package/dist/clis/xiaohongshu/download.d.ts +4 -1
- package/dist/clis/xiaohongshu/download.js +83 -22
- package/dist/clis/xiaohongshu/download.test.d.ts +1 -0
- package/dist/clis/xiaohongshu/download.test.js +75 -0
- package/dist/clis/xiaohongshu/note-helpers.d.ts +12 -0
- package/dist/clis/xiaohongshu/note-helpers.js +23 -0
- package/dist/clis/xiaohongshu/note.d.ts +7 -0
- package/dist/clis/xiaohongshu/note.js +76 -0
- package/dist/clis/xiaohongshu/note.test.d.ts +1 -0
- package/dist/clis/xiaohongshu/note.test.js +136 -0
- package/dist/clis/xiaohongshu/search.js +9 -0
- package/dist/clis/xiaohongshu/search.test.js +10 -4
- package/dist/clis/youtube/search.js +57 -17
- package/dist/clis/zhihu/question.js +19 -17
- package/dist/clis/zhihu/question.test.d.ts +1 -0
- package/dist/clis/zhihu/question.test.js +54 -0
- package/dist/commanderAdapter.js +9 -0
- package/dist/commanderAdapter.test.js +25 -0
- package/dist/commands/daemon.d.ts +9 -0
- package/dist/commands/daemon.js +124 -0
- package/dist/commands/daemon.test.d.ts +1 -0
- package/dist/commands/daemon.test.js +185 -0
- package/dist/completion.js +3 -1
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +2 -0
- package/dist/daemon.d.ts +1 -1
- package/dist/daemon.js +25 -14
- package/dist/daemon.test.d.ts +1 -0
- package/dist/daemon.test.js +65 -0
- package/dist/discovery.d.ts +9 -0
- package/dist/discovery.js +47 -2
- package/dist/electron-apps.d.ts +29 -0
- package/dist/electron-apps.js +65 -0
- package/dist/electron-apps.test.d.ts +1 -0
- package/dist/electron-apps.test.js +43 -0
- package/dist/engine.test.js +41 -9
- package/dist/execution.js +20 -16
- package/dist/idle-manager.d.ts +19 -0
- package/dist/idle-manager.js +54 -0
- package/dist/launcher.d.ts +36 -0
- package/dist/launcher.js +152 -0
- package/dist/launcher.test.d.ts +1 -0
- package/dist/launcher.test.js +57 -0
- package/dist/main.js +3 -3
- package/dist/registry.d.ts +1 -0
- package/dist/registry.js +31 -3
- package/dist/registry.test.js +13 -0
- package/dist/runtime.d.ts +5 -3
- package/dist/runtime.js +12 -5
- package/dist/serialization.d.ts +1 -0
- package/dist/serialization.js +3 -0
- package/dist/serialization.test.js +17 -1
- package/dist/tui.d.ts +7 -0
- package/dist/tui.js +52 -0
- package/dist/tui.test.d.ts +1 -0
- package/dist/tui.test.js +19 -0
- package/dist/weixin-download.test.js +14 -0
- package/docs/.vitepress/config.mts +1 -0
- package/docs/adapters/browser/notebooklm.md +69 -0
- package/docs/adapters/browser/xiaohongshu.md +19 -10
- package/docs/adapters/index.md +67 -66
- package/docs/guide/browser-bridge.md +12 -0
- package/docs/guide/troubleshooting.md +9 -4
- package/docs/superpowers/plans/2026-03-31-daemon-lifecycle-redesign.md +857 -0
- package/docs/superpowers/specs/2026-03-31-daemon-lifecycle-redesign.md +208 -0
- package/docs/zh/guide/browser-bridge.md +12 -0
- package/extension/dist/background.js +794 -513
- package/extension/src/background.test.ts +202 -2
- package/extension/src/background.ts +174 -10
- package/extension/src/cdp.ts +12 -0
- package/extension/src/protocol.ts +7 -5
- package/package.json +1 -1
- package/src/browser/cdp.ts +24 -17
- package/src/browser/daemon-client.ts +7 -1
- package/src/browser/dom-helpers.test.ts +15 -1
- package/src/browser/dom-helpers.ts +1 -0
- package/src/browser/mcp.ts +18 -13
- package/src/browser/page.test.ts +58 -0
- package/src/browser/page.ts +18 -2
- package/src/browser/stealth.test.ts +153 -0
- package/src/browser/stealth.ts +198 -0
- package/src/browser.test.ts +1 -1
- package/src/build-manifest.test.ts +2 -0
- package/src/build-manifest.ts +6 -1
- package/src/cli.ts +21 -3
- package/src/clis/antigravity/SKILL.md +3 -12
- package/src/clis/antigravity/serve.ts +5 -10
- package/src/clis/bilibili/subtitle.test.ts +60 -0
- package/src/clis/bilibili/subtitle.ts +4 -0
- package/src/clis/chatwise/ask.ts +0 -2
- package/src/clis/chatwise/export.ts +0 -2
- package/src/clis/chatwise/history.ts +0 -2
- package/src/clis/chatwise/model.ts +0 -2
- package/src/clis/chatwise/new.ts +1 -2
- package/src/clis/chatwise/read.ts +0 -2
- package/src/clis/chatwise/screenshot.ts +1 -2
- package/src/clis/chatwise/send.ts +0 -2
- package/src/clis/chatwise/status.ts +1 -2
- package/src/clis/ctrip/search.test.ts +73 -0
- package/src/clis/ctrip/search.ts +97 -47
- package/src/clis/douyin/_shared/sts2.test.ts +31 -0
- package/src/clis/douyin/_shared/sts2.ts +11 -3
- package/src/clis/douyin/activities.test.ts +41 -1
- package/src/clis/douyin/activities.ts +12 -3
- package/src/clis/douyin/collections.test.ts +35 -2
- package/src/clis/douyin/collections.ts +1 -1
- package/src/clis/douyin/draft.test.ts +444 -2
- package/src/clis/douyin/draft.ts +382 -218
- package/src/clis/douyin/hashtag.test.ts +42 -2
- package/src/clis/douyin/hashtag.ts +11 -3
- package/src/clis/douyin/profile.test.ts +43 -1
- package/src/clis/douyin/profile.ts +9 -2
- package/src/clis/douyin/videos.test.ts +52 -2
- package/src/clis/douyin/videos.ts +49 -15
- package/src/clis/facebook/search.test.ts +70 -0
- package/src/clis/facebook/search.yaml +4 -3
- package/src/clis/instagram/download.test.ts +159 -0
- package/src/clis/instagram/download.ts +286 -0
- package/src/clis/notebooklm/bind-current.test.ts +43 -0
- package/src/clis/notebooklm/bind-current.ts +36 -0
- package/src/clis/notebooklm/binding.test.ts +53 -0
- package/src/clis/notebooklm/compat.test.ts +19 -0
- package/src/clis/notebooklm/current.ts +38 -0
- package/src/clis/notebooklm/get.ts +53 -0
- package/src/clis/notebooklm/history.test.ts +70 -0
- package/src/clis/notebooklm/history.ts +36 -0
- package/src/clis/notebooklm/list.ts +40 -0
- package/src/clis/notebooklm/note-list.test.ts +64 -0
- package/src/clis/notebooklm/note-list.ts +42 -0
- package/src/clis/notebooklm/notes-get.test.ts +88 -0
- package/src/clis/notebooklm/notes-get.ts +67 -0
- package/src/clis/notebooklm/rpc.test.ts +126 -0
- package/src/clis/notebooklm/rpc.ts +286 -0
- package/src/clis/notebooklm/shared.ts +98 -0
- package/src/clis/notebooklm/source-fulltext.test.ts +123 -0
- package/src/clis/notebooklm/source-fulltext.ts +69 -0
- package/src/clis/notebooklm/source-get.test.ts +100 -0
- package/src/clis/notebooklm/source-get.ts +60 -0
- package/src/clis/notebooklm/source-guide.test.ts +121 -0
- package/src/clis/notebooklm/source-guide.ts +69 -0
- package/src/clis/notebooklm/source-list.ts +45 -0
- package/src/clis/notebooklm/status.ts +34 -0
- package/src/clis/notebooklm/summary.test.ts +94 -0
- package/src/clis/notebooklm/summary.ts +45 -0
- package/src/clis/notebooklm/utils.test.ts +446 -0
- package/src/clis/notebooklm/utils.ts +893 -0
- package/src/clis/substack/utils.test.ts +54 -0
- package/src/clis/substack/utils.ts +10 -2
- package/src/clis/v2ex/hot.yaml +4 -1
- package/src/clis/v2ex/latest.yaml +4 -1
- package/src/clis/v2ex/topic.yaml +6 -1
- package/src/clis/weixin/download.ts +95 -6
- package/src/clis/weread/book.ts +142 -2
- package/src/clis/weread/commands.test.ts +314 -154
- package/src/clis/weread/utils.ts +33 -4
- package/src/clis/xiaohongshu/comments.test.ts +85 -9
- package/src/clis/xiaohongshu/comments.ts +76 -17
- package/src/clis/xiaohongshu/download.test.ts +96 -0
- package/src/clis/xiaohongshu/download.ts +83 -22
- package/src/clis/xiaohongshu/note-helpers.ts +25 -0
- package/src/clis/xiaohongshu/note.test.ts +164 -0
- package/src/clis/xiaohongshu/note.ts +86 -0
- package/src/clis/xiaohongshu/search.test.ts +11 -4
- package/src/clis/xiaohongshu/search.ts +13 -0
- package/src/clis/youtube/search.ts +57 -17
- package/src/clis/zhihu/question.test.ts +71 -0
- package/src/clis/zhihu/question.ts +27 -15
- package/src/commanderAdapter.test.ts +30 -0
- package/src/commanderAdapter.ts +7 -0
- package/src/commands/daemon.test.ts +238 -0
- package/src/commands/daemon.ts +135 -0
- package/src/completion.ts +2 -1
- package/src/constants.ts +3 -0
- package/src/daemon.test.ts +88 -0
- package/src/daemon.ts +26 -14
- package/src/discovery.ts +52 -2
- package/src/electron-apps.test.ts +50 -0
- package/src/electron-apps.ts +89 -0
- package/src/engine.test.ts +45 -9
- package/src/execution.ts +24 -19
- package/src/idle-manager.ts +60 -0
- package/src/launcher.test.ts +67 -0
- package/src/launcher.ts +185 -0
- package/src/main.ts +3 -2
- package/src/registry.test.ts +15 -0
- package/src/registry.ts +32 -3
- package/src/runtime.ts +13 -7
- package/src/serialization.test.ts +19 -1
- package/src/serialization.ts +2 -0
- package/src/tui.test.ts +23 -0
- package/src/tui.ts +65 -0
- package/src/weixin-download.test.ts +27 -0
- package/tests/e2e/browser-public-extended.test.ts +6 -2
- package/chatwise-opencli.ps1 +0 -82
- package/dist/clis/chatwise/shared.d.ts +0 -2
- package/dist/clis/chatwise/shared.js +0 -6
- package/src/clis/chatwise/shared.ts +0 -8
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# Daemon Lifecycle Redesign
|
|
2
|
+
|
|
3
|
+
## Problem
|
|
4
|
+
|
|
5
|
+
OpenCLI's daemon auto-exits after 5 minutes of idle time. During typical development
|
|
6
|
+
cycles (write code → test → modify → test again), coding intervals frequently exceed
|
|
7
|
+
5 minutes. Each restart incurs 2-4 seconds of overhead (process spawn + Extension
|
|
8
|
+
WebSocket reconnection), creating a noticeable and frustrating delay.
|
|
9
|
+
|
|
10
|
+
The current design treats the daemon as a disposable process, but the actual cost
|
|
11
|
+
profile doesn't justify this:
|
|
12
|
+
|
|
13
|
+
| Cost of staying alive | Cost of restarting |
|
|
14
|
+
|-----------------------|--------------------|
|
|
15
|
+
| ~12 MB memory, 0% CPU | 2-4 seconds delay per restart |
|
|
16
|
+
|
|
17
|
+
The restart cost far outweighs the idle cost.
|
|
18
|
+
|
|
19
|
+
## Solution
|
|
20
|
+
|
|
21
|
+
Replace the aggressive 5-minute fixed timeout with a long-lived daemon model. The
|
|
22
|
+
daemon stays running for hours, exits only when truly abandoned, and reconnects to
|
|
23
|
+
the Chrome Extension faster when needed.
|
|
24
|
+
|
|
25
|
+
Four changes:
|
|
26
|
+
|
|
27
|
+
1. Extend idle timeout from 5 minutes to 4 hours (configurable)
|
|
28
|
+
2. Require dual idle condition: both no CLI requests AND no Extension connection
|
|
29
|
+
3. Reduce Extension WebSocket reconnect backoff cap from 60s to 5s
|
|
30
|
+
4. Add `opencli daemon status/stop/restart` commands
|
|
31
|
+
|
|
32
|
+
## Design
|
|
33
|
+
|
|
34
|
+
### Timeout Strategy
|
|
35
|
+
|
|
36
|
+
**Current behavior:** A single idle timer resets on each HTTP request. After 5
|
|
37
|
+
minutes without a request, the daemon calls `process.exit(0)`.
|
|
38
|
+
|
|
39
|
+
**New behavior:** The daemon tracks two activity signals independently:
|
|
40
|
+
|
|
41
|
+
- **CLI activity:** timestamp of the last HTTP request from any CLI invocation
|
|
42
|
+
- **Extension activity:** whether a WebSocket connection from the Chrome Extension
|
|
43
|
+
is currently open
|
|
44
|
+
|
|
45
|
+
The exit countdown starts only when BOTH conditions are met simultaneously:
|
|
46
|
+
|
|
47
|
+
- No CLI request for `IDLE_TIMEOUT` duration
|
|
48
|
+
- No Extension WebSocket connection
|
|
49
|
+
|
|
50
|
+
If either signal is active, the daemon stays alive. This means:
|
|
51
|
+
|
|
52
|
+
- A connected Extension keeps the daemon alive indefinitely (user has Chrome open,
|
|
53
|
+
likely still working)
|
|
54
|
+
- Recent CLI activity keeps the daemon alive even if Extension temporarily
|
|
55
|
+
disconnects (Chrome restarting, Extension updating)
|
|
56
|
+
|
|
57
|
+
**Timeout value:** 4 hours by default, configurable via `OPENCLI_DAEMON_TIMEOUT`
|
|
58
|
+
environment variable. Value in milliseconds. Set to `0` to disable timeout entirely.
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
const DEFAULT_IDLE_TIMEOUT = 4 * 60 * 60 * 1000; // 4 hours
|
|
62
|
+
const IDLE_TIMEOUT = Number(process.env.OPENCLI_DAEMON_TIMEOUT ?? DEFAULT_IDLE_TIMEOUT);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Timer implementation:**
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
resetIdleTimer():
|
|
69
|
+
clear existing timer
|
|
70
|
+
if Extension is connected:
|
|
71
|
+
do not start timer (Extension connection keeps daemon alive)
|
|
72
|
+
return
|
|
73
|
+
start timer with IDLE_TIMEOUT duration
|
|
74
|
+
on timeout: process.exit(0)
|
|
75
|
+
|
|
76
|
+
On CLI HTTP request:
|
|
77
|
+
update lastRequestTime
|
|
78
|
+
resetIdleTimer()
|
|
79
|
+
|
|
80
|
+
On Extension WebSocket connect:
|
|
81
|
+
clear timer (Extension keeps daemon alive)
|
|
82
|
+
|
|
83
|
+
On Extension WebSocket disconnect:
|
|
84
|
+
elapsed = now - lastRequestTime
|
|
85
|
+
if elapsed >= IDLE_TIMEOUT:
|
|
86
|
+
process.exit(0) // CLI has been idle long enough already
|
|
87
|
+
else:
|
|
88
|
+
start timer with (IDLE_TIMEOUT - elapsed) // count remaining time
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Extension Fast Reconnect
|
|
92
|
+
|
|
93
|
+
**Current behavior:** When the Extension loses its WebSocket connection to the
|
|
94
|
+
daemon, it reconnects with exponential backoff: 2s → 4s → 8s → 16s → 32s → 60s
|
|
95
|
+
(capped). In the worst case, the Extension waits up to 60 seconds before attempting
|
|
96
|
+
reconnection.
|
|
97
|
+
|
|
98
|
+
**New behavior:** Cap the backoff at 5 seconds instead of 60 seconds.
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
// extension/src/background.ts
|
|
102
|
+
const WS_RECONNECT_MAX_DELAY = 5000; // was 60000
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Rationale: with a 4-hour daemon timeout, the daemon is almost always running. Long
|
|
106
|
+
backoff intervals are unnecessary and only increase reconnection latency. A 5-second
|
|
107
|
+
cap means the Extension reconnects within 5 seconds of the daemon becoming available.
|
|
108
|
+
|
|
109
|
+
### Daemon Management Commands
|
|
110
|
+
|
|
111
|
+
Add three new CLI commands for daemon lifecycle management:
|
|
112
|
+
|
|
113
|
+
**`opencli daemon status`**
|
|
114
|
+
|
|
115
|
+
Queries the daemon's `/status` endpoint (new) and displays:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
Daemon: running (PID 12345)
|
|
119
|
+
Uptime: 2h 15m
|
|
120
|
+
Extension: connected
|
|
121
|
+
Last CLI request: 8 min ago
|
|
122
|
+
Memory: 12.3 MB
|
|
123
|
+
Port: 19825
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
If daemon is not running:
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
Daemon: not running
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**`opencli daemon stop`**
|
|
133
|
+
|
|
134
|
+
Sends a `POST /shutdown` request to the daemon, which triggers a graceful shutdown:
|
|
135
|
+
reject pending requests with a shutdown message, close WebSocket connections, close
|
|
136
|
+
HTTP server, then exit.
|
|
137
|
+
|
|
138
|
+
**`opencli daemon restart`**
|
|
139
|
+
|
|
140
|
+
Equivalent to `stop` followed by spawning a new daemon. Useful when the daemon gets
|
|
141
|
+
into a bad state.
|
|
142
|
+
|
|
143
|
+
**Daemon-side endpoints:**
|
|
144
|
+
|
|
145
|
+
- `GET /status` — returns JSON with PID, uptime, extension connection state, last
|
|
146
|
+
request time, memory usage
|
|
147
|
+
- `POST /shutdown` — initiates graceful shutdown
|
|
148
|
+
|
|
149
|
+
Both endpoints require the same `X-OpenCLI` header as existing endpoints for CSRF
|
|
150
|
+
protection.
|
|
151
|
+
|
|
152
|
+
### CLI Connection Experience
|
|
153
|
+
|
|
154
|
+
**Current behavior:** When daemon is running but Extension is not connected, the CLI
|
|
155
|
+
silently polls every 300ms and eventually times out with a generic error.
|
|
156
|
+
|
|
157
|
+
**New behavior:** Show a progress indicator and actionable message:
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
⏳ Waiting for Chrome extension to connect...
|
|
161
|
+
Make sure Chrome is open and the OpenCLI extension is enabled.
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Poll interval reduced from 300ms to 200ms for slightly faster detection.
|
|
165
|
+
|
|
166
|
+
If the daemon is not running at all (connection refused), the CLI spawns it as before
|
|
167
|
+
and shows:
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
⏳ Starting daemon...
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Files Changed
|
|
174
|
+
|
|
175
|
+
| File | Change | Estimated LOC |
|
|
176
|
+
|------|--------|---------------|
|
|
177
|
+
| `src/daemon.ts` | Dual-condition idle timeout, `/status` endpoint, `/shutdown` endpoint | ~40 |
|
|
178
|
+
| `extension/src/background.ts` | `WS_RECONNECT_MAX_DELAY` 60000 → 5000 | 1 |
|
|
179
|
+
| `src/browser/daemon-client.ts` | Better connection-waiting UX, 200ms poll interval | ~20 |
|
|
180
|
+
| `src/commands/daemon.ts` (new) | `status`, `stop`, `restart` subcommands | ~80 |
|
|
181
|
+
| `src/constants.ts` | `DEFAULT_IDLE_TIMEOUT` constant | 2 |
|
|
182
|
+
|
|
183
|
+
**Total: ~143 lines of new/changed code.**
|
|
184
|
+
|
|
185
|
+
## Backward Compatibility
|
|
186
|
+
|
|
187
|
+
- No breaking changes to CLI commands or Extension protocol
|
|
188
|
+
- Existing `OPENCLI_DAEMON_PORT` environment variable continues to work
|
|
189
|
+
- The only observable behavior change: daemon stays alive longer
|
|
190
|
+
- New `daemon` subcommands are additive
|
|
191
|
+
|
|
192
|
+
## Testing
|
|
193
|
+
|
|
194
|
+
- Unit test: idle timer starts only when both CLI and Extension are idle
|
|
195
|
+
- Unit test: idle timer is cleared when Extension connects
|
|
196
|
+
- Unit test: `/status` returns correct state
|
|
197
|
+
- Unit test: `/shutdown` triggers graceful exit
|
|
198
|
+
- Integration test: daemon survives 10+ minutes without CLI requests while Extension
|
|
199
|
+
is connected
|
|
200
|
+
- Integration test: daemon exits after configured timeout when fully idle
|
|
201
|
+
- Integration test: `opencli daemon status/stop/restart` work correctly
|
|
202
|
+
|
|
203
|
+
## Out of Scope
|
|
204
|
+
|
|
205
|
+
- OS-level daemon management (launchd/systemd) — can be added later if needed
|
|
206
|
+
- Daemon auto-update mechanism
|
|
207
|
+
- Multi-daemon coordination
|
|
208
|
+
- Persistent daemon state across restarts
|
|
@@ -22,3 +22,15 @@ OpenCLI 通过轻量级 **Browser Bridge** Chrome 扩展 + 微守护进程连接
|
|
|
22
22
|
```bash
|
|
23
23
|
opencli doctor # 检查扩展 + 守护进程连接
|
|
24
24
|
```
|
|
25
|
+
|
|
26
|
+
## Daemon 生命周期
|
|
27
|
+
|
|
28
|
+
Daemon 在首次运行浏览器命令时自动启动,默认保持 **4 小时**。仅当 CLI 空闲超时**且** Chrome 扩展未连接时才会退出。
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
opencli daemon status # 查看 daemon 状态(PID、运行时长、扩展连接、内存)
|
|
32
|
+
opencli daemon stop # 优雅关停
|
|
33
|
+
opencli daemon restart # 重启
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
通过 `OPENCLI_DAEMON_TIMEOUT` 环境变量覆盖超时时间(毫秒)。设为 `0` 则永不超时。
|