deepseek-tui 0.8.15 → 0.8.17
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/README.md +3 -2
- package/package.json +5 -3
- package/scripts/install.js +70 -2
- package/scripts/run.js +3 -3
- package/test/install.test.js +71 -0
- package/test/run.test.js +11 -0
package/README.md
CHANGED
|
@@ -70,6 +70,9 @@ build-from-source guide.
|
|
|
70
70
|
- Default binary version comes from `deepseekBinaryVersion` in `package.json`.
|
|
71
71
|
- Set `DEEPSEEK_TUI_VERSION` or `DEEPSEEK_VERSION` to override the release version.
|
|
72
72
|
- Set `DEEPSEEK_TUI_GITHUB_REPO` or `DEEPSEEK_GITHUB_REPO` to override the source repo (defaults to `Hmbown/DeepSeek-TUI`).
|
|
73
|
+
- Set `DEEPSEEK_TUI_RELEASE_BASE_URL` to use an internal or mirrored
|
|
74
|
+
release-asset directory when GitHub Releases is unavailable. The directory
|
|
75
|
+
must contain `deepseek-artifacts-sha256.txt` and the platform binaries.
|
|
73
76
|
- Set `DEEPSEEK_TUI_FORCE_DOWNLOAD=1` to force download even when the cached binary is already present.
|
|
74
77
|
- Set `DEEPSEEK_TUI_DISABLE_INSTALL=1` to skip install-time download.
|
|
75
78
|
- Set `DEEPSEEK_TUI_OPTIONAL_INSTALL=1` to make the `postinstall` step warn and exit `0` on download/extract errors instead of failing `npm install` (useful in CI matrices).
|
|
@@ -80,5 +83,3 @@ build-from-source guide.
|
|
|
80
83
|
exist for the target GitHub release before publishing.
|
|
81
84
|
- Install-time downloads are verified against the release checksum manifest before
|
|
82
85
|
the wrapper marks them executable.
|
|
83
|
-
- Set `DEEPSEEK_TUI_RELEASE_BASE_URL` to point the installer at a local or
|
|
84
|
-
staged release-asset directory for smoke tests.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deepseek-tui",
|
|
3
|
-
"version": "0.8.
|
|
4
|
-
"deepseekBinaryVersion": "0.8.
|
|
3
|
+
"version": "0.8.17",
|
|
4
|
+
"deepseekBinaryVersion": "0.8.17",
|
|
5
5
|
"description": "Install and run deepseek and deepseek-tui binaries from GitHub release artifacts.",
|
|
6
6
|
"author": "Hmbown",
|
|
7
7
|
"license": "MIT",
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
"release:check": "node scripts/verify-release-assets.js",
|
|
31
31
|
"postinstall": "node scripts/install.js",
|
|
32
32
|
"prepublishOnly": "node scripts/verify-release-assets.js",
|
|
33
|
-
"prepack": "node scripts/install.js"
|
|
33
|
+
"prepack": "node scripts/install.js",
|
|
34
|
+
"test": "node --test test/*.test.js"
|
|
34
35
|
},
|
|
35
36
|
"engines": {
|
|
36
37
|
"node": ">=18"
|
|
@@ -42,6 +43,7 @@
|
|
|
42
43
|
"files": [
|
|
43
44
|
"bin/*.js",
|
|
44
45
|
"scripts/*.js",
|
|
46
|
+
"test/*.js",
|
|
45
47
|
"README.md",
|
|
46
48
|
"package.json"
|
|
47
49
|
]
|
package/scripts/install.js
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
function assertSupportedNode() {
|
|
2
|
+
const version = process.versions && process.versions.node ? process.versions.node : "unknown";
|
|
3
|
+
const major = Number.parseInt(String(version).split(".")[0], 10);
|
|
4
|
+
if (Number.isNaN(major) || major < 18) {
|
|
5
|
+
process.stderr.write(
|
|
6
|
+
"deepseek-tui: Node.js 18 or newer is required for npm installation. " +
|
|
7
|
+
`Current Node.js version is ${version}. ` +
|
|
8
|
+
"Please upgrade Node.js and rerun `npm install -g deepseek-tui`.\n",
|
|
9
|
+
);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
assertSupportedNode();
|
|
15
|
+
|
|
1
16
|
const fs = require("fs");
|
|
2
17
|
const https = require("https");
|
|
3
18
|
const http = require("http");
|
|
@@ -105,6 +120,48 @@ function logInfo(message) {
|
|
|
105
120
|
process.stderr.write(`deepseek-tui: ${message}\n`);
|
|
106
121
|
}
|
|
107
122
|
|
|
123
|
+
function installFailureHint(error) {
|
|
124
|
+
const message = error && error.message ? String(error.message) : "";
|
|
125
|
+
const code = error && error.code ? String(error.code) : "";
|
|
126
|
+
const releaseBase =
|
|
127
|
+
process.env.DEEPSEEK_TUI_RELEASE_BASE_URL ||
|
|
128
|
+
process.env.DEEPSEEK_RELEASE_BASE_URL;
|
|
129
|
+
const networkMarkers = [
|
|
130
|
+
"github.com",
|
|
131
|
+
"ENOTFOUND",
|
|
132
|
+
"EAI_AGAIN",
|
|
133
|
+
"ETIMEDOUT",
|
|
134
|
+
"ECONNRESET",
|
|
135
|
+
"ENETUNREACH",
|
|
136
|
+
"EHOSTUNREACH",
|
|
137
|
+
"EDOWNLOADTIMEOUT",
|
|
138
|
+
];
|
|
139
|
+
const looksLikeNetworkDownloadFailure = networkMarkers.some(
|
|
140
|
+
(marker) => message.includes(marker) || code === marker,
|
|
141
|
+
);
|
|
142
|
+
if (!looksLikeNetworkDownloadFailure) {
|
|
143
|
+
return "";
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (releaseBase) {
|
|
147
|
+
return [
|
|
148
|
+
"deepseek-tui install hint:",
|
|
149
|
+
` DEEPSEEK_TUI_RELEASE_BASE_URL is set to ${releaseBase}`,
|
|
150
|
+
" Verify that this directory contains deepseek-artifacts-sha256.txt",
|
|
151
|
+
" plus the deepseek/deepseek-tui binary assets for your platform.",
|
|
152
|
+
].join("\n");
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return [
|
|
156
|
+
"deepseek-tui install hint:",
|
|
157
|
+
" The npm package downloads prebuilt binaries from GitHub Releases.",
|
|
158
|
+
" If GitHub is unavailable on this network, mirror the release assets and set:",
|
|
159
|
+
" DEEPSEEK_TUI_RELEASE_BASE_URL=https://<mirror>/<release-asset-directory>/",
|
|
160
|
+
" The directory must contain deepseek-artifacts-sha256.txt and the platform binaries.",
|
|
161
|
+
" See docs/INSTALL.md#npm-download-is-slow-or-times-out-from-mainland-china.",
|
|
162
|
+
].join("\n");
|
|
163
|
+
}
|
|
164
|
+
|
|
108
165
|
function envInt(name, fallback) {
|
|
109
166
|
const raw = process.env[name];
|
|
110
167
|
if (!raw) {
|
|
@@ -355,8 +412,14 @@ function connectThroughProxy(proxy, targetHost, targetPort, timeoutMs) {
|
|
|
355
412
|
// ────────────────────────────────────────────────────────────────────────────
|
|
356
413
|
|
|
357
414
|
function httpRequest(rawUrl, opts = {}) {
|
|
358
|
-
const totalTimeoutMs =
|
|
359
|
-
|
|
415
|
+
const totalTimeoutMs =
|
|
416
|
+
opts.totalTimeoutMs === undefined || opts.totalTimeoutMs === null
|
|
417
|
+
? downloadTimeoutMs()
|
|
418
|
+
: opts.totalTimeoutMs;
|
|
419
|
+
const stallMs =
|
|
420
|
+
opts.stallMs === undefined || opts.stallMs === null
|
|
421
|
+
? downloadStallMs()
|
|
422
|
+
: opts.stallMs;
|
|
360
423
|
|
|
361
424
|
return new Promise((resolve, reject) => {
|
|
362
425
|
let url;
|
|
@@ -924,12 +987,17 @@ async function getBinaryPath(name) {
|
|
|
924
987
|
|
|
925
988
|
module.exports = {
|
|
926
989
|
getBinaryPath,
|
|
990
|
+
installFailureHint,
|
|
927
991
|
run,
|
|
928
992
|
};
|
|
929
993
|
|
|
930
994
|
if (require.main === module) {
|
|
931
995
|
run().catch((error) => {
|
|
932
996
|
console.error("deepseek-tui install failed:", error.message);
|
|
997
|
+
const hint = installFailureHint(error);
|
|
998
|
+
if (hint) {
|
|
999
|
+
console.error(hint);
|
|
1000
|
+
}
|
|
933
1001
|
if (process.env.DEEPSEEK_TUI_OPTIONAL_INSTALL === "1") {
|
|
934
1002
|
console.error(
|
|
935
1003
|
"DEEPSEEK_TUI_OPTIONAL_INSTALL=1 set; continuing without a usable binary.",
|
package/scripts/run.js
CHANGED
|
@@ -3,9 +3,8 @@ const { getBinaryPath } = require("./install");
|
|
|
3
3
|
|
|
4
4
|
const pkg = require("../package.json");
|
|
5
5
|
|
|
6
|
-
function isVersionFlag() {
|
|
7
|
-
|
|
8
|
-
return args.includes("--version") || args.includes("-v") || args.includes("-V");
|
|
6
|
+
function isVersionFlag(args = process.argv.slice(2)) {
|
|
7
|
+
return args.includes("--version") || args.includes("-V");
|
|
9
8
|
}
|
|
10
9
|
|
|
11
10
|
function handleVersionFallback(binaryName) {
|
|
@@ -46,6 +45,7 @@ module.exports = {
|
|
|
46
45
|
run,
|
|
47
46
|
runDeepseek,
|
|
48
47
|
runDeepseekTui,
|
|
48
|
+
_internal: { isVersionFlag },
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
if (require.main === module) {
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const assert = require("node:assert/strict");
|
|
2
|
+
const fs = require("node:fs");
|
|
3
|
+
const path = require("node:path");
|
|
4
|
+
const test = require("node:test");
|
|
5
|
+
|
|
6
|
+
const installScript = fs.readFileSync(
|
|
7
|
+
path.join(__dirname, "..", "scripts", "install.js"),
|
|
8
|
+
"utf8",
|
|
9
|
+
);
|
|
10
|
+
const { installFailureHint } = require("../scripts/install");
|
|
11
|
+
|
|
12
|
+
test("install script checks Node support before loading helpers", () => {
|
|
13
|
+
const guardIndex = installScript.indexOf("assertSupportedNode();");
|
|
14
|
+
const firstRequireIndex = installScript.indexOf("require(");
|
|
15
|
+
|
|
16
|
+
assert.notEqual(guardIndex, -1);
|
|
17
|
+
assert.notEqual(firstRequireIndex, -1);
|
|
18
|
+
assert.ok(guardIndex < firstRequireIndex);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("install script remains parseable before the Node support guard runs", () => {
|
|
22
|
+
assert.equal(installScript.includes("??"), false);
|
|
23
|
+
assert.equal(installScript.includes("?."), false);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test("install failure hint explains release base override for blocked GitHub downloads", () => {
|
|
27
|
+
const previous = process.env.DEEPSEEK_TUI_RELEASE_BASE_URL;
|
|
28
|
+
delete process.env.DEEPSEEK_TUI_RELEASE_BASE_URL;
|
|
29
|
+
try {
|
|
30
|
+
const error = Object.assign(
|
|
31
|
+
new Error(
|
|
32
|
+
"fetch https://github.com/Hmbown/DeepSeek-TUI/releases/download/v0.8.17/deepseek-artifacts-sha256.txt failed after 5 attempts:\ngetaddrinfo ENOTFOUND github.com",
|
|
33
|
+
),
|
|
34
|
+
{ code: "ENOTFOUND" },
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const hint = installFailureHint(error);
|
|
38
|
+
|
|
39
|
+
assert.match(hint, /DEEPSEEK_TUI_RELEASE_BASE_URL/);
|
|
40
|
+
assert.match(hint, /deepseek-artifacts-sha256\.txt/);
|
|
41
|
+
assert.match(hint, /platform binaries/);
|
|
42
|
+
} finally {
|
|
43
|
+
if (previous === undefined) {
|
|
44
|
+
delete process.env.DEEPSEEK_TUI_RELEASE_BASE_URL;
|
|
45
|
+
} else {
|
|
46
|
+
process.env.DEEPSEEK_TUI_RELEASE_BASE_URL = previous;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("install failure hint checks configured release base when override is already set", () => {
|
|
52
|
+
const previous = process.env.DEEPSEEK_TUI_RELEASE_BASE_URL;
|
|
53
|
+
process.env.DEEPSEEK_TUI_RELEASE_BASE_URL = "https://mirror.example/deepseek/";
|
|
54
|
+
try {
|
|
55
|
+
const error = Object.assign(new Error("download stalled"), {
|
|
56
|
+
code: "EDOWNLOADTIMEOUT",
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const hint = installFailureHint(error);
|
|
60
|
+
|
|
61
|
+
assert.match(hint, /is set to https:\/\/mirror\.example\/deepseek\//);
|
|
62
|
+
assert.match(hint, /deepseek-artifacts-sha256\.txt/);
|
|
63
|
+
assert.doesNotMatch(hint, /If GitHub is unavailable/);
|
|
64
|
+
} finally {
|
|
65
|
+
if (previous === undefined) {
|
|
66
|
+
delete process.env.DEEPSEEK_TUI_RELEASE_BASE_URL;
|
|
67
|
+
} else {
|
|
68
|
+
process.env.DEEPSEEK_TUI_RELEASE_BASE_URL = previous;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
});
|
package/test/run.test.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const assert = require("node:assert/strict");
|
|
2
|
+
const test = require("node:test");
|
|
3
|
+
|
|
4
|
+
const { _internal } = require("../scripts/run");
|
|
5
|
+
|
|
6
|
+
test("version fallback handles only version flags", () => {
|
|
7
|
+
assert.equal(_internal.isVersionFlag(["--version"]), true);
|
|
8
|
+
assert.equal(_internal.isVersionFlag(["-V"]), true);
|
|
9
|
+
assert.equal(_internal.isVersionFlag(["-v"]), false);
|
|
10
|
+
assert.equal(_internal.isVersionFlag(["--verbose"]), false);
|
|
11
|
+
});
|