@liwenkai/deepcode 0.1.0
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 +39 -0
- package/bin/deepcode +36 -0
- package/install.mjs +210 -0
- package/package.json +35 -0
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# deepcode
|
|
2
|
+
|
|
3
|
+
AI coding assistant in your terminal — powered by DeepSeek.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install -g @liwenkai/deepcode
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
(The installed command is `deepcode`.)
|
|
12
|
+
|
|
13
|
+
The `postinstall` step downloads the prebuilt binary for your platform from
|
|
14
|
+
[GitHub Releases](https://github.com/liwenka1/deep-code/releases) and verifies
|
|
15
|
+
its SHA-256 checksum. Then run:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
deepcode
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Supported platforms
|
|
22
|
+
|
|
23
|
+
| OS | Arch |
|
|
24
|
+
|----|------|
|
|
25
|
+
| macOS | arm64, x64 |
|
|
26
|
+
| Linux | arm64, x64 |
|
|
27
|
+
| Windows | x64 (arm64 via x64 emulation) |
|
|
28
|
+
|
|
29
|
+
## Notes
|
|
30
|
+
|
|
31
|
+
- Requires Node.js >= 18 (for the installer only; the CLI itself is a native binary).
|
|
32
|
+
- If your network blocks GitHub, grab a binary from the
|
|
33
|
+
[releases page](https://github.com/liwenka1/deep-code/releases) manually, or
|
|
34
|
+
build from source: clone `liwenka1/deep-code` and run
|
|
35
|
+
`cargo build --release -p deep-code-tui`.
|
|
36
|
+
|
|
37
|
+
## License
|
|
38
|
+
|
|
39
|
+
MIT
|
package/bin/deepcode
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Cross-platform launcher for the deepcode CLI.
|
|
3
|
+
//
|
|
4
|
+
// `install.mjs` downloads the platform's prebuilt Rust binary next to this file
|
|
5
|
+
// (`deepcode-bin` on Unix, `deepcode.exe` on Windows). This launcher is what
|
|
6
|
+
// `package.json` `bin` points at and is shipped in the tarball, so npm's bin
|
|
7
|
+
// link always targets a real file — Windows no longer depends on PATHEXT
|
|
8
|
+
// resolving an extension-less name, and `--ignore-scripts` installs fail loudly
|
|
9
|
+
// instead of leaving a command pointing at nothing.
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
const { spawnSync } = require('node:child_process');
|
|
13
|
+
const { existsSync } = require('node:fs');
|
|
14
|
+
const { join } = require('node:path');
|
|
15
|
+
|
|
16
|
+
const binary = join(
|
|
17
|
+
__dirname,
|
|
18
|
+
process.platform === 'win32' ? 'deepcode.exe' : 'deepcode-bin',
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
if (!existsSync(binary)) {
|
|
22
|
+
console.error('deepcode: native binary not found.');
|
|
23
|
+
console.error('Reinstall without --ignore-scripts, or grab a prebuilt binary from');
|
|
24
|
+
console.error('https://github.com/liwenka1/deep-code/releases');
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const result = spawnSync(binary, process.argv.slice(2), { stdio: 'inherit' });
|
|
29
|
+
|
|
30
|
+
if (result.error) {
|
|
31
|
+
console.error(`deepcode: failed to launch binary: ${result.error.message}`);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Mirror the child's exit; a signal-terminated child reports null status.
|
|
36
|
+
process.exit(result.status === null ? 1 : result.status);
|
package/install.mjs
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
// install.mjs — npm postinstall script
|
|
2
|
+
//
|
|
3
|
+
// 检测当前平台(OS + Arch),从 GitHub Releases 下载对应
|
|
4
|
+
// 的预编译 deepcode 二进制到 bin/ 目录,并设置可执行权限。
|
|
5
|
+
|
|
6
|
+
import https from 'node:https';
|
|
7
|
+
import fs from 'node:fs';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import crypto from 'node:crypto';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
import { platform, arch } from 'node:os';
|
|
12
|
+
|
|
13
|
+
// ── 配置 ──
|
|
14
|
+
const REPO = 'liwenka1/deep-code';
|
|
15
|
+
const VERSION = process.env.npm_package_version || '0.1.0';
|
|
16
|
+
// `import.meta.dirname` only exists on Node 20.11+; derive it from the module
|
|
17
|
+
// URL so the `engines: node >=18` floor actually works.
|
|
18
|
+
const BIN_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), 'bin');
|
|
19
|
+
// The real binary sits next to the `deepcode` JS launcher (bin/deepcode), which
|
|
20
|
+
// spawns it. Distinct names so the download never clobbers the launcher.
|
|
21
|
+
const BIN_NAME = platform() === 'win32' ? 'deepcode.exe' : 'deepcode-bin';
|
|
22
|
+
|
|
23
|
+
// ── 平台 → GitHub Release asset 名称映射 ──
|
|
24
|
+
const ASSET_MAP = {
|
|
25
|
+
'darwin-arm64': 'deep-code-aarch64-apple-darwin',
|
|
26
|
+
'darwin-x64': 'deep-code-x86_64-apple-darwin',
|
|
27
|
+
'linux-arm64': 'deep-code-aarch64-unknown-linux-gnu',
|
|
28
|
+
'linux-x64': 'deep-code-x86_64-unknown-linux-gnu',
|
|
29
|
+
'win32-x64': 'deep-code-x86_64-pc-windows-msvc.exe',
|
|
30
|
+
// Windows on ARM runs x64 binaries via built-in emulation, so reuse the x64
|
|
31
|
+
// asset (matches the win32+arm64 combo allowed by package.json os/cpu).
|
|
32
|
+
'win32-arm64': 'deep-code-x86_64-pc-windows-msvc.exe',
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// ── 主逻辑 ──
|
|
36
|
+
async function main() {
|
|
37
|
+
const platformKey = `${platform()}-${arch()}`;
|
|
38
|
+
const assetName = ASSET_MAP[platformKey];
|
|
39
|
+
|
|
40
|
+
if (!assetName) {
|
|
41
|
+
console.error(`❌ deepcode: unsupported platform "${platformKey}"`);
|
|
42
|
+
console.error(
|
|
43
|
+
' Supported: darwin-arm64, darwin-x64, linux-arm64, linux-x64, win32-x64, win32-arm64',
|
|
44
|
+
);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const binPath = path.join(BIN_DIR, BIN_NAME);
|
|
49
|
+
const downloadUrl = `https://github.com/${REPO}/releases/download/v${VERSION}/${assetName}`;
|
|
50
|
+
|
|
51
|
+
// 已有二进制则跳过(npm install 幂等)
|
|
52
|
+
if (fs.existsSync(binPath)) {
|
|
53
|
+
console.log(`✅ deepcode binary already installed (${platformKey})`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
console.log(`📦 Downloading deepcode v${VERSION} for ${platformKey}...`);
|
|
58
|
+
console.log(` ${downloadUrl}`);
|
|
59
|
+
|
|
60
|
+
// 确保 bin 目录存在
|
|
61
|
+
fs.mkdirSync(BIN_DIR, { recursive: true });
|
|
62
|
+
|
|
63
|
+
// 下载
|
|
64
|
+
await downloadFile(downloadUrl, binPath);
|
|
65
|
+
|
|
66
|
+
// 校验完整性(SHA256SUMS 来自同一 release)
|
|
67
|
+
await verifyChecksum(assetName, binPath);
|
|
68
|
+
|
|
69
|
+
// 设置可执行权限(非 Windows)
|
|
70
|
+
if (platform() !== 'win32') {
|
|
71
|
+
fs.chmodSync(binPath, 0o755);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
console.log(`✅ deepcode v${VERSION} installed successfully!`);
|
|
75
|
+
console.log(' Run "deepcode" in your terminal to get started.');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ── 完整性校验 ──
|
|
79
|
+
// 从同一 release 拉取 SHA256SUMS,比对下载二进制的哈希。SHA256SUMS 缺失时
|
|
80
|
+
// (旧 release / 手动构建)跳过校验;哈希不匹配则删除文件并报错。
|
|
81
|
+
async function verifyChecksum(assetName, binPath) {
|
|
82
|
+
const sumsUrl = `https://github.com/${REPO}/releases/download/v${VERSION}/SHA256SUMS`;
|
|
83
|
+
const sumsPath = `${binPath}.SHA256SUMS`;
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
await downloadFile(sumsUrl, sumsPath);
|
|
87
|
+
} catch {
|
|
88
|
+
console.warn('⚠️ deepcode: SHA256SUMS not published for this release; skipping checksum verification.');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
let expected;
|
|
93
|
+
try {
|
|
94
|
+
expected = parseChecksum(fs.readFileSync(sumsPath, 'utf8'), assetName);
|
|
95
|
+
} finally {
|
|
96
|
+
fs.rmSync(sumsPath, { force: true });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!expected) {
|
|
100
|
+
console.warn(`⚠️ deepcode: no checksum entry for ${assetName}; skipping verification.`);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const actual = await sha256OfFile(binPath);
|
|
105
|
+
if (actual !== expected) {
|
|
106
|
+
fs.rmSync(binPath, { force: true });
|
|
107
|
+
throw new Error(
|
|
108
|
+
`checksum mismatch for ${assetName}\n expected: ${expected}\n actual: ${actual}\n` +
|
|
109
|
+
' The download may be corrupted or tampered with — aborting.'
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
console.log('🔒 deepcode: checksum verified.');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 解析 `sha256sum` 风格的清单(`<hex> name` 或 `<hex> *name`)。
|
|
116
|
+
function parseChecksum(text, assetName) {
|
|
117
|
+
for (const line of text.split('\n')) {
|
|
118
|
+
const match = line.trim().match(/^([0-9a-f]{64})\s+\*?(.+)$/i);
|
|
119
|
+
if (match && path.basename(match[2].trim()) === assetName) {
|
|
120
|
+
return match[1].toLowerCase();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function sha256OfFile(file) {
|
|
127
|
+
return new Promise((resolve, reject) => {
|
|
128
|
+
const hash = crypto.createHash('sha256');
|
|
129
|
+
const stream = fs.createReadStream(file);
|
|
130
|
+
stream.on('error', reject);
|
|
131
|
+
stream.on('data', (chunk) => hash.update(chunk));
|
|
132
|
+
stream.on('end', () => resolve(hash.digest('hex')));
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ── 辅助函数 ──
|
|
137
|
+
function downloadFile(url, dest) {
|
|
138
|
+
return new Promise((resolve, reject) => {
|
|
139
|
+
const file = fs.createWriteStream(dest, { mode: 0o755 });
|
|
140
|
+
|
|
141
|
+
const request = https.get(url, { headers: { 'User-Agent': 'deepcode-npm-installer' } }, (response) => {
|
|
142
|
+
// 处理重定向(GitHub release 资产会 302 到签名 URL)
|
|
143
|
+
if ([301, 302, 303, 307, 308].includes(response.statusCode)) {
|
|
144
|
+
const redirectUrl = response.headers.location;
|
|
145
|
+
if (!redirectUrl) {
|
|
146
|
+
reject(new Error(`Redirect with no location from ${url}`));
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
file.close();
|
|
150
|
+
fs.unlinkSync(dest);
|
|
151
|
+
downloadFile(redirectUrl, dest).then(resolve).catch(reject);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (response.statusCode === 404) {
|
|
156
|
+
file.close();
|
|
157
|
+
fs.unlinkSync(dest);
|
|
158
|
+
reject(new Error(
|
|
159
|
+
`Binary not found for ${platform()}-${arch()} (v${VERSION}). ` +
|
|
160
|
+
`Check https://github.com/${REPO}/releases for available versions.`
|
|
161
|
+
));
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (response.statusCode !== 200) {
|
|
166
|
+
file.close();
|
|
167
|
+
fs.unlinkSync(dest);
|
|
168
|
+
reject(new Error(`HTTP ${response.statusCode} from ${url}`));
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
response.pipe(file);
|
|
173
|
+
|
|
174
|
+
file.on('finish', () => {
|
|
175
|
+
file.close();
|
|
176
|
+
resolve();
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
file.on('error', (err) => {
|
|
180
|
+
file.close();
|
|
181
|
+
fs.unlink(dest, () => {});
|
|
182
|
+
reject(err);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
request.on('error', (err) => {
|
|
187
|
+
file.close();
|
|
188
|
+
fs.unlink(dest, () => {});
|
|
189
|
+
reject(new Error(`Download failed: ${err.message}`));
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// 设置超时(5 分钟,二进制 ~15MB)
|
|
193
|
+
request.setTimeout(5 * 60 * 1000, () => {
|
|
194
|
+
request.destroy();
|
|
195
|
+
file.close();
|
|
196
|
+
fs.unlink(dest, () => {});
|
|
197
|
+
reject(new Error('Download timed out (5min). Check your network connection.'));
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// ── 启动 ──
|
|
203
|
+
main().catch((err) => {
|
|
204
|
+
console.error('❌ deepcode installation failed:', err.message);
|
|
205
|
+
console.error('');
|
|
206
|
+
console.error('Manual install options:');
|
|
207
|
+
console.error(` 1. Prebuilt binaries: https://github.com/${REPO}/releases`);
|
|
208
|
+
console.error(` 2. Build from source: clone ${REPO}, then \`cargo build --release -p deep-code-tui\``);
|
|
209
|
+
process.exit(1);
|
|
210
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@liwenkai/deepcode",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "AI coding assistant in your terminal — powered by DeepSeek",
|
|
5
|
+
"bin": {
|
|
6
|
+
"deepcode": "bin/deepcode"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"postinstall": "node install.mjs"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/liwenka1/deep-code.git"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/liwenka1/deep-code#readme",
|
|
16
|
+
"keywords": [
|
|
17
|
+
"ai",
|
|
18
|
+
"coding",
|
|
19
|
+
"assistant",
|
|
20
|
+
"cli",
|
|
21
|
+
"terminal",
|
|
22
|
+
"deepseek"
|
|
23
|
+
],
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"files": [
|
|
26
|
+
"install.mjs",
|
|
27
|
+
"package.json",
|
|
28
|
+
"bin/deepcode"
|
|
29
|
+
],
|
|
30
|
+
"os": ["darwin", "linux", "win32"],
|
|
31
|
+
"cpu": ["x64", "arm64"],
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18"
|
|
34
|
+
}
|
|
35
|
+
}
|