@simonyea/holysheep-cli 1.7.106 → 1.7.107
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 +1 -1
- package/src/webui/index.html +39 -0
- package/src/webui/server.js +59 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simonyea/holysheep-cli",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.107",
|
|
4
4
|
"description": "Claude Code/Cursor/Cline API relay for China — ¥1=$1, WeChat/Alipay payment, no credit card, no VPN. One command setup for all AI coding tools.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"openai-china",
|
package/src/webui/index.html
CHANGED
|
@@ -346,6 +346,31 @@ async function loadTools() {
|
|
|
346
346
|
function renderToolCard(tool) {
|
|
347
347
|
let dotClass, statusBadges, actions, hintLine
|
|
348
348
|
|
|
349
|
+
// Claude Proxy 特殊卡片
|
|
350
|
+
if (tool.id === 'claude-proxy') {
|
|
351
|
+
if (tool.configured) {
|
|
352
|
+
dotClass = 'dot-ok'
|
|
353
|
+
statusBadges = `<span class="badge badge-ok">运行中</span>`
|
|
354
|
+
actions = `<button class="btn btn-danger btn-sm" onclick="doClaudeProxyStop()">停止代理</button>`
|
|
355
|
+
hintLine = tool.version ? `<span class="mono" style="font-size:0.78rem;color:var(--text2)">${esc(tool.version)}</span>` : ''
|
|
356
|
+
} else {
|
|
357
|
+
dotClass = 'dot-warn'
|
|
358
|
+
statusBadges = `<span class="badge badge-warn">未启动</span>`
|
|
359
|
+
actions = `<button class="btn btn-primary btn-sm" onclick="doClaudeProxyStart()">启动代理</button>`
|
|
360
|
+
hintLine = ''
|
|
361
|
+
}
|
|
362
|
+
const hintText = tool.hint ? `<div class="tool-hint">${esc(tool.hint)}</div>` : ''
|
|
363
|
+
return `<div class="tool-card" id="tool-${tool.id}">
|
|
364
|
+
<div class="tool-dot ${dotClass}"></div>
|
|
365
|
+
<div class="tool-body">
|
|
366
|
+
<div class="tool-name">${esc(tool.name)}</div>
|
|
367
|
+
<div class="tool-meta">${statusBadges} ${hintLine}</div>
|
|
368
|
+
${hintText}
|
|
369
|
+
</div>
|
|
370
|
+
<div class="tool-actions">${actions}</div>
|
|
371
|
+
</div>`
|
|
372
|
+
}
|
|
373
|
+
|
|
349
374
|
if (!tool.installed) {
|
|
350
375
|
dotClass = 'dot-gray'
|
|
351
376
|
statusBadges = `<span class="badge badge-gray">${t('notInstalled')}</span>`
|
|
@@ -424,6 +449,20 @@ async function doConfigureTool(id, name) {
|
|
|
424
449
|
loadTools()
|
|
425
450
|
}
|
|
426
451
|
|
|
452
|
+
async function doClaudeProxyStart() {
|
|
453
|
+
try {
|
|
454
|
+
await api('claude-proxy/start', { method: 'POST' })
|
|
455
|
+
loadTools()
|
|
456
|
+
} catch (e) { alert('启动失败: ' + e.message) }
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
async function doClaudeProxyStop() {
|
|
460
|
+
try {
|
|
461
|
+
await api('claude-proxy/stop', { method: 'POST' })
|
|
462
|
+
loadTools()
|
|
463
|
+
} catch (e) { alert('停止失败: ' + e.message) }
|
|
464
|
+
}
|
|
465
|
+
|
|
427
466
|
async function doLaunchTool(id) {
|
|
428
467
|
try {
|
|
429
468
|
await api('tool/launch', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ toolId: id }) })
|
package/src/webui/server.js
CHANGED
|
@@ -285,6 +285,17 @@ async function handleDoctor(_req, res) {
|
|
|
285
285
|
})
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
+
function isClaudeProxyRunning() {
|
|
289
|
+
try {
|
|
290
|
+
const pidFile = path.join(require('os').homedir(), '.holysheep', 'claude-proxy.pid')
|
|
291
|
+
const info = JSON.parse(fs.readFileSync(pidFile, 'utf8'))
|
|
292
|
+
process.kill(info.pid, 0) // check alive
|
|
293
|
+
return { running: true, port: info.port, pid: info.pid }
|
|
294
|
+
} catch {
|
|
295
|
+
return { running: false }
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
288
299
|
async function handleTools(_req, res) {
|
|
289
300
|
const tools = await Promise.all(TOOLS.map(async t => {
|
|
290
301
|
const installed = t.checkInstalled()
|
|
@@ -301,6 +312,23 @@ async function handleTools(_req, res) {
|
|
|
301
312
|
canUpgrade: !!UPGRADABLE_TOOLS.find(u => u.id === t.id),
|
|
302
313
|
}
|
|
303
314
|
}))
|
|
315
|
+
|
|
316
|
+
// 追加 claude-proxy 虚拟工具
|
|
317
|
+
const proxyState = isClaudeProxyRunning()
|
|
318
|
+
tools.push({
|
|
319
|
+
id: 'claude-proxy',
|
|
320
|
+
name: 'Claude 代理(VS Code)',
|
|
321
|
+
installed: true,
|
|
322
|
+
configured: proxyState.running,
|
|
323
|
+
version: proxyState.running ? `端口 ${proxyState.port}` : null,
|
|
324
|
+
installCmd: null,
|
|
325
|
+
hint: '启动后 VS Code Claude 扩展即可通过 HolySheep 使用',
|
|
326
|
+
launchCmd: 'hs claude-proxy',
|
|
327
|
+
canAutoInstall: false,
|
|
328
|
+
canUpgrade: false,
|
|
329
|
+
isProxy: true,
|
|
330
|
+
})
|
|
331
|
+
|
|
304
332
|
json(res, tools)
|
|
305
333
|
}
|
|
306
334
|
|
|
@@ -695,6 +723,35 @@ async function handleToolLaunch(req, res) {
|
|
|
695
723
|
json(res, { ok: true, type: 'terminal', cmd })
|
|
696
724
|
}
|
|
697
725
|
|
|
726
|
+
// ── Claude Proxy start/stop ──────────────────────────────────────────────────
|
|
727
|
+
|
|
728
|
+
async function handleClaudeProxyStart(_req, res) {
|
|
729
|
+
const state = isClaudeProxyRunning()
|
|
730
|
+
if (state.running) {
|
|
731
|
+
return json(res, { ok: true, message: '代理已在运行', port: state.port, pid: state.pid })
|
|
732
|
+
}
|
|
733
|
+
try {
|
|
734
|
+
const claudeProxy = require('../commands/claude-proxy')
|
|
735
|
+
await claudeProxy(['--daemon'])
|
|
736
|
+
// 等一下确认
|
|
737
|
+
await new Promise(r => setTimeout(r, 2000))
|
|
738
|
+
const newState = isClaudeProxyRunning()
|
|
739
|
+
json(res, { ok: newState.running, port: newState.port, pid: newState.pid })
|
|
740
|
+
} catch (e) {
|
|
741
|
+
json(res, { ok: false, error: e.message }, 500)
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
async function handleClaudeProxyStop(_req, res) {
|
|
746
|
+
try {
|
|
747
|
+
const claudeProxy = require('../commands/claude-proxy')
|
|
748
|
+
await claudeProxy(['--stop'])
|
|
749
|
+
json(res, { ok: true })
|
|
750
|
+
} catch (e) {
|
|
751
|
+
json(res, { ok: false, error: e.message }, 500)
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
|
|
698
755
|
// ── Environment variables ────────────────────────────────────────────────────
|
|
699
756
|
|
|
700
757
|
const HS_ENV_KEYS = ['ANTHROPIC_API_KEY', 'ANTHROPIC_AUTH_TOKEN', 'ANTHROPIC_BASE_URL', 'OPENAI_API_KEY', 'OPENAI_BASE_URL']
|
|
@@ -782,6 +839,8 @@ async function handleRequest(req, res) {
|
|
|
782
839
|
if (route === '/api/tool/reset' && req.method === 'POST') return await handleToolReset(req, res)
|
|
783
840
|
if (route === '/api/tool/upgrade' && req.method === 'POST') return await handleToolUpgrade(req, res)
|
|
784
841
|
if (route === '/api/tool/launch' && req.method === 'POST') return await handleToolLaunch(req, res)
|
|
842
|
+
if (route === '/api/claude-proxy/start' && req.method === 'POST') return await handleClaudeProxyStart(req, res)
|
|
843
|
+
if (route === '/api/claude-proxy/stop' && req.method === 'POST') return await handleClaudeProxyStop(req, res)
|
|
785
844
|
if (route === '/api/env' && req.method === 'GET') return handleEnv(req, res)
|
|
786
845
|
if (route === '/api/env/clean' && req.method === 'POST') return handleEnvClean(req, res)
|
|
787
846
|
if (route === '/api/restart' && req.method === 'POST') {
|