Require user action for Nova connector OAuth

This commit is contained in:
Ishaan Gupta 2026-08-11 18:58:25 +05:30
parent c0d958025a
commit 2c3ea97d2e
3 changed files with 0 additions and 90 deletions

View file

@ -89,10 +89,6 @@ import {
type NovaResearchRun,
researchPollDelayMs,
} from "@/lib/nova-research"
import {
releaseNovaKnowledgeConnectionWindow,
reserveNovaKnowledgeConnectionWindowForMessage,
} from "@/lib/chat-knowledge-connectors"
type ChatMessageSendSource = "typed" | "suggested" | "highlight" | "home"
@ -960,11 +956,6 @@ export function ChatSidebar({
if (hasBusy) return false
const hasErrored = drafts.some((d) => d.status === "error")
if (hasErrored) return false
const reservedKnowledgeProvider =
status !== "submitted" && status !== "streaming"
? reserveNovaKnowledgeConnectionWindowForMessage(trimmed)
: null
const chatIdForSend = threadId ?? fallbackChatId
try {
@ -1115,9 +1106,6 @@ export function ChatSidebar({
return true
} catch (error) {
if (reservedKnowledgeProvider) {
releaseNovaKnowledgeConnectionWindow(reservedKnowledgeProvider)
}
pendingRequestAttachmentsRef.current = []
toast.error("Failed to send message", {
description:

View file

@ -170,7 +170,6 @@ type NovaConnectorToolOutput = {
success?: boolean
error?: string
kind?: string
requestedAction?: "connect"
connectors?: NovaConnectorCardData[]
connector?: NovaConnectorCardData
keyReveal?: { pluginId: string; label?: string } | null
@ -529,13 +528,11 @@ function KnowledgeBaseConnectAction({
connector,
onConnected,
onPendingChange,
autoStart = false,
attemptKey,
}: {
connector: NovaConnectorCardData
onConnected: () => void
onPendingChange?: (pending: boolean) => void
autoStart?: boolean
attemptKey?: string
}) {
const [granolaOpen, setGranolaOpen] = useState(false)
@ -543,7 +540,6 @@ function KnowledgeBaseConnectAction({
"idle" | "starting" | "waiting" | "error"
>("idle")
const [error, setError] = useState<string | null>(null)
const startedRef = useRef(false)
const granolaSucceededRef = useRef(false)
const startingConnectionCountRef = useRef(connector.connectionCount ?? 0)
const provider = connector.provider
@ -630,33 +626,6 @@ function KnowledgeBaseConnectAction({
],
)
useEffect(() => {
if (
!autoStart ||
!provider ||
connector.kind !== "knowledge" ||
connector.canConnect === false ||
startedRef.current
) {
return
}
startedRef.current = true
if (attemptKey && sessionStorage.getItem(attemptKey)) {
setConnectionState("waiting")
onPendingChange?.(true)
return
}
void connect(false)
}, [
attemptKey,
autoStart,
connect,
connector.canConnect,
connector.kind,
onPendingChange,
provider,
])
useEffect(() => {
if (connectionState !== "waiting" || !provider || provider === "granola") {
return
@ -766,13 +735,11 @@ function NovaConnectorCard({
connector,
onConnectionsChanged,
onConnectionPendingChange,
autoStartConnection = false,
connectionAttemptKey,
}: {
connector: NovaConnectorCardData
onConnectionsChanged?: () => void
onConnectionPendingChange?: (pending: boolean) => void
autoStartConnection?: boolean
connectionAttemptKey?: string
}) {
const [revealedKey, setRevealedKey] = useState<string | undefined>()
@ -829,7 +796,6 @@ function NovaConnectorCard({
connector={displayedConnector}
onConnected={() => onConnectionsChanged?.()}
onPendingChange={onConnectionPendingChange}
autoStart={autoStartConnection}
attemptKey={connectionAttemptKey}
/>
)}
@ -944,7 +910,6 @@ function NovaConnectorCard({
connector={displayedConnector}
onConnected={() => onConnectionsChanged?.()}
onPendingChange={onConnectionPendingChange}
autoStart={autoStartConnection}
attemptKey={connectionAttemptKey}
/>
) : null}
@ -1031,9 +996,6 @@ function NovaConnectorToolDisplay({ part }: { part: ToolCallDisplayPart }) {
const [connectionPending, setConnectionPending] = useState(false)
const toolName = connectorToolName(part)
const output = unwrapToolOutput(part.output)
const autoStartConnection =
toolName === "startNovaKnowledgeBaseConnection" &&
output?.requestedAction === "connect"
const connectionAttemptKey = part.toolCallId
? `nova-knowledge-connect:${part.toolCallId}`
: undefined
@ -1169,7 +1131,6 @@ function NovaConnectorToolDisplay({ part }: { part: ToolCallDisplayPart }) {
connector={connector}
onConnectionsChanged={() => void refetchConnections()}
onConnectionPendingChange={setConnectionPending}
autoStartConnection={autoStartConnection}
connectionAttemptKey={connectionAttemptKey}
/>
),
@ -1181,7 +1142,6 @@ function NovaConnectorToolDisplay({ part }: { part: ToolCallDisplayPart }) {
connector={expandedConnector}
onConnectionsChanged={() => void refetchConnections()}
onConnectionPendingChange={setConnectionPending}
autoStartConnection={autoStartConnection}
connectionAttemptKey={connectionAttemptKey}
/>
</div>

View file

@ -38,22 +38,11 @@ type PendingKnowledgeConnectionWindow = {
cleanupTimer: number
}
const CONNECT_INTENT_RE = /\b(connect|link|authorize|add|set\s*up|setup)\b/i
const pendingConnectionWindows = new Map<
NovaKnowledgeBaseProvider,
PendingKnowledgeConnectionWindow
>()
const KNOWLEDGE_BASE_ALIASES: Record<
NovaKnowledgeBaseProvider,
readonly string[]
> = {
"google-drive": ["google drive", "gdrive"],
notion: ["notion"],
onedrive: ["onedrive", "one drive"],
granola: ["granola", "granola notes"],
}
const KNOWLEDGE_BASE_NAMES: Record<NovaKnowledgeBaseProvider, string> = {
"google-drive": "Google Drive",
notion: "Notion",
@ -61,24 +50,6 @@ const KNOWLEDGE_BASE_NAMES: Record<NovaKnowledgeBaseProvider, string> = {
granola: "Granola",
}
function normalizeConnectIntent(value: string): string {
return value.trim().toLowerCase().replace(/[_-]+/g, " ").replace(/\s+/g, " ")
}
export function detectNovaKnowledgeBaseConnectIntent(
message: string,
): NovaKnowledgeBaseProvider | null {
if (!CONNECT_INTENT_RE.test(message)) return null
const normalized = normalizeConnectIntent(message)
return (
NOVA_KNOWLEDGE_BASE_PROVIDERS.find((provider) =>
KNOWLEDGE_BASE_ALIASES[provider].some((alias) =>
normalized.includes(alias),
),
) ?? null
)
}
function closePendingConnectionWindow(
provider: NovaKnowledgeBaseProvider,
closePopup: boolean,
@ -123,15 +94,6 @@ export function reserveNovaKnowledgeConnectionWindow(
return true
}
export function reserveNovaKnowledgeConnectionWindowForMessage(
message: string,
): NovaKnowledgeBaseProvider | null {
const provider = detectNovaKnowledgeBaseConnectIntent(message)
if (!provider || provider === "granola") return null
reserveNovaKnowledgeConnectionWindow(provider)
return provider
}
export function navigateReservedNovaKnowledgeConnectionWindow(
provider: NovaKnowledgeBaseProvider,
authLink: string,