@bitseek/hermes-webui 0.1.1 → 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/README.md +18 -28
- package/bin/hermes-webui.mjs +65 -10
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# BitSeek Claw WebUI
|
|
2
2
|
|
|
3
|
-
`@bitseek/hermes-webui` 用来在本机启动和管理
|
|
4
|
-
|
|
5
|
-
它是一个轻量级 npm 包装器,负责进程生命周期、健康检查、日志和运行时状态。
|
|
6
|
-
WebUI 本体来自 vendored `agent-frontend-shell` 运行时。
|
|
3
|
+
`@bitseek/hermes-webui` 用来在本机启动和管理 BitSeek Claw WebUI。
|
|
7
4
|
|
|
8
5
|
## 快速开始
|
|
9
6
|
|
|
@@ -39,7 +36,7 @@ hermes-webui start --port 8788 --open
|
|
|
39
36
|
- 如果 WebUI 要调用 Hermes Agent,需要准备 Hermes Agent checkout,并确保其中有
|
|
40
37
|
`run_agent.py`。
|
|
41
38
|
|
|
42
|
-
|
|
39
|
+
默认情况下,WebUI 会尝试从以下位置查找 Hermes Agent:
|
|
43
40
|
|
|
44
41
|
```text
|
|
45
42
|
$HERMES_HOME/hermes-agent
|
|
@@ -79,13 +76,16 @@ hermes-webui doctor
|
|
|
79
76
|
|
|
80
77
|
## 首次启动会做什么
|
|
81
78
|
|
|
82
|
-
第一次运行 `hermes-webui start`
|
|
79
|
+
第一次运行 `hermes-webui start` 时,WebUI 会:
|
|
83
80
|
|
|
84
81
|
- 创建运行时状态目录。
|
|
85
82
|
- 创建并管理 Python venv。
|
|
86
|
-
-
|
|
83
|
+
- 安装 WebUI 所需的 Python 依赖。
|
|
84
|
+
- 检查当前 Python 是否能导入 Hermes Agent;如果不能,会把
|
|
85
|
+
`HERMES_WEBUI_AGENT_DIR` 指向的 Hermes Agent 以 editable 模式安装到 WebUI
|
|
86
|
+
venv。
|
|
87
87
|
- 默认启用 BitSeek 外观和扩展入口,包括 “AI 同事” 页面。
|
|
88
|
-
- 启动
|
|
88
|
+
- 启动 BitSeek Claw WebUI 服务。
|
|
89
89
|
- 等待 `/health` 健康检查通过。
|
|
90
90
|
- 把 PID、日志路径和运行时信息写入状态目录。
|
|
91
91
|
|
|
@@ -140,9 +140,8 @@ HERMES_WEBUI_EXTENSION_SCRIPT_URLS 默认 /extensions/themes/bitseek/inde
|
|
|
140
140
|
HERMES_WEBUI_BOT_NAME 默认 BitSeek Claw
|
|
141
141
|
```
|
|
142
142
|
|
|
143
|
-
这些默认值在 macOS、Linux、Windows
|
|
144
|
-
|
|
145
|
-
可以覆盖默认值。
|
|
143
|
+
这些默认值在 macOS、Linux、Windows 上都可用。显式设置同名环境变量可以覆盖
|
|
144
|
+
默认值。
|
|
146
145
|
|
|
147
146
|
示例:
|
|
148
147
|
|
|
@@ -152,7 +151,7 @@ export HERMES_WEBUI_AGENT_DIR="$HERMES_HOME/hermes-agent"
|
|
|
152
151
|
hermes-webui start --port 8787 --open
|
|
153
152
|
```
|
|
154
153
|
|
|
155
|
-
|
|
154
|
+
如果不想使用默认 venv,可以指定已有 Python:
|
|
156
155
|
|
|
157
156
|
```bash
|
|
158
157
|
export HERMES_WEBUI_PYTHON=/usr/bin/python3
|
|
@@ -174,23 +173,14 @@ hermes-webui doctor
|
|
|
174
173
|
`HERMES_WEBUI_PYTHON`。
|
|
175
174
|
- `Hermes Agent dir: not found`:设置 `HERMES_WEBUI_AGENT_DIR` 指向包含
|
|
176
175
|
`run_agent.py` 的 Hermes Agent 目录。
|
|
177
|
-
- `
|
|
178
|
-
|
|
176
|
+
- `AIAgent importable: fail`:当前 WebUI Python 不能导入 Hermes Agent。运行
|
|
177
|
+
`hermes-webui start` 会自动尝试修复;如果仍失败,请查看 `server.log` 和
|
|
178
|
+
`pip install -e` 的错误输出。
|
|
179
|
+
- `WebUI runtime is missing`:发布包缺少必要文件,需要维护者重新打包并发布。
|
|
179
180
|
|
|
180
181
|
## 维护者说明
|
|
181
182
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
```text
|
|
185
|
-
repo: adv-org/agent-frontend-shell
|
|
186
|
-
branch: dev-zkp
|
|
187
|
-
source checkout: /home/boj/hermes/agent-frontend-shell
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
该包装器不会把 Python + 原生 JavaScript WebUI 重写成 Node 应用,只负责用 npm
|
|
191
|
-
包形式分发和启动 vendored 运行时。
|
|
192
|
-
|
|
193
|
-
更新 vendored 运行时:
|
|
183
|
+
同步 WebUI 文件:
|
|
194
184
|
|
|
195
185
|
```bash
|
|
196
186
|
npm run sync:vendor
|
|
@@ -209,7 +199,7 @@ npm pack --dry-run
|
|
|
209
199
|
bin/
|
|
210
200
|
scripts/
|
|
211
201
|
templates/
|
|
212
|
-
vendor/
|
|
202
|
+
vendor/
|
|
213
203
|
README.md
|
|
214
204
|
```
|
|
215
205
|
|
package/bin/hermes-webui.mjs
CHANGED
|
@@ -218,6 +218,54 @@ function pythonImportsOk(python) {
|
|
|
218
218
|
return result.status === 0
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
+
function aiAgentImportCheck(python, agentDir) {
|
|
222
|
+
if (!python || !agentDir) {
|
|
223
|
+
return { ok: false, error: 'python or Hermes Agent dir not found' }
|
|
224
|
+
}
|
|
225
|
+
const env = {
|
|
226
|
+
...process.env,
|
|
227
|
+
HERMES_WEBUI_AGENT_DIR: agentDir,
|
|
228
|
+
PYTHONPATH: process.env.PYTHONPATH
|
|
229
|
+
? `${agentDir}${delimiter}${process.env.PYTHONPATH}`
|
|
230
|
+
: agentDir,
|
|
231
|
+
}
|
|
232
|
+
const result = spawnSync(python, ['-c', 'from run_agent import AIAgent; print("ok")'], {
|
|
233
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
234
|
+
env,
|
|
235
|
+
encoding: 'utf8',
|
|
236
|
+
})
|
|
237
|
+
return {
|
|
238
|
+
ok: result.status === 0,
|
|
239
|
+
error: (result.stderr || result.stdout || '').trim(),
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function ensureAiAgentImportable(python, agentDir) {
|
|
244
|
+
if (!agentDir) return
|
|
245
|
+
|
|
246
|
+
let check = aiAgentImportCheck(python, agentDir)
|
|
247
|
+
if (check.ok) return
|
|
248
|
+
|
|
249
|
+
const pyprojectPath = join(agentDir, 'pyproject.toml')
|
|
250
|
+
if (!existsSync(pyprojectPath)) {
|
|
251
|
+
throw new Error(`Hermes Agent cannot be imported and pyproject.toml was not found: ${pyprojectPath}`)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
console.log(`Installing Hermes Agent into WebUI Python env: ${agentDir}`)
|
|
255
|
+
const install = spawnSync(python, ['-m', 'pip', 'install', '-e', agentDir], {
|
|
256
|
+
stdio: 'inherit',
|
|
257
|
+
env: process.env,
|
|
258
|
+
})
|
|
259
|
+
if (install.status !== 0) {
|
|
260
|
+
throw new Error(`Failed to install Hermes Agent into WebUI Python env (exit ${install.status})`)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
check = aiAgentImportCheck(python, agentDir)
|
|
264
|
+
if (!check.ok) {
|
|
265
|
+
throw new Error(`Hermes Agent still cannot be imported after install:\n${check.error}`)
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
221
269
|
function preparePython() {
|
|
222
270
|
if (process.env.HERMES_WEBUI_PYTHON) {
|
|
223
271
|
return resolve(expandHome(process.env.HERMES_WEBUI_PYTHON))
|
|
@@ -311,7 +359,7 @@ async function waitForHealth(host, port, child, timeoutMs = 30000) {
|
|
|
311
359
|
|
|
312
360
|
async function start(options) {
|
|
313
361
|
if (!existsSync(bootstrapPath) || !existsSync(serverPath)) {
|
|
314
|
-
throw new Error('
|
|
362
|
+
throw new Error('WebUI runtime is missing. Run npm run sync:vendor.')
|
|
315
363
|
}
|
|
316
364
|
|
|
317
365
|
const existing = readPid()
|
|
@@ -329,6 +377,7 @@ async function start(options) {
|
|
|
329
377
|
mkdirSync(paths.dir, { recursive: true })
|
|
330
378
|
const python = preparePython()
|
|
331
379
|
const env = buildEnv(python, options)
|
|
380
|
+
ensureAiAgentImportable(python, env.HERMES_WEBUI_AGENT_DIR)
|
|
332
381
|
const args = [serverPath]
|
|
333
382
|
|
|
334
383
|
if (options.foreground) {
|
|
@@ -383,7 +432,7 @@ async function start(options) {
|
|
|
383
432
|
started_at: new Date().toISOString(),
|
|
384
433
|
})
|
|
385
434
|
|
|
386
|
-
console.log(`Starting
|
|
435
|
+
console.log(`Starting BitSeek Claw WebUI (PID ${child.pid}, port ${options.port})...`)
|
|
387
436
|
const health = await waitForHealth(options.host, options.port, child)
|
|
388
437
|
if (!health.ok) {
|
|
389
438
|
console.log(`Health check failed: ${health.error || health.status || 'unknown error'}`)
|
|
@@ -391,7 +440,7 @@ async function start(options) {
|
|
|
391
440
|
process.exit(1)
|
|
392
441
|
}
|
|
393
442
|
|
|
394
|
-
console.log('
|
|
443
|
+
console.log('BitSeek Claw WebUI started')
|
|
395
444
|
console.log(`URL: http://${options.host === '127.0.0.1' ? 'localhost' : options.host}:${options.port}`)
|
|
396
445
|
console.log(`Log: ${paths.log}`)
|
|
397
446
|
if (options.open) openBrowser(options.host, options.port)
|
|
@@ -408,13 +457,13 @@ async function stop() {
|
|
|
408
457
|
process.exit(1)
|
|
409
458
|
}
|
|
410
459
|
}
|
|
411
|
-
console.log('
|
|
460
|
+
console.log('BitSeek Claw WebUI is not running')
|
|
412
461
|
return
|
|
413
462
|
}
|
|
414
463
|
|
|
415
464
|
if (!isRunning(pid)) {
|
|
416
465
|
removePid()
|
|
417
|
-
console.log(`
|
|
466
|
+
console.log(`BitSeek Claw WebUI was not running; cleaned stale PID ${pid}`)
|
|
418
467
|
return
|
|
419
468
|
}
|
|
420
469
|
|
|
@@ -427,7 +476,7 @@ async function stop() {
|
|
|
427
476
|
process.kill(pid, 'SIGKILL')
|
|
428
477
|
}
|
|
429
478
|
removePid()
|
|
430
|
-
console.log(`
|
|
479
|
+
console.log(`BitSeek Claw WebUI stopped (PID ${pid})`)
|
|
431
480
|
}
|
|
432
481
|
|
|
433
482
|
async function restart(options) {
|
|
@@ -510,11 +559,17 @@ async function doctor(options) {
|
|
|
510
559
|
const agentDir = resolveAgentDir()
|
|
511
560
|
add('Hermes Agent dir', Boolean(agentDir), agentDir || 'not found')
|
|
512
561
|
add('run_agent.py', Boolean(agentDir && existsSync(join(agentDir, 'run_agent.py'))), agentDir ? join(agentDir, 'run_agent.py') : 'not found')
|
|
562
|
+
if (python && agentDir) {
|
|
563
|
+
const importCheck = aiAgentImportCheck(python, agentDir)
|
|
564
|
+
add('AIAgent importable', importCheck.ok, importCheck.ok ? python : importCheck.error || python)
|
|
565
|
+
} else {
|
|
566
|
+
add('AIAgent importable', false, 'python or Hermes Agent dir not found')
|
|
567
|
+
}
|
|
513
568
|
add('port available', !(await portOccupied(options.host, options.port)), `${options.host}:${options.port}`)
|
|
514
|
-
add('no
|
|
515
|
-
add('no
|
|
516
|
-
add('no
|
|
517
|
-
add('no
|
|
569
|
+
add('no bundled .env', !existsSync(join(vendorRoot, '.env')), join(vendorRoot, '.env'))
|
|
570
|
+
add('no bundled .git', !existsSync(join(vendorRoot, '.git')), join(vendorRoot, '.git'))
|
|
571
|
+
add('no bundled .venv', !existsSync(join(vendorRoot, '.venv')), join(vendorRoot, '.venv'))
|
|
572
|
+
add('no bundled node_modules', !existsSync(join(vendorRoot, 'node_modules')), join(vendorRoot, 'node_modules'))
|
|
518
573
|
|
|
519
574
|
for (const check of checks) {
|
|
520
575
|
console.log(`${check.ok ? 'ok' : 'fail'} - ${check.name}${check.detail ? `: ${check.detail}` : ''}`)
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bitseek/hermes-webui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "BitSeek Claw WebUI launcher.",
|
|
6
6
|
"bin": {
|
|
7
7
|
"hermes-webui": "bin/hermes-webui.mjs"
|
|
8
8
|
},
|