@jmtrin/opencode-kevin 0.1.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/README.md +248 -0
- package/dist/migrations/001_initial.sql +92 -0
- package/dist/migrations/002_indexes.sql +14 -0
- package/dist/plugin/ContextInjector.d.ts +27 -0
- package/dist/plugin/ContextInjector.js +131 -0
- package/dist/plugin/ContextInjector.js.map +1 -0
- package/dist/plugin/MemoryService.d.ts +49 -0
- package/dist/plugin/MemoryService.js +228 -0
- package/dist/plugin/MemoryService.js.map +1 -0
- package/dist/plugin/Migrate.d.ts +13 -0
- package/dist/plugin/Migrate.js +54 -0
- package/dist/plugin/Migrate.js.map +1 -0
- package/dist/plugin/Reflector.d.ts +30 -0
- package/dist/plugin/Reflector.js +117 -0
- package/dist/plugin/Reflector.js.map +1 -0
- package/dist/plugin/Retrospective.d.ts +13 -0
- package/dist/plugin/Retrospective.js +77 -0
- package/dist/plugin/Retrospective.js.map +1 -0
- package/dist/plugin/Store.d.ts +14 -0
- package/dist/plugin/Store.js +36 -0
- package/dist/plugin/Store.js.map +1 -0
- package/dist/plugin/ToolCallObserver.d.ts +28 -0
- package/dist/plugin/ToolCallObserver.js +150 -0
- package/dist/plugin/ToolCallObserver.js.map +1 -0
- package/dist/plugin/index.d.ts +9 -0
- package/dist/plugin/index.js +340 -0
- package/dist/plugin/index.js.map +1 -0
- package/dist/plugin/redact.d.ts +1 -0
- package/dist/plugin/redact.js +12 -0
- package/dist/plugin/redact.js.map +1 -0
- package/dist/plugin/sqlite-adapter.d.ts +12 -0
- package/dist/plugin/sqlite-adapter.js +27 -0
- package/dist/plugin/sqlite-adapter.js.map +1 -0
- package/dist/plugin/uuid.d.ts +1 -0
- package/dist/plugin/uuid.js +51 -0
- package/dist/plugin/uuid.js.map +1 -0
- package/migrations/001_initial.sql +92 -0
- package/migrations/002_indexes.sql +14 -0
- package/package.json +50 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { uuidv7 } from "./uuid.js";
|
|
2
|
+
const TYPE_PRIORITY = {
|
|
3
|
+
error: 0,
|
|
4
|
+
pattern: 1,
|
|
5
|
+
decision: 2,
|
|
6
|
+
context: 3,
|
|
7
|
+
};
|
|
8
|
+
const SESSION_DEFAULT_TTL_HOURS = 24;
|
|
9
|
+
const RELEVANCE_BUMP = 0.05;
|
|
10
|
+
const RELEVANCE_MAX = 1.0;
|
|
11
|
+
function sqliteUtcNowPlusHours(hours) {
|
|
12
|
+
const d = new Date(Date.now() + hours * 3_600_000);
|
|
13
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
14
|
+
return `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())} ${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())}`;
|
|
15
|
+
}
|
|
16
|
+
function mapRow(row, score) {
|
|
17
|
+
const mem = {
|
|
18
|
+
id: row.id,
|
|
19
|
+
type: row.type,
|
|
20
|
+
content: row.content,
|
|
21
|
+
scope: row.scope,
|
|
22
|
+
relevanceScore: row.relevance_score,
|
|
23
|
+
sourceTool: row.source_tool,
|
|
24
|
+
sourceSession: row.source_session,
|
|
25
|
+
metadata: row.metadata
|
|
26
|
+
? JSON.parse(row.metadata)
|
|
27
|
+
: null,
|
|
28
|
+
createdAt: row.created_at,
|
|
29
|
+
updatedAt: row.updated_at,
|
|
30
|
+
expiresAt: row.expires_at,
|
|
31
|
+
};
|
|
32
|
+
if (score !== undefined) {
|
|
33
|
+
if (!mem.metadata)
|
|
34
|
+
mem.metadata = {};
|
|
35
|
+
mem.metadata.score = score;
|
|
36
|
+
}
|
|
37
|
+
return mem;
|
|
38
|
+
}
|
|
39
|
+
function sanitizeMatch(text) {
|
|
40
|
+
const tokens = stripUnbalancedQuotes(text.trim())
|
|
41
|
+
.split(/\s+/)
|
|
42
|
+
.filter((t) => t.length > 0)
|
|
43
|
+
.map((t) => `"${t.replace(/"/g, '""')}"`);
|
|
44
|
+
return tokens.join(" ");
|
|
45
|
+
}
|
|
46
|
+
function stripUnbalancedQuotes(s) {
|
|
47
|
+
const count = (s.match(/"/g) ?? []).length;
|
|
48
|
+
if (count % 2 === 0)
|
|
49
|
+
return s;
|
|
50
|
+
return s.replace(/"/g, "");
|
|
51
|
+
}
|
|
52
|
+
function isNotSearchable(mem) {
|
|
53
|
+
return (mem.metadata?.not_searchable === true);
|
|
54
|
+
}
|
|
55
|
+
export class MemoryService {
|
|
56
|
+
store;
|
|
57
|
+
constructor(store) {
|
|
58
|
+
this.store = store;
|
|
59
|
+
}
|
|
60
|
+
save(input) {
|
|
61
|
+
const id = uuidv7();
|
|
62
|
+
const scope = input.scope ?? "project";
|
|
63
|
+
const relevanceScore = input.relevanceScore ?? 0.5;
|
|
64
|
+
const metadata = input.metadata ? JSON.stringify(input.metadata) : null;
|
|
65
|
+
let expiresAt = input.expiresAt ?? null;
|
|
66
|
+
if (scope === "session" && !input.expiresAt) {
|
|
67
|
+
expiresAt = sqliteUtcNowPlusHours(SESSION_DEFAULT_TTL_HOURS);
|
|
68
|
+
}
|
|
69
|
+
this.store
|
|
70
|
+
.prepare(`INSERT INTO memories
|
|
71
|
+
(id, type, content, scope, relevance_score, source_tool, source_session, metadata, expires_at)
|
|
72
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
73
|
+
.run(id, input.type, input.content, scope, relevanceScore, input.sourceTool ?? null, input.sourceSession ?? null, metadata, expiresAt);
|
|
74
|
+
return id;
|
|
75
|
+
}
|
|
76
|
+
getById(id) {
|
|
77
|
+
const row = this.store
|
|
78
|
+
.prepare(`SELECT id, type, content, scope, relevance_score, source_tool, source_session,
|
|
79
|
+
metadata, created_at, updated_at, expires_at
|
|
80
|
+
FROM memories WHERE id = ?`)
|
|
81
|
+
.get(id);
|
|
82
|
+
return row ? mapRow(row) : null;
|
|
83
|
+
}
|
|
84
|
+
update(id, fields) {
|
|
85
|
+
const cols = [];
|
|
86
|
+
const vals = [];
|
|
87
|
+
if (fields.content !== undefined) {
|
|
88
|
+
cols.push("content = ?");
|
|
89
|
+
vals.push(fields.content);
|
|
90
|
+
}
|
|
91
|
+
if (fields.relevanceScore !== undefined) {
|
|
92
|
+
cols.push("relevance_score = ?");
|
|
93
|
+
vals.push(fields.relevanceScore);
|
|
94
|
+
}
|
|
95
|
+
if (fields.scope !== undefined) {
|
|
96
|
+
cols.push("scope = ?");
|
|
97
|
+
vals.push(fields.scope);
|
|
98
|
+
}
|
|
99
|
+
if (fields.type !== undefined) {
|
|
100
|
+
cols.push("type = ?");
|
|
101
|
+
vals.push(fields.type);
|
|
102
|
+
}
|
|
103
|
+
if (fields.metadata !== undefined) {
|
|
104
|
+
cols.push("metadata = ?");
|
|
105
|
+
vals.push(fields.metadata ? JSON.stringify(fields.metadata) : null);
|
|
106
|
+
}
|
|
107
|
+
if (fields.expiresAt !== undefined) {
|
|
108
|
+
cols.push("expires_at = ?");
|
|
109
|
+
vals.push(fields.expiresAt);
|
|
110
|
+
}
|
|
111
|
+
if (cols.length === 0)
|
|
112
|
+
return;
|
|
113
|
+
cols.push("updated_at = datetime('now')");
|
|
114
|
+
vals.push(id);
|
|
115
|
+
this.store
|
|
116
|
+
.prepare(`UPDATE memories SET ${cols.join(", ")} WHERE id = ?`)
|
|
117
|
+
.run(...vals);
|
|
118
|
+
}
|
|
119
|
+
delete(id) {
|
|
120
|
+
this.store.prepare("DELETE FROM memories WHERE id = ?").run(id);
|
|
121
|
+
}
|
|
122
|
+
query(input) {
|
|
123
|
+
const match = sanitizeMatch(input.text);
|
|
124
|
+
if (!match)
|
|
125
|
+
return [];
|
|
126
|
+
const scope = input.scope ?? "all";
|
|
127
|
+
const limit = input.limit ?? 10;
|
|
128
|
+
let sql = `
|
|
129
|
+
SELECT m.id, m.type, m.content, m.scope, m.relevance_score,
|
|
130
|
+
m.source_tool, m.source_session, m.metadata,
|
|
131
|
+
m.created_at, m.updated_at, m.expires_at,
|
|
132
|
+
bm25(memories_fts) AS score
|
|
133
|
+
FROM memories_fts
|
|
134
|
+
JOIN memories m ON m.rowid = memories_fts.rowid
|
|
135
|
+
WHERE memories_fts MATCH ?
|
|
136
|
+
AND (m.expires_at IS NULL OR m.expires_at > datetime('now'))`;
|
|
137
|
+
const params = [match];
|
|
138
|
+
if (input.type) {
|
|
139
|
+
sql += " AND m.type = ?";
|
|
140
|
+
params.push(input.type);
|
|
141
|
+
}
|
|
142
|
+
if (scope !== "all") {
|
|
143
|
+
sql += " AND m.scope = ?";
|
|
144
|
+
params.push(scope);
|
|
145
|
+
}
|
|
146
|
+
sql += " ORDER BY bm25(memories_fts) LIMIT ?";
|
|
147
|
+
params.push(limit);
|
|
148
|
+
const rows = this.store.prepare(sql).all(...params);
|
|
149
|
+
return rows
|
|
150
|
+
.map((r) => mapRow(r, r.score))
|
|
151
|
+
.filter((m) => !isNotSearchable(m));
|
|
152
|
+
}
|
|
153
|
+
loadAll(scope) {
|
|
154
|
+
let sql = `
|
|
155
|
+
SELECT id, type, content, scope, relevance_score, source_tool, source_session,
|
|
156
|
+
metadata, created_at, updated_at, expires_at
|
|
157
|
+
FROM memories
|
|
158
|
+
WHERE (expires_at IS NULL OR expires_at > datetime('now'))`;
|
|
159
|
+
const params = [];
|
|
160
|
+
if (scope !== "all") {
|
|
161
|
+
sql += " AND scope = ?";
|
|
162
|
+
params.push(scope);
|
|
163
|
+
}
|
|
164
|
+
sql += " ORDER BY relevance_score DESC, created_at DESC";
|
|
165
|
+
return this.store.prepare(sql).all(...params);
|
|
166
|
+
}
|
|
167
|
+
queryRelevant(text, scope) {
|
|
168
|
+
const tokens = stripUnbalancedQuotes(text.trim())
|
|
169
|
+
.split(/\s+/)
|
|
170
|
+
.filter((t) => t.length > 0)
|
|
171
|
+
.map((t) => `"${t.replace(/"/g, '""')}"`);
|
|
172
|
+
if (tokens.length === 0)
|
|
173
|
+
return [];
|
|
174
|
+
const match = tokens.join(" OR ");
|
|
175
|
+
let sql = `
|
|
176
|
+
SELECT m.id, m.type, m.content, m.scope, m.relevance_score,
|
|
177
|
+
m.source_tool, m.source_session, m.metadata,
|
|
178
|
+
m.created_at, m.updated_at, m.expires_at,
|
|
179
|
+
bm25(memories_fts) AS score
|
|
180
|
+
FROM memories_fts
|
|
181
|
+
JOIN memories m ON m.rowid = memories_fts.rowid
|
|
182
|
+
WHERE memories_fts MATCH ?
|
|
183
|
+
AND (m.expires_at IS NULL OR m.expires_at > datetime('now'))`;
|
|
184
|
+
const params = [match];
|
|
185
|
+
if (scope !== "all") {
|
|
186
|
+
sql += " AND m.scope = ?";
|
|
187
|
+
params.push(scope);
|
|
188
|
+
}
|
|
189
|
+
sql += " ORDER BY bm25(memories_fts) LIMIT 100";
|
|
190
|
+
const rows = this.store.prepare(sql).all(...params);
|
|
191
|
+
return rows
|
|
192
|
+
.map((r) => mapRow(r, r.score))
|
|
193
|
+
.filter((m) => !isNotSearchable(m));
|
|
194
|
+
}
|
|
195
|
+
getRelevant(input) {
|
|
196
|
+
const maxTokens = input.maxTokens ?? 2000;
|
|
197
|
+
const charBudget = maxTokens * 4;
|
|
198
|
+
const scope = input.scope ?? "project";
|
|
199
|
+
let candidates;
|
|
200
|
+
if (input.query && input.query.trim().length > 0) {
|
|
201
|
+
candidates = this.queryRelevant(input.query, scope);
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
candidates = this.loadAll(scope)
|
|
205
|
+
.map((r) => mapRow(r))
|
|
206
|
+
.filter((m) => !isNotSearchable(m));
|
|
207
|
+
}
|
|
208
|
+
candidates.sort((a, b) => TYPE_PRIORITY[a.type] - TYPE_PRIORITY[b.type]);
|
|
209
|
+
const result = [];
|
|
210
|
+
let used = 0;
|
|
211
|
+
for (const mem of candidates) {
|
|
212
|
+
const len = mem.content.length + 32;
|
|
213
|
+
if (used + len > charBudget && result.length > 0)
|
|
214
|
+
break;
|
|
215
|
+
result.push(mem);
|
|
216
|
+
used += len;
|
|
217
|
+
}
|
|
218
|
+
if (result.length > 0) {
|
|
219
|
+
const bump = this.store.prepare("UPDATE memories SET relevance_score = MIN(?, relevance_score + ?) WHERE id = ?");
|
|
220
|
+
this.store.transaction(() => {
|
|
221
|
+
for (const m of result)
|
|
222
|
+
bump.run(RELEVANCE_MAX, RELEVANCE_BUMP, m.id);
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
return result;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=MemoryService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemoryService.js","sourceRoot":"","sources":["../../plugin/MemoryService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Store } from "./Store.js";
|
|
2
|
+
export interface MigrateResult {
|
|
3
|
+
from: string;
|
|
4
|
+
to: string;
|
|
5
|
+
applied: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare class Migrate {
|
|
8
|
+
private store;
|
|
9
|
+
private migrationsDir;
|
|
10
|
+
constructor(store: Store, migrationsDir: string);
|
|
11
|
+
run(): Promise<MigrateResult>;
|
|
12
|
+
private listPending;
|
|
13
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { readFileSync, readdirSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
export class Migrate {
|
|
4
|
+
store;
|
|
5
|
+
migrationsDir;
|
|
6
|
+
constructor(store, migrationsDir) {
|
|
7
|
+
this.store = store;
|
|
8
|
+
this.migrationsDir = migrationsDir;
|
|
9
|
+
}
|
|
10
|
+
async run() {
|
|
11
|
+
this.store.exec(`CREATE TABLE IF NOT EXISTS schema_version (
|
|
12
|
+
version TEXT PRIMARY KEY,
|
|
13
|
+
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
14
|
+
);`);
|
|
15
|
+
const currentRow = this.store
|
|
16
|
+
.prepare("SELECT version FROM schema_version ORDER BY version DESC LIMIT 1")
|
|
17
|
+
.get();
|
|
18
|
+
const from = currentRow?.version ?? "000";
|
|
19
|
+
const pending = this.listPending(from);
|
|
20
|
+
if (pending.length === 0) {
|
|
21
|
+
return { from, to: from, applied: [] };
|
|
22
|
+
}
|
|
23
|
+
const insertVersion = this.store.prepare("INSERT OR IGNORE INTO schema_version (version) VALUES (?)");
|
|
24
|
+
for (const migration of pending) {
|
|
25
|
+
const sql = readFileSync(join(this.migrationsDir, migration.file), "utf8");
|
|
26
|
+
this.store.transaction(() => {
|
|
27
|
+
this.store.exec(sql);
|
|
28
|
+
insertVersion.run(migration.version);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
from,
|
|
33
|
+
to: pending[pending.length - 1].version,
|
|
34
|
+
applied: pending.map((m) => m.version),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
listPending(current) {
|
|
38
|
+
let files = [];
|
|
39
|
+
try {
|
|
40
|
+
files = readdirSync(this.migrationsDir).filter((f) => f.endsWith(".sql"));
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
files.sort();
|
|
46
|
+
return files
|
|
47
|
+
.map((file) => {
|
|
48
|
+
const match = file.match(/^(\w+?)_/);
|
|
49
|
+
return match ? { version: match[1], file } : null;
|
|
50
|
+
})
|
|
51
|
+
.filter((m) => m !== null && m.version > current);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=Migrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Migrate.js","sourceRoot":"","sources":["../../plugin/Migrate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AASjC,MAAM,OAAO,OAAO;IAEV;IACA;IAFT,YACS,KAAY,EACZ,aAAqB;QADrB,UAAK,GAAL,KAAK,CAAO;QACZ,kBAAa,GAAb,aAAa,CAAQ;IAC3B,CAAC;IAEJ,KAAK,CAAC,GAAG;QACR,IAAI,CAAC,KAAK,CAAC,IAAI,CACd;;;UAGO,CACP,CAAC;QAEF,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK;aAC3B,OAAO,CACP,kEAAkE,CAClE;aACA,GAAG,EAAqC,CAAC;QAE3C,MAAM,IAAI,GAAG,UAAU,EAAE,OAAO,IAAI,KAAK,CAAC;QAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAEvC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QACxC,CAAC;QAED,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CACvC,2DAA2D,CAC3D,CAAC;QAEF,KAAK,MAAM,SAAS,IAAI,OAAO,EAAE,CAAC;YACjC,MAAM,GAAG,GAAG,YAAY,CACvB,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,IAAI,CAAC,EACxC,MAAM,CACN,CAAC;YACF,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;gBAC3B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACrB,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACtC,CAAC,CAAC,CAAC;QACJ,CAAC;QAED,OAAO;YACN,IAAI;YACJ,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,OAAO;YACvC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;SACtC,CAAC;IACH,CAAC;IAEO,WAAW,CAAC,OAAe;QAClC,IAAI,KAAK,GAAa,EAAE,CAAC;QACzB,IAAI,CAAC;YACJ,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QAC3E,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,EAAE,CAAC;QACX,CAAC;QACD,KAAK,CAAC,IAAI,EAAE,CAAC;QACb,OAAO,KAAK;aACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACb,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACrC,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACnD,CAAC,CAAC;aACD,MAAM,CACN,CAAC,CAAC,EAA0C,EAAE,CAC7C,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO,GAAG,OAAO,CAClC,CAAC;IACJ,CAAC;CACD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { MemoryService } from "./MemoryService.js";
|
|
2
|
+
export interface ReflectionInput {
|
|
3
|
+
toolName: string;
|
|
4
|
+
argsSummary: string;
|
|
5
|
+
stderr: string;
|
|
6
|
+
stdout: string;
|
|
7
|
+
exitCode?: number;
|
|
8
|
+
errorType: string;
|
|
9
|
+
sessionId: string;
|
|
10
|
+
}
|
|
11
|
+
export interface ReflectorOptions {
|
|
12
|
+
throttleMs?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface HeuristicLessonInput {
|
|
15
|
+
toolName: string;
|
|
16
|
+
errorType: string;
|
|
17
|
+
firstErrorLine: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const ERROR_LINE_RE: RegExp;
|
|
20
|
+
export declare class Reflector {
|
|
21
|
+
private memoryService;
|
|
22
|
+
private lastReflectionTs;
|
|
23
|
+
private throttleMs;
|
|
24
|
+
constructor(memoryService: MemoryService, options?: ReflectorOptions);
|
|
25
|
+
invoke(input: ReflectionInput): Promise<string | null>;
|
|
26
|
+
generateHeuristicLesson(input: HeuristicLessonInput): string;
|
|
27
|
+
redactPaths(text: string): string;
|
|
28
|
+
redactSecrets(text: string): string;
|
|
29
|
+
private extractFirstErrorLine;
|
|
30
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { redactPaths as redactPathsText } from "./redact.js";
|
|
2
|
+
const DEFAULT_THROTTLE_MS = 60_000;
|
|
3
|
+
const MAX_CONTENT_CHARS = 4096;
|
|
4
|
+
const MAX_ERROR_LINE_CHARS = 500;
|
|
5
|
+
const TRUNC_SUFFIX = "... [truncated]";
|
|
6
|
+
const CONTEXT_PREFIX = "\n\nContext:\n";
|
|
7
|
+
export const ERROR_LINE_RE = /\b(error|failed|fail|cannot find|cannot resolve|TS\d{4,}|exception|traceback|panic|fatal|referenceerror|typeerror|syntaxerror|command failed|non-zero exit)\b/i;
|
|
8
|
+
const SUGGESTIONS = {
|
|
9
|
+
typecheck: "Verify types and imports before running.",
|
|
10
|
+
lint: "Run linter and fix warnings before committing.",
|
|
11
|
+
test: "Run tests and fix failures before proceeding.",
|
|
12
|
+
runtime: "Check error message and stack trace for root cause.",
|
|
13
|
+
timeout: "Check for infinite loops or long-running operations.",
|
|
14
|
+
unknown: "Review the error output for details.",
|
|
15
|
+
};
|
|
16
|
+
const SECRET_PATTERNS = [
|
|
17
|
+
/(API_KEY|SECRET|PASSWORD|TOKEN)\s*[=:]\s*\S+/gi,
|
|
18
|
+
/\bBearer\s+\S+/gi,
|
|
19
|
+
/\btoken\s+\S+/gi,
|
|
20
|
+
];
|
|
21
|
+
const SECRET_VALUE_PATTERN = /\s*=\s*\S+(.*)$/;
|
|
22
|
+
const PATH_PATTERNS_DEPRECATED = null;
|
|
23
|
+
export class Reflector {
|
|
24
|
+
memoryService;
|
|
25
|
+
lastReflectionTs = 0;
|
|
26
|
+
throttleMs;
|
|
27
|
+
constructor(memoryService, options) {
|
|
28
|
+
this.memoryService = memoryService;
|
|
29
|
+
this.throttleMs = options?.throttleMs ?? DEFAULT_THROTTLE_MS;
|
|
30
|
+
}
|
|
31
|
+
async invoke(input) {
|
|
32
|
+
const now = Date.now();
|
|
33
|
+
if (now - this.lastReflectionTs < this.throttleMs) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
this.lastReflectionTs = now;
|
|
37
|
+
const redactedStderr = this.redactSecrets(this.redactPaths(input.stderr));
|
|
38
|
+
const redactedStdout = this.redactSecrets(this.redactPaths(input.stdout));
|
|
39
|
+
const sourceOutput = redactedStderr.length > 0 ? redactedStderr : redactedStdout;
|
|
40
|
+
const firstErrorLine = this.extractFirstErrorLine(sourceOutput);
|
|
41
|
+
const lesson = this.generateHeuristicLesson({
|
|
42
|
+
toolName: input.toolName,
|
|
43
|
+
errorType: input.errorType,
|
|
44
|
+
firstErrorLine,
|
|
45
|
+
});
|
|
46
|
+
const metadata = {};
|
|
47
|
+
let finalContent;
|
|
48
|
+
if (sourceOutput.length > 0) {
|
|
49
|
+
const fullLen = lesson.length + CONTEXT_PREFIX.length + sourceOutput.length;
|
|
50
|
+
if (fullLen <= MAX_CONTENT_CHARS) {
|
|
51
|
+
finalContent = `${lesson}${CONTEXT_PREFIX}${sourceOutput}`;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
const budget = MAX_CONTENT_CHARS -
|
|
55
|
+
lesson.length -
|
|
56
|
+
CONTEXT_PREFIX.length -
|
|
57
|
+
TRUNC_SUFFIX.length;
|
|
58
|
+
const truncated = sourceOutput.slice(0, Math.max(0, budget));
|
|
59
|
+
finalContent = `${lesson}${CONTEXT_PREFIX}${truncated}${TRUNC_SUFFIX}`;
|
|
60
|
+
metadata.truncated = true;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
finalContent = lesson;
|
|
65
|
+
}
|
|
66
|
+
const id = this.memoryService.save({
|
|
67
|
+
type: "error",
|
|
68
|
+
content: finalContent,
|
|
69
|
+
scope: "project",
|
|
70
|
+
sourceTool: input.toolName,
|
|
71
|
+
sourceSession: input.sessionId,
|
|
72
|
+
metadata,
|
|
73
|
+
});
|
|
74
|
+
return id;
|
|
75
|
+
}
|
|
76
|
+
generateHeuristicLesson(input) {
|
|
77
|
+
const suggestion = SUGGESTIONS[input.errorType] ?? SUGGESTIONS.unknown;
|
|
78
|
+
const line = input.firstErrorLine.length > MAX_ERROR_LINE_CHARS
|
|
79
|
+
? `${input.firstErrorLine.slice(0, MAX_ERROR_LINE_CHARS)}...`
|
|
80
|
+
: input.firstErrorLine;
|
|
81
|
+
return `When ${input.toolName} fails with ${input.errorType}: ${line}\nSuggestion: ${suggestion}`;
|
|
82
|
+
}
|
|
83
|
+
redactPaths(text) {
|
|
84
|
+
return redactPathsText(text);
|
|
85
|
+
}
|
|
86
|
+
redactSecrets(text) {
|
|
87
|
+
let out = text;
|
|
88
|
+
for (const pat of SECRET_PATTERNS) {
|
|
89
|
+
out = out.replace(pat, (match) => {
|
|
90
|
+
const eq = match.match(SECRET_VALUE_PATTERN);
|
|
91
|
+
if (eq) {
|
|
92
|
+
const label = match.split(/[=:]/)[0].trim();
|
|
93
|
+
return `${label}=<redacted>`;
|
|
94
|
+
}
|
|
95
|
+
const parts = match.split(/\s+/);
|
|
96
|
+
return `${parts[0]} <redacted>`;
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
extractFirstErrorLine(text) {
|
|
102
|
+
const lines = text.split(/\r?\n/);
|
|
103
|
+
for (const line of lines) {
|
|
104
|
+
const trimmed = line.trim();
|
|
105
|
+
if (trimmed.length > 0 && ERROR_LINE_RE.test(trimmed)) {
|
|
106
|
+
return trimmed;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
for (const line of lines) {
|
|
110
|
+
const trimmed = line.trim();
|
|
111
|
+
if (trimmed.length > 0)
|
|
112
|
+
return trimmed;
|
|
113
|
+
}
|
|
114
|
+
return "";
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=Reflector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Reflector.js","sourceRoot":"","sources":["../../plugin/Reflector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,aAAa,CAAC;AAsB7D,MAAM,mBAAmB,GAAG,MAAM,CAAC;AACnC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAC/B,MAAM,oBAAoB,GAAG,GAAG,CAAC;AACjC,MAAM,YAAY,GAAG,iBAAiB,CAAC;AACvC,MAAM,cAAc,GAAG,gBAAgB,CAAC;AAExC,MAAM,CAAC,MAAM,aAAa,GACzB,gKAAgK,CAAC;AAElK,MAAM,WAAW,GAA2B;IAC3C,SAAS,EAAE,0CAA0C;IACrD,IAAI,EAAE,gDAAgD;IACtD,IAAI,EAAE,+CAA+C;IACrD,OAAO,EAAE,qDAAqD;IAC9D,OAAO,EAAE,sDAAsD;IAC/D,OAAO,EAAE,sCAAsC;CAC/C,CAAC;AAEF,MAAM,eAAe,GAAa;IACjC,gDAAgD;IAChD,kBAAkB;IAClB,iBAAiB;CACjB,CAAC;AAEF,MAAM,oBAAoB,GAAG,iBAAiB,CAAC;AAE/C,MAAM,wBAAwB,GAAG,IAAI,CAAC;AAEtC,MAAM,OAAO,SAAS;IAKZ;IAJD,gBAAgB,GAAG,CAAC,CAAC;IACrB,UAAU,CAAS;IAE3B,YACS,aAA4B,EACpC,OAA0B;QADlB,kBAAa,GAAb,aAAa,CAAe;QAGpC,IAAI,CAAC,UAAU,GAAG,OAAO,EAAE,UAAU,IAAI,mBAAmB,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAsB;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,GAAG,GAAG,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YACnD,OAAO,IAAI,CAAC;QACb,CAAC;QACD,IAAI,CAAC,gBAAgB,GAAG,GAAG,CAAC;QAE5B,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QAC1E,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QAE1E,MAAM,YAAY,GACjB,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC;QAC7D,MAAM,cAAc,GAAG,IAAI,CAAC,qBAAqB,CAAC,YAAY,CAAC,CAAC;QAEhE,MAAM,MAAM,GAAG,IAAI,CAAC,uBAAuB,CAAC;YAC3C,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,cAAc;SACd,CAAC,CAAC;QAEH,MAAM,QAAQ,GAA4B,EAAE,CAAC;QAC7C,IAAI,YAAoB,CAAC;QACzB,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,OAAO,GACZ,MAAM,CAAC,MAAM,GAAG,cAAc,CAAC,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC;YAC7D,IAAI,OAAO,IAAI,iBAAiB,EAAE,CAAC;gBAClC,YAAY,GAAG,GAAG,MAAM,GAAG,cAAc,GAAG,YAAY,EAAE,CAAC;YAC5D,CAAC;iBAAM,CAAC;gBACP,MAAM,MAAM,GACX,iBAAiB;oBACjB,MAAM,CAAC,MAAM;oBACb,cAAc,CAAC,MAAM;oBACrB,YAAY,CAAC,MAAM,CAAC;gBACrB,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;gBAC7D,YAAY,GAAG,GAAG,MAAM,GAAG,cAAc,GAAG,SAAS,GAAG,YAAY,EAAE,CAAC;gBACvE,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAC;YAC3B,CAAC;QACF,CAAC;aAAM,CAAC;YACP,YAAY,GAAG,MAAM,CAAC;QACvB,CAAC;QAED,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YAClC,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,YAAY;YACrB,KAAK,EAAE,SAAS;YAChB,UAAU,EAAE,KAAK,CAAC,QAAQ;YAC1B,aAAa,EAAE,KAAK,CAAC,SAAS;YAC9B,QAAQ;SACR,CAAC,CAAC;QAEH,OAAO,EAAE,CAAC;IACX,CAAC;IAED,uBAAuB,CAAC,KAA2B;QAClD,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,WAAW,CAAC,OAAO,CAAC;QACvE,MAAM,IAAI,GACT,KAAK,CAAC,cAAc,CAAC,MAAM,GAAG,oBAAoB;YACjD,CAAC,CAAC,GAAG,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,oBAAoB,CAAC,KAAK;YAC7D,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC;QACzB,OAAO,QAAQ,KAAK,CAAC,QAAQ,eAAe,KAAK,CAAC,SAAS,KAAK,IAAI,iBAAiB,UAAU,EAAE,CAAC;IACnG,CAAC;IAED,WAAW,CAAC,IAAY;QACvB,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,aAAa,CAAC,IAAY;QACzB,IAAI,GAAG,GAAG,IAAI,CAAC;QACf,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;YACnC,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE;gBAChC,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;gBAC7C,IAAI,EAAE,EAAE,CAAC;oBACR,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;oBAC5C,OAAO,GAAG,KAAK,aAAa,CAAC;gBAC9B,CAAC;gBACD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBACjC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC;YACjC,CAAC,CAAC,CAAC;QACJ,CAAC;QACD,OAAO,GAAG,CAAC;IACZ,CAAC;IAEO,qBAAqB,CAAC,IAAY;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAClC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBACvD,OAAO,OAAO,CAAC;YAChB,CAAC;QACF,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,OAAO,CAAC;QACxC,CAAC;QACD,OAAO,EAAE,CAAC;IACX,CAAC;CACD"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { MemoryService } from "./MemoryService.js";
|
|
2
|
+
import type { Store } from "./Store.js";
|
|
3
|
+
export interface RetrospectiveOptions {
|
|
4
|
+
dir?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class Retrospective {
|
|
7
|
+
private store;
|
|
8
|
+
private memoryService;
|
|
9
|
+
private retrospectivesDir;
|
|
10
|
+
constructor(store: Store, memoryService: MemoryService, options?: RetrospectiveOptions);
|
|
11
|
+
generate(sessionId: string): Promise<string | null>;
|
|
12
|
+
private buildMarkdown;
|
|
13
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { uuidv7 } from "./uuid.js";
|
|
5
|
+
export class Retrospective {
|
|
6
|
+
store;
|
|
7
|
+
memoryService;
|
|
8
|
+
retrospectivesDir;
|
|
9
|
+
constructor(store, memoryService, options) {
|
|
10
|
+
this.store = store;
|
|
11
|
+
this.memoryService = memoryService;
|
|
12
|
+
this.retrospectivesDir = options?.dir ?? join(homedir(), ".opencode-kevin", "retrospectives");
|
|
13
|
+
}
|
|
14
|
+
async generate(sessionId) {
|
|
15
|
+
const existing = this.store
|
|
16
|
+
.prepare("SELECT file_path FROM retrospectives WHERE session_id = ?")
|
|
17
|
+
.get(sessionId);
|
|
18
|
+
if (existing?.file_path)
|
|
19
|
+
return existing.file_path;
|
|
20
|
+
const counts = this.store
|
|
21
|
+
.prepare(`SELECT
|
|
22
|
+
SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) AS success_count,
|
|
23
|
+
SUM(CASE WHEN success = 0 THEN 1 ELSE 0 END) AS failure_count,
|
|
24
|
+
COUNT(*) AS total
|
|
25
|
+
FROM tool_calls WHERE session_id = ?`)
|
|
26
|
+
.get(sessionId);
|
|
27
|
+
const successCount = counts?.success_count ?? 0;
|
|
28
|
+
const failureCount = counts?.failure_count ?? 0;
|
|
29
|
+
const total = counts?.total ?? 0;
|
|
30
|
+
if (failureCount === 0)
|
|
31
|
+
return null;
|
|
32
|
+
const failedTools = this.store
|
|
33
|
+
.prepare(`SELECT tool, args_summary, error_type
|
|
34
|
+
FROM tool_calls
|
|
35
|
+
WHERE session_id = ? AND success = 0
|
|
36
|
+
ORDER BY ts ASC`)
|
|
37
|
+
.all(sessionId);
|
|
38
|
+
const lessons = this.store
|
|
39
|
+
.prepare(`SELECT content FROM memories
|
|
40
|
+
WHERE type = 'error' AND source_session = ?
|
|
41
|
+
ORDER BY created_at ASC`)
|
|
42
|
+
.all(sessionId);
|
|
43
|
+
const md = this.buildMarkdown(sessionId, total, successCount, failureCount, failedTools, lessons);
|
|
44
|
+
mkdirSync(this.retrospectivesDir, { recursive: true });
|
|
45
|
+
const filePath = join(this.retrospectivesDir, `${sessionId}.md`);
|
|
46
|
+
writeFileSync(filePath, md, "utf8");
|
|
47
|
+
const id = uuidv7();
|
|
48
|
+
this.store
|
|
49
|
+
.prepare(`INSERT OR IGNORE INTO retrospectives
|
|
50
|
+
(id, session_id, ts, failure_count, success_count, lessons_count, file_path, metadata)
|
|
51
|
+
VALUES (?, ?, datetime('now'), ?, ?, ?, ?, ?)`)
|
|
52
|
+
.run(id, sessionId, failureCount, successCount, lessons.length, filePath, null);
|
|
53
|
+
return filePath;
|
|
54
|
+
}
|
|
55
|
+
buildMarkdown(sessionId, total, successCount, failureCount, failedTools, lessons) {
|
|
56
|
+
const lines = [];
|
|
57
|
+
lines.push(`# Retrospective — Session ${sessionId}`);
|
|
58
|
+
lines.push("");
|
|
59
|
+
lines.push("## Resumen");
|
|
60
|
+
lines.push(`- Tool calls: ${total} (${successCount} ok, ${failureCount} failed)`);
|
|
61
|
+
lines.push("");
|
|
62
|
+
lines.push("## Tools que fallaron");
|
|
63
|
+
for (const ft of failedTools) {
|
|
64
|
+
const et = ft.error_type ?? "unknown";
|
|
65
|
+
const summary = ft.args_summary ?? "";
|
|
66
|
+
lines.push(`- ${ft.tool} (${et}): ${summary}`);
|
|
67
|
+
}
|
|
68
|
+
lines.push("");
|
|
69
|
+
lines.push("## Lecciones generadas");
|
|
70
|
+
for (const lesson of lessons) {
|
|
71
|
+
lines.push(`- ${lesson.content}`);
|
|
72
|
+
}
|
|
73
|
+
lines.push("");
|
|
74
|
+
return lines.join("\n");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=Retrospective.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Retrospective.js","sourceRoot":"","sources":["../../plugin/Retrospective.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type SqliteAdapter } from "./sqlite-adapter.js";
|
|
2
|
+
export interface StoreOptions {
|
|
3
|
+
path: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class Store {
|
|
6
|
+
private db;
|
|
7
|
+
private closed;
|
|
8
|
+
constructor(options: StoreOptions);
|
|
9
|
+
prepare(sql: string): ReturnType<SqliteAdapter["prepare"]>;
|
|
10
|
+
transaction<T>(fn: () => T): T;
|
|
11
|
+
exec(sql: string): void;
|
|
12
|
+
close(): void;
|
|
13
|
+
get raw(): SqliteAdapter;
|
|
14
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { createDatabase } from "./sqlite-adapter.js";
|
|
2
|
+
export class Store {
|
|
3
|
+
db;
|
|
4
|
+
closed = false;
|
|
5
|
+
constructor(options) {
|
|
6
|
+
this.db = createDatabase(options.path);
|
|
7
|
+
this.db.exec("PRAGMA journal_mode = WAL");
|
|
8
|
+
this.db.exec("PRAGMA foreign_keys = ON");
|
|
9
|
+
}
|
|
10
|
+
prepare(sql) {
|
|
11
|
+
if (this.closed)
|
|
12
|
+
throw new Error("Store is closed");
|
|
13
|
+
return this.db.prepare(sql);
|
|
14
|
+
}
|
|
15
|
+
transaction(fn) {
|
|
16
|
+
if (this.closed)
|
|
17
|
+
throw new Error("Store is closed");
|
|
18
|
+
const tx = this.db.transaction(fn);
|
|
19
|
+
return tx();
|
|
20
|
+
}
|
|
21
|
+
exec(sql) {
|
|
22
|
+
if (this.closed)
|
|
23
|
+
throw new Error("Store is closed");
|
|
24
|
+
this.db.exec(sql);
|
|
25
|
+
}
|
|
26
|
+
close() {
|
|
27
|
+
if (this.closed)
|
|
28
|
+
return;
|
|
29
|
+
this.closed = true;
|
|
30
|
+
this.db.close();
|
|
31
|
+
}
|
|
32
|
+
get raw() {
|
|
33
|
+
return this.db;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=Store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Store.js","sourceRoot":"","sources":["../../plugin/Store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAsB,MAAM,qBAAqB,CAAC;AAMzE,MAAM,OAAO,KAAK;IACT,EAAE,CAAgB;IAClB,MAAM,GAAG,KAAK,CAAC;IAEvB,YAAY,OAAqB;QAChC,IAAI,CAAC,EAAE,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QAC1C,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAC1C,CAAC;IAED,OAAO,CAAC,GAAW;QAClB,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,WAAW,CAAI,EAAW;QACzB,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACpD,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACnC,OAAO,EAAE,EAAE,CAAC;IACb,CAAC;IAED,IAAI,CAAC,GAAW;QACf,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACpD,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IAED,KAAK;QACJ,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QACxB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,GAAG;QACN,OAAO,IAAI,CAAC,EAAE,CAAC;IAChB,CAAC;CACD"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Store } from "./Store.js";
|
|
2
|
+
export interface ToolExecuteInput {
|
|
3
|
+
tool: string;
|
|
4
|
+
args?: Record<string, unknown>;
|
|
5
|
+
agent?: string;
|
|
6
|
+
sessionId?: string;
|
|
7
|
+
callID?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ToolExecuteOutput {
|
|
10
|
+
success?: boolean;
|
|
11
|
+
stdout?: string;
|
|
12
|
+
stderr?: string;
|
|
13
|
+
exitCode?: number;
|
|
14
|
+
}
|
|
15
|
+
export declare class ToolCallObserver {
|
|
16
|
+
private store;
|
|
17
|
+
private startTs;
|
|
18
|
+
constructor(store: Store);
|
|
19
|
+
onBefore(input: ToolExecuteInput, _output: ToolExecuteOutput): void;
|
|
20
|
+
onAfter(input: ToolExecuteInput, output: ToolExecuteOutput): void;
|
|
21
|
+
redactSecrets(text: string): string;
|
|
22
|
+
summarizeArgs(args: Record<string, unknown>): string;
|
|
23
|
+
inferErrorType(stderr: string, stdout: string, exitCode?: number): string;
|
|
24
|
+
private key;
|
|
25
|
+
private looksSecret;
|
|
26
|
+
private redactArgs;
|
|
27
|
+
private redactValue;
|
|
28
|
+
}
|