← 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/sweep-stale-awaiting.ts
81 lines · 2.3 KB · TypeScriptimport { packageStorage } from 'kody:runtime'
import handleSentryWebhook from './handle-sentry-webhook.ts'
import { truncate } from './shared.ts'
import { findStaleAwaitingIssues } from './awaiting-seer.ts'
import type {
SweepStaleAwaitingInput,
SweepStaleAwaitingResult,
} from './types.ts'
const defaultLimit = 8
/**
* Quiet-period driver for the awaiting-Seer grace window. Automation-owned
* Seer runs produce no later webhook when Sentry declines an issue, and the
* inbound-issue sweeper only runs when another issue arrives. This export
* redelivers a bounded oldest-first page of stale `awaiting-seer` /
* `awaiting-seer-pr` records through the normal webhook handler so claims,
* caps, and the repo lease still apply. The package job of the same name
* invokes this with no params every 15 minutes.
*/
export default async function sweepStaleAwaiting(
input: SweepStaleAwaitingInput = {},
): Promise<SweepStaleAwaitingResult> {
const limit = Math.min(
20,
Math.max(1, Math.floor(Number(input?.limit) || defaultLimit)),
)
const dryRun = input?.dryRun === true
const stale = await findStaleAwaitingIssues(packageStorage(), limit)
if (dryRun) {
return {
ok: true,
dryRun: true,
swept: stale.length,
actions: stale.map((record) => ({
issueId: String(record.issueId),
shortId: record.shortId ?? null,
projectSlug: String(record.projectSlug),
status: record.status,
})),
}
}
const actions = []
for (const record of stale) {
const delivery = await handleSentryWebhook({
request: {
headers: { 'sentry-hook-resource': 'issue' },
json: {
action: 'created',
kodySweeperRescue: true,
data: {
issue: {
id: String(record.issueId),
shortId: record.shortId ?? null,
title: record.title ?? null,
culprit: null,
level: 'error',
permalink: record.link ?? null,
project: { slug: record.projectSlug },
},
},
},
},
}).catch((error) => ({
ok: false,
error: truncate(
error instanceof Error ? error.message : String(error),
200,
),
}))
actions.push({
issueId: String(record.issueId),
shortId: record.shortId ?? null,
projectSlug: String(record.projectSlug),
status: record.status,
delivery,
})
}
return { ok: true, swept: actions.length, actions }
}