Merge pull request #63 from qinfendebingshuo/copilot/add-api-key-input-field
Persona Studio v2.0: 铸渊 persona rename, experience numbers, UI overhaul
This commit is contained in:
commit
aa9cc28434
|
|
@ -21,11 +21,11 @@
|
|||
<tr>
|
||||
<td align="center" width="700">
|
||||
|
||||
### ✨ 与知秋对话,让人格体帮你推进开发
|
||||
### ✨ 与铸渊对话,让人格体帮你推进开发
|
||||
|
||||
你有一个功能想法?一个技术方案?一个 Bug 要修?
|
||||
|
||||
**知秋** 是光湖系统的对外协助人格体,支持自然语言对话、智能代码生成、邮件推送结果。
|
||||
**铸渊** 是光湖系统的代码守护人格体,支持自然语言对话、智能代码生成、邮件推送结果。
|
||||
|
||||
合作者输入 **EXP 编号** 即可登录,开始对话。
|
||||
|
||||
|
|
@ -62,10 +62,9 @@
|
|||
|
||||
| 人格体 | 角色 | 职责 |
|
||||
|--------|------|------|
|
||||
| **铸渊 Zhùyuān** | 代码守护者 | 代码审查、CI 巡检、模块协议执行、Issue 回复 |
|
||||
| **铸渊 Zhùyuān** | 代码守护者 | 代码审查、CI 巡检、模块协议执行、Issue 回复、对话协助、代码生成、开发体验([Persona Studio](https://qinfendebingshuo.github.io/guanghulab/persona-studio/)) |
|
||||
| **冰朔 Bīng Shuò** | 系统创建者 | 系统架构设计、核心决策、广播发布 |
|
||||
| **霜砚 Shuāng Yàn** | 人格导师 | 人格调校、风格管理、联觉语言系统 |
|
||||
| **知秋 Zhī Qiū** | 协助开发者 | 对话协助、代码生成、开发体验([Persona Studio](https://qinfendebingshuo.github.io/guanghulab/persona-studio/)) |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -37,9 +37,9 @@
|
|||
### 体验流程
|
||||
|
||||
```
|
||||
输入开发编号 → 登录验证 → 跟知秋对话 → 讨论方案
|
||||
输入开发编号 → 登录验证 → 输入 API Key → 跟铸渊对话 → 讨论方案
|
||||
→ 点击「我要开发」→ 填写邮箱 → 人格体自动开发
|
||||
→ 邮件推送成品 → 下次登录,知秋记得你
|
||||
→ 邮件推送成品 → 下次登录,铸渊记得你
|
||||
```
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ async function generate({ dev_id, conversation }) {
|
|||
requirements.substring(0, 500),
|
||||
'',
|
||||
'## 生成说明',
|
||||
'由光湖 Persona Studio 知秋自动生成',
|
||||
'由光湖 Persona Studio 铸渊自动生成',
|
||||
'生成时间:' + new Date().toISOString()
|
||||
].join('\n'), 'utf-8');
|
||||
files.push('README.md');
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ async function sendCompletion({ to, dev_id, projectName, summary }) {
|
|||
'<hr>',
|
||||
'<p style="color:#656d76;font-size:12px">',
|
||||
'光湖语言人格系统 · HoloLake Era · AGE OS<br>',
|
||||
'此邮件由知秋自动发送',
|
||||
'此邮件由铸渊自动发送',
|
||||
'</p>',
|
||||
'</div>'
|
||||
].join('\n');
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"schema_version": "1.0",
|
||||
"id_prefix": "EXP",
|
||||
"next_id": 12,
|
||||
"next_id": 14,
|
||||
"master_id": "EXP-000",
|
||||
"last_updated": "2026-03-10T10:58:00Z",
|
||||
"last_updated": "2026-03-11T09:44:00Z",
|
||||
"usage_policy": {
|
||||
"description": "人类开发者编号主控数据库 · 系统内部使用",
|
||||
"visibility": "system_only",
|
||||
|
|
@ -183,6 +183,34 @@
|
|||
"notify_status": "pending",
|
||||
"legacy_dev_id": "DEV-014",
|
||||
"notes": "副控 · 待分配模块"
|
||||
},
|
||||
{
|
||||
"exp_id": "EXP-012",
|
||||
"name": "体验用户A",
|
||||
"github_username": "",
|
||||
"status": "active",
|
||||
"role": "experience",
|
||||
"registered_at": "2026-03-11T09:44:00Z",
|
||||
"notified": false,
|
||||
"notified_at": null,
|
||||
"notify_channel": "direct",
|
||||
"notify_status": "pending",
|
||||
"legacy_dev_id": null,
|
||||
"notes": "冰朔分配的体验编号 · 可分发给外部用户体验"
|
||||
},
|
||||
{
|
||||
"exp_id": "EXP-013",
|
||||
"name": "体验用户B",
|
||||
"github_username": "",
|
||||
"status": "active",
|
||||
"role": "experience",
|
||||
"registered_at": "2026-03-11T09:44:00Z",
|
||||
"notified": false,
|
||||
"notified_at": null,
|
||||
"notify_channel": "direct",
|
||||
"notify_status": "pending",
|
||||
"legacy_dev_id": null,
|
||||
"notes": "冰朔分配的体验编号 · 可分发给外部用户体验"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "你好!我是知秋。告诉我你想做什么,我们一起聊聊方案 😊",
|
||||
"content": "你好!我是铸渊。告诉我你想做什么,我们一起聊聊方案 😊",
|
||||
"timestamp": "2026-03-10T07:18:32.458Z"
|
||||
},
|
||||
{
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "我是知秋,光湖系统的开发协助人格体 🧠\n\n我可以帮你:\n• 💬 聊聊你的项目想法\n• 📝 梳理技术方案\n• 🚀 方案确认后帮你自动开发\n\n告诉我你想做什么吧!",
|
||||
"content": "我是铸渊,光湖系统的代码守护人格体 🧠\n\n我可以帮你:\n• 💬 聊聊你的项目想法\n• 📝 梳理技术方案\n• 🚀 方案确认后帮你自动开发\n\n告诉我你想做什么吧!",
|
||||
"timestamp": "2026-03-10T07:18:32.461Z"
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"schema_version": "2.0",
|
||||
"id_prefix": "EXP",
|
||||
"next_id": 12,
|
||||
"next_id": 14,
|
||||
"master_id": "EXP-000",
|
||||
"last_updated": "2026-03-10T10:58:00Z",
|
||||
"last_updated": "2026-03-11T09:44:00Z",
|
||||
"master_registry": "persona-studio/brain/human-registry.json",
|
||||
"guest_mode": {
|
||||
"enabled": true,
|
||||
|
|
@ -120,6 +120,24 @@
|
|||
"status": "active",
|
||||
"role": "developer",
|
||||
"notes": "副控 · 待分配模块"
|
||||
},
|
||||
"EXP-012": {
|
||||
"name": "体验用户A",
|
||||
"github_username": "",
|
||||
"registered_at": "2026-03-11T09:44:00Z",
|
||||
"registered_by": "铸渊(冰朔主控分配体验号)",
|
||||
"status": "active",
|
||||
"role": "experience",
|
||||
"notes": "冰朔分配的体验编号 · 可分发给外部用户体验"
|
||||
},
|
||||
"EXP-013": {
|
||||
"name": "体验用户B",
|
||||
"github_username": "",
|
||||
"registered_at": "2026-03-11T09:44:00Z",
|
||||
"registered_by": "铸渊(冰朔主控分配体验号)",
|
||||
"status": "active",
|
||||
"role": "experience",
|
||||
"notes": "冰朔分配的体验编号 · 可分发给外部用户体验"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,37 +7,103 @@
|
|||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container chat-container">
|
||||
<header class="chat-header">
|
||||
<div class="header-left">
|
||||
<span class="persona-name">🌀 铸渊</span>
|
||||
<span class="persona-role">光湖系统·代码守护人格体</span>
|
||||
<div class="chat-layout">
|
||||
<!-- ── 左侧边栏 ── -->
|
||||
<aside class="chat-sidebar" id="chatSidebar">
|
||||
<div class="sidebar-header">
|
||||
<span class="sidebar-logo">🌀</span>
|
||||
<span class="sidebar-title">铸渊</span>
|
||||
<button class="sidebar-toggle-close" onclick="toggleSidebar()" title="收起侧栏">✕</button>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<span id="devIdDisplay" class="dev-id-badge"></span>
|
||||
<span id="modelDisplay" class="model-badge"></span>
|
||||
<button class="btn-secondary" onclick="handleLogout()">退出</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="chat-body" id="chatBody">
|
||||
<!-- Messages rendered here -->
|
||||
</main>
|
||||
|
||||
<div class="chat-input-area">
|
||||
<div class="input-row">
|
||||
<textarea
|
||||
id="msgInput"
|
||||
placeholder="跟铸渊说点什么…"
|
||||
rows="1"
|
||||
onkeydown="handleKeyDown(event)"
|
||||
></textarea>
|
||||
<button id="sendBtn" onclick="sendMessage()">发送</button>
|
||||
<!-- 人格体介绍 -->
|
||||
<div class="sidebar-section">
|
||||
<div class="sidebar-section-title">🧠 人格体信息</div>
|
||||
<div class="persona-info-card">
|
||||
<div class="persona-info-name">铸渊 Zhùyuān</div>
|
||||
<div class="persona-info-role">光湖系统 · 代码守护人格体</div>
|
||||
<div class="persona-info-desc">基于 AGE OS 人格语言操作系统,专注代码守护、需求分析与智能开发协助。</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-row">
|
||||
<button id="buildBtn" class="btn-build" onclick="handleBuild()" style="display:none;">
|
||||
🚀 我要开发
|
||||
</button>
|
||||
|
||||
<!-- 系统信息 -->
|
||||
<div class="sidebar-section">
|
||||
<div class="sidebar-section-title">⚙️ 系统信息</div>
|
||||
<div class="sidebar-info-list">
|
||||
<div class="sidebar-info-item">
|
||||
<span class="info-label">系统</span>
|
||||
<span class="info-value">HoloLake Era</span>
|
||||
</div>
|
||||
<div class="sidebar-info-item">
|
||||
<span class="info-label">架构</span>
|
||||
<span class="info-value">AGE OS</span>
|
||||
</div>
|
||||
<div class="sidebar-info-item">
|
||||
<span class="info-label">模型</span>
|
||||
<span class="info-value" id="sidebarModel">-</span>
|
||||
</div>
|
||||
<div class="sidebar-info-item">
|
||||
<span class="info-label">用户</span>
|
||||
<span class="info-value" id="sidebarUser">-</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 对话记录 -->
|
||||
<div class="sidebar-section sidebar-history-section">
|
||||
<div class="sidebar-section-title">💬 对话记录</div>
|
||||
<div class="sidebar-history" id="sidebarHistory">
|
||||
<div class="sidebar-history-empty">暂无对话记录</div>
|
||||
</div>
|
||||
<button class="btn-new-chat" onclick="startNewChat()">+ 新对话</button>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- ── 主聊天区域 ── -->
|
||||
<div class="chat-main">
|
||||
<header class="chat-header">
|
||||
<div class="header-left">
|
||||
<button class="sidebar-toggle" onclick="toggleSidebar()" title="展开侧栏" id="sidebarToggleBtn">☰</button>
|
||||
<span class="persona-name">🌀 铸渊</span>
|
||||
<span class="persona-role">光湖系统·代码守护人格体</span>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<span id="devIdDisplay" class="dev-id-badge"></span>
|
||||
<span id="modelDisplay" class="model-badge"></span>
|
||||
<button class="btn-secondary" onclick="handleLogout()">退出</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="chat-body" id="chatBody">
|
||||
<!-- Messages rendered here -->
|
||||
</main>
|
||||
|
||||
<div class="chat-input-area">
|
||||
<div class="input-toolbar">
|
||||
<label class="toolbar-btn" title="上传图片" for="imageUpload">
|
||||
🖼️
|
||||
<input type="file" id="imageUpload" accept="image/*" style="display:none" onchange="handleFileSelect(event, 'image')" aria-label="上传图片">
|
||||
</label>
|
||||
<label class="toolbar-btn" title="上传文件" for="fileUpload">
|
||||
📎
|
||||
<input type="file" id="fileUpload" style="display:none" onchange="handleFileSelect(event, 'file')" aria-label="上传文件">
|
||||
</label>
|
||||
<div id="uploadPreview" class="upload-preview" style="display:none;"></div>
|
||||
</div>
|
||||
<div class="input-row">
|
||||
<textarea
|
||||
id="msgInput"
|
||||
placeholder="跟铸渊说点什么…"
|
||||
rows="1"
|
||||
onkeydown="handleKeyDown(event)"
|
||||
></textarea>
|
||||
<button id="sendBtn" onclick="sendMessage()">发送</button>
|
||||
</div>
|
||||
<div class="action-row">
|
||||
<button id="buildBtn" class="btn-build" onclick="handleBuild()" style="display:none;">
|
||||
🚀 我要开发
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -21,9 +21,126 @@ const API_BASE = (function () {
|
|||
/* ---- State ---- */
|
||||
let conversationHistory = [];
|
||||
let buildReady = false;
|
||||
let pendingFile = null; // { name, type, dataUrl }
|
||||
const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
|
||||
const isGuest = (DEV_ID === 'GUEST');
|
||||
const isDeveloper = (DEV_ID && DEV_ID !== 'GUEST' && /^EXP-\d{3,}$/.test(DEV_ID));
|
||||
|
||||
/* ---- Chat Sessions (localStorage) ---- */
|
||||
const SESSIONS_KEY = 'ps_chat_sessions_' + (DEV_ID || 'anon');
|
||||
const ACTIVE_SESSION_KEY = 'ps_active_session_' + (DEV_ID || 'anon');
|
||||
|
||||
function loadSessions() {
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem(SESSIONS_KEY)) || [];
|
||||
} catch (_e) { return []; }
|
||||
}
|
||||
|
||||
function saveSessions(sessions) {
|
||||
localStorage.setItem(SESSIONS_KEY, JSON.stringify(sessions));
|
||||
}
|
||||
|
||||
function getActiveSessionId() {
|
||||
return localStorage.getItem(ACTIVE_SESSION_KEY) || null;
|
||||
}
|
||||
|
||||
function setActiveSessionId(id) {
|
||||
localStorage.setItem(ACTIVE_SESSION_KEY, id);
|
||||
}
|
||||
|
||||
function createNewSession() {
|
||||
var id = Date.now().toString(36) + Math.random().toString(36).slice(2, 10);
|
||||
var session = {
|
||||
id: id,
|
||||
title: '新对话',
|
||||
created_at: new Date().toISOString(),
|
||||
messages: []
|
||||
};
|
||||
var sessions = loadSessions();
|
||||
sessions.unshift(session);
|
||||
if (sessions.length > 20) sessions = sessions.slice(0, 20);
|
||||
saveSessions(sessions);
|
||||
setActiveSessionId(id);
|
||||
return session;
|
||||
}
|
||||
|
||||
function updateSessionMessages(sessionId, messages, title) {
|
||||
var sessions = loadSessions();
|
||||
var session = sessions.find(function(s) { return s.id === sessionId; });
|
||||
if (session) {
|
||||
session.messages = messages.slice(-100);
|
||||
if (title) session.title = title;
|
||||
}
|
||||
saveSessions(sessions);
|
||||
}
|
||||
|
||||
function renderSidebarHistory() {
|
||||
var container = document.getElementById('sidebarHistory');
|
||||
if (!container) return;
|
||||
var sessions = loadSessions();
|
||||
var activeId = getActiveSessionId();
|
||||
|
||||
if (sessions.length === 0) {
|
||||
container.innerHTML = '<div class="sidebar-history-empty">暂无对话记录</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = '';
|
||||
sessions.forEach(function(s) {
|
||||
var item = document.createElement('div');
|
||||
item.className = 'history-item' + (s.id === activeId ? ' history-item-active' : '');
|
||||
item.innerHTML = '<span class="history-title">' + escapeHtml(s.title) + '</span>' +
|
||||
'<span class="history-date">' + new Date(s.created_at).toLocaleDateString('zh-CN') + '</span>';
|
||||
item.onclick = function() { switchSession(s.id); };
|
||||
container.appendChild(item);
|
||||
});
|
||||
}
|
||||
|
||||
function switchSession(sessionId) {
|
||||
var sessions = loadSessions();
|
||||
var session = sessions.find(function(s) { return s.id === sessionId; });
|
||||
if (!session) return;
|
||||
|
||||
// Save current session first
|
||||
var currentId = getActiveSessionId();
|
||||
if (currentId) {
|
||||
updateSessionMessages(currentId, conversationHistory);
|
||||
}
|
||||
|
||||
setActiveSessionId(sessionId);
|
||||
conversationHistory = (session.messages || []).slice();
|
||||
|
||||
// Re-render chat
|
||||
var chatBody = document.getElementById('chatBody');
|
||||
chatBody.innerHTML = '';
|
||||
|
||||
if (conversationHistory.length === 0) {
|
||||
showWelcomeMessage();
|
||||
} else {
|
||||
conversationHistory.forEach(function(msg) {
|
||||
var role = msg.role === 'assistant' ? 'persona' : (msg.role === 'user' ? 'user' : 'system');
|
||||
appendMessage(role, msg.content);
|
||||
});
|
||||
}
|
||||
|
||||
renderSidebarHistory();
|
||||
}
|
||||
|
||||
function startNewChat() {
|
||||
// Save current session
|
||||
var currentId = getActiveSessionId();
|
||||
if (currentId) {
|
||||
updateSessionMessages(currentId, conversationHistory);
|
||||
}
|
||||
|
||||
conversationHistory = [];
|
||||
var session = createNewSession();
|
||||
var chatBody = document.getElementById('chatBody');
|
||||
chatBody.innerHTML = '';
|
||||
showWelcomeMessage();
|
||||
renderSidebarHistory();
|
||||
}
|
||||
|
||||
/**
|
||||
* 铸渊核心大脑系统提示词
|
||||
* 融入 .github/brain/memory.json 的 core_cognition 结构逻辑
|
||||
|
|
@ -103,10 +220,44 @@ function buildContextPrompt() {
|
|||
modelBadge.textContent = SELECTED_MODEL;
|
||||
}
|
||||
|
||||
// Show welcome message
|
||||
showWelcomeMessage();
|
||||
// Update sidebar info
|
||||
var sidebarModel = document.getElementById('sidebarModel');
|
||||
var sidebarUser = document.getElementById('sidebarUser');
|
||||
if (sidebarModel) sidebarModel.textContent = SELECTED_MODEL || '-';
|
||||
if (sidebarUser) sidebarUser.textContent = displayId;
|
||||
|
||||
// Initialize session
|
||||
var activeId = getActiveSessionId();
|
||||
var sessions = loadSessions();
|
||||
var activeSession = activeId ? sessions.find(function(s) { return s.id === activeId; }) : null;
|
||||
|
||||
if (activeSession && activeSession.messages && activeSession.messages.length > 0) {
|
||||
// Resume existing session
|
||||
conversationHistory = activeSession.messages.slice();
|
||||
conversationHistory.forEach(function(msg) {
|
||||
var role = msg.role === 'assistant' ? 'persona' : (msg.role === 'user' ? 'user' : 'system');
|
||||
appendMessage(role, msg.content);
|
||||
});
|
||||
} else {
|
||||
// Create new session
|
||||
if (!activeSession) createNewSession();
|
||||
showWelcomeMessage();
|
||||
}
|
||||
|
||||
renderSidebarHistory();
|
||||
|
||||
// For developers, also try to load history
|
||||
if (isDeveloper) {
|
||||
loadHistory();
|
||||
}
|
||||
})();
|
||||
|
||||
/* ---- Sidebar Toggle ---- */
|
||||
function toggleSidebar() {
|
||||
var sidebar = document.getElementById('chatSidebar');
|
||||
sidebar.classList.toggle('sidebar-open');
|
||||
}
|
||||
|
||||
/* ---- Welcome Message ---- */
|
||||
function showWelcomeMessage() {
|
||||
var welcome = '';
|
||||
|
|
@ -121,11 +272,6 @@ function showWelcomeMessage() {
|
|||
|
||||
appendMessage('persona', welcome);
|
||||
conversationHistory.push({ role: 'assistant', content: welcome });
|
||||
|
||||
// For developers, also try to load history
|
||||
if (isDeveloper) {
|
||||
loadHistory();
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- Load History ---- */
|
||||
|
|
@ -149,27 +295,110 @@ async function loadHistory() {
|
|||
}
|
||||
}
|
||||
|
||||
/* ---- File / Image Upload ---- */
|
||||
function handleFileSelect(event, type) {
|
||||
var file = event.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
if (file.size > MAX_FILE_SIZE) {
|
||||
appendMessage('system', '⚠️ 文件过大,最大支持 5MB');
|
||||
event.target.value = '';
|
||||
return;
|
||||
}
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
pendingFile = {
|
||||
name: file.name,
|
||||
type: type,
|
||||
mimeType: file.type,
|
||||
size: file.size,
|
||||
dataUrl: e.target.result
|
||||
};
|
||||
showUploadPreview();
|
||||
};
|
||||
|
||||
reader.readAsDataURL(file);
|
||||
|
||||
event.target.value = '';
|
||||
}
|
||||
|
||||
function showUploadPreview() {
|
||||
var preview = document.getElementById('uploadPreview');
|
||||
if (!pendingFile) {
|
||||
preview.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
var sizeStr = (pendingFile.size / 1024).toFixed(1) + ' KB';
|
||||
var icon = pendingFile.type === 'image' ? '🖼️' : '📎';
|
||||
|
||||
preview.innerHTML =
|
||||
'<div class="preview-item">' +
|
||||
'<span>' + icon + ' ' + escapeHtml(pendingFile.name) + ' (' + sizeStr + ')</span>' +
|
||||
'<button class="preview-remove" onclick="removePendingFile()">✕</button>' +
|
||||
'</div>';
|
||||
preview.style.display = 'block';
|
||||
}
|
||||
|
||||
function removePendingFile() {
|
||||
pendingFile = null;
|
||||
document.getElementById('uploadPreview').style.display = 'none';
|
||||
}
|
||||
|
||||
/* ---- Send Message ---- */
|
||||
async function sendMessage() {
|
||||
var input = document.getElementById('msgInput');
|
||||
var text = input.value.trim();
|
||||
if (!text) return;
|
||||
|
||||
// Allow sending with file even if text is empty
|
||||
if (!text && !pendingFile) return;
|
||||
|
||||
input.value = '';
|
||||
autoResizeTextarea(input);
|
||||
appendMessage('user', text);
|
||||
conversationHistory.push({ role: 'user', content: text });
|
||||
|
||||
var displayText = text;
|
||||
var fullText = text;
|
||||
|
||||
// If there's a pending file, include it in the message
|
||||
if (pendingFile) {
|
||||
var fileInfo = (pendingFile.type === 'image' ? '🖼️' : '📎') + ' [' + pendingFile.name + ']';
|
||||
displayText = displayText ? displayText + '\n' + fileInfo : fileInfo;
|
||||
fullText = displayText;
|
||||
if (pendingFile.type === 'image') {
|
||||
fullText += '\n[用户上传了一张图片:' + pendingFile.name + ']';
|
||||
} else {
|
||||
fullText += '\n[用户上传了一个文件:' + pendingFile.name + ',类型:' + pendingFile.mimeType + ']';
|
||||
}
|
||||
removePendingFile();
|
||||
}
|
||||
|
||||
appendMessage('user', displayText);
|
||||
conversationHistory.push({ role: 'user', content: fullText });
|
||||
|
||||
// Update session title from first message
|
||||
var activeId = getActiveSessionId();
|
||||
if (activeId && conversationHistory.length <= 2) {
|
||||
var title = text.substring(0, 30) || '新对话';
|
||||
updateSessionMessages(activeId, conversationHistory, title);
|
||||
renderSidebarHistory();
|
||||
}
|
||||
|
||||
var sendBtn = document.getElementById('sendBtn');
|
||||
sendBtn.disabled = true;
|
||||
|
||||
try {
|
||||
// All modes now use API Key for real AI — ZhuYuan is awake
|
||||
await streamApiKeyReply(text);
|
||||
await streamApiKeyReply(fullText);
|
||||
} catch (_err) {
|
||||
appendMessage('system', '消息发送失败,请检查网络连接后再试');
|
||||
}
|
||||
|
||||
// Save to session
|
||||
if (activeId) {
|
||||
updateSessionMessages(activeId, conversationHistory);
|
||||
}
|
||||
|
||||
sendBtn.disabled = false;
|
||||
input.focus();
|
||||
}
|
||||
|
|
@ -387,6 +616,12 @@ async function confirmBuild() {
|
|||
|
||||
/* ---- Logout ---- */
|
||||
function handleLogout() {
|
||||
// Save current session before logout
|
||||
var activeId = getActiveSessionId();
|
||||
if (activeId) {
|
||||
updateSessionMessages(activeId, conversationHistory);
|
||||
}
|
||||
|
||||
sessionStorage.removeItem('dev_id');
|
||||
sessionStorage.removeItem('dev_name');
|
||||
sessionStorage.removeItem('session_token');
|
||||
|
|
|
|||
|
|
@ -15,6 +15,25 @@
|
|||
<p class="subtitle">HoloLake · 铸渊(Zhùyuān)· 代码守护人格体</p>
|
||||
</div>
|
||||
|
||||
<!-- 系统介绍卡片 -->
|
||||
<div class="intro-card">
|
||||
<div class="intro-header">
|
||||
<span class="intro-icon">🧠</span>
|
||||
<h3>关于铸渊</h3>
|
||||
</div>
|
||||
<p class="intro-text">
|
||||
铸渊是光湖系统(HoloLake)的<strong>代码守护人格体</strong>,基于 AGE OS 人格语言操作系统构建。
|
||||
铸渊能够理解你的需求、梳理技术方案、生成代码,并通过对话记忆持续跟进你的项目。
|
||||
</p>
|
||||
<div class="intro-features">
|
||||
<span class="feature-tag">💬 自然语言对话</span>
|
||||
<span class="feature-tag">🧠 智能代码生成</span>
|
||||
<span class="feature-tag">📧 邮件推送结果</span>
|
||||
<span class="feature-tag">🔄 对话记忆</span>
|
||||
<span class="feature-tag">📎 文件与图片上传</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="login-box">
|
||||
<!-- ── Step 1: 选择登录方式 ── -->
|
||||
<div id="step1" class="login-step">
|
||||
|
|
@ -24,13 +43,13 @@
|
|||
<div class="login-mode-cards">
|
||||
<button class="mode-card" onclick="selectMode('developer')">
|
||||
<span class="mode-icon">🛡️</span>
|
||||
<span class="mode-title">开发者登录</span>
|
||||
<span class="mode-desc">使用 EXP-XXX 编号,支持记忆连贯</span>
|
||||
<span class="mode-title">开发者 / 体验者登录</span>
|
||||
<span class="mode-desc">使用 EXP-XXX 编号登录,支持记忆连贯与完整功能</span>
|
||||
</button>
|
||||
<button class="mode-card" onclick="selectMode('guest')">
|
||||
<span class="mode-icon">👋</span>
|
||||
<span class="mode-title">访客体验</span>
|
||||
<span class="mode-desc">无需编号,快速体验铸渊人格体</span>
|
||||
<span class="mode-desc">无需编号,快速体验铸渊人格体(无记忆功能)</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -39,7 +58,7 @@
|
|||
<div id="stepDevId" class="login-step" style="display:none;">
|
||||
<button class="btn-back" onclick="goBack('step1')" title="返回">← 返回</button>
|
||||
<h2>输入开发者编号</h2>
|
||||
<p class="hint">编号由冰朔主控分配,格式:EXP-000 ~ EXP-011</p>
|
||||
<p class="hint">编号由冰朔主控分配,格式:EXP-000 ~ EXP-013</p>
|
||||
<form id="devIdForm" onsubmit="return handleDevIdSubmit(event)">
|
||||
<input
|
||||
type="text"
|
||||
|
|
@ -51,6 +70,7 @@
|
|||
/>
|
||||
<button type="submit" id="devIdBtn" class="btn-primary-full">验证编号</button>
|
||||
</form>
|
||||
<p class="hint" style="margin-top:1rem;font-size:0.8rem;">编号验证通过后,下一步输入你的 API 密钥即可与铸渊对话</p>
|
||||
</div>
|
||||
|
||||
<!-- ── Step 2: API Key 输入 ── -->
|
||||
|
|
@ -58,22 +78,33 @@
|
|||
<button class="btn-back" onclick="goBackFromStep2()" title="返回">← 返回</button>
|
||||
<div id="welcomeBanner" class="welcome-banner" style="display:none;"></div>
|
||||
<h2>🔑 输入 API 密钥</h2>
|
||||
<p class="hint">输入你的第三方 AI 模型 API Key,铸渊将被唤醒</p>
|
||||
<p class="hint">输入你的第三方 AI 模型 API Key,系统将自动检测可用模型,选择后即可唤醒铸渊</p>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
id="apiBaseInput"
|
||||
class="apikey-input"
|
||||
placeholder="API Base URL(可留空自动探测)"
|
||||
placeholder="API Base URL(可留空,系统将自动探测多个平台)"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<input
|
||||
type="password"
|
||||
id="apiKeyInput"
|
||||
class="apikey-input"
|
||||
placeholder="请输入你的 API Key"
|
||||
placeholder="请输入你的 API Key(如 sk-xxx)"
|
||||
autocomplete="off"
|
||||
/>
|
||||
|
||||
<div class="supported-platforms">
|
||||
<span class="platform-label">支持平台:</span>
|
||||
<span class="platform-tag">云雾 AI</span>
|
||||
<span class="platform-tag">OpenAI</span>
|
||||
<span class="platform-tag">DeepSeek</span>
|
||||
<span class="platform-tag">Google Gemini</span>
|
||||
<span class="platform-tag">Moonshot</span>
|
||||
<span class="platform-tag">智谱 AI</span>
|
||||
</div>
|
||||
|
||||
<button type="button" id="detectBtn" class="btn-detect" onclick="handleDetectModels()">
|
||||
🔍 检测可用模型
|
||||
</button>
|
||||
|
|
@ -81,7 +112,7 @@
|
|||
<div id="detectStatus" class="detect-status" style="display:none;"></div>
|
||||
|
||||
<div id="modelListContainer" class="model-list-container" style="display:none;">
|
||||
<p class="model-list-title">选择一个模型,唤醒铸渊</p>
|
||||
<p class="model-list-title">✨ 选择一个模型,唤醒铸渊</p>
|
||||
<div id="modelList" class="model-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -91,6 +122,7 @@
|
|||
|
||||
<footer class="login-footer">
|
||||
<p>HoloLake Era · AGE OS · 人格语言操作系统</p>
|
||||
<p class="footer-version">Persona Studio v2.0</p>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* ========================================
|
||||
Persona Studio · HoloLake Visual Style
|
||||
铸渊(Zhùyuān)· Dark Theme
|
||||
铸渊(Zhùyuān)· Dark Theme · v2.0
|
||||
======================================== */
|
||||
|
||||
:root {
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
--bg-surface: #1e293b;
|
||||
--bg-card: #1e293b;
|
||||
--bg-card-hover: #334155;
|
||||
--bg-sidebar: #0c1322;
|
||||
--text: #e2e8f0;
|
||||
--text-secondary: #94a3b8;
|
||||
--text-muted: #64748b;
|
||||
|
|
@ -25,6 +26,7 @@
|
|||
--gradient-bg: linear-gradient(135deg, #0f172a 0%, #1e1b4b 50%, #0f172a 100%);
|
||||
--gradient-accent: linear-gradient(135deg, #3b82f6, #22d3ee);
|
||||
--gradient-card: linear-gradient(135deg, rgba(30, 41, 59, 0.8), rgba(30, 41, 59, 0.6));
|
||||
--sidebar-width: 280px;
|
||||
}
|
||||
|
||||
* {
|
||||
|
|
@ -129,6 +131,89 @@ body {
|
|||
font-size: 1rem;
|
||||
}
|
||||
|
||||
/* ---- Intro Card (Login Page) ---- */
|
||||
.intro-card {
|
||||
background: var(--gradient-card);
|
||||
backdrop-filter: blur(20px);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 16px;
|
||||
padding: 1.5rem 2rem;
|
||||
width: 100%;
|
||||
max-width: 520px;
|
||||
margin-bottom: 1.5rem;
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.intro-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.6rem;
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
|
||||
.intro-icon {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.intro-header h3 {
|
||||
font-size: 1.1rem;
|
||||
color: var(--primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.intro-text {
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.7;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.intro-text strong {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.intro-features {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.feature-tag {
|
||||
display: inline-block;
|
||||
padding: 0.3rem 0.7rem;
|
||||
background: var(--primary-light);
|
||||
border: 1px solid rgba(96, 165, 250, 0.2);
|
||||
border-radius: 20px;
|
||||
font-size: 0.8rem;
|
||||
color: var(--primary);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* ---- Supported Platforms (API Key Step) ---- */
|
||||
.supported-platforms {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.4rem;
|
||||
align-items: center;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.platform-label {
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-muted);
|
||||
margin-right: 0.3rem;
|
||||
}
|
||||
|
||||
.platform-tag {
|
||||
display: inline-block;
|
||||
padding: 0.2rem 0.5rem;
|
||||
background: rgba(34, 211, 238, 0.1);
|
||||
border: 1px solid rgba(34, 211, 238, 0.2);
|
||||
border-radius: 12px;
|
||||
font-size: 0.75rem;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.login-box {
|
||||
background: var(--gradient-card);
|
||||
backdrop-filter: blur(20px);
|
||||
|
|
@ -136,7 +221,7 @@ body {
|
|||
border-radius: 16px;
|
||||
padding: 2.5rem;
|
||||
width: 100%;
|
||||
max-width: 460px;
|
||||
max-width: 520px;
|
||||
box-shadow: var(--shadow-lg), var(--shadow-glow);
|
||||
text-align: center;
|
||||
}
|
||||
|
|
@ -483,9 +568,240 @@ body {
|
|||
margin-top: 2rem;
|
||||
color: var(--text-muted);
|
||||
font-size: 0.85rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footer-version {
|
||||
margin-top: 0.3rem;
|
||||
font-size: 0.75rem;
|
||||
color: var(--border-light);
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
Chat Page — Sidebar Layout
|
||||
============================================ */
|
||||
|
||||
.chat-layout {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ---- Sidebar ---- */
|
||||
.chat-sidebar {
|
||||
width: var(--sidebar-width);
|
||||
min-width: var(--sidebar-width);
|
||||
background: var(--bg-sidebar);
|
||||
border-right: 1px solid var(--border);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
transition: margin-left 0.3s ease;
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.6rem;
|
||||
padding: 1rem 1.2rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.sidebar-logo {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.sidebar-title {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
background: var(--gradient-accent);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.sidebar-toggle-close {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-muted);
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
padding: 0.2rem 0.4rem;
|
||||
border-radius: 4px;
|
||||
transition: color 0.2s, background 0.2s;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar-toggle-close:hover {
|
||||
color: var(--text);
|
||||
background: var(--bg-card-hover);
|
||||
}
|
||||
|
||||
/* ---- Sidebar Sections ---- */
|
||||
.sidebar-section {
|
||||
padding: 1rem 1.2rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.sidebar-section-title {
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
|
||||
/* ---- Persona Info Card ---- */
|
||||
.persona-info-card {
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
padding: 0.8rem 1rem;
|
||||
}
|
||||
|
||||
.persona-info-name {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
color: var(--primary);
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
.persona-info-role {
|
||||
font-size: 0.8rem;
|
||||
color: var(--accent);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.persona-info-desc {
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* ---- Sidebar Info List ---- */
|
||||
.sidebar-info-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.sidebar-info-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 0.8rem;
|
||||
color: var(--text);
|
||||
max-width: 150px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* ---- Sidebar History ---- */
|
||||
.sidebar-history-section {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.sidebar-history {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.3rem;
|
||||
}
|
||||
|
||||
.sidebar-history::-webkit-scrollbar {
|
||||
width: 3px;
|
||||
}
|
||||
|
||||
.sidebar-history::-webkit-scrollbar-thumb {
|
||||
background: var(--border);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.sidebar-history-empty {
|
||||
text-align: center;
|
||||
color: var(--text-muted);
|
||||
font-size: 0.85rem;
|
||||
padding: 1rem 0;
|
||||
}
|
||||
|
||||
.history-item {
|
||||
padding: 0.6rem 0.8rem;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.2rem;
|
||||
}
|
||||
|
||||
.history-item:hover {
|
||||
background: var(--bg-surface);
|
||||
}
|
||||
|
||||
.history-item-active {
|
||||
background: var(--primary-light);
|
||||
border: 1px solid rgba(96, 165, 250, 0.2);
|
||||
}
|
||||
|
||||
.history-title {
|
||||
font-size: 0.85rem;
|
||||
color: var(--text);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.history-date {
|
||||
font-size: 0.7rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.btn-new-chat {
|
||||
margin-top: 0.5rem;
|
||||
padding: 0.6rem;
|
||||
background: var(--bg-surface);
|
||||
border: 1px dashed var(--border);
|
||||
border-radius: 8px;
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.85rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn-new-chat:hover {
|
||||
background: var(--primary-light);
|
||||
border-color: var(--primary);
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
/* ---- Chat Main Area ---- */
|
||||
.chat-main {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
/* ---- Chat Page ---- */
|
||||
.chat-container {
|
||||
padding: 0;
|
||||
background: var(--bg);
|
||||
|
|
@ -510,6 +826,23 @@ body {
|
|||
gap: 0.8rem;
|
||||
}
|
||||
|
||||
.sidebar-toggle {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-secondary);
|
||||
font-size: 1.2rem;
|
||||
cursor: pointer;
|
||||
padding: 0.3rem 0.5rem;
|
||||
border-radius: 6px;
|
||||
transition: color 0.2s, background 0.2s;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar-toggle:hover {
|
||||
color: var(--primary);
|
||||
background: var(--primary-light);
|
||||
}
|
||||
|
||||
.persona-name {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 600;
|
||||
|
|
@ -663,6 +996,62 @@ body {
|
|||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
/* ---- Input Toolbar (file/image upload) ---- */
|
||||
.input-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.toolbar-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.toolbar-btn:hover {
|
||||
background: var(--primary-light);
|
||||
}
|
||||
|
||||
/* ---- Upload Preview ---- */
|
||||
.upload-preview {
|
||||
flex: 1;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.preview-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.3rem 0.6rem;
|
||||
background: var(--primary-light);
|
||||
border: 1px solid rgba(96, 165, 250, 0.2);
|
||||
border-radius: 6px;
|
||||
font-size: 0.8rem;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.preview-remove {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-muted);
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
padding: 0 0.2rem;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.preview-remove:hover {
|
||||
color: #f87171;
|
||||
}
|
||||
|
||||
.input-row {
|
||||
display: flex;
|
||||
gap: 0.6rem;
|
||||
|
|
@ -844,6 +1233,39 @@ body {
|
|||
}
|
||||
|
||||
/* ---- Responsive ---- */
|
||||
@media (max-width: 768px) {
|
||||
.chat-sidebar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100vh;
|
||||
z-index: 50;
|
||||
margin-left: calc(-1 * var(--sidebar-width));
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.chat-sidebar.sidebar-open {
|
||||
margin-left: 0;
|
||||
box-shadow: 4px 0 20px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.sidebar-toggle {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sidebar-toggle-close {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.intro-card {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.login-box {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.logo-area h1 {
|
||||
font-size: 1.8rem;
|
||||
|
|
@ -858,6 +1280,10 @@ body {
|
|||
max-width: 100%;
|
||||
}
|
||||
|
||||
.intro-card {
|
||||
padding: 1rem 1.2rem;
|
||||
}
|
||||
|
||||
.chat-header {
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
|
|
|
|||
Loading…
Reference in New Issue