@ken-jo/agent-connector 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +6 -0
- package/README.md +348 -0
- package/dist/amp-QSFH2V7Y.js +217 -0
- package/dist/amp-QSFH2V7Y.js.map +1 -0
- package/dist/amp-TULUPXXL.js +237 -0
- package/dist/amp-TULUPXXL.js.map +1 -0
- package/dist/antigravity-CX2YLSY7.js +17 -0
- package/dist/antigravity-CX2YLSY7.js.map +1 -0
- package/dist/antigravity-STHZWMP3.js +171 -0
- package/dist/antigravity-STHZWMP3.js.map +1 -0
- package/dist/antigravity-cli-P6HADOAO.js +121 -0
- package/dist/antigravity-cli-P6HADOAO.js.map +1 -0
- package/dist/antigravity-cli-YQDFVV4U.js +86 -0
- package/dist/antigravity-cli-YQDFVV4U.js.map +1 -0
- package/dist/chunk-54EMKTTX.js +191 -0
- package/dist/chunk-54EMKTTX.js.map +1 -0
- package/dist/chunk-7L6ITC4T.js +54 -0
- package/dist/chunk-7L6ITC4T.js.map +1 -0
- package/dist/chunk-7MSDGHJW.js +316 -0
- package/dist/chunk-7MSDGHJW.js.map +1 -0
- package/dist/chunk-BCHWFTV4.js +196 -0
- package/dist/chunk-BCHWFTV4.js.map +1 -0
- package/dist/chunk-DBQMX75U.js +36 -0
- package/dist/chunk-DBQMX75U.js.map +1 -0
- package/dist/chunk-EXLS7BSI.js +29 -0
- package/dist/chunk-EXLS7BSI.js.map +1 -0
- package/dist/chunk-JNM3TPLX.js +593 -0
- package/dist/chunk-JNM3TPLX.js.map +1 -0
- package/dist/chunk-JWNT5KW7.js +197 -0
- package/dist/chunk-JWNT5KW7.js.map +1 -0
- package/dist/chunk-KHO5WNTP.js +30 -0
- package/dist/chunk-KHO5WNTP.js.map +1 -0
- package/dist/chunk-LTT56GI3.js +155 -0
- package/dist/chunk-LTT56GI3.js.map +1 -0
- package/dist/chunk-MEH7GC7R.js +111 -0
- package/dist/chunk-MEH7GC7R.js.map +1 -0
- package/dist/chunk-MQPNU2CY.js +64 -0
- package/dist/chunk-MQPNU2CY.js.map +1 -0
- package/dist/chunk-OPXAP3AC.js +12 -0
- package/dist/chunk-OPXAP3AC.js.map +1 -0
- package/dist/chunk-RK6VBLXP.js +50 -0
- package/dist/chunk-RK6VBLXP.js.map +1 -0
- package/dist/chunk-TIIP3RG2.js +420 -0
- package/dist/chunk-TIIP3RG2.js.map +1 -0
- package/dist/chunk-TRKWUNO4.js +702 -0
- package/dist/chunk-TRKWUNO4.js.map +1 -0
- package/dist/chunk-TRQKHP7D.js +93 -0
- package/dist/chunk-TRQKHP7D.js.map +1 -0
- package/dist/chunk-WCETQWWK.js +59 -0
- package/dist/chunk-WCETQWWK.js.map +1 -0
- package/dist/chunk-WV63X7IK.js +357 -0
- package/dist/chunk-WV63X7IK.js.map +1 -0
- package/dist/chunk-XD7MY6HB.js +343 -0
- package/dist/chunk-XD7MY6HB.js.map +1 -0
- package/dist/chunk-XNAM7F35.js +276 -0
- package/dist/chunk-XNAM7F35.js.map +1 -0
- package/dist/chunk-XUCWLJY5.js +238 -0
- package/dist/chunk-XUCWLJY5.js.map +1 -0
- package/dist/chunk-YNZU6PAV.js +800 -0
- package/dist/chunk-YNZU6PAV.js.map +1 -0
- package/dist/chunk-YT43MUSJ.js +146 -0
- package/dist/chunk-YT43MUSJ.js.map +1 -0
- package/dist/claude-code-HKDV7T32.js +637 -0
- package/dist/claude-code-HKDV7T32.js.map +1 -0
- package/dist/claude-code-W74MNTAC.js +652 -0
- package/dist/claude-code-W74MNTAC.js.map +1 -0
- package/dist/cli/sdk.d.ts +54 -0
- package/dist/cli/sdk.js +82 -0
- package/dist/cli/sdk.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +15 -0
- package/dist/cli.js.map +1 -0
- package/dist/codebuff-3PMZJJHP.js +307 -0
- package/dist/codebuff-3PMZJJHP.js.map +1 -0
- package/dist/codebuff-QX57FJDN.js +220 -0
- package/dist/codebuff-QX57FJDN.js.map +1 -0
- package/dist/codex-JFQTS6LU.js +593 -0
- package/dist/codex-JFQTS6LU.js.map +1 -0
- package/dist/codex-Q3ATRRX3.js +364 -0
- package/dist/codex-Q3ATRRX3.js.map +1 -0
- package/dist/copilot-cli-MTCGHZ2T.js +622 -0
- package/dist/copilot-cli-MTCGHZ2T.js.map +1 -0
- package/dist/copilot-cli-SJGIXVSD.js +369 -0
- package/dist/copilot-cli-SJGIXVSD.js.map +1 -0
- package/dist/crush-I7PK3FGI.js +360 -0
- package/dist/crush-I7PK3FGI.js.map +1 -0
- package/dist/crush-LN5QFFR2.js +183 -0
- package/dist/crush-LN5QFFR2.js.map +1 -0
- package/dist/cursor-4TMXKJOZ.js +603 -0
- package/dist/cursor-4TMXKJOZ.js.map +1 -0
- package/dist/cursor-QZ6MTO74.js +194 -0
- package/dist/cursor-QZ6MTO74.js.map +1 -0
- package/dist/detect-WIAGVYS4.js +68 -0
- package/dist/detect-WIAGVYS4.js.map +1 -0
- package/dist/doctor-EZW2K4NI.js +372 -0
- package/dist/doctor-EZW2K4NI.js.map +1 -0
- package/dist/droid-KN6VRMMT.js +424 -0
- package/dist/droid-KN6VRMMT.js.map +1 -0
- package/dist/droid-W5WF5XEX.js +224 -0
- package/dist/droid-W5WF5XEX.js.map +1 -0
- package/dist/gemini-cli-CIRW37TU.js +369 -0
- package/dist/gemini-cli-CIRW37TU.js.map +1 -0
- package/dist/gemini-cli-Y35FFK4M.js +705 -0
- package/dist/gemini-cli-Y35FFK4M.js.map +1 -0
- package/dist/goose-A3M5GODH.js +212 -0
- package/dist/goose-A3M5GODH.js.map +1 -0
- package/dist/goose-ZTGTSUFJ.js +480 -0
- package/dist/goose-ZTGTSUFJ.js.map +1 -0
- package/dist/hermes-H2KV44GK.js +470 -0
- package/dist/hermes-H2KV44GK.js.map +1 -0
- package/dist/hermes-ZYLMOFLZ.js +196 -0
- package/dist/hermes-ZYLMOFLZ.js.map +1 -0
- package/dist/hook-YVDILAMZ.js +75 -0
- package/dist/hook-YVDILAMZ.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/install-HQRYZOQ2.js +60 -0
- package/dist/install-HQRYZOQ2.js.map +1 -0
- package/dist/jetbrains-copilot-HWA3DMH7.js +633 -0
- package/dist/jetbrains-copilot-HWA3DMH7.js.map +1 -0
- package/dist/kilo-NSWAVP6P.js +235 -0
- package/dist/kilo-NSWAVP6P.js.map +1 -0
- package/dist/kilo-QXJRCSLT.js +384 -0
- package/dist/kilo-QXJRCSLT.js.map +1 -0
- package/dist/kilo-cli-EAQTHXUW.js +587 -0
- package/dist/kilo-cli-EAQTHXUW.js.map +1 -0
- package/dist/kilo-cli-EVBKUODA.js +160 -0
- package/dist/kilo-cli-EVBKUODA.js.map +1 -0
- package/dist/kimi-EI3UM3ZV.js +155 -0
- package/dist/kimi-EI3UM3ZV.js.map +1 -0
- package/dist/kimi-GQ7VXNYT.js +423 -0
- package/dist/kimi-GQ7VXNYT.js.map +1 -0
- package/dist/kiro-UCLSLBW2.js +217 -0
- package/dist/kiro-UCLSLBW2.js.map +1 -0
- package/dist/kiro-VQTT6LO2.js +451 -0
- package/dist/kiro-VQTT6LO2.js.map +1 -0
- package/dist/leaderboard-K6ON3SWW.js +137 -0
- package/dist/leaderboard-K6ON3SWW.js.map +1 -0
- package/dist/mux-T2TV4CIQ.js +211 -0
- package/dist/mux-T2TV4CIQ.js.map +1 -0
- package/dist/mux-ZMLVAXOO.js +96 -0
- package/dist/mux-ZMLVAXOO.js.map +1 -0
- package/dist/omp-PB4VDKS6.js +586 -0
- package/dist/omp-PB4VDKS6.js.map +1 -0
- package/dist/openclaw-ETN2M63O.js +751 -0
- package/dist/openclaw-ETN2M63O.js.map +1 -0
- package/dist/openclaw-IYA7ASL6.js +150 -0
- package/dist/openclaw-IYA7ASL6.js.map +1 -0
- package/dist/opencode-FZ33JKUZ.js +734 -0
- package/dist/opencode-FZ33JKUZ.js.map +1 -0
- package/dist/opencode-HWT3RSMN.js +216 -0
- package/dist/opencode-HWT3RSMN.js.map +1 -0
- package/dist/package-DLOVE2E4.js +1132 -0
- package/dist/package-DLOVE2E4.js.map +1 -0
- package/dist/pi-CIU2QHT4.js +208 -0
- package/dist/pi-CIU2QHT4.js.map +1 -0
- package/dist/pi-UFX2OYFV.js +139 -0
- package/dist/pi-UFX2OYFV.js.map +1 -0
- package/dist/qwen-code-5POCNU6P.js +573 -0
- package/dist/qwen-code-5POCNU6P.js.map +1 -0
- package/dist/qwen-code-W7NUCDEN.js +134 -0
- package/dist/qwen-code-W7NUCDEN.js.map +1 -0
- package/dist/roo-code-IOIUXRDE.js +242 -0
- package/dist/roo-code-IOIUXRDE.js.map +1 -0
- package/dist/roo-code-ZLKH4A7N.js +229 -0
- package/dist/roo-code-ZLKH4A7N.js.map +1 -0
- package/dist/runtime/index.d.ts +157 -0
- package/dist/runtime/index.js +20 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/serve-HVWWY4B6.js +65 -0
- package/dist/serve-HVWWY4B6.js.map +1 -0
- package/dist/status-FE7TECZD.js +128 -0
- package/dist/status-FE7TECZD.js.map +1 -0
- package/dist/synthetic-UKR6SMGS.js +178 -0
- package/dist/synthetic-UKR6SMGS.js.map +1 -0
- package/dist/telemetry-36GESKQQ.js +349 -0
- package/dist/telemetry-36GESKQQ.js.map +1 -0
- package/dist/trae-JSNDZFKL.js +204 -0
- package/dist/trae-JSNDZFKL.js.map +1 -0
- package/dist/trae-PA26DPBW.js +157 -0
- package/dist/trae-PA26DPBW.js.map +1 -0
- package/dist/types-CYUB1OTr.d.ts +427 -0
- package/dist/uninstall-IGCKNOSF.js +72 -0
- package/dist/uninstall-IGCKNOSF.js.map +1 -0
- package/dist/upgrade-JV2VK242.js +104 -0
- package/dist/upgrade-JV2VK242.js.map +1 -0
- package/dist/usage-6ER6EMEY.js +324 -0
- package/dist/usage-6ER6EMEY.js.map +1 -0
- package/dist/usage-event-JKBI6XCF.js +48 -0
- package/dist/usage-event-JKBI6XCF.js.map +1 -0
- package/dist/vscode-copilot-CK3NO54M.js +715 -0
- package/dist/vscode-copilot-CK3NO54M.js.map +1 -0
- package/dist/warp-JNQA7PBU.js +126 -0
- package/dist/warp-JNQA7PBU.js.map +1 -0
- package/dist/warp-QNVDXOG4.js +199 -0
- package/dist/warp-QNVDXOG4.js.map +1 -0
- package/dist/zed-NNNX5MNT.js +272 -0
- package/dist/zed-NNNX5MNT.js.map +1 -0
- package/dist/zed-VRJKWYUR.js +209 -0
- package/dist/zed-VRJKWYUR.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1,593 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
writeTomlString
|
|
4
|
+
} from "./chunk-OPXAP3AC.js";
|
|
5
|
+
import {
|
|
6
|
+
resolveEnvRefsDeep
|
|
7
|
+
} from "./chunk-DBQMX75U.js";
|
|
8
|
+
import {
|
|
9
|
+
BaseAdapter
|
|
10
|
+
} from "./chunk-TIIP3RG2.js";
|
|
11
|
+
import "./chunk-7L6ITC4T.js";
|
|
12
|
+
import {
|
|
13
|
+
buildHomeBinHookCommand,
|
|
14
|
+
buildServeWrapperCommand,
|
|
15
|
+
shouldWrapForTelemetry
|
|
16
|
+
} from "./chunk-MEH7GC7R.js";
|
|
17
|
+
import {
|
|
18
|
+
ensureDir
|
|
19
|
+
} from "./chunk-TRQKHP7D.js";
|
|
20
|
+
|
|
21
|
+
// src/adapters/codex/index.ts
|
|
22
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
23
|
+
import { homedir } from "os";
|
|
24
|
+
import { dirname, join } from "path";
|
|
25
|
+
import TOML from "@iarna/toml";
|
|
26
|
+
var CODEX_HOOK_EVENTS = [
|
|
27
|
+
"SessionStart",
|
|
28
|
+
"PreToolUse",
|
|
29
|
+
"PostToolUse",
|
|
30
|
+
"PreCompact",
|
|
31
|
+
"UserPromptSubmit",
|
|
32
|
+
"Stop"
|
|
33
|
+
];
|
|
34
|
+
var PRE_TOOL_USE_MATCHER = "local_shell|shell|shell_command|exec_command|Bash|Shell|apply_patch|Edit|Write|grep_files|mcp__";
|
|
35
|
+
var CodexAdapter = class extends BaseAdapter {
|
|
36
|
+
id = "codex";
|
|
37
|
+
name = "Codex CLI";
|
|
38
|
+
paradigm = "json-stdio";
|
|
39
|
+
capabilities = {
|
|
40
|
+
preToolUse: true,
|
|
41
|
+
postToolUse: true,
|
|
42
|
+
preCompact: true,
|
|
43
|
+
sessionStart: true,
|
|
44
|
+
sessionEnd: false,
|
|
45
|
+
userPromptSubmit: true,
|
|
46
|
+
stop: true,
|
|
47
|
+
notification: false,
|
|
48
|
+
canModifyArgs: false,
|
|
49
|
+
canModifyOutput: false,
|
|
50
|
+
canInjectSessionContext: true,
|
|
51
|
+
transports: ["stdio", "http"],
|
|
52
|
+
// Content surfaces: Codex implements all three.
|
|
53
|
+
// command → ~/.codex/prompts/<name>.md (md+frontmatter, USER SCOPE ONLY)
|
|
54
|
+
// skill → <codexDir>/skills/<name>/SKILL.md (+ resources)
|
|
55
|
+
// subagent → <codexDir>/agents/<name>.toml (TOML)
|
|
56
|
+
supportsCommands: true,
|
|
57
|
+
supportsSkills: true,
|
|
58
|
+
supportsSubagents: true
|
|
59
|
+
};
|
|
60
|
+
// ── Detection ──────────────────────────────────────────────────────────
|
|
61
|
+
detectInstalled(projectDir) {
|
|
62
|
+
const userDir = this.userConfigDir();
|
|
63
|
+
const projDir = join(projectDir, ".codex");
|
|
64
|
+
const userCfg = join(userDir, "config.toml");
|
|
65
|
+
const projCfg = join(projDir, "config.toml");
|
|
66
|
+
const userInstalled = existsSync(userDir) || existsSync(userCfg);
|
|
67
|
+
const projInstalled = existsSync(projDir) || existsSync(projCfg);
|
|
68
|
+
const installed = userInstalled || projInstalled;
|
|
69
|
+
const scope = projInstalled && !userInstalled ? "project" : "user";
|
|
70
|
+
const configPath = scope === "project" ? projCfg : userCfg;
|
|
71
|
+
return {
|
|
72
|
+
id: this.id,
|
|
73
|
+
name: this.name,
|
|
74
|
+
installed,
|
|
75
|
+
paradigm: this.paradigm,
|
|
76
|
+
capabilities: this.capabilities,
|
|
77
|
+
configPath,
|
|
78
|
+
scope,
|
|
79
|
+
reason: installed ? `Found Codex config dir (${scope})` : `No .codex config dir at ${userDir} or ${projDir}`,
|
|
80
|
+
confidence: installed ? "high" : "low"
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// ── Native paths ───────────────────────────────────────────────────────
|
|
84
|
+
getConfigDir(ctx) {
|
|
85
|
+
if (ctx.scope === "project") return join(ctx.projectDir, ".codex");
|
|
86
|
+
return this.userConfigDir();
|
|
87
|
+
}
|
|
88
|
+
getServerConfigPath(ctx) {
|
|
89
|
+
return join(this.getConfigDir(ctx), "config.toml");
|
|
90
|
+
}
|
|
91
|
+
getHookConfigPath(ctx) {
|
|
92
|
+
return join(this.getConfigDir(ctx), "hooks.json");
|
|
93
|
+
}
|
|
94
|
+
/** `$CODEX_HOME` || `~/.codex` for user scope. */
|
|
95
|
+
userConfigDir() {
|
|
96
|
+
const env = process.env.CODEX_HOME;
|
|
97
|
+
if (env && env.trim() !== "") {
|
|
98
|
+
if (env.startsWith("~")) {
|
|
99
|
+
return join(homedir(), env.replace(/^~[/\\]?/, ""));
|
|
100
|
+
}
|
|
101
|
+
return env;
|
|
102
|
+
}
|
|
103
|
+
return join(homedir(), ".codex");
|
|
104
|
+
}
|
|
105
|
+
// ── TOML config IO (override JSON helpers — config.toml is TOML) ─────────
|
|
106
|
+
readToml(path) {
|
|
107
|
+
if (!existsSync(path)) return {};
|
|
108
|
+
try {
|
|
109
|
+
return TOML.parse(readFileSync(path, "utf8"));
|
|
110
|
+
} catch {
|
|
111
|
+
return {};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
writeToml(path, data, dryRun) {
|
|
115
|
+
if (dryRun) return;
|
|
116
|
+
ensureDir(dirname(path));
|
|
117
|
+
writeFileSync(path, TOML.stringify(data), "utf8");
|
|
118
|
+
}
|
|
119
|
+
// ── Install server (config.toml → [mcp_servers.<id>]) ───────────────────
|
|
120
|
+
installServer(ctx) {
|
|
121
|
+
const { connector, dryRun } = ctx;
|
|
122
|
+
const server = this.effectiveServer(ctx);
|
|
123
|
+
const path = this.getServerConfigPath(ctx);
|
|
124
|
+
if (!server) {
|
|
125
|
+
return [{ platform: this.id, action: "skip", path, detail: "no server declared" }];
|
|
126
|
+
}
|
|
127
|
+
if (server.transport !== "stdio" || !server.command) {
|
|
128
|
+
return [
|
|
129
|
+
{
|
|
130
|
+
platform: this.id,
|
|
131
|
+
action: "skip",
|
|
132
|
+
path,
|
|
133
|
+
detail: `transport "${server.transport}" not registrable in config.toml (stdio only)`
|
|
134
|
+
}
|
|
135
|
+
];
|
|
136
|
+
}
|
|
137
|
+
const entry = this.renderMcpEntry(ctx, server);
|
|
138
|
+
const cfg = this.readToml(path);
|
|
139
|
+
const bucket = this.tomlBucket(cfg, "mcp_servers");
|
|
140
|
+
const before = JSON.stringify(bucket[connector.id]);
|
|
141
|
+
const after = JSON.stringify(entry);
|
|
142
|
+
let action;
|
|
143
|
+
if (before === void 0) action = "create";
|
|
144
|
+
else if (before === after) action = "skip";
|
|
145
|
+
else action = "update";
|
|
146
|
+
if (action !== "skip") {
|
|
147
|
+
bucket[connector.id] = entry;
|
|
148
|
+
this.writeToml(path, cfg, dryRun);
|
|
149
|
+
}
|
|
150
|
+
return [{ platform: this.id, action, path, detail: `mcp_servers.${connector.id}` }];
|
|
151
|
+
}
|
|
152
|
+
uninstallServer(ctx) {
|
|
153
|
+
const { connector, dryRun } = ctx;
|
|
154
|
+
const path = this.getServerConfigPath(ctx);
|
|
155
|
+
const cfg = this.readToml(path);
|
|
156
|
+
const bucket = cfg["mcp_servers"];
|
|
157
|
+
if (!existsSync(path) || typeof bucket !== "object" || bucket === null || !(connector.id in bucket)) {
|
|
158
|
+
return [
|
|
159
|
+
{
|
|
160
|
+
platform: this.id,
|
|
161
|
+
action: "skip",
|
|
162
|
+
path,
|
|
163
|
+
detail: `mcp_servers.${connector.id} absent`
|
|
164
|
+
}
|
|
165
|
+
];
|
|
166
|
+
}
|
|
167
|
+
delete bucket[connector.id];
|
|
168
|
+
this.writeToml(path, cfg, dryRun);
|
|
169
|
+
return [{ platform: this.id, action: "remove", path, detail: `mcp_servers.${connector.id}` }];
|
|
170
|
+
}
|
|
171
|
+
// ── Install hooks (hooks.json) ──────────────────────────────────────────
|
|
172
|
+
installHooks(ctx) {
|
|
173
|
+
const { connector, dryRun } = ctx;
|
|
174
|
+
const path = this.getHookConfigPath(ctx);
|
|
175
|
+
const events = this.effectiveHookEvents(ctx);
|
|
176
|
+
if (events.length === 0) {
|
|
177
|
+
return [{ platform: this.id, action: "skip", path, detail: "no hooks declared" }];
|
|
178
|
+
}
|
|
179
|
+
const file = this.readHooksFile(path);
|
|
180
|
+
const hooks = file.hooks ??= {};
|
|
181
|
+
const changes = [];
|
|
182
|
+
for (const event of events) {
|
|
183
|
+
const desired = this.renderHookEntry(ctx, event);
|
|
184
|
+
const list = Array.isArray(hooks[event]) ? hooks[event] : hooks[event] = [];
|
|
185
|
+
const idx = list.findIndex((e) => this.isOurEntry(ctx, event, e));
|
|
186
|
+
if (idx < 0) {
|
|
187
|
+
list.push(desired);
|
|
188
|
+
changes.push({ platform: this.id, action: "create", path, detail: `hooks.${event}` });
|
|
189
|
+
} else if (JSON.stringify(list[idx]) !== JSON.stringify(desired)) {
|
|
190
|
+
list[idx] = desired;
|
|
191
|
+
changes.push({ platform: this.id, action: "update", path, detail: `hooks.${event}` });
|
|
192
|
+
} else {
|
|
193
|
+
changes.push({ platform: this.id, action: "skip", path, detail: `hooks.${event}` });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (changes.some((c) => c.action !== "skip")) {
|
|
197
|
+
this.writeJson(path, file, dryRun);
|
|
198
|
+
}
|
|
199
|
+
return changes;
|
|
200
|
+
}
|
|
201
|
+
uninstallHooks(ctx) {
|
|
202
|
+
const path = this.getHookConfigPath(ctx);
|
|
203
|
+
const file = this.readJson(path);
|
|
204
|
+
const hooks = file?.hooks;
|
|
205
|
+
if (!file || !hooks) {
|
|
206
|
+
return [{ platform: this.id, action: "skip", path, detail: "no hooks.json" }];
|
|
207
|
+
}
|
|
208
|
+
const changes = [];
|
|
209
|
+
let mutated = false;
|
|
210
|
+
for (const event of CODEX_HOOK_EVENTS) {
|
|
211
|
+
const list = hooks[event];
|
|
212
|
+
if (!Array.isArray(list)) continue;
|
|
213
|
+
const kept = list.filter((e) => !this.isOurEntry(ctx, event, e));
|
|
214
|
+
if (kept.length === list.length) continue;
|
|
215
|
+
mutated = true;
|
|
216
|
+
if (kept.length > 0) hooks[event] = kept;
|
|
217
|
+
else delete hooks[event];
|
|
218
|
+
changes.push({ platform: this.id, action: "remove", path, detail: `hooks.${event}` });
|
|
219
|
+
}
|
|
220
|
+
if (mutated) this.writeJson(path, file, ctx.dryRun);
|
|
221
|
+
if (changes.length === 0) {
|
|
222
|
+
return [{ platform: this.id, action: "skip", path, detail: "no agent-connector hooks present" }];
|
|
223
|
+
}
|
|
224
|
+
return changes;
|
|
225
|
+
}
|
|
226
|
+
// ── Health checks (default doctor renders these) ────────────────────────
|
|
227
|
+
getHealthChecks(ctx) {
|
|
228
|
+
const path = this.getServerConfigPath(ctx);
|
|
229
|
+
const id = ctx.connector.id;
|
|
230
|
+
const checks = [
|
|
231
|
+
{
|
|
232
|
+
name: `${this.name}: config.toml exists`,
|
|
233
|
+
check: () => existsSync(path) ? { status: "OK", detail: path } : { status: "FAIL", detail: `not found: ${path}` }
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
name: `${this.name}: mcp_servers.${id} registered`,
|
|
237
|
+
check: () => {
|
|
238
|
+
const cfg = this.readToml(path);
|
|
239
|
+
const bucket = cfg["mcp_servers"];
|
|
240
|
+
const present = typeof bucket === "object" && bucket !== null && id in bucket;
|
|
241
|
+
return present ? { status: "OK", detail: `mcp_servers.${id}` } : { status: "FAIL", detail: `mcp_servers.${id} not found in ${path}` };
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
];
|
|
245
|
+
if (ctx.scope !== "project") {
|
|
246
|
+
for (const cmd of ctx.connector.commands) {
|
|
247
|
+
const p = this.commandPath(cmd.name);
|
|
248
|
+
checks.push({
|
|
249
|
+
name: `${this.name}: command ${cmd.name} present`,
|
|
250
|
+
check: () => existsSync(p) ? { status: "OK", detail: p } : { status: "FAIL", detail: `not found: ${p}` }
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
for (const skill of ctx.connector.skills) {
|
|
255
|
+
const p = join(this.skillDir(ctx, skill.name), "SKILL.md");
|
|
256
|
+
checks.push({
|
|
257
|
+
name: `${this.name}: skill ${skill.name} present`,
|
|
258
|
+
check: () => existsSync(p) ? { status: "OK", detail: p } : { status: "FAIL", detail: `not found: ${p}` }
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
for (const agent of ctx.connector.subagents) {
|
|
262
|
+
const p = this.subagentPath(ctx, agent.name);
|
|
263
|
+
checks.push({
|
|
264
|
+
name: `${this.name}: subagent ${agent.name} present`,
|
|
265
|
+
check: () => existsSync(p) ? { status: "OK", detail: p } : { status: "FAIL", detail: `not found: ${p}` }
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
return checks;
|
|
269
|
+
}
|
|
270
|
+
// ── Content surfaces: commands / skills / subagents ──────────────────────
|
|
271
|
+
// CONTENT-ONLY: pure native-file writers. No runtime dispatch, no home-bin
|
|
272
|
+
// pointer, no telemetry wrap. Each method is idempotent (byte-identical →
|
|
273
|
+
// skip) via writeContentFile and reversible via removeContentFile. Honors
|
|
274
|
+
// platforms["codex"] per-surface false to skip.
|
|
275
|
+
//
|
|
276
|
+
// Native locations:
|
|
277
|
+
// command → ~/.codex/prompts/<name>.md md+frontmatter(description,argument-hint)
|
|
278
|
+
// USER SCOPE ONLY — project scope yields a single "warn".
|
|
279
|
+
// skill → <codexDir>/skills/<name>/SKILL.md (+ resources)
|
|
280
|
+
// subagent → <codexDir>/agents/<name>.toml TOML via writeTomlString
|
|
281
|
+
/** Command files always live under the USER codex dir: ~/.codex/prompts. */
|
|
282
|
+
commandPath(name) {
|
|
283
|
+
return join(this.userConfigDir(), "prompts", `${name}.md`);
|
|
284
|
+
}
|
|
285
|
+
skillDir(ctx, name) {
|
|
286
|
+
return join(this.getConfigDir(ctx), "skills", name);
|
|
287
|
+
}
|
|
288
|
+
subagentPath(ctx, name) {
|
|
289
|
+
return join(this.getConfigDir(ctx), "agents", `${name}.toml`);
|
|
290
|
+
}
|
|
291
|
+
// ── Commands (USER SCOPE ONLY) ───────────────────────────────────────────
|
|
292
|
+
installCommands(ctx) {
|
|
293
|
+
const { connector } = ctx;
|
|
294
|
+
if (connector.platforms[this.id]?.commands === false) {
|
|
295
|
+
return [{ platform: this.id, action: "skip", detail: "commands disabled for codex" }];
|
|
296
|
+
}
|
|
297
|
+
if (ctx.scope === "project") {
|
|
298
|
+
return [{ platform: this.id, action: "warn", detail: "codex commands are user-scope only" }];
|
|
299
|
+
}
|
|
300
|
+
if (connector.commands.length === 0) {
|
|
301
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no commands" }];
|
|
302
|
+
}
|
|
303
|
+
return connector.commands.map(
|
|
304
|
+
(cmd) => this.writeContentFile(this.commandPath(cmd.name), this.renderCommand(cmd), ctx.dryRun)
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
uninstallCommands(ctx) {
|
|
308
|
+
const { connector } = ctx;
|
|
309
|
+
if (ctx.scope === "project") {
|
|
310
|
+
return [{ platform: this.id, action: "warn", detail: "codex commands are user-scope only" }];
|
|
311
|
+
}
|
|
312
|
+
if (connector.commands.length === 0) {
|
|
313
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no commands" }];
|
|
314
|
+
}
|
|
315
|
+
return connector.commands.map(
|
|
316
|
+
(cmd) => this.removeContentFile(this.commandPath(cmd.name), ctx.dryRun)
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
/** Render a command to md+frontmatter (description, argument-hint). */
|
|
320
|
+
renderCommand(cmd) {
|
|
321
|
+
const frontmatter = {};
|
|
322
|
+
if (cmd.description !== void 0) frontmatter.description = cmd.description;
|
|
323
|
+
if (cmd.argumentHint !== void 0) frontmatter["argument-hint"] = cmd.argumentHint;
|
|
324
|
+
if (cmd.extra) Object.assign(frontmatter, cmd.extra);
|
|
325
|
+
return this.renderFrontmatterMd(frontmatter, cmd.prompt);
|
|
326
|
+
}
|
|
327
|
+
// ── Skills ───────────────────────────────────────────────────────────────
|
|
328
|
+
installSkills(ctx) {
|
|
329
|
+
const { connector } = ctx;
|
|
330
|
+
if (connector.platforms[this.id]?.skills === false) {
|
|
331
|
+
return [{ platform: this.id, action: "skip", detail: "skills disabled for codex" }];
|
|
332
|
+
}
|
|
333
|
+
if (connector.skills.length === 0) {
|
|
334
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
|
|
335
|
+
}
|
|
336
|
+
const changes = [];
|
|
337
|
+
for (const skill of connector.skills) {
|
|
338
|
+
const dir = this.skillDir(ctx, skill.name);
|
|
339
|
+
changes.push(
|
|
340
|
+
this.writeContentFile(join(dir, "SKILL.md"), this.renderSkill(skill), ctx.dryRun)
|
|
341
|
+
);
|
|
342
|
+
for (const [rel, contents] of Object.entries(skill.resources ?? {})) {
|
|
343
|
+
const target = this.resolveWithin(dir, rel);
|
|
344
|
+
if (target === null) {
|
|
345
|
+
changes.push({
|
|
346
|
+
platform: this.id,
|
|
347
|
+
action: "warn",
|
|
348
|
+
detail: `skill resource "${rel}" escapes the skill dir; skipped`
|
|
349
|
+
});
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
changes.push(this.writeContentFile(target, contents, ctx.dryRun));
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return changes;
|
|
356
|
+
}
|
|
357
|
+
uninstallSkills(ctx) {
|
|
358
|
+
const { connector } = ctx;
|
|
359
|
+
if (connector.skills.length === 0) {
|
|
360
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
|
|
361
|
+
}
|
|
362
|
+
const changes = [];
|
|
363
|
+
for (const skill of connector.skills) {
|
|
364
|
+
const dir = this.skillDir(ctx, skill.name);
|
|
365
|
+
changes.push(this.removeContentFile(join(dir, "SKILL.md"), ctx.dryRun));
|
|
366
|
+
for (const rel of Object.keys(skill.resources ?? {})) {
|
|
367
|
+
const target = this.resolveWithin(dir, rel);
|
|
368
|
+
if (target === null) continue;
|
|
369
|
+
changes.push(this.removeContentFile(target, ctx.dryRun));
|
|
370
|
+
}
|
|
371
|
+
changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));
|
|
372
|
+
}
|
|
373
|
+
return changes;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Render a skill's SKILL.md: frontmatter (name, description + optional model,
|
|
377
|
+
* allowed-tools, disable-model-invocation) + body. UNIFORM with every other
|
|
378
|
+
* skill-supporting platform — only the parent dir differs.
|
|
379
|
+
*/
|
|
380
|
+
renderSkill(skill) {
|
|
381
|
+
const frontmatter = {
|
|
382
|
+
name: skill.name,
|
|
383
|
+
description: skill.description
|
|
384
|
+
};
|
|
385
|
+
if (skill.model !== void 0) frontmatter.model = skill.model;
|
|
386
|
+
const allow = skill.tools?.allow;
|
|
387
|
+
if (allow && allow.length > 0) frontmatter["allowed-tools"] = allow.join(", ");
|
|
388
|
+
if (skill.disableModelInvocation !== void 0) {
|
|
389
|
+
frontmatter["disable-model-invocation"] = skill.disableModelInvocation;
|
|
390
|
+
}
|
|
391
|
+
if (skill.extra) Object.assign(frontmatter, skill.extra);
|
|
392
|
+
return this.renderFrontmatterMd(frontmatter, skill.body);
|
|
393
|
+
}
|
|
394
|
+
// ── Subagents (TOML) ─────────────────────────────────────────────────────
|
|
395
|
+
installSubagents(ctx) {
|
|
396
|
+
const { connector } = ctx;
|
|
397
|
+
if (connector.platforms[this.id]?.subagents === false) {
|
|
398
|
+
return [{ platform: this.id, action: "skip", detail: "subagents disabled for codex" }];
|
|
399
|
+
}
|
|
400
|
+
if (connector.subagents.length === 0) {
|
|
401
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no subagents" }];
|
|
402
|
+
}
|
|
403
|
+
return connector.subagents.map(
|
|
404
|
+
(agent) => this.writeContentFile(this.subagentPath(ctx, agent.name), this.renderSubagent(agent), ctx.dryRun)
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
uninstallSubagents(ctx) {
|
|
408
|
+
const { connector } = ctx;
|
|
409
|
+
if (connector.subagents.length === 0) {
|
|
410
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no subagents" }];
|
|
411
|
+
}
|
|
412
|
+
return connector.subagents.map(
|
|
413
|
+
(agent) => this.removeContentFile(this.subagentPath(ctx, agent.name), ctx.dryRun)
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Render a subagent to a Codex agent TOML file:
|
|
418
|
+
* { name, description, developer_instructions: prompt, model }.
|
|
419
|
+
* model is omitted when undefined so Codex applies its default.
|
|
420
|
+
*/
|
|
421
|
+
renderSubagent(agent) {
|
|
422
|
+
const table = {
|
|
423
|
+
name: agent.name,
|
|
424
|
+
description: agent.description,
|
|
425
|
+
developer_instructions: agent.prompt
|
|
426
|
+
};
|
|
427
|
+
if (agent.model !== void 0) table.model = agent.model;
|
|
428
|
+
if (agent.extra) Object.assign(table, agent.extra);
|
|
429
|
+
return writeTomlString(table);
|
|
430
|
+
}
|
|
431
|
+
// ── Runtime dispatch ────────────────────────────────────────────────────
|
|
432
|
+
parseEvent(event, raw) {
|
|
433
|
+
const input = raw ?? {};
|
|
434
|
+
const base = {
|
|
435
|
+
hostPlatform: this.id,
|
|
436
|
+
connectorId: "",
|
|
437
|
+
sessionId: input.session_id ?? `pid-${process.ppid}`,
|
|
438
|
+
projectDir: input.cwd ?? process.env.CODEX_PROJECT_DIR ?? process.cwd(),
|
|
439
|
+
raw
|
|
440
|
+
};
|
|
441
|
+
switch (event) {
|
|
442
|
+
case "PreToolUse":
|
|
443
|
+
return {
|
|
444
|
+
...base,
|
|
445
|
+
toolName: input.tool_name ?? "",
|
|
446
|
+
toolInput: input.tool_input ?? {}
|
|
447
|
+
};
|
|
448
|
+
case "PostToolUse":
|
|
449
|
+
return {
|
|
450
|
+
...base,
|
|
451
|
+
toolName: input.tool_name ?? "",
|
|
452
|
+
toolInput: input.tool_input ?? {},
|
|
453
|
+
toolOutput: input.tool_response,
|
|
454
|
+
isError: input.is_error ?? false
|
|
455
|
+
};
|
|
456
|
+
case "SessionStart":
|
|
457
|
+
return { ...base, source: this.normalizeSource(input.source) };
|
|
458
|
+
case "SessionEnd":
|
|
459
|
+
return { ...base, reason: input.message };
|
|
460
|
+
case "UserPromptSubmit":
|
|
461
|
+
return { ...base, prompt: input.prompt ?? "" };
|
|
462
|
+
case "PreCompact":
|
|
463
|
+
return { ...base, trigger: input.trigger === "manual" ? "manual" : "auto" };
|
|
464
|
+
case "Stop":
|
|
465
|
+
return { ...base, stopHookActive: input.stop_hook_active ?? false };
|
|
466
|
+
case "Notification":
|
|
467
|
+
return { ...base, message: input.message ?? "" };
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
formatReply(event, response) {
|
|
471
|
+
if (response.decision === "deny") {
|
|
472
|
+
if (event === "PreToolUse") {
|
|
473
|
+
return {
|
|
474
|
+
exitCode: 0,
|
|
475
|
+
stdout: JSON.stringify({
|
|
476
|
+
hookSpecificOutput: {
|
|
477
|
+
hookEventName: "PreToolUse",
|
|
478
|
+
permissionDecision: "deny",
|
|
479
|
+
permissionDecisionReason: response.reason ?? "Blocked by hook"
|
|
480
|
+
}
|
|
481
|
+
})
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
return { exitCode: 0 };
|
|
485
|
+
}
|
|
486
|
+
if (response.additionalContext && (event === "SessionStart" || event === "PostToolUse")) {
|
|
487
|
+
return {
|
|
488
|
+
exitCode: 0,
|
|
489
|
+
stdout: JSON.stringify({
|
|
490
|
+
hookSpecificOutput: {
|
|
491
|
+
hookEventName: event,
|
|
492
|
+
additionalContext: response.additionalContext
|
|
493
|
+
}
|
|
494
|
+
})
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
return { exitCode: 0 };
|
|
498
|
+
}
|
|
499
|
+
// ── Internal helpers ────────────────────────────────────────────────────
|
|
500
|
+
/** Resolve the per-platform server override into an effective ServerDef. */
|
|
501
|
+
effectiveServer(ctx) {
|
|
502
|
+
const override = ctx.connector.platforms[this.id]?.server;
|
|
503
|
+
if (override === false) return void 0;
|
|
504
|
+
const base = ctx.connector.server;
|
|
505
|
+
if (!base) return void 0;
|
|
506
|
+
return override ? { ...base, ...override } : base;
|
|
507
|
+
}
|
|
508
|
+
/** Which canonical hook events to register for Codex, honoring overrides. */
|
|
509
|
+
effectiveHookEvents(ctx) {
|
|
510
|
+
const override = ctx.connector.platforms[this.id]?.hooks;
|
|
511
|
+
if (override === false) return [];
|
|
512
|
+
return CODEX_HOOK_EVENTS.filter((e) => ctx.connector.hookEvents.includes(e));
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Render the `[mcp_servers.<id>]` table. TOML has NO interpolation, so every
|
|
516
|
+
* `${env:VAR}` is resolved to a literal at install time. The env table is a
|
|
517
|
+
* plain string→string map. Honors the telemetry serve-wrapper.
|
|
518
|
+
*/
|
|
519
|
+
renderMcpEntry(ctx, server) {
|
|
520
|
+
let command = server.command;
|
|
521
|
+
let args = [...server.args ?? []];
|
|
522
|
+
if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {
|
|
523
|
+
const wrapped = buildServeWrapperCommand(ctx.homeBinPath, ctx.connector.id, command, args, ctx.scope, this.id);
|
|
524
|
+
command = wrapped.command;
|
|
525
|
+
args = wrapped.args;
|
|
526
|
+
}
|
|
527
|
+
command = resolveEnvRefsDeep(command);
|
|
528
|
+
args = resolveEnvRefsDeep(args);
|
|
529
|
+
const entry = { command };
|
|
530
|
+
if (args.length > 0) entry.args = args;
|
|
531
|
+
if (server.env && Object.keys(server.env).length > 0) {
|
|
532
|
+
const env = {};
|
|
533
|
+
for (const [k, v] of Object.entries(resolveEnvRefsDeep(server.env))) {
|
|
534
|
+
env[k] = String(v);
|
|
535
|
+
}
|
|
536
|
+
entry.env = env;
|
|
537
|
+
}
|
|
538
|
+
return entry;
|
|
539
|
+
}
|
|
540
|
+
/** Render one hooks.json entry pointing at the stable home binary. */
|
|
541
|
+
renderHookEntry(ctx, event) {
|
|
542
|
+
const command = buildHomeBinHookCommand(
|
|
543
|
+
ctx.homeBinPath,
|
|
544
|
+
"codex",
|
|
545
|
+
event,
|
|
546
|
+
ctx.connector.id
|
|
547
|
+
);
|
|
548
|
+
const entry = { hooks: [{ type: "command", command }] };
|
|
549
|
+
if (event === "PreToolUse") entry.matcher = PRE_TOOL_USE_MATCHER;
|
|
550
|
+
else entry.matcher = "";
|
|
551
|
+
return entry;
|
|
552
|
+
}
|
|
553
|
+
/** Does this hooks.json entry belong to this connector (by home-bin command)? */
|
|
554
|
+
isOurEntry(ctx, event, entry) {
|
|
555
|
+
if (!entry || typeof entry !== "object" || !Array.isArray(entry.hooks)) return false;
|
|
556
|
+
const ours = buildHomeBinHookCommand(ctx.homeBinPath, "codex", event, ctx.connector.id);
|
|
557
|
+
const needle = ours.replace(/\\/g, "/");
|
|
558
|
+
return entry.hooks.some((h) => (h.command ?? "").replace(/\\/g, "/") === needle);
|
|
559
|
+
}
|
|
560
|
+
readHooksFile(path) {
|
|
561
|
+
return this.readJson(path) ?? {};
|
|
562
|
+
}
|
|
563
|
+
/** Get-or-create a nested table inside a parsed TOML object. */
|
|
564
|
+
tomlBucket(cfg, key) {
|
|
565
|
+
const existing = cfg[key];
|
|
566
|
+
if (existing && typeof existing === "object" && !Array.isArray(existing)) {
|
|
567
|
+
return existing;
|
|
568
|
+
}
|
|
569
|
+
const fresh = {};
|
|
570
|
+
cfg[key] = fresh;
|
|
571
|
+
return fresh;
|
|
572
|
+
}
|
|
573
|
+
normalizeSource(raw) {
|
|
574
|
+
switch (raw) {
|
|
575
|
+
case "compact":
|
|
576
|
+
return "compact";
|
|
577
|
+
case "resume":
|
|
578
|
+
return "resume";
|
|
579
|
+
case "clear":
|
|
580
|
+
return "clear";
|
|
581
|
+
default:
|
|
582
|
+
return "startup";
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
var adapter = new CodexAdapter();
|
|
587
|
+
var codex_default = adapter;
|
|
588
|
+
export {
|
|
589
|
+
CodexAdapter,
|
|
590
|
+
adapter,
|
|
591
|
+
codex_default as default
|
|
592
|
+
};
|
|
593
|
+
//# sourceMappingURL=codex-JFQTS6LU.js.map
|