@osovv/vv-opencode 1.2.8 → 1.2.10
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 +21 -0
- package/README.md +36 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/opencode.js +3 -0
- package/dist/lib/opencode.js.map +1 -1
- package/dist/lib/plugin-toggle-config.d.ts +40 -2
- package/dist/lib/plugin-toggle-config.js +119 -3
- package/dist/lib/plugin-toggle-config.js.map +1 -1
- package/dist/lib/vvoc-config.d.ts +47 -1
- package/dist/lib/vvoc-config.js +24 -11
- package/dist/lib/vvoc-config.js.map +1 -1
- package/dist/plugins/hashline-edit/routing.js +6 -14
- package/dist/plugins/hashline-edit/routing.js.map +1 -1
- package/dist/plugins/tool-history-compaction/config.d.ts +28 -0
- package/dist/plugins/tool-history-compaction/config.js +133 -0
- package/dist/plugins/tool-history-compaction/config.js.map +1 -0
- package/dist/plugins/tool-history-compaction/index.d.ts +2 -0
- package/dist/plugins/tool-history-compaction/index.js +35 -0
- package/dist/plugins/tool-history-compaction/index.js.map +1 -0
- package/dist/plugins/tool-history-compaction/prune.d.ts +22 -0
- package/dist/plugins/tool-history-compaction/prune.js +70 -0
- package/dist/plugins/tool-history-compaction/prune.js.map +1 -0
- package/dist/plugins/tool-history-compaction/read-slim.d.ts +27 -0
- package/dist/plugins/tool-history-compaction/read-slim.js +91 -0
- package/dist/plugins/tool-history-compaction/read-slim.js.map +1 -0
- package/dist/plugins/tool-history-compaction/retention.d.ts +10 -0
- package/dist/plugins/tool-history-compaction/retention.js +45 -0
- package/dist/plugins/tool-history-compaction/retention.js.map +1 -0
- package/dist/plugins/tool-history-compaction/transform.d.ts +15 -0
- package/dist/plugins/tool-history-compaction/transform.js +93 -0
- package/dist/plugins/tool-history-compaction/transform.js.map +1 -0
- package/package.json +5 -1
- package/schemas/vvoc/v3.json +15 -1
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// FILE: src/plugins/tool-history-compaction/read-slim.ts
|
|
2
|
+
// VERSION: 0.1.0
|
|
3
|
+
// START_MODULE_CONTRACT
|
|
4
|
+
// PURPOSE: Collapse old read tool outputs to a compact [Read <file>, lines X-Y] header, recovering the file from the input and the line range from the output when deterministically available.
|
|
5
|
+
// SCOPE: Read input file extraction, line-numbered output range recovery, savings-gated slim decision, and idempotence detection.
|
|
6
|
+
// DEPENDS: [src/plugins/tool-history-compaction/config.ts]
|
|
7
|
+
// LINKS: [M-PLUGIN-TOOL-HISTORY-COMPACTION]
|
|
8
|
+
// ROLE: RUNTIME
|
|
9
|
+
// MAP_MODE: EXPORTS
|
|
10
|
+
// END_MODULE_CONTRACT
|
|
11
|
+
//
|
|
12
|
+
// START_MODULE_MAP
|
|
13
|
+
// fileFromReadInput - Recover the file path from read input aliases.
|
|
14
|
+
// ReadInputLike - Read input object with filePath/path/file aliases.
|
|
15
|
+
// rangeFromReadOutput - Recover the covered line range from a line-numbered output.
|
|
16
|
+
// slimReadOutput - Return the [Read <file>] form when eligible, otherwise null (fallback to pruning).
|
|
17
|
+
// SlimReadResult - Slim form plus measured savings.
|
|
18
|
+
// END_MODULE_MAP
|
|
19
|
+
//
|
|
20
|
+
// START_CHANGE_SUMMARY
|
|
21
|
+
// LAST_CHANGE: [v0.1.0 - Established old-read collapse with fail-closed fallback.]
|
|
22
|
+
// END_CHANGE_SUMMARY
|
|
23
|
+
import { countCodePoints } from "./prune.js";
|
|
24
|
+
// START_BLOCK_RANGE
|
|
25
|
+
// Matches a line-numbered output line: OpenCode "N| content" / "N: content"
|
|
26
|
+
// and hashline anchored "N#ID#ANCHOR|content". Never fabricates a number.
|
|
27
|
+
const LINE_NUMBER_PREFIX = /^\s*(\d+)(?:#[^|:]*)?(?:\||:)/;
|
|
28
|
+
/** Recover the file path from read input aliases; unknown values yield undefined. */
|
|
29
|
+
export function fileFromReadInput(input) {
|
|
30
|
+
if (!input || typeof input !== "object")
|
|
31
|
+
return undefined;
|
|
32
|
+
for (const key of ["filePath", "path", "file"]) {
|
|
33
|
+
const value = input[key];
|
|
34
|
+
if (typeof value === "string" && value.length > 0)
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
// END_BLOCK_FILE
|
|
40
|
+
// START_BLOCK_RANGE_FN
|
|
41
|
+
/**
|
|
42
|
+
* Recover the covered line range ("first-last") from a line-numbered output.
|
|
43
|
+
* Returns undefined when the output is not deterministically line-numbered.
|
|
44
|
+
*/
|
|
45
|
+
export function rangeFromReadOutput(output) {
|
|
46
|
+
if (typeof output !== "string" || output.length === 0)
|
|
47
|
+
return undefined;
|
|
48
|
+
let first;
|
|
49
|
+
let last;
|
|
50
|
+
for (const line of output.split("\n")) {
|
|
51
|
+
const match = LINE_NUMBER_PREFIX.exec(line);
|
|
52
|
+
if (match) {
|
|
53
|
+
const number = Number.parseInt(match[1] ?? "0", 10);
|
|
54
|
+
if (first === undefined)
|
|
55
|
+
first = number;
|
|
56
|
+
last = number;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (first === undefined || last === undefined || first > last)
|
|
60
|
+
return undefined;
|
|
61
|
+
return `${first}-${last}`;
|
|
62
|
+
}
|
|
63
|
+
function alreadySlimmed(output) {
|
|
64
|
+
return output.startsWith("[Read ");
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Collapse an old read output to [Read <file>, lines X-Y] when the file is
|
|
68
|
+
* recoverable and the savings clear the min-savings guard. Returns null when
|
|
69
|
+
* not applicable; the caller falls back to output pruning (never fabricates).
|
|
70
|
+
* @param input - part.state.input.
|
|
71
|
+
* @param output - part.state.output.
|
|
72
|
+
* @param config - resolved compaction config.
|
|
73
|
+
* @returns slim form or null.
|
|
74
|
+
*/
|
|
75
|
+
export function slimReadOutput(input, output, config) {
|
|
76
|
+
if (typeof output !== "string" || output.length === 0)
|
|
77
|
+
return null;
|
|
78
|
+
if (alreadySlimmed(output))
|
|
79
|
+
return null;
|
|
80
|
+
const file = fileFromReadInput(input);
|
|
81
|
+
if (file === undefined)
|
|
82
|
+
return null;
|
|
83
|
+
const range = rangeFromReadOutput(output);
|
|
84
|
+
const slim = range === undefined ? `[Read ${file}]` : `[Read ${file}, lines ${range}]`;
|
|
85
|
+
const savings = countCodePoints(output) - countCodePoints(slim);
|
|
86
|
+
if (savings < config.minSavingsChars)
|
|
87
|
+
return null;
|
|
88
|
+
return { output: slim, savings };
|
|
89
|
+
}
|
|
90
|
+
// END_BLOCK_SLIM
|
|
91
|
+
//# sourceMappingURL=read-slim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-slim.js","sourceRoot":"","sources":["../../../src/plugins/tool-history-compaction/read-slim.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Knowledge-tool substrings: results that stay relevant for the whole session. */
|
|
2
|
+
export declare const DEFAULT_RETAIN_TOOLS: readonly string[];
|
|
3
|
+
export type RetainTools = readonly string[];
|
|
4
|
+
/**
|
|
5
|
+
* Whether a tool name matches any retain substring, case-insensitively.
|
|
6
|
+
* @param tool - tool name from a message part.
|
|
7
|
+
* @param retainTools - configured retain substrings.
|
|
8
|
+
* @returns true when the tool output must never be compacted.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isRetainedTool(tool: string | undefined, retainTools: RetainTools): boolean;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// FILE: src/plugins/tool-history-compaction/retention.ts
|
|
2
|
+
// VERSION: 0.1.0
|
|
3
|
+
// START_MODULE_CONTRACT
|
|
4
|
+
// PURPOSE: Classify tool outputs into knowledge (retained) versus ephemeral (compaction-eligible) by case-insensitive substring matching on the tool name.
|
|
5
|
+
// SCOPE: The pure isRetainedTool predicate; the default retention list is re-exported from the shared lib table.
|
|
6
|
+
// DEPENDS: [src/lib/plugin-toggle-config.ts]
|
|
7
|
+
// LINKS: [M-PLUGIN-TOOL-HISTORY-COMPACTION]
|
|
8
|
+
// ROLE: RUNTIME
|
|
9
|
+
// MAP_MODE: EXPORTS
|
|
10
|
+
// END_MODULE_CONTRACT
|
|
11
|
+
//
|
|
12
|
+
// START_MODULE_MAP
|
|
13
|
+
// DEFAULT_RETAIN_TOOLS - Default knowledge-tool substrings (re-exported from the shared lib table).
|
|
14
|
+
// RetainTools - Readonly array of case-insensitive tool-name substrings.
|
|
15
|
+
// isRetainedTool - Whether a tool name matches any retain substring.
|
|
16
|
+
// END_MODULE_MAP
|
|
17
|
+
//
|
|
18
|
+
// START_CHANGE_SUMMARY
|
|
19
|
+
// LAST_CHANGE: [v0.1.0 - Established the knowledge-versus-ephemeral retention classification; defaults owned by the shared lib table.]
|
|
20
|
+
// END_CHANGE_SUMMARY
|
|
21
|
+
import { DEFAULT_TOOL_HISTORY_COMPACTION_RETAIN_TOOLS } from "../../lib/plugin-toggle-config.js";
|
|
22
|
+
// START_BLOCK_DEFAULTS
|
|
23
|
+
/** Knowledge-tool substrings: results that stay relevant for the whole session. */
|
|
24
|
+
export const DEFAULT_RETAIN_TOOLS = DEFAULT_TOOL_HISTORY_COMPACTION_RETAIN_TOOLS;
|
|
25
|
+
// END_BLOCK_DEFAULTS
|
|
26
|
+
// START_BLOCK_MATCH
|
|
27
|
+
/**
|
|
28
|
+
* Whether a tool name matches any retain substring, case-insensitively.
|
|
29
|
+
* @param tool - tool name from a message part.
|
|
30
|
+
* @param retainTools - configured retain substrings.
|
|
31
|
+
* @returns true when the tool output must never be compacted.
|
|
32
|
+
*/
|
|
33
|
+
export function isRetainedTool(tool, retainTools) {
|
|
34
|
+
if (typeof tool !== "string" || tool.length === 0)
|
|
35
|
+
return false;
|
|
36
|
+
const lower = tool.toLowerCase();
|
|
37
|
+
for (const pattern of retainTools) {
|
|
38
|
+
if (pattern.length > 0 && lower.includes(pattern.toLowerCase())) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
// END_BLOCK_MATCH
|
|
45
|
+
//# sourceMappingURL=retention.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention.js","sourceRoot":"","sources":["../../../src/plugins/tool-history-compaction/retention.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,iBAAiB;AACjB,wBAAwB;AACxB,6JAA6J;AAC7J,mHAAmH;AACnH,+CAA+C;AAC/C,8CAA8C;AAC9C,kBAAkB;AAClB,sBAAsB;AACtB,sBAAsB;AACtB,EAAE;AACF,mBAAmB;AACnB,sGAAsG;AACtG,2EAA2E;AAC3E,uEAAuE;AACvE,iBAAiB;AACjB,EAAE;AACF,uBAAuB;AACvB,yIAAyI;AACzI,qBAAqB;AACrB,OAAO,EAAE,4CAA4C,EAAE,MAAM,mCAAmC,CAAC;AAEjG,uBAAuB;AACvB,mFAAmF;AACnF,MAAM,CAAC,MAAM,oBAAoB,GAAsB,4CAA4C,CAAC;AAIpG,qBAAqB;AAErB,oBAAoB;AACpB;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,IAAwB,EAAE,WAAwB;IAC/E,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAChE,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;QAClC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YAChE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AACD,kBAAkB"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Part } from "@opencode-ai/sdk";
|
|
2
|
+
import type { ToolHistoryCompactionConfig } from "./config.js";
|
|
3
|
+
export interface TransformMessage {
|
|
4
|
+
info: unknown;
|
|
5
|
+
parts: Part[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Deterministically rewrite eligible tool part outputs in place.
|
|
9
|
+
* Model-agnostic: the current model is not needed. Non-destructive to inputs,
|
|
10
|
+
* part structure, and ordering. Idempotent: already-compacted parts are skipped
|
|
11
|
+
* by their markers, so a second pass is a no-op.
|
|
12
|
+
* @param messages - the transform hook's in-memory message list.
|
|
13
|
+
* @param config - resolved compaction config.
|
|
14
|
+
*/
|
|
15
|
+
export declare function compactMessages(messages: TransformMessage[], config: ToolHistoryCompactionConfig): void;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// FILE: src/plugins/tool-history-compaction/transform.ts
|
|
2
|
+
// VERSION: 0.1.0
|
|
3
|
+
// START_MODULE_CONTRACT
|
|
4
|
+
// PURPOSE: Apply tool-history compaction to the in-memory message list the model is about to receive: walk messages newest-first, protect the recent tail, dispatch retained/read/other tools to the right compaction layer, and mutate only completed tool part outputs.
|
|
5
|
+
// SCOPE: Completed-tool-part detection, protected-tail accounting, retention dispatch, read-slim and prune application, and idempotent in-place output rewrites.
|
|
6
|
+
// DEPENDS: [src/plugins/tool-history-compaction/config.ts, src/plugins/tool-history-compaction/retention.ts, src/plugins/tool-history-compaction/prune.ts, src/plugins/tool-history-compaction/read-slim.ts]
|
|
7
|
+
// LINKS: [M-PLUGIN-TOOL-HISTORY-COMPACTION]
|
|
8
|
+
// ROLE: RUNTIME
|
|
9
|
+
// MAP_MODE: EXPORTS
|
|
10
|
+
// END_MODULE_CONTRACT
|
|
11
|
+
//
|
|
12
|
+
// START_MODULE_MAP
|
|
13
|
+
// TransformMessage - One message entry in the transform hook output.
|
|
14
|
+
// compactMessages - Deterministically rewrite eligible tool part outputs in place.
|
|
15
|
+
// END_MODULE_MAP
|
|
16
|
+
//
|
|
17
|
+
// START_CHANGE_SUMMARY
|
|
18
|
+
// LAST_CHANGE: [v0.1.0 - Established the transform core with protected tail, retention dispatch, and idempotence.]
|
|
19
|
+
// END_CHANGE_SUMMARY
|
|
20
|
+
import { pruneOutput } from "./prune.js";
|
|
21
|
+
import { slimReadOutput } from "./read-slim.js";
|
|
22
|
+
import { isRetainedTool } from "./retention.js";
|
|
23
|
+
function isCompletedToolPart(part) {
|
|
24
|
+
return part.type === "tool" && part.state.status === "completed";
|
|
25
|
+
}
|
|
26
|
+
function isCompactedByOpencode(part) {
|
|
27
|
+
const time = part.state.time;
|
|
28
|
+
return (typeof time === "object" && time !== null && "compacted" in time && time.compacted !== undefined);
|
|
29
|
+
}
|
|
30
|
+
function isReadTool(tool) {
|
|
31
|
+
return tool.toLowerCase() === "read";
|
|
32
|
+
}
|
|
33
|
+
// END_BLOCK_GUARDS
|
|
34
|
+
// START_BLOCK_COMPACT
|
|
35
|
+
/**
|
|
36
|
+
* Deterministically rewrite eligible tool part outputs in place.
|
|
37
|
+
* Model-agnostic: the current model is not needed. Non-destructive to inputs,
|
|
38
|
+
* part structure, and ordering. Idempotent: already-compacted parts are skipped
|
|
39
|
+
* by their markers, so a second pass is a no-op.
|
|
40
|
+
* @param messages - the transform hook's in-memory message list.
|
|
41
|
+
* @param config - resolved compaction config.
|
|
42
|
+
*/
|
|
43
|
+
export function compactMessages(messages, config) {
|
|
44
|
+
let remainingProtection = config.protectLastCalls;
|
|
45
|
+
let firstMessage = true;
|
|
46
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
47
|
+
const message = messages[i];
|
|
48
|
+
if (!message)
|
|
49
|
+
continue;
|
|
50
|
+
for (let j = message.parts.length - 1; j >= 0; j--) {
|
|
51
|
+
const part = message.parts[j];
|
|
52
|
+
if (!part || part.type !== "tool")
|
|
53
|
+
continue;
|
|
54
|
+
if (!isCompletedToolPart(part))
|
|
55
|
+
continue;
|
|
56
|
+
if (isCompactedByOpencode(part))
|
|
57
|
+
continue;
|
|
58
|
+
const withinTail = firstMessage || remainingProtection > 0;
|
|
59
|
+
if (withinTail) {
|
|
60
|
+
if (!firstMessage)
|
|
61
|
+
remainingProtection -= 1;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (isRetainedTool(part.tool, config.retainTools))
|
|
65
|
+
continue;
|
|
66
|
+
const output = part.state.output;
|
|
67
|
+
let rewritten;
|
|
68
|
+
if (config.readSlim && isReadTool(part.tool)) {
|
|
69
|
+
const slim = slimReadOutput(part.state.input, output, config);
|
|
70
|
+
if (slim) {
|
|
71
|
+
rewritten = slim.output;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
const pruned = pruneOutput(output, config);
|
|
75
|
+
if (pruned)
|
|
76
|
+
rewritten = pruned.output;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
const pruned = pruneOutput(output, config);
|
|
81
|
+
if (pruned)
|
|
82
|
+
rewritten = pruned.output;
|
|
83
|
+
}
|
|
84
|
+
if (rewritten !== undefined && rewritten !== output) {
|
|
85
|
+
part.state.output = rewritten;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (firstMessage)
|
|
89
|
+
firstMessage = false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// END_BLOCK_COMPACT
|
|
93
|
+
//# sourceMappingURL=transform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform.js","sourceRoot":"","sources":["../../../src/plugins/tool-history-compaction/transform.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@osovv/vv-opencode",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.10",
|
|
4
4
|
"description": "A curated, opinionated set of OpenCode plugins for spec-first, review-driven, safer agentic development.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -73,6 +73,10 @@
|
|
|
73
73
|
"./plugins/web-tools": {
|
|
74
74
|
"types": "./dist/plugins/web-tools/index.d.ts",
|
|
75
75
|
"import": "./dist/plugins/web-tools/index.js"
|
|
76
|
+
},
|
|
77
|
+
"./plugins/tool-history-compaction": {
|
|
78
|
+
"types": "./dist/plugins/tool-history-compaction/index.d.ts",
|
|
79
|
+
"import": "./dist/plugins/tool-history-compaction/index.js"
|
|
76
80
|
}
|
|
77
81
|
},
|
|
78
82
|
"scripts": {
|
package/schemas/vvoc/v3.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://cdn.jsdelivr.net/npm/@osovv/vv-opencode@1.2.
|
|
3
|
+
"$id": "https://cdn.jsdelivr.net/npm/@osovv/vv-opencode@1.2.10/schemas/vvoc/v3.json",
|
|
4
4
|
"title": "vvoc config",
|
|
5
5
|
"description": "Canonical vvoc configuration document.",
|
|
6
6
|
"type": "object",
|
|
@@ -162,6 +162,20 @@
|
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"type": "object",
|
|
168
|
+
"additionalProperties": false,
|
|
169
|
+
"properties": {
|
|
170
|
+
"enabled": { "type": "boolean" },
|
|
171
|
+
"protectLastCalls": { "type": "integer", "minimum": 0 },
|
|
172
|
+
"minSavingsChars": { "type": "integer", "minimum": 0 },
|
|
173
|
+
"outputMaxChars": { "type": "integer", "minimum": 0 },
|
|
174
|
+
"headChars": { "type": "integer", "minimum": 0 },
|
|
175
|
+
"tailChars": { "type": "integer", "minimum": 0 },
|
|
176
|
+
"readSlim": { "type": "boolean" },
|
|
177
|
+
"retainTools": { "type": "array", "items": { "type": "string", "minLength": 1 } }
|
|
178
|
+
}
|
|
165
179
|
}
|
|
166
180
|
]
|
|
167
181
|
}
|