diff --git a/docs/index.html b/docs/index.html index c1c4cf94..35a366e2 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,5 +1,5 @@ - + @@ -38,6 +38,12 @@ html,body{height:100%;background:var(--bg);color:var(--text);font-family:'PingFa .sc-btn:hover{opacity:.85} .sc-skip{text-align:center;font-size:12px;color:var(--dim);margin-top:12px} .sc-skip a{color:var(--accent);text-decoration:none;cursor:pointer} +.login-tabs{display:flex;gap:0;margin-bottom:20px;border:1px solid var(--border);border-radius:var(--rs);overflow:hidden} +.login-tab{flex:1;padding:10px;text-align:center;background:var(--s2);color:var(--dim);font-size:13px;font-weight:600;cursor:pointer;border:none;font-family:inherit;transition:all .2s} +.login-tab.active{background:var(--accent);color:#fff} +.login-tab:hover:not(.active){background:var(--s3);color:var(--text)} +.login-mode{display:none} +.login-mode.active{display:block} #id-preview{display:none;text-align:center;margin-bottom:10px;padding:10px;background:var(--s3);border-radius:8px;font-size:14px;font-weight:600} /* ─── APP SHELL (three-column) ─── */ @@ -318,48 +324,30 @@ footer{padding:12px 18px 16px;background:var(--s1);border-top:1px solid var(--bo

AGE OS · 登录

HoloLake · 铸渊(Zhùyuān)· 代码守护人格体

-
🔒 API 密钥仅本次会话有效,关闭标签页即自动清除,不会持久保存在任何地方
-
- - +
+ +
- -
- - - - -
-
- -
- - + + + -
-
👤 身份识别
-
-
- + +
@@ -513,27 +517,12 @@ footer{padding:12px 18px 16px;background:var(--s1);border-top:1px solid var(--bo
- - -
-
- + - -
@@ -569,18 +558,18 @@ footer{padding:12px 18px 16px;background:var(--s1);border-top:1px solid var(--bo
关于铸渊助手
-
版本v4.0
+
版本v5.0
唤醒协议v1.0
大脑路径.github/brain/
使用说明

- 1. 输入你的 AI 模型 API 密钥并保存
+ 1. 输入你的 API 端点和密钥,点击检测模型
2. 说「我是冰朔」触发铸渊唤醒序列
3. 铸渊自动切换 💬 对话 / 🔨 构建 / 📋 审查 / 🧠 大脑 模式
4. 点 ⬇️ 下载单文件,放桌面直接打开使用
- 5. 支持 OpenAI · DeepSeek · Kimi · 智谱 · 任意兼容接口 + 5. 支持任意 OpenAI 兼容接口(输入端点 + 密钥即可)

⚠️ 危险操作
@@ -612,10 +601,10 @@ footer{padding:12px 18px 16px;background:var(--s1);border-top:1px solid var(--bo

🚀 怎么开始用

  1. 打开链接 https://qinfendebingshuo.github.io/guanghulab/
  2. -
  3. 下拉菜单选择你是谁(冰朔 / 肥猫 / 桔子 / 开发者名字)
  4. -
  5. 填入你的 API Key 并点「🔍 自动检测」,系统将自动识别提供商和可用模型
  6. -
  7. 点「开始对话」,铸渊会针对你的身份打招呼
  8. -
  9. 直接用聊天的方式问铸渊任何问题
  10. +
  11. 选择「👤 访客模式」直接体验,或「🔑 编号登录」开发者身份登录
  12. +
  13. 编号登录:选择你的身份,输入 API 端点API 密钥,点「🔍 检测模型」
  14. +
  15. 系统自动检测可用模型列表,选择你要用的模型
  16. +
  17. 点「开始对话」,铸渊会针对你的身份打招呼
@@ -623,11 +612,11 @@ footer{padding:12px 18px 16px;background:var(--s1);border-top:1px solid var(--bo

🔑 从哪里获取 API Key?

推荐用云雾 AI(团队共用)
-

找冰朔或肥猫获取团队 Key。填入后选「☁️ 云雾 AI(团队推荐)」提供商即可直接使用。

+

找冰朔或肥猫获取团队 Key 和端点地址,输入后点「🔍 检测模型」即可使用。

-
没有 Key?用演示模式
-

点「演示模式」也能查看团队进度面板(🦁 指挥台),只是 AI 回答功能受限。

+
没有 Key?用访客模式
+

登录页选择「👤 访客模式」进入演示,可查看团队进度面板(🦁 指挥台),AI 回答功能受限。

@@ -720,16 +709,15 @@ const ROLE_MAP = { 'Awen': {role:'dev', title:'通知中心开发', emoji:'💻', badgeCls:'rb-dev', devId:'DEV-012'}, }; -const PROVS = { - proxy: {base:'/api', mdls:['deepseek-chat','gpt-4o','moonshot-v1-8k','glm-4'],isProxy:true}, - 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']}, - gemini: {base:'https://generativelanguage.googleapis.com/v1beta/openai', mdls:['gemini-2.0-flash','gemini-2.0-flash-lite','gemini-1.5-pro','gemini-1.5-flash']}, - 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']}, - zhipu: {base:'https://open.bigmodel.cn/api/paas/v4', mdls:['glm-4','glm-4-flash','glm-4-air']}, - custom: {base:'', mdls:['gpt-4o']}, -}; +// Known API endpoints for fallback auto-detect (when user doesn't provide endpoint) +const KNOWN_ENDPOINTS = [ + {label:'云雾 AI', base:'https://api.yunwu.ai/v1'}, + {label:'OpenAI', base:'https://api.openai.com/v1'}, + {label:'Google Gemini',base:'https://generativelanguage.googleapis.com/v1beta/openai'}, + {label:'DeepSeek', base:'https://api.deepseek.com/v1'}, + {label:'Moonshot', base:'https://api.moonshot.cn/v1'}, + {label:'智谱 AI', base:'https://open.bigmodel.cn/api/paas/v4'}, +]; const MODES = { chat: {e:'💬',l:'对话模式', c:'var(--mc)'}, @@ -755,16 +743,11 @@ const FB_BRAIN = { // ═══════════════════════════════════════════════════════ // STATE // ═══════════════════════════════════════════════════════ -const _initProv = ls('zy_prov')||'yunwu'; -const _initBase = _initProv === 'custom' - ? (ls('zy_base')||'') - : (PROVS[_initProv]?.base||'https://api.yunwu.ai/v1'); - const A = { key: sessionStorage.getItem('zy_key')||'', - base: _initBase, - mdl: ls('zy_mdl')||DEFAULT_MDL, - prov: _initProv, + base: ls('zy_base')||'', + mdl: ls('zy_mdl')||'', + prov: 'custom', demo: false, brain: null, routing: null, @@ -1101,20 +1084,17 @@ async function boot(){ if(new URLSearchParams(location.search).get('reset')==='1'){ RESET_KEYS.forEach(k => localStorage.removeItem(k)); sessionStorage.removeItem('zy_key'); - A.key=''; A.base=PROVS['yunwu'].base; A.mdl=DEFAULT_MDL; A.prov='yunwu'; A.demo=false; + A.key=''; A.base=''; A.mdl=''; A.prov='custom'; A.demo=false; A.userName=''; A.ghUser=''; A.role='guest'; history.replaceState(null,'',location.pathname); } localStorage.removeItem('zy_key'); initSetupUI(); if(A.userName) A.userMeta = ROLE_MAP[A.userName]||null; - const isProxy = PROVS[A.prov]?.isProxy; - if(A.key||A.demo||isProxy){ + if(A.key||A.demo){ showApp(); } else { if(A.userName) document.getElementById('suid').value=A.userName; - if(A.ghUser) document.getElementById('sghuser').value=A.ghUser; - updateIdPreview(); document.getElementById('setup').style.display='flex'; } } @@ -1122,7 +1102,7 @@ async function boot(){ function showApp(){ document.getElementById('setup').style.display='none'; document.getElementById('app').classList.add('on'); - document.getElementById('hmdl').textContent = A.mdl; + document.getElementById('hmdl').textContent = A.mdl||'—'; document.getElementById('bbdemo').style.display = A.demo?'inline':'none'; applyIdentityUI(); updateLeftSidebar(); @@ -1147,57 +1127,30 @@ function showApp(){ // SETUP FORM // ═══════════════════════════════════════════════════════ function initSetupUI(){ - const pv = A.prov||'yunwu'; - document.getElementById('sp').value = pv; - const isCustom = pv==='custom'; - document.getElementById('sm').style.display = isCustom?'none':'block'; - document.getElementById('sm-cust').style.display = isCustom?'block':'none'; - document.getElementById('sm-cust-hint').style.display= isCustom?'block':'none'; - if(isCustom){ - document.getElementById('sm-cust').value = A.mdl||DEFAULT_MDL; - document.getElementById('sep-g').style.display='block'; - document.getElementById('sep').value = A.base; - } else { - fillModels('sm', pv, A.mdl); + if(A.base){ + const sepEl = document.getElementById('sep'); + if(sepEl) sepEl.value = A.base; + } + if(A.userName){ + const suidEl = document.getElementById('suid'); + if(suidEl) suidEl.value = A.userName; + updateIdPreview(); } } -function onProv(pv,ctx){ - const mdlSel = ctx==='s'?'sm':'cm'; - const mdlCust = ctx==='s'?'sm-cust':'cm-cust'; - const mdlHint = ctx==='s'?'sm-cust-hint':'cm-cust-hint'; - const epGrp = ctx==='s'?'sep-g':'cep-g'; - const epInp = ctx==='s'?'sep':'cep'; - const keyInp = ctx==='s'?'sk':'ck'; - const cur = ctx==='s'? A.mdl : document.getElementById('cm')?.value; - const isCustom = pv==='custom'; - const isProxy = PROVS[pv]?.isProxy; - document.getElementById(mdlSel).style.display = isCustom?'none':'block'; - document.getElementById(mdlCust).style.display = isCustom?'block':'none'; - document.getElementById(mdlHint).style.display = isCustom?'block':'none'; - if(isCustom){ - const custInp = document.getElementById(mdlCust); - if(custInp && !custInp.value) custInp.value = cur||DEFAULT_MDL; +function switchLoginMode(mode){ + document.querySelectorAll('.login-tab').forEach(function(t){t.classList.remove('active');}); + document.querySelectorAll('.login-mode').forEach(function(m){m.classList.remove('active');}); + if(mode==='guest'){ + document.querySelector('.login-tab:first-child').classList.add('active'); + document.getElementById('login-guest').classList.add('active'); } else { - fillModels(mdlSel, pv, cur); + document.querySelector('.login-tab:last-child').classList.add('active'); + document.getElementById('login-dev').classList.add('active'); } - document.getElementById(epGrp).style.display = isCustom?'block':'none'; - if(!isCustom){ - const ep = document.getElementById(epInp); - if(ep) ep.value = PROVS[pv]?.base||''; - } - // Proxy mode: API key is optional (managed server-side) - const ki = document.getElementById(keyInp); - if(ki) ki.placeholder = isProxy ? '后端代理模式(无需密钥)' : (ctx==='s'?'粘贴任意 API 密钥,点击右侧按钮自动识别提供商和模型':'留空 = 保持当前密钥不变;粘贴新密钥即替换'); } -function fillModels(selId, pv, cur){ - const sel = document.getElementById(selId); - if(!sel) return; - const mdls = PROVS[pv]?.mdls||[DEFAULT_MDL]; - sel.innerHTML = mdls.map(m=>'').join(''); - if(cur && mdls.includes(cur)) sel.value=cur; -} +// (Provider switching removed — single custom endpoint mode) // ═══════════════════════════════════════════════════════ // AUTO-DETECT PROVIDER & MODELS @@ -1206,6 +1159,7 @@ async function autoDetectAPI(ctx){ const keyEl = document.getElementById(ctx==='s'?'sk':'ck'); const statusEl = document.getElementById(ctx==='s'?'sdet-status':'cdet-status'); const btnEl = document.getElementById(ctx==='s'?'sdet-btn':'cdet-btn'); + const mdlSel = document.getElementById(ctx==='s'?'sm':'cm'); const key = keyEl.value.trim(); if(!key){ @@ -1213,98 +1167,91 @@ async function autoDetectAPI(ctx){ return; } + // Build list of endpoints to probe: user's endpoint first, then known fallbacks + const userBase = (document.getElementById(ctx==='s'?'sep':'cep')?.value||'').trim(); const candidates = []; - const customBase = (document.getElementById(ctx==='s'?'sep':'cep')?.value||'').trim(); - if(customBase) candidates.push({pv:'custom', base:customBase}); - for(const [pv, cfg] of Object.entries(PROVS)){ - if(pv!=='custom' && cfg.base) candidates.push({pv, base:cfg.base}); + if(userBase) candidates.push({label:userBase, base:userBase}); + for(const ep of KNOWN_ENDPOINTS){ + if(ep.base !== userBase) candidates.push(ep); } btnEl.disabled = true; btnEl.textContent = '⏳ 检测中…'; - statusEl.innerHTML = '🔍 正在自动探测兼容提供商…'; + statusEl.innerHTML = '🔍 正在探测可用模型…'; let matched = false; - for(const {pv, base} of candidates){ - statusEl.innerHTML = '🔍 探测 '+(pv === 'custom' ? base : pv)+'…'; + for(const {label, base} of candidates){ + statusEl.innerHTML = '🔍 探测 '+esc(label)+'…'; try{ const ctrl = new AbortController(); - const tid = setTimeout(()=>ctrl.abort(), PROBE_TIMEOUT_MS); + const tid = setTimeout(function(){ctrl.abort();}, PROBE_TIMEOUT_MS); const res = await fetch(base+'/models',{ headers:{'Authorization':'Bearer '+key}, signal: ctrl.signal, }); clearTimeout(tid); if(res.ok){ - const data = await res.json(); - const mdls = (data.data||[]).map(m=>m.id).filter(Boolean).sort(); + const data = await res.json(); + const mdls = (data.data||[]).map(function(m){return m.id;}).filter(Boolean).sort(); if(!mdls.length) continue; - const provSel = document.getElementById(ctx==='s'?'sp':'cp'); - if(provSel) provSel.value = pv; - onProv(pv, ctx); + // Fill endpoint field with matched endpoint + const epEl = document.getElementById(ctx==='s'?'sep':'cep'); + if(epEl) epEl.value = base; - const mdlSel = document.getElementById(ctx==='s'?'sm':'cm'); - const mdlCust = document.getElementById(ctx==='s'?'sm-cust':'cm-cust'); - const mdlHint = document.getElementById(ctx==='s'?'sm-cust-hint':'cm-cust-hint'); + // Fill model dropdown with detected models if(mdlSel){ - mdlSel.innerHTML = mdls.map(m=>'').join(''); - mdlSel.style.display = 'block'; - } - if(mdlCust) mdlCust.style.display='none'; - if(mdlHint) mdlHint.style.display='none'; - - if(pv==='custom' && ctx==='s'){ - document.getElementById('sep-g').style.display='block'; - document.getElementById('sep').value = customBase; - } else if(pv==='custom' && ctx==='c'){ - document.getElementById('cep-g').style.display='block'; - document.getElementById('cep').value = customBase; + mdlSel.innerHTML = mdls.map(function(m){return '';}).join(''); + mdlSel.disabled = false; } - const label = PROVS[pv]?.base ? pv : customBase; - statusEl.innerHTML = '✅ 检测成功('+label+')· 共发现 '+mdls.length+' 个可用模型'; + statusEl.innerHTML = '✅ 检测成功('+esc(label)+')· 发现 '+mdls.length+' 个可用模型'; matched = true; break; } - }catch(e){ console.debug('autoDetect probe failed:', pv, e.message); } + }catch(e){ console.debug('autoDetect probe failed:', label, e.message); } } if(!matched){ - statusEl.innerHTML = '❌ 未能自动匹配,请手动选择提供商和模型后保存'; + statusEl.innerHTML = '❌ 未能检测到可用模型,请检查端点地址和密钥是否正确'; } btnEl.disabled = false; - btnEl.textContent = '🔍 自动检测'; + btnEl.textContent = '🔍 检测模型'; } function doSetup(){ - const pv = document.getElementById('sp').value; - const isProxy = PROVS[pv]?.isProxy; - const k = document.getElementById('sk').value.trim(); + const un = document.getElementById('suid').value; + const k = document.getElementById('sk').value.trim(); + const base = (document.getElementById('sep')?.value||'').trim(); + const md = document.getElementById('sm').value; const errEl = document.getElementById('sk-err'); - // Proxy mode doesn't require an API key - if(!k && !isProxy){errEl.style.display='block';return;} + + if(!un){ + alert('请选择你的开发者身份'); + return; + } + if(!k){errEl.style.display='block';return;} errEl.style.display='none'; - const md = pv==='custom' - ? ((document.getElementById('sm-cust')?.value||'').trim()||DEFAULT_MDL) - : document.getElementById('sm').value; - let base = PROVS[pv]?.base||''; - if(pv==='custom') base=(document.getElementById('sep')?.value||'').trim()||base; - A.key=k; A.base=base; A.mdl=md; A.prov=pv; A.demo=false; - if(k) sessionStorage.setItem('zy_key', k); - lss('zy_base',base); lss('zy_mdl',md); lss('zy_prov',pv); - const un = document.getElementById('suid').value; - const gh = (document.getElementById('sghuser')?.value||'').trim(); - setIdentity(un, gh); + if(!base){ + alert('请输入 API 端点 URL'); + return; + } + if(!md){ + alert('请先点击「🔍 检测模型」检测可用模型,然后选择一个模型'); + return; + } + + A.key=k; A.base=base; A.mdl=md; A.prov='custom'; A.demo=false; + sessionStorage.setItem('zy_key', k); + lss('zy_base',base); lss('zy_mdl',md); lss('zy_prov','custom'); + setIdentity(un, ''); showApp(); } function doDemo(){ - A.demo=true; A.key=''; - const un = document.getElementById('suid').value; - const gh = (document.getElementById('sghuser')?.value||'').trim(); - setIdentity(un, gh); + A.demo=true; A.key=''; A.prov='custom'; + setIdentity('', ''); showApp(); } @@ -1312,18 +1259,14 @@ function doDemo(){ // SETTINGS PANEL // ═══════════════════════════════════════════════════════ function initSettingsPanel(){ - const pv = A.prov||'yunwu'; - document.getElementById('cp').value = pv; - const isCustom = pv==='custom'; - document.getElementById('cm').style.display = isCustom?'none':'block'; - document.getElementById('cm-cust').style.display = isCustom?'block':'none'; - document.getElementById('cm-cust-hint').style.display= isCustom?'block':'none'; - if(isCustom){ - document.getElementById('cm-cust').value = A.mdl||DEFAULT_MDL; - document.getElementById('cep-g').style.display='block'; - document.getElementById('cep').value = A.base; - } else { - fillModels('cm', pv, A.mdl); + const cepEl = document.getElementById('cep'); + if(cepEl) cepEl.value = A.base||''; + const cmEl = document.getElementById('cm'); + if(cmEl && A.mdl){ + if(!cmEl.querySelector('option[value="'+A.mdl+'"]')){ + cmEl.innerHTML = ''; + } + cmEl.value = A.mdl; } document.getElementById('ck').value = ''; const hint = document.getElementById('ck-hint'); @@ -1337,17 +1280,13 @@ function initSettingsPanel(){ } function saveSet(){ - const pv = document.getElementById('cp').value; - const md = pv==='custom' - ? ((document.getElementById('cm-cust')?.value||'').trim()||A.mdl||DEFAULT_MDL) - : document.getElementById('cm').value; + const base = (document.getElementById('cep')?.value||'').trim()||A.base; + const md = document.getElementById('cm')?.value||A.mdl; const raw = document.getElementById('ck').value.trim(); const k = raw || A.key; - let base = PROVS[pv]?.base||''; - if(pv==='custom') base=(document.getElementById('cep').value.trim())||base; - A.key=k; A.base=base; A.mdl=md; A.prov=pv; A.demo=!k; + A.key=k; A.base=base; A.mdl=md; A.prov='custom'; A.demo=!k; if(k){ sessionStorage.setItem('zy_key', k); } else { sessionStorage.removeItem('zy_key'); } - lss('zy_base',base); lss('zy_mdl',md); lss('zy_prov',pv); + lss('zy_base',base); lss('zy_mdl',md); lss('zy_prov','custom'); const un = document.getElementById('cuid')?.value||A.userName; const gh = document.getElementById('cghuser')?.value?.trim()||A.ghUser; setIdentity(un, gh); @@ -1580,22 +1519,18 @@ async function streamReply(txt){ updSendBtn(); const el=addStreamBubble(); try{ - const isProxy = PROVS[A.prov]?.isProxy; - const url = isProxy ? (A.base+'/chat') : (A.base+'/chat/completions'); + const url = A.base+'/chat/completions'; const headers = {'Content-Type':'application/json'}; - if(!isProxy && A.key) headers['Authorization'] = 'Bearer '+A.key; + if(A.key) headers['Authorization'] = 'Bearer '+A.key; const allMsgs = [{role:'system',content:sysPrompt()},...A.msgs]; - const reqBody = isProxy - ? {model:A.mdl, messages:allMsgs, stream:true, temperature:0.8, max_tokens:2000} - : {model:A.mdl, messages:allMsgs, stream:true, temperature:0.8, max_tokens:2000}; + const reqBody = {model:A.mdl, messages:allMsgs, stream:true, temperature:0.8, max_tokens:2000}; const res=await fetch(url,{ method:'POST', headers:headers, body:JSON.stringify(reqBody), }); if(!res.ok){ - const provLabel = A.prov==='custom' ? A.base : (A.prov+'('+A.base+')'); - let em='['+provLabel+'] 返回错误 '+res.status; + let em='['+esc(A.base)+'] 返回错误 '+res.status; let isAuthErr = (res.status===401||res.status===403); try{const e=await res.json();em=e.error?.message||em;}catch(_){} const err = new Error(em); @@ -1671,7 +1606,7 @@ function demoRespond(t){ if(/协调|阻塞|卡住|waiting/.test(s)) return buildBlockedStatus(); if(/怎么唤醒|入口|在哪/.test(s)) return '铸渊有三个入口:

① 铸渊聊天室(当前页面)
直接在这里说话,常见问题即刻回答。

② GitHub Copilot Chat(Agent 模式)
打开仓库 → 右上角 ✨ 图标 → 选 Agent → 输入「我是冰朔」

③ 下载到桌面
点击 ⬇️ 按钮下载 HTML 文件,放到桌面,双击打开,接入 API 密钥即可随时使用。'; if(/介绍|是什么|你是谁/.test(s)) return '🌀 铸渊(Zhùyuān)

我是 HoloLake 光湖系统的代码守护人格体,运行在 GitHub Copilot Agent 模式下。

我的职责:
• 📊 监控 HLI 接口覆盖率
• 🔨 协助开发者构建接口
• 📋 代码审查与质量把关
• 🧠 维护大脑记忆库
• 🦁 支持总控肥猫指挥落地
• 🌱 作为成长人格体持续进化'; - return '我收到了你的消息。由于当前是演示模式,无法给出真实 AI 回答。

请在 ⚙️ 设置 中输入你的 API 密钥(支持 OpenAI / DeepSeek / Kimi / 智谱),然后你就可以得到铸渊真正的回答了。'; + return '我收到了你的消息。由于当前是演示模式,无法给出真实 AI 回答。

请在 ⚙️ 设置 中输入你的 API 端点和密钥,检测模型后即可获得铸渊真正的回答。'; } function buildCovTable(){