@cleocode/adapters 2026.3.37 → 2026.3.40

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 (234) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +503 -0
  3. package/dist/index.js +621 -496
  4. package/dist/index.js.map +4 -4
  5. package/package.json +12 -7
  6. package/src/__tests__/claude-code-adapter.test.d.ts +10 -0
  7. package/src/__tests__/claude-code-adapter.test.d.ts.map +1 -0
  8. package/src/__tests__/claude-code-adapter.test.js +192 -0
  9. package/src/__tests__/claude-code-adapter.test.js.map +1 -0
  10. package/src/__tests__/claude-code-adapter.test.ts +235 -0
  11. package/src/__tests__/cursor-adapter.test.d.ts +10 -0
  12. package/src/__tests__/cursor-adapter.test.d.ts.map +1 -0
  13. package/src/__tests__/cursor-adapter.test.js +196 -0
  14. package/src/__tests__/cursor-adapter.test.js.map +1 -0
  15. package/src/__tests__/cursor-adapter.test.ts +246 -0
  16. package/src/__tests__/opencode-adapter.test.d.ts +10 -0
  17. package/src/__tests__/opencode-adapter.test.d.ts.map +1 -0
  18. package/src/__tests__/opencode-adapter.test.js +204 -0
  19. package/src/__tests__/opencode-adapter.test.js.map +1 -0
  20. package/src/__tests__/opencode-adapter.test.ts +250 -0
  21. package/src/index.d.ts +28 -20
  22. package/src/index.d.ts.map +1 -1
  23. package/src/index.js +4 -19
  24. package/src/index.js.map +1 -1
  25. package/src/index.ts +25 -25
  26. package/src/providers/claude-code/__tests__/adapter.test.d.ts +1 -1
  27. package/src/providers/claude-code/__tests__/adapter.test.d.ts.map +0 -0
  28. package/src/providers/claude-code/__tests__/adapter.test.js +2 -2
  29. package/src/providers/claude-code/__tests__/adapter.test.js.map +1 -1
  30. package/src/providers/claude-code/__tests__/adapter.test.ts +2 -2
  31. package/src/providers/claude-code/adapter.d.ts +54 -50
  32. package/src/providers/claude-code/adapter.d.ts.map +0 -0
  33. package/src/providers/claude-code/adapter.js +1 -1
  34. package/src/providers/claude-code/adapter.js.map +1 -1
  35. package/src/providers/claude-code/adapter.ts +1 -1
  36. package/src/providers/claude-code/context-monitor.d.ts +6 -6
  37. package/src/providers/claude-code/context-monitor.d.ts.map +0 -0
  38. package/src/providers/claude-code/context-monitor.js +0 -0
  39. package/src/providers/claude-code/context-monitor.js.map +0 -0
  40. package/src/providers/claude-code/context-monitor.ts +0 -0
  41. package/src/providers/claude-code/hooks.d.ts +36 -36
  42. package/src/providers/claude-code/hooks.d.ts.map +0 -0
  43. package/src/providers/claude-code/hooks.js +0 -0
  44. package/src/providers/claude-code/hooks.js.map +0 -0
  45. package/src/providers/claude-code/hooks.ts +0 -0
  46. package/src/providers/claude-code/index.d.ts +6 -2
  47. package/src/providers/claude-code/index.d.ts.map +1 -1
  48. package/src/providers/claude-code/index.js +1 -1
  49. package/src/providers/claude-code/index.js.map +1 -1
  50. package/src/providers/claude-code/index.ts +2 -2
  51. package/src/providers/claude-code/install.d.ts +52 -52
  52. package/src/providers/claude-code/install.d.ts.map +1 -1
  53. package/src/providers/claude-code/install.js +1 -4
  54. package/src/providers/claude-code/install.js.map +1 -1
  55. package/src/providers/claude-code/install.ts +1 -4
  56. package/src/providers/claude-code/manifest.json +0 -0
  57. package/src/providers/claude-code/paths.d.ts +5 -5
  58. package/src/providers/claude-code/paths.d.ts.map +0 -0
  59. package/src/providers/claude-code/paths.js +0 -0
  60. package/src/providers/claude-code/paths.js.map +0 -0
  61. package/src/providers/claude-code/paths.ts +0 -0
  62. package/src/providers/claude-code/spawn.d.ts +37 -37
  63. package/src/providers/claude-code/spawn.d.ts.map +1 -1
  64. package/src/providers/claude-code/spawn.js +4 -0
  65. package/src/providers/claude-code/spawn.js.map +1 -1
  66. package/src/providers/claude-code/spawn.ts +5 -0
  67. package/src/providers/claude-code/statusline.d.ts +1 -2
  68. package/src/providers/claude-code/statusline.d.ts.map +0 -0
  69. package/src/providers/claude-code/statusline.js +2 -1
  70. package/src/providers/claude-code/statusline.js.map +1 -1
  71. package/src/providers/claude-code/statusline.ts +3 -3
  72. package/src/providers/claude-code/task-sync.js +1 -3
  73. package/src/providers/claude-code/task-sync.js.map +1 -1
  74. package/src/providers/claude-code/task-sync.ts +5 -22
  75. package/src/providers/claude-code/transport.d.ts +3 -3
  76. package/src/providers/claude-code/transport.d.ts.map +0 -0
  77. package/src/providers/claude-code/transport.js +0 -0
  78. package/src/providers/claude-code/transport.js.map +0 -0
  79. package/src/providers/claude-code/transport.ts +0 -0
  80. package/src/providers/cursor/__tests__/adapter.test.d.ts +1 -1
  81. package/src/providers/cursor/__tests__/adapter.test.d.ts.map +0 -0
  82. package/src/providers/cursor/__tests__/adapter.test.js +2 -2
  83. package/src/providers/cursor/__tests__/adapter.test.js.map +1 -1
  84. package/src/providers/cursor/__tests__/adapter.test.ts +2 -2
  85. package/src/providers/cursor/adapter.d.ts +44 -40
  86. package/src/providers/cursor/adapter.d.ts.map +0 -0
  87. package/src/providers/cursor/adapter.js +0 -0
  88. package/src/providers/cursor/adapter.js.map +0 -0
  89. package/src/providers/cursor/adapter.ts +0 -0
  90. package/src/providers/cursor/hooks.d.ts +29 -29
  91. package/src/providers/cursor/hooks.d.ts.map +0 -0
  92. package/src/providers/cursor/hooks.js +0 -0
  93. package/src/providers/cursor/hooks.js.map +0 -0
  94. package/src/providers/cursor/hooks.ts +0 -0
  95. package/src/providers/cursor/index.d.ts +1 -1
  96. package/src/providers/cursor/index.d.ts.map +0 -0
  97. package/src/providers/cursor/index.js +0 -0
  98. package/src/providers/cursor/index.js.map +0 -0
  99. package/src/providers/cursor/index.ts +0 -0
  100. package/src/providers/cursor/install.d.ts +67 -67
  101. package/src/providers/cursor/install.d.ts.map +1 -1
  102. package/src/providers/cursor/install.js +1 -4
  103. package/src/providers/cursor/install.js.map +1 -1
  104. package/src/providers/cursor/install.ts +1 -4
  105. package/src/providers/cursor/manifest.json +0 -0
  106. package/src/providers/cursor/spawn.d.ts +31 -31
  107. package/src/providers/cursor/spawn.d.ts.map +0 -0
  108. package/src/providers/cursor/spawn.js +0 -0
  109. package/src/providers/cursor/spawn.js.map +1 -1
  110. package/src/providers/cursor/spawn.ts +2 -2
  111. package/src/providers/opencode/__tests__/adapter.test.d.ts +1 -1
  112. package/src/providers/opencode/__tests__/adapter.test.d.ts.map +0 -0
  113. package/src/providers/opencode/__tests__/adapter.test.js +2 -2
  114. package/src/providers/opencode/__tests__/adapter.test.js.map +1 -1
  115. package/src/providers/opencode/__tests__/adapter.test.ts +2 -2
  116. package/src/providers/opencode/adapter.d.ts +50 -46
  117. package/src/providers/opencode/adapter.d.ts.map +0 -0
  118. package/src/providers/opencode/adapter.js +0 -0
  119. package/src/providers/opencode/adapter.js.map +0 -0
  120. package/src/providers/opencode/adapter.ts +0 -0
  121. package/src/providers/opencode/hooks.d.ts +36 -36
  122. package/src/providers/opencode/hooks.d.ts.map +0 -0
  123. package/src/providers/opencode/hooks.js +1 -1
  124. package/src/providers/opencode/hooks.js.map +1 -1
  125. package/src/providers/opencode/hooks.ts +1 -1
  126. package/src/providers/opencode/index.d.ts +2 -2
  127. package/src/providers/opencode/index.d.ts.map +1 -1
  128. package/src/providers/opencode/index.js +1 -1
  129. package/src/providers/opencode/index.js.map +1 -1
  130. package/src/providers/opencode/index.ts +1 -1
  131. package/src/providers/opencode/install.d.ts +46 -46
  132. package/src/providers/opencode/install.d.ts.map +1 -1
  133. package/src/providers/opencode/install.js +1 -4
  134. package/src/providers/opencode/install.js.map +1 -1
  135. package/src/providers/opencode/install.ts +1 -4
  136. package/src/providers/opencode/manifest.json +0 -0
  137. package/src/providers/opencode/spawn.d.ts +42 -39
  138. package/src/providers/opencode/spawn.d.ts.map +1 -1
  139. package/src/providers/opencode/spawn.js +0 -0
  140. package/src/providers/opencode/spawn.js.map +1 -1
  141. package/src/providers/opencode/spawn.ts +2 -7
  142. package/src/registry.d.ts +12 -12
  143. package/src/registry.d.ts.map +1 -1
  144. package/src/registry.js +0 -0
  145. package/src/registry.js.map +1 -1
  146. package/src/registry.ts +1 -3
  147. package/dist/index.d.ts +0 -27
  148. package/dist/index.d.ts.map +0 -1
  149. package/dist/providers/claude-code/adapter.d.ts +0 -75
  150. package/dist/providers/claude-code/adapter.d.ts.map +0 -1
  151. package/dist/providers/claude-code/adapter.js +0 -154
  152. package/dist/providers/claude-code/adapter.js.map +0 -1
  153. package/dist/providers/claude-code/context-monitor.d.ts +0 -24
  154. package/dist/providers/claude-code/context-monitor.d.ts.map +0 -1
  155. package/dist/providers/claude-code/context-monitor.js +0 -148
  156. package/dist/providers/claude-code/context-monitor.js.map +0 -1
  157. package/dist/providers/claude-code/hooks.d.ts +0 -59
  158. package/dist/providers/claude-code/hooks.d.ts.map +0 -1
  159. package/dist/providers/claude-code/hooks.js +0 -77
  160. package/dist/providers/claude-code/hooks.js.map +0 -1
  161. package/dist/providers/claude-code/index.d.ts +0 -24
  162. package/dist/providers/claude-code/index.d.ts.map +0 -1
  163. package/dist/providers/claude-code/index.js +0 -26
  164. package/dist/providers/claude-code/index.js.map +0 -1
  165. package/dist/providers/claude-code/install.d.ts +0 -75
  166. package/dist/providers/claude-code/install.d.ts.map +0 -1
  167. package/dist/providers/claude-code/install.js +0 -237
  168. package/dist/providers/claude-code/install.js.map +0 -1
  169. package/dist/providers/claude-code/paths.d.ts +0 -24
  170. package/dist/providers/claude-code/paths.d.ts.map +0 -1
  171. package/dist/providers/claude-code/paths.js +0 -33
  172. package/dist/providers/claude-code/paths.js.map +0 -1
  173. package/dist/providers/claude-code/spawn.d.ts +0 -60
  174. package/dist/providers/claude-code/spawn.d.ts.map +0 -1
  175. package/dist/providers/claude-code/spawn.js +0 -160
  176. package/dist/providers/claude-code/spawn.js.map +0 -1
  177. package/dist/providers/claude-code/statusline.d.ts +0 -24
  178. package/dist/providers/claude-code/statusline.d.ts.map +0 -1
  179. package/dist/providers/claude-code/statusline.js +0 -85
  180. package/dist/providers/claude-code/statusline.js.map +0 -1
  181. package/dist/providers/claude-code/task-sync.d.ts +0 -27
  182. package/dist/providers/claude-code/task-sync.d.ts.map +0 -1
  183. package/dist/providers/claude-code/task-sync.js +0 -124
  184. package/dist/providers/claude-code/task-sync.js.map +0 -1
  185. package/dist/providers/claude-code/transport.d.ts +0 -14
  186. package/dist/providers/claude-code/transport.d.ts.map +0 -1
  187. package/dist/providers/claude-code/transport.js +0 -18
  188. package/dist/providers/claude-code/transport.js.map +0 -1
  189. package/dist/providers/cursor/adapter.d.ts +0 -62
  190. package/dist/providers/cursor/adapter.d.ts.map +0 -1
  191. package/dist/providers/cursor/adapter.js +0 -124
  192. package/dist/providers/cursor/adapter.js.map +0 -1
  193. package/dist/providers/cursor/hooks.d.ts +0 -48
  194. package/dist/providers/cursor/hooks.d.ts.map +0 -1
  195. package/dist/providers/cursor/hooks.js +0 -55
  196. package/dist/providers/cursor/hooks.js.map +0 -1
  197. package/dist/providers/cursor/index.d.ts +0 -19
  198. package/dist/providers/cursor/index.d.ts.map +0 -1
  199. package/dist/providers/cursor/index.js +0 -21
  200. package/dist/providers/cursor/index.js.map +0 -1
  201. package/dist/providers/cursor/install.d.ts +0 -94
  202. package/dist/providers/cursor/install.d.ts.map +0 -1
  203. package/dist/providers/cursor/install.js +0 -241
  204. package/dist/providers/cursor/install.js.map +0 -1
  205. package/dist/providers/cursor/spawn.d.ts +0 -50
  206. package/dist/providers/cursor/spawn.d.ts.map +0 -1
  207. package/dist/providers/cursor/spawn.js +0 -59
  208. package/dist/providers/cursor/spawn.js.map +0 -1
  209. package/dist/providers/opencode/adapter.d.ts +0 -67
  210. package/dist/providers/opencode/adapter.d.ts.map +0 -1
  211. package/dist/providers/opencode/adapter.js +0 -144
  212. package/dist/providers/opencode/adapter.js.map +0 -1
  213. package/dist/providers/opencode/hooks.d.ts +0 -66
  214. package/dist/providers/opencode/hooks.d.ts.map +0 -1
  215. package/dist/providers/opencode/hooks.js +0 -89
  216. package/dist/providers/opencode/hooks.js.map +0 -1
  217. package/dist/providers/opencode/index.d.ts +0 -20
  218. package/dist/providers/opencode/index.d.ts.map +0 -1
  219. package/dist/providers/opencode/index.js +0 -22
  220. package/dist/providers/opencode/index.js.map +0 -1
  221. package/dist/providers/opencode/install.d.ts +0 -65
  222. package/dist/providers/opencode/install.d.ts.map +0 -1
  223. package/dist/providers/opencode/install.js +0 -183
  224. package/dist/providers/opencode/install.js.map +0 -1
  225. package/dist/providers/opencode/spawn.d.ts +0 -72
  226. package/dist/providers/opencode/spawn.d.ts.map +0 -1
  227. package/dist/providers/opencode/spawn.js +0 -219
  228. package/dist/providers/opencode/spawn.js.map +0 -1
  229. package/dist/registry.d.ts +0 -36
  230. package/dist/registry.d.ts.map +0 -1
  231. package/dist/registry.js +0 -55
  232. package/dist/registry.js.map +0 -1
  233. package/src/providers/claude-code/task-sync.d.ts +0 -27
  234. package/src/providers/claude-code/task-sync.d.ts.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleocode/adapters",
