Update ccweb codex app integration
This commit is contained in:
215
public/app.js
215
public/app.js
@@ -2,7 +2,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
const ASSET_VERSION = '20260615-codexapp-steer-status-session-menu';
|
||||
const ASSET_VERSION = '20260616-composer-mcp-list';
|
||||
const WS_URL = `${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/ws`;
|
||||
const RENDER_DEBOUNCE = 100;
|
||||
const COMPOSER_SUGGESTION_DEBOUNCE = 120;
|
||||
@@ -274,6 +274,21 @@
|
||||
pendingNotesByTarget.delete(draftKey);
|
||||
}
|
||||
|
||||
function updateGenerationControls() {
|
||||
const noteActive = !!noteMode;
|
||||
const allowRuntimeInsert = isGenerating && isCodexAppAgent(currentAgent) && !noteActive;
|
||||
const sendLabel = noteActive ? '记录笔记' : (allowRuntimeInsert ? '插入' : '发送');
|
||||
if (sendBtn) {
|
||||
sendBtn.classList.toggle('note-send', noteActive);
|
||||
sendBtn.title = sendLabel;
|
||||
sendBtn.setAttribute('aria-label', sendLabel);
|
||||
sendBtn.hidden = isGenerating ? !(noteActive || allowRuntimeInsert) : false;
|
||||
}
|
||||
if (abortBtn) {
|
||||
abortBtn.hidden = !isGenerating;
|
||||
}
|
||||
}
|
||||
|
||||
function updateNoteModeUI() {
|
||||
const active = !!noteMode;
|
||||
if (noteModeBtn) {
|
||||
@@ -283,16 +298,11 @@
|
||||
noteModeBtn.setAttribute('aria-label', active ? '关闭笔记模式' : '笔记模式');
|
||||
}
|
||||
if (inputWrapper) inputWrapper.classList.toggle('note-mode-active', active);
|
||||
if (sendBtn) {
|
||||
const allowRuntimeInsert = isGenerating && isCodexAppAgent(currentAgent) && !active;
|
||||
sendBtn.classList.toggle('note-send', active);
|
||||
sendBtn.title = active ? '记录笔记' : (allowRuntimeInsert ? '插入' : '发送');
|
||||
sendBtn.hidden = isGenerating ? (!active && !allowRuntimeInsert) : false;
|
||||
}
|
||||
if (msgInput) {
|
||||
msgInput.placeholder = active ? '记录笔记,稍后从气泡发送…' : defaultMsgInputPlaceholder;
|
||||
}
|
||||
if (active) hideCmdMenu();
|
||||
updateGenerationControls();
|
||||
}
|
||||
|
||||
function createNoteActionButton(action, label, title = label) {
|
||||
@@ -800,11 +810,19 @@
|
||||
}
|
||||
|
||||
function buildUserOutlineItems() {
|
||||
return Array.from(userMessageIndex.values()).map((entry) => ({
|
||||
id: entry.id,
|
||||
targetMessageId: entry.element?.id || '',
|
||||
label: shortMessagePreview(entry.content, 64),
|
||||
})).filter((entry) => entry.targetMessageId);
|
||||
const seen = new Set();
|
||||
return Array.from(messagesDiv.querySelectorAll('.msg.user[data-message-id]')).map((element) => {
|
||||
const id = String(element.dataset.messageId || '').trim();
|
||||
if (!id || seen.has(id)) return null;
|
||||
seen.add(id);
|
||||
const indexed = userMessageIndex.get(id);
|
||||
const content = indexed?.content || element.querySelector('.msg-text')?.textContent || '';
|
||||
return {
|
||||
id,
|
||||
targetMessageId: element.id || '',
|
||||
label: shortMessagePreview(content, 64),
|
||||
};
|
||||
}).filter((entry) => entry && entry.targetMessageId);
|
||||
}
|
||||
|
||||
function updateUserOutlinePanel() {
|
||||
@@ -844,8 +862,11 @@
|
||||
function scrollToMessage(anchorId) {
|
||||
if (!anchorId) return;
|
||||
const target = document.getElementById(anchorId);
|
||||
if (!target) return;
|
||||
target.scrollIntoView({ block: 'start', behavior: 'smooth' });
|
||||
if (!target || !messagesDiv.contains(target)) return;
|
||||
const containerRect = messagesDiv.getBoundingClientRect();
|
||||
const targetRect = target.getBoundingClientRect();
|
||||
const targetTop = messagesDiv.scrollTop + targetRect.top - containerRect.top - 12;
|
||||
messagesDiv.scrollTo({ top: Math.max(0, targetTop), behavior: 'smooth' });
|
||||
}
|
||||
|
||||
function updateSessionIdBadge() {
|
||||
@@ -2445,6 +2466,7 @@
|
||||
currentMode = localStorage.getItem(getAgentModeStorageKey(currentAgent)) || 'yolo';
|
||||
modeSelect.value = currentMode;
|
||||
updateAgentScopedUI();
|
||||
updateGenerationControls();
|
||||
}
|
||||
|
||||
function closeAgentMenu() {
|
||||
@@ -2478,8 +2500,7 @@
|
||||
uploadingAttachments = [];
|
||||
activeToolCalls.clear();
|
||||
activeTodoCallTargets.clear();
|
||||
sendBtn.hidden = false;
|
||||
abortBtn.hidden = true;
|
||||
updateGenerationControls();
|
||||
chatTitle.textContent = '新会话';
|
||||
updateSessionIdBadge();
|
||||
updateCwdBadge();
|
||||
@@ -2501,8 +2522,7 @@
|
||||
if (isGenerating && !preserveStreaming) {
|
||||
isGenerating = false;
|
||||
generatingSessionId = null;
|
||||
sendBtn.hidden = false;
|
||||
abortBtn.hidden = true;
|
||||
updateGenerationControls();
|
||||
pendingText = '';
|
||||
window.pendingContentBlocks = [];
|
||||
activeToolCalls.clear();
|
||||
@@ -3105,6 +3125,10 @@
|
||||
showCodexAppUserInputModal(msg);
|
||||
break;
|
||||
|
||||
case 'ccweb_mcp_child_agent_update':
|
||||
applyCcwebMcpChildAgentUpdate(msg);
|
||||
break;
|
||||
|
||||
case 'mode_changed':
|
||||
if (msg.mode && MODE_LABELS[msg.mode]) {
|
||||
currentMode = msg.mode;
|
||||
@@ -3132,8 +3156,7 @@
|
||||
if (!isGenerating || !document.getElementById('streaming-msg')) {
|
||||
startGenerating(msg.sessionId || currentSessionId);
|
||||
} else {
|
||||
sendBtn.hidden = true;
|
||||
abortBtn.hidden = false;
|
||||
updateGenerationControls();
|
||||
toolGroupCount = 0;
|
||||
hasGrouped = false;
|
||||
activeToolCalls.clear();
|
||||
@@ -3287,8 +3310,6 @@
|
||||
activeTodoCallTargets.clear();
|
||||
toolGroupCount = 0;
|
||||
hasGrouped = false;
|
||||
sendBtn.hidden = true;
|
||||
abortBtn.hidden = false;
|
||||
updateNoteModeUI();
|
||||
// 不禁用输入框,允许用户继续输入(但无法发送)
|
||||
|
||||
@@ -3317,8 +3338,6 @@
|
||||
if (sessionId && currentSessionId && sessionId !== currentSessionId) return;
|
||||
isGenerating = false;
|
||||
generatingSessionId = null;
|
||||
sendBtn.hidden = false;
|
||||
abortBtn.hidden = true;
|
||||
updateNoteModeUI();
|
||||
setCurrentSessionRunningState(false);
|
||||
msgInput.focus();
|
||||
@@ -3454,7 +3473,7 @@
|
||||
|
||||
function createMsgElement(role, content, attachments = [], meta = {}) {
|
||||
const div = document.createElement('div');
|
||||
const isCrossConversation = role === 'user' && !!meta.crossConversation;
|
||||
const isCrossConversation = !!meta.crossConversation;
|
||||
const isCrossConversationReply = isCrossConversation && !!(meta.crossConversation.reply || meta.crossConversation.replyToRequestId);
|
||||
const resolvedMessageId = meta?.messageId || meta?.id || createLocalId('user');
|
||||
div.className = `msg ${role}${role === 'assistant' ? ' agent-' + currentAgent : ''}${isCrossConversation ? ' cross-conversation' : ''}${isCrossConversationReply ? ' cross-conversation-reply' : ''}`;
|
||||
@@ -3512,36 +3531,37 @@
|
||||
const bubble = document.createElement('div');
|
||||
bubble.className = 'msg-bubble';
|
||||
|
||||
if (role === 'user') {
|
||||
if (isCrossConversation) {
|
||||
const source = meta.crossConversation || {};
|
||||
const sourceTitle = source.sourceTitle || '未命名对话';
|
||||
const sourceId = source.sourceSessionId || '';
|
||||
const sourceMeta = document.createElement('div');
|
||||
sourceMeta.className = 'cross-conversation-meta';
|
||||
if (isCrossConversation) {
|
||||
const source = meta.crossConversation || {};
|
||||
const sourceTitle = source.sourceTitle || '未命名对话';
|
||||
const sourceId = source.sourceSessionId || '';
|
||||
const sourceMeta = document.createElement('div');
|
||||
sourceMeta.className = 'cross-conversation-meta';
|
||||
|
||||
const label = document.createElement('span');
|
||||
label.className = 'cross-conversation-label';
|
||||
label.textContent = isCrossConversationReply
|
||||
? `来自「${sourceTitle}」的回复`
|
||||
: `来自「${sourceTitle}」的对话`;
|
||||
sourceMeta.appendChild(label);
|
||||
const label = document.createElement('span');
|
||||
label.className = 'cross-conversation-label';
|
||||
label.textContent = isCrossConversationReply
|
||||
? `来自「${sourceTitle}」的回复`
|
||||
: `来自「${sourceTitle}」的对话`;
|
||||
sourceMeta.appendChild(label);
|
||||
|
||||
if (sourceId) {
|
||||
const copyBtn = document.createElement('button');
|
||||
copyBtn.type = 'button';
|
||||
copyBtn.className = 'cross-conversation-id-btn';
|
||||
copyBtn.textContent = `ID ${shortSessionId(sourceId)}`;
|
||||
copyBtn.title = `复制来源会话 ID\n${sourceId}`;
|
||||
copyBtn.addEventListener('click', (event) => {
|
||||
event.stopPropagation();
|
||||
copyTextToClipboard(sourceId, '来源会话 ID 已复制');
|
||||
});
|
||||
sourceMeta.appendChild(copyBtn);
|
||||
}
|
||||
|
||||
bubble.appendChild(sourceMeta);
|
||||
if (sourceId) {
|
||||
const copyBtn = document.createElement('button');
|
||||
copyBtn.type = 'button';
|
||||
copyBtn.className = 'cross-conversation-id-btn';
|
||||
copyBtn.textContent = `ID ${shortSessionId(sourceId)}`;
|
||||
copyBtn.title = `复制来源会话 ID\n${sourceId}`;
|
||||
copyBtn.addEventListener('click', (event) => {
|
||||
event.stopPropagation();
|
||||
copyTextToClipboard(sourceId, '来源会话 ID 已复制');
|
||||
});
|
||||
sourceMeta.appendChild(copyBtn);
|
||||
}
|
||||
|
||||
bubble.appendChild(sourceMeta);
|
||||
}
|
||||
|
||||
if (role === 'user') {
|
||||
if (content) {
|
||||
const textNode = document.createElement('div');
|
||||
textNode.className = 'msg-text';
|
||||
@@ -3877,7 +3897,7 @@
|
||||
const label = String(state.label || state.title || state.nickname || state.name || `子代理 ${index + 1}`);
|
||||
const role = String(state.role || state.agent || state.agentType || '').trim();
|
||||
const status = String(state.status || state.state || 'pending').trim() || 'pending';
|
||||
const detail = String(state.summary || state.lastMessage || state.step || state.description || '').trim();
|
||||
const detail = String(state.candidateResult || state.finalMessage || state.summary || state.lastMessage || state.step || state.description || '').trim();
|
||||
return { id, label, role, status, detail };
|
||||
});
|
||||
}
|
||||
@@ -3885,7 +3905,8 @@
|
||||
function collabStateTone(statusText) {
|
||||
const normalized = String(statusText || '').toLowerCase();
|
||||
if (!normalized) return 'pending';
|
||||
if (/(done|completed|success|finished|idle)/.test(normalized)) return 'done';
|
||||
if (/(closed|close)/.test(normalized)) return 'closed';
|
||||
if (/(returned|done|completed|success|finished|idle)/.test(normalized)) return 'done';
|
||||
if (/(fail|error|cancel|aborted|rejected)/.test(normalized)) return 'error';
|
||||
if (/(running|working|active|inprogress|in_progress|executing)/.test(normalized)) return 'running';
|
||||
return 'pending';
|
||||
@@ -3895,7 +3916,9 @@
|
||||
const normalized = String(statusText || '').trim();
|
||||
if (!normalized) return '等待中';
|
||||
const lower = normalized.toLowerCase();
|
||||
if (/(done|completed|success|finished)/.test(lower)) return '已完成';
|
||||
if (/(closed|close)/.test(lower)) return '已关闭';
|
||||
if (/(returned)/.test(lower)) return '已返回';
|
||||
if (/(done|completed|success|finished)/.test(lower)) return '已返回';
|
||||
if (/(fail|error|rejected)/.test(lower)) return '失败';
|
||||
if (/(cancel|aborted)/.test(lower)) return '已取消';
|
||||
if (/(running|working|active|inprogress|in_progress|executing)/.test(lower)) return '进行中';
|
||||
@@ -3919,7 +3942,7 @@
|
||||
|
||||
const kicker = document.createElement('div');
|
||||
kicker.className = 'collab-agent-kicker';
|
||||
kicker.textContent = 'Codex App 子代理';
|
||||
kicker.textContent = 'ccweb MCP 子代理';
|
||||
titleWrap.appendChild(kicker);
|
||||
|
||||
const title = document.createElement('div');
|
||||
@@ -3971,6 +3994,25 @@
|
||||
chip.className = `collab-agent-item-status ${tone}`;
|
||||
chip.textContent = collabStateLabel(entry.status);
|
||||
row.appendChild(chip);
|
||||
|
||||
if (entry.id && tone !== 'closed') {
|
||||
const closeBtn = document.createElement('button');
|
||||
closeBtn.type = 'button';
|
||||
closeBtn.className = 'collab-agent-close-btn';
|
||||
closeBtn.textContent = '关闭';
|
||||
closeBtn.title = `关闭子代理\n${entry.id}`;
|
||||
closeBtn.addEventListener('click', (event) => {
|
||||
event.stopPropagation();
|
||||
closeBtn.disabled = true;
|
||||
closeBtn.textContent = '关闭中';
|
||||
send({
|
||||
type: 'ccweb_mcp_child_agent_close',
|
||||
sessionId: currentSessionId,
|
||||
threadId: entry.id,
|
||||
});
|
||||
});
|
||||
row.appendChild(closeBtn);
|
||||
}
|
||||
item.appendChild(row);
|
||||
|
||||
if (entry.role) {
|
||||
@@ -4032,7 +4074,9 @@
|
||||
}
|
||||
|
||||
function isGroupableToolCall(node) {
|
||||
return !!(node?.classList?.contains('tool-call') && node.dataset.toolKind !== 'todo_list');
|
||||
return !!(node?.classList?.contains('tool-call')
|
||||
&& node.dataset.toolKind !== 'todo_list'
|
||||
&& node.dataset.toolKind !== 'collab_agent_tool_call');
|
||||
}
|
||||
|
||||
function rememberToolCallTarget(toolUseId, tool, element) {
|
||||
@@ -4425,6 +4469,18 @@
|
||||
}
|
||||
|
||||
function createToolCallElement(toolUseId, tool, done) {
|
||||
const kind = toolKind(tool);
|
||||
if (kind === 'collab_agent_tool_call') {
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.className = 'tool-call ccweb-mcp-child-agent-tool-call collab-agent-inline';
|
||||
wrapper.id = `tool-node-${++toolDomSeq}`;
|
||||
wrapper.dataset.toolUseId = toolUseId ? String(toolUseId) : '';
|
||||
wrapper.dataset.toolName = tool.name || '';
|
||||
wrapper.dataset.toolKind = kind;
|
||||
wrapper.appendChild(buildToolContentElement({ ...tool, done }));
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
const details = document.createElement('details');
|
||||
details.className = 'tool-call';
|
||||
details.id = `tool-node-${++toolDomSeq}`;
|
||||
@@ -4439,7 +4495,6 @@
|
||||
// - For non-Codex sessions, auto-open in-flight command execution so users can watch output.
|
||||
// - For Codex sessions, keep everything collapsed by default (less noise), including in-flight commands.
|
||||
const agent = normalizeAgent(currentAgent);
|
||||
const kind = toolKind(tool);
|
||||
if (tool.name === 'AskUserQuestion') {
|
||||
details.open = true;
|
||||
} else if (!isCodexLikeAgent(agent) && !done && kind === 'command_execution') {
|
||||
@@ -4552,6 +4607,10 @@
|
||||
el = findLatestToolCallElement(scope, (candidate) => candidate.dataset.toolUseId === toolUseIdText);
|
||||
}
|
||||
|
||||
if (!el) {
|
||||
el = findLatestToolCallElement(messagesDiv, (candidate) => candidate.dataset.toolUseId === toolUseIdText);
|
||||
}
|
||||
|
||||
if (!el && tool?.kind === 'todo_list' && tool?.input?.id) {
|
||||
el = findTodoToolCallByTodoId(scope, tool.input.id);
|
||||
}
|
||||
@@ -4586,6 +4645,41 @@
|
||||
}
|
||||
}
|
||||
|
||||
function applyCcwebMcpChildAgentUpdate(msg) {
|
||||
const tool = msg?.tool;
|
||||
const toolUseId = msg?.toolUseId || tool?.id;
|
||||
if (!toolUseId || !tool) return;
|
||||
|
||||
updateCachedSession(msg.sessionId, (snapshot) => {
|
||||
const messages = Array.isArray(snapshot.messages) ? snapshot.messages : [];
|
||||
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
||||
const calls = Array.isArray(messages[i]?.toolCalls) ? messages[i].toolCalls : [];
|
||||
const target = calls.find((item) => item.id === toolUseId);
|
||||
if (!target) continue;
|
||||
target.name = tool.name || target.name;
|
||||
target.kind = tool.kind || target.kind;
|
||||
target.input = tool.input !== undefined ? tool.input : target.input;
|
||||
target.result = tool.result !== undefined ? tool.result : target.result;
|
||||
target.meta = tool.meta || target.meta || null;
|
||||
target.done = tool.done !== undefined ? !!tool.done : target.done;
|
||||
snapshot.updated = new Date().toISOString();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if (msg.sessionId !== currentSessionId) return;
|
||||
activeToolCalls.set(toolUseId, {
|
||||
id: toolUseId,
|
||||
name: tool.name,
|
||||
input: tool.input,
|
||||
result: tool.result,
|
||||
kind: tool.kind || null,
|
||||
meta: tool.meta || null,
|
||||
done: !!tool.done,
|
||||
});
|
||||
updateToolCall(toolUseId, tool.result, !!tool.done);
|
||||
}
|
||||
|
||||
function getDeleteConfirmMessage(agent) {
|
||||
const normalized = normalizeAgent(agent);
|
||||
if (normalized === 'codex') {
|
||||
@@ -5098,7 +5192,9 @@
|
||||
? 'Prompt'
|
||||
: item.kind === 'file'
|
||||
? (item.itemType === 'directory' ? 'Dir' : 'File')
|
||||
: 'Cmd';
|
||||
: item.kind === 'mcp'
|
||||
? 'MCP'
|
||||
: 'Cmd';
|
||||
return `<div class="cmd-item${i === 0 ? ' active' : ''}" data-index="${i}">
|
||||
<span class="cmd-item-kind">${kindLabel}</span>
|
||||
<span class="cmd-item-main">
|
||||
@@ -5127,7 +5223,6 @@
|
||||
|
||||
if (token.trigger === '/') {
|
||||
showCmdMenu(token, getLocalSlashSuggestions(token.query));
|
||||
return;
|
||||
}
|
||||
|
||||
clearTimeout(composerSuggestionTimer);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
document.documentElement.dataset.dividerTime = dividerTime;
|
||||
})();
|
||||
</script>
|
||||
<link rel="stylesheet" href="style.css?v=20260615-codexapp-steer-status-session-menu">
|
||||
<link rel="stylesheet" href="style.css?v=20260616-runtime-insert-controls">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css">
|
||||
</head>
|
||||
<body>
|
||||
@@ -150,6 +150,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="app.js?v=20260615-codexapp-steer-status-session-menu"></script>
|
||||
<script src="app.js?v=20260616-runtime-insert-controls"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1986,14 +1986,14 @@ body.session-loading-active {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-color: rgba(255, 255, 255, 0.28);
|
||||
}
|
||||
.msg.user.cross-conversation .msg-avatar {
|
||||
.msg.cross-conversation .msg-avatar {
|
||||
background: var(--info);
|
||||
color: #fff;
|
||||
}
|
||||
.msg.user.cross-conversation-reply .msg-avatar {
|
||||
.msg.cross-conversation-reply .msg-avatar {
|
||||
background: var(--success);
|
||||
}
|
||||
.msg.user.cross-conversation .msg-bubble {
|
||||
.msg.cross-conversation .msg-bubble {
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.76), transparent),
|
||||
rgba(91, 126, 161, 0.1);
|
||||
@@ -2001,20 +2001,20 @@ body.session-loading-active {
|
||||
color: var(--text-primary);
|
||||
box-shadow: 0 10px 22px rgba(45, 31, 20, 0.05);
|
||||
}
|
||||
.msg.user.cross-conversation-reply .msg-bubble {
|
||||
.msg.cross-conversation-reply .msg-bubble {
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.78), transparent),
|
||||
rgba(93, 138, 84, 0.12);
|
||||
border-color: rgba(93, 138, 84, 0.28);
|
||||
}
|
||||
.msg.user.cross-conversation-reply .cross-conversation-meta,
|
||||
.msg.user.cross-conversation-reply .cross-conversation-id-btn {
|
||||
.msg.cross-conversation-reply .cross-conversation-meta,
|
||||
.msg.cross-conversation-reply .cross-conversation-id-btn {
|
||||
color: var(--success);
|
||||
}
|
||||
.msg.user.cross-conversation-reply .cross-conversation-id-btn {
|
||||
.msg.cross-conversation-reply .cross-conversation-id-btn {
|
||||
border-color: rgba(93, 138, 84, 0.28);
|
||||
}
|
||||
.msg.user.cross-conversation-reply .cross-conversation-id-btn:hover {
|
||||
.msg.cross-conversation-reply .cross-conversation-id-btn:hover {
|
||||
background: rgba(93, 138, 84, 0.14);
|
||||
}
|
||||
.cross-conversation-meta {
|
||||
@@ -2350,11 +2350,14 @@ html[data-divider-time='hide'] .msg-bubble .agent-message-divider span {
|
||||
.tool-call.codex-file-change {
|
||||
border-color: rgba(93, 138, 84, 0.24);
|
||||
}
|
||||
.tool-call.codex-collab-agent-tool-call {
|
||||
.tool-call.ccweb-mcp-child-agent-tool-call {
|
||||
border-color: rgba(91, 126, 161, 0.28);
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.66), rgba(91, 126, 161, 0.04));
|
||||
}
|
||||
.tool-call.ccweb-mcp-child-agent-tool-call.collab-agent-inline {
|
||||
overflow: visible;
|
||||
}
|
||||
.tool-call summary {
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
@@ -2463,6 +2466,8 @@ html[data-divider-time='hide'] .msg-bubble .agent-message-divider span {
|
||||
font-family: inherit;
|
||||
white-space: normal;
|
||||
word-break: normal;
|
||||
max-height: none;
|
||||
overflow: visible;
|
||||
background:
|
||||
linear-gradient(180deg, rgba(252, 253, 255, 0.96), rgba(242, 247, 252, 0.98));
|
||||
color: var(--text-primary);
|
||||
@@ -4293,6 +4298,11 @@ html[data-theme='coolvibe'] .settings-back:hover {
|
||||
background: rgba(192, 85, 58, 0.14);
|
||||
color: var(--danger);
|
||||
}
|
||||
.collab-agent-overall-status.closed,
|
||||
.collab-agent-item-status.closed {
|
||||
background: rgba(122, 110, 100, 0.12);
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.collab-agent-overall-status.pending,
|
||||
.collab-agent-item-status.pending {
|
||||
background: rgba(91, 126, 161, 0.12);
|
||||
@@ -4354,6 +4364,28 @@ html[data-theme='coolvibe'] .settings-back:hover {
|
||||
.collab-agent-item-footer:hover {
|
||||
color: var(--info);
|
||||
}
|
||||
.collab-agent-close-btn {
|
||||
appearance: none;
|
||||
flex-shrink: 0;
|
||||
border: 1px solid rgba(122, 110, 100, 0.18);
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 255, 255, 0.86);
|
||||
color: var(--text-secondary);
|
||||
padding: 4px 9px;
|
||||
font: inherit;
|
||||
font-size: 11px;
|
||||
font-weight: 800;
|
||||
cursor: pointer;
|
||||
}
|
||||
.collab-agent-close-btn:hover {
|
||||
color: var(--danger);
|
||||
border-color: rgba(192, 85, 58, 0.22);
|
||||
background: rgba(192, 85, 58, 0.08);
|
||||
}
|
||||
.collab-agent-close-btn:disabled {
|
||||
cursor: default;
|
||||
opacity: 0.6;
|
||||
}
|
||||
.collab-agent-threads {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -4777,10 +4809,11 @@ html[data-theme='coolvibe'] .settings-back:hover {
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .file-browser-path,
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .file-browser-pane,
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .file-browser-preview-content,
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .collab-agent-prompt,
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .collab-agent-item,
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .collab-agent-thread-chip,
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .todo-list-container {
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .collab-agent-prompt,
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .collab-agent-item,
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .collab-agent-thread-chip,
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .collab-agent-close-btn,
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .todo-list-container {
|
||||
background: var(--dark-panel-soft);
|
||||
border-color: var(--border-color);
|
||||
color: var(--text-primary);
|
||||
@@ -4857,8 +4890,8 @@ html[data-theme='coolvibe'] .settings-back:hover {
|
||||
}
|
||||
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .msg.assistant .msg-bubble,
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .msg.user.cross-conversation .msg-bubble,
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .msg.user.cross-conversation-reply .msg-bubble {
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .msg.cross-conversation .msg-bubble,
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .msg.cross-conversation-reply .msg-bubble {
|
||||
background: var(--bg-bubble-assistant);
|
||||
border-color: var(--border-color);
|
||||
color: var(--text-primary);
|
||||
@@ -4908,7 +4941,7 @@ html[data-theme='coolvibe'] .settings-back:hover {
|
||||
}
|
||||
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call.codex-command,
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call.codex-collab-agent-tool-call {
|
||||
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call.ccweb-mcp-child-agent-tool-call {
|
||||
background: var(--dark-panel-bg);
|
||||
border-color: var(--note-border);
|
||||
box-shadow: none;
|
||||
|
||||
Reference in New Issue
Block a user