@fractary/codex-cli 0.8.0 → 0.9.0

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 CHANGED
@@ -2,7 +2,7 @@
2
2
  'use strict';
3
3
 
4
4
  var fs$1 = require('fs/promises');
5
- var path3 = require('path');
5
+ var path4 = require('path');
6
6
  var yaml = require('js-yaml');
7
7
  var codex = require('@fractary/codex');
8
8
  var os = require('os');
@@ -34,7 +34,7 @@ function _interopNamespace(e) {
34
34
  }
35
35
 
36
36
  var fs__namespace = /*#__PURE__*/_interopNamespace(fs$1);
37
- var path3__namespace = /*#__PURE__*/_interopNamespace(path3);
37
+ var path4__namespace = /*#__PURE__*/_interopNamespace(path4);
38
38
  var yaml__namespace = /*#__PURE__*/_interopNamespace(yaml);
39
39
  var os__namespace = /*#__PURE__*/_interopNamespace(os);
40
40
  var chalk8__default = /*#__PURE__*/_interopDefault(chalk8);
@@ -194,7 +194,7 @@ async function migrateConfig(legacyConfigPath, options) {
194
194
  }
195
195
  }
196
196
  async function writeYamlConfig(config, outputPath) {
197
- const dir = path3__namespace.dirname(outputPath);
197
+ const dir = path4__namespace.dirname(outputPath);
198
198
  await fs__namespace.mkdir(dir, { recursive: true });
199
199
  const yamlContent = yaml__namespace.dump(config, {
200
200
  indent: 2,
@@ -418,7 +418,7 @@ var init_codex_client = __esm({
418
418
  const { readYamlConfig: readYamlConfig2 } = await Promise.resolve().then(() => (init_migrate_config(), migrate_config_exports));
419
419
  const { resolveEnvVarsInConfig: resolveEnvVarsInConfig2 } = await Promise.resolve().then(() => (init_config_types(), config_types_exports));
420
420
  try {
421
- const configPath = path3__namespace.join(process.cwd(), ".fractary", "codex", "config.yaml");
421
+ const configPath = path4__namespace.join(process.cwd(), ".fractary", "codex", "config.yaml");
422
422
  let config;
423
423
  try {
424
424
  config = await readYamlConfig2(configPath);
@@ -688,7 +688,7 @@ function getTempCodexPath(config) {
688
688
  const codexRepo = config.codex_repository || "codex";
689
689
  const sanitizedOrg = sanitizePathComponent(config.organization);
690
690
  const sanitizedRepo = sanitizePathComponent(codexRepo);
691
- return path3__namespace.join(
691
+ return path4__namespace.join(
692
692
  os__namespace.tmpdir(),
693
693
  "fractary-codex-clone",
694
694
  `${sanitizedOrg}-${sanitizedRepo}-${process.pid}`
@@ -696,7 +696,7 @@ function getTempCodexPath(config) {
696
696
  }
697
697
  async function isValidGitRepo(repoPath) {
698
698
  try {
699
- const gitDir = path3__namespace.join(repoPath, ".git");
699
+ const gitDir = path4__namespace.join(repoPath, ".git");
700
700
  const stats = await fs__namespace.stat(gitDir);
701
701
  return stats.isDirectory();
702
702
  } catch {
@@ -729,7 +729,7 @@ async function execGit(repoPath, args) {
729
729
  }
730
730
  }
731
731
  async function gitClone(url, targetPath, options) {
732
- const parentDir = path3__namespace.dirname(targetPath);
732
+ const parentDir = path4__namespace.dirname(targetPath);
733
733
  await fs__namespace.mkdir(parentDir, { recursive: true });
734
734
  const args = ["clone"];
735
735
  if (options?.depth) {
@@ -901,7 +901,129 @@ init_cjs_shims();
901
901
 
902
902
  // src/commands/config/init.ts
903
903
  init_cjs_shims();
904
- init_migrate_config();
904
+
905
+ // src/config/unified-config.ts
906
+ init_cjs_shims();
907
+ function sanitizeForS3BucketName(name) {
908
+ return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/^-+|-+$/g, "").replace(/-+/g, "-").substring(0, 63);
909
+ }
910
+ function getDefaultUnifiedConfig(organization, project) {
911
+ const sanitizedProject = sanitizeForS3BucketName(project);
912
+ return {
913
+ file: {
914
+ schema_version: "2.0",
915
+ sources: {
916
+ specs: {
917
+ type: "s3",
918
+ bucket: `${sanitizedProject}-files`,
919
+ prefix: "specs/",
920
+ region: "us-east-1",
921
+ local: {
922
+ base_path: ".fractary/specs"
923
+ },
924
+ push: {
925
+ compress: false,
926
+ keep_local: true
927
+ },
928
+ auth: {
929
+ profile: "default"
930
+ }
931
+ },
932
+ logs: {
933
+ type: "s3",
934
+ bucket: `${sanitizedProject}-files`,
935
+ prefix: "logs/",
936
+ region: "us-east-1",
937
+ local: {
938
+ base_path: ".fractary/logs"
939
+ },
940
+ push: {
941
+ compress: true,
942
+ keep_local: true
943
+ },
944
+ auth: {
945
+ profile: "default"
946
+ }
947
+ }
948
+ }
949
+ },
950
+ codex: {
951
+ schema_version: "2.0",
952
+ organization,
953
+ project,
954
+ dependencies: {}
955
+ }
956
+ };
957
+ }
958
+ async function readUnifiedConfig(configPath) {
959
+ try {
960
+ const content = await fs__namespace.readFile(configPath, "utf-8");
961
+ const config = yaml__namespace.load(content);
962
+ return config;
963
+ } catch (error) {
964
+ if (error.code === "ENOENT") {
965
+ return null;
966
+ }
967
+ throw error;
968
+ }
969
+ }
970
+ async function writeUnifiedConfig(config, outputPath) {
971
+ const dir = path4__namespace.dirname(outputPath);
972
+ await fs__namespace.mkdir(dir, { recursive: true });
973
+ const yamlContent = yaml__namespace.dump(config, {
974
+ indent: 2,
975
+ lineWidth: 120,
976
+ noRefs: true,
977
+ sortKeys: false
978
+ });
979
+ await fs__namespace.writeFile(outputPath, yamlContent, "utf-8");
980
+ }
981
+ function mergeUnifiedConfigs(existing, updates) {
982
+ const merged = {};
983
+ if (updates.file || existing.file) {
984
+ merged.file = {
985
+ schema_version: updates.file?.schema_version || existing.file?.schema_version || "2.0",
986
+ sources: {
987
+ ...existing.file?.sources || {},
988
+ ...updates.file?.sources || {}
989
+ }
990
+ };
991
+ }
992
+ if (updates.codex || existing.codex) {
993
+ merged.codex = {
994
+ schema_version: updates.codex?.schema_version || existing.codex?.schema_version || "2.0",
995
+ organization: updates.codex?.organization || existing.codex?.organization || "default",
996
+ project: updates.codex?.project || existing.codex?.project || "default",
997
+ dependencies: {
998
+ ...existing.codex?.dependencies || {},
999
+ ...updates.codex?.dependencies || {}
1000
+ }
1001
+ };
1002
+ }
1003
+ return merged;
1004
+ }
1005
+ async function initializeUnifiedConfig(configPath, organization, project, options) {
1006
+ const existingConfig = await readUnifiedConfig(configPath);
1007
+ if (existingConfig && !options?.force) {
1008
+ const defaultConfig = getDefaultUnifiedConfig(organization, project);
1009
+ const merged = mergeUnifiedConfigs(existingConfig, defaultConfig);
1010
+ await writeUnifiedConfig(merged, configPath);
1011
+ return {
1012
+ created: false,
1013
+ merged: true,
1014
+ config: merged
1015
+ };
1016
+ }
1017
+ const config = getDefaultUnifiedConfig(organization, project);
1018
+ await writeUnifiedConfig(config, configPath);
1019
+ return {
1020
+ created: true,
1021
+ merged: false,
1022
+ config
1023
+ };
1024
+ }
1025
+
1026
+ // src/commands/config/init.ts
905
1027
  async function getOrgFromGitRemote() {
906
1028
  try {
907
1029
  const { execSync } = __require("child_process");
@@ -923,9 +1045,9 @@ async function fileExists(filePath) {
923
1045
  }
924
1046
  function initCommand() {
925
1047
  const cmd = new commander.Command("init");
926
- cmd.description("Initialize Codex v3.0 with YAML configuration").option("--org <slug>", 'Organization slug (e.g., "fractary")').option("--mcp", "Enable MCP server registration").option("--force", "Overwrite existing configuration").action(async (options) => {
1048
+ 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) => {
927
1049
  try {
928
- console.log(chalk8__default.default.blue("Initializing Codex v3.0 (YAML format)...\n"));
1050
+ console.log(chalk8__default.default.blue("Initializing unified Fractary configuration...\n"));
929
1051
  let org = options.org;
930
1052
  if (!org) {
931
1053
  org = await getOrgFromGitRemote();
@@ -934,60 +1056,71 @@ function initCommand() {
934
1056
  try {
935
1057
  const { resolveOrganization } = await import('@fractary/codex');
936
1058
  org = resolveOrganization({
937
- repoName: path3__namespace.basename(process.cwd())
1059
+ repoName: path4__namespace.basename(process.cwd())
938
1060
  });
939
1061
  } catch {
940
1062
  }
941
1063
  }
942
1064
  if (!org) {
943
- org = path3__namespace.basename(process.cwd()).split("-")[0] || "default";
1065
+ org = path4__namespace.basename(process.cwd()).split("-")[0] || "default";
944
1066
  console.log(chalk8__default.default.yellow(`\u26A0 Could not detect organization, using: ${org}`));
945
1067
  console.log(chalk8__default.default.dim(" Use --org <slug> to specify explicitly\n"));
946
1068
  } else {
947
1069
  console.log(chalk8__default.default.dim(`Organization: ${chalk8__default.default.cyan(org)}
948
1070
  `));
949
1071
  }
950
- const configDir = path3__namespace.join(process.cwd(), ".fractary", "codex");
951
- const configPath = path3__namespace.join(configDir, "config.yaml");
1072
+ let project = options.project;
1073
+ if (!project) {
1074
+ project = path4__namespace.basename(process.cwd());
1075
+ console.log(chalk8__default.default.dim(`Project: ${chalk8__default.default.cyan(project)}
1076
+ `));
1077
+ }
1078
+ const configPath = path4__namespace.join(process.cwd(), ".fractary", "config.yaml");
952
1079
  const configExists = await fileExists(configPath);
953
1080
  if (configExists && !options.force) {
954
- console.log(chalk8__default.default.yellow("\u26A0 Configuration already exists at .fractary/codex/config.yaml"));
955
- console.log(chalk8__default.default.dim("Use --force to overwrite"));
956
- process.exit(1);
1081
+ console.log(chalk8__default.default.yellow(`\u26A0 Configuration already exists at .fractary/config.yaml`));
1082
+ console.log(chalk8__default.default.dim("Merging with existing configuration...\n"));
957
1083
  }
958
1084
  console.log("Creating directory structure...");
959
1085
  const dirs = [
1086
+ ".fractary",
1087
+ ".fractary/specs",
1088
+ ".fractary/logs",
960
1089
  ".fractary/codex",
961
1090
  ".fractary/codex/cache"
962
1091
  ];
963
1092
  for (const dir of dirs) {
964
- await fs__namespace.mkdir(path3__namespace.join(process.cwd(), dir), { recursive: true });
1093
+ await fs__namespace.mkdir(path4__namespace.join(process.cwd(), dir), { recursive: true });
965
1094
  console.log(chalk8__default.default.green("\u2713"), chalk8__default.default.dim(dir + "/"));
966
1095
  }
967
- console.log("\nCreating YAML configuration...");
968
- const config = getDefaultYamlConfig(org);
969
- if (options.mcp && config.mcp) {
970
- config.mcp.enabled = true;
1096
+ console.log("\nInitializing configuration...");
1097
+ const result = await initializeUnifiedConfig(
1098
+ configPath,
1099
+ org,
1100
+ project,
1101
+ { force: options.force }
1102
+ );
1103
+ if (result.created) {
1104
+ console.log(chalk8__default.default.green("\u2713"), chalk8__default.default.dim(".fractary/config.yaml (created)"));
1105
+ } else if (result.merged) {
1106
+ console.log(chalk8__default.default.green("\u2713"), chalk8__default.default.dim(".fractary/config.yaml (merged with existing)"));
971
1107
  }
972
- await writeYamlConfig(config, configPath);
973
- console.log(chalk8__default.default.green("\u2713"), chalk8__default.default.dim(".fractary/codex/config.yaml"));
974
- console.log(chalk8__default.default.green("\n\u2713 Codex v4.0 initialized successfully!\n"));
1108
+ console.log(chalk8__default.default.green("\n\u2713 Unified configuration initialized successfully!\n"));
975
1109
  console.log(chalk8__default.default.bold("Configuration:"));
976
1110
  console.log(chalk8__default.default.dim(` Organization: ${org}`));
977
- console.log(chalk8__default.default.dim(` Cache: .fractary/codex/cache/`));
978
- console.log(chalk8__default.default.dim(` Config: .fractary/codex/config.yaml`));
979
- if (options.mcp) {
980
- console.log(chalk8__default.default.dim(` MCP Server: Enabled (port 3000)`));
981
- }
982
- console.log(chalk8__default.default.bold("\nStorage providers configured:"));
983
- console.log(chalk8__default.default.dim(" - Local filesystem (./knowledge)"));
984
- console.log(chalk8__default.default.dim(" - GitHub (requires GITHUB_TOKEN)"));
985
- console.log(chalk8__default.default.dim(" - HTTP endpoint"));
1111
+ console.log(chalk8__default.default.dim(` Project: ${project}`));
1112
+ console.log(chalk8__default.default.dim(` Config: .fractary/config.yaml`));
1113
+ console.log(chalk8__default.default.bold("\nFile plugin sources:"));
1114
+ console.log(chalk8__default.default.dim(" - specs: .fractary/specs/ \u2192 S3"));
1115
+ console.log(chalk8__default.default.dim(" - logs: .fractary/logs/ \u2192 S3"));
1116
+ console.log(chalk8__default.default.bold("\nCodex plugin:"));
1117
+ console.log(chalk8__default.default.dim(" - Cache: .fractary/codex/cache/"));
1118
+ console.log(chalk8__default.default.dim(" - Dependencies: (none configured)"));
986
1119
  console.log(chalk8__default.default.bold("\nNext steps:"));
987
- console.log(chalk8__default.default.dim(' 1. Set your GitHub token: export GITHUB_TOKEN="your_token"'));
988
- console.log(chalk8__default.default.dim(" 2. Edit .fractary/codex/config.yaml to configure storage providers"));
989
- console.log(chalk8__default.default.dim(" 3. Fetch a document: fractary codex fetch codex://org/project/path"));
990
- console.log(chalk8__default.default.dim(" 4. Check cache: fractary codex cache list"));
1120
+ console.log(chalk8__default.default.dim(" 1. Configure AWS credentials for S3 access"));
1121
+ console.log(chalk8__default.default.dim(" 2. Edit .fractary/config.yaml to add external project dependencies"));
1122
+ console.log(chalk8__default.default.dim(" 3. Access current project files: codex://specs/SPEC-001.md"));
1123
+ console.log(chalk8__default.default.dim(" 4. Access external projects: codex://org/project/docs/README.md"));
991
1124
  } catch (error) {
992
1125
  console.error(chalk8__default.default.red("Error:"), error.message);
993
1126
  process.exit(1);
@@ -1014,8 +1147,8 @@ function migrateCommand() {
1014
1147
  const cmd = new commander.Command("migrate");
1015
1148
  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) => {
1016
1149
  try {
1017
- const legacyConfigPath = path3__namespace.join(process.cwd(), ".fractary", "plugins", "codex", "config.json");
1018
- const newConfigPath = path3__namespace.join(process.cwd(), ".fractary", "codex", "config.yaml");
1150
+ const legacyConfigPath = path4__namespace.join(process.cwd(), ".fractary", "plugins", "codex", "config.json");
1151
+ const newConfigPath = path4__namespace.join(process.cwd(), ".fractary", "codex", "config.yaml");
1019
1152
  if (!await fileExists2(legacyConfigPath)) {
1020
1153
  if (options.json) {
1021
1154
  console.log(JSON.stringify({
@@ -1110,7 +1243,7 @@ function migrateCommand() {
1110
1243
  }
1111
1244
  if (!options.dryRun) {
1112
1245
  await writeYamlConfig(migrationResult.yamlConfig, newConfigPath);
1113
- const cacheDir = path3__namespace.join(process.cwd(), ".codex-cache");
1246
+ const cacheDir = path4__namespace.join(process.cwd(), ".codex-cache");
1114
1247
  await fs__namespace.mkdir(cacheDir, { recursive: true });
1115
1248
  if (!options.json) {
1116
1249
  console.log(chalk8__default.default.green("\u2713"), "YAML configuration created");
@@ -1131,7 +1264,7 @@ function migrateCommand() {
1131
1264
  console.log(chalk8__default.default.dim(" 3. Test fetching: fractary codex fetch codex://org/project/path"));
1132
1265
  if (migrationResult.backupPath) {
1133
1266
  console.log("");
1134
- console.log(chalk8__default.default.dim(`Backup saved: ${path3__namespace.basename(migrationResult.backupPath)}`));
1267
+ console.log(chalk8__default.default.dim(`Backup saved: ${path4__namespace.basename(migrationResult.backupPath)}`));
1135
1268
  }
1136
1269
  }
1137
1270
  }
@@ -1341,8 +1474,8 @@ async function fileExists3(filePath) {
1341
1474
  }
1342
1475
  }
1343
1476
  async function checkConfiguration() {
1344
- const configPath = path3__namespace.join(process.cwd(), ".fractary", "codex", "config.yaml");
1345
- const legacyConfigPath = path3__namespace.join(process.cwd(), ".fractary", "plugins", "codex", "config.json");
1477
+ const configPath = path4__namespace.join(process.cwd(), ".fractary", "codex", "config.yaml");
1478
+ const legacyConfigPath = path4__namespace.join(process.cwd(), ".fractary", "plugins", "codex", "config.json");
1346
1479
  try {
1347
1480
  if (!await fileExists3(configPath)) {
1348
1481
  if (await fileExists3(legacyConfigPath)) {
@@ -1449,7 +1582,7 @@ async function checkCache() {
1449
1582
  }
1450
1583
  }
1451
1584
  async function checkStorage() {
1452
- const configPath = path3__namespace.join(process.cwd(), ".fractary", "codex", "config.yaml");
1585
+ const configPath = path4__namespace.join(process.cwd(), ".fractary", "codex", "config.yaml");
1453
1586
  try {
1454
1587
  const config = await readYamlConfig(configPath);
1455
1588
  const providers = config.storage || [];
@@ -1607,7 +1740,7 @@ function syncCommand() {
1607
1740
  const cmd = new commander.Command("sync");
1608
1741
  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) => {
1609
1742
  try {
1610
- const configPath = path3__namespace.join(process.cwd(), ".fractary", "codex", "config.yaml");
1743
+ const configPath = path4__namespace.join(process.cwd(), ".fractary", "codex", "config.yaml");
1611
1744
  let config;
1612
1745
  try {
1613
1746
  config = await readYamlConfig(configPath);
@@ -1641,7 +1774,7 @@ function syncCommand() {
1641
1774
  const syncManager = createSyncManager({
1642
1775
  localStorage,
1643
1776
  config: config.sync,
1644
- manifestPath: path3__namespace.join(process.cwd(), ".fractary", ".codex-sync-manifest.json")
1777
+ manifestPath: path4__namespace.join(process.cwd(), ".fractary", ".codex-sync-manifest.json")
1645
1778
  });
1646
1779
  const defaultToCodexPatterns = [
1647
1780
  "docs/**/*.md",
@@ -1692,8 +1825,8 @@ function syncCommand() {
1692
1825
  }
1693
1826
  const targetFiles = await Promise.all(
1694
1827
  Array.from(matchedFilePaths).map(async (filePath) => {
1695
- const fullPath = path3__namespace.join(sourceDir, filePath);
1696
- const stats = await import('fs/promises').then((fs7) => fs7.stat(fullPath));
1828
+ const fullPath = path4__namespace.join(sourceDir, filePath);
1829
+ const stats = await import('fs/promises').then((fs8) => fs8.stat(fullPath));
1697
1830
  return {
1698
1831
  path: filePath,
1699
1832
  size: stats.size,
@@ -2141,7 +2274,7 @@ function typesAddCommand() {
2141
2274
  console.log(chalk8__default.default.dim("Examples: 30m, 24h, 7d"));
2142
2275
  process.exit(1);
2143
2276
  }
2144
- const configPath = path3__namespace.join(process.cwd(), ".fractary", "codex", "config.yaml");
2277
+ const configPath = path4__namespace.join(process.cwd(), ".fractary", "codex", "config.yaml");
2145
2278
  const config = await readYamlConfig(configPath);
2146
2279
  if (!config.types) {
2147
2280
  config.types = { custom: {} };
@@ -2210,7 +2343,7 @@ function typesRemoveCommand() {
2210
2343
  process.exit(1);
2211
2344
  }
2212
2345
  const typeInfo = registry.get(name);
2213
- const configPath = path3__namespace.join(process.cwd(), ".fractary", "codex", "config.yaml");
2346
+ const configPath = path4__namespace.join(process.cwd(), ".fractary", "codex", "config.yaml");
2214
2347
  const config = await readYamlConfig(configPath);
2215
2348
  if (!config.types?.custom?.[name]) {
2216
2349
  console.error(chalk8__default.default.red("Error:"), `Custom type "${name}" not found in configuration.`);
@@ -2266,8 +2399,8 @@ function typesCommand() {
2266
2399
  return cmd;
2267
2400
  }
2268
2401
  var __filename2 = url.fileURLToPath(importMetaUrl);
2269
- var __dirname$1 = path3.dirname(__filename2);
2270
- var packageJson = JSON.parse(fs.readFileSync(path3.join(__dirname$1, "../package.json"), "utf-8"));
2402
+ var __dirname$1 = path4.dirname(__filename2);
2403
+ var packageJson = JSON.parse(fs.readFileSync(path4.join(__dirname$1, "../package.json"), "utf-8"));
2271
2404
  var VERSION = packageJson.version;
2272
2405
  function createCLI() {
2273
2406
  const program = new commander.Command("fractary-codex");