@jmtrin/opencode-kevin 0.1.1 → 0.1.2
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 +8 -3
- package/dist/plugin/MemoryService.js +24 -24
- package/dist/plugin/Retrospective.js +13 -12
- package/dist/plugin/Retrospective.js.map +1 -1
- package/dist/plugin/Store.js.map +1 -1
- package/dist/plugin/ToolCallObserver.js +2 -2
- package/dist/plugin/sqlite-adapter.js +56 -1
- package/dist/plugin/sqlite-adapter.js.map +1 -1
- package/package.json +48 -50
package/README.md
CHANGED
|
@@ -45,8 +45,13 @@ Migrations run automatically on startup.
|
|
|
45
45
|
|
|
46
46
|
### Requirements
|
|
47
47
|
|
|
48
|
-
- Node.js >=
|
|
49
|
-
- OpenCode with plugin support (`@opencode-ai/plugin` >= 1.17)
|
|
48
|
+
- **Node.js >= 22.5** (uses `node:sqlite`, the built-in SQLite module — no native binaries to compile).
|
|
49
|
+
- OpenCode with plugin support (`@opencode-ai/plugin` >= 1.17).
|
|
50
|
+
|
|
51
|
+
> **Runtimes**:
|
|
52
|
+
> - **Bun**: uses `bun:sqlite` (built-in).
|
|
53
|
+
> - **Node 24+**: uses `node:sqlite` directly, no flags needed (emits an experimental warning, harmless).
|
|
54
|
+
> - **Node 22/23 without `--experimental-sqlite` flag** or **Node 20**: falls back to `better-sqlite3`, declared as `optionalDependencies`. If you need it, install it manually in your opencode config directory (`~/.config/opencode/`): `npm install better-sqlite3`.
|
|
50
55
|
|
|
51
56
|
### Verification
|
|
52
57
|
|
|
@@ -226,7 +231,7 @@ npm publish --access public
|
|
|
226
231
|
```
|
|
227
232
|
plugin/
|
|
228
233
|
index.ts # Entry point: KevinPlugin
|
|
229
|
-
Store.ts # Wrapper better-sqlite3
|
|
234
|
+
Store.ts # Wrapper SQLite (node:sqlite / bun:sqlite / better-sqlite3 fallback)
|
|
230
235
|
Migrate.ts # Idempotent migrations
|
|
231
236
|
MemoryService.ts # save/query/getRelevant (FTS5 + bm25)
|
|
232
237
|
ToolCallObserver.ts # onBefore/onAfter + redact + inferErrorType
|
|
@@ -67,16 +67,16 @@ export class MemoryService {
|
|
|
67
67
|
expiresAt = sqliteUtcNowPlusHours(SESSION_DEFAULT_TTL_HOURS);
|
|
68
68
|
}
|
|
69
69
|
this.store
|
|
70
|
-
.prepare(`INSERT INTO memories
|
|
71
|
-
(id, type, content, scope, relevance_score, source_tool, source_session, metadata, expires_at)
|
|
70
|
+
.prepare(`INSERT INTO memories
|
|
71
|
+
(id, type, content, scope, relevance_score, source_tool, source_session, metadata, expires_at)
|
|
72
72
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
73
73
|
.run(id, input.type, input.content, scope, relevanceScore, input.sourceTool ?? null, input.sourceSession ?? null, metadata, expiresAt);
|
|
74
74
|
return id;
|
|
75
75
|
}
|
|
76
76
|
getById(id) {
|
|
77
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
|
|
78
|
+
.prepare(`SELECT id, type, content, scope, relevance_score, source_tool, source_session,
|
|
79
|
+
metadata, created_at, updated_at, expires_at
|
|
80
80
|
FROM memories WHERE id = ?`)
|
|
81
81
|
.get(id);
|
|
82
82
|
return row ? mapRow(row) : null;
|
|
@@ -125,14 +125,14 @@ export class MemoryService {
|
|
|
125
125
|
return [];
|
|
126
126
|
const scope = input.scope ?? "all";
|
|
127
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 ?
|
|
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
136
|
AND (m.expires_at IS NULL OR m.expires_at > datetime('now'))`;
|
|
137
137
|
const params = [match];
|
|
138
138
|
if (input.type) {
|
|
@@ -151,10 +151,10 @@ export class MemoryService {
|
|
|
151
151
|
.filter((m) => !isNotSearchable(m));
|
|
152
152
|
}
|
|
153
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
|
|
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
158
|
WHERE (expires_at IS NULL OR expires_at > datetime('now'))`;
|
|
159
159
|
const params = [];
|
|
160
160
|
if (scope !== "all") {
|
|
@@ -172,14 +172,14 @@ export class MemoryService {
|
|
|
172
172
|
if (tokens.length === 0)
|
|
173
173
|
return [];
|
|
174
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 ?
|
|
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
183
|
AND (m.expires_at IS NULL OR m.expires_at > datetime('now'))`;
|
|
184
184
|
const params = [match];
|
|
185
185
|
if (scope !== "all") {
|
|
@@ -9,7 +9,8 @@ export class Retrospective {
|
|
|
9
9
|
constructor(store, memoryService, options) {
|
|
10
10
|
this.store = store;
|
|
11
11
|
this.memoryService = memoryService;
|
|
12
|
-
this.retrospectivesDir =
|
|
12
|
+
this.retrospectivesDir =
|
|
13
|
+
options?.dir ?? join(homedir(), ".opencode-kevin", "retrospectives");
|
|
13
14
|
}
|
|
14
15
|
async generate(sessionId) {
|
|
15
16
|
const existing = this.store
|
|
@@ -18,10 +19,10 @@ export class Retrospective {
|
|
|
18
19
|
if (existing?.file_path)
|
|
19
20
|
return existing.file_path;
|
|
20
21
|
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
|
|
22
|
+
.prepare(`SELECT
|
|
23
|
+
SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) AS success_count,
|
|
24
|
+
SUM(CASE WHEN success = 0 THEN 1 ELSE 0 END) AS failure_count,
|
|
25
|
+
COUNT(*) AS total
|
|
25
26
|
FROM tool_calls WHERE session_id = ?`)
|
|
26
27
|
.get(sessionId);
|
|
27
28
|
const successCount = counts?.success_count ?? 0;
|
|
@@ -30,14 +31,14 @@ export class Retrospective {
|
|
|
30
31
|
if (failureCount === 0)
|
|
31
32
|
return null;
|
|
32
33
|
const failedTools = this.store
|
|
33
|
-
.prepare(`SELECT tool, args_summary, error_type
|
|
34
|
-
FROM tool_calls
|
|
35
|
-
WHERE session_id = ? AND success = 0
|
|
34
|
+
.prepare(`SELECT tool, args_summary, error_type
|
|
35
|
+
FROM tool_calls
|
|
36
|
+
WHERE session_id = ? AND success = 0
|
|
36
37
|
ORDER BY ts ASC`)
|
|
37
38
|
.all(sessionId);
|
|
38
39
|
const lessons = this.store
|
|
39
|
-
.prepare(`SELECT content FROM memories
|
|
40
|
-
WHERE type = 'error' AND source_session = ?
|
|
40
|
+
.prepare(`SELECT content FROM memories
|
|
41
|
+
WHERE type = 'error' AND source_session = ?
|
|
41
42
|
ORDER BY created_at ASC`)
|
|
42
43
|
.all(sessionId);
|
|
43
44
|
const md = this.buildMarkdown(sessionId, total, successCount, failureCount, failedTools, lessons);
|
|
@@ -46,8 +47,8 @@ export class Retrospective {
|
|
|
46
47
|
writeFileSync(filePath, md, "utf8");
|
|
47
48
|
const id = uuidv7();
|
|
48
49
|
this.store
|
|
49
|
-
.prepare(`INSERT OR IGNORE INTO retrospectives
|
|
50
|
-
(id, session_id, ts, failure_count, success_count, lessons_count, file_path, metadata)
|
|
50
|
+
.prepare(`INSERT OR IGNORE INTO retrospectives
|
|
51
|
+
(id, session_id, ts, failure_count, success_count, lessons_count, file_path, metadata)
|
|
51
52
|
VALUES (?, ?, datetime('now'), ?, ?, ?, ?, ?)`)
|
|
52
53
|
.run(id, sessionId, failureCount, successCount, lessons.length, filePath, null);
|
|
53
54
|
return filePath;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Retrospective.js","sourceRoot":"","sources":["../../plugin/Retrospective.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAsBnC,MAAM,OAAO,aAAa;IAIhB;IACA;IAJD,iBAAiB,CAAS;IAElC,YACS,KAAY,EACZ,aAA4B,EACpC,OAA8B;QAFtB,UAAK,GAAL,KAAK,CAAO;QACZ,kBAAa,GAAb,aAAa,CAAe;QAGpC,IAAI,CAAC,iBAAiB,
|
|
1
|
+
{"version":3,"file":"Retrospective.js","sourceRoot":"","sources":["../../plugin/Retrospective.ts"],"names":[],"mappings":"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"}
|
package/dist/plugin/Store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Store.js","sourceRoot":"","sources":["../../plugin/Store.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"Store.js","sourceRoot":"","sources":["../../plugin/Store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,cAAc,EAAE,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"}
|
|
@@ -30,8 +30,8 @@ export class ToolCallObserver {
|
|
|
30
30
|
: null;
|
|
31
31
|
const metadata = JSON.stringify(this.redactArgs(input.args ?? {}));
|
|
32
32
|
this.store
|
|
33
|
-
.prepare(`INSERT INTO tool_calls
|
|
34
|
-
(id, session_id, ts, tool, args_summary, success, duration_ms, agent, error_type, metadata)
|
|
33
|
+
.prepare(`INSERT INTO tool_calls
|
|
34
|
+
(id, session_id, ts, tool, args_summary, success, duration_ms, agent, error_type, metadata)
|
|
35
35
|
VALUES (?, ?, datetime('now'), ?, ?, ?, ?, ?, ?, ?)`)
|
|
36
36
|
.run(uuidv7(), sessionId, input.tool, argsSummary, success, durationMs, agent, errorType, metadata);
|
|
37
37
|
}
|
|
@@ -13,11 +13,66 @@ function loadBunDatabase(path) {
|
|
|
13
13
|
const mod = localRequire("bun:sqlite");
|
|
14
14
|
return new mod.Database(path);
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Wrapper sobre `node:sqlite` (DatabaseSync, estable en Node 24+).
|
|
18
|
+
* API equivalente a better-sqlite3 excepto `transaction`, que implementamos
|
|
19
|
+
* manualmente con BEGIN/COMMIT/ROLLBACK.
|
|
20
|
+
*/
|
|
21
|
+
class NodeSqliteAdapter {
|
|
22
|
+
db;
|
|
23
|
+
constructor(db) {
|
|
24
|
+
this.db = db;
|
|
25
|
+
}
|
|
26
|
+
prepare(sql) {
|
|
27
|
+
return this.db.prepare(sql);
|
|
28
|
+
}
|
|
29
|
+
exec(sql) {
|
|
30
|
+
this.db.exec(sql);
|
|
31
|
+
}
|
|
32
|
+
close() {
|
|
33
|
+
this.db.close();
|
|
34
|
+
}
|
|
35
|
+
transaction(fn) {
|
|
36
|
+
return () => {
|
|
37
|
+
this.db.exec("BEGIN");
|
|
38
|
+
try {
|
|
39
|
+
const result = fn();
|
|
40
|
+
this.db.exec("COMMIT");
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
try {
|
|
45
|
+
this.db.exec("ROLLBACK");
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// ignore rollback errors
|
|
49
|
+
}
|
|
50
|
+
throw err;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function loadNodeSqliteDatabase(path) {
|
|
56
|
+
const mod = localRequire("node:sqlite");
|
|
57
|
+
return new NodeSqliteAdapter(new mod.DatabaseSync(path));
|
|
58
|
+
}
|
|
59
|
+
function loadBetterSqliteDatabase(path) {
|
|
17
60
|
const D = localRequire("better-sqlite3");
|
|
18
61
|
const Ctor = "default" in D ? D.default : D;
|
|
19
62
|
return new Ctor(path);
|
|
20
63
|
}
|
|
64
|
+
function loadNodeDatabase(path) {
|
|
65
|
+
// 1) Prefer node:sqlite (built-in, sin binarios nativos que descargar).
|
|
66
|
+
// Estable en Node 24+ sin flag; en Node 22/23 requiere --experimental-sqlite.
|
|
67
|
+
// Si require falla (modulo ausente o flag deshabilitado), cae al fallback.
|
|
68
|
+
try {
|
|
69
|
+
return loadNodeSqliteDatabase(path);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// 2) Fallback a better-sqlite3 (Node 20 o Node 22/23 sin flag).
|
|
73
|
+
return loadBetterSqliteDatabase(path);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
21
76
|
export function createDatabase(path) {
|
|
22
77
|
if (detectRuntime() === "bun") {
|
|
23
78
|
return loadBunDatabase(path);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-adapter.js","sourceRoot":"","sources":["../../plugin/sqlite-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAezC,MAAM,YAAY,GAAG,aAAa,CACjC,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,QAAQ;IAClC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG;IACjB,CAAC,CAAC,aAAa,CAAC,UAAU,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAC5C,CAAC;AAEF,SAAS,aAAa;IACrB,IAAI,OAAQ,UAAgC,CAAC,GAAG,KAAK,WAAW,EAAE,CAAC;QAClE,OAAO,KAAK,CAAC;IACd,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACpC,MAAM,GAAG,GAAG,YAAY,CAAC,YAAY,CAEpC,CAAC;IACF,OAAO,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,
|
|
1
|
+
{"version":3,"file":"sqlite-adapter.js","sourceRoot":"","sources":["../../plugin/sqlite-adapter.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,50 +1,48 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@jmtrin/opencode-kevin",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Kevin — Observa y aprende: capa de aprendizaje para OpenCode",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "dist/plugin/index.js",
|
|
7
|
-
"exports": {
|
|
8
|
-
".": {
|
|
9
|
-
"import": "./dist/plugin/index.js",
|
|
10
|
-
"types": "./dist/plugin/index.d.ts"
|
|
11
|
-
}
|
|
12
|
-
},
|
|
13
|
-
"files": [
|
|
14
|
-
|
|
15
|
-
"dist/migrations",
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
},
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"@
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"license": "MIT"
|
|
50
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@jmtrin/opencode-kevin",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Kevin — Observa y aprende: capa de aprendizaje para OpenCode",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/plugin/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/plugin/index.js",
|
|
10
|
+
"types": "./dist/plugin/index.d.ts"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": ["dist/plugin", "dist/migrations", "migrations"],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc --outDir dist && node scripts/copy-migrations.mjs",
|
|
16
|
+
"prepublishOnly": "npm run build",
|
|
17
|
+
"test": "vitest run",
|
|
18
|
+
"test:unit": "vitest run tests/unit",
|
|
19
|
+
"test:integration": "vitest run tests/integration",
|
|
20
|
+
"test:e2e": "vitest run tests/e2e",
|
|
21
|
+
"typecheck": "tsc --noEmit",
|
|
22
|
+
"lint": "biome check .",
|
|
23
|
+
"format": "biome format --write .",
|
|
24
|
+
"verify": "node --import tsx scripts/verify-install.ts"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@opencode-ai/plugin": "^1.17.6",
|
|
28
|
+
"zod": "^3.23.8"
|
|
29
|
+
},
|
|
30
|
+
"optionalDependencies": {
|
|
31
|
+
"better-sqlite3": "^12.11.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@biomejs/biome": "^1.9.4",
|
|
35
|
+
"@types/better-sqlite3": "^7.6.12",
|
|
36
|
+
"@types/node": "^22.10.0",
|
|
37
|
+
"tsx": "^4.19.0",
|
|
38
|
+
"typescript": "^5.7.2",
|
|
39
|
+
"vitest": "^2.1.8"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=22.5.0"
|
|
43
|
+
},
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
},
|
|
47
|
+
"license": "MIT"
|
|
48
|
+
}
|