fix(logs): scope graph preview lane requests

This commit is contained in:
777genius 2026-05-07 20:14:59 +03:00
parent 7c39fbd8e7
commit 0f9f79da66
5 changed files with 42 additions and 13 deletions

View file

@ -26,10 +26,18 @@ function buildRequestKey(input: {
textLimit: number; textLimit: number;
forceRefresh?: boolean; forceRefresh?: boolean;
}): string { }): string {
const laneEntries = Object.entries(input.laneIdsByMember) const laneEntriesByMember = new Map<string, string>();
.map(([memberName, laneId]) => [normalizeMemberName(memberName), laneId.trim()] as const) for (const [memberName, laneId] of Object.entries(input.laneIdsByMember)) {
.filter(([, laneId]) => laneId.length > 0) const normalizedMemberName = normalizeMemberName(memberName);
.sort((left, right) => left[0].localeCompare(right[0])); const trimmedLaneId = laneId.trim();
if (!normalizedMemberName || !trimmedLaneId || laneEntriesByMember.has(normalizedMemberName)) {
continue;
}
laneEntriesByMember.set(normalizedMemberName, trimmedLaneId);
}
const laneEntries = Array.from(laneEntriesByMember.entries()).sort((left, right) =>
left[0].localeCompare(right[0])
);
return JSON.stringify([ return JSON.stringify([
input.teamName, input.teamName,
input.memberNames.map(normalizeMemberName).sort((left, right) => left.localeCompare(right)), input.memberNames.map(normalizeMemberName).sort((left, right) => left.localeCompare(right)),
@ -84,6 +92,23 @@ function buildMemberCacheKey(input: {
]); ]);
} }
function buildLaneIdsForMembers(
memberNames: readonly string[],
laneIdsByMember: Readonly<Record<string, string>>
): Record<string, string> {
const result: Record<string, string> = {};
for (const memberName of memberNames) {
const laneId = laneIdForMember(memberName, laneIdsByMember);
if (!laneId) continue;
result[memberName] = laneId;
const normalizedMemberName = normalizeMemberName(memberName);
if (normalizedMemberName && normalizedMemberName !== memberName) {
result[normalizedMemberName] = laneId;
}
}
return result;
}
export function getSafeGraphLogPreviewLaneId( export function getSafeGraphLogPreviewLaneId(
member: ResolvedTeamMember | undefined member: ResolvedTeamMember | undefined
): string | undefined { ): string | undefined {
@ -226,10 +251,11 @@ export function useGraphMemberLogPreviews(input: {
return; return;
} }
const requestedLaneIdsByMember = buildLaneIdsForMembers(membersToRequest, laneIdsByMember);
const requestKey = buildRequestKey({ const requestKey = buildRequestKey({
teamName: input.teamName, teamName: input.teamName,
memberNames: membersToRequest, memberNames: membersToRequest,
laneIdsByMember, laneIdsByMember: requestedLaneIdsByMember,
maxItemsPerMember, maxItemsPerMember,
textLimit, textLimit,
forceRefresh: options?.forceRefresh, forceRefresh: options?.forceRefresh,
@ -247,7 +273,9 @@ export function useGraphMemberLogPreviews(input: {
const requestOptions: MemberLogPreviewRequestOptions = { const requestOptions: MemberLogPreviewRequestOptions = {
maxItemsPerMember, maxItemsPerMember,
textLimit, textLimit,
...(Object.keys(laneIdsByMember).length > 0 ? { laneIdsByMember } : {}), ...(Object.keys(requestedLaneIdsByMember).length > 0
? { laneIdsByMember: requestedLaneIdsByMember }
: {}),
...(options?.forceRefresh ? { forceRefresh: true } : {}), ...(options?.forceRefresh ? { forceRefresh: true } : {}),
}; };
request = api.memberLogStream request = api.memberLogStream

View file

@ -1601,11 +1601,7 @@ Reply to this comment using MCP tool task_add_comment.
title: 'Bash result', title: 'Bash result',
preview: 'Tests passed', preview: 'Tests passed',
}); });
expect(result.items[1]).toMatchObject({ expect(result.items).toHaveLength(1);
kind: 'tool_use',
title: 'Bash',
preview: 'pnpm test',
});
}); });
it('does not label arbitrary message fields as sent messages', () => { it('does not label arbitrary message fields as sent messages', () => {

View file

@ -533,6 +533,8 @@ function buildToolUseKey(input: {
function isToolUseSupersededBySuccessResult(toolName: string): boolean { function isToolUseSupersededBySuccessResult(toolName: string): boolean {
const canonical = canonicalToolName(toolName); const canonical = canonicalToolName(toolName);
return ( return (
canonical === 'bash' ||
canonical === 'shell' ||
canonical === 'sendmessage' || canonical === 'sendmessage' ||
canonical === 'message_send' || canonical === 'message_send' ||
canonical.startsWith('cross_team_') || canonical.startsWith('cross_team_') ||

View file

@ -189,7 +189,7 @@ describe('ClaudeMemberTranscriptPreviewSource', () => {
const result = await source.loadPreview(previewInput({ textLimit: 160 })); const result = await source.loadPreview(previewInput({ textLimit: 160 }));
expect(result.status).toBe('included'); expect(result.status).toBe('included');
expect(result.items.map((item) => item.kind)).toEqual(['tool_result', 'tool_use']); expect(result.items.map((item) => item.kind)).toEqual(['tool_result']);
expect(result.items[0]?.preview?.length).toBeLessThanOrEqual(160); expect(result.items[0]?.preview?.length).toBeLessThanOrEqual(160);
expect(parseFiles).toHaveBeenCalledWith(['/transcripts/latest.jsonl']); expect(parseFiles).toHaveBeenCalledWith(['/transcripts/latest.jsonl']);
}); });

View file

@ -139,7 +139,10 @@ describe('useGraphMemberLogPreviews', () => {
<HookProbe <HookProbe
teamName="alpha-team" teamName="alpha-team"
memberNames={['alice', 'alice']} memberNames={['alice', 'alice']}
laneIdsByMember={{ alice: 'secondary:opencode:alice' }} laneIdsByMember={{
alice: 'secondary:opencode:alice',
bob: 'secondary:opencode:bob',
}}
onState={() => undefined} onState={() => undefined}
/> />
); );