context-mode 1.0.164 → 1.0.165

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.
@@ -6,14 +6,14 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Claude Code plugins by Mert Koseoğlu",
9
- "version": "1.0.164"
9
+ "version": "1.0.165"
10
10
  },
11
11
  "plugins": [
12
12
  {
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": "1.0.164",
16
+ "version": "1.0.165",
17
17
  "author": {
18
18
  "name": "Mert Koseoğlu"
19
19
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "1.0.164",
3
+ "version": "1.0.165",
4
4
  "description": "MCP server that saves 98% of your context window with session continuity. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and automatic state restore across compactions.",
5
5
  "author": {
6
6
  "name": "Mert Koseoğlu",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "1.0.164",
3
+ "version": "1.0.165",
4
4
  "description": "MCP server that saves 98% of your context window with session continuity. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and automatic state restore across compactions.",
5
5
  "author": {
6
6
  "name": "Mert Koseoğlu",
@@ -3,7 +3,7 @@
3
3
  "name": "Context Mode",
4
4
  "kind": "tool",
5
5
  "description": "OpenClaw plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
6
- "version": "1.0.164",
6
+ "version": "1.0.165",
7
7
  "sandbox": {
8
8
  "mode": "permissive",
9
9
  "filesystem_access": "full",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "1.0.164",
3
+ "version": "1.0.165",
4
4
  "description": "OpenClaw 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",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "1.0.164",
3
+ "version": "1.0.165",
4
4
  "description": "context-mode for Antigravity CLI (agy): sandboxed code execution, FTS5 knowledge base, and session capture. Saves your context window by keeping raw bytes out of the conversation.",
5
5
  "author": {
6
6
  "name": "Mert Koseoğlu",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "context-mode",
3
3
  "description": "context-mode for GitHub Copilot CLI: sandboxed code execution in 11 languages, an FTS5 knowledge base with BM25 ranking, and session capture. Saves your context window by keeping raw bytes out of the conversation.",
4
- "version": "1.0.164",
4
+ "version": "1.0.165",
5
5
  "keywords": [
6
6
  "mcp",
7
7
  "context-window",
@@ -3,7 +3,7 @@
3
3
  "name": "Context Mode",
4
4
  "kind": "tool",
5
5
  "description": "OpenClaw plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
6
- "version": "1.0.164",
6
+ "version": "1.0.165",
7
7
  "sandbox": {
8
8
  "mode": "permissive",
9
9
  "filesystem_access": "full",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "1.0.164",
3
+ "version": "1.0.165",
4
4
  "type": "module",
5
5
  "description": "MCP plugin that saves 98% of your context window. Works with Claude Code, Gemini CLI, VS Code Copilot, OpenCode, and Codex CLI. Sandboxed code execution, FTS5 knowledge base, and intent-driven search.",
6
6
  "author": "Mert Koseoğlu",
package/start.mjs CHANGED
@@ -77,18 +77,60 @@ if (typeof globalThis.Bun === "undefined" && process.platform === "linux") {
77
77
  stdio: ["pipe", "inherit", "inherit"],
78
78
  env: process.env,
79
79
  });
80
+ const _keepAlive = setInterval(() => {}, 2147483647);
81
+ let _escTerm;
82
+ let _escKill;
83
+ let _tearingDown = false;
84
+ // #862: propagate parent death to the Bun child. When the MCP client (e.g.
85
+ // Claude Code) exits, its end of our stdin pipe closes. The original proxy
86
+ // ignored that ("end" was a no-op) and parked forever — so the child was
87
+ // never told the session was gone: its stdin (this pipe) stayed open and its
88
+ // direct parent (us) stayed alive, defeating BOTH paths of the child's
89
+ // lifecycle guard (the stdio-EOF assist AND the ppid poll). The pair
90
+ // orphaned to init and pinned a CPU core indefinitely. We now forward EOF
91
+ // (graceful self-reap via the child's own watchdog), then escalate
92
+ // SIGTERM → SIGKILL so a wedged child can never outlive its client. Still
93
+ // re-execs under Bun first, so #564's SIGSEGV avoidance is untouched.
94
+ const teardown = () => {
95
+ if (_tearingDown) return;
96
+ _tearingDown = true;
97
+ clearInterval(_keepAlive);
98
+ try {
99
+ if (child.stdin && !child.stdin.destroyed) child.stdin.end();
100
+ } catch {}
101
+ // NOT unref'd: these short-lived timers are what hold the event loop
102
+ // open through the teardown window (≤5 s). Liveness must not depend on
103
+ // the top-level `await new Promise()` below surviving a future refactor
104
+ // — if escalation is ever skipped, #862's orphan returns. child.on(
105
+ // "exit") clears both the instant the child reaps cleanly.
106
+ _escTerm = setTimeout(() => {
107
+ try {
108
+ child.kill("SIGTERM");
109
+ } catch {}
110
+ }, 2000);
111
+ _escKill = setTimeout(() => {
112
+ try {
113
+ child.kill("SIGKILL");
114
+ } catch {}
115
+ process.exit(0);
116
+ }, 5000);
117
+ };
80
118
  process.stdin.on("data", (chunk) => {
81
119
  if (!child.stdin.destroyed) child.stdin.write(chunk);
82
120
  });
83
- process.stdin.on("end", () => {});
84
- const _keepAlive = setInterval(() => {}, 2147483647);
121
+ // EOF, pipe close, or pipe error all mean the client is gone — tear down.
122
+ process.stdin.on("end", teardown);
123
+ process.stdin.on("close", teardown);
124
+ process.stdin.on("error", teardown);
85
125
  child.on("exit", (code) => {
86
126
  clearInterval(_keepAlive);
127
+ if (_escTerm) clearTimeout(_escTerm);
128
+ if (_escKill) clearTimeout(_escKill);
87
129
  process.exit(code ?? 0);
88
130
  });
89
131
  // Prevent rest of start.mjs from running — child owns the MCP session.
90
132
  process.stdin.resume();
91
- await new Promise(() => {}); // park this process forever
133
+ await new Promise(() => {}); // park until the child exits (see child 'exit')
92
134
  }
93
135
  }
94
136
 
@@ -445,21 +487,51 @@ import "./hooks/ensure-deps.mjs";
445
487
  const NPM_INSTALL_BG_PKGS = ["turndown", "turndown-plugin-gfm", "@mixmark-io/domino"];
446
488
  const IS_WIN32 = process.platform === "win32";
447
489
  const NPM_BIN = IS_WIN32 ? "npm.cmd" : "npm";
490
+ const NPM_FLAGS = ["--no-package-lock", "--no-save", "--silent", "--no-audit", "--no-fund"];
491
+ // #861: on Windows the npm shim is `npm.cmd`, which needs `shell: true` to
492
+ // run — but Node DROPS the `cwd` option when `shell: true`, so the spawned
493
+ // cmd.exe inherits an arbitrary working dir (C:\Windows under Claude Code).
494
+ // `npm install` then tries to create `C:\Windows\node_modules` → EPERM on
495
+ // every boot, and a cmd.exe window flashes each time. Prefer running npm's
496
+ // own CLI through node directly (no `.cmd` shim, no shell): `shell: false`
497
+ // honors `cwd` and `windowsHide` suppresses the console window. Fall back to
498
+ // the shim only when npm-cli.js can't be located, so a working host (e.g. a
499
+ // POSIX layout where npm-cli.js isn't beside node) can never regress.
500
+ const NPM_CLI_JS = resolve(dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js");
501
+ const useNodeCli = existsSync(NPM_CLI_JS);
448
502
  for (const pkg of NPM_INSTALL_BG_PKGS) {
449
503
  if (existsSync(resolve(__dirname, "node_modules", pkg))) continue;
450
504
  try {
451
- const child = spawn(
452
- NPM_BIN,
453
- ["install", pkg, "--no-package-lock", "--no-save", "--silent", "--no-audit", "--no-fund"],
454
- {
455
- cwd: __dirname,
456
- stdio: "ignore",
457
- detached: true,
458
- // npm on Windows ships as a `.cmd` shim — must go through cmd.exe.
459
- shell: IS_WIN32,
460
- },
461
- );
462
- child.on("error", () => { /* best effort — npm missing, broken cache, etc. */ });
505
+ const child = useNodeCli
506
+ ? spawn(process.execPath, [NPM_CLI_JS, "install", pkg, ...NPM_FLAGS], {
507
+ cwd: __dirname,
508
+ stdio: "ignore",
509
+ detached: true,
510
+ shell: false,
511
+ windowsHide: true,
512
+ })
513
+ : spawn(NPM_BIN, ["install", pkg, ...NPM_FLAGS], {
514
+ cwd: __dirname,
515
+ stdio: "ignore",
516
+ detached: true,
517
+ // npm on Windows ships as a `.cmd` shim — must go through cmd.exe.
518
+ shell: IS_WIN32,
519
+ windowsHide: true,
520
+ });
521
+ // #861: this EPERM was invisible for months behind stdio:"ignore" + an
522
+ // empty error handler. Surface both spawn failures and non-zero exits.
523
+ child.on("error", (err) => {
524
+ process.stderr.write(
525
+ `[context-mode] background install of ${pkg} failed to spawn: ${err?.message ?? err}\n`,
526
+ );
527
+ });
528
+ child.on("exit", (code) => {
529
+ if (code) {
530
+ process.stderr.write(
531
+ `[context-mode] background install of ${pkg} exited with code ${code}\n`,
532
+ );
533
+ }
534
+ });
463
535
  child.unref();
464
536
  } catch { /* best effort — never block MCP boot */ }
465
537
  }