@prometheus-ai/hashline 0.5.3 → 0.5.8
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/CHANGELOG.md +7 -0
- package/dist/types/apply.d.ts +2 -0
- package/dist/types/block.d.ts +24 -9
- package/dist/types/diff-preview.d.ts +6 -4
- package/dist/types/messages.d.ts +73 -60
- package/dist/types/patcher.d.ts +7 -1
- package/dist/types/prefixes.d.ts +8 -0
- package/dist/types/snapshots.d.ts +6 -0
- package/dist/types/tokenizer.d.ts +3 -0
- package/dist/types/types.d.ts +45 -9
- package/package.json +3 -1
- package/src/apply.ts +267 -9
- package/src/block.ts +89 -15
- package/src/diff-preview.ts +96 -21
- package/src/grammar.lark +3 -1
- package/src/input.ts +16 -7
- package/src/messages.ts +121 -68
- package/src/mismatch.ts +5 -25
- package/src/parser.ts +89 -5
- package/src/patcher.ts +47 -9
- package/src/prefixes.ts +10 -0
- package/src/prompt.md +53 -19
- package/src/snapshots.ts +17 -1
- package/src/tokenizer.ts +11 -0
- package/src/types.ts +46 -9
package/CHANGELOG.md
ADDED
package/dist/types/apply.d.ts
CHANGED
package/dist/types/block.d.ts
CHANGED
|
@@ -1,19 +1,34 @@
|
|
|
1
|
-
import type { BlockResolver, Edit } from "./types";
|
|
1
|
+
import type { BlockResolution, BlockResolver, Edit } from "./types";
|
|
2
2
|
export interface ResolveBlockEditsOptions {
|
|
3
3
|
/**
|
|
4
|
-
* How to handle a block edit that cannot be resolved
|
|
5
|
-
* `null` span). `"throw"` (default) raises a
|
|
6
|
-
* used by the authoritative apply + final
|
|
7
|
-
* skips the edit — used by the streaming
|
|
8
|
-
* or transient parse error must not
|
|
4
|
+
* How to handle a replace/delete block edit that cannot be resolved
|
|
5
|
+
* (missing resolver or a `null` span). `"throw"` (default) raises a
|
|
6
|
+
* `blockUnresolvedMessage` error — used by the authoritative apply + final
|
|
7
|
+
* preview paths. `"drop"` silently skips the edit — used by the streaming
|
|
8
|
+
* preview, where a half-written file or transient parse error must not
|
|
9
|
+
* throw. Unresolvable `insert after block N:` edits never reach this: they
|
|
10
|
+
* are lowered to plain `insert after N:` with a warning.
|
|
9
11
|
*/
|
|
10
12
|
onUnresolved?: "throw" | "drop";
|
|
13
|
+
/**
|
|
14
|
+
* Invoked once per successfully resolved block edit, in patch order, with
|
|
15
|
+
* the anchor line and the concrete span it resolved to. Lets the host echo
|
|
16
|
+
* the resolution back to the caller. Never fired for dropped/unresolvable
|
|
17
|
+
* edits.
|
|
18
|
+
*/
|
|
19
|
+
onResolved?: (resolution: BlockResolution) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Invoked once per diagnostic produced while resolving — currently the
|
|
22
|
+
* `insert after block N:` lowerings (closer anchor or unresolvable block).
|
|
23
|
+
* Hosts should surface these on the apply result's `warnings`.
|
|
24
|
+
*/
|
|
25
|
+
onWarning?: (message: string) => void;
|
|
11
26
|
}
|
|
12
|
-
/** True when at least one edit is an unresolved
|
|
27
|
+
/** True when at least one edit is an unresolved deferred block edit. */
|
|
13
28
|
export declare function hasBlockEdit(edits: readonly Edit[]): boolean;
|
|
14
29
|
/**
|
|
15
|
-
* Resolve every
|
|
16
|
-
*
|
|
30
|
+
* Resolve every deferred block edit in `edits` against `text` (parsed as the
|
|
31
|
+
* language inferred from `path`). Non-block edits pass through untouched.
|
|
17
32
|
* Returns a fresh edit list with no `block` variants. The fast path returns the
|
|
18
33
|
* input unchanged when there is nothing to resolve.
|
|
19
34
|
*
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Re-number a unified diff that uses the `+<lineNum>|content` /
|
|
3
3
|
* `-<lineNum>|content` / ` <lineNum>|content` line format into a compact
|
|
4
|
-
* preview
|
|
5
|
-
*
|
|
6
|
-
* so a follow-up edit can reuse
|
|
4
|
+
* current-file preview. Removed lines are counted for stats and post-edit
|
|
5
|
+
* offset tracking, but omitted from the preview. Added and context lines are
|
|
6
|
+
* anchored to their post-edit positions so a follow-up edit can reuse visible
|
|
7
|
+
* concrete lines directly. Long contiguous added runs are summarized with a
|
|
8
|
+
* `…` marker instead of echoing every inserted line.
|
|
7
9
|
*
|
|
8
10
|
* This is intentionally decoupled from the diff producer: anything that
|
|
9
11
|
* emits the `<sign><lineNum>|<content>` shape works.
|
|
10
12
|
*/
|
|
11
13
|
import type { CompactDiffOptions, CompactDiffPreview } from "./types";
|
|
12
|
-
export declare function buildCompactDiffPreview(diff: string,
|
|
14
|
+
export declare function buildCompactDiffPreview(diff: string, options?: CompactDiffOptions): CompactDiffPreview;
|
package/dist/types/messages.d.ts
CHANGED
|
@@ -1,85 +1,98 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Centralized error and warning text emitted by the hashline parser, applier,
|
|
3
|
-
* and patcher. Consolidating these as named constants makes them easy to
|
|
4
|
-
* audit and keeps wording stable across the rendering paths that surface
|
|
5
|
-
* them.
|
|
6
|
-
*/
|
|
1
|
+
/** Centralized error/warning text for the hashline parser, applier, and patcher. */
|
|
7
2
|
/** Lines of context shown either side of a hash mismatch. */
|
|
8
3
|
export declare const MISMATCH_CONTEXT = 2;
|
|
9
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Numbered `LINE:TEXT` rows around `anchorLines` (±{@link MISMATCH_CONTEXT}),
|
|
6
|
+
* `*`-marking anchors, `...` between non-adjacent runs. Out-of-range anchors
|
|
7
|
+
* contribute no rows.
|
|
8
|
+
*/
|
|
9
|
+
export declare function formatAnchoredContext(anchorLines: readonly number[], fileLines: readonly string[]): string[];
|
|
10
|
+
/** Optional patch envelope start marker; silently consumed. */
|
|
10
11
|
export declare const BEGIN_PATCH_MARKER = "*** Begin Patch";
|
|
11
|
-
/** Optional patch envelope end marker; terminates parsing
|
|
12
|
+
/** Optional patch envelope end marker; terminates parsing. */
|
|
12
13
|
export declare const END_PATCH_MARKER = "*** End Patch";
|
|
13
14
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* parsing — terminates the line loop — and does not surface a warning.
|
|
15
|
+
* Truncation sentinel emitted by an agent loop mid-call. Ends parsing like
|
|
16
|
+
* {@link END_PATCH_MARKER}, without a warning.
|
|
17
17
|
*/
|
|
18
18
|
export declare const ABORT_MARKER = "*** Abort";
|
|
19
|
-
/**
|
|
20
|
-
export declare const REPLACE_PAIR_COALESCED_WARNING = "
|
|
21
|
-
/**
|
|
22
|
-
export declare const REPLACE_PAIR_COALESCED_OVERLAP_WARNING = "
|
|
23
|
-
/**
|
|
24
|
-
export declare const BARE_BODY_AUTO_PIPED_WARNING = "Auto-prefixed bare body row(s) with `+`. Body rows must be `+TEXT` literal lines
|
|
25
|
-
/**
|
|
26
|
-
export declare const MINUS_ROW_REJECTED = "`-` rows are not valid;
|
|
27
|
-
/**
|
|
19
|
+
/** Two consecutive hunks targeted the exact same concrete range. */
|
|
20
|
+
export declare const REPLACE_PAIR_COALESCED_WARNING = "Two hunks targeted the same range; kept only the second. One `replace N..M:` hunk per range \u2014 the body is the final content, never old+new.";
|
|
21
|
+
/** Bare bodyless hunk followed by an overlapping concrete hunk. */
|
|
22
|
+
export declare const REPLACE_PAIR_COALESCED_OVERLAP_WARNING = "Dropped a bare hunk overlapped by the concrete hunk after it. One `replace N..M:` hunk per range \u2014 the body is the final content, never old+new.";
|
|
23
|
+
/** Bare body rows auto-converted to literal `+` rows. */
|
|
24
|
+
export declare const BARE_BODY_AUTO_PIPED_WARNING = "Auto-prefixed bare body row(s) with `+`. Body rows must be `+TEXT` literal lines.";
|
|
25
|
+
/** Unified-diff-style `-` row in a hunk body. */
|
|
26
|
+
export declare const MINUS_ROW_REJECTED = "`-` rows are not valid; the range already names the lines being changed. For a literal `-` line, write `+-\u2026`.";
|
|
27
|
+
/** Replace hunk with no body. */
|
|
28
28
|
export declare const EMPTY_REPLACE = "`replace N..M:` needs at least one `+TEXT` body row. To delete lines, use `delete N..M`.";
|
|
29
|
-
/**
|
|
30
|
-
export declare const EMPTY_BLOCK = "`replace block N:` needs at least one `+TEXT` body row. To delete a block, use `delete
|
|
29
|
+
/** `replace block N:` hunk with no body. */
|
|
30
|
+
export declare const EMPTY_BLOCK = "`replace block N:` needs at least one `+TEXT` body row. To delete a block, use `delete block N`.";
|
|
31
|
+
/**
|
|
32
|
+
* Block-anchored replace/delete could not resolve to a syntactic block
|
|
33
|
+
* (unsupported language, blank/out-of-range line, no node beginning on N, or
|
|
34
|
+
* parse error). Appends a {@link formatAnchoredContext} preview when
|
|
35
|
+
* `fileLines` is given. `insert after block N:` never reaches this — it is
|
|
36
|
+
* lowered to plain `insert after N:` instead (see
|
|
37
|
+
* {@link insertAfterBlockUnresolvedLoweredWarning}).
|
|
38
|
+
*/
|
|
39
|
+
export declare function blockUnresolvedMessage(line: number, op?: "replace" | "delete", fileLines?: readonly string[]): string;
|
|
40
|
+
/** Block-anchored edit reached a path with no {@link BlockResolver} wired in — a host-configuration bug. */
|
|
41
|
+
export declare const BLOCK_RESOLVER_UNAVAILABLE = "`replace block`/`delete block`/`insert after block` are not available here (no block resolver configured). Use a concrete line range.";
|
|
31
42
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* a syntax error). Names the offending line and steers back to an explicit
|
|
36
|
-
* `replace N..M:` range.
|
|
43
|
+
* `insert after block N:` anchored on a closing-delimiter line, lowered to
|
|
44
|
+
* plain `insert after N:` — the closer ends a block, and inserting after it
|
|
45
|
+
* is exactly what the plain form does.
|
|
37
46
|
*/
|
|
38
|
-
export declare function
|
|
47
|
+
export declare function insertAfterBlockCloserLoweredWarning(line: number): string;
|
|
39
48
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
49
|
+
* `insert after block N:` anchor unresolvable (unsupported language, blank
|
|
50
|
+
* line, parse error, or no resolver), lowered to plain `insert after N:` —
|
|
51
|
+
* applying with a warning beats failing the patch.
|
|
43
52
|
*/
|
|
44
|
-
export declare
|
|
53
|
+
export declare function insertAfterBlockUnresolvedLoweredWarning(line: number): string;
|
|
45
54
|
/**
|
|
46
|
-
* Internal invariant
|
|
47
|
-
*
|
|
48
|
-
* the applier; hitting this is a wiring bug, not authored-input error.
|
|
55
|
+
* Internal invariant: `applyEdits` received an unresolved `replace block N:`
|
|
56
|
+
* edit; `resolveBlockEdits` must run first. Wiring bug, not authored input.
|
|
49
57
|
*/
|
|
50
58
|
export declare const UNRESOLVED_BLOCK_INTERNAL = "internal error: unresolved `replace block` edit reached the applier (resolveBlockEdits was not run).";
|
|
51
|
-
/**
|
|
59
|
+
/** Delete hunk received a body row. */
|
|
52
60
|
export declare const DELETE_TAKES_NO_BODY = "`delete N..M` does not take body rows. Remove the body, or use `replace N..M:`.";
|
|
53
|
-
/**
|
|
54
|
-
export declare const DELETE_BLOCK_TAKES_NO_BODY = "`delete block N` does not take body rows. Remove the body, or use `replace block N
|
|
55
|
-
/**
|
|
61
|
+
/** `delete block N` hunk received a body row. */
|
|
62
|
+
export declare const DELETE_BLOCK_TAKES_NO_BODY = "`delete block N` does not take body rows. Remove the body, or use `replace block N:`.";
|
|
63
|
+
/** Insert hunk with no body. */
|
|
56
64
|
export declare const EMPTY_INSERT = "`insert` needs at least one `+TEXT` body row.";
|
|
57
|
-
/**
|
|
65
|
+
/**
|
|
66
|
+
* `insert after` body indented shallower than the anchor: the landing slid
|
|
67
|
+
* forward past trailing closer lines — the common "anchored on the last line
|
|
68
|
+
* I read instead of after the block" mistake.
|
|
69
|
+
*/
|
|
70
|
+
export declare function afterInsertLandingShiftWarning(anchorLine: number, landingLine: number, crossed: number): string;
|
|
71
|
+
/**
|
|
72
|
+
* `insert after block N:` body indented deeper than the block's closer: the
|
|
73
|
+
* landing was pulled inside the block — a deeper body almost always means
|
|
74
|
+
* "append inside the block's body".
|
|
75
|
+
*/
|
|
76
|
+
export declare function blockInsertLandingShiftWarning(blockStart: number, closerLine: number, landingLine: number): string;
|
|
77
|
+
/** `Recovery`: an external write matched a cached snapshot. */
|
|
58
78
|
export declare const RECOVERY_EXTERNAL_WARNING = "Recovered from a stale file hash using a previous read snapshot (file changed externally between read and edit).";
|
|
59
|
-
/**
|
|
60
|
-
export declare const RECOVERY_SESSION_CHAIN_WARNING = "Recovered from a stale file hash using an earlier in-session snapshot (
|
|
79
|
+
/** `Recovery`: a prior in-session edit advanced the hash. */
|
|
80
|
+
export declare const RECOVERY_SESSION_CHAIN_WARNING = "Recovered from a stale file hash using an earlier in-session snapshot (a prior edit in this session advanced the hash).";
|
|
61
81
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* insert+delete pair earlier in the chain could still leave an anchor's
|
|
67
|
-
* line number pointing at a duplicated row. Surface the hedge so the
|
|
68
|
-
* model verifies before continuing.
|
|
82
|
+
* `Recovery`: session-chain replay fast-path. Less certain than
|
|
83
|
+
* {@link RECOVERY_SESSION_CHAIN_WARNING} — the 3-way merge refused, the
|
|
84
|
+
* anchor-content gate passed, but a coincidental insert+delete earlier in
|
|
85
|
+
* the chain could still misplace an anchor — hence the verify hedge.
|
|
69
86
|
*/
|
|
70
|
-
export declare const RECOVERY_SESSION_REPLAY_WARNING = "Recovered by replaying your edits onto the current file content
|
|
87
|
+
export declare const RECOVERY_SESSION_REPLAY_WARNING = "Recovered by replaying your edits onto the current file content (a prior in-session edit changed the lines you re-targeted with a stale hash). Verify the diff matches your intent.";
|
|
71
88
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
* with drift — so this is non-fatal: the edit applies onto the live content and
|
|
76
|
-
* we surface the drift instead of hard-failing (unlike an anchored mismatch).
|
|
89
|
+
* `insert head:`/`insert tail:` applied despite a stale snapshot tag.
|
|
90
|
+
* Head/tail position is content-independent, so drift is non-fatal: apply
|
|
91
|
+
* onto live content and warn instead of hard-failing.
|
|
77
92
|
*/
|
|
78
|
-
export declare const HEADTAIL_DRIFT_WARNING = "Applied
|
|
93
|
+
export declare const HEADTAIL_DRIFT_WARNING = "Applied the `insert head:`/`insert tail:` edit despite a stale snapshot tag (file changed since your read) \u2014 head/tail position is content-independent. Re-read if the drift was unexpected.";
|
|
79
94
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* ({@link Patcher.prepare}) and the preview/diff path, so both surfaces reuse
|
|
83
|
-
* this single builder to stay in lockstep.
|
|
95
|
+
* Section omitted the mandatory snapshot tag. Shared by the apply
|
|
96
|
+
* ({@link Patcher.prepare}) and preview/diff paths so both stay in lockstep.
|
|
84
97
|
*/
|
|
85
98
|
export declare function missingSnapshotTagMessage(sectionPath: string): string;
|
package/dist/types/patcher.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { Patch, PatchSection } from "./input";
|
|
|
3
3
|
import { type LineEnding } from "./normalize";
|
|
4
4
|
import { Recovery } from "./recovery";
|
|
5
5
|
import type { SnapshotStore } from "./snapshots";
|
|
6
|
-
import type { ApplyResult, BlockResolver } from "./types";
|
|
6
|
+
import type { ApplyResult, BlockResolution, BlockResolver } from "./types";
|
|
7
7
|
export interface PatcherOptions {
|
|
8
8
|
/** Storage backend used for all reads and writes. */
|
|
9
9
|
fs: Filesystem;
|
|
@@ -40,6 +40,12 @@ export interface PatchSectionResult {
|
|
|
40
40
|
firstChangedLine?: number;
|
|
41
41
|
/** Warnings collected by the parser, applier, and (optionally) recovery. */
|
|
42
42
|
warnings: string[];
|
|
43
|
+
/**
|
|
44
|
+
* Resolved spans for any `replace block`/`delete block` ops, present when the
|
|
45
|
+
* apply matched the tagged content. Undefined for patches with no block ops
|
|
46
|
+
* (and for resolutions routed through drift recovery, where numbers shift).
|
|
47
|
+
*/
|
|
48
|
+
blockResolutions?: BlockResolution[];
|
|
43
49
|
}
|
|
44
50
|
export interface PatcherApplyResult {
|
|
45
51
|
sections: PatchSectionResult[];
|
package/dist/types/prefixes.d.ts
CHANGED
|
@@ -13,6 +13,14 @@
|
|
|
13
13
|
* common case for echoed file content, and erroneously echoed prefixes will
|
|
14
14
|
* otherwise turn every content line into a (malformed) op.
|
|
15
15
|
*/
|
|
16
|
+
/**
|
|
17
|
+
* Single-pass variant of {@link stripLeadingHashlinePrefixes} that strips at
|
|
18
|
+
* most one leading hashline prefix (`N:`, `>>>N:`, `+N:` etc.) and does NOT
|
|
19
|
+
* loop. Use this when the input carries at most one snapshot prefix (e.g. a
|
|
20
|
+
* bare body row paste from `read` output) — recursive stripping would corrupt
|
|
21
|
+
* content whose own text starts with `digits:`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function stripOneLeadingHashlinePrefix(line: string): string;
|
|
16
24
|
/**
|
|
17
25
|
* Strip whichever prefix scheme the lines appear to be carrying:
|
|
18
26
|
* - hashline line-number prefixes (`123:`) when every content line has one
|
|
@@ -34,6 +34,12 @@ export interface InMemorySnapshotStoreOptions {
|
|
|
34
34
|
maxPaths?: number;
|
|
35
35
|
/** Maximum full-file versions retained per path (default 4). Oldest dropped first. */
|
|
36
36
|
maxVersionsPerPath?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Global ceiling on retained snapshot text summed across every path's
|
|
39
|
+
* version history, measured in UTF-16 code units (default 64 MiB).
|
|
40
|
+
* Least-recently-used path histories are evicted to stay under it.
|
|
41
|
+
*/
|
|
42
|
+
maxTotalBytes?: number;
|
|
37
43
|
}
|
|
38
44
|
/**
|
|
39
45
|
* In-memory {@link SnapshotStore} backed by `lru-cache`. Per-path history is a
|
package/dist/types/types.d.ts
CHANGED
|
@@ -33,6 +33,13 @@ export type Edit = {
|
|
|
33
33
|
lineNum: number;
|
|
34
34
|
index: number;
|
|
35
35
|
mode?: "replacement";
|
|
36
|
+
/**
|
|
37
|
+
* Present on inserts lowered from `insert after block N:`: the
|
|
38
|
+
* resolved block's first line. Lets the applier slide a body that
|
|
39
|
+
* claims a depth inside the block back across the block's trailing
|
|
40
|
+
* closer lines (never above this line).
|
|
41
|
+
*/
|
|
42
|
+
blockStart?: number;
|
|
36
43
|
} | {
|
|
37
44
|
kind: "delete";
|
|
38
45
|
anchor: Anchor;
|
|
@@ -41,18 +48,21 @@ export type Edit = {
|
|
|
41
48
|
oldAssertion?: string;
|
|
42
49
|
} | {
|
|
43
50
|
/**
|
|
44
|
-
* Deferred block edit (`replace block N:` / `delete block N`
|
|
45
|
-
* line span is unknown at parse
|
|
46
|
-
* {@link resolveBlockEdits} once file text +
|
|
47
|
-
* available, then expanded into concrete edits:
|
|
48
|
-
* (from `replace block`) becomes
|
|
49
|
-
* that `replace start..end:`
|
|
50
|
-
*
|
|
51
|
+
* Deferred block edit (`replace block N:` / `delete block N` /
|
|
52
|
+
* `insert after block N:`). The exact line span is unknown at parse
|
|
53
|
+
* time — it is computed by {@link resolveBlockEdits} once file text +
|
|
54
|
+
* path (→ language) are available, then expanded into concrete edits:
|
|
55
|
+
* a non-empty `payloads` without `mode` (from `replace block`) becomes
|
|
56
|
+
* the same `replacement` inserts + deletes that `replace start..end:`
|
|
57
|
+
* produces; an empty `payloads` (from `delete block`) becomes a pure
|
|
58
|
+
* range deletion; `mode: "insert_after"` becomes plain `after_anchor`
|
|
59
|
+
* inserts at the block's last line. `applyEdits` never sees this
|
|
51
60
|
* variant.
|
|
52
61
|
*/
|
|
53
62
|
kind: "block";
|
|
54
63
|
anchor: Anchor;
|
|
55
64
|
payloads: string[];
|
|
65
|
+
mode?: "insert_after";
|
|
56
66
|
lineNum: number;
|
|
57
67
|
index: number;
|
|
58
68
|
};
|
|
@@ -64,6 +74,13 @@ export interface ApplyResult {
|
|
|
64
74
|
firstChangedLine?: number;
|
|
65
75
|
/** Diagnostic warnings collected by the parser, patcher, or recovery. */
|
|
66
76
|
warnings?: string[];
|
|
77
|
+
/**
|
|
78
|
+
* Resolved spans for each `replace block`/`delete block` op in this apply,
|
|
79
|
+
* in patch order. Present only when the apply matched the tagged content
|
|
80
|
+
* (the common no-drift path), so the line numbers line up with what the
|
|
81
|
+
* caller read. Absent when there were no block ops.
|
|
82
|
+
*/
|
|
83
|
+
blockResolutions?: BlockResolution[];
|
|
67
84
|
}
|
|
68
85
|
/** A parsed `[A..B]` line range. */
|
|
69
86
|
export interface ParsedRange {
|
|
@@ -96,9 +113,11 @@ export interface CompactDiffPreview {
|
|
|
96
113
|
addedLines: number;
|
|
97
114
|
removedLines: number;
|
|
98
115
|
}
|
|
99
|
-
/** Optional knobs for {@link buildCompactDiffPreview}.
|
|
116
|
+
/** Optional knobs for {@link buildCompactDiffPreview}. */
|
|
100
117
|
export interface CompactDiffOptions {
|
|
101
|
-
/**
|
|
118
|
+
/** Added lines kept on each side of a long added-run elision (default 2). */
|
|
119
|
+
maxAddedRunContext?: number;
|
|
120
|
+
/** Back-compat alias for {@link maxAddedRunContext}. */
|
|
102
121
|
maxUnchangedRun?: number;
|
|
103
122
|
}
|
|
104
123
|
/**
|
|
@@ -110,6 +129,23 @@ export interface BlockSpan {
|
|
|
110
129
|
/** Last line of the block (1-indexed, inclusive). */
|
|
111
130
|
end: number;
|
|
112
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* One `replace block N:` / `delete block N` / `insert after block N:` anchor
|
|
134
|
+
* resolved to its concrete line span. Surfaced on {@link ApplyResult} so the
|
|
135
|
+
* host can echo "block N → lines start..end" and let the model catch a wrong
|
|
136
|
+
* opener — e.g. a decorator or doc-comment that sits in a separate node
|
|
137
|
+
* outside the resolved block.
|
|
138
|
+
*/
|
|
139
|
+
export interface BlockResolution {
|
|
140
|
+
/** The 1-indexed line the block op was anchored on (the `N`). */
|
|
141
|
+
anchorLine: number;
|
|
142
|
+
/** First line of the resolved span (1-indexed, inclusive). */
|
|
143
|
+
start: number;
|
|
144
|
+
/** Last line of the resolved span (1-indexed, inclusive). */
|
|
145
|
+
end: number;
|
|
146
|
+
/** Which block op produced this resolution. */
|
|
147
|
+
op: "replace" | "delete" | "insert_after";
|
|
148
|
+
}
|
|
113
149
|
/** Request handed to a {@link BlockResolver} to resolve one `replace block N:` anchor. */
|
|
114
150
|
export interface BlockResolverRequest {
|
|
115
151
|
/** Target file path (used to infer language by extension). */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@prometheus-ai/hashline",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.8",
|
|
5
5
|
"description": "Hashline: a compact, line-anchored patch language and applier. Pluggable FS/IO so it works over disk, in-memory, or any custom backend.",
|
|
6
6
|
"homepage": "https://prometheus.trivlab.com",
|
|
7
7
|
"author": "Uttam Trivedi",
|
|
@@ -44,6 +44,8 @@
|
|
|
44
44
|
},
|
|
45
45
|
"files": [
|
|
46
46
|
"src",
|
|
47
|
+
"README.md",
|
|
48
|
+
"CHANGELOG.md",
|
|
47
49
|
"dist/types"
|
|
48
50
|
],
|
|
49
51
|
"exports": {
|