Просмотр исходного кода

Merge pull request #291 from deepseek-harness/codex/simp-hide-fs-internals

refactor: hide filesystem implementation helpers
Tianyi Cui 2 месяцев назад
Родитель
Сommit
60a3137fc2

+ 2 - 2
docs/config-catalog.md

@@ -256,7 +256,7 @@ export interface Config {
 }
 ```
 
-Source: [`packages/fs/fs-local/src/index.ts:49`](../packages/fs/fs-local/src/index.ts)
+Source: [`packages/fs/fs-local/src/index.ts:35`](../packages/fs/fs-local/src/index.ts)
 
 ## `@deepseek-ai/dsh-hooks-claude`
 
@@ -832,7 +832,7 @@ export interface Config {
 }
 ```
 
-Source: [`packages/fs/tool-fs/src/index.ts:31`](../packages/fs/tool-fs/src/index.ts)
+Source: [`packages/fs/tool-fs/src/index.ts:22`](../packages/fs/tool-fs/src/index.ts)
 
 ## `@deepseek-ai/dsh-tool-skill`
 

+ 1 - 1
packages/fs/fs-local/README.md

@@ -19,7 +19,7 @@ await ctx.plugin(LocalFileSystem, { cwd: process.cwd() })
 - **`writeText`** — atomic: writes to a temp file opened exclusively (`wx`, `0o600`) inside a randomly-named private staging dir (`0o700`) next to the target, fsyncs, then renames over the target. An existing file's mode is preserved, while new files default to `0o600`. The `expected` guard is OPTIONAL: omitting it unconditionally creates-or-overwrites; `createIfAbsent` creates a missing target and rejects an existing one (`FS_NOT_OBSERVED`); `replaceIfVersion` replaces only at the observed version (a missing target or mismatch is `FS_STALE_VERSION`).
 - **`editText`** — atomic literal read-modify-write over the same primitive, serialized per target by a mutation lock. The `expected` guard is OPTIONAL: when supplied it verifies the version BEFORE literal matching (a stale edit reports `FS_STALE_VERSION`, never `FS_EDIT_NOT_FOUND`/`FS_AMBIGUOUS_EDIT` against newer content); omitting it edits the current content unconditionally. A missing target reports `FS_STALE_VERSION` either way. LF-normalizes for matching, restores the file's dominant CRLF/LF style, and rejects empty `oldString` / zero matches (`FS_EDIT_NOT_FOUND`) or ambiguous multi-matches without `replace_all` (`FS_AMBIGUOUS_EDIT`).
 
-The raw I/O lives in `src/fsio.ts` (Cordis-free, independently unit-tested); `src/index.ts` is the thin service wiring.
+The package-root SDK surface is the default/named `LocalFileSystem` class plus `Config`. Raw I/O lives in `src/fsio.ts` (Cordis-free, independently unit-tested); `src/index.ts` is the thin service wiring.
 
 ## Model Experience
 

+ 0 - 14
packages/fs/fs-local/src/index.ts

@@ -31,20 +31,6 @@ import {
 } from './fsio.ts'
 import type { FsIoInternals } from './fsio.ts'
 
-export {
-  applyLiteralEdit,
-  listDirectory,
-  probe,
-  readForEdit,
-  readTextForDiff,
-  readWholeText,
-  resolveLocalTarget,
-  restoreLineEndings,
-  streamWholeText,
-  writeFileAtomic,
-} from './fsio.ts'
-export type { FsIoInternals, LineEndings, LocalDirEntry, LocalTarget, PathInfo } from './fsio.ts'
-
 /** Configuration for the local filesystem backend. */
 export interface Config {
   /** Base directory for relative paths. Defaults to `process.cwd()`. */

+ 2 - 2
packages/fs/fs-local/tests/fsio.spec.ts

@@ -20,8 +20,8 @@ import {
   restoreLineEndings,
   streamWholeText,
   writeFileAtomic,
-} from '@deepseek-ai/dsh-fs-local'
-import type { LocalTarget } from '@deepseek-ai/dsh-fs-local'
+} from '../src/fsio.ts'
+import type { LocalTarget } from '../src/fsio.ts'
 import { FsError, FsTargetKey } from '@deepseek-ai/dsh-fs'
 
 let dir: string

+ 1 - 1
packages/fs/tool-fs/README.md

