@cleocode/adapters 2026.4.6 → 2026.4.7
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.
- package/package.json +3 -3
- package/src/__tests__/claude-code-adapter.test.d.ts.map +0 -1
- package/src/__tests__/claude-code-adapter.test.js +0 -183
- package/src/__tests__/claude-code-adapter.test.js.map +0 -1
- package/src/__tests__/cursor-adapter.test.d.ts.map +0 -1
- package/src/__tests__/cursor-adapter.test.js +0 -192
- package/src/__tests__/cursor-adapter.test.js.map +0 -1
- package/src/__tests__/opencode-adapter.test.d.ts.map +0 -1
- package/src/__tests__/opencode-adapter.test.js +0 -205
- package/src/__tests__/opencode-adapter.test.js.map +0 -1
- package/src/providers/claude-code/__tests__/adapter.test.d.ts.map +0 -1
- package/src/providers/claude-code/__tests__/adapter.test.js +0 -276
- package/src/providers/claude-code/__tests__/adapter.test.js.map +0 -1
- package/src/providers/cursor/__tests__/adapter.test.d.ts.map +0 -1
- package/src/providers/cursor/__tests__/adapter.test.js +0 -271
- package/src/providers/cursor/__tests__/adapter.test.js.map +0 -1
- package/src/providers/opencode/__tests__/adapter.test.d.ts.map +0 -1
- package/src/providers/opencode/__tests__/adapter.test.js +0 -276
- package/src/providers/opencode/__tests__/adapter.test.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cleocode/adapters",
|
|
3
|
-
"version": "2026.4.
|
|
3
|
+
"version": "2026.4.7",
|
|
4
4
|
"description": "Unified provider adapters for CLEO (Claude Code, OpenCode, Cursor)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@cleocode/caamp": "2026.4.
|
|
16
|
-
"@cleocode/contracts": "2026.4.
|
|
15
|
+
"@cleocode/caamp": "2026.4.7",
|
|
16
|
+
"@cleocode/contracts": "2026.4.7"
|
|
17
17
|
},
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"engines": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code-adapter.test.d.ts","sourceRoot":"","sources":["claude-code-adapter.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
|
@@ -1,183 +0,0 @@
|
|
|
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(false);
|
|
29
|
-
expect(adapter.capabilities.supportsInstructionFiles).toBe(true);
|
|
30
|
-
expect(adapter.capabilities.instructionFilePattern).toBe('CLAUDE.md');
|
|
31
|
-
expect(adapter.capabilities.supportedHookEvents).toContain('SessionStart');
|
|
32
|
-
expect(adapter.capabilities.supportedHookEvents).toContain('SessionEnd');
|
|
33
|
-
expect(adapter.capabilities.supportedHookEvents).toContain('PostToolUse');
|
|
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 SessionStart', () => {
|
|
72
|
-
expect(hooks.mapProviderEvent('SessionStart')).toBe('SessionStart');
|
|
73
|
-
});
|
|
74
|
-
it('maps PostToolUse to PostToolUse', () => {
|
|
75
|
-
expect(hooks.mapProviderEvent('PostToolUse')).toBe('PostToolUse');
|
|
76
|
-
});
|
|
77
|
-
it('maps UserPromptSubmit to PromptSubmit', () => {
|
|
78
|
-
expect(hooks.mapProviderEvent('UserPromptSubmit')).toBe('PromptSubmit');
|
|
79
|
-
});
|
|
80
|
-
it('maps Stop to ResponseComplete', () => {
|
|
81
|
-
expect(hooks.mapProviderEvent('Stop')).toBe('ResponseComplete');
|
|
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', 'SessionStart');
|
|
97
|
-
expect(map).toHaveProperty('PostToolUse', 'PostToolUse');
|
|
98
|
-
expect(map).toHaveProperty('UserPromptSubmit', 'PromptSubmit');
|
|
99
|
-
expect(map).toHaveProperty('Stop', 'ResponseComplete');
|
|
100
|
-
expect(Object.keys(map)).toHaveLength(14);
|
|
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('install returns mcpRegistered false', async () => {
|
|
162
|
-
const result = await install.install({
|
|
163
|
-
projectDir: testDir,
|
|
164
|
-
});
|
|
165
|
-
expect(result.success).toBe(true);
|
|
166
|
-
expect(result.mcpRegistered).toBe(false);
|
|
167
|
-
expect(result.instructionFileUpdated).toBe(true);
|
|
168
|
-
});
|
|
169
|
-
it('uninstall is a no-op', async () => {
|
|
170
|
-
await install.install({
|
|
171
|
-
projectDir: testDir,
|
|
172
|
-
});
|
|
173
|
-
await expect(install.uninstall()).resolves.toBeUndefined();
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
describe('createAdapter factory', () => {
|
|
177
|
-
it('returns a ClaudeCodeAdapter instance', () => {
|
|
178
|
-
const adapter = createAdapter();
|
|
179
|
-
expect(adapter).toBeInstanceOf(ClaudeCodeAdapter);
|
|
180
|
-
expect(adapter.id).toBe('claude-code');
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
//# sourceMappingURL=claude-code-adapter.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code-adapter.test.js","sourceRoot":"","sources":["claude-code-adapter.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cursor-adapter.test.d.ts","sourceRoot":"","sources":["cursor-adapter.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
|
@@ -1,192 +0,0 @@
|
|
|
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
|
-
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
10
|
-
import { tmpdir } from 'node:os';
|
|
11
|
-
import { join } from 'node:path';
|
|
12
|
-
import { CursorAdapter, CursorHookProvider, CursorInstallProvider, createCursorAdapter as createAdapter, } from '@cleocode/adapters';
|
|
13
|
-
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
14
|
-
describe('CursorAdapter', () => {
|
|
15
|
-
let adapter;
|
|
16
|
-
beforeEach(() => {
|
|
17
|
-
adapter = new CursorAdapter();
|
|
18
|
-
});
|
|
19
|
-
it('has correct identity fields', () => {
|
|
20
|
-
expect(adapter.id).toBe('cursor');
|
|
21
|
-
expect(adapter.name).toBe('Cursor');
|
|
22
|
-
expect(adapter.version).toBe('1.0.0');
|
|
23
|
-
});
|
|
24
|
-
it('supports hooks with 10 CAAMP events', () => {
|
|
25
|
-
expect(adapter.capabilities.supportsHooks).toBe(true);
|
|
26
|
-
expect(adapter.capabilities.supportedHookEvents).toHaveLength(10);
|
|
27
|
-
expect(adapter.capabilities.supportedHookEvents).toContain('SessionStart');
|
|
28
|
-
expect(adapter.capabilities.supportedHookEvents).toContain('SessionEnd');
|
|
29
|
-
expect(adapter.capabilities.supportedHookEvents).toContain('PreToolUse');
|
|
30
|
-
expect(adapter.capabilities.supportedHookEvents).toContain('PostToolUse');
|
|
31
|
-
});
|
|
32
|
-
it('does not support spawn', () => {
|
|
33
|
-
expect(adapter.capabilities.supportsSpawn).toBe(false);
|
|
34
|
-
});
|
|
35
|
-
it('supports install and instruction files', () => {
|
|
36
|
-
expect(adapter.capabilities.supportsInstall).toBe(true);
|
|
37
|
-
expect(adapter.capabilities.supportsMcp).toBe(false);
|
|
38
|
-
expect(adapter.capabilities.supportsInstructionFiles).toBe(true);
|
|
39
|
-
expect(adapter.capabilities.instructionFilePattern).toBe('.cursor/rules/*.mdc');
|
|
40
|
-
});
|
|
41
|
-
it('has no spawn provider', () => {
|
|
42
|
-
expect(adapter.spawn).toBeUndefined();
|
|
43
|
-
});
|
|
44
|
-
it('exposes hooks and install providers', () => {
|
|
45
|
-
expect(adapter.hooks).toBeInstanceOf(CursorHookProvider);
|
|
46
|
-
expect(adapter.install).toBeInstanceOf(CursorInstallProvider);
|
|
47
|
-
});
|
|
48
|
-
it('tracks initialization state', async () => {
|
|
49
|
-
expect(adapter.isInitialized()).toBe(false);
|
|
50
|
-
await adapter.initialize('/tmp/test-project');
|
|
51
|
-
expect(adapter.isInitialized()).toBe(true);
|
|
52
|
-
expect(adapter.getProjectDir()).toBe('/tmp/test-project');
|
|
53
|
-
});
|
|
54
|
-
it('clears state on dispose', async () => {
|
|
55
|
-
await adapter.initialize('/tmp/test-project');
|
|
56
|
-
await adapter.dispose();
|
|
57
|
-
expect(adapter.isInitialized()).toBe(false);
|
|
58
|
-
expect(adapter.getProjectDir()).toBeNull();
|
|
59
|
-
});
|
|
60
|
-
it('reports unhealthy when not initialized', async () => {
|
|
61
|
-
const health = await adapter.healthCheck();
|
|
62
|
-
expect(health.healthy).toBe(false);
|
|
63
|
-
expect(health.provider).toBe('cursor');
|
|
64
|
-
expect(health.details?.error).toBe('Adapter not initialized');
|
|
65
|
-
});
|
|
66
|
-
it('reports health based on .cursor/ presence', async () => {
|
|
67
|
-
const testDir = join(tmpdir(), `cursor-health-${Date.now()}`);
|
|
68
|
-
mkdirSync(join(testDir, '.cursor'), { recursive: true });
|
|
69
|
-
try {
|
|
70
|
-
await adapter.initialize(testDir);
|
|
71
|
-
const health = await adapter.healthCheck();
|
|
72
|
-
expect(health.provider).toBe('cursor');
|
|
73
|
-
expect(health.details?.configDirExists).toBe(true);
|
|
74
|
-
}
|
|
75
|
-
finally {
|
|
76
|
-
rmSync(testDir, { recursive: true, force: true });
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
describe('CursorHookProvider', () => {
|
|
81
|
-
let hooks;
|
|
82
|
-
beforeEach(() => {
|
|
83
|
-
hooks = new CursorHookProvider();
|
|
84
|
-
});
|
|
85
|
-
it('maps Cursor native events to CAAMP canonical names', () => {
|
|
86
|
-
expect(hooks.mapProviderEvent('sessionStart')).toBe('SessionStart');
|
|
87
|
-
expect(hooks.mapProviderEvent('sessionEnd')).toBe('SessionEnd');
|
|
88
|
-
expect(hooks.mapProviderEvent('beforeSubmitPrompt')).toBe('PromptSubmit');
|
|
89
|
-
expect(hooks.mapProviderEvent('stop')).toBe('ResponseComplete');
|
|
90
|
-
expect(hooks.mapProviderEvent('preToolUse')).toBe('PreToolUse');
|
|
91
|
-
expect(hooks.mapProviderEvent('postToolUse')).toBe('PostToolUse');
|
|
92
|
-
expect(hooks.mapProviderEvent('postToolUseFailure')).toBe('PostToolUseFailure');
|
|
93
|
-
expect(hooks.mapProviderEvent('subagentStart')).toBe('SubagentStart');
|
|
94
|
-
expect(hooks.mapProviderEvent('subagentStop')).toBe('SubagentStop');
|
|
95
|
-
expect(hooks.mapProviderEvent('preCompact')).toBe('PreCompact');
|
|
96
|
-
});
|
|
97
|
-
it('returns null for unsupported or unknown events', () => {
|
|
98
|
-
expect(hooks.mapProviderEvent('SessionStart')).toBeNull();
|
|
99
|
-
expect(hooks.mapProviderEvent('')).toBeNull();
|
|
100
|
-
expect(hooks.mapProviderEvent('anything')).toBeNull();
|
|
101
|
-
});
|
|
102
|
-
it('tracks registration state', async () => {
|
|
103
|
-
expect(hooks.isRegistered()).toBe(false);
|
|
104
|
-
await hooks.registerNativeHooks('/tmp/test');
|
|
105
|
-
expect(hooks.isRegistered()).toBe(true);
|
|
106
|
-
await hooks.unregisterNativeHooks();
|
|
107
|
-
expect(hooks.isRegistered()).toBe(false);
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
describe('CursorInstallProvider', () => {
|
|
111
|
-
let install;
|
|
112
|
-
let testDir;
|
|
113
|
-
beforeEach(() => {
|
|
114
|
-
install = new CursorInstallProvider();
|
|
115
|
-
testDir = join(tmpdir(), `cleo-cursor-test-${Date.now()}`);
|
|
116
|
-
mkdirSync(testDir, { recursive: true });
|
|
117
|
-
});
|
|
118
|
-
afterEach(() => {
|
|
119
|
-
try {
|
|
120
|
-
rmSync(testDir, { recursive: true, force: true });
|
|
121
|
-
}
|
|
122
|
-
catch {
|
|
123
|
-
// cleanup best-effort
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
it('creates .cursor/rules/cleo.mdc with @-references', async () => {
|
|
127
|
-
await install.ensureInstructionReferences(testDir);
|
|
128
|
-
const mdcPath = join(testDir, '.cursor', 'rules', 'cleo.mdc');
|
|
129
|
-
expect(existsSync(mdcPath)).toBe(true);
|
|
130
|
-
const content = readFileSync(mdcPath, 'utf-8');
|
|
131
|
-
expect(content).toContain('alwaysApply: true');
|
|
132
|
-
expect(content).toContain('@~/.cleo/templates/CLEO-INJECTION.md');
|
|
133
|
-
expect(content).toContain('@.cleo/memory-bridge.md');
|
|
134
|
-
});
|
|
135
|
-
it('uses MDC frontmatter format', async () => {
|
|
136
|
-
await install.ensureInstructionReferences(testDir);
|
|
137
|
-
const mdcPath = join(testDir, '.cursor', 'rules', 'cleo.mdc');
|
|
138
|
-
const content = readFileSync(mdcPath, 'utf-8');
|
|
139
|
-
expect(content).toMatch(/^---\n/);
|
|
140
|
-
expect(content).toContain('description: CLEO task management protocol references');
|
|
141
|
-
expect(content).toContain('globs: "**/*"');
|
|
142
|
-
});
|
|
143
|
-
it('is idempotent for modern rules', async () => {
|
|
144
|
-
await install.ensureInstructionReferences(testDir);
|
|
145
|
-
const mdcPath = join(testDir, '.cursor', 'rules', 'cleo.mdc');
|
|
146
|
-
const first = readFileSync(mdcPath, 'utf-8');
|
|
147
|
-
await install.ensureInstructionReferences(testDir);
|
|
148
|
-
const second = readFileSync(mdcPath, 'utf-8');
|
|
149
|
-
expect(first).toBe(second);
|
|
150
|
-
});
|
|
151
|
-
it('appends to legacy .cursorrules if it exists', async () => {
|
|
152
|
-
const legacyPath = join(testDir, '.cursorrules');
|
|
153
|
-
writeFileSync(legacyPath, '# Project Rules\nUse TypeScript.\n', 'utf-8');
|
|
154
|
-
await install.ensureInstructionReferences(testDir);
|
|
155
|
-
const content = readFileSync(legacyPath, 'utf-8');
|
|
156
|
-
expect(content).toContain('# Project Rules');
|
|
157
|
-
expect(content).toContain('Use TypeScript.');
|
|
158
|
-
expect(content).toContain('@~/.cleo/templates/CLEO-INJECTION.md');
|
|
159
|
-
expect(content).toContain('@.cleo/memory-bridge.md');
|
|
160
|
-
});
|
|
161
|
-
it('does not create legacy .cursorrules if it does not exist', async () => {
|
|
162
|
-
await install.ensureInstructionReferences(testDir);
|
|
163
|
-
expect(existsSync(join(testDir, '.cursorrules'))).toBe(false);
|
|
164
|
-
});
|
|
165
|
-
it('does not duplicate references in legacy .cursorrules', async () => {
|
|
166
|
-
const legacyPath = join(testDir, '.cursorrules');
|
|
167
|
-
writeFileSync(legacyPath, '@~/.cleo/templates/CLEO-INJECTION.md\n@.cleo/memory-bridge.md\n', 'utf-8');
|
|
168
|
-
await install.ensureInstructionReferences(testDir);
|
|
169
|
-
const content = readFileSync(legacyPath, 'utf-8');
|
|
170
|
-
const injectionCount = content.split('@~/.cleo/templates/CLEO-INJECTION.md').length - 1;
|
|
171
|
-
expect(injectionCount).toBe(1);
|
|
172
|
-
});
|
|
173
|
-
it('install returns mcpRegistered false', async () => {
|
|
174
|
-
const result = await install.install({
|
|
175
|
-
projectDir: testDir,
|
|
176
|
-
});
|
|
177
|
-
expect(result.success).toBe(true);
|
|
178
|
-
expect(result.mcpRegistered).toBe(false);
|
|
179
|
-
expect(result.instructionFileUpdated).toBe(true);
|
|
180
|
-
});
|
|
181
|
-
it('uninstall is a no-op', async () => {
|
|
182
|
-
await expect(install.uninstall()).resolves.toBeUndefined();
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
|
-
describe('createAdapter factory', () => {
|
|
186
|
-
it('returns a CursorAdapter instance', () => {
|
|
187
|
-
const adapter = createAdapter();
|
|
188
|
-
expect(adapter).toBeInstanceOf(CursorAdapter);
|
|
189
|
-
expect(adapter.id).toBe('cursor');
|
|
190
|
-
});
|
|
191
|
-
});
|
|
192
|
-
//# sourceMappingURL=cursor-adapter.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cursor-adapter.test.js","sourceRoot":"","sources":["cursor-adapter.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"opencode-adapter.test.d.ts","sourceRoot":"","sources":["opencode-adapter.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit tests for @cleocode/adapter-opencode
|
|
3
|
-
*
|
|
4
|
-
* Tests the OpenCodeAdapter, OpenCodeHookProvider,
|
|
5
|
-
* OpenCodeSpawnProvider, and OpenCodeInstallProvider.
|
|
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 { createOpenCodeAdapter as createAdapter, OpenCodeAdapter, OpenCodeHookProvider, OpenCodeInstallProvider, OpenCodeSpawnProvider, } from '@cleocode/adapters';
|
|
13
|
-
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
14
|
-
describe('OpenCodeAdapter', () => {
|
|
15
|
-
let adapter;
|
|
16
|
-
beforeEach(() => {
|
|
17
|
-
adapter = new OpenCodeAdapter();
|
|
18
|
-
});
|
|
19
|
-
it('has correct identity fields', () => {
|
|
20
|
-
expect(adapter.id).toBe('opencode');
|
|
21
|
-
expect(adapter.name).toBe('OpenCode');
|
|
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(false);
|
|
29
|
-
expect(adapter.capabilities.supportsInstructionFiles).toBe(true);
|
|
30
|
-
expect(adapter.capabilities.instructionFilePattern).toBe('AGENTS.md');
|
|
31
|
-
});
|
|
32
|
-
it('supports 10 hook events (10/16 CAAMP)', () => {
|
|
33
|
-
const events = adapter.capabilities.supportedHookEvents;
|
|
34
|
-
expect(events).toHaveLength(10);
|
|
35
|
-
expect(events).toContain('SessionStart');
|
|
36
|
-
expect(events).toContain('SessionEnd');
|
|
37
|
-
expect(events).toContain('PromptSubmit');
|
|
38
|
-
expect(events).toContain('ResponseComplete');
|
|
39
|
-
expect(events).toContain('PreToolUse');
|
|
40
|
-
expect(events).toContain('PostToolUse');
|
|
41
|
-
expect(events).toContain('PermissionRequest');
|
|
42
|
-
expect(events).toContain('PreModel');
|
|
43
|
-
expect(events).toContain('PreCompact');
|
|
44
|
-
expect(events).toContain('PostCompact');
|
|
45
|
-
});
|
|
46
|
-
it('exposes hooks, spawn, and install providers', () => {
|
|
47
|
-
expect(adapter.hooks).toBeInstanceOf(OpenCodeHookProvider);
|
|
48
|
-
expect(adapter.spawn).toBeInstanceOf(OpenCodeSpawnProvider);
|
|
49
|
-
expect(adapter.install).toBeInstanceOf(OpenCodeInstallProvider);
|
|
50
|
-
});
|
|
51
|
-
it('tracks initialization state', async () => {
|
|
52
|
-
expect(adapter.isInitialized()).toBe(false);
|
|
53
|
-
await adapter.initialize('/tmp/test-project');
|
|
54
|
-
expect(adapter.isInitialized()).toBe(true);
|
|
55
|
-
expect(adapter.getProjectDir()).toBe('/tmp/test-project');
|
|
56
|
-
});
|
|
57
|
-
it('clears state on dispose', async () => {
|
|
58
|
-
await adapter.initialize('/tmp/test-project');
|
|
59
|
-
await adapter.dispose();
|
|
60
|
-
expect(adapter.isInitialized()).toBe(false);
|
|
61
|
-
expect(adapter.getProjectDir()).toBeNull();
|
|
62
|
-
});
|
|
63
|
-
it('reports unhealthy when not initialized', async () => {
|
|
64
|
-
const health = await adapter.healthCheck();
|
|
65
|
-
expect(health.healthy).toBe(false);
|
|
66
|
-
expect(health.provider).toBe('opencode');
|
|
67
|
-
expect(health.details?.error).toBe('Adapter not initialized');
|
|
68
|
-
});
|
|
69
|
-
it('reports health after initialization', async () => {
|
|
70
|
-
await adapter.initialize('/tmp/test-project');
|
|
71
|
-
const health = await adapter.healthCheck();
|
|
72
|
-
expect(health.provider).toBe('opencode');
|
|
73
|
-
expect(typeof health.healthy).toBe('boolean');
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
describe('OpenCodeHookProvider', () => {
|
|
77
|
-
let hooks;
|
|
78
|
-
beforeEach(() => {
|
|
79
|
-
hooks = new OpenCodeHookProvider();
|
|
80
|
-
});
|
|
81
|
-
it('maps event:session.created to SessionStart', () => {
|
|
82
|
-
expect(hooks.mapProviderEvent('event:session.created')).toBe('SessionStart');
|
|
83
|
-
});
|
|
84
|
-
it('maps event:session.deleted to SessionEnd', () => {
|
|
85
|
-
expect(hooks.mapProviderEvent('event:session.deleted')).toBe('SessionEnd');
|
|
86
|
-
});
|
|
87
|
-
it('maps chat.message to PromptSubmit', () => {
|
|
88
|
-
expect(hooks.mapProviderEvent('chat.message')).toBe('PromptSubmit');
|
|
89
|
-
});
|
|
90
|
-
it('maps event:session.idle to ResponseComplete', () => {
|
|
91
|
-
expect(hooks.mapProviderEvent('event:session.idle')).toBe('ResponseComplete');
|
|
92
|
-
});
|
|
93
|
-
it('maps tool.execute.before to PreToolUse', () => {
|
|
94
|
-
expect(hooks.mapProviderEvent('tool.execute.before')).toBe('PreToolUse');
|
|
95
|
-
});
|
|
96
|
-
it('maps tool.execute.after to PostToolUse', () => {
|
|
97
|
-
expect(hooks.mapProviderEvent('tool.execute.after')).toBe('PostToolUse');
|
|
98
|
-
});
|
|
99
|
-
it('maps permission.ask to PermissionRequest', () => {
|
|
100
|
-
expect(hooks.mapProviderEvent('permission.ask')).toBe('PermissionRequest');
|
|
101
|
-
});
|
|
102
|
-
it('maps chat.params to PreModel', () => {
|
|
103
|
-
expect(hooks.mapProviderEvent('chat.params')).toBe('PreModel');
|
|
104
|
-
});
|
|
105
|
-
it('maps experimental.session.compacting to PreCompact', () => {
|
|
106
|
-
expect(hooks.mapProviderEvent('experimental.session.compacting')).toBe('PreCompact');
|
|
107
|
-
});
|
|
108
|
-
it('maps event:session.compacted to PostCompact', () => {
|
|
109
|
-
expect(hooks.mapProviderEvent('event:session.compacted')).toBe('PostCompact');
|
|
110
|
-
});
|
|
111
|
-
it('returns null for unknown events', () => {
|
|
112
|
-
expect(hooks.mapProviderEvent('UnknownEvent')).toBeNull();
|
|
113
|
-
expect(hooks.mapProviderEvent('')).toBeNull();
|
|
114
|
-
});
|
|
115
|
-
it('tracks registration state', async () => {
|
|
116
|
-
expect(hooks.isRegistered()).toBe(false);
|
|
117
|
-
await hooks.registerNativeHooks('/tmp/test');
|
|
118
|
-
expect(hooks.isRegistered()).toBe(true);
|
|
119
|
-
await hooks.unregisterNativeHooks();
|
|
120
|
-
expect(hooks.isRegistered()).toBe(false);
|
|
121
|
-
});
|
|
122
|
-
it('exposes event map with 10 entries', () => {
|
|
123
|
-
const map = hooks.getEventMap();
|
|
124
|
-
expect(Object.keys(map)).toHaveLength(10);
|
|
125
|
-
expect(map['event:session.created']).toBe('SessionStart');
|
|
126
|
-
expect(map['tool.execute.after']).toBe('PostToolUse');
|
|
127
|
-
expect(map['chat.message']).toBe('PromptSubmit');
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
describe('OpenCodeSpawnProvider', () => {
|
|
131
|
-
let spawn;
|
|
132
|
-
beforeEach(() => {
|
|
133
|
-
spawn = new OpenCodeSpawnProvider();
|
|
134
|
-
});
|
|
135
|
-
it('canSpawn returns boolean', async () => {
|
|
136
|
-
const result = await spawn.canSpawn();
|
|
137
|
-
expect(typeof result).toBe('boolean');
|
|
138
|
-
});
|
|
139
|
-
it('listRunning returns empty array initially', async () => {
|
|
140
|
-
const running = await spawn.listRunning();
|
|
141
|
-
expect(running).toEqual([]);
|
|
142
|
-
});
|
|
143
|
-
it('terminate is no-op for unknown instance', async () => {
|
|
144
|
-
await expect(spawn.terminate('nonexistent')).resolves.toBeUndefined();
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
describe('OpenCodeInstallProvider', () => {
|
|
148
|
-
let install;
|
|
149
|
-
let testDir;
|
|
150
|
-
beforeEach(() => {
|
|
151
|
-
install = new OpenCodeInstallProvider();
|
|
152
|
-
testDir = join(tmpdir(), `cleo-opencode-test-${Date.now()}`);
|
|
153
|
-
mkdirSync(testDir, { recursive: true });
|
|
154
|
-
});
|
|
155
|
-
afterEach(() => {
|
|
156
|
-
try {
|
|
157
|
-
rmSync(testDir, { recursive: true, force: true });
|
|
158
|
-
}
|
|
159
|
-
catch {
|
|
160
|
-
// cleanup best-effort
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
it('creates AGENTS.md with @-references', async () => {
|
|
164
|
-
await install.ensureInstructionReferences(testDir);
|
|
165
|
-
const content = readFileSync(join(testDir, 'AGENTS.md'), 'utf-8');
|
|
166
|
-
expect(content).toContain('@~/.cleo/templates/CLEO-INJECTION.md');
|
|
167
|
-
expect(content).toContain('@.cleo/memory-bridge.md');
|
|
168
|
-
});
|
|
169
|
-
it('appends missing references to existing AGENTS.md', async () => {
|
|
170
|
-
const existing = '# Project Agents\n\nSome content.\n';
|
|
171
|
-
writeFileSync(join(testDir, 'AGENTS.md'), existing, 'utf-8');
|
|
172
|
-
await install.ensureInstructionReferences(testDir);
|
|
173
|
-
const content = readFileSync(join(testDir, 'AGENTS.md'), 'utf-8');
|
|
174
|
-
expect(content).toContain('# Project Agents');
|
|
175
|
-
expect(content).toContain('@~/.cleo/templates/CLEO-INJECTION.md');
|
|
176
|
-
expect(content).toContain('@.cleo/memory-bridge.md');
|
|
177
|
-
});
|
|
178
|
-
it('does not duplicate existing references', async () => {
|
|
179
|
-
const existing = '@~/.cleo/templates/CLEO-INJECTION.md\n@.cleo/memory-bridge.md\n';
|
|
180
|
-
writeFileSync(join(testDir, 'AGENTS.md'), existing, 'utf-8');
|
|
181
|
-
await install.ensureInstructionReferences(testDir);
|
|
182
|
-
const content = readFileSync(join(testDir, 'AGENTS.md'), 'utf-8');
|
|
183
|
-
const injectionCount = content.split('@~/.cleo/templates/CLEO-INJECTION.md').length - 1;
|
|
184
|
-
expect(injectionCount).toBe(1);
|
|
185
|
-
});
|
|
186
|
-
it('install returns mcpRegistered false', async () => {
|
|
187
|
-
const result = await install.install({
|
|
188
|
-
projectDir: testDir,
|
|
189
|
-
});
|
|
190
|
-
expect(result.success).toBe(true);
|
|
191
|
-
expect(result.mcpRegistered).toBe(false);
|
|
192
|
-
expect(result.instructionFileUpdated).toBe(true);
|
|
193
|
-
});
|
|
194
|
-
it('uninstall is a no-op', async () => {
|
|
195
|
-
await expect(install.uninstall()).resolves.toBeUndefined();
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
describe('createAdapter factory', () => {
|
|
199
|
-
it('returns an OpenCodeAdapter instance', () => {
|
|
200
|
-
const adapter = createAdapter();
|
|
201
|
-
expect(adapter).toBeInstanceOf(OpenCodeAdapter);
|
|
202
|
-
expect(adapter.id).toBe('opencode');
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
//# sourceMappingURL=opencode-adapter.test.js.map
|