/** * @license * Copyright 2025 Vybestack LLC * SPDX-License-Identifier: Apache-2.0 */ import type React from 'react'; import { Text, Box } from 'ink'; import { Colors, SemanticColors } from '../../colors.js'; import { createUrlLink, stripControlCharacters, } from '../../utils/terminalLinks.js'; interface OAuthUrlMessageProps { text: string; url: string; } export const OAuthUrlMessage: React.FC = ({ text, url, }) => { const prefixText = '[OAUTH] '; const prefixWidth = prefixText.length; // Extract provider name from text if available. OAuth history items are // exempt from the global ANSI escaping applied to other message types, so // the extracted name is cleaned here before it reaches the heading, the // link label, and the non-linkable fallback label. const providerMatch = text.match(/authorize with ([^\n:]+)/i); const provider = stripControlCharacters( providerMatch ? providerMatch[1] : 'the service', ); const clickHereLabel = `Click here to authorize with ${provider}`; const clickHereLink = createUrlLink(url, clickHereLabel) ?? clickHereLabel; // The full URL is the PRIMARY click target: both the OSC 8 target and the // visible label are the complete URL. This makes the URL copyable and // clickable even when OSC 8 metadata is unsupported or stripped, and Ink's // wrapping re-emits the hyperlink on every wrapped row. `createUrlLink` // returns null for a URL that must not be linkified (non-http(s) scheme or // control characters); the raw URL is still displayed so the user can see // and copy what the provider returned. const urlLink = createUrlLink(url); return ( {prefixText} OAuth Authentication Required for {provider} {clickHereLink} Or copy this URL: {urlLink ?? stripControlCharacters(url)} Tip: when mouse scrolling is enabled, drag to select and it will be copied to your clipboard. For terminal selection, run /mouse off (Ctrl+\). ); };