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 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.15",
4
- "deepseekBinaryVersion": "0.8.15",
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
  ]
@@ -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 = opts.totalTimeoutMs ?? downloadTimeoutMs();
359
- const stallMs = opts.stallMs ?? downloadStallMs();
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
- const args = process.argv.slice(2);
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
+ });
@@ -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
+ });