deepseek-tui 0.8.8 → 0.8.10

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "deepseek-tui",
3
- "version": "0.8.8",
4
- "deepseekBinaryVersion": "0.8.8",
3
+ "version": "0.8.10",
4
+ "deepseekBinaryVersion": "0.8.10",
5
5
  "description": "Install and run deepseek and deepseek-tui binaries from GitHub release artifacts.",
6
6
  "author": "Hmbown",
7
7
  "license": "MIT",
@@ -13,6 +13,7 @@ const {
13
13
  releaseAssetUrl,
14
14
  releaseBinaryDirectory,
15
15
  } = require("./artifacts");
16
+ const { preflightGlibc } = require("./preflight-glibc");
16
17
  const pkg = require("../package.json");
17
18
 
18
19
  function resolvePackageVersion() {
@@ -154,6 +155,7 @@ async function ensureBinary(targetPath, assetName, version, repo, getChecksums)
154
155
  await download(url, destination);
155
156
  try {
156
157
  await verifyChecksum(destination, assetName, checksums);
158
+ preflightGlibc(destination);
157
159
  } catch (error) {
158
160
  await unlink(destination).catch(() => {});
159
161
  throw error;
@@ -0,0 +1,135 @@
1
+ const fs = require("fs");
2
+ const { execFileSync } = require("child_process");
3
+
4
+ const GLIBC_VERSION_RE = /GLIBC_(\d+)\.(\d+)(?:\.(\d+))?/g;
5
+
6
+ function isLinux() {
7
+ return process.platform === "linux";
8
+ }
9
+
10
+ function parseVersion(text) {
11
+ const match = String(text || "").match(/(\d+)\.(\d+)(?:\.(\d+))?/);
12
+ if (!match) return null;
13
+ return [Number(match[1]), Number(match[2]), Number(match[3] || 0)];
14
+ }
15
+
16
+ function compareVersion(a, b) {
17
+ for (let i = 0; i < 3; i += 1) {
18
+ if (a[i] !== b[i]) return a[i] - b[i];
19
+ }
20
+ return 0;
21
+ }
22
+
23
+ function formatVersion(version) {
24
+ return version[2] ? `${version[0]}.${version[1]}.${version[2]}` : `${version[0]}.${version[1]}`;
25
+ }
26
+
27
+ function detectHostGlibc() {
28
+ try {
29
+ const out = execFileSync("getconf", ["GNU_LIBC_VERSION"], {
30
+ encoding: "utf8",
31
+ stdio: ["ignore", "pipe", "ignore"],
32
+ });
33
+ const version = parseVersion(out);
34
+ if (version) return version;
35
+ } catch {
36
+ // fall through to ldd
37
+ }
38
+ try {
39
+ const out = execFileSync("ldd", ["--version"], {
40
+ encoding: "utf8",
41
+ stdio: ["ignore", "pipe", "ignore"],
42
+ });
43
+ const firstLine = out.split("\n", 1)[0];
44
+ const version = parseVersion(firstLine);
45
+ if (version) return version;
46
+ } catch {
47
+ // glibc not present (e.g. musl / Alpine)
48
+ }
49
+ return null;
50
+ }
51
+
52
+ function detectBinaryRequiredGlibc(filePath) {
53
+ const buf = fs.readFileSync(filePath);
54
+ const text = buf.toString("latin1");
55
+ let highest = null;
56
+ GLIBC_VERSION_RE.lastIndex = 0;
57
+ let match;
58
+ while ((match = GLIBC_VERSION_RE.exec(text)) !== null) {
59
+ const version = [Number(match[1]), Number(match[2]), Number(match[3] || 0)];
60
+ if (!highest || compareVersion(version, highest) > 0) {
61
+ highest = version;
62
+ }
63
+ }
64
+ return highest;
65
+ }
66
+
67
+ function buildFromSourceHint() {
68
+ return [
69
+ "You can still run DeepSeek TUI by building from source with Cargo:",
70
+ "",
71
+ " # Requires Rust 1.85+ (https://rustup.rs)",
72
+ " cargo install deepseek-tui-cli --locked # provides `deepseek`",
73
+ " cargo install deepseek-tui --locked # provides `deepseek-tui`",
74
+ "",
75
+ "Or build from a checkout:",
76
+ "",
77
+ " git clone https://github.com/Hmbown/DeepSeek-TUI.git",
78
+ " cd DeepSeek-TUI",
79
+ " cargo install --path crates/cli --locked",
80
+ " cargo install --path crates/tui --locked",
81
+ "",
82
+ "See https://github.com/Hmbown/DeepSeek-TUI/blob/main/docs/INSTALL.md",
83
+ ].join("\n");
84
+ }
85
+
86
+ function preflightGlibc(filePath) {
87
+ if (!isLinux()) return;
88
+ if (
89
+ process.env.DEEPSEEK_TUI_SKIP_GLIBC_CHECK === "1" ||
90
+ process.env.DEEPSEEK_SKIP_GLIBC_CHECK === "1"
91
+ ) {
92
+ return;
93
+ }
94
+
95
+ const required = detectBinaryRequiredGlibc(filePath);
96
+ if (!required) {
97
+ // Statically linked / musl binary, or no GLIBC_* version dependencies present.
98
+ return;
99
+ }
100
+
101
+ const host = detectHostGlibc();
102
+ if (!host) {
103
+ throw new Error(
104
+ [
105
+ `The prebuilt binary requires GLIBC_${formatVersion(required)}, but no GNU libc was detected on this host.`,
106
+ "This usually means you're on a musl-based distro such as Alpine.",
107
+ "",
108
+ buildFromSourceHint(),
109
+ "",
110
+ "Set DEEPSEEK_TUI_SKIP_GLIBC_CHECK=1 to bypass this check at your own risk.",
111
+ ].join("\n"),
112
+ );
113
+ }
114
+
115
+ if (compareVersion(host, required) < 0) {
116
+ throw new Error(
117
+ [
118
+ `Prebuilt DeepSeek TUI binary requires GLIBC_${formatVersion(required)} but this system has glibc ${formatVersion(host)}.`,
119
+ "Older distros (CentOS 7/8, RHEL 7/8, Debian 10, etc.) ship an older glibc that is not compatible with the prebuilt artifact.",
120
+ "",
121
+ buildFromSourceHint(),
122
+ "",
123
+ "Set DEEPSEEK_TUI_SKIP_GLIBC_CHECK=1 to bypass this check at your own risk.",
124
+ ].join("\n"),
125
+ );
126
+ }
127
+ }
128
+
129
+ module.exports = {
130
+ preflightGlibc,
131
+ detectHostGlibc,
132
+ detectBinaryRequiredGlibc,
133
+ // exported for tests
134
+ _internal: { parseVersion, compareVersion, formatVersion },
135
+ };