diff --git a/apps/desktop/src/app/chat/composer/rich-editor.ts b/apps/desktop/src/app/chat/composer/rich-editor.ts
index 21f0286c9f8..8978d6f1520 100644
--- a/apps/desktop/src/app/chat/composer/rich-editor.ts
+++ b/apps/desktop/src/app/chat/composer/rich-editor.ts
@@ -11,11 +11,11 @@ import {
directiveIconElement,
directiveIconSvg,
formatRefValue,
+ refChipLabel,
slashChipClass,
type SlashChipKind,
slashIconElement
} from '@/components/assistant-ui/directive-text'
-import { sessionRefFallbackLabel } from '@/lib/session-refs'
export const RICH_INPUT_SLOT = 'composer-rich-input'
@@ -35,10 +35,6 @@ export function unquoteRef(raw: string) {
return quoted ? raw.slice(1, -1) : raw.replace(/[,.;!?]+$/, '')
}
-export function refLabel(id: string) {
- return id.split(/[\\/]/).filter(Boolean).pop() || id
-}
-
/** Always-quote variant of formatRefValue — chips need a fence even for safe values. */
export function quoteRefValue(value: string) {
if (!value.includes('`')) {
@@ -60,9 +56,9 @@ export function refChipHtml(kind: string, rawValue: string, displayLabel?: strin
const id = unquoteRef(rawValue)
const text = `@${kind}:${quoteRefValue(id)}`
- const label = displayLabel || (kind === 'session' ? sessionRefFallbackLabel(id) : refLabel(id))
+ const label = displayLabel || refChipLabel(kind, id)
- return `${directiveIconSvg(kind)}${escapeHtml(label)}`
+ return `${directiveIconSvg(kind)}${escapeHtml(label)}`
}
export function refChipElement(kind: string, rawValue: string, displayLabel?: string) {
@@ -72,12 +68,13 @@ export function refChipElement(kind: string, rawValue: string, displayLabel?: st
const label = document.createElement('span')
chip.contentEditable = 'false'
+ chip.title = id
chip.dataset.refText = text
chip.dataset.refId = id
chip.dataset.refKind = kind
chip.className = DIRECTIVE_CHIP_CLASS
label.className = 'truncate'
- label.textContent = displayLabel || (kind === 'session' ? sessionRefFallbackLabel(id) : refLabel(id))
+ label.textContent = displayLabel || refChipLabel(kind, id)
chip.append(directiveIconElement(kind), label)
return chip
diff --git a/apps/desktop/src/components/assistant-ui/directive-text.tsx b/apps/desktop/src/components/assistant-ui/directive-text.tsx
index 317489a96f8..312c7d9414d 100644
--- a/apps/desktop/src/components/assistant-ui/directive-text.tsx
+++ b/apps/desktop/src/components/assistant-ui/directive-text.tsx
@@ -277,7 +277,7 @@ function parseDirectiveText(text: string): Unstable_DirectiveSegment[] {
start: match.index ?? 0,
end: (match.index ?? 0) + match[0].length,
type: match[1] || 'file',
- label: shortLabel(match[1] as HermesRefType, id),
+ label: refChipLabel(match[1] || 'file', id),
id
}
}),
@@ -320,25 +320,30 @@ function parseDirectiveText(text: string): Unstable_DirectiveSegment[] {
return segments
}
-function shortLabel(type: HermesRefType, id: string): string {
+/** Display text for a `@kind:value` chip. Shared with the composer's
+ * contenteditable chips so a link reads the same before and after send: the
+ * host leads (scheme and `www.` are noise) and the path rides along for the
+ * chip's `truncate` to cut — a bare hostname can't tell two links apart. */
+export function refChipLabel(type: string, id: string): string {
if (type === 'terminal') {
return id || 'terminal'
}
+ if (type === 'session') {
+ return sessionRefFallbackLabel(id)
+ }
+
if (type === 'url') {
try {
- const parsed = new URL(id)
+ const { hostname, pathname, search } = new URL(id)
+ const path = `${pathname}${search}`.replace(/\/$/, '')
- return parsed.hostname || id
+ return `${hostname.replace(/^www\./i, '')}${path}` || id
} catch {
return id
}
}
- if (type === 'session') {
- return sessionRefFallbackLabel(id)
- }
-
const tail = id.split(/[\\/]/).filter(Boolean).pop()
return tail || id