@dptech-corp/bohr-cli 2.6.28 → 2.6.31

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 CHANGED
@@ -15,6 +15,32 @@
15
15
 
16
16
  ## [Unreleased]
17
17
 
18
+ ## [2.6.31] - 2026-08-18
19
+
20
+ ### Added
21
+
22
+ - **Vouch 登录支持双 audience(wenyon-svc + trisol-svc)**:device flow 和 token refresh 均请求双 audience,一次登录 wenyon 和 trisol 都可验签。存量单 audience 会话不受影响,升级后重新登录即可获得双 aud token。`BOHR_VOUCH_AUDIENCE` 支持逗号分隔覆盖。
23
+
24
+ ### Fixed
25
+
26
+ - **`bohr file download` 现在输出信封,进度提示不再污染 stdout**:此前该命令无论成功或失败都只打印纯文本,`-o json` 也一样,机读调用方连成功都无法解析;进度行 `Downloading ... to ...` 还固定打在 stdout。现在成功返回含 `remote_path`、`dest_path`、`space`、`project_id`、`size` 的信封,上游非 2xx 返回携带上游 HTTP 状态的错误信封,进度提示仅在 human 输出下打到 stderr。上游状态原样透传,不在 CLI 侧把 400 改写成 not-found。
27
+ - **`bohr job delete` 与 `bohr kb document list` 的失败路径补出信封**:此前二者失败时 stdout 为空,错误只以自由文本出现在 stderr,机读调用方拿不到可判别的 `error.code`。现在 `job delete` 在非 human 输出下透出上游失败信封(上游错误码原样保留),`kb document list` 对不存在的知识库返回 `RESOURCE_NOT_FOUND`、`http=404`、退出码 3 并给出 `bohr kb list` 指引。`job delete` 同一错误此前会重复输出两次,现已消除。
28
+ - **`bohr project get` 传不存在的项目 ID 不再报成功**:该命令由项目列表接口按 ID 过滤实现,此前查不到项目时会返回 `ok:true` 与退出码 0,只是 `data.items` 为空,调用方无法用退出码或 `ok` 区分「项目不存在」与「查到了」。现在返回 `error.code=RESOURCE_NOT_FOUND`、`error.http=404`、退出码 3,与 `file stat`、`sandbox get`、`batchjob describe` 等命令的 not-found 形态一致,并给出 `bohr project list` 的指引。项目存在时的返回结构不变。
29
+
30
+ ## [2.6.30] - 2026-08-18
31
+
32
+ ### Added
33
+
34
+ - **npm postinstall 自动下载 trisol 外部版**:`npm install -g @dptech-corp/bohr-cli` 后自动拉取 `?variant=bohrium` 的 trisol(与 wenyon 一致),无需手动 `bohr extension install trisol`;用 `BOHR_TRISOL_SERVER` / `BOHR_TRISOL_CHANNEL` 可指向非 prod 环境。
35
+ - **`bohr trisol` 支持 `BOHR_TRISOL_API_URL` 指定 trisol 环境**:dev 构建设 `BOHR_TRISOL_API_URL=https://trisol-dev.dp.tech` 即连 dev;不设则用 trisol CLI 自身配置(prod 默认)。显式可逆,不焊死安装环境——迁移 prod 只需取消该变量。
36
+ - **`bohr lkm parse` 异步 PDF 知识抽取**:支持 submit / query / result 子命令,通过 open-platform 调用 LKM 的论文解析服务。
37
+
38
+ ## [2.6.29] - 2026-08-18
39
+
40
+ ### Breaking
41
+
42
+ - **`bohr tools install` 移至 `bohr extension install`**:安装 trisol/wenyon 等配套扩展 CLI 的命令归入扩展管理命令组(与 `extension add/list/info/remove/pin/verify` 并列),`bohr tools` 回归纯科学工具发现(list/search/info/domains/subdomains)。此前 `bohr tools install <tool>` 的调用请改为 `bohr extension install <tool>`,参数与行为不变(`--dry-run`/`--silent`/`--server`/`--channel` 及 `BOHR_TOOLS_SERVER` 环境变量照旧)。
43
+
18
44
  ## [2.6.28] - 2026-08-18
19
45
 
20
46
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dptech-corp/bohr-cli",
3
- "version": "2.6.28",
3
+ "version": "2.6.31",
4
4
  "description": "CLI tool for Bohrium scientific computing platform",
5
5
  "bin": {
6
6
  "bohr": "run.js"
@@ -32,11 +32,11 @@
32
32
  "CHANGELOG.md"
33
33
  ],
34
34
  "optionalDependencies": {
35
- "@dptech-corp/bohr-cli-darwin-arm64": "2.6.28",
36
- "@dptech-corp/bohr-cli-darwin-amd64": "2.6.28",
37
- "@dptech-corp/bohr-cli-linux-amd64": "2.6.28",
38
- "@dptech-corp/bohr-cli-linux-arm64": "2.6.28",
39
- "@dptech-corp/bohr-cli-windows-amd64": "2.6.28",
40
- "@dptech-corp/bohr-cli-windows-arm64": "2.6.28"
35
+ "@dptech-corp/bohr-cli-darwin-arm64": "2.6.31",
36
+ "@dptech-corp/bohr-cli-darwin-amd64": "2.6.31",
37
+ "@dptech-corp/bohr-cli-linux-amd64": "2.6.31",
38
+ "@dptech-corp/bohr-cli-linux-arm64": "2.6.31",
39
+ "@dptech-corp/bohr-cli-windows-amd64": "2.6.31",
40
+ "@dptech-corp/bohr-cli-windows-arm64": "2.6.31"
41
41
  }
