chore: rebuild release package

This commit is contained in:
shiyue
2026-07-18 10:14:38 +08:00
parent fa15b54469
commit a76de06c47
112 changed files with 8858 additions and 399 deletions

View File

@@ -161,6 +161,19 @@
desc: '炭黑底配低饱和玫瑰色,暗色里保留一点温度。',
swatches: ['#151112', '#2a2022', '#e68193', '#67c587'],
},
{
value: 'gilded',
label: 'Warframe Wasteland',
desc: '暖象牙与焦土铜铺开 Orokin 荒野档案,冷青能量只作细节点缀。',
swatches: ['#fbf3e5', '#efe4d2', '#7a3f20', '#147276'],
hidden: true,
},
{
value: 'wasteland',
label: '暗金荒野',
desc: '黑铁面板悬浮于荒野骑士主视觉之上,以旧金、余烬与状态绿标记工作层级。',
swatches: ['#050707', '#171511', '#c49a5a', '#6f783f'],
},
];
// --- State ---
@@ -310,9 +323,39 @@
window.addEventListener('resize', setVH);
window.addEventListener('orientationchange', () => setTimeout(setVH, 100));
function buildWelcomeMarkup(agent) {
const label = AGENT_LABELS[agent] || AGENT_LABELS.claude;
return `<div class="welcome-msg"><div class="welcome-icon">✿</div><h3>欢迎使用 CC-Web</h3><p>开始与 ${label} 对话</p></div>`;
function getWelcomeProjectName(cwd = currentCwd) {
return getPathLeaf(cwd) || '当前项目';
}
function getWelcomeCopy(cwd = currentCwd) {
return `你正在操作 ${getWelcomeProjectName(cwd)}`;
}
function syncWelcomeCopy(cwd = currentCwd) {
const copy = messagesDiv.querySelector('[data-welcome-project-copy]');
if (copy) copy.textContent = getWelcomeCopy(cwd);
}
function buildWelcomeMarkup(cwd = currentCwd) {
return `<div class="welcome-msg">
<section class="warframe-hero" aria-labelledby="warframe-welcome-title">
<div class="warframe-hero-art" aria-hidden="true">
<img class="warframe-hero-image" src="assets/themes/gilded-wasteland.png" alt="" draggable="false" decoding="async">
<span class="warframe-hero-orbit"></span>
<span class="warframe-hero-emblem"></span>
</div>
<div class="wasteland-welcome-art" aria-hidden="true">
<div class="wasteland-welcome-surface"></div>
<img class="wasteland-welcome-frame" src="assets/themes/wasteland/frames/welcome-card.png" alt="" draggable="false" decoding="async">
</div>
<div class="welcome-icon">✿</div>
<div class="welcome-copy">
<div class="welcome-kicker">OROKIN FIELD ARCHIVE · CC-WEB</div>
<h3 id="warframe-welcome-title" data-welcome-project-copy>${escapeHtml(getWelcomeCopy(cwd))}</h3>
<p>本次你要构建什么?</p>
</div>
</section>
</div>`;
}
function normalizeAgent(agent) {
@@ -526,6 +569,8 @@
const text = document.createElement('div');
text.className = 'note-text';
text.textContent = message.text;
const attachmentSummary = renderAttachmentPreviews(message.attachments);
if (attachmentSummary) text.insertAdjacentHTML('beforeend', attachmentSummary);
const actions = document.createElement('div');
actions.className = 'note-actions';
@@ -738,16 +783,21 @@
return true;
}
function getQueuedMessageValidationError(content) {
function getQueuedMessageValidationError(content, attachments = []) {
const text = String(content || '').trim();
const attachmentList = Array.isArray(attachments) ? attachments : [];
if (!supportsQueuedSend()) return '排队发送仅支持 Codex App。';
if (!String(content || '').trim()) return '排队内容不能为空。';
if (String(content || '').trim().startsWith('/')) return '排队发送暂不支持 slash 指令。';
if (!text && attachmentList.length === 0) return '排队内容不能为空。';
if (text.startsWith('/')) return '排队发送暂不支持 slash 指令。';
return '';
}
function addQueuedMessage(text, options = {}) {
const content = String(text || '').trim();
const validationError = getQueuedMessageValidationError(content);
const attachments = Array.isArray(options.attachments)
? options.attachments.map((attachment) => ({ ...attachment }))
: [];
const validationError = getQueuedMessageValidationError(content, attachments);
if (validationError) {
appendError(validationError);
return false;
@@ -755,6 +805,7 @@
const message = {
id: `queued-${Date.now().toString(36)}-${++queuedMessageSeq}`,
text: content,
attachments,
createdAt: Date.now(),
};
getCurrentQueue(true).push(message);
@@ -765,15 +816,14 @@
function queueMessageFromInput() {
const text = msgInput.value.trim();
if (!text || isBlockingSessionLoad()) return;
if ((!text && pendingAttachments.length === 0) || isBlockingSessionLoad()) return;
hideCmdMenu();
hideOptionPicker();
if (pendingAttachments.length > 0) {
appendError('排队发送暂不支持图片附件,请先移除图片。');
return;
}
if (addQueuedMessage(text)) {
const attachments = pendingAttachments.map((attachment) => ({ ...attachment }));
if (addQueuedMessage(text, { attachments })) {
msgInput.value = '';
pendingAttachments = [];
renderPendingAttachments();
autoResize();
}
}
@@ -782,7 +832,7 @@
const found = findPendingNote(noteId);
if (!found) return;
const text = String(found.note.text || '').trim();
const validationError = getQueuedMessageValidationError(text);
const validationError = getQueuedMessageValidationError(text, []);
if (validationError) {
appendError(validationError);
return;
@@ -809,7 +859,10 @@
}
function removeQueuedMessage(queueId) {
if (!dropQueuedMessage(queueId)) return;
const message = dropQueuedMessage(queueId);
if (!message) return;
(Array.isArray(message.attachments) ? message.attachments : [])
.forEach((attachment) => deleteUploadedAttachment(attachment?.id));
renderPendingNotes({ scroll: false });
}
@@ -917,7 +970,7 @@
const save = () => {
const next = editor.value.trim();
const validationError = getQueuedMessageValidationError(next);
const validationError = getQueuedMessageValidationError(next, found.message.attachments);
if (validationError) {
appendError(validationError);
editor.focus();
@@ -980,15 +1033,18 @@
renderPendingNotes({ scroll: false });
const text = String(message?.text || '').trim();
if (!text) {
const attachments = Array.isArray(message?.attachments)
? message.attachments.map((attachment) => ({ ...attachment }))
: [];
if (!text && attachments.length === 0) {
scheduleQueuedMessageDrain();
return;
}
submitUserMessage(text);
submitUserMessage(text, attachments);
}
function normalizeTheme(theme) {
return THEME_OPTIONS.some((item) => item.value === theme) ? theme : 'washi';
return THEME_OPTIONS.some((item) => item.value === theme && !item.hidden) ? theme : 'washi';
}
function getThemeOption(theme) {
@@ -1034,7 +1090,7 @@
return `
${showSectionTitle ? '<div class="settings-section-title">界面主题</div>' : ''}
<div class="theme-grid">
${THEME_OPTIONS.map((theme) => `
${THEME_OPTIONS.filter((theme) => !theme.hidden).map((theme) => `
<button class="theme-card${theme.value === currentTheme ? ' active' : ''}" type="button" data-theme-value="${theme.value}">
<div class="theme-card-preview">
${theme.swatches.map((color) => `<span class="theme-card-swatch" style="background:${color}"></span>`).join('')}
@@ -4099,6 +4155,7 @@
}
chatCwd.disabled = !currentCwd;
chatCwd.hidden = !currentCwd;
syncWelcomeCopy(currentCwd);
}
function currentSessionWaitState() {
@@ -4212,7 +4269,7 @@
updateSessionIdBadge();
updateCwdBadge();
updateReloadMcpButtonUI();
messagesDiv.innerHTML = buildWelcomeMarkup(currentAgent);
messagesDiv.innerHTML = buildWelcomeMarkup(currentCwd);
setStatsDisplay(null);
renderPendingAttachments();
renderPendingNotes({ scroll: false });
@@ -6541,6 +6598,48 @@
return title.length > 36 ? `${title.slice(0, 36)}` : title;
}
const COLLAB_AGENT_AUTO_TITLE_TOKEN_LABELS = {
plan: '计划',
review: '审查',
reviewer: '审查',
backend: '后端',
frontend: '前端',
state: '状态',
implement: '实现',
implementation: '实现',
check: '检查',
test: '测试',
research: '调研',
design: '设计',
release: '发布',
runtime: '运行时',
audit: '审计',
fix: '修复',
document: '文档',
docs: '文档',
quality: '质量',
trellis: 'Trellis',
};
function joinCollabAgentAutoTitleParts(parts) {
return parts.reduce((title, part) => {
if (!title) return part;
const shouldJoinDirectly = /[\u4e00-\u9fff]$/.test(title) && /^[\u4e00-\u9fff]/.test(part);
return shouldJoinDirectly ? `${title}${part}` : `${title} ${part}`;
}, '');
}
function readableCollabAgentAutoTitle(value) {
const text = cleanCollabAgentText(value);
if (!/^[a-z0-9]+(?:[_-][a-z0-9]+)+$/.test(text)) return text;
const parts = text.split(/[_-]+/).map((token) => {
const mapped = COLLAB_AGENT_AUTO_TITLE_TOKEN_LABELS[token];
if (mapped) return mapped;
return token ? `${token.charAt(0).toUpperCase()}${token.slice(1)}` : '';
}).filter(Boolean);
return joinCollabAgentAutoTitleParts(parts);
}
function collabAgentTaskDescription(state = {}, fallbackPrompt = '') {
return cleanCollabAgentText(
state.taskDescription
@@ -6556,6 +6655,7 @@
function pickCollabAgentTitle(state, id, index) {
const taskDescription = cleanCollabAgentText(state?.taskDescription || state?.prompt || '');
const canReadAutomaticTitle = state?.hasReadableSourceTitle !== false;
const titleCandidates = [
state.label,
state.title,
@@ -6564,7 +6664,9 @@
];
for (const value of titleCandidates) {
const candidate = cleanCollabAgentText(value);
if (candidate && !isGenericCollabAgentLabel(candidate, id)) return candidate;
if (candidate && !isGenericCollabAgentLabel(candidate, id)) {
return canReadAutomaticTitle ? readableCollabAgentAutoTitle(candidate) : candidate;
}
}
const promptTitle = collabAgentTitleFromPrompt(taskDescription);
if (promptTitle) return promptTitle;
@@ -6589,6 +6691,7 @@
const incomingHasReadableSourceTitle = incomingState.hasReadableSourceTitle == null
? hasReadableCollabAgentTitle(incomingState, id)
: incomingState.hasReadableSourceTitle === true;
const hasReadableSourceTitle = incomingHasReadableSourceTitle || previousState.hasReadableSourceTitle === true;
if (incomingHasReadableSourceTitle) {
nextState.label = pickCollabAgentTitle(incomingState, id, index);
} else {
@@ -6599,6 +6702,7 @@
}
return {
...nextState,
hasReadableSourceTitle,
label: pickCollabAgentTitle(nextState, id, index),
taskDescription,
};
@@ -6727,7 +6831,10 @@
return Object.entries(states).map(([id, value], index) => {
const state = value && typeof value === 'object' ? value : { status: value };
const taskDescription = collabAgentTaskDescription(state, data?.prompt || '');
const label = pickCollabAgentTitle({ ...state, taskDescription }, id, index);
const hasReadableSourceTitle = state.hasReadableSourceTitle == null
? hasReadableCollabAgentTitle(state, id)
: state.hasReadableSourceTitle === true;
const label = pickCollabAgentTitle({ ...state, taskDescription, hasReadableSourceTitle }, id, index);
const role = cleanCollabAgentText(state.role || state.agent || state.agentType || '');
let status = cleanCollabAgentText(state.status || state.state || 'pending') || 'pending';
if (state.closedAt && collabStateTone(status) !== 'closed') status = 'closed';
@@ -6742,7 +6849,7 @@
status,
detail,
taskDescription,
hasReadableSourceTitle: hasReadableCollabAgentTitle(state, id),
hasReadableSourceTitle,
};
});
}
@@ -7190,11 +7297,14 @@
stateEntries.forEach((entry, index) => {
const tone = collabStateTone(entry.status);
const displayTitle = pickCollabAgentTitle(entry, entry.id, index);
const descriptionText = summarizePrompt(entry.taskDescription);
const fallbackDescription = `子代理任务:${displayTitle}`;
const descriptionText = summarizePrompt(entry.taskDescription) || fallbackDescription;
const descriptionTitle = cleanCollabAgentText(entry.taskDescription) || fallbackDescription;
const item = document.createElement('div');
item.className = 'collab-agent-item';
item.title = [
displayTitle,
descriptionTitle,
entry.role ? `角色: ${entry.role}` : '',
entry.detail ? `结果: ${entry.detail}` : '',
entry.id ? `ID: ${entry.id}` : '',
@@ -7218,7 +7328,7 @@
const label = document.createElement('div');
label.className = 'collab-agent-item-label';
label.textContent = pickCollabAgentTitle(entry, entry.id, index);
label.textContent = displayTitle;
row.appendChild(label);
const chip = document.createElement('span');
@@ -7246,13 +7356,11 @@
}
item.appendChild(row);
if (descriptionText) {
const description = document.createElement('div');
description.className = 'collab-agent-item-description';
description.textContent = descriptionText;
description.title = entry.taskDescription;
item.appendChild(description);
}
const description = document.createElement('div');
description.className = 'collab-agent-item-description';
description.textContent = descriptionText;
description.title = descriptionTitle;
item.appendChild(description);
if (entry.id || entry.role) {
const footer = document.createElement('div');
@@ -7392,7 +7500,7 @@
messagesDiv.innerHTML = '';
clearUserMessageIndex();
if (messages.length === 0) {
messagesDiv.innerHTML = buildWelcomeMarkup(currentAgent);
messagesDiv.innerHTML = buildWelcomeMarkup(currentCwd);
updateUserOutlinePanel();
renderPendingNotes({ scroll: false });
scrollToBottom();
@@ -8142,6 +8250,7 @@
if (!isDragging) scrollbarEl.classList.remove('scrolling');
}, 1200);
}, { passive: true });
new ResizeObserver(updateScrollbar).observe(messagesDiv);
// Drag logic
@@ -8809,16 +8918,13 @@
hideOptionPicker();
if (runtimeInsert) {
if (pendingAttachments.length > 0) {
appendError('Codex App 运行中插入暂不支持图片附件,请先移除图片。');
return;
}
if (isKnownSlashCommandText(text)) {
appendError('Codex App 运行中暂不支持 slash 指令插入。');
return;
}
const attachments = pendingAttachments.map((attachment) => ({ ...attachment }));
const messageId = createLocalId('user');
const element = createMsgElement('user', text, [], { messageId, codexAppSteerStatus: 'pending' });
const element = createMsgElement('user', text, attachments, { messageId, codexAppSteerStatus: 'pending' });
const streamEl = document.getElementById('streaming-msg');
const shouldFollow = isNearBottom();
if (streamEl && streamEl.parentNode === messagesDiv) {
@@ -8838,8 +8944,10 @@
} else {
updateScrollbar();
}
send({ type: 'message', text, sessionId: currentSessionId, mode: currentMode, agent: currentAgent, clientMessageId: messageId });
send({ type: 'message', text, attachments, sessionId: currentSessionId, mode: currentMode, agent: currentAgent, clientMessageId: messageId });
msgInput.value = '';
pendingAttachments = [];
renderPendingAttachments();
autoResize();
return;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -0,0 +1,151 @@
[
{
"name": "new-chat",
"source_box": [
15,
9,
304,
58
],
"size": [
289,
49
]
},
{
"name": "search",
"source_box": [
15,
67,
304,
103
],
"size": [
289,
36
]
},
{
"name": "project",
"source_box": [
15,
117,
304,
164
],
"size": [
289,
47
]
},
{
"name": "active-session",
"source_box": [
15,
163,
304,
209
],
"size": [
289,
46
]
},
{
"name": "composer",
"source_box": [
557,
830,
1364,
931
],
"size": [
807,
101
]
},
{
"name": "composer-action",
"source_box": [
1211,
845,
1257,
891
],
"size": [
46,
46
]
},
{
"name": "tool-call",
"source_box": [
421,
603,
1381,
664
],
"size": [
960,
61
]
},
{
"name": "composer-shell",
"derived_from": "composer.png",
"source_box": [
0,
0,
807,
74
],
"size": [
807,
74
]
},
{
"name": "composer-ornament",
"derived_from": "composer.png",
"source_box": [
130,
50,
547,
51
],
"size": [
547,
51
]
},
{
"name": "welcome-card",
"source": "2b88b81d-c5a8-4d92-a518-afeea691eade.webp",
"source_box": [
70,
0,
1165,
875
],
"size": [
1095,
875
],
"output": "frames/welcome-card.png"
},
{
"name": "welcome-card-surface",
"source": "2b88b81d-c5a8-4d92-a518-afeea691eade.webp",
"source_box": [
350,
250,
950,
600
],
"size": [
600,
350
],
"output": "textures/welcome-card-surface.webp"
}
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -0,0 +1,121 @@
{
"new-chat": {
"source": "43bd9ed6-2ba6-4c9d-bd9d-25b068cb4711.webp",
"card": "R1C1",
"variant": "32px",
"bbox": [204, 85, 69, 65],
"output": "icons/new-chat.png"
},
"search": {
"source": "43bd9ed6-2ba6-4c9d-bd9d-25b068cb4711.webp",
"card": "R1C3",
"variant": "32px",
"bbox": [746, 86, 62, 62],
"output": "icons/search.png"
},
"dropdown": {
"source": "43bd9ed6-2ba6-4c9d-bd9d-25b068cb4711.webp",
"card": "R1C2",
"variant": "32px",
"bbox": [480, 98, 59, 45],
"output": "icons/dropdown.png"
},
"theme": {
"source": "43bd9ed6-2ba6-4c9d-bd9d-25b068cb4711.webp",
"card": "R2C1",
"variant": "32px",
"bbox": [204, 236, 70, 65],
"output": "icons/theme.png"
},
"ai": {
"source": "43bd9ed6-2ba6-4c9d-bd9d-25b068cb4711.webp",
"card": "R2C2",
"variant": "32px",
"bbox": [476, 236, 65, 65],
"output": "icons/ai.png"
},
"status": {
"source": "43bd9ed6-2ba6-4c9d-bd9d-25b068cb4711.webp",
"card": "R2C3",
"variant": "32px",
"bbox": [749, 242, 53, 53],
"output": "icons/status.png"
},
"attachment": {
"source": "43bd9ed6-2ba6-4c9d-bd9d-25b068cb4711.webp",
"card": "R2C5",
"variant": "32px",
"bbox": [1277, 236, 49, 60],
"output": "icons/attachment.png"
},
"send": {
"source": "43bd9ed6-2ba6-4c9d-bd9d-25b068cb4711.webp",
"card": "R2C6",
"variant": "32px",
"bbox": [1533, 237, 63, 57],
"output": "icons/send.png"
},
"stop": {
"source": "43bd9ed6-2ba6-4c9d-bd9d-25b068cb4711.webp",
"card": "R3C1",
"variant": "32px",
"bbox": [211, 392, 56, 56],
"output": "icons/stop.png"
},
"settings": {
"source": "43bd9ed6-2ba6-4c9d-bd9d-25b068cb4711.webp",
"card": "R3C2",
"variant": "32px",
"bbox": [476, 389, 65, 62],
"output": "icons/settings.png"
},
"user": {
"source": "43bd9ed6-2ba6-4c9d-bd9d-25b068cb4711.webp",
"card": "R3C3",
"variant": "32px",
"bbox": [743, 389, 65, 62],
"output": "icons/user.png"
},
"terminal": {
"source": "43bd9ed6-2ba6-4c9d-bd9d-25b068cb4711.webp",
"card": "R3C4",
"variant": "32px",
"bbox": [1009, 393, 59, 55],
"output": "icons/terminal.png"
},
"copy": {
"source": "43bd9ed6-2ba6-4c9d-bd9d-25b068cb4711.webp",
"card": "R3C5",
"variant": "32px",
"bbox": [1278, 392, 48, 56],
"output": "icons/copy.png"
},
"refresh": {
"source": "43bd9ed6-2ba6-4c9d-bd9d-25b068cb4711.webp",
"card": "R4C1",
"variant": "32px",
"bbox": [211, 541, 57, 57],
"output": "icons/refresh.png"
},
"chat": {
"source": "43bd9ed6-2ba6-4c9d-bd9d-25b068cb4711.webp",
"card": "R4C3",
"variant": "32px",
"bbox": [745, 541, 62, 55],
"output": "icons/chat.png"
},
"close": {
"source": "43bd9ed6-2ba6-4c9d-bd9d-25b068cb4711.webp",
"card": "R5C3",
"variant": "32px",
"bbox": [749, 690, 53, 53],
"output": "icons/close.png"
},
"check": {
"source": "43bd9ed6-2ba6-4c9d-bd9d-25b068cb4711.webp",
"card": "R5C4",
"variant": "32px",
"bbox": [1010, 693, 56, 47],
"output": "icons/check.png"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

View File

@@ -0,0 +1,262 @@
[
{
"name": "search",
"variant": "16",
"slot_box": [
596,
80,
60,
75
],
"detected_box": [
607,
102,
34,
35
],
"size": [
20,
20
]
},
{
"name": "dropdown",
"variant": "16",
"slot_box": [
329,
80,
60,
75
],
"detected_box": [
343,
109,
30,
24
],
"size": [
14,
10
]
},
{
"name": "theme",
"variant": "24",
"slot_box": [
126,
231,
74,
75
],
"detected_box": [
136,
245,
45,
51
],
"size": [
26,
26
]
},
{
"name": "ai",
"variant": "32",
"slot_box": [
461,
231,
89,
75
],
"detected_box": [
477,
236,
63,
65
],
"size": [
36,
36
]
},
{
"name": "status",
"variant": "16",
"slot_box": [
596,
231,
60,
75
],
"detected_box": [
608,
255,
32,
33
],
"size": [
16,
16
]
},
{
"name": "attachment",
"variant": "24",
"slot_box": [
1187,
231,
74,
75
],
"detected_box": [
1202,
245,
40,
47
],
"size": [
26,
28
]
},
{
"name": "send",
"variant": "32",
"slot_box": [
1523,
231,
86,
75
],
"detected_box": [
1534,
238,
61,
56
],
"size": [
30,
30
]
},
{
"name": "queue",
"variant": "32",
"slot_box": [
992,
231,
88,
75
],
"detected_box": [
1012,
241,
52,
53
],
"size": [
30,
30
]
},
{
"name": "stop",
"variant": "24",
"slot_box": [
126,
384,
74,
75
],
"detected_box": [
138,
401,
41,
41
],
"size": [
26,
26
]
},
{
"name": "settings",
"variant": "16",
"slot_box": [
329,
384,
60,
75
],
"detected_box": [
338,
401,
41,
41
],
"size": [
20,
20
]
},
{
"name": "user",
"variant": "32",
"slot_box": [
728,
384,
89,
75
],
"detected_box": [
744,
388,
63,
63
],
"size": [
36,
36
]
},
{
"name": "terminal",
"variant": "16",
"slot_box": [
860,
384,
60,
75
],
"detected_box": [
869,
407,
35,
32
],
"size": [
20,
18
]
},
{
"name": "note",
"variant": "32",
"slot_box": [
728,
536,
89,
75
],
"detected_box": [
745,
541,
61,
70
],
"size": [
36,
36
]
}
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 834 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -15,12 +15,16 @@
<script>
(function () {
var theme = localStorage.getItem('cc-web-theme') || 'washi';
if (theme === 'gilded') {
theme = 'washi';
localStorage.setItem('cc-web-theme', theme);
}
var dividerTime = localStorage.getItem('cc-web-show-divider-time') === '0' ? 'hide' : 'show';
document.documentElement.dataset.theme = theme;
document.documentElement.dataset.dividerTime = dividerTime;
})();
</script>
<link rel="stylesheet" href="style.css?v=20260629-ccweb-prompt-dark-theme">
<link rel="stylesheet" href="style.css?v=20260717-wasteland-hifi-23">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css">
</head>
<body>
@@ -47,7 +51,7 @@
<aside id="sidebar" class="sidebar">
<div class="sidebar-header">
<div class="new-chat-split">
<button id="new-chat-btn" class="new-chat-btn">+ 新会话</button>
<button id="new-chat-btn" class="new-chat-btn"><span class="new-chat-glyph" aria-hidden="true">+</span> 新会话</button>
<button id="new-chat-arrow" class="new-chat-arrow" title="更多"></button>
</div>
<div id="new-chat-dropdown" class="new-chat-dropdown" hidden>
@@ -79,9 +83,23 @@
<div class="messages-wrap">
<div id="messages" class="messages">
<div class="welcome-msg">
<div class="welcome-icon"></div>
<h3>欢迎使用 CC-Web</h3>
<p>开始与 Claude 对话</p>
<section class="warframe-hero" aria-labelledby="warframe-welcome-title">
<div class="warframe-hero-art" aria-hidden="true">
<img class="warframe-hero-image" src="assets/themes/gilded-wasteland.png" alt="" draggable="false" decoding="async">
<span class="warframe-hero-orbit"></span>
<span class="warframe-hero-emblem"></span>
</div>
<div class="wasteland-welcome-art" aria-hidden="true">
<div class="wasteland-welcome-surface"></div>
<img class="wasteland-welcome-frame" src="assets/themes/wasteland/frames/welcome-card.png" alt="" draggable="false" decoding="async">
</div>
<div class="welcome-icon"></div>
<div class="welcome-copy">
<div class="welcome-kicker">OROKIN FIELD ARCHIVE · CC-WEB</div>
<h3 id="warframe-welcome-title" data-welcome-project-copy></h3>
<p>本次你要构建什么?</p>
</div>
</section>
</div>
</div>
<div class="custom-scrollbar" id="custom-scrollbar">
@@ -165,6 +183,6 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/12.0.1/marked.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.9.1/mermaid.min.js"></script>
<script src="app.js?v=20260705-codexapp-ui-agent"></script>
<script src="app.js?v=20260718-theme-bundle-4"></script>
</body>
</html>

File diff suppressed because it is too large Load Diff