@fractary/codex-cli 0.8.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.cjs +312 -55
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +309 -52
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import * as
|
|
2
|
+
import * as path5 from 'path';
|
|
3
3
|
import { dirname, join } from 'path';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
5
|
import * as fs from 'fs/promises';
|
|
@@ -161,7 +161,7 @@ async function migrateConfig(legacyConfigPath, options) {
|
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
async function writeYamlConfig(config, outputPath) {
|
|
164
|
-
const dir =
|
|
164
|
+
const dir = path5.dirname(outputPath);
|
|
165
165
|
await fs.mkdir(dir, { recursive: true });
|
|
166
166
|
const yamlContent = yaml.dump(config, {
|
|
167
167
|
indent: 2,
|
|
@@ -385,7 +385,7 @@ var init_codex_client = __esm({
|
|
|
385
385
|
const { readYamlConfig: readYamlConfig2 } = await Promise.resolve().then(() => (init_migrate_config(), migrate_config_exports));
|
|
386
386
|
const { resolveEnvVarsInConfig: resolveEnvVarsInConfig2 } = await Promise.resolve().then(() => (init_config_types(), config_types_exports));
|
|
387
387
|
try {
|
|
388
|
-
const configPath =
|
|
388
|
+
const configPath = path5.join(process.cwd(), ".fractary", "codex", "config.yaml");
|
|
389
389
|
let config;
|
|
390
390
|
try {
|
|
391
391
|
config = await readYamlConfig2(configPath);
|
|
@@ -655,7 +655,7 @@ function getTempCodexPath(config) {
|
|
|
655
655
|
const codexRepo = config.codex_repository || "codex";
|
|
656
656
|
const sanitizedOrg = sanitizePathComponent(config.organization);
|
|
657
657
|
const sanitizedRepo = sanitizePathComponent(codexRepo);
|
|
658
|
-
return
|
|
658
|
+
return path5.join(
|
|
659
659
|
os.tmpdir(),
|
|
660
660
|
"fractary-codex-clone",
|
|
661
661
|
`${sanitizedOrg}-${sanitizedRepo}-${process.pid}`
|
|
@@ -663,7 +663,7 @@ function getTempCodexPath(config) {
|
|
|
663
663
|
}
|
|
664
664
|
async function isValidGitRepo(repoPath) {
|
|
665
665
|
try {
|
|
666
|
-
const gitDir =
|
|
666
|
+
const gitDir = path5.join(repoPath, ".git");
|
|
667
667
|
const stats = await fs.stat(gitDir);
|
|
668
668
|
return stats.isDirectory();
|
|
669
669
|
} catch {
|
|
@@ -696,7 +696,7 @@ async function execGit(repoPath, args) {
|
|
|
696
696
|
}
|
|
697
697
|
}
|
|
698
698
|
async function gitClone(url, targetPath, options) {
|
|
699
|
-
const parentDir =
|
|
699
|
+
const parentDir = path5.dirname(targetPath);
|
|
700
700
|
await fs.mkdir(parentDir, { recursive: true });
|
|
701
701
|
const args = ["clone"];
|
|
702
702
|
if (options?.depth) {
|
|
@@ -868,7 +868,229 @@ init_esm_shims();
|
|
|
868
868
|
|
|
869
869
|
// src/commands/config/init.ts
|
|
870
870
|
init_esm_shims();
|
|
871
|
-
|
|
871
|
+
|
|
872
|
+
// src/config/unified-config.ts
|
|
873
|
+
init_esm_shims();
|
|
874
|
+
function sanitizeForS3BucketName(name) {
|
|
875
|
+
return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/^-+|-+$/g, "").replace(/-+/g, "-").substring(0, 63);
|
|
876
|
+
}
|
|
877
|
+
function getDefaultUnifiedConfig(organization, project) {
|
|
878
|
+
const sanitizedProject = sanitizeForS3BucketName(project);
|
|
879
|
+
return {
|
|
880
|
+
file: {
|
|
881
|
+
schema_version: "2.0",
|
|
882
|
+
sources: {
|
|
883
|
+
specs: {
|
|
884
|
+
type: "s3",
|
|
885
|
+
bucket: `${sanitizedProject}-files`,
|
|
886
|
+
prefix: "specs/",
|
|
887
|
+
region: "us-east-1",
|
|
888
|
+
local: {
|
|
889
|
+
base_path: ".fractary/specs"
|
|
890
|
+
},
|
|
891
|
+
push: {
|
|
892
|
+
compress: false,
|
|
893
|
+
keep_local: true
|
|
894
|
+
},
|
|
895
|
+
auth: {
|
|
896
|
+
profile: "default"
|
|
897
|
+
}
|
|
898
|
+
},
|
|
899
|
+
logs: {
|
|
900
|
+
type: "s3",
|
|
901
|
+
bucket: `${sanitizedProject}-files`,
|
|
902
|
+
prefix: "logs/",
|
|
903
|
+
region: "us-east-1",
|
|
904
|
+
local: {
|
|
905
|
+
base_path: ".fractary/logs"
|
|
906
|
+
},
|
|
907
|
+
push: {
|
|
908
|
+
compress: true,
|
|
909
|
+
keep_local: true
|
|
910
|
+
},
|
|
911
|
+
auth: {
|
|
912
|
+
profile: "default"
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
},
|
|
917
|
+
codex: {
|
|
918
|
+
schema_version: "2.0",
|
|
919
|
+
organization,
|
|
920
|
+
project,
|
|
921
|
+
dependencies: {}
|
|
922
|
+
}
|
|
923
|
+
};
|
|
924
|
+
}
|
|
925
|
+
async function readUnifiedConfig(configPath) {
|
|
926
|
+
try {
|
|
927
|
+
const content = await fs.readFile(configPath, "utf-8");
|
|
928
|
+
const config = yaml.load(content);
|
|
929
|
+
return config;
|
|
930
|
+
} catch (error) {
|
|
931
|
+
if (error.code === "ENOENT") {
|
|
932
|
+
return null;
|
|
933
|
+
}
|
|
934
|
+
throw error;
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
async function writeUnifiedConfig(config, outputPath) {
|
|
938
|
+
const dir = path5.dirname(outputPath);
|
|
939
|
+
await fs.mkdir(dir, { recursive: true });
|
|
940
|
+
const yamlContent = yaml.dump(config, {
|
|
941
|
+
indent: 2,
|
|
942
|
+
lineWidth: 120,
|
|
943
|
+
noRefs: true,
|
|
944
|
+
sortKeys: false
|
|
945
|
+
});
|
|
946
|
+
await fs.writeFile(outputPath, yamlContent, "utf-8");
|
|
947
|
+
}
|
|
948
|
+
function mergeUnifiedConfigs(existing, updates) {
|
|
949
|
+
const merged = {};
|
|
950
|
+
if (updates.file || existing.file) {
|
|
951
|
+
merged.file = {
|
|
952
|
+
schema_version: updates.file?.schema_version || existing.file?.schema_version || "2.0",
|
|
953
|
+
sources: {
|
|
954
|
+
...existing.file?.sources || {},
|
|
955
|
+
...updates.file?.sources || {}
|
|
956
|
+
}
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
if (updates.codex || existing.codex) {
|
|
960
|
+
merged.codex = {
|
|
961
|
+
schema_version: updates.codex?.schema_version || existing.codex?.schema_version || "2.0",
|
|
962
|
+
organization: updates.codex?.organization || existing.codex?.organization || "default",
|
|
963
|
+
project: updates.codex?.project || existing.codex?.project || "default",
|
|
964
|
+
dependencies: {
|
|
965
|
+
...existing.codex?.dependencies || {},
|
|
966
|
+
...updates.codex?.dependencies || {}
|
|
967
|
+
}
|
|
968
|
+
};
|
|
969
|
+
}
|
|
970
|
+
return merged;
|
|
971
|
+
}
|
|
972
|
+
async function initializeUnifiedConfig(configPath, organization, project, options) {
|
|
973
|
+
const existingConfig = await readUnifiedConfig(configPath);
|
|
974
|
+
if (existingConfig && !options?.force) {
|
|
975
|
+
const defaultConfig = getDefaultUnifiedConfig(organization, project);
|
|
976
|
+
const merged = mergeUnifiedConfigs(existingConfig, defaultConfig);
|
|
977
|
+
await writeUnifiedConfig(merged, configPath);
|
|
978
|
+
return {
|
|
979
|
+
created: false,
|
|
980
|
+
merged: true,
|
|
981
|
+
config: merged
|
|
982
|
+
};
|
|
983
|
+
}
|
|
984
|
+
const config = getDefaultUnifiedConfig(organization, project);
|
|
985
|
+
await writeUnifiedConfig(config, configPath);
|
|
986
|
+
return {
|
|
987
|
+
created: true,
|
|
988
|
+
merged: false,
|
|
989
|
+
config
|
|
990
|
+
};
|
|
991
|
+
}
|
|
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
|
+
|
|
1093
|
+
// src/commands/config/init.ts
|
|
872
1094
|
async function getOrgFromGitRemote() {
|
|
873
1095
|
try {
|
|
874
1096
|
const { execSync } = __require("child_process");
|
|
@@ -890,9 +1112,9 @@ async function fileExists(filePath) {
|
|
|
890
1112
|
}
|
|
891
1113
|
function initCommand() {
|
|
892
1114
|
const cmd = new Command("init");
|
|
893
|
-
cmd.description("Initialize
|
|
1115
|
+
cmd.description("Initialize unified Fractary configuration (.fractary/config.yaml)").option("--org <slug>", 'Organization slug (e.g., "fractary")').option("--project <name>", "Project name (default: derived from directory)").option("--force", "Overwrite existing configuration").action(async (options) => {
|
|
894
1116
|
try {
|
|
895
|
-
console.log(chalk8.blue("Initializing
|
|
1117
|
+
console.log(chalk8.blue("Initializing unified Fractary configuration...\n"));
|
|
896
1118
|
let org = options.org;
|
|
897
1119
|
if (!org) {
|
|
898
1120
|
org = await getOrgFromGitRemote();
|
|
@@ -901,60 +1123,79 @@ function initCommand() {
|
|
|
901
1123
|
try {
|
|
902
1124
|
const { resolveOrganization } = await import('@fractary/codex');
|
|
903
1125
|
org = resolveOrganization({
|
|
904
|
-
repoName:
|
|
1126
|
+
repoName: path5.basename(process.cwd())
|
|
905
1127
|
});
|
|
906
1128
|
} catch {
|
|
907
1129
|
}
|
|
908
1130
|
}
|
|
909
1131
|
if (!org) {
|
|
910
|
-
org =
|
|
1132
|
+
org = path5.basename(process.cwd()).split("-")[0] || "default";
|
|
911
1133
|
console.log(chalk8.yellow(`\u26A0 Could not detect organization, using: ${org}`));
|
|
912
1134
|
console.log(chalk8.dim(" Use --org <slug> to specify explicitly\n"));
|
|
913
1135
|
} else {
|
|
914
1136
|
console.log(chalk8.dim(`Organization: ${chalk8.cyan(org)}
|
|
915
1137
|
`));
|
|
916
1138
|
}
|
|
917
|
-
|
|
918
|
-
|
|
1139
|
+
let project = options.project;
|
|
1140
|
+
if (!project) {
|
|
1141
|
+
project = path5.basename(process.cwd());
|
|
1142
|
+
console.log(chalk8.dim(`Project: ${chalk8.cyan(project)}
|
|
1143
|
+
`));
|
|
1144
|
+
}
|
|
1145
|
+
const configPath = path5.join(process.cwd(), ".fractary", "config.yaml");
|
|
919
1146
|
const configExists = await fileExists(configPath);
|
|
920
1147
|
if (configExists && !options.force) {
|
|
921
|
-
console.log(chalk8.yellow(
|
|
922
|
-
console.log(chalk8.dim("
|
|
923
|
-
process.exit(1);
|
|
1148
|
+
console.log(chalk8.yellow(`\u26A0 Configuration already exists at .fractary/config.yaml`));
|
|
1149
|
+
console.log(chalk8.dim("Merging with existing configuration...\n"));
|
|
924
1150
|
}
|
|
925
1151
|
console.log("Creating directory structure...");
|
|
926
1152
|
const dirs = [
|
|
1153
|
+
".fractary",
|
|
1154
|
+
".fractary/specs",
|
|
1155
|
+
".fractary/logs",
|
|
927
1156
|
".fractary/codex",
|
|
928
1157
|
".fractary/codex/cache"
|
|
929
1158
|
];
|
|
930
1159
|
for (const dir of dirs) {
|
|
931
|
-
await fs.mkdir(
|
|
1160
|
+
await fs.mkdir(path5.join(process.cwd(), dir), { recursive: true });
|
|
932
1161
|
console.log(chalk8.green("\u2713"), chalk8.dim(dir + "/"));
|
|
933
1162
|
}
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
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
|
+
}
|
|
1171
|
+
console.log("\nInitializing configuration...");
|
|
1172
|
+
const result = await initializeUnifiedConfig(
|
|
1173
|
+
configPath,
|
|
1174
|
+
org,
|
|
1175
|
+
project,
|
|
1176
|
+
{ force: options.force }
|
|
1177
|
+
);
|
|
1178
|
+
if (result.created) {
|
|
1179
|
+
console.log(chalk8.green("\u2713"), chalk8.dim(".fractary/config.yaml (created)"));
|
|
1180
|
+
} else if (result.merged) {
|
|
1181
|
+
console.log(chalk8.green("\u2713"), chalk8.dim(".fractary/config.yaml (merged with existing)"));
|
|
938
1182
|
}
|
|
939
|
-
|
|
940
|
-
console.log(chalk8.green("\u2713"), chalk8.dim(".fractary/codex/config.yaml"));
|
|
941
|
-
console.log(chalk8.green("\n\u2713 Codex v4.0 initialized successfully!\n"));
|
|
1183
|
+
console.log(chalk8.green("\n\u2713 Unified configuration initialized successfully!\n"));
|
|
942
1184
|
console.log(chalk8.bold("Configuration:"));
|
|
943
1185
|
console.log(chalk8.dim(` Organization: ${org}`));
|
|
944
|
-
console.log(chalk8.dim(`
|
|
945
|
-
console.log(chalk8.dim(` Config: .fractary/
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
console.log(chalk8.bold("\
|
|
950
|
-
console.log(chalk8.dim(" -
|
|
951
|
-
console.log(chalk8.dim(" -
|
|
952
|
-
console.log(chalk8.dim(" - HTTP endpoint"));
|
|
1186
|
+
console.log(chalk8.dim(` Project: ${project}`));
|
|
1187
|
+
console.log(chalk8.dim(` Config: .fractary/config.yaml`));
|
|
1188
|
+
console.log(chalk8.bold("\nFile plugin sources:"));
|
|
1189
|
+
console.log(chalk8.dim(" - specs: .fractary/specs/ \u2192 S3"));
|
|
1190
|
+
console.log(chalk8.dim(" - logs: .fractary/logs/ \u2192 S3"));
|
|
1191
|
+
console.log(chalk8.bold("\nCodex plugin:"));
|
|
1192
|
+
console.log(chalk8.dim(" - Cache: .fractary/codex/cache/"));
|
|
1193
|
+
console.log(chalk8.dim(" - Dependencies: (none configured)"));
|
|
953
1194
|
console.log(chalk8.bold("\nNext steps:"));
|
|
954
|
-
console.log(chalk8.dim(
|
|
955
|
-
console.log(chalk8.dim(" 2. Edit .fractary/
|
|
956
|
-
console.log(chalk8.dim(" 3.
|
|
957
|
-
console.log(chalk8.dim(" 4.
|
|
1195
|
+
console.log(chalk8.dim(" 1. Configure AWS credentials for S3 access"));
|
|
1196
|
+
console.log(chalk8.dim(" 2. Edit .fractary/config.yaml to add external project dependencies"));
|
|
1197
|
+
console.log(chalk8.dim(" 3. Access current project files: codex://specs/SPEC-001.md"));
|
|
1198
|
+
console.log(chalk8.dim(" 4. Access external projects: codex://org/project/docs/README.md"));
|
|
958
1199
|
} catch (error) {
|
|
959
1200
|
console.error(chalk8.red("Error:"), error.message);
|
|
960
1201
|
process.exit(1);
|
|
@@ -981,8 +1222,8 @@ function migrateCommand() {
|
|
|
981
1222
|
const cmd = new Command("migrate");
|
|
982
1223
|
cmd.description("Migrate legacy JSON configuration to v3.0 YAML format").option("--dry-run", "Show migration plan without executing").option("--no-backup", "Skip creating backup of old config").option("--json", "Output as JSON").action(async (options) => {
|
|
983
1224
|
try {
|
|
984
|
-
const legacyConfigPath =
|
|
985
|
-
const newConfigPath =
|
|
1225
|
+
const legacyConfigPath = path5.join(process.cwd(), ".fractary", "plugins", "codex", "config.json");
|
|
1226
|
+
const newConfigPath = path5.join(process.cwd(), ".fractary", "codex", "config.yaml");
|
|
986
1227
|
if (!await fileExists2(legacyConfigPath)) {
|
|
987
1228
|
if (options.json) {
|
|
988
1229
|
console.log(JSON.stringify({
|
|
@@ -1015,8 +1256,9 @@ function migrateCommand() {
|
|
|
1015
1256
|
let legacyConfig;
|
|
1016
1257
|
try {
|
|
1017
1258
|
legacyConfig = JSON.parse(legacyContent);
|
|
1018
|
-
} catch {
|
|
1259
|
+
} catch (parseError) {
|
|
1019
1260
|
console.error(chalk8.red("Error:"), "Invalid JSON in legacy config file.");
|
|
1261
|
+
console.error(chalk8.dim("Details:"), parseError.message);
|
|
1020
1262
|
process.exit(1);
|
|
1021
1263
|
}
|
|
1022
1264
|
if (!options.json && !options.dryRun) {
|
|
@@ -1077,19 +1319,34 @@ function migrateCommand() {
|
|
|
1077
1319
|
}
|
|
1078
1320
|
if (!options.dryRun) {
|
|
1079
1321
|
await writeYamlConfig(migrationResult.yamlConfig, newConfigPath);
|
|
1080
|
-
const
|
|
1322
|
+
const configuredCacheDir = migrationResult.yamlConfig.cacheDir || ".fractary/codex/cache";
|
|
1323
|
+
const cacheDir = path5.join(process.cwd(), configuredCacheDir);
|
|
1081
1324
|
await fs.mkdir(cacheDir, { recursive: true });
|
|
1325
|
+
const gitignoreResult = await ensureCachePathIgnored(process.cwd(), configuredCacheDir);
|
|
1326
|
+
const isCustomCachePath = normalizeCachePath(configuredCacheDir) !== DEFAULT_CACHE_DIR;
|
|
1082
1327
|
if (!options.json) {
|
|
1083
1328
|
console.log(chalk8.green("\u2713"), "YAML configuration created");
|
|
1084
1329
|
console.log(chalk8.green("\u2713"), "Cache directory initialized");
|
|
1085
1330
|
if (migrationResult.backupPath) {
|
|
1086
1331
|
console.log(chalk8.green("\u2713"), "Legacy config backed up");
|
|
1087
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
|
+
}
|
|
1088
1345
|
console.log("");
|
|
1089
1346
|
console.log(chalk8.bold("New Configuration:"));
|
|
1090
1347
|
console.log(chalk8.dim(` Path: ${newConfigPath}`));
|
|
1091
1348
|
console.log(chalk8.dim(` Organization: ${migrationResult.yamlConfig.organization}`));
|
|
1092
|
-
console.log(chalk8.dim(` Cache: ${
|
|
1349
|
+
console.log(chalk8.dim(` Cache: ${configuredCacheDir}`));
|
|
1093
1350
|
console.log(chalk8.dim(` Storage Providers: ${migrationResult.yamlConfig.storage?.length || 0}`));
|
|
1094
1351
|
console.log("");
|
|
1095
1352
|
console.log(chalk8.bold("Next Steps:"));
|
|
@@ -1098,7 +1355,7 @@ function migrateCommand() {
|
|
|
1098
1355
|
console.log(chalk8.dim(" 3. Test fetching: fractary codex fetch codex://org/project/path"));
|
|
1099
1356
|
if (migrationResult.backupPath) {
|
|
1100
1357
|
console.log("");
|
|
1101
|
-
console.log(chalk8.dim(`Backup saved: ${
|
|
1358
|
+
console.log(chalk8.dim(`Backup saved: ${path5.basename(migrationResult.backupPath)}`));
|
|
1102
1359
|
}
|
|
1103
1360
|
}
|
|
1104
1361
|
}
|
|
@@ -1308,8 +1565,8 @@ async function fileExists3(filePath) {
|
|
|
1308
1565
|
}
|
|
1309
1566
|
}
|
|
1310
1567
|
async function checkConfiguration() {
|
|
1311
|
-
const configPath =
|
|
1312
|
-
const legacyConfigPath =
|
|
1568
|
+
const configPath = path5.join(process.cwd(), ".fractary", "codex", "config.yaml");
|
|
1569
|
+
const legacyConfigPath = path5.join(process.cwd(), ".fractary", "plugins", "codex", "config.json");
|
|
1313
1570
|
try {
|
|
1314
1571
|
if (!await fileExists3(configPath)) {
|
|
1315
1572
|
if (await fileExists3(legacyConfigPath)) {
|
|
@@ -1416,7 +1673,7 @@ async function checkCache() {
|
|
|
1416
1673
|
}
|
|
1417
1674
|
}
|
|
1418
1675
|
async function checkStorage() {
|
|
1419
|
-
const configPath =
|
|
1676
|
+
const configPath = path5.join(process.cwd(), ".fractary", "codex", "config.yaml");
|
|
1420
1677
|
try {
|
|
1421
1678
|
const config = await readYamlConfig(configPath);
|
|
1422
1679
|
const providers = config.storage || [];
|
|
@@ -1574,7 +1831,7 @@ function syncCommand() {
|
|
|
1574
1831
|
const cmd = new Command("sync");
|
|
1575
1832
|
cmd.description("Sync single project with codex repository").argument("[name]", "Project name (auto-detected if not provided)").option("--env <env>", "Target environment (dev/test/staging/prod)", "prod").option("--dry-run", "Show what would sync without executing").option("--direction <dir>", "Sync direction (to-codex/from-codex/bidirectional)", "bidirectional").option("--include <pattern>", "Include files matching pattern (can be used multiple times)", (val, prev) => prev.concat([val]), []).option("--exclude <pattern>", "Exclude files matching pattern (can be used multiple times)", (val, prev) => prev.concat([val]), []).option("--force", "Force sync without checking timestamps").option("--json", "Output as JSON").action(async (name, options) => {
|
|
1576
1833
|
try {
|
|
1577
|
-
const configPath =
|
|
1834
|
+
const configPath = path5.join(process.cwd(), ".fractary", "codex", "config.yaml");
|
|
1578
1835
|
let config;
|
|
1579
1836
|
try {
|
|
1580
1837
|
config = await readYamlConfig(configPath);
|
|
@@ -1608,7 +1865,7 @@ function syncCommand() {
|
|
|
1608
1865
|
const syncManager = createSyncManager({
|
|
1609
1866
|
localStorage,
|
|
1610
1867
|
config: config.sync,
|
|
1611
|
-
manifestPath:
|
|
1868
|
+
manifestPath: path5.join(process.cwd(), ".fractary", ".codex-sync-manifest.json")
|
|
1612
1869
|
});
|
|
1613
1870
|
const defaultToCodexPatterns = [
|
|
1614
1871
|
"docs/**/*.md",
|
|
@@ -1659,8 +1916,8 @@ function syncCommand() {
|
|
|
1659
1916
|
}
|
|
1660
1917
|
const targetFiles = await Promise.all(
|
|
1661
1918
|
Array.from(matchedFilePaths).map(async (filePath) => {
|
|
1662
|
-
const fullPath =
|
|
1663
|
-
const stats = await import('fs/promises').then((
|
|
1919
|
+
const fullPath = path5.join(sourceDir, filePath);
|
|
1920
|
+
const stats = await import('fs/promises').then((fs9) => fs9.stat(fullPath));
|
|
1664
1921
|
return {
|
|
1665
1922
|
path: filePath,
|
|
1666
1923
|
size: stats.size,
|
|
@@ -2108,7 +2365,7 @@ function typesAddCommand() {
|
|
|
2108
2365
|
console.log(chalk8.dim("Examples: 30m, 24h, 7d"));
|
|
2109
2366
|
process.exit(1);
|
|
2110
2367
|
}
|
|
2111
|
-
const configPath =
|
|
2368
|
+
const configPath = path5.join(process.cwd(), ".fractary", "codex", "config.yaml");
|
|
2112
2369
|
const config = await readYamlConfig(configPath);
|
|
2113
2370
|
if (!config.types) {
|
|
2114
2371
|
config.types = { custom: {} };
|
|
@@ -2177,7 +2434,7 @@ function typesRemoveCommand() {
|
|
|
2177
2434
|
process.exit(1);
|
|
2178
2435
|
}
|
|
2179
2436
|
const typeInfo = registry.get(name);
|
|
2180
|
-
const configPath =
|
|
2437
|
+
const configPath = path5.join(process.cwd(), ".fractary", "codex", "config.yaml");
|
|
2181
2438
|
const config = await readYamlConfig(configPath);
|
|
2182
2439
|
if (!config.types?.custom?.[name]) {
|
|
2183
2440
|
console.error(chalk8.red("Error:"), `Custom type "${name}" not found in configuration.`);
|