chore(portable): 回归纯开源 — 移除指纹/自动开户/崩溃上报
去掉不适合开源的商业逻辑,保持一个纯粹的开源 U 盘工具: - 删除设备指纹 (fingerprint.mjs)、虾盘云自动开户 (bootstrap-xiapan.mjs / xiapan-client.mjs)、自动崩溃上报 (report-bug.mjs),portable 和 Electron 两份都删 - 启动脚本去掉绑定指纹调用 + 全部 --auto 自动上报;保留 bonjour 禁用与括号转义 - config-server 删掉 /api/xiapan/* 和 /api/report-bug 端点 - Config.html:虾盘云改为普通「首选」卡片,强调中转站 / 国内外全部大模型, 和其它 provider 一样需用户自填 Key(去 u-claw.org/cloud.html 注册),不再自动开户 - 报 Bug 表单改为指向 GitHub Issue,不再上传日志 - README / release notes / CLAUDE.md 文案改为「选模型填 Key,不绑定设备、不打指纹、不上传数据」 - OPENCLAW_VERSION 跟进最新龙虾版本 2026.6.6 → 2026.6.8 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -413,21 +413,9 @@ input:focus { border-color: #ff6b35; }
|
||||
|
||||
<div class="section active skills-section" style="display:block; margin-top: 8px;">
|
||||
<h2>🐛 反馈 / 报 Bug</h2>
|
||||
<p class="desc">遇到问题?一键反馈给我们,会自动附带版本号和最近日志(不含你的 API Key),方便我们排查。</p>
|
||||
<div class="form-group">
|
||||
<label>问题标题 <span style="color:#888;font-weight:normal">(必填,简短描述)</span></label>
|
||||
<input type="text" id="bugTitle" placeholder="例如:点击打开 Dashboard 没反应" maxlength="200">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>详细描述 <span style="color:#888;font-weight:normal">(可选)</span></label>
|
||||
<textarea id="bugDesc" rows="4" placeholder="发生了什么?做了哪些操作?" style="width:100%;padding:12px;border-radius:8px;background:#1a1a1a;border:1px solid #333;color:#eee;font-family:inherit;font-size:0.95em;box-sizing:border-box;resize:vertical"></textarea>
|
||||
</div>
|
||||
<div class="form-group" style="display:flex;align-items:center;gap:8px">
|
||||
<input type="checkbox" id="bugLogs" checked style="width:auto;margin:0">
|
||||
<label for="bugLogs" style="margin:0;font-weight:normal">附带最近运行日志(推荐,帮助定位问题)</label>
|
||||
</div>
|
||||
<p class="desc">U-Claw 是开源项目。遇到问题欢迎到 GitHub 提 Issue —— 我们不会自动收集或上传你的任何数据。</p>
|
||||
<div class="btn-row">
|
||||
<button class="btn btn-primary" id="bugSubmitBtn" onclick="submitBug()">提交反馈</button>
|
||||
<a class="btn btn-primary" href="https://github.com/dongsheng123132/u-claw/issues/new" target="_blank">→ 在 GitHub 提交 Issue</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -726,32 +714,6 @@ async function viewConfig() {
|
||||
}
|
||||
}
|
||||
|
||||
// --- Bug report ---
|
||||
async function submitBug() {
|
||||
var title = document.getElementById('bugTitle').value.trim();
|
||||
if (title.length < 3) { showToast('请填写问题标题(至少 3 个字)', true); return; }
|
||||
var desc = document.getElementById('bugDesc').value.trim();
|
||||
var includeLogs = document.getElementById('bugLogs').checked;
|
||||
var btn = document.getElementById('bugSubmitBtn');
|
||||
btn.disabled = true; btn.textContent = '提交中…';
|
||||
try {
|
||||
var res = await fetch('/api/report-bug', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ title: title, description: desc, includeLogs: includeLogs })
|
||||
});
|
||||
var data = await res.json();
|
||||
if (!res.ok || !data.ok) throw new Error(data.reason || data.error || '提交失败');
|
||||
showToast('反馈已提交,编号 #' + data.id + ',谢谢!');
|
||||
document.getElementById('bugTitle').value = '';
|
||||
document.getElementById('bugDesc').value = '';
|
||||
} catch (e) {
|
||||
showToast('提交失败:' + e.message, true);
|
||||
} finally {
|
||||
btn.disabled = false; btn.textContent = '提交反馈';
|
||||
}
|
||||
}
|
||||
|
||||
// --- Toast ---
|
||||
function showToast(msg, isError) {
|
||||
var t = document.getElementById('toast');
|
||||
|
||||
@@ -393,32 +393,6 @@ const server = http.createServer((req, res) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// API: Xiapan Cloud status (fingerprint + apiKey + balance)
|
||||
if (req.url === '/api/xiapan/status' && req.method === 'GET') {
|
||||
(async () => {
|
||||
try {
|
||||
const fpMod = await import('../lib/fingerprint.mjs');
|
||||
const xpMod = await import('../lib/xiapan-client.mjs');
|
||||
const portableRoot = path.join(__dirname, '..');
|
||||
const fp = await fpMod.getFingerprint(portableRoot);
|
||||
const apiKey = xpMod.buildApiKey(fp.fingerprint);
|
||||
const balance = await xpMod.getBalance(apiKey);
|
||||
const rechargeUrl = xpMod.getRechargeUrl(apiKey);
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({
|
||||
source: fp.source,
|
||||
apiKey,
|
||||
rechargeUrl,
|
||||
balance,
|
||||
}));
|
||||
} catch (err) {
|
||||
res.writeHead(500, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ error: err.message }));
|
||||
}
|
||||
})();
|
||||
return;
|
||||
}
|
||||
|
||||
// API: Update status — read update-available.json written by check-update.mjs
|
||||
// Returns { available: false } if no info or stale; otherwise the manifest payload.
|
||||
if (req.url === '/api/update-status' && req.method === 'GET') {
|
||||
@@ -463,45 +437,6 @@ const server = http.createServer((req, res) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// API: Re-run bootstrap to inject the uclaw-cloud provider
|
||||
if (req.url === '/api/xiapan/bind' && req.method === 'POST') {
|
||||
(async () => {
|
||||
try {
|
||||
const mod = await import('../lib/bootstrap-xiapan.mjs');
|
||||
const portableRoot = path.join(__dirname, '..');
|
||||
const result = await mod.bootstrapXiapan({
|
||||
configPath: CONFIG_PATH,
|
||||
appRoot: portableRoot,
|
||||
});
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify(result));
|
||||
} catch (err) {
|
||||
res.writeHead(500, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ error: err.message }));
|
||||
}
|
||||
})();
|
||||
return;
|
||||
}
|
||||
|
||||
// API: Remove uclaw-cloud provider so the next bind regenerates it
|
||||
if (req.url === '/api/xiapan/unbind' && req.method === 'POST') {
|
||||
try {
|
||||
if (fs.existsSync(CONFIG_PATH)) {
|
||||
const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
|
||||
if (config.models && config.models.providers && config.models.providers['uclaw-cloud']) {
|
||||
delete config.models.providers['uclaw-cloud'];
|
||||
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
|
||||
}
|
||||
}
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ ok: true }));
|
||||
} catch (err) {
|
||||
res.writeHead(500, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ error: err.message }));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// API: Save config
|
||||
if (req.url === '/api/config' && req.method === 'POST') {
|
||||
let body = '';
|
||||
@@ -524,37 +459,6 @@ const server = http.createServer((req, res) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// API: Report a bug — user fills title/description in the web UI; this endpoint
|
||||
// attaches fingerprint/version/logs locally and forwards to api.u-claw.org.
|
||||
if (req.url === '/api/report-bug' && req.method === 'POST') {
|
||||
let body = '';
|
||||
req.on('data', chunk => {
|
||||
body += chunk;
|
||||
if (body.length > 2 * 1024 * 1024) req.destroy(); // 2MB cap on user input
|
||||
});
|
||||
req.on('end', () => {
|
||||
(async () => {
|
||||
try {
|
||||
const data = body ? JSON.parse(body) : {};
|
||||
const mod = await import('../lib/report-bug.mjs');
|
||||
const portableRoot = path.join(__dirname, '..');
|
||||
const result = await mod.submitBugReport({
|
||||
title: data.title,
|
||||
description: data.description,
|
||||
appRoot: portableRoot,
|
||||
includeLogs: data.includeLogs !== false, // 默认带日志,用户可勾掉
|
||||
});
|
||||
res.writeHead(result.ok ? 200 : 400, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify(result));
|
||||
} catch (err) {
|
||||
res.writeHead(500, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ ok: false, error: err.message }));
|
||||
}
|
||||
})();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Serve static files
|
||||
const filePath = req.url === '/'
|
||||
? path.join(__dirname, 'public/index.html')
|
||||
|
||||
Reference in New Issue
Block a user