mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-27 17:58:07 +00:00
feat(desktop): show resolved titles on @session chips
Route session refs in the transcript through the title resolver so a dropped session reads as its title instead of a truncated id, and use Tabler's funnel for the session chip icon.
This commit is contained in:
parent
cbad98e04e
commit
dfbc9dbb15
3 changed files with 30 additions and 13 deletions
|
|
@ -15,6 +15,7 @@ import {
|
|||
type SlashChipKind,
|
||||
slashIconElement
|
||||
} from '@/components/assistant-ui/directive-text'
|
||||
import { sessionRefFallbackLabel } from '@/lib/session-link-title'
|
||||
|
||||
export const RICH_INPUT_SLOT = 'composer-rich-input'
|
||||
|
||||
|
|
@ -59,7 +60,9 @@ export function refChipHtml(kind: string, rawValue: string, displayLabel?: strin
|
|||
const id = unquoteRef(rawValue)
|
||||
const text = `@${kind}:${quoteRefValue(id)}`
|
||||
|
||||
return `<span contenteditable="false" data-ref-text="${escapeHtml(text)}" data-ref-id="${escapeHtml(id)}" data-ref-kind="${escapeHtml(kind)}" class="${DIRECTIVE_CHIP_CLASS}">${directiveIconSvg(kind)}<span class="truncate">${escapeHtml(displayLabel || refLabel(id))}</span></span>`
|
||||
const label = displayLabel || (kind === 'session' ? sessionRefFallbackLabel(id) : refLabel(id))
|
||||
|
||||
return `<span contenteditable="false" data-ref-text="${escapeHtml(text)}" data-ref-id="${escapeHtml(id)}" data-ref-kind="${escapeHtml(kind)}" class="${DIRECTIVE_CHIP_CLASS}">${directiveIconSvg(kind)}<span class="truncate">${escapeHtml(label)}</span></span>`
|
||||
}
|
||||
|
||||
export function refChipElement(kind: string, rawValue: string, displayLabel?: string) {
|
||||
|
|
@ -74,7 +77,7 @@ export function refChipElement(kind: string, rawValue: string, displayLabel?: st
|
|||
chip.dataset.refKind = kind
|
||||
chip.className = DIRECTIVE_CHIP_CLASS
|
||||
label.className = 'truncate'
|
||||
label.textContent = displayLabel || refLabel(id)
|
||||
label.textContent = displayLabel || (kind === 'session' ? sessionRefFallbackLabel(id) : refLabel(id))
|
||||
chip.append(directiveIconElement(kind), label)
|
||||
|
||||
return chip
|
||||
|
|
|
|||
|
|
@ -36,4 +36,14 @@ describe('hermesDirectiveFormatter.parse', () => {
|
|||
{ kind: 'text', text: ' the entry point' }
|
||||
])
|
||||
})
|
||||
|
||||
it('parses session links with profile/id values', () => {
|
||||
const segments = hermesDirectiveFormatter.parse('see @session:work/20260101_abc123 next')
|
||||
|
||||
expect(segments).toEqual([
|
||||
{ kind: 'text', text: 'see ' },
|
||||
{ kind: 'mention', type: 'session', label: '20260101…', id: 'work/20260101_abc123' },
|
||||
{ kind: 'text', text: ' next' }
|
||||
])
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { Fragment, useEffect, useMemo, useState } from 'react'
|
|||
import { ZoomableImage } from '@/components/chat/zoomable-image'
|
||||
import { extractEmbeddedImages } from '@/lib/embedded-images'
|
||||
import { gatewayMediaDataUrl, isRemoteGateway } from '@/lib/media'
|
||||
import { sessionRefFallbackLabel, useSessionLinkTitle } from '@/lib/session-link-title'
|
||||
|
||||
const HERMES_REF_TYPES = ['file', 'folder', 'url', 'image', 'tool', 'line', 'terminal', 'session'] as const
|
||||
type HermesRefType = (typeof HERMES_REF_TYPES)[number]
|
||||
|
|
@ -40,11 +41,7 @@ const ICON_PATHS: Record<HermesRefType, string[]> = {
|
|||
tool: ['M7 10h3v-3l-3.5 -3.5a6 6 0 0 1 8 8l6 6a2 2 0 0 1 -3 3l-6 -6a6 6 0 0 1 -8 -8l3.5 3.5'],
|
||||
line: ['M5 9l14 0', 'M5 15l14 0', 'M11 4l-4 16', 'M17 4l-4 16'],
|
||||
terminal: ['M5 7l5 5l-5 5', 'M12 19l7 0'],
|
||||
session: [
|
||||
'M8 9h8',
|
||||
'M8 13h6',
|
||||
'M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3z'
|
||||
]
|
||||
session: ['M4 4h16v2.172a2 2 0 0 1 -.586 1.414l-4.414 4.414v7l-6 2v-8.5l-4.48 -4.928a2 2 0 0 1 -.52 -1.345v-2.227']
|
||||
}
|
||||
|
||||
const ICON_FALLBACK = ['M8 12a4 4 0 1 0 8 0a4 4 0 1 0 -8 0', 'M16 12v1.5a2.5 2.5 0 0 0 5 0v-1.5a9 9 0 1 0 -5.5 8.28']
|
||||
|
|
@ -314,12 +311,8 @@ function shortLabel(type: HermesRefType, id: string): string {
|
|||
}
|
||||
}
|
||||
|
||||
// `@session:<profile>/<id>` — show a short id; the composer chip carries the
|
||||
// friendly title, but once sent the wire form only has the id.
|
||||
if (type === 'session') {
|
||||
const sid = id.split('/').filter(Boolean).pop() || id
|
||||
|
||||
return sid.length > 10 ? `${sid.slice(0, 8)}…` : sid
|
||||
return sessionRefFallbackLabel(id)
|
||||
}
|
||||
|
||||
const tail = id.split(/[\\/]/).filter(Boolean).pop()
|
||||
|
|
@ -368,7 +361,9 @@ export function DirectiveContent({ text }: { text: string }) {
|
|||
{segments.map((segment, index) =>
|
||||
segment.kind === 'text' ? (
|
||||
<Fragment key={`t-${index}`}>{segment.text}</Fragment>
|
||||
) : segment.type === 'image' ? null : (
|
||||
) : segment.type === 'image' ? null : segment.type === 'session' ? (
|
||||
<SessionDirectiveChip id={segment.id} key={`m-${index}-${segment.id}`} label={segment.label} />
|
||||
) : (
|
||||
<DirectiveChip id={segment.id} key={`m-${index}-${segment.id}`} label={segment.label} type={segment.type} />
|
||||
)
|
||||
)}
|
||||
|
|
@ -451,6 +446,15 @@ const DirectiveImage: FC<{ id: string; label: string }> = ({ id, label }) => {
|
|||
)
|
||||
}
|
||||
|
||||
const SessionDirectiveChip: FC<{
|
||||
label: string
|
||||
id: string
|
||||
}> = ({ label, id }) => {
|
||||
const resolved = useSessionLinkTitle(id, label)
|
||||
|
||||
return <DirectiveChip id={id} label={resolved} type="session" />
|
||||
}
|
||||
|
||||
const DirectiveChip: FC<{
|
||||
type: string
|
||||
label: string
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue