Skip to content
← Public packages

@kentcdodds/kody-issue-triage

Loop-safe triage for Kody run errors and fleet package-runtime error-rate elevations. Wakes Cole (Grok Bot) to decide; Cursor agents only when Cole escalates.

src/probe-wake-webhook.ts

58 lines · 1.8 KB · TypeScript
import { packageStorage } from 'kody:runtime'
import { WAKE_WEBHOOK_STORAGE_KEY } from './configure-wake-webhook.ts'

/**
 * POST a dryRun (or tiny live) wake through the stored grok-bot wake webhook
 * and return response shape — never returns the URL.
 */
export default async function probeWakeWebhook(
	input: { live?: boolean; prompt?: string } = {},
) {
	const stored = await packageStorage().get(WAKE_WEBHOOK_STORAGE_KEY)
	if (typeof stored !== 'string' || !stored.startsWith('https://')) {
		return { ok: false as const, error: 'missing packageStorage wake URL' }
	}
	let host = ''
	try {
		host = new URL(stored).host
	} catch {
		return { ok: false as const, error: 'stored wake URL is invalid' }
	}
	const live = input.live === true
	const prompt =
		typeof input.prompt === 'string' && input.prompt.trim()
			? input.prompt.trim()
			: live
				? 'kody-issue-triage wake probe — reply with one word ACK and stop.'
				: 'kody-issue-triage wake dryRun probe'
	const response = await fetch(stored, {
		method: 'POST',
		headers: { 'content-type': 'application/json' },
		body: JSON.stringify({
			bot: 'patch',
			prompt,
			dryRun: !live,
		}),
	})
	const text = await response.text()
	let body: unknown = null
	try {
		body = text ? JSON.parse(text) : null
	} catch {
		body = { raw: text.slice(0, 500) }
	}
	const root =
		body && typeof body === 'object' ? (body as Record<string, unknown>) : null
	const nestedKeys = ['result', 'data', 'value', 'output'] as const
	const nestHits = nestedKeys.filter((k) => root && root[k] != null)
	return {
		ok: response.ok,
		host,
		httpStatus: response.status,
		bodyType: body === null ? 'null' : Array.isArray(body) ? 'array' : typeof body,
		bodyKeys: root ? Object.keys(root).slice(0, 30) : [],
		nestHits,
		bodyPreview: JSON.stringify(body).slice(0, 800),
		live,
	}
}