context-mode 1.0.53 → 1.0.56

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.
Files changed (66) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.openclaw-plugin/openclaw.plugin.json +1 -1
  4. package/.openclaw-plugin/package.json +1 -1
  5. package/README.md +103 -32
  6. package/build/adapters/antigravity/index.d.ts +1 -3
  7. package/build/adapters/antigravity/index.js +0 -30
  8. package/build/adapters/claude-code/hooks.d.ts +18 -0
  9. package/build/adapters/claude-code/hooks.js +23 -0
  10. package/build/adapters/claude-code/index.d.ts +1 -3
  11. package/build/adapters/claude-code/index.js +48 -35
  12. package/build/adapters/client-map.js +1 -0
  13. package/build/adapters/codex/index.d.ts +1 -3
  14. package/build/adapters/codex/index.js +1 -31
  15. package/build/adapters/cursor/index.d.ts +1 -3
  16. package/build/adapters/cursor/index.js +0 -11
  17. package/build/adapters/detect.d.ts +1 -0
  18. package/build/adapters/detect.js +18 -2
  19. package/build/adapters/gemini-cli/index.d.ts +1 -3
  20. package/build/adapters/gemini-cli/index.js +0 -30
  21. package/build/adapters/kiro/index.d.ts +1 -3
  22. package/build/adapters/kiro/index.js +0 -30
  23. package/build/adapters/openclaw/index.d.ts +1 -3
  24. package/build/adapters/openclaw/index.js +0 -38
  25. package/build/adapters/opencode/index.d.ts +5 -4
  26. package/build/adapters/opencode/index.js +37 -41
  27. package/build/adapters/types.d.ts +1 -14
  28. package/build/adapters/vscode-copilot/index.d.ts +1 -3
  29. package/build/adapters/vscode-copilot/index.js +0 -32
  30. package/build/adapters/zed/index.d.ts +1 -3
  31. package/build/adapters/zed/index.js +0 -30
  32. package/build/cli.js +12 -28
  33. package/build/executor.d.ts +0 -1
  34. package/build/executor.js +28 -16
  35. package/build/openclaw-plugin.js +12 -34
  36. package/build/opencode-plugin.d.ts +1 -0
  37. package/build/opencode-plugin.js +5 -9
  38. package/build/runtime.js +29 -11
  39. package/build/server.d.ts +2 -0
  40. package/build/server.js +69 -61
  41. package/build/store.d.ts +4 -3
  42. package/build/store.js +101 -34
  43. package/build/truncate.d.ts +4 -17
  44. package/build/truncate.js +4 -52
  45. package/cli.bundle.mjs +184 -157
  46. package/configs/codex/AGENTS.md +19 -0
  47. package/configs/kilo/AGENTS.md +58 -0
  48. package/configs/kilo/kilo.json +10 -0
  49. package/hooks/core/tool-naming.mjs +1 -0
  50. package/hooks/ensure-deps.mjs +80 -2
  51. package/hooks/pretooluse.mjs +25 -20
  52. package/hooks/routing-block.mjs +10 -1
  53. package/hooks/session-snapshot.bundle.mjs +13 -13
  54. package/hooks/sessionstart.mjs +25 -1
  55. package/openclaw.plugin.json +1 -1
  56. package/package.json +1 -1
  57. package/server.bundle.mjs +159 -129
  58. package/skills/context-mode-ops/SKILL.md +111 -0
  59. package/skills/context-mode-ops/agent-teams.md +198 -0
  60. package/skills/context-mode-ops/communication.md +224 -0
  61. package/skills/context-mode-ops/release.md +199 -0
  62. package/skills/context-mode-ops/review-pr.md +269 -0
  63. package/skills/context-mode-ops/tdd.md +329 -0
  64. package/skills/context-mode-ops/triage-issue.md +218 -0
  65. package/skills/context-mode-ops/validation.md +238 -0
  66. package/start.mjs +5 -52
@@ -9,6 +9,7 @@
9
9
  * Verified env vars per platform (from source code audit):
10
10
  * - Claude Code: CLAUDE_PROJECT_DIR, CLAUDE_SESSION_ID | ~/.claude/
11
11
  * - Gemini CLI: GEMINI_PROJECT_DIR (hooks), GEMINI_CLI (MCP) | ~/.gemini/
12
+ * - KiloCode: KILO, KILO_PID | ~/.config/kilo/
12
13
  * - OpenCode: OPENCODE, OPENCODE_PID | ~/.config/opencode/
