← Public packages
@kentcdodds/grok-bot
Wake a named Grok Bot from Kody by posting a prompt to that bot's own Cursor webhook.
src/handle-wake.ts
62 lines · 2.3 KB · TypeScriptimport { wakeDirect, type WakeInput } from './wake.ts'
function asRecord(value: unknown): Record<string, unknown> | null {
return value && typeof value === 'object' ? (value as Record<string, unknown>) : null
}
function wakeInputFrom(input: Record<string, unknown> = {}): WakeInput {
const nested = asRecord(input.params) ?? asRecord(input.event) ?? input
const images = Array.isArray(nested.images) ? nested.images : undefined
return {
bot: typeof nested.bot === 'string' ? nested.bot : '',
prompt: typeof nested.prompt === 'string' ? nested.prompt : '',
dryRun: nested.dryRun === true,
...(typeof nested.discordChannelId === 'string'
? { discordChannelId: nested.discordChannelId }
: {}),
...(typeof nested.discordMessageId === 'string'
? { discordMessageId: nested.discordMessageId }
: {}),
...(typeof nested.emailMessageId === 'string' ? { emailMessageId: nested.emailMessageId } : {}),
...(typeof nested.emailThreadId === 'string' ? { emailThreadId: nested.emailThreadId } : {}),
...(typeof nested.emailAlias === 'string' ? { emailAlias: nested.emailAlias } : {}),
...(typeof nested.emailAddress === 'string' ? { emailAddress: nested.emailAddress } : {}),
...(images ? { images: images as WakeInput['images'] } : {}),
}
}
/**
* Wake a named Grok Bot in this package's own secret context.
* The `wake` webhook (and this export) land here.
*
* Always uses the direct wake path (never re-dispatches).
*
* From other packages prefer `import wake from 'kody:@kentcdodds/grok-bot/wake'`
* with `@kentcdodds/grok-bot` in `kody.dependencies`. Stamp-aligned secret
* authority resolves package-scoped sender keys without dispatch.
*
* @param input.bot - Bot id or name
* @param input.prompt - Non-empty prompt
* @param input.dryRun - Validate only; do not POST
* @returns Slim wake result from `./wake` direct path
*
* @example
* import wake from 'kody:@kentcdodds/grok-bot/wake'
* const preview = await wake({
* bot: 'cole',
* prompt: 'Review this Loom on a waitlist thread.',
* dryRun: true,
* })
*/
export default async function handleWake(input: Record<string, unknown> = {}) {
try {
// Direct path only — topic/webhook handler must not re-dispatch.
return await wakeDirect(wakeInputFrom(input))
} catch (error) {
return {
ok: false,
woke: false,
error: error instanceof Error ? error.message : String(error),
}
}
}