dsh-hashline-edit 0.2.0 → 0.2.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/README.md +59 -55
- package/cordis.patch.yml +1 -1
- package/lib/index.js +7225 -6445
- package/lib/types/dsh/contracts.d.ts +3 -12
- package/lib/types/dsh/fs.d.ts +0 -3
- package/lib/types/dsh/guidance.d.ts +5 -5
- package/lib/types/dsh/host-compat.d.ts +78 -7
- package/lib/types/dsh/index.d.ts +7 -17
- package/lib/types/dsh/metrics/events.d.ts +1 -1
- package/lib/types/dsh/metrics/observer.d.ts +1 -1
- package/lib/types/dsh/sandbox.d.ts +2 -2
- package/lib/types/dsh/shell-hook.d.ts +1 -1
- package/lib/types/dsh/tools/edit.d.ts +10 -0
- package/lib/types/dsh/tools/read.d.ts +3 -3
- package/lib/types/src/domain-errors.d.ts +2 -16
- package/lib/types/src/edit-tool.d.ts +41 -0
- package/lib/types/src/edit-undo.d.ts +2 -11
- package/lib/types/src/file-content/index.d.ts +1 -1
- package/lib/types/src/file-content/preview.d.ts +1 -1
- package/lib/types/src/hash-store.d.ts +2 -2
- package/lib/types/src/hashline/alphabet.d.ts +16 -1
- package/lib/types/src/hashline/hash-identity.d.ts +10 -4
- package/lib/types/src/mutation-engine/engine.d.ts +31 -0
- package/lib/types/src/mutation-engine/pipeline.d.ts +1 -8
- package/lib/types/src/mutation-engine/types.d.ts +50 -40
- package/lib/types/src/payload-contract.d.ts +135 -0
- package/lib/types/src/served-session/serve-render.d.ts +0 -6
- package/lib/types/src/undo-store.d.ts +1 -17
- package/package.json +21 -10
- package/prompts/edit-guidelines.md +10 -0
- package/prompts/edit-snippet.md +1 -0
- package/prompts/edit.md +1 -0
- package/prompts/read-guidelines.md +4 -4
- package/prompts/read.md +1 -1
- package/prompts/undo-last-edit-guidelines.md +2 -2
- package/prompts/undo-last-edit-snippet.md +1 -1
- package/prompts/undo-last-edit.md +1 -1
- package/src/bash-classifier.ts +1626 -0
- package/src/bash-conversion/decide.ts +812 -0
- package/src/bash-display-transform.ts +50 -0
- package/src/bash-multifile-config.ts +239 -0
- package/src/bash-view-config.ts +158 -0
- package/src/cut-repair.ts +11 -77
- package/src/domain-errors.ts +3 -35
- package/src/edit-normalize.ts +8 -0
- package/src/edit-render.ts +161 -0
- package/src/edit-tool.ts +118 -0
- package/src/edit-undo.ts +25 -379
- package/src/edit.ts +136 -0
- package/src/file-content/index.ts +1 -1
- package/src/file-content/preview.ts +1 -1
- package/src/file-content/served-header.ts +1 -1
- package/src/hash-store.ts +1 -18
- package/src/hashline/alphabet.ts +42 -1
- package/src/hashline/hash-identity.ts +12 -3
- package/src/integrations/pi-lens/command.ts +712 -0
- package/src/integrations/pi-lens/config.ts +148 -0
- package/src/integrations/pi-lens/io-bridge-adapter.ts +234 -0
- package/src/integrations/pi-lens/io-bridge.ts +112 -0
- package/src/integrations/pi-lens/settings-overlay.ts +272 -0
- package/src/lifecycle-hooks/index.ts +1992 -0
- package/src/lifecycle-hooks/types.ts +64 -0
- package/src/mutated-files.ts +75 -0
- package/src/mutation-engine/engine.ts +239 -0
- package/src/mutation-engine/index.ts +17 -0
- package/src/mutation-engine/pipeline.ts +27 -198
- package/src/mutation-engine/types.ts +57 -39
- package/src/mutation-queue.ts +1 -1
- package/src/payload-contract.ts +685 -0
- package/src/preview-controller.ts +84 -0
- package/src/prompts.ts +43 -10
- package/src/read.ts +865 -0
- package/src/search-hook.ts +41 -0
- package/src/served-session/serve-render.ts +2 -2
- package/src/store-config.ts +73 -0
- package/src/store-janitor-warning.ts +169 -0
- package/src/store-janitor.ts +539 -0
- package/src/store-kernel/settings.ts +233 -0
- package/src/store.ts +154 -0
- package/src/tui-presenter.ts +134 -0
- package/src/undo-store.ts +5 -74
- package/src/write-hook.ts +130 -0
- package/lib/types/dsh/hide.d.ts +0 -78
- package/lib/types/dsh/tools/apply-patch.d.ts +0 -38
- package/lib/types/src/apply-patch/commit.d.ts +0 -49
- package/lib/types/src/apply-patch/grammar.d.ts +0 -29
- package/lib/types/src/apply-patch/lifecycle.d.ts +0 -32
- package/lib/types/src/apply-patch/plan.d.ts +0 -50
- package/lib/types/src/apply-patch/render.d.ts +0 -51
- package/lib/types/src/apply-patch/resolve.d.ts +0 -129
- package/lib/types/src/apply-patch/tool.d.ts +0 -54
- package/lib/types/src/apply-patch/types.d.ts +0 -362
- package/lib/types/src/fs-lifecycle.d.ts +0 -44
- package/lib/types/src/host-utils.d.ts +0 -63
- package/lib/types/src/mutation-engine/edit-request.d.ts +0 -34
- package/prompts/apply-patch-guidelines.md +0 -10
- package/prompts/apply-patch.md +0 -1
- package/src/apply-patch/commit.ts +0 -190
- package/src/apply-patch/grammar.ts +0 -620
- package/src/apply-patch/index.ts +0 -17
- package/src/apply-patch/lifecycle.ts +0 -195
- package/src/apply-patch/plan.ts +0 -800
- package/src/apply-patch/render.ts +0 -137
- package/src/apply-patch/resolve.ts +0 -470
- package/src/apply-patch/tool.ts +0 -257
- package/src/apply-patch/types.ts +0 -387
- package/src/fs-lifecycle.ts +0 -201
- package/src/host-utils.ts +0 -224
- package/src/mutation-engine/edit-request.ts +0 -39
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SAFETY: Guard + auto-read seam around `write`: the `tool_call` listener refuses
|
|
3
|
+
* reproduced served rows before they can reach disk.
|
|
4
|
+
* Ported from dsh@0.4.1 `src/write-hook.ts` adapted to pi's FileIO/session view.
|
|
5
|
+
* @module pi-better-edit/write-hook
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
9
|
+
import { abortIf, splitLines } from "./utils.js";
|
|
10
|
+
import { resolveTarget } from "./fs-write.js";
|
|
11
|
+
import { toCwd } from "./paths.js";
|
|
12
|
+
import { createSessionHandle, sessionKeyFor } from "./served-session/session.js";
|
|
13
|
+
import {
|
|
14
|
+
findServedHashEcho,
|
|
15
|
+
buildServedWriteMessage,
|
|
16
|
+
trackServedWriteRefusal,
|
|
17
|
+
} from "./served-session/serve-render.js";
|
|
18
|
+
import { reportDiagnostic } from "./diagnostics.js";
|
|
19
|
+
|
|
20
|
+
export { findServedHashEcho };
|
|
21
|
+
|
|
22
|
+
export interface WriteHookIO {
|
|
23
|
+
resolve(path: string, cwd: string, signal?: AbortSignal): Promise<string>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* SAFETY: Inspect one validated-looking built-in write request against session-scoped
|
|
28
|
+
* served state. Returns a pre-dispatch denial reason only with evidence: the
|
|
29
|
+
* candidate begins with a served anchor at any position AND reproduces the
|
|
30
|
+
* served content for that anchor (GLOSSARY.md served hash echo). No canon data
|
|
31
|
+
* means no evidence, so the check stays silent — never a shape refusal.
|
|
32
|
+
*/
|
|
33
|
+
export async function servedHashEchoDenial(
|
|
34
|
+
io: WriteHookIO | null | undefined,
|
|
35
|
+
rawPath: string,
|
|
36
|
+
content: string,
|
|
37
|
+
cwd: string,
|
|
38
|
+
sessionKey: string,
|
|
39
|
+
signal?: AbortSignal,
|
|
40
|
+
mode: "general" | "literal" = "general",
|
|
41
|
+
): Promise<string | undefined> {
|
|
42
|
+
abortIf(signal);
|
|
43
|
+
if (mode === "literal") return undefined;
|
|
44
|
+
let absolutePath: string;
|
|
45
|
+
if (io && typeof (io as WriteHookIO).resolve === "function") {
|
|
46
|
+
absolutePath = await (io as WriteHookIO).resolve(rawPath, cwd, signal);
|
|
47
|
+
} else {
|
|
48
|
+
absolutePath = await resolveTarget(toCwd(rawPath, cwd));
|
|
49
|
+
}
|
|
50
|
+
abortIf(signal);
|
|
51
|
+
const handle = createSessionHandle(sessionKey, absolutePath);
|
|
52
|
+
const served = await handle.load();
|
|
53
|
+
let canonDigests: (string | null)[] = [];
|
|
54
|
+
try {
|
|
55
|
+
canonDigests = await handle.loadCanonDigests();
|
|
56
|
+
} catch (error) {
|
|
57
|
+
reportDiagnostic("write-hook", "Failed to load served canon digests for write:", error);
|
|
58
|
+
canonDigests = [];
|
|
59
|
+
}
|
|
60
|
+
const lines = splitLines(content);
|
|
61
|
+
const reproduction = findServedHashEcho(lines, served, canonDigests, 1);
|
|
62
|
+
if (!reproduction) return undefined;
|
|
63
|
+
const offendingLine = lines[reproduction.k - 1] ?? "";
|
|
64
|
+
// WHY: verification side of the tally: this refusal runs pre-dispatch, so no bytes move
|
|
65
|
+
// WHY: and no clear is due — the clear belongs to the committed write, which re-serves
|
|
66
|
+
// WHY: the file (`lifecycle-hooks` post-write), never to this gate.
|
|
67
|
+
const count = trackServedWriteRefusal(sessionKey, absolutePath, offendingLine);
|
|
68
|
+
return buildServedWriteMessage({
|
|
69
|
+
path: rawPath,
|
|
70
|
+
line: reproduction.line,
|
|
71
|
+
hash: reproduction.hash,
|
|
72
|
+
servedLine: reproduction.servedLine,
|
|
73
|
+
count,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* SAFETY: Register the pre-write served hash echo guard on the calling extension's scope.
|
|
79
|
+
* The guard denies before dispatch; infrastructure failures fail open so the
|
|
80
|
+
* plugin never breaks an otherwise valid write.
|
|
81
|
+
*/
|
|
82
|
+
export function registerWriteHook(pi: ExtensionAPI): void {
|
|
83
|
+
pi.on("tool_call", async (event, ctx) => {
|
|
84
|
+
if (event.toolName !== "write") return;
|
|
85
|
+
const input = event.input as Record<string, unknown> | undefined;
|
|
86
|
+
const rawPath = input?.path as unknown;
|
|
87
|
+
const content = input?.content as unknown;
|
|
88
|
+
if (typeof rawPath !== "string" || typeof content !== "string") return;
|
|
89
|
+
// WHY: pi's builtin `write` schema tolerates the extra top-level `mode` field
|
|
90
|
+
// WHY: (verified with TypeBox `Compile`: an additional `mode?: "general" | "literal"`
|
|
91
|
+
// WHY: property passes `additionalProperties` handling on the builtin schema, so the
|
|
92
|
+
// WHY: literal declaration rides the same input object with no schema change).
|
|
93
|
+
const modeValue = (input as Record<string, unknown>)?.mode;
|
|
94
|
+
const mode: "general" | "literal" = modeValue === "literal" ? "literal" : "general";
|
|
95
|
+
|
|
96
|
+
const cwd = ctx.cwd;
|
|
97
|
+
// SAFETY: ExtensionAPI ctx carries sessionManager at runtime; cast narrows to sessionKeyFor's expected shape which is validated by sessionKeyFor's internal guards.
|
|
98
|
+
const sessionKey = sessionKeyFor(
|
|
99
|
+
ctx as unknown as { sessionManager?: { getSessionId(): string } },
|
|
100
|
+
);
|
|
101
|
+
const signal = ctx.signal;
|
|
102
|
+
try {
|
|
103
|
+
const io: WriteHookIO = {
|
|
104
|
+
resolve: async (p: string, c: string, sig?: AbortSignal) => {
|
|
105
|
+
abortIf(sig);
|
|
106
|
+
return resolveTarget(toCwd(p, c));
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
const reason = await servedHashEchoDenial(
|
|
110
|
+
io,
|
|
111
|
+
rawPath,
|
|
112
|
+
content,
|
|
113
|
+
cwd,
|
|
114
|
+
sessionKey,
|
|
115
|
+
signal,
|
|
116
|
+
mode,
|
|
117
|
+
);
|
|
118
|
+
if (reason !== undefined) {
|
|
119
|
+
return { block: true, reason };
|
|
120
|
+
}
|
|
121
|
+
} catch (error) {
|
|
122
|
+
if (signal?.aborted) throw error;
|
|
123
|
+
reportDiagnostic(
|
|
124
|
+
"write-hook",
|
|
125
|
+
`pi-better-edit: pre-write served hash guard failed open: ${error instanceof Error ? error.message : String(error)}`,
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
return;
|
|
129
|
+
});
|
|
130
|
+
}
|
package/lib/types/dsh/hide.d.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hide the native edit-class tools so every precise text change goes through
|
|
3
|
-
* `apply_patch` — the one mutation entry point of the v4 surface.
|
|
4
|
-
*
|
|
5
|
-
* DSH 0.2.2-alpha.3 owns tool declarations in the tool registry, not in the
|
|
6
|
-
* `system-prompt/assemble` waterfall: the waterfall receives sections, contexts
|
|
7
|
-
* and variables only. The authoritative schema filter is therefore the
|
|
8
|
-
* per-agent registry restriction (`tools.restrict({ deny })`), which removes a
|
|
9
|
-
* global tool from both the native schema list and the PTC `tools:sdk` section
|
|
10
|
-
* because both are rendered from `tools.definitions(scope, toolSet)`.
|
|
11
|
-
*
|
|
12
|
-
* Three seams still back that up, because a restriction only governs the
|
|
13
|
-
* registry view and a stale session or a hand-rolled section could carry a
|
|
14
|
-
* residual binding:
|
|
15
|
-
*
|
|
16
|
-
* 1. `tools.restrict({ deny })` drops the hidden schemas for this agent;
|
|
17
|
-
* 2. `system-prompt/assemble` empties the `tool:edit` guidance section (its
|
|
18
|
-
* text is prose, never a tool mention) and deletes the hidden tools' member
|
|
19
|
-
* blocks from any rendered PTC `tools:sdk` section;
|
|
20
|
-
* 3. `tools.guard` is the monotonic execution backstop for a stale schema or
|
|
21
|
-
* any residual binding.
|
|
22
|
-
*
|
|
23
|
-
* `write` stays visible on purpose: whole-file replacement has no operation in
|
|
24
|
-
* `apply_patch` (`*** Add File:` refuses to overwrite), so hiding it would leave
|
|
25
|
-
* a rewrite with nowhere to go. Callers that want it gone can list it in
|
|
26
|
-
* `hiddenToolNames`.
|
|
27
|
-
*
|
|
28
|
-
* The layer is installed only when `apply_patch` actually registered: hiding
|
|
29
|
-
* the native editors while owning no replacement would leave the profile with
|
|
30
|
-
* no way to change a file.
|
|
31
|
-
*
|
|
32
|
-
* @module dsh-hashline-edit/hide
|
|
33
|
-
*/
|
|
34
|
-
/** A boolean config value, or a live getter (used when a host exposes volatile config). */
|
|
35
|
-
type BooleanSource = boolean | (() => boolean);
|
|
36
|
-
/** The hide-layer configuration after the plugin-level defaults are applied. */
|
|
37
|
-
export interface NativeHideConfig {
|
|
38
|
-
/** The registered replacement tool name, protected from `hiddenToolNames`. */
|
|
39
|
-
readonly toolName: string;
|
|
40
|
-
/** Hide `edit`/`str_replace_editor`; defaults to true. */
|
|
41
|
-
readonly hideNativeWriteTools?: BooleanSource;
|
|
42
|
-
/** Extra global tool names to hide alongside the native set. */
|
|
43
|
-
readonly hiddenToolNames?: readonly string[];
|
|
44
|
-
/** The Agent scope key used for the agent-view probe; absent keeps the global probe. */
|
|
45
|
-
readonly scope?: unknown;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Delete the hidden tools' member blocks from one rendered `tools:sdk` text.
|
|
49
|
-
*
|
|
50
|
-
* Structural, renderer-specific parsing — never a mention match:
|
|
51
|
-
* - TypeScript: a member starts at ` name: type` (2-space indent) inside
|
|
52
|
-
* `ToolArgsMap`/`ToolOutputMap`, may open braces on the same line, and ends
|
|
53
|
-
* at the first line that closes every opened brace and ends with `;`. Its
|
|
54
|
-
* optional single-line JSDoc comment directly above goes with it.
|
|
55
|
-
* - Python: a `Tools` protocol member starts at an indented `async def` line
|
|
56
|
-
* and spans until the next line at that member indent or shallower.
|
|
57
|
-
* @param text - the rendered SDK section text.
|
|
58
|
-
* @param hidden - the tool names to remove.
|
|
59
|
-
* @returns the text with every hidden member block removed.
|
|
60
|
-
*/
|
|
61
|
-
export declare function stripSdkMembers(text: string, hidden: ReadonlySet<string>): string;
|
|
62
|
-
interface LoggerLike {
|
|
63
|
-
warn?(message: string): void;
|
|
64
|
-
}
|
|
65
|
-
declare function warn(rootCtx: {
|
|
66
|
-
logger?: LoggerLike;
|
|
67
|
-
}, message: string): void;
|
|
68
|
-
/**
|
|
69
|
-
* Install the hide layer for one agent. Only call this after `apply_patch`
|
|
70
|
-
* registered successfully.
|
|
71
|
-
*
|
|
72
|
-
* @param rootCtx - the plugin/root scope, used for the global-name probe and warnings.
|
|
73
|
-
* @param agentCtx - the agent scope whose tool view is restricted.
|
|
74
|
-
* @param config - the resolved hide configuration.
|
|
75
|
-
* @returns the exact disposer; disposing lifts the restriction and every listener.
|
|
76
|
-
*/
|
|
77
|
-
export declare function registerNativeToolHiding(rootCtx: Parameters<typeof warn>[0], agentCtx: unknown, config: NativeHideConfig): () => void;
|
|
78
|
-
export {};
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { FileDiff, ToolDefinition } from "@deepseek-ai/dsh-tools";
|
|
2
|
-
import { APPLY_PATCH_TOOL_NAME } from "../../src/apply-patch/tool.js";
|
|
3
|
-
import type { ApplyPatchTool } from "../../src/apply-patch/tool.js";
|
|
4
|
-
/** Public tool name re-exported for host registration and surface tests. */
|
|
5
|
-
export { APPLY_PATCH_TOOL_NAME };
|
|
6
|
-
import type { ToolDependencies } from "../contracts.js";
|
|
7
|
-
/** One call's intended file diffs, parsed from the patch headers for the pending card. */
|
|
8
|
-
interface PatchPreview {
|
|
9
|
-
readonly diffs: FileDiff[];
|
|
10
|
-
readonly locations: string[];
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Scan the patch headers for the pending card. This is a presentation-only
|
|
14
|
-
* projection: it never decides whether the patch is valid (the grammar and
|
|
15
|
-
* planner do), and it never throws on malformed text.
|
|
16
|
-
* @param input - the raw patch text.
|
|
17
|
-
* @returns the intended additions and every path the patch names.
|
|
18
|
-
*/
|
|
19
|
-
export declare function previewPatch(input: string): PatchPreview;
|
|
20
|
-
/** Every path this patch writes, including a Cut From source; Copy From sources are read-only. */
|
|
21
|
-
export declare function writtenPatchPaths(input: string): string[];
|
|
22
|
-
/** Options for {@link buildApplyPatchTool}; the factory seam is for tests. */
|
|
23
|
-
export interface ApplyPatchToolOptions {
|
|
24
|
-
/** Test seam: build the use case without touching the real engine/store. */
|
|
25
|
-
readonly create?: () => ApplyPatchTool;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Build the dsh 'apply_patch' tool for one agent install.
|
|
29
|
-
*
|
|
30
|
-
* The use case is created lazily: building a tool definition must not touch the
|
|
31
|
-
* engine or the store, and a composition where 'apply_patch' is skipped must
|
|
32
|
-
* still install the rest of the toolset.
|
|
33
|
-
*
|
|
34
|
-
* @param deps - the host seams this tool may touch; 'sandbox' advertises and resolves escalation.
|
|
35
|
-
* @param options - test seam for the use case.
|
|
36
|
-
* @returns a registry-ready dsh tool definition named 'apply_patch'.
|
|
37
|
-
*/
|
|
38
|
-
export declare function buildApplyPatchTool(deps: ToolDependencies, options?: ApplyPatchToolOptions): ToolDefinition;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import type { HashStore } from "../hash-store.js";
|
|
2
|
-
import type { ApplyPatchFailure, PatchPlan, ServedFileBlock } from "./types.js";
|
|
3
|
-
/** Options for {@link commitPlan}. */
|
|
4
|
-
export interface CommitPlanOptions {
|
|
5
|
-
readonly cwd: string;
|
|
6
|
-
readonly sessionKey: string;
|
|
7
|
-
readonly signal?: AbortSignal;
|
|
8
|
-
readonly store?: HashStore;
|
|
9
|
-
/** POSIX access-mode bitmask; defaults to read+write. */
|
|
10
|
-
readonly accessMode?: number;
|
|
11
|
-
/** TEST-ONLY: fires before the first rename, while the pre-images/undo rows are durable. */
|
|
12
|
-
readonly onBeforeFirstWrite?: () => void | Promise<void>;
|
|
13
|
-
/** TEST-ONLY: fires between two member renames, after the earlier one is durable. */
|
|
14
|
-
readonly onBetweenWrites?: (committedAbsolutePath: string) => void | Promise<void>;
|
|
15
|
-
/** TEST-ONLY: fires after a move rename and before the destination rewrite (mid-member failure). */
|
|
16
|
-
readonly onAfterMoveRename?: (toAbsolutePath: string) => void | Promise<void>;
|
|
17
|
-
}
|
|
18
|
-
/** One committed file's lifecycle status and line accounting. */
|
|
19
|
-
export interface CommittedFile {
|
|
20
|
-
readonly path: string;
|
|
21
|
-
readonly status: "A" | "M" | "R" | "D";
|
|
22
|
-
/** Original path for a rename (`R` only). */
|
|
23
|
-
readonly fromPath?: string;
|
|
24
|
-
readonly addedLines: number;
|
|
25
|
-
readonly removedLines: number;
|
|
26
|
-
/** New anchors for the changed lines; absent when the member wrote no content. */
|
|
27
|
-
readonly served?: ServedFileBlock;
|
|
28
|
-
}
|
|
29
|
-
/** Commit outcome: the per-file facts on success, the whole failure on rejection. */
|
|
30
|
-
export type CommitPlanResult = {
|
|
31
|
-
readonly ok: true;
|
|
32
|
-
readonly files: readonly CommittedFile[];
|
|
33
|
-
readonly diff: string;
|
|
34
|
-
readonly warnings: readonly string[];
|
|
35
|
-
} | {
|
|
36
|
-
readonly ok: false;
|
|
37
|
-
readonly failure: ApplyPatchFailure;
|
|
38
|
-
};
|
|
39
|
-
/**
|
|
40
|
-
* Commit one plan atomically (one correlated transaction, one undo record set).
|
|
41
|
-
*
|
|
42
|
-
* The implementation reuses `commitTransaction` — the existing correlated skeleton — and extends
|
|
43
|
-
* its member shape with the plan's lifecycle action; the undo schema gains the matching action.
|
|
44
|
-
*
|
|
45
|
-
* @param plan - the fully resolved plan.
|
|
46
|
-
* @param options - cwd/session/store, cancellation and the test fault seams.
|
|
47
|
-
* @returns the committed facts, or a failure whose `changedNothing` reflects the rollback.
|
|
48
|
-
*/
|
|
49
|
-
export declare function commitPlan(plan: PatchPlan, options: CommitPlanOptions): Promise<CommitPlanResult>;
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { AnchorSpan, ParsePatchResult } from "./types.js";
|
|
2
|
-
/** Hard cap on one patch input (bytes), mirroring the host request budget. */
|
|
3
|
-
export declare const PATCH_MAX_BYTES: number;
|
|
4
|
-
/** Options for {@link parseApplyPatch}. */
|
|
5
|
-
export interface ParsePatchOptions {
|
|
6
|
-
/** Maximum accepted input size in bytes; defaults to {@link PATCH_MAX_BYTES}. */
|
|
7
|
-
readonly maxBytes?: number;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Parse one patch document.
|
|
11
|
-
*
|
|
12
|
-
* Success returns the AST defined in `types.ts`; failure returns every syntax
|
|
13
|
-
* problem the parser could diagnose in one pass (never a throw for malformed
|
|
14
|
-
* user input). Rejections use `E_PATCH_SYNTAX` with the offending patch line.
|
|
15
|
-
*
|
|
16
|
-
* @param input - the raw `*** Begin Patch` … `*** End Patch` text.
|
|
17
|
-
* @param options - size guard knobs.
|
|
18
|
-
* @returns the parsed document or the collected problems.
|
|
19
|
-
*/
|
|
20
|
-
export declare function parseApplyPatch(input: string, options?: ParsePatchOptions): ParsePatchResult;
|
|
21
|
-
/**
|
|
22
|
-
* Parse an anchor token: `<a>` (single line) or `<a>-<b>` (closed span).
|
|
23
|
-
* Returns `undefined` when the token is not a valid four-character anchor pair; the
|
|
24
|
-
* grammar layer turns that into an `E_PATCH_SYNTAX` problem at the patch line.
|
|
25
|
-
*
|
|
26
|
-
* @param token - the text after `@@` (no leading space).
|
|
27
|
-
* @returns the closed span, or undefined for a malformed token.
|
|
28
|
-
*/
|
|
29
|
-
export declare function parseAnchorSpan(token: string): AnchorSpan | undefined;
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { type HashStore } from "../hash-store.js";
|
|
2
|
-
import type { ProcessedEditFile } from "../mutation-engine/types.js";
|
|
3
|
-
import type { PatchPath, PlannedFile } from "./types.js";
|
|
4
|
-
/**
|
|
5
|
-
* apply_patch lifecycle materialization — the plan-to-engine adapter.
|
|
6
|
-
*
|
|
7
|
-
* The planner resolves every mutation against a pre-call baseline; this module turns that plan
|
|
8
|
-
* into the mutation engine's `ProcessedEditFile` member shape (plus the engine-local lifecycle
|
|
9
|
-
* action). It never writes: the correlated transaction in `mutation-engine/pipeline.ts` owns the
|
|
10
|
-
* one commit path. Pure text application (splice at baseline coordinates) is the only work here,
|
|
11
|
-
* and the resulting anchors are always derived under the member's COMMITTED path.
|
|
12
|
-
*
|
|
13
|
-
* @module dsh-hashline-edit/apply-patch/lifecycle
|
|
14
|
-
*/
|
|
15
|
-
/** One materialized member: the plan facts plus the engine member the commit consumes. */
|
|
16
|
-
export interface MaterializedMember {
|
|
17
|
-
readonly planned: PlannedFile;
|
|
18
|
-
readonly member: ProcessedEditFile;
|
|
19
|
-
readonly status: "A" | "M" | "R" | "D";
|
|
20
|
-
/** The committed display path (destination for a move; the pre path otherwise). */
|
|
21
|
-
readonly committedPath: PatchPath;
|
|
22
|
-
/** The pre-transaction display path (move only). */
|
|
23
|
-
readonly fromPath?: PatchPath;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Materialize one planned file into the engine's member shape.
|
|
27
|
-
*
|
|
28
|
-
* The result text is produced by applying the plan's baseline-coordinate mutations; the anchors
|
|
29
|
-
* are then derived under the committed path. No file is read or written here — the plan already
|
|
30
|
-
* carries every baseline byte the commit needs.
|
|
31
|
-
*/
|
|
32
|
-
export declare function materializeMember(planned: PlannedFile, store?: HashStore): Promise<MaterializedMember>;
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import type { LeaseSpanSource } from "../hashline/resolve.js";
|
|
2
|
-
import { type HashStore } from "../hash-store.js";
|
|
3
|
-
import { type ServedAnchors } from "./resolve.js";
|
|
4
|
-
import type { ApplyPatchEngineOptions, FileBaseline, PatchDocument, PatchPath, PlannedMutation, PlanPatchResult } from "./types.js";
|
|
5
|
-
/**
|
|
6
|
-
* The baseline/served loader port.
|
|
7
|
-
*
|
|
8
|
-
* Production wires `readBaseline` to the file-content decode path,
|
|
9
|
-
* `readServed` to `createSessionHandle(...).load()` and `readLeaseSource` to
|
|
10
|
-
* the read-only lease identity source. Tests inject a pure in-memory
|
|
11
|
-
* implementation, which is what makes the planner testable without a store.
|
|
12
|
-
*/
|
|
13
|
-
export interface PlanFileLoader {
|
|
14
|
-
/** Load one file's baseline (LF-normalized text + anchors + BOM + ending). */
|
|
15
|
-
readBaseline(path: PatchPath, absolutePath: string, signal?: AbortSignal): Promise<FileBaseline>;
|
|
16
|
-
/** Load this session's served anchors for one file, parallel to its lines. */
|
|
17
|
-
readServed(absolutePath: string, sessionKey: string, store?: HashStore): Promise<ServedAnchors>;
|
|
18
|
-
/** Session-wide anchor homes, for foreign-anchor diagnosis (optional legacy port). */
|
|
19
|
-
anchorHomes?(anchor: string, sessionKey: string, store?: HashStore): readonly PatchPath[];
|
|
20
|
-
/** Build the read-only lease identity source for one file's baseline content. */
|
|
21
|
-
readLeaseSource?(absolutePath: string, sessionKey: string, content: string, store?: HashStore): Promise<LeaseSpanSource>;
|
|
22
|
-
}
|
|
23
|
-
/** Options for {@link planApplyPatch}; `loader` is the test seam. */
|
|
24
|
-
export interface PlanApplyPatchOptions extends ApplyPatchEngineOptions {
|
|
25
|
-
readonly loader?: PlanFileLoader;
|
|
26
|
-
}
|
|
27
|
-
/** A baseline for a file that does not exist yet (Add File / missing target). */
|
|
28
|
-
export declare function absentBaseline(path: PatchPath, absolutePath: string): FileBaseline;
|
|
29
|
-
/** The production loader over node:fs, the file-content decoder and the hash store. */
|
|
30
|
-
export declare function createDefaultPlanFileLoader(): PlanFileLoader;
|
|
31
|
-
/** Apply resolved baseline-coordinate mutations to a line array (descending, so coordinates stay valid). */
|
|
32
|
-
export declare function applyPlannedMutations(lines: readonly string[], mutations: readonly PlannedMutation[]): string[];
|
|
33
|
-
export declare function mutationDelta(baselineLines: readonly string[], mutation: PlannedMutation): {
|
|
34
|
-
added: number;
|
|
35
|
-
removed: number;
|
|
36
|
-
};
|
|
37
|
-
/**
|
|
38
|
-
* Plan one apply_patch call without writing anything.
|
|
39
|
-
*
|
|
40
|
-
* All hunks resolve against the pre-call baseline (never chained application);
|
|
41
|
-
* a later hunk's fragment window begins after the previous hunk's end. Any
|
|
42
|
-
* problem aborts the whole call: the returned list is every independently
|
|
43
|
-
* diagnosable problem, not just the first, together with the current rows of
|
|
44
|
-
* every named file (reject-and-serve).
|
|
45
|
-
*
|
|
46
|
-
* @param document - the parsed patch AST.
|
|
47
|
-
* @param options - cwd/session/store plus the optional baseline loader.
|
|
48
|
-
* @returns the plan, or every problem found plus the rows to serve.
|
|
49
|
-
*/
|
|
50
|
-
export declare function planApplyPatch(document: PatchDocument, options: PlanApplyPatchOptions): Promise<PlanPatchResult>;
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* apply_patch v4 — renderer.
|
|
3
|
-
*
|
|
4
|
-
* One renderer owns both surfaces:
|
|
5
|
-
*
|
|
6
|
-
* - success: file-level summary lines first (`A`/`M`/`R`/`D`), then the
|
|
7
|
-
* changed-line anchor rows (`HASH│content`) per file, so a second call needs
|
|
8
|
-
* no `read`;
|
|
9
|
-
* - rejection: every problem as `- patch line N ([E_*], path): message`,
|
|
10
|
-
* followed by each problem file's current rows.
|
|
11
|
-
*
|
|
12
|
-
* @module dsh-hashline-edit/apply-patch/render
|
|
13
|
-
*/
|
|
14
|
-
import type { ApplyPatchFailure, ApplyPatchResult, ApplyPatchSuccess, ApplyPatchToolResult, AppliedFileSummary, PatchProblem, ServedFileBlock } from "./types.js";
|
|
15
|
-
/**
|
|
16
|
-
* Render one apply_patch outcome into the model-facing tool envelope.
|
|
17
|
-
* @param result - the committed success or the collected rejection.
|
|
18
|
-
* @returns `{ content, details }` ready for the dsh tool registry.
|
|
19
|
-
*/
|
|
20
|
-
export declare function renderApplyPatchResult(result: ApplyPatchResult): ApplyPatchToolResult;
|
|
21
|
-
/**
|
|
22
|
-
* Render a successful outcome.
|
|
23
|
-
* @param success - committed file facts plus new anchor rows.
|
|
24
|
-
* @returns the model-facing envelope.
|
|
25
|
-
*/
|
|
26
|
-
export declare function renderSuccess(success: ApplyPatchSuccess): ApplyPatchToolResult;
|
|
27
|
-
/**
|
|
28
|
-
* Render a rejected outcome: all problems first, then the served rows.
|
|
29
|
-
* @param failure - the collected problems and current rows.
|
|
30
|
-
* @returns the model-facing envelope (as an `isError` tool result at the host seam).
|
|
31
|
-
*/
|
|
32
|
-
export declare function renderFailure(failure: ApplyPatchFailure): ApplyPatchToolResult;
|
|
33
|
-
/**
|
|
34
|
-
* Render the file-level summary block: `Updated N files:` then one status line
|
|
35
|
-
* per file (`R src/old.ts -> src/new.ts` for a rename).
|
|
36
|
-
* @param files - the committed file summaries.
|
|
37
|
-
* @returns the summary text.
|
|
38
|
-
*/
|
|
39
|
-
export declare function renderFileSummary(files: readonly AppliedFileSummary[]): string;
|
|
40
|
-
/**
|
|
41
|
-
* Render the new-anchor blocks for every changed file.
|
|
42
|
-
* @param blocks - per-file served rows.
|
|
43
|
-
* @returns one `<path>\nHASH│content` section per block.
|
|
44
|
-
*/
|
|
45
|
-
export declare function renderServedBlocks(blocks: readonly ServedFileBlock[]): string;
|
|
46
|
-
/**
|
|
47
|
-
* Render one problem line: `- patch line N ([E_*], path): message`.
|
|
48
|
-
* @param problem - one collected problem.
|
|
49
|
-
* @returns the single-line rendering, without a trailing newline.
|
|
50
|
-
*/
|
|
51
|
-
export declare function formatPatchProblem(problem: PatchProblem): string;
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* apply_patch v4 — resolution layer.
|
|
3
|
-
*
|
|
4
|
-
* Two addressing families meet here:
|
|
5
|
-
*
|
|
6
|
-
* - **fragment mode** is content matching against the pre-call baseline. The
|
|
7
|
-
* `oldLines` sequence (' ' and '-' lines) must match exactly one place in the
|
|
8
|
-
* hunk's window; `@@ <context>` must itself match exactly one line and moves
|
|
9
|
-
* the window start after it. Zero or multiple hits reject with candidate rows.
|
|
10
|
-
* - **identity mode** is served-lease addressing. Both anchors must belong to
|
|
11
|
-
* the `(session, file, anchor)` served set; a missing, retired or foreign
|
|
12
|
-
* anchor rejects with the file's current rows served back.
|
|
13
|
-
*
|
|
14
|
-
* The layer is pure over `FileBaseline` + served anchors: no I/O, no store
|
|
15
|
-
* access. `plan.ts` supplies the baselines and the lease source.
|
|
16
|
-
*
|
|
17
|
-
* @module dsh-hashline-edit/apply-patch/resolve
|
|
18
|
-
*/
|
|
19
|
-
import { type LeaseSpanSource } from "../hashline/resolve.js";
|
|
20
|
-
import type { Anchor, FileBaseline, FragmentHunk, IdentityHunk, LineRange, PatchCandidate, PatchPath, PatchProblem, PlannedMutation, PlannedReferenceUse, ReferenceHunk } from "./types.js";
|
|
21
|
-
/** A file's served anchors, parallel to its baseline lines; `null` = never served. */
|
|
22
|
-
export type ServedAnchors = readonly (string | null)[];
|
|
23
|
-
/** The inputs one hunk resolution reads. */
|
|
24
|
-
export interface ResolveContext {
|
|
25
|
-
readonly baseline: FileBaseline;
|
|
26
|
-
readonly served: ServedAnchors;
|
|
27
|
-
/**
|
|
28
|
-
* Read-only lease identity source for identity mode. When present it is
|
|
29
|
-
* authoritative (MVCC lease identity, including rebasing); the `served`
|
|
30
|
-
* mirror is only the fallback for tests/callers with no store lease view.
|
|
31
|
-
*/
|
|
32
|
-
readonly identity?: LeaseSpanSource;
|
|
33
|
-
/**
|
|
34
|
-
* Session-wide anchor homes — other files that served this anchor. Used only
|
|
35
|
-
* to diagnose a foreign anchor; a cross-file anchor is refused either way.
|
|
36
|
-
*/
|
|
37
|
-
readonly homesOf?: (anchor: Anchor) => readonly PatchPath[];
|
|
38
|
-
}
|
|
39
|
-
/** A successful fragment match in baseline coordinates. */
|
|
40
|
-
export interface FragmentMatch {
|
|
41
|
-
/** Inclusive range covering the hunk's oldLines (' ' + '-'); zero-width when oldLines is empty. */
|
|
42
|
-
readonly range: LineRange;
|
|
43
|
-
/** 1-based line where the search window began (after `@@ <context>`, else 1). */
|
|
44
|
-
readonly windowStart: number;
|
|
45
|
-
}
|
|
46
|
-
/** Fragment match failure: no occurrence or more than one, with candidate rows. */
|
|
47
|
-
export type FragmentMatchResult = {
|
|
48
|
-
readonly ok: true;
|
|
49
|
-
readonly match: FragmentMatch;
|
|
50
|
-
} | {
|
|
51
|
-
readonly ok: false;
|
|
52
|
-
readonly reason: "no-match" | "ambiguous";
|
|
53
|
-
readonly candidates: readonly PatchCandidate[];
|
|
54
|
-
};
|
|
55
|
-
/** Identity resolution outcome. */
|
|
56
|
-
export type IdentityResolveResult = {
|
|
57
|
-
readonly ok: true;
|
|
58
|
-
readonly range: LineRange;
|
|
59
|
-
} | {
|
|
60
|
-
readonly ok: false;
|
|
61
|
-
readonly problems: readonly PatchProblem[];
|
|
62
|
-
};
|
|
63
|
-
/** Reference resolution outcome. */
|
|
64
|
-
export type ReferenceResolveResult = {
|
|
65
|
-
readonly ok: true;
|
|
66
|
-
readonly reference: PlannedReferenceUse;
|
|
67
|
-
/** The destination replacement this reference materializes. */
|
|
68
|
-
readonly mutation: PlannedMutation;
|
|
69
|
-
} | {
|
|
70
|
-
readonly ok: false;
|
|
71
|
-
readonly problems: readonly PatchProblem[];
|
|
72
|
-
};
|
|
73
|
-
/** The baseline's lines; an empty file is zero lines, never one empty line. */
|
|
74
|
-
export declare function baselineLinesOf(baseline: FileBaseline): string[];
|
|
75
|
-
/**
|
|
76
|
-
* Match one fragment hunk against its baseline.
|
|
77
|
-
*
|
|
78
|
-
* Byte-exact: no whitespace, Unicode or newline normalization. The window is
|
|
79
|
-
* `[windowStart, end]` and every subsequent hunk's window begins after the
|
|
80
|
-
* previous hunk's end (the planner enforces the monotonic cursor).
|
|
81
|
-
*
|
|
82
|
-
* @param hunk - the parsed fragment hunk.
|
|
83
|
-
* @param context - baseline plus served anchors (served is unused here; kept for one call shape).
|
|
84
|
-
* @param windowStart - 1-based line the search starts at; defaults to 1.
|
|
85
|
-
* @returns the unique match or the rejection with candidates.
|
|
86
|
-
*/
|
|
87
|
-
export declare function matchFragmentHunk(hunk: FragmentHunk, context: ResolveContext, windowStart?: number): FragmentMatchResult;
|
|
88
|
-
/**
|
|
89
|
-
* Resolve one identity hunk (`@@<a>` / `@@<a>-<b>`) against the served set.
|
|
90
|
-
*
|
|
91
|
-
* The anchors must be present in `context.served` at exactly one position each
|
|
92
|
-
* (or hold a live lease when `context.identity` is present), `from` not after
|
|
93
|
-
* `to`. Every failure uses `E_STALE_ANCHOR` with the anchor named, so the
|
|
94
|
-
* planner can serve the file's current rows for a retry.
|
|
95
|
-
*
|
|
96
|
-
* @param hunk - the parsed identity hunk.
|
|
97
|
-
* @param context - baseline plus served anchors / lease source.
|
|
98
|
-
* @returns the resolved inclusive range, or all problems for this hunk.
|
|
99
|
-
*/
|
|
100
|
-
export declare function resolveIdentityHunk(hunk: IdentityHunk, context: ResolveContext): IdentityResolveResult;
|
|
101
|
-
/**
|
|
102
|
-
* Resolve one `*** Copy From:` / `*** Cut From:` hunk.
|
|
103
|
-
*
|
|
104
|
-
* The target addressing must be identity mode (`@@<a>` / `@@<a>-<b>`): a
|
|
105
|
-
* fragment-mode reference hunk is refused with `E_PATCH_SYNTAX` at the
|
|
106
|
-
* reference line. The source span must be served for the declared source file;
|
|
107
|
-
* the destination is replaced by the source bytes. A `cut` also plans the
|
|
108
|
-
* source retirement, in the same transaction, as a deletion over the same
|
|
109
|
-
* anchors.
|
|
110
|
-
*
|
|
111
|
-
* @param hunk - the parsed reference hunk.
|
|
112
|
-
* @param destination - the target file's baseline + served anchors / lease source.
|
|
113
|
-
* @param source - the source file's baseline + served anchors / lease source.
|
|
114
|
-
* @returns the materialized reference and destination mutation, or the problems.
|
|
115
|
-
*/
|
|
116
|
-
export declare function resolveReferenceHunk(hunk: ReferenceHunk, destination: ResolveContext, source: ResolveContext | FileBaseline, sourceServed?: ServedAnchors): ReferenceResolveResult;
|
|
117
|
-
/**
|
|
118
|
-
* Check one file's resolved mutations for overlap.
|
|
119
|
-
*
|
|
120
|
-
* Two mutations whose target ranges intersect reject the whole call with
|
|
121
|
-
* `E_BATCH_ABORT`-shaped evidence (both patch lines named). Zero-width
|
|
122
|
-
* insertions at the same point are ordered by submission, not treated as
|
|
123
|
-
* overlap; every other intersection is a rejection.
|
|
124
|
-
*
|
|
125
|
-
* @param mutations - one file's mutations, in submission order.
|
|
126
|
-
* @param path - the target file for the problem's path field.
|
|
127
|
-
* @returns every overlap problem found (empty when disjoint).
|
|
128
|
-
*/
|
|
129
|
-
export declare function checkMutationOverlaps(mutations: readonly PlannedMutation[], path?: PatchPath): readonly PatchProblem[];
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* apply_patch v4 — tool use case.
|
|
3
|
-
*
|
|
4
|
-
* The deep module the dsh host adapter calls. One `execute` owns the whole pipeline for one call:
|
|
5
|
-
*
|
|
6
|
-
* grammar.parseApplyPatch → plan.planApplyPatch → commit.commitPlan → render
|
|
7
|
-
*
|
|
8
|
-
* and returns the model-facing `{ content, details }` envelope. A rejection carries the rendered
|
|
9
|
-
* `[E_*]` envelope and is marked `isError`; nothing was written because plan/grammar own every
|
|
10
|
-
* pre-commit check and commit rolls back or reports its recovery report.
|
|
11
|
-
*
|
|
12
|
-
* The orchestration deps are injectable so the transaction lane can test the complete
|
|
13
|
-
* parse→plan→commit→render path before the grammar/resolve lanes merge into this branch.
|
|
14
|
-
*
|
|
15
|
-
* @module dsh-hashline-edit/apply-patch/tool
|
|
16
|
-
*/
|
|
17
|
-
import { parseApplyPatch, type ParsePatchOptions } from "./grammar.js";
|
|
18
|
-
import { planApplyPatch, type PlanApplyPatchOptions } from "./plan.js";
|
|
19
|
-
import { type CommitPlanOptions, type CommitPlanResult } from "./commit.js";
|
|
20
|
-
import { renderFailure, renderSuccess } from "./render.js";
|
|
21
|
-
import type { ApplyPatchContext, ApplyPatchToolResult, PatchPlan, PlanPatchResult } from "./types.js";
|
|
22
|
-
/** The registered tool name; `apply_patch` is the only mutation entry point. */
|
|
23
|
-
export declare const APPLY_PATCH_TOOL_NAME = "apply_patch";
|
|
24
|
-
/** The use-case seam: one narrow interface over the pipeline. */
|
|
25
|
-
export interface ApplyPatchTool {
|
|
26
|
-
/**
|
|
27
|
-
* Execute one apply_patch call.
|
|
28
|
-
* @param input - the raw patch text.
|
|
29
|
-
* @param ctx - live cwd, session identity and cancellation.
|
|
30
|
-
* @returns the model-facing envelope; `isError` marks a rejection (nothing written).
|
|
31
|
-
*/
|
|
32
|
-
execute(input: string, ctx: ApplyPatchContext): Promise<ApplyPatchToolResult>;
|
|
33
|
-
/**
|
|
34
|
-
* Parse + plan without writing, for previews and tests.
|
|
35
|
-
* @param input - the raw patch text.
|
|
36
|
-
* @param ctx - live cwd, session identity and cancellation.
|
|
37
|
-
* @returns the plan or every collected problem.
|
|
38
|
-
*/
|
|
39
|
-
plan(input: string, ctx: ApplyPatchContext): Promise<PlanPatchResult>;
|
|
40
|
-
}
|
|
41
|
-
/** The injectable seams of the pipeline; production uses the real modules. */
|
|
42
|
-
export interface ApplyPatchToolDeps {
|
|
43
|
-
readonly parse?: (input: string, options?: ParsePatchOptions) => ReturnType<typeof parseApplyPatch>;
|
|
44
|
-
readonly plan?: (document: Parameters<typeof planApplyPatch>[0], options: PlanApplyPatchOptions) => ReturnType<typeof planApplyPatch>;
|
|
45
|
-
readonly commit?: (plan: PatchPlan, options: CommitPlanOptions) => Promise<CommitPlanResult>;
|
|
46
|
-
readonly renderSuccess?: typeof renderSuccess;
|
|
47
|
-
readonly renderFailure?: typeof renderFailure;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Build the apply_patch use case.
|
|
51
|
-
* @param deps - optional seam overrides; production binds the real modules.
|
|
52
|
-
* @returns the tool seam bound to the real hashline engine and store.
|
|
53
|
-
*/
|
|
54
|
-
export declare function createApplyPatchTool(deps?: ApplyPatchToolDeps): ApplyPatchTool;
|