ai-agent-config 2.6.4 → 2.6.6

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/bin/cli.js CHANGED
@@ -75,8 +75,8 @@ Usage: ai-agent <command> [options]
75
75
  # Update all skills
76
76
  ai-agent update
77
77
 
78
- # Install to specific platform
79
- ai-agent install --platform claude
78
+ # Force reinstall all skills
79
+ ai-agent install --force
80
80
 
81
81
  # Export your config to share with team
82
82
  ai-agent config export my-config.json
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-agent-config",
3
- "version": "2.6.4",
3
+ "version": "2.6.6",
4
4
  "description": "Universal skill & workflow manager for AI coding assistants with bi-directional GitHub sync",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -102,11 +102,11 @@ function migrateConfig(oldConfig) {
102
102
  const newConfig = {
103
103
  version: "2.3",
104
104
  repository: {
105
- url: null,
106
- branch: "main",
107
- local: path.join(os.homedir(), ".ai-agent", "sync-repo"),
108
- lastSync: null,
109
- autoSync: true,
105
+ url: oldConfig.repository?.url || null,
106
+ branch: oldConfig.repository?.branch || "main",
107
+ local: oldConfig.repository?.local || path.join(os.homedir(), ".ai-agent", "sync-repo"),
108
+ lastSync: oldConfig.repository?.lastSync || null,
109
+ autoSync: oldConfig.repository?.autoSync !== undefined ? oldConfig.repository.autoSync : true,
110
110
  },
111
111
  sync: {
112
112
  conflictResolution: "pull-first",
@@ -359,13 +359,15 @@ function importConfig(inputPath, merge = false) {
359
359
  }
360
360
 
361
361
  if (merge) {
362
- // Merge with existing config
362
+ // Merge with existing config, deduplicating by source name
363
363
  const existing = loadConfig();
364
+ const existingNames = new Set(existing.sources.custom.map(s => s.name));
365
+ const newCustom = (importData.sources.custom || []).filter(s => !existingNames.has(s.name));
364
366
  const merged = {
365
367
  ...existing,
366
368
  sources: {
367
369
  official: existing.sources.official,
368
- custom: [...existing.sources.custom, ...(importData.sources.custom || [])],
370
+ custom: [...existing.sources.custom, ...newCustom],
369
371
  },
370
372
  };
371
373
  saveConfig(merged);
@@ -6,7 +6,7 @@
6
6
 
7
7
  const fs = require("fs");
8
8
  const path = require("path");
9
- const { execSync } = require("child_process");
9
+ const { spawnSync } = require("child_process");
10
10
  const configManager = require("./config-manager");
11
11
 
12
12
  const CACHE_DIR = path.join(require("os").homedir(), ".ai-agent-external-cache");
@@ -46,13 +46,19 @@ function syncRepo(source) {
46
46
  try {
47
47
  if (fs.existsSync(repoDir)) {
48
48
  console.log(` Updating ${source.name}...`);
49
- execSync(`git -C "${repoDir}" fetch origin`, { stdio: "pipe" });
50
- execSync(`git -C "${repoDir}" reset --hard origin/${source.branch}`, { stdio: "pipe" });
49
+ spawnSync("git", ["-C", repoDir, "fetch", "origin"], { stdio: "pipe" });
50
+ const resetResult = spawnSync("git", ["-C", repoDir, "reset", "--hard", `origin/${source.branch}`], { stdio: "pipe" });
51
+ if (resetResult.status !== 0) {
52
+ throw new Error(resetResult.stderr?.toString() || "git reset failed");
53
+ }
51
54
  } else {
52
55
  console.log(` Cloning ${source.name}...`);
53
- execSync(`git clone --branch ${source.branch} "${source.repo}" "${repoDir}"`, {
56
+ const cloneResult = spawnSync("git", ["clone", "--branch", source.branch, source.repo, repoDir], {
54
57
  stdio: "pipe",
55
58
  });
59
+ if (cloneResult.status !== 0) {
60
+ throw new Error(cloneResult.stderr?.toString() || "git clone failed");
61
+ }
56
62
  }
57
63
  return true;
58
64
  } catch (error) {
@@ -228,11 +228,14 @@ function fetchSecretsFromBitwarden(sessionKey, secretNames) {
228
228
 
229
229
  try {
230
230
  // List all items in the vault (across all folders)
231
- const itemsJson = execSync(`bw list items --session ${sessionKey}`, {
231
+ const listResult = spawnSync("bw", ["list", "items", "--session", sessionKey], {
232
232
  encoding: "utf-8",
233
233
  stdio: ["pipe", "pipe", "pipe"],
234
234
  });
235
- const items = JSON.parse(itemsJson);
235
+ if (listResult.status !== 0) {
236
+ throw new Error(listResult.stderr || "Failed to list Bitwarden items");
237
+ }
238
+ const items = JSON.parse(listResult.stdout || "[]");
236
239
 
237
240
  // Match secrets by name
238
241
  for (const secretName of secretNames) {
@@ -5,7 +5,7 @@
5
5
 
6
6
  const fs = require("fs");
7
7
  const path = require("path");
8
- const { execSync } = require("child_process");
8
+ const { execSync, spawnSync } = require("child_process");
9
9
 
10
10
  class SyncManager {
11
11
  constructor(config) {
@@ -149,10 +149,11 @@ class SyncManager {
149
149
  const branch = this.config.repository.branch || "main";
150
150
 
151
151
  // Compare local vs remote
152
- const diff = execSync(`git diff HEAD origin/${branch} --name-only`, {
152
+ const diffResult = spawnSync("git", ["diff", "HEAD", `origin/${branch}`, "--name-only"], {
153
153
  cwd: this.repoPath,
154
154
  encoding: "utf-8",
155
155
  });
156
+ const diff = diffResult.stdout || "";
156
157
 
157
158
  return diff.trim().split("\n").filter(Boolean);
158
159
  } catch (error) {
@@ -182,7 +183,7 @@ class SyncManager {
182
183
  const skills = fs.readdirSync(skillsDir);
183
184
  skills.forEach(skill => {
184
185
  if (!bundledSkills.includes(skill)) {
185
- execSync(`git add .agent/skills/${skill}`, {
186
+ spawnSync("git", ["add", `.agent/skills/${skill}`], {
186
187
  cwd: this.repoPath,
187
188
  stdio: "pipe"
188
189
  });
@@ -190,7 +191,13 @@ class SyncManager {
190
191
  });
191
192
  }
192
193
 
193
- execSync(`git commit -m "${message}"`, { cwd: this.repoPath, stdio: "pipe" });
194
+ const commitResult = spawnSync("git", ["commit", "-m", message], { cwd: this.repoPath, stdio: "pipe" });
195
+ if (commitResult.status !== 0) {
196
+ const output = (commitResult.stdout?.toString() || "") + (commitResult.stderr?.toString() || "");
197
+ if (!output.includes("nothing to commit")) {
198
+ throw new Error(output || "git commit failed");
199
+ }
200
+ }
194
201
  } catch (error) {
195
202
  // Ignore commit errors if nothing to commit
196
203
  if (!error.message.includes("nothing to commit")) {
@@ -204,7 +211,10 @@ class SyncManager {
204
211
  */
205
212
  gitPush() {
206
213
  const branch = this.config.repository.branch || "main";
207
- execSync(`git push origin ${branch}`, { cwd: this.repoPath, stdio: "inherit" });
214
+ const result = spawnSync("git", ["push", "origin", branch], { cwd: this.repoPath, stdio: "inherit" });
215
+ if (result.status !== 0) {
216
+ throw new Error("git push failed");
217
+ }
208
218
  }
209
219
 
210
220
  /**