opencode-athena 0.6.0 → 0.7.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 CHANGED
@@ -4,7 +4,7 @@ import { fileURLToPath } from 'url';
4
4
  import { confirm, select, checkbox } from '@inquirer/prompts';
5
5
  import chalk4 from 'chalk';
6
6
  import { Command } from 'commander';
7
- import { existsSync, readFileSync, copyFileSync, mkdirSync, writeFileSync } from 'fs';
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
10
  import ora2 from 'ora';
@@ -435,14 +435,14 @@ function getPackageVersion() {
435
435
  for (const pkgPath of possiblePaths) {
436
436
  if (!existsSync(pkgPath)) continue;
437
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
- }
438
+ const pkg = JSON.parse(content);
439
+ if (pkg.version) return pkg.version;
443
440
  }
444
441
  return "0.0.0";
445
- } catch {
442
+ } catch (error) {
443
+ if (error instanceof SyntaxError) {
444
+ console.error("[opencode-athena] Warning: package.json contains invalid JSON");
445
+ }
446
446
  return "0.0.0";
447
447
  }
448
448
  }
@@ -462,8 +462,14 @@ var CONFIG_PATHS = {
462
462
  commandsDir: join(homedir(), ".config", "opencode", "command"),
463
463
  /** Plugin directory */
464
464
  pluginDir: join(homedir(), ".config", "opencode", "plugin"),
465
+ /** Athena internal files directory (state, backups) */
466
+ athenaDir: join(homedir(), ".config", "opencode", "athena"),
467
+ /** Athena backups directory */
468
+ backupsDir: join(homedir(), ".config", "opencode", "athena", "backups"),
465
469
  /** Athena state file (for story tracking) */
466
- stateFile: join(homedir(), ".config", "opencode", "athena-state.json")
470
+ stateFile: join(homedir(), ".config", "opencode", "athena", "athena-state.json"),
471
+ /** Legacy state file path (for migration) */
472
+ legacyStateFile: join(homedir(), ".config", "opencode", "athena-state.json")
467
473
  };
