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