docs: rebalance prose cleanup and add trimming skill
This commit is contained in:
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user