opencode-athena 0.8.1-beta.2 → 0.8.1-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -393,7 +393,7 @@ For full model capabilities, use direct provider subscriptions when possible.
393
393
  │ ┌─────────────────────────────────────────────────────────────────────┐ │
394
394
  │ │ CLI Installer │ │
395
395
  │ │ npx opencode-athena install npx opencode-athena doctor │ │
396
- │ │ npx opencode-athena update npx opencode-athena uninstall │ │
396
+ │ │ npx opencode-athena upgrade npx opencode-athena uninstall │ │
397
397
  │ └─────────────────────────────────────────────────────────────────────┘ │
398
398
  │ │
399
399
  │ ┌─────────────────────────────────────────────────────────────────────┐ │
package/dist/cli/index.js CHANGED
@@ -7,7 +7,7 @@ import { Command } from 'commander';
7
7
  import { existsSync, readFileSync, mkdirSync, copyFileSync, unlinkSync, readdirSync, renameSync, writeFileSync } from 'fs';
8
8
  import { homedir } from 'os';
9
9
  import { exec, execSync } from 'child_process';
10
- import ora2 from 'ora';
10
+ import ora4 from 'ora';
11
11
  import { mkdir, writeFile, readdir, copyFile, rm } from 'fs/promises';
12
12
  import { promisify } from 'util';
13
13
  import 'yaml';
