greprag 5.47.0 → 5.49.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/dist/commands/assistant-reminder.d.ts +9 -0
- package/dist/commands/assistant-reminder.js +20 -0
- package/dist/commands/assistant-reminder.js.map +1 -0
- package/dist/commands/checkpoint-reminder.d.ts +14 -0
- package/dist/commands/checkpoint-reminder.js +50 -0
- package/dist/commands/checkpoint-reminder.js.map +1 -0
- package/dist/commands/crush.d.ts +9 -0
- package/dist/commands/crush.js +39 -0
- package/dist/commands/crush.js.map +1 -1
- package/dist/commands/frontdesk-reminder.d.ts +23 -0
- package/dist/commands/frontdesk-reminder.js +40 -0
- package/dist/commands/frontdesk-reminder.js.map +1 -0
- package/dist/commands/inbox-watch-supervisor.d.ts +25 -0
- package/dist/commands/inbox-watch-supervisor.js +112 -5
- package/dist/commands/inbox-watch-supervisor.js.map +1 -1
- package/dist/commands/init.js +47 -38
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/memory-reflex.d.ts +115 -0
- package/dist/commands/memory-reflex.js +243 -0
- package/dist/commands/memory-reflex.js.map +1 -0
- package/dist/commands/opencode-relay.d.ts +19 -4
- package/dist/commands/opencode-relay.js +56 -5
- package/dist/commands/opencode-relay.js.map +1 -1
- package/dist/commands/reminder-registry.d.ts +6 -2
- package/dist/commands/reminder-registry.js +20 -3
- package/dist/commands/reminder-registry.js.map +1 -1
- package/dist/commands/reminder-types.d.ts +27 -0
- package/dist/commands/setup-reminder.d.ts +9 -0
- package/dist/commands/setup-reminder.js +20 -0
- package/dist/commands/setup-reminder.js.map +1 -0
- package/dist/commands/watcher-registry.js +4 -2
- package/dist/commands/watcher-registry.js.map +1 -1
- package/dist/hook.js +329 -109
- package/dist/hook.js.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/opencode-plugin-crush.d.ts +88 -0
- package/dist/opencode-plugin-crush.js +193 -0
- package/dist/opencode-plugin-crush.js.map +1 -0
- package/dist/opencode-plugin.bundle.js +2132 -0
- package/dist/opencode-plugin.d.ts +6 -0
- package/dist/opencode-plugin.js +184 -51
- package/dist/opencode-plugin.js.map +1 -1
- package/dist/worktree-state.js +5 -5
- package/dist/worktree-state.js.map +1 -1
- package/package.json +3 -2
- package/scripts/bundle-opencode-plugin.mjs +54 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// adr: adr/opencode-context-compressor.md
|
|
3
|
+
/** opencode-plugin-crush.ts — the inline outbound-context CRUSHER for opencode.
|
|
4
|
+
*
|
|
5
|
+
* WHY THIS EXISTS — Claude Code's harness can only REWRITE a bash command to
|
|
6
|
+
* pipe its output through `greprag crush` (the pipe-wrap PreToolUse hook); it
|
|
7
|
+
* cannot replace context already sitting in the outbound message array. opencode
|
|
8
|
+
* CAN: `experimental.chat.messages.transform` fires before every LLM call with
|
|
9
|
+
* the full outbound `output.messages` in hand. This module is the engine the
|
|
10
|
+
* plugin's transform hook runs — it walks the message parts and crushes the
|
|
11
|
+
* bulky ones IN-PROCESS (no per-part subprocess), reversibly, reusing greprag's
|
|
12
|
+
* existing crush engine.
|
|
13
|
+
*
|
|
14
|
+
* HARD CONSTRAINTS this design serves:
|
|
15
|
+
* - DEP-FREE. The deployed plugin loads its sidecars by absolute path from
|
|
16
|
+
* ~/.greprag/ under Bun, where neither relative `require('./proc')` nor
|
|
17
|
+
* npm deps like `sql.js` resolve. So this file imports ONLY the pure crush
|
|
18
|
+
* engine (`./crush`, zero deps, deployed as ~/.greprag/crush/) — nothing
|
|
19
|
+
* else. The CCR store (sql.js) and the spawn wrapper (proc) are NOT imported
|
|
20
|
+
* here; CCR persistence is INJECTED via the `stash` callback so the sidecar
|
|
21
|
+
* stays loadable inside the plugin.
|
|
22
|
+
* - IN-PROCESS transform. The crush compression (CPU-bound, runs for every
|
|
23
|
+
* crushable part of every message on every LLM call) never spawns a process.
|
|
24
|
+
* Only the rare PERSISTENCE of an original is delegated (the plugin's stash
|
|
25
|
+
* fires `greprag ccr put` once per part actually crushed — off the hot path).
|
|
26
|
+
*
|
|
27
|
+
* INVARIANTS (mirror adr/crush-engine.md, enforced per-field here):
|
|
28
|
+
* - Reversible: a crushed field becomes `<crushed>\n<<ccr:HASH>>`; the stash
|
|
29
|
+
* callback persists the byte-exact original so `greprag retrieve <hash>`
|
|
30
|
+
* recovers it. HASH is sha256(original)[:16] — the SAME value CcrStore.put
|
|
31
|
+
* computes, so the plugin can compute it in-process and the CLI store agrees.
|
|
32
|
+
* - token-validate-or-revert (Headroom): a field is replaced ONLY when the
|
|
33
|
+
* crushed + marker text costs strictly fewer estimated tokens; else the
|
|
34
|
+
* original is kept untouched.
|
|
35
|
+
* - Idempotent: a field already carrying a `<<ccr:` marker is never re-crushed.
|
|
36
|
+
* - Non-destructive: mutates ONLY the message objects it is handed (the
|
|
37
|
+
* request-scoped `output.messages` copy). It never touches opencode's
|
|
38
|
+
* persisted session history — that contract is the caller's to honor by
|
|
39
|
+
* passing the request-scoped array.
|
|
40
|
+
* - Defensive: every part is processed under try/catch — a crush failure is
|
|
41
|
+
* swallowed and the part is left verbatim, so a turn is NEVER broken.
|
|
42
|
+
*/
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.DEFAULT_THRESHOLD_BYTES = void 0;
|
|
45
|
+
exports.ccrMarker = ccrMarker;
|
|
46
|
+
exports.classifyContent = classifyContent;
|
|
47
|
+
exports.crushField = crushField;
|
|
48
|
+
exports.crushMessages = crushMessages;
|
|
49
|
+
const crush_1 = require("./crush");
|
|
50
|
+
// ---------- CCR marker (inlined — see header: ccr-store.ts drags sql.js) ------
|
|
51
|
+
/** First 16 hex of sha256 — must match ccr-store.ts CCR_MARKER_HASH_LEN. */
|
|
52
|
+
const CCR_MARKER_HASH_LEN = 16;
|
|
53
|
+
/** `<<ccr:HASH>>` — must match ccr-store.ts ccrMarker(). */
|
|
54
|
+
function ccrMarker(hash) {
|
|
55
|
+
return `<<ccr:${hash.slice(0, CCR_MARKER_HASH_LEN)}>>`;
|
|
56
|
+
}
|
|
57
|
+
/** Already-crushed detector — idempotency guard. */
|
|
58
|
+
const CCR_MARKER_RE = /<<ccr:/;
|
|
59
|
+
/** Fixed length of `\n` + `<<ccr:` + 16-hex + `>>` appended to a crushed field. */
|
|
60
|
+
const FINAL_MARKER_OVERHEAD = 1 + '<<ccr:'.length + CCR_MARKER_HASH_LEN + '>>'.length; // 25
|
|
61
|
+
/** Default byte floor — fields smaller than this pass through untouched. */
|
|
62
|
+
exports.DEFAULT_THRESHOLD_BYTES = 2048;
|
|
63
|
+
// ---------- Content classifier (pure) ----------------------------------------
|
|
64
|
+
/** Pick the crush engine for a raw content string. Output-shape heuristics,
|
|
65
|
+
* since (unlike pipe-wrap) we see the OUTPUT, not the producing command:
|
|
66
|
+
* - leading `{` / `[` → json
|
|
67
|
+
* - majority `file:line:` → search (grep/rg match lines, incl. `-`-context)
|
|
68
|
+
* - else → log (the safe generalist: keeps errors + traces,
|
|
69
|
+
* dedupes spam; a misclassified field just
|
|
70
|
+
* compresses less, never wrongly). */
|
|
71
|
+
function classifyContent(text) {
|
|
72
|
+
const t = text.trimStart();
|
|
73
|
+
const head = t[0];
|
|
74
|
+
if (head === '{' || head === '[')
|
|
75
|
+
return 'json';
|
|
76
|
+
const lines = t.split('\n', 21).map(l => l.trim()).filter(Boolean).slice(0, 20);
|
|
77
|
+
if (lines.length) {
|
|
78
|
+
const matchLike = lines.filter(l => /^.+?[:\-]\d+[:\-]/.test(l)).length;
|
|
79
|
+
if (matchLike / lines.length >= 0.6)
|
|
80
|
+
return 'search';
|
|
81
|
+
}
|
|
82
|
+
return 'log';
|
|
83
|
+
}
|
|
84
|
+
function runEngine(type, content) {
|
|
85
|
+
switch (type) {
|
|
86
|
+
case 'search': return (0, crush_1.crushSearch)(content, '');
|
|
87
|
+
case 'json': return (0, crush_1.crushJson)(content);
|
|
88
|
+
default: return (0, crush_1.crushLog)(content);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// ---------- Single-field crush (pure except injected stash) -------------------
|
|
92
|
+
/** Crush one content string. Returns the replacement (`<crushed>\n<<ccr:HASH>>`)
|
|
93
|
+
* or null to leave the original UNTOUCHED. Honors byte threshold, idempotency,
|
|
94
|
+
* passthrough, and token-validate-or-revert. The stash side effect fires ONLY
|
|
95
|
+
* on a real crush (after validation passes), so a reverted/skipped field is
|
|
96
|
+
* never persisted. */
|
|
97
|
+
function crushField(content, stash, thresholdBytes = exports.DEFAULT_THRESHOLD_BYTES) {
|
|
98
|
+
if (typeof content !== 'string')
|
|
99
|
+
return null;
|
|
100
|
+
if (CCR_MARKER_RE.test(content))
|
|
101
|
+
return null; // idempotent
|
|
102
|
+
if (Buffer.byteLength(content, 'utf8') < thresholdBytes)
|
|
103
|
+
return null; // below floor
|
|
104
|
+
const type = classifyContent(content);
|
|
105
|
+
const result = runEngine(type, content);
|
|
106
|
+
if (result.stats.passthrough)
|
|
107
|
+
return null; // engine declined
|
|
108
|
+
const crushed = result.output;
|
|
109
|
+
// token-validate-or-revert: the FINAL field (crushed + fixed-size marker)
|
|
110
|
+
// must cost strictly fewer estimated tokens than the original. Estimate from
|
|
111
|
+
// length (same ceil(chars/4) basis as estimateTokens) so we never run the
|
|
112
|
+
// stash side effect for a non-win.
|
|
113
|
+
const finalTokens = Math.ceil((crushed.length + FINAL_MARKER_OVERHEAD) / 4);
|
|
114
|
+
if (finalTokens >= (0, crush_1.estimateTokens)(content))
|
|
115
|
+
return null;
|
|
116
|
+
const hash = stash(content, type);
|
|
117
|
+
return `${crushed}\n${ccrMarker(hash)}`;
|
|
118
|
+
}
|
|
119
|
+
// ---------- Message-array walker ----------------------------------------------
|
|
120
|
+
/** Apply crushField to one object's string field, accounting stats and
|
|
121
|
+
* mutating in place on a real crush. */
|
|
122
|
+
function crushAndApply(obj, key, stash, thresholdBytes, stats) {
|
|
123
|
+
const content = obj[key];
|
|
124
|
+
if (typeof content !== 'string')
|
|
125
|
+
return;
|
|
126
|
+
const bytes = Buffer.byteLength(content, 'utf8');
|
|
127
|
+
if (bytes < thresholdBytes) {
|
|
128
|
+
stats.partsSkipped++;
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (CCR_MARKER_RE.test(content)) {
|
|
132
|
+
stats.partsSkipped++;
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
stats.bytesBefore += bytes;
|
|
136
|
+
const replacement = crushField(content, stash, thresholdBytes);
|
|
137
|
+
if (replacement === null) {
|
|
138
|
+
stats.partsReverted++;
|
|
139
|
+
stats.bytesAfter += bytes;
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
obj[key] = replacement;
|
|
143
|
+
stats.partsCrushed++;
|
|
144
|
+
stats.bytesAfter += Buffer.byteLength(replacement, 'utf8');
|
|
145
|
+
}
|
|
146
|
+
/** Crush the bulky fields of one opencode message part:
|
|
147
|
+
* - text part → `.text`
|
|
148
|
+
* - tool part → `.state.output` (only when state.status === 'completed';
|
|
149
|
+
* an 'error' state's `.error` is precious — left alone). */
|
|
150
|
+
function processPart(part, stash, thresholdBytes, stats) {
|
|
151
|
+
if (!part || typeof part !== 'object')
|
|
152
|
+
return;
|
|
153
|
+
const p = part;
|
|
154
|
+
if (p.type === 'text' && typeof p.text === 'string') {
|
|
155
|
+
crushAndApply(p, 'text', stash, thresholdBytes, stats);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (p.type === 'tool' && p.state && typeof p.state === 'object') {
|
|
159
|
+
const state = p.state;
|
|
160
|
+
if (state.status === 'completed' && typeof state.output === 'string') {
|
|
161
|
+
crushAndApply(state, 'output', stash, thresholdBytes, stats);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/** Walk an opencode outbound message array (`output.messages`) and crush its
|
|
166
|
+
* bulky parts in place. Each message is `{ info, parts[] }`. Every part is
|
|
167
|
+
* processed under try/catch — a thrown crush (or a thrown stash) is swallowed,
|
|
168
|
+
* the part is left verbatim, and the walk continues: a crush failure NEVER
|
|
169
|
+
* breaks the turn. Non-array / malformed input is handled defensively. */
|
|
170
|
+
function crushMessages(messages, opts) {
|
|
171
|
+
const stats = {
|
|
172
|
+
partsCrushed: 0, partsSkipped: 0, partsReverted: 0, bytesBefore: 0, bytesAfter: 0,
|
|
173
|
+
};
|
|
174
|
+
const thresholdBytes = opts.thresholdBytes ?? exports.DEFAULT_THRESHOLD_BYTES;
|
|
175
|
+
if (!Array.isArray(messages))
|
|
176
|
+
return stats;
|
|
177
|
+
for (const msg of messages) {
|
|
178
|
+
const parts = msg && typeof msg === 'object' ? msg.parts : null;
|
|
179
|
+
if (!Array.isArray(parts))
|
|
180
|
+
continue;
|
|
181
|
+
for (const part of parts) {
|
|
182
|
+
try {
|
|
183
|
+
processPart(part, opts.stash, thresholdBytes, stats);
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
// per-part swallow — a crush/stash failure must never break the turn
|
|
187
|
+
stats.partsSkipped++;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return stats;
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=opencode-plugin-crush.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode-plugin-crush.js","sourceRoot":"","sources":["../src/opencode-plugin-crush.ts"],"names":[],"mappings":"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"}
|