context-mode 0.9.9 → 0.9.10
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 +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/build/cli.js +19 -82
- package/hooks/pretooluse.mjs +38 -0
- package/package.json +1 -1
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"name": "context-mode",
|
|
14
14
|
"source": "./",
|
|
15
15
|
"description": "Claude Code MCP plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
|
|
16
|
-
"version": "0.9.
|
|
16
|
+
"version": "0.9.10",
|
|
17
17
|
"author": {
|
|
18
18
|
"name": "Mert Koseoğlu"
|
|
19
19
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "context-mode",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.10",
|
|
4
4
|
"description": "Claude Code MCP plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Mert Koseoğlu",
|
package/build/cli.js
CHANGED
|
@@ -390,11 +390,13 @@ async function upgrade() {
|
|
|
390
390
|
timeout: 30000,
|
|
391
391
|
});
|
|
392
392
|
s.stop("Built successfully");
|
|
393
|
-
// Step 3:
|
|
393
|
+
// Step 3: Update in-place (same directory, no registry changes needed)
|
|
394
|
+
s.start("Updating files in-place");
|
|
395
|
+
// Clean stale version dirs from previous upgrade attempts
|
|
394
396
|
const cacheParentMatch = pluginRoot.match(/^(.*[\\/]plugins[\\/]cache[\\/][^\\/]+[\\/][^\\/]+[\\/])/);
|
|
395
397
|
if (cacheParentMatch) {
|
|
396
398
|
const cacheParent = cacheParentMatch[1];
|
|
397
|
-
const myDir = pluginRoot.replace(cacheParent, "");
|
|
399
|
+
const myDir = pluginRoot.replace(cacheParent, "").replace(/[\\/]/g, "");
|
|
398
400
|
try {
|
|
399
401
|
const oldDirs = readdirSync(cacheParent).filter(d => d !== myDir);
|
|
400
402
|
for (const d of oldDirs) {
|
|
@@ -404,37 +406,25 @@ async function upgrade() {
|
|
|
404
406
|
catch { /* skip */ }
|
|
405
407
|
}
|
|
406
408
|
if (oldDirs.length > 0) {
|
|
407
|
-
p.log.info(color.dim(` Cleaned ${oldDirs.length}
|
|
409
|
+
p.log.info(color.dim(` Cleaned ${oldDirs.length} stale cache dir(s)`));
|
|
408
410
|
}
|
|
409
411
|
}
|
|
410
412
|
catch { /* parent may not exist */ }
|
|
411
413
|
}
|
|
412
|
-
|
|
413
|
-
const
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
}
|
|
422
|
-
else {
|
|
423
|
-
// Same dir — copy files in-place
|
|
424
|
-
const items = [
|
|
425
|
-
"build", "src", "hooks", "skills", ".claude-plugin",
|
|
426
|
-
"start.mjs", "server.bundle.mjs", "package.json", ".mcp.json",
|
|
427
|
-
];
|
|
428
|
-
for (const item of items) {
|
|
429
|
-
try {
|
|
430
|
-
rmSync(resolve(pluginRoot, item), { recursive: true, force: true });
|
|
431
|
-
cpSync(resolve(srcDir, item), resolve(pluginRoot, item), { recursive: true });
|
|
432
|
-
}
|
|
433
|
-
catch { /* some files may not exist */ }
|
|
414
|
+
// Copy new files over old ones — same path, no registry update needed
|
|
415
|
+
const items = [
|
|
416
|
+
"build", "src", "hooks", "skills", ".claude-plugin",
|
|
417
|
+
"start.mjs", "server.bundle.mjs", "package.json", ".mcp.json",
|
|
418
|
+
];
|
|
419
|
+
for (const item of items) {
|
|
420
|
+
try {
|
|
421
|
+
rmSync(resolve(pluginRoot, item), { recursive: true, force: true });
|
|
422
|
+
cpSync(resolve(srcDir, item), resolve(pluginRoot, item), { recursive: true });
|
|
434
423
|
}
|
|
424
|
+
catch { /* some files may not exist in source */ }
|
|
435
425
|
}
|
|
436
|
-
s.stop(color.green(`
|
|
437
|
-
// Install production deps
|
|
426
|
+
s.stop(color.green(`Updated in-place to v${newVersion}`));
|
|
427
|
+
// Install production deps (rebuild native modules if needed)
|
|
438
428
|
s.start("Installing production dependencies");
|
|
439
429
|
execSync("npm install --production --no-audit --no-fund", {
|
|
440
430
|
cwd: pluginRoot,
|
|
@@ -442,58 +432,6 @@ async function upgrade() {
|
|
|
442
432
|
timeout: 60000,
|
|
443
433
|
});
|
|
444
434
|
s.stop("Dependencies ready");
|
|
445
|
-
// Step 4: Update installed_plugins.json via spawned script (works from any old version)
|
|
446
|
-
s.start("Updating plugin registry");
|
|
447
|
-
try {
|
|
448
|
-
const scriptPath = resolve(tmpDir + "-post-upgrade.mjs");
|
|
449
|
-
const scriptContent = [
|
|
450
|
-
`import { readFileSync, writeFileSync } from "fs";`,
|
|
451
|
-
`import { resolve } from "path";`,
|
|
452
|
-
`import { homedir } from "os";`,
|
|
453
|
-
`const pluginRoot = ${JSON.stringify(pluginRoot)};`,
|
|
454
|
-
`const newVersion = ${JSON.stringify(newVersion)};`,
|
|
455
|
-
`const ipPath = resolve(homedir(), ".claude", "plugins", "installed_plugins.json");`,
|
|
456
|
-
`try {`,
|
|
457
|
-
` const ipRaw = JSON.parse(readFileSync(ipPath, "utf-8"));`,
|
|
458
|
-
` const plugins = ipRaw.plugins || {};`,
|
|
459
|
-
` let updated = false;`,
|
|
460
|
-
` for (const [key, entries] of Object.entries(plugins)) {`,
|
|
461
|
-
` if (!key.toLowerCase().includes("context-mode")) continue;`,
|
|
462
|
-
` for (const entry of entries) {`,
|
|
463
|
-
` entry.installPath = pluginRoot;`,
|
|
464
|
-
` entry.version = newVersion;`,
|
|
465
|
-
` entry.lastUpdated = new Date().toISOString();`,
|
|
466
|
-
` updated = true;`,
|
|
467
|
-
` }`,
|
|
468
|
-
` }`,
|
|
469
|
-
` if (updated) {`,
|
|
470
|
-
` writeFileSync(ipPath, JSON.stringify(ipRaw, null, 2) + "\\n", "utf-8");`,
|
|
471
|
-
` console.log("REGISTRY_UPDATED");`,
|
|
472
|
-
` }`,
|
|
473
|
-
`} catch (e) { console.error("REGISTRY_FAILED:" + e.message); }`,
|
|
474
|
-
].join("\n");
|
|
475
|
-
writeFileSync(scriptPath, scriptContent, "utf-8");
|
|
476
|
-
const result = execSync(`node ${scriptPath}`, {
|
|
477
|
-
stdio: "pipe",
|
|
478
|
-
timeout: 10000,
|
|
479
|
-
encoding: "utf-8",
|
|
480
|
-
});
|
|
481
|
-
try {
|
|
482
|
-
rmSync(scriptPath, { force: true });
|
|
483
|
-
}
|
|
484
|
-
catch { /* ignore */ }
|
|
485
|
-
if (result.includes("REGISTRY_UPDATED")) {
|
|
486
|
-
s.stop(color.green("Plugin registry updated"));
|
|
487
|
-
changes.push("Updated plugin registry");
|
|
488
|
-
}
|
|
489
|
-
else {
|
|
490
|
-
s.stop(color.yellow("Plugin registry unchanged"));
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
catch (err) {
|
|
494
|
-
s.stop(color.yellow("Plugin registry update skipped"));
|
|
495
|
-
p.log.warn(color.yellow("Could not update plugin registry") + color.dim(` — ${err instanceof Error ? err.message : String(err)}`));
|
|
496
|
-
}
|
|
497
435
|
// Update global npm package from same GitHub source
|
|
498
436
|
s.start("Updating npm global package");
|
|
499
437
|
try {
|
|
@@ -608,12 +546,11 @@ async function upgrade() {
|
|
|
608
546
|
else {
|
|
609
547
|
p.log.info(color.dim("No changes were needed."));
|
|
610
548
|
}
|
|
611
|
-
// Step 7: Run doctor from
|
|
549
|
+
// Step 7: Run doctor from updated pluginRoot
|
|
612
550
|
p.log.step("Running doctor to verify...");
|
|
613
551
|
console.log();
|
|
614
552
|
try {
|
|
615
|
-
|
|
616
|
-
execSync(`node "${doctorScript}" doctor`, {
|
|
553
|
+
execSync(`node "${resolve(pluginRoot, "build", "cli.js")}" doctor`, {
|
|
617
554
|
stdio: "inherit",
|
|
618
555
|
timeout: 30000,
|
|
619
556
|
cwd: pluginRoot,
|
package/hooks/pretooluse.mjs
CHANGED
|
@@ -6,6 +6,44 @@
|
|
|
6
6
|
* Cross-platform (Windows/macOS/Linux) — no bash/jq dependency.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { readFileSync, writeFileSync, existsSync } from "node:fs";
|
|
10
|
+
import { resolve, dirname, basename } from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
import { homedir, tmpdir } from "node:os";
|
|
13
|
+
|
|
14
|
+
// ─── Self-heal registry (runs once per session via marker file) ───
|
|
15
|
+
try {
|
|
16
|
+
const marker = resolve(tmpdir(), "context-mode-registry-healed");
|
|
17
|
+
if (!existsSync(marker)) {
|
|
18
|
+
const hookDir = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
const myRoot = resolve(hookDir, "..");
|
|
20
|
+
const myVersion = basename(myRoot);
|
|
21
|
+
|
|
22
|
+
if (/^\d+\.\d+\.\d+/.test(myVersion)) {
|
|
23
|
+
const ipPath = resolve(homedir(), ".claude", "plugins", "installed_plugins.json");
|
|
24
|
+
const ip = JSON.parse(readFileSync(ipPath, "utf-8"));
|
|
25
|
+
let fixed = false;
|
|
26
|
+
|
|
27
|
+
for (const [key, entries] of Object.entries(ip.plugins || {})) {
|
|
28
|
+
if (!key.toLowerCase().includes("context-mode")) continue;
|
|
29
|
+
for (const entry of entries) {
|
|
30
|
+
if (entry.installPath !== myRoot) {
|
|
31
|
+
entry.installPath = myRoot;
|
|
32
|
+
entry.version = myVersion;
|
|
33
|
+
entry.lastUpdated = new Date().toISOString();
|
|
34
|
+
fixed = true;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (fixed) {
|
|
40
|
+
writeFileSync(ipPath, JSON.stringify(ip, null, 2) + "\n", "utf-8");
|
|
41
|
+
}
|
|
42
|
+
writeFileSync(marker, Date.now().toString(), "utf-8");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
} catch { /* best effort — don't block hook */ }
|
|
46
|
+
|
|
9
47
|
let raw = "";
|
|
10
48
|
process.stdin.setEncoding("utf-8");
|
|
11
49
|
for await (const chunk of process.stdin) raw += chunk;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "context-mode",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Claude Code MCP plugin that saves 98% of your context window. Sandboxed code execution, FTS5 knowledge base, and intent-driven search.",
|
|
6
6
|
"author": "Mert Koseoğlu",
|