agentprofiles-cli 0.4.0 → 0.4.1

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/index.js CHANGED
@@ -1684,9 +1684,6 @@ tmp/
1684
1684
  .DS_Store
1685
1685
  `;
1686
1686
  GEMINI_GITIGNORE = `# Generated by agentprofiles
1687
- # Shared Gemini state (all runtime/session data)
1688
- _shared/
1689
-
1690
1687
  # Runtime/session state per profile
1691
1688
  */antigravity
1692
1689
  */antigravity-browser-profile
@@ -2109,14 +2106,13 @@ var init_config = __esm({
2109
2106
  );
2110
2107
  }
2111
2108
  const profileDir = path3.join(this.contentDir, agent, profileName);
2109
+ let profileDirExists = false;
2112
2110
  try {
2113
2111
  await fs3.access(profileDir);
2112
+ profileDirExists = true;
2114
2113
  if (options.replaceExisting) {
2115
2114
  await fs3.rm(profileDir, { recursive: true, force: true });
2116
- } else {
2117
- throw new Error(
2118
- `Cannot adopt: profile '${profileName}' already exists for agent '${agent}'`
2119
- );
2115
+ profileDirExists = false;
2120
2116
  }
2121
2117
  } catch (err) {
2122
2118
  if (err instanceof Error && "code" in err && err.code === "ENOENT") {
@@ -2124,11 +2120,15 @@ var init_config = __esm({
2124
2120
  throw err;
2125
2121
  }
2126
2122
  }
2127
- await fs3.mkdir(profileDir, { recursive: true });
2123
+ if (!profileDirExists) {
2124
+ await fs3.mkdir(profileDir, { recursive: true });
2125
+ }
2128
2126
  const include = this.getProfileInclude(agent);
2129
2127
  if (!include) {
2130
2128
  throw new Error(`Agent '${agent}' has no .profileinclude \u2014 cannot use include strategy`);
2131
2129
  }
2130
+ const backupBase = `${globalPath}.bak-${Date.now()}`;
2131
+ let backupCreated = false;
2132
2132
  for (const entry of [...include.files, ...include.dirs]) {
2133
2133
  const isDir = include.dirs.includes(entry);
2134
2134
  const globalEntryPath = path3.join(globalPath, entry);
@@ -2143,25 +2143,42 @@ var init_config = __esm({
2143
2143
  continue;
2144
2144
  }
2145
2145
  if (entryStat) {
2146
- await movePath(globalEntryPath, profileEntryPath);
2147
- } else if (isDir) {
2148
- await fs3.mkdir(profileEntryPath, { recursive: true });
2149
- await fs3.writeFile(path3.join(profileEntryPath, ".gitkeep"), "");
2150
- } else {
2151
- continue;
2146
+ const profileEntryExists = await pathExists(profileEntryPath);
2147
+ if (profileDirExists && profileEntryExists) {
2148
+ if (!backupCreated) {
2149
+ await fs3.mkdir(backupBase, { recursive: true });
2150
+ backupCreated = true;
2151
+ }
2152
+ const backupEntryPath = path3.join(backupBase, entry);
2153
+ await fs3.mkdir(path3.dirname(backupEntryPath), { recursive: true });
2154
+ await movePath(globalEntryPath, backupEntryPath);
2155
+ } else {
2156
+ await movePath(globalEntryPath, profileEntryPath);
2157
+ }
2158
+ } else if (!profileDirExists || !await pathExists(profileEntryPath)) {
2159
+ if (isDir) {
2160
+ await fs3.mkdir(profileEntryPath, { recursive: true });
2161
+ await fs3.writeFile(path3.join(profileEntryPath, ".gitkeep"), "");
2162
+ } else {
2163
+ continue;
2164
+ }
2152
2165
  }
2166
+ if (!await pathExists(profileEntryPath)) continue;
2153
2167
  await fs3.mkdir(path3.dirname(globalEntryPath), { recursive: true });
2154
2168
  const relTarget = path3.relative(path3.dirname(globalEntryPath), profileEntryPath);
2155
2169
  await fs3.symlink(relTarget, globalEntryPath);
2156
2170
  }
2157
- const meta = {
2158
- name: profileName,
2159
- slug: profileName,
2160
- agent,
2161
- description: "Base profile (adopted from original config)",
2162
- created_at: (/* @__PURE__ */ new Date()).toISOString()
2163
- };
2164
- await fs3.writeFile(path3.join(profileDir, "meta.json"), JSON.stringify(meta, null, 2));
2171
+ const metaPath = path3.join(profileDir, "meta.json");
2172
+ if (!await pathExists(metaPath)) {
2173
+ const meta = {
2174
+ name: profileName,
2175
+ slug: profileName,
2176
+ agent,
2177
+ description: "Base profile (adopted from original config)",
2178
+ created_at: (/* @__PURE__ */ new Date()).toISOString()
2179
+ };
2180
+ await fs3.writeFile(metaPath, JSON.stringify(meta, null, 2));
2181
+ }
2165
2182
  await this.ensureIncludeAgentFiles(agent);
2166
2183
  }
2167
2184
  /**
@@ -2217,14 +2234,16 @@ var init_config = __esm({
2217
2234
  return "broken";
2218
2235
  }
2219
2236
  const absTarget = path3.isAbsolute(target) ? target : path3.resolve(path3.dirname(globalPath), target);
2220
- const contentDirAbs = path3.resolve(this.contentDir);
2221
- return absTarget.startsWith(contentDirAbs + path3.sep) ? "active" : "external";
2237
+ const contentDirAbs2 = path3.resolve(this.contentDir);
2238
+ return absTarget.startsWith(contentDirAbs2 + path3.sep) ? "active" : "external";
2222
2239
  }
2223
2240
  const basePath = path3.join(this.contentDir, agent, BASE_PROFILE_SLUG);
2224
2241
  if (!await pathExists(basePath)) {
2225
2242
  return "unmanaged";
2226
2243
  }
2227
2244
  const include = this.getProfileInclude(agent);
2245
+ const contentDirAbs = path3.resolve(this.contentDir);
2246
+ let managedSymlinkCount = 0;
2228
2247
  if (include) {
2229
2248
  for (const entry of [...include.files, ...include.dirs]) {
2230
2249
  const entryPath = path3.join(globalPath, entry);
@@ -2234,15 +2253,21 @@ var init_config = __esm({
2234
2253
  } catch {
2235
2254
  continue;
2236
2255
  }
2237
- if (entryStat.isSymbolicLink()) {
2238
- try {
2239
- await fs3.access(entryPath);
2240
- } catch {
2241
- return "broken";
2242
- }
2256
+ if (!entryStat.isSymbolicLink()) continue;
2257
+ const target = await fs3.readlink(entryPath);
2258
+ const absTarget = path3.isAbsolute(target) ? target : path3.resolve(path3.dirname(entryPath), target);
2259
+ if (!absTarget.startsWith(contentDirAbs + path3.sep)) continue;
2260
+ try {
2261
+ await fs3.access(entryPath);
2262
+ } catch {
2263
+ return "broken";
2243
2264
  }
2265
+ managedSymlinkCount++;
2244
2266
  }
2245
2267
  }
2268
+ if (managedSymlinkCount === 0) {
2269
+ return "unmanaged";
2270
+ }
2246
2271
  return "active";
2247
2272
  }
2248
2273
  /**
@@ -2476,14 +2501,13 @@ var init_config = __esm({
2476
2501
  );
2477
2502
  }
2478
2503
  const profileDir = path3.join(this.contentDir, agent, profileName);
2504
+ let profileDirExists = false;
2479
2505
  try {
2480
2506
  await fs3.access(profileDir);
2507
+ profileDirExists = true;
2481
2508
  if (options.replaceExisting) {
2482
2509
  await fs3.rm(profileDir, { recursive: true, force: true });
2483
- } else {
2484
- throw new Error(
2485
- `Cannot adopt: profile '${profileName}' already exists for agent '${agent}'`
2486
- );
2510
+ profileDirExists = false;
2487
2511
  }
2488
2512
  } catch (err) {
2489
2513
  if (err instanceof Error && "code" in err && err.code === "ENOENT") {
@@ -2491,26 +2515,32 @@ var init_config = __esm({
2491
2515
  throw err;
2492
2516
  }
2493
2517
  }
2494
- await moveDirectory(globalPath, profileDir);
2495
- const meta = {
2496
- name: profileName,
2497
- slug: profileName,
2498
- agent,
2499
- description: "Base profile (adopted from original config)",
2500
- created_at: (/* @__PURE__ */ new Date()).toISOString()
2501
- };
2502
- await fs3.writeFile(path3.join(profileDir, "meta.json"), JSON.stringify(meta, null, 2));
2503
- try {
2504
- await atomicSymlink(profileDir, globalPath);
2505
- } catch (err) {
2518
+ if (!profileDirExists) {
2519
+ await moveDirectory(globalPath, profileDir);
2520
+ const meta = {
2521
+ name: profileName,
2522
+ slug: profileName,
2523
+ agent,
2524
+ description: "Base profile (adopted from original config)",
2525
+ created_at: (/* @__PURE__ */ new Date()).toISOString()
2526
+ };
2527
+ await fs3.writeFile(path3.join(profileDir, "meta.json"), JSON.stringify(meta, null, 2));
2506
2528
  try {
2507
- await moveDirectory(profileDir, globalPath);
2508
- } catch (rollbackErr) {
2509
- throw new Error(
2510
- `Failed to create symlink and rollback failed: ${err instanceof Error ? err.message : String(err)}. Rollback error: ${rollbackErr instanceof Error ? rollbackErr.message : String(rollbackErr)}`
2511
- );
2529
+ await atomicSymlink(profileDir, globalPath);
2530
+ } catch (err) {
2531
+ try {
2532
+ await moveDirectory(profileDir, globalPath);
2533
+ } catch (rollbackErr) {
2534
+ throw new Error(
2535
+ `Failed to create symlink and rollback failed: ${err instanceof Error ? err.message : String(err)}. Rollback error: ${rollbackErr instanceof Error ? rollbackErr.message : String(rollbackErr)}`
2536
+ );
2537
+ }
2538
+ throw err;
2512
2539
  }
2513
- throw err;
2540
+ } else {
2541
+ const backupPath = `${globalPath}.bak-${Date.now()}`;
2542
+ await moveDirectory(globalPath, backupPath);
2543
+ await atomicSymlink(profileDir, globalPath);
2514
2544
  }
2515
2545
  }
