context-mode 1.0.75 → 1.0.76
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/.mcp.json +1 -1
- package/.openclaw-plugin/openclaw.plugin.json +1 -1
- package/.openclaw-plugin/package.json +1 -1
- package/README.md +33 -2
- package/build/adapters/claude-code/hooks.d.ts +11 -1
- package/build/adapters/claude-code/hooks.js +31 -1
- package/build/db-base.d.ts +32 -1
- package/build/db-base.js +162 -10
- package/build/lifecycle.d.ts +5 -2
- package/build/lifecycle.js +4 -11
- package/build/server.js +51 -26
- package/build/session/db.js +1 -1
- package/build/store.js +25 -3
- package/cli.bundle.mjs +93 -93
- package/configs/antigravity/GEMINI.md +1 -1
- package/configs/claude-code/CLAUDE.md +1 -1
- package/configs/codex/AGENTS.md +1 -1
- package/configs/gemini-cli/GEMINI.md +1 -1
- package/configs/kilo/AGENTS.md +1 -1
- package/configs/kiro/KIRO.md +1 -1
- package/configs/openclaw/AGENTS.md +1 -1
- package/configs/opencode/AGENTS.md +1 -1
- package/configs/pi/AGENTS.md +1 -1
- package/configs/vscode-copilot/copilot-instructions.md +1 -1
- package/configs/zed/AGENTS.md +1 -1
- package/hooks/codex/posttooluse.mjs +6 -5
- package/hooks/codex/sessionstart.mjs +5 -5
- package/hooks/core/mcp-ready.mjs +31 -0
- package/hooks/core/routing.mjs +27 -12
- package/hooks/cursor/posttooluse.mjs +6 -5
- package/hooks/cursor/sessionstart.mjs +5 -5
- package/hooks/cursor/stop.mjs +5 -4
- package/hooks/ensure-deps.mjs +38 -27
- package/hooks/gemini-cli/aftertool.mjs +5 -4
- package/hooks/gemini-cli/precompress.mjs +5 -4
- package/hooks/gemini-cli/sessionstart.mjs +5 -4
- package/hooks/hooks.json +13 -22
- package/hooks/kiro/posttooluse.mjs +6 -5
- package/hooks/routing-block.mjs +6 -2
- package/hooks/session-db.bundle.mjs +12 -12
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/server.bundle.mjs +73 -73
- package/.claude-plugin/hooks/hooks.json +0 -132
package/build/server.js
CHANGED
|
@@ -1602,38 +1602,51 @@ server.registerTool("ctx_doctor", {
|
|
|
1602
1602
|
else {
|
|
1603
1603
|
lines.push("- [-] Performance: NORMAL — install Bun for 3-5x speed boost");
|
|
1604
1604
|
}
|
|
1605
|
-
// Server test
|
|
1606
|
-
|
|
1605
|
+
// Server test — cleanup executor to prevent resource leaks (#247)
|
|
1606
|
+
{
|
|
1607
1607
|
const testExecutor = new PolyglotExecutor({ runtimes });
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1608
|
+
try {
|
|
1609
|
+
const result = await testExecutor.execute({ language: "javascript", code: 'console.log("ok");', timeout: 5000 });
|
|
1610
|
+
if (result.exitCode === 0 && result.stdout.trim() === "ok") {
|
|
1611
|
+
lines.push("- [x] Server test: PASS");
|
|
1612
|
+
}
|
|
1613
|
+
else {
|
|
1614
|
+
const detail = result.stderr?.trim() ? ` (${result.stderr.trim().slice(0, 200)})` : "";
|
|
1615
|
+
lines.push(`- [ ] Server test: FAIL — exit ${result.exitCode}${detail}`);
|
|
1616
|
+
}
|
|
1611
1617
|
}
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1618
|
+
catch (err) {
|
|
1619
|
+
lines.push(`- [ ] Server test: FAIL — ${err instanceof Error ? err.message : err}`);
|
|
1620
|
+
}
|
|
1621
|
+
finally {
|
|
1622
|
+
testExecutor.cleanupBackgrounded();
|
|
1615
1623
|
}
|
|
1616
1624
|
}
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1625
|
+
// FTS5 / SQLite — close in finally to prevent GC segfault (#247)
|
|
1626
|
+
{
|
|
1627
|
+
let testDb;
|
|
1628
|
+
try {
|
|
1629
|
+
const Database = loadDatabase();
|
|
1630
|
+
testDb = new Database(":memory:");
|
|
1631
|
+
testDb.exec("CREATE VIRTUAL TABLE fts_test USING fts5(content)");
|
|
1632
|
+
testDb.exec("INSERT INTO fts_test(content) VALUES ('hello world')");
|
|
1633
|
+
const row = testDb.prepare("SELECT * FROM fts_test WHERE fts_test MATCH 'hello'").get();
|
|
1634
|
+
if (row && row.content === "hello world") {
|
|
1635
|
+
lines.push("- [x] FTS5 / SQLite: PASS — native module works");
|
|
1636
|
+
}
|
|
1637
|
+
else {
|
|
1638
|
+
lines.push("- [ ] FTS5 / SQLite: FAIL — unexpected result");
|
|
1639
|
+
}
|
|
1630
1640
|
}
|
|
1631
|
-
|
|
1632
|
-
lines.push(
|
|
1641
|
+
catch (err) {
|
|
1642
|
+
lines.push(`- [ ] FTS5 / SQLite: FAIL — ${err instanceof Error ? err.message : err}`);
|
|
1643
|
+
}
|
|
1644
|
+
finally {
|
|
1645
|
+
try {
|
|
1646
|
+
testDb?.close();
|
|
1647
|
+
}
|
|
1648
|
+
catch { /* best effort */ }
|
|
1633
1649
|
}
|
|
1634
|
-
}
|
|
1635
|
-
catch (err) {
|
|
1636
|
-
lines.push(`- [ ] FTS5 / SQLite: FAIL — ${err instanceof Error ? err.message : err}`);
|
|
1637
1650
|
}
|
|
1638
1651
|
// Hook script
|
|
1639
1652
|
const hookPath = resolve(pluginRoot, "hooks", "pretooluse.mjs");
|
|
@@ -1849,6 +1862,8 @@ async function main() {
|
|
|
1849
1862
|
if (cleaned > 0) {
|
|
1850
1863
|
console.error(`Cleaned up ${cleaned} stale DB file(s) from previous sessions`);
|
|
1851
1864
|
}
|
|
1865
|
+
// MCP readiness sentinel path (#230)
|
|
1866
|
+
const mcpSentinel = join(tmpdir(), `context-mode-mcp-ready-${process.ppid}`);
|
|
1852
1867
|
// Clean up own DB + backgrounded processes + preload script on shutdown
|
|
1853
1868
|
const shutdown = () => {
|
|
1854
1869
|
executor.cleanupBackgrounded();
|
|
@@ -1858,6 +1873,11 @@ async function main() {
|
|
|
1858
1873
|
unlinkSync(CM_FS_PRELOAD);
|
|
1859
1874
|
}
|
|
1860
1875
|
catch { /* best effort */ }
|
|
1876
|
+
// Remove MCP readiness sentinel (#230)
|
|
1877
|
+
try {
|
|
1878
|
+
unlinkSync(mcpSentinel);
|
|
1879
|
+
}
|
|
1880
|
+
catch { /* best effort */ }
|
|
1861
1881
|
};
|
|
1862
1882
|
const gracefulShutdown = async () => {
|
|
1863
1883
|
shutdown();
|
|
@@ -1870,6 +1890,11 @@ async function main() {
|
|
|
1870
1890
|
startLifecycleGuard({ onShutdown: () => gracefulShutdown() });
|
|
1871
1891
|
const transport = new StdioServerTransport();
|
|
1872
1892
|
await server.connect(transport);
|
|
1893
|
+
// Write MCP readiness sentinel (#230)
|
|
1894
|
+
try {
|
|
1895
|
+
writeFileSync(mcpSentinel, String(process.pid));
|
|
1896
|
+
}
|
|
1897
|
+
catch { /* best effort */ }
|
|
1873
1898
|
// Detect platform adapter — stored for platform-aware session paths
|
|
1874
1899
|
try {
|
|
1875
1900
|
const { detectPlatform, getAdapter } = await import("./adapters/detect.js");
|
package/build/session/db.js
CHANGED
|
@@ -225,7 +225,7 @@ export class SessionDB extends SQLiteBase {
|
|
|
225
225
|
// Update meta if session exists
|
|
226
226
|
this.stmt(S.updateMetaLastEvent).run(sessionId);
|
|
227
227
|
});
|
|
228
|
-
transaction();
|
|
228
|
+
this.withRetry(() => transaction());
|
|
229
229
|
}
|
|
230
230
|
/**
|
|
231
231
|
* Retrieve events for a session with optional filtering.
|
package/build/store.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Use for documentation, API references, and any content where
|
|
8
8
|
* you need EXACT text later — not summaries.
|
|
9
9
|
*/
|
|
10
|
-
import { loadDatabase, applyWALPragmas, closeDB, withRetry } from "./db-base.js";
|
|
10
|
+
import { loadDatabase, applyWALPragmas, closeDB, cleanOrphanedWALFiles, withRetry, deleteDBFiles, isSQLiteCorruptionError } from "./db-base.js";
|
|
11
11
|
import { readFileSync, readdirSync, unlinkSync, existsSync, statSync } from "node:fs";
|
|
12
12
|
import { tmpdir } from "node:os";
|
|
13
13
|
import { join } from "node:path";
|
|
@@ -267,8 +267,30 @@ export class ContentStore {
|
|
|
267
267
|
const Database = loadDatabase();
|
|
268
268
|
this.#dbPath =
|
|
269
269
|
dbPath ?? join(tmpdir(), `context-mode-${process.pid}.db`);
|
|
270
|
-
|
|
271
|
-
|
|
270
|
+
cleanOrphanedWALFiles(this.#dbPath);
|
|
271
|
+
let db;
|
|
272
|
+
try {
|
|
273
|
+
db = new Database(this.#dbPath, { timeout: 30000 });
|
|
274
|
+
applyWALPragmas(db);
|
|
275
|
+
}
|
|
276
|
+
catch (err) {
|
|
277
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
278
|
+
if (isSQLiteCorruptionError(msg)) {
|
|
279
|
+
deleteDBFiles(this.#dbPath);
|
|
280
|
+
cleanOrphanedWALFiles(this.#dbPath);
|
|
281
|
+
try {
|
|
282
|
+
db = new Database(this.#dbPath, { timeout: 30000 });
|
|
283
|
+
applyWALPragmas(db);
|
|
284
|
+
}
|
|
285
|
+
catch (retryErr) {
|
|
286
|
+
throw new Error(`Failed to create fresh DB after deleting corrupt file: ${retryErr instanceof Error ? retryErr.message : String(retryErr)}`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
throw err;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
this.#db = db;
|
|
272
294
|
this.#initSchema();
|
|
273
295
|
this.#prepareStatements();
|
|
274
296
|
}
|