@cleocode/adapters 2.0.0
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.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1927 -0
- package/dist/index.js.map +7 -0
- package/dist/providers/claude-code/adapter.d.ts +75 -0
- package/dist/providers/claude-code/adapter.d.ts.map +1 -0
- package/dist/providers/claude-code/adapter.js +154 -0
- package/dist/providers/claude-code/adapter.js.map +1 -0
- package/dist/providers/claude-code/context-monitor.d.ts +24 -0
- package/dist/providers/claude-code/context-monitor.d.ts.map +1 -0
- package/dist/providers/claude-code/context-monitor.js +148 -0
- package/dist/providers/claude-code/context-monitor.js.map +1 -0
- package/dist/providers/claude-code/hooks.d.ts +59 -0
- package/dist/providers/claude-code/hooks.d.ts.map +1 -0
- package/dist/providers/claude-code/hooks.js +77 -0
- package/dist/providers/claude-code/hooks.js.map +1 -0
- package/dist/providers/claude-code/index.d.ts +24 -0
- package/dist/providers/claude-code/index.d.ts.map +1 -0
- package/dist/providers/claude-code/index.js +26 -0
- package/dist/providers/claude-code/index.js.map +1 -0
- package/dist/providers/claude-code/install.d.ts +75 -0
- package/dist/providers/claude-code/install.d.ts.map +1 -0
- package/dist/providers/claude-code/install.js +237 -0
- package/dist/providers/claude-code/install.js.map +1 -0
- package/dist/providers/claude-code/paths.d.ts +24 -0
- package/dist/providers/claude-code/paths.d.ts.map +1 -0
- package/dist/providers/claude-code/paths.js +33 -0
- package/dist/providers/claude-code/paths.js.map +1 -0
- package/dist/providers/claude-code/spawn.d.ts +60 -0
- package/dist/providers/claude-code/spawn.d.ts.map +1 -0
- package/dist/providers/claude-code/spawn.js +160 -0
- package/dist/providers/claude-code/spawn.js.map +1 -0
- package/dist/providers/claude-code/statusline.d.ts +24 -0
- package/dist/providers/claude-code/statusline.d.ts.map +1 -0
- package/dist/providers/claude-code/statusline.js +85 -0
- package/dist/providers/claude-code/statusline.js.map +1 -0
- package/dist/providers/claude-code/task-sync.d.ts +27 -0
- package/dist/providers/claude-code/task-sync.d.ts.map +1 -0
- package/dist/providers/claude-code/task-sync.js +124 -0
- package/dist/providers/claude-code/task-sync.js.map +1 -0
- package/dist/providers/claude-code/transport.d.ts +14 -0
- package/dist/providers/claude-code/transport.d.ts.map +1 -0
- package/dist/providers/claude-code/transport.js +18 -0
- package/dist/providers/claude-code/transport.js.map +1 -0
- package/dist/providers/cursor/adapter.d.ts +62 -0
- package/dist/providers/cursor/adapter.d.ts.map +1 -0
- package/dist/providers/cursor/adapter.js +124 -0
- package/dist/providers/cursor/adapter.js.map +1 -0
- package/dist/providers/cursor/hooks.d.ts +48 -0
- package/dist/providers/cursor/hooks.d.ts.map +1 -0
- package/dist/providers/cursor/hooks.js +55 -0
- package/dist/providers/cursor/hooks.js.map +1 -0
- package/dist/providers/cursor/index.d.ts +19 -0
- package/dist/providers/cursor/index.d.ts.map +1 -0
- package/dist/providers/cursor/index.js +21 -0
- package/dist/providers/cursor/index.js.map +1 -0
- package/dist/providers/cursor/install.d.ts +94 -0
- package/dist/providers/cursor/install.d.ts.map +1 -0
- package/dist/providers/cursor/install.js +241 -0
- package/dist/providers/cursor/install.js.map +1 -0
- package/dist/providers/cursor/spawn.d.ts +50 -0
- package/dist/providers/cursor/spawn.d.ts.map +1 -0
- package/dist/providers/cursor/spawn.js +59 -0
- package/dist/providers/cursor/spawn.js.map +1 -0
- package/dist/providers/opencode/adapter.d.ts +67 -0
- package/dist/providers/opencode/adapter.d.ts.map +1 -0
- package/dist/providers/opencode/adapter.js +144 -0
- package/dist/providers/opencode/adapter.js.map +1 -0
- package/dist/providers/opencode/hooks.d.ts +66 -0
- package/dist/providers/opencode/hooks.d.ts.map +1 -0
- package/dist/providers/opencode/hooks.js +89 -0
- package/dist/providers/opencode/hooks.js.map +1 -0
- package/dist/providers/opencode/index.d.ts +20 -0
- package/dist/providers/opencode/index.d.ts.map +1 -0
- package/dist/providers/opencode/index.js +22 -0
- package/dist/providers/opencode/index.js.map +1 -0
- package/dist/providers/opencode/install.d.ts +65 -0
- package/dist/providers/opencode/install.d.ts.map +1 -0
- package/dist/providers/opencode/install.js +183 -0
- package/dist/providers/opencode/install.js.map +1 -0
- package/dist/providers/opencode/spawn.d.ts +72 -0
- package/dist/providers/opencode/spawn.d.ts.map +1 -0
- package/dist/providers/opencode/spawn.js +219 -0
- package/dist/providers/opencode/spawn.js.map +1 -0
- package/dist/registry.d.ts +36 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +55 -0
- package/dist/registry.js.map +1 -0
- package/package.json +32 -0
- package/src/index.d.ts +27 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.js +28 -0
- package/src/index.js.map +1 -0
- package/src/index.ts +37 -0
- package/src/providers/claude-code/__tests__/adapter.test.d.ts +7 -0
- package/src/providers/claude-code/__tests__/adapter.test.d.ts.map +1 -0
- package/src/providers/claude-code/__tests__/adapter.test.js +249 -0
- package/src/providers/claude-code/__tests__/adapter.test.js.map +1 -0
- package/src/providers/claude-code/__tests__/adapter.test.ts +291 -0
- package/src/providers/claude-code/adapter.d.ts +75 -0
- package/src/providers/claude-code/adapter.d.ts.map +1 -0
- package/src/providers/claude-code/adapter.js +154 -0
- package/src/providers/claude-code/adapter.js.map +1 -0
- package/src/providers/claude-code/adapter.ts +175 -0
- package/src/providers/claude-code/context-monitor.d.ts +24 -0
- package/src/providers/claude-code/context-monitor.d.ts.map +1 -0
- package/src/providers/claude-code/context-monitor.js +148 -0
- package/src/providers/claude-code/context-monitor.js.map +1 -0
- package/src/providers/claude-code/context-monitor.ts +175 -0
- package/src/providers/claude-code/hooks.d.ts +59 -0
- package/src/providers/claude-code/hooks.d.ts.map +1 -0
- package/src/providers/claude-code/hooks.js +77 -0
- package/src/providers/claude-code/hooks.js.map +1 -0
- package/src/providers/claude-code/hooks.ts +85 -0
- package/src/providers/claude-code/index.d.ts +24 -0
- package/src/providers/claude-code/index.d.ts.map +1 -0
- package/src/providers/claude-code/index.js +26 -0
- package/src/providers/claude-code/index.js.map +1 -0
- package/src/providers/claude-code/index.ts +33 -0
- package/src/providers/claude-code/install.d.ts +75 -0
- package/src/providers/claude-code/install.d.ts.map +1 -0
- package/src/providers/claude-code/install.js +237 -0
- package/src/providers/claude-code/install.js.map +1 -0
- package/src/providers/claude-code/install.ts +267 -0
- package/src/providers/claude-code/manifest.json +26 -0
- package/src/providers/claude-code/paths.d.ts +24 -0
- package/src/providers/claude-code/paths.d.ts.map +1 -0
- package/src/providers/claude-code/paths.js +33 -0
- package/src/providers/claude-code/paths.js.map +1 -0
- package/src/providers/claude-code/paths.ts +38 -0
- package/src/providers/claude-code/spawn.d.ts +60 -0
- package/src/providers/claude-code/spawn.d.ts.map +1 -0
- package/src/providers/claude-code/spawn.js +160 -0
- package/src/providers/claude-code/spawn.js.map +1 -0
- package/src/providers/claude-code/spawn.ts +178 -0
- package/src/providers/claude-code/statusline.d.ts +24 -0
- package/src/providers/claude-code/statusline.d.ts.map +1 -0
- package/src/providers/claude-code/statusline.js +85 -0
- package/src/providers/claude-code/statusline.js.map +1 -0
- package/src/providers/claude-code/statusline.ts +99 -0
- package/src/providers/claude-code/task-sync.d.ts +27 -0
- package/src/providers/claude-code/task-sync.d.ts.map +1 -0
- package/src/providers/claude-code/task-sync.js +124 -0
- package/src/providers/claude-code/task-sync.js.map +1 -0
- package/src/providers/claude-code/task-sync.ts +158 -0
- package/src/providers/claude-code/transport.d.ts +14 -0
- package/src/providers/claude-code/transport.d.ts.map +1 -0
- package/src/providers/claude-code/transport.js +18 -0
- package/src/providers/claude-code/transport.js.map +1 -0
- package/src/providers/claude-code/transport.ts +21 -0
- package/src/providers/cursor/__tests__/adapter.test.d.ts +7 -0
- package/src/providers/cursor/__tests__/adapter.test.d.ts.map +1 -0
- package/src/providers/cursor/__tests__/adapter.test.js +246 -0
- package/src/providers/cursor/__tests__/adapter.test.js.map +1 -0
- package/src/providers/cursor/__tests__/adapter.test.ts +291 -0
- package/src/providers/cursor/adapter.d.ts +62 -0
- package/src/providers/cursor/adapter.d.ts.map +1 -0
- package/src/providers/cursor/adapter.js +124 -0
- package/src/providers/cursor/adapter.js.map +1 -0
- package/src/providers/cursor/adapter.ts +145 -0
- package/src/providers/cursor/hooks.d.ts +48 -0
- package/src/providers/cursor/hooks.d.ts.map +1 -0
- package/src/providers/cursor/hooks.js +55 -0
- package/src/providers/cursor/hooks.js.map +1 -0
- package/src/providers/cursor/hooks.ts +61 -0
- package/src/providers/cursor/index.d.ts +19 -0
- package/src/providers/cursor/index.d.ts.map +1 -0
- package/src/providers/cursor/index.js +21 -0
- package/src/providers/cursor/index.js.map +1 -0
- package/src/providers/cursor/index.ts +24 -0
- package/src/providers/cursor/install.d.ts +94 -0
- package/src/providers/cursor/install.d.ts.map +1 -0
- package/src/providers/cursor/install.js +241 -0
- package/src/providers/cursor/install.js.map +1 -0
- package/src/providers/cursor/install.ts +271 -0
- package/src/providers/cursor/manifest.json +26 -0
- package/src/providers/cursor/spawn.d.ts +50 -0
- package/src/providers/cursor/spawn.d.ts.map +1 -0
- package/src/providers/cursor/spawn.js +59 -0
- package/src/providers/cursor/spawn.js.map +1 -0
- package/src/providers/cursor/spawn.ts +66 -0
- package/src/providers/opencode/__tests__/adapter.test.d.ts +7 -0
- package/src/providers/opencode/__tests__/adapter.test.d.ts.map +1 -0
- package/src/providers/opencode/__tests__/adapter.test.js +263 -0
- package/src/providers/opencode/__tests__/adapter.test.js.map +1 -0
- package/src/providers/opencode/__tests__/adapter.test.ts +309 -0
- package/src/providers/opencode/adapter.d.ts +67 -0
- package/src/providers/opencode/adapter.d.ts.map +1 -0
- package/src/providers/opencode/adapter.js +144 -0
- package/src/providers/opencode/adapter.js.map +1 -0
- package/src/providers/opencode/adapter.ts +165 -0
- package/src/providers/opencode/hooks.d.ts +66 -0
- package/src/providers/opencode/hooks.d.ts.map +1 -0
- package/src/providers/opencode/hooks.js +89 -0
- package/src/providers/opencode/hooks.js.map +1 -0
- package/src/providers/opencode/hooks.ts +97 -0
- package/src/providers/opencode/index.d.ts +20 -0
- package/src/providers/opencode/index.d.ts.map +1 -0
- package/src/providers/opencode/index.js +22 -0
- package/src/providers/opencode/index.js.map +1 -0
- package/src/providers/opencode/index.ts +25 -0
- package/src/providers/opencode/install.d.ts +65 -0
- package/src/providers/opencode/install.d.ts.map +1 -0
- package/src/providers/opencode/install.js +183 -0
- package/src/providers/opencode/install.js.map +1 -0
- package/src/providers/opencode/install.ts +206 -0
- package/src/providers/opencode/manifest.json +26 -0
- package/src/providers/opencode/spawn.d.ts +72 -0
- package/src/providers/opencode/spawn.d.ts.map +1 -0
- package/src/providers/opencode/spawn.js +219 -0
- package/src/providers/opencode/spawn.js.map +1 -0
- package/src/providers/opencode/spawn.ts +253 -0
- package/src/registry.d.ts +36 -0
- package/src/registry.d.ts.map +1 -0
- package/src/registry.js +55 -0
- package/src/registry.js.map +1 -0
- package/src/registry.ts +81 -0
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the Cursor adapter package.
|
|
3
|
+
*
|
|
4
|
+
* @task T5240
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
8
|
+
import { CursorAdapter } from '../adapter.js';
|
|
9
|
+
import { CursorHookProvider } from '../hooks.js';
|
|
10
|
+
import { CursorSpawnProvider } from '../spawn.js'; // spawn.ts still exists for direct use
|
|
11
|
+
import { CursorInstallProvider } from '../install.js';
|
|
12
|
+
|
|
13
|
+
vi.mock('node:fs', async (importOriginal) => {
|
|
14
|
+
const actual = await importOriginal<typeof import('node:fs')>();
|
|
15
|
+
return {
|
|
16
|
+
...actual,
|
|
17
|
+
existsSync: vi.fn((path: string) => {
|
|
18
|
+
if (typeof path === 'string' && path.includes('.cursor')) return true;
|
|
19
|
+
if (typeof path === 'string' && path.includes('.cursorrules')) return false;
|
|
20
|
+
return false;
|
|
21
|
+
}),
|
|
22
|
+
readFileSync: vi.fn((path: string) => {
|
|
23
|
+
if (typeof path === 'string' && path.includes('mcp.json')) {
|
|
24
|
+
return JSON.stringify({ mcpServers: { cleo: { command: 'node', args: ['mcp.js'] } } });
|
|
25
|
+
}
|
|
26
|
+
return '{}';
|
|
27
|
+
}),
|
|
28
|
+
writeFileSync: vi.fn(),
|
|
29
|
+
mkdirSync: vi.fn(),
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('CursorAdapter', () => {
|
|
34
|
+
let adapter: CursorAdapter;
|
|
35
|
+
|
|
36
|
+
beforeEach(() => {
|
|
37
|
+
adapter = new CursorAdapter();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
afterEach(async () => {
|
|
41
|
+
if (adapter.isInitialized()) {
|
|
42
|
+
await adapter.dispose();
|
|
43
|
+
}
|
|
44
|
+
vi.restoreAllMocks();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('identity', () => {
|
|
48
|
+
it('has correct id', () => {
|
|
49
|
+
expect(adapter.id).toBe('cursor');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('has correct name', () => {
|
|
53
|
+
expect(adapter.name).toBe('Cursor');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('has correct version', () => {
|
|
57
|
+
expect(adapter.version).toBe('1.0.0');
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('capabilities', () => {
|
|
62
|
+
it('does not support hooks', () => {
|
|
63
|
+
expect(adapter.capabilities.supportsHooks).toBe(false);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('has no supported hook events', () => {
|
|
67
|
+
expect(adapter.capabilities.supportedHookEvents).toHaveLength(0);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('does not support spawn', () => {
|
|
71
|
+
expect(adapter.capabilities.supportsSpawn).toBe(false);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('supports install', () => {
|
|
75
|
+
expect(adapter.capabilities.supportsInstall).toBe(true);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('supports MCP', () => {
|
|
79
|
+
expect(adapter.capabilities.supportsMcp).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('supports instruction files with MDC pattern', () => {
|
|
83
|
+
expect(adapter.capabilities.supportsInstructionFiles).toBe(true);
|
|
84
|
+
expect(adapter.capabilities.instructionFilePattern).toBe('.cursor/rules/*.mdc');
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe('sub-providers', () => {
|
|
89
|
+
it('provides a hook provider (stub)', () => {
|
|
90
|
+
expect(adapter.hooks).toBeInstanceOf(CursorHookProvider);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('provides an install provider', () => {
|
|
94
|
+
expect(adapter.install).toBeInstanceOf(CursorInstallProvider);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
describe('initialize', () => {
|
|
99
|
+
it('sets initialized state', async () => {
|
|
100
|
+
expect(adapter.isInitialized()).toBe(false);
|
|
101
|
+
await adapter.initialize('/tmp/test-project');
|
|
102
|
+
expect(adapter.isInitialized()).toBe(true);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('stores project directory', async () => {
|
|
106
|
+
await adapter.initialize('/tmp/test-project');
|
|
107
|
+
expect(adapter.getProjectDir()).toBe('/tmp/test-project');
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('dispose', () => {
|
|
112
|
+
it('resets initialized state', async () => {
|
|
113
|
+
await adapter.initialize('/tmp/test-project');
|
|
114
|
+
await adapter.dispose();
|
|
115
|
+
expect(adapter.isInitialized()).toBe(false);
|
|
116
|
+
expect(adapter.getProjectDir()).toBeNull();
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe('healthCheck', () => {
|
|
121
|
+
it('returns unhealthy when not initialized', async () => {
|
|
122
|
+
const status = await adapter.healthCheck();
|
|
123
|
+
expect(status.healthy).toBe(false);
|
|
124
|
+
expect(status.provider).toBe('cursor');
|
|
125
|
+
expect(status.details?.error).toBe('Adapter not initialized');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('returns health status with provider id', async () => {
|
|
129
|
+
await adapter.initialize('/tmp/test-project');
|
|
130
|
+
const status = await adapter.healthCheck();
|
|
131
|
+
expect(status.provider).toBe('cursor');
|
|
132
|
+
expect(typeof status.healthy).toBe('boolean');
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('checks for .cursor directory existence', async () => {
|
|
136
|
+
await adapter.initialize('/tmp/test-project');
|
|
137
|
+
const status = await adapter.healthCheck();
|
|
138
|
+
expect(status.details?.configDirExists).toBeDefined();
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('checks for CURSOR_EDITOR env var', async () => {
|
|
142
|
+
await adapter.initialize('/tmp/test-project');
|
|
143
|
+
const status = await adapter.healthCheck();
|
|
144
|
+
expect(status.details?.editorEnvSet).toBeDefined();
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
describe('CursorHookProvider', () => {
|
|
150
|
+
let hooks: CursorHookProvider;
|
|
151
|
+
|
|
152
|
+
beforeEach(() => {
|
|
153
|
+
hooks = new CursorHookProvider();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
describe('mapProviderEvent', () => {
|
|
157
|
+
it('returns null for any event (no hook support)', () => {
|
|
158
|
+
expect(hooks.mapProviderEvent('session.start')).toBeNull();
|
|
159
|
+
expect(hooks.mapProviderEvent('tool.complete')).toBeNull();
|
|
160
|
+
expect(hooks.mapProviderEvent('any-event')).toBeNull();
|
|
161
|
+
expect(hooks.mapProviderEvent('')).toBeNull();
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
describe('registerNativeHooks', () => {
|
|
166
|
+
it('completes without error and marks as registered', async () => {
|
|
167
|
+
expect(hooks.isRegistered()).toBe(false);
|
|
168
|
+
await hooks.registerNativeHooks('/tmp/project');
|
|
169
|
+
expect(hooks.isRegistered()).toBe(true);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe('unregisterNativeHooks', () => {
|
|
174
|
+
it('completes without error and marks as unregistered', async () => {
|
|
175
|
+
await hooks.registerNativeHooks('/tmp/project');
|
|
176
|
+
await hooks.unregisterNativeHooks();
|
|
177
|
+
expect(hooks.isRegistered()).toBe(false);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
describe('CursorSpawnProvider', () => {
|
|
183
|
+
let spawnProvider: CursorSpawnProvider;
|
|
184
|
+
|
|
185
|
+
beforeEach(() => {
|
|
186
|
+
spawnProvider = new CursorSpawnProvider();
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
describe('canSpawn', () => {
|
|
190
|
+
it('returns false (spawn not supported)', async () => {
|
|
191
|
+
const result = await spawnProvider.canSpawn();
|
|
192
|
+
expect(result).toBe(false);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
describe('spawn', () => {
|
|
197
|
+
it('throws an error explaining spawn is not supported', async () => {
|
|
198
|
+
await expect(
|
|
199
|
+
spawnProvider.spawn({
|
|
200
|
+
taskId: 'T1234',
|
|
201
|
+
prompt: 'test prompt',
|
|
202
|
+
}),
|
|
203
|
+
).rejects.toThrow('Cursor does not support subagent spawning');
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
describe('listRunning', () => {
|
|
208
|
+
it('returns empty array', async () => {
|
|
209
|
+
const running = await spawnProvider.listRunning();
|
|
210
|
+
expect(running).toEqual([]);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
describe('terminate', () => {
|
|
215
|
+
it('handles any instance id gracefully (no-op)', async () => {
|
|
216
|
+
await expect(spawnProvider.terminate('any-id')).resolves.toBeUndefined();
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
describe('CursorInstallProvider', () => {
|
|
222
|
+
let installProvider: CursorInstallProvider;
|
|
223
|
+
|
|
224
|
+
beforeEach(() => {
|
|
225
|
+
installProvider = new CursorInstallProvider();
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
describe('isInstalled', () => {
|
|
229
|
+
it('returns a boolean', async () => {
|
|
230
|
+
const result = await installProvider.isInstalled();
|
|
231
|
+
expect(typeof result).toBe('boolean');
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
describe('install', () => {
|
|
236
|
+
it('returns a success result', async () => {
|
|
237
|
+
const result = await installProvider.install({
|
|
238
|
+
projectDir: '/tmp/test-project',
|
|
239
|
+
});
|
|
240
|
+
expect(result.success).toBe(true);
|
|
241
|
+
expect(result.installedAt).toBeTruthy();
|
|
242
|
+
expect(typeof result.instructionFileUpdated).toBe('boolean');
|
|
243
|
+
expect(typeof result.mcpRegistered).toBe('boolean');
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('registers MCP when mcpServerPath provided', async () => {
|
|
247
|
+
const result = await installProvider.install({
|
|
248
|
+
projectDir: '/tmp/test-project',
|
|
249
|
+
mcpServerPath: '/path/to/mcp-server.js',
|
|
250
|
+
});
|
|
251
|
+
expect(result.mcpRegistered).toBe(true);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('includes instruction files in details', async () => {
|
|
255
|
+
const result = await installProvider.install({
|
|
256
|
+
projectDir: '/tmp/test-project',
|
|
257
|
+
});
|
|
258
|
+
const files = result.details?.instructionFiles as string[];
|
|
259
|
+
expect(Array.isArray(files)).toBe(true);
|
|
260
|
+
expect(files.some((f) => f.includes('cleo.mdc'))).toBe(true);
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
describe('uninstall', () => {
|
|
265
|
+
it('handles uninstall when not installed', async () => {
|
|
266
|
+
await expect(installProvider.uninstall()).resolves.toBeUndefined();
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
describe('ensureInstructionReferences', () => {
|
|
271
|
+
it('completes without error', async () => {
|
|
272
|
+
await expect(
|
|
273
|
+
installProvider.ensureInstructionReferences('/tmp/test-project'),
|
|
274
|
+
).resolves.toBeUndefined();
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
describe('barrel exports', () => {
|
|
280
|
+
it('exports createAdapter factory function', async () => {
|
|
281
|
+
const module = await import('../index.js');
|
|
282
|
+
expect(typeof module.createAdapter).toBe('function');
|
|
283
|
+
const adapter = module.createAdapter();
|
|
284
|
+
expect(adapter).toBeInstanceOf(CursorAdapter);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('exports CursorAdapter as default', async () => {
|
|
288
|
+
const module = await import('../index.js');
|
|
289
|
+
expect(module.default).toBe(CursorAdapter);
|
|
290
|
+
});
|
|
291
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor Adapter
|
|
3
|
+
*
|
|
4
|
+
* Main CLEOProviderAdapter implementation for Cursor AI code editor.
|
|
5
|
+
* Provides install capabilities for CLEO integration. Hooks and spawn
|
|
6
|
+
* are not supported since Cursor lacks CLI-based lifecycle events
|
|
7
|
+
* and subagent spawning.
|
|
8
|
+
*
|
|
9
|
+
* @task T5240
|
|
10
|
+
*/
|
|
11
|
+
import type { AdapterCapabilities, AdapterHealthStatus, CLEOProviderAdapter } from '@cleocode/contracts';
|
|
12
|
+
import { CursorHookProvider } from './hooks.js';
|
|
13
|
+
import { CursorInstallProvider } from './install.js';
|
|
14
|
+
/**
|
|
15
|
+
* CLEO provider adapter for Cursor AI code editor.
|
|
16
|
+
*
|
|
17
|
+
* Bridges CLEO's adapter system with Cursor's capabilities:
|
|
18
|
+
* - Install: Registers MCP server in .cursor/mcp.json and manages rule files
|
|
19
|
+
* - Hooks: Stub provider (Cursor has no lifecycle event system)
|
|
20
|
+
* - Spawn: Not supported (Cursor has no CLI for subagent spawning)
|
|
21
|
+
*/
|
|
22
|
+
export declare class CursorAdapter implements CLEOProviderAdapter {
|
|
23
|
+
readonly id = "cursor";
|
|
24
|
+
readonly name = "Cursor";
|
|
25
|
+
readonly version = "1.0.0";
|
|
26
|
+
capabilities: AdapterCapabilities;
|
|
27
|
+
hooks: CursorHookProvider;
|
|
28
|
+
install: CursorInstallProvider;
|
|
29
|
+
private projectDir;
|
|
30
|
+
private initialized;
|
|
31
|
+
constructor();
|
|
32
|
+
/**
|
|
33
|
+
* Initialize the adapter for a given project directory.
|
|
34
|
+
*
|
|
35
|
+
* @param projectDir - Root directory of the project
|
|
36
|
+
*/
|
|
37
|
+
initialize(projectDir: string): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Dispose the adapter and clean up resources.
|
|
40
|
+
*/
|
|
41
|
+
dispose(): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Run a health check to verify Cursor is accessible.
|
|
44
|
+
*
|
|
45
|
+
* Checks:
|
|
46
|
+
* 1. Adapter has been initialized
|
|
47
|
+
* 2. .cursor/ configuration directory exists in the project
|
|
48
|
+
* 3. CURSOR_EDITOR env var is set
|
|
49
|
+
*
|
|
50
|
+
* @returns Health status with details about each check
|
|
51
|
+
*/
|
|
52
|
+
healthCheck(): Promise<AdapterHealthStatus>;
|
|
53
|
+
/**
|
|
54
|
+
* Check whether the adapter has been initialized.
|
|
55
|
+
*/
|
|
56
|
+
isInitialized(): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Get the project directory this adapter was initialized with.
|
|
59
|
+
*/
|
|
60
|
+
getProjectDir(): string | null;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAErD;;;;;;;GAOG;AACH,qBAAa,aAAc,YAAW,mBAAmB;IACvD,QAAQ,CAAC,EAAE,YAAY;IACvB,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,OAAO,WAAW;IAE3B,YAAY,EAAE,mBAAmB,CAa/B;IAEF,KAAK,EAAE,kBAAkB,CAAC;IAC1B,OAAO,EAAE,qBAAqB,CAAC;IAE/B,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,WAAW,CAAS;;IAO5B;;;;OAIG;IACG,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKnD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ9B;;;;;;;;;OASG;IACG,WAAW,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAwCjD;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,aAAa,IAAI,MAAM,GAAG,IAAI;CAG/B"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor Adapter
|
|
3
|
+
*
|
|
4
|
+
* Main CLEOProviderAdapter implementation for Cursor AI code editor.
|
|
5
|
+
* Provides install capabilities for CLEO integration. Hooks and spawn
|
|
6
|
+
* are not supported since Cursor lacks CLI-based lifecycle events
|
|
7
|
+
* and subagent spawning.
|
|
8
|
+
*
|
|
9
|
+
* @task T5240
|
|
10
|
+
*/
|
|
11
|
+
import { existsSync } from 'node:fs';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
import { CursorHookProvider } from './hooks.js';
|
|
14
|
+
import { CursorInstallProvider } from './install.js';
|
|
15
|
+
/**
|
|
16
|
+
* CLEO provider adapter for Cursor AI code editor.
|
|
17
|
+
*
|
|
18
|
+
* Bridges CLEO's adapter system with Cursor's capabilities:
|
|
19
|
+
* - Install: Registers MCP server in .cursor/mcp.json and manages rule files
|
|
20
|
+
* - Hooks: Stub provider (Cursor has no lifecycle event system)
|
|
21
|
+
* - Spawn: Not supported (Cursor has no CLI for subagent spawning)
|
|
22
|
+
*/
|
|
23
|
+
export class CursorAdapter {
|
|
24
|
+
id = 'cursor';
|
|
25
|
+
name = 'Cursor';
|
|
26
|
+
version = '1.0.0';
|
|
27
|
+
capabilities = {
|
|
28
|
+
supportsHooks: false,
|
|
29
|
+
supportedHookEvents: [],
|
|
30
|
+
supportsSpawn: false,
|
|
31
|
+
supportsInstall: true,
|
|
32
|
+
supportsMcp: true,
|
|
33
|
+
supportsInstructionFiles: true,
|
|
34
|
+
instructionFilePattern: '.cursor/rules/*.mdc',
|
|
35
|
+
supportsContextMonitor: false,
|
|
36
|
+
supportsStatusline: false,
|
|
37
|
+
supportsProviderPaths: true,
|
|
38
|
+
supportsTransport: false,
|
|
39
|
+
supportsTaskSync: false,
|
|
40
|
+
};
|
|
41
|
+
hooks;
|
|
42
|
+
install;
|
|
43
|
+
projectDir = null;
|
|
44
|
+
initialized = false;
|
|
45
|
+
constructor() {
|
|
46
|
+
this.hooks = new CursorHookProvider();
|
|
47
|
+
this.install = new CursorInstallProvider();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Initialize the adapter for a given project directory.
|
|
51
|
+
*
|
|
52
|
+
* @param projectDir - Root directory of the project
|
|
53
|
+
*/
|
|
54
|
+
async initialize(projectDir) {
|
|
55
|
+
this.projectDir = projectDir;
|
|
56
|
+
this.initialized = true;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Dispose the adapter and clean up resources.
|
|
60
|
+
*/
|
|
61
|
+
async dispose() {
|
|
62
|
+
if (this.hooks.isRegistered()) {
|
|
63
|
+
await this.hooks.unregisterNativeHooks();
|
|
64
|
+
}
|
|
65
|
+
this.initialized = false;
|
|
66
|
+
this.projectDir = null;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Run a health check to verify Cursor is accessible.
|
|
70
|
+
*
|
|
71
|
+
* Checks:
|
|
72
|
+
* 1. Adapter has been initialized
|
|
73
|
+
* 2. .cursor/ configuration directory exists in the project
|
|
74
|
+
* 3. CURSOR_EDITOR env var is set
|
|
75
|
+
*
|
|
76
|
+
* @returns Health status with details about each check
|
|
77
|
+
*/
|
|
78
|
+
async healthCheck() {
|
|
79
|
+
const details = {};
|
|
80
|
+
if (!this.initialized) {
|
|
81
|
+
return {
|
|
82
|
+
healthy: false,
|
|
83
|
+
provider: this.id,
|
|
84
|
+
details: { error: 'Adapter not initialized' },
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// Check for Cursor config directory in the project
|
|
88
|
+
let configExists = false;
|
|
89
|
+
if (this.projectDir) {
|
|
90
|
+
const cursorConfigDir = join(this.projectDir, '.cursor');
|
|
91
|
+
configExists = existsSync(cursorConfigDir);
|
|
92
|
+
details.configDirExists = configExists;
|
|
93
|
+
}
|
|
94
|
+
// Check for CURSOR_EDITOR env var
|
|
95
|
+
const editorEnvSet = process.env.CURSOR_EDITOR !== undefined;
|
|
96
|
+
details.editorEnvSet = editorEnvSet;
|
|
97
|
+
// Check for legacy .cursorrules file
|
|
98
|
+
if (this.projectDir) {
|
|
99
|
+
const legacyRulesExist = existsSync(join(this.projectDir, '.cursorrules'));
|
|
100
|
+
details.legacyRulesExist = legacyRulesExist;
|
|
101
|
+
}
|
|
102
|
+
// Healthy if we detect Cursor presence (config dir or env var)
|
|
103
|
+
const healthy = configExists || editorEnvSet;
|
|
104
|
+
details.detected = healthy;
|
|
105
|
+
return {
|
|
106
|
+
healthy,
|
|
107
|
+
provider: this.id,
|
|
108
|
+
details,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Check whether the adapter has been initialized.
|
|
113
|
+
*/
|
|
114
|
+
isInitialized() {
|
|
115
|
+
return this.initialized;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Get the project directory this adapter was initialized with.
|
|
119
|
+
*/
|
|
120
|
+
getProjectDir() {
|
|
121
|
+
return this.projectDir;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor Adapter
|
|
3
|
+
*
|
|
4
|
+
* Main CLEOProviderAdapter implementation for Cursor AI code editor.
|
|
5
|
+
* Provides install capabilities for CLEO integration. Hooks and spawn
|
|
6
|
+
* are not supported since Cursor lacks CLI-based lifecycle events
|
|
7
|
+
* and subagent spawning.
|
|
8
|
+
*
|
|
9
|
+
* @task T5240
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { existsSync } from 'node:fs';
|
|
13
|
+
import { join } from 'node:path';
|
|
14
|
+
import type {
|
|
15
|
+
AdapterCapabilities,
|
|
16
|
+
AdapterHealthStatus,
|
|
17
|
+
CLEOProviderAdapter,
|
|
18
|
+
} from '@cleocode/contracts';
|
|
19
|
+
import { CursorHookProvider } from './hooks.js';
|
|
20
|
+
import { CursorInstallProvider } from './install.js';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* CLEO provider adapter for Cursor AI code editor.
|
|
24
|
+
*
|
|
25
|
+
* Bridges CLEO's adapter system with Cursor's capabilities:
|
|
26
|
+
* - Install: Registers MCP server in .cursor/mcp.json and manages rule files
|
|
27
|
+
* - Hooks: Stub provider (Cursor has no lifecycle event system)
|
|
28
|
+
* - Spawn: Not supported (Cursor has no CLI for subagent spawning)
|
|
29
|
+
*/
|
|
30
|
+
export class CursorAdapter implements CLEOProviderAdapter {
|
|
31
|
+
readonly id = 'cursor';
|
|
32
|
+
readonly name = 'Cursor';
|
|
33
|
+
readonly version = '1.0.0';
|
|
34
|
+
|
|
35
|
+
capabilities: AdapterCapabilities = {
|
|
36
|
+
supportsHooks: false,
|
|
37
|
+
supportedHookEvents: [],
|
|
38
|
+
supportsSpawn: false,
|
|
39
|
+
supportsInstall: true,
|
|
40
|
+
supportsMcp: true,
|
|
41
|
+
supportsInstructionFiles: true,
|
|
42
|
+
instructionFilePattern: '.cursor/rules/*.mdc',
|
|
43
|
+
supportsContextMonitor: false,
|
|
44
|
+
supportsStatusline: false,
|
|
45
|
+
supportsProviderPaths: true,
|
|
46
|
+
supportsTransport: false,
|
|
47
|
+
supportsTaskSync: false,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
hooks: CursorHookProvider;
|
|
51
|
+
install: CursorInstallProvider;
|
|
52
|
+
|
|
53
|
+
private projectDir: string | null = null;
|
|
54
|
+
private initialized = false;
|
|
55
|
+
|
|
56
|
+
constructor() {
|
|
57
|
+
this.hooks = new CursorHookProvider();
|
|
58
|
+
this.install = new CursorInstallProvider();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Initialize the adapter for a given project directory.
|
|
63
|
+
*
|
|
64
|
+
* @param projectDir - Root directory of the project
|
|
65
|
+
*/
|
|
66
|
+
async initialize(projectDir: string): Promise<void> {
|
|
67
|
+
this.projectDir = projectDir;
|
|
68
|
+
this.initialized = true;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Dispose the adapter and clean up resources.
|
|
73
|
+
*/
|
|
74
|
+
async dispose(): Promise<void> {
|
|
75
|
+
if (this.hooks.isRegistered()) {
|
|
76
|
+
await this.hooks.unregisterNativeHooks();
|
|
77
|
+
}
|
|
78
|
+
this.initialized = false;
|
|
79
|
+
this.projectDir = null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Run a health check to verify Cursor is accessible.
|
|
84
|
+
*
|
|
85
|
+
* Checks:
|
|
86
|
+
* 1. Adapter has been initialized
|
|
87
|
+
* 2. .cursor/ configuration directory exists in the project
|
|
88
|
+
* 3. CURSOR_EDITOR env var is set
|
|
89
|
+
*
|
|
90
|
+
* @returns Health status with details about each check
|
|
91
|
+
*/
|
|
92
|
+
async healthCheck(): Promise<AdapterHealthStatus> {
|
|
93
|
+
const details: Record<string, unknown> = {};
|
|
94
|
+
|
|
95
|
+
if (!this.initialized) {
|
|
96
|
+
return {
|
|
97
|
+
healthy: false,
|
|
98
|
+
provider: this.id,
|
|
99
|
+
details: { error: 'Adapter not initialized' },
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Check for Cursor config directory in the project
|
|
104
|
+
let configExists = false;
|
|
105
|
+
if (this.projectDir) {
|
|
106
|
+
const cursorConfigDir = join(this.projectDir, '.cursor');
|
|
107
|
+
configExists = existsSync(cursorConfigDir);
|
|
108
|
+
details.configDirExists = configExists;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Check for CURSOR_EDITOR env var
|
|
112
|
+
const editorEnvSet = process.env.CURSOR_EDITOR !== undefined;
|
|
113
|
+
details.editorEnvSet = editorEnvSet;
|
|
114
|
+
|
|
115
|
+
// Check for legacy .cursorrules file
|
|
116
|
+
if (this.projectDir) {
|
|
117
|
+
const legacyRulesExist = existsSync(join(this.projectDir, '.cursorrules'));
|
|
118
|
+
details.legacyRulesExist = legacyRulesExist;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Healthy if we detect Cursor presence (config dir or env var)
|
|
122
|
+
const healthy = configExists || editorEnvSet;
|
|
123
|
+
details.detected = healthy;
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
healthy,
|
|
127
|
+
provider: this.id,
|
|
128
|
+
details,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Check whether the adapter has been initialized.
|
|
134
|
+
*/
|
|
135
|
+
isInitialized(): boolean {
|
|
136
|
+
return this.initialized;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Get the project directory this adapter was initialized with.
|
|
141
|
+
*/
|
|
142
|
+
getProjectDir(): string | null {
|
|
143
|
+
return this.projectDir;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor Hook Provider
|
|
3
|
+
*
|
|
4
|
+
* Cursor does not have a native hook/event system for external tools.
|
|
5
|
+
* This provider returns null for all event mappings and marks hooks
|
|
6
|
+
* as unsupported. It exists to satisfy the AdapterHookProvider contract
|
|
7
|
+
* so the adapter can be used uniformly by the AdapterManager.
|
|
8
|
+
*
|
|
9
|
+
* @task T5240
|
|
10
|
+
*/
|
|
11
|
+
import type { AdapterHookProvider } from '@cleocode/contracts';
|
|
12
|
+
/**
|
|
13
|
+
* Hook provider for Cursor (stub).
|
|
14
|
+
*
|
|
15
|
+
* Cursor lacks a hook-based lifecycle event system. All mapping
|
|
16
|
+
* operations return null. Registration is a no-op.
|
|
17
|
+
*/
|
|
18
|
+
export declare class CursorHookProvider implements AdapterHookProvider {
|
|
19
|
+
private registered;
|
|
20
|
+
/**
|
|
21
|
+
* Map a provider event name to a CAAMP hook event name.
|
|
22
|
+
*
|
|
23
|
+
* Always returns null since Cursor does not emit hook events.
|
|
24
|
+
*
|
|
25
|
+
* @param _providerEvent - Ignored; Cursor has no hook events
|
|
26
|
+
* @returns null (no mapping available)
|
|
27
|
+
*/
|
|
28
|
+
mapProviderEvent(_providerEvent: string): string | null;
|
|
29
|
+
/**
|
|
30
|
+
* Register native hooks for a project.
|
|
31
|
+
*
|
|
32
|
+
* No-op for Cursor since it has no hook system.
|
|
33
|
+
*
|
|
34
|
+
* @param _projectDir - Ignored
|
|
35
|
+
*/
|
|
36
|
+
registerNativeHooks(_projectDir: string): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Unregister native hooks.
|
|
39
|
+
*
|
|
40
|
+
* No-op for Cursor since it has no hook system.
|
|
41
|
+
*/
|
|
42
|
+
unregisterNativeHooks(): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Check whether hooks have been registered.
|
|
45
|
+
*/
|
|
46
|
+
isRegistered(): boolean;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D;;;;;GAKG;AACH,qBAAa,kBAAmB,YAAW,mBAAmB;IAC5D,OAAO,CAAC,UAAU,CAAS;IAE3B;;;;;;;OAOG;IACH,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIvD;;;;;;OAMG;IACG,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7D;;;;OAIG;IACG,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5C;;OAEG;IACH,YAAY,IAAI,OAAO;CAGxB"}
|