fix(logs): summarize operational tool previews
This commit is contained in:
parent
cade7b4fdb
commit
8bc460721f
2 changed files with 427 additions and 14 deletions
|
|
@ -1257,6 +1257,149 @@ Reply to this comment using MCP tool task_add_comment.
|
||||||
preview: '2 processes - vite dev running; pnpm test exited',
|
preview: '2 processes - vite dev running; pnpm test exited',
|
||||||
});
|
});
|
||||||
expect(processResult.items[0]?.preview).not.toContain('[{');
|
expect(processResult.items[0]?.preview).not.toContain('[{');
|
||||||
|
|
||||||
|
const taskUpdateResult = extractMemberLogPreviewItems({
|
||||||
|
provider: 'opencode_runtime',
|
||||||
|
maxItems: 3,
|
||||||
|
textLimit: 160,
|
||||||
|
messages: [
|
||||||
|
message({
|
||||||
|
uuid: 'task-update-call',
|
||||||
|
timestamp: '2026-04-01T10:00:00.000Z',
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: 'tool_use',
|
||||||
|
id: 'tool-task-update',
|
||||||
|
name: 'agent-teams_task_update',
|
||||||
|
input: {
|
||||||
|
taskId: 'abc12345-0000-0000-0000-000000000000',
|
||||||
|
status: 'in_progress',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
message({
|
||||||
|
uuid: 'task-update-result',
|
||||||
|
type: 'user',
|
||||||
|
role: 'user',
|
||||||
|
timestamp: '2026-04-01T10:01:00.000Z',
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: 'tool_result',
|
||||||
|
tool_use_id: 'tool-task-update',
|
||||||
|
content: {
|
||||||
|
taskId: 'abc12345-0000-0000-0000-000000000000',
|
||||||
|
status: 'in_progress',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(taskUpdateResult.items[0]).toMatchObject({
|
||||||
|
kind: 'tool_result',
|
||||||
|
title: 'Task updated',
|
||||||
|
preview: '#abc12345 -> in_progress',
|
||||||
|
});
|
||||||
|
|
||||||
|
const remainingOperationalTools = [
|
||||||
|
{
|
||||||
|
toolName: 'agent-teams_lead_briefing',
|
||||||
|
input: { teamName: 'relay-works-10' },
|
||||||
|
result: 'Lead briefing for team relay-works-10. CRITICAL: hidden rules',
|
||||||
|
expectedTitle: 'Lead briefing',
|
||||||
|
expectedPreview: 'Loaded lead briefing for relay-works-10',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
toolName: 'agent-teams_runtime_deliver_message',
|
||||||
|
input: { to: 'bob', text: 'Follow-up ready', runtimeSessionId: 'ses-secret' },
|
||||||
|
result: 'ok',
|
||||||
|
expectedTitle: 'Runtime delivery',
|
||||||
|
expectedPreview: 'Delivered to bob - Follow-up ready',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
toolName: 'agent-teams_cross_team_list_targets',
|
||||||
|
input: { teamName: 'relay-works-10' },
|
||||||
|
result: JSON.stringify([{ teamName: 'qa-team' }, { name: 'design-team' }]),
|
||||||
|
expectedTitle: 'Cross-team targets',
|
||||||
|
expectedPreview: '2 teams - qa-team; design-team',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
toolName: 'agent-teams_cross_team_get_outbox',
|
||||||
|
input: { teamName: 'relay-works-10' },
|
||||||
|
result: {
|
||||||
|
messages: [{ toTeam: 'qa-team', summary: 'Need smoke-test help' }],
|
||||||
|
},
|
||||||
|
expectedTitle: 'Cross-team outbox',
|
||||||
|
expectedPreview: '1 message - to qa-team: Need smoke-test help',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
toolName: 'agent-teams_process_register',
|
||||||
|
input: { label: 'vite dev', command: 'pnpm dev' },
|
||||||
|
result: { process: { label: 'vite dev', status: 'running' } },
|
||||||
|
expectedTitle: 'Process registered',
|
||||||
|
expectedPreview: 'Registered vite dev running',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
toolName: 'agent-teams_process_stop',
|
||||||
|
input: { label: 'vite dev' },
|
||||||
|
result: 'ok',
|
||||||
|
expectedTitle: 'Process stopped',
|
||||||
|
expectedPreview: 'Stopped vite dev',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
toolName: 'agent-teams_process_unregister',
|
||||||
|
input: { pid: 123 },
|
||||||
|
result: 'ok',
|
||||||
|
expectedTitle: 'Process unregistered',
|
||||||
|
expectedPreview: 'Unregistered 123',
|
||||||
|
},
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
for (const [index, tool] of remainingOperationalTools.entries()) {
|
||||||
|
const result = extractMemberLogPreviewItems({
|
||||||
|
provider: 'opencode_runtime',
|
||||||
|
maxItems: 3,
|
||||||
|
textLimit: 160,
|
||||||
|
messages: [
|
||||||
|
message({
|
||||||
|
uuid: `remaining-tool-call-${index}`,
|
||||||
|
timestamp: '2026-04-01T10:00:00.000Z',
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: 'tool_use',
|
||||||
|
id: `tool-remaining-${index}`,
|
||||||
|
name: tool.toolName,
|
||||||
|
input: tool.input,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
message({
|
||||||
|
uuid: `remaining-tool-result-${index}`,
|
||||||
|
type: 'user',
|
||||||
|
role: 'user',
|
||||||
|
timestamp: '2026-04-01T10:01:00.000Z',
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
type: 'tool_result',
|
||||||
|
tool_use_id: `tool-remaining-${index}`,
|
||||||
|
content: tool.result,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.items[0]).toMatchObject({
|
||||||
|
kind: 'tool_result',
|
||||||
|
title: tool.expectedTitle,
|
||||||
|
preview: tool.expectedPreview,
|
||||||
|
});
|
||||||
|
expect(`${result.items[0]?.title ?? ''} ${result.items[0]?.preview ?? ''}`).not.toMatch(
|
||||||
|
/CRITICAL|runtimeSessionId|agent_teams_|process_register|cross_team_/i
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('uses concrete names for generic runtime tool results', () => {
|
it('uses concrete names for generic runtime tool results', () => {
|
||||||
|
|
|
||||||
|
|
@ -136,20 +136,24 @@ function timestampIso(value: Date | string): string {
|
||||||
function stripAngleTags(value: string): string {
|
function stripAngleTags(value: string): string {
|
||||||
let result = '';
|
let result = '';
|
||||||
let insideTag = false;
|
let insideTag = false;
|
||||||
for (const char of value) {
|
for (let index = 0; index < value.length; index += 1) {
|
||||||
if (char === '<') {
|
const char = value[index];
|
||||||
insideTag = true;
|
if (!insideTag && char === '<') {
|
||||||
result += ' ';
|
const next = value[index + 1] ?? '';
|
||||||
|
if (/[A-Za-z/!]/.test(next)) {
|
||||||
|
insideTag = true;
|
||||||
|
result += ' ';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (insideTag) {
|
||||||
|
if (char === '>') {
|
||||||
|
insideTag = false;
|
||||||
|
result += ' ';
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (char === '>') {
|
result += char;
|
||||||
insideTag = false;
|
|
||||||
result += ' ';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!insideTag) {
|
|
||||||
result += char;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -468,6 +472,8 @@ function formatToolTitle(toolName: string): string {
|
||||||
const canonical = canonicalToolName(toolName);
|
const canonical = canonicalToolName(toolName);
|
||||||
if (canonical === 'sendmessage' || canonical === 'message_send') return 'Send message';
|
if (canonical === 'sendmessage' || canonical === 'message_send') return 'Send message';
|
||||||
if (canonical === 'cross_team_send') return 'Cross-team message';
|
if (canonical === 'cross_team_send') return 'Cross-team message';
|
||||||
|
if (canonical === 'cross_team_list_targets') return 'List teams';
|
||||||
|
if (canonical === 'cross_team_get_outbox') return 'Cross-team outbox';
|
||||||
if (canonical === 'runtime_deliver_message') return 'Runtime delivery';
|
if (canonical === 'runtime_deliver_message') return 'Runtime delivery';
|
||||||
if (canonical === 'runtime_task_event') return 'Runtime task event';
|
if (canonical === 'runtime_task_event') return 'Runtime task event';
|
||||||
if (canonical === 'runtime_heartbeat') return 'Runtime heartbeat';
|
if (canonical === 'runtime_heartbeat') return 'Runtime heartbeat';
|
||||||
|
|
@ -492,6 +498,7 @@ function formatToolTitle(toolName: string): string {
|
||||||
if (canonical === 'review_approve') return 'Approve review';
|
if (canonical === 'review_approve') return 'Approve review';
|
||||||
if (canonical === 'review_request_changes') return 'Request changes';
|
if (canonical === 'review_request_changes') return 'Request changes';
|
||||||
if (canonical === 'runtime_bootstrap_checkin') return 'Runtime check-in';
|
if (canonical === 'runtime_bootstrap_checkin') return 'Runtime check-in';
|
||||||
|
if (canonical === 'lead_briefing') return 'Lead briefing';
|
||||||
if (canonical === 'member_briefing') return 'Member briefing';
|
if (canonical === 'member_briefing') return 'Member briefing';
|
||||||
if (canonical === 'member_work_sync_status') return 'Work sync status';
|
if (canonical === 'member_work_sync_status') return 'Work sync status';
|
||||||
if (canonical === 'member_work_sync_report') return 'Work sync report';
|
if (canonical === 'member_work_sync_report') return 'Work sync report';
|
||||||
|
|
@ -499,6 +506,9 @@ function formatToolTitle(toolName: string): string {
|
||||||
if (canonical === 'task_update') return 'Update task';
|
if (canonical === 'task_update') return 'Update task';
|
||||||
if (canonical === 'task_delete') return 'Delete task';
|
if (canonical === 'task_delete') return 'Delete task';
|
||||||
if (canonical === 'process_list') return 'List processes';
|
if (canonical === 'process_list') return 'List processes';
|
||||||
|
if (canonical === 'process_register') return 'Register process';
|
||||||
|
if (canonical === 'process_stop') return 'Stop process';
|
||||||
|
if (canonical === 'process_unregister') return 'Unregister process';
|
||||||
return humanizeFallbackToolName(toolName);
|
return humanizeFallbackToolName(toolName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -525,14 +535,16 @@ function isToolUseSupersededBySuccessResult(toolName: string): boolean {
|
||||||
return (
|
return (
|
||||||
canonical === 'sendmessage' ||
|
canonical === 'sendmessage' ||
|
||||||
canonical === 'message_send' ||
|
canonical === 'message_send' ||
|
||||||
canonical === 'cross_team_send' ||
|
canonical.startsWith('cross_team_') ||
|
||||||
canonical === 'runtime_deliver_message' ||
|
canonical === 'runtime_deliver_message' ||
|
||||||
canonical === 'runtime_bootstrap_checkin' ||
|
canonical === 'runtime_bootstrap_checkin' ||
|
||||||
canonical === 'runtime_heartbeat' ||
|
canonical === 'runtime_heartbeat' ||
|
||||||
canonical === 'runtime_task_event' ||
|
canonical === 'runtime_task_event' ||
|
||||||
|
canonical === 'lead_briefing' ||
|
||||||
canonical === 'member_briefing' ||
|
canonical === 'member_briefing' ||
|
||||||
canonical === 'member_work_sync_status' ||
|
canonical === 'member_work_sync_status' ||
|
||||||
canonical === 'member_work_sync_report' ||
|
canonical === 'member_work_sync_report' ||
|
||||||
|
canonical.startsWith('process_') ||
|
||||||
canonical.startsWith('task_') ||
|
canonical.startsWith('task_') ||
|
||||||
canonical.startsWith('review_')
|
canonical.startsWith('review_')
|
||||||
);
|
);
|
||||||
|
|
@ -765,6 +777,172 @@ function formatProcessCollectionArrayPayload(items: readonly unknown[]): KnownPa
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function processLabelFromPayload(
|
||||||
|
payload: Record<string, unknown>,
|
||||||
|
fallbackInput?: Record<string, unknown> | null
|
||||||
|
): string | null {
|
||||||
|
const process = asRecord(payload.process) ?? asRecord(fallbackInput?.process) ?? undefined;
|
||||||
|
return (
|
||||||
|
[
|
||||||
|
stringField(payload, 'label'),
|
||||||
|
stringField(payload, 'name'),
|
||||||
|
stringField(payload, 'command'),
|
||||||
|
stringField(payload, 'processId'),
|
||||||
|
stringField(payload, 'id'),
|
||||||
|
stringifyPrimitive(payload.pid),
|
||||||
|
stringField(process, 'label'),
|
||||||
|
stringField(process, 'name'),
|
||||||
|
stringField(process, 'command'),
|
||||||
|
stringField(process, 'processId'),
|
||||||
|
stringField(process, 'id'),
|
||||||
|
stringifyPrimitive(process?.pid),
|
||||||
|
stringField(fallbackInput ?? undefined, 'label'),
|
||||||
|
stringField(fallbackInput ?? undefined, 'name'),
|
||||||
|
stringField(fallbackInput ?? undefined, 'command'),
|
||||||
|
stringField(fallbackInput ?? undefined, 'processId'),
|
||||||
|
stringField(fallbackInput ?? undefined, 'id'),
|
||||||
|
stringifyPrimitive(fallbackInput?.pid),
|
||||||
|
].find((value) => typeof value === 'string' && value.trim().length > 0) ?? null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatProcessLifecyclePayload(
|
||||||
|
payload: Record<string, unknown>,
|
||||||
|
canonicalToolNameValue: string | null,
|
||||||
|
fallbackInput?: Record<string, unknown> | null
|
||||||
|
): KnownPayloadPreview | null {
|
||||||
|
const canonical = canonicalToolNameValue ?? '';
|
||||||
|
if (
|
||||||
|
canonical !== 'process_register' &&
|
||||||
|
canonical !== 'process_stop' &&
|
||||||
|
canonical !== 'process_unregister'
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const label = processLabelFromPayload(payload, fallbackInput);
|
||||||
|
const status =
|
||||||
|
stringField(payload, 'status') ??
|
||||||
|
stringField(asRecord(payload.process), 'status') ??
|
||||||
|
stringField(fallbackInput ?? undefined, 'status');
|
||||||
|
|
||||||
|
if (canonical === 'process_register') {
|
||||||
|
const suffix = status && label ? ` ${status}` : '';
|
||||||
|
return {
|
||||||
|
title: 'Process registered',
|
||||||
|
text: label ? `Registered ${label}${suffix}` : 'Registered process',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (canonical === 'process_stop') {
|
||||||
|
return {
|
||||||
|
title: 'Process stopped',
|
||||||
|
text: label ? `Stopped ${label}` : 'Stopped process',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
title: 'Process unregistered',
|
||||||
|
text: label ? `Unregistered ${label}` : 'Unregistered process',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatCrossTeamTargetItem(item: Record<string, unknown>): string | null {
|
||||||
|
return (
|
||||||
|
stringField(item, 'teamName') ??
|
||||||
|
stringField(item, 'name') ??
|
||||||
|
stringField(item, 'id') ??
|
||||||
|
stringField(item, 'slug')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatCrossTeamOutboxItem(item: Record<string, unknown>): string | null {
|
||||||
|
const target =
|
||||||
|
stringField(item, 'toTeam') ??
|
||||||
|
stringField(item, 'targetTeam') ??
|
||||||
|
stringField(item, 'teamName') ??
|
||||||
|
stringField(item, 'target');
|
||||||
|
const summary =
|
||||||
|
stringField(item, 'summary') ??
|
||||||
|
stringField(item, 'text') ??
|
||||||
|
stringField(item, 'message') ??
|
||||||
|
stringField(item, 'content');
|
||||||
|
if (target && summary) return `to ${target}: ${summary}`;
|
||||||
|
return target ?? summary;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatCrossTeamCollectionArrayPayload(
|
||||||
|
items: readonly unknown[],
|
||||||
|
canonicalToolNameValue: string | null
|
||||||
|
): KnownPayloadPreview | null {
|
||||||
|
const canonical = canonicalToolNameValue ?? '';
|
||||||
|
const title =
|
||||||
|
canonical === 'cross_team_list_targets'
|
||||||
|
? 'Cross-team targets'
|
||||||
|
: canonical === 'cross_team_get_outbox'
|
||||||
|
? 'Cross-team outbox'
|
||||||
|
: null;
|
||||||
|
if (!title) return null;
|
||||||
|
|
||||||
|
const records = items
|
||||||
|
.map((item) => asRecord(item))
|
||||||
|
.filter((item): item is Record<string, unknown> => Boolean(item));
|
||||||
|
const summaries = records
|
||||||
|
.slice(0, 3)
|
||||||
|
.map((item) =>
|
||||||
|
canonical === 'cross_team_list_targets'
|
||||||
|
? formatCrossTeamTargetItem(item)
|
||||||
|
: formatCrossTeamOutboxItem(item)
|
||||||
|
)
|
||||||
|
.filter(Boolean);
|
||||||
|
const remainingCount = Math.max(0, records.length - summaries.length);
|
||||||
|
const moreText = remainingCount > 0 ? `; +${remainingCount} more` : '';
|
||||||
|
|
||||||
|
if (canonical === 'cross_team_list_targets') {
|
||||||
|
const countText = `${records.length} ${records.length === 1 ? 'team' : 'teams'}`;
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
text: summaries.length > 0 ? `${countText} - ${summaries.join('; ')}${moreText}` : countText,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const countText = `${records.length} ${records.length === 1 ? 'message' : 'messages'}`;
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
text: summaries.length > 0 ? `${countText} - ${summaries.join('; ')}${moreText}` : countText,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatCrossTeamCollectionPayload(
|
||||||
|
payload: Record<string, unknown>,
|
||||||
|
canonicalToolNameValue: string | null
|
||||||
|
): KnownPayloadPreview | null {
|
||||||
|
const canonical = canonicalToolNameValue ?? '';
|
||||||
|
if (canonical !== 'cross_team_list_targets' && canonical !== 'cross_team_get_outbox') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rawItems =
|
||||||
|
(Array.isArray(payload.targets) ? payload.targets : null) ??
|
||||||
|
(Array.isArray(payload.teams) ? payload.teams : null) ??
|
||||||
|
(Array.isArray(payload.messages) ? payload.messages : null) ??
|
||||||
|
(Array.isArray(payload.outbox) ? payload.outbox : null) ??
|
||||||
|
(Array.isArray(payload.items) ? payload.items : null);
|
||||||
|
if (rawItems) {
|
||||||
|
return formatCrossTeamCollectionArrayPayload(rawItems, canonical);
|
||||||
|
}
|
||||||
|
|
||||||
|
const summary =
|
||||||
|
stringField(payload, 'summary') ??
|
||||||
|
stringField(payload, 'message') ??
|
||||||
|
stringField(payload, 'text');
|
||||||
|
if (summary) {
|
||||||
|
return {
|
||||||
|
title: canonical === 'cross_team_list_targets' ? 'Cross-team targets' : 'Cross-team outbox',
|
||||||
|
text: summary,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
function formatRelationshipPayload(
|
function formatRelationshipPayload(
|
||||||
payload: Record<string, unknown>,
|
payload: Record<string, unknown>,
|
||||||
fallbackInput?: Record<string, unknown> | null
|
fallbackInput?: Record<string, unknown> | null
|
||||||
|
|
@ -959,6 +1137,26 @@ function formatRuntimePayload(
|
||||||
text: memberName ? `${memberName} checked in` : 'Runtime checked in',
|
text: memberName ? `${memberName} checked in` : 'Runtime checked in',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (canonical === 'runtime_deliver_message') {
|
||||||
|
const target =
|
||||||
|
stringField(payload, 'to') ??
|
||||||
|
stringField(payload, 'target') ??
|
||||||
|
stringField(fallbackInput ?? undefined, 'to') ??
|
||||||
|
stringField(fallbackInput ?? undefined, 'target');
|
||||||
|
const summary =
|
||||||
|
stringField(payload, 'summary') ??
|
||||||
|
stringField(payload, 'message') ??
|
||||||
|
stringField(payload, 'text') ??
|
||||||
|
stringField(fallbackInput ?? undefined, 'summary') ??
|
||||||
|
stringField(fallbackInput ?? undefined, 'message') ??
|
||||||
|
stringField(fallbackInput ?? undefined, 'text');
|
||||||
|
if (target && summary) {
|
||||||
|
return { title: 'Runtime delivery', text: `Delivered to ${target} - ${summary}` };
|
||||||
|
}
|
||||||
|
if (target) return { title: 'Runtime delivery', text: `Delivered to ${target}` };
|
||||||
|
if (summary) return { title: 'Runtime delivery', text: summary };
|
||||||
|
return { title: 'Runtime delivery', text: 'Delivered runtime message' };
|
||||||
|
}
|
||||||
if (canonical === 'runtime_heartbeat') {
|
if (canonical === 'runtime_heartbeat') {
|
||||||
return {
|
return {
|
||||||
title: 'Runtime heartbeat',
|
title: 'Runtime heartbeat',
|
||||||
|
|
@ -985,6 +1183,14 @@ function formatRuntimePayload(
|
||||||
text: memberName ? `Loaded briefing for ${memberName}` : 'Loaded member briefing',
|
text: memberName ? `Loaded briefing for ${memberName}` : 'Loaded member briefing',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (canonical === 'lead_briefing') {
|
||||||
|
const teamName =
|
||||||
|
stringField(payload, 'teamName') ?? stringField(fallbackInput ?? undefined, 'teamName');
|
||||||
|
return {
|
||||||
|
title: 'Lead briefing',
|
||||||
|
text: teamName ? `Loaded lead briefing for ${teamName}` : 'Loaded lead briefing',
|
||||||
|
};
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1125,14 +1331,25 @@ function formatPlainToolResultStatus(
|
||||||
if (!toolContext) {
|
if (!toolContext) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (toolContext.canonicalName === 'member_briefing') {
|
if (
|
||||||
|
toolContext.canonicalName === 'member_briefing' ||
|
||||||
|
toolContext.canonicalName === 'lead_briefing'
|
||||||
|
) {
|
||||||
const memberMatch = /^member briefing for\s+([^\s]+)\s+on team\b/i.exec(
|
const memberMatch = /^member briefing for\s+([^\s]+)\s+on team\b/i.exec(
|
||||||
compactWhitespace(value)
|
compactWhitespace(value)
|
||||||
);
|
);
|
||||||
|
const teamMatch = /^lead briefing for team\s+([^\s.]+)/i.exec(compactWhitespace(value));
|
||||||
const memberName =
|
const memberName =
|
||||||
memberMatch?.[1] ??
|
memberMatch?.[1] ??
|
||||||
stringField(asRecord(toolContext.input), 'memberName') ??
|
stringField(asRecord(toolContext.input), 'memberName') ??
|
||||||
stringField(asRecord(toolContext.input), 'member');
|
stringField(asRecord(toolContext.input), 'member');
|
||||||
|
if (toolContext.canonicalName === 'lead_briefing') {
|
||||||
|
const teamName = teamMatch?.[1] ?? stringField(asRecord(toolContext.input), 'teamName');
|
||||||
|
return {
|
||||||
|
title: 'Lead briefing',
|
||||||
|
text: teamName ? `Loaded lead briefing for ${teamName}` : 'Loaded lead briefing',
|
||||||
|
};
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
title: 'Member briefing',
|
title: 'Member briefing',
|
||||||
text: memberName ? `Loaded briefing for ${memberName}` : 'Loaded member briefing',
|
text: memberName ? `Loaded briefing for ${memberName}` : 'Loaded member briefing',
|
||||||
|
|
@ -1151,12 +1368,30 @@ function formatPlainToolResultStatus(
|
||||||
const text = fallbackInput ? formatCrossTeamPayload(fallbackInput) : null;
|
const text = fallbackInput ? formatCrossTeamPayload(fallbackInput) : null;
|
||||||
return text ? { title: 'Cross-team message', text } : null;
|
return text ? { title: 'Cross-team message', text } : null;
|
||||||
}
|
}
|
||||||
|
if (toolContext.canonicalName === 'cross_team_list_targets') {
|
||||||
|
const teamName = stringField(fallbackInput ?? undefined, 'teamName');
|
||||||
|
return {
|
||||||
|
title: 'Cross-team targets',
|
||||||
|
text: teamName ? `Listed teams for ${teamName}` : 'Listed cross-team targets',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (toolContext.canonicalName === 'cross_team_get_outbox') {
|
||||||
|
const teamName = stringField(fallbackInput ?? undefined, 'teamName');
|
||||||
|
return {
|
||||||
|
title: 'Cross-team outbox',
|
||||||
|
text: teamName ? `Loaded outbox for ${teamName}` : 'Loaded cross-team outbox',
|
||||||
|
};
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
toolContext.canonicalName === 'member_work_sync_status' ||
|
toolContext.canonicalName === 'member_work_sync_status' ||
|
||||||
toolContext.canonicalName === 'member_work_sync_report'
|
toolContext.canonicalName === 'member_work_sync_report'
|
||||||
) {
|
) {
|
||||||
return formatWorkSyncPayload({}, toolContext.canonicalName, fallbackInput);
|
return formatWorkSyncPayload({}, toolContext.canonicalName, fallbackInput);
|
||||||
}
|
}
|
||||||
|
const processText = formatProcessLifecyclePayload({}, toolContext.canonicalName, fallbackInput);
|
||||||
|
if (processText) {
|
||||||
|
return processText;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
formatTaskToolPayload({}, toolContext.canonicalName, fallbackInput) ??
|
formatTaskToolPayload({}, toolContext.canonicalName, fallbackInput) ??
|
||||||
formatRuntimePayload({}, toolContext.canonicalName, fallbackInput)
|
formatRuntimePayload({}, toolContext.canonicalName, fallbackInput)
|
||||||
|
|
@ -1268,6 +1503,14 @@ function formatKnownPayloadPreview(
|
||||||
if (workSyncText) {
|
if (workSyncText) {
|
||||||
return workSyncText;
|
return workSyncText;
|
||||||
}
|
}
|
||||||
|
const processLifecycleText = formatProcessLifecyclePayload(payload, canonical, fallbackInput);
|
||||||
|
if (processLifecycleText) {
|
||||||
|
return processLifecycleText;
|
||||||
|
}
|
||||||
|
const crossTeamCollectionText = formatCrossTeamCollectionPayload(payload, canonical);
|
||||||
|
if (crossTeamCollectionText) {
|
||||||
|
return crossTeamCollectionText;
|
||||||
|
}
|
||||||
if (canonical === 'process_list') {
|
if (canonical === 'process_list') {
|
||||||
const processText = formatProcessCollectionPayload(payload);
|
const processText = formatProcessCollectionPayload(payload);
|
||||||
if (processText) {
|
if (processText) {
|
||||||
|
|
@ -1340,6 +1583,16 @@ function previewUnknownValue(
|
||||||
if (knownCollection) {
|
if (knownCollection) {
|
||||||
return { ...truncatePreview(knownCollection.text, limit), title: knownCollection.title };
|
return { ...truncatePreview(knownCollection.text, limit), title: knownCollection.title };
|
||||||
}
|
}
|
||||||
|
const crossTeamCollection = formatCrossTeamCollectionArrayPayload(
|
||||||
|
value,
|
||||||
|
toolContext?.canonicalName ?? null
|
||||||
|
);
|
||||||
|
if (crossTeamCollection) {
|
||||||
|
return {
|
||||||
|
...truncatePreview(crossTeamCollection.text, limit),
|
||||||
|
title: crossTeamCollection.title,
|
||||||
|
};
|
||||||
|
}
|
||||||
if (toolContext?.canonicalName === 'process_list') {
|
if (toolContext?.canonicalName === 'process_list') {
|
||||||
const processCollection = formatProcessCollectionArrayPayload(value);
|
const processCollection = formatProcessCollectionArrayPayload(value);
|
||||||
return { ...truncatePreview(processCollection.text, limit), title: processCollection.title };
|
return { ...truncatePreview(processCollection.text, limit), title: processCollection.title };
|
||||||
|
|
@ -1396,6 +1649,19 @@ function previewToolInputValue(toolName: string, value: unknown, limit: number):
|
||||||
return truncatePreview(formatted, limit);
|
return truncatePreview(formatted, limit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (canonical === 'cross_team_list_targets' || canonical === 'cross_team_get_outbox') {
|
||||||
|
const payload = recordFromUnknown(value);
|
||||||
|
const teamName = payload ? stringField(payload, 'teamName') : null;
|
||||||
|
const text =
|
||||||
|
canonical === 'cross_team_list_targets'
|
||||||
|
? teamName
|
||||||
|
? `for ${teamName}`
|
||||||
|
: 'List cross-team targets'
|
||||||
|
: teamName
|
||||||
|
? `for ${teamName}`
|
||||||
|
: 'Read cross-team outbox';
|
||||||
|
return truncatePreview(text, limit);
|
||||||
|
}
|
||||||
const payload = recordFromUnknown(value);
|
const payload = recordFromUnknown(value);
|
||||||
if (payload) {
|
if (payload) {
|
||||||
const runtimeFormatted = formatRuntimePayload(payload, canonical, payload);
|
const runtimeFormatted = formatRuntimePayload(payload, canonical, payload);
|
||||||
|
|
@ -1406,6 +1672,10 @@ function previewToolInputValue(toolName: string, value: unknown, limit: number):
|
||||||
if (workSyncFormatted) {
|
if (workSyncFormatted) {
|
||||||
return truncatePreview(workSyncFormatted.text, limit);
|
return truncatePreview(workSyncFormatted.text, limit);
|
||||||
}
|
}
|
||||||
|
const processFormatted = formatProcessLifecyclePayload(payload, canonical, payload);
|
||||||
|
if (processFormatted) {
|
||||||
|
return truncatePreview(processFormatted.text, limit);
|
||||||
|
}
|
||||||
const taskFormatted = formatTaskToolInputPayload(canonical, payload);
|
const taskFormatted = formatTaskToolInputPayload(canonical, payload);
|
||||||
if (taskFormatted) {
|
if (taskFormatted) {
|
||||||
return truncatePreview(taskFormatted, limit);
|
return truncatePreview(taskFormatted, limit);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue