Merge remote-tracking branch 'origin/master' into codex/fs-directory-listing

# Conflicts:
#	docs/rfc/README.md
#	packages/fs/fs-local/src/index.ts
This commit is contained in:
Tianyi Cui
2026-07-04 00:56:17 +08:00
90 changed files with 4283 additions and 1192 deletions

View File

@@ -118,6 +118,16 @@ export interface FsWriteOutcome {
operation: 'create' | 'update'
/** Opaque version of the file after the write. */
version: FsVersion
/**
* The file's content BEFORE the write, or `null` when the file did not exist
* (a create) or was undiffable (binary/non-UTF-8). LF-normalized storage text
* (the diff basis), never a diff — a consumer computes the result-time
* contextual diff from `before`/`after` when `before` is present, else falls
* back to a whole-file diff.
*/
before: string | null
/** The file's content AFTER the write, LF-normalized to share `before`'s diff basis. */
after: string
}
/** A literal-replacement edit request. */
@@ -138,6 +148,14 @@ export interface FsEditOutcome {
replaceAll: boolean
/** Opaque version of the file after the edit. */
version: FsVersion
/**
* The file's content BEFORE the edit. Raw storage text (LF-normalized by the
* backend), never a diff — a consumer computes the result-time contextual diff
* (the applied hunk with context) from `before`/`after`.
*/
before: string
/** The file's content AFTER the edit. */
after: string
}
/**

View File

@@ -52,14 +52,15 @@ class FakeFileSystem extends FileSystem {
]
}
override async writeText(target: FsTarget, content: string, _expected?: FsWriteIntent): Promise<FsWriteOutcome> {
const existed = this.files.has(target.targetKey)
const before = this.files.get(target.targetKey) ?? null
this.files.set(target.targetKey, content)
return { operation: existed ? 'update' : 'create', version: FsVersion('v2') }
return { operation: before !== null ? 'update' : 'create', version: FsVersion('v2'), before, after: content }
}
override async editText(target: FsTarget, edit: FsEditRequest): Promise<FsEditOutcome> {
const content = this.files.get(target.targetKey) ?? ''
this.files.set(target.targetKey, content.split(edit.oldString).join(edit.newString))
return { replacements: 1, replaceAll: edit.replaceAll, version: FsVersion('v3') }
const after = content.split(edit.oldString).join(edit.newString)
this.files.set(target.targetKey, after)
return { replacements: 1, replaceAll: edit.replaceAll, version: FsVersion('v3'), before: content, after }
}
}