bookmark-research 0.5.0-beta.17 → 0.5.0-beta.19
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/.agents/plugins/marketplace.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +10 -13
- package/README.zh.md +10 -13
- package/docs/distribution.md +1 -1
- package/package.json +1 -1
- package/scripts/install.py +6 -3
- package/src/onboarding.py +70 -51
- package/src/tui.py +5 -2
package/README.md
CHANGED
|
@@ -3,15 +3,12 @@
|
|
|
3
3
|
**English** · [中文](README.zh.md)
|
|
4
4
|
|
|
5
5
|
[](https://github.com/Browser-bookmark-hub/Bookmark-Canvas)
|
|
6
|
-
[](https://www.npmjs.com/package/bookmark-research)
|
|
7
7
|
|
|
8
8
|
Research with bookmark context and retain reusable knowledge. Read a [Bookmark Canvas](https://github.com/Browser-bookmark-hub/Bookmark-Canvas) package, investigate with the host model or a research API, and save sourced Wiki pages. Works in **Codex, Claude Code and DeepSeek Harness (dsh)**.
|
|
9
9
|
|
|
10
10
|
[Installation guide](docs/installation.en.md) · [User guide](docs/user-guide.en.md) · [Details](docs/details.en.md) · [npm](https://www.npmjs.com/package/bookmark-research)
|
|
11
11
|
|
|
12
|
-
> [!NOTE]
|
|
13
|
-
> **0.5.0 is a prerelease**, published on npm's `beta` tag; the `latest` tag still points at an older build. Report problems on [GitHub Issues](https://github.com/Browser-bookmark-hub/Bookmark-Research/issues).
|
|
14
|
-
|
|
15
12
|
## How it works
|
|
16
13
|
|
|
17
14
|
- **Local understanding.** A Bookmark Canvas package is read as structure, not a flat URL list: card and group layout, edges with their direction and labels, and the same bookmark appearing across cards (spatial context); dated fields, protocol-defined date segments in IDs, and Git commits that changed content (temporal context). These queries run offline.
|
|
@@ -28,10 +25,10 @@ Research with bookmark context and retain reusable knowledge. Read a [Bookmark C
|
|
|
28
25
|
## Install
|
|
29
26
|
|
|
30
27
|
```sh
|
|
31
|
-
npx bookmark-research
|
|
28
|
+
npx bookmark-research install
|
|
32
29
|
```
|
|
33
30
|
|
|
34
|
-
|
|
31
|
+
Installs the latest version directly. Add `--lang zh` for the Chinese wizard. For a permanent command, run `npm install -g bookmark-research`; the GitHub convenience script uses the same npm release (macOS/Linux/WSL):
|
|
35
32
|
|
|
36
33
|
```sh
|
|
37
34
|
curl -fsSL https://raw.githubusercontent.com/Browser-bookmark-hub/Bookmark-Research/main/install.sh | bash
|
|
@@ -54,11 +51,11 @@ Enter keeps the highlighted value, so a full run can be just a few keystrokes. T
|
|
|
54
51
|
|
|
55
52
|
| Client | Command | Registers with |
|
|
56
53
|
| --- | --- | --- |
|
|
57
|
-
| Codex | `npx bookmark-research
|
|
58
|
-
| Claude Code | `npx bookmark-research
|
|
59
|
-
| DeepSeek Harness (dsh) | `npx bookmark-research
|
|
54
|
+
| Codex | `npx bookmark-research install codex --non-interactive` | `codex plugin add` |
|
|
55
|
+
| Claude Code | `npx bookmark-research install claude --scope user --non-interactive` | `claude plugin install` |
|
|
56
|
+
| DeepSeek Harness (dsh) | `npx bookmark-research install dsh --profile web --non-interactive` | `dsh plugin add` |
|
|
60
57
|
|
|
61
|
-
Several at once: `npx bookmark-research
|
|
58
|
+
Several at once: `npx bookmark-research install claude dsh --profile web --non-interactive`. Project scope: `--scope project --project /path/to/project` (Claude Code). All options: [installation guide](docs/installation.en.md).
|
|
62
59
|
|
|
63
60
|
**Ask your agent to install it.** Paste this into Codex, Claude Code or DeepSeek Harness (dsh):
|
|
64
61
|
|
|
@@ -66,7 +63,7 @@ Several at once: `npx bookmark-research@beta install claude dsh --profile web --
|
|
|
66
63
|
Install the Bookmark Research plugin into the client you are running in.
|
|
67
64
|
|
|
68
65
|
1. Identify your own client: codex, claude or dsh.
|
|
69
|
-
2. Run: npx bookmark-research
|
|
66
|
+
2. Run: npx bookmark-research install <client> --non-interactive
|
|
70
67
|
- Claude Code: add --scope user (or --scope project --project <dir>).
|
|
71
68
|
- DeepSeek Harness (dsh): add --profile <profile>; ask me for the profile name.
|
|
72
69
|
3. The command prints JSON. Confirm "verified": true and report any "error".
|
|
@@ -93,9 +90,9 @@ Install notes:
|
|
|
93
90
|
| Scripted preferences | `bookmark-research config show` · `bookmark-research config set --input prefs.json` |
|
|
94
91
|
| Update or verify all clients | `bookmark-research update` · `bookmark-research verify` |
|
|
95
92
|
|
|
96
|
-
Use `npx bookmark-research
|
|
93
|
+
Use `npx bookmark-research …` if the command is not installed globally. Preferences and keys are user-wide, so one change applies to every installed client; start a new client session afterwards. `--lang zh` shows the wizard and menu in Chinese. The default `quick` preset exposes 21 everyday tools. Use `bookmark-research config set --tool-scope-preset deep` for the full 43-tool catalog when a persistent collection audit is needed. An explicit `tool_scope` list still overrides the preset.
|
|
97
94
|
|
|
98
|
-
**Update.** `bookmark-research update` refreshes every installed client from its registered source and keeps preferences, keys and data. Re-running `npx bookmark-research
|
|
95
|
+
**Update.** `bookmark-research update` refreshes every installed client from its registered source and keeps preferences, keys and data. Re-running `npx bookmark-research install` or `bookmark-research update` also upgrades existing installations in place (including Codex, Claude Code, and DeepSeek Harness).
|
|
99
96
|
|
|
100
97
|
**API keys are optional.** Enter them in `bookmark-research setup` (hidden input, checked immediately, saved in a private local file) or set environment variables, which take precedence.
|
|
101
98
|
|
package/README.zh.md
CHANGED
|
@@ -3,15 +3,12 @@
|
|
|
3
3
|
[English](README.md) · **中文**
|
|
4
4
|
|
|
5
5
|
[](https://github.com/Browser-bookmark-hub/Bookmark-Canvas)
|
|
6
|
-
[](https://www.npmjs.com/package/bookmark-research)
|
|
7
7
|
|
|
8
8
|
带着书签上下文调研,把结论留成可复用知识。读取 [Bookmark Canvas](https://github.com/Browser-bookmark-hub/Bookmark-Canvas) 数据包,使用宿主模型或研究 API 调查,再保存带来源的 Wiki 页面。支持 **Codex、Claude Code、DeepSeek Harness (dsh)**。
|
|
9
9
|
|
|
10
10
|
[安装说明](docs/installation.md) · [使用指南](docs/user-guide.md) · [详细说明](docs/details.md) · [npm](https://www.npmjs.com/package/bookmark-research)
|
|
11
11
|
|
|
12
|
-
> [!NOTE]
|
|
13
|
-
> **0.5.0 是测试版**,发布在 npm 的 `beta` 标签上;`latest` 标签仍指向更早的构建。遇到问题请到 [GitHub Issues](https://github.com/Browser-bookmark-hub/Bookmark-Research/issues) 反馈。
|
|
14
|
-
|
|
15
12
|
## 它是怎么工作的
|
|
16
13
|
|
|
17
14
|
- **本地理解层。** 数据包按结构读,而不是一张平铺的 URL 清单:卡片与分组的位置、连线的方向与标签、同一书签在不同卡片的出现位置(空间上下文);日期字段、ID 中协议定义的日期段,以及真正改过内容的 Git 提交(时间上下文)。这些都是离线查询。
|
|
@@ -28,10 +25,10 @@
|
|
|
28
25
|
## 安装
|
|
29
26
|
|
|
30
27
|
```sh
|
|
31
|
-
npx bookmark-research
|
|
28
|
+
npx bookmark-research install
|
|
32
29
|
```
|
|
33
30
|
|
|
34
|
-
|
|
31
|
+
默认直接安装最新版本。加 `--lang zh` 可让向导显示中文。想一直能用 `bookmark-research` 命令,运行 `npm install -g bookmark-research`;GitHub 便捷脚本使用同一 npm 发布版(macOS/Linux/WSL):
|
|
35
32
|
|
|
36
33
|
```sh
|
|
37
34
|
curl -fsSL https://raw.githubusercontent.com/Browser-bookmark-hub/Bookmark-Research/main/install.sh | bash
|
|
@@ -54,11 +51,11 @@ curl -fsSL https://raw.githubusercontent.com/Browser-bookmark-hub/Bookmark-Resea
|
|
|
54
51
|
|
|
55
52
|
| 宿主 | 命令 | 实际登记方式 |
|
|
56
53
|
| --- | --- | --- |
|
|
57
|
-
| Codex | `npx bookmark-research
|
|
58
|
-
| Claude Code | `npx bookmark-research
|
|
59
|
-
| DeepSeek Harness (dsh) | `npx bookmark-research
|
|
54
|
+
| Codex | `npx bookmark-research install codex --non-interactive` | `codex plugin add` |
|
|
55
|
+
| Claude Code | `npx bookmark-research install claude --scope user --non-interactive` | `claude plugin install` |
|
|
56
|
+
| DeepSeek Harness (dsh) | `npx bookmark-research install dsh --profile web --non-interactive` | `dsh plugin add` |
|
|
60
57
|
|
|
61
|
-
一次装多个:`npx bookmark-research
|
|
58
|
+
一次装多个:`npx bookmark-research install claude dsh --profile web --non-interactive`。装到指定项目:`--scope project --project /path/to/project`(Claude Code)。全部参数见[安装说明](docs/installation.md)。
|
|
62
59
|
|
|
63
60
|
**让 agent 帮你装。** 把下面这段粘贴给 Codex、Claude Code 或 DeepSeek Harness (dsh):
|
|
64
61
|
|
|
@@ -66,7 +63,7 @@ curl -fsSL https://raw.githubusercontent.com/Browser-bookmark-hub/Bookmark-Resea
|
|
|
66
63
|
请把 Bookmark Research 插件安装到你当前运行的这个宿主里。
|
|
67
64
|
|
|
68
65
|
1. 先确认你自己是哪个宿主:codex、claude 或 dsh。
|
|
69
|
-
2. 运行:npx bookmark-research
|
|
66
|
+
2. 运行:npx bookmark-research install <宿主> --non-interactive
|
|
70
67
|
- Claude Code:加 --scope user(或 --scope project --project <目录>)。
|
|
71
68
|
- DeepSeek Harness (dsh):加 --profile <名称>;profile 名称请先问我。
|
|
72
69
|
3. 命令会输出 JSON。确认 "verified": true,有 "error" 就告诉我。
|
|
@@ -92,9 +89,9 @@ curl -fsSL https://raw.githubusercontent.com/Browser-bookmark-hub/Bookmark-Resea
|
|
|
92
89
|
| 用脚本改偏好 | `bookmark-research config show` · `bookmark-research config set --input prefs.json` |
|
|
93
90
|
| 更新或验证所有宿主 | `bookmark-research update` · `bookmark-research verify` |
|
|
94
91
|
|
|
95
|
-
没有全局安装时,在前面加 `npx bookmark-research
|
|
92
|
+
没有全局安装时,在前面加 `npx bookmark-research`。偏好和 Key 是用户级的,改一次就对所有已安装宿主生效;改完新建宿主会话即可。加 `--lang zh` 可让向导和菜单显示中文。工具面可用 `bookmark-research config set --tool-scope-preset quick` 使用默认 21 个日常工具;`deep`(或 `all`)启用完整 43 个工具,供明确需要的完整资料审计使用。显式 `tool_scope` 仍优先于预设。
|
|
96
93
|
|
|
97
|
-
**更新。** `bookmark-research update` 会按各自登记的来源刷新所有已安装宿主,并保留偏好、Key 和数据。重跑 `npx bookmark-research
|
|
94
|
+
**更新。** `bookmark-research update` 会按各自登记的来源刷新所有已安装宿主,并保留偏好、Key 和数据。重跑 `npx bookmark-research install` 或 `bookmark-research update` 也会就地升级已装的宿主(包括 Codex、Claude Code、DeepSeek Harness)。
|
|
98
95
|
|
|
99
96
|
**API Key 都是可选的。** 在 `bookmark-research setup` 里输入(隐藏显示,输完当场检查,保存在仅当前用户可读的本地文件),或者设置环境变量(优先于已保存的 Key)。
|
|
100
97
|
|
package/docs/distribution.md
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
候选版本在 `release/` 分支同步三个版本清单并运行 CI。该分支的 registry 集成测试使用当前已发布渠道版本,源码测试、原生安装测试和 npm 打包检查仍验证候选内容;主分支的 registry 测试始终验证 marketplace 固定版本。发布通过 CI 的 npm 包并核验 registry 后,再将候选分支合入主分支,避免默认安装清单提前指向未发布版本。
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
发布时保持 npm 的 `latest` 标签始终指向最新构建,用户直接使用 `npx bookmark-research install`(或 `npx bookmark-research@latest install`)即可默认安装最新版。启动器会自动读取当前运行包版本并固定内容来源,无需重复指定 `--source`。已存在的宿主配置支持无缝覆盖升级。
|
|
24
24
|
|
|
25
25
|
## 官方资料与项目实例
|
|
26
26
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bookmark-research",
|
|
3
|
-
"version": "0.5.0-beta.
|
|
3
|
+
"version": "0.5.0-beta.19",
|
|
4
4
|
"description": "Check bookmark URLs or Canvas packages, compare sources with host-led research, and retain verifiable reports.",
|
|
5
5
|
"license": "GPL-3.0-only",
|
|
6
6
|
"repository": {
|
package/scripts/install.py
CHANGED
|
@@ -157,7 +157,9 @@ def _check_source(marketplace, requested):
|
|
|
157
157
|
elif current["sourceType"] == requested["sourceType"] == "git":
|
|
158
158
|
equal = _repository(current["source"]) == requested["source"]
|
|
159
159
|
elif current["sourceType"] == requested["sourceType"] == "npm":
|
|
160
|
-
equal = current == requested
|
|
160
|
+
equal = current["source"] == requested["source"] and (
|
|
161
|
+
current == requested or requested.get("ref") != "latest"
|
|
162
|
+
)
|
|
161
163
|
else:
|
|
162
164
|
equal = False
|
|
163
165
|
if not equal:
|
|
@@ -401,8 +403,9 @@ def manage(action, cli, source=None, ref=None, dry_run=False, installed_path=Non
|
|
|
401
403
|
# Native list JSON omits the registered ref. Equal commit IDs
|
|
402
404
|
# cannot distinguish a moving branch from an immutable tag.
|
|
403
405
|
raise ValueError("An existing Git marketplace retains its registered ref. Reinstall without --ref, or explicitly change the source in Codex first")
|
|
404
|
-
if origin:
|
|
405
|
-
requested
|
|
406
|
+
if origin and ref is None and requested["sourceType"] == "git":
|
|
407
|
+
if origin.get("sourceType") == "git" and requested["source"] == origin["source"] and origin.get("ref"):
|
|
408
|
+
requested["ref"] = origin["ref"]
|
|
406
409
|
else:
|
|
407
410
|
if not current or not _installed(cli):
|
|
408
411
|
raise ValueError("No existing bookmark-research installation; run install first")
|
package/src/onboarding.py
CHANGED
|
@@ -119,57 +119,72 @@ class Console(Prompter):
|
|
|
119
119
|
client = resolve_dsh(getattr(args, "dsh", None))
|
|
120
120
|
if client["source"] == "desktop":
|
|
121
121
|
args.dsh = client["binary"]
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
label + ":
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
122
|
+
while True:
|
|
123
|
+
if requested:
|
|
124
|
+
hosts = list(dict.fromkeys(requested))
|
|
125
|
+
else:
|
|
126
|
+
found = {name: bool(shutil.which(getattr(args, name, None) or name)) for name, _, _ in HOSTS}
|
|
127
|
+
hints = {name: ("", None) if found[name] else ("CLI not found", "未找到 CLI") for name in found}
|
|
128
|
+
found["dsh"], hints["dsh"] = client["usable"], _dsh_hint(client)
|
|
129
|
+
if not any(found.values()):
|
|
130
|
+
self.warn("No supported host CLI (codex, claude, dsh) was found on PATH.",
|
|
131
|
+
"PATH 中未找到任何受支持的宿主 CLI(codex、claude、dsh)。")
|
|
132
|
+
raise ValueError("No host CLI found; install Codex, Claude Code or DeepSeek Harness (dsh), "
|
|
133
|
+
"or pass --codex/--claude/--dsh PATH to point at its executable")
|
|
134
|
+
hosts = self.multiselect("Install into which hosts? (Space to toggle, Enter to confirm)",
|
|
135
|
+
"安装到哪些宿主?(空格 勾选/取消,回车 确认)", [
|
|
136
|
+
Option(name, en, zh, *hints[name], disabled=not found[name]) for name, en, zh in HOSTS],
|
|
137
|
+
[name for name, _, _ in HOSTS if found[name]])
|
|
138
|
+
# A carrier that ships its own pnpm is the Desktop CLI, however it was found:
|
|
139
|
+
# only that CLI may manage the profile name Desktop reserves for itself.
|
|
140
|
+
desktop = client["bundled_pnpm"] is not None
|
|
141
|
+
targets = []
|
|
142
|
+
go_back = False
|
|
143
|
+
for host in hosts:
|
|
144
|
+
label = next((en for name, en, _ in HOSTS if name == host), host)
|
|
145
|
+
target = {"host": host, "scope": None, "project": None, "profile": None}
|
|
146
|
+
if host == "claude":
|
|
147
|
+
scope = args.scope
|
|
148
|
+
if scope is None:
|
|
149
|
+
options = [Option("user", "This user", "当前用户"), Option("project", "This project", "指定项目"),
|
|
150
|
+
Option("local", "This project, only for me", "指定项目(仅自己)")]
|
|
151
|
+
if not requested:
|
|
152
|
+
options.append(Option("back", "← Back to host selection", "← 返回重新选择宿主"))
|
|
153
|
+
scope = self.select(label + ": installation scope", label + ":安装范围", options, "user")
|
|
154
|
+
if scope == "back":
|
|
155
|
+
go_back = True
|
|
156
|
+
break
|
|
157
|
+
target["scope"] = scope
|
|
158
|
+
if scope in ("project", "local"):
|
|
159
|
+
target["project"] = args.project or self.input(
|
|
160
|
+
label + ": project directory", label + ":项目目录", str(Path.cwd()), _directory_problem)
|
|
161
|
+
elif host == "dsh":
|
|
162
|
+
# Never guess a DSH profile: it selects a distinct composed runtime.
|
|
163
|
+
profile = args.profile or self.dsh_profile(desktop, allow_back=not requested)
|
|
164
|
+
if profile == "back":
|
|
165
|
+
go_back = True
|
|
166
|
+
break
|
|
167
|
+
target["profile"] = profile
|
|
168
|
+
targets.append(target)
|
|
169
|
+
if go_back:
|
|
170
|
+
continue
|
|
171
|
+
lines = []
|
|
172
|
+
for target in targets:
|
|
173
|
+
label = next((en for name, en, _ in HOSTS if name == target["host"]), target["host"])
|
|
174
|
+
detail = ", ".join(key + "=" + target[key] for key in ("scope", "project", "profile") if target[key])
|
|
175
|
+
lines.append((label + (": " + detail if detail else ""), label + (":" + detail if detail else "")))
|
|
176
|
+
self.note("Installation plan", "安装计划", lines)
|
|
177
|
+
if client["source"] == "desktop" and any(target["host"] == "dsh" for target in targets):
|
|
178
|
+
self.note("DeepSeek Harness (dsh) CLI", "DeepSeek Harness (dsh) CLI", [(client["binary"], client["binary"])])
|
|
179
|
+
if not self.confirm("Install now?", "现在安装?", True):
|
|
180
|
+
if not requested and self.confirm("Re-select hosts and options?", "重新选择宿主与选项?", True):
|
|
181
|
+
continue
|
|
182
|
+
raise KeyboardInterrupt
|
|
183
|
+
first = targets[0]
|
|
184
|
+
args.host, args.scope, args.project, args.profile = first["host"], first["scope"], first["project"], first["profile"]
|
|
185
|
+
return targets
|
|
186
|
+
|
|
187
|
+
def dsh_profile(self, desktop, allow_back=False):
|
|
173
188
|
"""Choose an initialized DSH profile, or name a new one.
|
|
174
189
|
|
|
175
190
|
`dsh plugin` initializes a profile on first use, so the profiles on disk
|
|
@@ -186,8 +201,12 @@ class Console(Prompter):
|
|
|
186
201
|
return self.input(question[0], question[1], "desktop" if desktop else "", check)
|
|
187
202
|
options = [Option(row["name"], row["name"], row["name"], *_profile_hint(row)) for row in rows]
|
|
188
203
|
options.append(Option("", "Another profile name…", "其他 profile 名称…"))
|
|
204
|
+
if allow_back:
|
|
205
|
+
options.append(Option("back", "← Back to host selection", "← 返回重新选择宿主"))
|
|
189
206
|
default = "desktop" if any(row["name"] == "desktop" for row in rows) else None
|
|
190
207
|
chosen = self.select("Install into which DeepSeek Harness (dsh) profile?", "安装到哪个 DeepSeek Harness (dsh) profile?", options, default)
|
|
208
|
+
if chosen == "back":
|
|
209
|
+
return "back"
|
|
191
210
|
if chosen:
|
|
192
211
|
return chosen
|
|
193
212
|
return self.input(question[0], question[1], "desktop" if desktop else "", check)
|
package/src/tui.py
CHANGED
|
@@ -449,8 +449,11 @@ class Prompter:
|
|
|
449
449
|
while True:
|
|
450
450
|
lines = self._render_list(question, options, cursor, chosen, True, message)
|
|
451
451
|
if not message:
|
|
452
|
-
|
|
453
|
-
"
|
|
452
|
+
shortcut_hint = self.text(
|
|
453
|
+
"[Space] toggle [a] all/none [Enter] confirm",
|
|
454
|
+
"[空格] 勾选/取消 [a] 全选/全不选 [回车] 确认",
|
|
455
|
+
)
|
|
456
|
+
lines[-1] = "%s %s" % (self._color("36", "└"), self._color("36", shortcut_hint))
|
|
454
457
|
drawn = self._redraw(lines, drawn)
|
|
455
458
|
key = self._key()
|
|
456
459
|
message = None
|