@fractary/codex-cli 0.10.14 → 0.10.16

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
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import * as path5 from 'path';
2
+ import * as path3 from 'path';
3
3
  import { dirname, join } from 'path';
4
4
  import { fileURLToPath } from 'url';
5
- import * as fs from 'fs/promises';
6
- import * as yaml2 from 'js-yaml';
5
+ import * as fs4 from 'fs/promises';
6
+ import * as yaml from 'js-yaml';
7
7
  import { readCodexConfig, CONFIG_SCHEMA_VERSION, expandEnvVarsInConfig, expandEnvVars, parseSize, parseDuration, ValidationError, PermissionDeniedError, ConfigurationError, CodexError } from '@fractary/codex';
8
8
  import * as os from 'os';
9
9
  import { spawn } from 'child_process';
@@ -43,7 +43,7 @@ __export(migrate_config_exports, {
43
43
  });
44
44
  async function isLegacyConfig(configPath) {
45
45
  try {
46
- const content = await fs.readFile(configPath, "utf-8");
46
+ const content = await fs4.readFile(configPath, "utf-8");
47
47
  const config = JSON.parse(content);
48
48
  return config.version === "3.0" || config.organizationSlug !== void 0 || config.directories !== void 0 || config.rules !== void 0;
49
49
  } catch {
@@ -53,13 +53,13 @@ async function isLegacyConfig(configPath) {
53
53
  async function migrateConfig(legacyConfigPath, options) {
54
54
  const warnings = [];
55
55
  try {
56
- const content = await fs.readFile(legacyConfigPath, "utf-8");
56
+ const content = await fs4.readFile(legacyConfigPath, "utf-8");
57
57
  const legacy = JSON.parse(content);
58
58
  let backupPath;
59
59
  if (options?.createBackup !== false) {
60
60
  const suffix = options?.backupSuffix || (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
61
61
  backupPath = `${legacyConfigPath}.backup-${suffix}`;
62
- await fs.writeFile(backupPath, content, "utf-8");
62
+ await fs4.writeFile(backupPath, content, "utf-8");
63
63
  }
64
64
  const yamlConfig = {
65
65
  organization: legacy.organization || legacy.organizationSlug || "default"
@@ -161,15 +161,15 @@ async function migrateConfig(legacyConfigPath, options) {
161
161
  }
162
162
  }
163
163
  async function writeYamlConfig(config, outputPath) {
164
- const dir = path5.dirname(outputPath);
165
- await fs.mkdir(dir, { recursive: true });
166
- const yamlContent = yaml2.dump(config, {
164
+ const dir = path3.dirname(outputPath);
165
+ await fs4.mkdir(dir, { recursive: true });
166
+ const yamlContent = yaml.dump(config, {
167
167
  indent: 2,
168
168
  lineWidth: 80,
169
169
  noRefs: true,
170
170
  sortKeys: false
171
171
  });
172
- await fs.writeFile(outputPath, yamlContent, "utf-8");
172
+ await fs4.writeFile(outputPath, yamlContent, "utf-8");
173
173
  }
174
174
  function getDefaultYamlConfig(organization) {
175
175
  return {
@@ -297,14 +297,14 @@ var init_codex_client = __esm({
297
297
  const { readYamlConfig } = await Promise.resolve().then(() => (init_migrate_config(), migrate_config_exports));
298
298
  const { resolveEnvVarsInConfig } = await Promise.resolve().then(() => (init_config_types(), config_types_exports));
299
299
  try {
300
- const configPath = path5.join(process.cwd(), ".fractary", "config.yaml");
300
+ const configPath = path3.join(process.cwd(), ".fractary", "config.yaml");
301
301
  let config;
302
302
  try {
303
303
  config = await readYamlConfig(configPath);
304
304
  config = resolveEnvVarsInConfig(config);
305
305
  } catch (error) {
306
306
  throw new ConfigurationError2(
307
- `Failed to load configuration from ${configPath}. Run "fractary codex init" to create a configuration.`
307
+ `Failed to load configuration from ${configPath}. Run "fractary-codex configure" to create a configuration.`
308
308
  );
309
309
  }
310
310
  const organization = options?.organizationSlug || config.organization;
@@ -567,7 +567,7 @@ function getTempCodexPath(config) {
567
567
  const codexRepo = config.codex_repo || "codex";
568
568
  const sanitizedOrg = sanitizePathComponent(config.organization);
569
569
  const sanitizedRepo = sanitizePathComponent(codexRepo);
570
- return path5.join(
570
+ return path3.join(
571
571
  os.tmpdir(),
572
572
  "fractary-codex-clone",
573
573
  `${sanitizedOrg}-${sanitizedRepo}-${process.pid}`
@@ -575,8 +575,8 @@ function getTempCodexPath(config) {
575
575
  }
576
576
  async function isValidGitRepo(repoPath) {
577
577
  try {
578
- const gitDir = path5.join(repoPath, ".git");
579
- const stats = await fs.stat(gitDir);
578
+ const gitDir = path3.join(repoPath, ".git");
579
+ const stats = await fs4.stat(gitDir);
580
580
  return stats.isDirectory();
581
581
  } catch {
582
582
  return false;
@@ -608,8 +608,8 @@ async function execGit(repoPath, args) {
608
608
  }
609
609
  }
610
610
  async function gitClone(url, targetPath, options) {
611
- const parentDir = path5.dirname(targetPath);
612
- await fs.mkdir(parentDir, { recursive: true });
611
+ const parentDir = path3.dirname(targetPath);
612
+ await fs4.mkdir(parentDir, { recursive: true });
613
613
  const args = ["clone"];
614
614
  if (options?.depth) {
615
615
  if (!Number.isInteger(options.depth) || options.depth <= 0) {
@@ -656,12 +656,12 @@ async function ensureCodexCloned(config, options) {
656
656
  } catch (error) {
657
657
  console.warn(`Failed to update existing clone: ${error.message}`);
658
658
  console.warn(`Removing and cloning fresh...`);
659
- await fs.rm(tempPath, { recursive: true, force: true });
659
+ await fs4.rm(tempPath, { recursive: true, force: true });
660
660
  }
661
661
  }
662
662
  const repoUrl = getCodexRepoUrl(config);
663
663
  try {
664
- await fs.rm(tempPath, { recursive: true, force: true });
664
+ await fs4.rm(tempPath, { recursive: true, force: true });
665
665
  } catch (error) {
666
666
  console.warn(`Could not remove existing directory ${tempPath}: ${error.message}`);
667
667
  }
@@ -681,100 +681,6 @@ var init_codex_repository = __esm({
681
681
  // src/cli.ts
682
682
  init_esm_shims();
683
683
 
684
- // src/commands/document/index.ts
685
- init_esm_shims();
686
-
687
- // src/commands/document/fetch.ts
688
- init_esm_shims();
689
-
690
- // src/client/get-client.ts
691
- init_esm_shims();
692
- var clientInstance = null;
693
- async function getClient(options) {
694
- if (!clientInstance) {
695
- const { CodexClient: CodexClient2 } = await Promise.resolve().then(() => (init_codex_client(), codex_client_exports));
696
- clientInstance = await CodexClient2.create(options);
697
- }
698
- return clientInstance;
699
- }
700
-
701
- // src/commands/document/fetch.ts
702
- function hashContent(content) {
703
- return crypto.createHash("sha256").update(content).digest("hex").slice(0, 16);
704
- }
705
- function fetchCommand() {
706
- const cmd = new Command("fetch");
707
- cmd.description("Fetch a document by codex:// URI reference").argument("<uri>", "Codex URI (e.g., codex://org/project/docs/file.md)").option("--bypass-cache", "Skip cache and fetch directly from source").option("--ttl <seconds>", "Override default TTL (in seconds)", parseInt).option("--json", "Output as JSON with metadata").option("--output <file>", "Write content to file instead of stdout").action(async (uri, options) => {
708
- try {
709
- const { validateUri } = await import('@fractary/codex');
710
- if (!validateUri(uri)) {
711
- console.error(chalk7.red("Error: Invalid URI format"));
712
- console.log(chalk7.dim("Expected: codex://org/project/path/to/file.md"));
713
- console.log(chalk7.dim("Example: codex://fractary/codex/docs/api.md"));
714
- process.exit(1);
715
- }
716
- const client = await getClient();
717
- if (!options.json && !options.bypassCache) {
718
- console.error(chalk7.dim(`Fetching ${uri}...`));
719
- }
720
- const result = await client.fetch(uri, {
721
- bypassCache: options.bypassCache,
722
- ttl: options.ttl
723
- });
724
- if (options.json) {
725
- const output = {
726
- uri,
727
- content: result.content.toString("utf-8"),
728
- metadata: {
729
- fromCache: result.fromCache,
730
- fetchedAt: result.metadata?.fetchedAt,
731
- expiresAt: result.metadata?.expiresAt,
732
- contentLength: result.metadata?.contentLength || result.content.length,
733
- contentHash: hashContent(result.content)
734
- }
735
- };
736
- console.log(JSON.stringify(output, null, 2));
737
- } else if (options.output) {
738
- await fs.writeFile(options.output, result.content);
739
- console.log(chalk7.green("\u2713"), `Written to ${options.output}`);
740
- console.log(chalk7.dim(` Size: ${result.content.length} bytes`));
741
- if (result.fromCache) {
742
- console.log(chalk7.dim(" Source: cache"));
743
- } else {
744
- console.log(chalk7.dim(" Source: storage"));
745
- }
746
- } else {
747
- if (result.fromCache && !options.bypassCache) {
748
- console.error(chalk7.green("\u2713"), chalk7.dim("from cache\n"));
749
- } else {
750
- console.error(chalk7.green("\u2713"), chalk7.dim("fetched\n"));
751
- }
752
- console.log(result.content.toString("utf-8"));
753
- }
754
- } catch (error) {
755
- console.error(chalk7.red("Error:"), error.message);
756
- if (error.message.includes("Failed to load configuration")) {
757
- console.log(chalk7.dim('\nRun "fractary codex init" to create a configuration.'));
758
- } else if (error.message.includes("GITHUB_TOKEN")) {
759
- console.log(chalk7.dim('\nSet your GitHub token: export GITHUB_TOKEN="your_token"'));
760
- } else if (error.message.includes("not found") || error.message.includes("404")) {
761
- console.log(chalk7.dim("\nThe document may not exist or you may not have access."));
762
- console.log(chalk7.dim("Check the URI and ensure your storage providers are configured correctly."));
763
- }
764
- process.exit(1);
765
- }
766
- });
767
- return cmd;
768
- }
769
-
770
- // src/commands/document/index.ts
771
- function documentCommand() {
772
- const cmd = new Command("document");
773
- cmd.description("Manage document operations");
774
- cmd.addCommand(fetchCommand());
775
- return cmd;
776
- }
777
-
778
684
  // src/commands/config/index.ts
779
685
  init_esm_shims();
780
686
 
@@ -842,8 +748,8 @@ function getDefaultUnifiedConfig(organization, project, codexRepo) {
842
748
  }
843
749
  async function readUnifiedConfig(configPath) {
844
750
  try {
845
- const content = await fs.readFile(configPath, "utf-8");
846
- const config = yaml2.load(content);
751
+ const content = await fs4.readFile(configPath, "utf-8");
752
+ const config = yaml.load(content);
847
753
  return config;
848
754
  } catch (error) {
849
755
  if (error.code === "ENOENT") {
@@ -853,15 +759,15 @@ async function readUnifiedConfig(configPath) {
853
759
  }
854
760
  }
855
761
  async function writeUnifiedConfig(config, outputPath) {
856
- const dir = path5.dirname(outputPath);
857
- await fs.mkdir(dir, { recursive: true });
858
- const yamlContent = yaml2.dump(config, {
762
+ const dir = path3.dirname(outputPath);
763
+ await fs4.mkdir(dir, { recursive: true });
764
+ const yamlContent = yaml.dump(config, {
859
765
  indent: 2,
860
766
  lineWidth: 120,
861
767
  noRefs: true,
862
768
  sortKeys: false
863
769
  });
864
- await fs.writeFile(outputPath, yamlContent, "utf-8");
770
+ await fs4.writeFile(outputPath, yamlContent, "utf-8");
865
771
  }
866
772
  function mergeUnifiedConfigs(existing, updates) {
867
773
  const merged = {};
@@ -919,9 +825,9 @@ codex/cache/
919
825
  # ===== end fractary-codex =====
920
826
  `;
921
827
  async function readFractaryGitignore(projectRoot) {
922
- const gitignorePath = path5.join(projectRoot, ".fractary", ".gitignore");
828
+ const gitignorePath = path3.join(projectRoot, ".fractary", ".gitignore");
923
829
  try {
924
- return await fs.readFile(gitignorePath, "utf-8");
830
+ return await fs4.readFile(gitignorePath, "utf-8");
925
831
  } catch (error) {
926
832
  if (error.code === "ENOENT") {
927
833
  return null;
@@ -930,9 +836,9 @@ async function readFractaryGitignore(projectRoot) {
930
836
  }
931
837
  }
932
838
  async function writeFractaryGitignore(projectRoot, content) {
933
- const gitignorePath = path5.join(projectRoot, ".fractary", ".gitignore");
934
- await fs.mkdir(path5.join(projectRoot, ".fractary"), { recursive: true });
935
- await fs.writeFile(gitignorePath, content, "utf-8");
839
+ const gitignorePath = path3.join(projectRoot, ".fractary", ".gitignore");
840
+ await fs4.mkdir(path3.join(projectRoot, ".fractary"), { recursive: true });
841
+ await fs4.writeFile(gitignorePath, content, "utf-8");
936
842
  }
937
843
  function normalizeCachePath(cachePath) {
938
844
  let normalized = cachePath.replace(/\\/g, "/");
@@ -969,10 +875,10 @@ function addCachePathToGitignore(gitignoreContent, cachePath, comment) {
969
875
  return gitignoreContent.trimEnd() + addition;
970
876
  }
971
877
  async function ensureCachePathIgnored(projectRoot, cachePath) {
972
- const gitignorePath = path5.join(projectRoot, ".fractary", ".gitignore");
878
+ const gitignorePath = path3.join(projectRoot, ".fractary", ".gitignore");
973
879
  let relativeCachePath = cachePath;
974
- if (path5.isAbsolute(cachePath)) {
975
- relativeCachePath = path5.relative(path5.join(projectRoot, ".fractary"), cachePath);
880
+ if (path3.isAbsolute(cachePath)) {
881
+ relativeCachePath = path3.relative(path3.join(projectRoot, ".fractary"), cachePath);
976
882
  }
977
883
  relativeCachePath = normalizeCachePath(relativeCachePath);
978
884
  let content = await readFractaryGitignore(projectRoot);
@@ -1090,27 +996,27 @@ async function discoverCodexRepo(org) {
1090
996
  }
1091
997
  async function fileExists(filePath) {
1092
998
  try {
1093
- await fs.access(filePath);
999
+ await fs4.access(filePath);
1094
1000
  return true;
1095
1001
  } catch {
1096
1002
  return false;
1097
1003
  }
1098
1004
  }
1099
1005
  async function installMcpServer(projectRoot, configPath = ".fractary/config.yaml", options = {}) {
1100
- const mcpJsonPath = path5.join(projectRoot, ".mcp.json");
1006
+ const mcpJsonPath = path3.join(projectRoot, ".mcp.json");
1101
1007
  const { backup = true } = options;
1102
1008
  let existingConfig = { mcpServers: {} };
1103
1009
  let backupPath;
1104
1010
  let migrated = false;
1105
1011
  if (await fileExists(mcpJsonPath)) {
1106
1012
  try {
1107
- const content = await fs.readFile(mcpJsonPath, "utf-8");
1013
+ const content = await fs4.readFile(mcpJsonPath, "utf-8");
1108
1014
  existingConfig = JSON.parse(content);
1109
1015
  if (backup) {
1110
1016
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").slice(0, 18);
1111
1017
  const suffix = Math.random().toString(36).substring(2, 6);
1112
1018
  backupPath = `${mcpJsonPath}.backup.${timestamp}-${suffix}`;
1113
- await fs.writeFile(backupPath, content);
1019
+ await fs4.writeFile(backupPath, content);
1114
1020
  }
1115
1021
  } catch {
1116
1022
  console.log(chalk7.yellow("\u26A0 Warning: .mcp.json contains invalid JSON, starting fresh"));
@@ -1140,7 +1046,7 @@ async function installMcpServer(projectRoot, configPath = ".fractary/config.yaml
1140
1046
  command: "npx",
1141
1047
  args: ["-y", "@fractary/codex-mcp", "--config", configPath]
1142
1048
  };
1143
- await fs.writeFile(
1049
+ await fs4.writeFile(
1144
1050
  mcpJsonPath,
1145
1051
  JSON.stringify(existingConfig, null, 2) + "\n"
1146
1052
  );
@@ -1151,8 +1057,8 @@ async function installMcpServer(projectRoot, configPath = ".fractary/config.yaml
1151
1057
  backupPath
1152
1058
  };
1153
1059
  }
1154
- function initCommand() {
1155
- const cmd = new Command("init");
1060
+ function configureCommand() {
1061
+ const cmd = new Command("configure");
1156
1062
  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").option("--no-mcp", "Skip MCP server installation").action(async (options) => {
1157
1063
  try {
1158
1064
  console.log(chalk7.blue("Initializing unified Fractary configuration...\n"));
@@ -1164,13 +1070,13 @@ function initCommand() {
1164
1070
  try {
1165
1071
  const { resolveOrganization } = await import('@fractary/codex');
1166
1072
  org = resolveOrganization({
1167
- repoName: path5.basename(process.cwd())
1073
+ repoName: path3.basename(process.cwd())
1168
1074
  });
1169
1075
  } catch {
1170
1076
  }
1171
1077
  }
1172
1078
  if (!org) {
1173
- org = path5.basename(process.cwd()).split("-")[0] || "default";
1079
+ org = path3.basename(process.cwd()).split("-")[0] || "default";
1174
1080
  console.log(chalk7.yellow(`\u26A0 Could not detect organization, using: ${org}`));
1175
1081
  console.log(chalk7.dim(" Use --org <slug> to specify explicitly\n"));
1176
1082
  } else {
@@ -1185,7 +1091,7 @@ function initCommand() {
1185
1091
  }
1186
1092
  let project = options.project;
1187
1093
  if (!project) {
1188
- project = path5.basename(process.cwd());
1094
+ project = path3.basename(process.cwd());
1189
1095
  console.log(chalk7.dim(`Project: ${chalk7.cyan(project)}
1190
1096
  `));
1191
1097
  }
@@ -1226,7 +1132,7 @@ function initCommand() {
1226
1132
  console.log(chalk7.dim(` Using default: ${chalk7.cyan(codexRepo)}
1227
1133
  `));
1228
1134
  }
1229
- const configPath = path5.join(process.cwd(), ".fractary", "config.yaml");
1135
+ const configPath = path3.join(process.cwd(), ".fractary", "config.yaml");
1230
1136
  const configExists = await fileExists(configPath);
1231
1137
  if (configExists && !options.force) {
1232
1138
  console.log(chalk7.yellow(`\u26A0 Configuration already exists at .fractary/config.yaml`));
@@ -1241,7 +1147,7 @@ function initCommand() {
1241
1147
  ".fractary/codex/cache"
1242
1148
  ];
1243
1149
  for (const dir of dirs) {
1244
- await fs.mkdir(path5.join(process.cwd(), dir), { recursive: true });
1150
+ await fs4.mkdir(path3.join(process.cwd(), dir), { recursive: true });
1245
1151
  console.log(chalk7.green("\u2713"), chalk7.dim(dir + "/"));
1246
1152
  }
1247
1153
  const gitignoreResult = await ensureCachePathIgnored(process.cwd(), ".fractary/codex/cache");
@@ -1273,7 +1179,7 @@ function initCommand() {
1273
1179
  } else if (mcpResult.migrated) {
1274
1180
  console.log(chalk7.green("\u2713"), chalk7.dim(".mcp.json (migrated from old format)"));
1275
1181
  if (mcpResult.backupPath) {
1276
- console.log(chalk7.dim(` Backup: ${path5.basename(mcpResult.backupPath)}`));
1182
+ console.log(chalk7.dim(` Backup: ${path3.basename(mcpResult.backupPath)}`));
1277
1183
  }
1278
1184
  } else if (mcpResult.installed) {
1279
1185
  console.log(chalk7.green("\u2713"), chalk7.dim(".mcp.json (created)"));
@@ -1311,11 +1217,89 @@ function initCommand() {
1311
1217
  return cmd;
1312
1218
  }
1313
1219
 
1314
- // src/commands/config/index.ts
1315
- function configCommand() {
1316
- const cmd = new Command("config");
1317
- cmd.description("Manage configuration");
1318
- cmd.addCommand(initCommand());
1220
+ // src/commands/document/index.ts
1221
+ init_esm_shims();
1222
+
1223
+ // src/commands/document/fetch.ts
1224
+ init_esm_shims();
1225
+
1226
+ // src/client/get-client.ts
1227
+ init_esm_shims();
1228
+ var clientInstance = null;
1229
+ async function getClient(options) {
1230
+ if (!clientInstance) {
1231
+ const { CodexClient: CodexClient2 } = await Promise.resolve().then(() => (init_codex_client(), codex_client_exports));
1232
+ clientInstance = await CodexClient2.create(options);
1233
+ }
1234
+ return clientInstance;
1235
+ }
1236
+
1237
+ // src/commands/document/fetch.ts
1238
+ function hashContent(content) {
1239
+ return crypto.createHash("sha256").update(content).digest("hex").slice(0, 16);
1240
+ }
1241
+ function documentFetchCommand() {
1242
+ const cmd = new Command("document-fetch");
1243
+ cmd.description("Fetch a document by codex:// URI reference").argument("<uri>", "Codex URI (e.g., codex://org/project/docs/file.md)").option("--bypass-cache", "Skip cache and fetch directly from source").option("--ttl <seconds>", "Override default TTL (in seconds)", parseInt).option("--json", "Output as JSON with metadata").option("--output <file>", "Write content to file instead of stdout").action(async (uri, options) => {
1244
+ try {
1245
+ const { validateUri } = await import('@fractary/codex');
1246
+ if (!validateUri(uri)) {
1247
+ console.error(chalk7.red("Error: Invalid URI format"));
1248
+ console.log(chalk7.dim("Expected: codex://org/project/path/to/file.md"));
1249
+ console.log(chalk7.dim("Example: codex://fractary/codex/docs/api.md"));
1250
+ process.exit(1);
1251
+ }
1252
+ const client = await getClient();
1253
+ if (!options.json && !options.bypassCache) {
1254
+ console.error(chalk7.dim(`Fetching ${uri}...`));
1255
+ }
1256
+ const result = await client.fetch(uri, {
1257
+ bypassCache: options.bypassCache,
1258
+ ttl: options.ttl
1259
+ });
1260
+ if (options.json) {
1261
+ const output = {
1262
+ uri,
1263
+ content: result.content.toString("utf-8"),
1264
+ metadata: {
1265
+ fromCache: result.fromCache,
1266
+ fetchedAt: result.metadata?.fetchedAt,
1267
+ expiresAt: result.metadata?.expiresAt,
1268
+ contentLength: result.metadata?.contentLength || result.content.length,
1269
+ contentHash: hashContent(result.content)
1270
+ }
1271
+ };
1272
+ console.log(JSON.stringify(output, null, 2));
1273
+ } else if (options.output) {
1274
+ await fs4.writeFile(options.output, result.content);
1275
+ console.log(chalk7.green("\u2713"), `Written to ${options.output}`);
1276
+ console.log(chalk7.dim(` Size: ${result.content.length} bytes`));
1277
+ if (result.fromCache) {
1278
+ console.log(chalk7.dim(" Source: cache"));
1279
+ } else {
1280
+ console.log(chalk7.dim(" Source: storage"));
1281
+ }
1282
+ } else {
1283
+ if (result.fromCache && !options.bypassCache) {
1284
+ console.error(chalk7.green("\u2713"), chalk7.dim("from cache\n"));
1285
+ } else {
1286
+ console.error(chalk7.green("\u2713"), chalk7.dim("fetched\n"));
1287
+ }
1288
+ console.log(result.content.toString("utf-8"));
1289
+ }
1290
+ } catch (error) {
1291
+ console.error(chalk7.red("Error:"), error.message);
1292
+ if (error.message.includes("Failed to load configuration")) {
1293
+ console.log(chalk7.dim('\nRun "fractary-codex configure" to create a configuration.'));
1294
+ } else if (error.message.includes("GITHUB_TOKEN")) {
1295
+ console.log(chalk7.dim('\nSet your GitHub token: export GITHUB_TOKEN="your_token"'));
1296
+ } else if (error.message.includes("not found") || error.message.includes("404")) {
1297
+ console.log(chalk7.dim("\nThe document may not exist or you may not have access."));
1298
+ console.log(chalk7.dim("Check the URI and ensure your storage providers are configured correctly."));
1299
+ }
1300
+ process.exit(1);
1301
+ }
1302
+ });
1319
1303
  return cmd;
1320
1304
  }
1321
1305
 
@@ -1330,7 +1314,7 @@ function formatSize(bytes) {
1330
1314
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1331
1315
  }
1332
1316
  function cacheListCommand() {
1333
- const cmd = new Command("list");
1317
+ const cmd = new Command("cache-list");
1334
1318
  cmd.description("List cache information").option("--json", "Output as JSON").action(async (options) => {
1335
1319
  try {
1336
1320
  const client = await getClient();
@@ -1369,8 +1353,8 @@ function cacheListCommand() {
1369
1353
  console.log(`Cache health: ${healthColor(`${healthPercent.toFixed(0)}% fresh`)}`);
1370
1354
  console.log("");
1371
1355
  console.log(chalk7.dim("Note: Individual cache entries are managed by the SDK."));
1372
- console.log(chalk7.dim('Use "fractary codex cache stats" for detailed statistics.'));
1373
- console.log(chalk7.dim('Use "fractary codex cache clear" to clear cache entries.'));
1356
+ console.log(chalk7.dim('Use "fractary-codex cache-stats" for detailed statistics.'));
1357
+ console.log(chalk7.dim('Use "fractary-codex cache-clear" to clear cache entries.'));
1374
1358
  } catch (error) {
1375
1359
  console.error(chalk7.red("Error:"), error.message);
1376
1360
  process.exit(1);
@@ -1382,7 +1366,7 @@ function cacheListCommand() {
1382
1366
  // src/commands/cache/clear.ts
1383
1367
  init_esm_shims();
1384
1368
  function cacheClearCommand() {
1385
- const cmd = new Command("clear");
1369
+ const cmd = new Command("cache-clear");
1386
1370
  cmd.description("Clear cache entries").option("--all", "Clear entire cache").option("--pattern <glob>", 'Clear entries matching URI pattern (e.g., "codex://fractary/*")').option("--dry-run", "Show what would be cleared without actually clearing").action(async (options) => {
1387
1371
  try {
1388
1372
  const client = await getClient();
@@ -1402,8 +1386,8 @@ function cacheClearCommand() {
1402
1386
  console.log(chalk7.dim(' --pattern Clear entries matching pattern (e.g., "codex://fractary/*")'));
1403
1387
  console.log("");
1404
1388
  console.log(chalk7.dim("Examples:"));
1405
- console.log(chalk7.dim(" fractary codex cache clear --all"));
1406
- console.log(chalk7.dim(' fractary codex cache clear --pattern "codex://fractary/cli/*"'));
1389
+ console.log(chalk7.dim(" fractary-codex cache-clear --all"));
1390
+ console.log(chalk7.dim(' fractary-codex cache-clear --pattern "codex://fractary/cli/*"'));
1407
1391
  return;
1408
1392
  }
1409
1393
  if (options.dryRun) {
@@ -1455,7 +1439,7 @@ function formatSize3(bytes) {
1455
1439
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1456
1440
  }
1457
1441
  function cacheStatsCommand() {
1458
- const cmd = new Command("stats");
1442
+ const cmd = new Command("cache-stats");
1459
1443
  cmd.description("Display cache statistics").option("--json", "Output as JSON").action(async (options) => {
1460
1444
  try {
1461
1445
  const client = await getClient();
@@ -1476,7 +1460,7 @@ function cacheStatsCommand() {
1476
1460
  const healthColor = healthPercent > 80 ? chalk7.green : healthPercent > 50 ? chalk7.yellow : chalk7.red;
1477
1461
  console.log(`Cache health: ${healthColor(`${healthPercent.toFixed(0)}% fresh`)}`);
1478
1462
  if (stats.expiredCount > 0) {
1479
- console.log(chalk7.dim('\nRun "fractary codex cache clear --pattern <pattern>" to clean up entries.'));
1463
+ console.log(chalk7.dim('\nRun "fractary-codex cache-clear --pattern <pattern>" to clean up entries.'));
1480
1464
  }
1481
1465
  if (stats.entryCount === 0) {
1482
1466
  console.log(chalk7.dim("\nNo cached entries. Fetch some documents to populate the cache."));
@@ -1494,15 +1478,15 @@ init_esm_shims();
1494
1478
  init_migrate_config();
1495
1479
  async function fileExists2(filePath) {
1496
1480
  try {
1497
- await fs.access(filePath);
1481
+ await fs4.access(filePath);
1498
1482
  return true;
1499
1483
  } catch {
1500
1484
  return false;
1501
1485
  }
1502
1486
  }
1503
1487
  async function checkConfiguration() {
1504
- const configPath = path5.join(process.cwd(), ".fractary", "config.yaml");
1505
- const legacyConfigPath = path5.join(process.cwd(), ".fractary", "plugins", "codex", "config.json");
1488
+ const configPath = path3.join(process.cwd(), ".fractary", "config.yaml");
1489
+ const legacyConfigPath = path3.join(process.cwd(), ".fractary", "plugins", "codex", "config.json");
1506
1490
  try {
1507
1491
  if (!await fileExists2(configPath)) {
1508
1492
  if (await fileExists2(legacyConfigPath)) {
@@ -1510,14 +1494,14 @@ async function checkConfiguration() {
1510
1494
  name: "Configuration",
1511
1495
  status: "warn",
1512
1496
  message: "Legacy JSON configuration detected",
1513
- details: 'Run "fractary codex migrate" to upgrade to YAML format'
1497
+ details: "Migration from legacy JSON format may be required"
1514
1498
  };
1515
1499
  }
1516
1500
  return {
1517
1501
  name: "Configuration",
1518
1502
  status: "fail",
1519
1503
  message: "No configuration found",
1520
- details: 'Run "fractary codex init" to create configuration'
1504
+ details: 'Run "fractary-codex configure" to create configuration'
1521
1505
  };
1522
1506
  }
1523
1507
  const config = await readCodexConfig(configPath);
@@ -1609,7 +1593,7 @@ async function checkCache() {
1609
1593
  }
1610
1594
  }
1611
1595
  async function checkStorage() {
1612
- const configPath = path5.join(process.cwd(), ".fractary", "config.yaml");
1596
+ const configPath = path3.join(process.cwd(), ".fractary", "config.yaml");
1613
1597
  try {
1614
1598
  const config = await readCodexConfig(configPath);
1615
1599
  const providers = config.storage || [];
@@ -1673,8 +1657,8 @@ function formatSize4(bytes) {
1673
1657
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
1674
1658
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1675
1659
  }
1676
- function healthCommand() {
1677
- const cmd = new Command("health");
1660
+ function cacheHealthCommand() {
1661
+ const cmd = new Command("cache-health");
1678
1662
  cmd.description("Run diagnostics on codex setup").option("--json", "Output as JSON").action(async (options) => {
1679
1663
  try {
1680
1664
  const checks = [];
@@ -1717,8 +1701,7 @@ function healthCommand() {
1717
1701
  if (failed > 0 || warned > 0) {
1718
1702
  console.log("");
1719
1703
  console.log(chalk7.dim("Run checks individually for more details:"));
1720
- console.log(chalk7.dim(" fractary codex cache stats"));
1721
- console.log(chalk7.dim(" fractary codex types list"));
1704
+ console.log(chalk7.dim(" fractary-codex cache-stats"));
1722
1705
  }
1723
1706
  if (failed > 0) {
1724
1707
  process.exit(1);
@@ -1731,17 +1714,6 @@ function healthCommand() {
1731
1714
  return cmd;
1732
1715
  }
1733
1716
 
1734
- // src/commands/cache/index.ts
1735
- function cacheCommand() {
1736
- const cmd = new Command("cache");
1737
- cmd.description("Manage the codex document cache");
1738
- cmd.addCommand(cacheListCommand());
1739
- cmd.addCommand(cacheClearCommand());
1740
- cmd.addCommand(cacheStatsCommand());
1741
- cmd.addCommand(healthCommand());
1742
- return cmd;
1743
- }
1744
-
1745
1717
  // src/commands/sync.ts
1746
1718
  init_esm_shims();
1747
1719
  init_migrate_config();
@@ -1765,15 +1737,15 @@ function formatDuration(ms) {
1765
1737
  }
1766
1738
  function syncCommand() {
1767
1739
  const cmd = new Command("sync");
1768
- 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) => {
1740
+ 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").option("--work-id <id>", "GitHub issue number or URL to scope sync to").action(async (name, options) => {
1769
1741
  try {
1770
- const configPath = path5.join(process.cwd(), ".fractary", "config.yaml");
1742
+ const configPath = path3.join(process.cwd(), ".fractary", "config.yaml");
1771
1743
  let config;
1772
1744
  try {
1773
1745
  config = await readCodexConfig(configPath);
1774
1746
  } catch (error) {
1775
1747
  console.error(chalk7.red("Error:"), "Codex not initialized.");
1776
- console.log(chalk7.dim('Run "fractary codex init" first.'));
1748
+ console.log(chalk7.dim('Run "fractary-codex configure" first.'));
1777
1749
  process.exit(1);
1778
1750
  }
1779
1751
  const { createSyncManager, createLocalStorage, detectCurrentProject } = await import('@fractary/codex');
@@ -1804,7 +1776,7 @@ function syncCommand() {
1804
1776
  const syncManager = createSyncManager({
1805
1777
  localStorage,
1806
1778
  config: config.sync,
1807
- manifestPath: path5.join(process.cwd(), ".fractary", ".codex-sync-manifest.json")
1779
+ manifestPath: path3.join(process.cwd(), ".fractary", ".codex-sync-manifest.json")
1808
1780
  });
1809
1781
  const defaultToCodexPatterns = [
1810
1782
  "docs/**/*.md",
@@ -1839,7 +1811,7 @@ function syncCommand() {
1839
1811
  }
1840
1812
  const targetFiles = await Promise.all(
1841
1813
  Array.from(matchedFilePaths).map(async (filePath) => {
1842
- const fullPath = path5.join(sourceDir, filePath);
1814
+ const fullPath = path3.join(sourceDir, filePath);
1843
1815
  const stats = await import('fs/promises').then((fs8) => fs8.stat(fullPath));
1844
1816
  return {
1845
1817
  path: filePath,
@@ -1942,15 +1914,18 @@ function syncCommand() {
1942
1914
  syncOptions
1943
1915
  );
1944
1916
  plan.source = sourceDir;
1945
- plan.target = path5.join(codexRepoPath, "projects", projectName);
1917
+ plan.target = path3.join(codexRepoPath, "projects", projectName);
1946
1918
  }
1947
1919
  if (plan.totalFiles === 0) {
1948
1920
  if (options.json) {
1949
1921
  console.log(JSON.stringify({
1950
1922
  project: projectName,
1951
1923
  organization: config.organization,
1924
+ workId: options.workId || null,
1952
1925
  files: [],
1953
- synced: 0
1926
+ synced: 0,
1927
+ status: "success",
1928
+ message: "No files to sync"
1954
1929
  }, null, 2));
1955
1930
  } else {
1956
1931
  console.log(chalk7.yellow("No files to sync."));
@@ -1965,6 +1940,7 @@ function syncCommand() {
1965
1940
  branch: targetBranch,
1966
1941
  direction,
1967
1942
  dryRun: options.dryRun || false,
1943
+ workId: options.workId || null,
1968
1944
  plan: {
1969
1945
  totalFiles: plan.totalFiles,
1970
1946
  totalBytes: plan.totalBytes,
@@ -1979,12 +1955,24 @@ function syncCommand() {
1979
1955
  }))
1980
1956
  };
1981
1957
  if (options.dryRun) {
1982
- console.log(JSON.stringify(output, null, 2));
1958
+ console.log(JSON.stringify({
1959
+ ...output,
1960
+ status: "success"
1961
+ }, null, 2));
1983
1962
  return;
1984
1963
  }
1985
1964
  const result2 = await syncManager.executePlan(plan, syncOptions);
1965
+ let status;
1966
+ if (!result2.success && result2.synced === 0) {
1967
+ status = "failure";
1968
+ } else if (!result2.success || result2.failed > 0 || plan.conflicts.length > 0) {
1969
+ status = "warning";
1970
+ } else {
1971
+ status = "success";
1972
+ }
1986
1973
  console.log(JSON.stringify({
1987
1974
  ...output,
1975
+ status,
1988
1976
  result: {
1989
1977
  success: result2.success,
1990
1978
  synced: result2.synced,
@@ -2118,349 +2106,6 @@ Total: ${plan.totalFiles} files (${formatBytes(plan.totalBytes)})`));
2118
2106
  });
2119
2107
  return cmd;
2120
2108
  }
2121
-
2122
- // src/commands/types/index.ts
2123
- init_esm_shims();
2124
-
2125
- // src/commands/types/list.ts
2126
- init_esm_shims();
2127
- function formatTtl(seconds) {
2128
- if (seconds < 60) return `${seconds}s`;
2129
- if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
2130
- if (seconds < 86400) return `${Math.floor(seconds / 3600)}h`;
2131
- return `${Math.floor(seconds / 86400)}d`;
2132
- }
2133
- function typesListCommand() {
2134
- const cmd = new Command("list");
2135
- cmd.description("List all artifact types").option("--json", "Output as JSON").option("--custom-only", "Show only custom types").option("--builtin-only", "Show only built-in types").action(async (options) => {
2136
- try {
2137
- const client = await getClient();
2138
- const registry = client.getTypeRegistry();
2139
- const allTypes = registry.list();
2140
- let types = allTypes;
2141
- if (options.customOnly) {
2142
- types = allTypes.filter((t) => !registry.isBuiltIn(t.name));
2143
- } else if (options.builtinOnly) {
2144
- types = allTypes.filter((t) => registry.isBuiltIn(t.name));
2145
- }
2146
- if (options.json) {
2147
- const builtinCount = types.filter((t) => registry.isBuiltIn(t.name)).length;
2148
- const customCount = types.length - builtinCount;
2149
- console.log(JSON.stringify({
2150
- count: types.length,
2151
- builtinCount,
2152
- customCount,
2153
- types: types.map((t) => ({
2154
- name: t.name,
2155
- description: t.description,
2156
- patterns: t.patterns,
2157
- defaultTtl: t.defaultTtl,
2158
- ttl: formatTtl(t.defaultTtl),
2159
- builtin: registry.isBuiltIn(t.name),
2160
- archiveAfterDays: t.archiveAfterDays,
2161
- archiveStorage: t.archiveStorage
2162
- }))
2163
- }, null, 2));
2164
- return;
2165
- }
2166
- if (types.length === 0) {
2167
- console.log(chalk7.yellow("No types found."));
2168
- return;
2169
- }
2170
- console.log(chalk7.bold("Artifact Types\n"));
2171
- const builtinTypes = types.filter((t) => registry.isBuiltIn(t.name));
2172
- const customTypes = types.filter((t) => !registry.isBuiltIn(t.name));
2173
- if (builtinTypes.length > 0 && !options.customOnly) {
2174
- console.log(chalk7.bold("Built-in Types"));
2175
- console.log(chalk7.dim("\u2500".repeat(70)));
2176
- for (const type of builtinTypes) {
2177
- const patternStr = type.patterns[0] || "";
2178
- console.log(` ${chalk7.cyan(type.name.padEnd(12))} ${patternStr.padEnd(30)} ${chalk7.dim(`TTL: ${formatTtl(type.defaultTtl)}`)}`);
2179
- console.log(` ${chalk7.dim(" ".repeat(12) + type.description)}`);
2180
- }
2181
- console.log("");
2182
- }
2183
- if (customTypes.length > 0 && !options.builtinOnly) {
2184
- console.log(chalk7.bold("Custom Types"));
2185
- console.log(chalk7.dim("\u2500".repeat(70)));
2186
- for (const type of customTypes) {
2187
- const patternStr = type.patterns[0] || "";
2188
- console.log(` ${chalk7.green(type.name.padEnd(12))} ${patternStr.padEnd(30)} ${chalk7.dim(`TTL: ${formatTtl(type.defaultTtl)}`)}`);
2189
- console.log(` ${chalk7.dim(" ".repeat(12) + type.description)}`);
2190
- }
2191
- console.log("");
2192
- }
2193
- console.log(chalk7.dim(`Total: ${types.length} types (${builtinTypes.length} built-in, ${customTypes.length} custom)`));
2194
- } catch (error) {
2195
- console.error(chalk7.red("Error:"), error.message);
2196
- process.exit(1);
2197
- }
2198
- });
2199
- return cmd;
2200
- }
2201
-
2202
- // src/commands/types/show.ts
2203
- init_esm_shims();
2204
- function formatTtl2(seconds) {
2205
- if (seconds < 60) return `${seconds}s`;
2206
- if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
2207
- if (seconds < 86400) return `${Math.floor(seconds / 3600)}h`;
2208
- return `${Math.floor(seconds / 86400)}d`;
2209
- }
2210
- function typesShowCommand() {
2211
- const cmd = new Command("show");
2212
- cmd.description("Show details for a specific type").argument("<name>", "Type name").option("--json", "Output as JSON").action(async (name, options) => {
2213
- try {
2214
- const client = await getClient();
2215
- const registry = client.getTypeRegistry();
2216
- const type = registry.get(name);
2217
- if (!type) {
2218
- console.error(chalk7.red("Error:"), `Type "${name}" not found.`);
2219
- console.log(chalk7.dim('Run "fractary codex types list" to see available types.'));
2220
- process.exit(1);
2221
- }
2222
- const isBuiltin = registry.isBuiltIn(name);
2223
- if (options.json) {
2224
- console.log(JSON.stringify({
2225
- name: type.name,
2226
- builtin: isBuiltin,
2227
- description: type.description,
2228
- patterns: type.patterns,
2229
- defaultTtl: type.defaultTtl,
2230
- ttl: formatTtl2(type.defaultTtl),
2231
- archiveAfterDays: type.archiveAfterDays,
2232
- archiveStorage: type.archiveStorage,
2233
- syncPatterns: type.syncPatterns,
2234
- excludePatterns: type.excludePatterns
2235
- }, null, 2));
2236
- return;
2237
- }
2238
- const nameColor = isBuiltin ? chalk7.cyan : chalk7.green;
2239
- console.log(chalk7.bold(`Type: ${nameColor(name)}
2240
- `));
2241
- console.log(` ${chalk7.dim("Source:")} ${isBuiltin ? "Built-in" : "Custom"}`);
2242
- console.log(` ${chalk7.dim("Description:")} ${type.description}`);
2243
- console.log(` ${chalk7.dim("TTL:")} ${formatTtl2(type.defaultTtl)} (${type.defaultTtl} seconds)`);
2244
- console.log("");
2245
- console.log(chalk7.bold("Patterns"));
2246
- for (const pattern of type.patterns) {
2247
- console.log(` ${chalk7.dim("\u2022")} ${pattern}`);
2248
- }
2249
- if (type.archiveAfterDays !== null) {
2250
- console.log("");
2251
- console.log(chalk7.bold("Archive Settings"));
2252
- console.log(` ${chalk7.dim("After:")} ${type.archiveAfterDays} days`);
2253
- console.log(` ${chalk7.dim("Storage:")} ${type.archiveStorage || "not set"}`);
2254
- }
2255
- if (type.syncPatterns && type.syncPatterns.length > 0) {
2256
- console.log("");
2257
- console.log(chalk7.bold("Sync Patterns"));
2258
- for (const pattern of type.syncPatterns) {
2259
- console.log(` ${chalk7.dim("\u2022")} ${pattern}`);
2260
- }
2261
- }
2262
- if (type.excludePatterns && type.excludePatterns.length > 0) {
2263
- console.log("");
2264
- console.log(chalk7.bold("Exclude Patterns"));
2265
- for (const pattern of type.excludePatterns) {
2266
- console.log(` ${chalk7.dim("\u2022")} ${pattern}`);
2267
- }
2268
- }
2269
- } catch (error) {
2270
- console.error(chalk7.red("Error:"), error.message);
2271
- process.exit(1);
2272
- }
2273
- });
2274
- return cmd;
2275
- }
2276
-
2277
- // src/commands/types/add.ts
2278
- init_esm_shims();
2279
- init_migrate_config();
2280
- function isValidTypeName(name) {
2281
- return /^[a-z][a-z0-9-]*$/.test(name);
2282
- }
2283
- function parseTtl(ttl) {
2284
- const match = ttl.match(/^(\d+)([smhd])$/);
2285
- if (!match) {
2286
- throw new Error("Invalid TTL format");
2287
- }
2288
- const value = parseInt(match[1], 10);
2289
- const unit = match[2];
2290
- switch (unit) {
2291
- case "s":
2292
- return value;
2293
- case "m":
2294
- return value * 60;
2295
- case "h":
2296
- return value * 3600;
2297
- case "d":
2298
- return value * 86400;
2299
- default:
2300
- throw new Error("Unknown TTL unit");
2301
- }
2302
- }
2303
- function formatTtl3(seconds) {
2304
- if (seconds < 60) return `${seconds}s`;
2305
- if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
2306
- if (seconds < 86400) return `${Math.floor(seconds / 3600)}h`;
2307
- return `${Math.floor(seconds / 86400)}d`;
2308
- }
2309
- function typesAddCommand() {
2310
- const cmd = new Command("add");
2311
- cmd.description("Add a custom artifact type").argument("<name>", "Type name (lowercase, alphanumeric with hyphens)").requiredOption("--pattern <glob>", "File pattern (glob syntax)").option("--ttl <duration>", 'Cache TTL (e.g., "24h", "7d")', "24h").option("--description <text>", "Type description").option("--json", "Output as JSON").action(async (name, options) => {
2312
- try {
2313
- if (!isValidTypeName(name)) {
2314
- console.error(chalk7.red("Error:"), "Invalid type name.");
2315
- console.log(chalk7.dim("Type name must be lowercase, start with a letter, and contain only letters, numbers, and hyphens."));
2316
- process.exit(1);
2317
- }
2318
- const client = await getClient();
2319
- const registry = client.getTypeRegistry();
2320
- if (registry.isBuiltIn(name)) {
2321
- console.error(chalk7.red("Error:"), `Cannot override built-in type "${name}".`);
2322
- const builtinNames = registry.list().filter((t) => registry.isBuiltIn(t.name)).map((t) => t.name);
2323
- console.log(chalk7.dim("Built-in types: " + builtinNames.join(", ")));
2324
- process.exit(1);
2325
- }
2326
- if (registry.has(name)) {
2327
- console.error(chalk7.red("Error:"), `Custom type "${name}" already exists.`);
2328
- console.log(chalk7.dim('Use "fractary codex types remove" first to remove it.'));
2329
- process.exit(1);
2330
- }
2331
- let ttlSeconds;
2332
- try {
2333
- ttlSeconds = parseTtl(options.ttl);
2334
- } catch {
2335
- console.error(chalk7.red("Error:"), "Invalid TTL format.");
2336
- console.log(chalk7.dim("Expected format: <number><unit> where unit is s (seconds), m (minutes), h (hours), or d (days)"));
2337
- console.log(chalk7.dim("Examples: 30m, 24h, 7d"));
2338
- process.exit(1);
2339
- }
2340
- const configPath = path5.join(process.cwd(), ".fractary", "config.yaml");
2341
- const config = await readCodexConfig(configPath);
2342
- if (!config.types) {
2343
- config.types = { custom: {} };
2344
- }
2345
- if (!config.types.custom) {
2346
- config.types.custom = {};
2347
- }
2348
- config.types.custom[name] = {
2349
- description: options.description || `Custom type: ${name}`,
2350
- patterns: [options.pattern],
2351
- defaultTtl: ttlSeconds
2352
- };
2353
- await writeYamlConfig(config, configPath);
2354
- if (options.json) {
2355
- console.log(JSON.stringify({
2356
- success: true,
2357
- type: {
2358
- name,
2359
- description: config.types.custom[name].description,
2360
- patterns: config.types.custom[name].patterns,
2361
- defaultTtl: ttlSeconds,
2362
- ttl: formatTtl3(ttlSeconds),
2363
- builtin: false
2364
- },
2365
- message: "Custom type added successfully. Changes will take effect on next CLI invocation."
2366
- }, null, 2));
2367
- return;
2368
- }
2369
- console.log(chalk7.green("\u2713"), `Added custom type "${chalk7.cyan(name)}"`);
2370
- console.log("");
2371
- console.log(` ${chalk7.dim("Pattern:")} ${options.pattern}`);
2372
- console.log(` ${chalk7.dim("TTL:")} ${formatTtl3(ttlSeconds)} (${ttlSeconds} seconds)`);
2373
- if (options.description) {
2374
- console.log(` ${chalk7.dim("Description:")} ${options.description}`);
2375
- }
2376
- console.log("");
2377
- console.log(chalk7.dim("Note: Custom type will be available on next CLI invocation."));
2378
- } catch (error) {
2379
- console.error(chalk7.red("Error:"), error.message);
2380
- if (error.message.includes("Failed to load configuration")) {
2381
- console.log(chalk7.dim('\nRun "fractary codex init" to create a configuration.'));
2382
- }
2383
- process.exit(1);
2384
- }
2385
- });
2386
- return cmd;
2387
- }
2388
-
2389
- // src/commands/types/remove.ts
2390
- init_esm_shims();
2391
- init_migrate_config();
2392
- function typesRemoveCommand() {
2393
- const cmd = new Command("remove");
2394
- cmd.description("Remove a custom artifact type").argument("<name>", "Type name to remove").option("--json", "Output as JSON").option("--force", "Skip confirmation").action(async (name, options) => {
2395
- try {
2396
- const client = await getClient();
2397
- const registry = client.getTypeRegistry();
2398
- if (registry.isBuiltIn(name)) {
2399
- console.error(chalk7.red("Error:"), `Cannot remove built-in type "${name}".`);
2400
- console.log(chalk7.dim("Built-in types are permanent and cannot be removed."));
2401
- process.exit(1);
2402
- }
2403
- if (!registry.has(name)) {
2404
- console.error(chalk7.red("Error:"), `Custom type "${name}" not found.`);
2405
- console.log(chalk7.dim('Run "fractary codex types list --custom-only" to see custom types.'));
2406
- process.exit(1);
2407
- }
2408
- const typeInfo = registry.get(name);
2409
- const configPath = path5.join(process.cwd(), ".fractary", "config.yaml");
2410
- const config = await readCodexConfig(configPath);
2411
- if (!config.types?.custom?.[name]) {
2412
- console.error(chalk7.red("Error:"), `Custom type "${name}" not found in configuration.`);
2413
- process.exit(1);
2414
- }
2415
- delete config.types.custom[name];
2416
- if (Object.keys(config.types.custom).length === 0) {
2417
- delete config.types.custom;
2418
- }
2419
- if (config.types && Object.keys(config.types).length === 0) {
2420
- delete config.types;
2421
- }
2422
- await writeYamlConfig(config, configPath);
2423
- if (options.json) {
2424
- console.log(JSON.stringify({
2425
- success: true,
2426
- removed: {
2427
- name: typeInfo.name,
2428
- description: typeInfo.description,
2429
- patterns: typeInfo.patterns,
2430
- defaultTtl: typeInfo.defaultTtl
2431
- },
2432
- message: "Custom type removed successfully. Changes will take effect on next CLI invocation."
2433
- }, null, 2));
2434
- return;
2435
- }
2436
- console.log(chalk7.green("\u2713"), `Removed custom type "${chalk7.cyan(name)}"`);
2437
- console.log("");
2438
- console.log(chalk7.dim("Removed configuration:"));
2439
- console.log(` ${chalk7.dim("Pattern:")} ${typeInfo.patterns.join(", ")}`);
2440
- console.log(` ${chalk7.dim("Description:")} ${typeInfo.description}`);
2441
- console.log("");
2442
- console.log(chalk7.dim("Note: Custom type will be removed on next CLI invocation."));
2443
- } catch (error) {
2444
- console.error(chalk7.red("Error:"), error.message);
2445
- if (error.message.includes("Failed to load configuration")) {
2446
- console.log(chalk7.dim('\nRun "fractary codex init" to create a configuration.'));
2447
- }
2448
- process.exit(1);
2449
- }
2450
- });
2451
- return cmd;
2452
- }
2453
-
2454
- // src/commands/types/index.ts
2455
- function typesCommand() {
2456
- const cmd = new Command("types");
2457
- cmd.description("Manage artifact type registry");
2458
- cmd.addCommand(typesListCommand());
2459
- cmd.addCommand(typesShowCommand());
2460
- cmd.addCommand(typesAddCommand());
2461
- cmd.addCommand(typesRemoveCommand());
2462
- return cmd;
2463
- }
2464
2109
  var __filename2 = fileURLToPath(import.meta.url);
2465
2110
  var __dirname2 = dirname(__filename2);
2466
2111
  var packageJson = JSON.parse(readFileSync(join(__dirname2, "../package.json"), "utf-8"));
@@ -2468,11 +2113,13 @@ var VERSION = packageJson.version;
2468
2113
  function createCLI() {
2469
2114
  const program = new Command("fractary-codex");
2470
2115
  program.description("Centralized knowledge management and distribution for AI agents").version(VERSION);
2471
- program.addCommand(documentCommand());
2472
- program.addCommand(configCommand());
2473
- program.addCommand(cacheCommand());
2116
+ program.addCommand(configureCommand());
2117
+ program.addCommand(documentFetchCommand());
2118
+ program.addCommand(cacheListCommand());
2119
+ program.addCommand(cacheClearCommand());
2120
+ program.addCommand(cacheStatsCommand());
2121
+ program.addCommand(cacheHealthCommand());
2474
2122
  program.addCommand(syncCommand());
2475
- program.addCommand(typesCommand());
2476
2123
  return program;
2477
2124
  }
2478
2125
  async function main() {