Files
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

99 lines
3.1 KiB
TypeScript

import {
selectAttentionReadState,
type AttentionReadRecord,
type AgentSessionEngine
} from "@tutti-os/agent-activity-core";
import { useMemo, useRef, useState } from "react";
import {
useAgentGuiConversationList,
type AgentGUIConversationListQuery
} from "../../../contexts/workspace/presentation/renderer/agentGuiConversationList/useAgentGuiConversationList";
import { useEngineSelector } from "../../../shared/engine/useEngineSelector";
import type { AgentGUINodeData, AgentGUIAgentTarget } from "../../../types";
import {
createAgentGUIConversationFilterState,
type AgentGUIConversationFilter
} from "../model/agentGuiConversationFilter";
interface UseAgentGUIConversationListStateInput {
agentActivityRuntimeOrigin: string;
currentUserId?: string | null;
data: AgentGUINodeData;
normalizedProviderTargets: readonly AgentGUIAgentTarget[];
sessionEngine: AgentSessionEngine;
workspaceId: string;
}
interface AgentGUIAttentionReadState {
recordsBySessionId: Readonly<Record<string, AttentionReadRecord>>;
}
export function useAgentGUIConversationListState({
agentActivityRuntimeOrigin,
currentUserId,
data,
normalizedProviderTargets,
sessionEngine,
workspaceId
}: UseAgentGUIConversationListStateInput) {
const [conversationFilter, setConversationFilter] =
useState<AgentGUIConversationFilter>(
() => createAgentGUIConversationFilterState().filter
);
const conversationFilterRef = useRef(conversationFilter);
conversationFilterRef.current = conversationFilter;
const conversationListQuery =
useMemo<AgentGUIConversationListQuery | null>(() => {
const userId = currentUserId?.trim() ?? "";
const provider = data.provider?.trim() ?? "";
if (!workspaceId.trim() || !userId || !provider) {
return null;
}
return {
conversationFilter,
workspaceId,
userId,
provider: data.provider,
sessionOrigin: agentActivityRuntimeOrigin
};
}, [
agentActivityRuntimeOrigin,
conversationFilter,
currentUserId,
data.provider,
workspaceId
]);
const conversationListState = useAgentGuiConversationList(
sessionEngine,
conversationListQuery,
normalizedProviderTargets
);
const canonicalConversations = conversationListState?.conversations ?? [];
const attentionReadState: AgentGUIAttentionReadState = useEngineSelector(
sessionEngine,
(state) => selectAttentionReadState(state, currentUserId)
);
const conversations = useMemo(() => {
return canonicalConversations.map((conversation) => {
const attention = attentionReadState.recordsBySessionId[conversation.id];
return attention
? {
...conversation,
hasUnreadCompletion: attention.isUnread,
unreadCompletionKey: attention.completionKey
}
: conversation;
});
}, [attentionReadState.recordsBySessionId, canonicalConversations]);
return {
attentionReadState,
conversationFilter,
conversationFilterRef,
conversationListQuery,
conversationListState,
conversations,
setConversationFilter
};
}