@osovv/vv-opencode 1.2.7 → 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 +29 -0
- package/README.md +63 -3
- package/dist/commands/patch-provider.js +2 -0
- package/dist/commands/patch-provider.js.map +1 -1
- package/dist/commands/plugin-list.js +8 -3
- package/dist/commands/plugin-list.js.map +1 -1
- package/dist/commands/plugin-toggle.js +8 -1
- package/dist/commands/plugin-toggle.js.map +1 -1
- 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 +44 -2
- package/dist/lib/plugin-toggle-config.js +132 -11
- package/dist/lib/plugin-toggle-config.js.map +1 -1
- package/dist/lib/vvoc-config.d.ts +80 -2
- package/dist/lib/vvoc-config.js +62 -1
- package/dist/lib/vvoc-config.js.map +1 -1
- package/dist/plugins/hashline-edit/diff-summary.d.ts +7 -0
- package/dist/plugins/hashline-edit/diff-summary.js +79 -0
- package/dist/plugins/hashline-edit/diff-summary.js.map +1 -0
- package/dist/plugins/hashline-edit/edit-operation-primitives.js +22 -3
- package/dist/plugins/hashline-edit/edit-operation-primitives.js.map +1 -1
- package/dist/plugins/hashline-edit/index.js +315 -76
- package/dist/plugins/hashline-edit/index.js.map +1 -1
- package/dist/plugins/hashline-edit/normalize-edits.js +29 -25
- package/dist/plugins/hashline-edit/normalize-edits.js.map +1 -1
- package/dist/plugins/hashline-edit/replace-engine.d.ts +24 -0
- package/dist/plugins/hashline-edit/replace-engine.js +246 -0
- package/dist/plugins/hashline-edit/replace-engine.js.map +1 -0
- package/dist/plugins/hashline-edit/routing.d.ts +21 -0
- package/dist/plugins/hashline-edit/routing.js +105 -0
- package/dist/plugins/hashline-edit/routing.js.map +1 -0
- package/dist/plugins/hashline-edit/session-state.d.ts +23 -0
- package/dist/plugins/hashline-edit/session-state.js +70 -0
- package/dist/plugins/hashline-edit/session-state.js.map +1 -0
- package/dist/plugins/hashline-edit/str-replace-editor.d.ts +50 -0
- package/dist/plugins/hashline-edit/str-replace-editor.js +285 -0
- package/dist/plugins/hashline-edit/str-replace-editor.js.map +1 -0
- package/dist/plugins/hashline-edit/tool-description.d.ts +2 -1
- package/dist/plugins/hashline-edit/tool-description.js +31 -10
- package/dist/plugins/hashline-edit/tool-description.js.map +1 -1
- package/dist/plugins/hashline-edit/validation.d.ts +1 -0
- package/dist/plugins/hashline-edit/validation.js +13 -3
- package/dist/plugins/hashline-edit/validation.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 +43 -2
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// FILE: src/plugins/hashline-edit/validation.ts
|
|
2
|
-
// VERSION: 0.
|
|
2
|
+
// VERSION: 0.5.0
|
|
3
3
|
// START_MODULE_CONTRACT
|
|
4
4
|
// PURPOSE: Parse and validate hashline references with optional context-anchored hashes against the current file snapshot before edits are applied.
|
|
5
|
-
// SCOPE: Anchor normalization, line reference parsing with optional anchor hash, full-batch validation with anchor-hash verification, and mismatch diagnostics for current hashline anchors.
|
|
5
|
+
// SCOPE: Anchor normalization, line reference parsing with optional anchor hash, mandatory three-part edit reference enforcement, full-batch validation with anchor-hash verification, and mismatch diagnostics for current hashline anchors.
|
|
6
6
|
// DEPENDS: [src/plugins/hashline-edit/constants.ts, src/plugins/hashline-edit/hash-computation.ts]
|
|
7
7
|
// LINKS: [M-PLUGIN-HASHLINE-EDIT]
|
|
8
8
|
// ROLE: RUNTIME
|
|
@@ -13,13 +13,14 @@
|
|
|
13
13
|
// LineRef - Parsed `{ line, hash, anchorHash? }` structure for a normalized hashline anchor.
|
|
14
14
|
// normalizeLineRef - Strip copied prefixes and inline content from a raw anchor string.
|
|
15
15
|
// parseLineRef - Parse a normalized hashline anchor and fail loudly on malformed references.
|
|
16
|
+
// requireThreePartRef - Parse an edit anchor and reject two-part references missing the anchor hash.
|
|
16
17
|
// validateLineRef - Validate a single anchor against the current file lines including context-anchored hash.
|
|
17
18
|
// validateLineRefs - Validate a batch of anchors and aggregate mismatches.
|
|
18
19
|
// HashlineMismatchError - Rich mismatch error that includes updated surrounding anchors.
|
|
19
20
|
// END_MODULE_MAP
|
|
20
21
|
//
|
|
21
22
|
// START_CHANGE_SUMMARY
|
|
22
|
-
// LAST_CHANGE: [v0.
|
|
23
|
+
// LAST_CHANGE: [v0.5.0 - Added requireThreePartRef so edit anchors must carry the full line#hash#anchor triple.]
|
|
23
24
|
// END_CHANGE_SUMMARY
|
|
24
25
|
import { HASHLINE_REF_PATTERN } from "./constants.js";
|
|
25
26
|
import { computeAnchorHash, computeLineHash } from "./hash-computation.js";
|
|
@@ -77,6 +78,15 @@ export function parseLineRef(ref) {
|
|
|
77
78
|
}
|
|
78
79
|
throw new Error(`Invalid line reference format: "${ref}". Expected format: "{line_number}#{hash_id}" or "{line_number}#{hash_id}#{anchor_hash}"`);
|
|
79
80
|
}
|
|
81
|
+
export function requireThreePartRef(ref, context) {
|
|
82
|
+
const parsed = parseLineRefWithHint(ref, []);
|
|
83
|
+
if (!parsed.anchorHash) {
|
|
84
|
+
throw new Error(`${context}: anchor "${ref}" is missing the anchor hash. Use the full three-part ` +
|
|
85
|
+
'"{line_number}#{hash_id}#{anchor_hash}" reference copied exactly from the latest read output. ' +
|
|
86
|
+
"Two-part references are no longer accepted for edits.");
|
|
87
|
+
}
|
|
88
|
+
return parsed;
|
|
89
|
+
}
|
|
80
90
|
export class HashlineMismatchError extends Error {
|
|
81
91
|
mismatches;
|
|
82
92
|
fileLines;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/plugins/hashline-edit/validation.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,iBAAiB;AACjB,wBAAwB;AACxB,sJAAsJ;AACtJ
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/plugins/hashline-edit/validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type RetainTools } from "./retention.js";
|
|
2
|
+
import { DEFAULT_TOOL_HISTORY_COMPACTION_ENTRY } from "../../lib/plugin-toggle-config.js";
|
|
3
|
+
export interface ToolHistoryCompactionConfig {
|
|
4
|
+
/** Number of most recent completed tool calls (plus the last assistant message) never rewritten. */
|
|
5
|
+
protectLastCalls: number;
|
|
6
|
+
/** Minimum character savings for a rewrite to be applied; smaller rewrites are skipped. */
|
|
7
|
+
minSavingsChars: number;
|
|
8
|
+
/** Prune when output text exceeds this many code points; 0 disables pruning. */
|
|
9
|
+
outputMaxChars: number;
|
|
10
|
+
/** Leading code points retained when pruning. */
|
|
11
|
+
headChars: number;
|
|
12
|
+
/** Trailing code points retained when pruning. */
|
|
13
|
+
tailChars: number;
|
|
14
|
+
/** Replace old read outputs with a [Read <file>] header instead of pruning them. */
|
|
15
|
+
readSlim: boolean;
|
|
16
|
+
/** Tool names (case-insensitive substrings) whose outputs are never compacted. */
|
|
17
|
+
retainTools: RetainTools;
|
|
18
|
+
}
|
|
19
|
+
export interface ResolvedToolHistoryCompactionEntry {
|
|
20
|
+
enabled: boolean;
|
|
21
|
+
config: ToolHistoryCompactionConfig;
|
|
22
|
+
}
|
|
23
|
+
export { DEFAULT_TOOL_HISTORY_COMPACTION_ENTRY };
|
|
24
|
+
/** Resolve a partial config record against defaults, failing loudly on unknown keys or invalid values. */
|
|
25
|
+
export declare function resolveConfig(raw: unknown): ToolHistoryCompactionConfig;
|
|
26
|
+
/** Parse the plugins["tool-history-compaction"] boolean-or-object union. */
|
|
27
|
+
export declare function parseToolHistoryCompactionEntry(raw: unknown): ResolvedToolHistoryCompactionEntry;
|
|
28
|
+
export declare const DEFAULT_TOOL_HISTORY_COMPACTION: ToolHistoryCompactionConfig;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// FILE: src/plugins/tool-history-compaction/config.ts
|
|
2
|
+
// VERSION: 0.1.0
|
|
3
|
+
// START_MODULE_CONTRACT
|
|
4
|
+
// PURPOSE: Define strict tool-history-compaction configuration parsing, validation, and defaults.
|
|
5
|
+
// SCOPE: Config vocabulary, fail-loud validation of budgets and invariants, boolean-or-object plugin entry parsing, and the default materializable entry for vvoc sync.
|
|
6
|
+
// DEPENDS: [src/plugins/tool-history-compaction/retention.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
|
+
// ToolHistoryCompactionConfig - Resolved immutable compaction settings.
|
|
14
|
+
// ResolvedToolHistoryCompactionEntry - Enabled flag plus resolved config from an entry.
|
|
15
|
+
// DEFAULT_TOOL_HISTORY_COMPACTION_ENTRY - Default vvoc materializable plugin entry.
|
|
16
|
+
// DEFAULT_TOOL_HISTORY_COMPACTION - Resolved default config.
|
|
17
|
+
// resolveConfig - Strictly resolve a partial config record against defaults.
|
|
18
|
+
// parseToolHistoryCompactionEntry - Strictly parse the plugins entry into enabled flag and config.
|
|
19
|
+
// END_MODULE_MAP
|
|
20
|
+
//
|
|
21
|
+
// START_CHANGE_SUMMARY
|
|
22
|
+
// LAST_CHANGE: [v0.1.0 - Established config parsing with DSH-style head/tail budgets, retention list, protected tail, and min-savings guard.]
|
|
23
|
+
// END_CHANGE_SUMMARY
|
|
24
|
+
import { PRUNE_MARKER } from "./prune.js";
|
|
25
|
+
import { DEFAULT_TOOL_HISTORY_COMPACTION_ENTRY } from "../../lib/plugin-toggle-config.js";
|
|
26
|
+
// END_BLOCK_VOCABULARY
|
|
27
|
+
// START_BLOCK_DEFAULTS
|
|
28
|
+
export { DEFAULT_TOOL_HISTORY_COMPACTION_ENTRY };
|
|
29
|
+
// END_BLOCK_DEFAULTS
|
|
30
|
+
// START_BLOCK_PARSE
|
|
31
|
+
function isRecord(value) {
|
|
32
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
33
|
+
}
|
|
34
|
+
const CONFIG_KEYS = new Set([
|
|
35
|
+
"protectLastCalls",
|
|
36
|
+
"minSavingsChars",
|
|
37
|
+
"outputMaxChars",
|
|
38
|
+
"headChars",
|
|
39
|
+
"tailChars",
|
|
40
|
+
"readSlim",
|
|
41
|
+
"retainTools",
|
|
42
|
+
]);
|
|
43
|
+
function parseNonNegativeInt(raw, key) {
|
|
44
|
+
if (typeof raw !== "number" || !Number.isInteger(raw) || raw < 0) {
|
|
45
|
+
throw new Error(`tool-history-compaction: ${key} must be a non-negative integer; got ${JSON.stringify(raw)}`);
|
|
46
|
+
}
|
|
47
|
+
return raw;
|
|
48
|
+
}
|
|
49
|
+
function parseRetainTools(raw) {
|
|
50
|
+
if (!Array.isArray(raw)) {
|
|
51
|
+
throw new Error("tool-history-compaction: retainTools must be an array of non-empty strings");
|
|
52
|
+
}
|
|
53
|
+
for (const entry of raw) {
|
|
54
|
+
if (typeof entry !== "string" || entry.trim().length === 0) {
|
|
55
|
+
throw new Error("tool-history-compaction: retainTools entries must be non-empty strings");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return [...raw];
|
|
59
|
+
}
|
|
60
|
+
function assertBudgetsFit(config) {
|
|
61
|
+
if (config.outputMaxChars > 0) {
|
|
62
|
+
const required = config.headChars + config.tailChars + PRUNE_MARKER.length;
|
|
63
|
+
if (required > config.outputMaxChars) {
|
|
64
|
+
throw new Error(`tool-history-compaction: headChars + tailChars + marker (${required}) must fit within outputMaxChars (${config.outputMaxChars})`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Resolve a partial config record against defaults, failing loudly on unknown keys or invalid values. */
|
|
69
|
+
export function resolveConfig(raw) {
|
|
70
|
+
if (raw === undefined || raw === null) {
|
|
71
|
+
return { ...DEFAULT_TOOL_HISTORY_COMPACTION };
|
|
72
|
+
}
|
|
73
|
+
if (!isRecord(raw)) {
|
|
74
|
+
throw new Error("tool-history-compaction: config must be an object");
|
|
75
|
+
}
|
|
76
|
+
for (const key of Object.keys(raw)) {
|
|
77
|
+
if (!CONFIG_KEYS.has(key)) {
|
|
78
|
+
throw new Error(`tool-history-compaction: unknown config key "${key}"`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const readSlim = raw.readSlim === undefined ? DEFAULT_TOOL_HISTORY_COMPACTION.readSlim : raw.readSlim;
|
|
82
|
+
if (typeof readSlim !== "boolean") {
|
|
83
|
+
throw new Error(`tool-history-compaction: readSlim must be a boolean; got ${JSON.stringify(raw.readSlim)}`);
|
|
84
|
+
}
|
|
85
|
+
const resolved = {
|
|
86
|
+
protectLastCalls: raw.protectLastCalls === undefined
|
|
87
|
+
? DEFAULT_TOOL_HISTORY_COMPACTION.protectLastCalls
|
|
88
|
+
: parseNonNegativeInt(raw.protectLastCalls, "protectLastCalls"),
|
|
89
|
+
minSavingsChars: raw.minSavingsChars === undefined
|
|
90
|
+
? DEFAULT_TOOL_HISTORY_COMPACTION.minSavingsChars
|
|
91
|
+
: parseNonNegativeInt(raw.minSavingsChars, "minSavingsChars"),
|
|
92
|
+
outputMaxChars: raw.outputMaxChars === undefined
|
|
93
|
+
? DEFAULT_TOOL_HISTORY_COMPACTION.outputMaxChars
|
|
94
|
+
: parseNonNegativeInt(raw.outputMaxChars, "outputMaxChars"),
|
|
95
|
+
headChars: raw.headChars === undefined
|
|
96
|
+
? DEFAULT_TOOL_HISTORY_COMPACTION.headChars
|
|
97
|
+
: parseNonNegativeInt(raw.headChars, "headChars"),
|
|
98
|
+
tailChars: raw.tailChars === undefined
|
|
99
|
+
? DEFAULT_TOOL_HISTORY_COMPACTION.tailChars
|
|
100
|
+
: parseNonNegativeInt(raw.tailChars, "tailChars"),
|
|
101
|
+
readSlim,
|
|
102
|
+
retainTools: raw.retainTools === undefined
|
|
103
|
+
? [...DEFAULT_TOOL_HISTORY_COMPACTION.retainTools]
|
|
104
|
+
: parseRetainTools(raw.retainTools),
|
|
105
|
+
};
|
|
106
|
+
assertBudgetsFit(resolved);
|
|
107
|
+
return resolved;
|
|
108
|
+
}
|
|
109
|
+
/** Parse the plugins["tool-history-compaction"] boolean-or-object union. */
|
|
110
|
+
export function parseToolHistoryCompactionEntry(raw) {
|
|
111
|
+
if (raw === undefined || raw === null) {
|
|
112
|
+
return { enabled: true, config: { ...DEFAULT_TOOL_HISTORY_COMPACTION } };
|
|
113
|
+
}
|
|
114
|
+
if (typeof raw === "boolean") {
|
|
115
|
+
return { enabled: raw, config: { ...DEFAULT_TOOL_HISTORY_COMPACTION } };
|
|
116
|
+
}
|
|
117
|
+
if (!isRecord(raw)) {
|
|
118
|
+
throw new Error('tool-history-compaction: plugins["tool-history-compaction"] must be a boolean or an object');
|
|
119
|
+
}
|
|
120
|
+
const enabled = raw.enabled === undefined ? true : raw.enabled;
|
|
121
|
+
if (typeof enabled !== "boolean") {
|
|
122
|
+
throw new Error("tool-history-compaction: enabled must be a boolean");
|
|
123
|
+
}
|
|
124
|
+
const { enabled: _ignored, ...configRaw } = raw;
|
|
125
|
+
return { enabled, config: resolveConfig(configRaw) };
|
|
126
|
+
}
|
|
127
|
+
// END_BLOCK_PARSE
|
|
128
|
+
// START_BLOCK_DEFAULT_RESOLVE
|
|
129
|
+
// Computed after resolveConfig so module-level initialization stays free of TDZ hazards.
|
|
130
|
+
const defaultConfig = Object.fromEntries(Object.entries(DEFAULT_TOOL_HISTORY_COMPACTION_ENTRY).filter(([key]) => key !== "enabled"));
|
|
131
|
+
export const DEFAULT_TOOL_HISTORY_COMPACTION = resolveConfig(defaultConfig);
|
|
132
|
+
// END_BLOCK_DEFAULT_RESOLVE
|
|
133
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/plugins/tool-history-compaction/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// FILE: src/plugins/tool-history-compaction/index.ts
|
|
2
|
+
// VERSION: 0.1.0
|
|
3
|
+
// START_MODULE_CONTRACT
|
|
4
|
+
// PURPOSE: Register the tool-history-compaction plugin: load vvoc config, gate on the enabled toggle, and rewrite only the in-memory message copy the model is about to receive via experimental.chat.messages.transform.
|
|
5
|
+
// SCOPE: Plugin entry point, config loading, transform hook registration, and disabled no-op.
|
|
6
|
+
// DEPENDS: [@opencode-ai/plugin, src/lib/config-layers.ts, src/plugins/tool-history-compaction/config.ts, src/plugins/tool-history-compaction/transform.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
|
+
// ToolHistoryCompactionPlugin - OpenCode plugin that compacts old tool outputs in the replay without touching storage or inputs.
|
|
14
|
+
// END_MODULE_MAP
|
|
15
|
+
//
|
|
16
|
+
// START_CHANGE_SUMMARY
|
|
17
|
+
// LAST_CHANGE: [v0.1.0 - Established the transform-only compaction plugin with retention classification and DSH-style pruning.]
|
|
18
|
+
// END_CHANGE_SUMMARY
|
|
19
|
+
import { loadVvocConfig } from "../../lib/config-layers.js";
|
|
20
|
+
import { parseToolHistoryCompactionEntry } from "./config.js";
|
|
21
|
+
import { compactMessages } from "./transform.js";
|
|
22
|
+
// START_BLOCK_PLUGIN
|
|
23
|
+
export const ToolHistoryCompactionPlugin = async ({ directory }) => {
|
|
24
|
+
const vvoc = await loadVvocConfig({ cwd: directory });
|
|
25
|
+
const entry = parseToolHistoryCompactionEntry(vvoc.config.plugins?.["tool-history-compaction"]);
|
|
26
|
+
if (!entry.enabled)
|
|
27
|
+
return {};
|
|
28
|
+
return {
|
|
29
|
+
"experimental.chat.messages.transform": async (_input, output) => {
|
|
30
|
+
compactMessages(output.messages, entry.config);
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
// END_BLOCK_PLUGIN
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/tool-history-compaction/index.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,iBAAiB;AACjB,wBAAwB;AACxB,4NAA4N;AAC5N,gGAAgG;AAChG,8JAA8J;AAC9J,8CAA8C;AAC9C,kBAAkB;AAClB,sBAAsB;AACtB,sBAAsB;AACtB,EAAE;AACF,mBAAmB;AACnB,mIAAmI;AACnI,iBAAiB;AACjB,EAAE;AACF,uBAAuB;AACvB,kIAAkI;AAClI,qBAAqB;AAGrB,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,+BAA+B,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,qBAAqB;AACrB,MAAM,CAAC,MAAM,2BAA2B,GAAW,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE;IACzE,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,+BAA+B,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,yBAAyB,CAAC,CAAC,CAAC;IAChG,IAAI,CAAC,KAAK,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAE9B,OAAO;QACL,sCAAsC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YAC/D,eAAe,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACjD,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AACF,mBAAmB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ToolHistoryCompactionConfig } from "./config.js";
|
|
2
|
+
/** Fixed marker substituted for every pruned output middle. */
|
|
3
|
+
export declare const PRUNE_MARKER = "[... tool output pruned ...]";
|
|
4
|
+
/** Count Unicode code points without splitting surrogate pairs. */
|
|
5
|
+
export declare function countCodePoints(text: string): number;
|
|
6
|
+
/** Slice text by code points, never splitting a surrogate pair. */
|
|
7
|
+
export declare function codePointSlice(text: string, start: number, end: number): string;
|
|
8
|
+
/** Whether text already carries the prune marker (previous compaction pass). */
|
|
9
|
+
export declare function alreadyCompacted(text: string): boolean;
|
|
10
|
+
export interface PruneResult {
|
|
11
|
+
output: string;
|
|
12
|
+
savings: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Prune an over-budget output to head + marker + tail.
|
|
16
|
+
* Returns null when the output is ineligible: non-string, pruning disabled,
|
|
17
|
+
* under threshold, already compacted, or savings below minSavingsChars.
|
|
18
|
+
* @param text - tool output text.
|
|
19
|
+
* @param config - resolved compaction config.
|
|
20
|
+
* @returns pruned form or null.
|
|
21
|
+
*/
|
|
22
|
+
export declare function pruneOutput(text: string, config: ToolHistoryCompactionConfig): PruneResult | null;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// FILE: src/plugins/tool-history-compaction/prune.ts
|
|
2
|
+
// VERSION: 0.1.0
|
|
3
|
+
// START_MODULE_CONTRACT
|
|
4
|
+
// PURPOSE: Deterministic head/marker/tail pruning of over-budget tool outputs with code-point-safe slicing, min-savings guard, and marker-based idempotence.
|
|
5
|
+
// SCOPE: Code-point counting and slicing, the fixed prune marker, the prune decision function, and already-compacted 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
|
+
// PRUNE_MARKER - Fixed marker substituted for every pruned output middle.
|
|
14
|
+
// countCodePoints - Unicode code-point count without splitting surrogate pairs.
|
|
15
|
+
// codePointSlice - Slice text by code points.
|
|
16
|
+
// pruneOutput - Return the pruned form when eligible, otherwise null.
|
|
17
|
+
// alreadyCompacted - Whether text already carries the prune marker.
|
|
18
|
+
// PruneResult - Pruned output plus measured savings.
|
|
19
|
+
// END_MODULE_MAP
|
|
20
|
+
//
|
|
21
|
+
// START_CHANGE_SUMMARY
|
|
22
|
+
// LAST_CHANGE: [v0.1.0 - Established the DSH-style head/marker/tail prune engine.]
|
|
23
|
+
// END_CHANGE_SUMMARY
|
|
24
|
+
// START_BLOCK_CONSTANTS
|
|
25
|
+
/** Fixed marker substituted for every pruned output middle. */
|
|
26
|
+
export const PRUNE_MARKER = "[... tool output pruned ...]";
|
|
27
|
+
// END_BLOCK_CONSTANTS
|
|
28
|
+
// START_BLOCK_MEASURE
|
|
29
|
+
/** Count Unicode code points without splitting surrogate pairs. */
|
|
30
|
+
export function countCodePoints(text) {
|
|
31
|
+
return Array.from(text).length;
|
|
32
|
+
}
|
|
33
|
+
/** Slice text by code points, never splitting a surrogate pair. */
|
|
34
|
+
export function codePointSlice(text, start, end) {
|
|
35
|
+
return Array.from(text).slice(start, end).join("");
|
|
36
|
+
}
|
|
37
|
+
// END_BLOCK_MEASURE
|
|
38
|
+
// START_BLOCK_DETECT
|
|
39
|
+
/** Whether text already carries the prune marker (previous compaction pass). */
|
|
40
|
+
export function alreadyCompacted(text) {
|
|
41
|
+
return typeof text === "string" && text.includes(PRUNE_MARKER);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Prune an over-budget output to head + marker + tail.
|
|
45
|
+
* Returns null when the output is ineligible: non-string, pruning disabled,
|
|
46
|
+
* under threshold, already compacted, or savings below minSavingsChars.
|
|
47
|
+
* @param text - tool output text.
|
|
48
|
+
* @param config - resolved compaction config.
|
|
49
|
+
* @returns pruned form or null.
|
|
50
|
+
*/
|
|
51
|
+
export function pruneOutput(text, config) {
|
|
52
|
+
if (typeof text !== "string" || text.length === 0)
|
|
53
|
+
return null;
|
|
54
|
+
if (config.outputMaxChars <= 0)
|
|
55
|
+
return null;
|
|
56
|
+
if (alreadyCompacted(text))
|
|
57
|
+
return null;
|
|
58
|
+
const length = countCodePoints(text);
|
|
59
|
+
if (length <= config.outputMaxChars)
|
|
60
|
+
return null;
|
|
61
|
+
const head = codePointSlice(text, 0, config.headChars);
|
|
62
|
+
const tail = codePointSlice(text, length - config.tailChars, length);
|
|
63
|
+
const output = head + PRUNE_MARKER + tail;
|
|
64
|
+
const savings = length - countCodePoints(output);
|
|
65
|
+
if (savings < config.minSavingsChars)
|
|
66
|
+
return null;
|
|
67
|
+
return { output, savings };
|
|
68
|
+
}
|
|
69
|
+
// END_BLOCK_PRUNE
|
|
70
|
+
//# sourceMappingURL=prune.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prune.js","sourceRoot":"","sources":["../../../src/plugins/tool-history-compaction/prune.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,iBAAiB;AACjB,wBAAwB;AACxB,+JAA+J;AAC/J,kIAAkI;AAClI,6DAA6D;AAC7D,8CAA8C;AAC9C,kBAAkB;AAClB,sBAAsB;AACtB,sBAAsB;AACtB,EAAE;AACF,mBAAmB;AACnB,4EAA4E;AAC5E,kFAAkF;AAClF,gDAAgD;AAChD,wEAAwE;AACxE,sEAAsE;AACtE,uDAAuD;AACvD,iBAAiB;AACjB,EAAE;AACF,uBAAuB;AACvB,qFAAqF;AACrF,qBAAqB;AAIrB,wBAAwB;AACxB,+DAA+D;AAC/D,MAAM,CAAC,MAAM,YAAY,GAAG,8BAA8B,CAAC;AAC3D,sBAAsB;AAEtB,sBAAsB;AACtB,mEAAmE;AACnE,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;AACjC,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,KAAa,EAAE,GAAW;IACrE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACrD,CAAC;AACD,oBAAoB;AAEpB,qBAAqB;AACrB,gFAAgF;AAChF,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;AACjE,CAAC;AASD;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,MAAmC;IAC3E,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/D,IAAI,MAAM,CAAC,cAAc,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5C,IAAI,gBAAgB,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAExC,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,MAAM,IAAI,MAAM,CAAC,cAAc;QAAE,OAAO,IAAI,CAAC;IAEjD,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IACvD,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACrE,MAAM,MAAM,GAAG,IAAI,GAAG,YAAY,GAAG,IAAI,CAAC;IAC1C,MAAM,OAAO,GAAG,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IACjD,IAAI,OAAO,GAAG,MAAM,CAAC,eAAe;QAAE,OAAO,IAAI,CAAC;IAElD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC;AACD,kBAAkB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ToolHistoryCompactionConfig } from "./config.js";
|
|
2
|
+
export interface ReadInputLike {
|
|
3
|
+
filePath?: unknown;
|
|
4
|
+
path?: unknown;
|
|
5
|
+
file?: unknown;
|
|
6
|
+
}
|
|
7
|
+
/** Recover the file path from read input aliases; unknown values yield undefined. */
|
|
8
|
+
export declare function fileFromReadInput(input: ReadInputLike | undefined): string | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Recover the covered line range ("first-last") from a line-numbered output.
|
|
11
|
+
* Returns undefined when the output is not deterministically line-numbered.
|
|
12
|
+
*/
|
|
13
|
+
export declare function rangeFromReadOutput(output: string | undefined): string | undefined;
|
|
14
|
+
export interface SlimReadResult {
|
|
15
|
+
output: string;
|
|
16
|
+
savings: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Collapse an old read output to [Read <file>, lines X-Y] when the file is
|
|
20
|
+
* recoverable and the savings clear the min-savings guard. Returns null when
|
|
21
|
+
* not applicable; the caller falls back to output pruning (never fabricates).
|
|
22
|
+
* @param input - part.state.input.
|
|
23
|
+
* @param output - part.state.output.
|
|
24
|
+
* @param config - resolved compaction config.
|
|
25
|
+
* @returns slim form or null.
|
|
26
|
+
*/
|
|
27
|
+
export declare function slimReadOutput(input: unknown, output: unknown, config: ToolHistoryCompactionConfig): SlimReadResult | null;
|
|
@@ -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;
|