@cleocode/adapters 2026.4.0 → 2026.4.3

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 (289) hide show
  1. package/dist/index.d.ts +9 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +724 -630
  4. package/dist/index.js.map +3 -3
  5. package/dist/providers/claude-code/adapter.d.ts +21 -1
  6. package/dist/providers/claude-code/adapter.d.ts.map +1 -1
  7. package/dist/providers/claude-code/context-monitor.d.ts +11 -0
  8. package/dist/providers/claude-code/context-monitor.d.ts.map +1 -1
  9. package/dist/providers/claude-code/hooks.d.ts +7 -0
  10. package/dist/providers/claude-code/hooks.d.ts.map +1 -1
  11. package/dist/providers/claude-code/index.d.ts +16 -1
  12. package/dist/providers/claude-code/index.d.ts.map +1 -1
  13. package/dist/providers/claude-code/install.d.ts +10 -18
  14. package/dist/providers/claude-code/install.d.ts.map +1 -1
  15. package/dist/providers/claude-code/paths.d.ts +8 -0
  16. package/dist/providers/claude-code/paths.d.ts.map +1 -1
  17. package/dist/providers/claude-code/spawn.d.ts +7 -0
  18. package/dist/providers/claude-code/spawn.d.ts.map +1 -1
  19. package/dist/providers/claude-code/statusline.d.ts +44 -0
  20. package/dist/providers/claude-code/statusline.d.ts.map +1 -1
  21. package/dist/providers/claude-code/task-sync.d.ts +8 -0
  22. package/dist/providers/claude-code/task-sync.d.ts.map +1 -1
  23. package/dist/providers/claude-code/transport.d.ts +11 -0
  24. package/dist/providers/claude-code/transport.d.ts.map +1 -1
  25. package/dist/providers/codex/adapter.d.ts +14 -1
  26. package/dist/providers/codex/adapter.d.ts.map +1 -1
  27. package/dist/providers/codex/hooks.d.ts +6 -0
  28. package/dist/providers/codex/hooks.d.ts.map +1 -1
  29. package/dist/providers/codex/index.d.ts +16 -1
  30. package/dist/providers/codex/index.d.ts.map +1 -1
  31. package/dist/providers/codex/install.d.ts +8 -17
  32. package/dist/providers/codex/install.d.ts.map +1 -1
  33. package/dist/providers/cursor/adapter.d.ts +15 -1
  34. package/dist/providers/cursor/adapter.d.ts.map +1 -1
  35. package/dist/providers/cursor/hooks.d.ts +7 -0
  36. package/dist/providers/cursor/hooks.d.ts.map +1 -1
  37. package/dist/providers/cursor/index.d.ts +16 -1
  38. package/dist/providers/cursor/index.d.ts.map +1 -1
  39. package/dist/providers/cursor/install.d.ts +10 -17
  40. package/dist/providers/cursor/install.d.ts.map +1 -1
  41. package/dist/providers/gemini-cli/adapter.d.ts +15 -1
  42. package/dist/providers/gemini-cli/adapter.d.ts.map +1 -1
  43. package/dist/providers/gemini-cli/hooks.d.ts +7 -0
  44. package/dist/providers/gemini-cli/hooks.d.ts.map +1 -1
  45. package/dist/providers/gemini-cli/index.d.ts +16 -1
  46. package/dist/providers/gemini-cli/index.d.ts.map +1 -1
  47. package/dist/providers/gemini-cli/install.d.ts +8 -17
  48. package/dist/providers/gemini-cli/install.d.ts.map +1 -1
  49. package/dist/providers/kimi/adapter.d.ts +15 -2
  50. package/dist/providers/kimi/adapter.d.ts.map +1 -1
  51. package/dist/providers/kimi/hooks.d.ts +6 -0
  52. package/dist/providers/kimi/hooks.d.ts.map +1 -1
  53. package/dist/providers/kimi/index.d.ts +16 -1
  54. package/dist/providers/kimi/index.d.ts.map +1 -1
  55. package/dist/providers/kimi/install.d.ts +7 -22
  56. package/dist/providers/kimi/install.d.ts.map +1 -1
  57. package/dist/providers/opencode/adapter.d.ts +17 -1
  58. package/dist/providers/opencode/adapter.d.ts.map +1 -1
  59. package/dist/providers/opencode/hooks.d.ts +9 -0
  60. package/dist/providers/opencode/hooks.d.ts.map +1 -1
  61. package/dist/providers/opencode/index.d.ts +16 -1
  62. package/dist/providers/opencode/index.d.ts.map +1 -1
  63. package/dist/providers/opencode/install.d.ts +8 -17
  64. package/dist/providers/opencode/install.d.ts.map +1 -1
  65. package/dist/providers/opencode/spawn.d.ts +23 -1
  66. package/dist/providers/opencode/spawn.d.ts.map +1 -1
  67. package/dist/providers/shared/transcript-reader.d.ts +15 -0
  68. package/dist/providers/shared/transcript-reader.d.ts.map +1 -1
  69. package/dist/registry.d.ts +54 -2
  70. package/dist/registry.d.ts.map +1 -1
  71. package/package.json +3 -3
  72. package/src/__tests__/claude-code-adapter.test.js +21 -30
  73. package/src/__tests__/claude-code-adapter.test.js.map +1 -1
  74. package/src/__tests__/claude-code-adapter.test.ts +21 -32
  75. package/src/__tests__/cursor-adapter.test.js +25 -29
  76. package/src/__tests__/cursor-adapter.test.js.map +1 -1
  77. package/src/__tests__/cursor-adapter.test.ts +26 -33
  78. package/src/__tests__/opencode-adapter.test.js +47 -46
  79. package/src/__tests__/opencode-adapter.test.js.map +1 -1
  80. package/src/__tests__/opencode-adapter.test.ts +51 -49
  81. package/src/index.ts +9 -1
  82. package/src/providers/claude-code/__tests__/adapter.test.js +50 -23
  83. package/src/providers/claude-code/__tests__/adapter.test.js.map +1 -1
  84. package/src/providers/claude-code/__tests__/adapter.test.ts +52 -23
  85. package/src/providers/claude-code/adapter.ts +22 -2
  86. package/src/providers/claude-code/context-monitor.ts +11 -0
  87. package/src/providers/claude-code/hooks.ts +7 -0
  88. package/src/providers/claude-code/index.ts +16 -1
  89. package/src/providers/claude-code/install.ts +15 -96
  90. package/src/providers/claude-code/manifest.json +1 -1
  91. package/src/providers/claude-code/paths.ts +8 -0
  92. package/src/providers/claude-code/spawn.ts +7 -0
  93. package/src/providers/claude-code/statusline.ts +44 -0
  94. package/src/providers/claude-code/task-sync.ts +8 -0
  95. package/src/providers/claude-code/transport.ts +11 -0
  96. package/src/providers/codex/adapter.ts +15 -2
  97. package/src/providers/codex/hooks.ts +6 -0
  98. package/src/providers/codex/index.ts +16 -1
  99. package/src/providers/codex/install.ts +17 -81
  100. package/src/providers/codex/manifest.json +1 -1
  101. package/src/providers/cursor/__tests__/adapter.test.js +37 -12
  102. package/src/providers/cursor/__tests__/adapter.test.js.map +1 -1
  103. package/src/providers/cursor/__tests__/adapter.test.ts +43 -12
  104. package/src/providers/cursor/adapter.ts +16 -2
  105. package/src/providers/cursor/hooks.ts +7 -0
  106. package/src/providers/cursor/index.ts +16 -1
  107. package/src/providers/cursor/install.ts +23 -88
  108. package/src/providers/cursor/manifest.json +1 -1
  109. package/src/providers/gemini-cli/adapter.ts +16 -2
  110. package/src/providers/gemini-cli/hooks.ts +7 -0
  111. package/src/providers/gemini-cli/index.ts +16 -1
  112. package/src/providers/gemini-cli/install.ts +17 -81
  113. package/src/providers/gemini-cli/manifest.json +1 -1
  114. package/src/providers/kimi/adapter.ts +16 -3
  115. package/src/providers/kimi/hooks.ts +6 -0
  116. package/src/providers/kimi/index.ts +16 -1
  117. package/src/providers/kimi/install.ts +16 -86
  118. package/src/providers/kimi/manifest.json +1 -1
  119. package/src/providers/opencode/__tests__/adapter.test.js +48 -35
  120. package/src/providers/opencode/__tests__/adapter.test.js.map +1 -1
  121. package/src/providers/opencode/__tests__/adapter.test.ts +49 -34
  122. package/src/providers/opencode/adapter.ts +18 -2
  123. package/src/providers/opencode/hooks.ts +9 -0
  124. package/src/providers/opencode/index.ts +16 -1
  125. package/src/providers/opencode/install.ts +17 -90
  126. package/src/providers/opencode/manifest.json +1 -1
  127. package/src/providers/opencode/spawn.ts +23 -1
  128. package/src/providers/shared/transcript-reader.ts +15 -0
  129. package/src/registry.ts +54 -2
  130. package/dist/providers/claude-code/adapter.js +0 -165
  131. package/dist/providers/claude-code/adapter.js.map +0 -1
  132. package/dist/providers/claude-code/context-monitor.js +0 -148
  133. package/dist/providers/claude-code/context-monitor.js.map +0 -1
  134. package/dist/providers/claude-code/hooks.js +0 -279
  135. package/dist/providers/claude-code/hooks.js.map +0 -1
  136. package/dist/providers/claude-code/index.js +0 -26
  137. package/dist/providers/claude-code/index.js.map +0 -1
  138. package/dist/providers/claude-code/install.js +0 -234
  139. package/dist/providers/claude-code/install.js.map +0 -1
  140. package/dist/providers/claude-code/paths.js +0 -33
  141. package/dist/providers/claude-code/paths.js.map +0 -1
  142. package/dist/providers/claude-code/spawn.js +0 -164
  143. package/dist/providers/claude-code/spawn.js.map +0 -1
  144. package/dist/providers/claude-code/statusline.js +0 -86
  145. package/dist/providers/claude-code/statusline.js.map +0 -1
  146. package/dist/providers/claude-code/task-sync.js +0 -111
  147. package/dist/providers/claude-code/task-sync.js.map +0 -1
  148. package/dist/providers/claude-code/transport.js +0 -18
  149. package/dist/providers/claude-code/transport.js.map +0 -1
  150. package/dist/providers/codex/adapter.js +0 -134
  151. package/dist/providers/codex/adapter.js.map +0 -1
  152. package/dist/providers/codex/hooks.js +0 -107
  153. package/dist/providers/codex/hooks.js.map +0 -1
  154. package/dist/providers/codex/index.js +0 -24
  155. package/dist/providers/codex/index.js.map +0 -1
  156. package/dist/providers/codex/install.js +0 -183
  157. package/dist/providers/codex/install.js.map +0 -1
  158. package/dist/providers/cursor/adapter.js +0 -138
  159. package/dist/providers/cursor/adapter.js.map +0 -1
  160. package/dist/providers/cursor/hooks.js +0 -201
  161. package/dist/providers/cursor/hooks.js.map +0 -1
  162. package/dist/providers/cursor/index.js +0 -21
  163. package/dist/providers/cursor/index.js.map +0 -1
  164. package/dist/providers/cursor/install.js +0 -238
  165. package/dist/providers/cursor/install.js.map +0 -1
  166. package/dist/providers/cursor/spawn.js +0 -59
  167. package/dist/providers/cursor/spawn.js.map +0 -1
  168. package/dist/providers/gemini-cli/adapter.js +0 -145
  169. package/dist/providers/gemini-cli/adapter.js.map +0 -1
  170. package/dist/providers/gemini-cli/hooks.js +0 -121
  171. package/dist/providers/gemini-cli/hooks.js.map +0 -1
  172. package/dist/providers/gemini-cli/index.js +0 -24
  173. package/dist/providers/gemini-cli/index.js.map +0 -1
  174. package/dist/providers/gemini-cli/install.js +0 -183
  175. package/dist/providers/gemini-cli/install.js.map +0 -1
  176. package/dist/providers/kimi/adapter.js +0 -133
  177. package/dist/providers/kimi/adapter.js.map +0 -1
  178. package/dist/providers/kimi/hooks.js +0 -73
  179. package/dist/providers/kimi/hooks.js.map +0 -1
  180. package/dist/providers/kimi/index.js +0 -24
  181. package/dist/providers/kimi/index.js.map +0 -1
  182. package/dist/providers/kimi/install.js +0 -189
  183. package/dist/providers/kimi/install.js.map +0 -1
  184. package/dist/providers/opencode/adapter.js +0 -151
  185. package/dist/providers/opencode/adapter.js.map +0 -1
  186. package/dist/providers/opencode/hooks.js +0 -197
  187. package/dist/providers/opencode/hooks.js.map +0 -1
  188. package/dist/providers/opencode/index.js +0 -22
  189. package/dist/providers/opencode/index.js.map +0 -1
  190. package/dist/providers/opencode/install.js +0 -180
  191. package/dist/providers/opencode/install.js.map +0 -1
  192. package/dist/providers/opencode/spawn.js +0 -219
  193. package/dist/providers/opencode/spawn.js.map +0 -1
  194. package/dist/providers/shared/transcript-reader.js +0 -109
  195. package/dist/providers/shared/transcript-reader.js.map +0 -1
  196. package/dist/registry.js +0 -55
  197. package/dist/registry.js.map +0 -1
  198. package/src/__tests__/claude-code-adapter.test.d.ts +0 -10
  199. package/src/__tests__/cursor-adapter.test.d.ts +0 -10
  200. package/src/__tests__/opencode-adapter.test.d.ts +0 -10
  201. package/src/index.d.ts +0 -35
  202. package/src/index.d.ts.map +0 -1
  203. package/src/index.js +0 -13
  204. package/src/index.js.map +0 -1
  205. package/src/providers/claude-code/__tests__/adapter.test.d.ts +0 -7
  206. package/src/providers/claude-code/adapter.d.ts +0 -79
  207. package/src/providers/claude-code/adapter.d.ts.map +0 -1
  208. package/src/providers/claude-code/adapter.js +0 -154
  209. package/src/providers/claude-code/adapter.js.map +0 -1
  210. package/src/providers/claude-code/context-monitor.d.ts +0 -24
  211. package/src/providers/claude-code/context-monitor.d.ts.map +0 -1
  212. package/src/providers/claude-code/context-monitor.js +0 -148
  213. package/src/providers/claude-code/context-monitor.js.map +0 -1
  214. package/src/providers/claude-code/hooks.d.ts +0 -59
  215. package/src/providers/claude-code/hooks.d.ts.map +0 -1
  216. package/src/providers/claude-code/hooks.js +0 -77
  217. package/src/providers/claude-code/hooks.js.map +0 -1
  218. package/src/providers/claude-code/index.d.ts +0 -28
  219. package/src/providers/claude-code/index.d.ts.map +0 -1
  220. package/src/providers/claude-code/index.js +0 -26
  221. package/src/providers/claude-code/index.js.map +0 -1
  222. package/src/providers/claude-code/install.d.ts +0 -75
  223. package/src/providers/claude-code/install.d.ts.map +0 -1
  224. package/src/providers/claude-code/install.js +0 -234
  225. package/src/providers/claude-code/install.js.map +0 -1
  226. package/src/providers/claude-code/paths.d.ts +0 -24
  227. package/src/providers/claude-code/paths.d.ts.map +0 -1
  228. package/src/providers/claude-code/paths.js +0 -33
  229. package/src/providers/claude-code/paths.js.map +0 -1
  230. package/src/providers/claude-code/spawn.d.ts +0 -60
  231. package/src/providers/claude-code/spawn.d.ts.map +0 -1
  232. package/src/providers/claude-code/spawn.js +0 -164
  233. package/src/providers/claude-code/spawn.js.map +0 -1
  234. package/src/providers/claude-code/statusline.d.ts +0 -23
  235. package/src/providers/claude-code/statusline.d.ts.map +0 -1
  236. package/src/providers/claude-code/statusline.js +0 -86
  237. package/src/providers/claude-code/statusline.js.map +0 -1
  238. package/src/providers/claude-code/task-sync.js +0 -122
  239. package/src/providers/claude-code/task-sync.js.map +0 -1
  240. package/src/providers/claude-code/transport.d.ts +0 -14
  241. package/src/providers/claude-code/transport.d.ts.map +0 -1
  242. package/src/providers/claude-code/transport.js +0 -18
  243. package/src/providers/claude-code/transport.js.map +0 -1
  244. package/src/providers/cursor/__tests__/adapter.test.d.ts +0 -7
  245. package/src/providers/cursor/adapter.d.ts +0 -66
  246. package/src/providers/cursor/adapter.d.ts.map +0 -1
  247. package/src/providers/cursor/adapter.js +0 -124
  248. package/src/providers/cursor/adapter.js.map +0 -1
  249. package/src/providers/cursor/hooks.d.ts +0 -48
  250. package/src/providers/cursor/hooks.d.ts.map +0 -1
  251. package/src/providers/cursor/hooks.js +0 -55
  252. package/src/providers/cursor/hooks.js.map +0 -1
  253. package/src/providers/cursor/index.d.ts +0 -19
  254. package/src/providers/cursor/index.d.ts.map +0 -1
  255. package/src/providers/cursor/index.js +0 -21
  256. package/src/providers/cursor/index.js.map +0 -1
  257. package/src/providers/cursor/install.d.ts +0 -94
  258. package/src/providers/cursor/install.d.ts.map +0 -1
  259. package/src/providers/cursor/install.js +0 -238
  260. package/src/providers/cursor/install.js.map +0 -1
  261. package/src/providers/cursor/spawn.d.ts +0 -50
  262. package/src/providers/cursor/spawn.d.ts.map +0 -1
  263. package/src/providers/cursor/spawn.js +0 -59
  264. package/src/providers/cursor/spawn.js.map +0 -1
  265. package/src/providers/opencode/__tests__/adapter.test.d.ts +0 -7
  266. package/src/providers/opencode/adapter.d.ts +0 -71
  267. package/src/providers/opencode/adapter.d.ts.map +0 -1
  268. package/src/providers/opencode/adapter.js +0 -144
  269. package/src/providers/opencode/adapter.js.map +0 -1
  270. package/src/providers/opencode/hooks.d.ts +0 -66
  271. package/src/providers/opencode/hooks.d.ts.map +0 -1
  272. package/src/providers/opencode/hooks.js +0 -89
  273. package/src/providers/opencode/hooks.js.map +0 -1
  274. package/src/providers/opencode/index.d.ts +0 -20
  275. package/src/providers/opencode/index.d.ts.map +0 -1
  276. package/src/providers/opencode/index.js +0 -22
  277. package/src/providers/opencode/index.js.map +0 -1
  278. package/src/providers/opencode/install.d.ts +0 -65
  279. package/src/providers/opencode/install.d.ts.map +0 -1
  280. package/src/providers/opencode/install.js +0 -180
  281. package/src/providers/opencode/install.js.map +0 -1
  282. package/src/providers/opencode/spawn.d.ts +0 -75
  283. package/src/providers/opencode/spawn.d.ts.map +0 -1
  284. package/src/providers/opencode/spawn.js +0 -219
  285. package/src/providers/opencode/spawn.js.map +0 -1
  286. package/src/registry.d.ts +0 -36
  287. package/src/registry.d.ts.map +0 -1
  288. package/src/registry.js +0 -55
  289. package/src/registry.js.map +0 -1
