@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simonyea/holysheep-cli",
3
- "version": "1.7.106",
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",
@@ -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 }) })
@@ -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') {