2516
2546
  /**
@@ -2686,16 +2716,22 @@ var init_config = __esm({
2686
2716
  `Cannot adopt shared dir '${name}': status is '${status}' (expected 'unmanaged')`
2687
2717
  );
2688
2718
  }
2719
+ let contentPathExists = false;
2689
2720
  try {
2690
2721
  await fs3.access(contentPath);
2691
- throw new Error(`Cannot adopt: shared dir content already exists at ${contentPath}`);
2722
+ contentPathExists = true;
2692
2723
  } catch (err) {
2693
2724
  if (err instanceof Error && "code" in err && err.code === "ENOENT") {
2694
2725
  } else {
2695
2726
  throw err;
2696
2727
  }
2697
2728
  }
2698
- await moveDirectory(globalPath, contentPath);
2729
+ if (!contentPathExists) {
2730
+ await moveDirectory(globalPath, contentPath);
2731
+ } else {
2732
+ const backupPath = `${globalPath}.bak-${Date.now()}`;
2733
+ await moveDirectory(globalPath, backupPath);
2734
+ }
2699
2735
  await atomicSymlink(contentPath, globalPath);
2700
2736
  }
2701
2737
  /**
@@ -3797,7 +3833,7 @@ async function removeCommand(agent, name) {
3797
3833
  process.exit(1);
3798
3834
  }
3799
3835
  if (resolvedName === SHARED_PROFILE_SLUG) {
3800
- console.error(import_picocolors11.default.red(`Cannot remove reserved directory (${SHARED_PROFILE_SLUG}).`));
3836
+ console.error(import_picocolors11.default.red(`Cannot remove reserved profile name (${SHARED_PROFILE_SLUG}).`));
3801
3837
  process.exit(1);
3802
3838
  }
3803
3839
  const activeProfile = await config.getActiveProfile(resolvedAgent);