@tdsoft-tech/aikit 0.1.8 → 0.1.11

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.js CHANGED
@@ -1,6 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
5
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
6
+ }) : x)(function(x) {
7
+ if (typeof require !== "undefined") return require.apply(this, arguments);
8
+ throw Error('Dynamic require of "' + x + '" is not supported');
9
+ });
4
10
  var __esm = (fn, res) => function __init() {
5
11
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
6
12
  };
@@ -735,8 +741,8 @@ var init_memory = __esm({
735
741
  for (const subDir of subDirs) {
736
742
  const dirPath = join8(memoryPath, subDir);
737
743
  try {
738
- const { readdir: readdir7 } = await import("fs/promises");
739
- const files = await readdir7(dirPath);
744
+ const { readdir: readdir10 } = await import("fs/promises");
745
+ const files = await readdir10(dirPath);
740
746
  for (const file of files) {
741
747
  if (!file.endsWith(".md")) continue;
742
748
  const content = await readFile5(join8(dirPath, file), "utf-8");
@@ -797,8 +803,8 @@ var init_memory = __esm({
797
803
  const subDir = type === "observation" ? "observations" : type === "handoff" ? "handoffs" : type === "research" ? "research" : "";
798
804
  filePath = join8(memoryPath, subDir, `${key}.md`);
799
805
  }
800
- const { dirname: dirname2 } = await import("path");
801
- await mkdir4(dirname2(filePath), { recursive: true });
806
+ const { dirname: dirname4 } = await import("path");
807
+ await mkdir4(dirname4(filePath), { recursive: true });
802
808
  if (options?.append) {
803
809
  try {
804
810
  const existing = await readFile5(filePath, "utf-8");
@@ -928,8 +934,8 @@ var tool_config_exports = {};
928
934
  __export(tool_config_exports, {
929
935
  ToolConfigManager: () => ToolConfigManager
930
936
  });
931
- import { readFile as readFile7, writeFile as writeFile8, mkdir as mkdir8, access as access4, constants as constants4 } from "fs/promises";
932
- import { join as join13 } from "path";
937
+ import { readFile as readFile11, writeFile as writeFile12, mkdir as mkdir10, access as access4, constants as constants4 } from "fs/promises";
938
+ import { join as join17 } from "path";
933
939
  import { z as z3 } from "zod";
934
940
  var ToolConfigSchema, REGISTERED_TOOLS, ToolConfigManager;
935
941
  var init_tool_config = __esm({
@@ -957,7 +963,7 @@ var init_tool_config = __esm({
957
963
  toolsConfigPath;
958
964
  constructor(config) {
959
965
  this.config = config;
960
- this.toolsConfigPath = join13(this.config.configPath, "config", "tools.json");
966
+ this.toolsConfigPath = join17(this.config.configPath, "config", "tools.json");
961
967
  }
962
968
  /**
963
969
  * Get all registered tools with their current status
@@ -1041,7 +1047,7 @@ var init_tool_config = __esm({
1041
1047
  async loadConfigs() {
1042
1048
  try {
1043
1049
  await access4(this.toolsConfigPath, constants4.R_OK);
1044
- const content = await readFile7(this.toolsConfigPath, "utf-8");
1050
+ const content = await readFile11(this.toolsConfigPath, "utf-8");
1045
1051
  return JSON.parse(content);
1046
1052
  } catch {
1047
1053
  return {};
@@ -1051,9 +1057,9 @@ var init_tool_config = __esm({
1051
1057
  * Save configurations
1052
1058
  */
1053
1059
  async saveConfigs(configs) {
1054
- const configDir = join13(this.config.configPath, "config");
1055
- await mkdir8(configDir, { recursive: true });
1056
- await writeFile8(this.toolsConfigPath, JSON.stringify(configs, null, 2));
1060
+ const configDir = join17(this.config.configPath, "config");
1061
+ await mkdir10(configDir, { recursive: true });
1062
+ await writeFile12(this.toolsConfigPath, JSON.stringify(configs, null, 2));
1057
1063
  }
1058
1064
  };
1059
1065
  }
@@ -1100,8 +1106,8 @@ var init_figma_oauth = __esm({
1100
1106
  console.log('3. Give it a name (e.g., "AIKit")');
1101
1107
  console.log("4. Copy the token (you won't see it again!)");
1102
1108
  console.log("5. Paste it here when prompted\n");
1103
- const { default: inquirer2 } = await import("inquirer");
1104
- const { token } = await inquirer2.prompt([
1109
+ const { default: inquirer3 } = await import("inquirer");
1110
+ const { token } = await inquirer3.prompt([
1105
1111
  {
1106
1112
  type: "password",
1107
1113
  name: "token",
@@ -1131,14 +1137,14 @@ var init_figma_oauth = __esm({
1131
1137
  * Alternative: Manual token input
1132
1138
  */
1133
1139
  async authenticateManual() {
1134
- const { default: inquirer2 } = await import("inquirer");
1140
+ const { default: inquirer3 } = await import("inquirer");
1135
1141
  console.log("\n\u{1F510} Figma Authentication (Manual)\n");
1136
1142
  console.log("To get your Figma Personal Access Token:");
1137
1143
  console.log("1. Visit: https://www.figma.com/developers/api#access-tokens");
1138
1144
  console.log('2. Scroll to "Personal access tokens"');
1139
1145
  console.log('3. Click "Create new token"');
1140
1146
  console.log("4. Copy the token and paste it below\n");
1141
- const { token } = await inquirer2.prompt([
1147
+ const { token } = await inquirer3.prompt([
1142
1148
  {
1143
1149
  type: "password",
1144
1150
  name: "token",
@@ -1191,8 +1197,8 @@ var init_figma_oauth = __esm({
1191
1197
  // src/cli.ts
1192
1198
  init_esm_shims();
1193
1199
  import { Command } from "commander";
1194
- import chalk2 from "chalk";
1195
- import inquirer from "inquirer";
1200
+ import chalk3 from "chalk";
1201
+ import inquirer2 from "inquirer";
1196
1202
 
1197
1203
  // src/index.ts
1198
1204
  init_esm_shims();
@@ -2037,6 +2043,95 @@ Before marking complete:
2037
2043
  2. Display summary to user
2038
2044
  3. Propose next actions
2039
2045
  4. Continue from where left off`
2046
+ },
2047
+ {
2048
+ name: "one-shot",
2049
+ description: "End-to-end autonomous task execution (beta)",
2050
+ category: "core",
2051
+ usage: "/one-shot <task description>",
2052
+ examples: ["/one-shot Add user authentication", "/one-shot Fix navigation bug"],
2053
+ content: `One-Shot Mode (beta) - End-to-end autonomous task execution.
2054
+
2055
+ \u26A0\uFE0F This mode is experimental. Use for straightforward tasks first.
2056
+
2057
+ ## Workflow
2058
+
2059
+ **Phase 1: Requirements Gathering**
2060
+ - Interactive selection of task type (Feature, Bug Fix, Refactoring, etc.)
2061
+ - Scope clarification
2062
+ - Dependencies identification
2063
+ - Success criteria definition
2064
+ - User selects progress level (Minimal/Moderate/Detailed/Quiet)
2065
+
2066
+ **Phase 2: Planning**
2067
+ - Delegate to @planner agent
2068
+ - Create detailed implementation plan
2069
+ - Recommend relevant skills and tools
2070
+ - Create Beads task for tracking
2071
+
2072
+ **Phase 3: Complexity Check & Auto-Split**
2073
+ - Analyze task complexity
2074
+ - Split into multiple beads if needed:
2075
+ * Time > 30 minutes
2076
+ * >10 files affected
2077
+ * >500 lines to change
2078
+ * Touches >2 sub-systems
2079
+
2080
+ **Phase 4: Execution**
2081
+ - Build dependency graph
2082
+ - Execute tasks in parallel (max 3 concurrent)
2083
+ - Dynamic agent selection (@build \u2192 @review \u2192 @scout \u2192 ...)
2084
+ - Integrate skills (TDD, debugging, etc.)
2085
+ - Smart terminal access (auto-allow/ask/forbid)
2086
+
2087
+ **Phase 5: Enhanced Testing & Validation**
2088
+ - Auto-generate test scripts for new functionality
2089
+ - Run quality gates: typecheck, test, lint, build
2090
+ - Execute sample commands (with user approval)
2091
+ - Validate logs semantically with historical comparison
2092
+ - Retry loop (max 3 attempts) with:
2093
+ * Auto-fix type errors, lint errors
2094
+ * Alternative approaches from @review
2095
+ * User intervention on final failure
2096
+
2097
+ **Phase 6: Multi-Level Verification**
2098
+ - All quality gates passed \u2713
2099
+ - Manual verification confirmation
2100
+ - Deployment approval (if needed)
2101
+ - Rollback confirmation (if verification fails)
2102
+
2103
+ **Phase 7: Completion**
2104
+ - Generate proof of completion
2105
+ * Files changed
2106
+ * Test results
2107
+ * Build output
2108
+ * Deployment status
2109
+ - Update Beads task \u2192 completed
2110
+ - Store proof in bead notes
2111
+ - Collect beta feedback
2112
+
2113
+ ## Quality Gates (Must ALL Pass)
2114
+ - \`npm run typecheck\` - No type errors
2115
+ - \`npm run test\` - All tests pass
2116
+ - \`npm run lint\` - No linting errors
2117
+ - \`npm run build\` - Build succeeds
2118
+
2119
+ ## Success Criteria
2120
+ - All tests passing
2121
+ - No regressions
2122
+ - Manual verification
2123
+ - Deployment complete (if applicable)
2124
+ - Beads task completed with proof
2125
+
2126
+ ## Error Handling
2127
+ - **Level 1**: Auto-fix (type errors, lint --fix)
2128
+ - **Level 2**: Alternative approach (@review delegation)
2129
+ - **Level 3**: User intervention + follow-up bead creation
2130
+
2131
+ ## Tips
2132
+ \u2713 Use for straightforward tasks first
2133
+ \u2713 Consider /plan + /implement for complex features
2134
+ \u2713 Review changes before final approval`
2040
2135
  },
2041
2136
  // Quick Actions
2042
2137
  {
@@ -4117,13 +4212,18 @@ var CliDetector = class {
4117
4212
  try {
4118
4213
  const opencodePath = process.platform === "win32" ? process.env.APPDATA || join12(homedir2(), "AppData", "Roaming") : join12(homedir2(), ".config");
4119
4214
  const opencodeConfig = join12(opencodePath, "opencode", "opencode.json");
4120
- const installed = existsSync4(opencodeConfig);
4215
+ let installed = existsSync4(opencodeConfig);
4121
4216
  let version;
4122
4217
  if (installed) {
4123
4218
  try {
4124
4219
  execSync("opencode --version", { stdio: "ignore" });
4125
4220
  version = "installed";
4126
- } catch {
4221
+ } catch (error) {
4222
+ if (existsSync4(opencodeConfig)) {
4223
+ version = "installed (config exists)";
4224
+ } else {
4225
+ installed = false;
4226
+ }
4127
4227
  }
4128
4228
  }
4129
4229
  return {
@@ -4216,11 +4316,1058 @@ var CliDetector = class {
4216
4316
  // src/cli.ts
4217
4317
  init_logger();
4218
4318
  init_paths();
4319
+
4320
+ // src/core/sync-engine.ts
4321
+ init_esm_shims();
4322
+ import { readFile as readFile10, writeFile as writeFile11, copyFile, mkdir as mkdir9 } from "fs/promises";
4323
+ import { join as join16, dirname as dirname3 } from "path";
4324
+ import inquirer from "inquirer";
4325
+ import chalk2 from "chalk";
4326
+
4327
+ // src/core/version-manager.ts
4328
+ init_esm_shims();
4329
+ init_paths();
4330
+ init_logger();
4331
+ import { readFile as readFile7, readdir as readdir7, writeFile as writeFile8, stat } from "fs/promises";
4332
+ import { join as join13 } from "path";
4333
+ import { createHash } from "crypto";
4334
+ var VersionManager = class {
4335
+ config;
4336
+ constructor(config) {
4337
+ this.config = config;
4338
+ }
4339
+ /**
4340
+ * Get current installed version
4341
+ */
4342
+ async getCurrentVersion() {
4343
+ const versionPath = join13(paths.globalConfig(), ".version.json");
4344
+ try {
4345
+ const content = await readFile7(versionPath, "utf-8");
4346
+ return JSON.parse(content);
4347
+ } catch {
4348
+ return null;
4349
+ }
4350
+ }
4351
+ /**
4352
+ * Get package version from package.json
4353
+ */
4354
+ getPackageVersion() {
4355
+ try {
4356
+ const packageJson = __require(join13(process.cwd(), "package.json"));
4357
+ return packageJson.version || "0.0.0";
4358
+ } catch {
4359
+ return "0.0.0";
4360
+ }
4361
+ }
4362
+ /**
4363
+ * Check for updates
4364
+ */
4365
+ async checkForUpdates() {
4366
+ const installed = await this.getCurrentVersion();
4367
+ const packageVersion = this.getPackageVersion();
4368
+ if (!installed) {
4369
+ return {
4370
+ hasUpdate: true,
4371
+ fromVersion: "none",
4372
+ toVersion: packageVersion,
4373
+ newSkills: [],
4374
+ modifiedSkills: [],
4375
+ removedSkills: [],
4376
+ conflicts: [],
4377
+ configChanges: ["Initial version tracking"]
4378
+ };
4379
+ }
4380
+ const hasUpdate = installed.installedVersion !== packageVersion;
4381
+ if (!hasUpdate) {
4382
+ return {
4383
+ hasUpdate: false,
4384
+ fromVersion: installed.installedVersion,
4385
+ toVersion: packageVersion,
4386
+ newSkills: [],
4387
+ modifiedSkills: [],
4388
+ removedSkills: [],
4389
+ conflicts: [],
4390
+ configChanges: []
4391
+ };
4392
+ }
4393
+ const changes = await this.detectChanges();
4394
+ return {
4395
+ hasUpdate: true,
4396
+ fromVersion: installed.installedVersion,
4397
+ toVersion: packageVersion,
4398
+ ...changes
4399
+ };
4400
+ }
4401
+ /**
4402
+ * Detect changes between versions
4403
+ */
4404
+ async detectChanges() {
4405
+ const globalSkillsPath = paths.skills(paths.globalConfig());
4406
+ const projectSkillsPath = paths.skills(this.config.configPath);
4407
+ const sourceSkills = await this.loadSkillHashes(globalSkillsPath);
4408
+ const userSkills = await this.loadSkillHashes(projectSkillsPath);
4409
+ const newSkills = [];
4410
+ const modifiedSkills = [];
4411
+ const removedSkills = [];
4412
+ const conflicts = [];
4413
+ const installedSkills = /* @__PURE__ */ new Map();
4414
+ const installedPath = join13(paths.globalConfig(), ".installed-skills.json");
4415
+ try {
4416
+ const installedData = await readFile7(installedPath, "utf-8");
4417
+ const installedList = JSON.parse(installedData);
4418
+ installedList.forEach((skill) => {
4419
+ installedSkills.set(skill.name, skill);
4420
+ });
4421
+ } catch {
4422
+ }
4423
+ for (const sourceSkill of sourceSkills) {
4424
+ const installed = installedSkills.get(sourceSkill.name);
4425
+ const user = userSkills.find((s) => s.name === sourceSkill.name);
4426
+ if (!installed) {
4427
+ newSkills.push(sourceSkill);
4428
+ } else if (installed.hash !== sourceSkill.hash) {
4429
+ modifiedSkills.push(sourceSkill);
4430
+ if (user && user.hash !== installed.hash) {
4431
+ conflicts.push({
4432
+ skillName: sourceSkill.name,
4433
+ userHash: user.hash,
4434
+ sourceHash: sourceSkill.hash,
4435
+ installedHash: installed.hash,
4436
+ userModified: user.hash !== installed.hash,
4437
+ sourceModified: sourceSkill.hash !== installed.hash
4438
+ });
4439
+ }
4440
+ }
4441
+ }
4442
+ for (const [name, installedSkill] of installedSkills.entries()) {
4443
+ const existsInSource = sourceSkills.find((s) => s.name === name);
4444
+ if (!existsInSource) {
4445
+ removedSkills.push(installedSkill);
4446
+ }
4447
+ }
4448
+ return {
4449
+ newSkills,
4450
+ modifiedSkills,
4451
+ removedSkills,
4452
+ conflicts,
4453
+ configChanges: []
4454
+ // Will be detected separately
4455
+ };
4456
+ }
4457
+ /**
4458
+ * Load skill hashes from directory
4459
+ */
4460
+ async loadSkillHashes(skillsPath) {
4461
+ const hashes = [];
4462
+ try {
4463
+ const loadFromDir = async (dir) => {
4464
+ const files = await readdir7(dir);
4465
+ for (const file of files) {
4466
+ const filePath = join13(dir, file);
4467
+ const stats = await stat(filePath);
4468
+ if (stats.isDirectory()) {
4469
+ await loadFromDir(filePath);
4470
+ } else if (file.endsWith(".md")) {
4471
+ const hash = await this.calculateSkillHash(filePath);
4472
+ hashes.push({
4473
+ path: filePath,
4474
+ name: file.replace(".md", ""),
4475
+ hash,
4476
+ category: this.extractCategory(dir, skillsPath)
4477
+ });
4478
+ }
4479
+ }
4480
+ };
4481
+ await loadFromDir(skillsPath);
4482
+ } catch (error) {
4483
+ logger.debug(`Could not load skills from ${skillsPath}:`, error);
4484
+ }
4485
+ return hashes;
4486
+ }
4487
+ /**
4488
+ * Calculate hash for a skill file
4489
+ */
4490
+ async calculateSkillHash(filePath) {
4491
+ try {
4492
+ const content = await readFile7(filePath, "utf-8");
4493
+ return createHash("sha256").update(content).digest("hex");
4494
+ } catch {
4495
+ return "";
4496
+ }
4497
+ }
4498
+ /**
4499
+ * Extract category from path
4500
+ */
4501
+ extractCategory(filePath, basePath) {
4502
+ const relative = filePath.replace(basePath + "/", "");
4503
+ const parts = relative.split("/");
4504
+ if (parts.length > 1) {
4505
+ return parts[0];
4506
+ }
4507
+ return "uncategorized";
4508
+ }
4509
+ /**
4510
+ * Save installed skills info
4511
+ */
4512
+ async saveInstalledSkills(skills) {
4513
+ const installedPath = join13(paths.globalConfig(), ".installed-skills.json");
4514
+ try {
4515
+ await writeFile8(installedPath, JSON.stringify(skills, null, 2));
4516
+ } catch (error) {
4517
+ logger.error("Failed to save installed skills info:", error);
4518
+ }
4519
+ }
4520
+ /**
4521
+ * Update version file
4522
+ */
4523
+ async updateVersion(version, migration) {
4524
+ const current = await this.getCurrentVersion() || {
4525
+ installedVersion: "0.0.0",
4526
+ lastSynced: (/* @__PURE__ */ new Date()).toISOString(),
4527
+ packageVersion: "0.0.0",
4528
+ migrationHistory: []
4529
+ };
4530
+ const updated = {
4531
+ installedVersion: version,
4532
+ lastSynced: (/* @__PURE__ */ new Date()).toISOString(),
4533
+ packageVersion: this.getPackageVersion(),
4534
+ migrationHistory: migration ? [...current.migrationHistory, migration] : current.migrationHistory
4535
+ };
4536
+ const versionPath = join13(paths.globalConfig(), ".version.json");
4537
+ await writeFile8(versionPath, JSON.stringify(updated, null, 2));
4538
+ }
4539
+ /**
4540
+ * Check if migration is needed
4541
+ */
4542
+ async needsMigration() {
4543
+ const current = await this.getCurrentVersion();
4544
+ const packageVersion = this.getPackageVersion();
4545
+ return current?.installedVersion !== packageVersion;
4546
+ }
4547
+ };
4548
+
4549
+ // src/core/backup-manager.ts
4550
+ init_esm_shims();
4551
+ init_logger();
4552
+ import { readFile as readFile8, writeFile as writeFile9, readdir as readdir8, stat as stat2, unlink, mkdir as mkdir8 } from "fs/promises";
4553
+ import { join as join14, dirname as dirname2 } from "path";
4554
+ import { createHash as createHash2 } from "crypto";
4555
+ var BackupManager = class {
4556
+ configPath;
4557
+ backupsDir;
4558
+ maxBackups;
4559
+ constructor(configPath, maxBackups = 5) {
4560
+ this.configPath = configPath;
4561
+ this.backupsDir = join14(configPath, ".backups");
4562
+ this.maxBackups = maxBackups;
4563
+ }
4564
+ /**
4565
+ * Create backup before update
4566
+ */
4567
+ async createBackup(fromVersion, toVersion) {
4568
+ try {
4569
+ await mkdir8(this.backupsDir, { recursive: true });
4570
+ const backupId = `${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
4571
+ const backupPath = join14(this.backupsDir, `${backupId}-v${toVersion}`);
4572
+ await mkdir8(backupPath, { recursive: true });
4573
+ logger.info(`Creating backup: ${backupPath}`);
4574
+ const files = [];
4575
+ const backupItems = [
4576
+ "skills/",
4577
+ "aikit.json",
4578
+ "AGENTS.md",
4579
+ "config/"
4580
+ ];
4581
+ for (const item of backupItems) {
4582
+ const files2 = await this.backupItem(this.configPath, item, backupPath);
4583
+ files2.push(...files2);
4584
+ }
4585
+ const manifest = {
4586
+ backupId,
4587
+ fromVersion,
4588
+ toVersion,
4589
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4590
+ files,
4591
+ success: true
4592
+ };
4593
+ const manifestPath = join14(backupPath, "backup-manifest.json");
4594
+ await writeFile9(manifestPath, JSON.stringify(manifest, null, 2));
4595
+ await this.cleanupOldBackups();
4596
+ logger.success(`\u2713 Backup created: ${backupId}`);
4597
+ return backupId;
4598
+ } catch (error) {
4599
+ logger.error("Failed to create backup:", error);
4600
+ return null;
4601
+ }
4602
+ }
4603
+ /**
4604
+ * Backup a file or directory
4605
+ */
4606
+ async backupItem(sourceDir, item, targetDir) {
4607
+ const sourcePath = join14(sourceDir, item);
4608
+ const targetPath = join14(targetDir, item);
4609
+ const files = [];
4610
+ try {
4611
+ const stats = await stat2(sourcePath);
4612
+ if (stats.isDirectory()) {
4613
+ await mkdir8(targetPath, { recursive: true });
4614
+ const entries = await readdir8(sourcePath);
4615
+ for (const entry of entries) {
4616
+ const entryFiles = await this.backupItem(sourcePath, entry, targetPath);
4617
+ files.push(...entryFiles);
4618
+ }
4619
+ } else if (stats.isFile()) {
4620
+ await mkdir8(dirname2(targetPath), { recursive: true });
4621
+ await this.copyFile(sourcePath, targetPath);
4622
+ const hash = await this.calculateHash(targetPath);
4623
+ files.push({
4624
+ path: item,
4625
+ hash,
4626
+ size: stats.size
4627
+ });
4628
+ }
4629
+ } catch (error) {
4630
+ logger.debug(`Could not backup ${item}:`, error);
4631
+ }
4632
+ return files;
4633
+ }
4634
+ /**
4635
+ * Copy file with hash calculation
4636
+ */
4637
+ async copyFile(source, target) {
4638
+ const content = await readFile8(source);
4639
+ await writeFile9(target, content);
4640
+ }
4641
+ /**
4642
+ * Calculate file hash
4643
+ */
4644
+ async calculateHash(filePath) {
4645
+ try {
4646
+ const content = await readFile8(filePath);
4647
+ return createHash2("sha256").update(content).digest("hex");
4648
+ } catch {
4649
+ return "";
4650
+ }
4651
+ }
4652
+ /**
4653
+ * List available backups
4654
+ */
4655
+ async listBackups() {
4656
+ try {
4657
+ const entries = await readdir8(this.backupsDir);
4658
+ const backups = [];
4659
+ for (const entry of entries) {
4660
+ const backupPath = join14(this.backupsDir, entry);
4661
+ const manifestPath = join14(backupPath, "backup-manifest.json");
4662
+ try {
4663
+ const manifestContent = await readFile8(manifestPath, "utf-8");
4664
+ const manifest = JSON.parse(manifestContent);
4665
+ const size = await this.calculateBackupSize(backupPath);
4666
+ backups.push({
4667
+ manifest,
4668
+ path: backupPath,
4669
+ size
4670
+ });
4671
+ } catch {
4672
+ }
4673
+ }
4674
+ backups.sort(
4675
+ (a, b) => new Date(b.manifest.timestamp).getTime() - new Date(a.manifest.timestamp).getTime()
4676
+ );
4677
+ return backups;
4678
+ } catch {
4679
+ return [];
4680
+ }
4681
+ }
4682
+ /**
4683
+ * Calculate backup directory size
4684
+ */
4685
+ async calculateBackupSize(backupPath) {
4686
+ let totalSize = 0;
4687
+ try {
4688
+ const calculate = async (dir) => {
4689
+ const entries = await readdir8(dir);
4690
+ for (const entry of entries) {
4691
+ const entryPath = join14(dir, entry);
4692
+ const stats = await stat2(entryPath);
4693
+ if (stats.isDirectory()) {
4694
+ await calculate(entryPath);
4695
+ } else {
4696
+ totalSize += stats.size;
4697
+ }
4698
+ }
4699
+ };
4700
+ await calculate(backupPath);
4701
+ } catch {
4702
+ }
4703
+ return totalSize;
4704
+ }
4705
+ /**
4706
+ * Restore from backup
4707
+ */
4708
+ async restoreBackup(backupId) {
4709
+ try {
4710
+ const backups = await this.listBackups();
4711
+ const backup = backups.find((b) => b.manifest.backupId === backupId);
4712
+ if (!backup) {
4713
+ logger.error(`Backup not found: ${backupId}`);
4714
+ return false;
4715
+ }
4716
+ logger.info(`Restoring from backup: ${backupId}`);
4717
+ const isValid = await this.validateBackup(backup);
4718
+ if (!isValid) {
4719
+ logger.error("Backup validation failed");
4720
+ return false;
4721
+ }
4722
+ for (const file of backup.manifest.files) {
4723
+ const sourcePath = join14(backup.path, file.path);
4724
+ const targetPath = join14(this.configPath, file.path);
4725
+ await mkdir8(dirname2(targetPath), { recursive: true });
4726
+ await this.copyFile(sourcePath, targetPath);
4727
+ }
4728
+ logger.success(`\u2713 Backup restored: ${backupId}`);
4729
+ return true;
4730
+ } catch (error) {
4731
+ logger.error("Failed to restore backup:", error);
4732
+ return false;
4733
+ }
4734
+ }
4735
+ /**
4736
+ * Validate backup integrity
4737
+ */
4738
+ async validateBackup(backup) {
4739
+ try {
4740
+ const manifestPath = join14(backup.path, "backup-manifest.json");
4741
+ await readFile8(manifestPath, "utf-8");
4742
+ for (const file of backup.manifest.files) {
4743
+ const filePath = join14(backup.path, file.path);
4744
+ await stat2(filePath);
4745
+ const currentHash = await this.calculateHash(filePath);
4746
+ if (currentHash !== file.hash) {
4747
+ logger.warn(`File hash mismatch: ${file.path}`);
4748
+ return false;
4749
+ }
4750
+ }
4751
+ return true;
4752
+ } catch (error) {
4753
+ logger.debug("Backup validation failed:", error);
4754
+ return false;
4755
+ }
4756
+ }
4757
+ /**
4758
+ * Delete backup
4759
+ */
4760
+ async deleteBackup(backupId) {
4761
+ try {
4762
+ const backups = await this.listBackups();
4763
+ const backup = backups.find((b) => b.manifest.backupId === backupId);
4764
+ if (!backup) {
4765
+ return false;
4766
+ }
4767
+ const entries = await readdir8(backup.path);
4768
+ for (const entry of entries) {
4769
+ const entryPath = join14(backup.path, entry);
4770
+ const stats = await stat2(entryPath);
4771
+ if (stats.isDirectory()) {
4772
+ await this.removeDirectory(entryPath);
4773
+ } else {
4774
+ await unlink(entryPath);
4775
+ }
4776
+ }
4777
+ logger.success(`\u2713 Backup deleted: ${backupId}`);
4778
+ return true;
4779
+ } catch (error) {
4780
+ logger.error("Failed to delete backup:", error);
4781
+ return false;
4782
+ }
4783
+ }
4784
+ /**
4785
+ * Remove directory recursively
4786
+ */
4787
+ async removeDirectory(dirPath) {
4788
+ const entries = await readdir8(dirPath);
4789
+ for (const entry of entries) {
4790
+ const entryPath = join14(dirPath, entry);
4791
+ const stats = await stat2(entryPath);
4792
+ if (stats.isDirectory()) {
4793
+ await this.removeDirectory(entryPath);
4794
+ } else {
4795
+ await unlink(entryPath);
4796
+ }
4797
+ }
4798
+ await unlink(dirPath);
4799
+ }
4800
+ /**
4801
+ * Cleanup old backups (keep only maxBackups)
4802
+ */
4803
+ async cleanupOldBackups() {
4804
+ try {
4805
+ const backups = await this.listBackups();
4806
+ if (backups.length <= this.maxBackups) {
4807
+ return;
4808
+ }
4809
+ const toDelete = backups.slice(this.maxBackups);
4810
+ for (const backup of toDelete) {
4811
+ await this.deleteBackup(backup.manifest.backupId);
4812
+ }
4813
+ logger.info(`Cleaned up ${toDelete.length} old backup(s)`);
4814
+ } catch (error) {
4815
+ logger.error("Failed to cleanup old backups:", error);
4816
+ }
4817
+ }
4818
+ /**
4819
+ * Format backup size for display
4820
+ */
4821
+ formatSize(bytes) {
4822
+ const units = ["B", "KB", "MB", "GB"];
4823
+ let size = bytes;
4824
+ let unitIndex = 0;
4825
+ while (size >= 1024 && unitIndex < units.length - 1) {
4826
+ size /= 1024;
4827
+ unitIndex++;
4828
+ }
4829
+ return `${size.toFixed(2)} ${units[unitIndex]}`;
4830
+ }
4831
+ };
4832
+
4833
+ // src/core/migration-manager.ts
4834
+ init_esm_shims();
4835
+ init_logger();
4836
+ import { readFile as readFile9, writeFile as writeFile10, readdir as readdir9 } from "fs/promises";
4837
+ import { join as join15 } from "path";
4838
+ var MigrationManager = class {
4839
+ configPath;
4840
+ migrationsDir;
4841
+ constructor(configPath) {
4842
+ this.configPath = configPath;
4843
+ this.migrationsDir = join15(process.cwd(), "src/core/migrations");
4844
+ }
4845
+ /**
4846
+ * Load all available migrations
4847
+ */
4848
+ async loadMigrations() {
4849
+ const migrations = [];
4850
+ try {
4851
+ const files = await readdir9(this.migrationsDir);
4852
+ for (const file of files) {
4853
+ if (file.endsWith(".js") && file.startsWith("migrate-")) {
4854
+ try {
4855
+ const module = await import(join15(this.migrationsDir, file));
4856
+ const migration = module.default || module.migration;
4857
+ if (migration) {
4858
+ migrations.push(migration);
4859
+ }
4860
+ } catch (error) {
4861
+ logger.warn(`Failed to load migration ${file}:`, error);
4862
+ }
4863
+ }
4864
+ }
4865
+ } catch (error) {
4866
+ logger.debug("Could not load migrations:", error);
4867
+ }
4868
+ return migrations.sort((a, b) => a.version.localeCompare(b.version));
4869
+ }
4870
+ /**
4871
+ * Get applied migrations
4872
+ */
4873
+ async getAppliedMigrations() {
4874
+ const migrationHistoryPath = join15(this.configPath, ".migration-history.json");
4875
+ try {
4876
+ const content = await readFile9(migrationHistoryPath, "utf-8");
4877
+ const history = JSON.parse(content);
4878
+ return history.filter((m) => m.status === "completed").map((m) => m.to);
4879
+ } catch {
4880
+ return [];
4881
+ }
4882
+ }
4883
+ /**
4884
+ * Run pending migrations
4885
+ */
4886
+ async runPendingMigrations() {
4887
+ const appliedMigrations = await this.getAppliedMigrations();
4888
+ const allMigrations = await this.loadMigrations();
4889
+ const pendingMigrations = allMigrations.filter(
4890
+ (m) => !appliedMigrations.includes(m.version)
4891
+ );
4892
+ if (pendingMigrations.length === 0) {
4893
+ logger.info("No pending migrations");
4894
+ return { success: true, applied: [], failed: [] };
4895
+ }
4896
+ logger.info(`Running ${pendingMigrations.length} pending migration(s)...`);
4897
+ const applied = [];
4898
+ const failed = [];
4899
+ const migrationHistory = [];
4900
+ for (const migration of pendingMigrations) {
4901
+ try {
4902
+ logger.info(`Running migration: ${migration.version}`);
4903
+ logger.info(` ${migration.description}`);
4904
+ await migration.up();
4905
+ applied.push(migration.version);
4906
+ migrationHistory.push({
4907
+ from: "previous",
4908
+ to: migration.version,
4909
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4910
+ status: "completed"
4911
+ });
4912
+ logger.success(`\u2713 Migration completed: ${migration.version}`);
4913
+ } catch (error) {
4914
+ logger.error(`\u2717 Migration failed: ${migration.version}`, error);
4915
+ failed.push(migration.version);
4916
+ migrationHistory.push({
4917
+ from: "previous",
4918
+ to: migration.version,
4919
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4920
+ status: "failed"
4921
+ });
4922
+ break;
4923
+ }
4924
+ }
4925
+ await this.updateMigrationHistory(migrationHistory);
4926
+ return {
4927
+ success: failed.length === 0,
4928
+ applied,
4929
+ failed
4930
+ };
4931
+ }
4932
+ /**
4933
+ * Rollback migration
4934
+ */
4935
+ async rollbackMigration(version) {
4936
+ try {
4937
+ const applied = await this.getAppliedMigrations();
4938
+ if (!applied.includes(version)) {
4939
+ logger.error(`Migration not found in applied list: ${version}`);
4940
+ return false;
4941
+ }
4942
+ const allMigrations = await this.loadMigrations();
4943
+ const migration = allMigrations.find((m) => m.version === version);
4944
+ if (!migration) {
4945
+ logger.error(`Migration file not found: ${version}`);
4946
+ return false;
4947
+ }
4948
+ logger.info(`Rolling back migration: ${version}`);
4949
+ await migration.down();
4950
+ await this.updateMigrationHistoryStatus(version, "rolled-back");
4951
+ logger.success(`\u2713 Migration rolled back: ${version}`);
4952
+ return true;
4953
+ } catch (error) {
4954
+ logger.error("Failed to rollback migration:", error);
4955
+ return false;
4956
+ }
4957
+ }
4958
+ /**
4959
+ * Update migration history
4960
+ */
4961
+ async updateMigrationHistory(entries) {
4962
+ const historyPath = join15(this.configPath, ".migration-history.json");
4963
+ try {
4964
+ let history = [];
4965
+ try {
4966
+ const content = await readFile9(historyPath, "utf-8");
4967
+ history = JSON.parse(content);
4968
+ } catch {
4969
+ }
4970
+ history.push(...entries);
4971
+ await writeFile10(historyPath, JSON.stringify(history, null, 2));
4972
+ } catch (error) {
4973
+ logger.error("Failed to update migration history:", error);
4974
+ }
4975
+ }
4976
+ /**
4977
+ * Update migration history status
4978
+ */
4979
+ async updateMigrationHistoryStatus(version, status) {
4980
+ const historyPath = join15(this.configPath, ".migration-history.json");
4981
+ try {
4982
+ const content = await readFile9(historyPath, "utf-8");
4983
+ const history = JSON.parse(content);
4984
+ const updated = history.map(
4985
+ (m) => m.to === version ? { ...m, status } : m
4986
+ );
4987
+ await writeFile10(historyPath, JSON.stringify(updated, null, 2));
4988
+ } catch (error) {
4989
+ logger.error("Failed to update migration history status:", error);
4990
+ }
4991
+ }
4992
+ /**
4993
+ * Get migration history
4994
+ */
4995
+ async getMigrationHistory() {
4996
+ const historyPath = join15(this.configPath, ".migration-history.json");
4997
+ try {
4998
+ const content = await readFile9(historyPath, "utf-8");
4999
+ return JSON.parse(content);
5000
+ } catch {
5001
+ return [];
5002
+ }
5003
+ }
5004
+ /**
5005
+ * Check if migration is needed for version
5006
+ */
5007
+ async needsMigration(_fromVersion) {
5008
+ const applied = await this.getAppliedMigrations();
5009
+ const allMigrations = await this.loadMigrations();
5010
+ const pendingMigrations = allMigrations.filter(
5011
+ (m) => !applied.includes(m.version)
5012
+ );
5013
+ return pendingMigrations.length > 0;
5014
+ }
5015
+ };
5016
+
5017
+ // src/core/sync-engine.ts
5018
+ init_logger();
5019
+ init_paths();
5020
+ var SyncEngine = class {
5021
+ versionManager;
5022
+ backupManager;
5023
+ migrationManager;
5024
+ constructor(config) {
5025
+ this.versionManager = new VersionManager(config);
5026
+ this.backupManager = new BackupManager(config.configPath);
5027
+ this.migrationManager = new MigrationManager(config.configPath);
5028
+ }
5029
+ /**
5030
+ * Check for updates without applying
5031
+ */
5032
+ async checkForUpdates() {
5033
+ try {
5034
+ const changes = await this.versionManager.checkForUpdates();
5035
+ if (changes.hasUpdate) {
5036
+ this.displayUpdateInfo(changes);
5037
+ } else {
5038
+ console.log(chalk2.green("\u2713 Your AIKit is up to date"));
5039
+ console.log(` Installed: ${changes.fromVersion}`);
5040
+ console.log(` Latest: ${changes.toVersion}`);
5041
+ }
5042
+ return changes;
5043
+ } catch (error) {
5044
+ logger.error("Failed to check for updates:", error);
5045
+ return null;
5046
+ }
5047
+ }
5048
+ /**
5049
+ * Preview changes without applying
5050
+ */
5051
+ async previewUpdate() {
5052
+ try {
5053
+ console.log(chalk2.bold("\n\u{1F50D} Previewing update...\n"));
5054
+ const changes = await this.versionManager.checkForUpdates();
5055
+ if (!changes.hasUpdate) {
5056
+ console.log(chalk2.green("\u2713 No updates available"));
5057
+ return false;
5058
+ }
5059
+ await this.displayChanges(changes);
5060
+ console.log(chalk2.yellow("\n\u26A0\uFE0F This is a preview - no changes will be made."));
5061
+ console.log(chalk2.gray("Use `aikit sync apply` to apply these changes."));
5062
+ return true;
5063
+ } catch (error) {
5064
+ logger.error("Failed to preview update:", error);
5065
+ return false;
5066
+ }
5067
+ }
5068
+ /**
5069
+ * Apply update
5070
+ */
5071
+ async applyUpdate(options = {}) {
5072
+ try {
5073
+ const changes = await this.versionManager.checkForUpdates();
5074
+ if (!changes.hasUpdate) {
5075
+ console.log(chalk2.green("\u2713 Already up to date"));
5076
+ return {
5077
+ success: true,
5078
+ newSkills: [],
5079
+ updatedSkills: [],
5080
+ removedSkills: [],
5081
+ migrationsRun: []
5082
+ };
5083
+ }
5084
+ await this.displayChanges(changes);
5085
+ if (!options.force) {
5086
+ const { confirmed } = await inquirer.prompt([{
5087
+ type: "confirm",
5088
+ name: "confirmed",
5089
+ message: "Continue with update?",
5090
+ default: false
5091
+ }]);
5092
+ if (!confirmed) {
5093
+ console.log(chalk2.yellow("Update cancelled"));
5094
+ return {
5095
+ success: false,
5096
+ newSkills: [],
5097
+ updatedSkills: [],
5098
+ removedSkills: [],
5099
+ migrationsRun: []
5100
+ };
5101
+ }
5102
+ }
5103
+ let backupId = void 0;
5104
+ if (!options.dryRun && options.backup !== false) {
5105
+ console.log(chalk2.bold("\n\u{1F4E6} Creating backup..."));
5106
+ const backupResult = await this.backupManager.createBackup(
5107
+ changes.fromVersion,
5108
+ changes.toVersion
5109
+ );
5110
+ if (!backupResult) {
5111
+ throw new Error("Failed to create backup");
5112
+ }
5113
+ backupId = backupResult;
5114
+ }
5115
+ for (const conflict of changes.conflicts) {
5116
+ await this.resolveConflict(conflict);
5117
+ }
5118
+ console.log(chalk2.bold("\n\u{1F504} Running migrations..."));
5119
+ const migrationResult = await this.migrationManager.runPendingMigrations();
5120
+ if (!migrationResult.success) {
5121
+ throw new Error(`Migration failed: ${migrationResult.failed.join(", ")}`);
5122
+ }
5123
+ console.log(chalk2.bold("\n\u{1F4DD} Updating skills..."));
5124
+ const updateResult = await this.updateSkills(changes, options);
5125
+ await this.versionManager.updateVersion(changes.toVersion);
5126
+ if (backupId) {
5127
+ const allSkills = await this.versionManager.loadSkillHashes(paths.skills(paths.globalConfig()));
5128
+ await this.versionManager.saveInstalledSkills(allSkills);
5129
+ }
5130
+ console.log(chalk2.green("\n\u2705 Update complete!"));
5131
+ this.displaySummary({
5132
+ success: true,
5133
+ backupId,
5134
+ ...updateResult,
5135
+ migrationsRun: migrationResult.applied
5136
+ });
5137
+ return {
5138
+ success: true,
5139
+ backupId,
5140
+ ...updateResult,
5141
+ migrationsRun: migrationResult.applied
5142
+ };
5143
+ } catch (error) {
5144
+ logger.error("Update failed:", error);
5145
+ console.log(chalk2.red("\n\u274C Update failed"));
5146
+ return {
5147
+ success: false,
5148
+ newSkills: [],
5149
+ updatedSkills: [],
5150
+ removedSkills: [],
5151
+ migrationsRun: []
5152
+ };
5153
+ }
5154
+ }
5155
+ /**
5156
+ * Rollback to previous backup
5157
+ */
5158
+ async rollback(backupId) {
5159
+ try {
5160
+ console.log(chalk2.bold("\n\u{1F504} Rollback...\n"));
5161
+ if (!backupId) {
5162
+ const backups = await this.backupManager.listBackups();
5163
+ if (backups.length === 0) {
5164
+ console.log(chalk2.yellow("No backups available"));
5165
+ return false;
5166
+ }
5167
+ const { selectedBackup } = await inquirer.prompt([{
5168
+ type: "list",
5169
+ name: "selectedBackup",
5170
+ message: "Select backup to restore:",
5171
+ choices: backups.map((b) => ({
5172
+ name: `${b.manifest.backupId} (${b.manifest.fromVersion} \u2192 ${b.manifest.toVersion})`,
5173
+ value: b.manifest.backupId
5174
+ }))
5175
+ }]);
5176
+ backupId = selectedBackup;
5177
+ }
5178
+ if (!backupId) {
5179
+ console.log(chalk2.yellow("No backup ID provided"));
5180
+ return false;
5181
+ }
5182
+ const success = await this.backupManager.restoreBackup(backupId);
5183
+ if (success) {
5184
+ console.log(chalk2.green("\u2713 Rollback complete"));
5185
+ return true;
5186
+ }
5187
+ return false;
5188
+ } catch (error) {
5189
+ logger.error("Rollback failed:", error);
5190
+ return false;
5191
+ }
5192
+ }
5193
+ /**
5194
+ * Display update information
5195
+ */
5196
+ displayUpdateInfo(changes) {
5197
+ console.log(chalk2.bold("\n\u{1F4E2} New version available!\n"));
5198
+ console.log(` ${chalk2.cyan("Current:")} ${changes.fromVersion}`);
5199
+ console.log(` ${chalk2.cyan("Latest:")} ${changes.toVersion}
5200
+ `);
5201
+ }
5202
+ /**
5203
+ * Display changes summary
5204
+ */
5205
+ async displayChanges(changes) {
5206
+ console.log(chalk2.bold("\u{1F4CA} Changes detected:\n"));
5207
+ if (changes.newSkills.length > 0) {
5208
+ console.log(chalk2.green(" New Skills:"));
5209
+ changes.newSkills.forEach((skill) => {
5210
+ console.log(` + ${skill.name} (${skill.category})`);
5211
+ });
5212
+ }
5213
+ if (changes.modifiedSkills.length > 0) {
5214
+ console.log(chalk2.yellow(" Updated Skills:"));
5215
+ changes.modifiedSkills.forEach((skill) => {
5216
+ console.log(` ~ ${skill.name}`);
5217
+ });
5218
+ }
5219
+ if (changes.removedSkills.length > 0) {
5220
+ console.log(chalk2.red(" Removed Skills:"));
5221
+ changes.removedSkills.forEach((skill) => {
5222
+ console.log(` - ${skill.name}`);
5223
+ });
5224
+ }
5225
+ if (changes.conflicts.length > 0) {
5226
+ console.log(chalk2.bold.red(" \u26A0\uFE0F Conflicts:"));
5227
+ changes.conflicts.forEach((conflict) => {
5228
+ console.log(` ! ${conflict.skillName} (user modified)`);
5229
+ });
5230
+ }
5231
+ }
5232
+ /**
5233
+ * Resolve a conflict
5234
+ */
5235
+ async resolveConflict(conflict) {
5236
+ console.log(chalk2.bold.red(`
5237
+ \u26A0\uFE0F Conflict detected: ${conflict.skillName}
5238
+ `));
5239
+ console.log(chalk2.yellow("Your version differs from official version."));
5240
+ const { action } = await inquirer.prompt([{
5241
+ type: "list",
5242
+ name: "action",
5243
+ message: "Choose action:",
5244
+ choices: [
5245
+ {
5246
+ name: "Keep your version (will be renamed to -custom.md)",
5247
+ value: "preserve"
5248
+ },
5249
+ {
5250
+ name: "Overwrite with official version",
5251
+ value: "overwrite"
5252
+ },
5253
+ {
5254
+ name: "Skip this skill",
5255
+ value: "skip"
5256
+ }
5257
+ ]
5258
+ }]);
5259
+ if (action === "skip") {
5260
+ return;
5261
+ }
5262
+ if (action === "overwrite") {
5263
+ return;
5264
+ }
5265
+ console.log(chalk2.yellow(" Your version will be preserved as -custom.md"));
5266
+ }
5267
+ /**
5268
+ * Update skills based on changes
5269
+ */
5270
+ async updateSkills(changes, options) {
5271
+ const globalSkillsPath = paths.skills(paths.globalConfig());
5272
+ const projectSkillsPath = paths.skills(this.versionManager["config"].configPath);
5273
+ const newSkills = [];
5274
+ const updatedSkills = [];
5275
+ const removedSkills = [];
5276
+ for (const skill of changes.newSkills) {
5277
+ if (!options.dryRun) {
5278
+ await this.installSkill(globalSkillsPath, skill, projectSkillsPath);
5279
+ }
5280
+ newSkills.push(skill.name);
5281
+ console.log(chalk2.green(` + ${skill.name}`));
5282
+ }
5283
+ for (const skill of changes.modifiedSkills) {
5284
+ if (!options.dryRun) {
5285
+ await this.installSkill(globalSkillsPath, skill, projectSkillsPath);
5286
+ }
5287
+ updatedSkills.push(skill.name);
5288
+ console.log(chalk2.yellow(` ~ ${skill.name}`));
5289
+ }
5290
+ for (const skill of changes.removedSkills) {
5291
+ if (!options.dryRun) {
5292
+ await this.archiveSkill(projectSkillsPath, skill);
5293
+ }
5294
+ removedSkills.push(skill.name);
5295
+ console.log(chalk2.red(` - ${skill.name} (archived)`));
5296
+ }
5297
+ return {
5298
+ newSkills,
5299
+ updatedSkills,
5300
+ removedSkills
5301
+ };
5302
+ }
5303
+ /**
5304
+ * Install a skill
5305
+ */
5306
+ async installSkill(sourceDir, skill, targetDir) {
5307
+ const sourcePath = join16(sourceDir, skill.category, `${skill.name}.md`);
5308
+ const targetPath = join16(targetDir, skill.category, `${skill.name}.md`);
5309
+ await mkdir9(dirname3(targetPath), { recursive: true });
5310
+ await copyFile(sourcePath, targetPath);
5311
+ }
5312
+ /**
5313
+ * Archive a removed skill
5314
+ */
5315
+ async archiveSkill(targetDir, skill) {
5316
+ const sourcePath = join16(targetDir, skill.category, `${skill.name}.md`);
5317
+ const targetPath = join16(targetDir, skill.category, `${skill.name}-deprecated.md`);
5318
+ try {
5319
+ const content = await readFile10(sourcePath, "utf-8");
5320
+ const deprecatedNotice = `---
5321
+ \u26A0\uFE0F DEPRECATED: This skill has been removed
5322
+
5323
+ Deprecation date: ${(/* @__PURE__ */ new Date()).toISOString()}
5324
+ Reason: Check release notes for replacement
5325
+ ---
5326
+
5327
+ ${content}`;
5328
+ await mkdir9(dirname3(targetPath), { recursive: true });
5329
+ await writeFile11(targetPath, deprecatedNotice);
5330
+ } catch (error) {
5331
+ if (error.code === "ENOENT") {
5332
+ console.log(chalk2.yellow(` - ${skill.name} (not found, skipping)`));
5333
+ } else {
5334
+ throw error;
5335
+ }
5336
+ }
5337
+ }
5338
+ /**
5339
+ * Display sync summary
5340
+ */
5341
+ displaySummary(result) {
5342
+ console.log(chalk2.bold("\n\u{1F4CB} Summary:\n"));
5343
+ console.log(` Updated from: ${chalk2.cyan(result.backupId || "N/A")}`);
5344
+ console.log(` Updated to: ${chalk2.cyan("current")}`);
5345
+ console.log();
5346
+ if (result.newSkills.length > 0) {
5347
+ console.log(chalk2.green(` ${result.newSkills.length} new skills installed`));
5348
+ }
5349
+ if (result.updatedSkills.length > 0) {
5350
+ console.log(chalk2.yellow(` ${result.updatedSkills.length} skills updated`));
5351
+ }
5352
+ if (result.removedSkills.length > 0) {
5353
+ console.log(chalk2.red(` ${result.removedSkills.length} skills archived`));
5354
+ }
5355
+ if (result.migrationsRun.length > 0) {
5356
+ console.log(chalk2.blue(` ${result.migrationsRun.length} migrations run`));
5357
+ }
5358
+ if (result.backupId) {
5359
+ console.log(chalk2.gray(`
5360
+ Rollback available: aikit sync rollback ${result.backupId}`));
5361
+ }
5362
+ }
5363
+ };
5364
+
5365
+ // src/cli.ts
4219
5366
  var program = new Command();
4220
5367
  program.name("aikit").description("Open-source AI coding agent toolkit for OpenCode").version(getVersion());
4221
5368
  program.command("init").description("Initialize AIKit configuration").option("-g, --global", "Initialize global configuration").option("-p, --project", "Initialize project-level configuration").action(async (options) => {
4222
5369
  const configDir = options.global ? paths.globalConfig() : paths.projectConfig();
4223
- console.log(chalk2.bold("\n\u{1F680} AIKit Setup\n"));
5370
+ console.log(chalk3.bold("\n\u{1F680} AIKit Setup\n"));
4224
5371
  logger.info(`Initializing AIKit in ${configDir}...`);
4225
5372
  try {
4226
5373
  await initializeConfig(configDir, options.global);
@@ -4232,17 +5379,17 @@ program.command("init").description("Initialize AIKit configuration").option("-g
4232
5379
  if (result.count > 0) {
4233
5380
  logger.success(`\u2713 Synced ${result.count} skills`);
4234
5381
  }
4235
- console.log(chalk2.bold("\n\u{1F50D} Checking CLI tools...\n"));
5382
+ console.log(chalk3.bold("\n\u{1F50D} Checking CLI tools...\n"));
4236
5383
  const cliTools = await CliDetector.checkAll();
4237
5384
  const installableTools = CliDetector.filterInstallable(cliTools);
4238
5385
  for (const tool of cliTools) {
4239
- const status = tool.installed ? chalk2.green("\u2713 Installed") : chalk2.yellow("\u2717 Not installed");
4240
- const version = tool.version ? chalk2.gray(` (${tool.version})`) : "";
4241
- console.log(` ${status} ${chalk2.cyan(tool.displayName)}${version}`);
5386
+ const status = tool.installed ? chalk3.green("\u2713 Installed") : chalk3.yellow("\u2717 Not installed");
5387
+ const version = tool.version ? chalk3.gray(` (${tool.version})`) : "";
5388
+ console.log(` ${status} ${chalk3.cyan(tool.displayName)}${version}`);
4242
5389
  }
4243
5390
  if (installableTools.length > 0) {
4244
5391
  console.log();
4245
- const { action } = await inquirer.prompt([
5392
+ const { action } = await inquirer2.prompt([
4246
5393
  {
4247
5394
  type: "list",
4248
5395
  name: "action",
@@ -4282,7 +5429,7 @@ program.command("init").description("Initialize AIKit configuration").option("-g
4282
5429
  console.log();
4283
5430
  logger.success("\u2713 CLI tools installed");
4284
5431
  } else {
4285
- const { installTools } = await inquirer.prompt([
5432
+ const { installTools } = await inquirer2.prompt([
4286
5433
  {
4287
5434
  type: "checkbox",
4288
5435
  name: "installTools",
@@ -4326,16 +5473,16 @@ program.command("init").description("Initialize AIKit configuration").option("-g
4326
5473
  }
4327
5474
  const opencodePath = paths.opencodeConfig();
4328
5475
  await installToOpenCode(opencodePath);
4329
- console.log(chalk2.bold("\n\u2728 AIKit is ready!\n"));
5476
+ console.log(chalk3.bold("\n\u2728 AIKit is ready!\n"));
4330
5477
  console.log("Usage in OpenCode:");
4331
- console.log(chalk2.cyan(" /skills") + " - List all available skills");
4332
- console.log(chalk2.cyan(" /plan") + " - Create implementation plan");
4333
- console.log(chalk2.cyan(" /tdd") + " - Test-driven development");
4334
- console.log(chalk2.cyan(" /debug") + " - Systematic debugging");
4335
- console.log(chalk2.cyan(" /review") + " - Code review checklist");
4336
- console.log(chalk2.cyan(" /git") + " - Git workflow");
4337
- console.log(chalk2.cyan(" /frontend-aesthetics") + " - UI/UX guidelines");
4338
- console.log("\nPress " + chalk2.bold("Ctrl+K") + " in OpenCode to see all commands.\n");
5478
+ console.log(chalk3.cyan(" /skills") + " - List all available skills");
5479
+ console.log(chalk3.cyan(" /plan") + " - Create implementation plan");
5480
+ console.log(chalk3.cyan(" /tdd") + " - Test-driven development");
5481
+ console.log(chalk3.cyan(" /debug") + " - Systematic debugging");
5482
+ console.log(chalk3.cyan(" /review") + " - Code review checklist");
5483
+ console.log(chalk3.cyan(" /git") + " - Git workflow");
5484
+ console.log(chalk3.cyan(" /frontend-aesthetics") + " - UI/UX guidelines");
5485
+ console.log("\nPress " + chalk3.bold("Ctrl+K") + " in OpenCode to see all commands.\n");
4339
5486
  }
4340
5487
  } catch (error) {
4341
5488
  logger.error("Failed to initialize AIKit:", error);
@@ -4353,6 +5500,32 @@ program.command("install").description("Install AIKit to OpenCode configuration"
4353
5500
  process.exit(1);
4354
5501
  }
4355
5502
  });
5503
+ program.command("sync [subcommand]").description("Update AIKit to latest version").option("--dry-run", "Preview changes without applying").option("-f, --force", "Skip confirmation prompts").option("--no-backup", "Skip creating backup").action(async (subcommand, options) => {
5504
+ const config = await loadConfig();
5505
+ const syncEngine = new SyncEngine(config);
5506
+ if (!subcommand) {
5507
+ await syncEngine.applyUpdate(options);
5508
+ } else {
5509
+ switch (subcommand) {
5510
+ case "check":
5511
+ await syncEngine.checkForUpdates();
5512
+ break;
5513
+ case "preview":
5514
+ await syncEngine.previewUpdate();
5515
+ break;
5516
+ case "apply":
5517
+ await syncEngine.applyUpdate(options);
5518
+ break;
5519
+ case "rollback":
5520
+ await syncEngine.rollback();
5521
+ break;
5522
+ default:
5523
+ logger.error(`Unknown subcommand: ${subcommand}`);
5524
+ console.log(chalk3.gray("Available subcommands: check, preview, apply, rollback"));
5525
+ process.exit(1);
5526
+ }
5527
+ }
5528
+ });
4356
5529
  var skillsCmd = program.command("skills").description("Manage skills");
4357
5530
  skillsCmd.command("list").description("List available skills and tools with their configuration status").action(async () => {
4358
5531
  const config = await loadConfig();
@@ -4361,31 +5534,31 @@ skillsCmd.command("list").description("List available skills and tools with thei
4361
5534
  const { ToolConfigManager: ToolConfigManager2 } = await Promise.resolve().then(() => (init_tool_config(), tool_config_exports));
4362
5535
  const toolConfigManager = new ToolConfigManager2(config);
4363
5536
  const tools = await toolConfigManager.listTools();
4364
- console.log(chalk2.bold("\n\u{1F4DA} Available Skills:\n"));
5537
+ console.log(chalk3.bold("\n\u{1F4DA} Available Skills:\n"));
4365
5538
  for (const skill of skills) {
4366
- console.log(` ${chalk2.cyan(skill.name)} - ${skill.description}`);
5539
+ console.log(` ${chalk3.cyan(skill.name)} - ${skill.description}`);
4367
5540
  }
4368
- console.log(chalk2.bold("\n\u{1F527} Available Tools:\n"));
5541
+ console.log(chalk3.bold("\n\u{1F527} Available Tools:\n"));
4369
5542
  for (const tool of tools) {
4370
5543
  let statusIcon = " ";
4371
5544
  let statusText = "";
4372
5545
  if (tool.status === "ready") {
4373
- statusIcon = chalk2.green("\u2713");
4374
- statusText = chalk2.gray("(ready)");
5546
+ statusIcon = chalk3.green("\u2713");
5547
+ statusText = chalk3.gray("(ready)");
4375
5548
  } else if (tool.status === "needs_config") {
4376
- statusIcon = chalk2.yellow("\u26A0");
4377
- statusText = chalk2.yellow("(needs config)");
5549
+ statusIcon = chalk3.yellow("\u26A0");
5550
+ statusText = chalk3.yellow("(needs config)");
4378
5551
  } else if (tool.status === "error") {
4379
- statusIcon = chalk2.red("\u2717");
4380
- statusText = chalk2.red("(error)");
5552
+ statusIcon = chalk3.red("\u2717");
5553
+ statusText = chalk3.red("(error)");
4381
5554
  }
4382
- console.log(` ${statusIcon} ${chalk2.cyan(tool.name)} - ${tool.description} ${statusText}`);
5555
+ console.log(` ${statusIcon} ${chalk3.cyan(tool.name)} - ${tool.description} ${statusText}`);
4383
5556
  if (tool.errorMessage) {
4384
- console.log(` ${chalk2.red("Error:")} ${tool.errorMessage}`);
5557
+ console.log(` ${chalk3.red("Error:")} ${tool.errorMessage}`);
4385
5558
  }
4386
5559
  }
4387
5560
  console.log();
4388
- console.log(chalk2.gray('Tip: Use "aikit skills <tool-name> config" to configure a tool\n'));
5561
+ console.log(chalk3.gray('Tip: Use "aikit skills <tool-name> config" to configure a tool\n'));
4389
5562
  });
4390
5563
  skillsCmd.command("show <name>").description("Show skill details").action(async (name) => {
4391
5564
  const config = await loadConfig();
@@ -4395,11 +5568,11 @@ skillsCmd.command("show <name>").description("Show skill details").action(async
4395
5568
  logger.error(`Skill not found: ${name}`);
4396
5569
  process.exit(1);
4397
5570
  }
4398
- console.log(chalk2.bold(`
5571
+ console.log(chalk3.bold(`
4399
5572
  \u{1F4D6} Skill: ${skill.name}
4400
5573
  `));
4401
- console.log(chalk2.gray(skill.description));
4402
- console.log(chalk2.bold("\nWorkflow:"));
5574
+ console.log(chalk3.gray(skill.description));
5575
+ console.log(chalk3.bold("\nWorkflow:"));
4403
5576
  console.log(skill.content);
4404
5577
  });
4405
5578
  skillsCmd.command("create <name>").description("Create a new skill").action(async (name) => {
@@ -4415,11 +5588,11 @@ skillsCmd.command("sync").description("Sync global skills to project").action(as
4415
5588
  if (result.count === 0) {
4416
5589
  logger.info("Skills already in sync or no global skills to sync");
4417
5590
  } else {
4418
- console.log(chalk2.bold(`
5591
+ console.log(chalk3.bold(`
4419
5592
  \u2713 Synced ${result.count} skills to project:
4420
5593
  `));
4421
5594
  for (const skill of result.synced) {
4422
- console.log(` ${chalk2.cyan("\u2022")} ${skill}`);
5595
+ console.log(` ${chalk3.cyan("\u2022")} ${skill}`);
4423
5596
  }
4424
5597
  console.log();
4425
5598
  }
@@ -4431,18 +5604,18 @@ skillsCmd.command("config <tool-name>").description("Configure a tool (e.g., con
4431
5604
  const tool = await toolConfigManager.getToolConfig(toolName);
4432
5605
  if (!tool) {
4433
5606
  logger.error(`Tool not found: ${toolName}`);
4434
- console.log(chalk2.gray("\nAvailable tools:"));
5607
+ console.log(chalk3.gray("\nAvailable tools:"));
4435
5608
  const tools = await toolConfigManager.listTools();
4436
5609
  for (const t of tools) {
4437
- console.log(` - ${chalk2.cyan(t.name)}`);
5610
+ console.log(` - ${chalk3.cyan(t.name)}`);
4438
5611
  }
4439
5612
  console.log();
4440
5613
  process.exit(1);
4441
5614
  }
4442
- console.log(chalk2.bold(`
5615
+ console.log(chalk3.bold(`
4443
5616
  \u{1F527} Configuring: ${tool.name}
4444
5617
  `));
4445
- console.log(chalk2.gray(tool.description));
5618
+ console.log(chalk3.gray(tool.description));
4446
5619
  console.log();
4447
5620
  if (tool.configMethod === "oauth") {
4448
5621
  if (toolName === "figma-analysis") {
@@ -4450,12 +5623,12 @@ skillsCmd.command("config <tool-name>").description("Configure a tool (e.g., con
4450
5623
  const oauth = new FigmaOAuth2(toolConfigManager);
4451
5624
  try {
4452
5625
  const token = await oauth.authenticate();
4453
- console.log(chalk2.gray("\nValidating token..."));
5626
+ console.log(chalk3.gray("\nValidating token..."));
4454
5627
  const isValid = await oauth.validateToken(token);
4455
5628
  if (isValid) {
4456
5629
  logger.success(`
4457
5630
  \u2705 ${tool.name} configured successfully!`);
4458
- console.log(chalk2.gray("\nYou can now use the /analyze-figma command in OpenCode.\n"));
5631
+ console.log(chalk3.gray("\nYou can now use the /analyze-figma command in OpenCode.\n"));
4459
5632
  } else {
4460
5633
  await toolConfigManager.updateToolConfig(toolName, {
4461
5634
  status: "error",
@@ -4494,20 +5667,20 @@ skillsCmd.command("*").description("Configure a tool (e.g., figma-analysis confi
4494
5667
  const tool = await toolConfigManager.getToolConfig(toolName);
4495
5668
  if (!tool) {
4496
5669
  logger.error(`Tool not found: ${toolName}`);
4497
- console.log(chalk2.gray("\nAvailable tools:"));
5670
+ console.log(chalk3.gray("\nAvailable tools:"));
4498
5671
  const tools = await toolConfigManager.listTools();
4499
5672
  for (const t of tools) {
4500
- console.log(` - ${chalk2.cyan(t.name)}`);
5673
+ console.log(` - ${chalk3.cyan(t.name)}`);
4501
5674
  }
4502
5675
  console.log();
4503
- console.log(chalk2.gray("Tip: If you meant to show a skill, use: aikit skills show <name>"));
5676
+ console.log(chalk3.gray("Tip: If you meant to show a skill, use: aikit skills show <name>"));
4504
5677
  console.log();
4505
5678
  process.exit(1);
4506
5679
  }
4507
- console.log(chalk2.bold(`
5680
+ console.log(chalk3.bold(`
4508
5681
  \u{1F527} Configuring: ${tool.name}
4509
5682
  `));
4510
- console.log(chalk2.gray(tool.description));
5683
+ console.log(chalk3.gray(tool.description));
4511
5684
  console.log();
4512
5685
  if (tool.configMethod === "oauth") {
4513
5686
  if (toolName === "figma-analysis") {
@@ -4515,12 +5688,12 @@ skillsCmd.command("*").description("Configure a tool (e.g., figma-analysis confi
4515
5688
  const oauth = new FigmaOAuth2(toolConfigManager);
4516
5689
  try {
4517
5690
  const token = await oauth.authenticate();
4518
- console.log(chalk2.gray("\nValidating token..."));
5691
+ console.log(chalk3.gray("\nValidating token..."));
4519
5692
  const isValid = await oauth.validateToken(token);
4520
5693
  if (isValid) {
4521
5694
  logger.success(`
4522
5695
  \u2705 ${tool.name} configured successfully!`);
4523
- console.log(chalk2.gray("\nYou can now use the /analyze-figma command in OpenCode.\n"));
5696
+ console.log(chalk3.gray("\nYou can now use the /analyze-figma command in OpenCode.\n"));
4524
5697
  } else {
4525
5698
  await toolConfigManager.updateToolConfig(toolName, {
4526
5699
  status: "error",
@@ -4549,7 +5722,7 @@ skillsCmd.command("*").description("Configure a tool (e.g., figma-analysis confi
4549
5722
  }
4550
5723
  } else {
4551
5724
  logger.error(`Unknown command: ${toolName || "unknown"} ${action || ""}`);
4552
- console.log(chalk2.gray("\nAvailable commands:"));
5725
+ console.log(chalk3.gray("\nAvailable commands:"));
4553
5726
  console.log(" aikit skills list - List all skills and tools");
4554
5727
  console.log(" aikit skills show <name> - Show skill details");
4555
5728
  console.log(" aikit skills config <tool-name> - Configure a tool");
@@ -4563,10 +5736,10 @@ agentsCmd.command("list").description("List available agents").action(async () =
4563
5736
  const config = await loadConfig();
4564
5737
  const manager = new AgentManager(config);
4565
5738
  const agents = manager.listAgents();
4566
- console.log(chalk2.bold("\n\u{1F916} Available Agents:\n"));
5739
+ console.log(chalk3.bold("\n\u{1F916} Available Agents:\n"));
4567
5740
  for (const agent of agents) {
4568
- console.log(` ${chalk2.cyan(`@${agent.name}`)} - ${agent.description}`);
4569
- console.log(chalk2.gray(` Use when: ${agent.useWhen}`));
5741
+ console.log(` ${chalk3.cyan(`@${agent.name}`)} - ${agent.description}`);
5742
+ console.log(chalk3.gray(` Use when: ${agent.useWhen}`));
4570
5743
  }
4571
5744
  console.log();
4572
5745
  });
@@ -4575,13 +5748,13 @@ commandsCmd.command("list").description("List available commands").action(async
4575
5748
  const config = await loadConfig();
4576
5749
  const runner = new CommandRunner(config);
4577
5750
  const commands = await runner.listCommands();
4578
- console.log(chalk2.bold("\n\u26A1 Available Commands:\n"));
5751
+ console.log(chalk3.bold("\n\u26A1 Available Commands:\n"));
4579
5752
  const groups = groupBy(commands, (c) => c.category);
4580
5753
  for (const [category, cmds] of Object.entries(groups)) {
4581
- console.log(chalk2.bold.yellow(`
5754
+ console.log(chalk3.bold.yellow(`
4582
5755
  ${category}:`));
4583
5756
  for (const cmd of cmds) {
4584
- console.log(` ${chalk2.cyan(`/${cmd.name}`)} - ${cmd.description}`);
5757
+ console.log(` ${chalk3.cyan(`/${cmd.name}`)} - ${cmd.description}`);
4585
5758
  }
4586
5759
  }
4587
5760
  console.log();
@@ -4591,9 +5764,9 @@ toolsCmd.command("list").description("List available tools").action(async () =>
4591
5764
  const config = await loadConfig();
4592
5765
  const registry = new ToolRegistry(config);
4593
5766
  const tools = await registry.listTools();
4594
- console.log(chalk2.bold("\n\u{1F527} Available Tools:\n"));
5767
+ console.log(chalk3.bold("\n\u{1F527} Available Tools:\n"));
4595
5768
  for (const tool of tools) {
4596
- console.log(` ${chalk2.cyan(tool.name)} - ${tool.description}`);
5769
+ console.log(` ${chalk3.cyan(tool.name)} - ${tool.description}`);
4597
5770
  }
4598
5771
  console.log();
4599
5772
  });
@@ -4602,10 +5775,10 @@ pluginsCmd.command("list").description("List available plugins").action(async ()
4602
5775
  const config = await loadConfig();
4603
5776
  const system = new PluginSystem(config);
4604
5777
  const plugins = await system.listPlugins();
4605
- console.log(chalk2.bold("\n\u{1F50C} Available Plugins:\n"));
5778
+ console.log(chalk3.bold("\n\u{1F50C} Available Plugins:\n"));
4606
5779
  for (const plugin of plugins) {
4607
- const status = plugin.enabled ? chalk2.green("\u2713") : chalk2.gray("\u25CB");
4608
- console.log(` ${status} ${chalk2.cyan(plugin.name)} - ${plugin.description}`);
5780
+ const status = plugin.enabled ? chalk3.green("\u2713") : chalk3.gray("\u25CB");
5781
+ console.log(` ${status} ${chalk3.cyan(plugin.name)} - ${plugin.description}`);
4609
5782
  }
4610
5783
  console.log();
4611
5784
  });
@@ -4614,10 +5787,10 @@ memoryCmd.command("list").description("List memory entries").action(async () =>
4614
5787
  const config = await loadConfig();
4615
5788
  const memory = new MemoryManager(config);
4616
5789
  const entries = await memory.list();
4617
- console.log(chalk2.bold("\n\u{1F9E0} Memory Entries:\n"));
5790
+ console.log(chalk3.bold("\n\u{1F9E0} Memory Entries:\n"));
4618
5791
  for (const entry of entries) {
4619
- console.log(` ${chalk2.cyan(entry.key)} - ${entry.summary}`);
4620
- console.log(chalk2.gray(` Updated: ${entry.updatedAt}`));
5792
+ console.log(` ${chalk3.cyan(entry.key)} - ${entry.summary}`);
5793
+ console.log(chalk3.gray(` Updated: ${entry.updatedAt}`));
4621
5794
  }
4622
5795
  console.log();
4623
5796
  });
@@ -4635,19 +5808,19 @@ var beadsCmd = program.command("beads").description("Beads task management integ
4635
5808
  beadsCmd.command("status").description("Show current Beads status").action(async () => {
4636
5809
  const beads = new BeadsIntegration();
4637
5810
  const status = await beads.getStatus();
4638
- console.log(chalk2.bold("\n\u{1F4FF} Beads Status:\n"));
5811
+ console.log(chalk3.bold("\n\u{1F4FF} Beads Status:\n"));
4639
5812
  console.log(` Active tasks: ${status.activeTasks}`);
4640
5813
  console.log(` Completed: ${status.completedTasks}`);
4641
5814
  console.log(` Current: ${status.currentTask || "None"}`);
4642
5815
  console.log();
4643
5816
  });
4644
5817
  program.command("status").description("Show AIKit status").action(async () => {
4645
- console.log(chalk2.bold(`
5818
+ console.log(chalk3.bold(`
4646
5819
  \u{1F680} AIKit v${getVersion}
4647
5820
  `));
4648
5821
  try {
4649
5822
  const config = await loadConfig();
4650
- console.log(chalk2.green("\u2713 Configuration loaded"));
5823
+ console.log(chalk3.green("\u2713 Configuration loaded"));
4651
5824
  const skillEngine = new SkillEngine(config);
4652
5825
  const skills = await skillEngine.listSkills();
4653
5826
  console.log(` Skills: ${skills.length}`);
@@ -4662,15 +5835,15 @@ program.command("status").description("Show AIKit status").action(async () => {
4662
5835
  console.log(` Tools: ${tools.length}`);
4663
5836
  const beads = new BeadsIntegration();
4664
5837
  const beadsStatus = await beads.isInstalled();
4665
- console.log(` Beads: ${beadsStatus ? chalk2.green("Installed") : chalk2.yellow("Not installed")}`);
5838
+ console.log(` Beads: ${beadsStatus ? chalk3.green("Installed") : chalk3.yellow("Not installed")}`);
4666
5839
  } catch (error) {
4667
- console.log(chalk2.yellow('\u26A0 AIKit not initialized. Run "aikit init" to get started.'));
5840
+ console.log(chalk3.yellow('\u26A0 AIKit not initialized. Run "aikit init" to get started.'));
4668
5841
  }
4669
5842
  console.log();
4670
5843
  });
4671
5844
  async function initializeConfig(configDir, _isGlobal) {
4672
- const { mkdir: mkdir9, writeFile: writeFile9 } = await import("fs/promises");
4673
- const { join: join14 } = await import("path");
5845
+ const { mkdir: mkdir11, writeFile: writeFile13 } = await import("fs/promises");
5846
+ const { join: join18 } = await import("path");
4674
5847
  const dirs = [
4675
5848
  "",
4676
5849
  "skills",
@@ -4689,7 +5862,7 @@ async function initializeConfig(configDir, _isGlobal) {
4689
5862
  "memory/research"
4690
5863
  ];
4691
5864
  for (const dir of dirs) {
4692
- await mkdir9(join14(configDir, dir), { recursive: true });
5865
+ await mkdir11(join18(configDir, dir), { recursive: true });
4693
5866
  }
4694
5867
  const defaultConfig = {
4695
5868
  version: getVersion,
@@ -4702,8 +5875,8 @@ async function initializeConfig(configDir, _isGlobal) {
4702
5875
  beads: { enabled: true },
4703
5876
  antiHallucination: { enabled: true }
4704
5877
  };
4705
- await writeFile9(
4706
- join14(configDir, "aikit.json"),
5878
+ await writeFile13(
5879
+ join18(configDir, "aikit.json"),
4707
5880
  JSON.stringify(defaultConfig, null, 2)
4708
5881
  );
4709
5882
  const agentsMd = `# AIKit Agent Rules
@@ -4726,26 +5899,26 @@ async function initializeConfig(configDir, _isGlobal) {
4726
5899
  ## Project-Specific Rules
4727
5900
  Add your project-specific rules here.
4728
5901
  `;
4729
- await writeFile9(join14(configDir, "AGENTS.md"), agentsMd);
5902
+ await writeFile13(join18(configDir, "AGENTS.md"), agentsMd);
4730
5903
  }
4731
5904
  async function configureMcpServer(projectPath) {
4732
- const { mkdir: mkdir9, writeFile: writeFile9, readFile: readFile8 } = await import("fs/promises");
4733
- const { join: join14 } = await import("path");
5905
+ const { mkdir: mkdir11, writeFile: writeFile13, readFile: readFile12 } = await import("fs/promises");
5906
+ const { join: join18 } = await import("path");
4734
5907
  const { existsSync: existsSync5 } = await import("fs");
4735
5908
  const { homedir: homedir3 } = await import("os");
4736
5909
  const { fileURLToPath: fileURLToPath3 } = await import("url");
4737
- const { dirname: dirname2 } = await import("path");
5910
+ const { dirname: dirname4 } = await import("path");
4738
5911
  const currentFile = fileURLToPath3(import.meta.url);
4739
- const currentDir = dirname2(currentFile);
4740
- const aikitPath = join14(currentDir, "..");
4741
- const mcpServerPath = join14(aikitPath, "dist", "mcp-server.js");
5912
+ const currentDir = dirname4(currentFile);
5913
+ const aikitPath = join18(currentDir, "..");
5914
+ const mcpServerPath = join18(aikitPath, "dist", "mcp-server.js");
4742
5915
  const configLocations = [
4743
5916
  // Global config (most common)
4744
- join14(homedir3(), ".config", "opencode", "opencode.json"),
5917
+ join18(homedir3(), ".config", "opencode", "opencode.json"),
4745
5918
  // Project-level config
4746
- join14(projectPath, ".opencode", "opencode.json"),
5919
+ join18(projectPath, ".opencode", "opencode.json"),
4747
5920
  // Alternative global location
4748
- join14(homedir3(), ".opencode", "opencode.json")
5921
+ join18(homedir3(), ".opencode", "opencode.json")
4749
5922
  ];
4750
5923
  const mcpServerConfig = {
4751
5924
  type: "local",
@@ -4754,12 +5927,12 @@ async function configureMcpServer(projectPath) {
4754
5927
  };
4755
5928
  for (const configPath of configLocations) {
4756
5929
  try {
4757
- const configDir = join14(configPath, "..");
4758
- await mkdir9(configDir, { recursive: true });
5930
+ const configDir = join18(configPath, "..");
5931
+ await mkdir11(configDir, { recursive: true });
4759
5932
  let config = {};
4760
5933
  if (existsSync5(configPath)) {
4761
5934
  try {
4762
- const existing = await readFile8(configPath, "utf-8");
5935
+ const existing = await readFile12(configPath, "utf-8");
4763
5936
  config = JSON.parse(existing);
4764
5937
  } catch {
4765
5938
  config = {};
@@ -4769,7 +5942,7 @@ async function configureMcpServer(projectPath) {
4769
5942
  config.mcp = {};
4770
5943
  }
4771
5944
  config.mcp.aikit = mcpServerConfig;
4772
- await writeFile9(configPath, JSON.stringify(config, null, 2));
5945
+ await writeFile13(configPath, JSON.stringify(config, null, 2));
4773
5946
  logger.success(`
4774
5947
  \u2705 MCP server configured: ${configPath}`);
4775
5948
  logger.info(` Server: node ${mcpServerPath}`);
@@ -4778,9 +5951,9 @@ async function configureMcpServer(projectPath) {
4778
5951
  continue;
4779
5952
  }
4780
5953
  }
4781
- const instructionsPath = join14(projectPath, ".opencode", "MCP_SETUP.md");
4782
- await mkdir9(join14(projectPath, ".opencode"), { recursive: true });
4783
- await writeFile9(instructionsPath, `# AIKit MCP Server Configuration
5954
+ const instructionsPath = join18(projectPath, ".opencode", "MCP_SETUP.md");
5955
+ await mkdir11(join18(projectPath, ".opencode"), { recursive: true });
5956
+ await writeFile13(instructionsPath, `# AIKit MCP Server Configuration
4784
5957
 
4785
5958
  ## Automatic Setup Failed
4786
5959
 
@@ -4843,15 +6016,15 @@ async function installCliTool(tool) {
4843
6016
  }
4844
6017
  }
4845
6018
  async function installToOpenCode(_opencodePath) {
4846
- const { mkdir: mkdir9, writeFile: writeFile9, access: access5 } = await import("fs/promises");
4847
- const { join: join14 } = await import("path");
6019
+ const { mkdir: mkdir11, writeFile: writeFile13, access: access5 } = await import("fs/promises");
6020
+ const { join: join18 } = await import("path");
4848
6021
  const projectPath = process.cwd();
4849
- const opencodeCommandDir = join14(projectPath, ".opencode", "command");
4850
- const aikitDir = join14(projectPath, ".aikit");
4851
- const opencodeAgentDir = join14(paths.opencodeConfig(), "agent");
4852
- await mkdir9(opencodeCommandDir, { recursive: true });
4853
- await mkdir9(join14(aikitDir, "skills"), { recursive: true });
4854
- await mkdir9(opencodeAgentDir, { recursive: true });
6022
+ const opencodeCommandDir = join18(projectPath, ".opencode", "command");
6023
+ const aikitDir = join18(projectPath, ".aikit");
6024
+ const opencodeAgentDir = join18(paths.opencodeConfig(), "agent");
6025
+ await mkdir11(opencodeCommandDir, { recursive: true });
6026
+ await mkdir11(join18(aikitDir, "skills"), { recursive: true });
6027
+ await mkdir11(opencodeAgentDir, { recursive: true });
4855
6028
  const agentFiles = {
4856
6029
  agent: `---
4857
6030
  description: General-purpose default agent (OpenCode compatibility).
@@ -4923,11 +6096,11 @@ tools:
4923
6096
  Use to interpret visual assets (components, layout, colors, typography) and translate to tasks.`
4924
6097
  };
4925
6098
  for (const [name, content] of Object.entries(agentFiles)) {
4926
- const filePath = join14(opencodeAgentDir, `${name}.md`);
6099
+ const filePath = join18(opencodeAgentDir, `${name}.md`);
4927
6100
  try {
4928
6101
  await access5(filePath);
4929
6102
  } catch {
4930
- await writeFile9(filePath, content, "utf8");
6103
+ await writeFile13(filePath, content, "utf8");
4931
6104
  }
4932
6105
  }
4933
6106
  const config = await loadConfig();
@@ -5180,8 +6353,8 @@ ${cmd.content}
5180
6353
  }
5181
6354
  let count = 0;
5182
6355
  for (const [name, content] of Object.entries(opencodeCommands)) {
5183
- const filePath = join14(opencodeCommandDir, `${name}.md`);
5184
- await writeFile9(filePath, content.trim());
6356
+ const filePath = join18(opencodeCommandDir, `${name}.md`);
6357
+ await writeFile13(filePath, content.trim());
5185
6358
  logger.info(` \u2713 Created /${name} command`);
5186
6359
  count++;
5187
6360
  }