opencode-athena 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +529 -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
|
+
try {
|
|
439
|
+
const pkg = JSON.parse(content);
|
|
440
|
+
if (pkg.version) return pkg.version;
|
|
441
|
+
} catch {
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
return "0.0.0";
|
|
445
|
+
} catch {
|
|
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,273 @@ 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(/[:.]/g, "-");
|
|
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
|
+
|
|
2274
|
+
// src/cli/utils/migrations/runner.ts
|
|
2275
|
+
init_esm_shims();
|
|
2276
|
+
function migrateConfigs(athenaConfig, omoConfig, fromVersion) {
|
|
2277
|
+
const targetVersion = VERSION;
|
|
2278
|
+
const migrationsApplied = [];
|
|
2279
|
+
const breakingChangeWarnings = [];
|
|
2280
|
+
let hasBreakingChanges = false;
|
|
2281
|
+
let currentAthena = { ...athenaConfig };
|
|
2282
|
+
let currentOmo = { ...omoConfig };
|
|
2283
|
+
const normalizedFrom = semver.valid(semver.coerce(fromVersion)) || "0.0.0";
|
|
2284
|
+
const normalizedTarget = semver.valid(semver.coerce(targetVersion)) || VERSION;
|
|
2285
|
+
const sortedMigrations = [...MIGRATIONS].sort((a, b) => {
|
|
2286
|
+
const aVersion = semver.valid(semver.coerce(a.fromVersion)) || "0.0.0";
|
|
2287
|
+
const bVersion = semver.valid(semver.coerce(b.fromVersion)) || "0.0.0";
|
|
2288
|
+
return semver.compare(aVersion, bVersion);
|
|
2289
|
+
});
|
|
2290
|
+
for (const migration of sortedMigrations) {
|
|
2291
|
+
const migrationFrom = semver.valid(semver.coerce(migration.fromVersion)) || "0.0.0";
|
|
2292
|
+
const migrationTo = semver.valid(semver.coerce(migration.toVersion)) || "0.0.0";
|
|
2293
|
+
if (semver.gt(migrationFrom, normalizedFrom)) continue;
|
|
2294
|
+
if (semver.lte(migrationTo, normalizedFrom)) continue;
|
|
2295
|
+
if (semver.gt(migrationTo, normalizedTarget)) continue;
|
|
2296
|
+
if (migration.migrateAthena) {
|
|
2297
|
+
currentAthena = migration.migrateAthena(currentAthena);
|
|
2298
|
+
}
|
|
2299
|
+
if (migration.migrateOmo) {
|
|
2300
|
+
currentOmo = migration.migrateOmo(currentOmo);
|
|
2301
|
+
}
|
|
2302
|
+
migrationsApplied.push(
|
|
2303
|
+
`${migration.fromVersion} \u2192 ${migration.toVersion}: ${migration.description}`
|
|
2304
|
+
);
|
|
2305
|
+
if (isBreakingMigration(migration)) {
|
|
2306
|
+
hasBreakingChanges = true;
|
|
2307
|
+
breakingChangeWarnings.push(
|
|
2308
|
+
`Migration ${migration.fromVersion} \u2192 ${migration.toVersion} contains breaking changes: ${migration.description}`
|
|
2309
|
+
);
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
currentAthena.version = targetVersion;
|
|
2313
|
+
return {
|
|
2314
|
+
fromVersion,
|
|
2315
|
+
toVersion: targetVersion,
|
|
2316
|
+
migrationsApplied,
|
|
2317
|
+
athenaConfig: currentAthena,
|
|
2318
|
+
omoConfig: currentOmo,
|
|
2319
|
+
hasBreakingChanges,
|
|
2320
|
+
breakingChangeWarnings
|
|
2321
|
+
};
|
|
2322
|
+
}
|
|
2323
|
+
function isBreakingMigration(migration) {
|
|
2324
|
+
const fromMajor = semver.major(semver.coerce(migration.fromVersion) || "0.0.0");
|
|
2325
|
+
const toMajor = semver.major(semver.coerce(migration.toVersion) || "0.0.0");
|
|
2326
|
+
return toMajor > fromMajor;
|
|
2327
|
+
}
|
|
2328
|
+
|
|
2040
2329
|
// src/cli/utils/preset-loader.ts
|
|
2041
2330
|
init_esm_shims();
|
|
2042
2331
|
var PRESET_NAMES = ["minimal", "standard", "enterprise", "solo-quick"];
|
|
@@ -2203,9 +2492,168 @@ function formatPresetSummary(preset, name) {
|
|
|
2203
2492
|
}
|
|
2204
2493
|
|
|
2205
2494
|
// src/cli/commands/install.ts
|
|
2495
|
+
function detectInstallMode(options, configs) {
|
|
2496
|
+
if (options.reconfigure) {
|
|
2497
|
+
return { mode: "reconfigure" };
|
|
2498
|
+
}
|
|
2499
|
+
if (!configs.athena) {
|
|
2500
|
+
return { mode: "fresh" };
|
|
2501
|
+
}
|
|
2502
|
+
return {
|
|
2503
|
+
mode: "upgrade",
|
|
2504
|
+
existingVersion: configs.athenaVersion || "0.0.1",
|
|
2505
|
+
configs
|
|
2506
|
+
};
|
|
2507
|
+
}
|
|
2508
|
+
async function runUpgradeFlow(configs, existingVersion, options) {
|
|
2509
|
+
const { athena, omo } = configs;
|
|
2510
|
+
logger.section("Upgrading Configuration");
|
|
2511
|
+
console.log(chalk4.cyan(`
|
|
2512
|
+
Current version: ${existingVersion}`));
|
|
2513
|
+
console.log(chalk4.cyan(`New version: ${VERSION}
|
|
2514
|
+
`));
|
|
2515
|
+
if (!options.yes) {
|
|
2516
|
+
const proceed = await confirm({
|
|
2517
|
+
message: "Upgrade existing installation?",
|
|
2518
|
+
default: true
|
|
2519
|
+
});
|
|
2520
|
+
if (!proceed) {
|
|
2521
|
+
logger.info("Upgrade cancelled.");
|
|
2522
|
+
process.exit(0);
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
const spinner = ora2("Creating backup...").start();
|
|
2526
|
+
const backups = createBackups();
|
|
2527
|
+
const backupCount = [backups.athenaBackup, backups.omoBackup, backups.opencodeBackup].filter(
|
|
2528
|
+
Boolean
|
|
2529
|
+
).length;
|
|
2530
|
+
spinner.succeed(`Created ${backupCount} backup file(s)`);
|
|
2531
|
+
const migrationSpinner = ora2("Applying migrations...").start();
|
|
2532
|
+
const migrationResult = migrateConfigs(athena || {}, omo || {}, existingVersion);
|
|
2533
|
+
if (migrationResult.migrationsApplied.length > 0) {
|
|
2534
|
+
migrationSpinner.succeed(`Applied ${migrationResult.migrationsApplied.length} migration(s)`);
|
|
2535
|
+
for (const migration of migrationResult.migrationsApplied) {
|
|
2536
|
+
console.log(chalk4.gray(` \u2022 ${migration}`));
|
|
2537
|
+
}
|
|
2538
|
+
} else {
|
|
2539
|
+
migrationSpinner.succeed("No migrations needed");
|
|
2540
|
+
}
|
|
2541
|
+
if (migrationResult.hasBreakingChanges && !options.yes) {
|
|
2542
|
+
console.log(chalk4.yellow("\nBreaking changes detected:"));
|
|
2543
|
+
for (const warning of migrationResult.breakingChangeWarnings) {
|
|
2544
|
+
console.log(chalk4.yellow(` \u26A0 ${warning}`));
|
|
2545
|
+
}
|
|
2546
|
+
const continueUpgrade = await confirm({
|
|
2547
|
+
message: "Continue with upgrade despite breaking changes?",
|
|
2548
|
+
default: false
|
|
2549
|
+
});
|
|
2550
|
+
if (!continueUpgrade) {
|
|
2551
|
+
logger.info("Upgrade cancelled. Your backup files are preserved.");
|
|
2552
|
+
process.exit(0);
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
const existingSubscriptions = extractSubscriptions(migrationResult.athenaConfig);
|
|
2556
|
+
const existingModels = extractModels(migrationResult.athenaConfig);
|
|
2557
|
+
const existingMethodology = extractMethodology(migrationResult.athenaConfig);
|
|
2558
|
+
const existingFeatures = extractFeatures(migrationResult.athenaConfig);
|
|
2559
|
+
const existingAdvanced = extractAdvanced(migrationResult.athenaConfig);
|
|
2560
|
+
logger.section("Preserved Configuration");
|
|
2561
|
+
if (existingSubscriptions) {
|
|
2562
|
+
console.log(chalk4.bold("Subscriptions:"));
|
|
2563
|
+
if (existingSubscriptions.hasClaude)
|
|
2564
|
+
console.log(chalk4.green(` \u2713 Claude (${existingSubscriptions.claudeTier})`));
|
|
2565
|
+
if (existingSubscriptions.hasOpenAI) console.log(chalk4.green(" \u2713 OpenAI"));
|
|
2566
|
+
if (existingSubscriptions.hasGoogle)
|
|
2567
|
+
console.log(chalk4.green(` \u2713 Google (${existingSubscriptions.googleAuth})`));
|
|
2568
|
+
if (existingSubscriptions.hasGitHubCopilot)
|
|
2569
|
+
console.log(chalk4.green(` \u2713 GitHub Copilot (${existingSubscriptions.copilotPlan})`));
|
|
2570
|
+
}
|
|
2571
|
+
if (existingModels) {
|
|
2572
|
+
console.log(chalk4.bold("\nModel Assignments:"));
|
|
2573
|
+
console.log(chalk4.green(` \u2713 Sisyphus: ${existingModels.sisyphus}`));
|
|
2574
|
+
console.log(chalk4.green(` \u2713 Oracle: ${existingModels.oracle}`));
|
|
2575
|
+
console.log(chalk4.green(` \u2713 Librarian: ${existingModels.librarian}`));
|
|
2576
|
+
}
|
|
2577
|
+
console.log();
|
|
2578
|
+
const newFeatures = detectNewFeatures(migrationResult.athenaConfig);
|
|
2579
|
+
const updatedFeatures = existingFeatures;
|
|
2580
|
+
if (newFeatures.length > 0 && !options.yes) {
|
|
2581
|
+
logger.section("New Features Available");
|
|
2582
|
+
for (const feature of newFeatures) {
|
|
2583
|
+
if (feature === "autoGitOperations") {
|
|
2584
|
+
const enable = await confirm({
|
|
2585
|
+
message: "Enable automatic git operations? (commits, pushes by agents)",
|
|
2586
|
+
default: false
|
|
2587
|
+
});
|
|
2588
|
+
if (updatedFeatures) {
|
|
2589
|
+
if (enable) {
|
|
2590
|
+
updatedFeatures.enabledFeatures.push("auto-git");
|
|
2591
|
+
}
|
|
2592
|
+
}
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2596
|
+
let finalSubscriptions = existingSubscriptions;
|
|
2597
|
+
if (!options.yes) {
|
|
2598
|
+
const changeSubscriptions = await confirm({
|
|
2599
|
+
message: "Do you want to modify your LLM subscriptions?",
|
|
2600
|
+
default: false
|
|
2601
|
+
});
|
|
2602
|
+
if (changeSubscriptions) {
|
|
2603
|
+
logger.section("LLM Subscriptions");
|
|
2604
|
+
finalSubscriptions = await gatherSubscriptions();
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
if (!finalSubscriptions) {
|
|
2608
|
+
logger.error("Could not extract subscription information from existing config.");
|
|
2609
|
+
logger.info("Please run with --reconfigure to set up from scratch.");
|
|
2610
|
+
process.exit(1);
|
|
2611
|
+
}
|
|
2612
|
+
const fullAnswers = {
|
|
2613
|
+
subscriptions: finalSubscriptions,
|
|
2614
|
+
models: existingModels || {
|
|
2615
|
+
sisyphus: "",
|
|
2616
|
+
oracle: "",
|
|
2617
|
+
librarian: ""
|
|
2618
|
+
},
|
|
2619
|
+
methodology: existingMethodology || {
|
|
2620
|
+
defaultTrack: "bmad-method",
|
|
2621
|
+
autoStatusUpdate: true
|
|
2622
|
+
},
|
|
2623
|
+
features: updatedFeatures || {
|
|
2624
|
+
enabledFeatures: [],
|
|
2625
|
+
mcps: []
|
|
2626
|
+
},
|
|
2627
|
+
advanced: existingAdvanced || {
|
|
2628
|
+
parallelStoryLimit: 3,
|
|
2629
|
+
experimental: []
|
|
2630
|
+
},
|
|
2631
|
+
installLocation: options.local ? "local" : "global"
|
|
2632
|
+
};
|
|
2633
|
+
const merged = mergeConfigs({
|
|
2634
|
+
existingAthena: migrationResult.athenaConfig,
|
|
2635
|
+
fullAnswers
|
|
2636
|
+
});
|
|
2637
|
+
const writeSpinner = ora2("Writing configuration...").start();
|
|
2638
|
+
writeMergedConfigs(merged);
|
|
2639
|
+
writeSpinner.succeed("Configuration files updated");
|
|
2640
|
+
const fileManager = new FileManager();
|
|
2641
|
+
const commandsSpinner = ora2("Updating bridge commands...").start();
|
|
2642
|
+
const copiedCommands = await fileManager.copyCommands();
|
|
2643
|
+
commandsSpinner.succeed(`Updated ${copiedCommands.length} bridge commands`);
|
|
2644
|
+
logger.successBanner(`UPGRADED TO OPENCODE ATHENA ${VERSION}!`);
|
|
2645
|
+
if (backups.athenaBackup || backups.omoBackup || backups.opencodeBackup) {
|
|
2646
|
+
console.log(chalk4.gray("\nBackups saved:"));
|
|
2647
|
+
if (backups.athenaBackup) console.log(chalk4.gray(` \u2022 ${backups.athenaBackup}`));
|
|
2648
|
+
if (backups.omoBackup) console.log(chalk4.gray(` \u2022 ${backups.omoBackup}`));
|
|
2649
|
+
if (backups.opencodeBackup) console.log(chalk4.gray(` \u2022 ${backups.opencodeBackup}`));
|
|
2650
|
+
}
|
|
2651
|
+
console.log(chalk4.gray("\nRestart OpenCode to use the upgraded configuration."));
|
|
2652
|
+
console.log();
|
|
2653
|
+
}
|
|
2206
2654
|
async function install(options) {
|
|
2207
2655
|
logger.banner();
|
|
2208
|
-
const spinner =
|
|
2656
|
+
const spinner = ora2("Checking prerequisites...").start();
|
|
2209
2657
|
const prereqs = await checkPrerequisites();
|
|
2210
2658
|
if (!prereqs.node.installed) {
|
|
2211
2659
|
spinner.fail("Node.js not found");
|
|
@@ -2225,15 +2673,14 @@ async function install(options) {
|
|
|
2225
2673
|
} else {
|
|
2226
2674
|
spinner.succeed(`OpenCode ${prereqs.opencode.version || ""} detected`);
|
|
2227
2675
|
}
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
}
|
|
2676
|
+
const existingConfigs = loadExistingConfigs();
|
|
2677
|
+
const modeResult = detectInstallMode(options, existingConfigs);
|
|
2678
|
+
if (modeResult.mode === "upgrade" && modeResult.configs && modeResult.existingVersion) {
|
|
2679
|
+
await runUpgradeFlow(modeResult.configs, modeResult.existingVersion, options);
|
|
2680
|
+
return;
|
|
2681
|
+
}
|
|
2682
|
+
if (modeResult.mode === "reconfigure") {
|
|
2683
|
+
logger.info("Reconfiguring from scratch (--reconfigure flag)");
|
|
2237
2684
|
}
|
|
2238
2685
|
let preset = null;
|
|
2239
2686
|
let presetDefaults = null;
|
|
@@ -2268,14 +2715,14 @@ async function install(options) {
|
|
|
2268
2715
|
if (preset && presetDefaults && presetName) {
|
|
2269
2716
|
const modelWarnings = validatePresetModels(presetDefaults.models, subscriptions);
|
|
2270
2717
|
if (modelWarnings.length > 0) {
|
|
2271
|
-
console.log(
|
|
2718
|
+
console.log(chalk4.yellow("\nPreset model compatibility warnings:"));
|
|
2272
2719
|
for (const warning of modelWarnings) {
|
|
2273
|
-
console.log(
|
|
2720
|
+
console.log(chalk4.yellow(` - ${warning}`));
|
|
2274
2721
|
}
|
|
2275
2722
|
console.log();
|
|
2276
2723
|
}
|
|
2277
|
-
console.log(
|
|
2278
|
-
console.log(
|
|
2724
|
+
console.log(chalk4.bold("\nPreset Configuration:\n"));
|
|
2725
|
+
console.log(chalk4.gray(formatPresetSummary(preset, presetName)));
|
|
2279
2726
|
console.log();
|
|
2280
2727
|
if (options.yes) {
|
|
2281
2728
|
shouldCustomize = false;
|
|
@@ -2345,10 +2792,10 @@ async function install(options) {
|
|
|
2345
2792
|
};
|
|
2346
2793
|
const generator = new ConfigGenerator(answers);
|
|
2347
2794
|
const files = await generator.generate();
|
|
2348
|
-
console.log(
|
|
2795
|
+
console.log(chalk4.bold("Files to be created/modified:\n"));
|
|
2349
2796
|
for (const file of files) {
|
|
2350
|
-
const action = file.exists ?
|
|
2351
|
-
console.log(
|
|
2797
|
+
const action = file.exists ? chalk4.yellow("update") : chalk4.green("create");
|
|
2798
|
+
console.log(chalk4.gray(` [${action}] ${file.path}`));
|
|
2352
2799
|
}
|
|
2353
2800
|
console.log();
|
|
2354
2801
|
if (!options.yes) {
|
|
@@ -2361,7 +2808,7 @@ async function install(options) {
|
|
|
2361
2808
|
process.exit(0);
|
|
2362
2809
|
}
|
|
2363
2810
|
}
|
|
2364
|
-
const installSpinner =
|
|
2811
|
+
const installSpinner = ora2("Installing OpenCode Athena...").start();
|
|
2365
2812
|
try {
|
|
2366
2813
|
const fileManager = new FileManager(generator.getConfigDir());
|
|
2367
2814
|
await fileManager.writeFiles(files);
|
|
@@ -2418,30 +2865,30 @@ function getValidModelOrFirst(modelId, availableModels) {
|
|
|
2418
2865
|
function printNextSteps(subscriptions) {
|
|
2419
2866
|
const steps = [];
|
|
2420
2867
|
if (subscriptions.hasClaude) {
|
|
2421
|
-
steps.push(`Run: ${
|
|
2868
|
+
steps.push(`Run: ${chalk4.cyan("opencode auth login")} -> Select Anthropic -> Claude Pro/Max`);
|
|
2422
2869
|
}
|
|
2423
2870
|
if (subscriptions.hasOpenAI) {
|
|
2424
|
-
steps.push(`Run: ${
|
|
2871
|
+
steps.push(`Run: ${chalk4.cyan("opencode auth login")} -> Select OpenAI -> ChatGPT Plus/Pro`);
|
|
2425
2872
|
}
|
|
2426
2873
|
if (subscriptions.hasGoogle) {
|
|
2427
|
-
steps.push(`Run: ${
|
|
2874
|
+
steps.push(`Run: ${chalk4.cyan("opencode auth login")} -> Select Google -> OAuth with Google`);
|
|
2428
2875
|
}
|
|
2429
2876
|
if (subscriptions.hasGitHubCopilot) {
|
|
2430
|
-
steps.push(`Run: ${
|
|
2877
|
+
steps.push(`Run: ${chalk4.cyan("opencode auth login")} -> Select GitHub Copilot`);
|
|
2431
2878
|
}
|
|
2432
2879
|
logger.successBanner("OPENCODE ATHENA INSTALLED SUCCESSFULLY!");
|
|
2433
|
-
console.log(
|
|
2880
|
+
console.log(chalk4.bold("Next Steps:\n"));
|
|
2434
2881
|
steps.forEach((step, i) => {
|
|
2435
2882
|
console.log(` ${i + 1}. ${step}`);
|
|
2436
2883
|
});
|
|
2437
|
-
console.log(
|
|
2438
|
-
console.log(` ${
|
|
2439
|
-
console.log(` ${
|
|
2440
|
-
console.log(` ${
|
|
2441
|
-
console.log(
|
|
2442
|
-
console.log(` ${
|
|
2884
|
+
console.log(chalk4.bold("\nThen start OpenCode and try:\n"));
|
|
2885
|
+
console.log(` ${chalk4.cyan("/athena-dev")} Implement a BMAD story with Sisyphus`);
|
|
2886
|
+
console.log(` ${chalk4.cyan("/athena-status")} Check sprint status`);
|
|
2887
|
+
console.log(` ${chalk4.cyan("/athena-info")} View toolkit configuration`);
|
|
2888
|
+
console.log(chalk4.bold("\nFor BMAD project setup:\n"));
|
|
2889
|
+
console.log(` ${chalk4.cyan("npx bmad-method@alpha install")} Install BMAD in your project`);
|
|
2443
2890
|
console.log(
|
|
2444
|
-
|
|
2891
|
+
chalk4.gray("\nDocumentation: https://github.com/ZebulonRouseFrantzich/opencode-athena")
|
|
2445
2892
|
);
|
|
2446
2893
|
console.log();
|
|
2447
2894
|
}
|
|
@@ -2462,7 +2909,7 @@ async function uninstall(options) {
|
|
|
2462
2909
|
}
|
|
2463
2910
|
logger.section("Uninstalling OpenCode Athena");
|
|
2464
2911
|
const fileManager = new FileManager();
|
|
2465
|
-
const commandsSpinner =
|
|
2912
|
+
const commandsSpinner = ora2("Removing bridge commands...").start();
|
|
2466
2913
|
try {
|
|
2467
2914
|
const removedCommands = await fileManager.removeCommands();
|
|
2468
2915
|
if (removedCommands.length > 0) {
|
|
@@ -2475,7 +2922,7 @@ async function uninstall(options) {
|
|
|
2475
2922
|
logger.error(err instanceof Error ? err.message : String(err));
|
|
2476
2923
|
}
|
|
2477
2924
|
if (!options.keepConfig) {
|
|
2478
|
-
const configSpinner =
|
|
2925
|
+
const configSpinner = ora2("Removing configuration files...").start();
|
|
2479
2926
|
try {
|
|
2480
2927
|
const removedFiles = await fileManager.removeConfigFiles();
|
|
2481
2928
|
if (removedFiles.length > 0) {
|
|
@@ -2490,7 +2937,7 @@ async function uninstall(options) {
|
|
|
2490
2937
|
} else {
|
|
2491
2938
|
logger.info("Keeping configuration files (--keep-config)");
|
|
2492
2939
|
}
|
|
2493
|
-
const opencodeSpinner =
|
|
2940
|
+
const opencodeSpinner = ora2("Updating opencode.json...").start();
|
|
2494
2941
|
try {
|
|
2495
2942
|
const updated = await fileManager.removeFromOpencodeConfig();
|
|
2496
2943
|
if (updated) {
|
|
@@ -2503,7 +2950,7 @@ async function uninstall(options) {
|
|
|
2503
2950
|
logger.error(err instanceof Error ? err.message : String(err));
|
|
2504
2951
|
}
|
|
2505
2952
|
if (!options.keepDeps) {
|
|
2506
|
-
const depsSpinner =
|
|
2953
|
+
const depsSpinner = ora2("Removing npm dependencies...").start();
|
|
2507
2954
|
try {
|
|
2508
2955
|
const packagesToRemove = [
|
|
2509
2956
|
"oh-my-opencode",
|
|
@@ -2522,7 +2969,7 @@ async function uninstall(options) {
|
|
|
2522
2969
|
logger.success("OpenCode Athena has been uninstalled.");
|
|
2523
2970
|
if (options.keepConfig) {
|
|
2524
2971
|
logger.info("Configuration files were preserved.");
|
|
2525
|
-
logger.info(`Run ${
|
|
2972
|
+
logger.info(`Run ${chalk4.cyan("opencode-athena install")} to reinstall with existing config.`);
|
|
2526
2973
|
}
|
|
2527
2974
|
console.log();
|
|
2528
2975
|
}
|
|
@@ -2550,7 +2997,7 @@ async function checkPackageUpdate(name, currentVersion) {
|
|
|
2550
2997
|
async function update(options) {
|
|
2551
2998
|
logger.banner();
|
|
2552
2999
|
logger.section("Checking for Updates");
|
|
2553
|
-
const spinner =
|
|
3000
|
+
const spinner = ora2("Checking package versions...").start();
|
|
2554
3001
|
const installedPlugins = await getInstalledPlugins();
|
|
2555
3002
|
const packagesToCheck = [
|
|
2556
3003
|
"oh-my-opencode",
|
|
@@ -2578,7 +3025,7 @@ async function update(options) {
|
|
|
2578
3025
|
logger.section("Package Versions");
|
|
2579
3026
|
const updatesAvailable = updates.filter((u) => u.updateAvailable);
|
|
2580
3027
|
for (const pkg of updates) {
|
|
2581
|
-
const status = pkg.updateAvailable ?
|
|
3028
|
+
const status = pkg.updateAvailable ? chalk4.yellow(`${pkg.current} -> ${pkg.latest}`) : chalk4.green(pkg.current);
|
|
2582
3029
|
logger.keyValue(pkg.name, status);
|
|
2583
3030
|
}
|
|
2584
3031
|
console.log();
|
|
@@ -2589,7 +3036,7 @@ async function update(options) {
|
|
|
2589
3036
|
logger.info(`${updatesAvailable.length} update(s) available`);
|
|
2590
3037
|
if (options.check) {
|
|
2591
3038
|
console.log();
|
|
2592
|
-
logger.info(`Run ${
|
|
3039
|
+
logger.info(`Run ${chalk4.cyan("opencode-athena update")} (without --check) to apply updates.`);
|
|
2593
3040
|
return;
|
|
2594
3041
|
}
|
|
2595
3042
|
const proceed = await confirm({
|
|
@@ -2604,7 +3051,7 @@ async function update(options) {
|
|
|
2604
3051
|
const fileManager = new FileManager();
|
|
2605
3052
|
const athenaUpdate = updatesAvailable.find((u) => u.name === "opencode-athena");
|
|
2606
3053
|
if (athenaUpdate) {
|
|
2607
|
-
const athenaSpinner =
|
|
3054
|
+
const athenaSpinner = ora2("Updating opencode-athena...").start();
|
|
2608
3055
|
try {
|
|
2609
3056
|
await execAsync3("npm install -g opencode-athena@latest");
|
|
2610
3057
|
athenaSpinner.succeed(`opencode-athena updated to ${athenaUpdate.latest}`);
|
|
@@ -2615,7 +3062,7 @@ async function update(options) {
|
|
|
2615
3062
|
}
|
|
2616
3063
|
const pluginUpdates = updatesAvailable.filter((u) => u.name !== "opencode-athena");
|
|
2617
3064
|
if (pluginUpdates.length > 0) {
|
|
2618
|
-
const pluginSpinner =
|
|
3065
|
+
const pluginSpinner = ora2("Updating plugins...").start();
|
|
2619
3066
|
try {
|
|
2620
3067
|
const packages = pluginUpdates.map((u) => `${u.name}@latest`);
|
|
2621
3068
|
await fileManager.installDependencies(packages);
|
|
@@ -2625,7 +3072,7 @@ async function update(options) {
|
|
|
2625
3072
|
logger.error(err instanceof Error ? err.message : String(err));
|
|
2626
3073
|
}
|
|
2627
3074
|
}
|
|
2628
|
-
const commandsSpinner =
|
|
3075
|
+
const commandsSpinner = ora2("Updating bridge commands...").start();
|
|
2629
3076
|
try {
|
|
2630
3077
|
await fileManager.copyCommands();
|
|
2631
3078
|
commandsSpinner.succeed("Bridge commands updated");
|
|
@@ -2640,34 +3087,37 @@ async function update(options) {
|
|
|
2640
3087
|
// src/cli/index.ts
|
|
2641
3088
|
var program = new Command();
|
|
2642
3089
|
program.name("opencode-athena").description(
|
|
2643
|
-
`${
|
|
3090
|
+
`${chalk4.cyan(DISPLAY_NAME)} - ${TAGLINE}
|
|
2644
3091
|
Unified oh-my-opencode + BMAD METHOD toolkit for OpenCode`
|
|
2645
3092
|
).version(VERSION);
|
|
2646
3093
|
program.command("install").description("Install and configure OpenCode Athena").option(
|
|
2647
3094
|
"-p, --preset <preset>",
|
|
2648
3095
|
"Use a preset configuration (minimal, standard, enterprise, solo-quick)",
|
|
2649
3096
|
"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) => {
|
|
3097
|
+
).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
3098
|
if (options.listPresets) {
|
|
2652
3099
|
displayPresets();
|
|
2653
3100
|
return;
|
|
2654
3101
|
}
|
|
2655
3102
|
await install(options);
|
|
2656
3103
|
});
|
|
3104
|
+
program.command("upgrade").description("Upgrade OpenCode Athena configuration to latest version").option("-y, --yes", "Skip confirmation prompts", false).action(async (options) => {
|
|
3105
|
+
await install({ ...options, preset: "none", advanced: false, global: true, local: false });
|
|
3106
|
+
});
|
|
2657
3107
|
program.command("update").description("Update OpenCode Athena to latest version").option("--check", "Check for updates without installing", false).action(update);
|
|
2658
3108
|
program.command("doctor").description("Diagnose and fix common issues").option("--fix", "Automatically fix issues", false).action(doctor);
|
|
2659
3109
|
program.command("uninstall").description("Remove OpenCode Athena").option("--keep-config", "Keep configuration files", false).option("--keep-deps", "Keep npm dependencies", false).action(uninstall);
|
|
2660
3110
|
program.command("info").description("Show current configuration and status").action(info);
|
|
2661
3111
|
function displayPresets() {
|
|
2662
|
-
console.log(
|
|
3112
|
+
console.log(chalk4.bold.cyan("\nAvailable Presets:\n"));
|
|
2663
3113
|
const presets = listPresets();
|
|
2664
3114
|
for (const preset of presets) {
|
|
2665
|
-
console.log(
|
|
2666
|
-
console.log(
|
|
3115
|
+
console.log(chalk4.bold(` ${preset.name}`));
|
|
3116
|
+
console.log(chalk4.gray(` ${preset.description}`));
|
|
2667
3117
|
console.log();
|
|
2668
3118
|
}
|
|
2669
|
-
console.log(
|
|
2670
|
-
console.log(
|
|
3119
|
+
console.log(chalk4.gray("Usage: opencode-athena install --preset <name>"));
|
|
3120
|
+
console.log(chalk4.gray(" opencode-athena install --preset standard --yes\n"));
|
|
2671
3121
|
}
|
|
2672
3122
|
program.parse();
|
|
2673
3123
|
//# sourceMappingURL=index.js.map
|