@osovv/vv-opencode 1.2.6 → 1.2.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.
Files changed (53) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +29 -2
  3. package/dist/commands/patch-provider.js +2 -0
  4. package/dist/commands/patch-provider.js.map +1 -1
  5. package/dist/commands/plugin-list.js +8 -3
  6. package/dist/commands/plugin-list.js.map +1 -1
  7. package/dist/commands/plugin-toggle.js +8 -1
  8. package/dist/commands/plugin-toggle.js.map +1 -1
  9. package/dist/lib/plugin-toggle-config.d.ts +5 -1
  10. package/dist/lib/plugin-toggle-config.js +15 -10
  11. package/dist/lib/plugin-toggle-config.js.map +1 -1
  12. package/dist/lib/vvoc-config.d.ts +33 -1
  13. package/dist/lib/vvoc-config.js +49 -1
  14. package/dist/lib/vvoc-config.js.map +1 -1
  15. package/dist/plugins/hashline-edit/diff-summary.d.ts +7 -0
  16. package/dist/plugins/hashline-edit/diff-summary.js +79 -0
  17. package/dist/plugins/hashline-edit/diff-summary.js.map +1 -0
  18. package/dist/plugins/hashline-edit/edit-operation-primitives.d.ts +2 -2
  19. package/dist/plugins/hashline-edit/edit-operation-primitives.js +56 -37
  20. package/dist/plugins/hashline-edit/edit-operation-primitives.js.map +1 -1
  21. package/dist/plugins/hashline-edit/edit-operations.d.ts +1 -0
  22. package/dist/plugins/hashline-edit/edit-operations.js +17 -10
  23. package/dist/plugins/hashline-edit/edit-operations.js.map +1 -1
  24. package/dist/plugins/hashline-edit/edit-text-normalization.d.ts +27 -4
  25. package/dist/plugins/hashline-edit/edit-text-normalization.js +45 -56
  26. package/dist/plugins/hashline-edit/edit-text-normalization.js.map +1 -1
  27. package/dist/plugins/hashline-edit/index.js +331 -35
  28. package/dist/plugins/hashline-edit/index.js.map +1 -1
  29. package/dist/plugins/hashline-edit/normalize-edits.js +56 -20
  30. package/dist/plugins/hashline-edit/normalize-edits.js.map +1 -1
  31. package/dist/plugins/hashline-edit/replace-engine.d.ts +24 -0
  32. package/dist/plugins/hashline-edit/replace-engine.js +246 -0
  33. package/dist/plugins/hashline-edit/replace-engine.js.map +1 -0
  34. package/dist/plugins/hashline-edit/routing.d.ts +21 -0
  35. package/dist/plugins/hashline-edit/routing.js +113 -0
  36. package/dist/plugins/hashline-edit/routing.js.map +1 -0
  37. package/dist/plugins/hashline-edit/session-state.d.ts +23 -0
  38. package/dist/plugins/hashline-edit/session-state.js +70 -0
  39. package/dist/plugins/hashline-edit/session-state.js.map +1 -0
  40. package/dist/plugins/hashline-edit/str-replace-editor.d.ts +50 -0
  41. package/dist/plugins/hashline-edit/str-replace-editor.js +285 -0
  42. package/dist/plugins/hashline-edit/str-replace-editor.js.map +1 -0
  43. package/dist/plugins/hashline-edit/tool-description.d.ts +2 -1
  44. package/dist/plugins/hashline-edit/tool-description.js +44 -18
  45. package/dist/plugins/hashline-edit/tool-description.js.map +1 -1
  46. package/dist/plugins/hashline-edit/validation.d.ts +1 -0
  47. package/dist/plugins/hashline-edit/validation.js +13 -3
  48. package/dist/plugins/hashline-edit/validation.js.map +1 -1
  49. package/package.json +1 -1
  50. package/schemas/vvoc/v3.json +29 -2
  51. package/dist/plugins/hashline-edit/autocorrect-replacement-lines.d.ts +0 -1
  52. package/dist/plugins/hashline-edit/autocorrect-replacement-lines.js +0 -188
  53. package/dist/plugins/hashline-edit/autocorrect-replacement-lines.js.map +0 -1
@@ -1,9 +1,9 @@
1
1
  // FILE: src/plugins/hashline-edit/normalize-edits.ts
2
- // VERSION: 0.3.0
2
+ // VERSION: 0.5.0
3
3
  // START_MODULE_CONTRACT
4
4
  // PURPOSE: Validate and normalize raw hashline tool arguments into strongly-typed edit operations.
5
- // SCOPE: Raw edit input shape, anchor trimming, required-field validation, and replace/replace_range/append/prepend normalization.
6
- // DEPENDS: [src/plugins/hashline-edit/types.ts]
5
+ // SCOPE: Raw edit input shape, anchor trimming, three-part anchor enforcement, required-field validation, physical single-line payload enforcement, blank-payload rejection for replacements, and unified replace (optional end) with replace_range alias plus append/prepend normalization.
6
+ // DEPENDS: [src/plugins/hashline-edit/types.ts, src/plugins/hashline-edit/validation.ts]
7
7
  // LINKS: [M-PLUGIN-HASHLINE-EDIT]
8
8
  // ROLE: RUNTIME
9
9
  // MAP_MODE: EXPORTS
@@ -15,8 +15,9 @@
15
15
  // END_MODULE_MAP
16
16
  //
17
17
  // START_CHANGE_SUMMARY
18
- // LAST_CHANGE: [v0.3.0 - Split "replace" validation: "replace" rejects end, "replace_range" requires both pos and end.]
18
+ // LAST_CHANGE: [v0.5.0 - Unified replace to accept an optional end anchor (range semantics) with replace_range kept as an alias, rejected multi-line replace without end via add-end guidance, and enforced three-part anchors on all edit references.]
19
19
  // END_CHANGE_SUMMARY
