okit-cli 2.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 +222 -0
- package/dist/commands/check.d.ts +13 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +259 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/claude.d.ts +10 -0
- package/dist/commands/claude.d.ts.map +1 -0
- package/dist/commands/claude.js +504 -0
- package/dist/commands/claude.js.map +1 -0
- package/dist/commands/menu.d.ts +3 -0
- package/dist/commands/menu.d.ts.map +1 -0
- package/dist/commands/menu.js +152 -0
- package/dist/commands/menu.js.map +1 -0
- package/dist/commands/repo.d.ts +3 -0
- package/dist/commands/repo.d.ts.map +1 -0
- package/dist/commands/repo.js +266 -0
- package/dist/commands/repo.js.map +1 -0
- package/dist/commands/uninstall.d.ts +2 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +125 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/upgrade.d.ts +6 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/commands/upgrade.js +204 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/config/i18n.d.ts +141 -0
- package/dist/config/i18n.d.ts.map +1 -0
- package/dist/config/i18n.js +316 -0
- package/dist/config/i18n.js.map +1 -0
- package/dist/config/registry.d.ts +24 -0
- package/dist/config/registry.d.ts.map +1 -0
- package/dist/config/registry.js +388 -0
- package/dist/config/registry.js.map +1 -0
- package/dist/config/user.d.ts +32 -0
- package/dist/config/user.d.ts.map +1 -0
- package/dist/config/user.js +72 -0
- package/dist/config/user.js.map +1 -0
- package/dist/executor/deps/BrewDependencyProvider.d.ts +8 -0
- package/dist/executor/deps/BrewDependencyProvider.d.ts.map +1 -0
- package/dist/executor/deps/BrewDependencyProvider.js +52 -0
- package/dist/executor/deps/BrewDependencyProvider.js.map +1 -0
- package/dist/executor/deps/DependencyProvider.d.ts +11 -0
- package/dist/executor/deps/DependencyProvider.d.ts.map +1 -0
- package/dist/executor/deps/DependencyProvider.js +3 -0
- package/dist/executor/deps/DependencyProvider.js.map +1 -0
- package/dist/executor/deps/NpmDependencyProvider.d.ts +12 -0
- package/dist/executor/deps/NpmDependencyProvider.d.ts.map +1 -0
- package/dist/executor/deps/NpmDependencyProvider.js +78 -0
- package/dist/executor/deps/NpmDependencyProvider.js.map +1 -0
- package/dist/executor/deps/PipxDependencyProvider.d.ts +8 -0
- package/dist/executor/deps/PipxDependencyProvider.d.ts.map +1 -0
- package/dist/executor/deps/PipxDependencyProvider.js +32 -0
- package/dist/executor/deps/PipxDependencyProvider.js.map +1 -0
- package/dist/executor/deps/UvToolDependencyProvider.d.ts +8 -0
- package/dist/executor/deps/UvToolDependencyProvider.d.ts.map +1 -0
- package/dist/executor/deps/UvToolDependencyProvider.js +35 -0
- package/dist/executor/deps/UvToolDependencyProvider.js.map +1 -0
- package/dist/executor/plan/ExecutionPlanner.d.ts +13 -0
- package/dist/executor/plan/ExecutionPlanner.d.ts.map +1 -0
- package/dist/executor/plan/ExecutionPlanner.js +109 -0
- package/dist/executor/plan/ExecutionPlanner.js.map +1 -0
- package/dist/executor/plan/TopologicalSorter.d.ts +3 -0
- package/dist/executor/plan/TopologicalSorter.d.ts.map +1 -0
- package/dist/executor/plan/TopologicalSorter.js +49 -0
- package/dist/executor/plan/TopologicalSorter.js.map +1 -0
- package/dist/executor/plan/registryDeps.d.ts +3 -0
- package/dist/executor/plan/registryDeps.d.ts.map +1 -0
- package/dist/executor/plan/registryDeps.js +22 -0
- package/dist/executor/plan/registryDeps.js.map +1 -0
- package/dist/executor/runner.d.ts +13 -0
- package/dist/executor/runner.d.ts.map +1 -0
- package/dist/executor/runner.js +430 -0
- package/dist/executor/runner.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +244 -0
- package/dist/main.js.map +1 -0
- package/dist/utils/sound.d.ts +10 -0
- package/dist/utils/sound.d.ts.map +1 -0
- package/dist/utils/sound.js +36 -0
- package/dist/utils/sound.js.map +1 -0
- package/dist/web/api/config.js +73 -0
- package/dist/web/api/stats.js +130 -0
- package/dist/web/public/app.js +284 -0
- package/dist/web/public/index.html +367 -0
- package/dist/web/public/styles.css +1004 -0
- package/dist/web/server.js +41 -0
- package/package.json +61 -0
package/dist/main.js
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
const commander_1 = require("commander");
|
|
41
|
+
const kleur_1 = __importDefault(require("kleur"));
|
|
42
|
+
const prompts_1 = __importDefault(require("prompts"));
|
|
43
|
+
const package_json_1 = __importDefault(require("../package.json"));
|
|
44
|
+
const menu_1 = require("./commands/menu");
|
|
45
|
+
const upgrade_1 = require("./commands/upgrade");
|
|
46
|
+
const uninstall_1 = require("./commands/uninstall");
|
|
47
|
+
const repo_1 = require("./commands/repo");
|
|
48
|
+
const check_1 = require("./commands/check");
|
|
49
|
+
const registry_1 = require("./config/registry");
|
|
50
|
+
const i18n_1 = require("./config/i18n");
|
|
51
|
+
const user_1 = require("./config/user");
|
|
52
|
+
const program = new commander_1.Command();
|
|
53
|
+
// 显示 Banner
|
|
54
|
+
function showBanner() {
|
|
55
|
+
const banner = `
|
|
56
|
+
██████╗ ██╗ ██╗ ██╗ ████████╗
|
|
57
|
+
██╔═══██╗ ██║ ██╔╝ ██║ ╚══██╔══╝
|
|
58
|
+
██║ ██║ █████╔╝ ██║ ██║
|
|
59
|
+
██║ ██║ ██╔═██╗ ██║ ██║
|
|
60
|
+
╚██████╔╝ ██║ ██╗ ██║ ██║
|
|
61
|
+
╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
|
|
62
|
+
`;
|
|
63
|
+
console.log(kleur_1.default.cyan(banner));
|
|
64
|
+
console.log(kleur_1.default.gray(" OKIT v1 - macOS 开发工具管理器\n"));
|
|
65
|
+
}
|
|
66
|
+
program
|
|
67
|
+
.name("okit")
|
|
68
|
+
.description("OKIT v1 - 精简版工具执行器")
|
|
69
|
+
.version(package_json_1.default.version);
|
|
70
|
+
function getUnknownSubcommand() {
|
|
71
|
+
const argv = process.argv.slice(2);
|
|
72
|
+
const firstArg = argv.find((arg) => !arg.startsWith("-"));
|
|
73
|
+
if (!firstArg)
|
|
74
|
+
return null;
|
|
75
|
+
const known = new Set(program.commands.map((cmd) => cmd.name()));
|
|
76
|
+
return known.has(firstArg) ? null : firstArg;
|
|
77
|
+
}
|
|
78
|
+
// 语言选择(首次运行时显示)
|
|
79
|
+
async function selectLanguageIfNeeded() {
|
|
80
|
+
// 先尝试加载已保存的语言配置
|
|
81
|
+
const savedLang = await (0, i18n_1.loadLanguageConfig)();
|
|
82
|
+
if (savedLang) {
|
|
83
|
+
// 已有配置,直接使用
|
|
84
|
+
(0, i18n_1.setLanguage)(savedLang);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// 首次运行,显示语言选择
|
|
88
|
+
const response = await (0, prompts_1.default)({
|
|
89
|
+
type: "select",
|
|
90
|
+
name: "lang",
|
|
91
|
+
message: "选择语言 / Select language",
|
|
92
|
+
choices: [
|
|
93
|
+
{ title: "中文", value: "zh" },
|
|
94
|
+
{ title: "English", value: "en" },
|
|
95
|
+
],
|
|
96
|
+
});
|
|
97
|
+
if (response.lang) {
|
|
98
|
+
(0, i18n_1.setLanguage)(response.lang);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// 配置 prompts 使用中文提示
|
|
102
|
+
function configurePrompts(lang) {
|
|
103
|
+
if (lang === "zh") {
|
|
104
|
+
// 设置 prompts 的默认提示文本
|
|
105
|
+
prompts_1.default.prompts = {
|
|
106
|
+
...prompts_1.default.prompts,
|
|
107
|
+
autocomplete: {
|
|
108
|
+
instructions: "上下箭头选择,回车确认,输入过滤",
|
|
109
|
+
},
|
|
110
|
+
autocompleteMultiselect: {
|
|
111
|
+
instructions: "↑/↓: 高亮选项,←/→/空格: 选择/取消,Ctrl+A: 全选/取消全选,回车: 确认,Ctrl+C: 取消",
|
|
112
|
+
},
|
|
113
|
+
multiselect: {
|
|
114
|
+
instructions: "↑/↓: 高亮选项,空格: 选择/取消,Ctrl+A: 全选/取消全选,回车: 确认",
|
|
115
|
+
},
|
|
116
|
+
select: {
|
|
117
|
+
instructions: "↑/↓: 选择,回车: 确认",
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// 默认:交互菜单
|
|
123
|
+
program.action(async () => {
|
|
124
|
+
const unknown = getUnknownSubcommand();
|
|
125
|
+
if (unknown) {
|
|
126
|
+
console.log(kleur_1.default.red(`✗ Unknown command: ${unknown}`));
|
|
127
|
+
program.outputHelp();
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
checkPlatform();
|
|
131
|
+
showBanner();
|
|
132
|
+
await selectLanguageIfNeeded();
|
|
133
|
+
configurePrompts((0, i18n_1.getLanguage)());
|
|
134
|
+
await showMainHelpHintOnce();
|
|
135
|
+
await (0, menu_1.showMainMenu)();
|
|
136
|
+
});
|
|
137
|
+
// upgrade 子命令
|
|
138
|
+
program
|
|
139
|
+
.command("upgrade")
|
|
140
|
+
.description("升级 OKIT(默认)或工具")
|
|
141
|
+
.option("--tools", "升级所有工具")
|
|
142
|
+
.option("--menu", "打开升级菜单")
|
|
143
|
+
.action(async (options) => {
|
|
144
|
+
checkPlatform();
|
|
145
|
+
await selectLanguageIfNeeded();
|
|
146
|
+
if (options.menu) {
|
|
147
|
+
await (0, upgrade_1.showUpgradeMenu)();
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (options.tools) {
|
|
151
|
+
await (0, upgrade_1.upgradeTools)();
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
await (0, upgrade_1.upgradeSelf)();
|
|
155
|
+
});
|
|
156
|
+
// uninstall 子命令
|
|
157
|
+
program
|
|
158
|
+
.command("uninstall")
|
|
159
|
+
.description("卸载 OKIT")
|
|
160
|
+
.action(async () => {
|
|
161
|
+
checkPlatform();
|
|
162
|
+
await selectLanguageIfNeeded();
|
|
163
|
+
await (0, uninstall_1.uninstallOkit)();
|
|
164
|
+
});
|
|
165
|
+
// claude 子命令
|
|
166
|
+
program
|
|
167
|
+
.command("claude")
|
|
168
|
+
.description("Claude Code 交互菜单")
|
|
169
|
+
.action(async () => {
|
|
170
|
+
checkPlatform();
|
|
171
|
+
await selectLanguageIfNeeded();
|
|
172
|
+
await (0, menu_1.showClaudeMenu)();
|
|
173
|
+
});
|
|
174
|
+
// repo 子命令
|
|
175
|
+
const repo = program
|
|
176
|
+
.command("repo")
|
|
177
|
+
.description("Repo 设置与创建")
|
|
178
|
+
.action(async () => {
|
|
179
|
+
checkPlatform();
|
|
180
|
+
await selectLanguageIfNeeded();
|
|
181
|
+
await (0, repo_1.showRepoMenu)();
|
|
182
|
+
});
|
|
183
|
+
repo
|
|
184
|
+
.command("create")
|
|
185
|
+
.description("创建远程仓库并绑定")
|
|
186
|
+
.action(async () => {
|
|
187
|
+
checkPlatform();
|
|
188
|
+
await selectLanguageIfNeeded();
|
|
189
|
+
await (0, repo_1.createRepositoryFlow)();
|
|
190
|
+
});
|
|
191
|
+
// check 子命令 - 环境健康检查
|
|
192
|
+
program
|
|
193
|
+
.command("check")
|
|
194
|
+
.description("环境健康检查(工具版本、升级、授权状态)")
|
|
195
|
+
.option("--json", "输出 JSON 格式(适合 Agent 消费)")
|
|
196
|
+
.action(async (options) => {
|
|
197
|
+
checkPlatform();
|
|
198
|
+
await selectLanguageIfNeeded();
|
|
199
|
+
await (0, check_1.runCheck)({ json: options.json });
|
|
200
|
+
});
|
|
201
|
+
// reset 子命令 - 不需要选择语言
|
|
202
|
+
program
|
|
203
|
+
.command("reset")
|
|
204
|
+
.description("重置配置为默认")
|
|
205
|
+
.action(async () => {
|
|
206
|
+
checkPlatform();
|
|
207
|
+
// reset 使用默认中文
|
|
208
|
+
(0, i18n_1.setLanguage)("zh");
|
|
209
|
+
await (0, registry_1.resetRegistry)();
|
|
210
|
+
});
|
|
211
|
+
// web 子命令 - 启动 Web UI
|
|
212
|
+
program
|
|
213
|
+
.command("web")
|
|
214
|
+
.description("启动 Claude Code Web UI")
|
|
215
|
+
.option("-p, --port <number>", "端口号", "3000")
|
|
216
|
+
.option("-o, --open", "自动打开浏览器", false)
|
|
217
|
+
.action(async (options) => {
|
|
218
|
+
checkPlatform();
|
|
219
|
+
const port = parseInt(options.port, 10) || 3000;
|
|
220
|
+
// 动态导入 web server
|
|
221
|
+
// @ts-ignore
|
|
222
|
+
const { startServer } = await Promise.resolve().then(() => __importStar(require("./web/server.js")));
|
|
223
|
+
if (options.open) {
|
|
224
|
+
const { exec } = await Promise.resolve().then(() => __importStar(require("child_process")));
|
|
225
|
+
exec(`open http://localhost:${port}`);
|
|
226
|
+
}
|
|
227
|
+
// @ts-ignore
|
|
228
|
+
startServer(port);
|
|
229
|
+
});
|
|
230
|
+
function checkPlatform() {
|
|
231
|
+
if (process.platform !== "darwin") {
|
|
232
|
+
console.log(kleur_1.default.red("✗ 当前仅支持 macOS 平台"));
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
async function showMainHelpHintOnce() {
|
|
237
|
+
const config = await (0, user_1.loadUserConfig)();
|
|
238
|
+
if (config.hints?.mainHelpShown)
|
|
239
|
+
return;
|
|
240
|
+
console.log(kleur_1.default.gray((0, i18n_1.t)("mainHelpHint")));
|
|
241
|
+
await (0, user_1.updateUserConfig)({ hints: { mainHelpShown: true } });
|
|
242
|
+
}
|
|
243
|
+
program.parse();
|
|
244
|
+
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sound.d.ts","sourceRoot":"","sources":["../../src/utils/sound.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,GAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,OAAmB,QAmBpF;AAED;;GAEG;AACH,wBAAgB,IAAI,SAEnB"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.playSound = playSound;
|
|
4
|
+
exports.beep = beep;
|
|
5
|
+
const child_process_1 = require("child_process");
|
|
6
|
+
/**
|
|
7
|
+
* 播放提示音
|
|
8
|
+
* 使用 macOS 系统提示音或蜂鸣声
|
|
9
|
+
*/
|
|
10
|
+
function playSound(type = "success") {
|
|
11
|
+
try {
|
|
12
|
+
// 使用 macOS 的 afplay 播放系统提示音
|
|
13
|
+
const soundFiles = {
|
|
14
|
+
success: "/System/Library/Sounds/Glass.aiff",
|
|
15
|
+
error: "/System/Library/Sounds/Basso.aiff",
|
|
16
|
+
warning: "/System/Library/Sounds/Ping.aiff",
|
|
17
|
+
input: "/System/Library/Sounds/Tink.aiff",
|
|
18
|
+
};
|
|
19
|
+
const soundFile = soundFiles[type];
|
|
20
|
+
if (soundFile) {
|
|
21
|
+
// 后台播放,不阻塞程序
|
|
22
|
+
(0, child_process_1.execSync)(`afplay "${soundFile}" &`, { stdio: "ignore" });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// 如果 afplay 失败,使用蜂鸣声作为备选
|
|
27
|
+
process.stdout.write("\x07");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 蜂鸣声(最简单的方式,跨平台)
|
|
32
|
+
*/
|
|
33
|
+
function beep() {
|
|
34
|
+
process.stdout.write("\x07");
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=sound.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sound.js","sourceRoot":"","sources":["../../src/utils/sound.ts"],"names":[],"mappings":";;AAMA,8BAmBC;AAKD,oBAEC;AAhCD,iDAAyC;AAEzC;;;GAGG;AACH,SAAgB,SAAS,CAAC,OAAkD,SAAS;IACnF,IAAI,CAAC;QACH,4BAA4B;QAC5B,MAAM,UAAU,GAA2B;YACzC,OAAO,EAAE,mCAAmC;YAC5C,KAAK,EAAE,mCAAmC;YAC1C,OAAO,EAAE,kCAAkC;YAC3C,KAAK,EAAE,kCAAkC;SAC1C,CAAC;QAEF,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,SAAS,EAAE,CAAC;YACd,aAAa;YACb,IAAA,wBAAQ,EAAC,WAAW,SAAS,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,yBAAyB;QACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,IAAI;IAClB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const os = require('os');
|
|
4
|
+
|
|
5
|
+
const CLAUDE_DIR = path.join(os.homedir(), '.claude');
|
|
6
|
+
const SETTINGS_FILE = path.join(CLAUDE_DIR, 'settings.json');
|
|
7
|
+
const CLAUDE_JSON_FILE = path.join(os.homedir(), '.claude.json');
|
|
8
|
+
|
|
9
|
+
async function readSettings() {
|
|
10
|
+
try {
|
|
11
|
+
const content = await fs.readFile(SETTINGS_FILE, 'utf-8');
|
|
12
|
+
return JSON.parse(content);
|
|
13
|
+
} catch {
|
|
14
|
+
return {};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async function writeSettings(settings) {
|
|
19
|
+
await fs.writeFile(SETTINGS_FILE, JSON.stringify(settings, null, 2), 'utf-8');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function readClaudeJson() {
|
|
23
|
+
try {
|
|
24
|
+
const content = await fs.readFile(CLAUDE_JSON_FILE, 'utf-8');
|
|
25
|
+
return JSON.parse(content);
|
|
26
|
+
} catch {
|
|
27
|
+
return {};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function getConfig(req, res) {
|
|
32
|
+
try {
|
|
33
|
+
const [settings, claudeJson] = await Promise.all([
|
|
34
|
+
readSettings(),
|
|
35
|
+
readClaudeJson(),
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
res.json({
|
|
39
|
+
settings,
|
|
40
|
+
mcpServers: claudeJson.mcpServers || {},
|
|
41
|
+
});
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error('Error fetching config:', error);
|
|
44
|
+
res.status(500).json({ error: 'Failed to fetch config' });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function updateConfig(req, res) {
|
|
49
|
+
try {
|
|
50
|
+
const updates = req.body;
|
|
51
|
+
|
|
52
|
+
// Read current settings
|
|
53
|
+
const settings = await readSettings();
|
|
54
|
+
|
|
55
|
+
// Apply updates
|
|
56
|
+
const updatedSettings = { ...settings, ...updates };
|
|
57
|
+
|
|
58
|
+
// Write back
|
|
59
|
+
await writeSettings(updatedSettings);
|
|
60
|
+
|
|
61
|
+
// Return updated config
|
|
62
|
+
const claudeJson = await readClaudeJson();
|
|
63
|
+
res.json({
|
|
64
|
+
settings: updatedSettings,
|
|
65
|
+
mcpServers: claudeJson.mcpServers || {},
|
|
66
|
+
});
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.error('Error updating config:', error);
|
|
69
|
+
res.status(500).json({ error: 'Failed to update config' });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
module.exports = { getConfig, updateConfig };
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const os = require('os');
|
|
4
|
+
|
|
5
|
+
const CLAUDE_DIR = path.join(os.homedir(), '.claude');
|
|
6
|
+
const STATS_CACHE_FILE = path.join(CLAUDE_DIR, 'stats-cache.json');
|
|
7
|
+
const PROJECTS_DIR = path.join(CLAUDE_DIR, 'projects');
|
|
8
|
+
|
|
9
|
+
// Estimate cost based on model (rough estimation)
|
|
10
|
+
function estimateCost(tokens, model) {
|
|
11
|
+
// Default to Sonnet pricing if unknown
|
|
12
|
+
const inputPrice = 3e-6; // $3 per million
|
|
13
|
+
const outputPrice = 15e-6; // $15 per million
|
|
14
|
+
|
|
15
|
+
// Assume 50/50 split for estimation
|
|
16
|
+
return (tokens / 2) * inputPrice + (tokens / 2) * outputPrice;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function parseStatsCache() {
|
|
20
|
+
try {
|
|
21
|
+
const content = await fs.readFile(STATS_CACHE_FILE, 'utf-8');
|
|
22
|
+
return JSON.parse(content);
|
|
23
|
+
} catch {
|
|
24
|
+
return {};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function getProjectSessions() {
|
|
29
|
+
const sessions = [];
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
const projects = await fs.readdir(PROJECTS_DIR);
|
|
33
|
+
|
|
34
|
+
for (const projectDir of projects) {
|
|
35
|
+
const projectPath = path.join(PROJECTS_DIR, projectDir);
|
|
36
|
+
const stat = await fs.stat(projectPath);
|
|
37
|
+
|
|
38
|
+
if (!stat.isDirectory()) continue;
|
|
39
|
+
|
|
40
|
+
// Decode project name
|
|
41
|
+
const projectName = projectDir.replace(/-/g, '/').replace(/ /g, '/');
|
|
42
|
+
|
|
43
|
+
const sessionFiles = await fs.readdir(projectPath);
|
|
44
|
+
|
|
45
|
+
for (const sessionFile of sessionFiles) {
|
|
46
|
+
if (!sessionFile.endsWith('.jsonl')) continue;
|
|
47
|
+
if (sessionFile.startsWith('agent-')) continue; // Skip sub-agent sessions
|
|
48
|
+
|
|
49
|
+
const sessionPath = path.join(projectPath, sessionFile);
|
|
50
|
+
const sessionStat = await fs.stat(sessionPath);
|
|
51
|
+
|
|
52
|
+
let sessionTokens = 0;
|
|
53
|
+
let sessionModel = undefined;
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const content = await fs.readFile(sessionPath, 'utf-8');
|
|
57
|
+
const lines = content.split('\n').filter(Boolean);
|
|
58
|
+
|
|
59
|
+
for (const line of lines) {
|
|
60
|
+
try {
|
|
61
|
+
const entry = JSON.parse(line);
|
|
62
|
+
if (entry.message?.usage) {
|
|
63
|
+
sessionTokens +=
|
|
64
|
+
(entry.message.usage.input_tokens || 0) +
|
|
65
|
+
(entry.message.usage.output_tokens || 0);
|
|
66
|
+
}
|
|
67
|
+
if (entry.message?.model && !sessionModel) {
|
|
68
|
+
sessionModel = entry.message.model;
|
|
69
|
+
}
|
|
70
|
+
} catch {
|
|
71
|
+
// Skip invalid lines
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
} catch {
|
|
75
|
+
// Skip files that can't be read
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
sessions.push({
|
|
79
|
+
sessionId: sessionFile.replace('.jsonl', ''),
|
|
80
|
+
project: projectName,
|
|
81
|
+
timestamp: sessionStat.mtimeMs,
|
|
82
|
+
tokens: sessionTokens,
|
|
83
|
+
model: sessionModel,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
} catch {
|
|
88
|
+
// Return empty if projects dir doesn't exist
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Sort by timestamp descending
|
|
92
|
+
return sessions.sort((a, b) => b.timestamp - a.timestamp);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function getStats(req, res) {
|
|
96
|
+
try {
|
|
97
|
+
const [cache, sessions] = await Promise.all([
|
|
98
|
+
parseStatsCache(),
|
|
99
|
+
getProjectSessions(),
|
|
100
|
+
]);
|
|
101
|
+
|
|
102
|
+
const totalTokens = sessions.reduce((sum, s) => sum + s.tokens, 0);
|
|
103
|
+
const totalCost = estimateCost(totalTokens);
|
|
104
|
+
const sessionCount = sessions.length;
|
|
105
|
+
|
|
106
|
+
// Extract metrics from cache if available
|
|
107
|
+
const activeTime = cache.active_time_total || 0;
|
|
108
|
+
const linesOfCode = cache.lines_of_code_count || 0;
|
|
109
|
+
const commitCount = cache.commit_count || 0;
|
|
110
|
+
const prCount = cache.pull_request_count || 0;
|
|
111
|
+
|
|
112
|
+
const response = {
|
|
113
|
+
totalTokens,
|
|
114
|
+
totalCost,
|
|
115
|
+
sessionCount,
|
|
116
|
+
activeTime,
|
|
117
|
+
linesOfCode,
|
|
118
|
+
commitCount,
|
|
119
|
+
prCount,
|
|
120
|
+
recentSessions: sessions.slice(0, 20), // Last 20 sessions
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
res.json(response);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.error('Error fetching stats:', error);
|
|
126
|
+
res.status(500).json({ error: 'Failed to fetch stats' });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
module.exports = { getStats };
|