opencode-self-improvement 0.2.0 → 0.2.1
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/package.json +1 -1
- package/src/inject.ts +14 -9
- package/src/resolver.ts +26 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-self-improvement",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Durable memory for opencode: remember facts, decisions, and commands across sessions, plus a one-command per-repo setup (/repo-init).",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"exports": {
|
package/src/inject.ts
CHANGED
|
@@ -147,18 +147,23 @@ export async function storeVersion(): Promise<string> {
|
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
// Trim an injection block to `budget` characters at WHOLE-line boundaries:
|
|
150
|
-
// keep
|
|
151
|
-
// mid-line. Returns "" when even the header line exceeds the budget
|
|
152
|
-
//
|
|
150
|
+
// keep every line that still fits (skipping over-long ones), never cut
|
|
151
|
+
// mid-line. Returns "" when even the header line exceeds the budget, and ""
|
|
152
|
+
// when NOTHING but header lines survived — a dangling "## Relevant durable
|
|
153
|
+
// memory" over zero memories is noise, not memory (bug seen live: a store
|
|
154
|
+
// whose top matches all exceed the budget injected exactly the 26-char header).
|
|
153
155
|
export function capToBudget(block: string, budget: number): string {
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
const lines = block.split("\n");
|
|
157
|
+
// The header gives the block its meaning; if it does not fit, nothing does.
|
|
158
|
+
if (lines[0].length > budget) return "";
|
|
159
|
+
const kept: string[] = [lines[0]];
|
|
160
|
+
let len = lines[0].length;
|
|
161
|
+
for (const line of lines.slice(1)) {
|
|
162
|
+
if (len + line.length + 1 > budget) continue; // skip over-long lines, keep scanning
|
|
159
163
|
kept.push(line);
|
|
160
|
-
len +=
|
|
164
|
+
len += line.length + 1;
|
|
161
165
|
}
|
|
166
|
+
if (kept.every((l) => l.startsWith("## "))) return "";
|
|
162
167
|
return kept.join("\n");
|
|
163
168
|
}
|
|
164
169
|
|
package/src/resolver.ts
CHANGED
|
@@ -54,6 +54,30 @@ export function balancedParen(text: string, openIdx: number): { inner: string; e
|
|
|
54
54
|
|
|
55
55
|
const CALL_RE = /([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)+)\s*\(/g;
|
|
56
56
|
|
|
57
|
+
// Last dotted segment is a known file extension: `package.json(committed by…)`
|
|
58
|
+
// is a file reference followed by parenthetical prose, not a call to a method
|
|
59
|
+
// named `json`. This class produced 9 false drift_ref_stale_incoming blocks in
|
|
60
|
+
// live use before the guard existed.
|
|
61
|
+
const FILE_EXT = new Set([
|
|
62
|
+
"json", "jsonc", "jsonl", "logfmt", "md", "mdx", "ts", "tsx", "js", "jsx",
|
|
63
|
+
"mjs", "cjs", "py", "go", "rs", "rb", "java", "kt", "sh", "bash", "zsh",
|
|
64
|
+
"yaml", "yml", "toml", "ini", "conf", "cfg", "txt", "csv", "html", "htm",
|
|
65
|
+
"css", "scss", "xml", "sql", "tf", "lock", "log", "env",
|
|
66
|
+
]);
|
|
67
|
+
|
|
68
|
+
// Parenthetical PROSE is not a code call signature. A code-like arg list is
|
|
69
|
+
// empty or contains code punctuation ({ } ( ) : = , . < > quotes); the markers
|
|
70
|
+
// [ ] @ / never appear in the arg snippets drift detection cares about, and
|
|
71
|
+
// bare multi-word English with no code punctuation ("main-agent review fix")
|
|
72
|
+
// is prose.
|
|
73
|
+
function looksProseArgs(inner: string): boolean {
|
|
74
|
+
const s = inner.trim();
|
|
75
|
+
if (!s) return false;
|
|
76
|
+
if (/[[\]@/]/.test(s)) return true;
|
|
77
|
+
if (/[{}():=",.<>'"`]/.test(s)) return false;
|
|
78
|
+
return s.split(/\s+/).length >= 2;
|
|
79
|
+
}
|
|
80
|
+
|
|
57
81
|
export function extractCallForms(content: string): CallForm[] {
|
|
58
82
|
const forms: CallForm[] = [];
|
|
59
83
|
CALL_RE.lastIndex = 0;
|
|
@@ -65,6 +89,8 @@ export function extractCallForms(content: string): CallForm[] {
|
|
|
65
89
|
if (!paren) continue;
|
|
66
90
|
const parts = symbol.split(".");
|
|
67
91
|
const name = parts[parts.length - 1];
|
|
92
|
+
if (FILE_EXT.has(name.toLowerCase())) continue;
|
|
93
|
+
if (looksProseArgs(paren.inner)) continue;
|
|
68
94
|
const ownerPath = parts.slice(0, -1).join(".");
|
|
69
95
|
forms.push({
|
|
70
96
|
symbol,
|