diff --git a/apps/x/apps/renderer/src/components/connectors-popover.tsx b/apps/x/apps/renderer/src/components/connectors-popover.tsx
index e28f662e..92b13a48 100644
--- a/apps/x/apps/renderer/src/components/connectors-popover.tsx
+++ b/apps/x/apps/renderer/src/components/connectors-popover.tsx
@@ -2,7 +2,7 @@
import * as React from "react"
import { useState } from "react"
-import { AlertTriangle, Loader2, Mic, Mail, Calendar, MessageSquare, User } from "lucide-react"
+import { AlertTriangle, Loader2, Mic, Mail, Calendar, User } from "lucide-react"
import {
Popover,
@@ -15,7 +15,6 @@ import {
TooltipTrigger,
} from "@/components/ui/tooltip"
import { Button } from "@/components/ui/button"
-import { Switch } from "@/components/ui/switch"
import { Separator } from "@/components/ui/separator"
import { GoogleClientIdModal } from "@/components/google-client-id-modal"
import { ComposioApiKeyModal } from "@/components/composio-api-key-modal"
@@ -126,8 +125,6 @@ export function ConnectorsPopover({ children, tooltip, open: openProp, onOpenCha
// Check if Gmail is unconnected (for filtering in unconnected mode)
const isGmailUnconnected = c.useComposioForGoogle ? !c.gmailConnected && !c.gmailLoading : true
const isGoogleCalendarUnconnected = c.useComposioForGoogleCalendar ? !c.googleCalendarConnected && !c.googleCalendarLoading : true
- const isGranolaUnconnected = !c.granolaEnabled && !c.granolaLoading
- const isSlackUnconnected = !c.slackEnabled && !c.slackLoading
// For unconnected mode, check if there's anything to show
const hasUnconnectedEmailCalendar = (() => {
@@ -143,7 +140,6 @@ export function ConnectorsPopover({ children, tooltip, open: openProp, onOpenCha
const hasUnconnectedMeetingNotes = (() => {
if (!isUnconnectedMode) return true
- if (isGranolaUnconnected) return true
if (c.providers.includes('fireflies-ai')) {
const firefliesState = c.providerStates['fireflies-ai']
if (!firefliesState?.isConnected || c.providerStatus['fireflies-ai']?.error) return true
@@ -151,15 +147,13 @@ export function ConnectorsPopover({ children, tooltip, open: openProp, onOpenCha
return false
})()
- const hasUnconnectedSlack = !isUnconnectedMode || isSlackUnconnected
-
const isRowboatUnconnected = (() => {
if (!c.providers.includes('rowboat')) return false
const rowboatState = c.providerStates['rowboat']
return !rowboatState?.isConnected || rowboatState?.isLoading
})()
- const allConnected = isUnconnectedMode && !isRowboatUnconnected && !hasUnconnectedEmailCalendar && !hasUnconnectedMeetingNotes && !hasUnconnectedSlack
+ const allConnected = isUnconnectedMode && !isRowboatUnconnected && !hasUnconnectedEmailCalendar && !hasUnconnectedMeetingNotes
return (
<>
@@ -357,128 +351,12 @@ export function ConnectorsPopover({ children, tooltip, open: openProp, onOpenCha
Meeting Notes
- {/* Granola - show in unconnected mode only if not enabled */}
- {(!isUnconnectedMode || isGranolaUnconnected) && (
-
-
-
-
-
-
- Granola
-
- Local meeting notes
-
-
-
-
- {c.granolaLoading && (
-
- )}
-
-
-
- )}
-
{/* Fireflies */}
{c.providers.includes('fireflies-ai') && renderOAuthProvider('fireflies-ai', 'Fireflies', , 'AI meeting transcripts')}
>
)}
-
- {/* Team Communication Section */}
- {hasUnconnectedSlack && (
- <>
-
- Team Communication
-
-
-
-
-
-
-
-
-
- Slack
- {c.slackEnabled && c.slackWorkspaces.length > 0 ? (
-
- {c.slackWorkspaces.map(w => w.name).join(', ')}
-
- ) : (
-
- Send messages and view channels
-
- )}
-
-
-
- {(c.slackLoading || c.slackDiscovering) && (
-
- )}
- {c.slackEnabled ? (
- c.handleSlackDisable()}
- disabled={c.slackLoading}
- />
- ) : (
-
- )}
-
-
- {c.slackPickerOpen && (
-
- {c.slackDiscoverError ? (
-
{c.slackDiscoverError}
- ) : (
- <>
- {c.slackAvailableWorkspaces.map(w => (
-
- ))}
-
- >
- )}
-
- )}
-
- >
- )}
>
)}
diff --git a/apps/x/apps/renderer/src/components/onboarding/steps/completion-step.tsx b/apps/x/apps/renderer/src/components/onboarding/steps/completion-step.tsx
index c01e42ea..2b32309a 100644
--- a/apps/x/apps/renderer/src/components/onboarding/steps/completion-step.tsx
+++ b/apps/x/apps/renderer/src/components/onboarding/steps/completion-step.tsx
@@ -8,8 +8,8 @@ interface CompletionStepProps {
}
export function CompletionStep({ state }: CompletionStepProps) {
- const { connectedProviders, granolaEnabled, slackEnabled, gmailConnected, googleCalendarConnected, handleComplete } = state
- const hasConnections = connectedProviders.length > 0 || granolaEnabled || slackEnabled || gmailConnected || googleCalendarConnected
+ const { connectedProviders, gmailConnected, googleCalendarConnected, handleComplete } = state
+ const hasConnections = connectedProviders.length > 0 || gmailConnected || googleCalendarConnected
return (
@@ -109,28 +109,6 @@ export function CompletionStep({ state }: CompletionStepProps) {
Fireflies (Meeting transcripts)
)}
- {granolaEnabled && (
-
-
- Granola (Local meeting notes)
-
- )}
- {slackEnabled && (
-
-
- Slack (Team communication)
-
- )}
)}
diff --git a/apps/x/apps/renderer/src/components/onboarding/steps/connect-accounts-step.tsx b/apps/x/apps/renderer/src/components/onboarding/steps/connect-accounts-step.tsx
index b152d567..ae9afea8 100644
--- a/apps/x/apps/renderer/src/components/onboarding/steps/connect-accounts-step.tsx
+++ b/apps/x/apps/renderer/src/components/onboarding/steps/connect-accounts-step.tsx
@@ -1,9 +1,8 @@
import { Loader2, CheckCircle2, ArrowLeft, Calendar } from "lucide-react"
import { motion } from "motion/react"
import { Button } from "@/components/ui/button"
-import { Switch } from "@/components/ui/switch"
import { cn } from "@/lib/utils"
-import { GmailIcon, SlackIcon, FirefliesIcon, GranolaIcon } from "../provider-icons"
+import { GmailIcon, FirefliesIcon } from "../provider-icons"
import type { OnboardingState, ProviderState } from "../use-onboarding-state"
interface ConnectAccountsStepProps {
@@ -85,11 +84,6 @@ function ProviderCard({
export function ConnectAccountsStep({ state }: ConnectAccountsStepProps) {
const {
providers, providersLoading, providerStates, handleConnect,
- granolaEnabled, granolaLoading, handleGranolaToggle,
- slackEnabled, slackLoading, slackWorkspaces, slackAvailableWorkspaces,
- slackSelectedUrls, setSlackSelectedUrls, slackPickerOpen,
- slackDiscovering, slackDiscoverError,
- handleSlackEnable, handleSlackSaveWorkspaces, handleSlackDisable,
useComposioForGoogle, gmailConnected, gmailLoading, gmailConnecting, handleConnectGmail,
useComposioForGoogleCalendar, googleCalendarConnected, googleCalendarLoading, googleCalendarConnecting, handleConnectGoogleCalendar,
handleNext, handleBack,
@@ -158,30 +152,11 @@ export function ConnectAccountsStep({ state }: ConnectAccountsStepProps) {
)}
{/* Meeting Notes */}
-
-
- Meeting Notes
-
-
}
- iconBg="bg-purple-500/10"
- iconColor="text-purple-500"
- providerState={{ isConnected: granolaEnabled, isLoading: false, isConnecting: false }}
- rightSlot={
-
- {granolaLoading && }
-
-
- }
- index={cardIndex++}
- />
- {providers.includes('fireflies-ai') && (
+ {providers.includes('fireflies-ai') && (
+
+
+ Meeting Notes
+
handleConnect('fireflies-ai')}
index={cardIndex++}
/>
- )}
-
-
- {/* Team Communication */}
-
-
- Team Communication
-
-
-
0
- ? slackWorkspaces.map(w => w.name).join(', ')
- : "Enable Rowboat to understand your team conversations and provide relevant context"
- }
- icon={}
- iconBg="bg-emerald-500/10"
- iconColor="text-emerald-500"
- providerState={{ isConnected: slackEnabled, isLoading: false, isConnecting: false }}
- rightSlot={
-
- {(slackLoading || slackDiscovering) && }
- {slackEnabled ? (
- handleSlackDisable()}
- disabled={slackLoading}
- />
- ) : (
-
- )}
-
- }
- index={cardIndex++}
- />
- {slackPickerOpen && (
-
- {slackDiscoverError ? (
-
{slackDiscoverError}
- ) : (
- <>
- {slackAvailableWorkspaces.map(w => (
-
- ))}
-
- >
- )}
-
- )}
-
+ )}
)}
diff --git a/apps/x/apps/renderer/src/components/settings/connected-accounts-settings.tsx b/apps/x/apps/renderer/src/components/settings/connected-accounts-settings.tsx
index 1cb12f6e..cdacdc39 100644
--- a/apps/x/apps/renderer/src/components/settings/connected-accounts-settings.tsx
+++ b/apps/x/apps/renderer/src/components/settings/connected-accounts-settings.tsx
@@ -1,9 +1,8 @@
"use client"
import * as React from "react"
-import { Loader2, Mic, Mail, Calendar, MessageSquare } from "lucide-react"
+import { Loader2, Mic, Mail, Calendar } from "lucide-react"
import { Button } from "@/components/ui/button"
-import { Switch } from "@/components/ui/switch"
import { Separator } from "@/components/ui/separator"
import { GoogleClientIdModal } from "@/components/google-client-id-modal"
import { ComposioApiKeyModal } from "@/components/composio-api-key-modal"
@@ -235,129 +234,18 @@ export function ConnectedAccountsSettings({ dialogOpen }: ConnectedAccountsSetti
)}
{/* Meeting Notes Section */}
-
-
- Meeting Notes
-
-
-
- {/* Granola */}
-
-
-
-
-
-
-
Granola
-
- Local meeting notes
+ {c.providers.includes('fireflies-ai') && (
+ <>
+
+
+ Meeting Notes
-
-
- {c.granolaLoading && (
-
- )}
-
-
-
- {/* Fireflies */}
- {c.providers.includes('fireflies-ai') && renderOAuthProvider('fireflies-ai', 'Fireflies',
, 'AI meeting transcripts')}
-
-
-
- {/* Team Communication Section */}
-
-
- Team Communication
-
-
-
- {/* Slack */}
-
-
-
-
-
-
-
- Slack
- {c.slackEnabled && c.slackWorkspaces.length > 0 ? (
-
- {c.slackWorkspaces.map(w => w.name).join(', ')}
-
- ) : (
-
- Send messages and view channels
-
- )}
-
-
-
- {(c.slackLoading || c.slackDiscovering) && (
-
- )}
- {c.slackEnabled ? (
- c.handleSlackDisable()}
- disabled={c.slackLoading}
- />
- ) : (
-
- )}
-
-
- {c.slackPickerOpen && (
-
- {c.slackDiscoverError ? (
-
{c.slackDiscoverError}
- ) : (
- <>
- {c.slackAvailableWorkspaces.map(w => (
-
- ))}
-
- >
- )}
-
- )}
-
+ {/* Fireflies */}
+ {renderOAuthProvider('fireflies-ai', 'Fireflies',
, 'AI meeting transcripts')}
+ >
+ )}
>
)
diff --git a/apps/x/apps/renderer/src/hooks/useAnalyticsIdentity.ts b/apps/x/apps/renderer/src/hooks/useAnalyticsIdentity.ts
index 47975fa5..20fd6281 100644
--- a/apps/x/apps/renderer/src/hooks/useAnalyticsIdentity.ts
+++ b/apps/x/apps/renderer/src/hooks/useAnalyticsIdentity.ts
@@ -30,14 +30,14 @@ export function useAnalyticsIdentity() {
// Count notes for total_notes property
try {
- const dirs = await window.ipc.invoke('workspace:readdir', { path: '/' })
+ const entries = await window.ipc.invoke('workspace:readdir', { path: '/' })
let totalNotes = 0
- if (dirs?.entries) {
- for (const entry of dirs.entries) {
- if (entry.type === 'directory') {
+ if (entries) {
+ for (const entry of entries) {
+ if (entry.kind === 'dir') {
try {
const sub = await window.ipc.invoke('workspace:readdir', { path: `/${entry.name}` })
- totalNotes += sub?.entries?.length ?? 0
+ totalNotes += sub?.length ?? 0
} catch {
// skip inaccessible dirs
}
diff --git a/apps/x/packages/core/src/application/assistant/instructions.ts b/apps/x/packages/core/src/application/assistant/instructions.ts
index 3f923b38..76472c90 100644
--- a/apps/x/packages/core/src/application/assistant/instructions.ts
+++ b/apps/x/packages/core/src/application/assistant/instructions.ts
@@ -70,7 +70,6 @@ Rowboat is an agentic assistant for everyday work - emails, meetings, projects,
**App Control:** When users ask you to open notes, show the bases or graph view, filter or search notes, or manage saved views, load the \`app-navigation\` skill first. It provides structured guidance for navigating the app UI and controlling the knowledge base view.
-**Slack:** When users ask about Slack messages, want to send messages to teammates, check channel conversations, or find someone on Slack, load the \`slack\` skill. You can send messages, view channel history, search conversations, and find users. Always show message drafts to the user before sending.
## Learning About the User (save-to-memory)
diff --git a/apps/x/packages/core/src/application/assistant/skills/index.ts b/apps/x/packages/core/src/application/assistant/skills/index.ts
index ee51ecb3..84460961 100644
--- a/apps/x/packages/core/src/application/assistant/skills/index.ts
+++ b/apps/x/packages/core/src/application/assistant/skills/index.ts
@@ -7,7 +7,6 @@ import draftEmailsSkill from "./draft-emails/skill.js";
import mcpIntegrationSkill from "./mcp-integration/skill.js";
import meetingPrepSkill from "./meeting-prep/skill.js";
import organizeFilesSkill from "./organize-files/skill.js";
-import slackSkill from "./slack/skill.js";
import backgroundAgentsSkill from "./background-agents/skill.js";
import createPresentationsSkill from "./create-presentations/skill.js";
@@ -61,12 +60,6 @@ const definitions: SkillDefinition[] = [
summary: "Find, organize, and tidy up files on the user's machine. Move files to folders, clean up Desktop/Downloads, locate specific files.",
content: organizeFilesSkill,
},
- {
- id: "slack",
- title: "Slack Integration",
- summary: "Send Slack messages, view channel history, search conversations, find users, and manage team communication.",
- content: slackSkill,
- },
{
id: "background-agents",
title: "Background Agents",
diff --git a/apps/x/packages/shared/src/ipc.ts b/apps/x/packages/shared/src/ipc.ts
index 7e32a4fc..daf49b95 100644
--- a/apps/x/packages/shared/src/ipc.ts
+++ b/apps/x/packages/shared/src/ipc.ts
@@ -251,6 +251,7 @@ const ipcSchemas = {
config: z.record(z.string(), z.object({
connected: z.boolean(),
error: z.string().nullable().optional(),
+ userId: z.string().optional(),
})),
}),
},
@@ -267,6 +268,7 @@ const ipcSchemas = {
provider: z.string(),
success: z.boolean(),
error: z.string().optional(),
+ userId: z.string().optional(),
}),
res: z.null(),
},