fix(tui): preserve reference file mention urls

This commit is contained in:
Shoubhit Dash
2026-05-09 14:08:53 +05:30
parent 8318b686cb
commit e515c0c62c
2 changed files with 37 additions and 8 deletions
@@ -12,6 +12,7 @@ import fuzzysort from "fuzzysort"
import path from "path"
import { createEffect, createMemo, createResource, createSignal, onCleanup, onMount, type Accessor } from "solid-js"
import * as Locale from "@/util/locale"
import { ConfigReference } from "@/config/reference"
import {
createPromptHistory,
isExitCommand,
@@ -283,6 +284,19 @@ export function createPromptState(input: PromptInput): PromptState {
},
}))
})
const referenceNames = createMemo(() =>
input
.agents()
.filter((item) => item.options.reference !== undefined)
.map((item) => item.name)
.toSorted((a, b) => b.length - a.length),
)
const referenceFilePath = (value: string) => {
for (const name of referenceNames()) {
if (value.startsWith(`${name}:/`)) return { name, path: value.slice(name.length + 2).replace(/\\/g, "/") }
if (value.startsWith(`${name}/`)) return { name, path: value.slice(name.length + 1).replace(/\\/g, "/") }
}
}
const resources = createMemo<Auto[]>(() => {
return input.resources().map((item) => ({
kind: "mention",
@@ -331,7 +345,10 @@ export function createPromptState(input: PromptInput): PromptState {
return a.localeCompare(b)
})
.map((item): Auto => {
const url = pathToFileURL(path.resolve(input.directory, item))
const reference = referenceFilePath(item)
const url = reference
? new URL(ConfigReference.fileUrl(reference.name, reference.path))
: pathToFileURL(path.resolve(input.directory, item))
let filename = item
if (next.line && !item.endsWith("/")) {
filename = `${item}#${next.line.start}${next.line.end ? `-${next.line.end}` : ""}`
@@ -366,7 +383,9 @@ export function createPromptState(input: PromptInput): PromptState {
},
{ initialValue: [] as Auto[] },
)
const mentionOptions = createMemo(() => [...agents(), ...files(), ...resources()])
const mentionOptions = createMemo(() =>
referenceFilePath(removeLineRange(query())) ? files() : [...agents(), ...files(), ...resources()],
)
const slashOptions = createMemo<SlashOption[]>(() => {
const builtins = [
{ kind: "slash", name: "new", display: "/new", description: "start a new session" } satisfies SlashOption,
@@ -18,6 +18,7 @@ import { Locale } from "@/util/locale"
import type { PromptInfo } from "./history"
import { useFrecency } from "./frecency"
import { useBindings } from "../../keymap"
import { ConfigReference } from "@/config/reference"
function removeLineRange(input: string) {
const hashIndex = input.lastIndexOf("#")
@@ -225,8 +226,10 @@ export function Autocomplete(props: {
function createFilePart(item: string, lineRange?: { startLine: number; endLine?: number }) {
const baseDir = (sync.path.directory || process.cwd()).replace(/\/+$/, "")
const fullPath = path.isAbsolute(item) ? item : path.join(baseDir, item)
const urlObj = pathToFileURL(fullPath)
const reference = ConfigReference.parseFilePath(item, sync.data.config.reference)
const urlObj = reference
? new URL(ConfigReference.fileUrl(reference.name, reference.path))
: pathToFileURL(path.isAbsolute(item) ? item : path.join(baseDir, item))
const filename =
lineRange && !item.endsWith("/")
? `${item}#${lineRange.startLine}${lineRange.endLine ? `-${lineRange.endLine}` : ""}`
@@ -261,6 +264,9 @@ export function Autocomplete(props: {
}
function normalizeMentionPath(filePath: string) {
const reference = ConfigReference.parseFilePath(filePath, sync.data.config.reference)
if (reference) return ConfigReference.formatFilePath(reference.name, reference.path)
const baseDir = sync.path.directory || process.cwd()
const absolute = path.resolve(filePath)
const relative = path.relative(baseDir, absolute)
@@ -430,11 +436,15 @@ export function Autocomplete(props: {
const filesValue = files()
const agentsValue = agents()
const commandsValue = commands()
const searchValue = search()
const reference = ConfigReference.parseFilePath(removeLineRange(searchValue), sync.data.config.reference)
const mixed: AutocompleteOption[] =
store.visible === "@" ? [...agentsValue, ...(filesValue || []), ...mcpResources()] : [...commandsValue]
const searchValue = search()
store.visible === "@"
? reference
? filesValue || []
: [...agentsValue, ...(filesValue || []), ...mcpResources()]
: [...commandsValue]
if (!searchValue) {
return mixed
@@ -506,7 +516,7 @@ export function Autocomplete(props: {
const currentCursorOffset = input.cursorOffset
const displayText = selected.display.trimEnd()
const path = displayText.startsWith("@") ? displayText.slice(1) : displayText
const path = selected.path ?? (displayText.startsWith("@") ? displayText.slice(1) : displayText)
input.cursorOffset = store.index
const startCursor = input.logicalCursor