chore: rebuild release package
This commit is contained in:
250
public/app.js
250
public/app.js
@@ -174,6 +174,9 @@
|
||||
let activeToolCalls = new Map();
|
||||
let activeTodoCallTargets = new Map();
|
||||
let closedCollabAgentIds = new Set();
|
||||
let collabAgentStateCache = new Map();
|
||||
let collabAgentIdsByToolUseId = new Map();
|
||||
let closedCollabAgentIdsByToolUseId = new Map();
|
||||
let toolDomSeq = 0;
|
||||
let toolGroupCount = 0; // 当前 .msg-tools 直接子节点数(含已有父目录)
|
||||
let hasGrouped = false; // 本次输出是否已触发过折叠
|
||||
@@ -3721,10 +3724,6 @@
|
||||
async function handleSelectedImageFiles(fileList) {
|
||||
const files = Array.from(fileList || []).filter((file) => file && /^image\//.test(file.type || ''));
|
||||
if (!files.length) return;
|
||||
if (pendingAttachments.length + files.length > 4) {
|
||||
appendError('单条消息最多附带 4 张图片。');
|
||||
return;
|
||||
}
|
||||
const batch = files.map((file, index) => ({
|
||||
id: `${Date.now()}-${index}-${Math.random().toString(36).slice(2, 8)}`,
|
||||
filename: file.name || 'image',
|
||||
@@ -4199,6 +4198,9 @@
|
||||
activeToolCalls.clear();
|
||||
activeTodoCallTargets.clear();
|
||||
closedCollabAgentIds = new Set();
|
||||
collabAgentStateCache = new Map();
|
||||
collabAgentIdsByToolUseId = new Map();
|
||||
closedCollabAgentIdsByToolUseId = new Map();
|
||||
updateGenerationControls();
|
||||
chatTitle.textContent = '新会话';
|
||||
updateSessionIdBadge();
|
||||
@@ -6625,7 +6627,7 @@
|
||||
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';
|
||||
const detail = cleanCollabAgentText(state.candidateResult || state.finalMessage || state.result || state.output || state.summary || state.message || state.lastMessage || state.step || state.description || '');
|
||||
const detail = cleanCollabAgentText(state.detail || state.candidateResult || state.finalMessage || state.result || state.output || state.summary || state.message || state.lastMessage || state.step || state.description || '');
|
||||
return {
|
||||
id,
|
||||
label,
|
||||
@@ -6715,6 +6717,124 @@
|
||||
getClosedCollabAgentIdsFromTool(tool).forEach((id) => closedCollabAgentIds.add(id));
|
||||
}
|
||||
|
||||
function normalizeCollabAgentThreadId(id) {
|
||||
return cleanCollabAgentText(id);
|
||||
}
|
||||
|
||||
function addCollabAgentIdsToMap(map, key, ids) {
|
||||
const mapKey = cleanCollabAgentText(key);
|
||||
const values = Array.isArray(ids) || ids instanceof Set ? Array.from(ids) : [ids];
|
||||
const normalizedIds = values.map(normalizeCollabAgentThreadId).filter(Boolean);
|
||||
if (!mapKey || normalizedIds.length === 0) return;
|
||||
const set = map.get(mapKey) || new Set();
|
||||
normalizedIds.forEach((id) => set.add(id));
|
||||
map.set(mapKey, set);
|
||||
}
|
||||
|
||||
function rememberCollabAgentIdsForTool(toolUseId, ids) {
|
||||
addCollabAgentIdsToMap(collabAgentIdsByToolUseId, toolUseId, ids);
|
||||
}
|
||||
|
||||
function rememberClosedCollabAgentIdsForTool(toolUseId, ids) {
|
||||
addCollabAgentIdsToMap(closedCollabAgentIdsByToolUseId, toolUseId, ids);
|
||||
}
|
||||
|
||||
function collectScopedCollabAgentIdsForToolMap(map) {
|
||||
const ids = new Set();
|
||||
if (!(map instanceof Map)) return ids;
|
||||
map.forEach((tool, key) => {
|
||||
getCollabAgentIdsFromTool(tool).forEach((id) => ids.add(id));
|
||||
[key, tool?.id].forEach((toolKey) => {
|
||||
const normalizedKey = cleanCollabAgentText(toolKey);
|
||||
if (!normalizedKey) return;
|
||||
const cachedIds = collabAgentIdsByToolUseId.get(normalizedKey);
|
||||
if (cachedIds instanceof Set) cachedIds.forEach((id) => ids.add(id));
|
||||
});
|
||||
});
|
||||
return ids;
|
||||
}
|
||||
|
||||
function collectScopedClosedCollabAgentIdsForToolMap(map) {
|
||||
const ids = new Set();
|
||||
if (!(map instanceof Map)) return ids;
|
||||
map.forEach((tool, key) => {
|
||||
getClosedCollabAgentIdsFromTool(tool).forEach((id) => ids.add(id));
|
||||
[key, tool?.id].forEach((toolKey) => {
|
||||
const normalizedKey = cleanCollabAgentText(toolKey);
|
||||
if (!normalizedKey) return;
|
||||
const cachedIds = closedCollabAgentIdsByToolUseId.get(normalizedKey);
|
||||
if (cachedIds instanceof Set) cachedIds.forEach((id) => ids.add(id));
|
||||
});
|
||||
});
|
||||
return ids;
|
||||
}
|
||||
|
||||
function rememberCollabAgentState(id, incomingState = {}, fallbackPrompt = '', index = 0) {
|
||||
const threadId = normalizeCollabAgentThreadId(id);
|
||||
if (!threadId) return null;
|
||||
const state = incomingState && typeof incomingState === 'object' ? incomingState : { status: incomingState };
|
||||
const previousState = collabAgentStateCache.get(threadId) || {};
|
||||
const nextState = mergeCollabAgentTaskState(previousState, state, fallbackPrompt, threadId, index);
|
||||
const status = cleanCollabAgentText(state.status || state.state || nextState.status || previousState.status || '');
|
||||
const detail = cleanCollabAgentText(
|
||||
state.detail
|
||||
|| state.candidateResult
|
||||
|| state.finalMessage
|
||||
|| state.result
|
||||
|| state.output
|
||||
|| state.summary
|
||||
|| state.message
|
||||
|| state.lastMessage
|
||||
|| state.step
|
||||
|| state.description
|
||||
|| nextState.detail
|
||||
|| previousState.detail
|
||||
|| ''
|
||||
);
|
||||
const role = cleanCollabAgentText(state.role || state.agent || state.agentType || nextState.role || previousState.role || '');
|
||||
const cachedState = { ...nextState };
|
||||
if (status) cachedState.status = status;
|
||||
if (detail) cachedState.detail = detail;
|
||||
if (role) cachedState.role = role;
|
||||
if (state.candidateResult !== undefined) cachedState.candidateResult = state.candidateResult;
|
||||
if (state.finalMessage !== undefined) cachedState.finalMessage = state.finalMessage;
|
||||
if (state.closedAt !== undefined) cachedState.closedAt = state.closedAt;
|
||||
if (state.returnedAt !== undefined) cachedState.returnedAt = state.returnedAt;
|
||||
collabAgentStateCache.set(threadId, cachedState);
|
||||
return cachedState;
|
||||
}
|
||||
|
||||
function rememberCollabAgentStateFromChild(child, toolUseId = '') {
|
||||
if (!child || typeof child !== 'object') return '';
|
||||
const threadId = normalizeCollabAgentThreadId(
|
||||
child.threadId
|
||||
|| child.thread_id
|
||||
|| child.agentId
|
||||
|| child.agent_id
|
||||
|| child.id
|
||||
);
|
||||
if (!threadId) return '';
|
||||
const incomingState = {
|
||||
...child,
|
||||
label: child.label || child.title || child.nickname || child.name || '',
|
||||
name: child.name || child.label || threadId,
|
||||
role: child.role || child.agent || child.agentType || '',
|
||||
status: child.status || child.state || 'running',
|
||||
taskDescription: collabAgentTaskDescription(child),
|
||||
candidateResult: child.finalMessage || child.candidateResult || '',
|
||||
finalMessage: child.finalMessage || '',
|
||||
closedAt: child.closedAt || null,
|
||||
returnedAt: child.returnedAt || null,
|
||||
};
|
||||
const cachedState = rememberCollabAgentState(threadId, incomingState, '', collabAgentStateCache.size);
|
||||
rememberCollabAgentIdsForTool(toolUseId, [threadId]);
|
||||
if (collabStateTone(cachedState?.status || child.status) === 'closed') {
|
||||
closedCollabAgentIds.add(threadId);
|
||||
rememberClosedCollabAgentIdsForTool(toolUseId, [threadId]);
|
||||
}
|
||||
return threadId;
|
||||
}
|
||||
|
||||
function mergeCollabAgentTools(tools, options = {}) {
|
||||
const list = Array.isArray(tools) ? tools.filter((tool) => toolKind(tool) === 'collab_agent_tool_call') : [];
|
||||
if (list.length === 0) return null;
|
||||
@@ -6722,20 +6842,28 @@
|
||||
const receiverThreadIds = [];
|
||||
const knownClosedIds = options.closedAgentIds instanceof Set ? options.closedAgentIds : closedCollabAgentIds;
|
||||
const localClosedIds = new Set(knownClosedIds || []);
|
||||
const scopedRestoreIds = options.restoreAgentIds instanceof Set ? options.restoreAgentIds : new Set();
|
||||
const scopedClosedIds = options.closedAgentIds instanceof Set ? options.closedAgentIds : new Set();
|
||||
let toolName = '子代';
|
||||
let prompt = '';
|
||||
let status = '';
|
||||
let done = false;
|
||||
let hasCloseAction = false;
|
||||
|
||||
list.forEach((tool, toolIndex) => {
|
||||
list.forEach((tool) => {
|
||||
const data = normalizeCollabAgentData(tool);
|
||||
const action = getCollabAgentAction(tool, data);
|
||||
const isCloseAction = action === 'close_agent';
|
||||
if (isCloseAction) hasCloseAction = true;
|
||||
const displayAction = String(data.tool || tool.name || '').trim();
|
||||
if (displayAction && !['wait_agent', 'close_agent'].includes(action)) toolName = displayAction;
|
||||
if (!prompt && data.prompt) prompt = data.prompt;
|
||||
const toolAgentIds = getCollabAgentIdsFromTool(tool);
|
||||
const toolClosedIds = getClosedCollabAgentIdsFromTool(tool);
|
||||
rememberCollabAgentIdsForTool(tool.id, toolAgentIds);
|
||||
rememberClosedCollabAgentIdsForTool(tool.id, toolClosedIds);
|
||||
if (isCloseAction) {
|
||||
getCollabAgentIdsFromTool(tool).forEach((id) => localClosedIds.add(id));
|
||||
toolAgentIds.forEach((id) => localClosedIds.add(id));
|
||||
}
|
||||
const dataStatus = isCloseAction ? 'closed' : data.status;
|
||||
if (dataStatus) status = dataStatus;
|
||||
@@ -6750,14 +6878,23 @@
|
||||
entry.id,
|
||||
receiverThreadIds.indexOf(entry.id)
|
||||
);
|
||||
states[entry.id] = {
|
||||
const nextStatus = isCloseAction || localClosedIds.has(entry.id) ? 'closed' : entry.status;
|
||||
states[entry.id] = rememberCollabAgentState(
|
||||
entry.id,
|
||||
{
|
||||
...nextState,
|
||||
status: nextStatus,
|
||||
},
|
||||
data.prompt,
|
||||
receiverThreadIds.indexOf(entry.id)
|
||||
) || {
|
||||
...nextState,
|
||||
status: isCloseAction || localClosedIds.has(entry.id) ? 'closed' : entry.status,
|
||||
status: nextStatus,
|
||||
};
|
||||
if (collabStateTone(states[entry.id].status) === 'closed') localClosedIds.add(entry.id);
|
||||
});
|
||||
|
||||
getCollabAgentIdsFromTool(tool).forEach((id) => {
|
||||
toolAgentIds.forEach((id) => {
|
||||
if (!receiverThreadIds.includes(id)) receiverThreadIds.push(id);
|
||||
const nextState = mergeCollabAgentTaskState(
|
||||
states[id],
|
||||
@@ -6766,28 +6903,77 @@
|
||||
id,
|
||||
receiverThreadIds.indexOf(id)
|
||||
);
|
||||
states[id] = {
|
||||
const nextStatus = isCloseAction || localClosedIds.has(id)
|
||||
? 'closed'
|
||||
: (data.status || states[id]?.status || (tool.done ? 'completed' : 'running'));
|
||||
states[id] = rememberCollabAgentState(
|
||||
id,
|
||||
{
|
||||
...nextState,
|
||||
status: nextStatus,
|
||||
},
|
||||
data.prompt,
|
||||
receiverThreadIds.indexOf(id)
|
||||
) || {
|
||||
...nextState,
|
||||
status: isCloseAction || localClosedIds.has(id)
|
||||
? 'closed'
|
||||
: (data.status || states[id]?.status || (tool.done ? 'completed' : 'running')),
|
||||
status: nextStatus,
|
||||
};
|
||||
});
|
||||
|
||||
if (receiverThreadIds.length === 0 && list.length === 1) {
|
||||
const fallbackId = tool.id || `tool-${toolIndex + 1}`;
|
||||
receiverThreadIds.push(fallbackId);
|
||||
states[fallbackId] = {
|
||||
...mergeCollabAgentTaskState({}, { label: '子代理' }, data.prompt, fallbackId, toolIndex),
|
||||
status: isCloseAction ? 'closed' : (data.status || (tool.done ? 'completed' : 'running')),
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const recoverSourceIds = hasCloseAction
|
||||
? Array.from(scopedClosedIds)
|
||||
: Array.from(new Set([...scopedRestoreIds, ...scopedClosedIds]));
|
||||
recoverSourceIds.forEach((id) => {
|
||||
const threadId = normalizeCollabAgentThreadId(id);
|
||||
if (!threadId || receiverThreadIds.includes(threadId)) return;
|
||||
const cachedState = collabAgentStateCache.get(threadId);
|
||||
if (!cachedState) return;
|
||||
receiverThreadIds.push(threadId);
|
||||
const index = receiverThreadIds.indexOf(threadId);
|
||||
const nextStatus = localClosedIds.has(threadId)
|
||||
? 'closed'
|
||||
: (cachedState.status || (done ? 'completed' : 'running'));
|
||||
states[threadId] = rememberCollabAgentState(
|
||||
threadId,
|
||||
{
|
||||
...cachedState,
|
||||
status: nextStatus,
|
||||
},
|
||||
'',
|
||||
index
|
||||
) || {
|
||||
...mergeCollabAgentTaskState(cachedState, { status: nextStatus }, '', threadId, index),
|
||||
status: nextStatus,
|
||||
};
|
||||
});
|
||||
|
||||
if (receiverThreadIds.length === 0 && list.length === 1) {
|
||||
const tool = list[0];
|
||||
const data = normalizeCollabAgentData(tool);
|
||||
const action = getCollabAgentAction(tool, data);
|
||||
const isCloseAction = action === 'close_agent';
|
||||
const fallbackId = tool.id || 'tool-1';
|
||||
receiverThreadIds.push(fallbackId);
|
||||
states[fallbackId] = {
|
||||
...mergeCollabAgentTaskState({}, { label: '子代理' }, data.prompt, fallbackId, 0),
|
||||
status: isCloseAction ? 'closed' : (data.status || (tool.done ? 'completed' : 'running')),
|
||||
};
|
||||
}
|
||||
|
||||
receiverThreadIds.forEach((id, index) => {
|
||||
states[id] = {
|
||||
const nextStatus = localClosedIds.has(id) ? 'closed' : (states[id]?.status || 'pending');
|
||||
states[id] = rememberCollabAgentState(
|
||||
id,
|
||||
{
|
||||
...states[id],
|
||||
status: nextStatus,
|
||||
},
|
||||
'',
|
||||
index
|
||||
) || {
|
||||
...mergeCollabAgentTaskState(states[id], {}, '', id, index),
|
||||
status: localClosedIds.has(id) ? 'closed' : (states[id]?.status || 'pending'),
|
||||
status: nextStatus,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -7089,6 +7275,9 @@
|
||||
const epoch = renderEpoch;
|
||||
const baseIndex = Number.isFinite(Number(options.baseIndex)) ? Number(options.baseIndex) : 0;
|
||||
closedCollabAgentIds = collectClosedCollabAgentIds(messages);
|
||||
collabAgentStateCache = new Map();
|
||||
collabAgentIdsByToolUseId = new Map();
|
||||
closedCollabAgentIdsByToolUseId = new Map();
|
||||
messagesDiv.innerHTML = '';
|
||||
clearUserMessageIndex();
|
||||
if (messages.length === 0) {
|
||||
@@ -7455,7 +7644,12 @@
|
||||
rememberClosedCollabAgentIdsFromTool(nextTool);
|
||||
const map = existing?.__collabTools instanceof Map ? existing.__collabTools : new Map();
|
||||
map.set(toolUseId || nextTool.id || `collab-${map.size + 1}`, nextTool);
|
||||
const merged = mergeCollabAgentTools(Array.from(map.values()));
|
||||
const restoreAgentIds = collectScopedCollabAgentIdsForToolMap(map);
|
||||
const closedAgentIds = collectScopedClosedCollabAgentIdsForToolMap(map);
|
||||
const mergeOptions = {};
|
||||
if (restoreAgentIds.size > 0) mergeOptions.restoreAgentIds = restoreAgentIds;
|
||||
if (closedAgentIds.size > 0) mergeOptions.closedAgentIds = closedAgentIds;
|
||||
const merged = mergeCollabAgentTools(Array.from(map.values()), mergeOptions);
|
||||
if (!merged) return existing;
|
||||
|
||||
if (existing) {
|
||||
@@ -7643,10 +7837,12 @@
|
||||
const tool = msg?.tool;
|
||||
const toolUseId = msg?.toolUseId || tool?.id;
|
||||
if (!toolUseId || !tool) return;
|
||||
if (toolKind(tool) !== 'collab_agent_tool_call') return;
|
||||
const isCurrentSessionUpdate = msg.sessionId === currentSessionId;
|
||||
if (isCurrentSessionUpdate) {
|
||||
const childThreadId = rememberCollabAgentStateFromChild(msg.child, toolUseId);
|
||||
if (msg?.child?.threadId && collabStateTone(msg.child.status) === 'closed') {
|
||||
closedCollabAgentIds.add(String(msg.child.threadId));
|
||||
closedCollabAgentIds.add(String(childThreadId || msg.child.threadId));
|
||||
}
|
||||
rememberClosedCollabAgentIdsFromTool(tool);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user