opencode-athena 0.5.0 → 0.6.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/cli/index.js +532 -79
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +24 -2
- package/dist/index.js.map +1 -1
- package/dist/plugin/index.js +24 -2
- package/dist/plugin/index.js.map +1 -1
- package/package.json +3 -1
package/dist/cli/index.js
CHANGED
|
@@ -2,16 +2,17 @@
|
|
|
2
2
|
import { join, dirname } from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
import { confirm, select, checkbox } from '@inquirer/prompts';
|
|
5
|
-
import
|
|
5
|
+
import chalk4 from 'chalk';
|
|
6
6
|
import { Command } from 'commander';
|
|
7
|
+
import { existsSync, readFileSync, copyFileSync, mkdirSync, writeFileSync } from 'fs';
|
|
7
8
|
import { homedir } from 'os';
|
|
8
9
|
import { exec, execSync } from 'child_process';
|
|
9
|
-
import
|
|
10
|
-
import { existsSync, readFileSync } from 'fs';
|
|
10
|
+
import ora2 from 'ora';
|
|
11
11
|
import { mkdir, writeFile, readdir, copyFile, rm } from 'fs/promises';
|
|
12
12
|
import { promisify } from 'util';
|
|
13
13
|
import 'yaml';
|
|
14
14
|
import { z } from 'zod';
|
|
15
|
+
import * as semver from 'semver';
|
|
15
16
|
|
|
16
17
|
var __defProp = Object.defineProperty;
|
|
17
18
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -424,7 +425,28 @@ init_esm_shims();
|
|
|
424
425
|
|
|
425
426
|
// src/shared/constants.ts
|
|
426
427
|
init_esm_shims();
|
|
427
|
-
|
|
428
|
+
function getPackageVersion() {
|
|
429
|
+
try {
|
|
430
|
+
const currentDir = dirname(fileURLToPath(import.meta.url));
|
|
431
|
+
const possiblePaths = [
|
|
432
|
+
join(currentDir, "..", "..", "package.json"),
|
|
433
|
+
join(currentDir, "..", "..", "..", "package.json")
|
|
434
|
+
];
|
|
435
|
+
for (const pkgPath of possiblePaths) {
|
|
436
|
+
if (!existsSync(pkgPath)) continue;
|
|
437
|
+
const content = readFileSync(pkgPath, "utf-8");
|
|
438
|
+
const pkg = JSON.parse(content);
|
|
439
|
+
if (pkg.version) return pkg.version;
|
|
440
|
+
}
|
|
441
|
+
return "0.0.0";
|
|
442
|
+
} catch (error) {
|
|
443
|
+
if (error instanceof SyntaxError) {
|
|
444
|
+
console.error("[opencode-athena] Warning: package.json contains invalid JSON");
|
|
445
|
+
}
|
|
446
|
+
return "0.0.0";
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
var VERSION = getPackageVersion();
|
|
428
450
|
var DISPLAY_NAME = "OpenCode Athena";
|
|
429
451
|
var TAGLINE = "Strategic wisdom meets practical execution";
|
|
430
452
|
var CONFIG_PATHS = {
|
|
@@ -676,39 +698,39 @@ var logger = {
|
|
|
676
698
|
* Log an informational message
|
|
677
699
|
*/
|
|
678
700
|
info: (message) => {
|
|
679
|
-
console.log(
|
|
701
|
+
console.log(chalk4.blue("i"), message);
|
|
680
702
|
},
|
|
681
703
|
/**
|
|
682
704
|
* Log a success message
|
|
683
705
|
*/
|
|
684
706
|
success: (message) => {
|
|
685
|
-
console.log(
|
|
707
|
+
console.log(chalk4.green("\u2713"), message);
|
|
686
708
|
},
|
|
687
709
|
/**
|
|
688
710
|
* Log a warning message
|
|
689
711
|
*/
|
|
690
712
|
warn: (message) => {
|
|
691
|
-
console.log(
|
|
713
|
+
console.log(chalk4.yellow("!"), message);
|
|
692
714
|
},
|
|
693
715
|
/**
|
|
694
716
|
* Log an error message
|
|
695
717
|
*/
|
|
696
718
|
error: (message) => {
|
|
697
|
-
console.log(
|
|
719
|
+
console.log(chalk4.red("\u2716"), message);
|
|
698
720
|
},
|
|
699
721
|
/**
|
|
700
722
|
* Log a debug message (only when DEBUG env var is set)
|
|
701
723
|
*/
|
|
702
724
|
debug: (message) => {
|
|
703
725
|
if (process.env.DEBUG) {
|
|
704
|
-
console.log(
|
|
726
|
+
console.log(chalk4.gray("[debug]"), message);
|
|
705
727
|
}
|
|
706
728
|
},
|
|
707
729
|
/**
|
|
708
730
|
* Log a step in a process
|
|
709
731
|
*/
|
|
710
732
|
step: (step, total, message) => {
|
|
711
|
-
console.log(
|
|
733
|
+
console.log(chalk4.cyan(`[${step}/${total}]`), message);
|
|
712
734
|
},
|
|
713
735
|
/**
|
|
714
736
|
* Log a blank line
|
|
@@ -721,7 +743,7 @@ var logger = {
|
|
|
721
743
|
*/
|
|
722
744
|
section: (title) => {
|
|
723
745
|
console.log();
|
|
724
|
-
console.log(
|
|
746
|
+
console.log(chalk4.bold(title));
|
|
725
747
|
console.log();
|
|
726
748
|
},
|
|
727
749
|
/**
|
|
@@ -729,21 +751,21 @@ var logger = {
|
|
|
729
751
|
*/
|
|
730
752
|
keyValue: (key, value, indent = 0) => {
|
|
731
753
|
const padding = " ".repeat(indent);
|
|
732
|
-
console.log(`${padding}${
|
|
754
|
+
console.log(`${padding}${chalk4.gray(`${key}:`)} ${value}`);
|
|
733
755
|
},
|
|
734
756
|
/**
|
|
735
757
|
* Log a list item
|
|
736
758
|
*/
|
|
737
759
|
listItem: (item, indent = 0) => {
|
|
738
760
|
const padding = " ".repeat(indent);
|
|
739
|
-
console.log(`${padding}${
|
|
761
|
+
console.log(`${padding}${chalk4.gray("-")} ${item}`);
|
|
740
762
|
},
|
|
741
763
|
/**
|
|
742
764
|
* Display the Athena banner
|
|
743
765
|
*/
|
|
744
766
|
banner: () => {
|
|
745
767
|
console.log(
|
|
746
|
-
|
|
768
|
+
chalk4.cyan(`
|
|
747
769
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
748
770
|
\u2551 OPENCODE ATHENA \u2551
|
|
749
771
|
\u2551 Strategic Wisdom Meets Practical Execution \u2551
|
|
@@ -759,7 +781,7 @@ var logger = {
|
|
|
759
781
|
successBanner: (message) => {
|
|
760
782
|
const line = "\u2550".repeat(message.length + 4);
|
|
761
783
|
console.log(
|
|
762
|
-
|
|
784
|
+
chalk4.green(`
|
|
763
785
|
\u2554${line}\u2557
|
|
764
786
|
\u2551 ${message} \u2551
|
|
765
787
|
\u255A${line}\u255D
|
|
@@ -1119,7 +1141,7 @@ async function doctor(options) {
|
|
|
1119
1141
|
status: omoInstalled.installed ? "pass" : "fail",
|
|
1120
1142
|
message: omoInstalled.installed ? `Version ${omoInstalled.version}` : "Not installed",
|
|
1121
1143
|
fix: async () => {
|
|
1122
|
-
const spinner =
|
|
1144
|
+
const spinner = ora2("Installing oh-my-opencode...").start();
|
|
1123
1145
|
try {
|
|
1124
1146
|
await fileManager.installDependencies(["oh-my-opencode"]);
|
|
1125
1147
|
spinner.succeed("oh-my-opencode installed");
|
|
@@ -1135,7 +1157,7 @@ async function doctor(options) {
|
|
|
1135
1157
|
status: commandsDirExists ? "pass" : "warn",
|
|
1136
1158
|
message: commandsDirExists ? "Exists" : "Not found",
|
|
1137
1159
|
fix: async () => {
|
|
1138
|
-
const spinner =
|
|
1160
|
+
const spinner = ora2("Creating commands directory...").start();
|
|
1139
1161
|
try {
|
|
1140
1162
|
await fileManager.ensureDir(CONFIG_PATHS.commandsDir);
|
|
1141
1163
|
await fileManager.copyCommands();
|
|
@@ -1177,16 +1199,16 @@ async function doctor(options) {
|
|
|
1177
1199
|
switch (result.status) {
|
|
1178
1200
|
case "pass":
|
|
1179
1201
|
icon = "\u2713";
|
|
1180
|
-
color =
|
|
1202
|
+
color = chalk4.green;
|
|
1181
1203
|
break;
|
|
1182
1204
|
case "warn":
|
|
1183
1205
|
icon = "!";
|
|
1184
|
-
color =
|
|
1206
|
+
color = chalk4.yellow;
|
|
1185
1207
|
hasWarnings = true;
|
|
1186
1208
|
break;
|
|
1187
1209
|
case "fail":
|
|
1188
1210
|
icon = "\u2716";
|
|
1189
|
-
color =
|
|
1211
|
+
color = chalk4.red;
|
|
1190
1212
|
hasFailures = true;
|
|
1191
1213
|
if (result.fix) {
|
|
1192
1214
|
fixableIssues.push(result);
|
|
@@ -1214,7 +1236,7 @@ async function doctor(options) {
|
|
|
1214
1236
|
logger.blank();
|
|
1215
1237
|
logger.info("Run 'opencode-athena doctor' again to verify fixes.");
|
|
1216
1238
|
} else if (fixableIssues.length > 0) {
|
|
1217
|
-
logger.info(`Run ${
|
|
1239
|
+
logger.info(`Run ${chalk4.cyan("opencode-athena doctor --fix")} to attempt automatic fixes.`);
|
|
1218
1240
|
}
|
|
1219
1241
|
} else if (hasWarnings) {
|
|
1220
1242
|
logger.warn("Some checks have warnings, but Athena should work.");
|
|
@@ -1231,26 +1253,26 @@ async function info() {
|
|
|
1231
1253
|
const athenaConfig = fileManager.readJsonFile(CONFIG_PATHS.globalAthenaConfig);
|
|
1232
1254
|
if (!athenaConfig) {
|
|
1233
1255
|
logger.warn("OpenCode Athena is not installed.");
|
|
1234
|
-
logger.info(`Run ${
|
|
1256
|
+
logger.info(`Run ${chalk4.cyan("opencode-athena install")} to get started.`);
|
|
1235
1257
|
return;
|
|
1236
1258
|
}
|
|
1237
1259
|
logger.section("Version Information");
|
|
1238
1260
|
logger.keyValue("Athena Version", athenaConfig.version || VERSION);
|
|
1239
1261
|
logger.section("Prerequisites");
|
|
1240
1262
|
const prereqs = await checkPrerequisites();
|
|
1241
|
-
const nodeStatus = prereqs.node.installed ? prereqs.node.compatible ?
|
|
1263
|
+
const nodeStatus = prereqs.node.installed ? prereqs.node.compatible ? chalk4.green("\u2713") : chalk4.yellow("!") : chalk4.red("\u2716");
|
|
1242
1264
|
logger.keyValue("Node.js", `${nodeStatus} ${prereqs.node.version || "not found"}`);
|
|
1243
|
-
const opencodeStatus = prereqs.opencode.installed ? prereqs.opencode.compatible ?
|
|
1265
|
+
const opencodeStatus = prereqs.opencode.installed ? prereqs.opencode.compatible ? chalk4.green("\u2713") : chalk4.yellow("!") : chalk4.red("\u2716");
|
|
1244
1266
|
logger.keyValue("OpenCode", `${opencodeStatus} ${prereqs.opencode.version || "not found"}`);
|
|
1245
1267
|
logger.section("Configured Providers");
|
|
1246
|
-
const claudeStatus = athenaConfig.subscriptions.claude.enabled ?
|
|
1268
|
+
const claudeStatus = athenaConfig.subscriptions.claude.enabled ? chalk4.green("enabled") : chalk4.gray("disabled");
|
|
1247
1269
|
logger.keyValue(
|
|
1248
1270
|
"Claude",
|
|
1249
1271
|
`${claudeStatus}${athenaConfig.subscriptions.claude.tier !== "none" ? ` (${athenaConfig.subscriptions.claude.tier})` : ""}`
|
|
1250
1272
|
);
|
|
1251
|
-
const openaiStatus = athenaConfig.subscriptions.openai.enabled ?
|
|
1273
|
+
const openaiStatus = athenaConfig.subscriptions.openai.enabled ? chalk4.green("enabled") : chalk4.gray("disabled");
|
|
1252
1274
|
logger.keyValue("OpenAI", openaiStatus);
|
|
1253
|
-
const googleStatus = athenaConfig.subscriptions.google.enabled ?
|
|
1275
|
+
const googleStatus = athenaConfig.subscriptions.google.enabled ? chalk4.green("enabled") : chalk4.gray("disabled");
|
|
1254
1276
|
logger.keyValue(
|
|
1255
1277
|
"Google",
|
|
1256
1278
|
`${googleStatus}${athenaConfig.subscriptions.google.authMethod !== "none" ? ` (${athenaConfig.subscriptions.google.authMethod})` : ""}`
|
|
@@ -1284,14 +1306,14 @@ async function info() {
|
|
|
1284
1306
|
{ name: "LSP Tools", enabled: features.lspTools }
|
|
1285
1307
|
];
|
|
1286
1308
|
for (const feature of featureList) {
|
|
1287
|
-
const status = feature.enabled ?
|
|
1309
|
+
const status = feature.enabled ? chalk4.green("on") : chalk4.gray("off");
|
|
1288
1310
|
logger.keyValue(feature.name, status);
|
|
1289
1311
|
}
|
|
1290
1312
|
logger.section("MCP Servers");
|
|
1291
1313
|
const mcps = athenaConfig.mcps;
|
|
1292
|
-
logger.keyValue("context7", mcps.context7 ?
|
|
1293
|
-
logger.keyValue("exa", mcps.exa ?
|
|
1294
|
-
logger.keyValue("grep_app", mcps.grepApp ?
|
|
1314
|
+
logger.keyValue("context7", mcps.context7 ? chalk4.green("on") : chalk4.gray("off"));
|
|
1315
|
+
logger.keyValue("exa", mcps.exa ? chalk4.green("on") : chalk4.gray("off"));
|
|
1316
|
+
logger.keyValue("grep_app", mcps.grepApp ? chalk4.green("on") : chalk4.gray("off"));
|
|
1295
1317
|
logger.section("Installed Plugins");
|
|
1296
1318
|
const plugins = await getInstalledPlugins();
|
|
1297
1319
|
if (Object.keys(plugins).length === 0) {
|
|
@@ -2037,6 +2059,277 @@ async function gatherAdvanced(defaults) {
|
|
|
2037
2059
|
};
|
|
2038
2060
|
}
|
|
2039
2061
|
|
|
2062
|
+
// src/cli/utils/config-loader.ts
|
|
2063
|
+
init_esm_shims();
|
|
2064
|
+
function loadExistingConfigs() {
|
|
2065
|
+
const result = {
|
|
2066
|
+
athena: null,
|
|
2067
|
+
athenaValid: false,
|
|
2068
|
+
athenaVersion: null,
|
|
2069
|
+
omo: null,
|
|
2070
|
+
omoValid: false
|
|
2071
|
+
};
|
|
2072
|
+
if (existsSync(CONFIG_PATHS.globalAthenaConfig)) {
|
|
2073
|
+
try {
|
|
2074
|
+
const content = readFileSync(CONFIG_PATHS.globalAthenaConfig, "utf-8");
|
|
2075
|
+
result.athena = JSON.parse(content);
|
|
2076
|
+
result.athenaVersion = result.athena?.version || "0.0.1";
|
|
2077
|
+
result.athenaValid = result.athena !== null && typeof result.athena.version === "string";
|
|
2078
|
+
} catch {
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
if (existsSync(CONFIG_PATHS.globalOmoConfig)) {
|
|
2082
|
+
try {
|
|
2083
|
+
const content = readFileSync(CONFIG_PATHS.globalOmoConfig, "utf-8");
|
|
2084
|
+
result.omo = JSON.parse(content);
|
|
2085
|
+
result.omoValid = result.omo !== null;
|
|
2086
|
+
} catch {
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
return result;
|
|
2090
|
+
}
|
|
2091
|
+
function extractSubscriptions(athena) {
|
|
2092
|
+
try {
|
|
2093
|
+
const subs = athena.subscriptions;
|
|
2094
|
+
if (!subs) return null;
|
|
2095
|
+
const claude = subs.claude;
|
|
2096
|
+
const openai = subs.openai;
|
|
2097
|
+
const google = subs.google;
|
|
2098
|
+
const copilot = subs.githubCopilot;
|
|
2099
|
+
return {
|
|
2100
|
+
hasClaude: claude?.enabled === true,
|
|
2101
|
+
claudeTier: claude?.tier || "none",
|
|
2102
|
+
hasOpenAI: openai?.enabled === true,
|
|
2103
|
+
hasGoogle: google?.enabled === true,
|
|
2104
|
+
googleAuth: google?.authMethod || "none",
|
|
2105
|
+
hasGitHubCopilot: copilot?.enabled === true,
|
|
2106
|
+
copilotPlan: copilot?.plan || "none",
|
|
2107
|
+
copilotEnabledModels: copilot?.enabledModels || []
|
|
2108
|
+
};
|
|
2109
|
+
} catch {
|
|
2110
|
+
return null;
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
function extractModels(athena) {
|
|
2114
|
+
try {
|
|
2115
|
+
const models = athena.models;
|
|
2116
|
+
if (!models) return null;
|
|
2117
|
+
return {
|
|
2118
|
+
sisyphus: models.sisyphus || "",
|
|
2119
|
+
oracle: models.oracle || "",
|
|
2120
|
+
librarian: models.librarian || "",
|
|
2121
|
+
frontend: models.frontend,
|
|
2122
|
+
documentWriter: models.documentWriter,
|
|
2123
|
+
multimodalLooker: models.multimodalLooker,
|
|
2124
|
+
explore: models.explore,
|
|
2125
|
+
settings: models.settings,
|
|
2126
|
+
custom: models.custom
|
|
2127
|
+
};
|
|
2128
|
+
} catch {
|
|
2129
|
+
return null;
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
function extractMethodology(athena) {
|
|
2133
|
+
try {
|
|
2134
|
+
const bmad = athena.bmad;
|
|
2135
|
+
if (!bmad) return null;
|
|
2136
|
+
return {
|
|
2137
|
+
defaultTrack: bmad.defaultTrack || "bmad-method",
|
|
2138
|
+
autoStatusUpdate: bmad.autoStatusUpdate !== false
|
|
2139
|
+
};
|
|
2140
|
+
} catch {
|
|
2141
|
+
return null;
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
2144
|
+
function extractFeatures(athena) {
|
|
2145
|
+
try {
|
|
2146
|
+
const features = athena.features;
|
|
2147
|
+
const mcps = athena.mcps;
|
|
2148
|
+
if (!features) return null;
|
|
2149
|
+
const enabledFeatures = [];
|
|
2150
|
+
if (features.autoStatus) enabledFeatures.push("auto-status");
|
|
2151
|
+
if (features.parallelExecution) enabledFeatures.push("parallel");
|
|
2152
|
+
if (features.notifications) enabledFeatures.push("notifications");
|
|
2153
|
+
if (features.contextMonitor) enabledFeatures.push("context-monitor");
|
|
2154
|
+
if (features.commentChecker) enabledFeatures.push("comment-checker");
|
|
2155
|
+
if (features.lspTools) enabledFeatures.push("lsp-tools");
|
|
2156
|
+
const mcpList = [];
|
|
2157
|
+
if (mcps?.context7) mcpList.push("context7");
|
|
2158
|
+
if (mcps?.exa) mcpList.push("exa");
|
|
2159
|
+
if (mcps?.grepApp) mcpList.push("grep_app");
|
|
2160
|
+
return {
|
|
2161
|
+
enabledFeatures,
|
|
2162
|
+
mcps: mcpList
|
|
2163
|
+
};
|
|
2164
|
+
} catch {
|
|
2165
|
+
return null;
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
function extractAdvanced(athena) {
|
|
2169
|
+
try {
|
|
2170
|
+
const bmad = athena.bmad;
|
|
2171
|
+
return {
|
|
2172
|
+
parallelStoryLimit: bmad?.parallelStoryLimit || 3,
|
|
2173
|
+
experimental: []
|
|
2174
|
+
};
|
|
2175
|
+
} catch {
|
|
2176
|
+
return null;
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
function detectNewFeatures(existingAthena) {
|
|
2180
|
+
const newFeatures = [];
|
|
2181
|
+
const features = existingAthena.features;
|
|
2182
|
+
if (features?.autoGitOperations === void 0) {
|
|
2183
|
+
newFeatures.push("autoGitOperations");
|
|
2184
|
+
}
|
|
2185
|
+
return newFeatures;
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
// src/cli/utils/config-merger.ts
|
|
2189
|
+
init_esm_shims();
|
|
2190
|
+
function deepMerge(baseObj, newObj) {
|
|
2191
|
+
const result = { ...baseObj };
|
|
2192
|
+
for (const [key, value] of Object.entries(newObj)) {
|
|
2193
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value) && typeof result[key] === "object" && result[key] !== null && !Array.isArray(result[key])) {
|
|
2194
|
+
result[key] = deepMerge(
|
|
2195
|
+
result[key],
|
|
2196
|
+
value
|
|
2197
|
+
);
|
|
2198
|
+
} else {
|
|
2199
|
+
result[key] = value;
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
return result;
|
|
2203
|
+
}
|
|
2204
|
+
function mergeConfigs(options) {
|
|
2205
|
+
const { existingAthena, fullAnswers } = options;
|
|
2206
|
+
const freshAthena = generateAthenaConfig(fullAnswers);
|
|
2207
|
+
const freshOmo = generateOmoConfig(fullAnswers);
|
|
2208
|
+
const mergedAthena = deepMerge(existingAthena, freshAthena);
|
|
2209
|
+
mergedAthena.version = VERSION;
|
|
2210
|
+
return {
|
|
2211
|
+
athena: mergedAthena,
|
|
2212
|
+
omo: freshOmo
|
|
2213
|
+
};
|
|
2214
|
+
}
|
|
2215
|
+
function createBackups() {
|
|
2216
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.TZ]/g, "-").replace(/--+/g, "-").replace(/-$/, "");
|
|
2217
|
+
const result = {
|
|
2218
|
+
athenaBackup: null,
|
|
2219
|
+
omoBackup: null,
|
|
2220
|
+
opencodeBackup: null
|
|
2221
|
+
};
|
|
2222
|
+
if (existsSync(CONFIG_PATHS.globalAthenaConfig)) {
|
|
2223
|
+
result.athenaBackup = `${CONFIG_PATHS.globalAthenaConfig}.backup-${timestamp}`;
|
|
2224
|
+
copyFileSync(CONFIG_PATHS.globalAthenaConfig, result.athenaBackup);
|
|
2225
|
+
}
|
|
2226
|
+
if (existsSync(CONFIG_PATHS.globalOmoConfig)) {
|
|
2227
|
+
result.omoBackup = `${CONFIG_PATHS.globalOmoConfig}.backup-${timestamp}`;
|
|
2228
|
+
copyFileSync(CONFIG_PATHS.globalOmoConfig, result.omoBackup);
|
|
2229
|
+
}
|
|
2230
|
+
if (existsSync(CONFIG_PATHS.globalOpencodeConfig)) {
|
|
2231
|
+
result.opencodeBackup = `${CONFIG_PATHS.globalOpencodeConfig}.backup-${timestamp}`;
|
|
2232
|
+
copyFileSync(CONFIG_PATHS.globalOpencodeConfig, result.opencodeBackup);
|
|
2233
|
+
}
|
|
2234
|
+
return result;
|
|
2235
|
+
}
|
|
2236
|
+
function writeMergedConfigs(configs) {
|
|
2237
|
+
const athenaDir = dirname(CONFIG_PATHS.globalAthenaConfig);
|
|
2238
|
+
if (!existsSync(athenaDir)) {
|
|
2239
|
+
mkdirSync(athenaDir, { recursive: true });
|
|
2240
|
+
}
|
|
2241
|
+
writeFileSync(CONFIG_PATHS.globalAthenaConfig, JSON.stringify(configs.athena, null, 2), "utf-8");
|
|
2242
|
+
writeFileSync(CONFIG_PATHS.globalOmoConfig, JSON.stringify(configs.omo, null, 2), "utf-8");
|
|
2243
|
+
}
|
|
2244
|
+
|
|
2245
|
+
// src/cli/utils/migrations/index.ts
|
|
2246
|
+
init_esm_shims();
|
|
2247
|
+
|
|
2248
|
+
// src/cli/utils/migrations/types.ts
|
|
2249
|
+
init_esm_shims();
|
|
2250
|
+
|
|
2251
|
+
// src/cli/utils/migrations/migrations.ts
|
|
2252
|
+
init_esm_shims();
|
|
2253
|
+
var MIGRATIONS = [
|
|
2254
|
+
{
|
|
2255
|
+
fromVersion: "0.0.1",
|
|
2256
|
+
toVersion: "0.1.0",
|
|
2257
|
+
description: "Initial version normalization",
|
|
2258
|
+
migrateAthena: (config) => config
|
|
2259
|
+
},
|
|
2260
|
+
{
|
|
2261
|
+
fromVersion: "0.4.0",
|
|
2262
|
+
toVersion: "0.5.0",
|
|
2263
|
+
description: "Add autoGitOperations feature flag",
|
|
2264
|
+
migrateAthena: (config) => {
|
|
2265
|
+
const features = config.features || {};
|
|
2266
|
+
if (features.autoGitOperations === void 0) {
|
|
2267
|
+
features.autoGitOperations = false;
|
|
2268
|
+
}
|
|
2269
|
+
return { ...config, features };
|
|
2270
|
+
}
|
|
2271
|
+
},
|
|
2272
|
+
{
|
|
2273
|
+
fromVersion: "0.5.0",
|
|
2274
|
+
toVersion: "0.6.0",
|
|
2275
|
+
description: "Migration system infrastructure (no config changes)",
|
|
2276
|
+
migrateAthena: (config) => config
|
|
2277
|
+
}
|
|
2278
|
+
];
|
|
2279
|
+
|
|
2280
|
+
// src/cli/utils/migrations/runner.ts
|
|
2281
|
+
init_esm_shims();
|
|
2282
|
+
function migrateConfigs(athenaConfig, omoConfig, fromVersion) {
|
|
2283
|
+
const targetVersion = VERSION;
|
|
2284
|
+
const migrationsApplied = [];
|
|
2285
|
+
const breakingChangeWarnings = [];
|
|
2286
|
+
let hasBreakingChanges = false;
|
|
2287
|
+
let currentAthena = { ...athenaConfig };
|
|
2288
|
+
let currentOmo = { ...omoConfig };
|
|
2289
|
+
const normalizedFrom = semver.valid(semver.coerce(fromVersion)) || "0.0.0";
|
|
2290
|
+
const normalizedTarget = semver.valid(semver.coerce(targetVersion)) || VERSION;
|
|
2291
|
+
const sortedMigrations = [...MIGRATIONS].sort((a, b) => {
|
|
2292
|
+
const aVersion = semver.valid(semver.coerce(a.fromVersion)) || "0.0.0";
|
|
2293
|
+
const bVersion = semver.valid(semver.coerce(b.fromVersion)) || "0.0.0";
|
|
2294
|
+
return semver.compare(aVersion, bVersion);
|
|
2295
|
+
});
|
|
2296
|
+
for (const migration of sortedMigrations) {
|
|
2297
|
+
const migrationTo = semver.valid(semver.coerce(migration.toVersion)) || "0.0.0";
|
|
2298
|
+
if (semver.lte(migrationTo, normalizedFrom)) continue;
|
|
2299
|
+
if (semver.gt(migrationTo, normalizedTarget)) continue;
|
|
2300
|
+
if (migration.migrateAthena) {
|
|
2301
|
+
currentAthena = migration.migrateAthena(currentAthena);
|
|
2302
|
+
}
|
|
2303
|
+
if (migration.migrateOmo) {
|
|
2304
|
+
currentOmo = migration.migrateOmo(currentOmo);
|
|
2305
|
+
}
|
|
2306
|
+
migrationsApplied.push(
|
|
2307
|
+
`${migration.fromVersion} \u2192 ${migration.toVersion}: ${migration.description}`
|
|
2308
|
+
);
|
|
2309
|
+
if (isBreakingMigration(migration)) {
|
|
2310
|
+
hasBreakingChanges = true;
|
|
2311
|
+
breakingChangeWarnings.push(
|
|
2312
|
+
`Migration ${migration.fromVersion} \u2192 ${migration.toVersion} contains breaking changes: ${migration.description}`
|
|
2313
|
+
);
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
currentAthena.version = targetVersion;
|
|
2317
|
+
return {
|
|
2318
|
+
fromVersion,
|
|
2319
|
+
toVersion: targetVersion,
|
|
2320
|
+
migrationsApplied,
|
|
2321
|
+
athenaConfig: currentAthena,
|
|
2322
|
+
omoConfig: currentOmo,
|
|
2323
|
+
hasBreakingChanges,
|
|
2324
|
+
breakingChangeWarnings
|
|
2325
|
+
};
|
|
2326
|
+
}
|
|
2327
|
+
function isBreakingMigration(migration) {
|
|
2328
|
+
const fromMajor = semver.major(semver.coerce(migration.fromVersion) || "0.0.0");
|
|
2329
|
+
const toMajor = semver.major(semver.coerce(migration.toVersion) || "0.0.0");
|
|
2330
|
+
return toMajor > fromMajor;
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2040
2333
|
// src/cli/utils/preset-loader.ts
|
|
2041
2334
|
init_esm_shims();
|
|
2042
2335
|
var PRESET_NAMES = ["minimal", "standard", "enterprise", "solo-quick"];
|
|
@@ -2203,9 +2496,167 @@ function formatPresetSummary(preset, name) {
|
|
|
2203
2496
|
}
|
|
2204
2497
|
|
|
2205
2498
|
// src/cli/commands/install.ts
|
|
2499
|
+
function detectInstallMode(options, configs) {
|
|
2500
|
+
if (options.reconfigure) {
|
|
2501
|
+
return { mode: "reconfigure" };
|
|
2502
|
+
}
|
|
2503
|
+
if (!configs.athena) {
|
|
2504
|
+
return { mode: "fresh" };
|
|
2505
|
+
}
|
|
2506
|
+
return {
|
|
2507
|
+
mode: "upgrade",
|
|
2508
|
+
existingVersion: configs.athenaVersion || "0.0.1",
|
|
2509
|
+
configs
|
|
2510
|
+
};
|
|
2511
|
+
}
|
|
2512
|
+
async function runUpgradeFlow(configs, existingVersion, options) {
|
|
2513
|
+
const { athena, omo } = configs;
|
|
2514
|
+
logger.section("Upgrading Configuration");
|
|
2515
|
+
console.log(chalk4.cyan(`
|
|
2516
|
+
Current version: ${existingVersion}`));
|
|
2517
|
+
console.log(chalk4.cyan(`New version: ${VERSION}
|
|
2518
|
+
`));
|
|
2519
|
+
if (!options.yes) {
|
|
2520
|
+
const proceed = await confirm({
|
|
2521
|
+
message: "Upgrade existing installation?",
|
|
2522
|
+
default: true
|
|
2523
|
+
});
|
|
2524
|
+
if (!proceed) {
|
|
2525
|
+
logger.info("Upgrade cancelled.");
|
|
2526
|
+
process.exit(0);
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
const spinner = ora2("Creating backup...").start();
|
|
2530
|
+
const backups = createBackups();
|
|
2531
|
+
const backupCount = [backups.athenaBackup, backups.omoBackup, backups.opencodeBackup].filter(
|
|
2532
|
+
Boolean
|
|
2533
|
+
).length;
|
|
2534
|
+
spinner.succeed(`Created ${backupCount} backup file(s)`);
|
|
2535
|
+
const migrationSpinner = ora2("Applying migrations...").start();
|
|
2536
|
+
const migrationResult = migrateConfigs(athena || {}, omo || {}, existingVersion);
|
|
2537
|
+
if (migrationResult.migrationsApplied.length > 0) {
|
|
2538
|
+
migrationSpinner.succeed(`Applied ${migrationResult.migrationsApplied.length} migration(s)`);
|
|
2539
|
+
for (const migration of migrationResult.migrationsApplied) {
|
|
2540
|
+
console.log(chalk4.gray(` \u2022 ${migration}`));
|
|
2541
|
+
}
|
|
2542
|
+
} else {
|
|
2543
|
+
migrationSpinner.succeed("No migrations needed");
|
|
2544
|
+
}
|
|
2545
|
+
if (migrationResult.hasBreakingChanges && !options.yes) {
|
|
2546
|
+
console.log(chalk4.yellow("\nBreaking changes detected:"));
|
|
2547
|
+
for (const warning of migrationResult.breakingChangeWarnings) {
|
|
2548
|
+
console.log(chalk4.yellow(` \u26A0 ${warning}`));
|
|
2549
|
+
}
|
|
2550
|
+
const continueUpgrade = await confirm({
|
|
2551
|
+
message: "Continue with upgrade despite breaking changes?",
|
|
2552
|
+
default: false
|
|
2553
|
+
});
|
|
2554
|
+
if (!continueUpgrade) {
|
|
2555
|
+
logger.info("Upgrade cancelled. Your backup files are preserved.");
|
|
2556
|
+
process.exit(0);
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
const existingSubscriptions = extractSubscriptions(migrationResult.athenaConfig);
|
|
2560
|
+
const existingModels = extractModels(migrationResult.athenaConfig);
|
|
2561
|
+
const existingMethodology = extractMethodology(migrationResult.athenaConfig);
|
|
2562
|
+
const existingFeatures = extractFeatures(migrationResult.athenaConfig);
|
|
2563
|
+
const existingAdvanced = extractAdvanced(migrationResult.athenaConfig);
|
|
2564
|
+
logger.section("Preserved Configuration");
|
|
2565
|
+
if (existingSubscriptions) {
|
|
2566
|
+
console.log(chalk4.bold("Subscriptions:"));
|
|
2567
|
+
if (existingSubscriptions.hasClaude)
|
|
2568
|
+
console.log(chalk4.green(` \u2713 Claude (${existingSubscriptions.claudeTier})`));
|
|
2569
|
+
if (existingSubscriptions.hasOpenAI) console.log(chalk4.green(" \u2713 OpenAI"));
|
|
2570
|
+
if (existingSubscriptions.hasGoogle)
|
|
2571
|
+
console.log(chalk4.green(` \u2713 Google (${existingSubscriptions.googleAuth})`));
|
|
2572
|
+
if (existingSubscriptions.hasGitHubCopilot)
|
|
2573
|
+
console.log(chalk4.green(` \u2713 GitHub Copilot (${existingSubscriptions.copilotPlan})`));
|
|
2574
|
+
}
|
|
2575
|
+
if (existingModels) {
|
|
2576
|
+
console.log(chalk4.bold("\nModel Assignments:"));
|
|
2577
|
+
console.log(chalk4.green(` \u2713 Sisyphus: ${existingModels.sisyphus}`));
|
|
2578
|
+
console.log(chalk4.green(` \u2713 Oracle: ${existingModels.oracle}`));
|
|
2579
|
+
console.log(chalk4.green(` \u2713 Librarian: ${existingModels.librarian}`));
|
|
2580
|
+
}
|
|
2581
|
+
console.log();
|
|
2582
|
+
const newFeatures = detectNewFeatures(migrationResult.athenaConfig);
|
|
2583
|
+
const updatedFeatures = existingFeatures;
|
|
2584
|
+
if (newFeatures.length > 0 && !options.yes) {
|
|
2585
|
+
logger.section("New Features Available");
|
|
2586
|
+
for (const feature of newFeatures) {
|
|
2587
|
+
if (feature === "autoGitOperations") {
|
|
2588
|
+
const enable = await confirm({
|
|
2589
|
+
message: "Enable automatic git operations? (commits, pushes by agents)",
|
|
2590
|
+
default: false
|
|
2591
|
+
});
|
|
2592
|
+
if (enable) {
|
|
2593
|
+
const migratedFeatures = migrationResult.athenaConfig.features;
|
|
2594
|
+
migratedFeatures.autoGitOperations = true;
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
}
|
|
2598
|
+
}
|
|
2599
|
+
let finalSubscriptions = existingSubscriptions;
|
|
2600
|
+
if (!options.yes) {
|
|
2601
|
+
const changeSubscriptions = await confirm({
|
|
2602
|
+
message: "Do you want to modify your LLM subscriptions?",
|
|
2603
|
+
default: false
|
|
2604
|
+
});
|
|
2605
|
+
if (changeSubscriptions) {
|
|
2606
|
+
logger.section("LLM Subscriptions");
|
|
2607
|
+
finalSubscriptions = await gatherSubscriptions();
|
|
2608
|
+
}
|
|
2609
|
+
}
|
|
2610
|
+
if (!finalSubscriptions) {
|
|
2611
|
+
logger.error("Could not extract subscription information from existing config.");
|
|
2612
|
+
logger.info("Please run with --reconfigure to set up from scratch.");
|
|
2613
|
+
process.exit(1);
|
|
2614
|
+
}
|
|
2615
|
+
const fullAnswers = {
|
|
2616
|
+
subscriptions: finalSubscriptions,
|
|
2617
|
+
models: existingModels || {
|
|
2618
|
+
sisyphus: "",
|
|
2619
|
+
oracle: "",
|
|
2620
|
+
librarian: ""
|
|
2621
|
+
},
|
|
2622
|
+
methodology: existingMethodology || {
|
|
2623
|
+
defaultTrack: "bmad-method",
|
|
2624
|
+
autoStatusUpdate: true
|
|
2625
|
+
},
|
|
2626
|
+
features: updatedFeatures || {
|
|
2627
|
+
enabledFeatures: [],
|
|
2628
|
+
mcps: []
|
|
2629
|
+
},
|
|
2630
|
+
advanced: existingAdvanced || {
|
|
2631
|
+
parallelStoryLimit: 3,
|
|
2632
|
+
experimental: []
|
|
2633
|
+
},
|
|
2634
|
+
installLocation: options.local ? "local" : "global"
|
|
2635
|
+
};
|
|
2636
|
+
const merged = mergeConfigs({
|
|
2637
|
+
existingAthena: migrationResult.athenaConfig,
|
|
2638
|
+
fullAnswers
|
|
2639
|
+
});
|
|
2640
|
+
const writeSpinner = ora2("Writing configuration...").start();
|
|
2641
|
+
writeMergedConfigs(merged);
|
|
2642
|
+
writeSpinner.succeed("Configuration files updated");
|
|
2643
|
+
const fileManager = new FileManager();
|
|
2644
|
+
const commandsSpinner = ora2("Updating bridge commands...").start();
|
|
2645
|
+
const copiedCommands = await fileManager.copyCommands();
|
|
2646
|
+
commandsSpinner.succeed(`Updated ${copiedCommands.length} bridge commands`);
|
|
2647
|
+
logger.successBanner(`UPGRADED TO OPENCODE ATHENA ${VERSION}!`);
|
|
2648
|
+
if (backups.athenaBackup || backups.omoBackup || backups.opencodeBackup) {
|
|
2649
|
+
console.log(chalk4.gray("\nBackups saved:"));
|
|
2650
|
+
if (backups.athenaBackup) console.log(chalk4.gray(` \u2022 ${backups.athenaBackup}`));
|
|
2651
|
+
if (backups.omoBackup) console.log(chalk4.gray(` \u2022 ${backups.omoBackup}`));
|
|
2652
|
+
if (backups.opencodeBackup) console.log(chalk4.gray(` \u2022 ${backups.opencodeBackup}`));
|
|
2653
|
+
}
|
|
2654
|
+
console.log(chalk4.gray("\nRestart OpenCode to use the upgraded configuration."));
|
|
2655
|
+
console.log();
|
|
2656
|
+
}
|
|
2206
2657
|
async function install(options) {
|
|
2207
2658
|
logger.banner();
|
|
2208
|
-
const spinner =
|
|
2659
|
+
const spinner = ora2("Checking prerequisites...").start();
|
|
2209
2660
|
const prereqs = await checkPrerequisites();
|
|
2210
2661
|
if (!prereqs.node.installed) {
|
|
2211
2662
|
spinner.fail("Node.js not found");
|
|
@@ -2225,15 +2676,14 @@ async function install(options) {
|
|
|
2225
2676
|
} else {
|
|
2226
2677
|
spinner.succeed(`OpenCode ${prereqs.opencode.version || ""} detected`);
|
|
2227
2678
|
}
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
}
|
|
2679
|
+
const existingConfigs = loadExistingConfigs();
|
|
2680
|
+
const modeResult = detectInstallMode(options, existingConfigs);
|
|
2681
|
+
if (modeResult.mode === "upgrade" && modeResult.configs && modeResult.existingVersion) {
|
|
2682
|
+
await runUpgradeFlow(modeResult.configs, modeResult.existingVersion, options);
|
|
2683
|
+
return;
|
|
2684
|
+
}
|
|
2685
|
+
if (modeResult.mode === "reconfigure") {
|
|
2686
|
+
logger.info("Reconfiguring from scratch (--reconfigure flag)");
|
|
2237
2687
|
}
|
|
2238
2688
|
let preset = null;
|
|
2239
2689
|
let presetDefaults = null;
|
|
@@ -2268,14 +2718,14 @@ async function install(options) {
|
|
|
2268
2718
|
if (preset && presetDefaults && presetName) {
|
|
2269
2719
|
const modelWarnings = validatePresetModels(presetDefaults.models, subscriptions);
|
|
2270
2720
|
if (modelWarnings.length > 0) {
|
|
2271
|
-
console.log(
|
|
2721
|
+
console.log(chalk4.yellow("\nPreset model compatibility warnings:"));
|
|
2272
2722
|
for (const warning of modelWarnings) {
|
|
2273
|
-
console.log(
|
|
2723
|
+
console.log(chalk4.yellow(` - ${warning}`));
|
|
2274
2724
|
}
|
|
2275
2725
|
console.log();
|
|
2276
2726
|
}
|
|
2277
|
-
console.log(
|
|
2278
|
-
console.log(
|
|
2727
|
+
console.log(chalk4.bold("\nPreset Configuration:\n"));
|
|
2728
|
+
console.log(chalk4.gray(formatPresetSummary(preset, presetName)));
|
|
2279
2729
|
console.log();
|
|
2280
2730
|
if (options.yes) {
|
|
2281
2731
|
shouldCustomize = false;
|
|
@@ -2345,10 +2795,10 @@ async function install(options) {
|
|
|
2345
2795
|
};
|
|
2346
2796
|
const generator = new ConfigGenerator(answers);
|
|
2347
2797
|
const files = await generator.generate();
|
|
2348
|
-
console.log(
|
|
2798
|
+
console.log(chalk4.bold("Files to be created/modified:\n"));
|
|
2349
2799
|
for (const file of files) {
|
|
2350
|
-
const action = file.exists ?
|
|
2351
|
-
console.log(
|
|
2800
|
+
const action = file.exists ? chalk4.yellow("update") : chalk4.green("create");
|
|
2801
|
+
console.log(chalk4.gray(` [${action}] ${file.path}`));
|
|
2352
2802
|
}
|
|
2353
2803
|
console.log();
|
|
2354
2804
|
if (!options.yes) {
|
|
@@ -2361,7 +2811,7 @@ async function install(options) {
|
|
|
2361
2811
|
process.exit(0);
|
|
2362
2812
|
}
|
|
2363
2813
|
}
|
|
2364
|
-
const installSpinner =
|
|
2814
|
+
const installSpinner = ora2("Installing OpenCode Athena...").start();
|
|
2365
2815
|
try {
|
|
2366
2816
|
const fileManager = new FileManager(generator.getConfigDir());
|
|
2367
2817
|
await fileManager.writeFiles(files);
|
|
@@ -2418,30 +2868,30 @@ function getValidModelOrFirst(modelId, availableModels) {
|
|
|
2418
2868
|
function printNextSteps(subscriptions) {
|
|
2419
2869
|
const steps = [];
|
|
2420
2870
|
if (subscriptions.hasClaude) {
|
|
2421
|
-
steps.push(`Run: ${
|
|
2871
|
+
steps.push(`Run: ${chalk4.cyan("opencode auth login")} -> Select Anthropic -> Claude Pro/Max`);
|
|
2422
2872
|
}
|
|
2423
2873
|
if (subscriptions.hasOpenAI) {
|
|
2424
|
-
steps.push(`Run: ${
|
|
2874
|
+
steps.push(`Run: ${chalk4.cyan("opencode auth login")} -> Select OpenAI -> ChatGPT Plus/Pro`);
|
|
2425
2875
|
}
|
|
2426
2876
|
if (subscriptions.hasGoogle) {
|
|
2427
|
-
steps.push(`Run: ${
|
|
2877
|
+
steps.push(`Run: ${chalk4.cyan("opencode auth login")} -> Select Google -> OAuth with Google`);
|
|
2428
2878
|
}
|
|
2429
2879
|
if (subscriptions.hasGitHubCopilot) {
|
|
2430
|
-
steps.push(`Run: ${
|
|
2880
|
+
steps.push(`Run: ${chalk4.cyan("opencode auth login")} -> Select GitHub Copilot`);
|
|
2431
2881
|
}
|
|
2432
2882
|
logger.successBanner("OPENCODE ATHENA INSTALLED SUCCESSFULLY!");
|
|
2433
|
-
console.log(
|
|
2883
|
+
console.log(chalk4.bold("Next Steps:\n"));
|
|
2434
2884
|
steps.forEach((step, i) => {
|
|
2435
2885
|
console.log(` ${i + 1}. ${step}`);
|
|
2436
2886
|
});
|
|
2437
|
-
console.log(
|
|
2438
|
-
console.log(` ${
|
|
2439
|
-
console.log(` ${
|
|
2440
|
-
console.log(` ${
|
|
2441
|
-
console.log(
|
|
2442
|
-
console.log(` ${
|
|
2887
|
+
console.log(chalk4.bold("\nThen start OpenCode and try:\n"));
|
|
2888
|
+
console.log(` ${chalk4.cyan("/athena-dev")} Implement a BMAD story with Sisyphus`);
|
|
2889
|
+
console.log(` ${chalk4.cyan("/athena-status")} Check sprint status`);
|
|
2890
|
+
console.log(` ${chalk4.cyan("/athena-info")} View toolkit configuration`);
|
|
2891
|
+
console.log(chalk4.bold("\nFor BMAD project setup:\n"));
|
|
2892
|
+
console.log(` ${chalk4.cyan("npx bmad-method@alpha install")} Install BMAD in your project`);
|
|
2443
2893
|
console.log(
|
|
2444
|
-
|
|
2894
|
+
chalk4.gray("\nDocumentation: https://github.com/ZebulonRouseFrantzich/opencode-athena")
|
|
2445
2895
|
);
|
|
2446
2896
|
console.log();
|
|
2447
2897
|
}
|
|
@@ -2462,7 +2912,7 @@ async function uninstall(options) {
|
|
|
2462
2912
|
}
|
|
2463
2913
|
logger.section("Uninstalling OpenCode Athena");
|
|
2464
2914
|
const fileManager = new FileManager();
|
|
2465
|
-
const commandsSpinner =
|
|
2915
|
+
const commandsSpinner = ora2("Removing bridge commands...").start();
|
|
2466
2916
|
try {
|
|
2467
2917
|
const removedCommands = await fileManager.removeCommands();
|
|
2468
2918
|
if (removedCommands.length > 0) {
|
|
@@ -2475,7 +2925,7 @@ async function uninstall(options) {
|
|
|
2475
2925
|
logger.error(err instanceof Error ? err.message : String(err));
|
|
2476
2926
|
}
|
|
2477
2927
|
if (!options.keepConfig) {
|
|
2478
|
-
const configSpinner =
|
|
2928
|
+
const configSpinner = ora2("Removing configuration files...").start();
|
|
2479
2929
|
try {
|
|
2480
2930
|
const removedFiles = await fileManager.removeConfigFiles();
|
|
2481
2931
|
if (removedFiles.length > 0) {
|
|
@@ -2490,7 +2940,7 @@ async function uninstall(options) {
|
|
|
2490
2940
|
} else {
|
|
2491
2941
|
logger.info("Keeping configuration files (--keep-config)");
|
|
2492
2942
|
}
|
|
2493
|
-
const opencodeSpinner =
|
|
2943
|
+
const opencodeSpinner = ora2("Updating opencode.json...").start();
|
|
2494
2944
|
try {
|
|
2495
2945
|
const updated = await fileManager.removeFromOpencodeConfig();
|
|
2496
2946
|
if (updated) {
|
|
@@ -2503,7 +2953,7 @@ async function uninstall(options) {
|
|
|
2503
2953
|
logger.error(err instanceof Error ? err.message : String(err));
|
|
2504
2954
|
}
|
|
2505
2955
|
if (!options.keepDeps) {
|
|
2506
|
-
const depsSpinner =
|
|
2956
|
+
const depsSpinner = ora2("Removing npm dependencies...").start();
|
|
2507
2957
|
try {
|
|
2508
2958
|
const packagesToRemove = [
|
|
2509
2959
|
"oh-my-opencode",
|
|
@@ -2522,7 +2972,7 @@ async function uninstall(options) {
|
|
|
2522
2972
|
logger.success("OpenCode Athena has been uninstalled.");
|
|
2523
2973
|
if (options.keepConfig) {
|
|
2524
2974
|
logger.info("Configuration files were preserved.");
|
|
2525
|
-
logger.info(`Run ${
|
|
2975
|
+
logger.info(`Run ${chalk4.cyan("opencode-athena install")} to reinstall with existing config.`);
|
|
2526
2976
|
}
|
|
2527
2977
|
console.log();
|
|
2528
2978
|
}
|
|
@@ -2550,7 +3000,7 @@ async function checkPackageUpdate(name, currentVersion) {
|
|
|
2550
3000
|
async function update(options) {
|
|
2551
3001
|
logger.banner();
|
|
2552
3002
|
logger.section("Checking for Updates");
|
|
2553
|
-
const spinner =
|
|
3003
|
+
const spinner = ora2("Checking package versions...").start();
|
|
2554
3004
|
const installedPlugins = await getInstalledPlugins();
|
|
2555
3005
|
const packagesToCheck = [
|
|
2556
3006
|
"oh-my-opencode",
|
|
@@ -2578,7 +3028,7 @@ async function update(options) {
|
|
|
2578
3028
|
logger.section("Package Versions");
|
|
2579
3029
|
const updatesAvailable = updates.filter((u) => u.updateAvailable);
|
|
2580
3030
|
for (const pkg of updates) {
|
|
2581
|
-
const status = pkg.updateAvailable ?
|
|
3031
|
+
const status = pkg.updateAvailable ? chalk4.yellow(`${pkg.current} -> ${pkg.latest}`) : chalk4.green(pkg.current);
|
|
2582
3032
|
logger.keyValue(pkg.name, status);
|
|
2583
3033
|
}
|
|
2584
3034
|
console.log();
|
|
@@ -2589,7 +3039,7 @@ async function update(options) {
|
|
|
2589
3039
|
logger.info(`${updatesAvailable.length} update(s) available`);
|
|
2590
3040
|
if (options.check) {
|
|
2591
3041
|
console.log();
|
|
2592
|
-
logger.info(`Run ${
|
|
3042
|
+
logger.info(`Run ${chalk4.cyan("opencode-athena update")} (without --check) to apply updates.`);
|
|
2593
3043
|
return;
|
|
2594
3044
|
}
|
|
2595
3045
|
const proceed = await confirm({
|
|
@@ -2604,7 +3054,7 @@ async function update(options) {
|
|
|
2604
3054
|
const fileManager = new FileManager();
|
|
2605
3055
|
const athenaUpdate = updatesAvailable.find((u) => u.name === "opencode-athena");
|
|
2606
3056
|
if (athenaUpdate) {
|
|
2607
|
-
const athenaSpinner =
|
|
3057
|
+
const athenaSpinner = ora2("Updating opencode-athena...").start();
|
|
2608
3058
|
try {
|
|
2609
3059
|
await execAsync3("npm install -g opencode-athena@latest");
|
|
2610
3060
|
athenaSpinner.succeed(`opencode-athena updated to ${athenaUpdate.latest}`);
|
|
@@ -2615,7 +3065,7 @@ async function update(options) {
|
|
|
2615
3065
|
}
|
|
2616
3066
|
const pluginUpdates = updatesAvailable.filter((u) => u.name !== "opencode-athena");
|
|
2617
3067
|
if (pluginUpdates.length > 0) {
|
|
2618
|
-
const pluginSpinner =
|
|
3068
|
+
const pluginSpinner = ora2("Updating plugins...").start();
|
|
2619
3069
|
try {
|
|
2620
3070
|
const packages = pluginUpdates.map((u) => `${u.name}@latest`);
|
|
2621
3071
|
await fileManager.installDependencies(packages);
|
|
@@ -2625,7 +3075,7 @@ async function update(options) {
|
|
|
2625
3075
|
logger.error(err instanceof Error ? err.message : String(err));
|
|
2626
3076
|
}
|
|
2627
3077
|
}
|
|
2628
|
-
const commandsSpinner =
|
|
3078
|
+
const commandsSpinner = ora2("Updating bridge commands...").start();
|
|
2629
3079
|
try {
|
|
2630
3080
|
await fileManager.copyCommands();
|
|
2631
3081
|
commandsSpinner.succeed("Bridge commands updated");
|
|
@@ -2640,34 +3090,37 @@ async function update(options) {
|
|
|
2640
3090
|
// src/cli/index.ts
|
|
2641
3091
|
var program = new Command();
|
|
2642
3092
|
program.name("opencode-athena").description(
|
|
2643
|
-
`${
|
|
3093
|
+
`${chalk4.cyan(DISPLAY_NAME)} - ${TAGLINE}
|
|
2644
3094
|
Unified oh-my-opencode + BMAD METHOD toolkit for OpenCode`
|
|
2645
3095
|
).version(VERSION);
|
|
2646
3096
|
program.command("install").description("Install and configure OpenCode Athena").option(
|
|
2647
3097
|
"-p, --preset <preset>",
|
|
2648
3098
|
"Use a preset configuration (minimal, standard, enterprise, solo-quick)",
|
|
2649
3099
|
"standard"
|
|
2650
|
-
).option("-y, --yes", "Skip confirmation prompts", false).option("--advanced", "Show advanced configuration options", false).option("--global", "Install globally (default)", true).option("--local", "Install to current project only", false).option("--list-presets", "List available presets and exit", false).action(async (options) => {
|
|
3100
|
+
).option("-y, --yes", "Skip confirmation prompts", false).option("--advanced", "Show advanced configuration options", false).option("--global", "Install globally (default)", true).option("--local", "Install to current project only", false).option("--list-presets", "List available presets and exit", false).option("--reconfigure", "Force full reconfiguration (ignore existing config)", false).action(async (options) => {
|
|
2651
3101
|
if (options.listPresets) {
|
|
2652
3102
|
displayPresets();
|
|
2653
3103
|
return;
|
|
2654
3104
|
}
|
|
2655
3105
|
await install(options);
|
|
2656
3106
|
});
|
|
3107
|
+
program.command("upgrade").description("Upgrade OpenCode Athena configuration to latest version").option("-y, --yes", "Skip confirmation prompts", false).action(async (options) => {
|
|
3108
|
+
await install({ ...options, preset: void 0, advanced: false, global: true, local: false });
|
|
3109
|
+
});
|
|
2657
3110
|
program.command("update").description("Update OpenCode Athena to latest version").option("--check", "Check for updates without installing", false).action(update);
|
|
2658
3111
|
program.command("doctor").description("Diagnose and fix common issues").option("--fix", "Automatically fix issues", false).action(doctor);
|
|
2659
3112
|
program.command("uninstall").description("Remove OpenCode Athena").option("--keep-config", "Keep configuration files", false).option("--keep-deps", "Keep npm dependencies", false).action(uninstall);
|
|
2660
3113
|
program.command("info").description("Show current configuration and status").action(info);
|
|
2661
3114
|
function displayPresets() {
|
|
2662
|
-
console.log(
|
|
3115
|
+
console.log(chalk4.bold.cyan("\nAvailable Presets:\n"));
|
|
2663
3116
|
const presets = listPresets();
|
|
2664
3117
|
for (const preset of presets) {
|
|
2665
|
-
console.log(
|
|
2666
|
-
console.log(
|
|
3118
|
+
console.log(chalk4.bold(` ${preset.name}`));
|
|
3119
|
+
console.log(chalk4.gray(` ${preset.description}`));
|
|
2667
3120
|
console.log();
|
|
2668
3121
|
}
|
|
2669
|
-
console.log(
|
|
2670
|
-
console.log(
|
|
3122
|
+
console.log(chalk4.gray("Usage: opencode-athena install --preset <name>"));
|
|
3123
|
+
console.log(chalk4.gray(" opencode-athena install --preset standard --yes\n"));
|
|
2671
3124
|
}
|
|
2672
3125
|
program.parse();
|
|
2673
3126
|
//# sourceMappingURL=index.js.map
|