Files
tutti/packages/agent/gui/shared/agentGUIConversationSummaryProjection.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

135 lines
4.7 KiB
TypeScript

import {
selectWorkspaceAgentConsumerSessions,
type AgentActivitySession,
type AgentSessionEngineState
} from "@tutti-os/agent-activity-core";
import {
isAgentGUIProviderUnresolved,
resolveAgentGUIConversationBrowserFreeTitle,
resolveAgentGUIConversationTitle,
resolveAgentGUIConversationTitleDisplayPrompt,
resolveAgentGUIConversationTitleLeadingMentionKind,
resolveAgentGUIProviderIdentity,
type AgentGUIConversationTitleFallback,
type AgentGUIConversationTitleLeadingMentionKind,
type AgentGUIResolvedProvider
} from "./agentConversationTitleProjection.ts";
import type { AgentGUIConversationRailTitlePromptsBySessionId } from "./agentConversationRailTitlePromptSelector.ts";
import { resolveWorkspaceAgentSessionSortTimeUnixMs } from "./workspaceAgentSessionSortTime.ts";
export type AgentGUIConsumerSessions = ReturnType<
typeof selectWorkspaceAgentConsumerSessions
>;
export type AgentConversationRailStatus =
| "working"
| "waiting"
| "ready"
| "completed"
| "failed"
| "canceled";
export interface AgentConversationRailSummary {
agentTargetId?: string | null;
cwd: string;
id: string;
isolation?: AgentActivitySession["isolation"];
needsUserAction?: boolean;
pinnedAtUnixMs?: number | null;
provider: AgentGUIResolvedProvider;
railSectionKey?: string;
resumable?: boolean;
sortTimeUnixMs?: number;
status: AgentConversationRailStatus;
title: string;
titleFallback?: AgentGUIConversationTitleFallback;
titleLeadingMentionKind?: AgentGUIConversationTitleLeadingMentionKind | null;
updatedAtUnixMs: number;
userId?: string;
}
export function projectCanonicalAgentGUIConversationSummaries(
sessions: AgentGUIConsumerSessions,
firstUserDisplayPromptsBySessionId: AgentGUIConversationRailTitlePromptsBySessionId = {},
rootSessionIdsAwaitingUserAction?: ReadonlySet<string>
): AgentConversationRailSummary[] {
return sessions.map((item): AgentConversationRailSummary => {
const provider = resolveAgentGUIProviderIdentity({
sessionProvider: item.session.provider
});
const { title: canonicalTitle } = resolveAgentGUIConversationTitle(
item.session.title
);
const firstUserDisplayPrompt =
firstUserDisplayPromptsBySessionId[item.session.agentSessionId];
const titleDisplayPrompt = resolveAgentGUIConversationTitleDisplayPrompt({
firstUserDisplayPrompt,
title: canonicalTitle
});
const { title, titleFallback } = resolveAgentGUIConversationTitle(
resolveAgentGUIConversationBrowserFreeTitle({
firstUserDisplayPrompt,
title: canonicalTitle
})
);
const canonicalUpdatedAtUnixMs =
item.session.updatedAtUnixMs ?? item.session.createdAtUnixMs ?? 0;
const titleLeadingMentionKind =
resolveAgentGUIConversationTitleLeadingMentionKind(titleDisplayPrompt);
return {
agentTargetId: item.session.agentTargetId ?? null,
cwd: item.session.cwd,
id: item.session.agentSessionId,
isolation: item.session.isolation,
needsUserAction:
rootSessionIdsAwaitingUserAction?.has(item.session.agentSessionId) ??
item.pendingInteractions.length > 0,
pinnedAtUnixMs: item.session.pinnedAtUnixMs ?? null,
provider,
railSectionKey: item.session.railSectionKey,
resumable: item.session.resumable,
sortTimeUnixMs: resolveWorkspaceAgentSessionSortTimeUnixMs({
createdAtUnixMs: item.session.createdAtUnixMs,
latestTurn: item.latestTurn
}),
status: item.displayStatus === "idle" ? "ready" : item.displayStatus,
title,
titleLeadingMentionKind,
titleFallback,
updatedAtUnixMs: canonicalUpdatedAtUnixMs,
userId: item.session.userId?.trim() ?? ""
};
});
}
export function projectCanonicalAgentGUIConversationSummariesFromState(
state: AgentSessionEngineState,
input: {
firstUserDisplayPromptsBySessionId?: AgentGUIConversationRailTitlePromptsBySessionId;
provider?: string | null;
rootSessionIdsAwaitingUserAction?: ReadonlySet<string>;
workspaceId: string;
}
): AgentConversationRailSummary[] {
const provider = input.provider?.trim().toLowerCase() ?? "";
return projectCanonicalAgentGUIConversationSummaries(
selectWorkspaceAgentConsumerSessions(state).filter(
(item) => item.session.workspaceId === input.workspaceId
),
input.firstUserDisplayPromptsBySessionId,
input.rootSessionIdsAwaitingUserAction
)
.filter(
(conversation) =>
!provider ||
conversation.provider === provider ||
isAgentGUIProviderUnresolved(conversation.provider)
)
.sort(
(left, right) =>
(right.sortTimeUnixMs ?? right.updatedAtUnixMs) -
(left.sortTimeUnixMs ?? left.updatedAtUnixMs) ||
left.id.localeCompare(right.id)
);
}