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

135 lines
3.9 KiB
TypeScript

import type { WorkspaceAgentActivityTimelineItem } from "../../../shared/workspaceAgentTimelineTypes";
import type { AgentGUITimelineRow } from "./agentGuiConversationTypes";
export function timelineRowTime(
timelineItems: readonly WorkspaceAgentActivityTimelineItem[],
rowID: string
): number {
const item = timelineItems.find((candidate) => itemID(candidate) === rowID);
return item?.occurredAtUnixMs ?? item?.createdAtUnixMs ?? 0;
}
export function timelineRowStatus(
timelineItems: readonly WorkspaceAgentActivityTimelineItem[],
rowID: string
): string | null {
const item = timelineItems.find((candidate) => itemID(candidate) === rowID);
return itemStatus(item);
}
export function timelineRowTimeByCallId(
timelineItems: readonly WorkspaceAgentActivityTimelineItem[],
callID: string
): number {
const item = [...timelineItems]
.filter((candidate) => candidate.callId?.trim() === callID)
.sort(
(left, right) =>
(right.occurredAtUnixMs ?? 0) - (left.occurredAtUnixMs ?? 0)
)[0];
return item?.occurredAtUnixMs ?? item?.createdAtUnixMs ?? 0;
}
export function timelineRowStatusByCallId(
timelineItems: readonly WorkspaceAgentActivityTimelineItem[],
callID: string
): string | null {
const item = latestTimelineItemByCallId(timelineItems, callID);
return itemStatus(item);
}
export function latestTimelineItemByCallId(
timelineItems: readonly WorkspaceAgentActivityTimelineItem[],
callID: string
): WorkspaceAgentActivityTimelineItem | undefined {
return [...timelineItems]
.filter((candidate) => candidate.callId?.trim() === callID)
.sort(
(left, right) =>
(right.occurredAtUnixMs ?? 0) - (left.occurredAtUnixMs ?? 0)
)[0];
}
export function itemStatus(
item: WorkspaceAgentActivityTimelineItem | undefined
): string | null {
if (!item) {
return null;
}
return item.status?.trim() || stringPayload(item.payload?.status) || null;
}
export function itemID(item: WorkspaceAgentActivityTimelineItem): string {
const eventID = item.eventId?.trim();
if (eventID) {
return eventID;
}
if (Number.isFinite(item.id) && item.id > 0) {
return `server:${item.id}`;
}
return `local:${item.occurredAtUnixMs ?? 0}:${item.itemType}:${item.role ?? ""}`;
}
export function stableTimelineRowID(
timelineItems: readonly WorkspaceAgentActivityTimelineItem[],
detailItemID: string
): string {
const item = timelineItems.find(
(candidate) => itemID(candidate) === detailItemID
);
const eventID = item?.eventId?.trim();
return eventID ? `event:${eventID}` : detailItemID;
}
export function normalizeToolCallID(callID: string): string {
return callID.startsWith("call:") ? callID.slice("call:".length) : callID;
}
export function dedupeTimelineRowsByID(
rows: AgentGUITimelineRow[]
): AgentGUITimelineRow[] {
const byID = new Map<string, AgentGUITimelineRow>();
for (const row of rows) {
byID.set(row.id, row);
}
return sortTimelineRows([...byID.values()]);
}
export function sortTimelineRows(
rows: AgentGUITimelineRow[]
): AgentGUITimelineRow[] {
return rows.sort(
(a, b) =>
a.occurredAtUnixMs - b.occurredAtUnixMs || a.id.localeCompare(b.id)
);
}
export function latestTimelineTime(
timelineItems: readonly WorkspaceAgentActivityTimelineItem[]
): number {
return Math.max(
0,
...timelineItems.map(
(item) => item.occurredAtUnixMs ?? item.createdAtUnixMs ?? 0
)
);
}
export function stringPayload(value: unknown): string {
return typeof value === "string" ? value.trim() : "";
}
export function objectPayload(value: unknown): Record<string, unknown> | null {
return value && typeof value === "object" && !Array.isArray(value)
? (value as Record<string, unknown>)
: null;
}
export function hashStringToPositiveInt(value: string): number {
let hash = 0;
for (let index = 0; index < value.length; index += 1) {
hash = (hash * 31 + value.charCodeAt(index)) | 0;
}
return Math.max(1, Math.abs(hash));
}