import { type TreeIndex } from "../forest.js"; import type { TreeNode } from "../types.js"; import type { TimelineSpan } from "./spans.js"; export type SpanGroup = { key: string; spanIds: string[]; count: number; totalSelfMs: number; /** Of the spans' wall-clock envelope. MAY exceed 1.0 for parallel work * (two forked branches busy 10s each in a 10s window = 2.0) — that is * true compute time, distinct from the nesting double-count that * self-time prevents. */ share: number; models: string[]; }; export declare function groupSpans(spans: TimelineSpan[], root: TreeNode, index?: TreeIndex): SpanGroup[]; /** Single-lookup convenience (occurrences re-resolves its remembered key * through this once per setData). Builds its own tree index; bulk callers * go through groupSpans, which builds it once. */ export declare function groupKeyOf(spanId: string, root: TreeNode): string; /** How a span is named everywhere a short name is needed: tool name, * `node X`, `llm(model)`, else the span kind. Built ON spanText's * spanDetail so the tree and the timeline can never disagree. */ export declare function spanDisplayName(node: TreeNode): string; /** Per-scope threadId→label maps, built once per process subtree instead * of re-scanning the scope for every llm call (O(k·n) otherwise). */ export type ScopeLabelCache = Record>; /** Process scope for legacy display labels. Fresh tool stores also reuse * local thread ids within this scope; this is not a thread identity. */ export declare function threadScopeOf(node: TreeNode, index: TreeIndex): TreeNode; export declare function scopeThreadLabels(scope: TreeNode, cache: ScopeLabelCache): Record; export declare function unambiguousThreadLabels(scope: TreeNode, cache: ScopeLabelCache): Record;