@simonyea/holysheep-cli 2.1.69 → 2.1.71
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/dist/configure-worker.js +2 -2
- package/dist/index.html +135 -47
- package/dist/index.js +92 -70
- package/package.json +2 -2
package/dist/configure-worker.js
CHANGED
|
@@ -4135,11 +4135,11 @@ var require_package = __commonJS({
|
|
|
4135
4135
|
"package.json"(exports2, module2) {
|
|
4136
4136
|
module2.exports = {
|
|
4137
4137
|
name: "@simonyea/holysheep-cli",
|
|
4138
|
-
version: "2.1.
|
|
4138
|
+
version: "2.1.71",
|
|
4139
4139
|
description: "Claude Code/Cursor/Cline API relay for China \u2014 \xA51=$1, WeChat/Alipay payment, no credit card, no VPN. One command setup for all AI coding tools.",
|
|
4140
4140
|
scripts: {
|
|
4141
4141
|
build: "node scripts/build.mjs",
|
|
4142
|
-
test: "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js && node tests/opencode-auth-purge.test.js && node tests/shell-winpath.test.js && node tests/openclaw-atomic-write.test.js && node tests/openclaw-disable-auth-direct.test.js && node tests/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-runtime-resources.test.js && node tests/aionui-wrapper-claude-proxy.test.js && node tests/aionui-wrapper-probe.test.js && node tests/aionui-wrapper-proxy-integration.test.js && node tests/aionui-wrapper-all-clis-autoconf.test.js && node tests/aionui-wrapper-env-signal.test.js && node tests/aionui-wrapper-csp-rewrite.test.js && node tests/aionui-wrapper-version-status.test.js && node tests/claude-proxy-daemon.test.js && node tests/claude-proxy-vscode-settings.test.js && node tests/claude-proxy-vscode-env.test.js && node tests/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js && node tests/claude-code-configure-preserve.test.js && node tests/webui-claude-proxy-virtual-tool.test.js && node tests/webui-claude-proxy-ui.test.js",
|
|
4142
|
+
test: "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js && node tests/opencode-auth-purge.test.js && node tests/shell-winpath.test.js && node tests/openclaw-atomic-write.test.js && node tests/openclaw-disable-auth-direct.test.js && node tests/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-runtime-resources.test.js && node tests/aionui-wrapper-claude-proxy.test.js && node tests/aionui-wrapper-probe.test.js && node tests/aionui-wrapper-proxy-integration.test.js && node tests/aionui-wrapper-all-clis-autoconf.test.js && node tests/aionui-wrapper-env-signal.test.js && node tests/aionui-wrapper-csp-rewrite.test.js && node tests/aionui-wrapper-version-status.test.js && node tests/claude-proxy-daemon.test.js && node tests/claude-proxy-vscode-settings.test.js && node tests/claude-proxy-vscode-env.test.js && node tests/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js && node tests/claude-code-configure-preserve.test.js && node tests/webui-claude-proxy-virtual-tool.test.js && node tests/webui-claude-proxy-ui.test.js && node tests/webui-response-consumer.test.js && node tests/webui-claude-proxy-install-gating.test.js",
|
|
4143
4143
|
prepublishOnly: "npm run build && npm test && node scripts/check-tarball-size.js"
|
|
4144
4144
|
},
|
|
4145
4145
|
keywords: [
|
package/dist/index.html
CHANGED
|
@@ -584,7 +584,7 @@ button { cursor: pointer; }
|
|
|
584
584
|
<button class="nav-item" data-route="dashboard"><span class="nav-dot"></span><span>Dashboard</span></button>
|
|
585
585
|
<button class="nav-item" data-route="workspace"><span class="nav-dot"></span><span>Conversations</span></button>
|
|
586
586
|
<button class="nav-item" data-route="tasks"><span class="nav-dot"></span><span>Scheduled Tasks</span></button>
|
|
587
|
-
<button class="nav-item" data-route="tools"><span class="nav-dot"></span><span>
|
|
587
|
+
<button class="nav-item" data-route="tools"><span class="nav-dot"></span><span>CLI 管理</span></button>
|
|
588
588
|
<button class="nav-item" data-route="account"><span class="nav-dot"></span><span>HolySheep Account</span></button>
|
|
589
589
|
</div>
|
|
590
590
|
<div class="sidebar-card">
|
|
@@ -646,8 +646,8 @@ const pageMeta = {
|
|
|
646
646
|
subtitle: 'Manage recurring prompts and maintain the default HolySheep API config directly below the task list.',
|
|
647
647
|
},
|
|
648
648
|
tools: {
|
|
649
|
-
title: '
|
|
650
|
-
subtitle: '
|
|
649
|
+
title: 'CLI 管理',
|
|
650
|
+
subtitle: 'Manage local AI CLI adapters, MCP, and the VS Code Claude proxy from one place.',
|
|
651
651
|
},
|
|
652
652
|
account: {
|
|
653
653
|
title: 'HolySheep Account',
|
|
@@ -679,16 +679,81 @@ function formatDate(value) {
|
|
|
679
679
|
return date.toLocaleString()
|
|
680
680
|
}
|
|
681
681
|
|
|
682
|
-
function
|
|
683
|
-
return
|
|
682
|
+
function contentTypeOf(response) {
|
|
683
|
+
return (response.headers.get('content-type') || '').toLowerCase()
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
async function parseResponseBody(response) {
|
|
687
|
+
const contentType = contentTypeOf(response)
|
|
688
|
+
if (contentType.includes('text/event-stream')) {
|
|
689
|
+
const text = await response.text()
|
|
690
|
+
return { kind: 'sse', events: parseSseText(text), text }
|
|
691
|
+
}
|
|
692
|
+
if (contentType.includes('application/json')) {
|
|
684
693
|
const payload = await response.json().catch(() => ({}))
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
694
|
+
return { kind: 'json', payload }
|
|
695
|
+
}
|
|
696
|
+
const text = await response.text().catch(() => '')
|
|
697
|
+
return { kind: 'text', text }
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
function parseSseText(text) {
|
|
701
|
+
return String(text || '').split('\n\n').map((chunk) => {
|
|
702
|
+
const lines = chunk.split('\n').filter((line) => line.startsWith('data:'))
|
|
703
|
+
if (!lines.length) return null
|
|
704
|
+
const data = lines.map((line) => line.slice(5).trim()).join('\n')
|
|
705
|
+
try { return JSON.parse(data) }
|
|
706
|
+
catch { return { type: 'output', text: data } }
|
|
707
|
+
}).filter(Boolean)
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
async function api(path, options) {
|
|
711
|
+
const response = await fetch(path.startsWith('/api/') ? path : `/api/${path}`, options)
|
|
712
|
+
const parsed = await parseResponseBody(response)
|
|
713
|
+
const payload = parsed.kind === 'json' ? parsed.payload : parsed
|
|
714
|
+
if (!response.ok) {
|
|
715
|
+
const error = new Error(payload.error || payload.message || payload.text || `HTTP ${response.status}`)
|
|
716
|
+
error.payload = payload
|
|
717
|
+
throw error
|
|
718
|
+
}
|
|
719
|
+
return payload
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
function appendSseEventToConsole(payload) {
|
|
723
|
+
if (payload.type === 'output') appendConsole(payload.text || '', '')
|
|
724
|
+
else if (payload.type === 'progress') appendConsole(payload.message || JSON.stringify(payload), payload.status === 'error' ? 'error' : payload.status === 'ok' ? 'ok' : 'warn')
|
|
725
|
+
else if (payload.type === 'done') appendConsole(payload.message || 'Done.', payload.success === false ? 'error' : 'ok')
|
|
726
|
+
else appendConsole(JSON.stringify(payload), '')
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
async function postMaybeSse(path, body, title) {
|
|
730
|
+
openConsole(title)
|
|
731
|
+
const response = await fetch(path.startsWith('/api/') ? path : `/api/${path}`, {
|
|
732
|
+
method: 'POST',
|
|
733
|
+
headers: { 'Content-Type': 'application/json' },
|
|
734
|
+
body: JSON.stringify(body || {}),
|
|
735
|
+
})
|
|
736
|
+
const contentType = contentTypeOf(response)
|
|
737
|
+
if (contentType.includes('text/event-stream')) {
|
|
738
|
+
const events = await consumeSseResponse(response)
|
|
739
|
+
const failed = events.some((event) => event.type === 'done' && event.success === false)
|
|
740
|
+
if (!response.ok || failed) {
|
|
741
|
+
const lastError = [...events].reverse().find((event) => event.error || event.message)
|
|
742
|
+
throw new Error(lastError?.error || lastError?.message || `HTTP ${response.status}`)
|
|
743
|
+
}
|
|
744
|
+
return { kind: 'sse', events }
|
|
745
|
+
}
|
|
746
|
+
const parsed = await parseResponseBody(response)
|
|
747
|
+
if (parsed.kind === 'json') {
|
|
748
|
+
const payload = parsed.payload
|
|
749
|
+
if (!response.ok || payload.ok === false || payload.success === false) {
|
|
750
|
+
throw new Error(payload.error || payload.message || `HTTP ${response.status}`)
|
|
689
751
|
}
|
|
690
752
|
return payload
|
|
691
|
-
}
|
|
753
|
+
}
|
|
754
|
+
if (!response.ok) throw new Error(parsed.text || `HTTP ${response.status}`)
|
|
755
|
+
if (parsed.text) appendConsole(parsed.text, '')
|
|
756
|
+
return parsed
|
|
692
757
|
}
|
|
693
758
|
|
|
694
759
|
async function loadBaseState() {
|
|
@@ -812,7 +877,7 @@ function renderDashboard() {
|
|
|
812
877
|
</div>
|
|
813
878
|
<div style="margin-top:16px;" class="inline-actions">
|
|
814
879
|
<button class="btn primary" onclick="setRoute('tasks')">Open Scheduled Tasks</button>
|
|
815
|
-
<button class="btn" onclick="setRoute('tools')"
|
|
880
|
+
<button class="btn" onclick="setRoute('tools')">打开 CLI 管理</button>
|
|
816
881
|
</div>
|
|
817
882
|
</div>
|
|
818
883
|
</section>
|
|
@@ -1054,8 +1119,8 @@ function renderTools() {
|
|
|
1054
1119
|
<section class="panel">
|
|
1055
1120
|
<div class="panel-header">
|
|
1056
1121
|
<div>
|
|
1057
|
-
<h2>
|
|
1058
|
-
<p
|
|
1122
|
+
<h2>CLI 管理</h2>
|
|
1123
|
+
<p>统一管理本地 AI CLI、MCP 与 VS Code Claude 代理;Claude Code 未安装时先安装 CLI,再启动代理。</p>
|
|
1059
1124
|
</div>
|
|
1060
1125
|
</div>
|
|
1061
1126
|
<div class="panel-body tool-grid">
|
|
@@ -1071,12 +1136,11 @@ function renderTools() {
|
|
|
1071
1136
|
</div>
|
|
1072
1137
|
</div>
|
|
1073
1138
|
<div class="inline-actions">
|
|
1074
|
-
|
|
1075
|
-
<button class="btn primary" onclick="configureTool('${tool.id}')">${tool.configured ? 'Reconfigure' : 'Configure'}</button>
|
|
1139
|
+
${renderToolActions(tool)}
|
|
1076
1140
|
</div>
|
|
1077
1141
|
</div>
|
|
1078
1142
|
<div class="tool-hint">${esc(tool.hint || 'No additional hint')}</div>
|
|
1079
|
-
${tool.id === 'claude-code' ? renderClaudeProxySubstatus(tool
|
|
1143
|
+
${tool.id === 'claude-code' ? renderClaudeProxySubstatus(tool) : ''}
|
|
1080
1144
|
</div>
|
|
1081
1145
|
`).join('')}
|
|
1082
1146
|
</div>
|
|
@@ -1084,19 +1148,40 @@ function renderTools() {
|
|
|
1084
1148
|
`
|
|
1085
1149
|
}
|
|
1086
1150
|
|
|
1087
|
-
function
|
|
1088
|
-
|
|
1151
|
+
function renderToolActions(tool) {
|
|
1152
|
+
if (tool.id === 'claude-code' && tool.requiresInstall) {
|
|
1153
|
+
return `<button class="btn primary" onclick="installTool('claude-code')">${esc(tool.installLabel || '安装 Claude Code CLI')}</button>`
|
|
1154
|
+
}
|
|
1155
|
+
const launchButton = tool.launchCmd ? `<button class="btn" onclick="launchTool('${tool.id}')">Launch</button>` : ''
|
|
1156
|
+
const configureButton = tool.installed ? `<button class="btn primary" onclick="configureTool('${tool.id}')">${tool.configured ? 'Reconfigure' : 'Configure'}</button>` : ''
|
|
1157
|
+
const installButton = !tool.installed && tool.canAutoInstall ? `<button class="btn primary" onclick="installTool('${tool.id}')">Install</button>` : ''
|
|
1158
|
+
return `${installButton}${launchButton}${configureButton}` || '<span class="task-meta">Manual setup required</span>'
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
function renderClaudeProxySubstatus(tool) {
|
|
1162
|
+
if (tool?.requiresInstall || !tool?.installed || !tool?.vsCodeProxy) {
|
|
1163
|
+
return `
|
|
1164
|
+
<div class="tool-substatus install-first" data-requires-install="true">
|
|
1165
|
+
<div>
|
|
1166
|
+
<div class="tool-substatus-title">先安装 Claude Code CLI</div>
|
|
1167
|
+
<div class="tool-substatus-meta">${esc(tool?.installHint || '不存在单独的 vscode-claudecode 插件;VS Code 里使用官方 Claude Code 扩展 + HolySheep 本地代理。')}</div>
|
|
1168
|
+
</div>
|
|
1169
|
+
</div>
|
|
1170
|
+
`
|
|
1171
|
+
}
|
|
1172
|
+
const proxy = tool.vsCodeProxy
|
|
1173
|
+
const running = !!proxy.running
|
|
1089
1174
|
const meta = running
|
|
1090
1175
|
? `127.0.0.1:${proxy.port || '?'} · PID ${proxy.pid || '?'}`
|
|
1091
1176
|
: '未启动 · Windows 启动后需要完全退出 Code.exe 再重开 VS Code'
|
|
1092
1177
|
return `
|
|
1093
1178
|
<div class="tool-substatus">
|
|
1094
1179
|
<div>
|
|
1095
|
-
<div class="tool-substatus-title"
|
|
1180
|
+
<div class="tool-substatus-title">${esc(proxy.label || 'VS Code Claude 代理(hs claude-proxy)')}</div>
|
|
1096
1181
|
<div class="tool-substatus-meta">${esc(meta)}</div>
|
|
1097
1182
|
</div>
|
|
1098
1183
|
<div class="inline-actions">
|
|
1099
|
-
<button class="btn ${running ? '' : 'primary'}" onclick="startClaudeProxy()">${running ? '重新校准' : '
|
|
1184
|
+
<button class="btn ${running ? '' : 'primary'}" onclick="startClaudeProxy()">${running ? '重新校准' : '启动 VS Code 代理'}</button>
|
|
1100
1185
|
${running ? '<button class="btn danger" onclick="stopClaudeProxy()">停止</button>' : ''}
|
|
1101
1186
|
</div>
|
|
1102
1187
|
</div>
|
|
@@ -1395,11 +1480,10 @@ async function launchTool(toolId) {
|
|
|
1395
1480
|
}
|
|
1396
1481
|
|
|
1397
1482
|
async function startClaudeProxy() {
|
|
1398
|
-
openConsole('Start VS Code Claude proxy')
|
|
1399
|
-
appendConsole('正在启动 claude-proxy...', 'warn')
|
|
1400
1483
|
try {
|
|
1401
|
-
|
|
1402
|
-
|
|
1484
|
+
appendConsole('正在启动 claude-proxy...', 'warn')
|
|
1485
|
+
const result = await postMaybeSse('claude-proxy/start', {}, 'Start VS Code Claude proxy')
|
|
1486
|
+
if (result.kind !== 'sse') appendConsole(result.message || `代理已启动: 127.0.0.1:${result.port || '?'}`, 'ok')
|
|
1403
1487
|
appendConsole('Windows 用户:请完全退出所有 Code.exe,再重新打开 VS Code。', 'warn')
|
|
1404
1488
|
await loadBaseState()
|
|
1405
1489
|
render()
|
|
@@ -1409,11 +1493,10 @@ async function startClaudeProxy() {
|
|
|
1409
1493
|
}
|
|
1410
1494
|
|
|
1411
1495
|
async function stopClaudeProxy() {
|
|
1412
|
-
openConsole('Stop VS Code Claude proxy')
|
|
1413
|
-
appendConsole('正在停止 claude-proxy...', 'warn')
|
|
1414
1496
|
try {
|
|
1415
|
-
|
|
1416
|
-
|
|
1497
|
+
appendConsole('正在停止 claude-proxy...', 'warn')
|
|
1498
|
+
const result = await postMaybeSse('claude-proxy/stop', {}, 'Stop VS Code Claude proxy')
|
|
1499
|
+
if (result.kind !== 'sse') appendConsole(result.message || '代理已停止', 'ok')
|
|
1417
1500
|
await loadBaseState()
|
|
1418
1501
|
render()
|
|
1419
1502
|
} catch (error) {
|
|
@@ -1445,32 +1528,37 @@ document.getElementById('console-close').onclick = () => {
|
|
|
1445
1528
|
document.getElementById('console-drawer').classList.remove('open')
|
|
1446
1529
|
}
|
|
1447
1530
|
|
|
1448
|
-
async function
|
|
1449
|
-
openConsole(title)
|
|
1450
|
-
const response = await fetch(`/api/${path}`, {
|
|
1451
|
-
method: 'POST',
|
|
1452
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1453
|
-
body: JSON.stringify(body),
|
|
1454
|
-
})
|
|
1531
|
+
async function consumeSseResponse(response) {
|
|
1455
1532
|
const reader = response.body.getReader()
|
|
1456
1533
|
const decoder = new TextDecoder()
|
|
1534
|
+
const events = []
|
|
1457
1535
|
let buffer = ''
|
|
1536
|
+
async function flush(chunk, final = false) {
|
|
1537
|
+
buffer += chunk
|
|
1538
|
+
const chunks = buffer.split('\n\n')
|
|
1539
|
+
buffer = final ? '' : chunks.pop()
|
|
1540
|
+
for (const part of chunks) {
|
|
1541
|
+
for (const payload of parseSseText(part + '\n\n')) {
|
|
1542
|
+
events.push(payload)
|
|
1543
|
+
appendSseEventToConsole(payload)
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1458
1547
|
while (true) {
|
|
1459
1548
|
const { value, done } = await reader.read()
|
|
1460
1549
|
if (done) break
|
|
1461
|
-
|
|
1462
|
-
const chunks = buffer.split('\n\n')
|
|
1463
|
-
buffer = chunks.pop()
|
|
1464
|
-
for (const chunk of chunks) {
|
|
1465
|
-
const line = chunk.split('\n').find((entry) => entry.startsWith('data:'))
|
|
1466
|
-
if (!line) continue
|
|
1467
|
-
const payload = JSON.parse(line.slice(5).trim())
|
|
1468
|
-
if (payload.type === 'output') appendConsole(payload.text, '')
|
|
1469
|
-
else if (payload.type === 'progress') appendConsole(payload.message || JSON.stringify(payload), payload.status === 'error' ? 'error' : payload.status === 'ok' ? 'ok' : 'warn')
|
|
1470
|
-
else if (payload.type === 'done') appendConsole('Done.', payload.success === false ? 'error' : 'ok')
|
|
1471
|
-
else appendConsole(JSON.stringify(payload), '')
|
|
1472
|
-
}
|
|
1550
|
+
await flush(decoder.decode(value, { stream: true }))
|
|
1473
1551
|
}
|
|
1552
|
+
if (buffer) await flush(buffer, true)
|
|
1553
|
+
return events
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
async function consumeSse(path, body, title) {
|
|
1557
|
+
await postMaybeSse(path, body, title)
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
function installTool(toolId) {
|
|
1561
|
+
consumeSse('tool/install', { toolId }, `Install ${toolNames[toolId] || toolId}`).then(() => refreshWorkspace(false))
|
|
1474
1562
|
}
|
|
1475
1563
|
|
|
1476
1564
|
function configureTool(toolId) {
|
package/dist/index.js
CHANGED
|
@@ -12,11 +12,11 @@ var require_package = __commonJS({
|
|
|
12
12
|
"package.json"(exports2, module2) {
|
|
13
13
|
module2.exports = {
|
|
14
14
|
name: "@simonyea/holysheep-cli",
|
|
15
|
-
version: "2.1.
|
|
15
|
+
version: "2.1.71",
|
|
16
16
|
description: "Claude Code/Cursor/Cline API relay for China \u2014 \xA51=$1, WeChat/Alipay payment, no credit card, no VPN. One command setup for all AI coding tools.",
|
|
17
17
|
scripts: {
|
|
18
18
|
build: "node scripts/build.mjs",
|
|
19
|
-
test: "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js && node tests/opencode-auth-purge.test.js && node tests/shell-winpath.test.js && node tests/openclaw-atomic-write.test.js && node tests/openclaw-disable-auth-direct.test.js && node tests/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-runtime-resources.test.js && node tests/aionui-wrapper-claude-proxy.test.js && node tests/aionui-wrapper-probe.test.js && node tests/aionui-wrapper-proxy-integration.test.js && node tests/aionui-wrapper-all-clis-autoconf.test.js && node tests/aionui-wrapper-env-signal.test.js && node tests/aionui-wrapper-csp-rewrite.test.js && node tests/aionui-wrapper-version-status.test.js && node tests/claude-proxy-daemon.test.js && node tests/claude-proxy-vscode-settings.test.js && node tests/claude-proxy-vscode-env.test.js && node tests/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js && node tests/claude-code-configure-preserve.test.js && node tests/webui-claude-proxy-virtual-tool.test.js && node tests/webui-claude-proxy-ui.test.js",
|
|
19
|
+
test: "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js && node tests/opencode-auth-purge.test.js && node tests/shell-winpath.test.js && node tests/openclaw-atomic-write.test.js && node tests/openclaw-disable-auth-direct.test.js && node tests/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-runtime-resources.test.js && node tests/aionui-wrapper-claude-proxy.test.js && node tests/aionui-wrapper-probe.test.js && node tests/aionui-wrapper-proxy-integration.test.js && node tests/aionui-wrapper-all-clis-autoconf.test.js && node tests/aionui-wrapper-env-signal.test.js && node tests/aionui-wrapper-csp-rewrite.test.js && node tests/aionui-wrapper-version-status.test.js && node tests/claude-proxy-daemon.test.js && node tests/claude-proxy-vscode-settings.test.js && node tests/claude-proxy-vscode-env.test.js && node tests/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js && node tests/claude-code-configure-preserve.test.js && node tests/webui-claude-proxy-virtual-tool.test.js && node tests/webui-claude-proxy-ui.test.js && node tests/webui-response-consumer.test.js && node tests/webui-claude-proxy-install-gating.test.js",
|
|
20
20
|
prepublishOnly: "npm run build && npm test && node scripts/check-tarball-size.js"
|
|
21
21
|
},
|
|
22
22
|
keywords: [
|
|
@@ -7685,29 +7685,37 @@ var require_server = __commonJS({
|
|
|
7685
7685
|
async function buildToolSummary(tool) {
|
|
7686
7686
|
var _a, _b;
|
|
7687
7687
|
const installed = await detectToolInstalled(tool);
|
|
7688
|
+
const isClaudeCode = tool.id === "claude-code";
|
|
7688
7689
|
const summary = {
|
|
7689
7690
|
id: tool.id,
|
|
7690
|
-
name: tool.name,
|
|
7691
|
+
name: isClaudeCode ? "Claude Code CLI" : tool.name,
|
|
7691
7692
|
installed,
|
|
7692
7693
|
configured: installed ? ((_a = tool.isConfigured) == null ? void 0 : _a.call(tool)) || false : false,
|
|
7693
7694
|
version: installed ? await getVersionAsync(tool) : null,
|
|
7694
7695
|
installCmd: tool.installCmd,
|
|
7695
|
-
hint: tool.hint || null,
|
|
7696
|
-
launchCmd: tool.launchCmd || null,
|
|
7696
|
+
hint: isClaudeCode ? "\u5B98\u65B9 Claude Code CLI\uFF1BVS Code \u91CC\u4F7F\u7528\u5B98\u65B9 Claude Code \u6269\u5C55 + HolySheep \u672C\u5730\u4EE3\u7406\uFF0C\u4E0D\u5B58\u5728\u5355\u72EC\u7684 vscode-claudecode \u63D2\u4EF6\u3002" : tool.hint || null,
|
|
7697
|
+
launchCmd: installed ? tool.launchCmd || null : null,
|
|
7697
7698
|
canAutoInstall: !!AUTO_INSTALL[tool.id],
|
|
7698
|
-
canUpgrade: !!UPGRADABLE_TOOLS.find((item) => item.id === tool.id),
|
|
7699
|
+
canUpgrade: installed && !!UPGRADABLE_TOOLS.find((item) => item.id === tool.id),
|
|
7699
7700
|
npmPkg: ((_b = UPGRADABLE_TOOLS.find((item) => item.id === tool.id)) == null ? void 0 : _b.npmPkg) || null
|
|
7700
7701
|
};
|
|
7701
|
-
if (
|
|
7702
|
-
|
|
7703
|
-
summary.
|
|
7704
|
-
|
|
7705
|
-
|
|
7706
|
-
|
|
7707
|
-
|
|
7708
|
-
|
|
7709
|
-
|
|
7710
|
-
|
|
7702
|
+
if (isClaudeCode) {
|
|
7703
|
+
summary.requiresInstall = !installed;
|
|
7704
|
+
summary.installLabel = "\u5B89\u88C5 Claude Code CLI";
|
|
7705
|
+
summary.installHint = process.platform === "win32" ? "Windows \u5C06\u8FD0\u884C\u5B98\u65B9\u5B89\u88C5\u811A\u672C\uFF1Airm https://claude.ai/install.ps1 | iex\u3002\u5B89\u88C5\u540E\u8BF7\u91CD\u65B0\u6253\u5F00 PowerShell/VS Code\u3002" : "\u5B89\u88C5\u5B98\u65B9 Claude Code CLI \u540E\uFF0C\u624D\u80FD\u542F\u52A8 VS Code Claude \u4EE3\u7406\uFF08hs claude-proxy\uFF09\u3002";
|
|
7706
|
+
if (installed) {
|
|
7707
|
+
const proxyState = isClaudeProxyRunning();
|
|
7708
|
+
summary.vsCodeProxy = {
|
|
7709
|
+
running: proxyState.running,
|
|
7710
|
+
configured: proxyState.running,
|
|
7711
|
+
requiresInstall: false,
|
|
7712
|
+
port: proxyState.port || null,
|
|
7713
|
+
pid: proxyState.pid || null,
|
|
7714
|
+
launchCmd: "hs claude-proxy --daemon",
|
|
7715
|
+
label: "VS Code Claude \u4EE3\u7406\uFF08hs claude-proxy\uFF09",
|
|
7716
|
+
hint: proxyState.running ? `VS Code Claude \u4EE3\u7406\u8FD0\u884C\u4E2D\uFF1A127.0.0.1:${proxyState.port}` : "\u5DF2\u5B89\u88C5 Claude Code CLI\u3002\u542F\u52A8 VS Code Claude \u4EE3\u7406\u540E\uFF0C\u8BF7\u5B8C\u5168\u9000\u51FA\u6240\u6709 Code.exe\uFF0C\u518D\u91CD\u65B0\u6253\u5F00 VS Code\u3002"
|
|
7717
|
+
};
|
|
7718
|
+
}
|
|
7711
7719
|
}
|
|
7712
7720
|
return summary;
|
|
7713
7721
|
}
|
|
@@ -9712,16 +9720,16 @@ var require_aionui_wrapper = __commonJS({
|
|
|
9712
9720
|
d.addEventListener('click',function(){if(d.parentNode)d.parentNode.removeChild(d);sessionStorage.setItem(DISMISS_KEY,'1')});
|
|
9713
9721
|
setTimeout(function(){if(d.parentNode)d.parentNode.removeChild(d);},30000);
|
|
9714
9722
|
})();
|
|
9715
|
-
// [v2.1.
|
|
9723
|
+
// [v2.1.70] Single CLI management panel \u2014 floating "\u{1F527} CLI \u7BA1\u7406" button bottom-left
|
|
9716
9724
|
(function(){
|
|
9717
|
-
var btn=el('div','position:fixed;bottom:16px;left:16px;z-index:99998;background:#2d3748;color:#fff;padding:8px 14px;border-radius:20px;font-size:12px;cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,.2);user-select:none','\u{1F527} CLI \
|
|
9718
|
-
btn.title='\
|
|
9725
|
+
var btn=el('div','position:fixed;bottom:16px;left:16px;z-index:99998;background:#2d3748;color:#fff;padding:8px 14px;border-radius:20px;font-size:12px;cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,.2);user-select:none','\u{1F527} CLI \u7BA1\u7406');
|
|
9726
|
+
btn.title='\u7EDF\u4E00\u7BA1\u7406 CLI\u3001MCP \u4E0E VS Code Claude \u4EE3\u7406';
|
|
9719
9727
|
document.body.appendChild(btn);
|
|
9720
9728
|
var panel=null;
|
|
9721
9729
|
btn.addEventListener('click',function(){
|
|
9722
9730
|
if(panel){if(panel.parentNode)panel.parentNode.removeChild(panel);panel=null;return}
|
|
9723
9731
|
panel=el('div','position:fixed;bottom:56px;left:16px;z-index:99998;background:#fff;color:#222;width:420px;max-height:70vh;overflow-y:auto;border-radius:8px;box-shadow:0 4px 20px rgba(0,0,0,.25);padding:16px;font-size:13px',
|
|
9724
|
-
'<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px"><b>CLI \
|
|
9732
|
+
'<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px"><b>CLI \u7BA1\u7406</b><span id="hs-cli-close" style="cursor:pointer;font-size:16px;color:#999">\xD7</span></div>'+
|
|
9725
9733
|
'<div id="hs-cli-list" style="color:#666">\u52A0\u8F7D\u4E2D...</div>'+
|
|
9726
9734
|
'<div id="hs-cli-log" style="margin-top:12px;font-size:11px;background:#1e1e1e;color:#0f0;padding:8px;border-radius:4px;max-height:200px;overflow-y:auto;display:none;font-family:monospace;white-space:pre-wrap"></div>');
|
|
9727
9735
|
document.body.appendChild(panel);
|
|
@@ -9742,10 +9750,14 @@ var require_aionui_wrapper = __commonJS({
|
|
|
9742
9750
|
// [v2.1.63] \u542F\u52A8 button \u2014 installed + has launchCmd (covers OpenClaw etc.)
|
|
9743
9751
|
if(t.installed&&t.launchCmd)btns+='<button data-act="launch" data-id="'+t.id+'" style="'+btnSty+';background:#f59e0b">\u542F\u52A8</button>';
|
|
9744
9752
|
var proxy='';
|
|
9745
|
-
if(t.id==='claude-code'
|
|
9746
|
-
|
|
9747
|
-
|
|
9748
|
-
|
|
9753
|
+
if(t.id==='claude-code'){
|
|
9754
|
+
if(t.requiresInstall||!t.installed||!t.vsCodeProxy){
|
|
9755
|
+
proxy='<div style="margin-top:6px;padding:6px 8px;background:#eff6ff;border:1px solid #bfdbfe;border-radius:6px;font-size:11px;color:#1d4ed8" data-requires-install="true">\u5148\u5B89\u88C5 Claude Code CLI\uFF1B\u4E0D\u5B58\u5728\u5355\u72EC\u7684 vscode-claudecode \u63D2\u4EF6\uFF0CVS Code \u91CC\u4F7F\u7528\u5B98\u65B9 Claude Code \u6269\u5C55 + HolySheep \u672C\u5730\u4EE3\u7406\u3002</div>';
|
|
9756
|
+
}else{
|
|
9757
|
+
var p=t.vsCodeProxy;
|
|
9758
|
+
var pText=p.running?('\u8FD0\u884C\u4E2D 127.0.0.1:'+p.port+' \xB7 PID '+p.pid):'\u672A\u542F\u52A8\uFF08Windows \u542F\u52A8\u540E\u9700\u5B8C\u5168\u9000\u51FA Code.exe \u518D\u91CD\u5F00 VS Code\uFF09';
|
|
9759
|
+
proxy='<div style="margin-top:6px;padding:6px 8px;background:#fff7ed;border:1px solid #fed7aa;border-radius:6px;font-size:11px;color:#9a3412">VS Code Claude \u4EE3\u7406\uFF08hs claude-proxy\uFF09\uFF1A'+pText+' <button data-act="launch" data-id="claude-proxy" style="'+btnSty+';background:#f59e0b">'+(p.running?'\u91CD\u65B0\u6821\u51C6':'\u542F\u52A8 VS Code \u4EE3\u7406')+'</button>'+(p.running?' <button data-act="reset" data-id="claude-proxy" style="'+btnSty+';background:#dc2626">\u505C\u6B62</button>':'')+'</div>';
|
|
9760
|
+
}
|
|
9749
9761
|
}
|
|
9750
9762
|
return '<div style="padding:8px 0;border-bottom:1px solid #eee"><div style="display:flex;justify-content:space-between;align-items:center"><div><b>'+t.name+'</b> '+statusBadge+' '+verText+'</div><div>'+btns+'</div></div>'+proxy+'</div>';
|
|
9751
9763
|
}).join('')+'<div style="padding-top:10px"><button id="hs-cli-upgrade-all" style="width:100%;padding:8px;background:#16a34a;color:#fff;border:0;border-radius:4px;cursor:pointer;font-weight:600">\u4E00\u952E\u5347\u7EA7\u5168\u90E8\u5DF2\u5B89\u88C5\u7684 CLI</button></div>';
|
|
@@ -9756,31 +9768,16 @@ var require_aionui_wrapper = __commonJS({
|
|
|
9756
9768
|
if(allBtn)allBtn.addEventListener('click',function(){runAllUpgrade(allBtn)});
|
|
9757
9769
|
}
|
|
9758
9770
|
function runAction(act,id,b){
|
|
9759
|
-
// [v2.1.63] launch returns plain JSON (not SSE) with { url, ... }
|
|
9760
9771
|
if(act==='launch'){
|
|
9761
9772
|
b.disabled=true;b.style.opacity='.5';b.textContent='\u542F\u52A8\u4E2D...';
|
|
9762
|
-
logEl.style.display='block';logEl.textContent='\u6B63\u5728\u542F\u52A8 '+id+'
|
|
9763
|
-
|
|
9764
|
-
|
|
9765
|
-
.
|
|
9766
|
-
|
|
9767
|
-
|
|
9768
|
-
|
|
9769
|
-
|
|
9770
|
-
try{ window.open(j.url,'_blank') }catch(e){}
|
|
9771
|
-
}else if(j&&j.success===false){
|
|
9772
|
-
logEl.textContent+='\u542F\u52A8\u5931\u8D25: '+(j.message||j.error||'unknown')+'\\n';
|
|
9773
|
-
b.textContent='\u2717 \u5931\u8D25 (\u91CD\u8BD5)';
|
|
9774
|
-
}else{
|
|
9775
|
-
logEl.textContent+=JSON.stringify(j)+'\\n';
|
|
9776
|
-
b.textContent='\u2713 \u5DF2\u542F\u52A8';
|
|
9777
|
-
}
|
|
9778
|
-
setTimeout(loadTools,500);
|
|
9779
|
-
})
|
|
9780
|
-
.catch(function(e){
|
|
9781
|
-
b.disabled=false;b.style.opacity='1';b.textContent='\u2717 \u5931\u8D25 (\u91CD\u8BD5)';
|
|
9782
|
-
logEl.textContent+='\u8BF7\u6C42\u5931\u8D25: '+e.message+'\\n';
|
|
9783
|
-
});
|
|
9773
|
+
logEl.style.display='block';logEl.textContent='\u6B63\u5728\u542F\u52A8 '+id+'...
|
|
9774
|
+
';
|
|
9775
|
+
postMaybeSse('/api/holysheep/tool/launch',{toolId:id},logEl,function(ok,j){
|
|
9776
|
+
b.disabled=false;b.style.opacity='1';
|
|
9777
|
+
if(j&&j.url){try{ window.open(j.url,'_blank') }catch(e){}}
|
|
9778
|
+
b.textContent=ok?'\u2713 \u5DF2\u542F\u52A8':'\u2717 \u5931\u8D25 (\u91CD\u8BD5)';
|
|
9779
|
+
setTimeout(loadTools,500);
|
|
9780
|
+
});
|
|
9784
9781
|
return;
|
|
9785
9782
|
}
|
|
9786
9783
|
b.disabled=true;b.style.opacity='.5';b.textContent=act==='install'?'\u5B89\u88C5\u4E2D...':act==='upgrade'?'\u5347\u7EA7\u4E2D...':'\u914D\u7F6E\u4E2D...';
|
|
@@ -9799,31 +9796,56 @@ var require_aionui_wrapper = __commonJS({
|
|
|
9799
9796
|
setTimeout(loadTools,500);
|
|
9800
9797
|
});
|
|
9801
9798
|
}
|
|
9802
|
-
function
|
|
9799
|
+
function contentTypeOf(r){return String((r.headers&&r.headers.get&&r.headers.get('content-type'))||'').toLowerCase()}
|
|
9800
|
+
function appendSseEvent(ev,logEl){
|
|
9801
|
+
if(ev.type==='output'&&ev.text){logEl.textContent+=ev.text;logEl.scrollTop=logEl.scrollHeight}
|
|
9802
|
+
else if(ev.type==='progress'&&ev.message){logEl.textContent+='\u2192 '+ev.message+'
|
|
9803
|
+
';logEl.scrollTop=logEl.scrollHeight}
|
|
9804
|
+
else if(ev.type==='tool'&&ev.status){logEl.textContent+='['+ev.name+'] '+ev.status+(ev.newVer?' v'+ev.newVer:'')+'
|
|
9805
|
+
'}
|
|
9806
|
+
else if(ev.type==='done'&&ev.success===false){logEl.textContent+='\u2717 '+(ev.message||ev.error||'\u5931\u8D25')+'
|
|
9807
|
+
'}
|
|
9808
|
+
}
|
|
9809
|
+
function consumeSseResponse(r,logEl,done){
|
|
9810
|
+
var reader=r.body.getReader();var dec=new TextDecoder();var buf='';var ok=true;
|
|
9811
|
+
function handlePart(p){
|
|
9812
|
+
var line=p.split('
|
|
9813
|
+
').find(function(l){return l.startsWith('data:')});
|
|
9814
|
+
if(!line)return;
|
|
9815
|
+
try{var ev=JSON.parse(line.slice(5).trim());if(ev.type==='done'&&ev.success===false)ok=false;appendSseEvent(ev,logEl)}catch(e){logEl.textContent+=line.slice(5).trim()+'
|
|
9816
|
+
'}
|
|
9817
|
+
}
|
|
9818
|
+
function pump(){
|
|
9819
|
+
reader.read().then(function(s){
|
|
9820
|
+
if(s.done){if(buf)handlePart(buf);return done(ok)}
|
|
9821
|
+
buf+=dec.decode(s.value,{stream:true});
|
|
9822
|
+
var parts=buf.split('
|
|
9823
|
+
|
|
9824
|
+
');buf=parts.pop();parts.forEach(handlePart);pump();
|
|
9825
|
+
}).catch(function(e){logEl.textContent+='
|
|
9826
|
+
[\u9519\u8BEF] '+e.message;done(false)})
|
|
9827
|
+
}
|
|
9828
|
+
pump();
|
|
9829
|
+
}
|
|
9830
|
+
function postMaybeSse(url,body,logEl,done){
|
|
9803
9831
|
fetch(url,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body||{})}).then(function(r){
|
|
9804
|
-
var
|
|
9805
|
-
|
|
9806
|
-
|
|
9807
|
-
|
|
9808
|
-
|
|
9809
|
-
|
|
9810
|
-
|
|
9811
|
-
|
|
9812
|
-
|
|
9813
|
-
|
|
9814
|
-
|
|
9815
|
-
|
|
9816
|
-
|
|
9817
|
-
|
|
9818
|
-
|
|
9819
|
-
}catch(e){}
|
|
9820
|
-
});
|
|
9821
|
-
pump();
|
|
9822
|
-
}).catch(function(e){logEl.textContent+='\\n[\u9519\u8BEF] '+e.message;done(false)})
|
|
9823
|
-
}
|
|
9824
|
-
pump();
|
|
9825
|
-
}).catch(function(e){logEl.textContent='\u8BF7\u6C42\u5931\u8D25: '+e.message;done(false)});
|
|
9832
|
+
var ct=contentTypeOf(r);
|
|
9833
|
+
if(ct.indexOf('text/event-stream')>=0)return consumeSseResponse(r,logEl,done);
|
|
9834
|
+
if(ct.indexOf('application/json')>=0)return r.json().then(function(j){
|
|
9835
|
+
if(j&&j.url)logEl.textContent+='\u5DF2\u542F\u52A8: '+j.url+'
|
|
9836
|
+
';
|
|
9837
|
+
else if(j&&(j.ok===false||j.success===false))logEl.textContent+='\u5931\u8D25: '+(j.message||j.error||'unknown')+'
|
|
9838
|
+
';
|
|
9839
|
+
else logEl.textContent+=JSON.stringify(j)+'
|
|
9840
|
+
';
|
|
9841
|
+
done(!(j&&(j.ok===false||j.success===false)),j);
|
|
9842
|
+
});
|
|
9843
|
+
return r.text().then(function(t){logEl.textContent+=t+'
|
|
9844
|
+
';done(r.ok)})
|
|
9845
|
+
}).catch(function(e){logEl.textContent+='\u8BF7\u6C42\u5931\u8D25: '+e.message+'
|
|
9846
|
+
';done(false)});
|
|
9826
9847
|
}
|
|
9848
|
+
function consumeSse(url,body,logEl,done){postMaybeSse(url,body,logEl,done)}
|
|
9827
9849
|
function loadTools(){
|
|
9828
9850
|
fetch('/api/holysheep/tools').then(function(r){return r.json()}).then(renderTools).catch(function(e){listEl.innerHTML='<i style="color:#dc2626">\u52A0\u8F7D\u5931\u8D25: '+e.message+'</i>'});
|
|
9829
9851
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simonyea/holysheep-cli",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.71",
|
|
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
|
"scripts": {
|
|
6
6
|
"build": "node scripts/build.mjs",
|
|
7
|
-
"test": "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js && node tests/opencode-auth-purge.test.js && node tests/shell-winpath.test.js && node tests/openclaw-atomic-write.test.js && node tests/openclaw-disable-auth-direct.test.js && node tests/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-runtime-resources.test.js && node tests/aionui-wrapper-claude-proxy.test.js && node tests/aionui-wrapper-probe.test.js && node tests/aionui-wrapper-proxy-integration.test.js && node tests/aionui-wrapper-all-clis-autoconf.test.js && node tests/aionui-wrapper-env-signal.test.js && node tests/aionui-wrapper-csp-rewrite.test.js && node tests/aionui-wrapper-version-status.test.js && node tests/claude-proxy-daemon.test.js && node tests/claude-proxy-vscode-settings.test.js && node tests/claude-proxy-vscode-env.test.js && node tests/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js && node tests/claude-code-configure-preserve.test.js && node tests/webui-claude-proxy-virtual-tool.test.js && node tests/webui-claude-proxy-ui.test.js",
|
|
7
|
+
"test": "node tests/droid.test.js && node tests/workspace-store.test.js && node tests/runtime-stale-upgrade.test.js && node tests/hermes.test.js && node tests/preflight.test.js && node tests/opencode-auth-purge.test.js && node tests/shell-winpath.test.js && node tests/openclaw-atomic-write.test.js && node tests/openclaw-disable-auth-direct.test.js && node tests/opencode-default-model.test.js && node tests/paths-bundled.test.js && node tests/aionui-runtime-resources.test.js && node tests/aionui-wrapper-claude-proxy.test.js && node tests/aionui-wrapper-probe.test.js && node tests/aionui-wrapper-proxy-integration.test.js && node tests/aionui-wrapper-all-clis-autoconf.test.js && node tests/aionui-wrapper-env-signal.test.js && node tests/aionui-wrapper-csp-rewrite.test.js && node tests/aionui-wrapper-version-status.test.js && node tests/claude-proxy-daemon.test.js && node tests/claude-proxy-vscode-settings.test.js && node tests/claude-proxy-vscode-env.test.js && node tests/acptypes-patch.test.js && node tests/codex-approval-policy.test.js && node tests/version-check.test.js && node tests/runclaude-missing-binary.test.js && node tests/claude-code-configure-preserve.test.js && node tests/webui-claude-proxy-virtual-tool.test.js && node tests/webui-claude-proxy-ui.test.js && node tests/webui-response-consumer.test.js && node tests/webui-claude-proxy-install-gating.test.js",
|
|
8
8
|
"prepublishOnly": "npm run build && npm test && node scripts/check-tarball-size.js"
|
|
9
9
|
},
|
|
10
10
|
"keywords": [
|