@@ -46,7 +46,7 @@ The tool passes `exec` (the tool-execution context) as the opaque `actor` on eve
 
 `fs/observed` fires AFTER the read/write/edit already succeeded, via a plain `ctx.emit`. A listener is contractually a synchronous, side-effect-only recorder (`@deepseek-ai/dsh-fs-policy`'s is a `WeakMap.set`); the tool does not guard the emit, so a listener that throws would surface as the tool's `isError` result — async or fallible observation does not belong on this event.
 
-The read rendering (line windowing + output formatting) lives in `src/read-render.ts` (Cordis-free, independently unit-tested); `src/read.ts`/`write.ts`/`edit.ts` are the tool executors and `src/index.ts` composes them.
+The package root exports only the Cordis plugin contract (`name`, `inject`, `Config`, and `apply`). Read rendering (line windowing + output formatting) lives in `src/read-render.ts` (Cordis-free, independently unit-tested); `src/read.ts`/`write.ts`/`edit.ts` are the tool executors and `src/index.ts` composes them.
 
 ## Model Experience
 

+ 0 - 9
packages/fs/tool-fs/src/index.ts

@@ -12,15 +12,6 @@ import { applyWriteTool } from './write.ts'
 import { applyEditTool } from './edit.ts'
 import { READ_MAX_BYTES, READ_MAX_LINE_LENGTH } from './read-render.ts'
 
-export { READ_LIMIT, STREAM_MIN_SIZE, applyReadTool, parseReadArgs } from './read.ts'
-export type { ReadToolCaps } from './read.ts'
-export { applyWriteTool, formatWriteOutput, parseWriteArgs } from './write.ts'
-export { applyEditTool, formatEditOutput, parseEditArgs } from './edit.ts'
-export { READ_MAX_BYTES, READ_MAX_LINE_LENGTH, buildWindow, formatReadOutput } from './read-render.ts'
-export type { FileReadOutcome, FileTextLine, ReadWindow, WindowResult } from './read-render.ts'
-export { DIFF_CONTEXT, computeHunkDiffs, diffsFromMeta } from './diff.ts'
-export type { FsDiffMeta } from './diff.ts'
-
 /** Cordis plugin name used by loader diagnostics. */
 export const name = 'tool-fs'
 

+ 1 - 1
packages/fs/tool-fs/tests/diff.spec.ts

@@ -6,7 +6,7 @@
  */
 
 import { describe, expect, it } from 'vitest'
-import { computeHunkDiffs, diffsFromMeta, DIFF_CONTEXT } from '@deepseek-ai/dsh-tool-fs'
+import { computeHunkDiffs, diffsFromMeta, DIFF_CONTEXT } from '../src/diff.ts'
 import type { JsonValue } from '@deepseek-ai/dsh-session'
 
 const lines = (n: number): string => Array.from({ length: n }, (_, i) => `line${i + 1}`).join('\n') + '\n'

+ 2 - 2
packages/fs/tool-fs/tests/read-render.spec.ts

@@ -6,8 +6,8 @@
  */
 
 import { describe, expect, it } from 'vitest'
-import { buildWindow, READ_MAX_BYTES, READ_MAX_LINE_LENGTH } from '@deepseek-ai/dsh-tool-fs'
-import type { ReadWindow } from '@deepseek-ai/dsh-tool-fs'
+import { buildWindow, READ_MAX_BYTES, READ_MAX_LINE_LENGTH } from '../src/read-render.ts'
+import type { ReadWindow } from '../src/read-render.ts'
 
 const DEFAULT_CAPS = { maxLineLength: READ_MAX_LINE_LENGTH, maxBytes: READ_MAX_BYTES }
 const READ_ALL: ReadWindow = { offset: 1, limit: 2000, ...DEFAULT_CAPS }

+ 3 - 2
packages/fs/tool-fs/tests/tools.spec.ts

@@ -20,8 +20,9 @@ import type {
 } from '@deepseek-ai/dsh-fs'
 import * as FsPolicy from '@deepseek-ai/dsh-fs-policy'
 import * as ToolFs from '@deepseek-ai/dsh-tool-fs'
-import { formatReadOutput, STREAM_MIN_SIZE } from '@deepseek-ai/dsh-tool-fs'
-import type { FileReadOutcome } from '@deepseek-ai/dsh-tool-fs'
+import { STREAM_MIN_SIZE } from '../src/read.ts'
+import { formatReadOutput } from '../src/read-render.ts'
+import type { FileReadOutcome } from '../src/read-render.ts'
 
 /** An in-memory fake provider; a test can arm a rejection on any primitive. */
 class FakeFs extends FileSystem {