@cleocode/adapters 2026.9.7 → 2026.9.9
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/dist/index.js +1894 -942
- package/dist/index.js.map +2 -2
- package/package.json +5 -5
- package/src/__tests__/claude-code-adapter.test.ts +22 -11
- package/src/__tests__/cursor-adapter.test.ts +11 -1
- package/src/__tests__/opencode-adapter.test.ts +20 -9
- package/src/providers/claude-code/__tests__/hooks-install.test.ts +6 -1
- package/src/providers/cursor/__tests__/hooks-install.test.ts +12 -2
- package/src/providers/opencode/__tests__/hooks-install.test.ts +12 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cleocode/adapters",
|
|
3
|
-
"version": "2026.9.
|
|
3
|
+
"version": "2026.9.9",
|
|
4
4
|
"description": "Unified provider adapters for CLEO (Claude Code, OpenCode, Cursor)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
"@ai-sdk/anthropic": "^3.0.69",
|
|
16
16
|
"@ai-sdk/openai": "^2.0.53",
|
|
17
17
|
"ai": "^6.0.168",
|
|
18
|
-
"@cleocode/
|
|
19
|
-
"@cleocode/
|
|
20
|
-
"@cleocode/contracts": "2026.9.
|
|
18
|
+
"@cleocode/paths": "2026.9.9",
|
|
19
|
+
"@cleocode/caamp": "2026.9.9",
|
|
20
|
+
"@cleocode/contracts": "2026.9.9"
|
|
21
21
|
},
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"engines": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/node": "^24.3.0",
|
|
32
32
|
"vitest": "^4.1.4",
|
|
33
|
-
"@cleocode/playbooks": "2026.9.
|
|
33
|
+
"@cleocode/playbooks": "2026.9.9"
|
|
34
34
|
},
|
|
35
35
|
"repository": {
|
|
36
36
|
"type": "git",
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
ClaudeCodeSpawnProvider,
|
|
18
18
|
createClaudeCodeAdapter as createAdapter,
|
|
19
19
|
} from '@cleocode/adapters';
|
|
20
|
-
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
20
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
21
21
|
|
|
22
22
|
describe('ClaudeCodeAdapter — integration', () => {
|
|
23
23
|
let adapter: ClaudeCodeAdapter;
|
|
@@ -155,9 +155,19 @@ describe('ClaudeCodeInstallProvider — integration', () => {
|
|
|
155
155
|
install = new ClaudeCodeInstallProvider();
|
|
156
156
|
testDir = join(tmpdir(), `cleo-adapter-test-${Date.now()}`);
|
|
157
157
|
mkdirSync(testDir, { recursive: true });
|
|
158
|
+
const fixtureHome = join(testDir, 'fixture-home');
|
|
159
|
+
vi.stubEnv('HOME', fixtureHome);
|
|
160
|
+
vi.stubEnv('USERPROFILE', fixtureHome);
|
|
161
|
+
vi.stubEnv('CLEO_HOME', join(fixtureHome, '.cleo'));
|
|
162
|
+
mkdirSync(join(fixtureHome, '.cleo', 'templates'), { recursive: true });
|
|
163
|
+
writeFileSync(
|
|
164
|
+
join(fixtureHome, '.cleo', 'templates', 'CLEO-INJECTION.md'),
|
|
165
|
+
'Fixture protocol: inspect authority and coverage.',
|
|
166
|
+
);
|
|
158
167
|
});
|
|
159
168
|
|
|
160
169
|
afterEach(() => {
|
|
170
|
+
vi.unstubAllEnvs();
|
|
161
171
|
try {
|
|
162
172
|
rmSync(testDir, { recursive: true, force: true });
|
|
163
173
|
} catch {
|
|
@@ -165,15 +175,15 @@ describe('ClaudeCodeInstallProvider — integration', () => {
|
|
|
165
175
|
}
|
|
166
176
|
});
|
|
167
177
|
|
|
168
|
-
it('creates CLAUDE.md with
|
|
178
|
+
it('creates CLAUDE.md with embedded protocol', async () => {
|
|
169
179
|
await install.ensureInstructionReferences(testDir);
|
|
170
180
|
const content = readFileSync(join(testDir, 'CLAUDE.md'), 'utf-8');
|
|
171
|
-
|
|
172
|
-
expect(content).
|
|
173
|
-
expect(content).toContain('@.cleo/memory-bridge.md');
|
|
181
|
+
expect(content).toContain('Fixture protocol: inspect authority and coverage.');
|
|
182
|
+
expect(content).toContain('Project memory bridge unavailable.');
|
|
183
|
+
expect(content).not.toContain('@.cleo/memory-bridge.md');
|
|
174
184
|
});
|
|
175
185
|
|
|
176
|
-
it('
|
|
186
|
+
it('embeds protocol while preserving existing CLAUDE.md', async () => {
|
|
177
187
|
const existing = '# Project\n@AGENTS.md\n';
|
|
178
188
|
writeFileSync(join(testDir, 'CLAUDE.md'), existing, 'utf-8');
|
|
179
189
|
|
|
@@ -181,23 +191,24 @@ describe('ClaudeCodeInstallProvider — integration', () => {
|
|
|
181
191
|
const content = readFileSync(join(testDir, 'CLAUDE.md'), 'utf-8');
|
|
182
192
|
expect(content).toContain('# Project');
|
|
183
193
|
expect(content).toContain('@AGENTS.md');
|
|
184
|
-
|
|
185
|
-
expect(content).
|
|
186
|
-
expect(content).toContain('@.cleo/memory-bridge.md');
|
|
194
|
+
expect(content).toContain('Fixture protocol: inspect authority and coverage.');
|
|
195
|
+
expect(content).toContain('Project memory bridge unavailable.');
|
|
196
|
+
expect(content).not.toContain('@.cleo/memory-bridge.md');
|
|
187
197
|
});
|
|
188
198
|
|
|
189
199
|
it('is idempotent — calling twice does not duplicate the CAAMP block', async () => {
|
|
190
200
|
// First call creates the CAAMP-managed block
|
|
191
201
|
await install.ensureInstructionReferences(testDir);
|
|
192
202
|
const firstContent = readFileSync(join(testDir, 'CLAUDE.md'), 'utf-8');
|
|
193
|
-
const firstCount = (firstContent.match(
|
|
203
|
+
const firstCount = (firstContent.match(/<!-- CAAMP:START -->/g) ?? []).length;
|
|
194
204
|
expect(firstCount).toBe(1);
|
|
195
205
|
|
|
196
206
|
// Second call must be idempotent — CAAMP detects existing block and returns 'intact'
|
|
197
207
|
await install.ensureInstructionReferences(testDir);
|
|
198
208
|
const secondContent = readFileSync(join(testDir, 'CLAUDE.md'), 'utf-8');
|
|
199
|
-
const secondCount = (secondContent.match(
|
|
209
|
+
const secondCount = (secondContent.match(/<!-- CAAMP:START -->/g) ?? []).length;
|
|
200
210
|
expect(secondCount).toBe(1);
|
|
211
|
+
expect(secondContent).toBe(firstContent);
|
|
201
212
|
});
|
|
202
213
|
|
|
203
214
|
it('install returns expected shape', async () => {
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
CursorInstallProvider,
|
|
17
17
|
createCursorAdapter as createAdapter,
|
|
18
18
|
} from '@cleocode/adapters';
|
|
19
|
-
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
19
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
20
20
|
|
|
21
21
|
describe('CursorAdapter — integration', () => {
|
|
22
22
|
let adapter: CursorAdapter;
|
|
@@ -138,9 +138,19 @@ describe('CursorInstallProvider — integration', () => {
|
|
|
138
138
|
install = new CursorInstallProvider();
|
|
139
139
|
testDir = join(tmpdir(), `cleo-cursor-test-${Date.now()}`);
|
|
140
140
|
mkdirSync(testDir, { recursive: true });
|
|
141
|
+
const fixtureHome = join(testDir, 'fixture-home');
|
|
142
|
+
vi.stubEnv('HOME', fixtureHome);
|
|
143
|
+
vi.stubEnv('USERPROFILE', fixtureHome);
|
|
144
|
+
vi.stubEnv('CLEO_HOME', join(fixtureHome, '.cleo'));
|
|
145
|
+
mkdirSync(join(fixtureHome, '.cleo', 'templates'), { recursive: true });
|
|
146
|
+
writeFileSync(
|
|
147
|
+
join(fixtureHome, '.cleo', 'templates', 'CLEO-INJECTION.md'),
|
|
148
|
+
'Fixture protocol: inspect authority and coverage.',
|
|
149
|
+
);
|
|
141
150
|
});
|
|
142
151
|
|
|
143
152
|
afterEach(() => {
|
|
153
|
+
vi.unstubAllEnvs();
|
|
144
154
|
try {
|
|
145
155
|
rmSync(testDir, { recursive: true, force: true });
|
|
146
156
|
} catch {
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
OpenCodeInstallProvider,
|
|
18
18
|
OpenCodeSpawnProvider,
|
|
19
19
|
} from '@cleocode/adapters';
|
|
20
|
-
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
20
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
21
21
|
|
|
22
22
|
describe('OpenCodeAdapter — integration', () => {
|
|
23
23
|
let adapter: OpenCodeAdapter;
|
|
@@ -189,9 +189,19 @@ describe('OpenCodeInstallProvider — integration', () => {
|
|
|
189
189
|
install = new OpenCodeInstallProvider();
|
|
190
190
|
testDir = join(tmpdir(), `cleo-opencode-test-${Date.now()}`);
|
|
191
191
|
mkdirSync(testDir, { recursive: true });
|
|
192
|
+
const fixtureHome = join(testDir, 'fixture-home');
|
|
193
|
+
vi.stubEnv('HOME', fixtureHome);
|
|
194
|
+
vi.stubEnv('USERPROFILE', fixtureHome);
|
|
195
|
+
vi.stubEnv('CLEO_HOME', join(fixtureHome, '.cleo'));
|
|
196
|
+
mkdirSync(join(fixtureHome, '.cleo', 'templates'), { recursive: true });
|
|
197
|
+
writeFileSync(
|
|
198
|
+
join(fixtureHome, '.cleo', 'templates', 'CLEO-INJECTION.md'),
|
|
199
|
+
'Fixture protocol: inspect authority and coverage.',
|
|
200
|
+
);
|
|
192
201
|
});
|
|
193
202
|
|
|
194
203
|
afterEach(() => {
|
|
204
|
+
vi.unstubAllEnvs();
|
|
195
205
|
try {
|
|
196
206
|
rmSync(testDir, { recursive: true, force: true });
|
|
197
207
|
} catch {
|
|
@@ -199,24 +209,24 @@ describe('OpenCodeInstallProvider — integration', () => {
|
|
|
199
209
|
}
|
|
200
210
|
});
|
|
201
211
|
|
|
202
|
-
it('creates AGENTS.md with
|
|
212
|
+
it('creates AGENTS.md with embedded protocol', async () => {
|
|
203
213
|
await install.ensureInstructionReferences(testDir);
|
|
204
214
|
const content = readFileSync(join(testDir, 'AGENTS.md'), 'utf-8');
|
|
205
|
-
|
|
206
|
-
expect(content).
|
|
207
|
-
expect(content).toContain('@.cleo/memory-bridge.md');
|
|
215
|
+
expect(content).toContain('Fixture protocol: inspect authority and coverage.');
|
|
216
|
+
expect(content).toContain('Project memory bridge unavailable.');
|
|
217
|
+
expect(content).not.toContain('@.cleo/memory-bridge.md');
|
|
208
218
|
});
|
|
209
219
|
|
|
210
|
-
it('
|
|
220
|
+
it('embeds protocol while preserving existing AGENTS.md', async () => {
|
|
211
221
|
const existing = '# Project Agents\n\nSome content.\n';
|
|
212
222
|
writeFileSync(join(testDir, 'AGENTS.md'), existing, 'utf-8');
|
|
213
223
|
|
|
214
224
|
await install.ensureInstructionReferences(testDir);
|
|
215
225
|
const content = readFileSync(join(testDir, 'AGENTS.md'), 'utf-8');
|
|
216
226
|
expect(content).toContain('# Project Agents');
|
|
217
|
-
|
|
218
|
-
expect(content).
|
|
219
|
-
expect(content).toContain('@.cleo/memory-bridge.md');
|
|
227
|
+
expect(content).toContain('Fixture protocol: inspect authority and coverage.');
|
|
228
|
+
expect(content).toContain('Project memory bridge unavailable.');
|
|
229
|
+
expect(content).not.toContain('@.cleo/memory-bridge.md');
|
|
220
230
|
});
|
|
221
231
|
|
|
222
232
|
it('does not duplicate CAAMP block on repeated calls', async () => {
|
|
@@ -231,6 +241,7 @@ describe('OpenCodeInstallProvider — integration', () => {
|
|
|
231
241
|
const afterSecond = readFileSync(join(testDir, 'AGENTS.md'), 'utf-8');
|
|
232
242
|
const blockCountSecond = (afterSecond.match(/<!-- CAAMP:START -->/g) ?? []).length;
|
|
233
243
|
expect(blockCountSecond).toBe(1);
|
|
244
|
+
expect(afterSecond).toBe(afterFirst);
|
|
234
245
|
});
|
|
235
246
|
|
|
236
247
|
it('install returns expected shape', async () => {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* @epic T1000
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import { mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
|
20
|
+
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
21
21
|
import { tmpdir } from 'node:os';
|
|
22
22
|
import { join } from 'node:path';
|
|
23
23
|
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
@@ -39,6 +39,11 @@ describe('ClaudeCodeInstallProvider — PreCompact hook templates', () => {
|
|
|
39
39
|
process.env.HOME = fakeHome;
|
|
40
40
|
process.env.USERPROFILE = fakeHome;
|
|
41
41
|
process.env.CLAUDE_HOME = join(fakeHome, '.claude');
|
|
42
|
+
mkdirSync(join(fakeHome, '.cleo', 'templates'), { recursive: true });
|
|
43
|
+
writeFileSync(
|
|
44
|
+
join(fakeHome, '.cleo', 'templates', 'CLEO-INJECTION.md'),
|
|
45
|
+
'Fixture protocol: inspect authority and coverage.',
|
|
46
|
+
);
|
|
42
47
|
});
|
|
43
48
|
|
|
44
49
|
afterEach(() => {
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
* @epic T1000
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import { mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
|
18
|
+
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
19
19
|
import { tmpdir } from 'node:os';
|
|
20
20
|
import { join } from 'node:path';
|
|
21
|
-
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
21
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
22
22
|
import { CursorInstallProvider } from '../install.js';
|
|
23
23
|
|
|
24
24
|
describe('CursorInstallProvider — PreCompact hook templates', () => {
|
|
@@ -26,9 +26,19 @@ describe('CursorInstallProvider — PreCompact hook templates', () => {
|
|
|
26
26
|
|
|
27
27
|
beforeEach(() => {
|
|
28
28
|
projectDir = mkdtempSync(join(tmpdir(), 'cleo-cursor-install-'));
|
|
29
|
+
const fixtureHome = join(projectDir, 'fixture-home');
|
|
30
|
+
vi.stubEnv('HOME', fixtureHome);
|
|
31
|
+
vi.stubEnv('USERPROFILE', fixtureHome);
|
|
32
|
+
vi.stubEnv('CLEO_HOME', join(fixtureHome, '.cleo'));
|
|
33
|
+
mkdirSync(join(fixtureHome, '.cleo', 'templates'), { recursive: true });
|
|
34
|
+
writeFileSync(
|
|
35
|
+
join(fixtureHome, '.cleo', 'templates', 'CLEO-INJECTION.md'),
|
|
36
|
+
'Fixture protocol: inspect authority and coverage.',
|
|
37
|
+
);
|
|
29
38
|
});
|
|
30
39
|
|
|
31
40
|
afterEach(() => {
|
|
41
|
+
vi.unstubAllEnvs();
|
|
32
42
|
rmSync(projectDir, { recursive: true, force: true });
|
|
33
43
|
});
|
|
34
44
|
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
* @epic T1000
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
|
16
|
+
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
17
17
|
import { tmpdir } from 'node:os';
|
|
18
18
|
import { join } from 'node:path';
|
|
19
|
-
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
19
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
20
20
|
import { OpenCodeInstallProvider } from '../install.js';
|
|
21
21
|
|
|
22
22
|
describe('OpenCodeInstallProvider — PreCompact hook templates', () => {
|
|
@@ -24,9 +24,19 @@ describe('OpenCodeInstallProvider — PreCompact hook templates', () => {
|
|
|
24
24
|
|
|
25
25
|
beforeEach(() => {
|
|
26
26
|
projectDir = mkdtempSync(join(tmpdir(), 'cleo-opencode-install-'));
|
|
27
|
+
const fixtureHome = join(projectDir, 'fixture-home');
|
|
28
|
+
vi.stubEnv('HOME', fixtureHome);
|
|
29
|
+
vi.stubEnv('USERPROFILE', fixtureHome);
|
|
30
|
+
vi.stubEnv('CLEO_HOME', join(fixtureHome, '.cleo'));
|
|
31
|
+
mkdirSync(join(fixtureHome, '.cleo', 'templates'), { recursive: true });
|
|
32
|
+
writeFileSync(
|
|
33
|
+
join(fixtureHome, '.cleo', 'templates', 'CLEO-INJECTION.md'),
|
|
34
|
+
'Fixture protocol: inspect authority and coverage.',
|
|
35
|
+
);
|
|
27
36
|
});
|
|
28
37
|
|
|
29
38
|
afterEach(() => {
|
|
39
|
+
vi.unstubAllEnvs();
|
|
30
40
|
rmSync(projectDir, { recursive: true, force: true });
|
|
31
41
|
});
|
|
32
42
|
|