docs: rebalance prose cleanup and add trimming skill

This commit is contained in:
Tianyi Cui
2026-07-13 23:27:00 +08:00
parent fcdc318dda
commit 148046b9c8
392 changed files with 2801 additions and 1754 deletions
+6 -3
View File
@@ -1,5 +1,6 @@
/**
* Result-time contextual-diff computation for the `write`/`edit` tools.
* Result-time contextual diff presentation for write and edit. Storage returns before/after
* text; this model-facing layer derives one three-line-context card per applied hunk.
* @module @deepseek-ai/dsh-tool-fs/src/diff
*/
@@ -21,7 +22,8 @@ export type FsDiffMeta = { diffs: FileDiff[] }
/**
* Compute one {@link FileDiff} per hunk between `before` and `after`, each carrying the
* applied change plus {@link DIFF_CONTEXT} context lines.
* applied change plus {@link DIFF_CONTEXT} context lines. Pure insertions use `oldText: null`,
* patch-only no-newline markers are omitted, and scattered replacements remain separate hunks.
*
* @param path - the path stamped on every produced diff (the model-facing `file_path`; the
* bridge relativizes it).
@@ -65,7 +67,8 @@ function isFileDiff(value: unknown): value is FileDiff {
}
/**
* Narrow opaque live or replayed result metadata to non-empty file diffs.
* Narrow opaque live or replayed result metadata to non-empty file diffs. Malformed metadata
* returns `undefined` so presentation can fall back instead of throwing during replay.
* @param meta - result metadata.
* @returns validated hunks, or `undefined` for absent or malformed data.
*/
+6 -4
View File
@@ -1,6 +1,7 @@
/**
* The model-facing `edit` tool: update an existing UTF-8 text file by replacing literal text,
* requiring a unique match by default.
* Model-facing literal edit, unique-match by default. It obtains an optional guard from the
* single intent slot, calls `ctx.fs.editText` without a separate stat, then records the observed
* version; no policy means an unconditional atomic edit.
* @module @deepseek-ai/dsh-tool-fs/src/edit
*/
@@ -88,7 +89,7 @@ export function applyEditTool(ctx: Context): void {
)
// Record the observed version (a no-op when no policy plugin listens).
ctx.emit('fs/observed', target, outcome.version, exec)
// The result-time applied-hunk diff (before→after with context lines).
// An edit necessarily changes content, so result metadata carries at least one applied hunk.
const diffs = computeHunkDiffs(input.filePath, outcome.before, outcome.after)
return {
content: [{ type: 'text', text: formatEditOutput(target.displayPath, input.replaceAll) }],
@@ -106,7 +107,8 @@ export function applyEditTool(ctx: Context): void {
locations: [{ path: args.file_path }],
}
},
// Result-time display: the applied contextual-diff hunks carried on `meta`.
// Applied metadata replaces the call-time snippet; errors or malformed replay metadata use
// the generic result rendering.
presentResult(args, result: ToolResult): DiffResultView | undefined {
if (result.isError) return undefined
const diffs = diffsFromMeta(result.meta)
+3 -2
View File
@@ -1,6 +1,7 @@
/**
* The model-facing filesystem tool suite (`read`, `write`, `edit`) over the `ctx.fs` provider
* seam. This single plugin registers all three tools.
* Model-facing read, write, and edit tools over `ctx.fs`. This package owns schemas, validation,
* read windows, formatting, and observation events, never a concrete provider. An optional
* event policy supplies mutation guards; without one the tools use unconditional provider calls.
* @module @deepseek-ai/dsh-tool-fs
*/
+5 -5
View File
@@ -1,7 +1,7 @@
/**
* Cordis-free read rendering for `@deepseek-ai/dsh-tool-fs`: turn a file's decoded text into a
* bounded, line-numbered window (offset/limit, byte cap, per-line truncation) and format it as
* the model-facing text block.
* Pure read presentation: turn provider-decoded text into a bounded, line-numbered window and
* model-facing envelope. Chunk scanning caps the current line, so even one newline-free giant
* line cannot grow memory without bound.
* @module @deepseek-ai/dsh-tool-fs/read-render
*/
@@ -102,8 +102,8 @@ function finish(acc: WindowAccumulator, request: ReadWindow, displayPath: string
}
/**
* Build a bounded, line-numbered window from a file's decoded text chunks.
*
* Build one window from streamed or whole-file chunks, enforcing line and byte caps and throwing
* `FS_NOT_FOUND` when the requested offset is past EOF.
* @param chunks - decoded text chunks in file order; chunk boundaries carry no meaning.
* @param request - the resolved window; the caller has already applied its defaults and caps.
* @param displayPath - the caller-facing path used in the offset-out-of-range error.
+5 -3
View File
@@ -1,6 +1,6 @@
/**
* The model-facing `read` tool: inspect a UTF-8 text file and return line-numbered content
* with pagination guidance.
* Model-facing UTF-8 read. It performs one provider stat for type, routing, and observed version,
* streams large or size-unknown files, renders a bounded window, then emits the observation.
* @module @deepseek-ai/dsh-tool-fs/src/read
*/
@@ -90,6 +90,7 @@ export function applyReadTool(ctx: Context, caps: ReadToolCaps): void {
const target = await ctx.fs.resolve(input.filePath, cwd !== undefined ? { cwd } : undefined)
// One stat: type check + size routing + the version recorded as observed.
// A concurrent write can only make a later guarded mutation fail stale and require reread.
const info = await ctx.fs.stat(target, exec.signal)
if (!info) throw new FsError(`cannot read "${target.displayPath}": not found`, 'FS_NOT_FOUND')
if (info.type !== 'file') throw new FsError(`cannot read "${target.displayPath}": not a regular file`, 'FS_NOT_REGULAR_FILE')
@@ -119,7 +120,8 @@ export function applyReadTool(ctx: Context, caps: ReadToolCaps): void {
},
// Pure display: a generic card titled by the file with the read window appended (`Read
// foo.txt (5 - 8)`), `read` kind (icon), and a follow-along location whose line is the
// read's offset (defaulting to 1).
// read's offset (defaulting to 1). The window reflects raw args, so an omitted limit keeps
// the title bare instead of smuggling config into this pure presenter.
presentCall(args): GenericCallView {
const { offset, limit } = args
const window = limit !== undefined && limit > 0
+2
View File
@@ -3,6 +3,8 @@
* agent's per-session workspace (`exec.agent.session.header.cwd`), so each ACP session's
* `read`/`write`/`edit` act on ITS workspace, not the server's launch dir — mirroring how
* `dsh-tool-bash` defaults a bash `workdir` to the session cwd.
* Non-agent calls return `undefined`, leaving the fallback in the provider rather than reading
* `process.cwd()` at the tool seam.
* @module @deepseek-ai/dsh-tool-fs/session-cwd
*/
+7 -3
View File
@@ -1,5 +1,7 @@
/**
* The model-facing `write` tool: create or fully replace a UTF-8 text file.
* Model-facing full-file write. It obtains an optional intent from the single policy slot, calls
* `ctx.fs.writeText` without a stat, then records the resulting version; no policy means an
* unconditional atomic create-or-overwrite.
* @module @deepseek-ai/dsh-tool-fs/src/write
*/
@@ -67,7 +69,8 @@ export function applyWriteTool(ctx: Context): void {
const outcome = await ctx.fs.writeText(target, input.content, intent, exec.signal)
// Record the observed version (a no-op when no policy plugin listens).
ctx.emit('fs/observed', target, outcome.version, exec)
// Attach a contextual hunk as `meta` only for an overwrite (a before-version exists).
// Overwrites carry applied hunks. Creates have no prior text, so result presentation uses
// the args-derived whole-file diff instead.
const diffs = outcome.before !== null ? computeHunkDiffs(input.filePath, outcome.before, outcome.after) : []
return {
content: [{ type: 'text', text: formatWriteOutput(target.displayPath, outcome) }],
@@ -87,7 +90,8 @@ export function applyWriteTool(ctx: Context): void {
},
// Result-time display: a `diff` card so the completed `tool_call_update` re-installs the
// diff rather than the model-facing result text (an ACP `tool_call_update.content` REPLACES
// the call's content, so a text result would clobber the pending diff card).
// the call's content, so a text result would clobber the pending diff card). Overwrites use
// applied metadata; creates and identical overwrites use the replay-safe args fallback.
presentResult(args, result: ToolResult): DiffResultView | undefined {
if (result.isError) return undefined
const diffs = diffsFromMeta(result.meta)