@ghenya/clinn 0.7.12 → 0.7.13

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.
@@ -2,6 +2,6 @@
2
2
  ██ ██ ██ ████ ██ ████ ██
3
3
  ██ ██ ██ ██ ██ ██ ██ ██ ██
4
4
  ██ ██ ██ ██ ██ ██ ██ ██ ██
5
- ██████ ███████ ██ ██ ████ ██ █0.7.12
5
+ ██████ ███████ ██ ██ ████ ██ █0.7.13
6
6
 
7
7
 
package/config.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "agent": {
3
3
  "name": "Clinn",
4
- "version": "0.7.12",
4
+ "version": "0.7.13",
5
5
  "description": "控制台智能体助手"
6
6
  },
7
7
  "llm": {
package/install.js CHANGED
@@ -6,133 +6,127 @@ const fs = require("fs");
6
6
  const path = require("path");
7
7
  const { execSync } = require("child_process");
8
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";
9
+ const VER = "0.7.13";
10
+ const G = "\x1b[0;32m", C = "\x1b[0;36m", Y = "\x1b[0;33m", R = "\x1b[0;31m", N = "\x1b[0m", D = "\x1b[2m";
16
11
 
17
12
  const IS_WIN = process.platform === "win32";
13
+ const HOME = os.homedir();
18
14
  const SRC = __dirname;
15
+ const CLINN_HOME = path.join(HOME, ".clinn");
16
+ const CLINN_CONFIG = path.join(CLINN_HOME, "config.json");
19
17
 
20
18
  function run(cmd, silent) {
21
- try {
22
- return execSync(cmd, { encoding: "utf-8", stdio: silent ? "pipe" : "inherit" });
23
- } catch (_) {
24
- return "";
25
- }
19
+ try { return execSync(cmd, { encoding: "utf-8", stdio: silent ? "pipe" : "inherit" }); }
20
+ catch (_) { return ""; }
26
21
  }
27
22
 
28
23
  function panic(msg) {
29
- console.error(`${RED}${msg}${NC}`);
24
+ console.error(`${R}${msg}${N}`);
30
25
  process.exit(1);
31
26
  }
32
27
 
33
28
  console.log("");
34
- console.log(` ${CYAN}============================================${NC}`);
35
- console.log(` ${CYAN} Clinn v${VER} — npm 强力安装${NC}`);
36
- console.log(` ${CYAN}============================================${NC}`);
29
+ console.log(` ${C}============================================${N}`);
30
+ console.log(` ${C} Clinn v${VER} — 安装中...${N}`);
31
+ console.log(` ${C}============================================${N}`);
37
32
  console.log("");
38
33
 
39
- try { run("node --version", true); } catch (_) { panic("Node.js not found >= 18"); }
34
+ try { run("node --version", true); } catch (_) { panic("Node.js >= 18 required"); }
40
35
 
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";
36
+ function ensureClinnDir() {
37
+ if (!fs.existsSync(CLINN_HOME)) fs.mkdirSync(CLINN_HOME, { recursive: true });
38
+ const memDir = path.join(CLINN_HOME, "mem");
39
+ if (!fs.existsSync(memDir)) fs.mkdirSync(memDir, { recursive: true });
40
+ const toolsDir = path.join(CLINN_HOME, "Tools", "custom");
41
+ if (!fs.existsSync(toolsDir)) fs.mkdirSync(toolsDir, { recursive: true });
47
42
  }
48
43
 
49
- console.log(` ${DIM}目标目录: ${DEST}${NC}`);
50
-
51
44
  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 (_) {}
45
+ if (fs.existsSync(CLINN_CONFIG)) {
46
+ try { oldKey = require(CLINN_CONFIG).llm?.apiKey || ""; } catch (_) {}
57
47
  }
58
48
 
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() {
49
+ function cleanOldShellRC() {
68
50
  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);
51
+ for (const f of [".bashrc", ".zshrc", ".bash_profile", ".profile"]) {
52
+ const p = path.join(HOME, f);
73
53
  if (!fs.existsSync(p)) continue;
74
54
  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");
55
+ const oldLen = content.split("\n").length;
56
+ content = content.split("\n").filter(l => !/clinn/i.test(l)).join("\n");
57
+ if (content.split("\n").length !== oldLen) fs.writeFileSync(p, content, "utf-8");
77
58
  }
78
59
  }
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
60
 
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 (_) {}
61
+ function cleanOldPATH() {
62
+ if (!IS_WIN) return;
63
+ for (const level of ["User", "Machine"]) {
64
+ let raw = "";
65
+ try {
66
+ raw = execSync(`powershell -NoProfile -Command "[Environment]::GetEnvironmentVariable('Path', '${level}')"`, { encoding: "utf-8", windowsHide: true }).trim();
67
+ } catch (_) { continue; }
68
+ const parts = raw.split(";").filter(p => {
69
+ const lo = p.toLowerCase().replace(/\//g, "\\");
70
+ return lo && !lo.includes("clinn") && !lo.includes("\\Clinn\\");
71
+ });
72
+ const clean = parts.join(";");
73
+ try {
74
+ execSync(`powershell -NoProfile -Command "[Environment]::SetEnvironmentVariable('Path', '${clean.replace(/\\/g, "\\\\")}', '${level}')"`, { windowsHide: true });
75
+ } catch (_) {}
76
+ }
99
77
  }
100
78
 
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;
79
+ function addToPATH() {
80
+ if (!IS_WIN) return;
81
+ const dest = path.join(process.env.LOCALAPPDATA || "", "Programs", "Clinn");
82
+ for (const level of ["User"]) {
83
+ let raw = "";
84
+ try {
85
+ raw = execSync(`powershell -NoProfile -Command "[Environment]::GetEnvironmentVariable('Path', '${level}')"`, { encoding: "utf-8", windowsHide: true }).trim();
86
+ } catch (_) { continue; }
87
+ if (!raw.toLowerCase().includes(dest.toLowerCase())) {
88
+ raw = raw + ";" + dest;
111
89
  try {
112
- execSync(`powershell -NoProfile -Command "[Environment]::SetEnvironmentVariable('Path', '${clean.replace(/\\/g, "\\\\")}', '${level}')"`, { windowsHide: true });
90
+ execSync(`powershell -NoProfile -Command "[Environment]::SetEnvironmentVariable('Path', '${raw.replace(/\\/g, "\\\\")}', '${level}')"`, { windowsHide: true });
113
91
  } catch (_) {}
114
92
  }
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
93
  }
121
94
  }
122
- updatePATH();
123
95
 
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");
96
+ cleanOldShellRC();
97
+ cleanOldPATH();
98
+
99
+ ensureClinnDir();
100
+
101
+ if (!fs.existsSync(CLINN_CONFIG)) {
102
+ const pkgCfg = path.join(SRC, "config.json");
103
+ if (fs.existsSync(pkgCfg)) {
104
+ const cfg = JSON.parse(fs.readFileSync(pkgCfg, "utf-8"));
105
+ if (oldKey && oldKey !== "YOUR_API_KEY" && oldKey !== "YOUR_DEEPSEEK_API_KEY_HERE") {
106
+ cfg.llm.apiKey = oldKey;
107
+ }
108
+ fs.writeFileSync(CLINN_CONFIG, JSON.stringify(cfg, null, 2), "utf-8");
109
+ console.log(` ${G}配置文件已创建:${N} ${D}${CLINN_CONFIG}${N}`);
110
+ }
111
+ } else if (oldKey && oldKey !== "YOUR_API_KEY" && oldKey !== "YOUR_DEEPSEEK_API_KEY_HERE") {
112
+ try {
113
+ const cfg = JSON.parse(fs.readFileSync(CLINN_CONFIG, "utf-8"));
114
+ if (cfg.llm.apiKey !== oldKey) {
115
+ cfg.llm.apiKey = oldKey;
116
+ fs.writeFileSync(CLINN_CONFIG, JSON.stringify(cfg, null, 2), "utf-8");
117
+ }
118
+ } catch (_) {}
127
119
  }
128
120
 
121
+ addToPATH();
122
+
123
+ console.log(` ${Y}npm bin shim 已由 npm 自动创建${N}`);
129
124
  console.log("");
130
- console.log(` ${GREEN}============================================${NC}`);
131
- console.log(` ${GREEN} 安装完成! 输入 clinn 即可启动${NC}`);
132
- console.log(` ${GREEN}============================================${NC}`);
125
+ console.log(` ${G}============================================${N}`);
126
+ console.log(` ${G} 安装完成! 输入 clinn 即可启动${N}`);
127
+ console.log(` ${G}============================================${N}`);
133
128
  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}`);
129
+ console.log(` 版本: ${C}clinn --version${N}`);
130
+ console.log(` 配置: ${C}${CLINN_CONFIG}${N}`);
131
+ console.log(` 设置Key: ${C}clinn → /api key <你的Key>${N}`);
138
132
  console.log("");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ghenya/clinn",
3
- "version": "0.7.12",
3
+ "version": "0.7.13",
4
4
  "description": "终端原生 AI 编程助手 — DeepSeek 驱动,50+ 工具,对话记忆,虚拟浏览器",
5
5
  "main": "Src/index.js",
6
6
  "bin": {
@@ -19,6 +19,7 @@
19
19
  "install.bat"
20
20
  ],
21
21
  "scripts": {
22
+ "postinstall": "node install.js",
22
23
  "start": "node Src/index.js",
23
24
  "lint": "node --check Src/index.js && node --check Src/agent.js && node --check Src/llm.js && node --check Tools/index.js && node --check Tools/extended_tools.js && node --check Tools/search_tools.js && node --check Tools/browser.js && node --check Mem/index.js && node --check Mem/history.js"
24
25
  },