fix: show conversation context status

This commit is contained in:
kris
2026-04-03 10:09:19 +08:00
parent 459b301939
commit da55071a99
6 changed files with 382 additions and 33 deletions

View File

@@ -353,7 +353,7 @@ function buildConversationItem(state: BossState, project: Project): Conversation
const topThread = threadViews[0]?.snapshot;
const threadTitle = project.threadMeta?.threadDisplayName ?? project.name;
const folderLabel = project.threadMeta?.folderName ?? "";
const activityIconCount = project.threadMeta?.activityIconCount ?? 1;
const activityIconCount = deriveConversationActivityIconCount(state, project);
const topPinnedLabel = isTopPinnedConversation(project) ? "置顶" : undefined;
const groupMembers = project.isGroup
? project.groupMembers.map((member) => ({
@@ -392,17 +392,44 @@ function buildConversationItem(state: BossState, project: Project): Conversation
},
groupMembers,
contextBudgetIndicator: {
visible: !project.isGroup && Boolean(topThread),
visible: Boolean(topThread),
style: "ring_percent",
percent: !project.isGroup ? topThread?.contextBudgetRemainingPct : undefined,
level: !project.isGroup ? topThread?.contextBudgetLevel : undefined,
percent: topThread?.contextBudgetRemainingPct,
level: topThread?.contextBudgetLevel,
},
contextBudgetSourceNodeId: !project.isGroup ? topThread?.nodeId : undefined,
contextBudgetUpdatedAt: !project.isGroup ? topThread?.capturedAt : undefined,
contextBudgetSourceNodeId: topThread?.nodeId,
contextBudgetUpdatedAt: topThread?.capturedAt,
mustFinishBeforeCompaction: Boolean(topThread?.mustFinishBeforeCompaction),
} satisfies ConversationItem;
}
function deriveConversationActivityIconCount(state: BossState, project: Project): number {
let count = 0;
if (
state.dispatchPlans.some(
(plan) => plan.groupProjectId === project.id && plan.status === "pending_user_confirmation",
)
) {
count += 1;
}
count += state.dispatchExecutions.filter(
(execution) =>
(execution.groupProjectId === project.id || execution.targetProjectId === project.id) &&
(execution.status === "queued" || execution.status === "running"),
).length;
count += state.masterAgentTasks.filter(
(task) =>
task.projectId === project.id &&
task.taskType !== "device_import_resolution" &&
(task.status === "queued" || task.status === "running"),
).length;
return Math.max(0, Math.min(4, count));
}
function sortConversationItems(items: ConversationItem[]) {
return items.sort((a, b) => {
if (a.projectId === "master-agent") return -1;
@@ -461,6 +488,16 @@ export function getConversationHomeItems(state: BossState): ConversationItem[] {
const device = project?.deviceIds[0]
? state.devices.find((entry) => entry.id === project.deviceIds[0])
: undefined;
const topContextItem = [...items]
.filter((item) => item.contextBudgetIndicator.visible)
.sort((a, b) => {
const aLevel = a.contextBudgetIndicator.level ?? "safe";
const bLevel = b.contextBudgetIndicator.level ?? "safe";
if (levelPriority[aLevel] !== levelPriority[bLevel]) {
return levelPriority[aLevel] - levelPriority[bLevel];
}
return (a.contextBudgetIndicator.percent ?? 100) - (b.contextBudgetIndicator.percent ?? 100);
})[0];
passthrough.push({
conversationId: `folder-${folderKey}`,
conversationType: "folder_archive",
@@ -480,13 +517,7 @@ export function getConversationHomeItems(state: BossState): ConversationItem[] {
latestItem.lastMessagePreview ||
latestItem.preview ||
`包含 ${items.length} 个线程,最近活跃:《${latestItem.threadTitle}`,
activityIconCount: Math.max(
1,
Math.min(
4,
items.reduce((sum, entry) => sum + Math.max(1, entry.activityIconCount), 0),
),
),
activityIconCount: Math.max(0, Math.min(4, items.reduce((sum, entry) => sum + entry.activityIconCount, 0))),
manualPinned: false,
topPinnedLabel: undefined,
latestReplyAt: latestItem.latestReplyAt,
@@ -503,10 +534,12 @@ export function getConversationHomeItems(state: BossState): ConversationItem[] {
primary: device?.avatar ?? latestItem.avatar.primary,
},
contextBudgetIndicator: {
visible: false,
visible: Boolean(topContextItem?.contextBudgetIndicator.visible),
style: "ring_percent",
percent: topContextItem?.contextBudgetIndicator.percent,
level: topContextItem?.contextBudgetIndicator.level,
},
mustFinishBeforeCompaction: false,
mustFinishBeforeCompaction: items.some((item) => item.mustFinishBeforeCompaction),
});
}