Files
tutti/packages/agent/gui/agent-gui/agentGuiNode/model/agentGuiConversationRailViewState.ts
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

92 lines
2.9 KiB
TypeScript

import type { AgentGUIConversationFilter } from "./agentGuiConversationFilter";
export const AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE = 5;
export type AgentGUIConversationRailRevealReason = "created" | "external-open";
export interface AgentGUIConversationRailRevealRequest {
agentSessionId: string;
reason: AgentGUIConversationRailRevealReason;
revision: number;
}
export interface AgentGUIConversationRailScopedViewState {
collapsedSectionIds: ReadonlySet<string>;
visibleItemLimitBySectionId: ReadonlyMap<string, number>;
}
export type AgentGUIConversationRailViewState = ReadonlyMap<
string,
AgentGUIConversationRailScopedViewState
>;
export type AgentGUIConversationRailViewStateAction =
| { scopeKey: string; sectionId: string; type: "section-collapsed-toggled" }
| {
limit: number;
scopeKey: string;
sectionId: string;
type: "section-visible-limit-set";
};
const EMPTY_SCOPED_RAIL_VIEW_STATE: AgentGUIConversationRailScopedViewState = {
collapsedSectionIds: new Set(),
visibleItemLimitBySectionId: new Map()
};
export function agentGUIConversationRailViewScopeKey(input: {
conversationFilter: AgentGUIConversationFilter;
workspaceId: string;
}): string {
const filterScope =
input.conversationFilter.kind === "agentTarget"
? `agentTarget:${input.conversationFilter.agentTargetId.trim()}`
: "all";
return `${input.workspaceId.trim()}:${filterScope}`;
}
export function agentGUIConversationRailScopedViewState(
state: AgentGUIConversationRailViewState,
scopeKey: string
): AgentGUIConversationRailScopedViewState {
return state.get(scopeKey) ?? EMPTY_SCOPED_RAIL_VIEW_STATE;
}
export function reduceAgentGUIConversationRailViewState(
state: AgentGUIConversationRailViewState,
action: AgentGUIConversationRailViewStateAction
): AgentGUIConversationRailViewState {
const current = agentGUIConversationRailScopedViewState(
state,
action.scopeKey
);
if (action.type === "section-collapsed-toggled") {
const collapsedSectionIds = new Set(current.collapsedSectionIds);
if (collapsedSectionIds.has(action.sectionId)) {
collapsedSectionIds.delete(action.sectionId);
} else {
collapsedSectionIds.add(action.sectionId);
}
const next = new Map(state);
next.set(action.scopeKey, { ...current, collapsedSectionIds });
return next;
}
const limit = Math.max(
AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE,
Math.floor(action.limit)
);
if (
(current.visibleItemLimitBySectionId.get(action.sectionId) ??
AGENT_GUI_CONVERSATION_RAIL_SECTION_PAGE_SIZE) === limit
) {
return state;
}
const visibleItemLimitBySectionId = new Map(
current.visibleItemLimitBySectionId
);
visibleItemLimitBySectionId.set(action.sectionId, limit);
const next = new Map(state);
next.set(action.scopeKey, { ...current, visibleItemLimitBySectionId });
return next;
}