13
14
  * - OpenClaw: OPENCLAW_HOME, OPENCLAW_CLI | ~/.openclaw/
14
15
  * - Codex CLI: CODEX_CI, CODEX_THREAD_ID | ~/.codex/
@@ -41,7 +42,7 @@ export function detectPlatform(clientInfo) {
41
42
  const platformOverride = process.env.CONTEXT_MODE_PLATFORM;
42
43
  if (platformOverride) {
43
44
  const validPlatforms = [
44
- "claude-code", "gemini-cli", "opencode", "codex",
45
+ "claude-code", "gemini-cli", "kilo", "opencode", "codex",
45
46
  "vscode-copilot", "cursor", "antigravity", "kiro", "pi", "zed",
46
47
  ];
47
48
  if (validPlatforms.includes(platformOverride)) {
@@ -74,6 +75,13 @@ export function detectPlatform(clientInfo) {
74
75
  reason: "OPENCLAW_HOME or OPENCLAW_CLI env var set",
75
76
  };
76
77
  }
78
+ if (process.env.KILO || process.env.KILO_PID) {
79
+ return {
80
+ platform: "kilo",
81
+ confidence: "high",
82
+ reason: "KILO or KILO_PID env var set",
83
+ };
84
+ }
77
85
  if (process.env.OPENCODE || process.env.OPENCODE_PID) {
78
86
  return {
79
87
  platform: "opencode",
@@ -153,6 +161,13 @@ export function detectPlatform(clientInfo) {
153
161
  reason: "~/.openclaw/ directory exists",
154
162
  };
155
163
  }
164
+ if (existsSync(resolve(home, ".config", "kilo"))) {
165
+ return {
166
+ platform: "kilo",
167
+ confidence: "medium",
168
+ reason: "~/.config/kilo/ directory exists",
169
+ };
170
+ }
156
171
  if (existsSync(resolve(home, ".config", "opencode"))) {
157
172
  return {
158
173
  platform: "opencode",
@@ -189,9 +204,10 @@ export async function getAdapter(platform) {
189
204
  const { GeminiCLIAdapter } = await import("./gemini-cli/index.js");
190
205
  return new GeminiCLIAdapter();
191
206
  }
207
+ case "kilo":
192
208
  case "opencode": {
193
209
  const { OpenCodeAdapter } = await import("./opencode/index.js");
194
- return new OpenCodeAdapter();
210
+ return new OpenCodeAdapter(target);
195
211
  }
196
212
  case "openclaw": {
197
213
  const { OpenClawAdapter } = await import("./openclaw/index.js");
@@ -18,7 +18,7 @@
18
18
  * - Project dir env: GEMINI_PROJECT_DIR (also CLAUDE_PROJECT_DIR alias)
19
19
  * - Session dir: ~/.gemini/context-mode/sessions/
20
20
  */
21
- import type { HookAdapter, HookParadigm, PlatformCapabilities, DiagnosticResult, PreToolUseEvent, PostToolUseEvent, PreCompactEvent, SessionStartEvent, PreToolUseResponse, PostToolUseResponse, PreCompactResponse, SessionStartResponse, HookRegistration, RoutingInstructionsConfig } from "../types.js";
21
+ import type { HookAdapter, HookParadigm, PlatformCapabilities, DiagnosticResult, PreToolUseEvent, PostToolUseEvent, PreCompactEvent, SessionStartEvent, PreToolUseResponse, PostToolUseResponse, PreCompactResponse, SessionStartResponse, HookRegistration } from "../types.js";
22
22
  export declare class GeminiCLIAdapter implements HookAdapter {
23
23
  readonly name = "Gemini CLI";
24
24
  readonly paradigm: HookParadigm;
@@ -45,8 +45,6 @@ export declare class GeminiCLIAdapter implements HookAdapter {
45
45
  backupSettings(): string | null;
46
46
  setHookPermissions(pluginRoot: string): string[];
47
47
  updatePluginRegistry(pluginRoot: string, version: string): void;
48
- getRoutingInstructionsConfig(): RoutingInstructionsConfig;
49
- writeRoutingInstructions(projectDir: string, pluginRoot: string): string | null;
50
48
  /** Get the project directory from environment variables. */
51
49
  private getProjectDir;
52
50
  /**
@@ -421,36 +421,6 @@ export class GeminiCLIAdapter {
421
421
  /* best effort */
422
422
  }
423
423
  }
424
- // ── Routing Instructions (soft enforcement) ────────────
425
- getRoutingInstructionsConfig() {
426
- return {
427
- fileName: "GEMINI.md",
428
- globalPath: resolve(homedir(), ".gemini", "GEMINI.md"),
429
- projectRelativePath: "GEMINI.md",
430
- };
431
- }
432
- writeRoutingInstructions(projectDir, pluginRoot) {
433
- const config = this.getRoutingInstructionsConfig();
434
- const targetPath = resolve(projectDir, config.projectRelativePath);
435
- const sourcePath = resolve(pluginRoot, "configs", "gemini-cli", config.fileName);
436
- try {
437
- const content = readFileSync(sourcePath, "utf-8");
438
- try {
439
- const existing = readFileSync(targetPath, "utf-8");
440
- if (existing.includes("context-mode"))
441
- return null;
442
- writeFileSync(targetPath, existing.trimEnd() + "\n\n" + content, "utf-8");
443
- return targetPath;
444
- }
445
- catch {
446
- writeFileSync(targetPath, content, "utf-8");
447
- return targetPath;
448
- }
449
- }
450
- catch {
451
- return null;
452
- }
453
- }
454
424
  // ── Internal helpers ───────────────────────────────────
455
425
  /** Get the project directory from environment variables. */
456
426
  getProjectDir() {
@@ -17,7 +17,7 @@
17
17
  * - clientInfo.name: https://github.com/kirodotdev/Kiro/issues/5205 ("Kiro CLI")
18
18
  * - CLI hooks: https://kiro.dev/docs/cli/custom-agents/configuration-reference#hooks-field
19
19
  */
20
- import type { HookAdapter, HookParadigm, PlatformCapabilities, DiagnosticResult, PreToolUseEvent, PostToolUseEvent, PreCompactEvent, SessionStartEvent, PreToolUseResponse, PostToolUseResponse, PreCompactResponse, SessionStartResponse, HookRegistration, RoutingInstructionsConfig } from "../types.js";
20
+ import type { HookAdapter, HookParadigm, PlatformCapabilities, DiagnosticResult, PreToolUseEvent, PostToolUseEvent, PreCompactEvent, SessionStartEvent, PreToolUseResponse, PostToolUseResponse, PreCompactResponse, SessionStartResponse, HookRegistration } from "../types.js";
21
21
  export declare class KiroAdapter implements HookAdapter {
22
22
  readonly name = "Kiro";
23
23
  readonly paradigm: HookParadigm;
@@ -44,7 +44,5 @@ export declare class KiroAdapter implements HookAdapter {
44
44
  backupSettings(): string | null;
45
45
  setHookPermissions(_pluginRoot: string): string[];
46
46
  updatePluginRegistry(_pluginRoot: string, _version: string): void;
47
- getRoutingInstructionsConfig(): RoutingInstructionsConfig;
48
- writeRoutingInstructions(projectDir: string, pluginRoot: string): string | null;
49
47
  getRoutingInstructions(): string;
50
48
  }
@@ -283,36 +283,6 @@ export class KiroAdapter {
283
283
  updatePluginRegistry(_pluginRoot, _version) {
284
284
  // Kiro plugin registry is managed via mcp.json
285
285
  }
286
- // ── Routing Instructions (soft enforcement) ────────────
287
- getRoutingInstructionsConfig() {
288
- return {
289
- fileName: "KIRO.md",
290
- globalPath: resolve(homedir(), ".kiro", "KIRO.md"),
291
- projectRelativePath: "KIRO.md",
292
- };
293
- }
294
- writeRoutingInstructions(projectDir, pluginRoot) {
295
- const config = this.getRoutingInstructionsConfig();
296
- const targetPath = resolve(projectDir, config.projectRelativePath);
297
- const sourcePath = resolve(pluginRoot, "configs", "kiro", config.fileName);
298
- try {
299
- const content = readFileSync(sourcePath, "utf-8");
300
- try {
301
- const existing = readFileSync(targetPath, "utf-8");
302
- if (existing.includes("context-mode"))
303
- return null;
304
- writeFileSync(targetPath, existing.trimEnd() + "\n\n" + content, "utf-8");
305
- return targetPath;
306
- }
307
- catch {
308
- writeFileSync(targetPath, content, "utf-8");
309
- return targetPath;
310
- }
311
- }
312
- catch {
313
- return null;
314
- }
315
- }
316
286
  getRoutingInstructions() {
317
287
  const instructionsPath = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "..", "configs", "kiro", "KIRO.md");
318
288
  try {
@@ -15,7 +15,7 @@
15
15
  * - Config: openclaw.json plugins.entries, ~/.openclaw/extensions/
16
16
  * - Session dir: ~/.openclaw/context-mode/sessions/
17
17
  */
18
- import type { HookAdapter, HookParadigm, PlatformCapabilities, DiagnosticResult, PreToolUseEvent, PostToolUseEvent, PreCompactEvent, SessionStartEvent, PreToolUseResponse, PostToolUseResponse, PreCompactResponse, SessionStartResponse, HookRegistration, RoutingInstructionsConfig } from "../types.js";
18
+ import type { HookAdapter, HookParadigm, PlatformCapabilities, DiagnosticResult, PreToolUseEvent, PostToolUseEvent, PreCompactEvent, SessionStartEvent, PreToolUseResponse, PostToolUseResponse, PreCompactResponse, SessionStartResponse, HookRegistration } from "../types.js";
19
19
  export declare class OpenClawAdapter implements HookAdapter {
20
20
  readonly name = "OpenClaw";
21
21
  readonly paradigm: HookParadigm;
@@ -42,8 +42,6 @@ export declare class OpenClawAdapter implements HookAdapter {
42
42
  backupSettings(): string | null;
43
43
  setHookPermissions(_pluginRoot: string): string[];
44
44
  updatePluginRegistry(_pluginRoot: string, _version: string): void;
45
- getRoutingInstructionsConfig(): RoutingInstructionsConfig;
46
- writeRoutingInstructions(projectDir: string, pluginRoot: string): string | null;
47
45
  /**
48
46
  * Extract session ID from OpenClaw hook input.
49
47
  */
@@ -409,44 +409,6 @@ export class OpenClawAdapter {
409
409
  updatePluginRegistry(_pluginRoot, _version) {
410
410
  // OpenClaw manages plugins through npm/openclaw.json — no separate registry
411
411
  }
412
- // ── Routing Instructions (soft enforcement) ────────────
413
- getRoutingInstructionsConfig() {
414
- return {
415
- fileName: "AGENTS.md",
416
- globalPath: resolve(homedir(), ".openclaw", "AGENTS.md"),
417
- projectRelativePath: "AGENTS.md",
418
- };
419
- }
420
- writeRoutingInstructions(projectDir, pluginRoot) {
421
- const config = this.getRoutingInstructionsConfig();
422
- const targetPath = resolve(projectDir, config.projectRelativePath);
423
- const sourcePath = resolve(pluginRoot, "configs", "openclaw", config.fileName);
424
- try {
425
- let content;
426
- try {
427
- content = readFileSync(sourcePath, "utf-8");
428
- }
429
- catch {
430
- // Fall back to opencode config if openclaw-specific doesn't exist yet
431
- const fallbackPath = resolve(pluginRoot, "configs", "opencode", config.fileName);
432
- content = readFileSync(fallbackPath, "utf-8");
433
- }
434
- try {
435
- const existing = readFileSync(targetPath, "utf-8");
436
- if (existing.includes("context-mode"))
437
- return null;
438
- writeFileSync(targetPath, existing.trimEnd() + "\n\n" + content, "utf-8");
439
- return targetPath;
440
- }
441
- catch {
442
- writeFileSync(targetPath, content, "utf-8");
443
- return targetPath;
444
- }
445
- }
446
- catch {
447
- return null;
448
- }
449
- }
450
412
  // ── Internal helpers ───────────────────────────────────
451
413
  /**
452
414
  * Extract session ID from OpenClaw hook input.
@@ -15,12 +15,15 @@
15
15
  * - Config: opencode.json plugin array, .opencode/plugins/*.ts
16
16
  * - Session dir: ~/.config/opencode/context-mode/sessions/
17
17
  */
18
- import type { HookAdapter, HookParadigm, PlatformCapabilities, DiagnosticResult, PreToolUseEvent, PostToolUseEvent, PreCompactEvent, SessionStartEvent, PreToolUseResponse, PostToolUseResponse, PreCompactResponse, SessionStartResponse, HookRegistration, RoutingInstructionsConfig } from "../types.js";
18
+ import type { HookAdapter, HookParadigm, PlatformCapabilities, DiagnosticResult, PreToolUseEvent, PostToolUseEvent, PreCompactEvent, SessionStartEvent, PreToolUseResponse, PostToolUseResponse, PreCompactResponse, SessionStartResponse, HookRegistration, PlatformId } from "../types.js";
19
+ export type AdapterPlatformType = Extract<PlatformId, "opencode" | "kilo">;
19
20
  export declare class OpenCodeAdapter implements HookAdapter {
20
- readonly name = "OpenCode";
21
+ get name(): string;
21
22
  readonly paradigm: HookParadigm;
22
23
  private settingsPath?;
23
24
  readonly capabilities: PlatformCapabilities;
25
+ private platform;
26
+ constructor(platform?: AdapterPlatformType);
24
27
  parsePreToolUseInput(raw: unknown): PreToolUseEvent;
25
28
  parsePostToolUseInput(raw: unknown): PostToolUseEvent;
26
29
  parsePreCompactInput(raw: unknown): PreCompactEvent;
@@ -44,8 +47,6 @@ export declare class OpenCodeAdapter implements HookAdapter {
44
47
  backupSettings(): string | null;
45
48
  setHookPermissions(_pluginRoot: string): string[];
46
49
  updatePluginRegistry(_pluginRoot: string, _version: string): void;
47
- getRoutingInstructionsConfig(): RoutingInstructionsConfig;
48
- writeRoutingInstructions(projectDir: string, pluginRoot: string): string | null;
49
50
  /**
50
51
  * Extract session ID from OpenCode hook input.
51
52
  * OpenCode uses camelCase sessionID.
@@ -16,6 +16,13 @@
16
16
  * - Session dir: ~/.config/opencode/context-mode/sessions/
17
17
  */
18
18
  import { createHash } from "node:crypto";
19
+ /** Strip JSONC comments (// and /* *​/) and trailing commas for JSON.parse. */
20
+ function stripJsonComments(str) {
21
+ return str
22
+ .replace(/\/\/.*$/gm, "")
23
+ .replace(/\/\*[\s\S]*?\*\//g, "")
24
+ .replace(/,(\s*[}\]])/g, "$1");
25
+ }
19
26
  import { readFileSync, writeFileSync, mkdirSync, copyFileSync, accessSync, constants, } from "node:fs";
20
27
  import { resolve, join } from "node:path";
21
28
  import { homedir } from "node:os";
@@ -23,22 +30,25 @@ import { homedir } from "node:os";
23
30
  // Hook constants (re-exported from hooks.ts)
24
31
  // ─────────────────────────────────────────────────────────
25
32
  import { HOOK_TYPES as OPENCODE_HOOK_NAMES } from "./hooks.js";
26
- // ─────────────────────────────────────────────────────────
27
- // Adapter implementation
28
- // ─────────────────────────────────────────────────────────
29
33
  export class OpenCodeAdapter {
30
- name = "OpenCode";
34
+ get name() {
35
+ return this.platform === "kilo" ? "KiloCode" : "OpenCode";
36
+ }
31
37
  paradigm = "ts-plugin";
32
38
  settingsPath;
33
39
  capabilities = {
34
40
  preToolUse: true,
35
41
  postToolUse: true,
36
42
  preCompact: true, // experimental
37
- sessionStart: true,
43
+ sessionStart: false,
38
44
  canModifyArgs: true,
39
45
  canModifyOutput: true, // with TUI bug caveat for bash (#13575)
40
46
  canInjectSessionContext: false,
41
47
  };
48
+ platform;
49
+ constructor(platform = "opencode") {
50
+ this.platform = platform;
51
+ }
42
52
  // ── Input parsing ──────────────────────────────────────
43
53
  parsePreToolUseInput(raw) {
44
54
  const input = raw;
@@ -134,17 +144,28 @@ export class OpenCodeAdapter {
134
144
  }
135
145
  // ── Configuration ──────────────────────────────────────
136
146
  getSettingsPath() {
137
- return this.settingsPath ?? resolve("opencode.json");
147
+ // OpenCode uses opencode.json in the project root or .opencode/opencode.json
148
+ return this.settingsPath ?? resolve(`${this.platform}.json`);
138
149
  }
139
150
  paths() {
151
+ if (this.platform === "kilo") {
152
+ return [
153
+ resolve("kilo.json"),
154
+ resolve(".kilocode", "kilo.json"),
155
+ join(homedir(), ".config", "kilo", "kilo.json"),
156
+ ];
157
+ }
140
158
  return [
141
159
  resolve("opencode.json"),
160
+ resolve("opencode.jsonc"),
142
161
  resolve(".opencode", "opencode.json"),
162
+ resolve(".opencode", "opencode.jsonc"),
143
163
  join(homedir(), ".config", "opencode", "opencode.json"),
164
+ join(homedir(), ".config", "opencode", "opencode.jsonc"),
144
165
  ];
145
166
  }
146
167
  getSessionDir() {
147
- const dir = join(homedir(), ".config", "opencode", "context-mode", "sessions");
168
+ const dir = join(homedir(), ".config", this.platform, "context-mode", "sessions");
148
169
  mkdirSync(dir, { recursive: true });
149
170
  return dir;
150
171
  }
@@ -203,12 +224,16 @@ export class OpenCodeAdapter {
203
224
  };
204
225
  }
205
226
  readSettings() {
227
+ // Try project-local paths first, then global config
228
+ // const paths = this.getConfigFilePaths();
229
+ // for (const configPath of paths) {
206
230
  this.settingsPath = undefined;
207
231
  for (const configPath of this.paths()) {
208
232
  try {
209
233
  const raw = readFileSync(configPath, "utf-8");
210
234
  this.settingsPath = configPath;
211
- return JSON.parse(raw);
235
+ const text = configPath.endsWith(".jsonc") ? stripJsonComments(raw) : raw;
236
+ return JSON.parse(text);
212
237
  }
213
238
  catch {
214
239
  continue;
@@ -217,6 +242,7 @@ export class OpenCodeAdapter {
217
242
  return null;
218
243
  }
219
244
  writeSettings(settings) {
245
+ // Write to opencode.json/kilo.json in current directory
220
246
  writeFileSync(this.getSettingsPath(), JSON.stringify(settings, null, 2) + "\n", "utf-8");
221
247
  }
222
248
  // ── Diagnostics (doctor) ─────────────────────────────────
@@ -227,7 +253,7 @@ export class OpenCodeAdapter {
227
253
  results.push({
228
254
  check: "Plugin configuration",
229
255
  status: "fail",
230
- message: "Could not read opencode.json",
256
+ message: `Could not read ${this.platform}.json or ${this.platform}.jsonc`,
231
257
  fix: "context-mode upgrade",
232
258
  });
233
259
  return results;
@@ -269,7 +295,7 @@ export class OpenCodeAdapter {
269
295
  return {
270
296
  check: "Plugin registration",
271
297
  status: "warn",
272
- message: "Could not read opencode.json",
298
+ message: `Could not read ${this.platform}.json or ${this.platform}.jsonc`,
273
299
  };
274
300
  }
275
301
  const plugins = settings.plugin;
@@ -293,7 +319,7 @@ export class OpenCodeAdapter {
293
319
  getInstalledVersion() {
294
320
  // Check ~/.cache/opencode/node_modules/ for context-mode
295
321
  try {
296
- const pkgPath = resolve(homedir(), ".cache", "opencode", "node_modules", "context-mode", "package.json");
322
+ const pkgPath = resolve(homedir(), ".cache", this.platform, "node_modules", "context-mode", "package.json");
297
323
  const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
298
324
  if (typeof pkg.version === "string")
299
325
  return pkg.version;
@@ -343,36 +369,6 @@ export class OpenCodeAdapter {
343
369
  updatePluginRegistry(_pluginRoot, _version) {
344
370
  // OpenCode manages plugins through npm/opencode.json — no separate registry
345
371
  }
346
- // ── Routing Instructions (soft enforcement) ────────────
347
- getRoutingInstructionsConfig() {
348
- return {
349
- fileName: "AGENTS.md",
350
- globalPath: resolve(homedir(), ".config", "opencode", "AGENTS.md"),
351
- projectRelativePath: "AGENTS.md",
352
- };
353
- }
354
- writeRoutingInstructions(projectDir, pluginRoot) {
355
- const config = this.getRoutingInstructionsConfig();
356
- const targetPath = resolve(projectDir, config.projectRelativePath);
357
- const sourcePath = resolve(pluginRoot, "configs", "opencode", config.fileName);
358
- try {
359
- const content = readFileSync(sourcePath, "utf-8");
360
- try {
361
- const existing = readFileSync(targetPath, "utf-8");
362
- if (existing.includes("context-mode"))
363
- return null;
364
- writeFileSync(targetPath, existing.trimEnd() + "\n\n" + content, "utf-8");
365
- return targetPath;
366
- }
367
- catch {
368
- writeFileSync(targetPath, content, "utf-8");
369
- return targetPath;
370
- }
371
- }
372
- catch {
373
- return null;
374
- }
375
- }
376
372
  // ── Internal helpers ───────────────────────────────────
377
373
  /**
378
374
  * Extract session ID from OpenCode hook input.
@@ -180,19 +180,6 @@ export interface HookAdapter {
180
180
  setHookPermissions(pluginRoot: string): string[];
181
181
  /** Update platform's plugin registry to point to given path and version. */
182
182
  updatePluginRegistry(pluginRoot: string, version: string): void;
183
- /** Get the routing instructions file config for this platform. */
184
- getRoutingInstructionsConfig(): RoutingInstructionsConfig;
185
- /** Write routing instructions file to project directory if not present. Returns path written or null if already exists. */
186
- writeRoutingInstructions(projectDir: string, pluginRoot: string): string | null;
187
- }
188
- /** Configuration for platform-specific routing instruction files. */
189
- export interface RoutingInstructionsConfig {
190
- /** File name the platform reads (e.g., "CLAUDE.md", "GEMINI.md", "AGENTS.md"). */
191
- fileName: string;
192
- /** Global path for this platform (e.g., "~/.claude/CLAUDE.md"). */
193
- globalPath: string;
194
- /** Project-level path relative to project root (e.g., "GEMINI.md", ".github/copilot-instructions.md"). */
195
- projectRelativePath: string;
196
183
  }
197
184
  /** Result from a platform-specific diagnostic check. */
198
185
  export interface DiagnosticResult {
@@ -206,7 +193,7 @@ export interface DiagnosticResult {
206
193
  fix?: string;
207
194
  }
208
195
  /** Supported platform identifiers. */
209
- export type PlatformId = "claude-code" | "gemini-cli" | "opencode" | "openclaw" | "codex" | "vscode-copilot" | "cursor" | "antigravity" | "kiro" | "pi" | "zed" | "unknown";
196
+ export type PlatformId = "claude-code" | "gemini-cli" | "opencode" | "kilo" | "openclaw" | "codex" | "vscode-copilot" | "cursor" | "antigravity" | "kiro" | "pi" | "zed" | "unknown";
210
197
  /** Detection signal used to identify which platform is running. */
211
198
  export interface DetectionSignal {
212
199
  /** Platform identifier. */
@@ -21,7 +21,7 @@
21
21
  * - Session dir: ~/.vscode/context-mode/sessions/ (fallback)
22
22
  * - Preview status — API may change
23
23
  */
24
- import type { HookAdapter, HookParadigm, PlatformCapabilities, DiagnosticResult, PreToolUseEvent, PostToolUseEvent, PreCompactEvent, SessionStartEvent, PreToolUseResponse, PostToolUseResponse, PreCompactResponse, SessionStartResponse, HookRegistration, RoutingInstructionsConfig } from "../types.js";
24
+ import type { HookAdapter, HookParadigm, PlatformCapabilities, DiagnosticResult, PreToolUseEvent, PostToolUseEvent, PreCompactEvent, SessionStartEvent, PreToolUseResponse, PostToolUseResponse, PreCompactResponse, SessionStartResponse, HookRegistration } from "../types.js";
25
25
  export declare class VSCodeCopilotAdapter implements HookAdapter {
26
26
  readonly name = "VS Code Copilot";
27
27
  readonly paradigm: HookParadigm;
@@ -48,8 +48,6 @@ export declare class VSCodeCopilotAdapter implements HookAdapter {
48
48
  backupSettings(): string | null;
49
49
  setHookPermissions(pluginRoot: string): string[];
50
50
  updatePluginRegistry(_pluginRoot: string, _version: string): void;
51
- getRoutingInstructionsConfig(): RoutingInstructionsConfig;
52
- writeRoutingInstructions(projectDir: string, pluginRoot: string): string | null;
53
51
  /**
54
52
  * Extract session ID from VS Code Copilot hook input.
55
53
  * VS Code Copilot uses camelCase sessionId (NOT session_id).
@@ -465,38 +465,6 @@ export class VSCodeCopilotAdapter {
465
465
  // VS Code manages extensions through its own marketplace/extension system.
466
466
  // No manual registry update needed.
467
467
  }
468
- // ── Routing Instructions (soft enforcement) ────────────
469
- getRoutingInstructionsConfig() {
470
- return {
471
- fileName: "copilot-instructions.md",
472
- globalPath: "", // VS Code Copilot uses org-level, not global file
473
- projectRelativePath: join(".github", "copilot-instructions.md"),
474
- };
475
- }
476
- writeRoutingInstructions(projectDir, pluginRoot) {
477
- const config = this.getRoutingInstructionsConfig();
478
- const targetPath = resolve(projectDir, config.projectRelativePath);
479
- const sourcePath = resolve(pluginRoot, "configs", "vscode-copilot", config.fileName);
480
- try {
481
- const content = readFileSync(sourcePath, "utf-8");
482
- // Ensure .github directory exists
483
- mkdirSync(resolve(projectDir, ".github"), { recursive: true });
484
- try {
485
- const existing = readFileSync(targetPath, "utf-8");
486
- if (existing.includes("context-mode"))
487
- return null;
488
- writeFileSync(targetPath, existing.trimEnd() + "\n\n" + content, "utf-8");
489
- return targetPath;
490
- }
491
- catch {
492
- writeFileSync(targetPath, content, "utf-8");
493
- return targetPath;
494
- }
495
- }
496
- catch {
497
- return null;
498
- }
499
- }
500
468
  // ── Internal helpers ───────────────────────────────────
501
469
  /**
502
470
  * Extract session ID from VS Code Copilot hook input.
@@ -10,7 +10,7 @@
10
10
  * - All capabilities are false — MCP is the only integration path
11
11
  * - Session dir: ~/.config/zed/context-mode/sessions/
12
12
  */
13
- import type { HookAdapter, HookParadigm, PlatformCapabilities, DiagnosticResult, PreToolUseEvent, PostToolUseEvent, PreCompactEvent, SessionStartEvent, PreToolUseResponse, PostToolUseResponse, PreCompactResponse, SessionStartResponse, HookRegistration, RoutingInstructionsConfig } from "../types.js";
13
+ import type { HookAdapter, HookParadigm, PlatformCapabilities, DiagnosticResult, PreToolUseEvent, PostToolUseEvent, PreCompactEvent, SessionStartEvent, PreToolUseResponse, PostToolUseResponse, PreCompactResponse, SessionStartResponse, HookRegistration } from "../types.js";
14
14
  export declare class ZedAdapter implements HookAdapter {
15
15
  readonly name = "Zed";
16
16
  readonly paradigm: HookParadigm;
@@ -37,7 +37,5 @@ export declare class ZedAdapter implements HookAdapter {
37
37
  backupSettings(): string | null;
38
38
  setHookPermissions(_pluginRoot: string): string[];
39
39
  updatePluginRegistry(_pluginRoot: string, _version: string): void;
40
- getRoutingInstructionsConfig(): RoutingInstructionsConfig;
41
- writeRoutingInstructions(projectDir: string, pluginRoot: string): string | null;
42
40
  getRoutingInstructions(): string;
43
41
  }
@@ -175,36 +175,6 @@ export class ZedAdapter {
175
175
  updatePluginRegistry(_pluginRoot, _version) {
176
176
  // Zed has no plugin registry
177
177
  }
178
- // ── Routing Instructions (soft enforcement) ────────────
179
- getRoutingInstructionsConfig() {
180
- return {
181
- fileName: "AGENTS.md",
182
- globalPath: resolve(homedir(), ".config", "zed", "AGENTS.md"),
183
- projectRelativePath: "AGENTS.md",
184
- };
185
- }
186
- writeRoutingInstructions(projectDir, pluginRoot) {
187
- const config = this.getRoutingInstructionsConfig();
188
- const targetPath = resolve(projectDir, config.projectRelativePath);
189
- const sourcePath = resolve(pluginRoot, "configs", "zed", config.fileName);
190
- try {
191
- const content = readFileSync(sourcePath, "utf-8");
192
- try {
193
- const existing = readFileSync(targetPath, "utf-8");
194
- if (existing.includes("context-mode"))
195
- return null;
196
- writeFileSync(targetPath, existing.trimEnd() + "\n\n" + content, "utf-8");
197
- return targetPath;
198
- }
199
- catch {
200
- writeFileSync(targetPath, content, "utf-8");
201
- return targetPath;
202
- }
203
- }
204
- catch {
205
- return null;
206
- }
207
- }
208
178
  getRoutingInstructions() {
209
179
  const instructionsPath = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "..", "configs", "zed", "AGENTS.md");
210
180
  try {