3
- "version": "2026.3.37",
3
+ "version": "2026.3.40",
4
4
  "description": "Unified provider adapters for CLEO (Claude Code, OpenCode, Cursor)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -11,12 +11,8 @@
11
11
  "import": "./dist/index.js"
12
12
  }
13
13
  },
14
- "scripts": {
15
- "build": "tsc",
16
- "build:check": "tsc --noEmit"
17
- },
18
14
  "dependencies": {
19
- "@cleocode/contracts": "workspace:*"
15
+ "@cleocode/contracts": "2026.3.40"
20
16
  },
21
17
  "license": "MIT",
22
18
  "engines": {
@@ -28,5 +24,14 @@
28
24
  ],
29
25
  "devDependencies": {
30
26
  "@types/node": "^22.19.15"
27
+ },
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/kryptobaseddev/cleo",
31
+ "directory": "packages/adapters"
32
+ },
33
+ "scripts": {
34
+ "build": "tsc",
35
+ "build:check": "tsc --noEmit"
31
36
  }
32
- }
37
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Unit tests for @cleocode/adapter-claude-code
3
+ *
4
+ * Tests the ClaudeCodeAdapter, ClaudeCodeHookProvider,
5
+ * ClaudeCodeSpawnProvider, and ClaudeCodeInstallProvider.
6
+ *
7
+ * @task T5240
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=claude-code-adapter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code-adapter.test.d.ts","sourceRoot":"","sources":["claude-code-adapter.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Unit tests for @cleocode/adapter-claude-code
3
+ *
4
+ * Tests the ClaudeCodeAdapter, ClaudeCodeHookProvider,
5
+ * ClaudeCodeSpawnProvider, and ClaudeCodeInstallProvider.
6
+ *
7
+ * @task T5240
8
+ */
9
+ import { mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
10
+ import { tmpdir } from 'node:os';
11
+ import { join } from 'node:path';
12
+ import { ClaudeCodeAdapter, ClaudeCodeHookProvider, ClaudeCodeInstallProvider, ClaudeCodeSpawnProvider, createClaudeCodeAdapter as createAdapter, } from '@cleocode/adapters';
13
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
14
+ describe('ClaudeCodeAdapter', () => {
15
+ let adapter;
16
+ beforeEach(() => {
17
+ adapter = new ClaudeCodeAdapter();
18
+ });
19
+ it('has correct identity fields', () => {
20
+ expect(adapter.id).toBe('claude-code');
21
+ expect(adapter.name).toBe('Claude Code');
22
+ expect(adapter.version).toBe('1.0.0');
23
+ });
24
+ it('has correct capabilities', () => {
25
+ expect(adapter.capabilities.supportsHooks).toBe(true);
26
+ expect(adapter.capabilities.supportsSpawn).toBe(true);
27
+ expect(adapter.capabilities.supportsInstall).toBe(true);
28
+ expect(adapter.capabilities.supportsMcp).toBe(true);
29
+ expect(adapter.capabilities.supportsInstructionFiles).toBe(true);
30
+ expect(adapter.capabilities.instructionFilePattern).toBe('CLAUDE.md');
31
+ expect(adapter.capabilities.supportedHookEvents).toContain('onSessionStart');
32
+ expect(adapter.capabilities.supportedHookEvents).toContain('onSessionEnd');
33
+ expect(adapter.capabilities.supportedHookEvents).toContain('onToolComplete');
34
+ });
35
+ it('exposes hooks, spawn, and install providers', () => {
36
+ expect(adapter.hooks).toBeInstanceOf(ClaudeCodeHookProvider);
37
+ expect(adapter.spawn).toBeInstanceOf(ClaudeCodeSpawnProvider);
38
+ expect(adapter.install).toBeInstanceOf(ClaudeCodeInstallProvider);
39
+ });
40
+ it('tracks initialization state', async () => {
41
+ expect(adapter.isInitialized()).toBe(false);
42
+ await adapter.initialize('/tmp/test-project');
43
+ expect(adapter.isInitialized()).toBe(true);
44
+ expect(adapter.getProjectDir()).toBe('/tmp/test-project');
45
+ });
46
+ it('clears state on dispose', async () => {
47
+ await adapter.initialize('/tmp/test-project');
48
+ await adapter.dispose();
49
+ expect(adapter.isInitialized()).toBe(false);
50
+ expect(adapter.getProjectDir()).toBeNull();
51
+ });
52
+ it('reports unhealthy when not initialized', async () => {
53
+ const health = await adapter.healthCheck();
54
+ expect(health.healthy).toBe(false);
55
+ expect(health.provider).toBe('claude-code');
56
+ expect(health.details?.error).toBe('Adapter not initialized');
57
+ });
58
+ it('reports health after initialization', async () => {
59
+ await adapter.initialize('/tmp/test-project');
60
+ const health = await adapter.healthCheck();
61
+ expect(health.provider).toBe('claude-code');
62
+ // healthy depends on whether `claude` CLI is available in the test env
63
+ expect(typeof health.healthy).toBe('boolean');
64
+ });
65
+ });
66
+ describe('ClaudeCodeHookProvider', () => {
67
+ let hooks;
68
+ beforeEach(() => {
69
+ hooks = new ClaudeCodeHookProvider();
70
+ });
71
+ it('maps SessionStart to onSessionStart', () => {
72
+ expect(hooks.mapProviderEvent('SessionStart')).toBe('onSessionStart');
73
+ });
74
+ it('maps PostToolUse to onToolComplete', () => {
75
+ expect(hooks.mapProviderEvent('PostToolUse')).toBe('onToolComplete');
76
+ });
77
+ it('maps UserPromptSubmit to onPromptSubmit', () => {
78
+ expect(hooks.mapProviderEvent('UserPromptSubmit')).toBe('onPromptSubmit');
79
+ });
80
+ it('maps Stop to onSessionEnd', () => {
81
+ expect(hooks.mapProviderEvent('Stop')).toBe('onSessionEnd');
82
+ });
83
+ it('returns null for unknown events', () => {
84
+ expect(hooks.mapProviderEvent('UnknownEvent')).toBeNull();
85
+ expect(hooks.mapProviderEvent('')).toBeNull();
86
+ });
87
+ it('tracks registration state', async () => {
88
+ expect(hooks.isRegistered()).toBe(false);
89
+ await hooks.registerNativeHooks('/tmp/test');
90
+ expect(hooks.isRegistered()).toBe(true);
91
+ await hooks.unregisterNativeHooks();
92
+ expect(hooks.isRegistered()).toBe(false);
93
+ });
94
+ it('exposes event map for introspection', () => {
95
+ const map = hooks.getEventMap();
96
+ expect(map).toHaveProperty('SessionStart', 'onSessionStart');
97
+ expect(map).toHaveProperty('PostToolUse', 'onToolComplete');
98
+ expect(map).toHaveProperty('UserPromptSubmit', 'onPromptSubmit');
99
+ expect(map).toHaveProperty('Stop', 'onSessionEnd');
100
+ expect(Object.keys(map)).toHaveLength(4);
101
+ });
102
+ });
103
+ describe('ClaudeCodeSpawnProvider', () => {
104
+ let spawn;
105
+ beforeEach(() => {
106
+ spawn = new ClaudeCodeSpawnProvider();
107
+ });
108
+ it('canSpawn returns boolean', async () => {
109
+ const result = await spawn.canSpawn();
110
+ expect(typeof result).toBe('boolean');
111
+ });
112
+ it('listRunning returns empty array initially', async () => {
113
+ const running = await spawn.listRunning();
114
+ expect(running).toEqual([]);
115
+ });
116
+ it('terminate is no-op for unknown instance', async () => {
117
+ await expect(spawn.terminate('nonexistent')).resolves.toBeUndefined();
118
+ });
119
+ });
120
+ describe('ClaudeCodeInstallProvider', () => {
121
+ let install;
122
+ let testDir;
123
+ beforeEach(() => {
124
+ install = new ClaudeCodeInstallProvider();
125
+ testDir = join(tmpdir(), `cleo-adapter-test-${Date.now()}`);
126
+ mkdirSync(testDir, { recursive: true });
127
+ });
128
+ afterEach(() => {
129
+ try {
130
+ rmSync(testDir, { recursive: true, force: true });
131
+ }
132
+ catch {
133
+ // cleanup best-effort
134
+ }
135
+ });
136
+ it('creates CLAUDE.md with @-references', async () => {
137
+ await install.ensureInstructionReferences(testDir);
138
+ const content = readFileSync(join(testDir, 'CLAUDE.md'), 'utf-8');
139
+ expect(content).toContain('@~/.cleo/templates/CLEO-INJECTION.md');
140
+ expect(content).toContain('@.cleo/memory-bridge.md');
141
+ });
142
+ it('appends missing references to existing CLAUDE.md', async () => {
143
+ const existing = '# Project\n@AGENTS.md\n';
144
+ writeFileSync(join(testDir, 'CLAUDE.md'), existing, 'utf-8');
145
+ await install.ensureInstructionReferences(testDir);
146
+ const content = readFileSync(join(testDir, 'CLAUDE.md'), 'utf-8');
147
+ expect(content).toContain('# Project');
148
+ expect(content).toContain('@AGENTS.md');
149
+ expect(content).toContain('@~/.cleo/templates/CLEO-INJECTION.md');
150
+ expect(content).toContain('@.cleo/memory-bridge.md');
151
+ });
152
+ it('does not duplicate existing references', async () => {
153
+ const existing = '@~/.cleo/templates/CLEO-INJECTION.md\n@.cleo/memory-bridge.md\n';
154
+ writeFileSync(join(testDir, 'CLAUDE.md'), existing, 'utf-8');
155
+ await install.ensureInstructionReferences(testDir);
156
+ const content = readFileSync(join(testDir, 'CLAUDE.md'), 'utf-8');
157
+ // Should not have duplicated lines
158
+ const injectionCount = content.split('@~/.cleo/templates/CLEO-INJECTION.md').length - 1;
159
+ expect(injectionCount).toBe(1);
160
+ });
161
+ it('registers MCP server in .mcp.json', async () => {
162
+ const result = await install.install({
163
+ projectDir: testDir,
164
+ mcpServerPath: '/path/to/cleo-mcp.js',
165
+ });
166
+ expect(result.success).toBe(true);
167
+ expect(result.mcpRegistered).toBe(true);
168
+ expect(result.instructionFileUpdated).toBe(true);
169
+ const mcpConfig = JSON.parse(readFileSync(join(testDir, '.mcp.json'), 'utf-8'));
170
+ expect(mcpConfig.mcpServers.cleo).toEqual({
171
+ command: 'node',
172
+ args: ['/path/to/cleo-mcp.js'],
173
+ });
174
+ });
175
+ it('uninstall removes MCP server from .mcp.json', async () => {
176
+ await install.install({
177
+ projectDir: testDir,
178
+ mcpServerPath: '/path/to/cleo-mcp.js',
179
+ });
180
+ await install.uninstall();
181
+ const mcpConfig = JSON.parse(readFileSync(join(testDir, '.mcp.json'), 'utf-8'));
182
+ expect(mcpConfig.mcpServers.cleo).toBeUndefined();
183
+ });
184
+ });
185
+ describe('createAdapter factory', () => {
186
+ it('returns a ClaudeCodeAdapter instance', () => {
187
+ const adapter = createAdapter();
188
+ expect(adapter).toBeInstanceOf(ClaudeCodeAdapter);
189
+ expect(adapter.id).toBe('claude-code');
190
+ });
191
+ });
192
+ //# sourceMappingURL=claude-code-adapter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code-adapter.test.js","sourceRoot":"","sources":["claude-code-adapter.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Unit tests for @cleocode/adapter-claude-code
3
+ *
4
+ * Tests the ClaudeCodeAdapter, ClaudeCodeHookProvider,
5
+ * ClaudeCodeSpawnProvider, and ClaudeCodeInstallProvider.
6
+ *
7
+ * @task T5240
8
+ */
9
+
10
+ import { mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
11
+ import { tmpdir } from 'node:os';
12
+ import { join } from 'node:path';
13
+ import {
14
+ ClaudeCodeAdapter,
15
+ ClaudeCodeHookProvider,
16
+ ClaudeCodeInstallProvider,
17
+ ClaudeCodeSpawnProvider,
18
+ createClaudeCodeAdapter as createAdapter,
19
+ } from '@cleocode/adapters';
20
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
21
+
22
+ describe('ClaudeCodeAdapter', () => {
23
+ let adapter: ClaudeCodeAdapter;
24
+
25
+ beforeEach(() => {
26
+ adapter = new ClaudeCodeAdapter();
27
+ });
28
+
29
+ it('has correct identity fields', () => {
30
+ expect(adapter.id).toBe('claude-code');
31
+ expect(adapter.name).toBe('Claude Code');
32
+ expect(adapter.version).toBe('1.0.0');
33
+ });
34
+
35
+ it('has correct capabilities', () => {
36
+ expect(adapter.capabilities.supportsHooks).toBe(true);
37
+ expect(adapter.capabilities.supportsSpawn).toBe(true);
38
+ expect(adapter.capabilities.supportsInstall).toBe(true);
39
+ expect(adapter.capabilities.supportsMcp).toBe(true);
40
+ expect(adapter.capabilities.supportsInstructionFiles).toBe(true);
41
+ expect(adapter.capabilities.instructionFilePattern).toBe('CLAUDE.md');
42
+ expect(adapter.capabilities.supportedHookEvents).toContain('onSessionStart');
43
+ expect(adapter.capabilities.supportedHookEvents).toContain('onSessionEnd');
44
+ expect(adapter.capabilities.supportedHookEvents).toContain('onToolComplete');
45
+ });
46
+
47
+ it('exposes hooks, spawn, and install providers', () => {
48
+ expect(adapter.hooks).toBeInstanceOf(ClaudeCodeHookProvider);
49
+ expect(adapter.spawn).toBeInstanceOf(ClaudeCodeSpawnProvider);
50
+ expect(adapter.install).toBeInstanceOf(ClaudeCodeInstallProvider);
51
+ });
52
+
53
+ it('tracks initialization state', async () => {
54
+ expect(adapter.isInitialized()).toBe(false);
55
+ await adapter.initialize('/tmp/test-project');
56
+ expect(adapter.isInitialized()).toBe(true);
57
+ expect(adapter.getProjectDir()).toBe('/tmp/test-project');
58
+ });
59
+
60
+ it('clears state on dispose', async () => {
61
+ await adapter.initialize('/tmp/test-project');
62
+ await adapter.dispose();
63
+ expect(adapter.isInitialized()).toBe(false);
64
+ expect(adapter.getProjectDir()).toBeNull();
65
+ });
66
+
67
+ it('reports unhealthy when not initialized', async () => {
68
+ const health = await adapter.healthCheck();
69
+ expect(health.healthy).toBe(false);
70
+ expect(health.provider).toBe('claude-code');
71
+ expect(health.details?.error).toBe('Adapter not initialized');
72
+ });
73
+
74
+ it('reports health after initialization', async () => {
75
+ await adapter.initialize('/tmp/test-project');
76
+ const health = await adapter.healthCheck();
77
+ expect(health.provider).toBe('claude-code');
78
+ // healthy depends on whether `claude` CLI is available in the test env
79
+ expect(typeof health.healthy).toBe('boolean');
80
+ });
81
+ });
82
+
83
+ describe('ClaudeCodeHookProvider', () => {
84
+ let hooks: ClaudeCodeHookProvider;
85
+
86
+ beforeEach(() => {
87
+ hooks = new ClaudeCodeHookProvider();
88
+ });
89
+
90
+ it('maps SessionStart to onSessionStart', () => {
91
+ expect(hooks.mapProviderEvent('SessionStart')).toBe('onSessionStart');
92
+ });
93
+
94
+ it('maps PostToolUse to onToolComplete', () => {
95
+ expect(hooks.mapProviderEvent('PostToolUse')).toBe('onToolComplete');
96
+ });
97
+
98
+ it('maps UserPromptSubmit to onPromptSubmit', () => {
99
+ expect(hooks.mapProviderEvent('UserPromptSubmit')).toBe('onPromptSubmit');
100
+ });
101
+
102
+ it('maps Stop to onSessionEnd', () => {
103
+ expect(hooks.mapProviderEvent('Stop')).toBe('onSessionEnd');
104
+ });
105
+
106
+ it('returns null for unknown events', () => {
107
+ expect(hooks.mapProviderEvent('UnknownEvent')).toBeNull();
108
+ expect(hooks.mapProviderEvent('')).toBeNull();
109
+ });
110
+
111
+ it('tracks registration state', async () => {
112
+ expect(hooks.isRegistered()).toBe(false);
113
+ await hooks.registerNativeHooks('/tmp/test');
114
+ expect(hooks.isRegistered()).toBe(true);
115
+ await hooks.unregisterNativeHooks();
116
+ expect(hooks.isRegistered()).toBe(false);
117
+ });
118
+
119
+ it('exposes event map for introspection', () => {
120
+ const map = hooks.getEventMap();
121
+ expect(map).toHaveProperty('SessionStart', 'onSessionStart');
122
+ expect(map).toHaveProperty('PostToolUse', 'onToolComplete');
123
+ expect(map).toHaveProperty('UserPromptSubmit', 'onPromptSubmit');
124
+ expect(map).toHaveProperty('Stop', 'onSessionEnd');
125
+ expect(Object.keys(map)).toHaveLength(4);
126
+ });
127
+ });
128
+
129
+ describe('ClaudeCodeSpawnProvider', () => {
130
+ let spawn: ClaudeCodeSpawnProvider;
131
+
132
+ beforeEach(() => {
133
+ spawn = new ClaudeCodeSpawnProvider();
134
+ });
135
+
136
+ it('canSpawn returns boolean', async () => {
137
+ const result = await spawn.canSpawn();
138
+ expect(typeof result).toBe('boolean');
139
+ });
140
+
141
+ it('listRunning returns empty array initially', async () => {
142
+ const running = await spawn.listRunning();
143
+ expect(running).toEqual([]);
144
+ });
145
+
146
+ it('terminate is no-op for unknown instance', async () => {
147
+ await expect(spawn.terminate('nonexistent')).resolves.toBeUndefined();
148
+ });
149
+ });
150
+
151
+ describe('ClaudeCodeInstallProvider', () => {
152
+ let install: ClaudeCodeInstallProvider;
153
+ let testDir: string;
154
+
155
+ beforeEach(() => {
156
+ install = new ClaudeCodeInstallProvider();
157
+ testDir = join(tmpdir(), `cleo-adapter-test-${Date.now()}`);
158
+ mkdirSync(testDir, { recursive: true });
159
+ });
160
+
161
+ afterEach(() => {
162
+ try {
163
+ rmSync(testDir, { recursive: true, force: true });
164
+ } catch {
165
+ // cleanup best-effort
166
+ }
167
+ });
168
+
169
+ it('creates CLAUDE.md with @-references', async () => {
170
+ await install.ensureInstructionReferences(testDir);
171
+ const content = readFileSync(join(testDir, 'CLAUDE.md'), 'utf-8');
172
+ expect(content).toContain('@~/.cleo/templates/CLEO-INJECTION.md');
173
+ expect(content).toContain('@.cleo/memory-bridge.md');
174
+ });
175
+
176
+ it('appends missing references to existing CLAUDE.md', async () => {
177
+ const existing = '# Project\n@AGENTS.md\n';
178
+ writeFileSync(join(testDir, 'CLAUDE.md'), existing, 'utf-8');
179
+
180
+ await install.ensureInstructionReferences(testDir);
181
+ const content = readFileSync(join(testDir, 'CLAUDE.md'), 'utf-8');
182
+ expect(content).toContain('# Project');
183
+ expect(content).toContain('@AGENTS.md');
184
+ expect(content).toContain('@~/.cleo/templates/CLEO-INJECTION.md');
185
+ expect(content).toContain('@.cleo/memory-bridge.md');
186
+ });
187
+
188
+ it('does not duplicate existing references', async () => {
189
+ const existing = '@~/.cleo/templates/CLEO-INJECTION.md\n@.cleo/memory-bridge.md\n';
190
+ writeFileSync(join(testDir, 'CLAUDE.md'), existing, 'utf-8');
191
+
192
+ await install.ensureInstructionReferences(testDir);
193
+ const content = readFileSync(join(testDir, 'CLAUDE.md'), 'utf-8');
194
+ // Should not have duplicated lines
195
+ const injectionCount = content.split('@~/.cleo/templates/CLEO-INJECTION.md').length - 1;
196
+ expect(injectionCount).toBe(1);
197
+ });
198
+
199
+ it('registers MCP server in .mcp.json', async () => {
200
+ const result = await install.install({
201
+ projectDir: testDir,
202
+ mcpServerPath: '/path/to/cleo-mcp.js',
203
+ });
204
+
205
+ expect(result.success).toBe(true);
206
+ expect(result.mcpRegistered).toBe(true);
207
+ expect(result.instructionFileUpdated).toBe(true);
208
+
209
+ const mcpConfig = JSON.parse(readFileSync(join(testDir, '.mcp.json'), 'utf-8'));
210
+ expect(mcpConfig.mcpServers.cleo).toEqual({
211
+ command: 'node',
212
+ args: ['/path/to/cleo-mcp.js'],
213
+ });
214
+ });
215
+
216
+ it('uninstall removes MCP server from .mcp.json', async () => {
217
+ await install.install({
218
+ projectDir: testDir,
219
+ mcpServerPath: '/path/to/cleo-mcp.js',
220
+ });
221
+
222
+ await install.uninstall();
223
+
224
+ const mcpConfig = JSON.parse(readFileSync(join(testDir, '.mcp.json'), 'utf-8'));
225
+ expect(mcpConfig.mcpServers.cleo).toBeUndefined();
226
+ });
227
+ });
228
+
229
+ describe('createAdapter factory', () => {
230
+ it('returns a ClaudeCodeAdapter instance', () => {
231
+ const adapter = createAdapter();
232
+ expect(adapter).toBeInstanceOf(ClaudeCodeAdapter);
233
+ expect(adapter.id).toBe('claude-code');
234
+ });
235
+ });
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Unit tests for @cleocode/adapter-cursor
3
+ *
4
+ * Tests the CursorAdapter, CursorHookProvider, and CursorInstallProvider.
5
+ * Cursor has no spawn support, so no spawn provider tests.
6
+ *
7
+ * @task T5240
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=cursor-adapter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor-adapter.test.d.ts","sourceRoot":"","sources":["cursor-adapter.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}