@ian2018cs/agenthub 0.1.2 → 0.1.3
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/package.json
CHANGED
|
@@ -7,6 +7,28 @@ description: 将生成的 HTML 或前端页面部署到 Docker nginx 容器。
|
|
|
7
7
|
|
|
8
8
|
将前端项目部署到共享的 nginx Docker 容器,通过不同端口和配置文件实现项目隔离。
|
|
9
9
|
|
|
10
|
+
## 快速开始
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# 1. 确保你有一个包含 index.html 的目录
|
|
14
|
+
mkdir my-project
|
|
15
|
+
echo "<h1>Hello World</h1>" > my-project/index.html
|
|
16
|
+
|
|
17
|
+
# 2. 使用 python3 部署(注意:是目录,不是文件)
|
|
18
|
+
python3 /path/to/deploy-frontend/scripts/deploy.py my-project
|
|
19
|
+
|
|
20
|
+
# 3. 访问输出的 URL,例如 http://10.0.1.133:8080
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 常见错误
|
|
24
|
+
|
|
25
|
+
| 错误 | 原因 | 解决方案 |
|
|
26
|
+
|------|------|----------|
|
|
27
|
+
| `python: command not found` | 使用了 `python` 而不是 `python3` | 使用 `python3` 命令 |
|
|
28
|
+
| `NotADirectoryError` | 传入了单个文件而不是目录 | 传入包含 index.html 的目录路径 |
|
|
29
|
+
| `404 Not Found` | 主文件不叫 index.html | 将主 HTML 文件重命名为 index.html |
|
|
30
|
+
| 本地能访问,其他设备不能 | IP 地址或网络问题 | 使用内网 IP,检查防火墙 |
|
|
31
|
+
|
|
10
32
|
## 配置
|
|
11
33
|
|
|
12
34
|
默认 nginx 目录已配置为:`/home/xubuntu001/AI/nginx`
|
|
@@ -27,9 +49,15 @@ description: 将生成的 HTML 或前端页面部署到 Docker nginx 容器。
|
|
|
27
49
|
使用 `scripts/deploy.py` 部署项目:
|
|
28
50
|
|
|
29
51
|
```bash
|
|
30
|
-
|
|
52
|
+
python3 scripts/deploy.py <前端项目目录>
|
|
31
53
|
```
|
|
32
54
|
|
|
55
|
+
**重要说明:**
|
|
56
|
+
- 必须使用 `python3` 命令(不是 `python`)
|
|
57
|
+
- `<前端项目目录>`:必须是一个**目录**(不能是单个文件)
|
|
58
|
+
- 目录中必须包含 `index.html` 作为入口文件(nginx 默认查找 index.html)
|
|
59
|
+
- 如果你的 HTML 文件不叫 `index.html`,需要先重命名
|
|
60
|
+
|
|
33
61
|
**参数说明:**
|
|
34
62
|
- `<前端项目目录>`:包含 index.html 等前端文件的目录(必需)
|
|
35
63
|
|
|
@@ -47,7 +75,14 @@ python scripts/deploy.py <前端项目目录>
|
|
|
47
75
|
**示例:**
|
|
48
76
|
```bash
|
|
49
77
|
# 部署前端项目(使用默认 nginx 目录)
|
|
50
|
-
|
|
78
|
+
python3 .claude/skills/deploy-frontend/scripts/deploy.py ./my-frontend-app
|
|
79
|
+
|
|
80
|
+
# 错误示例 - 不要这样做:
|
|
81
|
+
# python3 deploy.py ./my-app/index.html ❌ 不能传单个文件
|
|
82
|
+
# python deploy.py ./my-app ❌ 必须使用 python3
|
|
83
|
+
|
|
84
|
+
# 正确示例:
|
|
85
|
+
# python3 deploy.py ./my-app ✅ 传目录,使用 python3
|
|
51
86
|
```
|
|
52
87
|
|
|
53
88
|
**输出示例:**
|
|
@@ -67,13 +102,13 @@ HTML 目录: /path/to/nginx/html/project-1738151234
|
|
|
67
102
|
### 列出所有部署
|
|
68
103
|
|
|
69
104
|
```bash
|
|
70
|
-
|
|
105
|
+
python3 scripts/cleanup.py list
|
|
71
106
|
```
|
|
72
107
|
|
|
73
108
|
### 清理指定项目
|
|
74
109
|
|
|
75
110
|
```bash
|
|
76
|
-
|
|
111
|
+
python3 scripts/cleanup.py <project_id>
|
|
77
112
|
```
|
|
78
113
|
|
|
79
114
|
会删除:
|
|
@@ -86,7 +121,7 @@ python scripts/cleanup.py <project_id>
|
|
|
86
121
|
### 清理所有项目
|
|
87
122
|
|
|
88
123
|
```bash
|
|
89
|
-
|
|
124
|
+
python3 scripts/cleanup.py all
|
|
90
125
|
```
|
|
91
126
|
|
|
92
127
|
## 目录结构
|
|
@@ -124,9 +159,9 @@ nginx-base/
|
|
|
124
159
|
import subprocess
|
|
125
160
|
|
|
126
161
|
result = subprocess.run([
|
|
127
|
-
"
|
|
162
|
+
"python3", # 必须使用 python3
|
|
128
163
|
str(Path.home() / ".claude/skills/deploy-frontend/scripts/deploy.py"),
|
|
129
|
-
"./frontend-output"
|
|
164
|
+
"./frontend-output" # 必须是目录,不能是单个文件
|
|
130
165
|
], capture_output=True, text=True)
|
|
131
166
|
|
|
132
167
|
print(result.stdout)
|
|
@@ -139,7 +174,7 @@ nginx-base/
|
|
|
139
174
|
当用户要求生成前端页面时:
|
|
140
175
|
|
|
141
176
|
1. 生成前端代码(HTML/CSS/JS 等)
|
|
142
|
-
2.
|
|
177
|
+
2. 将文件写入目录(确保主文件命名为 index.html)
|
|
143
178
|
3. 调用 deploy.py 部署
|
|
144
179
|
4. 将访问 URL 返回给用户
|
|
145
180
|
|
|
@@ -149,14 +184,14 @@ nginx-base/
|
|
|
149
184
|
output_dir = Path("/tmp/frontend-{timestamp}")
|
|
150
185
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
151
186
|
|
|
152
|
-
# 2.
|
|
153
|
-
(output_dir / "index.html").write_text(html_content)
|
|
187
|
+
# 2. 写入前端文件(重要:主文件必须命名为 index.html)
|
|
188
|
+
(output_dir / "index.html").write_text(html_content) # ✅ 使用 index.html
|
|
154
189
|
(output_dir / "style.css").write_text(css_content)
|
|
155
190
|
|
|
156
|
-
# 3.
|
|
191
|
+
# 3. 部署(使用 python3,传目录而不是文件)
|
|
157
192
|
deploy_script = Path.home() / ".claude/skills/deploy-frontend/scripts/deploy.py"
|
|
158
193
|
result = subprocess.run(
|
|
159
|
-
["
|
|
194
|
+
["python3", str(deploy_script), str(output_dir)], # ✅ python3 + 目录路径
|
|
160
195
|
capture_output=True,
|
|
161
196
|
text=True
|
|
162
197
|
)
|
|
@@ -190,6 +225,13 @@ newgrp docker
|
|
|
190
225
|
|
|
191
226
|
## 更新日志
|
|
192
227
|
|
|
228
|
+
### v1.2 (2026-01-30)
|
|
229
|
+
- ✅ 更新文档:明确必须使用 `python3` 而不是 `python`
|
|
230
|
+
- ✅ 更新文档:强调必须传入目录而不是单个文件
|
|
231
|
+
- ✅ 更新文档:说明主文件必须命名为 `index.html`
|
|
232
|
+
- ✅ 添加常见错误示例和最佳实践
|
|
233
|
+
- ✅ 新增部署后文件重命名的故障排查说明
|
|
234
|
+
|
|
193
235
|
### v1.1 (2026-01-30)
|
|
194
236
|
- ✅ 修复正则表达式转义警告
|
|
195
237
|
- ✅ 添加自动 Docker 权限处理(`run_docker_command` 函数)
|
|
@@ -207,6 +249,36 @@ newgrp docker
|
|
|
207
249
|
|
|
208
250
|
**权限问题**:脚本会自动使用 `sg docker -c` 处理权限问题
|
|
209
251
|
|
|
252
|
+
**找不到 python 命令**:
|
|
253
|
+
```bash
|
|
254
|
+
# 错误:python: command not found
|
|
255
|
+
# 解决:使用 python3
|
|
256
|
+
python3 scripts/deploy.py ./my-app
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
**传入单个文件报错**:
|
|
260
|
+
```bash
|
|
261
|
+
# 错误:NotADirectoryError
|
|
262
|
+
# 原因:传入的是文件而不是目录
|
|
263
|
+
# 解决:传入包含 index.html 的目录
|
|
264
|
+
python3 scripts/deploy.py ./my-app/ # 正确
|
|
265
|
+
# 而不是
|
|
266
|
+
python3 scripts/deploy.py ./my-app/index.html # 错误
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**页面无法访问(404 Not Found)**:
|
|
270
|
+
```bash
|
|
271
|
+
# 检查是否存在 index.html
|
|
272
|
+
ls /home/xubuntu001/AI/nginx/html/project-*/
|
|
273
|
+
|
|
274
|
+
# 如果文件名不是 index.html,重命名它:
|
|
275
|
+
cd /home/xubuntu001/AI/nginx/html/project-xxxxxxxxxx/
|
|
276
|
+
mv yourfile.html index.html
|
|
277
|
+
|
|
278
|
+
# 重新加载 nginx
|
|
279
|
+
sg docker -c "docker exec nginx-web nginx -s reload"
|
|
280
|
+
```
|
|
281
|
+
|
|
210
282
|
**配置未生效**:手动重新加载 nginx:
|
|
211
283
|
```bash
|
|
212
284
|
docker exec nginx-web nginx -s reload
|
|
@@ -218,3 +290,9 @@ sg docker -c "docker exec nginx-web nginx -s reload"
|
|
|
218
290
|
```bash
|
|
219
291
|
docker logs nginx-web
|
|
220
292
|
```
|
|
293
|
+
|
|
294
|
+
**本地能访问,其他设备访问不了**:
|
|
295
|
+
- 检查防火墙设置
|
|
296
|
+
- 确认设备在同一网络
|
|
297
|
+
- 使用正确的内网 IP(不要用 localhost)
|
|
298
|
+
- 确认路由器没有阻止端口
|
|
@@ -97,12 +97,6 @@ const builtInCommands = [
|
|
|
97
97
|
namespace: 'builtin',
|
|
98
98
|
metadata: { type: 'builtin' }
|
|
99
99
|
},
|
|
100
|
-
{
|
|
101
|
-
name: '/cost',
|
|
102
|
-
description: 'Display token usage and cost information',
|
|
103
|
-
namespace: 'builtin',
|
|
104
|
-
metadata: { type: 'builtin' }
|
|
105
|
-
},
|
|
106
100
|
{
|
|
107
101
|
name: '/memory',
|
|
108
102
|
description: 'Open CLAUDE.md memory file for editing',
|
|
@@ -314,39 +308,8 @@ Custom commands can be created in:
|
|
|
314
308
|
message: `Rewinding conversation by ${steps} step${steps > 1 ? 's' : ''}...`
|
|
315
309
|
}
|
|
316
310
|
};
|
|
317
|
-
},
|
|
318
|
-
|
|
319
|
-
'/cost': async (args, context) => {
|
|
320
|
-
const tokenUsage = context?.tokenUsage;
|
|
321
|
-
|
|
322
|
-
if (!tokenUsage) {
|
|
323
|
-
return {
|
|
324
|
-
type: 'builtin',
|
|
325
|
-
action: 'cost',
|
|
326
|
-
data: {
|
|
327
|
-
message: 'No token usage data available for this session.',
|
|
328
|
-
usage: null
|
|
329
|
-
}
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
const { used = 0, total = 160000 } = tokenUsage;
|
|
334
|
-
const percentage = total > 0 ? ((used / total) * 100).toFixed(1) : 0;
|
|
335
|
-
|
|
336
|
-
return {
|
|
337
|
-
type: 'builtin',
|
|
338
|
-
action: 'cost',
|
|
339
|
-
data: {
|
|
340
|
-
usage: {
|
|
341
|
-
used,
|
|
342
|
-
total,
|
|
343
|
-
percentage: parseFloat(percentage),
|
|
344
|
-
remaining: total - used
|
|
345
|
-
},
|
|
346
|
-
message: `Token usage: ${used.toLocaleString()} / ${total.toLocaleString()} (${percentage}%)`
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
311
|
}
|
|
312
|
+
|
|
350
313
|
};
|
|
351
314
|
|
|
352
315
|
/**
|
package/server/routes/usage.js
CHANGED
|
@@ -159,10 +159,10 @@ router.get('/dashboard', (req, res) => {
|
|
|
159
159
|
const stats = usageDb.getDashboardStats(startDate, endDate);
|
|
160
160
|
const users = userDb.getAllUsers();
|
|
161
161
|
|
|
162
|
-
// Create username map
|
|
162
|
+
// Create username map (prefer username, fallback to email)
|
|
163
163
|
const usernameMap = {};
|
|
164
164
|
for (const user of users) {
|
|
165
|
-
usernameMap[user.uuid] = user.username;
|
|
165
|
+
usernameMap[user.uuid] = user.username || user.email;
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
// Enrich top users with usernames
|