mirror of
https://github.com/stablyai/orca.git
synced 2026-11-03 10:37:35 +00:00
* feat(native-chat): preview cards for web links in chat Hovering an http(s) link that isn't the repo's own PR or issue shows the page's image, favicon, site name, title and description. The chat's host fetches the page with no cookies, refusing private, loopback and link-local addresses after DNS and on every redirect, and returns images as data URLs. A Chat > Behavior setting turns web previews off. * perf(native-chat): cap link preview caches at 20 MB each Preview images are held as data URLs, so a count limit alone let the renderer and main caches grow to hundreds of MB in a long session. * fix(link-preview): keep a > inside quoted attribute values Page tags ended at the first >, so content="Home > Docs" was cut short and an og tag whose content came before its property was dropped. * fix(native-chat): keep link preview caches within budget and keyed by host A preview that finished after newer ones stopped eviction at itself, so both caches could stay over their byte limit. The GitHub card's load key also left out the host its repo lives on. * fix(link-preview): decode the named entities page titles use Only five named entities were decoded, so titles like Docs – Guide showed the raw codes in preview cards.
29 lines
1.0 KiB
TypeScript
29 lines
1.0 KiB
TypeScript
/** What a page says about itself in its <head>, for a chat link's hover card. */
|
|
export type LinkPreview = {
|
|
/** The page that answered, after redirects. */
|
|
url: string
|
|
title: string | null
|
|
description: string | null
|
|
siteName: string | null
|
|
/** Fetched by the host through the same address guard; never a URL the renderer loads. */
|
|
imageDataUrl: string | null
|
|
faviconDataUrl: string | null
|
|
}
|
|
|
|
export type LinkPreviewRequest = { url: string }
|
|
|
|
/** `unavailable` covers blocked addresses, non-HTML responses, timeouts and pages with no title. */
|
|
export type LinkPreviewResult = { kind: 'page'; preview: LinkPreview } | { kind: 'unavailable' }
|
|
|
|
/** Characters held by a preview; data URLs are ASCII, so this tracks its memory closely. */
|
|
export function linkPreviewSize(preview: LinkPreview): number {
|
|
return [
|
|
preview.url,
|
|
preview.title,
|
|
preview.description,
|
|
preview.siteName,
|
|
preview.imageDataUrl,
|
|
preview.faviconDataUrl
|
|
].reduce((total, text) => total + (text?.length ?? 0), 0)
|
|
}
|