coding-friend-cli 1.38.4 → 1.39.1
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/{chunk-32UAW3NX.js → chunk-2EY7VVFT.js} +1 -1
- package/dist/{chunk-RCE4OWNX.js → chunk-463QKRBN.js} +1 -1
- package/dist/{chunk-ETTZRJ55.js → chunk-4CPUWHIN.js} +1 -1
- package/dist/{chunk-6NXZKAOV.js → chunk-7JQZRMOG.js} +37 -4
- package/dist/{chunk-5KHZQCZB.js → chunk-FQUIO5BW.js} +1 -1
- package/dist/chunk-GTOEIGDM.js +510 -0
- package/dist/{chunk-PLSJW7QJ.js → chunk-IV5OPG34.js} +47 -1
- package/dist/{chunk-I2DQYPKT.js → chunk-MO4SUPZN.js} +176 -17
- package/dist/{chunk-S4ENKXXC.js → chunk-ODW27NAC.js} +8 -8
- package/dist/chunk-OFEC6OVI.js +99 -0
- package/dist/{chunk-5QCGEPQO.js → chunk-RL3DCID7.js} +11 -1
- package/dist/{chunk-GIH6E7GJ.js → chunk-VMODQCSL.js} +4 -53
- package/dist/{chunk-VHUU3QDC.js → chunk-YPW67OGP.js} +1 -1
- package/dist/{chunk-BXSCYGWE.js → chunk-ZGIUKUL2.js} +51 -6
- package/dist/chunk-ZZNTNIM4.js +63 -0
- package/dist/{clean-MSRZSOSO.js → clean-LPWEBJJ5.js} +2 -2
- package/dist/{config-EX3B3HWO.js → config-VNSC2NAY.js} +15 -13
- package/dist/{dev-PTBNMKZT.js → dev-NRTDUQAR.js} +3 -3
- package/dist/{disable-MO7AXYYF.js → disable-6L352DMD.js} +19 -4
- package/dist/{enable-4GXLQEHD.js → enable-6KXREKRP.js} +24 -4
- package/dist/{guide-HCR43LJN.js → guide-HCLEOAGR.js} +1 -1
- package/dist/{host-VIQ5YI3V.js → host-2JOPHLN3.js} +4 -3
- package/dist/index.js +46 -46
- package/dist/{init-S2K4CQO2.js → init-VENKICVP.js} +54 -18
- package/dist/{install-LUPE3VTC.js → install-A4TSBGOV.js} +52 -9
- package/dist/{learn-A3TP6PLL.js → learn-SSNBBDY3.js} +2 -2
- package/dist/{mcp-QNJTCZMS.js → mcp-J5VO3OH7.js} +13 -11
- package/dist/{mcp-serve-4VP4KDYG.js → mcp-serve-55DSE2J4.js} +4 -3
- package/dist/{mcp-serve-learn-UVXIDOEZ.js → mcp-serve-learn-EDBWNL4I.js} +3 -2
- package/dist/{memory-7GKTQSIW.js → memory-CDZKWOFL.js} +9 -7
- package/dist/{permission-VISPGMUK.js → permission-DPKPA2HU.js} +11 -3
- package/dist/{permissions-2SBACQHV.js → permissions-HZYUVKCY.js} +2 -2
- package/dist/{session-VDGNTICO.js → session-YWJDLNBP.js} +2 -2
- package/dist/{status-RHSL5MBU.js → status-ZOAYLVH6.js} +18 -16
- package/dist/{statusline-AOZHEQSV.js → statusline-R5BNYK3H.js} +2 -2
- package/dist/{uninstall-QN6527IR.js → uninstall-TCMK2WNW.js} +52 -8
- package/dist/{update-ZQG25VOJ.js → update-6OYI5BAY.js} +10 -7
- package/dist/{update-check-7LKJLJPM.js → update-check-EJSGVGO6.js} +1 -1
- package/package.json +1 -1
- package/dist/chunk-RZRT7NGT.js +0 -18
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ensureStatusline,
|
|
3
3
|
getInstalledVersion
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-4CPUWHIN.js";
|
|
5
5
|
import {
|
|
6
6
|
ensureShellCompletion
|
|
7
7
|
} from "./chunk-667NMPN4.js";
|
|
@@ -9,15 +9,28 @@ import {
|
|
|
9
9
|
isMemoryMcpRegistered,
|
|
10
10
|
registerMemoryMcp,
|
|
11
11
|
removeMemoryMcpEntry
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-ZGIUKUL2.js";
|
|
13
|
+
import {
|
|
14
|
+
isPluginInstalled
|
|
15
|
+
} from "./chunk-2EY7VVFT.js";
|
|
13
16
|
import {
|
|
14
17
|
CODEX_MARKETPLACE_NAME,
|
|
15
|
-
getCodexInstalledVersion
|
|
16
|
-
|
|
18
|
+
getCodexInstalledVersion,
|
|
19
|
+
isCodexMarketplaceLocal,
|
|
20
|
+
isCodexMarketplaceRegistered
|
|
21
|
+
} from "./chunk-RL3DCID7.js";
|
|
22
|
+
import {
|
|
23
|
+
deployOmpAgents,
|
|
24
|
+
isOmpAgentInstalled,
|
|
25
|
+
writeOmpExtensionEntry
|
|
26
|
+
} from "./chunk-GTOEIGDM.js";
|
|
17
27
|
import {
|
|
18
28
|
resolveHostFlags,
|
|
19
29
|
resolveScope
|
|
20
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-VMODQCSL.js";
|
|
31
|
+
import {
|
|
32
|
+
detectHostsAvailable
|
|
33
|
+
} from "./chunk-OFEC6OVI.js";
|
|
21
34
|
import {
|
|
22
35
|
commandExists,
|
|
23
36
|
run,
|
|
@@ -29,7 +42,7 @@ import {
|
|
|
29
42
|
} from "./chunk-5UVDWG5L.js";
|
|
30
43
|
import {
|
|
31
44
|
claudeSettingsPath
|
|
32
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-IV5OPG34.js";
|
|
33
46
|
import {
|
|
34
47
|
log,
|
|
35
48
|
printBanner
|
|
@@ -98,14 +111,75 @@ function getStatuslineVersion() {
|
|
|
98
111
|
);
|
|
99
112
|
return match?.[1]?.replace(/^v/, "") ?? null;
|
|
100
113
|
}
|
|
114
|
+
function argvHasAgentFlag() {
|
|
115
|
+
return process.argv.some((a) => a === "--agent" || a.startsWith("--agent="));
|
|
116
|
+
}
|
|
117
|
+
function hasExplicitHost(opts) {
|
|
118
|
+
if (opts.codex === true || opts.omp === true) return true;
|
|
119
|
+
if (argvHasAgentFlag()) return true;
|
|
120
|
+
const agent = opts.agent?.trim().toLowerCase();
|
|
121
|
+
return agent === "codex" || agent === "omp";
|
|
122
|
+
}
|
|
123
|
+
function flagsForHostResolve(opts) {
|
|
124
|
+
if (!argvHasAgentFlag() && opts.agent === "claude" && (opts.codex === true || opts.omp === true)) {
|
|
125
|
+
return { ...opts, agent: void 0 };
|
|
126
|
+
}
|
|
127
|
+
return opts;
|
|
128
|
+
}
|
|
129
|
+
function isHostInstalled(host) {
|
|
130
|
+
switch (host) {
|
|
131
|
+
case "claude":
|
|
132
|
+
return isPluginInstalled();
|
|
133
|
+
case "codex":
|
|
134
|
+
return isCodexMarketplaceRegistered();
|
|
135
|
+
case "omp":
|
|
136
|
+
return isOmpAgentInstalled("user") || isOmpAgentInstalled("project");
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function hostSectionTitle(host) {
|
|
140
|
+
switch (host) {
|
|
141
|
+
case "claude":
|
|
142
|
+
return "Claude";
|
|
143
|
+
case "codex":
|
|
144
|
+
return "Codex";
|
|
145
|
+
case "omp":
|
|
146
|
+
return "omp";
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async function updateHost(host, opts, mode) {
|
|
150
|
+
if (host === "codex") return updateCodexCommand(opts, mode);
|
|
151
|
+
if (host === "omp") return updateOmpCommand(opts, mode);
|
|
152
|
+
return updateClaudeCommand(opts, mode);
|
|
153
|
+
}
|
|
101
154
|
async function updateCommand(opts) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
await
|
|
155
|
+
if (hasExplicitHost(opts)) {
|
|
156
|
+
const { host } = resolveHostFlags(flagsForHostResolve(opts));
|
|
157
|
+
await updateHost(host, opts);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const installed = detectHostsAvailable().filter(isHostInstalled);
|
|
161
|
+
if (installed.length === 0) {
|
|
162
|
+
await updateClaudeCommand(opts);
|
|
105
163
|
return;
|
|
106
164
|
}
|
|
165
|
+
if (installed.length === 1) {
|
|
166
|
+
await updateHost(installed[0], opts);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
printBanner("\u2728 Coding Friend Update \u2728");
|
|
170
|
+
console.log();
|
|
171
|
+
for (const [index, host] of installed.entries()) {
|
|
172
|
+
console.log(chalk.bold(`\u2500\u2500 ${hostSectionTitle(host)} \u2500\u2500`));
|
|
173
|
+
console.log();
|
|
174
|
+
await updateHost(host, opts, {
|
|
175
|
+
skipBanner: true,
|
|
176
|
+
skipCli: index > 0
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
async function updateClaudeCommand(opts, mode) {
|
|
107
181
|
const updateAll = !opts.cli && !opts.plugin && !opts.statusline;
|
|
108
|
-
const doCli = updateAll || !!opts.cli;
|
|
182
|
+
const doCli = (updateAll || !!opts.cli) && !mode?.skipCli;
|
|
109
183
|
const doPlugin = updateAll || !!opts.plugin;
|
|
110
184
|
const doStatusline = updateAll || !!opts.statusline;
|
|
111
185
|
const hasScopeFlag = !!(opts.user || opts.global || opts.project || opts.local);
|
|
@@ -115,8 +189,10 @@ async function updateCommand(opts) {
|
|
|
115
189
|
} else if (doPlugin && !hasScopeFlag) {
|
|
116
190
|
scope = "user";
|
|
117
191
|
}
|
|
118
|
-
|
|
119
|
-
|
|
192
|
+
if (!mode?.skipBanner) {
|
|
193
|
+
printBanner("\u2728 Coding Friend Update \u2728");
|
|
194
|
+
console.log();
|
|
195
|
+
}
|
|
120
196
|
const currentVersion = getInstalledVersion();
|
|
121
197
|
const latestVersion = getLatestVersion();
|
|
122
198
|
const statuslineVersion = getStatuslineVersion();
|
|
@@ -235,7 +311,7 @@ async function updateCommand(opts) {
|
|
|
235
311
|
}
|
|
236
312
|
let refreshMemoryAfterUpdate = null;
|
|
237
313
|
if (doCli) {
|
|
238
|
-
({ refreshMemoryAfterUpdate } = await import("./memory-
|
|
314
|
+
({ refreshMemoryAfterUpdate } = await import("./memory-CDZKWOFL.js"));
|
|
239
315
|
if (!latestCliVersion) {
|
|
240
316
|
log.warn("Cannot check latest CLI version from npm.");
|
|
241
317
|
} else {
|
|
@@ -293,12 +369,14 @@ async function updateCommand(opts) {
|
|
|
293
369
|
console.log();
|
|
294
370
|
log.dim("Restart Claude Code (or start a new session) to see changes.");
|
|
295
371
|
}
|
|
296
|
-
async function updateCodexCommand(opts) {
|
|
372
|
+
async function updateCodexCommand(opts, mode) {
|
|
297
373
|
const updateAll = !opts.cli && !opts.plugin && !opts.statusline;
|
|
298
|
-
const doCli = updateAll || !!opts.cli;
|
|
374
|
+
const doCli = (updateAll || !!opts.cli) && !mode?.skipCli;
|
|
299
375
|
const doPlugin = updateAll || !!opts.plugin;
|
|
300
|
-
|
|
301
|
-
|
|
376
|
+
if (!mode?.skipBanner) {
|
|
377
|
+
printBanner("\u2728 Coding Friend Codex Update \u2728");
|
|
378
|
+
console.log();
|
|
379
|
+
}
|
|
302
380
|
if (doPlugin) {
|
|
303
381
|
const beforeVersion = getCodexInstalledVersion();
|
|
304
382
|
console.log(
|
|
@@ -306,6 +384,19 @@ async function updateCodexCommand(opts) {
|
|
|
306
384
|
);
|
|
307
385
|
if (!commandExists("codex")) {
|
|
308
386
|
log.error("Codex CLI not found. Cannot update Codex plugin.");
|
|
387
|
+
} else if (isCodexMarketplaceLocal()) {
|
|
388
|
+
if (beforeVersion) {
|
|
389
|
+
log.info(
|
|
390
|
+
"Codex marketplace is a local dev source \u2014 skipping git upgrade (it only works on git marketplaces)."
|
|
391
|
+
);
|
|
392
|
+
log.dim(
|
|
393
|
+
`Codex runs a cached copy at v${beforeVersion}; to pick up working-tree changes, reinstall via Codex \u2192 /plugins.`
|
|
394
|
+
);
|
|
395
|
+
} else {
|
|
396
|
+
log.warn(
|
|
397
|
+
"Codex marketplace is a local dev source, but coding-friend is not installed yet. Open Codex and run /plugins to install it."
|
|
398
|
+
);
|
|
399
|
+
}
|
|
309
400
|
} else {
|
|
310
401
|
log.step("Updating Codex marketplace...");
|
|
311
402
|
const result = runWithStderr("codex", [
|
|
@@ -371,6 +462,74 @@ async function updateCodexCommand(opts) {
|
|
|
371
462
|
console.log();
|
|
372
463
|
log.dim("Restart Codex CLI (or start a new session) to see changes.");
|
|
373
464
|
}
|
|
465
|
+
function ompUpdateScopes(opts) {
|
|
466
|
+
if (opts.project || opts.local) return ["project"];
|
|
467
|
+
if (opts.user || opts.global) return ["user"];
|
|
468
|
+
const scopes = [];
|
|
469
|
+
if (isOmpAgentInstalled("user")) scopes.push("user");
|
|
470
|
+
if (isOmpAgentInstalled("project")) scopes.push("project");
|
|
471
|
+
return scopes.length > 0 ? scopes : ["user"];
|
|
472
|
+
}
|
|
473
|
+
async function updateOmpCommand(opts, mode) {
|
|
474
|
+
const updateAll = !opts.cli && !opts.plugin && !opts.statusline;
|
|
475
|
+
const doCli = (updateAll || !!opts.cli) && !mode?.skipCli;
|
|
476
|
+
const doPlugin = updateAll || !!opts.plugin;
|
|
477
|
+
const scopes = ompUpdateScopes(opts);
|
|
478
|
+
if (!mode?.skipBanner) {
|
|
479
|
+
printBanner("\u2728 Coding Friend omp Update \u2728");
|
|
480
|
+
console.log();
|
|
481
|
+
}
|
|
482
|
+
if (doPlugin) {
|
|
483
|
+
const cliVersion = getCliVersion();
|
|
484
|
+
console.log(` CLI ${cliVersion}`);
|
|
485
|
+
for (const scope of scopes) {
|
|
486
|
+
log.step(`Updating omp agents (${scope} scope)...`);
|
|
487
|
+
const { deployed, skipped } = deployOmpAgents(scope);
|
|
488
|
+
writeOmpExtensionEntry(scope);
|
|
489
|
+
const fileLabel = deployed.length === 1 ? "file" : "files";
|
|
490
|
+
log.success(
|
|
491
|
+
`omp agents updated (${deployed.length} ${fileLabel}, ${scope} scope).`
|
|
492
|
+
);
|
|
493
|
+
if (skipped.length > 0) {
|
|
494
|
+
log.warn(`Skipped ${skipped.length} agent file(s).`);
|
|
495
|
+
}
|
|
496
|
+
log.success("omp extension entry refreshed.");
|
|
497
|
+
}
|
|
498
|
+
registerMemoryMcp("omp");
|
|
499
|
+
log.success("omp memory MCP entry refreshed.");
|
|
500
|
+
}
|
|
501
|
+
if (doCli) {
|
|
502
|
+
const cliVersion = getCliVersion();
|
|
503
|
+
const latestCliVersion = getLatestCliVersion();
|
|
504
|
+
if (!latestCliVersion) {
|
|
505
|
+
log.warn("Cannot check latest CLI version from npm.");
|
|
506
|
+
} else {
|
|
507
|
+
const cmp = semverCompare(cliVersion, latestCliVersion);
|
|
508
|
+
if (cmp < 0) {
|
|
509
|
+
log.step(
|
|
510
|
+
`CLI update available: ${chalk.yellow(`v${cliVersion}`)} \u2192 ${chalk.green(`v${latestCliVersion}`)}`
|
|
511
|
+
);
|
|
512
|
+
const result = run("npm", [
|
|
513
|
+
"install",
|
|
514
|
+
"-g",
|
|
515
|
+
"coding-friend-cli@latest"
|
|
516
|
+
]);
|
|
517
|
+
if (result === null) {
|
|
518
|
+
log.error(
|
|
519
|
+
"CLI update failed. Try manually: npm install -g coding-friend-cli@latest"
|
|
520
|
+
);
|
|
521
|
+
} else {
|
|
522
|
+
log.success(`CLI updated to ${chalk.green(`v${latestCliVersion}`)}`);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
if (opts.statusline) {
|
|
528
|
+
log.warn("omp does not use the Claude statusline. Skipping.");
|
|
529
|
+
}
|
|
530
|
+
console.log();
|
|
531
|
+
log.dim("Restart omp (or start a new session) to see changes.");
|
|
532
|
+
}
|
|
374
533
|
|
|
375
534
|
export {
|
|
376
535
|
semverCompare,
|
|
@@ -2,23 +2,23 @@ import {
|
|
|
2
2
|
checkMemoryMcpHealth,
|
|
3
3
|
printHealthSection,
|
|
4
4
|
warnStaleMcpJson
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-YPW67OGP.js";
|
|
6
6
|
import {
|
|
7
7
|
loadConfig,
|
|
8
8
|
resolveMemoryDir
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-FQUIO5BW.js";
|
|
10
10
|
import {
|
|
11
11
|
getMemoryMcpStatus,
|
|
12
12
|
isMemoryMcpRegistered,
|
|
13
13
|
memoryConfigMenu,
|
|
14
14
|
registerMemoryMcp
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import {
|
|
17
|
-
getLibPath
|
|
18
|
-
} from "./chunk-RZRT7NGT.js";
|
|
15
|
+
} from "./chunk-ZGIUKUL2.js";
|
|
19
16
|
import {
|
|
20
17
|
showConfigHint
|
|
21
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-VMODQCSL.js";
|
|
19
|
+
import {
|
|
20
|
+
getLibPath
|
|
21
|
+
} from "./chunk-ZZNTNIM4.js";
|
|
22
22
|
import {
|
|
23
23
|
run,
|
|
24
24
|
runWithStderr
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
import {
|
|
31
31
|
globalConfigPath,
|
|
32
32
|
localConfigPath
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-IV5OPG34.js";
|
|
34
34
|
import {
|
|
35
35
|
log,
|
|
36
36
|
printBanner
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import {
|
|
2
|
+
commandExists,
|
|
3
|
+
run
|
|
4
|
+
} from "./chunk-EVGXUDX4.js";
|
|
5
|
+
|
|
6
|
+
// src/lib/host.ts
|
|
7
|
+
var CODEX_MIN_VERSION = "0.130.0";
|
|
8
|
+
var OMP_MIN_VERSION = "0.1.0";
|
|
9
|
+
function detectHostsAvailable() {
|
|
10
|
+
const hosts = [];
|
|
11
|
+
if (commandExists("claude")) hosts.push("claude");
|
|
12
|
+
if (commandExists("codex")) hosts.push("codex");
|
|
13
|
+
if (commandExists("omp")) hosts.push("omp");
|
|
14
|
+
return hosts;
|
|
15
|
+
}
|
|
16
|
+
function resolveHost(opts = {}) {
|
|
17
|
+
const agent = opts.agent?.trim().toLowerCase();
|
|
18
|
+
const codexAlias = opts.codex === true;
|
|
19
|
+
const ompAlias = opts.omp === true;
|
|
20
|
+
if (agent && agent !== "claude" && agent !== "codex" && agent !== "omp") {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`Unsupported agent "${opts.agent}". Use "claude", "codex", or "omp".`
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
if (codexAlias && ompAlias) {
|
|
26
|
+
throw new Error("Use either --codex or --omp, not both.");
|
|
27
|
+
}
|
|
28
|
+
if (codexAlias && agent === "claude") {
|
|
29
|
+
throw new Error("Use either --agent claude or --codex, not both.");
|
|
30
|
+
}
|
|
31
|
+
if (ompAlias && agent === "claude") {
|
|
32
|
+
throw new Error("Use either --agent claude or --omp, not both.");
|
|
33
|
+
}
|
|
34
|
+
if (ompAlias && agent === "codex") {
|
|
35
|
+
throw new Error("Use either --agent codex or --omp, not both.");
|
|
36
|
+
}
|
|
37
|
+
if (codexAlias && agent === "omp") {
|
|
38
|
+
throw new Error("Use either --agent omp or --codex, not both.");
|
|
39
|
+
}
|
|
40
|
+
if (ompAlias) return "omp";
|
|
41
|
+
if (agent === "omp") return "omp";
|
|
42
|
+
if (codexAlias) return "codex";
|
|
43
|
+
if (agent === "codex") return "codex";
|
|
44
|
+
return "claude";
|
|
45
|
+
}
|
|
46
|
+
function getCodexMinVersion() {
|
|
47
|
+
return CODEX_MIN_VERSION;
|
|
48
|
+
}
|
|
49
|
+
function getOmpMinVersion() {
|
|
50
|
+
return OMP_MIN_VERSION;
|
|
51
|
+
}
|
|
52
|
+
function checkCodexVersion() {
|
|
53
|
+
const min = getCodexMinVersion();
|
|
54
|
+
const output = run("codex", ["--version"]);
|
|
55
|
+
const actual = output ? extractVersion(output) : void 0;
|
|
56
|
+
return {
|
|
57
|
+
ok: actual ? compareVersions(actual, min) >= 0 : false,
|
|
58
|
+
actual,
|
|
59
|
+
min
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function checkOmpVersion() {
|
|
63
|
+
const min = getOmpMinVersion();
|
|
64
|
+
const output = run("omp", ["--version"]);
|
|
65
|
+
const actual = output ? extractVersion(output) : void 0;
|
|
66
|
+
return {
|
|
67
|
+
ok: actual ? compareVersions(actual, min) >= 0 : false,
|
|
68
|
+
actual,
|
|
69
|
+
min
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function extractVersion(input) {
|
|
73
|
+
return input.match(/\b(\d+\.\d+\.\d+)\b/)?.[1];
|
|
74
|
+
}
|
|
75
|
+
function compareVersions(a, b) {
|
|
76
|
+
const left = parseVersion(a);
|
|
77
|
+
const right = parseVersion(b);
|
|
78
|
+
for (let i = 0; i < 3; i += 1) {
|
|
79
|
+
if (left[i] > right[i]) return 1;
|
|
80
|
+
if (left[i] < right[i]) return -1;
|
|
81
|
+
}
|
|
82
|
+
return 0;
|
|
83
|
+
}
|
|
84
|
+
function parseVersion(version) {
|
|
85
|
+
const parts = version.split(".").map((part) => Number.parseInt(part, 10));
|
|
86
|
+
return [
|
|
87
|
+
Number.isFinite(parts[0]) ? parts[0] : 0,
|
|
88
|
+
Number.isFinite(parts[1]) ? parts[1] : 0,
|
|
89
|
+
Number.isFinite(parts[2]) ? parts[2] : 0
|
|
90
|
+
];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export {
|
|
94
|
+
detectHostsAvailable,
|
|
95
|
+
resolveHost,
|
|
96
|
+
checkCodexVersion,
|
|
97
|
+
checkOmpVersion,
|
|
98
|
+
compareVersions
|
|
99
|
+
};
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
codexAgentsDir,
|
|
3
3
|
codexConfigTomlPath,
|
|
4
4
|
codexInstalledPluginsPath
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-IV5OPG34.js";
|
|
6
6
|
|
|
7
7
|
// src/lib/codex-config.ts
|
|
8
8
|
import {
|
|
@@ -97,6 +97,15 @@ function isCodexMarketplaceRegistered(configPath = codexConfigTomlPath()) {
|
|
|
97
97
|
(line) => line.trim() === tableHeader(`marketplaces.${CODEX_MARKETPLACE_NAME}`)
|
|
98
98
|
);
|
|
99
99
|
}
|
|
100
|
+
function isCodexMarketplaceLocal(configPath = codexConfigTomlPath()) {
|
|
101
|
+
const table = getTable(
|
|
102
|
+
readToml(configPath),
|
|
103
|
+
`marketplaces.${CODEX_MARKETPLACE_NAME}`
|
|
104
|
+
);
|
|
105
|
+
return table.some(
|
|
106
|
+
(line) => /^\s*source_type\s*=\s*["']local["']\s*(?:#.*)?$/.test(line)
|
|
107
|
+
);
|
|
108
|
+
}
|
|
100
109
|
function setCodexPluginEnabled(enabled, configPath = codexConfigTomlPath()) {
|
|
101
110
|
const content = readToml(configPath);
|
|
102
111
|
writeToml(
|
|
@@ -225,6 +234,7 @@ function deployCodexAgents(sourceDir, targetDir = codexAgentsDir()) {
|
|
|
225
234
|
export {
|
|
226
235
|
CODEX_MARKETPLACE_NAME,
|
|
227
236
|
isCodexMarketplaceRegistered,
|
|
237
|
+
isCodexMarketplaceLocal,
|
|
228
238
|
setCodexPluginEnabled,
|
|
229
239
|
isCodexPluginDisabled,
|
|
230
240
|
removeCodexMemoryMcpConfig,
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveHost
|
|
3
|
+
} from "./chunk-OFEC6OVI.js";
|
|
1
4
|
import {
|
|
2
5
|
run
|
|
3
6
|
} from "./chunk-EVGXUDX4.js";
|
|
@@ -7,62 +10,11 @@ import {
|
|
|
7
10
|
import {
|
|
8
11
|
globalConfigPath,
|
|
9
12
|
localConfigPath
|
|
10
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-IV5OPG34.js";
|
|
11
14
|
import {
|
|
12
15
|
log
|
|
13
16
|
} from "./chunk-NREZK463.js";
|
|
14
17
|
|
|
15
|
-
// src/lib/host.ts
|
|
16
|
-
var CODEX_MIN_VERSION = "0.130.0";
|
|
17
|
-
function resolveHost(opts = {}) {
|
|
18
|
-
const agent = opts.agent?.trim().toLowerCase();
|
|
19
|
-
const codexAlias = opts.codex === true;
|
|
20
|
-
if (agent && agent !== "claude" && agent !== "codex") {
|
|
21
|
-
throw new Error(
|
|
22
|
-
`Unsupported agent "${opts.agent}". Use "claude" or "codex".`
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
if (codexAlias && agent === "claude") {
|
|
26
|
-
throw new Error("Use either --agent claude or --codex, not both.");
|
|
27
|
-
}
|
|
28
|
-
if (codexAlias) return "codex";
|
|
29
|
-
if (agent === "codex") return "codex";
|
|
30
|
-
return "claude";
|
|
31
|
-
}
|
|
32
|
-
function getCodexMinVersion() {
|
|
33
|
-
return CODEX_MIN_VERSION;
|
|
34
|
-
}
|
|
35
|
-
function checkCodexVersion() {
|
|
36
|
-
const min = getCodexMinVersion();
|
|
37
|
-
const output = run("codex", ["--version"]);
|
|
38
|
-
const actual = output ? extractVersion(output) : void 0;
|
|
39
|
-
return {
|
|
40
|
-
ok: actual ? compareVersions(actual, min) >= 0 : false,
|
|
41
|
-
actual,
|
|
42
|
-
min
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
function extractVersion(input) {
|
|
46
|
-
return input.match(/\b(\d+\.\d+\.\d+)\b/)?.[1];
|
|
47
|
-
}
|
|
48
|
-
function compareVersions(a, b) {
|
|
49
|
-
const left = parseVersion(a);
|
|
50
|
-
const right = parseVersion(b);
|
|
51
|
-
for (let i = 0; i < 3; i += 1) {
|
|
52
|
-
if (left[i] > right[i]) return 1;
|
|
53
|
-
if (left[i] < right[i]) return -1;
|
|
54
|
-
}
|
|
55
|
-
return 0;
|
|
56
|
-
}
|
|
57
|
-
function parseVersion(version) {
|
|
58
|
-
const parts = version.split(".").map((part) => Number.parseInt(part, 10));
|
|
59
|
-
return [
|
|
60
|
-
Number.isFinite(parts[0]) ? parts[0] : 0,
|
|
61
|
-
Number.isFinite(parts[1]) ? parts[1] : 0,
|
|
62
|
-
Number.isFinite(parts[2]) ? parts[2] : 0
|
|
63
|
-
];
|
|
64
|
-
}
|
|
65
|
-
|
|
66
18
|
// src/lib/prompt-utils.ts
|
|
67
19
|
import { select, Separator } from "@inquirer/prompts";
|
|
68
20
|
import { existsSync } from "fs";
|
|
@@ -232,7 +184,6 @@ function applyDocsDirChange(newValue, oldValue, scope, subfolders = []) {
|
|
|
232
184
|
}
|
|
233
185
|
|
|
234
186
|
export {
|
|
235
|
-
checkCodexVersion,
|
|
236
187
|
BACK,
|
|
237
188
|
injectBackChoice,
|
|
238
189
|
askScope,
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
readOmpMcpJson,
|
|
3
|
+
removeOmpMcpEntry,
|
|
4
|
+
writeOmpMcpEntry
|
|
5
|
+
} from "./chunk-GTOEIGDM.js";
|
|
4
6
|
import {
|
|
5
7
|
BACK,
|
|
6
8
|
askScope,
|
|
7
9
|
formatScopeLabel,
|
|
8
10
|
injectBackChoice
|
|
9
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-VMODQCSL.js";
|
|
12
|
+
import {
|
|
13
|
+
getLibPath
|
|
14
|
+
} from "./chunk-ZZNTNIM4.js";
|
|
10
15
|
import {
|
|
11
16
|
runWithStderr
|
|
12
17
|
} from "./chunk-EVGXUDX4.js";
|
|
@@ -19,14 +24,32 @@ import {
|
|
|
19
24
|
claudeConfigDir,
|
|
20
25
|
globalConfigPath,
|
|
21
26
|
localConfigPath
|
|
22
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-IV5OPG34.js";
|
|
23
28
|
import {
|
|
24
29
|
log
|
|
25
30
|
} from "./chunk-NREZK463.js";
|
|
26
31
|
|
|
27
32
|
// src/lib/memory-mcp-register.ts
|
|
28
33
|
var MCP_NAME = "coding-friend-memory";
|
|
29
|
-
|
|
34
|
+
var OMP_MEMORY_SERVER = {
|
|
35
|
+
command: "npx",
|
|
36
|
+
args: ["-y", "coding-friend-cli", "mcp-serve"]
|
|
37
|
+
};
|
|
38
|
+
function hasOmpMemoryEntry() {
|
|
39
|
+
const data = readOmpMcpJson();
|
|
40
|
+
return data !== null && MCP_NAME in data.mcpServers;
|
|
41
|
+
}
|
|
42
|
+
function registerMemoryMcp(host = "claude") {
|
|
43
|
+
if (host === "omp") {
|
|
44
|
+
try {
|
|
45
|
+
writeOmpMcpEntry(MCP_NAME, OMP_MEMORY_SERVER);
|
|
46
|
+
return true;
|
|
47
|
+
} catch (error) {
|
|
48
|
+
const detail = error instanceof Error ? error.message : "unknown error";
|
|
49
|
+
log.warn(`Could not register MCP: ${detail}`);
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
30
53
|
const result = runWithStderr("claude", [
|
|
31
54
|
"mcp",
|
|
32
55
|
"add",
|
|
@@ -53,10 +76,31 @@ function registerMemoryMcp() {
|
|
|
53
76
|
}
|
|
54
77
|
return true;
|
|
55
78
|
}
|
|
56
|
-
function isMemoryMcpRegistered() {
|
|
79
|
+
function isMemoryMcpRegistered(host = "claude") {
|
|
80
|
+
if (host === "omp") return hasOmpMemoryEntry();
|
|
57
81
|
const result = runWithStderr("claude", ["mcp", "get", MCP_NAME]);
|
|
58
82
|
return result.exitCode === 0;
|
|
59
83
|
}
|
|
84
|
+
function unregisterMemoryMcp(host = "claude") {
|
|
85
|
+
if (host === "omp") {
|
|
86
|
+
try {
|
|
87
|
+
removeOmpMcpEntry(MCP_NAME);
|
|
88
|
+
return !hasOmpMemoryEntry();
|
|
89
|
+
} catch (error) {
|
|
90
|
+
const detail = error instanceof Error ? error.message : "unknown error";
|
|
91
|
+
log.warn(`Could not unregister MCP: ${detail}`);
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const result = runWithStderr("claude", [
|
|
96
|
+
"mcp",
|
|
97
|
+
"remove",
|
|
98
|
+
"--scope",
|
|
99
|
+
"user",
|
|
100
|
+
MCP_NAME
|
|
101
|
+
]);
|
|
102
|
+
return result.exitCode === 0;
|
|
103
|
+
}
|
|
60
104
|
|
|
61
105
|
// src/lib/memory-prompts.ts
|
|
62
106
|
import { confirm, input, select } from "@inquirer/prompts";
|
|
@@ -402,6 +446,7 @@ async function memoryConfigMenu(opts) {
|
|
|
402
446
|
export {
|
|
403
447
|
registerMemoryMcp,
|
|
404
448
|
isMemoryMcpRegistered,
|
|
449
|
+
unregisterMemoryMcp,
|
|
405
450
|
removeMemoryMcpEntry,
|
|
406
451
|
getMemoryMcpStatus,
|
|
407
452
|
memoryConfigMenu
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import {
|
|
2
|
+
compareVersions
|
|
3
|
+
} from "./chunk-OFEC6OVI.js";
|
|
4
|
+
import {
|
|
5
|
+
pluginCachePath
|
|
6
|
+
} from "./chunk-IV5OPG34.js";
|
|
7
|
+
|
|
8
|
+
// src/lib/lib-path.ts
|
|
9
|
+
import { existsSync, readdirSync } from "fs";
|
|
10
|
+
import { dirname, join, resolve } from "path";
|
|
11
|
+
import { fileURLToPath } from "url";
|
|
12
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
function getLibPath(name) {
|
|
14
|
+
const bundled = join(__dirname, "..", "lib", name);
|
|
15
|
+
if (existsSync(bundled)) return bundled;
|
|
16
|
+
const dev = join(__dirname, "..", "..", "lib", name);
|
|
17
|
+
if (existsSync(dev)) return dev;
|
|
18
|
+
throw new Error(
|
|
19
|
+
`Could not find lib/${name}. Ensure it exists in the CLI package.`
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
function existingOmpExtension(root) {
|
|
23
|
+
const nested = join(root, "plugin", "omp", "extension.ts");
|
|
24
|
+
if (existsSync(nested)) return nested;
|
|
25
|
+
const flat = join(root, "omp", "extension.ts");
|
|
26
|
+
if (existsSync(flat)) return flat;
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
function cachedOmpExtensionDirs(cacheRoot) {
|
|
30
|
+
let names = [];
|
|
31
|
+
try {
|
|
32
|
+
names = readdirSync(cacheRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
33
|
+
} catch {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
const versions = names.filter((name) => /^\d/.test(name)).sort(compareVersions).reverse();
|
|
37
|
+
const rest = names.filter((name) => !/^\d/.test(name));
|
|
38
|
+
return [...versions, ...rest].map((name) => join(cacheRoot, name));
|
|
39
|
+
}
|
|
40
|
+
function cachedOmpExtension() {
|
|
41
|
+
const cacheRoot = pluginCachePath();
|
|
42
|
+
if (!existsSync(cacheRoot)) return null;
|
|
43
|
+
const direct = existingOmpExtension(cacheRoot);
|
|
44
|
+
if (direct) return direct;
|
|
45
|
+
for (const dir of cachedOmpExtensionDirs(cacheRoot)) {
|
|
46
|
+
const found = existingOmpExtension(dir);
|
|
47
|
+
if (found) return found;
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
function getOmpExtensionPath(repoRoot = process.cwd()) {
|
|
52
|
+
const root = resolve(repoRoot);
|
|
53
|
+
const fromCwd = existingOmpExtension(root);
|
|
54
|
+
if (fromCwd) return fromCwd;
|
|
55
|
+
const fromParent = existingOmpExtension(resolve(root, ".."));
|
|
56
|
+
if (fromParent) return fromParent;
|
|
57
|
+
return cachedOmpExtension();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export {
|
|
61
|
+
getLibPath,
|
|
62
|
+
getOmpExtensionPath
|
|
63
|
+
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadConfig,
|
|
3
3
|
resolveMemoryDir
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-FQUIO5BW.js";
|
|
5
5
|
import "./chunk-3WIZA5OZ.js";
|
|
6
6
|
import "./chunk-EVGXUDX4.js";
|
|
7
7
|
import "./chunk-5UVDWG5L.js";
|
|
8
8
|
import {
|
|
9
9
|
resolvePath
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-IV5OPG34.js";
|
|
11
11
|
import {
|
|
12
12
|
log,
|
|
13
13
|
printBanner
|