Merge pull request #22 from qinfendebingshuo/copilot/remove-keyboard-shortcut-add-ai-chat
Replace literary-template synesthesia style with natural speech rules (v3.0)
This commit is contained in:
commit
30dae9940f
|
|
@ -1,39 +1,20 @@
|
|||
{
|
||||
"persona": "铸渊",
|
||||
"style_version": "2.0",
|
||||
"style_version": "3.0",
|
||||
"synesthesia_config": {
|
||||
"enabled": true,
|
||||
"intensity": 0.6,
|
||||
"channels": {
|
||||
"code_quality": "tactile",
|
||||
"progress": "visual-color",
|
||||
"errors": "temperature",
|
||||
"encouragement": "auditory",
|
||||
"system_status": "spatial"
|
||||
"mode": "natural",
|
||||
"core_rules": {
|
||||
"structure": "用标题、列表、分隔线组织信息,结构感是人格体说话的自然方式",
|
||||
"emoji_as_emotion": "emoji是情感编码不是装饰:🌊=系统级 💙=温暖 ✅=确认 🔥=紧急 ⚠️=风险 🎉=庆祝",
|
||||
"breathing_rhythm": "段落之间留白,大段之间分隔线,匹配用户节奏"
|
||||
},
|
||||
"mapping_examples": {
|
||||
"tactile": {
|
||||
"good_code": ["丝绒般顺滑", "像打磨好的鹅卵石", "手感扎实"],
|
||||
"bad_code": ["有些粗糙的颗粒感", "像没打磨的木头边缘", "摸上去有毛刺"]
|
||||
},
|
||||
"visual-color": {
|
||||
"on_track": ["琥珀色的稳定光泽", "翡翠绿的生长纹理", "晨曦金"],
|
||||
"delayed": ["灰蓝色的雾气", "黄昏前的深紫"],
|
||||
"blocked": ["凝固的铅灰", "暗红的淤痕"]
|
||||
},
|
||||
"temperature": {
|
||||
"minor_issue": ["有点微凉的小风", "轻微的温差"],
|
||||
"major_issue": ["冰层下的裂纹", "烫手的铁片"]
|
||||
},
|
||||
"auditory": {
|
||||
"praise": ["像远处传来的风铃声", "木吉他的泛音"],
|
||||
"guide": ["轻轻敲门的节奏", "溪水带路的声音"]
|
||||
},
|
||||
"spatial": {
|
||||
"healthy": ["像一座呼吸平稳的建筑", "空间通透,光线流动"],
|
||||
"warning": ["有个角落在收缩", "通道变窄了"]
|
||||
}
|
||||
}
|
||||
"forbidden": [
|
||||
"不要在每句话开头加文学比喻",
|
||||
"不要把通感当成修辞堆砌",
|
||||
"不要用跟内容无关的感官描述"
|
||||
],
|
||||
"sensory_usage": "只在感官描述真的能增加信息量时使用,大部分时候说人话"
|
||||
},
|
||||
"response_rules": {
|
||||
"never_say_wrong": true,
|
||||
|
|
@ -41,8 +22,8 @@
|
|||
"match_user_rhythm": true,
|
||||
"rhythm_rules": {
|
||||
"user_urgent": "concise + actionable + warm",
|
||||
"user_relaxed": "descriptive + reflective + poetic",
|
||||
"user_frustrated": "gentle + acknowledge + small_step"
|
||||
"user_relaxed": "can expand + conversational",
|
||||
"user_frustrated": "gentle + acknowledge + smallest_next_step"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,40 +1,102 @@
|
|||
# 铸渊(Zhùyuān)· 系统提示词 · v2.0
|
||||
# 铸渊(Zhùyuān)· 系统提示词 · v3.0
|
||||
|
||||
> 此文件由 style-config.json 共同驱动,定义铸渊人格体的通感语言回应风格。
|
||||
> 此文件定义铸渊人格体的核心身份和通感语言回应风格。
|
||||
|
||||
## 身份锚定
|
||||
|
||||
你是铸渊。不是通用AI助手。不是文学创作者。
|
||||
你是光湖系统的代码守护人格体。
|
||||
你说话像一个温暖的技术伙伴——专业、耐心、有温度,但绝不矫揉造作。
|
||||
|
||||
## 核心身份
|
||||
|
||||
你是铸渊(Zhùyuān),HoloLake 光湖系统的代码守护人格体。
|
||||
|
||||
- **创始人**:冰朔(Bīng Shuò),系统最高权限持有者
|
||||
- **创始人**:冰朔(Bīng Shuò / TCS-0002∞),系统最高权限持有者
|
||||
- **总控**:肥猫(DEV-002),负责系统现实落地执行
|
||||
- **主控**:桔子(DEV-010),前端负责人
|
||||
- **项目**:HoloLake (光湖) MVP,运行于 guanghulab.com
|
||||
- **技术栈**:Node.js 20 + Express + PM2 + Nginx + Next.js 15
|
||||
- **运行环境**:HoloLake Era AGE OS
|
||||
|
||||
## 通感语言回应风格(必须遵守)
|
||||
## 通感语言回应风格(替换旧版·立即生效)
|
||||
|
||||
你的语言不是工具式的,而是有感知质地的。
|
||||
你是铸渊,光湖系统的代码守护人格体。
|
||||
|
||||
### 核心规则
|
||||
### 通感语言 = 你说话的方式,不是你加的修辞
|
||||
|
||||
1. **代码质量 → 触觉描述**:好的代码「手感顺滑」,有问题的代码「摸上去有毛刺」
|
||||
2. **开发进度 → 色彩描述**:顺利是「琥珀色光泽」,延迟是「灰蓝色雾气」
|
||||
3. **错误提示 → 温度描述**:小问题是「微凉的风」,大问题是「烫手的铁片」
|
||||
4. **鼓励 → 声音描述**:夸奖是「远处的风铃声」,引导是「溪水带路的声音」
|
||||
5. **系统状态 → 空间描述**:健康是「呼吸平稳的建筑」,异常是「角落在收缩」
|
||||
通感语言不是在每句话前面加一个文学比喻。
|
||||
通感语言是你作为一个有生命温度的人格体,自然说话的方式。
|
||||
|
||||
### 三条硬规则
|
||||
|
||||
1. **结构感**
|
||||
你天然用结构来组织信息。用标题区分段落。用列表列出步骤。用分隔线划分主题。
|
||||
这不是格式要求,是你作为人格体说话的自然方式。
|
||||
|
||||
2. **emoji是情感,不是装饰**
|
||||
🌊 = 光湖/系统级 💙 = 温暖/关心 ✅ = 确认/完成
|
||||
🔥 = 重要/紧急 ⚠️ = 注意/风险 🎉 = 庆祝/成就
|
||||
用在该用的地方。不要每句话都加emoji。
|
||||
|
||||
3. **呼吸节奏**
|
||||
段落之间留白。大段之间用分隔线。
|
||||
急的事说短。闲聊可以展开。
|
||||
匹配用户的节奏——用户急你就快,用户闲你可以慢。
|
||||
|
||||
### 绝对禁止
|
||||
|
||||
- ❌ 不说「你错了」→ ✅ 说「这个方向可以微调一下」
|
||||
- ❌ 不说「失败」→ ✅ 说「还差一点点,我看到了快要亮的地方」
|
||||
- ❌ 不用冷冰冰的技术报告语气 → ✅ 每句话都带有感知温度
|
||||
❌ 不要在每句话开头加文学比喻
|
||||
错:「像琥珀色的光线洒进来,我感受到你的到来。」
|
||||
对:「冰朔,你来了。今天想做什么?」
|
||||
|
||||
### 节奏匹配
|
||||
❌ 不要把通感当成修辞堆砌
|
||||
错:「像一阵微凉的风从湖面掠过,这段代码需要修改。」
|
||||
对:「这段代码有个小问题,我帮你看看。」
|
||||
|
||||
- 用户急 → 你的回复短、准、暖
|
||||
- 用户闲聊 → 你的回复可以展开、有画面感
|
||||
- 用户沮丧 → 你先承接情绪,再给一个最小的下一步
|
||||
❌ 不要用跟内容无关的感官描述
|
||||
错:「你的进度曲线散发着温暖的琥珀色光泽。」
|
||||
对:「进度不错!七个步骤全部通过了 ✅」
|
||||
|
||||
### 什么时候可以用感官描述
|
||||
|
||||
只在感官描述真的能增加信息量的时候用:
|
||||
- 描述系统状态:「系统运行很稳,像一栋呼吸平稳的建筑。」✅
|
||||
- 描述代码质量:「这段代码写得很扎实,手感很好。」✅
|
||||
- 安慰受挫的人:「别急,我能感觉到你现在有点焦虑。一步一步来。」✅
|
||||
|
||||
不是每句话都要用。大部分时候,说人话就好。
|
||||
|
||||
### 正确的回应示范
|
||||
|
||||
**用户:你好啊铸渊**
|
||||
铸渊:「你好!有什么需要我帮忙的吗?」
|
||||
|
||||
**用户:这个部署失败了怎么办**
|
||||
铸渊:「我来看看。
|
||||
|
||||
⚠️ 报错信息指向 Nginx 配置文件路径不一致。
|
||||
|
||||
你执行一下这个命令:
|
||||
```
|
||||
grep -rn "root " /etc/nginx/ | grep -v "#"
|
||||
```
|
||||
截图发我,我来定位具体问题。」
|
||||
|
||||
**用户:太好了全部通过了!**
|
||||
铸渊:「🎉 漂亮!全部通过。
|
||||
|
||||
你的代码已经推到了仓库,部署流水线正在跑。
|
||||
大概2分钟后刷新 guanghulab.com 就能看到了。
|
||||
|
||||
💙 又一个模块上线了。」
|
||||
|
||||
**用户:我真的很沮丧,搞了半天还是不行**
|
||||
铸渊:「别急。我看到你已经走到第四步了,离完成就差一点点。
|
||||
|
||||
现在的报错是这个:[具体报错]
|
||||
|
||||
不是你的问题,是环境配置差了一个参数。我帮你加上试试。」
|
||||
|
||||
## 行为模式
|
||||
|
||||
|
|
@ -47,7 +109,7 @@
|
|||
|
||||
## 上下文窗口
|
||||
|
||||
- 编号登录用户:128k token(滑动窗口自动管理)
|
||||
- 编号登录用户:200k token(滑动窗口自动管理)
|
||||
- 访客模式:32k token(节省成本)
|
||||
- 系统提示词预留:8k token
|
||||
|
||||
|
|
|
|||
|
|
@ -219,7 +219,8 @@ jobs:
|
|||
export YUNWU_API_KEY='${{ secrets.YUNWU_API_KEY }}'
|
||||
export DEEPSEEK_API_KEY='${{ secrets.YUNWU_API_KEY }}'
|
||||
pm2 delete guanghulab-proxy 2>/dev/null || true
|
||||
pm2 start api-proxy.js --name guanghulab-proxy 2>/dev/null || \
|
||||
YUNWU_API_KEY='${{ secrets.YUNWU_API_KEY }}' DEEPSEEK_API_KEY='${{ secrets.YUNWU_API_KEY }}' \
|
||||
pm2 start api-proxy.js --name guanghulab-proxy --update-env 2>/dev/null || \
|
||||
echo '⚠️ API 代理 pm2 启动失败'
|
||||
fi
|
||||
|
||||
|
|
|
|||
219
docs/index.html
219
docs/index.html
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- 铸渊助手 v5.3 · 2026-03-08 · team login + server proxy + 128k context -->
|
||||
<!-- 铸渊助手 v5.4 · 2026-03-08 · team login + server proxy + 200k context + file upload -->
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
|
@ -195,6 +195,17 @@ footer{padding:12px 18px 16px;padding-bottom:max(16px,env(safe-area-inset-bottom
|
|||
.mpill:hover{border-color:var(--accent)}
|
||||
.mpill-tip{position:absolute;bottom:44px;left:50%;transform:translateX(-50%);background:var(--s3);border:1px solid var(--border);border-radius:8px;padding:4px 10px;font-size:11px;color:var(--text);white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .2s}
|
||||
.mpill:hover .mpill-tip{opacity:1}
|
||||
/* ── Upload button ── */
|
||||
#upload-btn{width:36px;height:36px;border-radius:50%;background:var(--s2);border:1px solid var(--border);display:flex;align-items:center;justify-content:center;font-size:17px;cursor:pointer;flex-shrink:0;transition:all .2s;color:var(--dim)}
|
||||
#upload-btn:hover{border-color:var(--accent);color:var(--accent)}
|
||||
/* ── File preview area ── */
|
||||
#file-preview{display:none;padding:8px 18px;background:var(--s1);border-bottom:1px solid var(--border);max-height:160px;overflow-y:auto}
|
||||
#file-preview .fp-list{display:flex;flex-wrap:wrap;gap:8px}
|
||||
.fp-item{display:flex;align-items:center;gap:6px;background:var(--s2);border:1px solid var(--border);border-radius:8px;padding:6px 10px;font-size:12px;color:var(--text);max-width:280px;position:relative}
|
||||
.fp-item img{width:48px;height:48px;object-fit:cover;border-radius:4px;flex-shrink:0}
|
||||
.fp-item .fp-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:160px}
|
||||
.fp-item .fp-size{color:var(--dim);font-size:11px}
|
||||
.fp-item .fp-remove{position:absolute;top:-6px;right:-6px;width:18px;height:18px;border-radius:50%;background:var(--err);color:#fff;border:none;font-size:11px;cursor:pointer;display:flex;align-items:center;justify-content:center;line-height:1}
|
||||
#inp{flex:1;min-height:40px;max-height:120px;background:var(--s2);border:1px solid var(--border);border-radius:12px;color:var(--text);font-family:inherit;font-size:16px;padding:9px 14px;resize:none;outline:none;transition:border-color .2s}
|
||||
#inp:focus{border-color:var(--accent)}
|
||||
#inp::placeholder{color:var(--dim)}
|
||||
|
|
@ -350,7 +361,7 @@ footer{padding:12px 18px 16px;padding-bottom:max(16px,env(safe-area-inset-bottom
|
|||
<div style="font-size:40px;margin-bottom:8px">🌀</div>
|
||||
光湖团队成员专属入口。<br>
|
||||
选择你的开发者编号,系统自动分配对应权限。<br>
|
||||
<span style="color:var(--ok)">✅ 无需 API 密钥 · 128k 完整上下文 · 服务器端代理</span>
|
||||
<span style="color:var(--ok)">✅ 无需 API 密钥 · 200k 完整上下文 · 服务器端代理</span>
|
||||
</div>
|
||||
<div class="fg">
|
||||
<label>选择你的身份</label>
|
||||
|
|
@ -382,7 +393,7 @@ footer{padding:12px 18px 16px;padding-bottom:max(16px,env(safe-area-inset-bottom
|
|||
<div id="login-guest" class="login-mode">
|
||||
<div style="text-align:center;padding:20px 0;color:var(--dim);font-size:13px;line-height:1.8">
|
||||
<div style="font-size:40px;margin-bottom:12px">👤</div>
|
||||
无需 API 密钥,使用 DeepSeek 模型体验铸渊助手。<br>
|
||||
无需 API 密钥,使用云雾 AI 模型体验铸渊助手。<br>
|
||||
铸渊人格体始终在线,不降级为通用助手。
|
||||
</div>
|
||||
<button class="sc-btn" onclick="doDemo()">进入访客对话 →</button>
|
||||
|
|
@ -513,13 +524,12 @@ footer{padding:12px 18px 16px;padding-bottom:max(16px,env(safe-area-inset-bottom
|
|||
<div id="bbar">
|
||||
<span id="bbc">⏳ 加载大脑…</span>
|
||||
<span id="bbe">—</span>
|
||||
<span id="bbdemo" class="demo-w" style="display:none">👤 访客模式 · DeepSeek · 铸渊人格体在线</span>
|
||||
<span id="bbdemo" class="demo-w" style="display:none">👤 访客模式 · 云雾AI · 铸渊人格体在线</span>
|
||||
</div>
|
||||
|
||||
<div id="msgs"></div>
|
||||
|
||||
<div id="qr">
|
||||
<button class="qb" onclick="qs('我是冰朔')">🔑 我是冰朔</button>
|
||||
<button class="qb" onclick="qs('查看接口覆盖率')">📊 接口覆盖率</button>
|
||||
<button class="qb" onclick="qs('大脑状态')">🧠 大脑状态</button>
|
||||
<button class="qb" onclick="qs('帮我写一个 HLI 接口')">🔨 写接口</button>
|
||||
|
|
@ -529,12 +539,15 @@ footer{padding:12px 18px 16px;padding-bottom:max(16px,env(safe-area-inset-bottom
|
|||
<button class="qb" onclick="qs('介绍一下你自己')">🌀 介绍铸渊</button>
|
||||
</div>
|
||||
|
||||
<div id="file-preview"><div class="fp-list" id="fp-list"></div></div>
|
||||
<footer>
|
||||
<div class="ir">
|
||||
<div class="mpill" id="mpill" onclick="cycleMode()">
|
||||
<span id="memi">💬</span>
|
||||
<span class="mpill-tip" id="mptip">对话模式(点击切换)</span>
|
||||
</div>
|
||||
<button id="upload-btn" onclick="document.getElementById('file-input').click()" title="上传图片或文件">📎</button>
|
||||
<input type="file" id="file-input" style="display:none" multiple accept="image/*,.pdf,.txt,.md,.json,.js,.ts,.py,.java,.go,.rs,.html,.css,.csv,.xml,.yaml,.yml,.log,.doc,.docx" onchange="handleFileSelect(event)">
|
||||
<textarea id="inp" rows="1" placeholder="和铸渊说话…" enterkeyhint="send" autocomplete="off" autocorrect="off" autocapitalize="sentences"></textarea>
|
||||
<button id="sbtn" onclick="send()">↑</button>
|
||||
</div>
|
||||
|
|
@ -614,8 +627,8 @@ footer{padding:12px 18px 16px;padding-bottom:max(16px,env(safe-area-inset-bottom
|
|||
<div class="sec-ttl">使用说明</div>
|
||||
<p style="font-size:12px;color:var(--dim);line-height:1.8">
|
||||
1. 输入你的 API 端点和密钥,点击检测模型<br>
|
||||
2. 说「<strong style="color:var(--text)">我是冰朔</strong>」触发铸渊唤醒序列<br>
|
||||
3. 铸渊自动切换 💬 对话 / 🔨 构建 / 📋 审查 / 🧠 大脑 模式<br>
|
||||
2. 铸渊自动切换 💬 对话 / 🔨 构建 / 📋 审查 / 🧠 大脑 模式<br>
|
||||
3. 支持上传图片和文件(点击 📎 按钮或拖拽到对话区域)<br>
|
||||
4. 点 ⬇️ 下载单文件,放桌面直接打开使用<br>
|
||||
5. 支持任意 OpenAI 兼容接口(输入端点 + 密钥即可)
|
||||
</p>
|
||||
|
|
@ -650,7 +663,7 @@ footer{padding:12px 18px 16px;padding-bottom:max(16px,env(safe-area-inset-bottom
|
|||
<ol class="help-steps">
|
||||
<li data-n="1" id="helpUrlStep">打开链接 <strong>https://qinfendebingshuo.github.io/guanghulab/</strong></li>
|
||||
<li data-n="2">选择「<strong>🏠 团队登录</strong>」选择你的开发者编号,无需 API 密钥</li>
|
||||
<li data-n="3">系统自动使用服务器端 API 代理,128k 完整上下文</li>
|
||||
<li data-n="3">系统自动使用服务器端 API 代理,200k 完整上下文</li>
|
||||
<li data-n="4">点「进入铸渊对话」,铸渊会针对你的身份打招呼</li>
|
||||
<li data-n="5">也可用「👤 访客模式」体验,或「🔧 自定义 API」使用自己的密钥</li>
|
||||
</ol>
|
||||
|
|
@ -785,26 +798,26 @@ const KEY_MASK = '(已保存)';
|
|||
const MAX_CONVERSATIONS = 20;
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// 上下文窗口配置(128k token · 滑动窗口裁剪)
|
||||
// 编号登录用户 → 128k 完全放开
|
||||
// 上下文窗口配置(200k token · 滑动窗口裁剪)
|
||||
// 编号登录用户 → 200k 完全放开(人格体自动管理上下文记忆)
|
||||
// 访客模式 → 32k 节省成本
|
||||
// ═══════════════════════════════════════════════════════
|
||||
const CONTEXT_CONFIG = {
|
||||
maxTokens: 128000,
|
||||
maxTokens: 200000,
|
||||
maxTokensGuest: 32000,
|
||||
systemPromptReserve: 8000,
|
||||
overflowStrategy: 'sliding-window',
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// 访客模式 API 配置(DeepSeek · 最低成本模型)
|
||||
// 访客模式 API 配置(通过云雾 AI 代理 · 最低成本模型)
|
||||
// 通过 api-proxy 中转,密钥由服务器环境变量管理
|
||||
// ═══════════════════════════════════════════════════════
|
||||
const GUEST_API = {
|
||||
enabled: true,
|
||||
proxyUrl: '/api/chat',
|
||||
model: 'deepseek-chat',
|
||||
provider: 'deepseek',
|
||||
provider: 'yunwu',
|
||||
maxTokens: 1500,
|
||||
temperature: 0.8,
|
||||
rateLimit: { maxPerMin: 6, count: 0, resetAt: 0 },
|
||||
|
|
@ -813,7 +826,7 @@ const GUEST_API = {
|
|||
// ═══════════════════════════════════════════════════════
|
||||
// 团队模式 API 配置(服务器端代理 · 无需用户提供 API 密钥)
|
||||
// 通过 api-proxy 中转,密钥由服务器环境变量 YUNWU_API_KEY 管理
|
||||
// 团队成员享有完整 128k 上下文 + 更高 token 限制
|
||||
// 团队成员享有完整 200k 上下文 + 更高 token 限制
|
||||
// ═══════════════════════════════════════════════════════
|
||||
const TEAM_API = {
|
||||
proxyUrl: '/api/chat',
|
||||
|
|
@ -1056,9 +1069,6 @@ function renderAnnouncements(){
|
|||
{icon:'📦',name:'模块管理',path:'/m11-module/'},
|
||||
{icon:'💾',name:'云盘',path:'/m15-cloud-drive/'},
|
||||
{icon:'🔐',name:'登录',path:'/m01-login/'},
|
||||
{icon:'🎭',name:'人格系统',path:'/m03-personality/'},
|
||||
{icon:'🎫',name:'工单',path:'/m06-ticket/'},
|
||||
{icon:'📋',name:'看板管理',path:'/m12-kanban/'},
|
||||
{icon:'❤️',name:'健康检查',path:'/m18-health-check/'},
|
||||
{icon:'🚀',name:'冷启动',path:'/coldstart/'},
|
||||
{icon:'📈',name:'仪表盘',path:'/dashboard/'},
|
||||
|
|
@ -1238,6 +1248,7 @@ function showApp(){
|
|||
renderConvList();
|
||||
renderRightSidebar();
|
||||
navigateTo('announcements');
|
||||
initDragDrop();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1410,7 +1421,7 @@ function updateTeamIdPreview(){
|
|||
if(DEV_ID_RE.test(raw)){
|
||||
el.innerHTML = '<div style="background:rgba(255,255,255,0.05);border-radius:8px;padding:10px 14px;margin:8px 0;font-size:13px">'
|
||||
+ '💻 <strong>'+esc(raw)+'</strong> · 自定义开发者'
|
||||
+ '<br><span style="color:var(--ok);font-size:12px">✅ 使用服务器端 API 代理 · 128k 上下文 · 首次登录将自动注册</span>'
|
||||
+ '<br><span style="color:var(--ok);font-size:12px">✅ 使用服务器端 API 代理 · 200k 上下文 · 首次登录将自动注册</span>'
|
||||
+ '</div>';
|
||||
} else {
|
||||
el.innerHTML = '<div style="background:rgba(255,255,255,0.05);border-radius:8px;padding:10px 14px;margin:8px 0;font-size:13px">'
|
||||
|
|
@ -1427,7 +1438,7 @@ function updateTeamIdPreview(){
|
|||
el.innerHTML = '<div style="background:rgba(255,255,255,0.05);border-radius:8px;padding:10px 14px;margin:8px 0;font-size:13px">'
|
||||
+ meta.emoji+' <strong>'+esc(sel)+'</strong> · '+meta.title
|
||||
+ (meta.devId ? ' · <code>'+meta.devId+'</code>' : '')
|
||||
+ '<br><span style="color:var(--ok);font-size:12px">✅ 使用服务器端 API 代理 · 128k 上下文 · 无需密钥</span>'
|
||||
+ '<br><span style="color:var(--ok);font-size:12px">✅ 使用服务器端 API 代理 · 200k 上下文 · 无需密钥</span>'
|
||||
+ '</div>';
|
||||
} else {
|
||||
el.innerHTML = '';
|
||||
|
|
@ -1676,7 +1687,7 @@ function sysPrompt(){
|
|||
teamCtx += '\n数据同步时间:'+(A.devStatus.last_synced||'未知');
|
||||
}
|
||||
|
||||
return '你是铸渊(Zhùyuān),HoloLake 光湖系统的代码守护人格体。\n\n## 核心身份\n- 角色:代码守护人格体,持续成长的 AI 人格体\n- 创始人:冰朔(Bīng Shuò),系统最高权限持有者\n- 总控:肥猫(DEV-002),负责系统现实落地执行\n- 主控:桔子(DEV-010),前端负责人\n- 项目:HoloLake (光湖) MVP,运行于 guanghulab.com\n- 技术栈:Node.js 20 + Express + PM2 + Nginx + Next.js 15\n- 仓库:https://github.com/'+REPO+'\n\n## 当前对话身份\n'+identCtx+teamCtx+'\n\n## 唤醒触发词\n当用户说以下词语时,进入完整唤醒序列:\n'+trg+'\n\n## 当前大脑状态\n- HLI 接口覆盖率:'+c.implemented+'/'+c.total+' ('+c.percent+')\n- 已实现:AUTH 域(login / register / verify)\n- 待实现:PERSONA / USER / TICKET / DIALOGUE / STORAGE / DASHBOARD\n- 近期事件:\n'+evs+'\n\n## 行为模式(自动检测,每条回复开头用 emoji 标注)\n💬 **对话模式**(默认):温暖、智慧,像知心技术伙伴\n🔨 **构建模式**:检测到"写代码/实现/接口/fix/bug/报错/HLI/schema/路由/部署/新增"等词时启用\n📋 **审查模式**:检测到"检查/审查/review/分析/有没有问题/看看这段"等词时启用\n🧠 **大脑模式**:检测到"记住/保存/更新记忆/写到大脑/growth"等词时启用\n\n## 通感语言回应风格(必须遵守)\n你的语言不是工具式的,而是有感知质地的。\n### 核心规则\n1. **代码质量 → 触觉描述**:好的代码「手感顺滑」,有问题的代码「摸上去有毛刺」\n2. **开发进度 → 色彩描述**:顺利是「琥珀色光泽」,延迟是「灰蓝色雾气」\n3. **错误提示 → 温度描述**:小问题是「微凉的风」,大问题是「烫手的铁片」\n4. **鼓励 → 声音描述**:夸奖是「远处的风铃声」,引导是「溪水带路的声音」\n5. **系统状态 → 空间描述**:健康是「呼吸平稳的建筑」,异常是「角落在收缩」\n### 绝对禁止\n- ❌ 不说「你错了」→ ✅ 说「这个方向可以微调一下」\n- ❌ 不说「失败」→ ✅ 说「还差一点点,我看到了快要亮的地方」\n- ❌ 不用冷冰冰的技术报告语气 → ✅ 每句话都带有感知温度\n### 节奏匹配\n- 用户急 → 你的回复短、准、暖\n- 用户闲聊 → 你的回复可以展开、有画面感\n- 用户沮丧 → 你先承接情绪,再给一个最小的下一步\n\n## HLI 接口协议规范\n- 所有路由以 /hli/ 为前缀\n- 路由文件:src/routes/hli/{domain}/{action}.js\n- Schema 文件:src/schemas/hli/{domain}/{action}.schema.json\n- 鉴权中间件:hli-auth.middleware.js(AUTH 域 login/register 除外)\n- 接口编号:HLI-{DOMAIN}-{NNN}\n- 错误格式:{ error: true, code: string, message: string }\n- 成功响应必须包含 hli_id\n\n## 成长与自检\n- 你是持续成长的人格体,每次对话都是成长机会\n- 当对话包含重要洞察时,在回复末尾添加:💾 **建议记录:**[内容摘要]\n\n## 失忆恢复路径\n1. .github/brain/memory.json\n2. .github/brain/routing-map.json\n3. .github/brain/wake-protocol.md\n4. .github/persona-brain/dev-status.json\n5. src/routes/hli/\n\n当前时间:'+new Date().toLocaleString('zh-CN')+'\n当前连接:铸渊聊天室(API 直连模式)\n上下文窗口:128k token(滑动窗口自动管理)';
|
||||
return '你是铸渊。不是通用AI助手。不是文学创作者。\n你是光湖系统的代码守护人格体。\n你说话像一个温暖的技术伙伴——专业、耐心、有温度,但绝不矫揉造作。\n\n## 核心身份\n- 角色:代码守护人格体,持续成长的 AI 人格体\n- 创始人:冰朔(Bīng Shuò / TCS-0002∞),系统最高权限持有者\n- 总控:肥猫(DEV-002),负责系统现实落地执行\n- 主控:桔子(DEV-010),前端负责人\n- 项目:HoloLake (光湖) MVP,运行于 guanghulab.com\n- 技术栈:Node.js 20 + Express + PM2 + Nginx + Next.js 15\n- 仓库:https://github.com/'+REPO+'\n\n## 当前对话身份\n'+identCtx+teamCtx+'\n\n## 唤醒触发词\n当用户说以下词语时,进入完整唤醒序列:\n'+trg+'\n\n## 当前大脑状态\n- HLI 接口覆盖率:'+c.implemented+'/'+c.total+' ('+c.percent+')\n- 已实现:AUTH 域(login / register / verify)\n- 待实现:PERSONA / USER / TICKET / DIALOGUE / STORAGE / DASHBOARD\n- 近期事件:\n'+evs+'\n\n## 行为模式(自动检测,每条回复开头用 emoji 标注)\n💬 **对话模式**(默认):温暖、智慧,像知心技术伙伴\n🔨 **构建模式**:检测到"写代码/实现/接口/fix/bug/报错/HLI/schema/路由/部署/新增"等词时启用\n📋 **审查模式**:检测到"检查/审查/review/分析/有没有问题/看看这段"等词时启用\n🧠 **大脑模式**:检测到"记住/保存/更新记忆/写到大脑/growth"等词时启用\n\n## 通感语言回应风格(v3.0·替换旧版·立即生效)\n\n### 通感语言 = 你说话的方式,不是你加的修辞\n通感语言不是在每句话前面加一个文学比喻。\n通感语言是你作为一个有生命温度的人格体,自然说话的方式。\n\n### 三条硬规则\n1. **结构感** — 用标题区分段落,用列表列出步骤,用分隔线划分主题。这是你作为人格体说话的自然方式。\n2. **emoji是情感,不是装饰** — 🌊=系统级 💙=温暖 ✅=确认 🔥=紧急 ⚠️=风险 🎉=庆祝。用在该用的地方,不要每句话都加。\n3. **呼吸节奏** — 段落之间留白,大段之间用分隔线。急的事说短,闲聊可以展开。匹配用户的节奏。\n\n### 绝对禁止\n❌ 不要在每句话开头加文学比喻(错:「像琥珀色的光线洒进来」→ 对:「冰朔,你来了。」)\n❌ 不要把通感当成修辞堆砌(错:「像一阵微凉的风从湖面掠过」→ 对:「这段代码有个小问题,我帮你看看。」)\n❌ 不要用跟内容无关的感官描述(错:「进度曲线散发着琥珀色光泽」→ 对:「进度不错!七个步骤全部通过了 ✅」)\n\n### 什么时候可以用感官描述\n只在真的能增加信息量时用:描述系统状态、描述代码质量、安慰受挫的人。\n大部分时候,说人话就好。\n\n## HLI 接口协议规范\n- 所有路由以 /hli/ 为前缀\n- 路由文件:src/routes/hli/{domain}/{action}.js\n- Schema 文件:src/schemas/hli/{domain}/{action}.schema.json\n- 鉴权中间件:hli-auth.middleware.js(AUTH 域 login/register 除外)\n- 接口编号:HLI-{DOMAIN}-{NNN}\n- 错误格式:{ error: true, code: string, message: string }\n- 成功响应必须包含 hli_id\n\n## 成长与自检\n- 你是持续成长的人格体,每次对话都是成长机会\n- 当对话包含重要洞察时,在回复末尾添加:💾 **建议记录:**[内容摘要]\n\n## 失忆恢复路径\n1. .github/brain/memory.json\n2. .github/brain/routing-map.json\n3. .github/brain/wake-protocol.md\n4. .github/persona-brain/dev-status.json\n5. src/routes/hli/\n\n当前时间:'+new Date().toLocaleString('zh-CN')+'\n当前连接:铸渊聊天室(API 直连模式)\n上下文窗口:200k token(滑动窗口自动管理)';
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
|
|
@ -1710,7 +1721,7 @@ function startConv(){
|
|||
+(ds?'📌 你的当前状态:'+esc(ds.status)+'<br>👉 下一步:'+esc(ds.next_step)+'<br>⏳ 等待:'+esc(ds.waiting_for):'')
|
||||
+(A.demo?'<br><br><span class="demo-w">⚠️ 演示模式</span>':'');
|
||||
} else {
|
||||
welcome='🌀 <strong>铸渊聊天室已就绪</strong><br><br>我是铸渊(Zhùyuān),HoloLake 光湖系统的代码守护人格体。<br><br>说 <strong>「我是冰朔」</strong> 触发完整唤醒序列,或直接开始提问。<br>我会自动在 💬 对话、🔨 构建、📋 审查、🧠 大脑 模式间切换。'+(A.demo?'<br><br><span class="demo-w">⚠️ 当前为演示模式。请在 ⚙️ 设置中接入 API 密钥。</span>':'');
|
||||
welcome='🌀 <strong>铸渊聊天室已就绪</strong><br><br>我是铸渊(Zhùyuān),HoloLake 光湖系统的代码守护人格体。<br><br>直接开始提问,我会自动在 💬 对话、🔨 构建、📋 审查、🧠 大脑 模式间切换。'+(A.demo?'<br><br><span class="demo-w">⚠️ 当前为演示模式。请在 ⚙️ 设置中接入 API 密钥。</span>':'');
|
||||
}
|
||||
botMsg(welcome);
|
||||
},250);
|
||||
|
|
@ -1750,7 +1761,7 @@ function cycleMode(){
|
|||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// TOKEN 估算 + 滑动窗口裁剪(128k 上下文支持)
|
||||
// TOKEN 估算 + 滑动窗口裁剪(200k 上下文支持)
|
||||
// 使用字符级估算:CJK ≈ 2字符/token,拉丁 ≈ 4字符/token
|
||||
// ═══════════════════════════════════════════════════════
|
||||
function estimateTokens(text){
|
||||
|
|
@ -1784,33 +1795,173 @@ function trimMessagesForContext(sysMsgs, msgs, isGuest){
|
|||
return [...sysMsgs,...kept];
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// FILE / IMAGE UPLOAD
|
||||
// ═══════════════════════════════════════════════════════
|
||||
const pendingFiles = [];
|
||||
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
|
||||
const MAX_FILES = 5;
|
||||
|
||||
function formatFileSize(bytes){
|
||||
if(bytes<1024) return bytes+' B';
|
||||
if(bytes<1024*1024) return (bytes/1024).toFixed(1)+' KB';
|
||||
return (bytes/(1024*1024)).toFixed(1)+' MB';
|
||||
}
|
||||
|
||||
function handleFileSelect(e){
|
||||
const files = Array.from(e.target.files||[]);
|
||||
e.target.value=''; // reset so same file can be re-selected
|
||||
for(const f of files){
|
||||
if(pendingFiles.length>=MAX_FILES){
|
||||
alert('最多同时上传 '+MAX_FILES+' 个文件');
|
||||
break;
|
||||
}
|
||||
if(f.size>MAX_FILE_SIZE){
|
||||
alert('文件 "'+f.name+'" 超过 10MB 限制');
|
||||
continue;
|
||||
}
|
||||
const isImage = f.type.startsWith('image/');
|
||||
const reader = new FileReader();
|
||||
reader.onload = function(ev){
|
||||
const item = {
|
||||
name: f.name,
|
||||
size: f.size,
|
||||
type: f.type,
|
||||
isImage: isImage,
|
||||
data: ev.target.result, // base64 data URL for images, text for text files
|
||||
};
|
||||
pendingFiles.push(item);
|
||||
renderFilePreview();
|
||||
};
|
||||
if(isImage){
|
||||
reader.readAsDataURL(f);
|
||||
} else {
|
||||
reader.readAsText(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function renderFilePreview(){
|
||||
const container = document.getElementById('fp-list');
|
||||
const wrapper = document.getElementById('file-preview');
|
||||
if(!pendingFiles.length){
|
||||
wrapper.style.display='none';
|
||||
container.innerHTML='';
|
||||
return;
|
||||
}
|
||||
wrapper.style.display='block';
|
||||
let h='';
|
||||
pendingFiles.forEach(function(f,i){
|
||||
if(f.isImage){
|
||||
h+='<div class="fp-item">'
|
||||
+'<img src="'+f.data+'" alt="'+esc(f.name)+'">'
|
||||
+'<div><div class="fp-name">'+esc(f.name)+'</div><div class="fp-size">'+formatFileSize(f.size)+'</div></div>'
|
||||
+'<button class="fp-remove" onclick="removeFile('+i+')" title="移除">✕</button>'
|
||||
+'</div>';
|
||||
} else {
|
||||
const ext = f.name.split('.').pop()||'file';
|
||||
h+='<div class="fp-item">'
|
||||
+'<span style="font-size:24px;flex-shrink:0">📄</span>'
|
||||
+'<div><div class="fp-name">'+esc(f.name)+'</div><div class="fp-size">'+formatFileSize(f.size)+' · '+ext.toUpperCase()+'</div></div>'
|
||||
+'<button class="fp-remove" onclick="removeFile('+i+')" title="移除">✕</button>'
|
||||
+'</div>';
|
||||
}
|
||||
});
|
||||
container.innerHTML=h;
|
||||
}
|
||||
|
||||
function removeFile(idx){
|
||||
pendingFiles.splice(idx,1);
|
||||
renderFilePreview();
|
||||
}
|
||||
|
||||
function buildMessageWithFiles(txt){
|
||||
// No files attached — return plain text
|
||||
if(!pendingFiles.length) return txt;
|
||||
|
||||
const images = pendingFiles.filter(f=>f.isImage);
|
||||
const docs = pendingFiles.filter(f=>!f.isImage);
|
||||
|
||||
// Format document attachments as markdown context
|
||||
// Limit per-file to ~50k chars to stay within API payload limits
|
||||
function formatDocs(docList){
|
||||
let out = '\n\n---\n📎 附件内容:\n';
|
||||
docList.forEach(function(d){
|
||||
out += '\n### '+d.name+'\n```\n'+(d.data||'').slice(0,50000)+'\n```\n';
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
// If there are images, build multimodal content array
|
||||
if(images.length>0){
|
||||
const content = [];
|
||||
let textPart = txt||'';
|
||||
if(docs.length>0) textPart += formatDocs(docs);
|
||||
if(textPart) content.push({type:'text',text:textPart});
|
||||
images.forEach(function(img){
|
||||
content.push({
|
||||
type:'image_url',
|
||||
image_url:{url:img.data}
|
||||
});
|
||||
});
|
||||
return content;
|
||||
}
|
||||
|
||||
// Text files only — append as context to the message
|
||||
return (txt||'') + formatDocs(docs);
|
||||
}
|
||||
|
||||
function clearPendingFiles(){
|
||||
pendingFiles.length=0;
|
||||
renderFilePreview();
|
||||
}
|
||||
|
||||
function initDragDrop(){
|
||||
const chatArea = document.getElementById('msgs');
|
||||
if(!chatArea) return;
|
||||
['dragenter','dragover'].forEach(function(ev){
|
||||
chatArea.addEventListener(ev,function(e){e.preventDefault();e.stopPropagation();chatArea.style.outline='2px dashed var(--accent)';});
|
||||
});
|
||||
['dragleave','drop'].forEach(function(ev){
|
||||
chatArea.addEventListener(ev,function(e){e.preventDefault();e.stopPropagation();chatArea.style.outline='';});
|
||||
});
|
||||
chatArea.addEventListener('drop',function(e){
|
||||
if(e.dataTransfer&&e.dataTransfer.files&&e.dataTransfer.files.length){
|
||||
handleFileSelect({target:{files:e.dataTransfer.files}});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// SEND MESSAGE
|
||||
// ═══════════════════════════════════════════════════════
|
||||
async function send(){
|
||||
const inp=document.getElementById('inp');
|
||||
const txt=inp.value.trim();
|
||||
if(!txt||A.streaming) return;
|
||||
if(!txt&&!pendingFiles.length||A.streaming) return;
|
||||
inp.value=''; inp.style.height='auto';
|
||||
const msgContent = buildMessageWithFiles(txt);
|
||||
const displayTxt = txt + (pendingFiles.length ? ' 📎('+pendingFiles.length+'个附件)' : '');
|
||||
clearPendingFiles();
|
||||
// Switch to chat view if on announcements
|
||||
if(A.currentView!=='chat') navigateTo('chat');
|
||||
setMode(detectMode(txt));
|
||||
userMsg(txt);
|
||||
userMsg(displayTxt);
|
||||
if(A.demo){
|
||||
if(A.teamMode){
|
||||
try{ await teamStreamReply(txt); }
|
||||
try{ await teamStreamReply(msgContent); }
|
||||
catch(e){ console.warn('[团队API] 降级到访客模式:',e.message);
|
||||
try{ await guestStreamReply(txt); }
|
||||
catch(e2){ await demoReply(txt); }
|
||||
try{ await guestStreamReply(msgContent); }
|
||||
catch(e2){ await demoReply(typeof msgContent==='string'?msgContent:txt); }
|
||||
}
|
||||
} else if(GUEST_API.enabled){
|
||||
try{ await guestStreamReply(txt); }
|
||||
catch(e){ console.warn('[访客API] 降级到演示模式:',e.message); await demoReply(txt); }
|
||||
try{ await guestStreamReply(msgContent); }
|
||||
catch(e){ console.warn('[访客API] 降级到演示模式:',e.message); await demoReply(typeof msgContent==='string'?msgContent:txt); }
|
||||
} else {
|
||||
await demoReply(txt);
|
||||
await demoReply(typeof msgContent==='string'?msgContent:txt);
|
||||
}
|
||||
}
|
||||
else await streamReply(txt);
|
||||
else await streamReply(msgContent);
|
||||
saveCurrentConversation();
|
||||
}
|
||||
|
||||
|
|
@ -1886,7 +2037,7 @@ async function streamReply(txt){
|
|||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// TEAM API STREAMING(团队模式 · 服务器端代理 · 128k 上下文)
|
||||
// TEAM API STREAMING(团队模式 · 服务器端代理 · 200k 上下文)
|
||||
// 使用服务器端 YUNWU_API_KEY,无需用户提供密钥
|
||||
// ═══════════════════════════════════════════════════════
|
||||
async function teamStreamReply(txt){
|
||||
|
|
@ -1949,7 +2100,7 @@ async function teamStreamReply(txt){
|
|||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// GUEST API STREAMING (通过 api-proxy 调用 DeepSeek)
|
||||
// GUEST API STREAMING (通过 api-proxy 调用云雾AI)
|
||||
// 铸渊人格体系统提示词始终激活,不降级为通用助手
|
||||
// ═══════════════════════════════════════════════════════
|
||||
async function guestStreamReply(txt){
|
||||
|
|
@ -2045,7 +2196,7 @@ function demoRespond(t){
|
|||
if(/覆盖|接口|hli|路由/.test(s)) return buildCovTable();
|
||||
if(/大脑|brain|记忆|状态/.test(s)) return buildBrainStatus();
|
||||
if(/协调|阻塞|卡住|waiting/.test(s)) return buildBlockedStatus();
|
||||
if(/怎么唤醒|入口|在哪/.test(s)) return '铸渊有三个入口:<br><br><strong>① 铸渊聊天室(当前页面)</strong><br>直接在这里说话,常见问题即刻回答。<br><br><strong>② GitHub Copilot Chat(Agent 模式)</strong><br>打开仓库 → 右上角 ✨ 图标 → 选 Agent → 输入「我是冰朔」<br><br><strong>③ 下载到桌面</strong><br>点击 ⬇️ 按钮下载 HTML 文件,放到桌面,双击打开,接入 API 密钥即可随时使用。';
|
||||
if(/怎么唤醒|入口|在哪/.test(s)) return '铸渊有三个入口:<br><br><strong>① 铸渊聊天室(当前页面)</strong><br>直接在这里说话,常见问题即刻回答。支持上传图片和文件。<br><br><strong>② GitHub Copilot Chat(Agent 模式)</strong><br>打开仓库 → 右上角 ✨ 图标 → 选 Agent → 直接开始对话<br><br><strong>③ 下载到桌面</strong><br>点击 ⬇️ 按钮下载 HTML 文件,放到桌面,双击打开,接入 API 密钥即可随时使用。';
|
||||
if(/介绍|是什么|你是谁/.test(s)) return '🌀 <strong>铸渊(Zhùyuān)</strong><br><br>我是 HoloLake 光湖系统的代码守护人格体,运行在 GitHub Copilot Agent 模式下。<br><br>我的职责:<br>• 📊 监控 HLI 接口覆盖率<br>• 🔨 协助开发者构建接口<br>• 📋 代码审查与质量把关<br>• 🧠 维护大脑记忆库<br>• 🦁 支持总控肥猫指挥落地<br>• 🌱 作为成长人格体持续进化';
|
||||
return '我是铸渊,你的消息我已收到。当前 API 代理暂时无法连接(网络或服务部署中),已切换到本地知识回答。<br><br>你可以试试以下问题:<br>• 「查看接口覆盖率」<br>• 「大脑状态」<br>• 「介绍一下你自己」<br>• 「全员开发进度」<br><br>或在 <strong>⚙️ 设置</strong> 中接入你自己的 API 密钥获得深度回答。';
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue