@mxalbert/context-mode 2.0.0 → 2.0.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.
@@ -6,14 +6,14 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Claude Code plugins by Mert Koseoğlu",
9
- "version": "2.0.0"
9
+ "version": "2.0.1"
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": "2.0.0",
16
+ "version": "2.0.1",
17
17
  "author": {
18
18
  "name": "Mert Koseoğlu"
19
19
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
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": "2.0.0",
3
+ "version": "2.0.1",
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": "2.0.0",
6
+ "version": "2.0.1",
7
7
  "sandbox": {
8
8
  "mode": "permissive",
9
9
  "filesystem_access": "full",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mxalbert/context-mode",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
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",
package/README.md CHANGED
@@ -483,13 +483,7 @@ Full configs: [`configs/cursor/hooks.json`](configs/cursor/hooks.json) | [`confi
483
483
 
484
484
  The `plugin` entry registers all 11 `ctx_*` tools natively and enables hooks — OpenCode calls context-mode's TypeScript plugin in-process, so there is no redundant stdio MCP child per session.
485
485
 
486
- 2. *(Optional)* Copy the routing rules file:
487
-
488
- ```bash
489
- cp node_modules/context-mode/configs/opencode/AGENTS.md AGENTS.md
490
- ```
491
-
492
- The plugin already injects its routing guidance (which tools to use, which commands are blocked and why) into the system prompt on every model dispatch — on both opencode v1 and v2. The copy is only useful if you want the same guidance also visible as native project rules (`AGENTS.md`) for sessions without the plugin. Your own `AGENTS.md`/`CLAUDE.md`/`CONTEXT.md` rules are captured automatically for session continuity — no copy needed.
486
+ 2. **No AGENTS.md copy needed.** The plugin injects the FULL routing mandate — Think in Code, BLOCKED/REDIRECTED commands, tool selection, memory tables (the complete [`configs/opencode/AGENTS.md`](configs/opencode/AGENTS.md) content, verbatim) — into the system prompt on every model dispatch. An existing copy stays harmless: OpenCode loads a project `AGENTS.md` natively as active project rules, and the plugin auto-skips its own injection when the project file's content matches the shipped template (normalized full-content comparison — an edited copy keeps getting re-injected, deliberately, so your edits don't get shadowed by the stale shipped version).
493
487
 
494
488
  3. Restart OpenCode.
495
489
 
@@ -497,7 +491,7 @@ Full configs: [`configs/cursor/hooks.json`](configs/cursor/hooks.json) | [`confi
497
491
 
498
492
  **Upgrade note:** If an existing config has BOTH `plugin: ["context-mode"]` AND `mcp.context-mode`, OpenCode will register zero `ctx_*` tools — the plugin path correctly suppresses MCP duplicates, but the legacy MCP entry confuses the loader. Run `context-mode upgrade` to remove the legacy `mcp.context-mode` entry; your other MCP servers are preserved. v1.0.140+ emits a stderr diagnostic with the same guidance when this happens.
499
493
 
500
- **Routing:** Hooks enforce routing programmatically via `tool.execute.before` and `tool.execute.after`. The optional [`AGENTS.md`](configs/opencode/AGENTS.md) file provides routing instructions for model awareness. The `experimental.session.compacting` hook builds resume snapshots when the conversation compacts. The `experimental.chat.system.transform` hook injects the routing block and prior-session snapshots at session start, enabling session continuity across restarts. The `chat.message` hook captures user prompts and decisions (UserPromptSubmit equivalent).
494
+ **Routing:** Hooks enforce routing programmatically via `tool.execute.before` and `tool.execute.after`, and the plugin injects the full routing guidance (condensed block + complete AGENTS.md mandate) into the system prompt on every model dispatch — no copied AGENTS.md is required. The `experimental.session.compacting` hook builds resume snapshots when the conversation compacts. The `experimental.chat.system.transform` hook injects the routing block and prior-session snapshots at session start, enabling session continuity across restarts. The `chat.message` hook captures user prompts and decisions (UserPromptSubmit equivalent).
501
495
 
502
496
  > **Note:** OpenCode lacks a real SessionStart hook ([#14808](https://github.com/sst/opencode/issues/14808), [#5409](https://github.com/sst/opencode/issues/5409)). The plugin uses `experimental.chat.system.transform` as a surrogate — it injects both the routing block and resume snapshots into the system prompt. User-prompt capture uses `chat.message` instead of the missing UserPromptSubmit hook. AGENTS.md/CLAUDE.md/CONTEXT.md rules are captured automatically on first hook fire per project.
503
497
 
@@ -523,11 +517,7 @@ Full configs: [`configs/opencode/opencode.json`](configs/opencode/opencode.json)
523
517
 
524
518
  The `plugin` entry registers all 11 `ctx_*` tools natively and enables hooks — KiloCode calls context-mode's TypeScript plugin in-process, so there is no redundant stdio MCP child per session.
525
519
 
526
- 2. *(Optional)* Copy the routing rules file. KiloCode shares the OpenCode plugin architecture; the plugin already injects its routing guidance into the system prompt on every model dispatch, so the copy is only useful if you want the guidance also visible as native project rules:
527
-
528
- ```bash
529
- cp node_modules/context-mode/configs/opencode/AGENTS.md AGENTS.md
530
- ```
520
+ 2. **No AGENTS.md copy needed.** KiloCode shares the OpenCode plugin architecture the plugin injects the FULL routing mandate ([`configs/opencode/AGENTS.md`](configs/opencode/AGENTS.md), verbatim) into the system prompt on every model dispatch. An existing copy is harmless (the host loads it natively as project rules) and identical copies are auto-skipped by the plugin's dedupe guard, so the mandate is never injected twice.
531
521
 
532
522
  3. Restart KiloCode.
533
523
 
@@ -535,7 +525,7 @@ Full configs: [`configs/opencode/opencode.json`](configs/opencode/opencode.json)
535
525
 
536
526
  **Upgrade note:** If an existing config has BOTH `plugin: ["context-mode"]` AND `mcp.context-mode`, KiloCode will register zero `ctx_*` tools — the plugin path correctly suppresses MCP duplicates, but the legacy MCP entry confuses the loader. Run `context-mode upgrade` to remove the legacy `mcp.context-mode` entry; your other MCP servers are preserved. v1.0.140+ emits a stderr diagnostic with the same guidance when this happens.
537
527
 
538
- **Routing:** Hooks enforce routing programmatically via `tool.execute.before` and `tool.execute.after`. The optional [`AGENTS.md`](configs/opencode/AGENTS.md) file provides routing instructions for model awareness. The `experimental.session.compacting` hook builds resume snapshots when the conversation compacts. The `experimental.chat.system.transform` hook injects the routing block and prior-session snapshots at session start, enabling session continuity across restarts. The `chat.message` hook captures user prompts and decisions (UserPromptSubmit equivalent).
528
+ **Routing:** Hooks enforce routing programmatically via `tool.execute.before` and `tool.execute.after`, and the plugin injects the full routing guidance (condensed block + complete AGENTS.md mandate) into the system prompt on every model dispatch — no copied AGENTS.md is required. The `experimental.session.compacting` hook builds resume snapshots when the conversation compacts. The `experimental.chat.system.transform` hook injects the routing block and prior-session snapshots at session start, enabling session continuity across restarts. The `chat.message` hook captures user prompts and decisions (UserPromptSubmit equivalent).
539
529
 
540
530
  > **Note:** KiloCode shares the same plugin architecture as OpenCode, using the OpenCodeAdapter with platform-specific configuration paths (`kilo.json` instead of `opencode.json`, `~/.config/kilo/` instead of `~/.config/opencode/`). Like OpenCode, it lacks a real SessionStart hook — the plugin uses `experimental.chat.system.transform` as a surrogate. User-prompt capture uses `chat.message` instead of the missing UserPromptSubmit hook. AGENTS.md/CLAUDE.md/CONTEXT.md rules are captured automatically on first hook fire per project.
541
531
 
@@ -182,6 +182,8 @@ interface ChatMessageHookOutput {
182
182
  message: unknown;
183
183
  parts: ChatMessagePart[];
184
184
  }
185
+ /** Test-only: point the template loader at a specific path (tests pass a nonexistent path to simulate a missing template). */
186
+ export declare function __setAgentsTemplatePathForTests(path: string | undefined): void;
185
187
  declare const ROUTING_MARKERS: string[];
186
188
  declare function systemHasRoutingInstructions(system: string[]): boolean;
187
189
  /** Test-only: clear process-global activation + log-dedupe state. */
@@ -75,6 +75,93 @@ function isSyntheticMessage(text) {
75
75
  const trimmed = text.trim();
76
76
  return SYNTHETIC_MESSAGE_PREFIXES.some((p) => trimmed.startsWith(p));
77
77
  }
78
+ // ── Full AGENTS.md mandate injection (user decision: opencode must not
79
+ // require the copied AGENTS.md — the injected guidance carries the FULL
80
+ // mandate, not just the condensed block) ─────────────────
81
+ /** Test-only override for the template path (null/undefined → default). */
82
+ let agentsTemplatePathOverride;
83
+ /** Test-only: point the template loader at a specific path (tests pass a nonexistent path to simulate a missing template). */
84
+ export function __setAgentsTemplatePathForTests(path) {
85
+ agentsTemplatePathOverride = path;
86
+ }
87
+ function agentsTemplatePathFor(buildDir) {
88
+ if (agentsTemplatePathOverride !== undefined)
89
+ return agentsTemplatePathOverride;
90
+ // Same buildDir-relative pattern as the routing .mjs islands: the plugin
91
+ // runs from build/adapters/opencode (or src/adapters/opencode under tsx),
92
+ // so ../../.. is the package root where configs/ lives.
93
+ return resolve(buildDir, "..", "..", "..", "configs", "opencode", "AGENTS.md");
94
+ }
95
+ /**
96
+ * Normalize a markdown document for content comparison: strip \r, trim each
97
+ * line, drop empty lines, re-join with "\n". Absorbs CRLF line endings,
98
+ * trailing whitespace, and blank-line differences — content-equal documents
99
+ * normalize identically; ANY edited line does not.
100
+ */
101
+ function normalizeMarkdownForCompare(content) {
102
+ return content
103
+ .replace(/\r/g, "")
104
+ .split("\n")
105
+ .map((line) => line.trim())
106
+ .filter((line) => line.length > 0)
107
+ .join("\n");
108
+ }
109
+ /**
110
+ * Compose the injected guidance: the condensed routing block FIRST
111
+ * (<context_window_protection> + quorum markers), then the FULL AGENTS.md
112
+ * mandate (Think in Code, BLOCKED/REDIRECTED, tool selection, memory
113
+ * tables, ctx commands) appended VERBATIM — the template uses the SAME
114
+ * tool naming (`context-mode_ctx_*`) as the runtime redirect guidance, so
115
+ * no rewrite is needed, and it does NOT contain the condensed block's XML
116
+ * tag, so there is no tag collision.
117
+ *
118
+ * Best-effort: a missing/unreadable template degrades to the condensed
119
+ * block alone (nothing logged — same degrade-honestly pattern; the
120
+ * condensed block alone must keep working).
121
+ *
122
+ * Dedupe guard (evaluated ONCE at setup) — NORMALIZED FULL-CONTENT
123
+ * EQUALITY: the template is skipped ONLY when the project-root AGENTS.md is
124
+ * content-equal to the template after normalization (CRLF/trailing-
125
+ * whitespace/blank-line differences absorbed). Rationale: the v1 host then
126
+ * loads the identical mandate natively, so appending it again would
127
+ * double-inject and waste context. ANY edited copy re-appends the full
128
+ * template DELIBERATELY — even when the copy still carries the old
129
+ * signature line — because an edited copy is no longer guaranteed to match
130
+ * what the plugin injects, and the injected guidance is the authoritative
131
+ * mandate. Unreadable project files fall through and append (harmless
132
+ * duplicate worst-case; never break setup over a diagnostics read).
133
+ */
134
+ function composeRoutingGuidance(condensedBlock, templatePath, projectDir) {
135
+ let agentsMdContent = "";
136
+ try {
137
+ if (existsSync(templatePath)) {
138
+ const content = readFileSync(templatePath, "utf-8");
139
+ if (content.trim())
140
+ agentsMdContent = content;
141
+ }
142
+ }
143
+ catch {
144
+ agentsMdContent = ""; // unreadable template — condensed block alone
145
+ }
146
+ if (!agentsMdContent)
147
+ return condensedBlock;
148
+ try {
149
+ const projectAgentsPath = join(projectDir, "AGENTS.md");
150
+ if (existsSync(projectAgentsPath)) {
151
+ const projectAgents = readFileSync(projectAgentsPath, "utf-8");
152
+ if (normalizeMarkdownForCompare(projectAgents) === normalizeMarkdownForCompare(agentsMdContent)) {
153
+ // Content-equal copy → the v1 host loads the identical mandate
154
+ // natively — skip the template. Edited copies re-append above.
155
+ return condensedBlock;
156
+ }
157
+ }
158
+ }
159
+ catch {
160
+ // Unreadable project file — fall through and append (harmless duplicate
161
+ // worst-case; never break setup over a diagnostics read).
162
+ }
163
+ return `${condensedBlock}\n\n${agentsMdContent}`;
164
+ }
78
165
  // ── Helpers ───────────────────────────────────────────────
79
166
  // Quorum markers — must NOT be substrings of each other (#487).
80
167
  // Each token uniquely identifies the routing block / context-mode rules
@@ -368,12 +455,16 @@ async function createPluginRuntime(ctx, projectDirOverride, adapterOptions) {
368
455
  // sessionID, so we cache it. createToolNamer accepts both "opencode" and
369
456
  // "kilo" per hooks/core/tool-naming.mjs:25-26.
370
457
  const toolNamer = toolNamingMod.createToolNamer(platform);
371
- const routingBlock = routingBlockMod.createRoutingBlock(toolNamer);
458
+ const condensedRoutingBlock = routingBlockMod.createRoutingBlock(toolNamer);
372
459
  // Initialize per-process state. We do NOT fabricate a sessionId here —
373
460
  // OpenCode/Kilo provide the real `input.sessionID` on every hook, and a
374
461
  // process-global UUID would (a) never match prior-session resume rows and
375
462
  // (b) collide across multi-session reuse (Mickey / PR #376 root cause).
376
463
  const projectDir = projectDirOverride ?? ctx?.directory ?? process.cwd();
464
+ // Compose the FULL injected guidance (condensed block first + the complete
465
+ // AGENTS.md mandate verbatim, subject to the project-root dedupe guard) —
466
+ // evaluated ONCE per process; needs the resolved project dir.
467
+ const routingBlock = composeRoutingGuidance(condensedRoutingBlock, agentsTemplatePathFor(buildDir), projectDir);
377
468
  // C2 narrowing: resolve DB path through the canonical helper directly.
378
469
  // BaseAdapter no longer exposes getSessionDBPath; the adapter only owns
379
470
  // the sessions DIR (per-platform), the helper owns the per-project FILE
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
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": "2.0.0",
4
+ "version": "2.0.1",
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": "2.0.0",
6
+ "version": "2.0.1",
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": "@mxalbert/context-mode",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
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",