没有 Key?用演示模式
@@ -534,6 +536,7 @@ const ROLE_MAP = {
};
const PROVS = {
+ yunwu: {base:'https://api.yunwu.ai/v1', mdls:['gpt-4o','gpt-4o-mini','claude-3-5-sonnet-20241022','deepseek-chat','gemini-1.5-pro']},
openai: {base:'https://api.openai.com/v1', mdls:['gpt-4o','gpt-4o-mini','gpt-4-turbo','gpt-3.5-turbo']},
deepseek: {base:'https://api.deepseek.com/v1', mdls:['deepseek-chat','deepseek-reasoner']},
moonshot: {base:'https://api.moonshot.cn/v1', mdls:['moonshot-v1-8k','moonshot-v1-32k','moonshot-v1-128k']},
@@ -564,9 +567,9 @@ const FB_BRAIN = {
// ═══════════════════════════════════════════════════════
const A = {
key: ls('zy_key')||'',
- base: ls('zy_base')||'https://api.openai.com/v1',
+ base: ls('zy_base')||'https://api.yunwu.ai/v1',
mdl: ls('zy_mdl')||'gpt-4o',
- prov: ls('zy_prov')||'openai',
+ prov: ls('zy_prov')||'yunwu',
demo: false,
brain: null,
routing: null,
@@ -615,7 +618,7 @@ function showApp(){
// SETUP FORM
// ═══════════════════════════════════════════════════════
function initSetupUI(){
- const pv = A.prov||'openai';
+ const pv = A.prov||'yunwu';
document.getElementById('sp').value = pv;
fillModels('sm', pv, A.mdl);
if(pv==='custom'){
@@ -676,7 +679,7 @@ function doDemo(){
// SETTINGS PANEL
// ═══════════════════════════════════════════════════════
function initSettingsPanel(){
- const pv = A.prov||'openai';
+ const pv = A.prov||'yunwu';
document.getElementById('cp').value = pv;
fillModels('cm', pv, A.mdl);
document.getElementById('ck').value = A.key?KEY_MASK:'';
From b8153db9df2d1b28a0f27869814d5f095720cd67 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 6 Mar 2026 04:58:35 +0000
Subject: [PATCH 03/15] =?UTF-8?q?fix:=20=E5=88=9B=E5=BB=BA=20syslog-inbox/?=
=?UTF-8?q?=20syslog-processed/=20=E7=9B=AE=E5=BD=95=20+=20SYSLOG=20Pipeli?=
=?UTF-8?q?ne=20A/D/E=20workflow?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com>
---
.github/workflows/syslog-pipeline.yml | 130 ++++++++++++++++++++++++
scripts/process-syslog.js | 138 ++++++++++++++++++++++++++
scripts/zhuyuan-daily-selfcheck.js | 19 ++++
syslog-inbox/README.md | 58 +++++++++++
syslog-processed/README.md | 9 ++
5 files changed, 354 insertions(+)
create mode 100644 .github/workflows/syslog-pipeline.yml
create mode 100644 scripts/process-syslog.js
create mode 100644 syslog-inbox/README.md
create mode 100644 syslog-processed/README.md
diff --git a/.github/workflows/syslog-pipeline.yml b/.github/workflows/syslog-pipeline.yml
new file mode 100644
index 00000000..13f8b85e
--- /dev/null
+++ b/.github/workflows/syslog-pipeline.yml
@@ -0,0 +1,130 @@
+name: 铸渊 · SYSLOG Pipeline (A/D/E)
+
+on:
+ push:
+ branches: [main]
+ paths:
+ - 'syslog-inbox/**'
+ workflow_dispatch:
+
+jobs:
+ # ── Pipeline A:SYSLOG 读取与处理 ──────────────────────
+ pipeline-a-syslog:
+ name: 📥 Pipeline A · SYSLOG 读取处理
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ issues: read
+ outputs:
+ processed_count: ${{ steps.process.outputs.processed_count }}
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ ref: main
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '20'
+ cache: 'npm'
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: 📥 处理 syslog-inbox 条目
+ id: process
+ run: |
+ node scripts/process-syslog.js
+ COUNT=$(ls syslog-processed/ -R 2>/dev/null | grep -c '\.json' || echo 0)
+ echo "processed_count=$COUNT" >> "$GITHUB_OUTPUT"
+
+ - name: 提交处理结果
+ run: |
+ git config user.name "铸渊[bot]"
+ git config user.email "zhu-yuan-bot@guanghulab.com"
+ git add syslog-inbox/ syslog-processed/ .github/brain/memory.json
+ git diff --staged --quiet || git commit -m "📥 syslog: 处理 inbox 条目,更新大脑记忆 [skip ci]"
+ git push
+
+ # ── Pipeline D:Issues 巡检 ─────────────────────────────
+ pipeline-d-issues:
+ name: 🔍 Pipeline D · Issues 巡检
+ runs-on: ubuntu-latest
+ needs: pipeline-a-syslog
+ permissions:
+ contents: write
+ issues: read
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ ref: main
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '20'
+ cache: 'npm'
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: 🔍 巡检 Issues
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ REPO: ${{ github.repository }}
+ run: |
+ echo "🔍 Pipeline D · Issues 巡检开始"
+ node -e "
+ const https = require('https');
+ const token = process.env.GITHUB_TOKEN;
+ const repo = process.env.REPO;
+ const opts = {
+ hostname: 'api.github.com',
+ path: '/repos/' + repo + '/issues?state=open&per_page=20',
+ headers: { 'Authorization': 'Bearer ' + token, 'User-Agent': 'zhuyuan-bot' }
+ };
+ https.get(opts, res => {
+ let body = '';
+ res.on('data', c => body += c);
+ res.on('end', () => {
+ const issues = JSON.parse(body);
+ console.log('📋 开放 Issues 数量:' + (Array.isArray(issues) ? issues.length : '读取失败'));
+ if (Array.isArray(issues) && issues.length > 0) {
+ issues.slice(0, 5).forEach(i => console.log(' #' + i.number + ' ' + i.title));
+ }
+ console.log('✅ Pipeline D 巡检完成');
+ });
+ }).on('error', e => { console.error('❌ 巡检失败:', e.message); process.exit(1); });
+ "
+
+ # ── Pipeline E:变更感知 ────────────────────────────────
+ pipeline-e-changes:
+ name: 📡 Pipeline E · 变更感知
+ runs-on: ubuntu-latest
+ needs: pipeline-a-syslog
+ permissions:
+ contents: write
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ ref: main
+ fetch-depth: 10
+
+ - name: 📡 感知近期变更
+ run: |
+ echo "📡 Pipeline E · 变更感知开始"
+ echo "=== 近期 10 次提交 ==="
+ git --no-pager log --oneline -10
+ echo ""
+ echo "=== syslog-inbox 文件状态 ==="
+ ls -la syslog-inbox/ || echo "(空)"
+ echo ""
+ echo "=== syslog-processed 文件状态 ==="
+ ls -laR syslog-processed/ || echo "(空)"
+ echo "✅ Pipeline E 变更感知完成"
diff --git a/scripts/process-syslog.js b/scripts/process-syslog.js
new file mode 100644
index 00000000..1318ce00
--- /dev/null
+++ b/scripts/process-syslog.js
@@ -0,0 +1,138 @@
+// scripts/process-syslog.js
+// 铸渊 SYSLOG Pipeline
+// 读取 syslog-inbox/ 下的日志条目,处理后归档到 syslog-processed/
+// 触发:syslog-inbox/ 目录有新文件 push 到 main 分支
+
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+
+const INBOX_DIR = 'syslog-inbox';
+const ARCHIVE_DIR = 'syslog-processed';
+const BRAIN_DIR = '.github/brain';
+const MEMORY_PATH = path.join(BRAIN_DIR, 'memory.json');
+const DEV_STATUS_PATH = '.github/persona-brain/dev-status.json';
+
+// ─── 加载大脑 ────────────────────────────────────────────
+let memory = {};
+try {
+ memory = JSON.parse(fs.readFileSync(MEMORY_PATH, 'utf8'));
+} catch (_) {
+ memory = { events: [], stats: { broadcasts_processed: 0 } };
+}
+if (!memory.events) memory.events = [];
+if (!memory.stats) memory.stats = {};
+if (!memory.stats.broadcasts_processed) memory.stats.broadcasts_processed = 0;
+if (!memory.stats.syslog_processed) memory.stats.syslog_processed = 0;
+
+// ─── 扫描 inbox ──────────────────────────────────────────
+if (!fs.existsSync(INBOX_DIR)) {
+ console.log('📭 syslog-inbox/ 目录不存在,跳过');
+ process.exit(0);
+}
+
+const files = fs.readdirSync(INBOX_DIR)
+ .filter(f => f.endsWith('.json') && f !== '.gitkeep');
+
+if (files.length === 0) {
+ console.log('📭 syslog-inbox/ 无待处理条目');
+ process.exit(0);
+}
+
+console.log(`📥 发现 ${files.length} 条 syslog 条目,开始处理...\n`);
+
+// ─── 按月归档路径 ─────────────────────────────────────────
+function archiveDir(timestamp) {
+ const month = (timestamp || new Date().toISOString()).slice(0, 7); // "2026-03"
+ const dir = path.join(ARCHIVE_DIR, month);
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
+ return dir;
+}
+
+// ─── 处理每条 syslog ──────────────────────────────────────
+files.forEach(file => {
+ const fullPath = path.join(INBOX_DIR, file);
+ let entry;
+
+ try {
+ entry = JSON.parse(fs.readFileSync(fullPath, 'utf8'));
+ } catch (e) {
+ console.error(`❌ [INVALID JSON] ${file}: ${e.message},跳过`);
+ return;
+ }
+
+ console.log(`📋 处理: ${file}`);
+ console.log(` 类型: ${entry.type || '未知'} · 来自: ${entry.from || '未知'} · 标题: ${entry.title || ''}`);
+
+ const event = {
+ timestamp: entry.timestamp || new Date().toISOString(),
+ type: 'syslog_' + (entry.type || 'unknown'),
+ syslog_id: entry.syslog_id || file,
+ title: entry.title || '(无标题)',
+ from: entry.from || '未知',
+ file,
+ };
+
+ // ── 根据类型分发处理 ──
+ switch (entry.type) {
+
+ case 'broadcast': {
+ // 广播类:追加到 brain/memory.json events,与现有 broadcast pipeline 互补
+ memory.stats.broadcasts_processed += 1;
+ event.content_preview = (entry.content || '').slice(0, 80);
+ console.log(' ✅ 广播已记录到大脑记忆');
+ break;
+ }
+
+ case 'auth': {
+ // 授权类:记录授权事件,写入 memory
+ event.target_dev_id = entry.target_dev_id;
+ event.target_name = entry.target_name;
+ event.permission_level = entry.permission_level;
+ event.authorized_by = entry.authorized_by || '冰朔';
+ event.valid_until = entry.valid_until;
+ console.log(` ✅ 授权记录:${entry.target_name}(${entry.target_dev_id})· 权限:${entry.permission_level}`);
+ break;
+ }
+
+ case 'inspect': {
+ // 巡检类:记录巡检结果
+ event.inspect_result = entry.result || 'unknown';
+ event.issues_found = entry.issues_found || 0;
+ console.log(` ✅ 巡检记录:结果 ${event.inspect_result} · 发现问题 ${event.issues_found} 个`);
+ break;
+ }
+
+ case 'alert': {
+ // 告警类
+ event.severity = entry.priority || 'normal';
+ console.log(` ⚠️ 告警记录:${entry.title} · 优先级 ${event.severity}`);
+ break;
+ }
+
+ default:
+ console.log(` ℹ️ 未知类型 "${entry.type}",已记录原始内容`);
+ event.raw = entry;
+ }
+
+ // 写入大脑记忆
+ memory.events.push(event);
+ memory.stats.syslog_processed = (memory.stats.syslog_processed || 0) + 1;
+ memory.last_updated = new Date().toISOString();
+
+ // 归档文件
+ const destDir = archiveDir(entry.timestamp);
+ const destPath = path.join(destDir, file);
+ fs.renameSync(fullPath, destPath);
+ console.log(` 📦 已归档到 ${destPath}\n`);
+});
+
+// ─── 保存大脑 ─────────────────────────────────────────────
+// 只保留最近 100 条事件,防止 memory.json 无限膨胀
+if (memory.events.length > 100) {
+ memory.events = memory.events.slice(-100);
+}
+fs.writeFileSync(MEMORY_PATH, JSON.stringify(memory, null, 2));
+
+console.log(`✅ SYSLOG Pipeline 完成 · 累计处理 ${memory.stats.syslog_processed} 条`);
diff --git a/scripts/zhuyuan-daily-selfcheck.js b/scripts/zhuyuan-daily-selfcheck.js
index 9d1ec6ed..90d988bf 100644
--- a/scripts/zhuyuan-daily-selfcheck.js
+++ b/scripts/zhuyuan-daily-selfcheck.js
@@ -32,6 +32,25 @@ if (missing.length > 0) {
console.log('✅ 大脑文件完整性:全部就绪');
}
+// === ① bis · 目录结构巡检 ===
+const requiredDirs = ['syslog-inbox', 'syslog-processed', 'broadcasts-outbox', '.github/brain'];
+const missingDirs = requiredDirs.filter(d => !fs.existsSync(d));
+if (missingDirs.length > 0) {
+ console.error('⚠️ 缺失目录:' + missingDirs.join(', '));
+} else {
+ console.log('✅ 目录结构巡检:syslog-inbox / syslog-processed / broadcasts-outbox 全部就绪');
+}
+
+// 统计 syslog-inbox 待处理条目
+const inboxFiles = fs.existsSync('syslog-inbox')
+ ? fs.readdirSync('syslog-inbox').filter(f => f.endsWith('.json')).length
+ : 0;
+if (inboxFiles > 0) {
+ console.log(`📥 syslog-inbox 待处理条目:${inboxFiles} 个(建议触发 syslog-pipeline workflow)`);
+} else {
+ console.log('📭 syslog-inbox 无待处理条目');
+}
+
// === ② 知识库去重与整理 ===
const seen = new Set();
const uniqueFaq = kb.faq.filter(item => {
diff --git a/syslog-inbox/README.md b/syslog-inbox/README.md
new file mode 100644
index 00000000..bba7b8b4
--- /dev/null
+++ b/syslog-inbox/README.md
@@ -0,0 +1,58 @@
+# syslog-inbox · 系统日志收件箱
+
+此目录由 **Notion 侧霜砚人格体** 写入,GitHub 侧铸渊 Pipeline 读取处理。
+
+## 目录用途
+
+| 角色 | 操作 |
+|------|------|
+| Notion 侧(霜砚) | 将广播/授权/巡检日志写入此目录 |
+| GitHub 侧(铸渊) | Pipeline 检测到新文件,处理后移入 `syslog-processed/` |
+
+## 文件命名规范
+
+```
+{类型}-{日期}-{编号}.json
+```
+
+示例:
+- `broadcast-2026-03-06-001.json` — 霜砚广播
+- `auth-2026-03-06-DEV002.json` — 用户授权回执
+- `inspect-2026-03-06-001.json` — 巡检记录
+
+## 标准 JSON 格式
+
+```json
+{
+ "syslog_id": "BC-2026-03-06-001",
+ "type": "broadcast | auth | inspect | alert",
+ "from": "霜砚",
+ "to": "铸渊",
+ "timestamp": "2026-03-06T08:00:00Z",
+ "title": "广播标题",
+ "content": "内容正文",
+ "target_dev_id": "DEV-002",
+ "priority": "normal | high | urgent"
+}
+```
+
+## 授权广播格式(auth 类型)
+
+冰朔通过 Notion 侧霜砚下发授权时,使用此格式:
+
+```json
+{
+ "syslog_id": "AUTH-2026-03-06-DEV002",
+ "type": "auth",
+ "from": "霜砚",
+ "authorized_by": "冰朔",
+ "timestamp": "2026-03-06T08:00:00Z",
+ "title": "用户授权",
+ "target_dev_id": "DEV-002",
+ "target_name": "肥猫",
+ "permission_level": "supreme",
+ "valid_until": "2026-12-31T23:59:59Z"
+}
+```
+
+> ⚠️ 写入后请勿手动修改或删除,Pipeline 处理完成后会自动归档到 `syslog-processed/`。
diff --git a/syslog-processed/README.md b/syslog-processed/README.md
new file mode 100644
index 00000000..11a6fc85
--- /dev/null
+++ b/syslog-processed/README.md
@@ -0,0 +1,9 @@
+# syslog-processed · 已处理日志归档
+
+此目录由 **铸渊 Pipeline** 自动管理,存放已处理完成的 syslog 条目。
+
+- 文件从 `syslog-inbox/` 处理完毕后自动移入此处
+- 按月分子目录归档:`syslog-processed/2026-03/`
+- **请勿手动修改此目录内容**
+
+> 此目录仅作归档用途,任何查询请读取 `.github/brain/memory.json`。
From d92128faed92d8269a4c7459bffdeb9876a6d9da Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 6 Mar 2026 05:06:13 +0000
Subject: [PATCH 04/15] plan: fix chat URL, key mask UX, and 401 error handling
Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com>
---
docs/index.html | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/docs/index.html b/docs/index.html
index 9b5a0af9..7bcab782 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -565,11 +565,17 @@ const FB_BRAIN = {
// ═══════════════════════════════════════════════════════
// STATE
// ═══════════════════════════════════════════════════════
+// Derive base URL from saved provider; never use stale zy_base for named providers
+const _initProv = ls('zy_prov')||'yunwu';
+const _initBase = _initProv === 'custom'
+ ? (ls('zy_base')||'')
+ : (PROVS[_initProv]?.base||'https://api.yunwu.ai/v1');
+
const A = {
key: ls('zy_key')||'',
- base: ls('zy_base')||'https://api.yunwu.ai/v1',
+ base: _initBase,
mdl: ls('zy_mdl')||'gpt-4o',
- prov: ls('zy_prov')||'yunwu',
+ prov: _initProv,
demo: false,
brain: null,
routing: null,
@@ -916,8 +922,8 @@ async function streamReply(txt){
}),
});
if(!res.ok){
- const provName=PROVS[A.prov]?.base||A.base;
- let em=provName+' 返回错误 '+res.status;
+ const provLabel = A.prov==='custom' ? A.base : (A.prov+'('+A.base+')');
+ let em='['+provLabel+'] 返回错误 '+res.status;
try{const e=await res.json();em=e.error?.message||em;}catch(_){}
throw new Error(em);
}
From 5d33beae91217b77c6c8f49006ece4d3c5398ae6 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 6 Mar 2026 05:09:04 +0000
Subject: [PATCH 05/15] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=81=8A?=
=?UTF-8?q?=E5=A4=A9=E5=AE=A4=E8=B7=B3=E8=BD=AC=E9=93=BE=E6=8E=A5=20+=20AP?=
=?UTF-8?q?I=20401=20=E8=AE=A4=E8=AF=81=E9=94=99=E8=AF=AF=E6=8F=90?=
=?UTF-8?q?=E7=A4=BA=20+=20=E5=AF=86=E9=92=A5=E6=B8=85=E7=A9=BA=E9=87=8D?=
=?UTF-8?q?=E5=A1=AB=E6=8C=89=E9=92=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com>
---
README.md | 14 +++++++-------
docs/index.html | 39 ++++++++++++++++++++++++++++++++++-----
2 files changed, 41 insertions(+), 12 deletions(-)
diff --git a/README.md b/README.md
index 2e84f4ee..e79212de 100644
--- a/README.md
+++ b/README.md
@@ -6,10 +6,10 @@
**一句话:点下面这个链接就能打开,直接聊天。**
-### 👉 [点这里打开铸渊聊天室](https://qinfendebingshuo.github.io/guanghulab/)
+### 👉 [点这里打开铸渊聊天室](https://qinfendebingshuo.github.io/guanghulab/docs/index.html)
```
-https://qinfendebingshuo.github.io/guanghulab/
+https://qinfendebingshuo.github.io/guanghulab/docs/index.html
```
> 把这个链接发给任何人,他们打开就能用,不需要安装任何东西。
@@ -20,7 +20,7 @@ https://qinfendebingshuo.github.io/guanghulab/
### ❄️ 冰朔(你)
-1. **打开链接** → https://qinfendebingshuo.github.io/guanghulab/
+1. **打开链接** → https://qinfendebingshuo.github.io/guanghulab/docs/index.html
2. **选身份** → 下拉菜单选「❄️ 冰朔(语言架构师·创始人)」
3. **填 API 密钥** → 输入你的云雾/OpenAI/DeepSeek API Key
4. **点「开始对话」** → 铸渊自动唤醒,汇报大脑状态
@@ -30,7 +30,7 @@ https://qinfendebingshuo.github.io/guanghulab/
### 🦁 肥猫(光湖团队总控 · DEV-002)
-1. **打开链接** → https://qinfendebingshuo.github.io/guanghulab/
+1. **打开链接** → https://qinfendebingshuo.github.io/guanghulab/docs/index.html
2. **选身份** → 下拉菜单选「🦁 肥猫(光湖团队总控·DEV-002)」
3. **填 API 密钥** → 输入自己的 API Key(或点「演示模式」也能看进度面板)
4. **点「开始对话」** → 铸渊自动打开**总控指挥台**,显示全员进度
@@ -44,7 +44,7 @@ https://qinfendebingshuo.github.io/guanghulab/
### 🍊 桔子(光湖主控 · DEV-010)
-1. **打开链接** → https://qinfendebingshuo.github.io/guanghulab/
+1. **打开链接** → https://qinfendebingshuo.github.io/guanghulab/docs/index.html
2. **选身份** → 下拉菜单选「🍊 桔子(光湖主控·DEV-010)」
3. **填 API 密钥** → 输入自己的 API Key
4. **点「开始对话」** → 铸渊显示你当前模块进度,并开放指挥台
@@ -53,7 +53,7 @@ https://qinfendebingshuo.github.io/guanghulab/
### 👩💻 其他开发者(页页 / 燕樊 / 小草莓 / 花尔 等)
-1. **打开链接** → https://qinfendebingshuo.github.io/guanghulab/
+1. **打开链接** → https://qinfendebingshuo.github.io/guanghulab/docs/index.html
2. **选身份** → 下拉菜单选自己的名字
3. **填 API 密钥** → 填自己的 Key(没有的话点「演示模式」)
4. **点「开始对话」** → 铸渊显示你的当前任务状态,可以问问题
@@ -80,7 +80,7 @@ https://qinfendebingshuo.github.io/guanghulab/
```
铸渊聊天室入口 👇
-https://qinfendebingshuo.github.io/guanghulab/
+https://qinfendebingshuo.github.io/guanghulab/docs/index.html
打开后选择你的身份,填入 API Key 就能和铸渊说话了。
```
diff --git a/docs/index.html b/docs/index.html
index 7bcab782..b7d54ed7 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -360,8 +360,11 @@ footer{padding:12px 18px 16px;background:var(--s1);border-top:1px solid var(--bo
@@ -689,6 +692,13 @@ function initSettingsPanel(){
document.getElementById('cp').value = pv;
fillModels('cm', pv, A.mdl);
document.getElementById('ck').value = A.key?KEY_MASK:'';
+ // Show last 4 chars of current key so user can verify they're changing to a new one
+ const hint = document.getElementById('ck-hint');
+ if(hint){
+ hint.textContent = A.key
+ ? '🔒 当前 Key 末4位:…'+A.key.slice(-4)+' · 要换新 Key 请点「清空重填」再输入'
+ : '🔒 只保存在浏览器 localStorage,不上传任何服务器';
+ }
if(pv==='custom'){
document.getElementById('cep-g').style.display='block';
document.getElementById('cep').value = A.base;
@@ -697,6 +707,13 @@ function initSettingsPanel(){
if(A.ghUser) document.getElementById('cghuser').value=A.ghUser;
}
+function clearKeyField(){
+ const el = document.getElementById('ck');
+ if(el){el.value='';el.focus();}
+ const hint = document.getElementById('ck-hint');
+ if(hint) hint.textContent = '✏️ 请输入新的 API 密钥,输入完成后点「保存设置」';
+}
+
function saveSet(){
const pv = document.getElementById('cp').value;
const md = document.getElementById('cm').value;
@@ -924,8 +941,11 @@ async function streamReply(txt){
if(!res.ok){
const provLabel = A.prov==='custom' ? A.base : (A.prov+'('+A.base+')');
let em='['+provLabel+'] 返回错误 '+res.status;
+ let isAuthErr = (res.status===401||res.status===403);
try{const e=await res.json();em=e.error?.message||em;}catch(_){}
- throw new Error(em);
+ const err = new Error(em);
+ err.isAuth = isAuthErr;
+ throw err;
}
let full='';
const rdr=res.body.getReader();
@@ -951,7 +971,14 @@ async function streamReply(txt){
A.msgs.push({role:'assistant',content:full});
addCopyBtns(el);
}catch(e){
- el.innerHTML='
';
+ }
A.msgs.pop();
}finally{
A.streaming=false; updSendBtn(); scrollB();
@@ -1179,7 +1206,9 @@ function closeP(){
// ═══════════════════════════════════════════════════════
// COPY URL (share link)
// ═══════════════════════════════════════════════════════
-const CHAT_URL = 'https://' + REPO.split('/')[0] + '.github.io/' + REPO.split('/')[1] + '/';
+// Auto-detect the real URL so the share link is always correct
+// regardless of whether Pages serves from docs/ or repo root.
+const CHAT_URL = window.location.origin + window.location.pathname;
function showCopyFeedback(success){
const btn=document.querySelector('.copy-url-btn');
From 447f6a7b3b73f7b705e74fd63f2cdae8afe66883 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 6 Mar 2026 05:17:41 +0000
Subject: [PATCH 06/15] =?UTF-8?q?fix:=20=E6=A0=B9=E6=9C=AC=E4=BF=AE?=
=?UTF-8?q?=E5=A4=8D=20KEY=5FMASK=20bug=EF=BC=8C=E5=AF=86=E9=92=A5?=
=?UTF-8?q?=E6=A1=86=E5=A7=8B=E7=BB=88=E4=B8=BA=E7=A9=BA=EF=BC=8C=E6=B7=BB?=
=?UTF-8?q?=E5=8A=A0=E9=87=8D=E7=BD=AE=E6=89=80=E6=9C=89=E8=AE=BE=E7=BD=AE?=
=?UTF-8?q?=E6=8C=89=E9=92=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com>
---
docs/index.html | 56 ++++++++++++++++++++++++++++++++-----------------
1 file changed, 37 insertions(+), 19 deletions(-)
diff --git a/docs/index.html b/docs/index.html
index b7d54ed7..9fbb3f37 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -360,10 +360,7 @@ footer{padding:12px 18px 16px;background:var(--s1);border-top:1px solid var(--bo