@ghenya/clinn 0.7.11 → 0.7.12
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/Logos/StartLogo.txt +1 -1
- package/config.json +1 -1
- package/install.js +138 -0
- package/package.json +2 -1
package/Logos/StartLogo.txt
CHANGED
package/config.json
CHANGED
package/install.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const os = require("os");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const { execSync } = require("child_process");
|
|
8
|
+
|
|
9
|
+
const VER = "0.7.12";
|
|
10
|
+
const GREEN = "\x1b[0;32m";
|
|
11
|
+
const CYAN = "\x1b[0;36m";
|
|
12
|
+
const YELLOW = "\x1b[0;33m";
|
|
13
|
+
const RED = "\x1b[0;31m";
|
|
14
|
+
const NC = "\x1b[0m";
|
|
15
|
+
const DIM = "\x1b[2m";
|
|
16
|
+
|
|
17
|
+
const IS_WIN = process.platform === "win32";
|
|
18
|
+
const SRC = __dirname;
|
|
19
|
+
|
|
20
|
+
function run(cmd, silent) {
|
|
21
|
+
try {
|
|
22
|
+
return execSync(cmd, { encoding: "utf-8", stdio: silent ? "pipe" : "inherit" });
|
|
23
|
+
} catch (_) {
|
|
24
|
+
return "";
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function panic(msg) {
|
|
29
|
+
console.error(`${RED}${msg}${NC}`);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
console.log("");
|
|
34
|
+
console.log(` ${CYAN}============================================${NC}`);
|
|
35
|
+
console.log(` ${CYAN} Clinn v${VER} — npm 强力安装${NC}`);
|
|
36
|
+
console.log(` ${CYAN}============================================${NC}`);
|
|
37
|
+
console.log("");
|
|
38
|
+
|
|
39
|
+
try { run("node --version", true); } catch (_) { panic("Node.js not found >= 18"); }
|
|
40
|
+
|
|
41
|
+
let DEST;
|
|
42
|
+
if (IS_WIN) {
|
|
43
|
+
try { run("net session", true); DEST = path.join(process.env.ProgramFiles, "Clinn"); }
|
|
44
|
+
catch (_) { DEST = path.join(process.env.LOCALAPPDATA, "Programs", "Clinn"); }
|
|
45
|
+
} else {
|
|
46
|
+
DEST = "/usr/local/lib/clinn";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
console.log(` ${DIM}目标目录: ${DEST}${NC}`);
|
|
50
|
+
|
|
51
|
+
let oldKey = "";
|
|
52
|
+
const oldConfig = path.join(DEST, "config.json");
|
|
53
|
+
if (fs.existsSync(oldConfig)) {
|
|
54
|
+
try {
|
|
55
|
+
oldKey = require(oldConfig).llm?.apiKey || "";
|
|
56
|
+
} catch (_) {}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
console.log(` ${YELLOW}正在清除旧安装...${NC}`);
|
|
60
|
+
if (fs.existsSync(DEST)) fs.rmSync(DEST, { recursive: true, force: true });
|
|
61
|
+
if (!IS_WIN) {
|
|
62
|
+
for (const bin of ["/usr/local/bin/clinn", "/usr/bin/clinn", "/usr/local/sbin/clinn"]) {
|
|
63
|
+
try { fs.unlinkSync(bin); } catch (_) {}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function cleanShellRC() {
|
|
68
|
+
if (IS_WIN) return;
|
|
69
|
+
const home = os.homedir();
|
|
70
|
+
const files = [".bashrc", ".zshrc", ".bash_profile", ".profile"];
|
|
71
|
+
for (const f of files) {
|
|
72
|
+
const p = path.join(home, f);
|
|
73
|
+
if (!fs.existsSync(p)) continue;
|
|
74
|
+
let content = fs.readFileSync(p, "utf-8");
|
|
75
|
+
const lines = content.split("\n").filter(l => !/clinn/i.test(l));
|
|
76
|
+
fs.writeFileSync(p, lines.join("\n"), "utf-8");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
cleanShellRC();
|
|
80
|
+
|
|
81
|
+
console.log(` ${CYAN}正在复制文件...${NC}`);
|
|
82
|
+
const dirs = ["Src", "Tools", "Mem", "Logos", "bin"];
|
|
83
|
+
fs.mkdirSync(DEST, { recursive: true });
|
|
84
|
+
for (const d of dirs) {
|
|
85
|
+
const src = path.join(SRC, d);
|
|
86
|
+
if (fs.existsSync(src)) fs.cpSync(src, path.join(DEST, d), { recursive: true });
|
|
87
|
+
}
|
|
88
|
+
const cfgSrc = path.join(SRC, "config.json");
|
|
89
|
+
if (fs.existsSync(cfgSrc)) fs.copyFileSync(cfgSrc, path.join(DEST, "config.json"));
|
|
90
|
+
fs.mkdirSync(path.join(DEST, "Tools", "custom"), { recursive: true });
|
|
91
|
+
|
|
92
|
+
if (oldKey && oldKey !== "YOUR_API_KEY" && oldKey !== "YOUR_DEEPSEEK_API_KEY_HERE") {
|
|
93
|
+
console.log(` ${YELLOW}正在恢复旧 API Key...${NC}`);
|
|
94
|
+
try {
|
|
95
|
+
const cfg = JSON.parse(fs.readFileSync(path.join(DEST, "config.json"), "utf-8"));
|
|
96
|
+
cfg.llm.apiKey = oldKey;
|
|
97
|
+
fs.writeFileSync(path.join(DEST, "config.json"), JSON.stringify(cfg, null, 2), "utf-8");
|
|
98
|
+
} catch (_) {}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function updatePATH() {
|
|
102
|
+
if (IS_WIN) {
|
|
103
|
+
const levels = ["User", "Machine"];
|
|
104
|
+
for (const level of levels) {
|
|
105
|
+
let raw = "";
|
|
106
|
+
try {
|
|
107
|
+
raw = execSync(`powershell -NoProfile -Command "[Environment]::GetEnvironmentVariable('Path', '${level}')"`, { encoding: "utf-8", windowsHide: true }).trim();
|
|
108
|
+
} catch (_) { continue; }
|
|
109
|
+
const parts = raw.split(";").filter(p => p && p.toLowerCase().replace(/\//g, "\\") !== DEST.toLowerCase().replace(/\//g, "\\"));
|
|
110
|
+
const clean = parts.join(";") + ";" + DEST;
|
|
111
|
+
try {
|
|
112
|
+
execSync(`powershell -NoProfile -Command "[Environment]::SetEnvironmentVariable('Path', '${clean.replace(/\\/g, "\\\\")}', '${level}')"`, { windowsHide: true });
|
|
113
|
+
} catch (_) {}
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
const launcher = `#!/usr/bin/env bash\nexec node ${DEST}/Src/index.js "$@"\n`;
|
|
117
|
+
const binPath = "/usr/local/bin/clinn";
|
|
118
|
+
try { fs.writeFileSync(binPath, launcher, { mode: 0o755 }); }
|
|
119
|
+
catch (_) { try { run(`sudo bash -c 'cat > ${binPath} && chmod +x ${binPath}' <<< "${launcher}"`, false); } catch (_) {} }
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
updatePATH();
|
|
123
|
+
|
|
124
|
+
if (IS_WIN) {
|
|
125
|
+
const bat = `@echo off\r\nnode "${DEST}\\Src\\index.js" %*\r\n`;
|
|
126
|
+
fs.writeFileSync(path.join(DEST, "clinn.bat"), bat, "utf-8");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
console.log("");
|
|
130
|
+
console.log(` ${GREEN}============================================${NC}`);
|
|
131
|
+
console.log(` ${GREEN} 安装完成! 输入 clinn 即可启动${NC}`);
|
|
132
|
+
console.log(` ${GREEN}============================================${NC}`);
|
|
133
|
+
console.log("");
|
|
134
|
+
console.log(` 运行: ${CYAN}clinn${NC}`);
|
|
135
|
+
console.log(` 版本: ${CYAN}clinn --version${NC}`);
|
|
136
|
+
console.log(` 配置: ${CYAN}${DEST}/config.json${NC}`);
|
|
137
|
+
console.log(` 卸载: ${CYAN}${IS_WIN ? `rmdir /s /q "${DEST}"` : `sudo rm -rf ${DEST} /usr/local/bin/clinn`}${NC}`);
|
|
138
|
+
console.log("");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ghenya/clinn",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.12",
|
|
4
4
|
"description": "终端原生 AI 编程助手 — DeepSeek 驱动,50+ 工具,对话记忆,虚拟浏览器",
|
|
5
5
|
"main": "Src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"bin/",
|
|
15
15
|
"config.json",
|
|
16
16
|
"README.md",
|
|
17
|
+
"install.js",
|
|
17
18
|
"install.sh",
|
|
18
19
|
"install.bat"
|
|
19
20
|
],
|