Optimize workspace instruction change detection

This commit is contained in:
Yichen Jiang
2026-07-13 17:01:42 +08:00
parent aa62b5109a
commit a0e917ffe3
11 changed files with 423 additions and 106 deletions

View File

@@ -21,7 +21,7 @@
import { randomUUID } from 'node:crypto'
import { createReadStream } from 'node:fs'
import { chmod, lstat, mkdir, open, readFile, realpath, readdir, rename, rm, stat } from 'node:fs/promises'
import type { Dirent, Stats } from 'node:fs'
import type { BigIntStats, Dirent, Stats } from 'node:fs'
import { basename, dirname, join, resolve } from 'node:path'
import { TextDecoder } from 'node:util'
import { FsError, FsTargetKey, FsVersion } from '@deepseek-ai/dsh-fs'
@@ -76,9 +76,9 @@ async function readFileAbortable(absolutePath: string, verb: 'read' | 'edit', si
}
}
/** Opaque version token from a stat: millisecond mtime plus byte size. */
function versionOf(info: Stats): FsVersion {
return FsVersion(`${info.mtimeMs}:${info.size}`)
/** Opaque version token from high-resolution identity and freshness metadata. */
function versionOf(info: BigIntStats): FsVersion {
return FsVersion(`${info.dev}:${info.ino}:${info.size}:${info.mtimeNs}:${info.ctimeNs}`)
}
/**
@@ -176,18 +176,21 @@ export async function resolveLocalTarget(cwd: string, path: string): Promise<Loc
}
}
function pathType(info: Stats): PathInfo['type'] {
function pathType(info: Stats | BigIntStats): PathInfo['type'] {
if (info.isFile()) return 'file'
if (info.isDirectory()) return 'directory'
return 'other'
}
function pathLinkType(info: Stats): PathLinkInfo['type'] {
function pathLinkType(info: Stats | BigIntStats): PathLinkInfo['type'] {
if (info.isSymbolicLink()) return 'symlink'
return pathType(info)
}
async function probeStats(absolutePath: string, readStats: (path: string) => Promise<Stats>): Promise<Stats | null> {
async function probeStats<T extends Stats | BigIntStats>(
absolutePath: string,
readStats: (path: string) => Promise<T>,
): Promise<T | null> {
try {
return await readStats(absolutePath)
} catch (error: unknown) {
@@ -206,9 +209,14 @@ async function probeStats(absolutePath: string, readStats: (path: string) => Pro
* @returns the metadata, or null when the path — or a parent segment — does not exist.
*/
export async function probe(absolutePath: string): Promise<PathInfo | null> {
const info = await probeStats(absolutePath, stat)
const info = await probeStats(absolutePath, path => stat(path, { bigint: true }))
if (!info) return null
return { version: versionOf(info), mode: info.mode & 0o777, type: pathType(info), size: info.size }
return {
version: versionOf(info),
mode: Number(info.mode & 0o777n),
type: pathType(info),
size: Number(info.size),
}
}
/**
@@ -217,9 +225,14 @@ export async function probe(absolutePath: string): Promise<PathInfo | null> {
* @returns path-entry metadata, or null when the entry is absent.
*/
export async function probeNoFollow(absolutePath: string): Promise<PathLinkInfo | null> {
const info = await probeStats(absolutePath, lstat)
const info = await probeStats(absolutePath, path => lstat(path, { bigint: true }))
if (!info) return null
return { version: versionOf(info), mode: info.mode & 0o777, type: pathLinkType(info), size: info.size }
return {
version: versionOf(info),
mode: Number(info.mode & 0o777n),
type: pathLinkType(info),
size: Number(info.size),
}
}
// --- Directory listing ---