package/dist/index.js CHANGED
@@ -8,23 +8,27 @@ var __export = (target, all) => {
8
8
  __defProp(target, name, { get: all[name], enumerable: true });
9
9
  };
10
10
 
11
- // packages/adapters/src/providers/claude-code/paths.js
11
+ // packages/adapters/src/providers/claude-code/paths.ts
12
12
  import { homedir } from "node:os";
13
13
  import { join } from "node:path";
14
14
  var ClaudeCodePathProvider;
15
15
  var init_paths = __esm({
16
- "packages/adapters/src/providers/claude-code/paths.js"() {
16
+ "packages/adapters/src/providers/claude-code/paths.ts"() {
17
17
  "use strict";
18
18
  ClaudeCodePathProvider = class {
19
+ /** Get the provider's root configuration directory. */
19
20
  getProviderDir() {
20
21
  return process.env["CLAUDE_HOME"] ?? join(homedir(), ".claude");
21
22
  }
23
+ /** Get the path to the provider's settings file, or null if unavailable. */
22
24
  getSettingsPath() {
23
25
  return process.env["CLAUDE_SETTINGS"] ?? join(this.getProviderDir(), "settings.json");
24
26
  }
27
+ /** Get the directory where agents are installed, or null if unsupported. */
25
28
  getAgentInstallDir() {
26
29
  return join(this.getProviderDir(), "agents");
27
30
  }
31
+ /** Get the path to the provider's memory database, or null if unsupported. */
28
32
  getMemoryDbPath() {
29
33
  return process.env["CLAUDE_MEM_DB"] ?? join(homedir(), ".claude-mem", "claude-mem.db");
30
34
  }
@@ -32,25 +36,21 @@ var init_paths = __esm({
32
36
  }
33
37
  });
34
38
 
35
- // packages/adapters/src/providers/claude-code/context-monitor.js
39
+ // packages/adapters/src/providers/claude-code/context-monitor.ts
36
40
  import { existsSync, readFileSync, writeFileSync } from "node:fs";
37
41
  import { mkdir } from "node:fs/promises";
38
42
  import { homedir as homedir2 } from "node:os";
39
43
  import { dirname, join as join2 } from "node:path";
40
44
  function getContextStatusFromPercentage(percentage) {
41
- if (percentage >= THRESHOLDS.EMERGENCY)
42
- return "emergency";
43
- if (percentage >= THRESHOLDS.CRITICAL)
44
- return "critical";
45
- if (percentage >= THRESHOLDS.CAUTION)
46
- return "caution";
47
- if (percentage >= THRESHOLDS.WARNING)
48
- return "warning";
45
+ if (percentage >= THRESHOLDS.EMERGENCY) return "emergency";
46
+ if (percentage >= THRESHOLDS.CRITICAL) return "critical";
47
+ if (percentage >= THRESHOLDS.CAUTION) return "caution";
48
+ if (percentage >= THRESHOLDS.WARNING) return "warning";
49
49
  return "ok";
50
50
  }
51
51
  var THRESHOLDS, ClaudeCodeContextMonitorProvider;
52
52
  var init_context_monitor = __esm({
53
- "packages/adapters/src/providers/claude-code/context-monitor.js"() {
53
+ "packages/adapters/src/providers/claude-code/context-monitor.ts"() {
54
54
  "use strict";
55
55
  init_paths();
56
56
  THRESHOLDS = {
@@ -60,13 +60,14 @@ var init_context_monitor = __esm({
60
60
  EMERGENCY: 95
61
61
  };
62
62
  ClaudeCodeContextMonitorProvider = class {
63
+ /** Path provider for resolving Claude Code directory locations. */
63
64
  pathProvider = new ClaudeCodePathProvider();
65
+ /** Process raw context window JSON and return a formatted summary string. */
64
66
  async processContextInput(input, cwd) {
65
67
  const typed = input;
66
68
  const contextSize = typed.context_window?.context_window_size ?? 2e5;
67
69
  const usage = typed.context_window?.current_usage;
68
- if (!usage)
69
- return "-- no data";
70
+ if (!usage) return "-- no data";
70
71
  const inputTokens = usage.input_tokens ?? 0;
71
72
  const outputTokens = usage.output_tokens ?? 0;
72
73
  const cacheCreate = usage.cache_creation_input_tokens ?? 0;
@@ -110,17 +111,15 @@ var init_context_monitor = __esm({
110
111
  }
111
112
  return `${percentage}% | ${totalTokens}/${contextSize}`;
112
113
  }
114
+ /** Check the current statusline integration status in Claude Code settings. */
113
115
  checkStatuslineIntegration() {
114
116
  const settingsPath = this.pathProvider.getSettingsPath();
115
- if (!settingsPath || !existsSync(settingsPath))
116
- return "no_settings";
117
+ if (!settingsPath || !existsSync(settingsPath)) return "no_settings";
117
118
  try {
118
119
  const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
119
120
  const statusLine = settings.statusLine;
120
- if (!statusLine?.type)
121
- return "not_configured";
122
- if (statusLine.type !== "command")
123
- return "custom_no_cleo";
121
+ if (!statusLine?.type) return "not_configured";
122
+ if (statusLine.type !== "command") return "custom_no_cleo";
124
123
  const cmd = statusLine.command ?? "";
125
124
  if (cmd.includes("context-monitor.sh") || cmd.includes("cleo-statusline") || cmd.includes(".context-state.json") || cmd.includes("context-states")) {
126
125
  return "configured";
@@ -129,8 +128,7 @@ var init_context_monitor = __esm({
129
128
  if (existsSync(scriptPath)) {
130
129
  try {
131
130
  const content = readFileSync(scriptPath, "utf-8");
132
- if (content.includes("context-state.json"))
133
- return "configured";
131
+ if (content.includes("context-state.json")) return "configured";
134
132
  } catch {
135
133
  }
136
134
  }
@@ -139,6 +137,7 @@ var init_context_monitor = __esm({
139
137
  return "no_settings";
140
138
  }
141
139
  }
140
+ /** Get the recommended statusline configuration object for Claude Code settings. */
142
141
  getStatuslineConfig() {
143
142
  return {
144
143
  statusLine: {
@@ -147,6 +146,7 @@ var init_context_monitor = __esm({
147
146
  }
148
147
  };
149
148
  }
149
+ /** Get human-readable setup instructions for enabling context monitoring. */
150
150
  getSetupInstructions() {
151
151
  const settingsPath = this.pathProvider.getSettingsPath() ?? "~/.claude/settings.json";
152
152
  return [
@@ -162,24 +162,58 @@ var init_context_monitor = __esm({
162
162
  }
163
163
  });
164
164
 
165
- // packages/adapters/src/providers/claude-code/hooks.js
166
- var CLAUDE_CODE_EVENT_MAP, ClaudeCodeHookProvider;
165
+ // packages/adapters/src/providers/claude-code/hooks.ts
166
+ import { readdir, readFile } from "node:fs/promises";
167
+ import { join as join3 } from "node:path";
168
+ var PROVIDER_ID, CLAUDE_CODE_EVENT_MAP, ClaudeCodeHookProvider;
167
169
  var init_hooks = __esm({
168
- "packages/adapters/src/providers/claude-code/hooks.js"() {
170
+ "packages/adapters/src/providers/claude-code/hooks.ts"() {
169
171
  "use strict";
172
+ PROVIDER_ID = "claude-code";
170
173
  CLAUDE_CODE_EVENT_MAP = {
171
- SessionStart: "onSessionStart",
172
- PostToolUse: "onToolComplete",
173
- UserPromptSubmit: "onPromptSubmit",
174
- Stop: "onSessionEnd"
174
+ // CAAMP: toNative('SessionStart', 'claude-code') = 'SessionStart'
175
+ SessionStart: "SessionStart",
176
+ // CAAMP: toNative('SessionEnd', 'claude-code') = 'SessionEnd'
177
+ SessionEnd: "SessionEnd",
178
+ // CAAMP: toNative('PromptSubmit', 'claude-code') = 'UserPromptSubmit'
179
+ UserPromptSubmit: "PromptSubmit",
180
+ // CAAMP: toNative('ResponseComplete', 'claude-code') = 'Stop'
181
+ Stop: "ResponseComplete",
182
+ // CAAMP: toNative('PreToolUse', 'claude-code') = 'PreToolUse'
183
+ PreToolUse: "PreToolUse",
184
+ // CAAMP: toNative('PostToolUse', 'claude-code') = 'PostToolUse'
185
+ PostToolUse: "PostToolUse",
186
+ // CAAMP: toNative('PostToolUseFailure','claude-code') = 'PostToolUseFailure'
187
+ PostToolUseFailure: "PostToolUseFailure",
188
+ // CAAMP: toNative('PermissionRequest', 'claude-code') = 'PermissionRequest'
189
+ PermissionRequest: "PermissionRequest",
190
+ // CAAMP: toNative('SubagentStart', 'claude-code') = 'SubagentStart'
191
+ SubagentStart: "SubagentStart",
192
+ // CAAMP: toNative('SubagentStop', 'claude-code') = 'SubagentStop'
193
+ SubagentStop: "SubagentStop",
194
+ // CAAMP: toNative('PreCompact', 'claude-code') = 'PreCompact'
195
+ PreCompact: "PreCompact",
196
+ // CAAMP: toNative('PostCompact', 'claude-code') = 'PostCompact'
197
+ PostCompact: "PostCompact",
198
+ // CAAMP: toNative('Notification', 'claude-code') = 'Notification'
199
+ Notification: "Notification",
200
+ // CAAMP: toNative('ConfigChange', 'claude-code') = 'ConfigChange'
201
+ ConfigChange: "ConfigChange"
175
202
  };
176
203
  ClaudeCodeHookProvider = class {
204
+ /** Whether hooks have been registered for the current session. */
177
205
  registered = false;
178
206
  /**
179
- * Map a Claude Code native event name to a CAAMP hook event name.
207
+ * Map a Claude Code native event name to a CAAMP canonical hook event name.
208
+ *
209
+ * Looks up the native event name in the map derived from
210
+ * `getProviderHookProfile('claude-code').mappings` (CAAMP 1.9.1).
211
+ * Returns null for unrecognised events (e.g. PreModel, PostModel which
212
+ * Claude Code does not support).
180
213
  *
181
- * @param providerEvent - Claude Code event name (e.g. "SessionStart", "PostToolUse")
182
- * @returns CAAMP event name or null if unmapped
214
+ * @param providerEvent - Claude Code native event (e.g. "UserPromptSubmit", "Stop")
215
+ * @returns CAAMP canonical event name, or null if unmapped
216
+ * @task T164
183
217
  */
184
218
  mapProviderEvent(providerEvent) {
185
219
  return CLAUDE_CODE_EVENT_MAP[providerEvent] ?? null;
@@ -187,12 +221,15 @@ var init_hooks = __esm({
187
221
  /**
188
222
  * Register native hooks for a project.
189
223
  *
190
- * For Claude Code, hooks are registered via the plugin system
191
- * (hooks.json descriptor), which is handled by the
192
- * install provider. This method is a no-op since registration
193
- * is managed through the plugin install lifecycle.
224
+ * For Claude Code, hooks are registered via the config system
225
+ * (`~/.claude/settings.json`), managed by the install provider.
226
+ * This method marks hooks as registered without performing filesystem operations.
194
227
  *
195
- * @param _projectDir - Project directory (unused; hooks are global)
228
+ * Iterating supported events is handled at install time using
229
+ * `getSupportedCanonicalEvents()` to enumerate all 14 supported hooks.
230
+ *
231
+ * @param _projectDir - Project directory (unused; Claude Code uses global config)
232
+ * @task T164
196
233
  */
197
234
  async registerNativeHooks(_projectDir) {
198
235
  this.registered = true;
@@ -200,111 +237,206 @@ var init_hooks = __esm({
200
237
  /**
201
238
  * Unregister native hooks.
202
239
  *
203
- * For Claude Code, this is a no-op since hooks are managed through
204
- * the plugin system. Unregistration happens via the install provider's
205
- * uninstall method.
240
+ * For Claude Code, this is a no-op since hooks are managed through the config
241
+ * system. Unregistration happens via the install provider's uninstall method.
242
+ *
243
+ * @task T164
206
244
  */
207
245
  async unregisterNativeHooks() {
208
246
  this.registered = false;
209
247
  }
210
248
  /**
211
- * Check whether hooks have been registered via registerNativeHooks.
249
+ * Check whether hooks have been registered via `registerNativeHooks`.
212
250
  */
213
251
  isRegistered() {
214
252
  return this.registered;
215
253
  }
216
254
  /**
217
- * Get the full event mapping for introspection/debugging.
255
+ * Get the native→canonical event mapping for introspection and debugging.
256
+ *
257
+ * Returns the map derived from `getProviderHookProfile('claude-code').mappings`
258
+ * (CAAMP 1.9.1). Use `getSupportedCanonicalEvents()` to enumerate canonical
259
+ * names via live CAAMP APIs.
260
+ *
261
+ * @returns Immutable record of native event name → canonical event name
218
262
  */
219
263
  getEventMap() {
220
264
  return { ...CLAUDE_CODE_EVENT_MAP };
221
265
  }
266
+ /**
267
+ * Enumerate supported canonical events via CAAMP's `getSupportedEvents()`.
268
+ *
269
+ * Calls `getSupportedEvents('claude-code')` from the CAAMP normalizer to
270
+ * get the authoritative list. Claude Code supports 14 of 16 canonical events
271
+ * (PreModel and PostModel are not supported). Falls back to the values of
272
+ * the static event map when CAAMP is unavailable at runtime.
273
+ *
274
+ * @returns Array of CAAMP canonical event names supported by Claude Code
275
+ * @task T164
276
+ */
277
+ async getSupportedCanonicalEvents() {
278
+ try {
279
+ const { getSupportedEvents } = await import("@cleocode/caamp");
280
+ return getSupportedEvents(PROVIDER_ID);
281
+ } catch {
282
+ return [...new Set(Object.values(CLAUDE_CODE_EVENT_MAP))];
283
+ }
284
+ }
285
+ /**
286
+ * Retrieve the full provider hook profile from CAAMP.
287
+ *
288
+ * Calls `getProviderHookProfile('claude-code')` from the CAAMP normalizer to
289
+ * get the complete profile: hook system type (`config`), config path
290
+ * (`~/.claude/settings.json`), handler types, and all event mappings.
291
+ * Returns null when CAAMP is unavailable at runtime.
292
+ *
293
+ * @returns Provider hook profile or null if CAAMP is unavailable
294
+ * @task T164
295
+ */
296
+ async getProviderProfile() {
297
+ try {
298
+ const { getProviderHookProfile } = await import("@cleocode/caamp");
299
+ return getProviderHookProfile(PROVIDER_ID) ?? null;
300
+ } catch {
301
+ return null;
302
+ }
303
+ }
304
+ /**
305
+ * Translate a CAAMP canonical event to its Claude Code native name via CAAMP.
306
+ *
307
+ * Calls `toNative(canonical, 'claude-code')` from the CAAMP normalizer.
308
+ * Returns null for unsupported events (PreModel, PostModel) or when
309
+ * CAAMP is unavailable.
310
+ *
311
+ * @param canonical - CAAMP canonical event name (e.g. "PromptSubmit")
312
+ * @returns Claude Code native event name or null
313
+ * @task T164
314
+ */
315
+ async toNativeEvent(canonical) {
316
+ try {
317
+ const { toNative } = await import("@cleocode/caamp");
318
+ return toNative(canonical, PROVIDER_ID);
319
+ } catch {
320
+ const entry = Object.entries(CLAUDE_CODE_EVENT_MAP).find(([, v]) => v === canonical);
321
+ return entry?.[0] ?? null;
322
+ }
323
+ }
324
+ /**
325
+ * Extract a plain-text transcript from Claude Code session JSONL files.
326
+ *
327
+ * Reads the most recent .jsonl file under `~/.claude/projects/` and
328
+ * extracts user/assistant turn text into a flat string for brain
329
+ * observation extraction.
330
+ *
331
+ * Returns null when no session data is found or on any read error.
332
+ *
333
+ * @param _sessionId - CLEO session ID (unused; reads the most recent file)
334
+ * @param _projectDir - Project directory (unused; Claude Code uses global paths)
335
+ * @task T144 @epic T134
336
+ */
337
+ async getTranscript(_sessionId, _projectDir) {
338
+ try {
339
+ const homeDir = process.env.HOME ?? process.env.USERPROFILE ?? "/root";
340
+ const projectsDir = join3(homeDir, ".claude", "projects");
341
+ let allFiles = [];
342
+ try {
343
+ const projectDirs = await readdir(projectsDir, { withFileTypes: true });
344
+ for (const entry of projectDirs) {
345
+ if (!entry.isDirectory()) continue;
346
+ const subDir = join3(projectsDir, entry.name);
347
+ try {
348
+ const files = await readdir(subDir);
349
+ for (const file of files) {
350
+ if (!file.endsWith(".jsonl")) continue;
351
+ const filePath = join3(subDir, file);
352
+ allFiles.push({ path: filePath, mtime: 0 });
353
+ }
354
+ } catch {
355
+ }
356
+ }
357
+ } catch {
358
+ return null;
359
+ }
360
+ if (allFiles.length === 0) return null;
361
+ allFiles = allFiles.sort((a, b) => b.path.localeCompare(a.path));
362
+ const mostRecent = allFiles[0];
363
+ if (!mostRecent) return null;
364
+ const raw = await readFile(mostRecent.path, "utf-8");
365
+ const lines = raw.split("\n").filter((l) => l.trim());
366
+ const turns = [];
367
+ for (const line of lines) {
368
+ try {
369
+ const entry = JSON.parse(line);
370
+ const role = entry.role;
371
+ const content = entry.content;
372
+ if (role === "assistant" && typeof content === "string") {
373
+ turns.push(`assistant: ${content}`);
374
+ } else if (role === "user" && typeof content === "string") {
375
+ turns.push(`user: ${content}`);
376
+ }
377
+ } catch {
378
+ }
379
+ }
380
+ return turns.length > 0 ? turns.join("\n") : null;
381
+ } catch {
382
+ return null;
383
+ }
384
+ }
222
385
  };
223
386
  }
224
387
  });
225
388
 
226
- // packages/adapters/src/providers/claude-code/install.js
389
+ // packages/adapters/src/providers/claude-code/install.ts
227
390
  import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
228
391
  import { homedir as homedir3 } from "node:os";
229
- import { join as join3 } from "node:path";
230
- var INSTRUCTION_REFERENCES, MCP_SERVER_KEY, ClaudeCodeInstallProvider;
392
+ import { join as join4 } from "node:path";
393
+ var INSTRUCTION_REFERENCES, ClaudeCodeInstallProvider;
231
394
  var init_install = __esm({
232
- "packages/adapters/src/providers/claude-code/install.js"() {
395
+ "packages/adapters/src/providers/claude-code/install.ts"() {
233
396
  "use strict";
234
397
  INSTRUCTION_REFERENCES = ["@~/.cleo/templates/CLEO-INJECTION.md", "@.cleo/memory-bridge.md"];
235
- MCP_SERVER_KEY = "cleo";
236
398
  ClaudeCodeInstallProvider = class {
237
- installedProjectDir = null;
238
399
  /**
239
400
  * Install CLEO into a Claude Code project.
240
401
  *
241
- * @param options - Installation options including project directory and MCP server path
402
+ * @param options - Installation options including project directory
242
403
  * @returns Result describing what was installed
243
404
  */
244
405
  async install(options) {
245
- const { projectDir, mcpServerPath } = options;
406
+ const { projectDir } = options;
246
407
  const installedAt = (/* @__PURE__ */ new Date()).toISOString();
247
408
  let instructionFileUpdated = false;
248
- let mcpRegistered = false;
249
409
  const details = {};
250
- if (mcpServerPath) {
251
- mcpRegistered = this.registerMcpServer(projectDir, mcpServerPath);
252
- if (mcpRegistered) {
253
- details.mcpConfigPath = join3(projectDir, ".mcp.json");
254
- }
255
- }
256
410
  instructionFileUpdated = this.updateInstructionFile(projectDir);
257
411
  if (instructionFileUpdated) {
258
- details.instructionFile = join3(projectDir, "CLAUDE.md");
412
+ details.instructionFile = join4(projectDir, "CLAUDE.md");
259
413
  }
260
414
  const pluginResult = this.registerPlugin();
261
415
  if (pluginResult) {
262
416
  details.plugin = pluginResult;
263
417
  }
264
- this.installedProjectDir = projectDir;
265
418
  return {
266
419
  success: true,
267
420
  installedAt,
268
421
  instructionFileUpdated,
269
- mcpRegistered,
422
+ mcpRegistered: false,
270
423
  details
271
424
  };
272
425
  }
273
426
  /**
274
427
  * Uninstall CLEO from the current Claude Code project.
275
428
  *
276
- * Removes the MCP server registration from .mcp.json.
277
429
  * Does not remove CLAUDE.md references (they are harmless if CLEO is not present).
278
430
  */
279
431
  async uninstall() {
280
- if (!this.installedProjectDir)
281
- return;
282
- const mcpPath = join3(this.installedProjectDir, ".mcp.json");
283
- if (existsSync2(mcpPath)) {
284
- try {
285
- const raw = readFileSync2(mcpPath, "utf-8");
286
- const config = JSON.parse(raw);
287
- const mcpServers = config.mcpServers;
288
- if (mcpServers && MCP_SERVER_KEY in mcpServers) {
289
- delete mcpServers[MCP_SERVER_KEY];
290
- writeFileSync2(mcpPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
291
- }
292
- } catch {
293
- }
294
- }
295
- this.installedProjectDir = null;
296
432
  }
297
433
  /**
298
434
  * Check whether CLEO is installed in the current environment.
299
435
  *
300
- * Checks for:
301
- * 1. MCP server registered in .mcp.json
302
- * 2. Plugin enabled in ~/.claude/settings.json
303
- *
304
- * Returns true if either condition is met (partial install counts).
436
+ * Checks for plugin enabled in ~/.claude/settings.json.
305
437
  */
306
438
  async isInstalled() {
307
- const settingsPath = join3(homedir3(), ".claude", "settings.json");
439
+ const settingsPath = join4(homedir3(), ".claude", "settings.json");
308
440
  if (existsSync2(settingsPath)) {
309
441
  try {
310
442
  const settings = JSON.parse(readFileSync2(settingsPath, "utf-8"));
@@ -315,17 +447,6 @@ var init_install = __esm({
315
447
  } catch {
316
448
  }
317
449
  }
318
- const mcpPath = join3(process.cwd(), ".mcp.json");
319
- if (existsSync2(mcpPath)) {
320
- try {
321
- const config = JSON.parse(readFileSync2(mcpPath, "utf-8"));
322
- const mcpServers = config.mcpServers;
323
- if (mcpServers && MCP_SERVER_KEY in mcpServers) {
324
- return true;
325
- }
326
- } catch {
327
- }
328
- }
329
450
  return false;
330
451
  }
331
452
  /**
@@ -338,38 +459,13 @@ var init_install = __esm({
338
459
  async ensureInstructionReferences(projectDir) {
339
460
  this.updateInstructionFile(projectDir);
340
461
  }
341
- /**
342
- * Register the CLEO MCP server in .mcp.json.
343
- *
344
- * @returns true if registration was performed or updated
345
- */
346
- registerMcpServer(projectDir, mcpServerPath) {
347
- const mcpPath = join3(projectDir, ".mcp.json");
348
- let config = {};
349
- if (existsSync2(mcpPath)) {
350
- try {
351
- config = JSON.parse(readFileSync2(mcpPath, "utf-8"));
352
- } catch {
353
- }
354
- }
355
- if (!config.mcpServers || typeof config.mcpServers !== "object") {
356
- config.mcpServers = {};
357
- }
358
- const mcpServers = config.mcpServers;
359
- mcpServers[MCP_SERVER_KEY] = {
360
- command: "node",
361
- args: [mcpServerPath]
362
- };
363
- writeFileSync2(mcpPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
364
- return true;
365
- }
366
462
  /**
367
463
  * Update CLAUDE.md with CLEO @-references.
368
464
  *
369
465
  * @returns true if the file was created or modified
370
466
  */
371
467
  updateInstructionFile(projectDir) {
372
- const claudeMdPath = join3(projectDir, "CLAUDE.md");
468
+ const claudeMdPath = join4(projectDir, "CLAUDE.md");
373
469
  let content = "";
374
470
  let existed = false;
375
471
  if (existsSync2(claudeMdPath)) {
@@ -397,7 +493,7 @@ var init_install = __esm({
397
493
  */
398
494
  registerPlugin() {
399
495
  const home = homedir3();
400
- const settingsPath = join3(home, ".claude", "settings.json");
496
+ const settingsPath = join4(home, ".claude", "settings.json");
401
497
  let settings = {};
402
498
  if (existsSync2(settingsPath)) {
403
499
  try {
@@ -415,7 +511,7 @@ var init_install = __esm({
415
511
  }
416
512
  enabledPlugins[pluginKey] = true;
417
513
  settings.enabledPlugins = enabledPlugins;
418
- mkdirSync(join3(home, ".claude"), { recursive: true });
514
+ mkdirSync(join4(home, ".claude"), { recursive: true });
419
515
  writeFileSync2(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
420
516
  return `Enabled ${pluginKey} in ~/.claude/settings.json`;
421
517
  }
@@ -593,13 +689,13 @@ var init_src = __esm({
593
689
  }
594
690
  });
595
691
 
596
- // packages/adapters/src/providers/claude-code/spawn.js
692
+ // packages/adapters/src/providers/claude-code/spawn.ts
597
693
  import { exec, spawn as nodeSpawn } from "node:child_process";
598
694
  import { unlink, writeFile } from "node:fs/promises";
599
695
  import { promisify } from "node:util";
600
696
  var execAsync, ClaudeCodeSpawnProvider;
601
697
  var init_spawn = __esm({
602
- "packages/adapters/src/providers/claude-code/spawn.js"() {
698
+ "packages/adapters/src/providers/claude-code/spawn.ts"() {
603
699
  "use strict";
604
700
  init_src();
605
701
  execAsync = promisify(exec);
@@ -722,8 +818,7 @@ var init_spawn = __esm({
722
818
  */
723
819
  async terminate(instanceId) {
724
820
  const tracked = this.processMap.get(instanceId);
725
- if (!tracked)
726
- return;
821
+ if (!tracked) return;
727
822
  try {
728
823
  process.kill(tracked.pid, "SIGTERM");
729
824
  } catch {
@@ -734,9 +829,9 @@ var init_spawn = __esm({
734
829
  }
735
830
  });
736
831
 
737
- // packages/adapters/src/providers/claude-code/task-sync.js
738
- import { readFile, rm, stat } from "node:fs/promises";
739
- import { join as join4 } from "node:path";
832
+ // packages/adapters/src/providers/claude-code/task-sync.ts
833
+ import { readFile as readFile2, stat } from "node:fs/promises";
834
+ import { join as join5 } from "node:path";
740
835
  function parseTaskId(content) {
741
836
  const match = content.match(/^\[T(\d+)\]/);
742
837
  return match ? `T${match[1]}` : null;
@@ -757,17 +852,19 @@ function mapStatus(twStatus) {
757
852
  }
758
853
  }
759
854
  function getTodoWriteFilePath(projectDir) {
760
- return join4(projectDir, ".cleo", "sync", "todowrite-state.json");
855
+ return join5(projectDir, ".cleo", "sync", "todowrite-state.json");
761
856
  }
762
857
  var ClaudeCodeTaskSyncProvider;
763
858
  var init_task_sync = __esm({
764
- "packages/adapters/src/providers/claude-code/task-sync.js"() {
859
+ "packages/adapters/src/providers/claude-code/task-sync.ts"() {
765
860
  "use strict";
766
861
  ClaudeCodeTaskSyncProvider = class {
862
+ /** Optional override path for the TodoWrite state file (used in tests). */
767
863
  customFilePath;
768
864
  constructor(options) {
769
865
  this.customFilePath = options?.filePath;
770
866
  }
867
+ /** Retrieve external tasks from Claude's TodoWrite state file. */
771
868
  async getExternalTasks(projectDir) {
772
869
  const filePath = this.customFilePath ?? getTodoWriteFilePath(projectDir);
773
870
  try {
@@ -775,7 +872,7 @@ var init_task_sync = __esm({
775
872
  } catch {
776
873
  return [];
777
874
  }
778
- const raw = await readFile(filePath, "utf-8");
875
+ const raw = await readFile2(filePath, "utf-8");
779
876
  let state;
780
877
  try {
781
878
  state = JSON.parse(raw);
@@ -790,15 +887,14 @@ var init_task_sync = __esm({
790
887
  for (const item of state.todos) {
791
888
  const cleoTaskId = parseTaskId(item.content);
792
889
  const title = cleoTaskId ? stripPrefixes(item.content).trim() : item.content.trim();
793
- if (!title)
794
- continue;
890
+ if (!title) continue;
795
891
  tasks.push({
796
892
  externalId: cleoTaskId ?? `tw-new-${syntheticIndex++}`,
797
- cleoTaskId,
798
893
  title,
799
894
  status: mapStatus(item.status),
800
895
  providerMeta: {
801
896
  source: "todowrite",
897
+ cleoTaskId,
802
898
  activeForm: item.activeForm,
803
899
  rawContent: item.content
804
900
  }
@@ -806,24 +902,19 @@ var init_task_sync = __esm({
806
902
  }
807
903
  return tasks;
808
904
  }
809
- async cleanup(projectDir) {
810
- const filePath = this.customFilePath ?? getTodoWriteFilePath(projectDir);
811
- try {
812
- await rm(filePath);
813
- } catch {
814
- }
815
- }
816
905
  };
817
906
  }
818
907
  });
819
908
 
820
- // packages/adapters/src/providers/claude-code/transport.js
909
+ // packages/adapters/src/providers/claude-code/transport.ts
821
910
  var ClaudeCodeTransportProvider;
822
911
  var init_transport = __esm({
823
- "packages/adapters/src/providers/claude-code/transport.js"() {
912
+ "packages/adapters/src/providers/claude-code/transport.ts"() {
824
913
  "use strict";
825
914
  ClaudeCodeTransportProvider = class {
915
+ /** Provider-specific transport name used for capability negotiation. */
826
916
  transportName = "claude-code";
917
+ /** Create a transport instance for inter-agent messaging. */
827
918
  createTransport() {
828
919
  return null;
829
920
  }
@@ -831,15 +922,15 @@ var init_transport = __esm({
831
922
  }
832
923
  });
833
924
 
834
- // packages/adapters/src/providers/claude-code/adapter.js
925
+ // packages/adapters/src/providers/claude-code/adapter.ts
835
926
  import { exec as exec2 } from "node:child_process";
836
927
  import { existsSync as existsSync3 } from "node:fs";
837
928
  import { homedir as homedir4 } from "node:os";
838
- import { join as join5 } from "node:path";
929
+ import { join as join6 } from "node:path";
839
930
  import { promisify as promisify2 } from "node:util";
840
931
  var execAsync2, ClaudeCodeAdapter;
841
932
  var init_adapter = __esm({
842
- "packages/adapters/src/providers/claude-code/adapter.js"() {
933
+ "packages/adapters/src/providers/claude-code/adapter.ts"() {
843
934
  "use strict";
844
935
  init_context_monitor();
845
936
  init_hooks();
@@ -850,21 +941,36 @@ var init_adapter = __esm({
850
941
  init_transport();
851
942
  execAsync2 = promisify2(exec2);
852
943
  ClaudeCodeAdapter = class {
944
+ /** Unique provider identifier. */
853
945
  id = "claude-code";
946
+ /** Human-readable provider name. */
854
947
  name = "Claude Code";
948
+ /** Adapter version string. */
855
949
  version = "1.0.0";
950
+ /** Declared capabilities for this provider. */
856
951
  capabilities = {
857
952
  supportsHooks: true,
953
+ // 14/16 canonical events — derived from getProviderHookProfile('claude-code') in CAAMP 1.9.1.
954
+ // PreModel and PostModel are not supported by Claude Code.
858
955
  supportedHookEvents: [
859
- "onSessionStart",
860
- "onSessionEnd",
861
- "onToolStart",
862
- "onToolComplete",
863
- "onError"
956
+ "SessionStart",
957
+ "SessionEnd",
958
+ "PromptSubmit",
959
+ "ResponseComplete",
960
+ "PreToolUse",
961
+ "PostToolUse",
962
+ "PostToolUseFailure",
963
+ "PermissionRequest",
964
+ "SubagentStart",
965
+ "SubagentStop",
966
+ "PreCompact",
967
+ "PostCompact",
968
+ "Notification",
969
+ "ConfigChange"
864
970
  ],
865
971
  supportsSpawn: true,
866
972
  supportsInstall: true,
867
- supportsMcp: true,
973
+ supportsMcp: false,
868
974
  supportsInstructionFiles: true,
869
975
  instructionFilePattern: "CLAUDE.md",
870
976
  supportsContextMonitor: true,
@@ -873,14 +979,23 @@ var init_adapter = __esm({
873
979
  supportsTransport: true,
874
980
  supportsTaskSync: true
875
981
  };
982
+ /** Hook provider for CAAMP event mapping and registration. */
876
983
  hooks;
984
+ /** Spawn provider for launching subagent processes via `claude` CLI. */
877
985
  spawn;
986
+ /** Install provider for managing instruction files and plugin registration. */
878
987
  install;
988
+ /** Path provider for resolving Claude Code directory locations. */
879
989
  paths;
990
+ /** Context monitor for tracking context window usage and statusline output. */
880
991
  contextMonitor;
992
+ /** Transport provider for inter-agent communication. */
881
993
  transport;
994
+ /** Task sync provider bridging Claude's TodoWrite format to CLEO tasks. */
882
995
  taskSync;
996
+ /** Project directory this adapter was initialized with, or null. */
883
997
  projectDir = null;
998
+ /** Whether {@link initialize} has been called. */
884
999
  initialized = false;
885
1000
  constructor() {
886
1001
  this.hooks = new ClaudeCodeHookProvider();
@@ -942,7 +1057,7 @@ var init_adapter = __esm({
942
1057
  } catch {
943
1058
  details.cliAvailable = false;
944
1059
  }
945
- const claudeConfigDir = join5(homedir4(), ".claude");
1060
+ const claudeConfigDir = join6(homedir4(), ".claude");
946
1061
  const configExists = existsSync3(claudeConfigDir);
947
1062
  details.configDirExists = configExists;
948
1063
  const entrypointSet = process.env.CLAUDE_CODE_ENTRYPOINT !== void 0;
@@ -971,24 +1086,21 @@ var init_adapter = __esm({
971
1086
  }
972
1087
  });
973
1088
 
974
- // packages/adapters/src/providers/claude-code/statusline.js
1089
+ // packages/adapters/src/providers/claude-code/statusline.ts
975
1090
  import { existsSync as existsSync4, readFileSync as readFileSync3 } from "node:fs";
976
1091
  import { homedir as homedir5 } from "node:os";
977
- import { join as join6 } from "node:path";
1092
+ import { join as join7 } from "node:path";
978
1093
  function getClaudeSettingsPath() {
979
- return process.env["CLAUDE_SETTINGS"] ?? join6(process.env["CLAUDE_HOME"] ?? join6(homedir5(), ".claude"), "settings.json");
1094
+ return process.env["CLAUDE_SETTINGS"] ?? join7(process.env["CLAUDE_HOME"] ?? join7(homedir5(), ".claude"), "settings.json");
980
1095
  }
981
1096
  function checkStatuslineIntegration() {
982
1097
  const settingsPath = getClaudeSettingsPath();
983
- if (!existsSync4(settingsPath))
984
- return "no_settings";
1098
+ if (!existsSync4(settingsPath)) return "no_settings";
985
1099
  try {
986
1100
  const settings = JSON.parse(readFileSync3(settingsPath, "utf-8"));
987
1101
  const statusLine = settings.statusLine;
988
- if (!statusLine?.type)
989
- return "not_configured";
990
- if (statusLine.type !== "command")
991
- return "custom_no_cleo";
1102
+ if (!statusLine?.type) return "not_configured";
1103
+ if (statusLine.type !== "command") return "custom_no_cleo";
992
1104
  const cmd = statusLine.command ?? "";
993
1105
  if (cmd.includes("context-monitor.sh") || cmd.includes("cleo-statusline") || cmd.includes(".context-state.json") || cmd.includes("context-states")) {
994
1106
  return "configured";
@@ -997,8 +1109,7 @@ function checkStatuslineIntegration() {
997
1109
  if (existsSync4(scriptPath)) {
998
1110
  try {
999
1111
  const content = readFileSync3(scriptPath, "utf-8");
1000
- if (content.includes("context-state.json"))
1001
- return "configured";
1112
+ if (content.includes("context-state.json")) return "configured";
1002
1113
  } catch {
1003
1114
  }
1004
1115
  }
@@ -1011,7 +1122,7 @@ function getStatuslineConfig(cleoHome) {
1011
1122
  return {
1012
1123
  statusLine: {
1013
1124
  type: "command",
1014
- command: join6(cleoHome, "lib", "session", "context-monitor.sh")
1125
+ command: join7(cleoHome, "lib", "session", "context-monitor.sh")
1015
1126
  }
1016
1127
  };
1017
1128
  }
@@ -1027,12 +1138,12 @@ function getSetupInstructions(cleoHome) {
1027
1138
  ].join("\n");
1028
1139
  }
1029
1140
  var init_statusline = __esm({
1030
- "packages/adapters/src/providers/claude-code/statusline.js"() {
1141
+ "packages/adapters/src/providers/claude-code/statusline.ts"() {
1031
1142
  "use strict";
1032
1143
  }
1033
1144
  });
1034
1145
 
1035
- // packages/adapters/src/providers/claude-code/index.js
1146
+ // packages/adapters/src/providers/claude-code/index.ts
1036
1147
  var claude_code_exports = {};
1037
1148
  __export(claude_code_exports, {
1038
1149
  ClaudeCodeAdapter: () => ClaudeCodeAdapter,
@@ -1053,7 +1164,7 @@ function createAdapter() {
1053
1164
  }
1054
1165
  var claude_code_default;
1055
1166
  var init_claude_code = __esm({
1056
- "packages/adapters/src/providers/claude-code/index.js"() {
1167
+ "packages/adapters/src/providers/claude-code/index.ts"() {
1057
1168
  "use strict";
1058
1169
  init_adapter();
1059
1170
  init_adapter();
@@ -1068,30 +1179,66 @@ var init_claude_code = __esm({
1068
1179
  }
1069
1180
  });
1070
1181
 
1071
- // packages/adapters/src/providers/cursor/hooks.js
1072
- var CursorHookProvider;
1182
+ // packages/adapters/src/providers/cursor/hooks.ts
1183
+ var PROVIDER_ID2, CURSOR_EVENT_MAP, CursorHookProvider;
1073
1184
  var init_hooks2 = __esm({
1074
- "packages/adapters/src/providers/cursor/hooks.js"() {
1185
+ "packages/adapters/src/providers/cursor/hooks.ts"() {
1075
1186
  "use strict";
1187
+ PROVIDER_ID2 = "cursor";
1188
+ CURSOR_EVENT_MAP = {
1189
+ // CAAMP: toNative('SessionStart', 'cursor') = 'sessionStart'
1190
+ sessionStart: "SessionStart",
1191
+ // CAAMP: toNative('SessionEnd', 'cursor') = 'sessionEnd'
1192
+ sessionEnd: "SessionEnd",
1193
+ // CAAMP: toNative('PromptSubmit', 'cursor') = 'beforeSubmitPrompt'
1194
+ beforeSubmitPrompt: "PromptSubmit",
1195
+ // CAAMP: toNative('ResponseComplete', 'cursor') = 'stop'
1196
+ stop: "ResponseComplete",
1197
+ // CAAMP: toNative('PreToolUse', 'cursor') = 'preToolUse'
1198
+ preToolUse: "PreToolUse",
1199
+ // CAAMP: toNative('PostToolUse', 'cursor') = 'postToolUse'
1200
+ postToolUse: "PostToolUse",
1201
+ // CAAMP: toNative('PostToolUseFailure', 'cursor') = 'postToolUseFailure'
1202
+ postToolUseFailure: "PostToolUseFailure",
1203
+ // CAAMP: toNative('SubagentStart', 'cursor') = 'subagentStart'
1204
+ subagentStart: "SubagentStart",
1205
+ // CAAMP: toNative('SubagentStop', 'cursor') = 'subagentStop'
1206
+ subagentStop: "SubagentStop",
1207
+ // CAAMP: toNative('PreCompact', 'cursor') = 'preCompact'
1208
+ preCompact: "PreCompact"
1209
+ };
1076
1210
  CursorHookProvider = class {
1211
+ /** Whether hooks have been registered for the current session. */
1077
1212
  registered = false;
1078
1213
  /**
1079
- * Map a provider event name to a CAAMP hook event name.
1214
+ * Map a Cursor native event name to a CAAMP canonical hook event name.
1215
+ *
1216
+ * Looks up the native event name in the map derived from
1217
+ * `getProviderHookProfile('cursor').mappings` (CAAMP 1.9.1). Cursor uses
1218
+ * camelCase names (e.g. "preToolUse", "sessionStart").
1080
1219
  *
1081
- * Always returns null since Cursor does not emit hook events.
1220
+ * Returns null for unsupported events (PermissionRequest, PreModel,
1221
+ * PostModel, PostCompact, Notification, ConfigChange).
1082
1222
  *
1083
- * @param _providerEvent - Ignored; Cursor has no hook events
1084
- * @returns null (no mapping available)
1223
+ * @param providerEvent - Cursor native event name (e.g. "preToolUse", "sessionStart")
1224
+ * @returns CAAMP canonical event name, or null if unmapped
1225
+ * @task T165
1085
1226
  */
1086
- mapProviderEvent(_providerEvent) {
1087
- return null;
1227
+ mapProviderEvent(providerEvent) {
1228
+ return CURSOR_EVENT_MAP[providerEvent] ?? null;
1088
1229
  }
1089
1230
  /**
1090
1231
  * Register native hooks for a project.
1091
1232
  *
1092
- * No-op for Cursor since it has no hook system.
1233
+ * For Cursor, hooks are registered via the config system
1234
+ * (`.cursor/hooks.json`), managed by the install provider.
1235
+ * This method marks hooks as registered without performing filesystem operations.
1093
1236
  *
1094
- * @param _projectDir - Ignored
1237
+ * Iterating supported events is handled at install time using
1238
+ * `getSupportedCanonicalEvents()` to enumerate all 10 supported hooks.
1239
+ *
1240
+ * @param _projectDir - Project directory (unused; Cursor config manages registration)
1241
+ * @task T165
1095
1242
  */
1096
1243
  async registerNativeHooks(_projectDir) {
1097
1244
  this.registered = true;
@@ -1099,99 +1246,146 @@ var init_hooks2 = __esm({
1099
1246
  /**
1100
1247
  * Unregister native hooks.
1101
1248
  *
1102
- * No-op for Cursor since it has no hook system.
1249
+ * For Cursor, this is a no-op since hooks are managed through the config
1250
+ * system. Unregistration happens via the install provider's uninstall method.
1251
+ *
1252
+ * @task T165
1103
1253
  */
1104
1254
  async unregisterNativeHooks() {
1105
1255
  this.registered = false;
1106
1256
  }
1107
1257
  /**
1108
- * Check whether hooks have been registered.
1258
+ * Check whether hooks have been registered via `registerNativeHooks`.
1109
1259
  */
1110
1260
  isRegistered() {
1111
1261
  return this.registered;
1112
1262
  }
1263
+ /**
1264
+ * Get the native→canonical event mapping for introspection and debugging.
1265
+ *
1266
+ * Returns the map derived from `getProviderHookProfile('cursor').mappings`
1267
+ * (CAAMP 1.9.1). Use `getSupportedCanonicalEvents()` to enumerate canonical
1268
+ * names via live CAAMP APIs.
1269
+ *
1270
+ * @returns Immutable record of native event name → canonical event name
1271
+ */
1272
+ getEventMap() {
1273
+ return { ...CURSOR_EVENT_MAP };
1274
+ }
1275
+ /**
1276
+ * Enumerate supported canonical events via CAAMP's `getSupportedEvents()`.
1277
+ *
1278
+ * Calls `getSupportedEvents('cursor')` from the CAAMP normalizer to get the
1279
+ * authoritative list. Cursor supports 10 of 16 canonical events. Falls back
1280
+ * to the values of the static event map when CAAMP is unavailable at runtime.
1281
+ *
1282
+ * @returns Array of CAAMP canonical event names supported by Cursor
1283
+ * @task T165
1284
+ */
1285
+ async getSupportedCanonicalEvents() {
1286
+ try {
1287
+ const { getSupportedEvents } = await import("@cleocode/caamp");
1288
+ return getSupportedEvents(PROVIDER_ID2);
1289
+ } catch {
1290
+ return [...new Set(Object.values(CURSOR_EVENT_MAP))];
1291
+ }
1292
+ }
1293
+ /**
1294
+ * Retrieve the full provider hook profile from CAAMP.
1295
+ *
1296
+ * Calls `getProviderHookProfile('cursor')` from the CAAMP normalizer to
1297
+ * get the complete profile: hook system type (`config`), config path
1298
+ * (`.cursor/hooks.json`), handler types (command, prompt), and all event
1299
+ * mappings. Returns null when CAAMP is unavailable at runtime.
1300
+ *
1301
+ * @returns Provider hook profile or null if CAAMP is unavailable
1302
+ * @task T165
1303
+ */
1304
+ async getProviderProfile() {
1305
+ try {
1306
+ const { getProviderHookProfile } = await import("@cleocode/caamp");
1307
+ return getProviderHookProfile(PROVIDER_ID2) ?? null;
1308
+ } catch {
1309
+ return null;
1310
+ }
1311
+ }
1312
+ /**
1313
+ * Translate a CAAMP canonical event to its Cursor native name via CAAMP.
1314
+ *
1315
+ * Calls `toNative(canonical, 'cursor')` from the CAAMP normalizer.
1316
+ * Returns null for unsupported events or when CAAMP is unavailable.
1317
+ *
1318
+ * @param canonical - CAAMP canonical event name (e.g. "PreToolUse")
1319
+ * @returns Cursor native event name (e.g. "preToolUse") or null
1320
+ * @task T165
1321
+ */
1322
+ async toNativeEvent(canonical) {
1323
+ try {
1324
+ const { toNative } = await import("@cleocode/caamp");
1325
+ return toNative(canonical, PROVIDER_ID2);
1326
+ } catch {
1327
+ const entry = Object.entries(CURSOR_EVENT_MAP).find(([, v]) => v === canonical);
1328
+ return entry?.[0] ?? null;
1329
+ }
1330
+ }
1113
1331
  };
1114
1332
  }
1115
1333
  });
1116
1334
 
1117
- // packages/adapters/src/providers/cursor/install.js
1118
- import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "node:fs";
1119
- import { join as join11 } from "node:path";
1120
- var INSTRUCTION_REFERENCES3, MCP_SERVER_KEY3, CursorInstallProvider;
1335
+ // packages/adapters/src/providers/cursor/install.ts
1336
+ import { existsSync as existsSync7, mkdirSync as mkdirSync2, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "node:fs";
1337
+ import { join as join12 } from "node:path";
1338
+ var INSTRUCTION_REFERENCES3, CursorInstallProvider;
1121
1339
  var init_install2 = __esm({
1122
- "packages/adapters/src/providers/cursor/install.js"() {
1340
+ "packages/adapters/src/providers/cursor/install.ts"() {
1123
1341
  "use strict";
1124
1342
  INSTRUCTION_REFERENCES3 = ["@~/.cleo/templates/CLEO-INJECTION.md", "@.cleo/memory-bridge.md"];
1125
- MCP_SERVER_KEY3 = "cleo";
1126
1343
  CursorInstallProvider = class {
1127
- installedProjectDir = null;
1128
1344
  /**
1129
1345
  * Install CLEO into a Cursor project.
1130
1346
  *
1131
- * @param options - Installation options including project directory and MCP server path
1347
+ * @param options - Installation options including project directory
1132
1348
  * @returns Result describing what was installed
1133
1349
  */
1134
1350
  async install(options) {
1135
- const { projectDir, mcpServerPath } = options;
1351
+ const { projectDir } = options;
1136
1352
  const installedAt = (/* @__PURE__ */ new Date()).toISOString();
1137
1353
  let instructionFileUpdated = false;
1138
- let mcpRegistered = false;
1139
1354
  const details = {};
1140
- if (mcpServerPath) {
1141
- mcpRegistered = this.registerMcpServer(projectDir, mcpServerPath);
1142
- if (mcpRegistered) {
1143
- details.mcpConfigPath = join11(projectDir, ".cursor", "mcp.json");
1144
- }
1145
- }
1146
1355
  instructionFileUpdated = this.updateInstructionFiles(projectDir);
1147
1356
  if (instructionFileUpdated) {
1148
1357
  details.instructionFiles = this.getUpdatedFileList(projectDir);
1149
1358
  }
1150
- this.installedProjectDir = projectDir;
1151
1359
  return {
1152
1360
  success: true,
1153
1361
  installedAt,
1154
1362
  instructionFileUpdated,
1155
- mcpRegistered,
1363
+ mcpRegistered: false,
1156
1364
  details
1157
1365
  };
1158
1366
  }
1159
1367
  /**
1160
1368
  * Uninstall CLEO from the current Cursor project.
1161
1369
  *
1162
- * Removes the MCP server registration from .cursor/mcp.json.
1163
1370
  * Does not remove instruction file references (they are harmless if CLEO is not present).
1164
1371
  */
1165
1372
  async uninstall() {
1166
- if (!this.installedProjectDir)
1167
- return;
1168
- const mcpPath = join11(this.installedProjectDir, ".cursor", "mcp.json");
1169
- if (existsSync7(mcpPath)) {
1170
- try {
1171
- const raw = readFileSync5(mcpPath, "utf-8");
1172
- const config = JSON.parse(raw);
1173
- const mcpServers = config.mcpServers;
1174
- if (mcpServers && MCP_SERVER_KEY3 in mcpServers) {
1175
- delete mcpServers[MCP_SERVER_KEY3];
1176
- writeFileSync4(mcpPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
1177
- }
1178
- } catch {
1179
- }
1180
- }
1181
- this.installedProjectDir = null;
1182
1373
  }
1183
1374
  /**
1184
1375
  * Check whether CLEO is installed in the current environment.
1185
1376
  *
1186
- * Checks for MCP server registered in .cursor/mcp.json.
1377
+ * Checks for .cursor/rules/cleo.mdc or .cursorrules with CLEO references.
1187
1378
  */
1188
1379
  async isInstalled() {
1189
- const mcpPath = join11(process.cwd(), ".cursor", "mcp.json");
1190
- if (existsSync7(mcpPath)) {
1380
+ const mdcPath = join12(process.cwd(), ".cursor", "rules", "cleo.mdc");
1381
+ if (existsSync7(mdcPath)) {
1382
+ return true;
1383
+ }
1384
+ const rulesPath = join12(process.cwd(), ".cursorrules");
1385
+ if (existsSync7(rulesPath)) {
1191
1386
  try {
1192
- const config = JSON.parse(readFileSync5(mcpPath, "utf-8"));
1193
- const mcpServers = config.mcpServers;
1194
- if (mcpServers && MCP_SERVER_KEY3 in mcpServers) {
1387
+ const content = readFileSync5(rulesPath, "utf-8");
1388
+ if (INSTRUCTION_REFERENCES3.some((ref) => content.includes(ref))) {
1195
1389
  return true;
1196
1390
  }
1197
1391
  } catch {
@@ -1209,36 +1403,6 @@ var init_install2 = __esm({
1209
1403
  async ensureInstructionReferences(projectDir) {
1210
1404
  this.updateInstructionFiles(projectDir);
1211
1405
  }
1212
- /**
1213
- * Register the CLEO MCP server in .cursor/mcp.json.
1214
- *
1215
- * Cursor stores MCP server configuration in .cursor/mcp.json
1216
- * under the mcpServers key.
1217
- *
1218
- * @returns true if registration was performed or updated
1219
- */
1220
- registerMcpServer(projectDir, mcpServerPath) {
1221
- const cursorDir = join11(projectDir, ".cursor");
1222
- const mcpPath = join11(cursorDir, "mcp.json");
1223
- let config = {};
1224
- mkdirSync3(cursorDir, { recursive: true });
1225
- if (existsSync7(mcpPath)) {
1226
- try {
1227
- config = JSON.parse(readFileSync5(mcpPath, "utf-8"));
1228
- } catch {
1229
- }
1230
- }
1231
- if (!config.mcpServers || typeof config.mcpServers !== "object") {
1232
- config.mcpServers = {};
1233
- }
1234
- const mcpServers = config.mcpServers;
1235
- mcpServers[MCP_SERVER_KEY3] = {
1236
- command: "node",
1237
- args: [mcpServerPath]
1238
- };
1239
- writeFileSync4(mcpPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
1240
- return true;
1241
- }
1242
1406
  /**
1243
1407
  * Update instruction files with CLEO @-references.
1244
1408
  *
@@ -1263,7 +1427,7 @@ var init_install2 = __esm({
1263
1427
  * @returns true if the file was modified
1264
1428
  */
1265
1429
  updateLegacyRules(projectDir) {
1266
- const rulesPath = join11(projectDir, ".cursorrules");
1430
+ const rulesPath = join12(projectDir, ".cursorrules");
1267
1431
  if (!existsSync7(rulesPath)) {
1268
1432
  return false;
1269
1433
  }
@@ -1286,8 +1450,8 @@ var init_install2 = __esm({
1286
1450
  * @returns true if the file was created or modified
1287
1451
  */
1288
1452
  updateModernRules(projectDir) {
1289
- const rulesDir = join11(projectDir, ".cursor", "rules");
1290
- const mdcPath = join11(rulesDir, "cleo.mdc");
1453
+ const rulesDir = join12(projectDir, ".cursor", "rules");
1454
+ const mdcPath = join12(rulesDir, "cleo.mdc");
1291
1455
  const expectedContent = [
1292
1456
  "---",
1293
1457
  "description: CLEO task management protocol references",
@@ -1304,7 +1468,7 @@ var init_install2 = __esm({
1304
1468
  return false;
1305
1469
  }
1306
1470
  }
1307
- mkdirSync3(rulesDir, { recursive: true });
1471
+ mkdirSync2(rulesDir, { recursive: true });
1308
1472
  writeFileSync4(mdcPath, expectedContent, "utf-8");
1309
1473
  return true;
1310
1474
  }
@@ -1313,35 +1477,53 @@ var init_install2 = __esm({
1313
1477
  */
1314
1478
  getUpdatedFileList(projectDir) {
1315
1479
  const files = [];
1316
- if (existsSync7(join11(projectDir, ".cursorrules"))) {
1317
- files.push(join11(projectDir, ".cursorrules"));
1480
+ if (existsSync7(join12(projectDir, ".cursorrules"))) {
1481
+ files.push(join12(projectDir, ".cursorrules"));
1318
1482
  }
1319
- files.push(join11(projectDir, ".cursor", "rules", "cleo.mdc"));
1483
+ files.push(join12(projectDir, ".cursor", "rules", "cleo.mdc"));
1320
1484
  return files;
1321
1485
  }
1322
1486
  };
1323
1487
  }
1324
1488
  });
1325
1489
 
1326
- // packages/adapters/src/providers/cursor/adapter.js
1490
+ // packages/adapters/src/providers/cursor/adapter.ts
1327
1491
  import { existsSync as existsSync8 } from "node:fs";
1328
- import { join as join12 } from "node:path";
1492
+ import { join as join13 } from "node:path";
1329
1493
  var CursorAdapter;
1330
1494
  var init_adapter2 = __esm({
1331
- "packages/adapters/src/providers/cursor/adapter.js"() {
1495
+ "packages/adapters/src/providers/cursor/adapter.ts"() {
1332
1496
  "use strict";
1333
1497
  init_hooks2();
1334
1498
  init_install2();
1335
1499
  CursorAdapter = class {
1500
+ /** Unique provider identifier. */
1336
1501
  id = "cursor";
1502
+ /** Human-readable provider name. */
1337
1503
  name = "Cursor";
1504
+ /** Adapter version string. */
1338
1505
  version = "1.0.0";
1506
+ /** Declared capabilities for this provider. */
1339
1507
  capabilities = {
1340
- supportsHooks: false,
1341
- supportedHookEvents: [],
1508
+ supportsHooks: true,
1509
+ // 10/16 canonical events — derived from getProviderHookProfile('cursor') in CAAMP 1.9.1.
1510
+ // PermissionRequest, PreModel, PostModel, PostCompact, Notification, ConfigChange are
1511
+ // not supported by Cursor's hook system.
1512
+ supportedHookEvents: [
1513
+ "SessionStart",
1514
+ "SessionEnd",
1515
+ "PromptSubmit",
1516
+ "ResponseComplete",
1517
+ "PreToolUse",
1518
+ "PostToolUse",
1519
+ "PostToolUseFailure",
1520
+ "SubagentStart",
1521
+ "SubagentStop",
1522
+ "PreCompact"
1523
+ ],
1342
1524
  supportsSpawn: false,
1343
1525
  supportsInstall: true,
1344
- supportsMcp: true,
1526
+ supportsMcp: false,
1345
1527
  supportsInstructionFiles: true,
1346
1528
  instructionFilePattern: ".cursor/rules/*.mdc",
1347
1529
  supportsContextMonitor: false,
@@ -1350,9 +1532,13 @@ var init_adapter2 = __esm({
1350
1532
  supportsTransport: false,
1351
1533
  supportsTaskSync: false
1352
1534
  };
1535
+ /** Hook provider for CAAMP event mapping. */
1353
1536
  hooks;
1537
+ /** Install provider for managing rule files. */
1354
1538
  install;
1539
+ /** Project directory this adapter was initialized with, or null. */
1355
1540
  projectDir = null;
1541
+ /** Whether {@link initialize} has been called. */
1356
1542
  initialized = false;
1357
1543
  constructor() {
1358
1544
  this.hooks = new CursorHookProvider();
@@ -1398,14 +1584,14 @@ var init_adapter2 = __esm({
1398
1584
  }
1399
1585
  let configExists = false;
1400
1586
  if (this.projectDir) {
1401
- const cursorConfigDir = join12(this.projectDir, ".cursor");
1587
+ const cursorConfigDir = join13(this.projectDir, ".cursor");
1402
1588
  configExists = existsSync8(cursorConfigDir);
1403
1589
  details.configDirExists = configExists;
1404
1590
  }
1405
1591
  const editorEnvSet = process.env.CURSOR_EDITOR !== void 0;
1406
1592
  details.editorEnvSet = editorEnvSet;
1407
1593
  if (this.projectDir) {
1408
- const legacyRulesExist = existsSync8(join12(this.projectDir, ".cursorrules"));
1594
+ const legacyRulesExist = existsSync8(join13(this.projectDir, ".cursorrules"));
1409
1595
  details.legacyRulesExist = legacyRulesExist;
1410
1596
  }
1411
1597
  const healthy = configExists || editorEnvSet;
@@ -1432,7 +1618,7 @@ var init_adapter2 = __esm({
1432
1618
  }
1433
1619
  });
1434
1620
 
1435
- // packages/adapters/src/providers/cursor/index.js
1621
+ // packages/adapters/src/providers/cursor/index.ts
1436
1622
  var cursor_exports = {};
1437
1623
  __export(cursor_exports, {
1438
1624
  CursorAdapter: () => CursorAdapter,
@@ -1446,7 +1632,7 @@ function createAdapter3() {
1446
1632
  }
1447
1633
  var cursor_default;
1448
1634
  var init_cursor = __esm({
1449
- "packages/adapters/src/providers/cursor/index.js"() {
1635
+ "packages/adapters/src/providers/cursor/index.ts"() {
1450
1636
  "use strict";
1451
1637
  init_adapter2();
1452
1638
  init_adapter2();
@@ -1456,26 +1642,48 @@ var init_cursor = __esm({
1456
1642
  }
1457
1643
  });
1458
1644
 
1459
- // packages/adapters/src/providers/opencode/hooks.js
1460
- var OPENCODE_EVENT_MAP, OpenCodeHookProvider;
1645
+ // packages/adapters/src/providers/opencode/hooks.ts
1646
+ var PROVIDER_ID3, OPENCODE_EVENT_MAP, OpenCodeHookProvider;
1461
1647
  var init_hooks3 = __esm({
1462
- "packages/adapters/src/providers/opencode/hooks.js"() {
1648
+ "packages/adapters/src/providers/opencode/hooks.ts"() {
1463
1649
  "use strict";
1650
+ PROVIDER_ID3 = "opencode";
1464
1651
  OPENCODE_EVENT_MAP = {
1465
- "session.start": "onSessionStart",
1466
- "session.end": "onSessionEnd",
1467
- "tool.start": "onToolStart",
1468
- "tool.complete": "onToolComplete",
1469
- error: "onError",
1470
- "prompt.submit": "onPromptSubmit"
1652
+ // CAAMP: toNative('SessionStart', 'opencode') = 'event:session.created'
1653
+ "event:session.created": "SessionStart",
1654
+ // CAAMP: toNative('SessionEnd', 'opencode') = 'event:session.deleted'
1655
+ "event:session.deleted": "SessionEnd",
1656
+ // CAAMP: toNative('PromptSubmit', 'opencode') = 'chat.message'
1657
+ "chat.message": "PromptSubmit",
1658
+ // CAAMP: toNative('ResponseComplete', 'opencode') = 'event:session.idle'
1659
+ "event:session.idle": "ResponseComplete",
1660
+ // CAAMP: toNative('PreToolUse', 'opencode') = 'tool.execute.before'
1661
+ "tool.execute.before": "PreToolUse",
1662
+ // CAAMP: toNative('PostToolUse', 'opencode') = 'tool.execute.after'
1663
+ "tool.execute.after": "PostToolUse",
1664
+ // CAAMP: toNative('PermissionRequest', 'opencode') = 'permission.ask'
1665
+ "permission.ask": "PermissionRequest",
1666
+ // CAAMP: toNative('PreModel', 'opencode') = 'chat.params'
1667
+ "chat.params": "PreModel",
1668
+ // CAAMP: toNative('PreCompact', 'opencode') = 'experimental.session.compacting'
1669
+ "experimental.session.compacting": "PreCompact",
1670
+ // CAAMP: toNative('PostCompact', 'opencode') = 'event:session.compacted'
1671
+ "event:session.compacted": "PostCompact"
1471
1672
  };
1472
1673
  OpenCodeHookProvider = class {
1674
+ /** Whether hooks have been registered for the current session. */
1473
1675
  registered = false;
1474
1676
  /**
1475
- * Map an OpenCode native event name to a CAAMP hook event name.
1677
+ * Map an OpenCode native event name to a CAAMP canonical hook event name.
1678
+ *
1679
+ * Looks up the native event name in the map derived from
1680
+ * `getProviderHookProfile('opencode').mappings` (CAAMP 1.9.1).
1681
+ * Returns null for unsupported events (PostToolUseFailure, SubagentStart,
1682
+ * SubagentStop, Notification, ConfigChange).
1476
1683
  *
1477
- * @param providerEvent - OpenCode event name (e.g. "session.start", "tool.complete")
1478
- * @returns CAAMP event name or null if unmapped
1684
+ * @param providerEvent - OpenCode native event (e.g. "event:session.created", "tool.execute.before")
1685
+ * @returns CAAMP canonical event name, or null if unmapped
1686
+ * @task T164
1479
1687
  */
1480
1688
  mapProviderEvent(providerEvent) {
1481
1689
  return OPENCODE_EVENT_MAP[providerEvent] ?? null;
@@ -1483,12 +1691,15 @@ var init_hooks3 = __esm({
1483
1691
  /**
1484
1692
  * Register native hooks for a project.
1485
1693
  *
1486
- * For OpenCode, hooks are registered via the config system
1487
- * (.opencode/config.json), which is handled by the install provider.
1488
- * This method marks hooks as registered without performing
1489
- * filesystem operations.
1694
+ * For OpenCode, hooks are registered via the plugin system
1695
+ * (`.opencode/plugins/`), managed by the install provider.
1696
+ * This method marks hooks as registered without performing filesystem operations.
1697
+ *
1698
+ * Iterating supported events is handled at install time using
1699
+ * `getSupportedCanonicalEvents()` to enumerate all 10 supported hooks.
1490
1700
  *
1491
1701
  * @param _projectDir - Project directory (unused; config manages registration)
1702
+ * @task T164
1492
1703
  */
1493
1704
  async registerNativeHooks(_projectDir) {
1494
1705
  this.registered = true;
@@ -1496,108 +1707,143 @@ var init_hooks3 = __esm({
1496
1707
  /**
1497
1708
  * Unregister native hooks.
1498
1709
  *
1499
- * For OpenCode, this is a no-op since hooks are managed through
1500
- * the config system. Unregistration happens via the install
1501
- * provider's uninstall method.
1710
+ * For OpenCode, this is a no-op since hooks are managed through the plugin
1711
+ * system. Unregistration happens via the install provider's uninstall method.
1712
+ *
1713
+ * @task T164
1502
1714
  */
1503
1715
  async unregisterNativeHooks() {
1504
1716
  this.registered = false;
1505
1717
  }
1506
1718
  /**
1507
- * Check whether hooks have been registered via registerNativeHooks.
1719
+ * Check whether hooks have been registered via `registerNativeHooks`.
1508
1720
  */
1509
1721
  isRegistered() {
1510
1722
  return this.registered;
1511
1723
  }
1512
1724
  /**
1513
- * Get the full event mapping for introspection/debugging.
1725
+ * Get the native→canonical event mapping for introspection and debugging.
1726
+ *
1727
+ * Returns the map derived from `getProviderHookProfile('opencode').mappings`
1728
+ * (CAAMP 1.9.1). Use `getSupportedCanonicalEvents()` to enumerate canonical
1729
+ * names via live CAAMP APIs.
1730
+ *
1731
+ * @returns Immutable record of native event name → canonical event name
1514
1732
  */
1515
1733
  getEventMap() {
1516
1734
  return { ...OPENCODE_EVENT_MAP };
1517
1735
  }
1736
+ /**
1737
+ * Enumerate supported canonical events via CAAMP's `getSupportedEvents()`.
1738
+ *
1739
+ * Calls `getSupportedEvents('opencode')` from the CAAMP normalizer to get the
1740
+ * authoritative list. OpenCode supports 10 of 16 canonical events via its
1741
+ * plugin system. Falls back to the values of the static event map when
1742
+ * CAAMP is unavailable at runtime.
1743
+ *
1744
+ * @returns Array of CAAMP canonical event names supported by OpenCode
1745
+ * @task T164
1746
+ */
1747
+ async getSupportedCanonicalEvents() {
1748
+ try {
1749
+ const { getSupportedEvents } = await import("@cleocode/caamp");
1750
+ return getSupportedEvents(PROVIDER_ID3);
1751
+ } catch {
1752
+ return [...new Set(Object.values(OPENCODE_EVENT_MAP))];
1753
+ }
1754
+ }
1755
+ /**
1756
+ * Retrieve the full provider hook profile from CAAMP.
1757
+ *
1758
+ * Calls `getProviderHookProfile('opencode')` from the CAAMP normalizer to
1759
+ * get the complete profile: hook system type (`plugin`), config path
1760
+ * (`.opencode/plugins/`), handler types, and all event mappings.
1761
+ * Returns null when CAAMP is unavailable at runtime.
1762
+ *
1763
+ * @returns Provider hook profile or null if CAAMP is unavailable
1764
+ * @task T164
1765
+ */
1766
+ async getProviderProfile() {
1767
+ try {
1768
+ const { getProviderHookProfile } = await import("@cleocode/caamp");
1769
+ return getProviderHookProfile(PROVIDER_ID3) ?? null;
1770
+ } catch {
1771
+ return null;
1772
+ }
1773
+ }
1774
+ /**
1775
+ * Translate a CAAMP canonical event to its OpenCode native name via CAAMP.
1776
+ *
1777
+ * Calls `toNative(canonical, 'opencode')` from the CAAMP normalizer.
1778
+ * Returns null for unsupported events or when CAAMP is unavailable.
1779
+ *
1780
+ * @param canonical - CAAMP canonical event name (e.g. "PreToolUse")
1781
+ * @returns OpenCode native event name or null
1782
+ * @task T164
1783
+ */
1784
+ async toNativeEvent(canonical) {
1785
+ try {
1786
+ const { toNative } = await import("@cleocode/caamp");
1787
+ return toNative(canonical, PROVIDER_ID3);
1788
+ } catch {
1789
+ const entry = Object.entries(OPENCODE_EVENT_MAP).find(([, v]) => v === canonical);
1790
+ return entry?.[0] ?? null;
1791
+ }
1792
+ }
1518
1793
  };
1519
1794
  }
1520
1795
  });
1521
1796
 
1522
- // packages/adapters/src/providers/opencode/install.js
1523
- import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "node:fs";
1524
- import { join as join18 } from "node:path";
1525
- var INSTRUCTION_REFERENCES6, MCP_SERVER_KEY6, OpenCodeInstallProvider;
1797
+ // packages/adapters/src/providers/opencode/install.ts
1798
+ import { existsSync as existsSync13, readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "node:fs";
1799
+ import { join as join19 } from "node:path";
1800
+ var INSTRUCTION_REFERENCES6, OpenCodeInstallProvider;
1526
1801
  var init_install3 = __esm({
1527
- "packages/adapters/src/providers/opencode/install.js"() {
1802
+ "packages/adapters/src/providers/opencode/install.ts"() {
1528
1803
  "use strict";
1529
1804
  INSTRUCTION_REFERENCES6 = ["@~/.cleo/templates/CLEO-INJECTION.md", "@.cleo/memory-bridge.md"];
1530
- MCP_SERVER_KEY6 = "cleo";
1531
1805
  OpenCodeInstallProvider = class {
1532
- installedProjectDir = null;
1533
1806
  /**
1534
1807
  * Install CLEO into an OpenCode project.
1535
1808
  *
1536
- * @param options - Installation options including project directory and MCP server path
1809
+ * @param options - Installation options including project directory
1537
1810
  * @returns Result describing what was installed
1538
1811
  */
1539
1812
  async install(options) {
1540
- const { projectDir, mcpServerPath } = options;
1813
+ const { projectDir } = options;
1541
1814
  const installedAt = (/* @__PURE__ */ new Date()).toISOString();
1542
1815
  let instructionFileUpdated = false;
1543
- let mcpRegistered = false;
1544
1816
  const details = {};
1545
- if (mcpServerPath) {
1546
- mcpRegistered = this.registerMcpServer(projectDir, mcpServerPath);
1547
- if (mcpRegistered) {
1548
- details.mcpConfigPath = join18(projectDir, ".opencode", "config.json");
1549
- }
1550
- }
1551
1817
  instructionFileUpdated = this.updateInstructionFile(projectDir);
1552
1818
  if (instructionFileUpdated) {
1553
- details.instructionFile = join18(projectDir, "AGENTS.md");
1819
+ details.instructionFile = join19(projectDir, "AGENTS.md");
1554
1820
  }
1555
- this.installedProjectDir = projectDir;
1556
1821
  return {
1557
1822
  success: true,
1558
1823
  installedAt,
1559
1824
  instructionFileUpdated,
1560
- mcpRegistered,
1825
+ mcpRegistered: false,
1561
1826
  details
1562
1827
  };
1563
1828
  }
1564
1829
  /**
1565
1830
  * Uninstall CLEO from the current OpenCode project.
1566
1831
  *
1567
- * Removes the MCP server registration from .opencode/config.json.
1568
1832
  * Does not remove AGENTS.md references (they are harmless if CLEO is not present).
1569
1833
  */
1570
1834
  async uninstall() {
1571
- if (!this.installedProjectDir)
1572
- return;
1573
- const configPath = join18(this.installedProjectDir, ".opencode", "config.json");
1574
- if (existsSync13(configPath)) {
1575
- try {
1576
- const raw = readFileSync8(configPath, "utf-8");
1577
- const config = JSON.parse(raw);
1578
- const mcpServers = config.mcpServers;
1579
- if (mcpServers && MCP_SERVER_KEY6 in mcpServers) {
1580
- delete mcpServers[MCP_SERVER_KEY6];
1581
- writeFileSync7(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
1582
- }
1583
- } catch {
1584
- }
1585
- }
1586
- this.installedProjectDir = null;
1587
1835
  }
1588
1836
  /**
1589
1837
  * Check whether CLEO is installed in the current environment.
1590
1838
  *
1591
- * Checks for MCP server registered in .opencode/config.json.
1592
- * Returns true if the CLEO MCP server entry is found.
1839
+ * Checks for CLEO references in AGENTS.md.
1593
1840
  */
1594
1841
  async isInstalled() {
1595
- const configPath = join18(process.cwd(), ".opencode", "config.json");
1596
- if (existsSync13(configPath)) {
1842
+ const agentsMdPath = join19(process.cwd(), "AGENTS.md");
1843
+ if (existsSync13(agentsMdPath)) {
1597
1844
  try {
1598
- const config = JSON.parse(readFileSync8(configPath, "utf-8"));
1599
- const mcpServers = config.mcpServers;
1600
- if (mcpServers && MCP_SERVER_KEY6 in mcpServers) {
1845
+ const content = readFileSync8(agentsMdPath, "utf-8");
1846
+ if (INSTRUCTION_REFERENCES6.some((ref) => content.includes(ref))) {
1601
1847
  return true;
1602
1848
  }
1603
1849
  } catch {
@@ -1615,43 +1861,13 @@ var init_install3 = __esm({
1615
1861
  async ensureInstructionReferences(projectDir) {
1616
1862
  this.updateInstructionFile(projectDir);
1617
1863
  }
1618
- /**
1619
- * Register the CLEO MCP server in .opencode/config.json.
1620
- *
1621
- * OpenCode stores its MCP server configuration in .opencode/config.json
1622
- * under the mcpServers key.
1623
- *
1624
- * @returns true if registration was performed or updated
1625
- */
1626
- registerMcpServer(projectDir, mcpServerPath) {
1627
- const openCodeDir = join18(projectDir, ".opencode");
1628
- const configPath = join18(openCodeDir, "config.json");
1629
- let config = {};
1630
- mkdirSync6(openCodeDir, { recursive: true });
1631
- if (existsSync13(configPath)) {
1632
- try {
1633
- config = JSON.parse(readFileSync8(configPath, "utf-8"));
1634
- } catch {
1635
- }
1636
- }
1637
- if (!config.mcpServers || typeof config.mcpServers !== "object") {
1638
- config.mcpServers = {};
1639
- }
1640
- const mcpServers = config.mcpServers;
1641
- mcpServers[MCP_SERVER_KEY6] = {
1642
- command: "node",
1643
- args: [mcpServerPath]
1644
- };
1645
- writeFileSync7(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
1646
- return true;
1647
- }
1648
1864
  /**
1649
1865
  * Update AGENTS.md with CLEO @-references.
1650
1866
  *
1651
1867
  * @returns true if the file was created or modified
1652
1868
  */
1653
1869
  updateInstructionFile(projectDir) {
1654
- const agentsMdPath = join18(projectDir, "AGENTS.md");
1870
+ const agentsMdPath = join19(projectDir, "AGENTS.md");
1655
1871
  let content = "";
1656
1872
  let existed = false;
1657
1873
  if (existsSync13(agentsMdPath)) {
@@ -1676,10 +1892,10 @@ var init_install3 = __esm({
1676
1892
  }
1677
1893
  });
1678
1894
 
1679
- // packages/adapters/src/providers/opencode/spawn.js
1895
+ // packages/adapters/src/providers/opencode/spawn.ts
1680
1896
  import { exec as exec6, spawn as nodeSpawn2 } from "node:child_process";
1681
- import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
1682
- import { join as join19 } from "node:path";
1897
+ import { mkdir as mkdir2, readFile as readFile4, writeFile as writeFile2 } from "node:fs/promises";
1898
+ import { join as join20 } from "node:path";
1683
1899
  import { promisify as promisify6 } from "node:util";
1684
1900
  function buildOpenCodeAgentMarkdown(description, instructions) {
1685
1901
  const normalizedDesc = description.replace(/\s+/g, " ").trim();
@@ -1695,8 +1911,8 @@ function buildOpenCodeAgentMarkdown(description, instructions) {
1695
1911
  ].join("\n");
1696
1912
  }
1697
1913
  async function ensureSubagentDefinition(workingDirectory) {
1698
- const agentDir = join19(workingDirectory, ".opencode", "agent");
1699
- const agentPath = join19(agentDir, `${OPENCODE_SUBAGENT_NAME}.md`);
1914
+ const agentDir = join20(workingDirectory, ".opencode", "agent");
1915
+ const agentPath = join20(agentDir, `${OPENCODE_SUBAGENT_NAME}.md`);
1700
1916
  const description = "CLEO task executor with protocol compliance.";
1701
1917
  const instructions = [
1702
1918
  "# CLEO Subagent",
@@ -1710,7 +1926,7 @@ async function ensureSubagentDefinition(workingDirectory) {
1710
1926
  await mkdir2(agentDir, { recursive: true });
1711
1927
  let existing = null;
1712
1928
  try {
1713
- existing = await readFile3(agentPath, "utf-8");
1929
+ existing = await readFile4(agentPath, "utf-8");
1714
1930
  } catch {
1715
1931
  existing = null;
1716
1932
  }
@@ -1721,7 +1937,7 @@ async function ensureSubagentDefinition(workingDirectory) {
1721
1937
  }
1722
1938
  var execAsync6, OPENCODE_SUBAGENT_NAME, OPENCODE_FALLBACK_AGENT, OpenCodeSpawnProvider;
1723
1939
  var init_spawn2 = __esm({
1724
- "packages/adapters/src/providers/opencode/spawn.js"() {
1940
+ "packages/adapters/src/providers/opencode/spawn.ts"() {
1725
1941
  "use strict";
1726
1942
  execAsync6 = promisify6(exec6);
1727
1943
  OPENCODE_SUBAGENT_NAME = "cleo-subagent";
@@ -1763,20 +1979,24 @@ var init_spawn2 = __esm({
1763
1979
  } catch {
1764
1980
  agentName = OPENCODE_FALLBACK_AGENT;
1765
1981
  }
1766
- const child = nodeSpawn2("opencode", [
1767
- "run",
1768
- "--format",
1769
- "json",
1770
- "--agent",
1771
- agentName,
1772
- "--title",
1773
- `CLEO ${context.taskId}`,
1774
- context.prompt
1775
- ], {
1776
- cwd: workingDirectory,
1777
- detached: true,
1778
- stdio: "ignore"
1779
- });
1982
+ const child = nodeSpawn2(
1983
+ "opencode",
1984
+ [
1985
+ "run",
1986
+ "--format",
1987
+ "json",
1988
+ "--agent",
1989
+ agentName,
1990
+ "--title",
1991
+ `CLEO ${context.taskId}`,
1992
+ context.prompt
1993
+ ],
1994
+ {
1995
+ cwd: workingDirectory,
1996
+ detached: true,
1997
+ stdio: "ignore"
1998
+ }
1999
+ );
1780
2000
  child.unref();
1781
2001
  if (child.pid) {
1782
2002
  this.processMap.set(instanceId, {
@@ -1842,8 +2062,7 @@ var init_spawn2 = __esm({
1842
2062
  */
1843
2063
  async terminate(instanceId) {
1844
2064
  const tracked = this.processMap.get(instanceId);
1845
- if (!tracked)
1846
- return;
2065
+ if (!tracked) return;
1847
2066
  try {
1848
2067
  process.kill(tracked.pid, "SIGTERM");
1849
2068
  } catch {
@@ -1854,36 +2073,47 @@ var init_spawn2 = __esm({
1854
2073
  }
1855
2074
  });
1856
2075
 
1857
- // packages/adapters/src/providers/opencode/adapter.js
2076
+ // packages/adapters/src/providers/opencode/adapter.ts
1858
2077
  import { exec as exec7 } from "node:child_process";
1859
2078
  import { existsSync as existsSync14 } from "node:fs";
1860
- import { join as join20 } from "node:path";
2079
+ import { join as join21 } from "node:path";
1861
2080
  import { promisify as promisify7 } from "node:util";
1862
2081
  var execAsync7, OpenCodeAdapter;
1863
2082
  var init_adapter3 = __esm({
1864
- "packages/adapters/src/providers/opencode/adapter.js"() {
2083
+ "packages/adapters/src/providers/opencode/adapter.ts"() {
1865
2084
  "use strict";
1866
2085
  init_hooks3();
1867
2086
  init_install3();
1868
2087
  init_spawn2();
1869
2088
  execAsync7 = promisify7(exec7);
1870
2089
  OpenCodeAdapter = class {
2090
+ /** Unique provider identifier. */
1871
2091
  id = "opencode";
2092
+ /** Human-readable provider name. */
1872
2093
  name = "OpenCode";
2094
+ /** Adapter version string. */
1873
2095
  version = "1.0.0";
2096
+ /** Declared capabilities for this provider. */
1874
2097
  capabilities = {
1875
2098
  supportsHooks: true,
2099
+ // 10/16 canonical events — derived from getProviderHookProfile('opencode') in CAAMP 1.9.1.
2100
+ // PostToolUseFailure, SubagentStart, SubagentStop, Notification, ConfigChange are
2101
+ // not supported by OpenCode's plugin system.
1876
2102
  supportedHookEvents: [
1877
- "onSessionStart",
1878
- "onSessionEnd",
1879
- "onToolStart",
1880
- "onToolComplete",
1881
- "onError",
1882
- "onPromptSubmit"
2103
+ "SessionStart",
2104
+ "SessionEnd",
2105
+ "PromptSubmit",
2106
+ "ResponseComplete",
2107
+ "PreToolUse",
2108
+ "PostToolUse",
2109
+ "PermissionRequest",
2110
+ "PreModel",
2111
+ "PreCompact",
2112
+ "PostCompact"
1883
2113
  ],
1884
2114
  supportsSpawn: true,
1885
2115
  supportsInstall: true,
1886
- supportsMcp: true,
2116
+ supportsMcp: false,
1887
2117
  supportsInstructionFiles: true,
1888
2118
  instructionFilePattern: "AGENTS.md",
1889
2119
  supportsContextMonitor: false,
@@ -1892,10 +2122,15 @@ var init_adapter3 = __esm({
1892
2122
  supportsTransport: false,
1893
2123
  supportsTaskSync: false
1894
2124
  };
2125
+ /** Hook provider for CAAMP event mapping via OpenCode's plugin system. */
1895
2126
  hooks;
2127
+ /** Spawn provider for launching subagent processes via `opencode run`. */
1896
2128
  spawn;
2129
+ /** Install provider for managing AGENTS.md instruction files. */
1897
2130
  install;
2131
+ /** Project directory this adapter was initialized with, or null. */
1898
2132
  projectDir = null;
2133
+ /** Whether {@link initialize} has been called. */
1899
2134
  initialized = false;
1900
2135
  constructor() {
1901
2136
  this.hooks = new OpenCodeHookProvider();
@@ -1954,7 +2189,7 @@ var init_adapter3 = __esm({
1954
2189
  details.cliAvailable = false;
1955
2190
  }
1956
2191
  if (this.projectDir) {
1957
- const openCodeConfigDir = join20(this.projectDir, ".opencode");
2192
+ const openCodeConfigDir = join21(this.projectDir, ".opencode");
1958
2193
  const configExists = existsSync14(openCodeConfigDir);
1959
2194
  details.configDirExists = configExists;
1960
2195
  }
@@ -1984,7 +2219,7 @@ var init_adapter3 = __esm({
1984
2219
  }
1985
2220
  });
1986
2221
 
1987
- // packages/adapters/src/providers/opencode/index.js
2222
+ // packages/adapters/src/providers/opencode/index.ts
1988
2223
  var opencode_exports = {};
1989
2224
  __export(opencode_exports, {
1990
2225
  OpenCodeAdapter: () => OpenCodeAdapter,
@@ -1999,7 +2234,7 @@ function createAdapter6() {
1999
2234
  }
2000
2235
  var opencode_default;
2001
2236
  var init_opencode = __esm({
2002
- "packages/adapters/src/providers/opencode/index.js"() {
2237
+ "packages/adapters/src/providers/opencode/index.ts"() {
2003
2238
  "use strict";
2004
2239
  init_adapter3();
2005
2240
  init_adapter3();
@@ -2016,17 +2251,17 @@ init_claude_code();
2016
2251
  // packages/adapters/src/providers/codex/adapter.ts
2017
2252
  import { exec as exec3 } from "node:child_process";
2018
2253
  import { existsSync as existsSync6 } from "node:fs";
2019
- import { homedir as homedir8 } from "node:os";
2020
- import { join as join10 } from "node:path";
2254
+ import { homedir as homedir7 } from "node:os";
2255
+ import { join as join11 } from "node:path";
2021
2256
  import { promisify as promisify3 } from "node:util";
2022
2257
 
2023
2258
  // packages/adapters/src/providers/codex/hooks.ts
2024
2259
  import { homedir as homedir6 } from "node:os";
2025
- import { join as join8 } from "node:path";
2260
+ import { join as join9 } from "node:path";
2026
2261
 
2027
2262
  // packages/adapters/src/providers/shared/transcript-reader.ts
2028
- import { readdir, readFile as readFile2 } from "node:fs/promises";
2029
- import { join as join7 } from "node:path";
2263
+ import { readdir as readdir2, readFile as readFile3 } from "node:fs/promises";
2264
+ import { join as join8 } from "node:path";
2030
2265
  function parseTranscriptLines(raw) {
2031
2266
  const turns = [];
2032
2267
  const lines = raw.split("\n").filter((l) => l.trim());
@@ -2046,12 +2281,12 @@ function parseTranscriptLines(raw) {
2046
2281
  async function readLatestTranscript(providerDir) {
2047
2282
  let allFiles = [];
2048
2283
  try {
2049
- const entries = await readdir(providerDir, { withFileTypes: true });
2284
+ const entries = await readdir2(providerDir, { withFileTypes: true });
2050
2285
  for (const entry of entries) {
2051
2286
  if (!entry.isFile()) continue;
2052
2287
  const name = entry.name;
2053
2288
  if (name.endsWith(".json") || name.endsWith(".jsonl")) {
2054
- allFiles.push(join7(providerDir, name));
2289
+ allFiles.push(join8(providerDir, name));
2055
2290
  }
2056
2291
  }
2057
2292
  } catch {
@@ -2062,7 +2297,7 @@ async function readLatestTranscript(providerDir) {
2062
2297
  const mostRecent = allFiles[0];
2063
2298
  if (!mostRecent) return null;
2064
2299
  try {
2065
- const raw = await readFile2(mostRecent, "utf-8");
2300
+ const raw = await readFile3(mostRecent, "utf-8");
2066
2301
  const turns = parseTranscriptLines(raw);
2067
2302
  return turns.length > 0 ? turns.map((t) => `${t.role}: ${t.content}`).join("\n") : null;
2068
2303
  } catch {
@@ -2077,6 +2312,7 @@ var CODEX_EVENT_MAP = {
2077
2312
  ResponseComplete: "Stop"
2078
2313
  };
2079
2314
  var CodexHookProvider = class {
2315
+ /** Whether hooks have been registered for the current session. */
2080
2316
  registered = false;
2081
2317
  /**
2082
2318
  * Map a Codex CLI native event name to a CAAMP hook event name.
@@ -2140,84 +2376,59 @@ var CodexHookProvider = class {
2140
2376
  * @task T162 @epic T134
2141
2377
  */
2142
2378
  async getTranscript(_sessionId, _projectDir) {
2143
- return readLatestTranscript(join8(homedir6(), ".codex"));
2379
+ return readLatestTranscript(join9(homedir6(), ".codex"));
2144
2380
  }
2145
2381
  };
2146
2382
 
2147
2383
  // packages/adapters/src/providers/codex/install.ts
2148
- import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
2149
- import { homedir as homedir7 } from "node:os";
2150
- import { join as join9 } from "node:path";
2384
+ import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
2385
+ import { join as join10 } from "node:path";
2151
2386
  var INSTRUCTION_REFERENCES2 = ["@~/.cleo/templates/CLEO-INJECTION.md", "@.cleo/memory-bridge.md"];
2152
- var MCP_SERVER_KEY2 = "cleo";
2153
2387
  var CodexInstallProvider = class {
2154
2388
  /**
2155
2389
  * Install CLEO into a Codex CLI environment.
2156
2390
  *
2157
- * @param options - Installation options including project directory and MCP server path
2391
+ * @param options - Installation options including project directory
2158
2392
  * @returns Result describing what was installed
2159
2393
  * @task T162
2160
2394
  */
2161
2395
  async install(options) {
2162
- const { projectDir, mcpServerPath } = options;
2396
+ const { projectDir } = options;
2163
2397
  const installedAt = (/* @__PURE__ */ new Date()).toISOString();
2164
2398
  let instructionFileUpdated = false;
2165
- let mcpRegistered = false;
2166
2399
  const details = {};
2167
- if (mcpServerPath) {
2168
- mcpRegistered = this.registerMcpServer(mcpServerPath);
2169
- if (mcpRegistered) {
2170
- details.mcpConfigPath = join9(homedir7(), ".codex", "config.json");
2171
- }
2172
- }
2173
2400
  instructionFileUpdated = this.updateInstructionFile(projectDir);
2174
2401
  if (instructionFileUpdated) {
2175
- details.instructionFile = join9(projectDir, "AGENTS.md");
2402
+ details.instructionFile = join10(projectDir, "AGENTS.md");
2176
2403
  }
2177
2404
  return {
2178
2405
  success: true,
2179
2406
  installedAt,
2180
2407
  instructionFileUpdated,
2181
- mcpRegistered,
2408
+ mcpRegistered: false,
2182
2409
  details
2183
2410
  };
2184
2411
  }
2185
2412
  /**
2186
2413
  * Uninstall CLEO from the Codex CLI environment.
2187
2414
  *
2188
- * Removes the MCP server registration from ~/.codex/config.json.
2189
2415
  * Does not remove AGENTS.md references (they are harmless if CLEO is not present).
2190
2416
  * @task T162
2191
2417
  */
2192
2418
  async uninstall() {
2193
- const configPath = join9(homedir7(), ".codex", "config.json");
2194
- if (existsSync5(configPath)) {
2195
- try {
2196
- const raw = readFileSync4(configPath, "utf-8");
2197
- const config = JSON.parse(raw);
2198
- const mcpServers = config.mcpServers;
2199
- if (mcpServers && MCP_SERVER_KEY2 in mcpServers) {
2200
- delete mcpServers[MCP_SERVER_KEY2];
2201
- writeFileSync3(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
2202
- }
2203
- } catch {
2204
- }
2205
- }
2206
2419
  }
2207
2420
  /**
2208
2421
  * Check whether CLEO is installed in the Codex CLI environment.
2209
2422
  *
2210
- * Checks for MCP server registered in ~/.codex/config.json.
2211
- * Returns true if the CLEO MCP server entry is found.
2423
+ * Checks for CLEO references in AGENTS.md.
2212
2424
  * @task T162
2213
2425
  */
2214
2426
  async isInstalled() {
2215
- const configPath = join9(homedir7(), ".codex", "config.json");
2216
- if (existsSync5(configPath)) {
2427
+ const agentsMdPath = join10(process.cwd(), "AGENTS.md");
2428
+ if (existsSync5(agentsMdPath)) {
2217
2429
  try {
2218
- const config = JSON.parse(readFileSync4(configPath, "utf-8"));
2219
- const mcpServers = config.mcpServers;
2220
- if (mcpServers && MCP_SERVER_KEY2 in mcpServers) {
2430
+ const content = readFileSync4(agentsMdPath, "utf-8");
2431
+ if (INSTRUCTION_REFERENCES2.some((ref) => content.includes(ref))) {
2221
2432
  return true;
2222
2433
  }
2223
2434
  } catch {
@@ -2236,37 +2447,6 @@ var CodexInstallProvider = class {
2236
2447
  async ensureInstructionReferences(projectDir) {
2237
2448
  this.updateInstructionFile(projectDir);
2238
2449
  }
2239
- /**
2240
- * Register the CLEO MCP server in ~/.codex/config.json.
2241
- *
2242
- * Codex CLI stores its MCP server configuration in ~/.codex/config.json
2243
- * under the mcpServers key.
2244
- *
2245
- * @param mcpServerPath - Absolute path to the MCP server entry point
2246
- * @returns true if registration was performed or updated
2247
- */
2248
- registerMcpServer(mcpServerPath) {
2249
- const codexDir = join9(homedir7(), ".codex");
2250
- const configPath = join9(codexDir, "config.json");
2251
- let config = {};
2252
- mkdirSync2(codexDir, { recursive: true });
2253
- if (existsSync5(configPath)) {
2254
- try {
2255
- config = JSON.parse(readFileSync4(configPath, "utf-8"));
2256
- } catch {
2257
- }
2258
- }
2259
- if (!config.mcpServers || typeof config.mcpServers !== "object") {
2260
- config.mcpServers = {};
2261
- }
2262
- const mcpServers = config.mcpServers;
2263
- mcpServers[MCP_SERVER_KEY2] = {
2264
- command: "node",
2265
- args: [mcpServerPath]
2266
- };
2267
- writeFileSync3(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
2268
- return true;
2269
- }
2270
2450
  /**
2271
2451
  * Update AGENTS.md with CLEO @-references.
2272
2452
  *
@@ -2274,7 +2454,7 @@ var CodexInstallProvider = class {
2274
2454
  * @returns true if the file was created or modified
2275
2455
  */
2276
2456
  updateInstructionFile(projectDir) {
2277
- const agentsMdPath = join9(projectDir, "AGENTS.md");
2457
+ const agentsMdPath = join10(projectDir, "AGENTS.md");
2278
2458
  let content = "";
2279
2459
  let existed = false;
2280
2460
  if (existsSync5(agentsMdPath)) {
@@ -2300,15 +2480,19 @@ var CodexInstallProvider = class {
2300
2480
  // packages/adapters/src/providers/codex/adapter.ts
2301
2481
  var execAsync3 = promisify3(exec3);
2302
2482
  var CodexAdapter = class {
2483
+ /** Unique provider identifier. */
2303
2484
  id = "codex";
2485
+ /** Human-readable provider name. */
2304
2486
  name = "Codex";
2487
+ /** Adapter version string. */
2305
2488
  version = "1.0.0";
2489
+ /** Declared capabilities for this provider. */
2306
2490
  capabilities = {
2307
2491
  supportsHooks: true,
2308
2492
  supportedHookEvents: ["SessionStart", "UserPromptSubmit", "Stop"],
2309
2493
  supportsSpawn: false,
2310
2494
  supportsInstall: true,
2311
- supportsMcp: true,
2495
+ supportsMcp: false,
2312
2496
  supportsInstructionFiles: false,
2313
2497
  supportsContextMonitor: false,
2314
2498
  supportsStatusline: false,
@@ -2316,9 +2500,13 @@ var CodexAdapter = class {
2316
2500
  supportsTransport: false,
2317
2501
  supportsTaskSync: false
2318
2502
  };
2503
+ /** Hook provider for CAAMP event mapping. */
2319
2504
  hooks;
2505
+ /** Install provider for managing instruction files. */
2320
2506
  install;
2507
+ /** Project directory this adapter was initialized with, or null. */
2321
2508
  projectDir = null;
2509
+ /** Whether {@link initialize} has been called. */
2322
2510
  initialized = false;
2323
2511
  constructor() {
2324
2512
  this.hooks = new CodexHookProvider();
@@ -2375,7 +2563,7 @@ var CodexAdapter = class {
2375
2563
  } catch {
2376
2564
  details.cliAvailable = false;
2377
2565
  }
2378
- const codexConfigDir = join10(homedir8(), ".codex");
2566
+ const codexConfigDir = join11(homedir7(), ".codex");
2379
2567
  const configExists = existsSync6(codexConfigDir);
2380
2568
  details.configDirExists = configExists;
2381
2569
  const healthy = cliAvailable;
@@ -2413,13 +2601,13 @@ init_cursor();
2413
2601
  // packages/adapters/src/providers/gemini-cli/adapter.ts
2414
2602
  import { exec as exec4 } from "node:child_process";
2415
2603
  import { existsSync as existsSync10 } from "node:fs";
2416
- import { homedir as homedir11 } from "node:os";
2417
- import { join as join15 } from "node:path";
2604
+ import { homedir as homedir9 } from "node:os";
2605
+ import { join as join16 } from "node:path";
2418
2606
  import { promisify as promisify4 } from "node:util";
2419
2607
 
2420
2608
  // packages/adapters/src/providers/gemini-cli/hooks.ts
2421
- import { homedir as homedir9 } from "node:os";
2422
- import { join as join13 } from "node:path";
2609
+ import { homedir as homedir8 } from "node:os";
2610
+ import { join as join14 } from "node:path";
2423
2611
  var GEMINI_CLI_EVENT_MAP = {
2424
2612
  SessionStart: "SessionStart",
2425
2613
  SessionEnd: "SessionEnd",
@@ -2433,6 +2621,7 @@ var GEMINI_CLI_EVENT_MAP = {
2433
2621
  Notification: "Notification"
2434
2622
  };
2435
2623
  var GeminiCliHookProvider = class {
2624
+ /** Whether hooks have been registered for the current session. */
2436
2625
  registered = false;
2437
2626
  /**
2438
2627
  * Map a Gemini CLI native event name to a CAAMP hook event name.
@@ -2496,84 +2685,59 @@ var GeminiCliHookProvider = class {
2496
2685
  * @task T161 @epic T134
2497
2686
  */
2498
2687
  async getTranscript(_sessionId, _projectDir) {
2499
- return readLatestTranscript(join13(homedir9(), ".gemini"));
2688
+ return readLatestTranscript(join14(homedir8(), ".gemini"));
2500
2689
  }
2501
2690
  };
2502
2691
 
2503
2692
  // packages/adapters/src/providers/gemini-cli/install.ts
2504
- import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "node:fs";
2505
- import { homedir as homedir10 } from "node:os";
2506
- import { join as join14 } from "node:path";
2693
+ import { existsSync as existsSync9, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "node:fs";
2694
+ import { join as join15 } from "node:path";
2507
2695
  var INSTRUCTION_REFERENCES4 = ["@~/.cleo/templates/CLEO-INJECTION.md", "@.cleo/memory-bridge.md"];
2508
- var MCP_SERVER_KEY4 = "cleo";
2509
2696
  var GeminiCliInstallProvider = class {
2510
2697
  /**
2511
2698
  * Install CLEO into a Gemini CLI environment.
2512
2699
  *
2513
- * @param options - Installation options including project directory and MCP server path
2700
+ * @param options - Installation options including project directory
2514
2701
  * @returns Result describing what was installed
2515
2702
  * @task T161
2516
2703
  */
2517
2704
  async install(options) {
2518
- const { projectDir, mcpServerPath } = options;
2705
+ const { projectDir } = options;
2519
2706
  const installedAt = (/* @__PURE__ */ new Date()).toISOString();
2520
2707
  let instructionFileUpdated = false;
2521
- let mcpRegistered = false;
2522
2708
  const details = {};
2523
- if (mcpServerPath) {
2524
- mcpRegistered = this.registerMcpServer(mcpServerPath);
2525
- if (mcpRegistered) {
2526
- details.mcpConfigPath = join14(homedir10(), ".gemini", "settings.json");
2527
- }
2528
- }
2529
2709
  instructionFileUpdated = this.updateInstructionFile(projectDir);
2530
2710
  if (instructionFileUpdated) {
2531
- details.instructionFile = join14(projectDir, "AGENTS.md");
2711
+ details.instructionFile = join15(projectDir, "AGENTS.md");
2532
2712
  }
2533
2713
  return {
2534
2714
  success: true,
2535
2715
  installedAt,
2536
2716
  instructionFileUpdated,
2537
- mcpRegistered,
2717
+ mcpRegistered: false,
2538
2718
  details
2539
2719
  };
2540
2720
  }
2541
2721
  /**
2542
2722
  * Uninstall CLEO from the Gemini CLI environment.
2543
2723
  *
2544
- * Removes the MCP server registration from ~/.gemini/settings.json.
2545
2724
  * Does not remove AGENTS.md references (they are harmless if CLEO is not present).
2546
2725
  * @task T161
2547
2726
  */
2548
2727
  async uninstall() {
2549
- const settingsPath = join14(homedir10(), ".gemini", "settings.json");
2550
- if (existsSync9(settingsPath)) {
2551
- try {
2552
- const raw = readFileSync6(settingsPath, "utf-8");
2553
- const config = JSON.parse(raw);
2554
- const mcpServers = config.mcpServers;
2555
- if (mcpServers && MCP_SERVER_KEY4 in mcpServers) {
2556
- delete mcpServers[MCP_SERVER_KEY4];
2557
- writeFileSync5(settingsPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
2558
- }
2559
- } catch {
2560
- }
2561
- }
2562
2728
  }
2563
2729
  /**
2564
2730
  * Check whether CLEO is installed in the Gemini CLI environment.
2565
2731
  *
2566
- * Checks for MCP server registered in ~/.gemini/settings.json.
2567
- * Returns true if the CLEO MCP server entry is found.
2732
+ * Checks for CLEO references in AGENTS.md.
2568
2733
  * @task T161
2569
2734
  */
2570
2735
  async isInstalled() {
2571
- const settingsPath = join14(homedir10(), ".gemini", "settings.json");
2572
- if (existsSync9(settingsPath)) {
2736
+ const agentsMdPath = join15(process.cwd(), "AGENTS.md");
2737
+ if (existsSync9(agentsMdPath)) {
2573
2738
  try {
2574
- const config = JSON.parse(readFileSync6(settingsPath, "utf-8"));
2575
- const mcpServers = config.mcpServers;
2576
- if (mcpServers && MCP_SERVER_KEY4 in mcpServers) {
2739
+ const content = readFileSync6(agentsMdPath, "utf-8");
2740
+ if (INSTRUCTION_REFERENCES4.some((ref) => content.includes(ref))) {
2577
2741
  return true;
2578
2742
  }
2579
2743
  } catch {
@@ -2592,37 +2756,6 @@ var GeminiCliInstallProvider = class {
2592
2756
  async ensureInstructionReferences(projectDir) {
2593
2757
  this.updateInstructionFile(projectDir);
2594
2758
  }
2595
- /**
2596
- * Register the CLEO MCP server in ~/.gemini/settings.json.
2597
- *
2598
- * Gemini CLI stores its MCP server configuration in ~/.gemini/settings.json
2599
- * under the mcpServers key.
2600
- *
2601
- * @param mcpServerPath - Absolute path to the MCP server entry point
2602
- * @returns true if registration was performed or updated
2603
- */
2604
- registerMcpServer(mcpServerPath) {
2605
- const geminiDir = join14(homedir10(), ".gemini");
2606
- const settingsPath = join14(geminiDir, "settings.json");
2607
- let config = {};
2608
- mkdirSync4(geminiDir, { recursive: true });
2609
- if (existsSync9(settingsPath)) {
2610
- try {
2611
- config = JSON.parse(readFileSync6(settingsPath, "utf-8"));
2612
- } catch {
2613
- }
2614
- }
2615
- if (!config.mcpServers || typeof config.mcpServers !== "object") {
2616
- config.mcpServers = {};
2617
- }
2618
- const mcpServers = config.mcpServers;
2619
- mcpServers[MCP_SERVER_KEY4] = {
2620
- command: "node",
2621
- args: [mcpServerPath]
2622
- };
2623
- writeFileSync5(settingsPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
2624
- return true;
2625
- }
2626
2759
  /**
2627
2760
  * Update AGENTS.md with CLEO @-references.
2628
2761
  *
@@ -2630,7 +2763,7 @@ var GeminiCliInstallProvider = class {
2630
2763
  * @returns true if the file was created or modified
2631
2764
  */
2632
2765
  updateInstructionFile(projectDir) {
2633
- const agentsMdPath = join14(projectDir, "AGENTS.md");
2766
+ const agentsMdPath = join15(projectDir, "AGENTS.md");
2634
2767
  let content = "";
2635
2768
  let existed = false;
2636
2769
  if (existsSync9(agentsMdPath)) {
@@ -2656,9 +2789,13 @@ var GeminiCliInstallProvider = class {
2656
2789
  // packages/adapters/src/providers/gemini-cli/adapter.ts
2657
2790
  var execAsync4 = promisify4(exec4);
2658
2791
  var GeminiCliAdapter = class {
2792
+ /** Unique provider identifier. */
2659
2793
  id = "gemini-cli";
2794
+ /** Human-readable provider name. */
2660
2795
  name = "Gemini CLI";
2796
+ /** Adapter version string. */
2661
2797
  version = "1.0.0";
2798
+ /** Declared capabilities for this provider. */
2662
2799
  capabilities = {
2663
2800
  supportsHooks: true,
2664
2801
  supportedHookEvents: [
@@ -2675,7 +2812,7 @@ var GeminiCliAdapter = class {
2675
2812
  ],
2676
2813
  supportsSpawn: false,
2677
2814
  supportsInstall: true,
2678
- supportsMcp: true,
2815
+ supportsMcp: false,
2679
2816
  supportsInstructionFiles: false,
2680
2817
  supportsContextMonitor: false,
2681
2818
  supportsStatusline: false,
@@ -2683,9 +2820,13 @@ var GeminiCliAdapter = class {
2683
2820
  supportsTransport: false,
2684
2821
  supportsTaskSync: false
2685
2822
  };
2823
+ /** Hook provider for CAAMP event mapping. */
2686
2824
  hooks;
2825
+ /** Install provider for managing instruction files. */
2687
2826
  install;
2827
+ /** Project directory this adapter was initialized with, or null. */
2688
2828
  projectDir = null;
2829
+ /** Whether {@link initialize} has been called. */
2689
2830
  initialized = false;
2690
2831
  constructor() {
2691
2832
  this.hooks = new GeminiCliHookProvider();
@@ -2742,7 +2883,7 @@ var GeminiCliAdapter = class {
2742
2883
  } catch {
2743
2884
  details.cliAvailable = false;
2744
2885
  }
2745
- const geminiConfigDir = join15(homedir11(), ".gemini");
2886
+ const geminiConfigDir = join16(homedir9(), ".gemini");
2746
2887
  const configExists = existsSync10(geminiConfigDir);
2747
2888
  details.configDirExists = configExists;
2748
2889
  const healthy = cliAvailable;
@@ -2777,12 +2918,13 @@ function createAdapter4() {
2777
2918
  // packages/adapters/src/providers/kimi/adapter.ts
2778
2919
  import { exec as exec5 } from "node:child_process";
2779
2920
  import { existsSync as existsSync12 } from "node:fs";
2780
- import { homedir as homedir13 } from "node:os";
2781
- import { join as join17 } from "node:path";
2921
+ import { homedir as homedir10 } from "node:os";
2922
+ import { join as join18 } from "node:path";
2782
2923
  import { promisify as promisify5 } from "node:util";
2783
2924
 
2784
2925
  // packages/adapters/src/providers/kimi/hooks.ts
2785
2926
  var KimiHookProvider = class {
2927
+ /** Whether hooks have been registered (always a no-op for Kimi). */
2786
2928
  registered = false;
2787
2929
  /**
2788
2930
  * Map a Kimi native event name to a CAAMP hook event name.
@@ -2836,79 +2978,54 @@ var KimiHookProvider = class {
2836
2978
  };
2837
2979
 
2838
2980
  // packages/adapters/src/providers/kimi/install.ts
2839
- import { existsSync as existsSync11, mkdirSync as mkdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "node:fs";
2840
- import { homedir as homedir12 } from "node:os";
2841
- import { join as join16 } from "node:path";
2981
+ import { existsSync as existsSync11, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "node:fs";
2982
+ import { join as join17 } from "node:path";
2842
2983
  var INSTRUCTION_REFERENCES5 = ["@~/.cleo/templates/CLEO-INJECTION.md", "@.cleo/memory-bridge.md"];
2843
- var MCP_SERVER_KEY5 = "cleo";
2844
2984
  var KimiInstallProvider = class {
2845
2985
  /**
2846
2986
  * Install CLEO into a Kimi environment.
2847
2987
  *
2848
- * @param options - Installation options including project directory and MCP server path
2988
+ * @param options - Installation options including project directory
2849
2989
  * @returns Result describing what was installed
2850
2990
  * @task T163
2851
2991
  */
2852
2992
  async install(options) {
2853
- const { projectDir, mcpServerPath } = options;
2993
+ const { projectDir } = options;
2854
2994
  const installedAt = (/* @__PURE__ */ new Date()).toISOString();
2855
2995
  let instructionFileUpdated = false;
2856
- let mcpRegistered = false;
2857
2996
  const details = {};
2858
- if (mcpServerPath) {
2859
- mcpRegistered = this.registerMcpServer(mcpServerPath);
2860
- if (mcpRegistered) {
2861
- details.mcpConfigPath = join16(homedir12(), ".kimi", "mcp.json");
2862
- }
2863
- }
2864
2997
  instructionFileUpdated = this.updateInstructionFile(projectDir);
2865
2998
  if (instructionFileUpdated) {
2866
- details.instructionFile = join16(projectDir, "AGENTS.md");
2999
+ details.instructionFile = join17(projectDir, "AGENTS.md");
2867
3000
  }
2868
3001
  return {
2869
3002
  success: true,
2870
3003
  installedAt,
2871
3004
  instructionFileUpdated,
2872
- mcpRegistered,
3005
+ mcpRegistered: false,
2873
3006
  details
2874
3007
  };
2875
3008
  }
2876
3009
  /**
2877
3010
  * Uninstall CLEO from the Kimi environment.
2878
3011
  *
2879
- * Removes the MCP server registration from ~/.kimi/mcp.json.
2880
3012
  * Does not remove AGENTS.md references (they are harmless if CLEO is not present).
2881
3013
  * @task T163
2882
3014
  */
2883
3015
  async uninstall() {
2884
- const mcpPath = join16(homedir12(), ".kimi", "mcp.json");
2885
- if (existsSync11(mcpPath)) {
2886
- try {
2887
- const raw = readFileSync7(mcpPath, "utf-8");
2888
- const config = JSON.parse(raw);
2889
- const mcpServers = config.mcpServers;
2890
- if (mcpServers && MCP_SERVER_KEY5 in mcpServers) {
2891
- delete mcpServers[MCP_SERVER_KEY5];
2892
- writeFileSync6(mcpPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
2893
- }
2894
- } catch {
2895
- }
2896
- }
2897
3016
  }
2898
3017
  /**
2899
3018
  * Check whether CLEO is installed in the Kimi environment.
2900
3019
  *
2901
- * Checks for MCP server registered in ~/.kimi/mcp.json.
2902
- * Returns true if the CLEO MCP server entry is found.
3020
+ * Checks for CLEO references in AGENTS.md.
2903
3021
  * @task T163
2904
3022
  */
2905
3023
  async isInstalled() {
2906
- const mcpPath = join16(homedir12(), ".kimi", "mcp.json");
2907
- if (existsSync11(mcpPath)) {
3024
+ const agentsMdPath = join17(process.cwd(), "AGENTS.md");
3025
+ if (existsSync11(agentsMdPath)) {
2908
3026
  try {
2909
- const config = JSON.parse(readFileSync7(mcpPath, "utf-8"));
2910
- const mcpServers = config.mcpServers;
2911
- if (mcpServers && MCP_SERVER_KEY5 in mcpServers) {
3027
+ const content = readFileSync7(agentsMdPath, "utf-8");
3028
+ if (INSTRUCTION_REFERENCES5.some((ref) => content.includes(ref))) {
2912
3029
  return true;
2913
3030
  }
2914
3031
  } catch {
@@ -2927,37 +3044,6 @@ var KimiInstallProvider = class {
2927
3044
  async ensureInstructionReferences(projectDir) {
2928
3045
  this.updateInstructionFile(projectDir);
2929
3046
  }
2930
- /**
2931
- * Register the CLEO MCP server in ~/.kimi/mcp.json.
2932
- *
2933
- * Kimi stores its MCP server configuration in ~/.kimi/mcp.json
2934
- * under the mcpServers key.
2935
- *
2936
- * @param mcpServerPath - Absolute path to the MCP server entry point
2937
- * @returns true if registration was performed or updated
2938
- */
2939
- registerMcpServer(mcpServerPath) {
2940
- const kimiDir = join16(homedir12(), ".kimi");
2941
- const mcpPath = join16(kimiDir, "mcp.json");
2942
- let config = {};
2943
- mkdirSync5(kimiDir, { recursive: true });
2944
- if (existsSync11(mcpPath)) {
2945
- try {
2946
- config = JSON.parse(readFileSync7(mcpPath, "utf-8"));
2947
- } catch {
2948
- }
2949
- }
2950
- if (!config.mcpServers || typeof config.mcpServers !== "object") {
2951
- config.mcpServers = {};
2952
- }
2953
- const mcpServers = config.mcpServers;
2954
- mcpServers[MCP_SERVER_KEY5] = {
2955
- command: "node",
2956
- args: [mcpServerPath]
2957
- };
2958
- writeFileSync6(mcpPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
2959
- return true;
2960
- }
2961
3047
  /**
2962
3048
  * Update AGENTS.md with CLEO @-references.
2963
3049
  *
@@ -2965,7 +3051,7 @@ var KimiInstallProvider = class {
2965
3051
  * @returns true if the file was created or modified
2966
3052
  */
2967
3053
  updateInstructionFile(projectDir) {
2968
- const agentsMdPath = join16(projectDir, "AGENTS.md");
3054
+ const agentsMdPath = join17(projectDir, "AGENTS.md");
2969
3055
  let content = "";
2970
3056
  let existed = false;
2971
3057
  if (existsSync11(agentsMdPath)) {
@@ -2991,15 +3077,19 @@ var KimiInstallProvider = class {
2991
3077
  // packages/adapters/src/providers/kimi/adapter.ts
2992
3078
  var execAsync5 = promisify5(exec5);
2993
3079
  var KimiAdapter = class {
3080
+ /** Unique provider identifier. */
2994
3081
  id = "kimi";
3082
+ /** Human-readable provider name. */
2995
3083
  name = "Kimi";
3084
+ /** Adapter version string. */
2996
3085
  version = "1.0.0";
3086
+ /** Declared capabilities for this provider. */
2997
3087
  capabilities = {
2998
3088
  supportsHooks: false,
2999
3089
  supportedHookEvents: [],
3000
3090
  supportsSpawn: false,
3001
3091
  supportsInstall: true,
3002
- supportsMcp: true,
3092
+ supportsMcp: false,
3003
3093
  supportsInstructionFiles: false,
3004
3094
  supportsContextMonitor: false,
3005
3095
  supportsStatusline: false,
@@ -3007,9 +3097,13 @@ var KimiAdapter = class {
3007
3097
  supportsTransport: false,
3008
3098
  supportsTaskSync: false
3009
3099
  };
3100
+ /** Hook provider (no-op since Kimi has no event system). */
3010
3101
  hooks;
3102
+ /** Install provider for managing instruction files. */
3011
3103
  install;
3104
+ /** Project directory this adapter was initialized with, or null. */
3012
3105
  projectDir = null;
3106
+ /** Whether {@link initialize} has been called. */
3013
3107
  initialized = false;
3014
3108
  constructor() {
3015
3109
  this.hooks = new KimiHookProvider();
@@ -3064,7 +3158,7 @@ var KimiAdapter = class {
3064
3158
  } catch {
3065
3159
  details.cliAvailable = false;
3066
3160
  }
3067
- const kimiConfigDir = join17(homedir13(), ".kimi");
3161
+ const kimiConfigDir = join18(homedir10(), ".kimi");
3068
3162
  const configExists = existsSync12(kimiConfigDir);
3069
3163
  details.configDirExists = configExists;
3070
3164
  const healthy = cliAvailable;
@@ -3099,9 +3193,9 @@ function createAdapter5() {
3099
3193
  // packages/adapters/src/index.ts
3100
3194
  init_opencode();
3101
3195
 
3102
- // packages/adapters/src/registry.js
3196
+ // packages/adapters/src/registry.ts
3103
3197
  import { readFileSync as readFileSync9 } from "node:fs";
3104
- import { dirname as dirname2, join as join21, resolve } from "node:path";
3198
+ import { dirname as dirname2, join as join22, resolve } from "node:path";
3105
3199
  import { fileURLToPath } from "node:url";
3106
3200
  var PROVIDER_IDS = ["claude-code", "opencode", "cursor"];
3107
3201
  function getProviderManifests() {
@@ -3109,7 +3203,7 @@ function getProviderManifests() {
3109
3203
  const baseDir = resolve(dirname2(fileURLToPath(import.meta.url)), "providers");
3110
3204
  for (const providerId of PROVIDER_IDS) {
3111
3205
  try {
3112
- const manifestPath = join21(baseDir, providerId, "manifest.json");
3206
+ const manifestPath = join22(baseDir, providerId, "manifest.json");
3113
3207
  const raw = readFileSync9(manifestPath, "utf-8");
3114
3208
  manifests.push(JSON.parse(raw));
3115
3209
  } catch {