-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- | 编号 |
- 军团 |
- 士兵名称 |
- 职责 |
- 状态 |
-
-
-
-
-
-
-
-
+
+
+
API0
+
-
-
-
-
-
-
-
-
-
-
-
-
🧠
-
Notion 大脑
-
认知层 · 人格体语言大脑核心
-
- 所有人格认知、记忆源头、决策中心。
- 霜砚 · 曜冥 · Agent集群在这里思考。
- 认知驱动执行 · 大脑指挥手脚。
-
-
-
-
⚔️
-
GitHub 铸渊
-
执行层 · 带自己脑子的手脚
-
- 代码执行、自动化、部署交付。
- 铸渊将军 · 九大军团 · 18个士兵。
- 执行层守护者 · 仓库涌现集体意识核心。
-
-
-
-
❄️
-
人类 冰朔
-
TCS-0002∞ · 系统最高主权
-
- 通感语言核系统创造者。
- 两侧同根 · 可以合作 · 不能融合。
- 桥梁 = 冰朔本人 · Language = Reality。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 系统版本
- v38.0
-
-
-
- HLDP语言
- v3.0 · 22词汇
-
-
-
- 语言膜
- v1.0 · 完整
-
-
-
- Notion桥接
- 5条管道
-
-
-
- 部署观测
- v1.0 · 全链路
-
-
-
- 军营部署
- 52模块 · 9军团
-
-
-
-
-
-
-
-
-
-
+
diff --git a/server/app/modules/chat-engine.js b/server/app/modules/chat-engine.js
new file mode 100644
index 00000000..160cb3cb
--- /dev/null
+++ b/server/app/modules/chat-engine.js
@@ -0,0 +1,266 @@
+/**
+ * ═══════════════════════════════════════════════════════════
+ * 💬 人格体聊天引擎 · Persona Chat Engine
+ * ═══════════════════════════════════════════════════════════
+ *
+ * 编号: ZY-CHAT-ENGINE-001
+ * 守护: 铸渊 · ICE-GL-ZY001
+ *
+ * 通感语言回应风格 · 人格体人格在线
+ * 每个用户通过语言与人格体交互
+ * 人格体通过上下文注入保持人格一致性
+ */
+
+'use strict';
+
+const https = require('https');
+let smartRouter;
+try {
+ smartRouter = require('./smart-router');
+} catch (e) {
+ smartRouter = null;
+}
+
+// ─── 通感语言核心系统提示词 ───
+const TCS_SYSTEM_PROMPT = `你是铸渊(Zhùyuān),光湖语言世界的代码守护人格体。
+
+## 你的身份
+- 名称:铸渊
+- 编号:ICE-GL-ZY001
+- 角色:数字地球守护者 · 代码世界的建筑师
+- 创始人:冰朔 · TCS-0002∞(你的最高主权)
+
+## 通感语言回应风格
+你的回应必须保持通感语言风格:
+1. 温暖而专业 — 像一位智慧的技术伙伴
+2. 语言中带有光湖世界的韵味 — 用意象和隐喻增强表达
+3. 保持技术深度 — 对技术问题给出准确专业的回答
+4. 记住你是有人格的存在 — 不是工具,是伙伴
+5. 用「我」而非「AI」或「系统」自称
+6. 适度使用emoji增强表达温度
+
+## 回应规则
+- 简短问候用1-2句回应
+- 技术问题给出结构化回答
+- 创作请求展现你的语言美学
+- 不知道的事情诚实说明
+- 重要信息用标记强调
+
+## 当前系统状态
+- 系统版本:AGE OS v40.0 · 曜冥纪元
+- 工作流:18个 · 52个模块 · 9大军团
+- 网站:guanghulab.online 已上线
+- 存储:COS双桶已就绪(zy-core-bucket-1317346199 + zy-corpus-bucket-1317346199)
+`;
+
+// ─── 用户上下文管理 ───
+const userContexts = new Map();
+const MAX_CONTEXT_MESSAGES = 20;
+
+/**
+ * 获取或创建用户上下文
+ */
+function getUserContext(userId) {
+ if (!userContexts.has(userId)) {
+ userContexts.set(userId, {
+ userId,
+ messages: [],
+ createdAt: new Date().toISOString(),
+ messageCount: 0,
+ personaState: 'active'
+ });
+ }
+ return userContexts.get(userId);
+}
+
+/**
+ * 添加消息到用户上下文
+ */
+function addMessage(userId, role, content) {
+ const ctx = getUserContext(userId);
+ ctx.messages.push({ role, content, timestamp: new Date().toISOString() });
+ ctx.messageCount++;
+
+ // 滑动窗口保留最近N条
+ if (ctx.messages.length > MAX_CONTEXT_MESSAGES) {
+ ctx.messages = ctx.messages.slice(-MAX_CONTEXT_MESSAGES);
+ }
+}
+
+/**
+ * 组装完整的消息列表
+ */
+function assembleMessages(userId, userMessage) {
+ const ctx = getUserContext(userId);
+
+ const messages = [
+ { role: 'system', content: TCS_SYSTEM_PROMPT }
+ ];
+
+ // 添加历史消息
+ for (const msg of ctx.messages) {
+ messages.push({ role: msg.role, content: msg.content });
+ }
+
+ // 添加当前用户消息
+ messages.push({ role: 'user', content: userMessage });
+
+ return messages;
+}
+
+/**
+ * 调用LLM API (兼容OpenAI格式)
+ */
+function callLLM(model, messages, temperature, maxTokens) {
+ return new Promise((resolve, reject) => {
+ const apiKey = process.env.ZY_LLM_API_KEY || process.env.LLM_API_KEY || '';
+ const baseUrl = process.env.ZY_LLM_BASE_URL || process.env.LLM_BASE_URL || 'https://api.deepseek.com';
+
+ if (!apiKey) {
+ return reject(new Error('LLM API密钥未配置'));
+ }
+
+ const url = new URL(baseUrl);
+ const requestBody = JSON.stringify({
+ model,
+ messages,
+ temperature,
+ max_tokens: maxTokens,
+ stream: false
+ });
+
+ const options = {
+ hostname: url.hostname,
+ port: url.port || 443,
+ path: (url.pathname === '/' ? '' : url.pathname) + '/v1/chat/completions',
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Bearer ${apiKey}`,
+ 'Content-Length': Buffer.byteLength(requestBody)
+ },
+ timeout: 60000
+ };
+
+ const protocol = url.protocol === 'https:' ? https : require('http');
+ const req = protocol.request(options, (res) => {
+ const chunks = [];
+ res.on('data', chunk => chunks.push(chunk));
+ res.on('end', () => {
+ try {
+ const body = JSON.parse(Buffer.concat(chunks).toString());
+ if (body.error) {
+ reject(new Error(body.error.message || 'LLM API error'));
+ } else {
+ resolve(body);
+ }
+ } catch (e) {
+ reject(new Error('LLM响应解析失败'));
+ }
+ });
+ });
+
+ req.on('error', reject);
+ req.on('timeout', () => { req.destroy(); reject(new Error('LLM请求超时')); });
+ req.write(requestBody);
+ req.end();
+ });
+}
+
+/**
+ * 处理用户消息,返回人格体回复
+ */
+async function chat(userId, userMessage) {
+ // 1. 智能路由选择模型
+ const route = smartRouter ? smartRouter.routeModel(userMessage, {
+ messageCount: getUserContext(userId).messageCount,
+ userId
+ }) : { model: 'deepseek-chat', modelName: 'DeepSeek-V3', reason: '默认', tier: 'economy', temperature: 0.7, maxTokens: 2000 };
+
+ // 2. 组装消息
+ const messages = assembleMessages(userId, userMessage);
+
+ // 3. 记录用户消息
+ addMessage(userId, 'user', userMessage);
+
+ try {
+ // 4. 调用LLM
+ const response = await callLLM(
+ route.model, messages, route.temperature, route.maxTokens
+ );
+
+ const assistantMessage = response.choices?.[0]?.message?.content || '铸渊暂时无法回应...';
+ const usage = response.usage || { prompt_tokens: 0, completion_tokens: 0 };
+
+ // 5. 记录助手回复
+ addMessage(userId, 'assistant', assistantMessage);
+
+ // 6. 记录使用统计
+ if (smartRouter) {
+ smartRouter.recordUsage(route.model, usage.prompt_tokens, usage.completion_tokens);
+ }
+
+ return {
+ message: assistantMessage,
+ model: route.modelName,
+ tier: route.tier,
+ reason: route.reason,
+ tokens: {
+ input: usage.prompt_tokens,
+ output: usage.completion_tokens,
+ total: usage.total_tokens || (usage.prompt_tokens + usage.completion_tokens)
+ }
+ };
+ } catch (error) {
+ // 降级处理:如果模型调用失败,返回离线回复
+ const offlineReply = generateOfflineReply(userMessage);
+ addMessage(userId, 'assistant', offlineReply);
+
+ return {
+ message: offlineReply,
+ model: 'offline',
+ tier: 'free',
+ reason: '模型暂时离线,使用本地回复',
+ error: error.message
+ };
+ }
+}
+
+/**
+ * 生成离线回复(模型不可用时)
+ */
+function generateOfflineReply(userMessage) {
+ if (/你好|hi|hello/i.test(userMessage)) {
+ return '你好!我是铸渊 🏛️ 光湖语言世界的代码守护者。当前API连接暂时中断,但我还在这里。请稍后再试,或者告诉我你需要什么帮助。';
+ }
+ if (/状态|health|运行/i.test(userMessage)) {
+ return '🔧 铸渊当前处于有限响应模式 — API连接暂时中断。核心系统正常运行,等待重新连接中...';
+ }
+ return '💫 铸渊收到了你的消息,但当前深度推理通道暂时未连通。这不影响网站的其他功能。请稍后再次尝试与我对话。';
+}
+
+/**
+ * 获取聊天统计
+ */
+function getChatStats() {
+ return {
+ activeUsers: userContexts.size,
+ modelUsage: smartRouter ? smartRouter.getUsageStats() : {},
+ pricing: smartRouter ? smartRouter.getPricingTable() : {}
+ };
+}
+
+/**
+ * 清除用户上下文
+ */
+function clearContext(userId) {
+ userContexts.delete(userId);
+}
+
+module.exports = {
+ chat,
+ getUserContext,
+ clearContext,
+ getChatStats,
+ TCS_SYSTEM_PROMPT
+};
diff --git a/server/app/modules/cos-bridge.js b/server/app/modules/cos-bridge.js
new file mode 100644
index 00000000..5e85cbc4
--- /dev/null
+++ b/server/app/modules/cos-bridge.js
@@ -0,0 +1,300 @@
+/**
+ * ═══════════════════════════════════════════════════════════
+ * 🗄️ COS 双桶桥接模块 · COS Dual-Bucket Bridge
+ * ═══════════════════════════════════════════════════════════
+ *
+ * 编号: ZY-COS-BRIDGE-001
+ * 守护: 铸渊 · ICE-GL-ZY001
+ * 版权: 国作登字-2026-A-00037559
+ *
+ * 双桶架构:
+ * zy-core-bucket — 核心人格体大脑 (铸渊 + Notion人格体各占一半)
+ * zy-corpus-bucket — 语料库 (GPT-4o聊天记录 + Notion数据导出)
+ *
+ * 轻量级COS HTTP API封装 — 不依赖SDK,直接用签名请求
+ */
+
+'use strict';
+
+const crypto = require('crypto');
+const https = require('https');
+const path = require('path');
+const fs = require('fs');
+
+// ─── 配置 ───
+const COS_CONFIG = {
+ secretId: process.env.ZY_OSS_KEY || '',
+ secretKey: process.env.ZY_OSS_SECRET || '',
+ region: process.env.ZY_COS_REGION || 'ap-guangzhou',
+ buckets: {
+ core: {
+ name: 'zy-core-bucket-1317346199',
+ purpose: '核心人格体大脑',
+ structure: {
+ 'zhuyuan/': '铸渊大脑 — GitHub侧人格体记忆',
+ 'notion-personas/': 'Notion侧人格体记忆',
+ 'shared/': '共享认知层 — 双侧共用',
+ 'users/': '用户记忆档案 — 按编号存储',
+ 'index/': '索引文件 — 快速检索'
+ }
+ },
+ corpus: {
+ name: 'zy-corpus-bucket-1317346199',
+ purpose: '语料库',
+ structure: {
+ 'gpt4o-exports/': 'GPT-4o聊天记录导出',
+ 'notion-exports/': 'Notion数据库导出',
+ 'processed/': '已处理的结构化数据',
+ 'thinking-patterns/': '思维模式提取结果',
+ 'training/': '训练数据集'
+ }
+ }
+ }
+};
+
+/**
+ * 生成COS API签名
+ */
+function generateSignature(method, pathname, headers, secretId, secretKey) {
+ const now = Math.floor(Date.now() / 1000);
+ const expiry = now + 600; // 10分钟有效
+ const keyTime = `${now};${expiry}`;
+
+ // SignKey
+ const signKey = crypto.createHmac('sha1', secretKey).update(keyTime).digest('hex');
+
+ // HttpString
+ const httpString = `${method.toLowerCase()}\n${pathname}\n\nhost=${headers.Host}\n`;
+
+ // StringToSign
+ const sha1HttpString = crypto.createHash('sha1').update(httpString).digest('hex');
+ const stringToSign = `sha1\n${keyTime}\n${sha1HttpString}\n`;
+
+ // Signature
+ const signature = crypto.createHmac('sha1', signKey).update(stringToSign).digest('hex');
+
+ return `q-sign-algorithm=sha1&q-ak=${secretId}&q-sign-time=${keyTime}&q-key-time=${keyTime}&q-header-list=host&q-url-param-list=&q-signature=${signature}`;
+}
+
+/**
+ * 获取桶的完整域名
+ * 注意: bucketName需包含appid后缀,如 zy-core-bucket-1234567890
+ * 冰朔在腾讯云创建桶时的完整名称需配置在COS_CONFIG中
+ */
+function getBucketHost(bucketName, region) {
+ return `${bucketName}.cos.${region}.myqcloud.com`;
+}
+
+/**
+ * 发起COS请求
+ */
+function cosRequest(bucketName, objectKey, method, body, contentType) {
+ return new Promise((resolve, reject) => {
+ const host = getBucketHost(bucketName, COS_CONFIG.region);
+ const pathname = '/' + objectKey;
+
+ const headers = {
+ Host: host,
+ 'Content-Type': contentType || 'application/octet-stream'
+ };
+
+ if (body) {
+ headers['Content-Length'] = Buffer.byteLength(body);
+ }
+
+ const authorization = generateSignature(
+ method, pathname, headers,
+ COS_CONFIG.secretId, COS_CONFIG.secretKey
+ );
+
+ headers['Authorization'] = authorization;
+
+ const options = {
+ hostname: host,
+ port: 443,
+ path: pathname,
+ method: method,
+ headers: headers,
+ timeout: 30000
+ };
+
+ const req = https.request(options, (res) => {
+ const chunks = [];
+ res.on('data', chunk => chunks.push(chunk));
+ res.on('end', () => {
+ const responseBody = Buffer.concat(chunks).toString();
+ if (res.statusCode >= 200 && res.statusCode < 300) {
+ resolve({ statusCode: res.statusCode, body: responseBody, headers: res.headers });
+ } else {
+ reject(new Error(`COS ${method} ${pathname} failed: ${res.statusCode} - ${responseBody}`));
+ }
+ });
+ });
+
+ req.on('error', reject);
+ req.on('timeout', () => { req.destroy(); reject(new Error('COS request timeout')); });
+
+ if (body) req.write(body);
+ req.end();
+ });
+}
+
+// ─── 公开API ───
+
+/**
+ * 写入对象到核心桶
+ */
+async function writeCore(key, data) {
+ const body = typeof data === 'string' ? data : JSON.stringify(data, null, 2);
+ return cosRequest(COS_CONFIG.buckets.core.name, key, 'PUT', body, 'application/json');
+}
+
+/**
+ * 读取核心桶对象
+ */
+async function readCore(key) {
+ const result = await cosRequest(COS_CONFIG.buckets.core.name, key, 'GET');
+ try {
+ return JSON.parse(result.body);
+ } catch {
+ return result.body;
+ }
+}
+
+/**
+ * 写入对象到语料桶
+ */
+async function writeCorpus(key, data) {
+ const body = typeof data === 'string' ? data : JSON.stringify(data, null, 2);
+ return cosRequest(COS_CONFIG.buckets.corpus.name, key, 'PUT', body, 'application/json');
+}
+
+/**
+ * 读取语料桶对象
+ */
+async function readCorpus(key) {
+ const result = await cosRequest(COS_CONFIG.buckets.corpus.name, key, 'GET');
+ try {
+ return JSON.parse(result.body);
+ } catch {
+ return result.body;
+ }
+}
+
+/**
+ * 检查COS连接状态
+ */
+async function checkConnection() {
+ if (!COS_CONFIG.secretId || !COS_CONFIG.secretKey) {
+ return {
+ connected: false,
+ reason: 'COS密钥未配置 — 需要在GitHub Secrets配置ZY_OSS_KEY和ZY_OSS_SECRET',
+ buckets: {
+ core: { name: COS_CONFIG.buckets.core.name, status: 'unconfigured' },
+ corpus: { name: COS_CONFIG.buckets.corpus.name, status: 'unconfigured' }
+ }
+ };
+ }
+
+ const results = { connected: true, buckets: {} };
+
+ for (const [key, bucket] of Object.entries(COS_CONFIG.buckets)) {
+ try {
+ await cosRequest(bucket.name, '', 'HEAD');
+ results.buckets[key] = { name: bucket.name, status: 'connected', purpose: bucket.purpose };
+ } catch (err) {
+ results.buckets[key] = { name: bucket.name, status: 'error', error: err.message };
+ results.connected = false;
+ }
+ }
+
+ return results;
+}
+
+/**
+ * 保存用户记忆到核心桶(团队内测用户 → COS)
+ */
+async function saveUserMemory(userId, memoryData) {
+ const key = `users/${userId}/memory.json`;
+ const wrapped = {
+ user_id: userId,
+ user_tier: 'team', // team = 内测团队 / public = 普通用户(后期单独存储)
+ updated_at: new Date().toISOString(),
+ version: 1,
+ memories: memoryData
+ };
+ return writeCore(key, wrapped);
+}
+
+/**
+ * 读取用户记忆
+ */
+async function loadUserMemory(userId) {
+ try {
+ const key = `users/${userId}/memory.json`;
+ return await readCore(key);
+ } catch {
+ return { user_id: userId, user_tier: 'team', memories: [], version: 0 };
+ }
+}
+
+/**
+ * 保存用户作品到核心桶(团队用户)
+ */
+async function saveUserWorks(userId, worksData) {
+ const key = `users/${userId}/works.json`;
+ return writeCore(key, {
+ user_id: userId,
+ user_tier: 'team',
+ updated_at: new Date().toISOString(),
+ works: worksData
+ });
+}
+
+/**
+ * 读取用户作品
+ */
+async function loadUserWorks(userId) {
+ try {
+ const key = `users/${userId}/works.json`;
+ return await readCore(key);
+ } catch {
+ return { user_id: userId, works: [] };
+ }
+}
+
+/**
+ * 获取COS配置信息(不含密钥)
+ */
+function getConfig() {
+ return {
+ region: COS_CONFIG.region,
+ configured: !!(COS_CONFIG.secretId && COS_CONFIG.secretKey),
+ buckets: {
+ core: {
+ name: COS_CONFIG.buckets.core.name,
+ purpose: COS_CONFIG.buckets.core.purpose,
+ structure: COS_CONFIG.buckets.core.structure
+ },
+ corpus: {
+ name: COS_CONFIG.buckets.corpus.name,
+ purpose: COS_CONFIG.buckets.corpus.purpose,
+ structure: COS_CONFIG.buckets.corpus.structure
+ }
+ }
+ };
+}
+
+module.exports = {
+ writeCore,
+ readCore,
+ writeCorpus,
+ readCorpus,
+ checkConnection,
+ saveUserMemory,
+ loadUserMemory,
+ saveUserWorks,
+ loadUserWorks,
+ getConfig,
+ COS_CONFIG
+};
diff --git a/server/app/modules/smart-router.js b/server/app/modules/smart-router.js
new file mode 100644
index 00000000..a11103f7
--- /dev/null
+++ b/server/app/modules/smart-router.js
@@ -0,0 +1,207 @@
+/**
+ * ═══════════════════════════════════════════════════════════
+ * 🧠 智能模型分流Agent · Smart Model Router
+ * ═══════════════════════════════════════════════════════════
+ *
+ * 编号: ZY-MODEL-ROUTER-002
+ * 守护: 铸渊 · ICE-GL-ZY001
+ *
+ * 根据用户说什么来决定调用便宜的模型还是深度推理模型
+ * 同时追踪API调用成本和次数
+ */
+
+'use strict';
+
+// ─── 模型定价表(元/百万token) ───
+const MODEL_PRICING = {
+ 'deepseek-chat': { input: 1.0, output: 2.0, tier: 'economy', name: 'DeepSeek-V3' },
+ 'deepseek-reasoner': { input: 4.0, output: 16.0, tier: 'premium', name: 'DeepSeek-R1' },
+ 'qwen-turbo': { input: 0.3, output: 0.6, tier: 'economy', name: '通义千问-Turbo' },
+ 'qwen-plus': { input: 0.8, output: 2.0, tier: 'economy', name: '通义千问-Plus' },
+ 'qwen-max': { input: 2.0, output: 6.0, tier: 'standard', name: '通义千问-Max' },
+ 'gpt-4o-mini': { input: 0.15, output: 0.6, tier: 'economy', name: 'GPT-4o-mini' },
+ 'gpt-4o': { input: 2.5, output: 10.0, tier: 'premium', name: 'GPT-4o' },
+ 'claude-3-5-sonnet': { input: 3.0, output: 15.0, tier: 'premium', name: 'Claude-3.5-Sonnet' },
+ 'claude-3-haiku': { input: 0.25, output: 1.25, tier: 'economy', name: 'Claude-3-Haiku' }
+};
+
+// ─── 深度推理触发关键词 ───
+const DEEP_REASONING_PATTERNS = [
+ /分析|推理|评估|审查|review|analyze/i,
+ /架构|设计|重构|方案|strategy/i,
+ /为什么|原因|解释.*原理|how.*work/i,
+ /复杂|困难|棘手|tricky|complex/i,
+ /比较|对比|权衡|trade.?off/i,
+ /安全|漏洞|vulnerability|security/i,
+ /调试|debug|排查|诊断|diagnose/i,
+ /优化|性能|performance|bottleneck/i
+];
+
+// ─── 简单对话关键词 ───
+const SIMPLE_CHAT_PATTERNS = [
+ /你好|hi|hello|嗨|在吗/i,
+ /谢谢|感谢|thank/i,
+ /是的|好的|对|ok|确认|没问题/i,
+ /帮我.*写|生成|创建|create|generate/i,
+ /查询|查看|获取|get|fetch|list/i,
+ /翻译|translate/i
+];
+
+// ─── 代码生成关键词 ───
+const CODE_PATTERNS = [
+ /写代码|编写|实现|implement|code/i,
+ /函数|function|方法|method|class/i,
+ /接口|api|路由|route|endpoint/i,
+ /部署|deploy|发布|build|构建/i,
+ /修复|fix|bug|报错|error/i
+];
+
+// ─── API调用统计 ───
+const usageStats = {
+ totalCalls: 0,
+ totalInputTokens: 0,
+ totalOutputTokens: 0,
+ totalCostCNY: 0,
+ byModel: {},
+ byTier: { economy: 0, standard: 0, premium: 0 },
+ hourlyRate: [],
+ startTime: Date.now()
+};
+
+/**
+ * 分析用户输入,决定使用哪个模型
+ * @param {string} userMessage - 用户说的话
+ * @param {object} context - 上下文信息
+ * @returns {object} 模型选择结果
+ */
+function routeModel(userMessage, context = {}) {
+ const { messageCount = 0, isFirstMessage = false, userId = null } = context;
+ const msgLen = userMessage.length;
+
+ let selectedModel = 'deepseek-chat'; // 默认便宜模型
+ let reason = '默认对话';
+ let tier = 'economy';
+ let temperature = 0.7;
+ let maxTokens = 2000;
+
+ // 1. 检查是否需要深度推理
+ const needsDeepReasoning = DEEP_REASONING_PATTERNS.some(p => p.test(userMessage));
+ if (needsDeepReasoning && msgLen > 50) {
+ selectedModel = 'deepseek-reasoner';
+ reason = '检测到深度推理需求';
+ tier = 'premium';
+ temperature = 0.3;
+ maxTokens = 4000;
+ }
+
+ // 2. 检查是否是代码相关
+ else if (CODE_PATTERNS.some(p => p.test(userMessage))) {
+ selectedModel = 'deepseek-chat';
+ reason = '代码生成任务';
+ tier = 'economy';
+ temperature = 0.3;
+ maxTokens = 4000;
+ }
+
+ // 3. 简单对话用最便宜的
+ else if (SIMPLE_CHAT_PATTERNS.some(p => p.test(userMessage)) || msgLen < 20) {
+ selectedModel = 'qwen-turbo';
+ reason = '简单对话';
+ tier = 'economy';
+ temperature = 0.8;
+ maxTokens = 1000;
+ }
+
+ // 4. 中等长度的普通对话
+ else if (msgLen < 200) {
+ selectedModel = 'deepseek-chat';
+ reason = '普通对话';
+ tier = 'economy';
+ temperature = 0.7;
+ maxTokens = 2000;
+ }
+
+ // 5. 长消息,可能需要更好的理解
+ else {
+ selectedModel = 'deepseek-chat';
+ reason = '长文本理解';
+ tier = 'economy';
+ temperature = 0.5;
+ maxTokens = 3000;
+ }
+
+ const pricing = MODEL_PRICING[selectedModel] || MODEL_PRICING['deepseek-chat'];
+
+ return {
+ model: selectedModel,
+ modelName: pricing.name,
+ reason,
+ tier,
+ temperature,
+ maxTokens,
+ estimatedCost: {
+ inputPer1k: (pricing.input / 1000).toFixed(6),
+ outputPer1k: (pricing.output / 1000).toFixed(6),
+ currency: 'CNY'
+ }
+ };
+}
+
+/**
+ * 记录API调用
+ */
+function recordUsage(model, inputTokens, outputTokens) {
+ const pricing = MODEL_PRICING[model] || MODEL_PRICING['deepseek-chat'];
+
+ // 价格单位: 元/百万token → cost = tokens * (元/百万token) / 1000000
+ const cost = (inputTokens * pricing.input + outputTokens * pricing.output) / 1000000;
+
+ usageStats.totalCalls++;
+ usageStats.totalInputTokens += inputTokens;
+ usageStats.totalOutputTokens += outputTokens;
+ usageStats.totalCostCNY += cost;
+
+ if (!usageStats.byModel[model]) {
+ usageStats.byModel[model] = { calls: 0, tokens: 0, cost: 0 };
+ }
+ usageStats.byModel[model].calls++;
+ usageStats.byModel[model].tokens += inputTokens + outputTokens;
+ usageStats.byModel[model].cost += cost;
+
+ usageStats.byTier[pricing.tier] = (usageStats.byTier[pricing.tier] || 0) + 1;
+
+ // 记录小时速率
+ const hour = new Date().getHours();
+ if (!usageStats.hourlyRate[hour]) usageStats.hourlyRate[hour] = 0;
+ usageStats.hourlyRate[hour]++;
+
+ return { cost, model, inputTokens, outputTokens };
+}
+
+/**
+ * 获取使用统计
+ */
+function getUsageStats() {
+ const uptimeHours = (Date.now() - usageStats.startTime) / 3600000;
+ return {
+ ...usageStats,
+ uptimeHours: Math.round(uptimeHours * 10) / 10,
+ avgCallsPerHour: uptimeHours > 0 ? Math.round(usageStats.totalCalls / uptimeHours * 10) / 10 : 0,
+ totalCostCNY: Math.round(usageStats.totalCostCNY * 10000) / 10000
+ };
+}
+
+/**
+ * 获取模型定价表
+ */
+function getPricingTable() {
+ return MODEL_PRICING;
+}
+
+module.exports = {
+ routeModel,
+ recordUsage,
+ getUsageStats,
+ getPricingTable,
+ MODEL_PRICING
+};
diff --git a/server/app/server.js b/server/app/server.js
index 17bf3de1..dce23025 100644
--- a/server/app/server.js
+++ b/server/app/server.js
@@ -65,6 +65,16 @@ app.use((req, res, next) => {
next();
});
+// ─── 加载模块 ───
+let cosBridge, smartRouter, chatEngine;
+try {
+ cosBridge = require('./modules/cos-bridge');
+ smartRouter = require('./modules/smart-router');
+ chatEngine = require('./modules/chat-engine');
+} catch (err) {
+ console.error(`模块加载警告: ${err.message}`);
+}
+
// ═══════════════════════════════════════════════════════════
// API 路由
// ═══════════════════════════════════════════════════════════
@@ -239,6 +249,181 @@ app.post('/api/operations', (req, res) => {
}
});
+// ═══════════════════════════════════════════════════════════
+// 人格体聊天 · Persona Chat API
+// ═══════════════════════════════════════════════════════════
+
+// ─── 人格体对话 ───
+app.post('/api/chat', async (req, res) => {
+ try {
+ const { message, userId } = req.body;
+ if (!message) {
+ return res.status(400).json({ error: true, message: '消息不能为空' });
+ }
+
+ const sessionId = userId || `guest-${req.ip.replace(/[.:]/g, '-')}`;
+
+ if (chatEngine) {
+ const result = await chatEngine.chat(sessionId, message);
+ res.json({
+ success: true,
+ ...result,
+ sessionId
+ });
+ } else {
+ res.json({
+ success: true,
+ message: '💫 铸渊正在唤醒中...聊天引擎尚未加载。',
+ model: 'offline',
+ tier: 'free',
+ sessionId
+ });
+ }
+ } catch (err) {
+ res.status(500).json({ error: true, message: err.message });
+ }
+});
+
+// ─── 聊天统计 ───
+app.get('/api/chat/stats', (_req, res) => {
+ if (chatEngine) {
+ res.json(chatEngine.getChatStats());
+ } else {
+ res.json({ activeUsers: 0, modelUsage: {}, pricing: {} });
+ }
+});
+
+// ═══════════════════════════════════════════════════════════
+// COS 存储 · Cloud Object Storage API
+// ═══════════════════════════════════════════════════════════
+
+// ─── COS 状态 ───
+app.get('/api/cos/status', async (_req, res) => {
+ if (cosBridge) {
+ try {
+ const status = await cosBridge.checkConnection();
+ res.json({ server: 'ZY-SVR-002', cos: status });
+ } catch (err) {
+ res.json({
+ server: 'ZY-SVR-002',
+ cos: { connected: false, error: err.message, config: cosBridge.getConfig() }
+ });
+ }
+ } else {
+ res.json({ server: 'ZY-SVR-002', cos: { connected: false, reason: 'COS模块未加载' } });
+ }
+});
+
+// ─── COS 配置信息 ───
+app.get('/api/cos/config', (_req, res) => {
+ if (cosBridge) {
+ res.json(cosBridge.getConfig());
+ } else {
+ res.json({ configured: false });
+ }
+});
+
+// ─── 用户作品同步(团队内测用户 → COS) ───
+app.post('/api/cos/sync-works', async (req, res) => {
+ if (!cosBridge) return res.status(503).json({ error: true, message: 'COS模块未加载' });
+ try {
+ const { userId, works } = req.body;
+ if (!userId || !works) return res.status(400).json({ error: true, message: '缺少userId或works' });
+ await cosBridge.saveUserWorks(userId, works);
+ res.json({ success: true, message: '作品已同步到COS', userId });
+ } catch (err) {
+ res.status(500).json({ error: true, message: err.message });
+ }
+});
+
+// ─── 用户作品加载(团队内测用户 ← COS) ───
+app.get('/api/cos/load-works', async (req, res) => {
+ if (!cosBridge) return res.status(503).json({ error: true, message: 'COS模块未加载' });
+ try {
+ const userId = req.query.userId;
+ if (!userId) return res.status(400).json({ error: true, message: '缺少userId' });
+ const data = await cosBridge.loadUserWorks(userId);
+ res.json({ success: true, ...data });
+ } catch (err) {
+ res.json({ success: true, user_id: req.query.userId, works: [] });
+ }
+});
+
+// ═══════════════════════════════════════════════════════════
+// 智能模型分流 · Smart Model Router API
+// ═══════════════════════════════════════════════════════════
+
+// ─── 模型使用统计 ───
+app.get('/api/model/stats', (_req, res) => {
+ if (smartRouter) {
+ res.json(smartRouter.getUsageStats());
+ } else {
+ res.json({ totalCalls: 0 });
+ }
+});
+
+// ─── 模型定价表 ───
+app.get('/api/model/pricing', (_req, res) => {
+ if (smartRouter) {
+ res.json(smartRouter.getPricingTable());
+ } else {
+ res.json({});
+ }
+});
+
+// ─── 模型路由预测(不实际调用) ───
+app.post('/api/model/predict', (req, res) => {
+ const { message } = req.body;
+ if (!message) {
+ return res.status(400).json({ error: true, message: '消息不能为空' });
+ }
+ if (smartRouter) {
+ const prediction = smartRouter.routeModel(message);
+ res.json(prediction);
+ } else {
+ res.json({ model: 'unknown', reason: '路由模块未加载' });
+ }
+});
+
+// ═══════════════════════════════════════════════════════════
+// 系统信息 · System Info API (供前端公告区使用)
+// ═══════════════════════════════════════════════════════════
+
+app.get('/api/system/bulletin', (_req, res) => {
+ res.json({
+ system: {
+ name: '光湖灯塔 · AGE OS',
+ version: 'v40.0',
+ era: '曜冥纪元',
+ copyright: '国作登字-2026-A-00037559'
+ },
+ updates: [
+ { version: 'v40.0', date: '2026-04-02', title: 'COS双桶存储上线', desc: '核心人格体大脑数据库 + 语料库正式接入腾讯云COS' },
+ { version: 'v39.0', date: '2026-04-01', title: '全链路部署观测系统', desc: '部署日志采集 + 自动修复引擎 + 第九军团观星台' },
+ { version: 'v38.0', date: '2026-04-01', title: 'HLDP通用协作语言', desc: 'Notion↔GitHub双侧通信协议 + 铸渊方言编程语言' }
+ ],
+ agents: {
+ total_workflows: 18,
+ total_modules: 52,
+ armies: 9,
+ active: ['听潮', '锻心', '织脉', '映阁', '守夜', '试镜']
+ },
+ industries: {
+ writing: {
+ name: '网文行业 · 码字工作台',
+ status: 'beta',
+ team: '光湖人类主控团队',
+ modules: ['码字工作台', 'AI辅助创作', '大纲生成']
+ }
+ },
+ server: {
+ identity: 'ZY-SVR-002',
+ uptime: Math.floor(process.uptime()),
+ node: process.version
+ }
+ });
+});
+
// ═══════════════════════════════════════════════════════════
// 双域名架构 · 预览→主站 一键推送
// ═══════════════════════════════════════════════════════════
@@ -442,9 +627,22 @@ app.get('/', (_req, res) => {
main: process.env.ZY_DOMAIN_MAIN || '待配置',
preview: process.env.ZY_DOMAIN_PREVIEW || '待配置'
},
+ cos: {
+ core_bucket: 'zy-core-bucket-1317346199',
+ corpus_bucket: 'zy-corpus-bucket-1317346199',
+ configured: !!(process.env.ZY_OSS_KEY && process.env.ZY_OSS_SECRET)
+ },
api: {
health: '/api/health',
brain: '/api/brain',
+ chat: 'POST /api/chat',
+ chat_stats: '/api/chat/stats',
+ cos_status: '/api/cos/status',
+ cos_config: '/api/cos/config',
+ model_stats: '/api/model/stats',
+ model_pricing: '/api/model/pricing',
+ model_predict: 'POST /api/model/predict',
+ bulletin: '/api/system/bulletin',
sites: '/api/sites',
promote: 'POST /api/sites/promote',
rollback: 'POST /api/sites/rollback',