42
42
  }
package/postinstall.js CHANGED
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * postinstall: downloads wenyon-cli (external) for the current platform.
3
+ * postinstall: downloads wenyon-cli and the trisol external edition
4
+ * (variant=bohrium) for the current platform.
4
5
  * Runs after `npm install -g @dptech-corp/bohr-cli`.
5
- * Failure is non-fatal — bohr-cli works without wenyon, and `bohr tools install wenyon`
6
+ * Failure is non-fatal — bohr-cli works without them, and `bohr extension install <tool>`
6
7
  * can retry later.
7
8
  */
8
9
  const https = require("https");
@@ -15,6 +16,12 @@ const crypto = require("crypto");
15
16
  const WENYON_SERVER = "https://wenyon.dp.tech";
16
17
  const INSTALL_DIR = path.join(os.homedir(), ".bohr", "tools", "wenyon", "current");
17
18
 
19
+ // trisol is installed from the trisol manifest protocol (trisol-manifest).
20
+ // BOHR_TRISOL_SERVER / BOHR_TRISOL_CHANNEL let a dev build point at a non-prod
21
+ // env (e.g. https://trisol-dev.dp.tech + channel dev).
22
+ const TRISOL_SERVER = process.env.BOHR_TRISOL_SERVER || "https://trisol.dp.tech";
23
+ const TRISOL_INSTALL_DIR = path.join(os.homedir(), ".bohr", "tools", "trisol", "current");
24
+
18
25
  function getPlatform() {
19
26
  const p = os.platform();
20
27
  const a = os.arch();
@@ -76,12 +83,83 @@ function downloadToFile(url, dest, timeoutMs = 300000) {
76
83
  });
77
84
  }
78
85
 
79
- async function main() {
86
+ // installTrisol downloads the trisol external edition (variant=bohrium) via
87
+ // the trisol manifest protocol: fetch manifest → pick channel → download
88
+ // binary + sha256 sidecar → verify → install to ~/.bohr/tools/trisol/current.
89
+ async function installTrisol() {
80
90
  const platform = getPlatform();
81
- if (!platform) {
82
- // Unsupported platform for wenyon — skip silently
91
+ if (!platform) return;
92
+ const [osName, archName] = platform.split("-");
93
+
94
+ let manifest;
95
+ try {
96
+ const buf = await get(`${TRISOL_SERVER}/api/v1/cli/manifest`);
97
+ manifest = JSON.parse(buf.toString());
98
+ } catch (e) {
99
+ console.error(`[postinstall] trisol: could not fetch manifest (${e.message}), skipping`);
83
100
  return;
84
101
  }
102
+ const channel = process.env.BOHR_TRISOL_CHANNEL || manifest.default_channel || "stable";
103
+ const ch = (manifest.channels || {})[channel];
104
+ const version = ch && ch.version;
105
+ if (!version) {
106
+ console.error(`[postinstall] trisol: channel "${channel}" has no version, skipping`);
107
+ return;
108
+ }
109
+
110
+ const base = `${TRISOL_SERVER}/api/v1/cli/download/${version}/${osName}/${archName}`;
111
+ const binaryURL = `${base}?variant=bohrium`;
112
+ const shaURL = `${base}.sha256?variant=bohrium`;
113
+ const ext = osName === "windows" ? ".exe" : "";
114
+ const destPath = path.join(TRISOL_INSTALL_DIR, `trisol${ext}`);
115
+
116
+ // Skip re-download when the installed binary already matches this version.
117
+ if (fs.existsSync(destPath)) {
118
+ try {
119
+ const { execFileSync } = require("child_process");
120
+ const out = execFileSync(destPath, ["version"], { encoding: "utf8", timeout: 5000 });
121
+ if (out.includes(version)) {
122
+ console.log(`[postinstall] trisol ${version} already installed`);
123
+ return;
124
+ }
125
+ } catch (_) {
126
+ // version check failed, proceed with install
127
+ }
128
+ }
129
+
130
+ let expectedHash;
131
+ try {
132
+ const buf = await get(shaURL);
133
+ expectedHash = buf.toString().trim().split(/\s+/)[0];
134
+ } catch (e) {
135
+ console.error(`[postinstall] trisol: could not fetch sha256 (${e.message}), skipping`);
136
+ return;
137
+ }
138
+
139
+ console.log(`[postinstall] Installing trisol ${version} (${platform}, variant=bohrium)...`);
140
+ fs.mkdirSync(TRISOL_INSTALL_DIR, { recursive: true });
141
+ const tmpPath = destPath + ".tmp";
142
+ try {
143
+ const actualHash = await downloadToFile(binaryURL, tmpPath);
144
+ if (expectedHash && actualHash !== expectedHash) {
145
+ fs.unlinkSync(tmpPath);
146
+ console.error(`[postinstall] trisol: SHA256 mismatch (expected ${expectedHash}, got ${actualHash}), skipping`);
147
+ return;
148
+ }
149
+ fs.chmodSync(tmpPath, 0o755);
150
+ fs.renameSync(tmpPath, destPath);
151
+ console.log(`[postinstall] trisol ${version} installed to ${destPath}`);
152
+ } catch (e) {
153
+ try { fs.unlinkSync(tmpPath); } catch (_) {}
154
+ console.error(`[postinstall] trisol: download failed (${e.message}), skipping`);
155
+ }
156
+ }
157
+
158
+ async function main() {
159
+ const platform = getPlatform();
160
+ if (platform) {
161
+ await installTrisol();
162
+ }
85
163
 
86
164
  const metaUrl = `${WENYON_SERVER}/cli/releases/latest/download?platform=${platform}&variant=external`;
87
165