@fractary/codex-cli 0.9.0 → 0.9.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/cli.js CHANGED
@@ -990,6 +990,106 @@ async function initializeUnifiedConfig(configPath, organization, project, option
990
990
  };
991
991
  }
992
992
 
993
+ // src/config/gitignore-utils.ts
994
+ init_esm_shims();
995
+ var DEFAULT_FRACTARY_GITIGNORE = `# .fractary/.gitignore
996
+ # This file is managed by multiple plugins - each plugin manages its own section
997
+
998
+ # ===== fractary-codex (managed) =====
999
+ codex/cache/
1000
+ # ===== end fractary-codex =====
1001
+ `;
1002
+ var DEFAULT_CACHE_DIR = "codex/cache/";
1003
+ async function readFractaryGitignore(projectRoot) {
1004
+ const gitignorePath = path5.join(projectRoot, ".fractary", ".gitignore");
1005
+ try {
1006
+ return await fs.readFile(gitignorePath, "utf-8");
1007
+ } catch (error) {
1008
+ if (error.code === "ENOENT") {
1009
+ return null;
1010
+ }
1011
+ throw error;
1012
+ }
1013
+ }
1014
+ async function writeFractaryGitignore(projectRoot, content) {
1015
+ const gitignorePath = path5.join(projectRoot, ".fractary", ".gitignore");
1016
+ await fs.mkdir(path5.join(projectRoot, ".fractary"), { recursive: true });
1017
+ await fs.writeFile(gitignorePath, content, "utf-8");
1018
+ }
1019
+ function normalizeCachePath(cachePath) {
1020
+ let normalized = cachePath.replace(/\\/g, "/");
1021
+ normalized = normalized.replace(/^\.fractary\//, "");
1022
+ if (!normalized.endsWith("/")) {
1023
+ normalized += "/";
1024
+ }
1025
+ return normalized;
1026
+ }
1027
+ function isCachePathIgnored(gitignoreContent, cachePath) {
1028
+ const normalized = normalizeCachePath(cachePath);
1029
+ const lines = gitignoreContent.split("\n").map((l) => l.trim());
1030
+ return lines.some((line) => {
1031
+ if (line.startsWith("#") || line === "") return false;
1032
+ let normalizedLine = line.replace(/\\/g, "/");
1033
+ if (!normalizedLine.endsWith("/")) {
1034
+ normalizedLine += "/";
1035
+ }
1036
+ return normalizedLine === normalized;
1037
+ });
1038
+ }
1039
+ function addCachePathToGitignore(gitignoreContent, cachePath, comment) {
1040
+ const normalized = normalizeCachePath(cachePath);
1041
+ if (isCachePathIgnored(gitignoreContent, cachePath)) {
1042
+ return gitignoreContent;
1043
+ }
1044
+ let addition = "";
1045
+ {
1046
+ addition += `
1047
+ # ${comment}
1048
+ `;
1049
+ }
1050
+ addition += normalized + "\n";
1051
+ return gitignoreContent.trimEnd() + addition;
1052
+ }
1053
+ async function ensureCachePathIgnored(projectRoot, cachePath) {
1054
+ const gitignorePath = path5.join(projectRoot, ".fractary", ".gitignore");
1055
+ let relativeCachePath = cachePath;
1056
+ if (path5.isAbsolute(cachePath)) {
1057
+ relativeCachePath = path5.relative(path5.join(projectRoot, ".fractary"), cachePath);
1058
+ }
1059
+ relativeCachePath = normalizeCachePath(relativeCachePath);
1060
+ let content = await readFractaryGitignore(projectRoot);
1061
+ const gitignoreExists = content !== null;
1062
+ if (!gitignoreExists) {
1063
+ content = DEFAULT_FRACTARY_GITIGNORE;
1064
+ if (!isCachePathIgnored(content, relativeCachePath)) {
1065
+ content = addCachePathToGitignore(content, relativeCachePath, "Custom cache directory");
1066
+ }
1067
+ await writeFractaryGitignore(projectRoot, content);
1068
+ return {
1069
+ created: true,
1070
+ updated: false,
1071
+ alreadyIgnored: false,
1072
+ gitignorePath
1073
+ };
1074
+ }
1075
+ if (isCachePathIgnored(content, relativeCachePath)) {
1076
+ return {
1077
+ created: false,
1078
+ updated: false,
1079
+ alreadyIgnored: true,
1080
+ gitignorePath
1081
+ };
1082
+ }
1083
+ content = addCachePathToGitignore(content, relativeCachePath, "Custom cache directory");
1084
+ await writeFractaryGitignore(projectRoot, content);
1085
+ return {
1086
+ created: false,
1087
+ updated: true,
1088
+ alreadyIgnored: false,
1089
+ gitignorePath
1090
+ };
1091
+ }
1092
+
993
1093
  // src/commands/config/init.ts
994
1094
  async function getOrgFromGitRemote() {
995
1095
  try {
@@ -1060,6 +1160,14 @@ function initCommand() {
1060
1160
  await fs.mkdir(path5.join(process.cwd(), dir), { recursive: true });
1061
1161
  console.log(chalk8.green("\u2713"), chalk8.dim(dir + "/"));
1062
1162
  }
1163
+ const gitignoreResult = await ensureCachePathIgnored(process.cwd(), ".fractary/codex/cache");
1164
+ if (gitignoreResult.created) {
1165
+ console.log(chalk8.green("\u2713"), chalk8.dim(".fractary/.gitignore (created)"));
1166
+ } else if (gitignoreResult.updated) {
1167
+ console.log(chalk8.green("\u2713"), chalk8.dim(".fractary/.gitignore (updated)"));
1168
+ } else {
1169
+ console.log(chalk8.green("\u2713"), chalk8.dim(".fractary/.gitignore (exists)"));
1170
+ }
1063
1171
  console.log("\nInitializing configuration...");
1064
1172
  const result = await initializeUnifiedConfig(
1065
1173
  configPath,
@@ -1148,8 +1256,9 @@ function migrateCommand() {
1148
1256
  let legacyConfig;
1149
1257
  try {
1150
1258
  legacyConfig = JSON.parse(legacyContent);
1151
- } catch {
1259
+ } catch (parseError) {
1152
1260
  console.error(chalk8.red("Error:"), "Invalid JSON in legacy config file.");
1261
+ console.error(chalk8.dim("Details:"), parseError.message);
1153
1262
  process.exit(1);
1154
1263
  }
1155
1264
  if (!options.json && !options.dryRun) {
@@ -1210,19 +1319,34 @@ function migrateCommand() {
1210
1319
  }
1211
1320
  if (!options.dryRun) {
1212
1321
  await writeYamlConfig(migrationResult.yamlConfig, newConfigPath);
1213
- const cacheDir = path5.join(process.cwd(), ".codex-cache");
1322
+ const configuredCacheDir = migrationResult.yamlConfig.cacheDir || ".fractary/codex/cache";
1323
+ const cacheDir = path5.join(process.cwd(), configuredCacheDir);
1214
1324
  await fs.mkdir(cacheDir, { recursive: true });
1325
+ const gitignoreResult = await ensureCachePathIgnored(process.cwd(), configuredCacheDir);
1326
+ const isCustomCachePath = normalizeCachePath(configuredCacheDir) !== DEFAULT_CACHE_DIR;
1215
1327
  if (!options.json) {
1216
1328
  console.log(chalk8.green("\u2713"), "YAML configuration created");
1217
1329
  console.log(chalk8.green("\u2713"), "Cache directory initialized");
1218
1330
  if (migrationResult.backupPath) {
1219
1331
  console.log(chalk8.green("\u2713"), "Legacy config backed up");
1220
1332
  }
1333
+ if (gitignoreResult.created) {
1334
+ console.log(chalk8.green("\u2713"), ".fractary/.gitignore created");
1335
+ } else if (gitignoreResult.updated) {
1336
+ console.log(chalk8.green("\u2713"), ".fractary/.gitignore updated with cache path");
1337
+ } else if (gitignoreResult.alreadyIgnored) {
1338
+ console.log(chalk8.green("\u2713"), "Cache path already in .fractary/.gitignore");
1339
+ }
1340
+ if (isCustomCachePath) {
1341
+ console.log("");
1342
+ console.log(chalk8.yellow("\u26A0 Custom cache directory detected:"), chalk8.dim(configuredCacheDir));
1343
+ console.log(chalk8.dim(" Ensure .fractary/.gitignore includes this path to avoid committing cache files."));
1344
+ }
1221
1345
  console.log("");
1222
1346
  console.log(chalk8.bold("New Configuration:"));
1223
1347
  console.log(chalk8.dim(` Path: ${newConfigPath}`));
1224
1348
  console.log(chalk8.dim(` Organization: ${migrationResult.yamlConfig.organization}`));
1225
- console.log(chalk8.dim(` Cache: ${migrationResult.yamlConfig.cacheDir || ".codex-cache"}`));
1349
+ console.log(chalk8.dim(` Cache: ${configuredCacheDir}`));
1226
1350
  console.log(chalk8.dim(` Storage Providers: ${migrationResult.yamlConfig.storage?.length || 0}`));
1227
1351
  console.log("");
1228
1352
  console.log(chalk8.bold("Next Steps:"));
@@ -1793,7 +1917,7 @@ function syncCommand() {
1793
1917
  const targetFiles = await Promise.all(
1794
1918
  Array.from(matchedFilePaths).map(async (filePath) => {
1795
1919
  const fullPath = path5.join(sourceDir, filePath);
1796
- const stats = await import('fs/promises').then((fs8) => fs8.stat(fullPath));
1920
+ const stats = await import('fs/promises').then((fs9) => fs9.stat(fullPath));
1797
1921
  return {
1798
1922
  path: filePath,
1799
1923
  size: stats.size,