diff --git a/apps/docs/components/icons.tsx b/apps/docs/components/icons.tsx index 0cf5773ca48..cd0c085f913 100644 --- a/apps/docs/components/icons.tsx +++ b/apps/docs/components/icons.tsx @@ -5091,6 +5091,17 @@ export function GrainIcon(props: SVGProps) { ) } +export function GranolaIcon(props: SVGProps) { + return ( + + + + ) +} + export function CirclebackIcon(props: SVGProps) { const id = useId() const patternId = `circleback_pattern_${id}` diff --git a/apps/docs/components/ui/icon-mapping.ts b/apps/docs/components/ui/icon-mapping.ts index 900229eaad7..5563108d3b8 100644 --- a/apps/docs/components/ui/icon-mapping.ts +++ b/apps/docs/components/ui/icon-mapping.ts @@ -74,6 +74,7 @@ import { GoogleVaultIcon, GrafanaIcon, GrainIcon, + GranolaIcon, GreenhouseIcon, GreptileIcon, HexIcon, @@ -247,6 +248,7 @@ export const blockTypeToIconMap: Record = { google_vault: GoogleVaultIcon, grafana: GrafanaIcon, grain: GrainIcon, + granola: GranolaIcon, greenhouse: GreenhouseIcon, greptile: GreptileIcon, hex: HexIcon, diff --git a/apps/docs/content/docs/en/tools/granola.mdx b/apps/docs/content/docs/en/tools/granola.mdx new file mode 100644 index 00000000000..88eb50622a3 --- /dev/null +++ b/apps/docs/content/docs/en/tools/granola.mdx @@ -0,0 +1,92 @@ +--- +title: Granola +description: Access meeting notes and transcripts from Granola +--- + +import { BlockInfoCard } from "@/components/ui/block-info-card" + + + +## Usage Instructions + +Integrate Granola into your workflow to retrieve meeting notes, summaries, attendees, and transcripts. + + + +## Tools + +### `granola_list_notes` + +Lists meeting notes from Granola with optional date filters and pagination. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Granola API key | +| `createdBefore` | string | No | Return notes created before this date \(ISO 8601\) | +| `createdAfter` | string | No | Return notes created after this date \(ISO 8601\) | +| `updatedAfter` | string | No | Return notes updated after this date \(ISO 8601\) | +| `cursor` | string | No | Pagination cursor from a previous response | +| `pageSize` | number | No | Number of notes per page \(1-30, default 10\) | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `notes` | json | List of meeting notes | +| ↳ `id` | string | Note ID | +| ↳ `title` | string | Note title | +| ↳ `ownerName` | string | Note owner name | +| ↳ `ownerEmail` | string | Note owner email | +| ↳ `createdAt` | string | Creation timestamp | +| ↳ `updatedAt` | string | Last update timestamp | +| `hasMore` | boolean | Whether more notes are available | +| `cursor` | string | Pagination cursor for the next page | + +### `granola_get_note` + +Retrieves a specific meeting note from Granola by ID, including summary, attendees, calendar event details, and optionally the transcript. + +#### Input + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `apiKey` | string | Yes | Granola API key | +| `noteId` | string | Yes | The note ID \(e.g., not_1d3tmYTlCICgjy\) | +| `includeTranscript` | string | No | Whether to include the meeting transcript | + +#### Output + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `id` | string | Note ID | +| `title` | string | Note title | +| `ownerName` | string | Note owner name | +| `ownerEmail` | string | Note owner email | +| `createdAt` | string | Creation timestamp | +| `updatedAt` | string | Last update timestamp | +| `summaryText` | string | Plain text summary of the meeting | +| `summaryMarkdown` | string | Markdown-formatted summary of the meeting | +| `attendees` | json | Meeting attendees | +| ↳ `name` | string | Attendee name | +| ↳ `email` | string | Attendee email | +| `folders` | json | Folders the note belongs to | +| ↳ `id` | string | Folder ID | +| ↳ `name` | string | Folder name | +| `calendarEventTitle` | string | Calendar event title | +| `calendarOrganiser` | string | Calendar event organiser email | +| `calendarEventId` | string | Calendar event ID | +| `scheduledStartTime` | string | Scheduled start time | +| `scheduledEndTime` | string | Scheduled end time | +| `invitees` | json | Calendar event invitee emails | +| `transcript` | json | Meeting transcript entries \(only if requested\) | +| ↳ `speaker` | string | Speaker source \(microphone or speaker\) | +| ↳ `text` | string | Transcript text | +| ↳ `startTime` | string | Segment start time | +| ↳ `endTime` | string | Segment end time | + + diff --git a/apps/docs/content/docs/en/tools/meta.json b/apps/docs/content/docs/en/tools/meta.json index 9ff8f3ff78a..549aa09bb7c 100644 --- a/apps/docs/content/docs/en/tools/meta.json +++ b/apps/docs/content/docs/en/tools/meta.json @@ -68,6 +68,7 @@ "google_vault", "grafana", "grain", + "granola", "greenhouse", "greptile", "hex", diff --git a/apps/sim/app/(landing)/integrations/data/icon-mapping.ts b/apps/sim/app/(landing)/integrations/data/icon-mapping.ts index 7580b713c57..c2e2c8f975f 100644 --- a/apps/sim/app/(landing)/integrations/data/icon-mapping.ts +++ b/apps/sim/app/(landing)/integrations/data/icon-mapping.ts @@ -74,6 +74,7 @@ import { GoogleVaultIcon, GrafanaIcon, GrainIcon, + GranolaIcon, GreenhouseIcon, GreptileIcon, HexIcon, @@ -247,6 +248,7 @@ export const blockTypeToIconMap: Record = { google_vault: GoogleVaultIcon, grafana: GrafanaIcon, grain: GrainIcon, + granola: GranolaIcon, greenhouse: GreenhouseIcon, greptile: GreptileIcon, hex: HexIcon, diff --git a/apps/sim/app/(landing)/integrations/data/integrations.json b/apps/sim/app/(landing)/integrations/data/integrations.json index 7d8cf706be5..67ab2d0bca8 100644 --- a/apps/sim/app/(landing)/integrations/data/integrations.json +++ b/apps/sim/app/(landing)/integrations/data/integrations.json @@ -4871,6 +4871,33 @@ "integrationType": "media", "tags": ["meeting", "note-taking"] }, + { + "type": "granola", + "slug": "granola", + "name": "Granola", + "description": "Access meeting notes and transcripts from Granola", + "longDescription": "Integrate Granola into your workflow to retrieve meeting notes, summaries, attendees, and transcripts.", + "bgColor": "#B2C147", + "iconName": "GranolaIcon", + "docsUrl": "https://docs.sim.ai/tools/granola", + "operations": [ + { + "name": "List Notes", + "description": "Lists meeting notes from Granola with optional date filters and pagination." + }, + { + "name": "Get Note", + "description": "Retrieves a specific meeting note from Granola by ID, including summary, attendees, calendar event details, and optionally the transcript." + } + ], + "operationCount": 2, + "triggers": [], + "triggerCount": 0, + "authType": "api-key", + "category": "tools", + "integrationType": "productivity", + "tags": ["meeting", "note-taking"] + }, { "type": "greenhouse", "slug": "greenhouse", diff --git a/apps/sim/blocks/blocks/granola.ts b/apps/sim/blocks/blocks/granola.ts new file mode 100644 index 00000000000..0062fbee815 --- /dev/null +++ b/apps/sim/blocks/blocks/granola.ts @@ -0,0 +1,169 @@ +import { GranolaIcon } from '@/components/icons' +import { AuthMode, type BlockConfig, IntegrationType } from '@/blocks/types' + +export const GranolaBlock: BlockConfig = { + type: 'granola', + name: 'Granola', + description: 'Access meeting notes and transcripts from Granola', + longDescription: + 'Integrate Granola into your workflow to retrieve meeting notes, summaries, attendees, and transcripts.', + docsLink: 'https://docs.sim.ai/tools/granola', + category: 'tools', + integrationType: IntegrationType.Productivity, + tags: ['meeting', 'note-taking'], + bgColor: '#B2C147', + icon: GranolaIcon, + authMode: AuthMode.ApiKey, + + subBlocks: [ + { + id: 'operation', + title: 'Operation', + type: 'dropdown', + options: [ + { label: 'List Notes', id: 'list_notes' }, + { label: 'Get Note', id: 'get_note' }, + ], + value: () => 'list_notes', + }, + { + id: 'apiKey', + title: 'API Key', + type: 'short-input', + required: true, + placeholder: 'Enter your Granola API key', + password: true, + }, + { + id: 'noteId', + title: 'Note ID', + type: 'short-input', + required: { field: 'operation', value: 'get_note' }, + placeholder: 'e.g., not_1d3tmYTlCICgjy', + condition: { field: 'operation', value: 'get_note' }, + }, + { + id: 'includeTranscript', + title: 'Include Transcript', + type: 'dropdown', + options: [ + { label: 'No', id: 'false' }, + { label: 'Yes', id: 'true' }, + ], + value: () => 'false', + condition: { field: 'operation', value: 'get_note' }, + mode: 'advanced', + }, + { + id: 'createdAfter', + title: 'Created After', + type: 'short-input', + placeholder: 'e.g., 2026-01-01', + condition: { field: 'operation', value: 'list_notes' }, + mode: 'advanced', + wandConfig: { + enabled: true, + prompt: + 'Generate an ISO 8601 date or datetime string. Return ONLY the date string - no explanations, no extra text.', + generationType: 'timestamp', + }, + }, + { + id: 'createdBefore', + title: 'Created Before', + type: 'short-input', + placeholder: 'e.g., 2026-03-01', + condition: { field: 'operation', value: 'list_notes' }, + mode: 'advanced', + wandConfig: { + enabled: true, + prompt: + 'Generate an ISO 8601 date or datetime string. Return ONLY the date string - no explanations, no extra text.', + generationType: 'timestamp', + }, + }, + { + id: 'updatedAfter', + title: 'Updated After', + type: 'short-input', + placeholder: 'e.g., 2026-01-01', + condition: { field: 'operation', value: 'list_notes' }, + mode: 'advanced', + wandConfig: { + enabled: true, + prompt: + 'Generate an ISO 8601 date or datetime string. Return ONLY the date string - no explanations, no extra text.', + generationType: 'timestamp', + }, + }, + { + id: 'pageSize', + title: 'Page Size', + type: 'short-input', + placeholder: '10 (1-30)', + condition: { field: 'operation', value: 'list_notes' }, + mode: 'advanced', + }, + { + id: 'cursor', + title: 'Cursor', + type: 'short-input', + placeholder: 'Pagination cursor from previous response', + condition: { field: 'operation', value: 'list_notes' }, + mode: 'advanced', + }, + ], + + tools: { + access: ['granola_list_notes', 'granola_get_note'], + config: { + tool: (params) => `granola_${params.operation}`, + params: (params) => { + const result: Record = {} + if (params.pageSize) result.pageSize = Number(params.pageSize) + return result + }, + }, + }, + + inputs: { + operation: { type: 'string', description: 'Operation to perform' }, + apiKey: { type: 'string', description: 'Granola API key' }, + noteId: { type: 'string', description: 'Note ID for get_note operation' }, + includeTranscript: { type: 'string', description: 'Whether to include transcript' }, + createdAfter: { type: 'string', description: 'Filter notes created after this date' }, + createdBefore: { type: 'string', description: 'Filter notes created before this date' }, + updatedAfter: { type: 'string', description: 'Filter notes updated after this date' }, + pageSize: { type: 'number', description: 'Results per page (1-30)' }, + cursor: { type: 'string', description: 'Pagination cursor' }, + }, + + outputs: { + notes: { + type: 'json', + description: 'List of meeting notes (id, title, ownerName, ownerEmail, createdAt, updatedAt)', + }, + hasMore: { type: 'boolean', description: 'Whether more notes are available' }, + cursor: { type: 'string', description: 'Pagination cursor for next page' }, + id: { type: 'string', description: 'Note ID' }, + title: { type: 'string', description: 'Note title' }, + ownerName: { type: 'string', description: 'Note owner name' }, + ownerEmail: { type: 'string', description: 'Note owner email' }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + updatedAt: { type: 'string', description: 'Last update timestamp' }, + summaryText: { type: 'string', description: 'Plain text meeting summary' }, + summaryMarkdown: { type: 'string', description: 'Markdown meeting summary' }, + attendees: { type: 'json', description: 'Meeting attendees (name, email)' }, + folders: { type: 'json', description: 'Folders the note belongs to (id, name)' }, + calendarEventTitle: { type: 'string', description: 'Calendar event title' }, + calendarOrganiser: { type: 'string', description: 'Calendar event organiser email' }, + calendarEventId: { type: 'string', description: 'Calendar event ID' }, + scheduledStartTime: { type: 'string', description: 'Scheduled start time' }, + scheduledEndTime: { type: 'string', description: 'Scheduled end time' }, + invitees: { type: 'json', description: 'Calendar event invitee emails' }, + transcript: { + type: 'json', + description: 'Meeting transcript entries (speaker, text, startTime, endTime)', + }, + }, +} diff --git a/apps/sim/blocks/registry.ts b/apps/sim/blocks/registry.ts index 15363a8ad53..697b18af433 100644 --- a/apps/sim/blocks/registry.ts +++ b/apps/sim/blocks/registry.ts @@ -73,6 +73,7 @@ import { GoogleTranslateBlock } from '@/blocks/blocks/google_translate' import { GoogleVaultBlock } from '@/blocks/blocks/google_vault' import { GrafanaBlock } from '@/blocks/blocks/grafana' import { GrainBlock } from '@/blocks/blocks/grain' +import { GranolaBlock } from '@/blocks/blocks/granola' import { GreenhouseBlock } from '@/blocks/blocks/greenhouse' import { GreptileBlock } from '@/blocks/blocks/greptile' import { GuardrailsBlock } from '@/blocks/blocks/guardrails' @@ -292,6 +293,7 @@ export const registry: Record = { google_vault: GoogleVaultBlock, grafana: GrafanaBlock, grain: GrainBlock, + granola: GranolaBlock, greenhouse: GreenhouseBlock, greptile: GreptileBlock, guardrails: GuardrailsBlock, diff --git a/apps/sim/components/icons.tsx b/apps/sim/components/icons.tsx index 0cf5773ca48..cd0c085f913 100644 --- a/apps/sim/components/icons.tsx +++ b/apps/sim/components/icons.tsx @@ -5091,6 +5091,17 @@ export function GrainIcon(props: SVGProps) { ) } +export function GranolaIcon(props: SVGProps) { + return ( + + + + ) +} + export function CirclebackIcon(props: SVGProps) { const id = useId() const patternId = `circleback_pattern_${id}` diff --git a/apps/sim/tools/granola/get_note.ts b/apps/sim/tools/granola/get_note.ts new file mode 100644 index 00000000000..a4b1556d7eb --- /dev/null +++ b/apps/sim/tools/granola/get_note.ts @@ -0,0 +1,156 @@ +import type { GranolaGetNoteParams, GranolaGetNoteResponse } from '@/tools/granola/types' +import type { ToolConfig } from '@/tools/types' + +export const getNoteTool: ToolConfig = { + id: 'granola_get_note', + name: 'Granola Get Note', + description: + 'Retrieves a specific meeting note from Granola by ID, including summary, attendees, calendar event details, and optionally the transcript.', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Granola API key', + }, + noteId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'The note ID (e.g., not_1d3tmYTlCICgjy)', + }, + includeTranscript: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Whether to include the meeting transcript', + }, + }, + + request: { + url: (params) => { + const url = new URL(`https://public-api.granola.ai/v1/notes/${params.noteId.trim()}`) + if (params.includeTranscript === 'true') url.searchParams.append('include', 'transcript') + return url.toString() + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const error = await response.text() + throw new Error(`Granola API error (${response.status}): ${error}`) + } + + const data = await response.json() + + return { + success: true, + output: { + id: data.id ?? '', + title: data.title ?? null, + ownerName: data.owner?.name ?? null, + ownerEmail: data.owner?.email ?? '', + createdAt: data.created_at ?? '', + updatedAt: data.updated_at ?? '', + summaryText: data.summary_text ?? '', + summaryMarkdown: data.summary_markdown ?? null, + attendees: (data.attendees ?? []).map((a: { name: string | null; email: string }) => ({ + name: a.name ?? null, + email: a.email ?? '', + })), + folders: (data.folder_membership ?? []).map((f: { id: string; name: string }) => ({ + id: f.id ?? '', + name: f.name ?? '', + })), + calendarEventTitle: data.calendar_event?.event_title ?? null, + calendarOrganiser: data.calendar_event?.organiser ?? null, + calendarEventId: data.calendar_event?.calendar_event_id ?? null, + scheduledStartTime: data.calendar_event?.scheduled_start_time ?? null, + scheduledEndTime: data.calendar_event?.scheduled_end_time ?? null, + invitees: (data.calendar_event?.invitees ?? []).map((i: { email: string }) => i.email), + transcript: data.transcript + ? data.transcript.map( + (t: { + speaker: { source: string } + text: string + start_time: string + end_time: string + }) => ({ + speaker: t.speaker?.source ?? 'unknown', + text: t.text ?? '', + startTime: t.start_time ?? '', + endTime: t.end_time ?? '', + }) + ) + : null, + }, + } + }, + + outputs: { + id: { type: 'string', description: 'Note ID' }, + title: { type: 'string', description: 'Note title', optional: true }, + ownerName: { type: 'string', description: 'Note owner name', optional: true }, + ownerEmail: { type: 'string', description: 'Note owner email' }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + updatedAt: { type: 'string', description: 'Last update timestamp' }, + summaryText: { type: 'string', description: 'Plain text summary of the meeting' }, + summaryMarkdown: { + type: 'string', + description: 'Markdown-formatted summary of the meeting', + optional: true, + }, + attendees: { + type: 'json', + description: 'Meeting attendees', + properties: { + name: { type: 'string', description: 'Attendee name' }, + email: { type: 'string', description: 'Attendee email' }, + }, + }, + folders: { + type: 'json', + description: 'Folders the note belongs to', + properties: { + id: { type: 'string', description: 'Folder ID' }, + name: { type: 'string', description: 'Folder name' }, + }, + }, + calendarEventTitle: { + type: 'string', + description: 'Calendar event title', + optional: true, + }, + calendarOrganiser: { + type: 'string', + description: 'Calendar event organiser email', + optional: true, + }, + calendarEventId: { type: 'string', description: 'Calendar event ID', optional: true }, + scheduledStartTime: { + type: 'string', + description: 'Scheduled start time', + optional: true, + }, + scheduledEndTime: { type: 'string', description: 'Scheduled end time', optional: true }, + invitees: { type: 'json', description: 'Calendar event invitee emails' }, + transcript: { + type: 'json', + description: 'Meeting transcript entries (only if requested)', + optional: true, + properties: { + speaker: { type: 'string', description: 'Speaker source (microphone or speaker)' }, + text: { type: 'string', description: 'Transcript text' }, + startTime: { type: 'string', description: 'Segment start time' }, + endTime: { type: 'string', description: 'Segment end time' }, + }, + }, + }, +} diff --git a/apps/sim/tools/granola/index.ts b/apps/sim/tools/granola/index.ts new file mode 100644 index 00000000000..27d011ad437 --- /dev/null +++ b/apps/sim/tools/granola/index.ts @@ -0,0 +1,5 @@ +import { getNoteTool } from '@/tools/granola/get_note' +import { listNotesTool } from '@/tools/granola/list_notes' + +export const granolaListNotesTool = listNotesTool +export const granolaGetNoteTool = getNoteTool diff --git a/apps/sim/tools/granola/list_notes.ts b/apps/sim/tools/granola/list_notes.ts new file mode 100644 index 00000000000..032b8eef6d1 --- /dev/null +++ b/apps/sim/tools/granola/list_notes.ts @@ -0,0 +1,122 @@ +import type { GranolaListNotesParams, GranolaListNotesResponse } from '@/tools/granola/types' +import type { ToolConfig } from '@/tools/types' + +export const listNotesTool: ToolConfig = { + id: 'granola_list_notes', + name: 'Granola List Notes', + description: 'Lists meeting notes from Granola with optional date filters and pagination.', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + visibility: 'user-only', + description: 'Granola API key', + }, + createdBefore: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Return notes created before this date (ISO 8601)', + }, + createdAfter: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Return notes created after this date (ISO 8601)', + }, + updatedAfter: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Return notes updated after this date (ISO 8601)', + }, + cursor: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Pagination cursor from a previous response', + }, + pageSize: { + type: 'number', + required: false, + visibility: 'user-or-llm', + description: 'Number of notes per page (1-30, default 10)', + }, + }, + + request: { + url: (params) => { + const url = new URL('https://public-api.granola.ai/v1/notes') + if (params.createdBefore) url.searchParams.append('created_before', params.createdBefore) + if (params.createdAfter) url.searchParams.append('created_after', params.createdAfter) + if (params.updatedAfter) url.searchParams.append('updated_after', params.updatedAfter) + if (params.cursor) url.searchParams.append('cursor', params.cursor) + if (params.pageSize) url.searchParams.append('page_size', String(params.pageSize)) + return url.toString() + }, + method: 'GET', + headers: (params) => ({ + Authorization: `Bearer ${params.apiKey}`, + 'Content-Type': 'application/json', + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const error = await response.text() + throw new Error(`Granola API error (${response.status}): ${error}`) + } + + const data = await response.json() + + return { + success: true, + output: { + notes: (data.notes ?? []).map( + (note: { + id: string + title: string | null + owner: { name: string | null; email: string } + created_at: string + updated_at: string + }) => ({ + id: note.id, + title: note.title ?? null, + ownerName: note.owner?.name ?? null, + ownerEmail: note.owner?.email ?? '', + createdAt: note.created_at ?? '', + updatedAt: note.updated_at ?? '', + }) + ), + hasMore: data.hasMore ?? false, + cursor: data.cursor ?? null, + }, + } + }, + + outputs: { + notes: { + type: 'json', + description: 'List of meeting notes', + properties: { + id: { type: 'string', description: 'Note ID' }, + title: { type: 'string', description: 'Note title' }, + ownerName: { type: 'string', description: 'Note owner name' }, + ownerEmail: { type: 'string', description: 'Note owner email' }, + createdAt: { type: 'string', description: 'Creation timestamp' }, + updatedAt: { type: 'string', description: 'Last update timestamp' }, + }, + }, + hasMore: { + type: 'boolean', + description: 'Whether more notes are available', + }, + cursor: { + type: 'string', + description: 'Pagination cursor for the next page', + optional: true, + }, + }, +} diff --git a/apps/sim/tools/granola/types.ts b/apps/sim/tools/granola/types.ts new file mode 100644 index 00000000000..b9328262cbc --- /dev/null +++ b/apps/sim/tools/granola/types.ts @@ -0,0 +1,53 @@ +import type { ToolResponse } from '@/tools/types' + +export interface GranolaListNotesParams { + apiKey: string + createdBefore?: string + createdAfter?: string + updatedAfter?: string + cursor?: string + pageSize?: number +} + +export interface GranolaGetNoteParams { + apiKey: string + noteId: string + includeTranscript?: string +} + +export interface GranolaListNotesResponse extends ToolResponse { + output: { + notes: { + id: string + title: string | null + ownerName: string | null + ownerEmail: string + createdAt: string + updatedAt: string + }[] + hasMore: boolean + cursor: string | null + } +} + +export interface GranolaGetNoteResponse extends ToolResponse { + output: { + id: string + title: string | null + ownerName: string | null + ownerEmail: string + createdAt: string + updatedAt: string + summaryText: string + summaryMarkdown: string | null + attendees: { name: string | null; email: string }[] + folders: { id: string; name: string }[] + calendarEventTitle: string | null + calendarOrganiser: string | null + calendarEventId: string | null + scheduledStartTime: string | null + scheduledEndTime: string | null + invitees: string[] + transcript: { speaker: string; text: string; startTime: string; endTime: string }[] | null + } +} diff --git a/apps/sim/tools/registry.ts b/apps/sim/tools/registry.ts index 99efb6dcbbc..c754d0e80db 100644 --- a/apps/sim/tools/registry.ts +++ b/apps/sim/tools/registry.ts @@ -980,6 +980,7 @@ import { grainListTeamsTool, grainListViewsTool, } from '@/tools/grain' +import { granolaGetNoteTool, granolaListNotesTool } from '@/tools/granola' import { greenhouseGetApplicationTool, greenhouseGetCandidateTool, @@ -2660,6 +2661,8 @@ export const tools: Record = { greenhouse_list_departments: greenhouseListDepartmentsTool, greenhouse_list_offices: greenhouseListOfficesTool, greenhouse_list_job_stages: greenhouseListJobStagesTool, + granola_list_notes: granolaListNotesTool, + granola_get_note: granolaGetNoteTool, guardrails_validate: guardrailsValidateTool, hex_cancel_run: hexCancelRunTool, hex_create_collection: hexCreateCollectionTool,