@fractary/codex-cli 0.10.0 → 0.10.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 +130 -9
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +130 -9
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -874,7 +874,7 @@ init_esm_shims();
|
|
|
874
874
|
function sanitizeForS3BucketName(name) {
|
|
875
875
|
return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/^-+|-+$/g, "").replace(/-+/g, "-").substring(0, 63);
|
|
876
876
|
}
|
|
877
|
-
function getDefaultUnifiedConfig(organization, project) {
|
|
877
|
+
function getDefaultUnifiedConfig(organization, project, codexRepo) {
|
|
878
878
|
const sanitizedProject = sanitizeForS3BucketName(project);
|
|
879
879
|
return {
|
|
880
880
|
file: {
|
|
@@ -918,6 +918,7 @@ function getDefaultUnifiedConfig(organization, project) {
|
|
|
918
918
|
schema_version: "2.0",
|
|
919
919
|
organization,
|
|
920
920
|
project,
|
|
921
|
+
codex_repo: codexRepo,
|
|
921
922
|
dependencies: {}
|
|
922
923
|
}
|
|
923
924
|
};
|
|
@@ -961,6 +962,7 @@ function mergeUnifiedConfigs(existing, updates) {
|
|
|
961
962
|
schema_version: updates.codex?.schema_version || existing.codex?.schema_version || "2.0",
|
|
962
963
|
organization: updates.codex?.organization || existing.codex?.organization || "default",
|
|
963
964
|
project: updates.codex?.project || existing.codex?.project || "default",
|
|
965
|
+
codex_repo: updates.codex?.codex_repo || existing.codex?.codex_repo || "",
|
|
964
966
|
dependencies: {
|
|
965
967
|
...existing.codex?.dependencies || {},
|
|
966
968
|
...updates.codex?.dependencies || {}
|
|
@@ -969,10 +971,10 @@ function mergeUnifiedConfigs(existing, updates) {
|
|
|
969
971
|
}
|
|
970
972
|
return merged;
|
|
971
973
|
}
|
|
972
|
-
async function initializeUnifiedConfig(configPath, organization, project, options) {
|
|
974
|
+
async function initializeUnifiedConfig(configPath, organization, project, codexRepo, options) {
|
|
973
975
|
const existingConfig = await readUnifiedConfig(configPath);
|
|
974
976
|
if (existingConfig && !options?.force) {
|
|
975
|
-
const defaultConfig = getDefaultUnifiedConfig(organization, project);
|
|
977
|
+
const defaultConfig = getDefaultUnifiedConfig(organization, project, codexRepo);
|
|
976
978
|
const merged = mergeUnifiedConfigs(existingConfig, defaultConfig);
|
|
977
979
|
await writeUnifiedConfig(merged, configPath);
|
|
978
980
|
return {
|
|
@@ -981,7 +983,7 @@ async function initializeUnifiedConfig(configPath, organization, project, option
|
|
|
981
983
|
config: merged
|
|
982
984
|
};
|
|
983
985
|
}
|
|
984
|
-
const config = getDefaultUnifiedConfig(organization, project);
|
|
986
|
+
const config = getDefaultUnifiedConfig(organization, project, codexRepo);
|
|
985
987
|
await writeUnifiedConfig(config, configPath);
|
|
986
988
|
return {
|
|
987
989
|
created: true,
|
|
@@ -1090,6 +1092,20 @@ async function ensureCachePathIgnored(projectRoot, cachePath) {
|
|
|
1090
1092
|
}
|
|
1091
1093
|
|
|
1092
1094
|
// src/commands/config/init.ts
|
|
1095
|
+
function validateNameFormat(name, type) {
|
|
1096
|
+
if (!name || typeof name !== "string") {
|
|
1097
|
+
throw new Error(`${type} name is required`);
|
|
1098
|
+
}
|
|
1099
|
+
if (name.length > 100) {
|
|
1100
|
+
throw new Error(`${type} name too long (max 100 characters)`);
|
|
1101
|
+
}
|
|
1102
|
+
const safePattern = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
|
|
1103
|
+
if (!safePattern.test(name)) {
|
|
1104
|
+
throw new Error(
|
|
1105
|
+
`Invalid ${type} name format: "${name}". Must start with alphanumeric and contain only: a-z, A-Z, 0-9, ., -, _`
|
|
1106
|
+
);
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1093
1109
|
async function getOrgFromGitRemote() {
|
|
1094
1110
|
try {
|
|
1095
1111
|
const { execSync } = __require("child_process");
|
|
@@ -1101,6 +1117,60 @@ async function getOrgFromGitRemote() {
|
|
|
1101
1117
|
return null;
|
|
1102
1118
|
}
|
|
1103
1119
|
}
|
|
1120
|
+
async function discoverCodexRepo(org) {
|
|
1121
|
+
try {
|
|
1122
|
+
validateNameFormat(org, "organization");
|
|
1123
|
+
} catch (error) {
|
|
1124
|
+
return { repo: null, error: "unknown", message: error.message };
|
|
1125
|
+
}
|
|
1126
|
+
try {
|
|
1127
|
+
const { execSync } = __require("child_process");
|
|
1128
|
+
try {
|
|
1129
|
+
execSync("gh --version", { encoding: "utf-8", stdio: "pipe" });
|
|
1130
|
+
} catch {
|
|
1131
|
+
return {
|
|
1132
|
+
repo: null,
|
|
1133
|
+
error: "gh_not_installed",
|
|
1134
|
+
message: "GitHub CLI (gh) is not installed. Install from https://cli.github.com/"
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
try {
|
|
1138
|
+
execSync("gh auth status", { encoding: "utf-8", stdio: "pipe" });
|
|
1139
|
+
} catch {
|
|
1140
|
+
return {
|
|
1141
|
+
repo: null,
|
|
1142
|
+
error: "auth_failed",
|
|
1143
|
+
message: "GitHub CLI not authenticated. Run: gh auth login"
|
|
1144
|
+
};
|
|
1145
|
+
}
|
|
1146
|
+
const result = execSync(
|
|
1147
|
+
`gh repo list ${org} --json name --jq '.[].name | select(startswith("codex."))' 2>&1`,
|
|
1148
|
+
{ encoding: "utf-8" }
|
|
1149
|
+
).trim();
|
|
1150
|
+
if (result.includes("Could not resolve to an Organization") || result.includes("Not Found")) {
|
|
1151
|
+
return {
|
|
1152
|
+
repo: null,
|
|
1153
|
+
error: "org_not_found",
|
|
1154
|
+
message: `Organization '${org}' not found on GitHub`
|
|
1155
|
+
};
|
|
1156
|
+
}
|
|
1157
|
+
const repos = result.split("\n").filter(Boolean);
|
|
1158
|
+
if (repos.length === 0) {
|
|
1159
|
+
return {
|
|
1160
|
+
repo: null,
|
|
1161
|
+
error: "no_repos_found",
|
|
1162
|
+
message: `No codex.* repositories found in organization '${org}'`
|
|
1163
|
+
};
|
|
1164
|
+
}
|
|
1165
|
+
return { repo: repos[0] };
|
|
1166
|
+
} catch (error) {
|
|
1167
|
+
return {
|
|
1168
|
+
repo: null,
|
|
1169
|
+
error: "unknown",
|
|
1170
|
+
message: error.message || "Unknown error during discovery"
|
|
1171
|
+
};
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1104
1174
|
async function fileExists(filePath) {
|
|
1105
1175
|
try {
|
|
1106
1176
|
await fs.access(filePath);
|
|
@@ -1111,7 +1181,7 @@ async function fileExists(filePath) {
|
|
|
1111
1181
|
}
|
|
1112
1182
|
function initCommand() {
|
|
1113
1183
|
const cmd = new Command("init");
|
|
1114
|
-
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) => {
|
|
1184
|
+
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("--codex-repo <name>", 'Codex repository name (e.g., "codex.fractary.com")').option("--force", "Overwrite existing configuration").action(async (options) => {
|
|
1115
1185
|
try {
|
|
1116
1186
|
console.log(chalk7.blue("Initializing unified Fractary configuration...\n"));
|
|
1117
1187
|
let org = options.org;
|
|
@@ -1135,10 +1205,53 @@ function initCommand() {
|
|
|
1135
1205
|
console.log(chalk7.dim(`Organization: ${chalk7.cyan(org)}
|
|
1136
1206
|
`));
|
|
1137
1207
|
}
|
|
1208
|
+
try {
|
|
1209
|
+
validateNameFormat(org, "organization");
|
|
1210
|
+
} catch (error) {
|
|
1211
|
+
console.error(chalk7.red("Error:"), error.message);
|
|
1212
|
+
process.exit(1);
|
|
1213
|
+
}
|
|
1138
1214
|
let project = options.project;
|
|
1139
1215
|
if (!project) {
|
|
1140
1216
|
project = path5.basename(process.cwd());
|
|
1141
1217
|
console.log(chalk7.dim(`Project: ${chalk7.cyan(project)}
|
|
1218
|
+
`));
|
|
1219
|
+
}
|
|
1220
|
+
let codexRepo = options.codexRepo;
|
|
1221
|
+
if (codexRepo) {
|
|
1222
|
+
try {
|
|
1223
|
+
validateNameFormat(codexRepo, "repository");
|
|
1224
|
+
} catch (error) {
|
|
1225
|
+
console.error(chalk7.red("Error:"), error.message);
|
|
1226
|
+
process.exit(1);
|
|
1227
|
+
}
|
|
1228
|
+
console.log(chalk7.dim(`Codex repository: ${chalk7.cyan(codexRepo)}
|
|
1229
|
+
`));
|
|
1230
|
+
} else {
|
|
1231
|
+
const discoveryResult = await discoverCodexRepo(org);
|
|
1232
|
+
if (discoveryResult.repo) {
|
|
1233
|
+
codexRepo = discoveryResult.repo;
|
|
1234
|
+
console.log(chalk7.dim(`Codex repository: ${chalk7.cyan(codexRepo)} (auto-discovered)
|
|
1235
|
+
`));
|
|
1236
|
+
} else {
|
|
1237
|
+
if (discoveryResult.error === "gh_not_installed") {
|
|
1238
|
+
console.log(chalk7.dim(` Note: ${discoveryResult.message}
|
|
1239
|
+
`));
|
|
1240
|
+
} else if (discoveryResult.error === "auth_failed") {
|
|
1241
|
+
console.log(chalk7.dim(` Note: ${discoveryResult.message}
|
|
1242
|
+
`));
|
|
1243
|
+
} else if (discoveryResult.error === "org_not_found") {
|
|
1244
|
+
console.log(chalk7.dim(` Note: ${discoveryResult.message}
|
|
1245
|
+
`));
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
if (!codexRepo) {
|
|
1250
|
+
console.log(chalk7.yellow(`\u26A0 Could not discover codex repository in organization '${org}'`));
|
|
1251
|
+
console.log(chalk7.dim(" Use --codex-repo <name> to specify explicitly"));
|
|
1252
|
+
console.log(chalk7.dim(" Expected naming convention: codex.{org}.{tld} (e.g., codex.fractary.com)\n"));
|
|
1253
|
+
codexRepo = `codex.${org}.com`;
|
|
1254
|
+
console.log(chalk7.dim(` Using default: ${chalk7.cyan(codexRepo)}
|
|
1142
1255
|
`));
|
|
1143
1256
|
}
|
|
1144
1257
|
const configPath = path5.join(process.cwd(), ".fractary", "config.yaml");
|
|
@@ -1172,6 +1285,7 @@ function initCommand() {
|
|
|
1172
1285
|
configPath,
|
|
1173
1286
|
org,
|
|
1174
1287
|
project,
|
|
1288
|
+
codexRepo,
|
|
1175
1289
|
{ force: options.force }
|
|
1176
1290
|
);
|
|
1177
1291
|
if (result.created) {
|
|
@@ -1183,6 +1297,7 @@ function initCommand() {
|
|
|
1183
1297
|
console.log(chalk7.bold("Configuration:"));
|
|
1184
1298
|
console.log(chalk7.dim(` Organization: ${org}`));
|
|
1185
1299
|
console.log(chalk7.dim(` Project: ${project}`));
|
|
1300
|
+
console.log(chalk7.dim(` Codex Repository: ${codexRepo}`));
|
|
1186
1301
|
console.log(chalk7.dim(` Config: .fractary/config.yaml`));
|
|
1187
1302
|
console.log(chalk7.bold("\nFile plugin sources:"));
|
|
1188
1303
|
console.log(chalk7.dim(" - specs: .fractary/specs/ \u2192 S3"));
|
|
@@ -1190,11 +1305,17 @@ function initCommand() {
|
|
|
1190
1305
|
console.log(chalk7.bold("\nCodex plugin:"));
|
|
1191
1306
|
console.log(chalk7.dim(" - Cache: .fractary/codex/cache/"));
|
|
1192
1307
|
console.log(chalk7.dim(" - Dependencies: (none configured)"));
|
|
1308
|
+
console.log(chalk7.bold("\nGit Authentication:"));
|
|
1309
|
+
console.log(chalk7.dim(" Codex sync uses your existing git credentials."));
|
|
1310
|
+
console.log(chalk7.dim(" Ensure you have access to the codex repository:"));
|
|
1311
|
+
console.log(chalk7.dim(` gh repo view ${org}/${codexRepo}`));
|
|
1312
|
+
console.log(chalk7.dim(" Or set GITHUB_TOKEN environment variable."));
|
|
1193
1313
|
console.log(chalk7.bold("\nNext steps:"));
|
|
1194
|
-
console.log(chalk7.dim(" 1.
|
|
1195
|
-
console.log(chalk7.dim(" 2.
|
|
1196
|
-
console.log(chalk7.dim(" 3.
|
|
1197
|
-
console.log(chalk7.dim(" 4. Access
|
|
1314
|
+
console.log(chalk7.dim(" 1. Verify codex repository access: gh repo view " + org + "/" + codexRepo));
|
|
1315
|
+
console.log(chalk7.dim(" 2. Configure AWS credentials for S3 access (if using file plugin)"));
|
|
1316
|
+
console.log(chalk7.dim(" 3. Edit .fractary/config.yaml to add external project dependencies"));
|
|
1317
|
+
console.log(chalk7.dim(" 4. Access current project files: codex://specs/SPEC-001.md"));
|
|
1318
|
+
console.log(chalk7.dim(" 5. Access external projects: codex://org/project/docs/README.md"));
|
|
1198
1319
|
} catch (error) {
|
|
1199
1320
|
console.error(chalk7.red("Error:"), error.message);
|
|
1200
1321
|
process.exit(1);
|