@@ -1152,7 +1152,7 @@ async function doctor(options) {
1152
1152
  status: omoInstalled.installed ? "pass" : "fail",
1153
1153
  message: omoInstalled.installed ? `Version ${omoInstalled.version}` : "Not installed",
1154
1154
  fix: async () => {
1155
- const spinner = ora2("Installing oh-my-opencode...").start();
1155
+ const spinner = ora4("Installing oh-my-opencode...").start();
1156
1156
  try {
1157
1157
  await fileManager.installDependencies(["oh-my-opencode"]);
1158
1158
  spinner.succeed("oh-my-opencode installed");
@@ -1168,7 +1168,7 @@ async function doctor(options) {
1168
1168
  status: commandsDirExists ? "pass" : "warn",
1169
1169
  message: commandsDirExists ? "Exists" : "Not found",
1170
1170
  fix: async () => {
1171
- const spinner = ora2("Creating commands directory...").start();
1171
+ const spinner = ora4("Creating commands directory...").start();
1172
1172
  try {
1173
1173
  await fileManager.ensureDir(CONFIG_PATHS.commandsDir);
1174
1174
  await fileManager.copyCommands();
@@ -2583,7 +2583,7 @@ Current version: ${existingVersion}`));
2583
2583
  process.exit(0);
2584
2584
  }
2585
2585
  }
2586
- const spinner = ora2("Creating backup...").start();
2586
+ const spinner = ora4("Creating backup...").start();
2587
2587
  const backups = createBackups();
2588
2588
  const backupCount = [backups.athenaBackup, backups.omoBackup, backups.opencodeBackup].filter(
2589
2589
  Boolean
@@ -2597,7 +2597,7 @@ Current version: ${existingVersion}`));
2597
2597
  moved.push(`${fileMigrationResult.backupsMoved} backup(s)`);
2598
2598
  console.log(chalk4.gray(` Migrated ${moved.join(", ")} to new athena/ directory`));
2599
2599
  }
2600
- const migrationSpinner = ora2("Applying migrations...").start();
2600
+ const migrationSpinner = ora4("Applying migrations...").start();
2601
2601
  const migrationResult = migrateConfigs(athena || {}, omo || {}, existingVersion);
2602
2602
  if (migrationResult.migrationsApplied.length > 0) {
2603
2603
  migrationSpinner.succeed(`Applied ${migrationResult.migrationsApplied.length} migration(s)`);
@@ -2702,11 +2702,18 @@ Current version: ${existingVersion}`));
2702
2702
  existingAthena: migrationResult.athenaConfig,
2703
2703
  fullAnswers
2704
2704
  });
2705
- const writeSpinner = ora2("Writing configuration...").start();
2705
+ const writeSpinner = ora4("Writing configuration...").start();
2706
2706
  writeMergedConfigs(merged);
2707
2707
  writeSpinner.succeed("Configuration files updated");
2708
2708
  const fileManager = new FileManager();
2709
- const commandsSpinner = ora2("Updating bridge commands...").start();
2709
+ const generator = new ConfigGenerator(fullAnswers);
2710
+ const packages = generator.getRequiredPackages();
2711
+ if (packages.length > 0) {
2712
+ const installSpinner = ora4(`Installing packages: ${packages.join(", ")}...`).start();
2713
+ await fileManager.installDependencies(packages);
2714
+ installSpinner.succeed(`Installed ${packages.length} package(s)`);
2715
+ }
2716
+ const commandsSpinner = ora4("Updating bridge commands...").start();
2710
2717
  const copiedCommands = await fileManager.copyCommands();
2711
2718
  commandsSpinner.succeed(`Updated ${copiedCommands.length} bridge commands`);
2712
2719
  logger.successBanner(`UPGRADED TO OPENCODE ATHENA ${VERSION}!`);
@@ -2721,7 +2728,7 @@ Current version: ${existingVersion}`));
2721
2728
  }
2722
2729
  async function install(options) {
2723
2730
  logger.banner();
2724
- const spinner = ora2("Checking prerequisites...").start();
2731
+ const spinner = ora4("Checking prerequisites...").start();
2725
2732
  const prereqs = await checkPrerequisites();
2726
2733
  if (!prereqs.node.installed) {
2727
2734
  spinner.fail("Node.js not found");
@@ -2876,7 +2883,7 @@ async function install(options) {
2876
2883
  process.exit(0);
2877
2884
  }
2878
2885
  }
2879
- const installSpinner = ora2("Installing OpenCode Athena...").start();
2886
+ const installSpinner = ora4("Installing OpenCode Athena...").start();
2880
2887
  try {
2881
2888
  const fileManager = new FileManager(generator.getConfigDir());
2882
2889
  await fileManager.writeFiles(files);
@@ -2977,7 +2984,7 @@ async function uninstall(options) {
2977
2984
  }
2978
2985
  logger.section("Uninstalling OpenCode Athena");
2979
2986
  const fileManager = new FileManager();
2980
- const commandsSpinner = ora2("Removing bridge commands...").start();
2987
+ const commandsSpinner = ora4("Removing bridge commands...").start();
2981
2988
  try {
2982
2989
  const removedCommands = await fileManager.removeCommands();
2983
2990
  if (removedCommands.length > 0) {
@@ -2990,7 +2997,7 @@ async function uninstall(options) {
2990
2997
  logger.error(err instanceof Error ? err.message : String(err));
2991
2998
  }
2992
2999
  if (!options.keepConfig) {
2993
- const configSpinner = ora2("Removing configuration files...").start();
3000
+ const configSpinner = ora4("Removing configuration files...").start();
2994
3001
  try {
2995
3002
  const removedFiles = await fileManager.removeConfigFiles();
2996
3003
  if (removedFiles.length > 0) {
@@ -3005,7 +3012,7 @@ async function uninstall(options) {
3005
3012
  } else {
3006
3013
  logger.info("Keeping configuration files (--keep-config)");
3007
3014
  }
3008
- const opencodeSpinner = ora2("Updating opencode.json...").start();
3015
+ const opencodeSpinner = ora4("Updating opencode.json...").start();
3009
3016
  try {
3010
3017
  const updated = await fileManager.removeFromOpencodeConfig();
3011
3018
  if (updated) {
@@ -3018,7 +3025,7 @@ async function uninstall(options) {
3018
3025
  logger.error(err instanceof Error ? err.message : String(err));
3019
3026
  }
3020
3027
  if (!options.keepDeps) {
3021
- const depsSpinner = ora2("Removing npm dependencies...").start();
3028
+ const depsSpinner = ora4("Removing npm dependencies...").start();
3022
3029
  try {
3023
3030
  const packagesToRemove = [
3024
3031
  "oh-my-opencode",
@@ -3042,7 +3049,7 @@ async function uninstall(options) {
3042
3049
  console.log();
3043
3050
  }
3044
3051
 
3045
- // src/cli/commands/update.ts
3052
+ // src/cli/commands/upgrade.ts
3046
3053
  init_esm_shims();
3047
3054
  var execAsync3 = promisify(exec);
3048
3055
  function detectReleaseChannel(version) {
@@ -3068,10 +3075,17 @@ async function checkPackageUpdate(name, currentVersion) {
3068
3075
  updateAvailable: hasUpdate
3069
3076
  };
3070
3077
  }
3071
- async function update(options) {
3078
+ async function upgrade(options) {
3072
3079
  logger.banner();
3080
+ const configs = loadExistingConfigs();
3081
+ if (!configs.athena) {
3082
+ logger.error("No existing Athena installation found.");
3083
+ logger.info(`Run ${chalk4.cyan("opencode-athena install")} to install for the first time.`);
3084
+ process.exit(1);
3085
+ }
3086
+ const existingVersion = configs.athenaVersion || "0.0.1";
3073
3087
  logger.section("Checking for Updates");
3074
- const spinner = ora2("Checking package versions...").start();
3088
+ const spinner = ora4("Checking package versions...").start();
3075
3089
  const installedPlugins = await getInstalledPlugins();
3076
3090
  const packagesToCheck = [
3077
3091
  "oh-my-opencode",
@@ -3105,29 +3119,160 @@ async function update(options) {
3105
3119
  logger.keyValue(pkg.name, status);
3106
3120
  }
3107
3121
  console.log();
3108
- if (updatesAvailable.length === 0) {
3122
+ if (updatesAvailable.length === 0 && existingVersion === VERSION) {
3109
3123
  logger.success("All packages are up to date!");
3110
3124
  return;
3111
3125
  }
3112
- logger.info(`${updatesAvailable.length} update(s) available`);
3126
+ if (updatesAvailable.length > 0) {
3127
+ logger.info(`${updatesAvailable.length} package update(s) available`);
3128
+ }
3129
+ const coercedExisting = semver__default.coerce(existingVersion);
3130
+ const coercedTarget = semver__default.coerce(VERSION);
3131
+ if (coercedExisting && coercedTarget && semver__default.lt(coercedExisting, coercedTarget)) {
3132
+ logger.info(`Configuration upgrade needed: ${existingVersion} -> ${VERSION}`);
3133
+ }
3113
3134
  if (options.check) {
3114
3135
  console.log();
3115
- logger.info(`Run ${chalk4.cyan("opencode-athena update")} (without --check) to apply updates.`);
3136
+ logger.info(
3137
+ `Run ${chalk4.cyan("opencode-athena upgrade")} (without --check) to apply upgrades.`
3138
+ );
3116
3139
  return;
3117
3140
  }
3118
- const proceed = await confirm({
3119
- message: `Update ${updatesAvailable.length} package(s)?`,
3120
- default: true
3121
- });
3122
- if (!proceed) {
3123
- logger.info("Update cancelled.");
3141
+ const actionCount = updatesAvailable.length + (existingVersion !== VERSION ? 1 : 0);
3142
+ if (actionCount === 0) {
3143
+ logger.success("Everything is up to date!");
3124
3144
  return;
3125
3145
  }
3126
- logger.section("Applying Updates");
3146
+ if (!options.yes) {
3147
+ const proceed = await confirm({
3148
+ message: `Upgrade ${actionCount > 1 ? `${actionCount} item(s)` : "configuration"}?`,
3149
+ default: true
3150
+ });
3151
+ if (!proceed) {
3152
+ logger.info("Upgrade cancelled.");
3153
+ process.exit(0);
3154
+ }
3155
+ }
3156
+ logger.section("Upgrading Configuration");
3157
+ console.log(chalk4.cyan(`
3158
+ Current version: ${existingVersion}`));
3159
+ console.log(chalk4.cyan(`New version: ${VERSION}
3160
+ `));
3161
+ const backupSpinner = ora4("Creating backup...").start();
3162
+ const backups = createBackups();
3163
+ const backupCount = [backups.athenaBackup, backups.omoBackup, backups.opencodeBackup].filter(
3164
+ Boolean
3165
+ ).length;
3166
+ backupSpinner.succeed(`Created ${backupCount} backup file(s)`);
3167
+ const fileMigrationResult = migrateLegacyFiles();
3168
+ if (fileMigrationResult.stateFileMoved || fileMigrationResult.backupsMoved > 0) {
3169
+ const moved = [];
3170
+ if (fileMigrationResult.stateFileMoved) moved.push("state file");
3171
+ if (fileMigrationResult.backupsMoved > 0)
3172
+ moved.push(`${fileMigrationResult.backupsMoved} backup(s)`);
3173
+ console.log(chalk4.gray(` Migrated ${moved.join(", ")} to new athena/ directory`));
3174
+ }
3175
+ const migrationSpinner = ora4("Applying migrations...").start();
3176
+ const migrationResult = migrateConfigs(configs.athena || {}, configs.omo || {}, existingVersion);
3177
+ if (migrationResult.migrationsApplied.length > 0) {
3178
+ migrationSpinner.succeed(`Applied ${migrationResult.migrationsApplied.length} migration(s)`);
3179
+ for (const migration of migrationResult.migrationsApplied) {
3180
+ console.log(chalk4.gray(` \u2022 ${migration}`));
3181
+ }
3182
+ } else {
3183
+ migrationSpinner.succeed("No migrations needed");
3184
+ }
3185
+ if (migrationResult.hasBreakingChanges && !options.yes) {
3186
+ console.log(chalk4.yellow("\nBreaking changes detected:"));
3187
+ for (const warning of migrationResult.breakingChangeWarnings) {
3188
+ console.log(chalk4.yellow(` \u26A0 ${warning}`));
3189
+ }
3190
+ const continueUpgrade = await confirm({
3191
+ message: "Continue with upgrade despite breaking changes?",
3192
+ default: false
3193
+ });
3194
+ if (!continueUpgrade) {
3195
+ logger.info("Upgrade cancelled. Your backup files are preserved.");
3196
+ process.exit(0);
3197
+ }
3198
+ }
3199
+ const existingSubscriptions = extractSubscriptions(migrationResult.athenaConfig);
3200
+ const existingModels = extractModels(migrationResult.athenaConfig);
3201
+ const existingMethodology = extractMethodology(migrationResult.athenaConfig);
3202
+ const existingFeatures = extractFeatures(migrationResult.athenaConfig);
3203
+ const existingAdvanced = extractAdvanced(migrationResult.athenaConfig);
3204
+ logger.section("Preserved Configuration");
3205
+ if (existingSubscriptions) {
3206
+ console.log(chalk4.bold("Subscriptions:"));
3207
+ if (existingSubscriptions.hasClaude)
3208
+ console.log(chalk4.green(` \u2713 Claude (${existingSubscriptions.claudeTier})`));
3209
+ if (existingSubscriptions.hasOpenAI) console.log(chalk4.green(" \u2713 OpenAI"));
3210
+ if (existingSubscriptions.hasGoogle)
3211
+ console.log(chalk4.green(` \u2713 Google (${existingSubscriptions.googleAuth})`));
3212
+ if (existingSubscriptions.hasGitHubCopilot)
3213
+ console.log(chalk4.green(` \u2713 GitHub Copilot (${existingSubscriptions.copilotPlan})`));
3214
+ }
3215
+ if (existingModels) {
3216
+ console.log(chalk4.bold("\nModel Assignments:"));
3217
+ console.log(chalk4.green(` \u2713 Sisyphus: ${existingModels.sisyphus}`));
3218
+ console.log(chalk4.green(` \u2713 Oracle: ${existingModels.oracle}`));
3219
+ console.log(chalk4.green(` \u2713 Librarian: ${existingModels.librarian}`));
3220
+ }
3221
+ console.log();
3222
+ const newFeatures = detectNewFeatures(migrationResult.athenaConfig);
3223
+ if (newFeatures.length > 0 && !options.yes) {
3224
+ logger.section("New Features Available");
3225
+ for (const feature of newFeatures) {
3226
+ if (feature === "autoGitOperations") {
3227
+ const enable = await confirm({
3228
+ message: "Enable automatic git operations? (commits, pushes by agents)",
3229
+ default: false
3230
+ });
3231
+ if (enable) {
3232
+ const migratedFeatures = migrationResult.athenaConfig.features;
3233
+ migratedFeatures.autoGitOperations = true;
3234
+ }
3235
+ }
3236
+ }
3237
+ }
3238
+ if (!existingSubscriptions) {
3239
+ logger.error("Could not extract subscription information from existing config.");
3240
+ logger.info("Please run with --reconfigure to set up from scratch.");
3241
+ process.exit(1);
3242
+ }
3243
+ const fullAnswers = {
3244
+ subscriptions: existingSubscriptions,
3245
+ models: existingModels || {
3246
+ sisyphus: "",
3247
+ oracle: "",
3248
+ librarian: ""
3249
+ },
3250
+ methodology: existingMethodology || {
3251
+ defaultTrack: "bmad-method",
3252
+ autoStatusUpdate: true
3253
+ },
3254
+ features: existingFeatures || {
3255
+ enabledFeatures: [],
3256
+ mcps: []
3257
+ },
3258
+ advanced: existingAdvanced || {
3259
+ parallelStoryLimit: 3,
3260
+ experimental: []
3261
+ },
3262
+ installLocation: "global"
3263
+ };
3264
+ const merged = mergeConfigs({
3265
+ existingAthena: migrationResult.athenaConfig,
3266
+ fullAnswers
3267
+ });
3268
+ const writeSpinner = ora4("Writing configuration...").start();
3269
+ writeMergedConfigs(merged);
3270
+ writeSpinner.succeed("Configuration files updated");
3271
+ logger.section("Updating Packages");
3127
3272
  const fileManager = new FileManager();
3128
3273
  const athenaUpdate = updatesAvailable.find((u) => u.name === "opencode-athena");
3129
3274
  if (athenaUpdate) {
3130
- const athenaSpinner = ora2("Updating opencode-athena...").start();
3275
+ const athenaSpinner = ora4("Updating opencode-athena...").start();
3131
3276
  try {
3132
3277
  const channel = detectReleaseChannel(VERSION);
3133
3278
  await fileManager.installDependencies([`opencode-athena@${channel}`]);
@@ -3136,10 +3281,25 @@ async function update(options) {
3136
3281
  athenaSpinner.fail("Failed to update opencode-athena");
3137
3282
  logger.error(err instanceof Error ? err.message : String(err));
3138
3283
  }
3284
+ } else {
3285
+ const generator = new ConfigGenerator(fullAnswers);
3286
+ const packages = generator.getRequiredPackages();
3287
+ const athenaPackage = packages.find((p) => p.startsWith("opencode-athena"));
3288
+ if (athenaPackage) {
3289
+ const athenaSpinner = ora4("Installing opencode-athena...").start();
3290
+ try {
3291
+ const channel = detectReleaseChannel(VERSION);
3292
+ await fileManager.installDependencies([`opencode-athena@${channel}`]);
3293
+ athenaSpinner.succeed("opencode-athena installed");
3294
+ } catch (err) {
3295
+ athenaSpinner.fail("Failed to install opencode-athena");
3296
+ logger.error(err instanceof Error ? err.message : String(err));
3297
+ }
3298
+ }
3139
3299
  }
3140
3300
  const pluginUpdates = updatesAvailable.filter((u) => u.name !== "opencode-athena");
3141
3301
  if (pluginUpdates.length > 0) {
3142
- const pluginSpinner = ora2("Updating plugins...").start();
3302
+ const pluginSpinner = ora4("Updating plugins...").start();
3143
3303
  try {
3144
3304
  const packages = pluginUpdates.map((u) => `${u.name}@latest`);
3145
3305
  await fileManager.installDependencies(packages);
@@ -3148,17 +3308,37 @@ async function update(options) {
3148
3308
  pluginSpinner.fail("Failed to update plugins");
3149
3309
  logger.error(err instanceof Error ? err.message : String(err));
3150
3310
  }
3311
+ } else {
3312
+ const generator = new ConfigGenerator(fullAnswers);
3313
+ const allPackages = generator.getRequiredPackages();
3314
+ const pluginPackages = allPackages.filter((p) => !p.startsWith("opencode-athena"));
3315
+ if (pluginPackages.length > 0) {
3316
+ const pluginSpinner = ora4(`Installing plugins: ${pluginPackages.join(", ")}...`).start();
3317
+ try {
3318
+ await fileManager.installDependencies(pluginPackages);
3319
+ pluginSpinner.succeed(`Installed ${pluginPackages.length} plugin(s)`);
3320
+ } catch (err) {
3321
+ pluginSpinner.fail("Failed to install plugins");
3322
+ logger.error(err instanceof Error ? err.message : String(err));
3323
+ }
3324
+ }
3151
3325
  }
3152
- const commandsSpinner = ora2("Updating bridge commands...").start();
3326
+ const commandsSpinner = ora4("Updating bridge commands...").start();
3153
3327
  try {
3154
- await fileManager.copyCommands();
3155
- commandsSpinner.succeed("Bridge commands updated");
3328
+ const copiedCommands = await fileManager.copyCommands();
3329
+ commandsSpinner.succeed(`Updated ${copiedCommands.length} bridge commands`);
3156
3330
  } catch (_err) {
3157
3331
  commandsSpinner.warn("Could not update bridge commands");
3158
3332
  }
3333
+ logger.successBanner(`UPGRADED TO OPENCODE ATHENA ${VERSION}!`);
3334
+ if (backups.athenaBackup || backups.omoBackup || backups.opencodeBackup) {
3335
+ console.log(chalk4.gray("\nBackups saved:"));
3336
+ if (backups.athenaBackup) console.log(chalk4.gray(` \u2022 ${backups.athenaBackup}`));
3337
+ if (backups.omoBackup) console.log(chalk4.gray(` \u2022 ${backups.omoBackup}`));
3338
+ if (backups.opencodeBackup) console.log(chalk4.gray(` \u2022 ${backups.opencodeBackup}`));
3339
+ }
3340
+ console.log(chalk4.gray("\nRestart OpenCode to use the upgraded configuration."));
3159
3341
  console.log();
3160
- logger.success("Update complete!");
3161
- logger.info("Restart OpenCode to use the updated version.");
3162
3342
  }
3163
3343
 
3164
3344
  // src/cli/index.ts
@@ -3178,10 +3358,7 @@ program.command("install").description("Install and configure OpenCode Athena").
3178
3358
  }
3179
3359
  await install(options);
3180
3360
  });
3181
- program.command("upgrade").description("Upgrade OpenCode Athena configuration to latest version").option("-y, --yes", "Skip confirmation prompts", false).action(async (options) => {
3182
- await install({ ...options, preset: void 0, advanced: false, global: true, local: false });
3183
- });
3184
- program.command("update").description("Update OpenCode Athena to latest version").option("--check", "Check for updates without installing", false).action(update);
3361
+ program.command("upgrade").description("Upgrade OpenCode Athena to latest version").option("--check", "Check for updates without installing", false).option("-y, --yes", "Skip confirmation prompts", false).action(upgrade);
3185
3362
  program.command("doctor").description("Diagnose and fix common issues").option("--fix", "Automatically fix issues", false).action(doctor);
3186
3363
  program.command("uninstall").description("Remove OpenCode Athena").option("--keep-config", "Keep configuration files", false).option("--keep-deps", "Keep npm dependencies", false).action(uninstall);
3187
3364
  program.command("info").description("Show current configuration and status").action(info);