mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-30 01:41:43 +00:00
fix(tui): wrap markdown links in Link so Ghostty/iTerm/kitty get real OSC 8 hyperlinks
renderLink was discarding the URL entirely — it rendered the label as amber underlined text and dropped the href. Result: Cmd+Click / Ctrl+Click did nothing in any terminal, including Ghostty. Now both markdown links `[label](url)` and bare `https://…` URLs are wrapped in @hermes/ink's Link component, which emits OSC 8 (\\x1b]8;;url\\x07label\\x1b]8;;\\x07) when supportsHyperlinks() returns true. ADDITIONAL_HYPERLINK_TERMINALS already includes ghostty, iTerm2, kitty, alacritty, Hyper. Autolinks that look like bare emails (foo@bar.com) now prepend mailto: in the href so they open the mail client correctly. Also adds a typed declaration for Link in hermes-ink.d.ts.
This commit is contained in:
parent
a7f4d756b7
commit
5c8b291607
2 changed files with 24 additions and 11 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { Box, Text } from '@hermes/ink'
|
||||
import { Box, Link, Text } from '@hermes/ink'
|
||||
import { memo, type ReactNode, useMemo } from 'react'
|
||||
|
||||
import { highlightLine, isHighlightable } from '../lib/syntax.js'
|
||||
|
|
@ -23,10 +23,12 @@ type Fence = {
|
|||
len: number
|
||||
}
|
||||
|
||||
const renderLink = (key: number, t: Theme, label: string) => (
|
||||
<Text color={t.color.amber} key={key} underline>
|
||||
{label}
|
||||
</Text>
|
||||
const renderLink = (key: number, t: Theme, label: string, url: string) => (
|
||||
<Link key={key} url={url}>
|
||||
<Text color={t.color.amber} underline>
|
||||
{label}
|
||||
</Text>
|
||||
</Link>
|
||||
)
|
||||
|
||||
const trimBareUrl = (value: string) => {
|
||||
|
|
@ -38,11 +40,17 @@ const trimBareUrl = (value: string) => {
|
|||
}
|
||||
}
|
||||
|
||||
const renderAutolink = (key: number, t: Theme, raw: string) => (
|
||||
<Text color={t.color.amber} key={key} underline>
|
||||
{raw.replace(/^mailto:/, '')}
|
||||
</Text>
|
||||
)
|
||||
const renderAutolink = (key: number, t: Theme, raw: string) => {
|
||||
const url = raw.startsWith('mailto:') ? raw : raw.includes('@') && !raw.startsWith('http') ? `mailto:${raw}` : raw
|
||||
|
||||
return (
|
||||
<Link key={key} url={url}>
|
||||
<Text color={t.color.amber} underline>
|
||||
{raw.replace(/^mailto:/, '')}
|
||||
</Text>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
const indentDepth = (indent: string) => Math.floor(indent.replace(/\t/g, ' ').length / 2)
|
||||
|
||||
|
|
@ -142,7 +150,7 @@ function MdInline({ t, text }: { t: Theme; text: string }) {
|
|||
</Text>
|
||||
)
|
||||
} else if (m[4] && m[5]) {
|
||||
parts.push(renderLink(parts.length, t, m[4]))
|
||||
parts.push(renderLink(parts.length, t, m[4], m[5]))
|
||||
} else if (m[6]) {
|
||||
parts.push(renderAutolink(parts.length, t, m[6]))
|
||||
} else if (m[7]) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue