opencode-hashline 1.0.0

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.
@@ -0,0 +1,74 @@
1
+ import { H as HashlineConfig, e as HashlineCache } from './hashline-Civwirvf.cjs';
2
+ export { D as DEFAULT_CONFIG, f as DEFAULT_EXCLUDE_PATTERNS, g as DEFAULT_PREFIX, a as HashEditInput, b as HashEditOperation, c as HashEditResult, d as HashlineInstance, R as ResolvedRange, V as VerifyHashResult, h as applyHashEdit, i as buildHashMap, j as computeLineHash, k as createHashline, l as formatFileWithHashes, m as getAdaptiveHashLength, n as getByteLength, o as matchesGlob, p as normalizeHashRef, q as parseHashRef, r as replaceRange, s as resolveConfig, t as resolveRange, u as shouldExclude, v as stripHashes, w as verifyHash } from './hashline-Civwirvf.cjs';
3
+ import { Hooks } from '@opencode-ai/plugin';
4
+
5
+ /**
6
+ * OpenCode plugin hooks for Hashline.
7
+ *
8
+ * - `onFileReadAfter`: Injects hashline annotations into file-read tool output
9
+ * so the AI model sees content-addressable line references.
10
+ * - `onFileEditBefore`: Strips hashline prefixes from the AI's edit arguments
11
+ * before they are applied to the actual file.
12
+ */
13
+
14
+ /**
15
+ * Check if a tool input looks like a file-reading tool.
16
+ * Matches by tool name OR by presence of path-like args.
17
+ *
18
+ * NOTE: This is a fallback heuristic. The OpenCode plugin API (as of v1.2.2)
19
+ * does not expose a semantic tool category (e.g. "read" vs "write") in the
20
+ * hook input. If a future API version provides an explicit tool type or
21
+ * category field, prefer that over this name-based detection.
22
+ *
23
+ * ### How tool name matching works:
24
+ *
25
+ * 1. **Exact match** — tool name (lowercased) is compared against the allow-list:
26
+ * `read`, `file_read`, `read_file`, `cat`, `view`.
27
+ *
28
+ * 2. **Dotted suffix match** — for namespaced tools like `mcp.read` or
29
+ * `custom_provider.file_read`, the part after the last `.` is matched.
30
+ *
31
+ * 3. **Fallback heuristic** — if the tool has `path`, `filePath`, or `file`
32
+ * arguments AND the tool name does NOT contain write/edit/execute indicators
33
+ * (`write`, `edit`, `patch`, `execute`, `run`, `command`, `shell`, `bash`),
34
+ * it is treated as a file-read tool.
35
+ *
36
+ * ### How to customize:
37
+ *
38
+ * If your custom tool is not detected, you can either:
39
+ * - Name it to match one of the patterns above (e.g. `my_read_file`)
40
+ * - Include `path`/`filePath`/`file` in its arguments
41
+ * - Or extend the FILE_READ_TOOLS list in a fork
42
+ */
43
+ declare function isFileReadTool(toolName: string, args?: Record<string, unknown>): boolean;
44
+ /**
45
+ * Create the `tool.execute.after` hook.
46
+ *
47
+ * When a file-read tool completes, this hook annotates the output
48
+ * with hashline prefixes so the AI can reference lines precisely.
49
+ *
50
+ * @param cache - optional LRU cache for annotated content
51
+ * @param config - resolved hashline configuration
52
+ */
53
+ declare function createFileReadAfterHook(cache?: HashlineCache, config?: Required<HashlineConfig>): NonNullable<Hooks["tool.execute.after"]>;
54
+ /**
55
+ * Create the `tool.execute.before` hook.
56
+ *
57
+ * When a file-edit tool is about to execute, this hook strips any
58
+ * hashline prefixes from the content arguments so the edits apply
59
+ * cleanly to the original file.
60
+ *
61
+ * @param config - resolved hashline configuration
62
+ */
63
+ declare function createFileEditBeforeHook(config?: Required<HashlineConfig>): NonNullable<Hooks["tool.execute.before"]>;
64
+ /**
65
+ * Create the system prompt injection hook.
66
+ *
67
+ * Adds detailed instructions to the system prompt explaining the hashline format,
68
+ * edit operations, and hash verification rules so the AI model can use them precisely.
69
+ *
70
+ * @param config - resolved hashline configuration
71
+ */
72
+ declare function createSystemPromptHook(config?: Required<HashlineConfig>): NonNullable<Hooks["experimental.chat.system.transform"]>;
73
+
74
+ export { HashlineCache, HashlineConfig, createFileEditBeforeHook, createFileReadAfterHook, createSystemPromptHook, isFileReadTool };
@@ -0,0 +1,74 @@
1
+ import { H as HashlineConfig, e as HashlineCache } from './hashline-Civwirvf.js';
2
+ export { D as DEFAULT_CONFIG, f as DEFAULT_EXCLUDE_PATTERNS, g as DEFAULT_PREFIX, a as HashEditInput, b as HashEditOperation, c as HashEditResult, d as HashlineInstance, R as ResolvedRange, V as VerifyHashResult, h as applyHashEdit, i as buildHashMap, j as computeLineHash, k as createHashline, l as formatFileWithHashes, m as getAdaptiveHashLength, n as getByteLength, o as matchesGlob, p as normalizeHashRef, q as parseHashRef, r as replaceRange, s as resolveConfig, t as resolveRange, u as shouldExclude, v as stripHashes, w as verifyHash } from './hashline-Civwirvf.js';
3
+ import { Hooks } from '@opencode-ai/plugin';
4
+
5
+ /**
6
+ * OpenCode plugin hooks for Hashline.
7
+ *
8
+ * - `onFileReadAfter`: Injects hashline annotations into file-read tool output
9
+ * so the AI model sees content-addressable line references.
10
+ * - `onFileEditBefore`: Strips hashline prefixes from the AI's edit arguments
11
+ * before they are applied to the actual file.
12
+ */
13
+
14
+ /**
15
+ * Check if a tool input looks like a file-reading tool.
16
+ * Matches by tool name OR by presence of path-like args.
17
+ *
18
+ * NOTE: This is a fallback heuristic. The OpenCode plugin API (as of v1.2.2)
19
+ * does not expose a semantic tool category (e.g. "read" vs "write") in the
20
+ * hook input. If a future API version provides an explicit tool type or
21
+ * category field, prefer that over this name-based detection.
22
+ *
23
+ * ### How tool name matching works:
24
+ *
25
+ * 1. **Exact match** — tool name (lowercased) is compared against the allow-list:
26
+ * `read`, `file_read`, `read_file`, `cat`, `view`.
27
+ *
28
+ * 2. **Dotted suffix match** — for namespaced tools like `mcp.read` or
29
+ * `custom_provider.file_read`, the part after the last `.` is matched.
30
+ *
31
+ * 3. **Fallback heuristic** — if the tool has `path`, `filePath`, or `file`
32
+ * arguments AND the tool name does NOT contain write/edit/execute indicators
33
+ * (`write`, `edit`, `patch`, `execute`, `run`, `command`, `shell`, `bash`),
34
+ * it is treated as a file-read tool.
35
+ *
36
+ * ### How to customize:
37
+ *
38
+ * If your custom tool is not detected, you can either:
39
+ * - Name it to match one of the patterns above (e.g. `my_read_file`)
40
+ * - Include `path`/`filePath`/`file` in its arguments
41
+ * - Or extend the FILE_READ_TOOLS list in a fork
42
+ */
43
+ declare function isFileReadTool(toolName: string, args?: Record<string, unknown>): boolean;
44
+ /**
45
+ * Create the `tool.execute.after` hook.
46
+ *
47
+ * When a file-read tool completes, this hook annotates the output
48
+ * with hashline prefixes so the AI can reference lines precisely.
49
+ *
50
+ * @param cache - optional LRU cache for annotated content
51
+ * @param config - resolved hashline configuration
52
+ */
53
+ declare function createFileReadAfterHook(cache?: HashlineCache, config?: Required<HashlineConfig>): NonNullable<Hooks["tool.execute.after"]>;
54
+ /**
55
+ * Create the `tool.execute.before` hook.
56
+ *
57
+ * When a file-edit tool is about to execute, this hook strips any
58
+ * hashline prefixes from the content arguments so the edits apply
59
+ * cleanly to the original file.
60
+ *
61
+ * @param config - resolved hashline configuration
62
+ */
63
+ declare function createFileEditBeforeHook(config?: Required<HashlineConfig>): NonNullable<Hooks["tool.execute.before"]>;
64
+ /**
65
+ * Create the system prompt injection hook.
66
+ *
67
+ * Adds detailed instructions to the system prompt explaining the hashline format,
68
+ * edit operations, and hash verification rules so the AI model can use them precisely.
69
+ *
70
+ * @param config - resolved hashline configuration
71
+ */
72
+ declare function createSystemPromptHook(config?: Required<HashlineConfig>): NonNullable<Hooks["experimental.chat.system.transform"]>;
73
+
74
+ export { HashlineCache, HashlineConfig, createFileEditBeforeHook, createFileReadAfterHook, createSystemPromptHook, isFileReadTool };
package/dist/utils.js ADDED
@@ -0,0 +1,54 @@
1
+ import {
2
+ createFileEditBeforeHook,
3
+ createFileReadAfterHook,
4
+ createSystemPromptHook,
5
+ isFileReadTool
6
+ } from "./chunk-C2EVIAGV.js";
7
+ import {
8
+ DEFAULT_CONFIG,
9
+ DEFAULT_EXCLUDE_PATTERNS,
10
+ DEFAULT_PREFIX,
11
+ HashlineCache,
12
+ applyHashEdit,
13
+ buildHashMap,
14
+ computeLineHash,
15
+ createHashline,
16
+ formatFileWithHashes,
17
+ getAdaptiveHashLength,
18
+ getByteLength,
19
+ matchesGlob,
20
+ normalizeHashRef,
21
+ parseHashRef,
22
+ replaceRange,
23
+ resolveConfig,
24
+ resolveRange,
25
+ shouldExclude,
26
+ stripHashes,
27
+ verifyHash
28
+ } from "./chunk-IVZSANZ4.js";
29
+ export {
30
+ DEFAULT_CONFIG,
31
+ DEFAULT_EXCLUDE_PATTERNS,
32
+ DEFAULT_PREFIX,
33
+ HashlineCache,
34
+ applyHashEdit,
35
+ buildHashMap,
36
+ computeLineHash,
37
+ createFileEditBeforeHook,
38
+ createFileReadAfterHook,
39
+ createHashline,
40
+ createSystemPromptHook,
41
+ formatFileWithHashes,
42
+ getAdaptiveHashLength,
43
+ getByteLength,
44
+ isFileReadTool,
45
+ matchesGlob,
46
+ normalizeHashRef,
47
+ parseHashRef,
48
+ replaceRange,
49
+ resolveConfig,
50
+ resolveRange,
51
+ shouldExclude,
52
+ stripHashes,
53
+ verifyHash
54
+ };
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "opencode-hashline",
3
+ "version": "1.0.0",
4
+ "description": "Hashline plugin for OpenCode — content-addressable line hashing for precise AI code editing",
5
+ "main": "dist/index.cjs",
6
+ "module": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "type": "module",
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js",
16
+ "require": "./dist/index.cjs"
17
+ },
18
+ "./utils": {
19
+ "types": "./dist/utils.d.ts",
20
+ "import": "./dist/utils.js",
21
+ "require": "./dist/utils.cjs"
22
+ }
23
+ },
24
+ "scripts": {
25
+ "build": "tsup",
26
+ "test": "vitest run",
27
+ "test:watch": "vitest",
28
+ "typecheck": "tsc --noEmit",
29
+ "benchmark": "npx tsx benchmarks/benchmark.ts",
30
+ "prepublishOnly": "npm run build"
31
+ },
32
+ "keywords": [
33
+ "opencode",
34
+ "opencode-plugin",
35
+ "plugin",
36
+ "hashline",
37
+ "line-hashing",
38
+ "ai",
39
+ "code-editing"
40
+ ],
41
+ "license": "MIT",
42
+ "peerDependencies": {
43
+ "@opencode-ai/plugin": "^1.2.2"
44
+ },
45
+ "devDependencies": {
46
+ "@opencode-ai/plugin": "^1.2.2",
47
+ "@types/node": "^25.2.3",
48
+ "@types/picomatch": "^4.0.2",
49
+ "tsup": "^8.5.1",
50
+ "typescript": "^5.9.3",
51
+ "vitest": "^4.0.18"
52
+ },
53
+ "dependencies": {
54
+ "picomatch": "^4.0.3"
55
+ }
56
+ }