✨ feat(vscode): 代码阅读预览里工作区外的库文件也能问 AI,问答记进第一个工作区文件夹,重写注释不对库文件开放

This commit is contained in:
cruldra committed 2026-10-13 21:50:54 +11:00
1 parent cecae0e244
commit 39dfd9b084
24 files changed
+463 -79

No files matched your search

+35 -2
View File
@@ -1,6 +1,7 @@
/**
* 按文件 / 目录记东西的一份表(文件注释、代码问答):每个工作区文件夹一份,落盘到 `.spx` 里的一个 JSON 文件,
* 形状是 `{ "相对路径": 值 }`。键相对这个工作区文件夹、`/` 分隔;改名、挪位置、删除时整棵子树跟着走。
* 代码问答还记工作区外的库文件,键是 `~/…` 或绝对路径(见 [outsideKey])。
*/
import { promises as fsp } from 'node:fs'
@@ -31,6 +32,38 @@ export function toPathKey(rootPath: string, targetPath: string): string | undefi
return normalizeKey(path.posix.relative(rootPath, targetPath))
}
/**
* 工作区外的文件 / 目录(比如库源码)的键:在家目录下写成 `~/…`,别处写绝对路径。
* 工作区里的键是相对路径,开头不会是 `~/` 或 `/`,两边撞不上。
*
* @param targetPath 文件 / 目录的 `Uri.path`
* @param homePath 家目录的 `Uri.path`
*/
export function outsideKey(targetPath: string, homePath: string): string {
const underHome = toPathKey(homePath, targetPath)
return underHome === undefined ? path.posix.normalize(targetPath).replace(/\/+$/, '') : `~/${underHome}`
}
/** 工作区外的键(见 [outsideKey])在磁盘上的 `Uri.path`;工作区里的相对路径键返回 `undefined`。 */
export function outsidePath(key: string, homePath: string): string | undefined {
if (key.startsWith('~/'))
return path.posix.join(homePath, key.slice(2))
return key.startsWith('/') ? key : undefined
}
/** 读表时把一个键规范成统一写法:相对路径同 [normalizeKey],工作区外的 `~/…`、绝对路径(见 [outsideKey])也认;跑出家目录的、空的返回 `undefined`。 */
export function tableKey(raw: string): string | undefined {
if (raw.startsWith('~/')) {
const underHome = normalizeKey(raw.slice(2))
return underHome === undefined ? undefined : `~/${underHome}`
}
if (raw.startsWith('/')) {
const absolute = path.posix.normalize(raw).replace(/\/+$/, '')
return absolute === '' ? undefined : absolute
}
return normalizeKey(raw)
}
function isUnder(candidate: string, key: string): boolean {
return candidate === key || candidate.startsWith(`${key}/`)
}
@@ -68,7 +101,7 @@ function fileIn<T>(workspaceRoot: string, file: PathMapFile<T>): string {
return path.join(workspaceRoot, ...file.path.split('/'))
}
/** 读工作区文件夹里的这份表。文件缺失 / 解析失败 / 不是对象都返回 `{}`;键不合法、值认不出的条目跳过。 */
/** 读工作区文件夹里的这份表。文件缺失 / 解析失败 / 不是对象都返回 `{}`;键认不出(见 [tableKey])、值认不出的条目跳过。 */
export async function readPathMap<T>(workspaceRoot: string, file: PathMapFile<T>): Promise<PathMap<T>> {
let raw: string
try {
@@ -83,7 +116,7 @@ export async function readPathMap<T>(workspaceRoot: string, file: PathMapFile<T>
return {}
const map: PathMap<T> = {}
for (const [rawKey, rawValue] of Object.entries(parsed as Record<string, unknown>)) {
const key = normalizeKey(rawKey)
const key = tableKey(rawKey)
const value = file.parse(rawValue)
if (key !== undefined && value !== undefined)
map[key] = value