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.
- package/LICENSE +21 -0
- package/README.md +442 -0
- package/README.ru.md +417 -0
- package/dist/chunk-C2EVIAGV.js +177 -0
- package/dist/chunk-IVZSANZ4.js +411 -0
- package/dist/hashline-Civwirvf.d.cts +278 -0
- package/dist/hashline-Civwirvf.d.ts +278 -0
- package/dist/hashline-W2FT5QN4.js +44 -0
- package/dist/index.cjs +811 -0
- package/dist/index.d.cts +48 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.js +197 -0
- package/dist/utils.cjs +637 -0
- package/dist/utils.d.cts +74 -0
- package/dist/utils.d.ts +74 -0
- package/dist/utils.js +54 -0
- package/package.json +56 -0
package/dist/utils.d.cts
ADDED
|
@@ -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 };
|
package/dist/utils.d.ts
ADDED
|
@@ -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
|
+
}
|