← Public packages
@kentcdodds/sentry-triage
Sentry triage wakes Cole (Grok Bot) per issue: one active wake per repo (lease + queue), loop-safe Discord. Cole may spawn Cursor for isolated repo work.
src/format-discord-report.ts
111 lines · 3.3 KB · TypeScriptimport { formatKentReport } from 'kody:@kentcdodds/discord/format-report'
// Rebundle official v3 application emoji mentions from format-report.
import postMessage from 'kody:@kentcdodds/discord/post-message'
import editMessage from 'kody:@kentcdodds/discord/edit-message'
import { formatReportDecisionFields } from './decision-fields.ts'
import { readTriageSettings } from './settings.ts'
export type SentryReportInput = {
status: string
title?: string | null
shortId?: string | null
issueId?: string | null
projectSlug?: string | null
link?: string | null
summary?: string | null
prUrl?: string | null
prUrls?: string[]
agentUrl?: string | null
mergeCommitUrl?: string | null
deployUrl?: string | null
activityUrl?: string | null
extras?: string[]
context?: string | null
recommendation?: string | null
rightFix?: string | null
whyNotRightFix?: string | null
options?: Array<string | { label?: string; text?: string; difficulty?: string; change?: string }> | string | null
}
function pushUniqueLink(
links: Array<{ label: string; url: string }>,
label: string,
url: string | null | undefined,
) {
const trimmed = typeof url === 'string' ? url.trim() : ''
if (!trimmed) return
if (links.some((link) => link.url === trimmed && link.label === label)) return
links.push({ label, url: trimmed })
}
export function formatSentryReport(input: SentryReportInput) {
const decision = formatReportDecisionFields(input)
const facts = []
if (input.projectSlug) facts.push({ label: 'Project', value: input.projectSlug })
const links = []
pushUniqueLink(links, 'Issue', input.link)
pushUniqueLink(links, 'Activity', input.activityUrl)
if (input.agentUrl === 'grok-bot:cole') {
facts.push({ label: 'Owner', value: 'Cole (Grok Bot)' })
} else {
pushUniqueLink(links, 'Agent', input.agentUrl)
}
pushUniqueLink(links, 'PR', input.prUrl)
for (const url of input.prUrls || []) {
pushUniqueLink(links, 'PR', url)
}
pushUniqueLink(links, 'Merge', input.mergeCommitUrl)
pushUniqueLink(links, 'Deploy', input.deployUrl)
return formatKentReport({
kind: 'sentry',
title:
decision.title ||
String(input.title || 'Sentry issue').trim() ||
'Sentry issue',
status: input.status,
id: input.shortId || input.issueId || undefined,
facts,
context: decision.context,
recommendation: decision.recommendation,
rightFix: decision.rightFix,
whyNotRightFix: decision.whyNotRightFix,
options: decision.options,
summary: decision.summary,
links,
extras: input.extras,
})
}
export async function postSentryReport(input: SentryReportInput) {
const formatted = formatSentryReport(input)
// 429 retries live in @kentcdodds/discord/post-message (honors retry_after).
return postMessage({
channelId: (await readTriageSettings()).discordChannelId,
content: formatted.content,
flags: formatted.flags,
})
}
export async function editSentryReport(
messageId: string,
input: SentryReportInput,
) {
const formatted = formatSentryReport(input)
return editMessage({
channelId: (await readTriageSettings()).discordChannelId,
messageId,
content: formatted.content,
flags: formatted.flags,
})
}
export async function upsertSentryReport(
messageId: string | null | undefined,
input: SentryReportInput,
) {
if (messageId) {
await editSentryReport(messageId, input).catch(() => {})
return { id: messageId }
}
return postSentryReport(input)
}