import type { TriggerOutput } from '@/triggers/types' /** * Trigger dropdown options for Grain triggers. * New options (Item Added / Item Updated / All Events) correctly scope by view_id only. * Legacy options are hidden from the picker but still resolve for existing workflows. */ export const grainTriggerOptions = [ { label: 'Item Added', id: 'grain_item_added' }, { label: 'Item Updated', id: 'grain_item_updated' }, { label: 'All Events', id: 'grain_webhook' }, { label: 'Recording Created', id: 'grain_recording_created', hidden: true }, { label: 'Recording Updated', id: 'grain_recording_updated', hidden: true }, { label: 'Highlight Created', id: 'grain_highlight_created', hidden: true }, { label: 'Highlight Updated', id: 'grain_highlight_updated', hidden: true }, { label: 'Story Created', id: 'grain_story_created', hidden: true }, ] /** * Generate setup instructions for a specific Grain event type */ export function grainSetupInstructions(eventType: string): string { const instructions = [ 'Enter your Grain API Key (Personal Access Token) above.', `Enter the Grain view ID that matches the ${eventType} trigger. Grain requires view_id for webhook creation.`, 'Use the Grain "List Views" tool or GET /_/public-api/views to find the correct view ID.', 'You can find or create your API key in Grain at Workspace Settings > API under Integrations on grain.com.', 'The webhook will be automatically deleted when you remove this trigger.', ] return instructions .map( (instruction, index) => `
${index + 1}. ${instruction}
` ) .join('') } /** * Setup instructions for the v2 triggers that correctly explain view-based scoping. */ export function grainV2SetupInstructions(action: 'item added' | 'item updated' | 'all'): string { const viewSentence = action === 'all' ? 'Enter a Grain view ID. Each view has a type — recordings, highlights, or stories — and this trigger will fire on every event (added, updated, or removed) for items in that view.' : `Enter a Grain view ID. Each view has a type — recordings, highlights, or stories — and only items matching that type will fire the ${action} event.` const instructions = [ 'Enter your Grain API Key (Personal Access Token). You can find or create one in Grain at Workspace Settings > API under Integrations on grain.com.', viewSentence, 'To find your view IDs, use the List Views operation on this block or call GET /_/public-api/views directly.', 'The webhook is created automatically when you save and will be deleted when you remove this trigger.', ] return instructions .map( (instruction, index) => `
${index + 1}. ${instruction}
` ) .join('') } /** * Build output schema for recording events * Webhook payload structure: { type, user_id, data: { ...recording } } */ export function buildRecordingOutputs(): Record { return { type: { type: 'string', description: 'Event type', }, user_id: { type: 'string', description: 'User UUID who triggered the event', }, data: { id: { type: 'string', description: 'Recording UUID', }, title: { type: 'string', description: 'Recording title', }, start_datetime: { type: 'string', description: 'ISO8601 start timestamp', }, end_datetime: { type: 'string', description: 'ISO8601 end timestamp', }, duration_ms: { type: 'number', description: 'Duration in milliseconds', }, media_type: { type: 'string', description: 'audio, transcript, or video', }, source: { type: 'string', description: 'Recording source (zoom, meet, local_capture, etc.)', }, url: { type: 'string', description: 'URL to view in Grain', }, thumbnail_url: { type: 'string', description: 'Thumbnail URL (nullable)', }, tags: { type: 'array', description: 'Array of tag strings', }, teams: { type: 'array', description: 'Array of team objects', }, meeting_type: { type: 'object', description: 'Meeting type info with id, name, scope (nullable)', }, }, } as Record } /** * Build output schema for highlight events * Note: Grain API docs only show recording webhooks. Highlight webhooks may have similar structure. */ export function buildHighlightOutputs(): Record { return { type: { type: 'string', description: 'Event type', }, user_id: { type: 'string', description: 'User UUID who triggered the event', }, data: { id: { type: 'string', description: 'Highlight UUID', }, recording_id: { type: 'string', description: 'Parent recording UUID', }, text: { type: 'string', description: 'Highlight title/description', }, transcript: { type: 'string', description: 'Transcript text of the clip', }, speakers: { type: 'array', description: 'Array of speaker names', }, timestamp: { type: 'number', description: 'Start timestamp in ms', }, duration: { type: 'number', description: 'Duration in ms', }, tags: { type: 'array', description: 'Array of tag strings', }, url: { type: 'string', description: 'URL to view in Grain', }, thumbnail_url: { type: 'string', description: 'Thumbnail URL', }, created_datetime: { type: 'string', description: 'ISO8601 creation timestamp', }, }, } as Record } /** * Build output schema for story events * Note: Grain API docs only show recording webhooks. Story webhooks may have similar structure. */ export function buildStoryOutputs(): Record { return { type: { type: 'string', description: 'Event type', }, user_id: { type: 'string', description: 'User UUID who triggered the event', }, data: { id: { type: 'string', description: 'Story UUID', }, title: { type: 'string', description: 'Story title', }, url: { type: 'string', description: 'URL to view in Grain', }, created_datetime: { type: 'string', description: 'ISO8601 creation timestamp', }, }, } as Record } /** * Build output schema for generic webhook events * Webhook payload structure: { type, user_id, data: { ... } } */ export function buildGenericOutputs(): Record { return { type: { type: 'string', description: 'Event type (e.g., recording_added)', }, user_id: { type: 'string', description: 'User UUID who triggered the event', }, data: { type: 'object', description: 'Event data object (recording, highlight, etc.)', }, } as Record }