@dahawa/hawa-cli-analysis 1.0.4

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/.tools.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "tools": {
3
+ "blacklist": [],
4
+ "descriptions": {
5
+ }
6
+ }
7
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": [
7
+ {
8
+ "name": "Launch Program2",
9
+ "program": "${workspaceFolder}/codex/mcpserver.js",
10
+ "request": "launch",
11
+ "skipFiles": [
12
+ "<node_internals>/**"
13
+ ],
14
+ "type": "node"
15
+ },
16
+
17
+ {
18
+ "type": "node",
19
+ "request": "launch",
20
+ "name": "Launch Program",
21
+ "skipFiles": [
22
+ "<node_internals>/**"
23
+ ],
24
+ "program": "${workspaceFolder}\\tests\\test.js"
25
+ }
26
+ ]
27
+ }
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,196 @@
1
+ # Hawa CLI 分析工具
2
+
3
+ 这是一个用于增强 Claude CLI、Codex CLI 的上下文日志分析工具。通过代理模式拦截和分析 API 调用,提供详细的日志记录和分析功能。
4
+
5
+ ## 🌟 功能特性
6
+
7
+ - **多 CLI 支持**: 支持 Claude CLI、Codex CLI
8
+ - **代理模式**: 通过本地代理服务器拦截和分析 API 调用
9
+ - **详细日志记录**: 记录所有 API 请求和响应,支持完整和简化日志模式
10
+ - **多模型支持**: 支持 Kimi、DeepSeek、OpenRouter 等多种 AI 模型
11
+ - **MCP 服务器代理**: 支持 MCP (Model Context Protocol) 服务器代理
12
+ - **端口管理**: 自动分配可用端口,避免端口冲突
13
+ - **配置管理**: 灵活的配置文件管理,支持多环境配置
14
+ - **多进程支持**: 支持多进程多个端口同时运行
15
+
16
+ ## 📋 支持的 CLI 工具
17
+
18
+ ### 1. Claude CLI (`uclaude`)
19
+ - 支持 Claude Code 命令行工具
20
+ - 支持多种 AI 模型 (Kimi, DeepSeek, OpenRouter)
21
+ - 自动代理配置和端口管理
22
+
23
+ ### 2. Codex CLI (`ucodex`)
24
+ - 支持 OpenAI Codex 命令行工具
25
+ - 使用代理模式进行日志获取
26
+ - 支持多种 AI 模型配置
27
+
28
+ ## 🚀 安装方式
29
+
30
+ ### 前置要求
31
+ - Node.js >= 16.0.0
32
+ - npm 或 yarn
33
+
34
+ ### 安装步骤
35
+
36
+ ```bash
37
+ npm install -g @dahawa/hawa-cli-analysis
38
+ ```
39
+
40
+ 1. **克隆项目**
41
+ ```bash
42
+ git clone https://github.com/jiweigang1/hawa-cli-analysis.git
43
+ cd hawa-cli-analysis
44
+ ```
45
+
46
+ 2. **安装依赖**
47
+ ```bash
48
+ npm install
49
+ ```
50
+
51
+ 3. **链接到全局**
52
+ ```bash
53
+ npm link
54
+ ```
55
+
56
+ 4. **初始化配置** (首次使用)
57
+ ```bash
58
+ # 运行任意命令会自动创建配置文件
59
+ uclaude
60
+ ```
61
+
62
+ ## ⚙️ 配置说明
63
+
64
+ ### 配置文件位置
65
+ 配置文件位于用户主目录下的 `.hawa-cli-analysis/config.json`:
66
+ - **Windows**: `C:\Users\用户名\.hawa-cli-analysis\config.json`
67
+ - **macOS/Linux**: `~/.hawa-cli-analysis/config.json`
68
+
69
+ ### 默认配置
70
+ ```json
71
+ {
72
+ "kimi-k2": {
73
+ "enable": false,
74
+ "env": {
75
+ "BASE_URL": "https://api.moonshot.cn/anthropic",
76
+ "AUTH_TOKEN": "sk-{使用自己的token}",
77
+ "MODEL": "kimi-k2-0905-preview",
78
+ "SMALL_FAST_MODEL": "kimi-k2-0905-preview"
79
+ }
80
+ },
81
+ "deepseek": {
82
+ "enable": false,
83
+ "env": {
84
+ "BASE_URL": "https://api.deepseek.com/anthropic",
85
+ "AUTH_TOKEN": "sk-{使用自己的token}",
86
+ "API_TIMEOUT_MS": "600000",
87
+ "MODEL": "deepseek-chat",
88
+ "SMALL_FAST_MODEL": "deepseek-chat",
89
+ "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
90
+ }
91
+ },
92
+ "openrouter": {
93
+ "enable": false,
94
+ "env": {
95
+ "BASE_URL": "http://127.0.0.1:3000",
96
+ "AUTH_TOKEN": "sk-or-v1-{使用自己的token}",
97
+ "MODEL": "anthropic/claude-sonnet-4",
98
+ "SMALL_FAST_MODEL": "anthropic/claude-sonnet-4"
99
+ }
100
+ }
101
+ }
102
+ ```
103
+
104
+ ### 启用模型
105
+ 将对应模型的 `enable` 设置为 `true`,并填入您的 API Token。
106
+
107
+ ## 📖 使用方法
108
+
109
+ ### Claude CLI 使用
110
+ ```bash
111
+ # 启动 Claude CLI
112
+ uclaude
113
+
114
+ # 选择启用的模型,程序会自动启动代理服务器和 Claude Code
115
+ ```
116
+
117
+ ### Codex CLI 使用
118
+ ```bash
119
+ # 启动 Codex CLI
120
+ ucodex
121
+
122
+ # 程序会自动启动代理服务器和 Codex CLI
123
+ ```
124
+
125
+ ## 🔧 高级配置
126
+
127
+ ### MCP 服务器配置
128
+ 支持配置 MCP (Model Context Protocol) 服务器:
129
+
130
+ 配置文件位置:`~/.hawa-cli-analysis/mcp.json`
131
+
132
+ ```json
133
+ {
134
+ "mcpServers": {
135
+ "supabase": {
136
+ "url": "https://mcp.supabase.com/mcp",
137
+ "bearer_token": "sbp_xxxxx",
138
+ "tools": {
139
+ "blacklist": ["tool_name_to_exclude"],
140
+ "descriptions": {
141
+ "tool_name": "Custom description for this tool"
142
+ }
143
+ }
144
+ }
145
+ }
146
+ }
147
+ ```
148
+
149
+ ### 环境变量
150
+ - `LOG_LEVEL`: 日志级别 (debug, info, warn, error)
151
+ - `PIPE_PATH_PRE`: 管道路径前缀
152
+ - `BASE_URL`: API 基础地址
153
+ - `AUTH_TOKEN`: API 认证令牌
154
+
155
+ ## 📁 项目结构
156
+
157
+ ```
158
+ hawa-cli-analysis/
159
+ ├── api-anthropic.js # Anthropic API 处理
160
+ ├── api-openai.js # OpenAI API 处理
161
+ ├── anthropic-transformer.js # Anthropic 数据转换
162
+ ├── clogger.js # 主日志模块
163
+ ├── clogger-openai.js # OpenAI 日志模块
164
+ ├── config.js # 配置管理
165
+ ├── logger-manager.js # 日志管理器
166
+ ├── logger.js # 日志模块
167
+ ├── mcp_oauth_tokens.js # MCP OAuth 令牌
168
+ ├── port-manager.js # 端口管理
169
+ ├── simple-transform-example.js # 简单转换示例
170
+ ├── ucodex-proxy.js # Codex 代理
171
+ ├── uclaude.js # Claude CLI 启动器
172
+ ├── ucodex.js # Codex CLI 启动器
173
+ ├── untils.js # 工具函数
174
+ ├── _uclaude.js # Claude CLI 备用启动器
175
+ ├── index.js # 主入口文件
176
+ ├── claude/ # Claude 相关配置
177
+ ├── codex/ # Codex 相关配置
178
+ ├── mcp/ # MCP 服务器配置
179
+ ├── tests/ # 测试文件
180
+ └── package.json
181
+ ```
182
+
183
+ ## 🔍 日志文件
184
+
185
+ 日志文件保存在用户主目录下的 `.hawa-cli-analysis/logs/` 目录中:
186
+ - **系统日志**: `system/api-simple-{timestamp}.log`
187
+ - **完整日志**: `{cli-type}/api-full-{timestamp}.log`
188
+ - **简化日志**: `{cli-type}/api-simple-{timestamp}.log`
189
+
190
+ ## 🤝 贡献指南
191
+
192
+ 欢迎提交 Issue 和 Pull Request!
193
+
194
+ ## 📄 许可证
195
+
196
+ ISC License
package/_uclaude.js ADDED
@@ -0,0 +1,165 @@
1
+ #!/usr/bin/env node
2
+
3
+ global.CLI_TYPE = "claude"
4
+ import {initConfig,loadConfig} from "./config.js"
5
+ import readline from 'readline';
6
+ import { spawn } from 'child_process';
7
+ import {getClaudePath} from './untils.js';
8
+ import inquirer from 'inquirer';
9
+ import path from "path";
10
+ import { fileURLToPath, pathToFileURL } from "url";
11
+ import LogManager from './logger-manager.js';
12
+
13
+ const logger = LogManager.getSystemLogger();
14
+
15
+ /**
16
+ * 启动 calude code
17
+ */
18
+ function start(){
19
+ initConfig();
20
+ let allConfig = loadConfig();
21
+ let choices = [];
22
+ Object.entries(allConfig).forEach(([key, value], index) => {
23
+ if (value.enable === true) {
24
+ choices.push({ name: `${index}. ${key}`, value: key });
25
+ }
26
+ });
27
+
28
+ // 检查是否有启用的模型
29
+ if (choices.length === 0) {
30
+ console.error("错误:没有启用的模型配置!");
31
+ console.log("请检查配置文件,确保至少有一个模型的 enable 设置为 true。");
32
+ logger.error("没有启用的模型配置,程序退出");
33
+ process.exit(1);
34
+ }
35
+
36
+ (async () => {
37
+ const answers = await inquirer.prompt([
38
+ {
39
+ type: "list", // 单选模式
40
+ name: "choice", // 返回结果的 key
41
+ message: "请选择一个模型:",
42
+ choices: choices
43
+ }
44
+ ]);
45
+
46
+ var config = allConfig[answers.choice];
47
+ let env = config.env;
48
+ // 添加 ANTHROPIC_ 前缀到环境变量
49
+ let anthropicEnv = {};
50
+ Object.keys(env).forEach(key => {
51
+ if (['BASE_URL', 'AUTH_TOKEN', 'MODEL', 'SMALL_FAST_MODEL'].includes(key)) {
52
+ anthropicEnv[`ANTHROPIC_${key}`] = env[key];
53
+ } else {
54
+ anthropicEnv[key] = env[key];
55
+ }
56
+ });
57
+ // claudecode 环境变量是可以通过 env 传递到 mcpserver
58
+ let claudePath = config?.CLAUDE_PATH || process.env.CLAUDE_PATH || getClaudePath();
59
+ let dir = path.dirname(fileURLToPath(import.meta.url));
60
+ if(answers.choice=="openrouter"){
61
+ claudePath = "node --import " + pathToFileURL(path.join(dir, 'clogger-openai.js')) + " " + claudePath;
62
+ }else{
63
+ claudePath = "node --import "+ pathToFileURL(path.join(dir, 'clogger.js')) + " " + claudePath;
64
+ }
65
+
66
+ logger.debug(`启动 Claude 进程: ${claudePath}`);
67
+
68
+ const child = spawn(claudePath,[],{
69
+ env:{
70
+ ...anthropicEnv,
71
+ PIPE_PATH_PRE: process.pid
72
+ },
73
+ stdio: 'inherit', // 继承父进程 stdio,方便交互,
74
+ shell: true
75
+ }
76
+ );
77
+
78
+ child.on("error", (error) => {
79
+ console.error("Failed to start claude command:", error.message);
80
+ logger.debug(
81
+ "Make sure Claude Code is installed: npm install -g @anthropic-ai/claude-code"
82
+ );
83
+ process.exit(1);
84
+ });
85
+
86
+ child.on("close", (code) => {
87
+ process.exit(code || 0);
88
+ });
89
+
90
+
91
+ })();
92
+
93
+
94
+
95
+ }
96
+ // 这里需要判断是否启动完成,不然后面 mcp 会连接失败
97
+ /**
98
+ function startMCPServerProxy(){
99
+ let dir = path.dirname(fileURLToPath(import.meta.url));
100
+ // 启动 MCP 代理服务
101
+ const child = spawn("node " + (path.join(dir, "mcp" ,'claude-mcpproxy-launcher.js')), [], {
102
+ stdio: "pipe" ,
103
+ shell: true,
104
+ env: {
105
+ PIPE_PATH_PRE: process.pid
106
+ }
107
+ });
108
+
109
+ child.stdout.on("data", (data) => {
110
+ console.log("子进程输出:", data.toString());
111
+ });
112
+
113
+ child.on("error", (error) => {
114
+ console.error("Failed to start MCP server proxy:", error.message);
115
+ process.exit(1);
116
+ });
117
+
118
+ child.on("close", (code) => {
119
+ process.exit(code || 0);
120
+ });
121
+ }
122
+ */
123
+
124
+ async function startMCPServerProxy() {
125
+ return new Promise((resolve, reject) => {
126
+ const dir = path.dirname(fileURLToPath(import.meta.url));
127
+ const child = spawn("node " + path.join(dir, "mcp", "claude-mcpproxy-launcher.js"), [], {
128
+ stdio: "pipe",
129
+ shell: true,
130
+ env: {
131
+ PIPE_PATH_PRE: process.pid
132
+ }
133
+ });
134
+
135
+ child.stdout.on("data", (data) => {
136
+ const msg = data.toString().trim();
137
+ //console.log("子进程输出:", msg);
138
+ if (msg.includes("ok_ok")) {
139
+ resolve("MCP server proxy started successfully");
140
+ }
141
+ });
142
+
143
+ child.stderr.on("data", (data) => {
144
+ console.error("子进程错误输出:", data.toString());
145
+ });
146
+
147
+ child.on("error", (error) => {
148
+ reject(new Error("Failed to start MCP server proxy: " + error.message));
149
+ });
150
+
151
+ child.on("close", (code) => {
152
+ if (code !== 0) {
153
+ reject(new Error("MCP server proxy exited with code " + code));
154
+ }
155
+ });
156
+ });
157
+ }
158
+
159
+ async function main(){
160
+ console.log("Starting MCP server proxy...");
161
+ await startMCPServerProxy();
162
+ console.log("MCP server proxy started successfully.");
163
+ start();
164
+ }
165
+ await main();