style(lens): format native actor conversation handling

This commit is contained in:
moe-berri 2026-10-06 11:55:17 -07:00
parent bead5162d4
commit cd163d5886
3 changed files with 33 additions and 12 deletions

View file

@ -616,11 +616,18 @@ describe("coding sessions", () => {
});
});
it("keeps explicit native actors separate across workflow branches and background resumes", () => {
const span = (id: string, actor: string, parentActor: string | null, offset: number): Span => ({
...root, span_id: id, name: "claude_code.llm_request", type: "llm", framework: "claude-code",
parent_span_id: "root", actor_id: actor, parent_actor_id: parentActor, agent: "general-purpose", start_offset_ms: offset,
...root,
span_id: id,
name: "claude_code.llm_request",
type: "llm",
framework: "claude-code",
parent_span_id: "root",
actor_id: actor,
parent_actor_id: parentActor,
agent: "general-purpose",
start_offset_ms: offset,
});
const spans = [
{ ...root, framework: "claude-code", actor_id: "root-actor", parent_actor_id: null, agent: "claude-code" },
@ -635,6 +642,12 @@ it("keeps explicit native actors separate across workflow branches and backgroun
const groups = groupConversation(items, spans);
const branches = groups.filter((group) => group.kind === "branch");
expect(branches.map((group) => group.id)).toEqual(["actor-one", "actor-two"]);
expect(branches[0].children.map((group) => group.kind === "branch" ? group.id : group.item.span.span_id)).toEqual(["first", "actor-three", "resumed"]);
expect(items.filter((item) => ["first", "resumed"].includes(item.span.span_id)).map((item) => item.agentName)).toEqual(["general-purpose (1)", "general-purpose (1)"]);
expect(branches[0].children.map((group) => (group.kind === "branch" ? group.id : group.item.span.span_id))).toEqual([
"first",
"actor-three",
"resumed",
]);
expect(
items.filter((item) => ["first", "resumed"].includes(item.span.span_id)).map((item) => item.agentName),
).toEqual(["general-purpose (1)", "general-purpose (1)"]);
});

View file

@ -223,7 +223,10 @@ function conversationBranch(span: Span, byId: ReadonlyMap<string, Span>): string
}
function agentIdentity(span: Span, details: ReadonlyMap<string, SpanDetail>): string {
return span.actor_id || (isNativeAgent(span) ? span.span_id : details.get(span.span_id)?.attributes["gen_ai.agent.id"] || span.span_id);
return (
span.actor_id ||
(isNativeAgent(span) ? span.span_id : details.get(span.span_id)?.attributes["gen_ai.agent.id"] || span.span_id)
);
}
function agentLabels(agents: readonly Span[], details: ReadonlyMap<string, SpanDetail>): ReadonlyMap<string, string> {
@ -327,7 +330,9 @@ export function buildConversation(
};
if (combined.length || item.showError) items.push(item);
}
const byBranch = new Map([...spans].sort((a, b) => b.start_offset_ms - a.start_offset_ms).map((span) => [branch(span), span]));
const byBranch = new Map(
[...spans].sort((a, b) => b.start_offset_ms - a.start_offset_ms).map((span) => [branch(span), span]),
);
const agents = [...new Set(conversationSteps(spans).map(branch))].flatMap((id) => {
const span = byId.get(id) ?? byBranch.get(id);
return span ? [span] : [];
@ -342,9 +347,10 @@ export function buildConversation(
.map((item) => ({
...item,
agentId: actor(branch(item.span)),
agentName: item.span.framework === "claude-code" && item.span.actor_id === null
? "Unassigned"
: labels.get(actor(branch(item.span))) || item.span.agent,
agentName:
item.span.framework === "claude-code" && item.span.actor_id === null
? "Unassigned"
: labels.get(actor(branch(item.span))) || item.span.agent,
branchId: branch(item.span),
parentBranchId: (() => {
if (item.span.actor_id) return item.span.parent_actor_id || undefined;
@ -367,7 +373,8 @@ export function groupConversation(items: readonly ConversationItem[], spans: rea
const parentById = new Map(
conversationSteps(spans).flatMap((span) => {
if (span.actor_id) return [[span.actor_id, span.parent_actor_id || undefined] as const];
if (span.framework === "claude-code" && span.actor_id === null) return [[conversationBranch(span, byId), undefined] as const];
if (span.framework === "claude-code" && span.actor_id === null)
return [[conversationBranch(span, byId), undefined] as const];
const branch = byId.get(conversationBranch(span, byId));
if (!branch) return [];
const parent = branch.parent_span_id ? byId.get(branch.parent_span_id) : undefined;

View file

@ -113,7 +113,8 @@ export function errorSource(span: Span): ErrorSource | null {
type GroupOrSpan = Span | { group: Span[] };
const groupKey = (span: Pick<Span, "name" | "type" | "agent" | "actor_id">): string => `${span.actor_id ?? span.agent}|${span.name}|${span.type}`;
const groupKey = (span: Pick<Span, "name" | "type" | "agent" | "actor_id">): string =>
`${span.actor_id ?? span.agent}|${span.name}|${span.type}`;
/** Siblings sharing agent + name + type fold into one group once there are enough of them (or enough failures). */
function groupChildren(children: readonly Span[]): GroupOrSpan[] {