@swoop111/dsh-tool-fs 0.0.0-stage → 0.2.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.i18n.yaml +142 -0
- package/README.md +277 -2
- package/README.zh.md +278 -0
- package/lib/index.js +1838 -0
- package/lib/types/completion.d.ts +58 -0
- package/lib/types/diff.d.ts +41 -0
- package/lib/types/edit.d.ts +73 -0
- package/lib/types/error.d.ts +19 -0
- package/lib/types/index.d.ts +36 -0
- package/lib/types/read-image.d.ts +80 -0
- package/lib/types/read-render.d.ts +129 -0
- package/lib/types/read-target.d.ts +33 -0
- package/lib/types/read.d.ts +150 -0
- package/lib/types/sandbox.d.ts +82 -0
- package/lib/types/session-cwd.d.ts +26 -0
- package/lib/types/structure.d.ts +67 -0
- package/lib/types/write.d.ts +57 -0
- package/package.json +70 -4
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The sandbox-escalation API shared by the `write` and `edit` tools: the
|
|
3
|
+
* per-call policy resolution, the advertised escalation fields, and the denial-marker
|
|
4
|
+
* mapping — all delegating the vocabulary and the fail-closed approval
|
|
5
|
+
* sequence to `@deepseek-ai/dsh-sandbox` (the same pieces `@deepseek-ai/dsh-tool-bash`
|
|
6
|
+
* uses), so bash and fs escalate identically. Built ONCE per plugin from
|
|
7
|
+
* `ctx.fs.sandboxMode` (the capability fact — is a confining backend mounted?)
|
|
8
|
+
* and shared by both mutating tools.
|
|
9
|
+
*
|
|
10
|
+
* @module @deepseek-ai/dsh-tool-fs/sandbox
|
|
11
|
+
*/
|
|
12
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
13
|
+
import type { ToolExecution } from '@deepseek-ai/dsh-tools';
|
|
14
|
+
import type { SandboxExecutionPolicy, SandboxMode } from '@deepseek-ai/dsh-sandbox';
|
|
15
|
+
/** The two escalation arguments a mutating tool may carry (advertised only under a confining backend). */
|
|
16
|
+
export interface FsEscalationArgs {
|
|
17
|
+
sandbox_permissions?: string;
|
|
18
|
+
justification?: string;
|
|
19
|
+
}
|
|
20
|
+
/** The schema fields for the escalation arguments, spread into a tool's `parameters` when a confining backend is mounted. */
|
|
21
|
+
export interface EscalationSchemaFields {
|
|
22
|
+
sandbox_permissions: {
|
|
23
|
+
type: 'string';
|
|
24
|
+
enum: string[];
|
|
25
|
+
description: string;
|
|
26
|
+
};
|
|
27
|
+
justification: {
|
|
28
|
+
type: 'string';
|
|
29
|
+
description: string;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The filesystem escalation API: advertisement gating, per-call policy
|
|
34
|
+
* resolution, the one-approved wider retry, and denial-marker mapping. A pure
|
|
35
|
+
* product of `ctx` at plugin apply time.
|
|
36
|
+
*/
|
|
37
|
+
export declare class FsSandboxController {
|
|
38
|
+
private readonly ctx;
|
|
39
|
+
/** The escalation targets this composition advertises (`[]` when no confining backend is mounted). */
|
|
40
|
+
readonly escalationModes: readonly SandboxMode[];
|
|
41
|
+
/** Shared per-session policy resolver, required by a confining backend. */
|
|
42
|
+
private readonly policy;
|
|
43
|
+
constructor(ctx: Context);
|
|
44
|
+
/**
|
|
45
|
+
* The escalation schema fields for a mutating tool's `parameters`. Call it
|
|
46
|
+
* only under a confining backend (guard on {@link escalationModes}); the
|
|
47
|
+
* enum pins the closed target vocabulary, the strict-wider check happens per
|
|
48
|
+
* call at execution.
|
|
49
|
+
* @returns the two escalation parameter specs.
|
|
50
|
+
*/
|
|
51
|
+
schemaFields(): EscalationSchemaFields;
|
|
52
|
+
/**
|
|
53
|
+
* The policy to stamp onto this mutation: an approved escalation grant (a
|
|
54
|
+
* strictly wider retry resolved through `ctx.approval` before anything
|
|
55
|
+
* executes), else the session's standing mode. Repeating the standing mode
|
|
56
|
+
* requires no approval. The calling session's cwd is
|
|
57
|
+
* always carried as the workspace root. Validates the escalation argument
|
|
58
|
+
* pairing first.
|
|
59
|
+
* @param toolName - the mutating tool's name, for the approval audit trail.
|
|
60
|
+
* @param args - the call's escalation arguments.
|
|
61
|
+
* @param exec - the tool-execution context (agent, callId, signal).
|
|
62
|
+
* @returns the policy to pass to the mutation, or undefined for an
|
|
63
|
+
* unsandboxed backend.
|
|
64
|
+
*/
|
|
65
|
+
resolvePolicy(toolName: string, args: FsEscalationArgs, exec: ToolExecution): Promise<SandboxExecutionPolicy | undefined>;
|
|
66
|
+
/**
|
|
67
|
+
* Map a thrown provider error for the model: a `FS_SANDBOX_DENIED` becomes a
|
|
68
|
+
* `FsError` whose text is the shared `[sandbox: …]` denial marker plus the
|
|
69
|
+
* same-turn escalation hint, so a policy denial reads identically to bash's
|
|
70
|
+
* WHILE keeping the structured `FS_SANDBOX_DENIED` code — `ToolRuntime`
|
|
71
|
+
* populates `result.error` only for `HarnessError` instances, so a plain
|
|
72
|
+
* `Error` would strip the code retry/observers key off. Any other error
|
|
73
|
+
* passes through unchanged. A `FS_SANDBOX_DENIED` only arises under a
|
|
74
|
+
* confining backend, which always advertises the escalation fields, so the
|
|
75
|
+
* hint always applies here.
|
|
76
|
+
* @param error - the error thrown by the mutation.
|
|
77
|
+
* @param policy - the policy stamped onto the call (names the mode in the marker).
|
|
78
|
+
* @returns the error to throw — the marker `FsError` for a sandbox denial, else the original.
|
|
79
|
+
*/
|
|
80
|
+
mapError(error: unknown, policy: SandboxExecutionPolicy | undefined): unknown;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=sandbox.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derive the working directory a filesystem tool resolves relative paths against: the calling
|
|
3
|
+
* agent's per-session workspace (`exec.agent.session.header.cwd`), so each session's
|
|
4
|
+
* `read`/`write`/`edit` act on its workspace, not the server's launch directory.
|
|
5
|
+
* Non-agent calls return `undefined`, leaving the fallback in the provider rather than reading
|
|
6
|
+
* `process.cwd()` at the tool boundary.
|
|
7
|
+
* @module @deepseek-ai/dsh-tool-fs/session-cwd
|
|
8
|
+
*/
|
|
9
|
+
import type { ToolExecution } from '@deepseek-ai/dsh-tools';
|
|
10
|
+
/**
|
|
11
|
+
* The session workspace cwd for this call, or `undefined` when none applies.
|
|
12
|
+
* @param exec - the tool-execution context; only its optional `agent` is read.
|
|
13
|
+
* @returns the calling agent's session cwd, or undefined for a non-agent caller (the backend then applies its own default).
|
|
14
|
+
*/
|
|
15
|
+
export declare function sessionCwd(exec: ToolExecution): string | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Resolution options shared by all model-facing filesystem tools.
|
|
18
|
+
* @param exec - the tool-execution context supplying session cwd and cancellation.
|
|
19
|
+
* @param policyWorkspaceRoot - resolved per-call root, when a mutation carries sandbox policy.
|
|
20
|
+
* @returns provider resolution options for the current tool call.
|
|
21
|
+
*/
|
|
22
|
+
export declare function sessionResolveOptions(exec: ToolExecution, policyWorkspaceRoot?: string): {
|
|
23
|
+
cwd?: string;
|
|
24
|
+
signal?: AbortSignal;
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=session-cwd.d.ts.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural analysis of file text for read-window completion: markdown
|
|
3
|
+
* fences, bracket nesting, and indentation blocks. The analyzers are pure
|
|
4
|
+
* functions over already-delivered text; they decide which construct a window
|
|
5
|
+
* boundary falls inside, and how many neighbouring lines close an open one.
|
|
6
|
+
*
|
|
7
|
+
* Precision is traded for never touching delivered content: a wrong verdict
|
|
8
|
+
* only costs a few appended real lines, or a silent non-completion. String
|
|
9
|
+
* literals are scanned per line (an unterminated quote never carries into the
|
|
10
|
+
* next line), line comments and C-style block comments are skipped, and
|
|
11
|
+
* brackets inside an open fence are content, so prose and code samples do not
|
|
12
|
+
* fabricate unbalanced constructs.
|
|
13
|
+
* @module @deepseek-ai/dsh-tool-fs/structure
|
|
14
|
+
*/
|
|
15
|
+
/** Which structural rule produced a completion. */
|
|
16
|
+
export type CompletionRule = 'fence' | 'brace' | 'indent';
|
|
17
|
+
/** An unbalanced construct at a window boundary. */
|
|
18
|
+
export type OpenConstruct = {
|
|
19
|
+
kind: 'fence';
|
|
20
|
+
/** The opening fence marker, e.g. ` ``` ` or `~~~~`. */
|
|
21
|
+
marker: string;
|
|
22
|
+
/** Index of the line that opened the construct, within the scanned lines. */
|
|
23
|
+
lineIndex: number;
|
|
24
|
+
} | {
|
|
25
|
+
kind: 'brace';
|
|
26
|
+
/** Bracket levels still open at the boundary. */
|
|
27
|
+
depth: number;
|
|
28
|
+
/** Index of the innermost opening line, within the scanned lines. */
|
|
29
|
+
lineIndex: number;
|
|
30
|
+
} | {
|
|
31
|
+
kind: 'indent';
|
|
32
|
+
/** Indent width of the open block's body. */
|
|
33
|
+
width: number;
|
|
34
|
+
/** Index of the block header line, within the scanned lines. */
|
|
35
|
+
lineIndex: number;
|
|
36
|
+
};
|
|
37
|
+
/** The construct a window starts inside, and the line that opened it. */
|
|
38
|
+
export interface HeadContext {
|
|
39
|
+
/** Which rule found the construct. */
|
|
40
|
+
kind: CompletionRule;
|
|
41
|
+
/** Index into the preceding lines of the line that opened the construct. */
|
|
42
|
+
startIndex: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The construct a window ends inside.
|
|
46
|
+
* @param lines - the delivered window lines, in file order.
|
|
47
|
+
* @returns the construct to close, or `undefined` when the tail is balanced.
|
|
48
|
+
*/
|
|
49
|
+
export declare function detectOpenTail(lines: readonly string[]): OpenConstruct | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* The construct a window starts inside, resolved from the lines that precede it.
|
|
52
|
+
* A fence outranks a bracket block, which outranks an indented block. A
|
|
53
|
+
* construct opened before the supplied preceding lines is not provable and
|
|
54
|
+
* reports nothing, so the completion stays silent rather than guessing.
|
|
55
|
+
* @param window - the delivered window lines, in file order.
|
|
56
|
+
* @param preceding - the lines immediately before the window, in file order; the last entry is the line that precedes the window.
|
|
57
|
+
* @returns the leading context, or `undefined` when the window starts at a construct boundary.
|
|
58
|
+
*/
|
|
59
|
+
export declare function detectOpenHead(window: readonly string[], preceding: readonly string[]): HeadContext | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* How many of the following lines close an open construct.
|
|
62
|
+
* @param construct - the construct {@link detectOpenTail} found.
|
|
63
|
+
* @param appended - the lines following the window, in file order.
|
|
64
|
+
* @returns the count of lines to append, or `0` when the sequence closes nothing.
|
|
65
|
+
*/
|
|
66
|
+
export declare function closureLength(construct: OpenConstruct, appended: readonly string[]): number;
|
|
67
|
+
//# sourceMappingURL=structure.d.ts.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model-facing full-file write. It obtains an optional intent from the single policy slot, calls
|
|
3
|
+
* `ctx.fs.writeText` without a stat, then records the resulting version; no policy means an
|
|
4
|
+
* unconditional atomic create-or-overwrite.
|
|
5
|
+
* @module @deepseek-ai/dsh-tool-fs/src/write
|
|
6
|
+
*/
|
|
7
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
8
|
+
import type { FsWriteOutcome } from '@deepseek-ai/dsh-fs';
|
|
9
|
+
import type { Session } from '@deepseek-ai/dsh-session';
|
|
10
|
+
import type { FsSandboxController } from './sandbox.ts';
|
|
11
|
+
/**
|
|
12
|
+
* Tuning for the drifted-path hint: on a create, a verified high-similarity
|
|
13
|
+
* existing path is disclosed as a note — never rewritten.
|
|
14
|
+
*/
|
|
15
|
+
export interface WriteHintTuning {
|
|
16
|
+
/** Master switch for the drifted-path hint. */
|
|
17
|
+
pathHint: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Absolute path arguments of the session's prior successful tool calls, most
|
|
20
|
+
* recent first — the similarity matcher's history source.
|
|
21
|
+
*/
|
|
22
|
+
priorPaths(session: Session | undefined, limit?: number): string[];
|
|
23
|
+
}
|
|
24
|
+
/** Plugin-config shape for the write hint tuning. */
|
|
25
|
+
export interface WriteRepairConfig {
|
|
26
|
+
/** Disable the drifted-path hint so creates stay silent (default enabled). */
|
|
27
|
+
pathHint?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Validate value constraints the schema DSL can't express: only a non-blank
|
|
31
|
+
* `file_path` — an empty `content` is legitimate (it writes an empty file).
|
|
32
|
+
* @param args - the schema-validated raw tool arguments.
|
|
33
|
+
* @returns the camelCased input; `content` passes through untouched.
|
|
34
|
+
*/
|
|
35
|
+
export declare function parseWriteArgs(args: {
|
|
36
|
+
file_path: string;
|
|
37
|
+
content: string;
|
|
38
|
+
}): {
|
|
39
|
+
filePath: string;
|
|
40
|
+
content: string;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Format a write outcome as one model-facing text block body.
|
|
44
|
+
* @param displayPath - the backend-resolved path rendered in the envelope's `<path>` element.
|
|
45
|
+
* @param outcome - the write outcome; its `operation` selects the Created/Updated wording.
|
|
46
|
+
* @param hint - the drifted-path disclosure appended inside the content block, or undefined.
|
|
47
|
+
* @returns the model-facing confirmation envelope (no file content is echoed back).
|
|
48
|
+
*/
|
|
49
|
+
export declare function formatWriteOutput(displayPath: string, outcome: Pick<FsWriteOutcome, 'operation'>, hint?: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* Register the `write` tool and its scope-aware system-prompt guidance.
|
|
52
|
+
* @param ctx - the plugin context; registrations are effects scoped to it, and execution uses its `fs` service.
|
|
53
|
+
* @param sandbox - the shared sandbox-escalation API (advertisement, mode stamping, denial mapping).
|
|
54
|
+
* @param hints - the drifted-path hint tuning; disabled keeps creates silent.
|
|
55
|
+
*/
|
|
56
|
+
export declare function applyWriteTool(ctx: Context, sandbox: FsSandboxController, hints: WriteHintTuning): void;
|
|
57
|
+
//# sourceMappingURL=write.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,72 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swoop111/dsh-tool-fs",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"description": "Model-facing filesystem tools (read, write, edit) over the DeepSeek Harness filesystem seam (ctx.fs)",
|
|
4
|
+
"version": "0.2.0-rc.2",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
|
|
11
|
+
"directory": "packages/fs/tool-fs"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "lib/index.js",
|
|
15
|
+
"types": "lib/types/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./lib/types/index.d.ts",
|
|
19
|
+
"default": "./lib/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./src/*": "./src/*",
|
|
22
|
+
"./package.json": "./package.json"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"lib/index.js",
|
|
26
|
+
"lib/types/**/*.d.ts"
|
|
27
|
+
],
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"diff": "^9.0.0",
|
|
31
|
+
"@deepseek-ai/schemastery": "~3.18.4",
|
|
32
|
+
"@deepseek-ai/dsh-util-code-language": "0.2.0-rc.2"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"@deepseek-ai/dsh-arg-repair": "0.2.0-rc.2",
|
|
36
|
+
"@deepseek-ai/dsh-sandbox": "0.2.0-rc.2",
|
|
37
|
+
"@deepseek-ai/dsh-llm": "0.2.0-rc.2",
|
|
38
|
+
"@deepseek-ai/dsh-session": "0.2.0-rc.2",
|
|
39
|
+
"@deepseek-ai/dsh-attachment": "0.2.0-rc.2",
|
|
40
|
+
"@deepseek-ai/dsh-fs": "0.2.0-rc.2",
|
|
41
|
+
"@deepseek-ai/dsh-fs-edit-repair": "0.2.0-rc.2",
|
|
42
|
+
"@deepseek-ai/dsh-sandbox-policy": "0.2.0-rc.2",
|
|
43
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.0-rc.2",
|
|
44
|
+
"@deepseek-ai/dsh-tools": "0.2.0-rc.2",
|
|
45
|
+
"@deepseek-ai/dsh-user-approval": "0.2.0-rc.2",
|
|
46
|
+
"@deepseek-ai/cordis": "~4.0.4"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@deepseek-ai/dsh-agent-loop": "0.2.0-rc.2",
|
|
50
|
+
"@deepseek-ai/dsh-agent": "0.2.0-rc.2",
|
|
51
|
+
"@deepseek-ai/dsh-arg-repair": "0.2.0-rc.2",
|
|
52
|
+
"@deepseek-ai/dsh-agent-loop-testkit": "0.2.0-rc.2",
|
|
53
|
+
"@deepseek-ai/dsh-attachment": "0.2.0-rc.2",
|
|
54
|
+
"@deepseek-ai/dsh-fs": "0.2.0-rc.2",
|
|
55
|
+
"@deepseek-ai/dsh-fs-local": "0.2.0-rc.2",
|
|
56
|
+
"@deepseek-ai/dsh-fs-edit-repair": "0.2.0-rc.2",
|
|
57
|
+
"@deepseek-ai/dsh-llm": "0.2.0-rc.2",
|
|
58
|
+
"@deepseek-ai/dsh-llm-deepseek": "0.2.0-rc.2",
|
|
59
|
+
"@deepseek-ai/dsh-fs-observation-policy": "0.2.0-rc.2",
|
|
60
|
+
"@deepseek-ai/dsh-llm-deepseek-api-key": "0.2.0-rc.2",
|
|
61
|
+
"@deepseek-ai/dsh-user-approval": "0.2.0-rc.2",
|
|
62
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.0-rc.2",
|
|
63
|
+
"@deepseek-ai/dsh-sandbox": "0.2.0-rc.2",
|
|
64
|
+
"@deepseek-ai/dsh-sandbox-policy": "0.2.0-rc.2",
|
|
65
|
+
"@deepseek-ai/dsh-session": "0.2.0-rc.2",
|
|
66
|
+
"@deepseek-ai/cordis": "~4.0.4",
|
|
67
|
+
"@deepseek-ai/dsh-tools": "0.2.0-rc.2",
|
|
68
|
+
"@deepseek-ai/dsh-scope": "0.2.0-rc.2",
|
|
69
|
+
"@deepseek-ai/dsh-ptc-runtime": "0.2.0-rc.2",
|
|
70
|
+
"@deepseek-ai/dsh-session-projection": "0.2.0-rc.2"
|
|
71
|
+
}
|
|
72
|
+
}
|