deepseek-tui 0.3.28
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 +31 -0
- package/bin/deepseek-tui.js +8 -0
- package/bin/deepseek.js +8 -0
- package/package.json +42 -0
- package/scripts/artifacts.js +53 -0
- package/scripts/install.js +142 -0
- package/scripts/run.js +36 -0
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# deepseek-tui
|
|
2
|
+
|
|
3
|
+
This package installs the `deepseek` and `deepseek-tui` binaries from the
|
|
4
|
+
`DeepSeek-TUI` GitHub release artifacts and exposes them as Node-compatible
|
|
5
|
+
console entry points.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install deepseek-tui
|
|
11
|
+
# or
|
|
12
|
+
pnpm add deepseek-tui
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
This runs `postinstall`, downloads the platform-specific binaries for version
|
|
16
|
+
`0.3.28`, and makes `deepseek` and `deepseek-tui` available on your PATH.
|
|
17
|
+
|
|
18
|
+
## Supported platforms
|
|
19
|
+
|
|
20
|
+
- Linux x64
|
|
21
|
+
- macOS x64 / arm64
|
|
22
|
+
- Windows x64
|
|
23
|
+
|
|
24
|
+
## Notes
|
|
25
|
+
|
|
26
|
+
- Binaries come directly from release assets in
|
|
27
|
+
`https://github.com/Hmbown/DeepSeek-TUI/releases`.
|
|
28
|
+
- Set `DEEPSEEK_VERSION` to install a different release version (defaults to package version).
|
|
29
|
+
- Set `DEEPSEEK_GITHUB_REPO` to override the repo source (defaults to `Hmbown/DeepSeek-TUI`).
|
|
30
|
+
- Set `DEEPSEEK_TUI_FORCE_DOWNLOAD=1` to force download even when the cached binary is already present.
|
|
31
|
+
- Set `DEEPSEEK_TUI_DISABLE_INSTALL=1` to skip install-time download.
|
package/bin/deepseek.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "deepseek-tui",
|
|
3
|
+
"version": "0.3.28",
|
|
4
|
+
"description": "Install and run deepseek and deepseek-tui binaries from GitHub release artifacts.",
|
|
5
|
+
"author": "Hmbown",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://github.com/Hmbown/DeepSeek-TUI",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/Hmbown/DeepSeek-TUI.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/Hmbown/DeepSeek-TUI/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"deepseek",
|
|
17
|
+
"cli",
|
|
18
|
+
"tui",
|
|
19
|
+
"rust",
|
|
20
|
+
"binary",
|
|
21
|
+
"terminal"
|
|
22
|
+
],
|
|
23
|
+
"type": "commonjs",
|
|
24
|
+
"bin": {
|
|
25
|
+
"deepseek": "bin/deepseek.js",
|
|
26
|
+
"deepseek-tui": "bin/deepseek-tui.js"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"postinstall": "node scripts/install.js",
|
|
30
|
+
"prepack": "node scripts/install.js"
|
|
31
|
+
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18"
|
|
34
|
+
},
|
|
35
|
+
"preferGlobal": true,
|
|
36
|
+
"files": [
|
|
37
|
+
"bin/*.js",
|
|
38
|
+
"scripts/*.js",
|
|
39
|
+
"README.md",
|
|
40
|
+
"package.json"
|
|
41
|
+
]
|
|
42
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const os = require("os");
|
|
3
|
+
|
|
4
|
+
const ASSET_MATRIX = {
|
|
5
|
+
linux: {
|
|
6
|
+
x64: ["deepseek-linux-x64", "deepseek-tui-linux-x64"],
|
|
7
|
+
default: ["deepseek-linux-x64", "deepseek-tui-linux-x64"],
|
|
8
|
+
},
|
|
9
|
+
darwin: {
|
|
10
|
+
x64: ["deepseek-macos-x64", "deepseek-tui-macos-x64"],
|
|
11
|
+
arm64: ["deepseek-macos-arm64", "deepseek-tui-macos-arm64"],
|
|
12
|
+
default: ["deepseek-macos-x64", "deepseek-tui-macos-x64"],
|
|
13
|
+
},
|
|
14
|
+
win32: {
|
|
15
|
+
x64: ["deepseek-windows-x64.exe", "deepseek-tui-windows-x64.exe"],
|
|
16
|
+
default: ["deepseek-windows-x64.exe", "deepseek-tui-windows-x64.exe"],
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
function detectBinaryNames() {
|
|
21
|
+
const platform = os.platform();
|
|
22
|
+
const arch = os.arch();
|
|
23
|
+
const defaults = ASSET_MATRIX[platform];
|
|
24
|
+
if (!defaults) {
|
|
25
|
+
throw new Error(`Unsupported platform: ${platform}`);
|
|
26
|
+
}
|
|
27
|
+
const pair = defaults[arch] || defaults.default;
|
|
28
|
+
return {
|
|
29
|
+
platform,
|
|
30
|
+
arch,
|
|
31
|
+
deepseek: pair[0],
|
|
32
|
+
tui: pair[1],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function executableName(base, platform) {
|
|
37
|
+
return platform === "win32" ? `${base}.exe` : base;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function releaseAssetUrl(baseName, version, repo = "Hmbown/DeepSeek-TUI") {
|
|
41
|
+
return `https://github.com/${repo}/releases/download/v${version}/${baseName}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function releaseBinaryDirectory() {
|
|
45
|
+
return path.join(__dirname, "..", "bin", "downloads");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = {
|
|
49
|
+
detectBinaryNames,
|
|
50
|
+
executableName,
|
|
51
|
+
releaseAssetUrl,
|
|
52
|
+
releaseBinaryDirectory,
|
|
53
|
+
};
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const https = require("https");
|
|
3
|
+
const http = require("http");
|
|
4
|
+
const { mkdir, chmod, stat, rename, readFile, writeFile } = fs.promises;
|
|
5
|
+
const { createWriteStream } = fs;
|
|
6
|
+
const { pipeline } = require("stream/promises");
|
|
7
|
+
const path = require("path");
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
detectBinaryNames,
|
|
11
|
+
releaseAssetUrl,
|
|
12
|
+
releaseBinaryDirectory,
|
|
13
|
+
} = require("./artifacts");
|
|
14
|
+
|
|
15
|
+
function resolvePackageVersion() {
|
|
16
|
+
const pkg = require("../package.json");
|
|
17
|
+
return process.env.DEEPSEEK_TUI_VERSION || process.env.DEEPSEEK_VERSION || pkg.version;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function resolveRepo() {
|
|
21
|
+
return process.env.DEEPSEEK_TUI_GITHUB_REPO || process.env.DEEPSEEK_GITHUB_REPO || "Hmbown/DeepSeek-TUI";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function binaryPaths() {
|
|
25
|
+
const { deepseek, tui } = detectBinaryNames();
|
|
26
|
+
const releaseDir = releaseBinaryDirectory();
|
|
27
|
+
return {
|
|
28
|
+
deepseek: {
|
|
29
|
+
asset: deepseek,
|
|
30
|
+
target: path.join(releaseDir, process.platform === "win32" ? "deepseek.exe" : "deepseek"),
|
|
31
|
+
},
|
|
32
|
+
tui: {
|
|
33
|
+
asset: tui,
|
|
34
|
+
target: path.join(releaseDir, process.platform === "win32" ? "deepseek-tui.exe" : "deepseek-tui"),
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function httpGet(url) {
|
|
40
|
+
const client = url.startsWith("https:") ? https : http;
|
|
41
|
+
const response = await new Promise((resolve, reject) => {
|
|
42
|
+
client.get(url, (res) => {
|
|
43
|
+
const status = res.statusCode || 0;
|
|
44
|
+
if (status >= 300 && status < 400 && res.headers.location) {
|
|
45
|
+
resolve({ redirect: res.headers.location, response: null });
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (status !== 200) {
|
|
49
|
+
reject(new Error(`Request failed with status ${status}: ${url}`));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
resolve({ redirect: null, response: res });
|
|
53
|
+
}).on("error", reject);
|
|
54
|
+
});
|
|
55
|
+
return response;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function download(url, destination) {
|
|
59
|
+
const resolved = await httpGet(url);
|
|
60
|
+
if (resolved.redirect) {
|
|
61
|
+
return download(resolved.redirect, destination);
|
|
62
|
+
}
|
|
63
|
+
await mkdir(path.dirname(destination), { recursive: true });
|
|
64
|
+
await pipeline(resolved.response, createWriteStream(destination));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function readLocalVersion(file) {
|
|
68
|
+
return readFile(file, "utf8").catch(() => "");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function fileExists(file) {
|
|
72
|
+
try {
|
|
73
|
+
const result = await stat(file);
|
|
74
|
+
return result.isFile();
|
|
75
|
+
} catch {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function ensureBinary(targetPath, assetName, version, repo) {
|
|
81
|
+
const marker = `${targetPath}.version`;
|
|
82
|
+
const downloadIfNeeded =
|
|
83
|
+
process.env.DEEPSEEK_TUI_FORCE_DOWNLOAD === "1" || process.env.DEEPSEEK_FORCE_DOWNLOAD === "1";
|
|
84
|
+
if (!downloadIfNeeded) {
|
|
85
|
+
const existing = await fileExists(targetPath);
|
|
86
|
+
if (existing) {
|
|
87
|
+
const markerVersion = await readLocalVersion(marker);
|
|
88
|
+
if (markerVersion === String(version)) {
|
|
89
|
+
return targetPath;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const url = releaseAssetUrl(assetName, version, repo);
|
|
94
|
+
const destination = `${targetPath}.download`;
|
|
95
|
+
await download(url, destination);
|
|
96
|
+
if (process.platform !== "win32") {
|
|
97
|
+
await chmod(destination, 0o755);
|
|
98
|
+
}
|
|
99
|
+
await rename(destination, targetPath);
|
|
100
|
+
await writeFile(marker, String(version), "utf8");
|
|
101
|
+
return targetPath;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function run() {
|
|
105
|
+
if (process.env.DEEPSEEK_TUI_DISABLE_INSTALL === "1" || process.env.DEEPSEEK_DISABLE_INSTALL === "1") {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const version = resolvePackageVersion();
|
|
109
|
+
const repo = resolveRepo();
|
|
110
|
+
const paths = binaryPaths();
|
|
111
|
+
const releaseDir = releaseBinaryDirectory();
|
|
112
|
+
await mkdir(releaseDir, { recursive: true });
|
|
113
|
+
|
|
114
|
+
await Promise.all([
|
|
115
|
+
ensureBinary(paths.deepseek.target, paths.deepseek.asset, version, repo),
|
|
116
|
+
ensureBinary(paths.tui.target, paths.tui.asset, version, repo),
|
|
117
|
+
]);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async function getBinaryPath(name) {
|
|
121
|
+
await run();
|
|
122
|
+
const paths = binaryPaths();
|
|
123
|
+
if (name === "deepseek") {
|
|
124
|
+
return paths.deepseek.target;
|
|
125
|
+
}
|
|
126
|
+
if (name === "deepseek-tui") {
|
|
127
|
+
return paths.tui.target;
|
|
128
|
+
}
|
|
129
|
+
throw new Error(`Unknown binary: ${name}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
module.exports = {
|
|
133
|
+
getBinaryPath,
|
|
134
|
+
run,
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
if (require.main === module) {
|
|
138
|
+
run().catch((error) => {
|
|
139
|
+
console.error("deepseek-tui install failed:", error.message);
|
|
140
|
+
process.exit(1);
|
|
141
|
+
});
|
|
142
|
+
}
|
package/scripts/run.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const { spawnSync } = require("child_process");
|
|
2
|
+
const { getBinaryPath } = require("./install");
|
|
3
|
+
|
|
4
|
+
async function run(binaryName) {
|
|
5
|
+
const binaryPath = await getBinaryPath(binaryName);
|
|
6
|
+
const result = spawnSync(binaryPath, process.argv.slice(2), {
|
|
7
|
+
stdio: "inherit",
|
|
8
|
+
});
|
|
9
|
+
if (result.error) {
|
|
10
|
+
throw result.error;
|
|
11
|
+
}
|
|
12
|
+
process.exit(result.status ?? 1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function runDeepseek() {
|
|
16
|
+
await run("deepseek");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function runDeepseekTui() {
|
|
20
|
+
await run("deepseek-tui");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = {
|
|
24
|
+
run,
|
|
25
|
+
runDeepseek,
|
|
26
|
+
runDeepseekTui,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
if (require.main === module) {
|
|
30
|
+
const command = process.argv[1] || "";
|
|
31
|
+
if (command.includes("tui")) {
|
|
32
|
+
runDeepseekTui();
|
|
33
|
+
} else {
|
|
34
|
+
runDeepseek();
|
|
35
|
+
}
|
|
36
|
+
}
|