20
+ import { requireThreePartRef } from "./validation.js";
20
21
  function normalizeAnchor(value) {
21
22
  if (typeof value !== "string") {
22
23
  return undefined;
@@ -24,6 +25,14 @@ function normalizeAnchor(value) {
24
25
  const trimmed = value.trim();
25
26
  return trimmed === "" ? undefined : trimmed;
26
27
  }
28
+ function requireAnchor(value, index, field) {
29
+ const anchor = normalizeAnchor(value);
30
+ if (anchor === undefined) {
31
+ return undefined;
32
+ }
33
+ requireThreePartRef(anchor, `Edit ${index} ${field}`);
34
+ return anchor;
35
+ }
27
36
  function requireLines(edit, index) {
28
37
  if (edit.lines === undefined) {
29
38
  throw new Error(`Edit ${index}: lines is required for ${edit.op ?? "unknown"}`);
@@ -34,41 +43,47 @@ function requireLines(edit, index) {
34
43
  return edit.lines;
35
44
  }
36
45
  function normalizeReplaceEdit(edit, index) {
37
- const pos = normalizeAnchor(edit.pos);
46
+ const pos = requireAnchor(edit.pos, index, "pos");
38
47
  if (!pos) {
39
48
  throw new Error(`Edit ${index}: replace requires pos anchor`);
40
49
  }
41
- if (edit.end !== undefined && edit.end !== null && edit.end.trim() !== "") {
42
- throw new Error(`Edit ${index}: replace does not accept end — use "replace_range" for multi-line replacements`);
50
+ const end = requireAnchor(edit.end, index, "end");
51
+ const lines = requireLines(edit, index);
52
+ assertNonBlankReplacement(edit, index, lines);
53
+ assertPhysicalLines(edit, index, lines);
54
+ // With an end anchor, replace applies as an inclusive range (pos..end).
55
+ if (end) {
56
+ return { op: "replace_range", pos, end, lines };
43
57
  }
44
- if (Array.isArray(edit.lines) && edit.lines.length > 1) {
45
- throw new Error(`Edit ${index}: replace is for single-line replacement only. ` +
46
- `You passed ${edit.lines.length} replacement lines. Use "replace_range" with pos + end for multi-line replacement.`);
58
+ const lineCount = Array.isArray(lines) ? lines.length : lines.split("\n").length;
59
+ if (lineCount > 1) {
60
+ throw new Error(`Edit ${index}: replace received ${lineCount} replacement lines but no end anchor. ` +
61
+ "Add the end anchor of the last line to replace (pos..end is inclusive), or pass a single replacement line.");
47
62
  }
48
- return {
49
- op: "replace",
50
- pos,
51
- lines: requireLines(edit, index),
52
- };
63
+ return { op: "replace", pos, lines };
53
64
  }
54
65
  function normalizeReplaceRangeEdit(edit, index) {
55
- const pos = normalizeAnchor(edit.pos);
56
- const end = normalizeAnchor(edit.end);
66
+ const pos = requireAnchor(edit.pos, index, "pos");
67
+ const end = requireAnchor(edit.end, index, "end");
57
68
  if (!pos || !end) {
58
69
  throw new Error(`Edit ${index}: replace_range requires both pos and end anchors`);
59
70
  }
71
+ const lines = requireLines(edit, index);
72
+ assertNonBlankReplacement(edit, index, lines);
73
+ assertPhysicalLines(edit, index, lines);
60
74
  return {
61
75
  op: "replace_range",
62
76
  pos,
63
77
  end,
64
- lines: requireLines(edit, index),
78
+ lines,
65
79
  };
66
80
  }
67
81
  function normalizeInsertEdit(edit, index, op) {
68
- const pos = normalizeAnchor(edit.pos);
69
- const end = normalizeAnchor(edit.end);
82
+ const pos = requireAnchor(edit.pos, index, "pos");
83
+ const end = requireAnchor(edit.end, index, "end");
70
84
  const anchor = pos ?? end;
71
85
  const lines = requireLines(edit, index);
86
+ assertPhysicalLines(edit, index, lines);
72
87
  const normalized = {
73
88
  op,
74
89
  lines,
@@ -78,6 +93,27 @@ function normalizeInsertEdit(edit, index, op) {
78
93
  }
79
94
  return normalized;
80
95
  }
96
+ function assertPhysicalLines(edit, index, lines) {
97
+ if (typeof lines === "string") {
98
+ return;
99
+ }
100
+ for (let entryIndex = 0; entryIndex < lines.length; entryIndex += 1) {
101
+ const entry = lines[entryIndex] ?? "";
102
+ if (entry.includes("\n") || entry.includes("\r")) {
103
+ throw new Error(`Edit ${index}: lines[${entryIndex}] for ${edit.op ?? "unknown"} contains an embedded newline. ` +
104
+ "Each array entry must be exactly one physical line; split the content into separate entries.");
105
+ }
106
+ }
107
+ }
108
+ function assertNonBlankReplacement(edit, index, lines) {
109
+ const isBlank = (typeof lines === "string" && lines === "") ||
110
+ (Array.isArray(lines) && lines.length === 1 && lines[0] === "");
111
+ if (!isBlank) {
112
+ return;
113
+ }
114
+ throw new Error(`Edit ${index}: ${edit.op ?? "unknown"} with a single blank line (lines: [""]) is ambiguous and was rejected. ` +
115
+ "To delete lines use lines: [] or lines: null. To insert a blank line use append or prepend.");
116
+ }
81
117
  export function normalizeHashlineEdits(rawEdits) {
82
118
  return rawEdits.map((rawEdit, index) => {
83
119
  const edit = rawEdit ?? {};
@@ -1 +1 @@
1
- {"version":3,"file":"normalize-edits.js","sourceRoot":"","sources":["../../../src/plugins/hashline-edit/normalize-edits.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"normalize-edits.js","sourceRoot":"","sources":["../../../src/plugins/hashline-edit/normalize-edits.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export interface ReplaceEditParams {
2
+ oldString: string;
3
+ newString: string;
4
+ replaceAll?: boolean;
5
+ }
6
+ export type ReplaceMatchLayer = "exact" | "unicode_confusables" | "trailing_whitespace";
7
+ export type ReplaceApplyResult = {
8
+ ok: true;
9
+ content: string;
10
+ layer: ReplaceMatchLayer;
11
+ replacements: number;
12
+ warnings: string[];
13
+ } | {
14
+ ok: false;
15
+ error: string;
16
+ warnings: string[];
17
+ };
18
+ export declare function applyReplaceEdit(content: string, params: ReplaceEditParams): ReplaceApplyResult;
19
+ export declare function formatReplaceSuccess(filePath: string, beforeContent: string, result: {
20
+ content: string;
21
+ layer: ReplaceMatchLayer;
22
+ replacements: number;
23
+ warnings: string[];
24
+ }): string;
@@ -0,0 +1,246 @@
1
+ // FILE: src/plugins/hashline-edit/replace-engine.ts
2
+ // VERSION: 0.1.0
3
+ // START_MODULE_CONTRACT
4
+ // PURPOSE: Apply oldString/newString replace edits with the native qwen/kimi harness contract: exact literal matching, limited visible fallback layers, uniqueness rules, and teaching errors. Tool-facing snake_case aliases (old_string/new_string) are resolved to this engine at the plugin layer.
5
+ // SCOPE: Pure content-level replace application with exact, unicode-confusables, and trailing-whitespace layers; occurrence counting; replace-all mode; result formatting with bounded diff summary.
6
+ // DEPENDS: [src/plugins/hashline-edit/diff-summary.ts]
7
+ // LINKS: [M-PLUGIN-HASHLINE-EDIT]
8
+ // ROLE: RUNTIME
9
+ // MAP_MODE: EXPORTS
10
+ // END_MODULE_CONTRACT
11
+ //
12
+ // START_MODULE_MAP
13
+ // ReplaceEditParams - Tool-facing replace arguments (oldString, newString, replaceAll).
14
+ // ReplaceMatchLayer - Which matching layer produced the applied match.
15
+ // ReplaceApplyResult - Structured outcome: applied content with layer and replacement count, or a teaching error.
16
+ // applyReplaceEdit - Apply a replace edit to file content with layered fail-closed matching.
17
+ // formatReplaceSuccess - Render the success output with stats, warnings, and bounded diff.
18
+ // END_MODULE_MAP
19
+ //
20
+ // START_CHANGE_SUMMARY
21
+ // LAST_CHANGE: [v0.1.0 - Established the replace profile engine with exact, unicode-confusables, and trailing-whitespace layers adapted from the qwen-code contract (Apache-2.0).]
22
+ // END_CHANGE_SUMMARY
23
+ import { findFirstChangedLine, summarizeEditDiff } from "./diff-summary.js";
24
+ // END_BLOCK_TYPES
25
+ // START_BLOCK_CONFUSABLES
26
+ // Character-level typography normalization adapted from qwen-code editHelper
27
+ // (Apache-2.0). Every entry maps one code point to one code point so string
28
+ // offsets are preserved between original and normalized text.
29
+ const UNICODE_EQUIVALENT_MAP = {
30
+ "\u2010": "-",
31
+ "\u2011": "-",
32
+ "\u2012": "-",
33
+ "\u2013": "-",
34
+ "\u2014": "-",
35
+ "\u2015": "-",
36
+ "\u2212": "-",
37
+ "\u2018": "'",
38
+ "\u2019": "'",
39
+ "\u201A": "'",
40
+ "\u201B": "'",
41
+ "\u201C": '"',
42
+ "\u201D": '"',
43
+ "\u201E": '"',
44
+ "\u201F": '"',
45
+ "\u00A0": " ",
46
+ "\u2002": " ",
47
+ "\u2003": " ",
48
+ "\u2004": " ",
49
+ "\u2005": " ",
50
+ "\u2006": " ",
51
+ "\u2007": " ",
52
+ "\u2008": " ",
53
+ "\u2009": " ",
54
+ "\u200A": " ",
55
+ "\u202F": " ",
56
+ "\u205F": " ",
57
+ "\u3000": " ",
58
+ };
59
+ function normalizeConfusables(text) {
60
+ let normalized = "";
61
+ for (const char of text) {
62
+ normalized += UNICODE_EQUIVALENT_MAP[char] ?? char;
63
+ }
64
+ return normalized;
65
+ }
66
+ // END_BLOCK_CONFUSABLES
67
+ // START_BLOCK_MATCHING
68
+ function countOccurrences(content, needle) {
69
+ if (needle.length === 0) {
70
+ return 0;
71
+ }
72
+ let count = 0;
73
+ let position = 0;
74
+ while (position < content.length) {
75
+ const index = content.indexOf(needle, position);
76
+ if (index === -1) {
77
+ break;
78
+ }
79
+ count += 1;
80
+ position = index + needle.length;
81
+ }
82
+ return count;
83
+ }
84
+ function matchTrailingWhitespaceBlocks(content, oldString) {
85
+ const contentLines = content.split("\n");
86
+ const searchLines = oldString.split("\n").map((line) => line.trimEnd());
87
+ if (searchLines.every((line) => line === "")) {
88
+ return [];
89
+ }
90
+ const offsets = [];
91
+ let cursor = 0;
92
+ for (const line of contentLines) {
93
+ offsets.push(cursor);
94
+ cursor += line.length + 1;
95
+ }
96
+ const blocks = [];
97
+ for (let i = 0; i + searchLines.length <= contentLines.length; i += 1) {
98
+ let matches = true;
99
+ for (let j = 0; j < searchLines.length; j += 1) {
100
+ if ((contentLines[i + j] ?? "").trimEnd() !== searchLines[j]) {
101
+ matches = false;
102
+ break;
103
+ }
104
+ }
105
+ if (!matches) {
106
+ continue;
107
+ }
108
+ const lastIndex = i + searchLines.length - 1;
109
+ blocks.push({
110
+ start: offsets[i],
111
+ end: offsets[lastIndex] + (contentLines[lastIndex] ?? "").length,
112
+ });
113
+ i = lastIndex;
114
+ }
115
+ return blocks;
116
+ }
117
+ function ambiguityError(count) {
118
+ return (`Failed to edit: oldString matches ${count} locations in the file. ` +
119
+ "Provide more surrounding context to make the match unique, or set replaceAll to true to replace every occurrence.");
120
+ }
121
+ function notFoundError() {
122
+ return ("Failed to edit: oldString not found. The exact text was not found in the file. " +
123
+ "Check whitespace, indentation, and context, and use the Read tool to verify the current " +
124
+ "content before retrying; the file may have changed since you last read it.");
125
+ }
126
+ // Offsets are identical in original and normalized text because every
127
+ // confusable maps one code point to one code point.
128
+ function replaceNormalizedOccurrences(original, normalized, normalizedNeedle, replacement, all) {
129
+ let result = "";
130
+ let cursor = 0;
131
+ let position = 0;
132
+ while (position < normalized.length) {
133
+ const index = normalized.indexOf(normalizedNeedle, position);
134
+ if (index === -1) {
135
+ break;
136
+ }
137
+ result += original.slice(cursor, index) + replacement;
138
+ cursor = index + normalizedNeedle.length;
139
+ position = index + normalizedNeedle.length;
140
+ if (!all) {
141
+ break;
142
+ }
143
+ }
144
+ result += original.slice(cursor);
145
+ return result;
146
+ }
147
+ // END_BLOCK_MATCHING
148
+ // START_BLOCK_APPLY
149
+ export function applyReplaceEdit(content, params) {
150
+ const warnings = [];
151
+ const replaceAll = params.replaceAll ?? false;
152
+ if (params.oldString === params.newString) {
153
+ return {
154
+ ok: false,
155
+ error: "No changes to apply: oldString and newString are identical.",
156
+ warnings,
157
+ };
158
+ }
159
+ if (params.oldString === "") {
160
+ return {
161
+ ok: false,
162
+ error: "oldString cannot be empty when editing an existing file. Provide the exact text to replace.",
163
+ warnings,
164
+ };
165
+ }
166
+ // Layer 1: exact literal match.
167
+ const exactCount = countOccurrences(content, params.oldString);
168
+ if (exactCount > 0) {
169
+ if (!replaceAll && exactCount > 1) {
170
+ return { ok: false, error: ambiguityError(exactCount), warnings };
171
+ }
172
+ const next = replaceAll
173
+ ? content.split(params.oldString).join(params.newString)
174
+ : content.replace(params.oldString, params.newString);
175
+ return {
176
+ ok: true,
177
+ content: next,
178
+ layer: "exact",
179
+ replacements: replaceAll ? exactCount : 1,
180
+ warnings,
181
+ };
182
+ }
183
+ // Layer 2: unicode confusables (typography characters equated to ASCII).
184
+ const normalizedContent = normalizeConfusables(content);
185
+ const normalizedOld = normalizeConfusables(params.oldString);
186
+ if (normalizedContent !== content || normalizedOld !== params.oldString) {
187
+ const normalizedCount = countOccurrences(normalizedContent, normalizedOld);
188
+ if (normalizedCount > 0) {
189
+ if (!replaceAll && normalizedCount > 1) {
190
+ return { ok: false, error: ambiguityError(normalizedCount), warnings };
191
+ }
192
+ warnings.push("oldString matched after unicode confusables normalization (typography characters such as curly quotes, dashes, or special spaces were equated to ASCII); the replacement was applied to the original bytes.");
193
+ const next = replaceNormalizedOccurrences(content, normalizedContent, normalizedOld, params.newString, replaceAll);
194
+ return {
195
+ ok: true,
196
+ content: next,
197
+ layer: "unicode_confusables",
198
+ replacements: replaceAll ? normalizedCount : 1,
199
+ warnings,
200
+ };
201
+ }
202
+ }
203
+ // Layer 3: trailing whitespace ignored per line; indentation stays exact.
204
+ const blocks = matchTrailingWhitespaceBlocks(content, params.oldString);
205
+ if (blocks.length > 0) {
206
+ if (!replaceAll && blocks.length > 1) {
207
+ return { ok: false, error: ambiguityError(blocks.length), warnings };
208
+ }
209
+ warnings.push(`oldString matched after ignoring trailing whitespace on ${blocks.length} block(s); leading whitespace (indentation) was matched exactly.`);
210
+ const selected = replaceAll ? blocks : blocks.slice(0, 1);
211
+ let next = content;
212
+ for (let i = selected.length - 1; i >= 0; i -= 1) {
213
+ const block = selected[i];
214
+ next = next.slice(0, block.start) + params.newString + next.slice(block.end);
215
+ }
216
+ return {
217
+ ok: true,
218
+ content: next,
219
+ layer: "trailing_whitespace",
220
+ replacements: selected.length,
221
+ warnings,
222
+ };
223
+ }
224
+ return { ok: false, error: notFoundError(), warnings };
225
+ }
226
+ // END_BLOCK_APPLY
227
+ // START_BLOCK_FORMAT
228
+ export function formatReplaceSuccess(filePath, beforeContent, result) {
229
+ const diff = summarizeEditDiff(beforeContent, result.content);
230
+ const firstChangedLine = findFirstChangedLine(beforeContent, result.content);
231
+ const stats = `+${diff.additions}/-${diff.deletions}${firstChangedLine !== undefined ? `, first change line ${firstChangedLine}` : ""}`;
232
+ const parts = [`Updated ${filePath} (${stats})`];
233
+ if (result.layer !== "exact") {
234
+ parts.push(`Note: matched via ${result.layer} fallback layer.`);
235
+ }
236
+ if (result.replacements > 1) {
237
+ parts.push(`Note: replaced ${result.replacements} occurrences.`);
238
+ }
239
+ for (const warning of result.warnings) {
240
+ parts.push(`Warning: ${warning}`);
241
+ }
242
+ parts.push(...diff.rendered);
243
+ return parts.join("\n");
244
+ }
245
+ // END_BLOCK_FORMAT
246
+ //# sourceMappingURL=replace-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replace-engine.js","sourceRoot":"","sources":["../../../src/plugins/hashline-edit/replace-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export declare const EDIT_MODES: readonly ["hashline", "replace", "str_replace_editor", "passthrough"];
2
+ export type EditMode = (typeof EDIT_MODES)[number];
3
+ export interface RoutingRule {
4
+ pattern: string;
5
+ mode: EditMode;
6
+ }
7
+ export interface RoutingConfig {
8
+ default: EditMode;
9
+ rules: RoutingRule[];
10
+ }
11
+ export declare const DEFAULT_ROUTING_CONFIG: RoutingConfig;
12
+ export declare function parseRoutingConfig(raw: unknown): RoutingConfig;
13
+ export interface HashlineEditPluginSettings {
14
+ enabled: boolean;
15
+ routing: RoutingConfig;
16
+ }
17
+ export declare function parseHashlineEditPluginEntry(raw: unknown): HashlineEditPluginSettings;
18
+ export declare function resolveEditMode(config: RoutingConfig, model: {
19
+ providerID?: string;
20
+ modelID?: string;
21
+ } | undefined): EditMode;
@@ -0,0 +1,113 @@
1
+ // FILE: src/plugins/hashline-edit/routing.ts
2
+ // VERSION: 0.1.0
3
+ // START_MODULE_CONTRACT
4
+ // PURPOSE: Define edit-mode routing configuration and resolve the active edit mode for a session model.
5
+ // SCOPE: EditMode vocabulary, strict routing config parsing with the default routing table, plugin entry union resolution, and case-insensitive provider-then-model substring matching.
6
+ // DEPENDS: [none]
7
+ // LINKS: [M-PLUGIN-HASHLINE-EDIT]
8
+ // ROLE: RUNTIME
9
+ // MAP_MODE: EXPORTS
10
+ // END_MODULE_CONTRACT
11
+ //
12
+ // START_MODULE_MAP
13
+ // EDIT_MODES - Canonical edit mode identifiers accepted by routing configuration.
14
+ // EditMode - Union type of edit mode identifiers.
15
+ // RoutingRule - One ordered pattern-to-mode routing entry.
16
+ // RoutingConfig - Parsed routing table with default mode and ordered rules.
17
+ // DEFAULT_ROUTING_CONFIG - Built-in routing table applied when config does not override it.
18
+ // parseRoutingConfig - Strictly parse an unknown routing value into a RoutingConfig or throw.
19
+ // HashlineEditPluginSettings - Resolved enabled flag and routing config for the hashline-edit plugin entry.
20
+ // parseHashlineEditPluginEntry - Resolve the plugins["hashline-edit"] boolean-or-object union into enabled flag and routing config.
21
+ // resolveEditMode - Resolve the active edit mode for a provider/model pair against a routing config.
22
+ // END_MODULE_MAP
23
+ //
24
+ // START_CHANGE_SUMMARY
25
+ // LAST_CHANGE: [v0.1.0 - Established routing vocabulary, default table, strict parsing, and provider-then-model resolution.]
26
+ // END_CHANGE_SUMMARY
27
+ // START_BLOCK_VOCABULARY
28
+ export const EDIT_MODES = ["hashline", "replace", "str_replace_editor", "passthrough"];
29
+ // END_BLOCK_VOCABULARY
30
+ // START_BLOCK_DEFAULT_TABLE
31
+ export const DEFAULT_ROUTING_CONFIG = {
32
+ default: "hashline",
33
+ rules: [
34
+ { pattern: "deepseek", mode: "str_replace_editor" },
35
+ { pattern: "kimi", mode: "replace" },
36
+ { pattern: "qwen", mode: "replace" },
37
+ { pattern: "gpt", mode: "passthrough" },
38
+ { pattern: "codex", mode: "passthrough" },
39
+ ],
40
+ };
41
+ // END_BLOCK_DEFAULT_TABLE
42
+ // START_BLOCK_PARSE
43
+ function isRecord(value) {
44
+ return typeof value === "object" && value !== null && !Array.isArray(value);
45
+ }
46
+ function parseEditMode(value, where) {
47
+ if (typeof value === "string" && EDIT_MODES.includes(value)) {
48
+ return value;
49
+ }
50
+ throw new Error(`hashline-edit routing: ${where} must be one of ${EDIT_MODES.join(", ")}; got ${JSON.stringify(value)}`);
51
+ }
52
+ export function parseRoutingConfig(raw) {
53
+ if (raw === undefined || raw === null) {
54
+ return DEFAULT_ROUTING_CONFIG;
55
+ }
56
+ if (!isRecord(raw)) {
57
+ throw new Error("hashline-edit routing: routing config must be an object");
58
+ }
59
+ const defaultMode = raw.default === undefined ? "hashline" : parseEditMode(raw.default, "default");
60
+ const rules = [];
61
+ if (raw.rules !== undefined) {
62
+ if (!isRecord(raw.rules)) {
63
+ throw new Error("hashline-edit routing: rules must be an object mapping patterns to modes");
64
+ }
65
+ for (const [pattern, mode] of Object.entries(raw.rules)) {
66
+ if (pattern.trim().length === 0) {
67
+ throw new Error("hashline-edit routing: rule patterns must be non-empty strings");
68
+ }
69
+ rules.push({ pattern, mode: parseEditMode(mode, `rules["${pattern}"]`) });
70
+ }
71
+ }
72
+ return { default: defaultMode, rules };
73
+ }
74
+ export function parseHashlineEditPluginEntry(raw) {
75
+ if (raw === undefined || raw === null) {
76
+ return { enabled: true, routing: DEFAULT_ROUTING_CONFIG };
77
+ }
78
+ if (typeof raw === "boolean") {
79
+ return { enabled: raw, routing: DEFAULT_ROUTING_CONFIG };
80
+ }
81
+ if (!isRecord(raw)) {
82
+ throw new Error('hashline-edit: plugins["hashline-edit"] must be a boolean or an object');
83
+ }
84
+ const enabled = raw.enabled === undefined ? true : raw.enabled;
85
+ if (typeof enabled !== "boolean") {
86
+ throw new Error("hashline-edit: enabled must be a boolean");
87
+ }
88
+ return { enabled, routing: parseRoutingConfig(raw.routing) };
89
+ }
90
+ // END_BLOCK_PARSE
91
+ // START_BLOCK_RESOLVE
92
+ export function resolveEditMode(config, model) {
93
+ if (!model) {
94
+ return config.default;
95
+ }
96
+ const providerID = model.providerID?.toLowerCase();
97
+ const modelID = model.modelID?.toLowerCase();
98
+ for (const rule of config.rules) {
99
+ const pattern = rule.pattern.toLowerCase();
100
+ if (providerID !== undefined && providerID.includes(pattern)) {
101
+ return rule.mode;
102
+ }
103
+ }
104
+ for (const rule of config.rules) {
105
+ const pattern = rule.pattern.toLowerCase();
106
+ if (modelID !== undefined && modelID.includes(pattern)) {
107
+ return rule.mode;
108
+ }
109
+ }
110
+ return config.default;
111
+ }
112
+ // END_BLOCK_RESOLVE
113
+ //# sourceMappingURL=routing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing.js","sourceRoot":"","sources":["../../../src/plugins/hashline-edit/routing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export interface SessionModelInfo {
2
+ providerID: string;
3
+ modelID: string;
4
+ }
5
+ export declare class SessionModelCache {
6
+ #private;
7
+ set(sessionID: string, model: SessionModelInfo): void;
8
+ get(sessionID: string): SessionModelInfo | undefined;
9
+ delete(sessionID: string): void;
10
+ clear(): void;
11
+ }
12
+ export interface FileSnapshot {
13
+ mtimeMs: number;
14
+ size: number;
15
+ }
16
+ export type FileCacheVerdict = "unread" | "fresh" | "drifted";
17
+ export declare class SessionFileCache {
18
+ #private;
19
+ record(sessionID: string, filePath: string, snapshot: FileSnapshot): void;
20
+ check(sessionID: string, filePath: string, current: FileSnapshot | undefined): FileCacheVerdict;
21
+ forget(sessionID: string, filePath: string): void;
22
+ clear(): void;
23
+ }