468
474
  var DEFAULTS = {
469
475
  /** Maximum parallel stories */
@@ -635,13 +641,17 @@ var FileManager = class {
635
641
  */
636
642
  async removeConfigFiles() {
637
643
  const removedFiles = [];
638
- const filesToRemove = [CONFIG_PATHS.globalAthenaConfig, CONFIG_PATHS.stateFile];
644
+ const filesToRemove = [CONFIG_PATHS.globalAthenaConfig, CONFIG_PATHS.legacyStateFile];
639
645
  for (const file of filesToRemove) {
640
646
  if (existsSync(file)) {
641
647
  await rm(file);
642
648
  removedFiles.push(file);
643
649
  }
644
650
  }
651
+ if (existsSync(CONFIG_PATHS.athenaDir)) {
652
+ await rm(CONFIG_PATHS.athenaDir, { recursive: true });
653
+ removedFiles.push(CONFIG_PATHS.athenaDir);
654
+ }
645
655
  return removedFiles;
646
656
  }
647
657
  /**
@@ -2213,22 +2223,25 @@ function mergeConfigs(options) {
2213
2223
  };
2214
2224
  }
2215
2225
  function createBackups() {
2216
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
2226
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.TZ]/g, "-").replace(/--+/g, "-").replace(/-$/, "");
2217
2227
  const result = {
2218
2228
  athenaBackup: null,
2219
2229
  omoBackup: null,
2220
2230
  opencodeBackup: null
2221
2231
  };
2232
+ if (!existsSync(CONFIG_PATHS.backupsDir)) {
2233
+ mkdirSync(CONFIG_PATHS.backupsDir, { recursive: true });
2234
+ }
2222
2235
  if (existsSync(CONFIG_PATHS.globalAthenaConfig)) {
2223
- result.athenaBackup = `${CONFIG_PATHS.globalAthenaConfig}.backup-${timestamp}`;
2236
+ result.athenaBackup = join(CONFIG_PATHS.backupsDir, `athena.json.backup-${timestamp}`);
2224
2237
  copyFileSync(CONFIG_PATHS.globalAthenaConfig, result.athenaBackup);
2225
2238
  }
2226
2239
  if (existsSync(CONFIG_PATHS.globalOmoConfig)) {
2227
- result.omoBackup = `${CONFIG_PATHS.globalOmoConfig}.backup-${timestamp}`;
2240
+ result.omoBackup = join(CONFIG_PATHS.backupsDir, `oh-my-opencode.json.backup-${timestamp}`);
2228
2241
  copyFileSync(CONFIG_PATHS.globalOmoConfig, result.omoBackup);
2229
2242
  }
2230
2243
  if (existsSync(CONFIG_PATHS.globalOpencodeConfig)) {
2231
- result.opencodeBackup = `${CONFIG_PATHS.globalOpencodeConfig}.backup-${timestamp}`;
2244
+ result.opencodeBackup = join(CONFIG_PATHS.backupsDir, `opencode.json.backup-${timestamp}`);
2232
2245
  copyFileSync(CONFIG_PATHS.globalOpencodeConfig, result.opencodeBackup);
2233
2246
  }
2234
2247
  return result;
@@ -2268,8 +2281,57 @@ var MIGRATIONS = [
2268
2281
  }
2269
2282
  return { ...config, features };
2270
2283
  }
2284
+ },
2285
+ {
2286
+ fromVersion: "0.5.0",
2287
+ toVersion: "0.6.0",
2288
+ description: "Migration system infrastructure (no config changes)",
2289
+ migrateAthena: (config) => config
2290
+ },
2291
+ {
2292
+ fromVersion: "0.6.0",
2293
+ toVersion: "0.7.0",
2294
+ description: "Reorganize athena files into dedicated directory",
2295
+ migrateAthena: (config) => config
2271
2296
  }
2272
2297
  ];
2298
+ function migrateLegacyFiles() {
2299
+ const result = {
2300
+ stateFileMoved: false,
2301
+ backupsMoved: 0
2302
+ };
2303
+ if (!existsSync(CONFIG_PATHS.athenaDir)) {
2304
+ mkdirSync(CONFIG_PATHS.athenaDir, { recursive: true });
2305
+ }
2306
+ if (existsSync(CONFIG_PATHS.legacyStateFile) && !existsSync(CONFIG_PATHS.stateFile)) {
2307
+ if (!existsSync(CONFIG_PATHS.athenaDir)) {
2308
+ mkdirSync(CONFIG_PATHS.athenaDir, { recursive: true });
2309
+ }
2310
+ copyFileSync(CONFIG_PATHS.legacyStateFile, CONFIG_PATHS.stateFile);
2311
+ unlinkSync(CONFIG_PATHS.legacyStateFile);
2312
+ result.stateFileMoved = true;
2313
+ }
2314
+ const backupPattern = /\.(backup-\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2}-\d{3})$/;
2315
+ const configDir = CONFIG_PATHS.globalConfigDir;
2316
+ if (existsSync(configDir)) {
2317
+ const files = readdirSync(configDir);
2318
+ const legacyBackups = files.filter((f) => backupPattern.test(f));
2319
+ if (legacyBackups.length > 0) {
2320
+ if (!existsSync(CONFIG_PATHS.backupsDir)) {
2321
+ mkdirSync(CONFIG_PATHS.backupsDir, { recursive: true });
2322
+ }
2323
+ for (const backupFile of legacyBackups) {
2324
+ const sourcePath = join(configDir, backupFile);
2325
+ const destPath = join(CONFIG_PATHS.backupsDir, backupFile);
2326
+ if (!existsSync(destPath)) {
2327
+ renameSync(sourcePath, destPath);
2328
+ result.backupsMoved++;
2329
+ }
2330
+ }
2331
+ }
2332
+ }
2333
+ return result;
2334
+ }
2273
2335
 
2274
2336
  // src/cli/utils/migrations/runner.ts
2275
2337
  init_esm_shims();
@@ -2288,9 +2350,7 @@ function migrateConfigs(athenaConfig, omoConfig, fromVersion) {
2288
2350
  return semver.compare(aVersion, bVersion);
2289
2351
  });
2290
2352
  for (const migration of sortedMigrations) {
2291
- const migrationFrom = semver.valid(semver.coerce(migration.fromVersion)) || "0.0.0";
2292
2353
  const migrationTo = semver.valid(semver.coerce(migration.toVersion)) || "0.0.0";
2293
- if (semver.gt(migrationFrom, normalizedFrom)) continue;
2294
2354
  if (semver.lte(migrationTo, normalizedFrom)) continue;
2295
2355
  if (semver.gt(migrationTo, normalizedTarget)) continue;
2296
2356
  if (migration.migrateAthena) {
@@ -2528,6 +2588,14 @@ Current version: ${existingVersion}`));
2528
2588
  Boolean
2529
2589
  ).length;
2530
2590
  spinner.succeed(`Created ${backupCount} backup file(s)`);
2591
+ const fileMigrationResult = migrateLegacyFiles();
2592
+ if (fileMigrationResult.stateFileMoved || fileMigrationResult.backupsMoved > 0) {
2593
+ const moved = [];
2594
+ if (fileMigrationResult.stateFileMoved) moved.push("state file");
2595
+ if (fileMigrationResult.backupsMoved > 0)
2596
+ moved.push(`${fileMigrationResult.backupsMoved} backup(s)`);
2597
+ console.log(chalk4.gray(` Migrated ${moved.join(", ")} to new athena/ directory`));
2598
+ }
2531
2599
  const migrationSpinner = ora2("Applying migrations...").start();
2532
2600
  const migrationResult = migrateConfigs(athena || {}, omo || {}, existingVersion);
2533
2601
  if (migrationResult.migrationsApplied.length > 0) {
@@ -2585,10 +2653,9 @@ Current version: ${existingVersion}`));
2585
2653
  message: "Enable automatic git operations? (commits, pushes by agents)",
2586
2654
  default: false
2587
2655
  });
2588
- if (updatedFeatures) {
2589
- if (enable) {
2590
- updatedFeatures.enabledFeatures.push("auto-git");
2591
- }
2656
+ if (enable) {
2657
+ const migratedFeatures = migrationResult.athenaConfig.features;
2658
+ migratedFeatures.autoGitOperations = true;
2592
2659
  }
2593
2660
  }
2594
2661
  }
@@ -3102,7 +3169,7 @@ program.command("install").description("Install and configure OpenCode Athena").
3102
3169
  await install(options);
3103
3170
  });
3104
3171
  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 });
3172
+ await install({ ...options, preset: void 0, advanced: false, global: true, local: false });
3106
3173
  });
3107
3174
  program.command("update").description("Update OpenCode Athena to latest version").option("--check", "Check for updates without installing", false).action(update);
3108
3175
  program.command("doctor").description("Diagnose and fix common issues").option("--fix", "Automatically fix issues", false).action(doctor);