@fractary/codex-cli 0.2.2 → 0.4.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/README.md +3 -3
- package/dist/cli.cjs +1004 -1232
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +754 -983
- package/dist/cli.js.map +1 -1
- package/package.json +3 -3
package/dist/cli.cjs
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var fs = require('fs/promises');
|
|
5
|
-
var
|
|
5
|
+
var path3 = require('path');
|
|
6
6
|
var yaml = require('js-yaml');
|
|
7
7
|
var codex = require('@fractary/codex');
|
|
8
8
|
var commander = require('commander');
|
|
9
|
-
var
|
|
10
|
-
var
|
|
9
|
+
var chalk8 = require('chalk');
|
|
10
|
+
var crypto = require('crypto');
|
|
11
11
|
|
|
12
12
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
13
|
|
|
@@ -30,9 +30,10 @@ function _interopNamespace(e) {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
|
|
33
|
-
var
|
|
33
|
+
var path3__namespace = /*#__PURE__*/_interopNamespace(path3);
|
|
34
34
|
var yaml__namespace = /*#__PURE__*/_interopNamespace(yaml);
|
|
35
|
-
var
|
|
35
|
+
var chalk8__default = /*#__PURE__*/_interopDefault(chalk8);
|
|
36
|
+
var crypto__namespace = /*#__PURE__*/_interopNamespace(crypto);
|
|
36
37
|
|
|
37
38
|
var __defProp = Object.defineProperty;
|
|
38
39
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -89,7 +90,7 @@ async function migrateConfig(legacyConfigPath, options) {
|
|
|
89
90
|
organization: legacy.organization || legacy.organizationSlug || "default"
|
|
90
91
|
};
|
|
91
92
|
if (legacy.cache) {
|
|
92
|
-
yamlConfig.cacheDir = legacy.cache.directory || ".codex
|
|
93
|
+
yamlConfig.cacheDir = legacy.cache.directory || ".fractary/codex/cache";
|
|
93
94
|
}
|
|
94
95
|
if (legacy.storage?.providers) {
|
|
95
96
|
yamlConfig.storage = [];
|
|
@@ -185,7 +186,7 @@ async function migrateConfig(legacyConfigPath, options) {
|
|
|
185
186
|
}
|
|
186
187
|
}
|
|
187
188
|
async function writeYamlConfig(config, outputPath) {
|
|
188
|
-
const dir =
|
|
189
|
+
const dir = path3__namespace.dirname(outputPath);
|
|
189
190
|
await fs__namespace.mkdir(dir, { recursive: true });
|
|
190
191
|
const yamlContent = yaml__namespace.dump(config, {
|
|
191
192
|
indent: 2,
|
|
@@ -198,7 +199,7 @@ async function writeYamlConfig(config, outputPath) {
|
|
|
198
199
|
function getDefaultYamlConfig(organization) {
|
|
199
200
|
return {
|
|
200
201
|
organization,
|
|
201
|
-
cacheDir: ".codex
|
|
202
|
+
cacheDir: ".fractary/codex/cache",
|
|
202
203
|
storage: [
|
|
203
204
|
{
|
|
204
205
|
type: "local",
|
|
@@ -409,7 +410,7 @@ var init_codex_client = __esm({
|
|
|
409
410
|
const { readYamlConfig: readYamlConfig2 } = await Promise.resolve().then(() => (init_migrate_config(), migrate_config_exports));
|
|
410
411
|
const { resolveEnvVarsInConfig: resolveEnvVarsInConfig2 } = await Promise.resolve().then(() => (init_config_types(), config_types_exports));
|
|
411
412
|
try {
|
|
412
|
-
const configPath =
|
|
413
|
+
const configPath = path3__namespace.join(process.cwd(), ".fractary", "codex.yaml");
|
|
413
414
|
let config;
|
|
414
415
|
try {
|
|
415
416
|
config = await readYamlConfig2(configPath);
|
|
@@ -621,13 +622,110 @@ var init_codex_client = __esm({
|
|
|
621
622
|
// src/cli.ts
|
|
622
623
|
init_cjs_shims();
|
|
623
624
|
|
|
624
|
-
// src/commands/
|
|
625
|
+
// src/commands/document/index.ts
|
|
626
|
+
init_cjs_shims();
|
|
627
|
+
|
|
628
|
+
// src/commands/document/fetch.ts
|
|
629
|
+
init_cjs_shims();
|
|
630
|
+
|
|
631
|
+
// src/client/get-client.ts
|
|
632
|
+
init_cjs_shims();
|
|
633
|
+
var clientInstance = null;
|
|
634
|
+
async function getClient(options) {
|
|
635
|
+
if (!clientInstance) {
|
|
636
|
+
const { CodexClient: CodexClient2 } = await Promise.resolve().then(() => (init_codex_client(), codex_client_exports));
|
|
637
|
+
clientInstance = await CodexClient2.create(options);
|
|
638
|
+
}
|
|
639
|
+
return clientInstance;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// src/commands/document/fetch.ts
|
|
643
|
+
function hashContent(content) {
|
|
644
|
+
return crypto__namespace.createHash("sha256").update(content).digest("hex").slice(0, 16);
|
|
645
|
+
}
|
|
646
|
+
function fetchCommand() {
|
|
647
|
+
const cmd = new commander.Command("fetch");
|
|
648
|
+
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) => {
|
|
649
|
+
try {
|
|
650
|
+
const { validateUri } = await import('@fractary/codex');
|
|
651
|
+
if (!validateUri(uri)) {
|
|
652
|
+
console.error(chalk8__default.default.red("Error: Invalid URI format"));
|
|
653
|
+
console.log(chalk8__default.default.dim("Expected: codex://org/project/path/to/file.md"));
|
|
654
|
+
console.log(chalk8__default.default.dim("Example: codex://fractary/codex/docs/api.md"));
|
|
655
|
+
process.exit(1);
|
|
656
|
+
}
|
|
657
|
+
const client = await getClient();
|
|
658
|
+
if (!options.json && !options.bypassCache) {
|
|
659
|
+
console.error(chalk8__default.default.dim(`Fetching ${uri}...`));
|
|
660
|
+
}
|
|
661
|
+
const result = await client.fetch(uri, {
|
|
662
|
+
bypassCache: options.bypassCache,
|
|
663
|
+
ttl: options.ttl
|
|
664
|
+
});
|
|
665
|
+
if (options.json) {
|
|
666
|
+
const output = {
|
|
667
|
+
uri,
|
|
668
|
+
content: result.content.toString("utf-8"),
|
|
669
|
+
metadata: {
|
|
670
|
+
fromCache: result.fromCache,
|
|
671
|
+
fetchedAt: result.metadata?.fetchedAt,
|
|
672
|
+
expiresAt: result.metadata?.expiresAt,
|
|
673
|
+
contentLength: result.metadata?.contentLength || result.content.length,
|
|
674
|
+
contentHash: hashContent(result.content)
|
|
675
|
+
}
|
|
676
|
+
};
|
|
677
|
+
console.log(JSON.stringify(output, null, 2));
|
|
678
|
+
} else if (options.output) {
|
|
679
|
+
await fs__namespace.writeFile(options.output, result.content);
|
|
680
|
+
console.log(chalk8__default.default.green("\u2713"), `Written to ${options.output}`);
|
|
681
|
+
console.log(chalk8__default.default.dim(` Size: ${result.content.length} bytes`));
|
|
682
|
+
if (result.fromCache) {
|
|
683
|
+
console.log(chalk8__default.default.dim(" Source: cache"));
|
|
684
|
+
} else {
|
|
685
|
+
console.log(chalk8__default.default.dim(" Source: storage"));
|
|
686
|
+
}
|
|
687
|
+
} else {
|
|
688
|
+
if (result.fromCache && !options.bypassCache) {
|
|
689
|
+
console.error(chalk8__default.default.green("\u2713"), chalk8__default.default.dim("from cache\n"));
|
|
690
|
+
} else {
|
|
691
|
+
console.error(chalk8__default.default.green("\u2713"), chalk8__default.default.dim("fetched\n"));
|
|
692
|
+
}
|
|
693
|
+
console.log(result.content.toString("utf-8"));
|
|
694
|
+
}
|
|
695
|
+
} catch (error) {
|
|
696
|
+
console.error(chalk8__default.default.red("Error:"), error.message);
|
|
697
|
+
if (error.message.includes("Failed to load configuration")) {
|
|
698
|
+
console.log(chalk8__default.default.dim('\nRun "fractary codex init" to create a configuration.'));
|
|
699
|
+
} else if (error.message.includes("GITHUB_TOKEN")) {
|
|
700
|
+
console.log(chalk8__default.default.dim('\nSet your GitHub token: export GITHUB_TOKEN="your_token"'));
|
|
701
|
+
} else if (error.message.includes("not found") || error.message.includes("404")) {
|
|
702
|
+
console.log(chalk8__default.default.dim("\nThe document may not exist or you may not have access."));
|
|
703
|
+
console.log(chalk8__default.default.dim("Check the URI and ensure your storage providers are configured correctly."));
|
|
704
|
+
}
|
|
705
|
+
process.exit(1);
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
return cmd;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// src/commands/document/index.ts
|
|
712
|
+
function documentCommand() {
|
|
713
|
+
const cmd = new commander.Command("document");
|
|
714
|
+
cmd.description("Manage document operations");
|
|
715
|
+
cmd.addCommand(fetchCommand());
|
|
716
|
+
return cmd;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// src/commands/config/index.ts
|
|
720
|
+
init_cjs_shims();
|
|
721
|
+
|
|
722
|
+
// src/commands/config/init.ts
|
|
625
723
|
init_cjs_shims();
|
|
626
724
|
init_migrate_config();
|
|
627
725
|
async function getOrgFromGitRemote() {
|
|
628
726
|
try {
|
|
629
|
-
const { execSync
|
|
630
|
-
const remote =
|
|
727
|
+
const { execSync } = __require("child_process");
|
|
728
|
+
const remote = execSync("git remote get-url origin 2>/dev/null", { encoding: "utf-8" }).trim();
|
|
631
729
|
const sshMatch = remote.match(/git@github\.com:([^/]+)\//);
|
|
632
730
|
const httpsMatch = remote.match(/github\.com\/([^/]+)\//);
|
|
633
731
|
return sshMatch?.[1] || httpsMatch?.[1] || null;
|
|
@@ -647,7 +745,7 @@ function initCommand() {
|
|
|
647
745
|
const cmd = new commander.Command("init");
|
|
648
746
|
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) => {
|
|
649
747
|
try {
|
|
650
|
-
console.log(
|
|
748
|
+
console.log(chalk8__default.default.blue("Initializing Codex v3.0 (YAML format)...\n"));
|
|
651
749
|
let org = options.org;
|
|
652
750
|
if (!org) {
|
|
653
751
|
org = await getOrgFromGitRemote();
|
|
@@ -656,41 +754,35 @@ function initCommand() {
|
|
|
656
754
|
try {
|
|
657
755
|
const { resolveOrganization } = await import('@fractary/codex');
|
|
658
756
|
org = resolveOrganization({
|
|
659
|
-
repoName:
|
|
757
|
+
repoName: path3__namespace.basename(process.cwd())
|
|
660
758
|
});
|
|
661
759
|
} catch {
|
|
662
760
|
}
|
|
663
761
|
}
|
|
664
762
|
if (!org) {
|
|
665
|
-
org =
|
|
666
|
-
console.log(
|
|
667
|
-
console.log(
|
|
763
|
+
org = path3__namespace.basename(process.cwd()).split("-")[0] || "default";
|
|
764
|
+
console.log(chalk8__default.default.yellow(`\u26A0 Could not detect organization, using: ${org}`));
|
|
765
|
+
console.log(chalk8__default.default.dim(" Use --org <slug> to specify explicitly\n"));
|
|
668
766
|
} else {
|
|
669
|
-
console.log(
|
|
767
|
+
console.log(chalk8__default.default.dim(`Organization: ${chalk8__default.default.cyan(org)}
|
|
670
768
|
`));
|
|
671
769
|
}
|
|
672
|
-
const configDir =
|
|
673
|
-
const configPath =
|
|
770
|
+
const configDir = path3__namespace.join(process.cwd(), ".fractary", "codex");
|
|
771
|
+
const configPath = path3__namespace.join(configDir, "config.yaml");
|
|
674
772
|
const configExists = await fileExists(configPath);
|
|
675
|
-
const legacyConfigPath = path2__namespace.join(process.cwd(), ".fractary", "plugins", "codex", "config.json");
|
|
676
|
-
const legacyExists = await fileExists(legacyConfigPath);
|
|
677
773
|
if (configExists && !options.force) {
|
|
678
|
-
console.log(
|
|
679
|
-
console.log(
|
|
774
|
+
console.log(chalk8__default.default.yellow("\u26A0 Configuration already exists at .fractary/codex/config.yaml"));
|
|
775
|
+
console.log(chalk8__default.default.dim("Use --force to overwrite"));
|
|
680
776
|
process.exit(1);
|
|
681
777
|
}
|
|
682
|
-
if (legacyExists && !configExists) {
|
|
683
|
-
console.log(chalk6__default.default.yellow("\u26A0 Legacy configuration detected at .fractary/plugins/codex/config.json"));
|
|
684
|
-
console.log(chalk6__default.default.dim('Run "fractary codex migrate" to upgrade to YAML format\n'));
|
|
685
|
-
}
|
|
686
778
|
console.log("Creating directory structure...");
|
|
687
779
|
const dirs = [
|
|
688
|
-
".fractary",
|
|
689
|
-
".codex
|
|
780
|
+
".fractary/codex",
|
|
781
|
+
".fractary/codex/cache"
|
|
690
782
|
];
|
|
691
783
|
for (const dir of dirs) {
|
|
692
|
-
await fs__namespace.mkdir(
|
|
693
|
-
console.log(
|
|
784
|
+
await fs__namespace.mkdir(path3__namespace.join(process.cwd(), dir), { recursive: true });
|
|
785
|
+
console.log(chalk8__default.default.green("\u2713"), chalk8__default.default.dim(dir + "/"));
|
|
694
786
|
}
|
|
695
787
|
console.log("\nCreating YAML configuration...");
|
|
696
788
|
const config = getDefaultYamlConfig(org);
|
|
@@ -698,113 +790,179 @@ function initCommand() {
|
|
|
698
790
|
config.mcp.enabled = true;
|
|
699
791
|
}
|
|
700
792
|
await writeYamlConfig(config, configPath);
|
|
701
|
-
console.log(
|
|
702
|
-
console.log(
|
|
703
|
-
console.log(
|
|
704
|
-
console.log(
|
|
705
|
-
console.log(
|
|
706
|
-
console.log(
|
|
793
|
+
console.log(chalk8__default.default.green("\u2713"), chalk8__default.default.dim(".fractary/codex/config.yaml"));
|
|
794
|
+
console.log(chalk8__default.default.green("\n\u2713 Codex v4.0 initialized successfully!\n"));
|
|
795
|
+
console.log(chalk8__default.default.bold("Configuration:"));
|
|
796
|
+
console.log(chalk8__default.default.dim(` Organization: ${org}`));
|
|
797
|
+
console.log(chalk8__default.default.dim(` Cache: .fractary/codex/cache/`));
|
|
798
|
+
console.log(chalk8__default.default.dim(` Config: .fractary/codex/config.yaml`));
|
|
707
799
|
if (options.mcp) {
|
|
708
|
-
console.log(
|
|
709
|
-
}
|
|
710
|
-
console.log(
|
|
711
|
-
console.log(
|
|
712
|
-
console.log(
|
|
713
|
-
console.log(
|
|
714
|
-
console.log(
|
|
715
|
-
console.log(
|
|
716
|
-
console.log(
|
|
717
|
-
console.log(
|
|
718
|
-
console.log(
|
|
719
|
-
if (legacyExists) {
|
|
720
|
-
console.log(chalk6__default.default.yellow("\n\u26A0 Legacy config detected:"));
|
|
721
|
-
console.log(chalk6__default.default.dim(' Run "fractary codex migrate" to convert your existing config'));
|
|
722
|
-
}
|
|
800
|
+
console.log(chalk8__default.default.dim(` MCP Server: Enabled (port 3000)`));
|
|
801
|
+
}
|
|
802
|
+
console.log(chalk8__default.default.bold("\nStorage providers configured:"));
|
|
803
|
+
console.log(chalk8__default.default.dim(" - Local filesystem (./knowledge)"));
|
|
804
|
+
console.log(chalk8__default.default.dim(" - GitHub (requires GITHUB_TOKEN)"));
|
|
805
|
+
console.log(chalk8__default.default.dim(" - HTTP endpoint"));
|
|
806
|
+
console.log(chalk8__default.default.bold("\nNext steps:"));
|
|
807
|
+
console.log(chalk8__default.default.dim(' 1. Set your GitHub token: export GITHUB_TOKEN="your_token"'));
|
|
808
|
+
console.log(chalk8__default.default.dim(" 2. Edit .fractary/codex/config.yaml to configure storage providers"));
|
|
809
|
+
console.log(chalk8__default.default.dim(" 3. Fetch a document: fractary codex fetch codex://org/project/path"));
|
|
810
|
+
console.log(chalk8__default.default.dim(" 4. Check cache: fractary codex cache list"));
|
|
723
811
|
} catch (error) {
|
|
724
|
-
console.error(
|
|
812
|
+
console.error(chalk8__default.default.red("Error:"), error.message);
|
|
725
813
|
process.exit(1);
|
|
726
814
|
}
|
|
727
815
|
});
|
|
728
816
|
return cmd;
|
|
729
817
|
}
|
|
730
818
|
|
|
731
|
-
// src/commands/
|
|
732
|
-
init_cjs_shims();
|
|
733
|
-
|
|
734
|
-
// src/client/get-client.ts
|
|
819
|
+
// src/commands/config/migrate.ts
|
|
735
820
|
init_cjs_shims();
|
|
736
|
-
|
|
737
|
-
async function
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
821
|
+
init_migrate_config();
|
|
822
|
+
async function fileExists2(filePath) {
|
|
823
|
+
try {
|
|
824
|
+
await fs__namespace.access(filePath);
|
|
825
|
+
return true;
|
|
826
|
+
} catch {
|
|
827
|
+
return false;
|
|
741
828
|
}
|
|
742
|
-
return clientInstance;
|
|
743
829
|
}
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
function hashContent(content) {
|
|
747
|
-
const crypto = __require("crypto");
|
|
748
|
-
return crypto.createHash("sha256").update(content).digest("hex").slice(0, 16);
|
|
830
|
+
async function readFileContent(filePath) {
|
|
831
|
+
return fs__namespace.readFile(filePath, "utf-8");
|
|
749
832
|
}
|
|
750
|
-
function
|
|
751
|
-
const cmd = new commander.Command("
|
|
752
|
-
cmd.description("
|
|
833
|
+
function migrateCommand() {
|
|
834
|
+
const cmd = new commander.Command("migrate");
|
|
835
|
+
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) => {
|
|
753
836
|
try {
|
|
754
|
-
const
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
837
|
+
const legacyConfigPath = path3__namespace.join(process.cwd(), ".fractary", "plugins", "codex", "config.json");
|
|
838
|
+
const newConfigPath = path3__namespace.join(process.cwd(), ".fractary", "codex.yaml");
|
|
839
|
+
if (!await fileExists2(legacyConfigPath)) {
|
|
840
|
+
if (options.json) {
|
|
841
|
+
console.log(JSON.stringify({
|
|
842
|
+
status: "no_config",
|
|
843
|
+
message: "No legacy configuration file found",
|
|
844
|
+
path: legacyConfigPath
|
|
845
|
+
}));
|
|
846
|
+
} else {
|
|
847
|
+
console.log(chalk8__default.default.yellow("\u26A0 No legacy configuration file found."));
|
|
848
|
+
console.log(chalk8__default.default.dim(` Expected: ${legacyConfigPath}`));
|
|
849
|
+
console.log(chalk8__default.default.dim('\nRun "fractary codex init" to create a new v3.0 YAML configuration.'));
|
|
850
|
+
}
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
if (await fileExists2(newConfigPath) && !options.dryRun) {
|
|
854
|
+
if (options.json) {
|
|
855
|
+
console.log(JSON.stringify({
|
|
856
|
+
status: "already_migrated",
|
|
857
|
+
message: "YAML configuration already exists",
|
|
858
|
+
path: newConfigPath
|
|
859
|
+
}));
|
|
860
|
+
} else {
|
|
861
|
+
console.log(chalk8__default.default.yellow("\u26A0 YAML configuration already exists."));
|
|
862
|
+
console.log(chalk8__default.default.dim(` Path: ${newConfigPath}`));
|
|
863
|
+
console.log(chalk8__default.default.dim('\nUse "fractary codex init --force" to recreate.'));
|
|
864
|
+
}
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
const legacyContent = await readFileContent(legacyConfigPath);
|
|
868
|
+
let legacyConfig;
|
|
869
|
+
try {
|
|
870
|
+
legacyConfig = JSON.parse(legacyContent);
|
|
871
|
+
} catch {
|
|
872
|
+
console.error(chalk8__default.default.red("Error:"), "Invalid JSON in legacy config file.");
|
|
759
873
|
process.exit(1);
|
|
760
874
|
}
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
875
|
+
if (!options.json && !options.dryRun) {
|
|
876
|
+
console.log(chalk8__default.default.blue("Migrating Codex configuration to v3.0 YAML format...\n"));
|
|
877
|
+
}
|
|
878
|
+
const migrationResult = await migrateConfig(
|
|
879
|
+
legacyConfigPath,
|
|
880
|
+
{
|
|
881
|
+
createBackup: options.backup !== false,
|
|
882
|
+
backupSuffix: (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")
|
|
883
|
+
}
|
|
884
|
+
);
|
|
885
|
+
if (!options.json) {
|
|
886
|
+
console.log(chalk8__default.default.bold("Legacy Configuration:"));
|
|
887
|
+
console.log(chalk8__default.default.dim(` Path: ${legacyConfigPath}`));
|
|
888
|
+
console.log(chalk8__default.default.dim(` Organization: ${legacyConfig.organization || legacyConfig.organizationSlug || "unknown"}`));
|
|
889
|
+
console.log("");
|
|
890
|
+
console.log(chalk8__default.default.bold("Migration Changes:"));
|
|
891
|
+
console.log(chalk8__default.default.green(" + Format: JSON \u2192 YAML"));
|
|
892
|
+
console.log(chalk8__default.default.green(" + Location: .fractary/plugins/codex/ \u2192 .fractary/"));
|
|
893
|
+
console.log(chalk8__default.default.green(" + File: config.json \u2192 codex.yaml"));
|
|
894
|
+
console.log(chalk8__default.default.green(" + Storage: Multi-provider configuration"));
|
|
895
|
+
console.log(chalk8__default.default.green(" + Cache: Modern cache management"));
|
|
896
|
+
console.log(chalk8__default.default.green(" + Types: Custom type registry"));
|
|
897
|
+
if (migrationResult.warnings.length > 0) {
|
|
898
|
+
console.log("");
|
|
899
|
+
console.log(chalk8__default.default.yellow("Warnings:"));
|
|
900
|
+
for (const warning of migrationResult.warnings) {
|
|
901
|
+
console.log(chalk8__default.default.yellow(" \u26A0"), chalk8__default.default.dim(warning));
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
console.log("");
|
|
905
|
+
if (options.dryRun) {
|
|
906
|
+
console.log(chalk8__default.default.blue("Dry run - no changes made."));
|
|
907
|
+
console.log(chalk8__default.default.dim("Run without --dry-run to execute migration."));
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
764
910
|
}
|
|
765
|
-
const result = await client.fetch(uri, {
|
|
766
|
-
bypassCache: options.bypassCache,
|
|
767
|
-
ttl: options.ttl
|
|
768
|
-
});
|
|
769
911
|
if (options.json) {
|
|
770
912
|
const output = {
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
913
|
+
status: options.dryRun ? "migration_ready" : "migrated",
|
|
914
|
+
dryRun: options.dryRun || false,
|
|
915
|
+
legacyConfig: {
|
|
916
|
+
path: legacyConfigPath,
|
|
917
|
+
organization: legacyConfig.organization || legacyConfig.organizationSlug
|
|
918
|
+
},
|
|
919
|
+
newConfig: {
|
|
920
|
+
path: newConfigPath,
|
|
921
|
+
organization: migrationResult.yamlConfig.organization
|
|
922
|
+
},
|
|
923
|
+
warnings: migrationResult.warnings,
|
|
924
|
+
backupPath: migrationResult.backupPath
|
|
780
925
|
};
|
|
781
926
|
console.log(JSON.stringify(output, null, 2));
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
console.log(chalk6__default.default.green("\u2713"), `Written to ${options.output}`);
|
|
785
|
-
console.log(chalk6__default.default.dim(` Size: ${result.content.length} bytes`));
|
|
786
|
-
if (result.fromCache) {
|
|
787
|
-
console.log(chalk6__default.default.dim(" Source: cache"));
|
|
788
|
-
} else {
|
|
789
|
-
console.log(chalk6__default.default.dim(" Source: storage"));
|
|
927
|
+
if (options.dryRun) {
|
|
928
|
+
return;
|
|
790
929
|
}
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
930
|
+
}
|
|
931
|
+
if (!options.dryRun) {
|
|
932
|
+
await writeYamlConfig(migrationResult.yamlConfig, newConfigPath);
|
|
933
|
+
const cacheDir = path3__namespace.join(process.cwd(), ".codex-cache");
|
|
934
|
+
await fs__namespace.mkdir(cacheDir, { recursive: true });
|
|
935
|
+
if (!options.json) {
|
|
936
|
+
console.log(chalk8__default.default.green("\u2713"), "YAML configuration created");
|
|
937
|
+
console.log(chalk8__default.default.green("\u2713"), "Cache directory initialized");
|
|
938
|
+
if (migrationResult.backupPath) {
|
|
939
|
+
console.log(chalk8__default.default.green("\u2713"), "Legacy config backed up");
|
|
940
|
+
}
|
|
941
|
+
console.log("");
|
|
942
|
+
console.log(chalk8__default.default.bold("New Configuration:"));
|
|
943
|
+
console.log(chalk8__default.default.dim(` Path: ${newConfigPath}`));
|
|
944
|
+
console.log(chalk8__default.default.dim(` Organization: ${migrationResult.yamlConfig.organization}`));
|
|
945
|
+
console.log(chalk8__default.default.dim(` Cache: ${migrationResult.yamlConfig.cacheDir || ".codex-cache"}`));
|
|
946
|
+
console.log(chalk8__default.default.dim(` Storage Providers: ${migrationResult.yamlConfig.storage?.length || 0}`));
|
|
947
|
+
console.log("");
|
|
948
|
+
console.log(chalk8__default.default.bold("Next Steps:"));
|
|
949
|
+
console.log(chalk8__default.default.dim(" 1. Review the new configuration: .fractary/codex.yaml"));
|
|
950
|
+
console.log(chalk8__default.default.dim(' 2. Set your GitHub token: export GITHUB_TOKEN="your_token"'));
|
|
951
|
+
console.log(chalk8__default.default.dim(" 3. Test fetching: fractary codex fetch codex://org/project/path"));
|
|
952
|
+
if (migrationResult.backupPath) {
|
|
953
|
+
console.log("");
|
|
954
|
+
console.log(chalk8__default.default.dim(`Backup saved: ${path3__namespace.basename(migrationResult.backupPath)}`));
|
|
955
|
+
}
|
|
796
956
|
}
|
|
797
|
-
console.log(result.content.toString("utf-8"));
|
|
798
957
|
}
|
|
799
958
|
} catch (error) {
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
} else
|
|
806
|
-
console.
|
|
807
|
-
console.log(chalk6__default.default.dim("Check the URI and ensure your storage providers are configured correctly."));
|
|
959
|
+
if (options.json) {
|
|
960
|
+
console.log(JSON.stringify({
|
|
961
|
+
status: "error",
|
|
962
|
+
message: error.message
|
|
963
|
+
}));
|
|
964
|
+
} else {
|
|
965
|
+
console.error(chalk8__default.default.red("Error:"), error.message);
|
|
808
966
|
}
|
|
809
967
|
process.exit(1);
|
|
810
968
|
}
|
|
@@ -812,6 +970,15 @@ function fetchCommand() {
|
|
|
812
970
|
return cmd;
|
|
813
971
|
}
|
|
814
972
|
|
|
973
|
+
// src/commands/config/index.ts
|
|
974
|
+
function configCommand() {
|
|
975
|
+
const cmd = new commander.Command("config");
|
|
976
|
+
cmd.description("Manage configuration");
|
|
977
|
+
cmd.addCommand(initCommand());
|
|
978
|
+
cmd.addCommand(migrateCommand());
|
|
979
|
+
return cmd;
|
|
980
|
+
}
|
|
981
|
+
|
|
815
982
|
// src/commands/cache/index.ts
|
|
816
983
|
init_cjs_shims();
|
|
817
984
|
|
|
@@ -832,8 +999,8 @@ function cacheListCommand() {
|
|
|
832
999
|
if (options.json) {
|
|
833
1000
|
console.log(JSON.stringify({ entries: 0, message: "Cache is empty" }));
|
|
834
1001
|
} else {
|
|
835
|
-
console.log(
|
|
836
|
-
console.log(
|
|
1002
|
+
console.log(chalk8__default.default.yellow("Cache is empty."));
|
|
1003
|
+
console.log(chalk8__default.default.dim("Fetch some documents to populate the cache."));
|
|
837
1004
|
}
|
|
838
1005
|
return;
|
|
839
1006
|
}
|
|
@@ -847,25 +1014,25 @@ function cacheListCommand() {
|
|
|
847
1014
|
}, null, 2));
|
|
848
1015
|
return;
|
|
849
1016
|
}
|
|
850
|
-
console.log(
|
|
851
|
-
console.log(
|
|
852
|
-
console.log(` Total: ${
|
|
853
|
-
console.log(` Fresh: ${
|
|
854
|
-
console.log(` Stale: ${stats.staleCount > 0 ?
|
|
855
|
-
console.log(` Expired: ${stats.expiredCount > 0 ?
|
|
1017
|
+
console.log(chalk8__default.default.bold("Cache Overview\n"));
|
|
1018
|
+
console.log(chalk8__default.default.bold("Entries:"));
|
|
1019
|
+
console.log(` Total: ${chalk8__default.default.cyan(stats.entryCount.toString())} entries`);
|
|
1020
|
+
console.log(` Fresh: ${chalk8__default.default.green(stats.freshCount.toString())} entries`);
|
|
1021
|
+
console.log(` Stale: ${stats.staleCount > 0 ? chalk8__default.default.yellow(stats.staleCount.toString()) : chalk8__default.default.dim("0")} entries`);
|
|
1022
|
+
console.log(` Expired: ${stats.expiredCount > 0 ? chalk8__default.default.red(stats.expiredCount.toString()) : chalk8__default.default.dim("0")} entries`);
|
|
856
1023
|
console.log("");
|
|
857
|
-
console.log(
|
|
858
|
-
console.log(` Total size: ${
|
|
1024
|
+
console.log(chalk8__default.default.bold("Storage:"));
|
|
1025
|
+
console.log(` Total size: ${chalk8__default.default.cyan(formatSize(stats.totalSize))}`);
|
|
859
1026
|
console.log("");
|
|
860
1027
|
const healthPercent = stats.entryCount > 0 ? stats.freshCount / stats.entryCount * 100 : 100;
|
|
861
|
-
const healthColor = healthPercent > 80 ?
|
|
1028
|
+
const healthColor = healthPercent > 80 ? chalk8__default.default.green : healthPercent > 50 ? chalk8__default.default.yellow : chalk8__default.default.red;
|
|
862
1029
|
console.log(`Cache health: ${healthColor(`${healthPercent.toFixed(0)}% fresh`)}`);
|
|
863
1030
|
console.log("");
|
|
864
|
-
console.log(
|
|
865
|
-
console.log(
|
|
866
|
-
console.log(
|
|
1031
|
+
console.log(chalk8__default.default.dim("Note: Individual cache entries are managed by the SDK."));
|
|
1032
|
+
console.log(chalk8__default.default.dim('Use "fractary codex cache stats" for detailed statistics.'));
|
|
1033
|
+
console.log(chalk8__default.default.dim('Use "fractary codex cache clear" to clear cache entries.'));
|
|
867
1034
|
} catch (error) {
|
|
868
|
-
console.error(
|
|
1035
|
+
console.error(chalk8__default.default.red("Error:"), error.message);
|
|
869
1036
|
process.exit(1);
|
|
870
1037
|
}
|
|
871
1038
|
});
|
|
@@ -881,7 +1048,7 @@ function cacheClearCommand() {
|
|
|
881
1048
|
const client = await getClient();
|
|
882
1049
|
const statsBefore = await client.getCacheStats();
|
|
883
1050
|
if (statsBefore.entryCount === 0) {
|
|
884
|
-
console.log(
|
|
1051
|
+
console.log(chalk8__default.default.yellow("Cache is already empty. Nothing to clear."));
|
|
885
1052
|
return;
|
|
886
1053
|
}
|
|
887
1054
|
let pattern;
|
|
@@ -890,45 +1057,45 @@ function cacheClearCommand() {
|
|
|
890
1057
|
} else if (options.pattern) {
|
|
891
1058
|
pattern = options.pattern;
|
|
892
1059
|
} else {
|
|
893
|
-
console.log(
|
|
894
|
-
console.log(
|
|
895
|
-
console.log(
|
|
1060
|
+
console.log(chalk8__default.default.yellow("Please specify what to clear:"));
|
|
1061
|
+
console.log(chalk8__default.default.dim(" --all Clear entire cache"));
|
|
1062
|
+
console.log(chalk8__default.default.dim(' --pattern Clear entries matching pattern (e.g., "codex://fractary/*")'));
|
|
896
1063
|
console.log("");
|
|
897
|
-
console.log(
|
|
898
|
-
console.log(
|
|
899
|
-
console.log(
|
|
1064
|
+
console.log(chalk8__default.default.dim("Examples:"));
|
|
1065
|
+
console.log(chalk8__default.default.dim(" fractary codex cache clear --all"));
|
|
1066
|
+
console.log(chalk8__default.default.dim(' fractary codex cache clear --pattern "codex://fractary/cli/*"'));
|
|
900
1067
|
return;
|
|
901
1068
|
}
|
|
902
1069
|
if (options.dryRun) {
|
|
903
|
-
console.log(
|
|
1070
|
+
console.log(chalk8__default.default.blue("Dry run - would clear:\n"));
|
|
904
1071
|
if (pattern) {
|
|
905
|
-
console.log(
|
|
906
|
-
console.log(
|
|
1072
|
+
console.log(chalk8__default.default.dim(` Pattern: ${pattern}`));
|
|
1073
|
+
console.log(chalk8__default.default.dim(` This would invalidate matching cache entries`));
|
|
907
1074
|
} else {
|
|
908
|
-
console.log(
|
|
1075
|
+
console.log(chalk8__default.default.dim(` All cache entries (${statsBefore.entryCount} entries)`));
|
|
909
1076
|
}
|
|
910
|
-
console.log(
|
|
1077
|
+
console.log(chalk8__default.default.dim(`
|
|
911
1078
|
Total size: ${formatSize2(statsBefore.totalSize)}`));
|
|
912
1079
|
return;
|
|
913
1080
|
}
|
|
914
1081
|
if (pattern) {
|
|
915
|
-
console.log(
|
|
1082
|
+
console.log(chalk8__default.default.blue(`Clearing cache entries matching pattern: ${pattern}
|
|
916
1083
|
`));
|
|
917
1084
|
await client.invalidateCache(pattern);
|
|
918
1085
|
} else {
|
|
919
|
-
console.log(
|
|
1086
|
+
console.log(chalk8__default.default.blue(`Clearing entire cache (${statsBefore.entryCount} entries)...
|
|
920
1087
|
`));
|
|
921
1088
|
await client.invalidateCache();
|
|
922
1089
|
}
|
|
923
1090
|
const statsAfter = await client.getCacheStats();
|
|
924
1091
|
const entriesCleared = statsBefore.entryCount - statsAfter.entryCount;
|
|
925
1092
|
const sizeFreed = statsBefore.totalSize - statsAfter.totalSize;
|
|
926
|
-
console.log(
|
|
1093
|
+
console.log(chalk8__default.default.green(`\u2713 Cleared ${entriesCleared} entries (${formatSize2(sizeFreed)} freed)`));
|
|
927
1094
|
if (statsAfter.entryCount > 0) {
|
|
928
|
-
console.log(
|
|
1095
|
+
console.log(chalk8__default.default.dim(` Remaining: ${statsAfter.entryCount} entries (${formatSize2(statsAfter.totalSize)})`));
|
|
929
1096
|
}
|
|
930
1097
|
} catch (error) {
|
|
931
|
-
console.error(
|
|
1098
|
+
console.error(chalk8__default.default.red("Error:"), error.message);
|
|
932
1099
|
process.exit(1);
|
|
933
1100
|
}
|
|
934
1101
|
});
|
|
@@ -957,557 +1124,560 @@ function cacheStatsCommand() {
|
|
|
957
1124
|
console.log(JSON.stringify(stats, null, 2));
|
|
958
1125
|
return;
|
|
959
1126
|
}
|
|
960
|
-
console.log(
|
|
961
|
-
console.log(
|
|
962
|
-
console.log(` Total entries: ${
|
|
963
|
-
console.log(` Total size: ${
|
|
964
|
-
console.log(` Fresh entries: ${
|
|
965
|
-
console.log(` Stale entries: ${stats.staleCount > 0 ?
|
|
966
|
-
console.log(` Expired entries: ${stats.expiredCount > 0 ?
|
|
1127
|
+
console.log(chalk8__default.default.bold("Cache Statistics\n"));
|
|
1128
|
+
console.log(chalk8__default.default.bold("Overview"));
|
|
1129
|
+
console.log(` Total entries: ${chalk8__default.default.cyan(stats.entryCount.toString())}`);
|
|
1130
|
+
console.log(` Total size: ${chalk8__default.default.cyan(formatSize3(stats.totalSize))}`);
|
|
1131
|
+
console.log(` Fresh entries: ${chalk8__default.default.green(stats.freshCount.toString())}`);
|
|
1132
|
+
console.log(` Stale entries: ${stats.staleCount > 0 ? chalk8__default.default.yellow(stats.staleCount.toString()) : chalk8__default.default.dim("0")}`);
|
|
1133
|
+
console.log(` Expired entries: ${stats.expiredCount > 0 ? chalk8__default.default.red(stats.expiredCount.toString()) : chalk8__default.default.dim("0")}`);
|
|
967
1134
|
console.log("");
|
|
968
1135
|
const healthPercent = stats.entryCount > 0 ? stats.freshCount / stats.entryCount * 100 : 100;
|
|
969
|
-
const healthColor = healthPercent > 80 ?
|
|
1136
|
+
const healthColor = healthPercent > 80 ? chalk8__default.default.green : healthPercent > 50 ? chalk8__default.default.yellow : chalk8__default.default.red;
|
|
970
1137
|
console.log(`Cache health: ${healthColor(`${healthPercent.toFixed(0)}% fresh`)}`);
|
|
971
1138
|
if (stats.expiredCount > 0) {
|
|
972
|
-
console.log(
|
|
1139
|
+
console.log(chalk8__default.default.dim('\nRun "fractary codex cache clear --pattern <pattern>" to clean up entries.'));
|
|
973
1140
|
}
|
|
974
1141
|
if (stats.entryCount === 0) {
|
|
975
|
-
console.log(
|
|
1142
|
+
console.log(chalk8__default.default.dim("\nNo cached entries. Fetch some documents to populate the cache."));
|
|
976
1143
|
}
|
|
977
1144
|
} catch (error) {
|
|
978
|
-
console.error(
|
|
1145
|
+
console.error(chalk8__default.default.red("Error:"), error.message);
|
|
979
1146
|
process.exit(1);
|
|
980
1147
|
}
|
|
981
1148
|
});
|
|
982
1149
|
return cmd;
|
|
983
1150
|
}
|
|
984
1151
|
|
|
985
|
-
// src/commands/cache/
|
|
986
|
-
function cacheCommand() {
|
|
987
|
-
const cmd = new commander.Command("cache");
|
|
988
|
-
cmd.description("Manage the codex document cache");
|
|
989
|
-
cmd.addCommand(cacheListCommand());
|
|
990
|
-
cmd.addCommand(cacheClearCommand());
|
|
991
|
-
cmd.addCommand(cacheStatsCommand());
|
|
992
|
-
return cmd;
|
|
993
|
-
}
|
|
994
|
-
|
|
995
|
-
// src/commands/sync/index.ts
|
|
996
|
-
init_cjs_shims();
|
|
997
|
-
|
|
998
|
-
// src/commands/sync/project.ts
|
|
1152
|
+
// src/commands/cache/health.ts
|
|
999
1153
|
init_cjs_shims();
|
|
1000
1154
|
init_migrate_config();
|
|
1001
|
-
function
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
}
|
|
1008
|
-
return envMap[env] || env;
|
|
1009
|
-
}
|
|
1010
|
-
function formatBytes(bytes) {
|
|
1011
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
1012
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
1013
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
1014
|
-
}
|
|
1015
|
-
function formatDuration(ms) {
|
|
1016
|
-
if (ms < 1e3) return `${ms}ms`;
|
|
1017
|
-
return `${(ms / 1e3).toFixed(1)}s`;
|
|
1155
|
+
async function fileExists3(filePath) {
|
|
1156
|
+
try {
|
|
1157
|
+
await fs__namespace.access(filePath);
|
|
1158
|
+
return true;
|
|
1159
|
+
} catch {
|
|
1160
|
+
return false;
|
|
1161
|
+
}
|
|
1018
1162
|
}
|
|
1019
|
-
function
|
|
1020
|
-
const
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
process.exit(1);
|
|
1031
|
-
}
|
|
1032
|
-
const { createSyncManager, createLocalStorage, detectCurrentProject } = await import('@fractary/codex');
|
|
1033
|
-
let projectName = name;
|
|
1034
|
-
if (!projectName) {
|
|
1035
|
-
const detected = detectCurrentProject();
|
|
1036
|
-
projectName = detected.project || null;
|
|
1037
|
-
}
|
|
1038
|
-
if (!projectName) {
|
|
1039
|
-
console.error(chalk6__default.default.red("Error:"), "Could not determine project name.");
|
|
1040
|
-
console.log(chalk6__default.default.dim("Provide project name as argument or run from a git repository."));
|
|
1041
|
-
process.exit(1);
|
|
1042
|
-
}
|
|
1043
|
-
const validDirections = ["to-codex", "from-codex", "bidirectional"];
|
|
1044
|
-
if (!validDirections.includes(options.direction)) {
|
|
1045
|
-
console.error(chalk6__default.default.red("Error:"), `Invalid direction: ${options.direction}`);
|
|
1046
|
-
console.log(chalk6__default.default.dim("Valid options: to-codex, from-codex, bidirectional"));
|
|
1047
|
-
process.exit(1);
|
|
1048
|
-
}
|
|
1049
|
-
const direction = options.direction;
|
|
1050
|
-
const targetBranch = getEnvironmentBranch(config, options.env);
|
|
1051
|
-
const localStorage = createLocalStorage({
|
|
1052
|
-
baseDir: process.cwd()
|
|
1053
|
-
});
|
|
1054
|
-
const syncManager = createSyncManager({
|
|
1055
|
-
localStorage,
|
|
1056
|
-
config: config.sync,
|
|
1057
|
-
manifestPath: path2__namespace.join(process.cwd(), ".fractary", ".codex-sync-manifest.json")
|
|
1058
|
-
});
|
|
1059
|
-
const defaultPatterns = config.sync?.include || [
|
|
1060
|
-
"docs/**/*.md",
|
|
1061
|
-
"specs/**/*.md",
|
|
1062
|
-
".fractary/standards/**",
|
|
1063
|
-
".fractary/templates/**"
|
|
1064
|
-
];
|
|
1065
|
-
const includePatterns = options.include.length > 0 ? options.include : defaultPatterns;
|
|
1066
|
-
const excludePatterns = [
|
|
1067
|
-
...config.sync?.exclude || [],
|
|
1068
|
-
...options.exclude
|
|
1069
|
-
];
|
|
1070
|
-
const sourceDir = process.cwd();
|
|
1071
|
-
const allFiles = await syncManager.listLocalFiles(sourceDir);
|
|
1072
|
-
const targetFiles = allFiles.filter((file) => {
|
|
1073
|
-
for (const pattern of excludePatterns) {
|
|
1074
|
-
const regex = new RegExp("^" + pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*") + "$");
|
|
1075
|
-
if (regex.test(file.path)) {
|
|
1076
|
-
return false;
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
for (const pattern of includePatterns) {
|
|
1080
|
-
const regex = new RegExp("^" + pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*") + "$");
|
|
1081
|
-
if (regex.test(file.path)) {
|
|
1082
|
-
return true;
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
return false;
|
|
1086
|
-
});
|
|
1087
|
-
const syncOptions = {
|
|
1088
|
-
direction,
|
|
1089
|
-
dryRun: options.dryRun,
|
|
1090
|
-
force: options.force,
|
|
1091
|
-
include: includePatterns,
|
|
1092
|
-
exclude: excludePatterns
|
|
1093
|
-
};
|
|
1094
|
-
const plan = await syncManager.createPlan(
|
|
1095
|
-
config.organization,
|
|
1096
|
-
projectName,
|
|
1097
|
-
sourceDir,
|
|
1098
|
-
targetFiles,
|
|
1099
|
-
syncOptions
|
|
1100
|
-
);
|
|
1101
|
-
if (plan.totalFiles === 0) {
|
|
1102
|
-
if (options.json) {
|
|
1103
|
-
console.log(JSON.stringify({
|
|
1104
|
-
project: projectName,
|
|
1105
|
-
organization: config.organization,
|
|
1106
|
-
files: [],
|
|
1107
|
-
synced: 0
|
|
1108
|
-
}, null, 2));
|
|
1109
|
-
} else {
|
|
1110
|
-
console.log(chalk6__default.default.yellow("No files to sync."));
|
|
1111
|
-
}
|
|
1112
|
-
return;
|
|
1113
|
-
}
|
|
1114
|
-
if (options.json) {
|
|
1115
|
-
const output = {
|
|
1116
|
-
project: projectName,
|
|
1117
|
-
organization: config.organization,
|
|
1118
|
-
environment: options.env,
|
|
1119
|
-
branch: targetBranch,
|
|
1120
|
-
direction,
|
|
1121
|
-
dryRun: options.dryRun || false,
|
|
1122
|
-
plan: {
|
|
1123
|
-
totalFiles: plan.totalFiles,
|
|
1124
|
-
totalBytes: plan.totalBytes,
|
|
1125
|
-
estimatedTime: plan.estimatedTime,
|
|
1126
|
-
conflicts: plan.conflicts.length,
|
|
1127
|
-
skipped: plan.skipped.length
|
|
1128
|
-
},
|
|
1129
|
-
files: plan.files.map((f) => ({
|
|
1130
|
-
path: f.path,
|
|
1131
|
-
operation: f.operation,
|
|
1132
|
-
size: f.size
|
|
1133
|
-
}))
|
|
1163
|
+
async function checkConfiguration() {
|
|
1164
|
+
const configPath = path3__namespace.join(process.cwd(), ".fractary", "codex.yaml");
|
|
1165
|
+
const legacyConfigPath = path3__namespace.join(process.cwd(), ".fractary", "plugins", "codex", "config.json");
|
|
1166
|
+
try {
|
|
1167
|
+
if (!await fileExists3(configPath)) {
|
|
1168
|
+
if (await fileExists3(legacyConfigPath)) {
|
|
1169
|
+
return {
|
|
1170
|
+
name: "Configuration",
|
|
1171
|
+
status: "warn",
|
|
1172
|
+
message: "Legacy JSON configuration detected",
|
|
1173
|
+
details: 'Run "fractary codex migrate" to upgrade to YAML format'
|
|
1134
1174
|
};
|
|
1135
|
-
if (options.dryRun) {
|
|
1136
|
-
console.log(JSON.stringify(output, null, 2));
|
|
1137
|
-
return;
|
|
1138
|
-
}
|
|
1139
|
-
const result2 = await syncManager.executePlan(plan, syncOptions);
|
|
1140
|
-
console.log(JSON.stringify({
|
|
1141
|
-
...output,
|
|
1142
|
-
result: {
|
|
1143
|
-
success: result2.success,
|
|
1144
|
-
synced: result2.synced,
|
|
1145
|
-
failed: result2.failed,
|
|
1146
|
-
skipped: result2.skipped,
|
|
1147
|
-
duration: result2.duration,
|
|
1148
|
-
errors: result2.errors
|
|
1149
|
-
}
|
|
1150
|
-
}, null, 2));
|
|
1151
|
-
return;
|
|
1152
|
-
}
|
|
1153
|
-
console.log(chalk6__default.default.bold("Sync Plan\n"));
|
|
1154
|
-
console.log(` Project: ${chalk6__default.default.cyan(projectName)}`);
|
|
1155
|
-
console.log(` Organization: ${chalk6__default.default.cyan(config.organization)}`);
|
|
1156
|
-
console.log(` Environment: ${chalk6__default.default.cyan(options.env)} (${targetBranch})`);
|
|
1157
|
-
console.log(` Direction: ${chalk6__default.default.cyan(direction)}`);
|
|
1158
|
-
console.log(` Files: ${chalk6__default.default.cyan(plan.totalFiles.toString())}`);
|
|
1159
|
-
console.log(` Total size: ${chalk6__default.default.cyan(formatBytes(plan.totalBytes))}`);
|
|
1160
|
-
if (plan.estimatedTime) {
|
|
1161
|
-
console.log(` Est. time: ${chalk6__default.default.dim(formatDuration(plan.estimatedTime))}`);
|
|
1162
|
-
}
|
|
1163
|
-
console.log("");
|
|
1164
|
-
if (plan.conflicts.length > 0) {
|
|
1165
|
-
console.log(chalk6__default.default.yellow(`\u26A0 ${plan.conflicts.length} conflicts detected:`));
|
|
1166
|
-
for (const conflict of plan.conflicts.slice(0, 5)) {
|
|
1167
|
-
console.log(chalk6__default.default.yellow(` \u2022 ${conflict.path}`));
|
|
1168
|
-
}
|
|
1169
|
-
if (plan.conflicts.length > 5) {
|
|
1170
|
-
console.log(chalk6__default.default.dim(` ... and ${plan.conflicts.length - 5} more`));
|
|
1171
|
-
}
|
|
1172
|
-
console.log("");
|
|
1173
|
-
}
|
|
1174
|
-
if (plan.skipped.length > 0) {
|
|
1175
|
-
console.log(chalk6__default.default.dim(`${plan.skipped.length} files skipped (no changes)`));
|
|
1176
|
-
console.log("");
|
|
1177
|
-
}
|
|
1178
|
-
if (options.dryRun) {
|
|
1179
|
-
console.log(chalk6__default.default.blue("Dry run - would sync:\n"));
|
|
1180
|
-
const filesToShow = plan.files.slice(0, 10);
|
|
1181
|
-
for (const file of filesToShow) {
|
|
1182
|
-
const arrow = direction === "to-codex" ? "\u2192" : direction === "from-codex" ? "\u2190" : "\u2194";
|
|
1183
|
-
const opColor = file.operation === "create" ? chalk6__default.default.green : file.operation === "update" ? chalk6__default.default.yellow : chalk6__default.default.dim;
|
|
1184
|
-
console.log(
|
|
1185
|
-
chalk6__default.default.dim(` ${arrow}`),
|
|
1186
|
-
opColor(file.operation.padEnd(7)),
|
|
1187
|
-
file.path,
|
|
1188
|
-
chalk6__default.default.dim(`(${formatBytes(file.size || 0)})`)
|
|
1189
|
-
);
|
|
1190
|
-
}
|
|
1191
|
-
if (plan.files.length > 10) {
|
|
1192
|
-
console.log(chalk6__default.default.dim(` ... and ${plan.files.length - 10} more files`));
|
|
1193
|
-
}
|
|
1194
|
-
console.log(chalk6__default.default.dim(`
|
|
1195
|
-
Total: ${plan.totalFiles} files (${formatBytes(plan.totalBytes)})`));
|
|
1196
|
-
console.log(chalk6__default.default.dim("Run without --dry-run to execute sync."));
|
|
1197
|
-
return;
|
|
1198
|
-
}
|
|
1199
|
-
console.log(chalk6__default.default.blue("Syncing...\n"));
|
|
1200
|
-
const startTime = Date.now();
|
|
1201
|
-
const result = await syncManager.executePlan(plan, syncOptions);
|
|
1202
|
-
const duration = Date.now() - startTime;
|
|
1203
|
-
console.log("");
|
|
1204
|
-
if (result.success) {
|
|
1205
|
-
console.log(chalk6__default.default.green(`\u2713 Sync completed successfully`));
|
|
1206
|
-
console.log(chalk6__default.default.dim(` Synced: ${result.synced} files`));
|
|
1207
|
-
if (result.skipped > 0) {
|
|
1208
|
-
console.log(chalk6__default.default.dim(` Skipped: ${result.skipped} files`));
|
|
1209
|
-
}
|
|
1210
|
-
console.log(chalk6__default.default.dim(` Duration: ${formatDuration(duration)}`));
|
|
1211
|
-
} else {
|
|
1212
|
-
console.log(chalk6__default.default.yellow(`\u26A0 Sync completed with errors`));
|
|
1213
|
-
console.log(chalk6__default.default.green(` Synced: ${result.synced} files`));
|
|
1214
|
-
console.log(chalk6__default.default.red(` Failed: ${result.failed} files`));
|
|
1215
|
-
if (result.skipped > 0) {
|
|
1216
|
-
console.log(chalk6__default.default.dim(` Skipped: ${result.skipped} files`));
|
|
1217
|
-
}
|
|
1218
|
-
if (result.errors.length > 0) {
|
|
1219
|
-
console.log("");
|
|
1220
|
-
console.log(chalk6__default.default.red("Errors:"));
|
|
1221
|
-
for (const error of result.errors.slice(0, 5)) {
|
|
1222
|
-
console.log(chalk6__default.default.red(` \u2022 ${error.path}: ${error.error}`));
|
|
1223
|
-
}
|
|
1224
|
-
if (result.errors.length > 5) {
|
|
1225
|
-
console.log(chalk6__default.default.dim(` ... and ${result.errors.length - 5} more errors`));
|
|
1226
|
-
}
|
|
1227
|
-
}
|
|
1228
1175
|
}
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1176
|
+
return {
|
|
1177
|
+
name: "Configuration",
|
|
1178
|
+
status: "fail",
|
|
1179
|
+
message: "No configuration found",
|
|
1180
|
+
details: 'Run "fractary codex init" to create configuration'
|
|
1181
|
+
};
|
|
1232
1182
|
}
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
name: repo.name,
|
|
1258
|
-
url: repo.url,
|
|
1259
|
-
defaultBranch: repo.defaultBranchRef?.name || "main"
|
|
1260
|
-
}));
|
|
1183
|
+
const config = await readYamlConfig(configPath);
|
|
1184
|
+
if (!config.organization) {
|
|
1185
|
+
return {
|
|
1186
|
+
name: "Configuration",
|
|
1187
|
+
status: "warn",
|
|
1188
|
+
message: "No organization configured",
|
|
1189
|
+
details: "Organization slug is required"
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
const providerCount = config.storage?.length || 0;
|
|
1193
|
+
if (providerCount === 0) {
|
|
1194
|
+
return {
|
|
1195
|
+
name: "Configuration",
|
|
1196
|
+
status: "warn",
|
|
1197
|
+
message: "No storage providers configured",
|
|
1198
|
+
details: "At least one storage provider is recommended"
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
return {
|
|
1202
|
+
name: "Configuration",
|
|
1203
|
+
status: "pass",
|
|
1204
|
+
message: "Valid YAML configuration",
|
|
1205
|
+
details: `Organization: ${config.organization}, ${providerCount} storage provider(s)`
|
|
1206
|
+
};
|
|
1261
1207
|
} catch (error) {
|
|
1262
|
-
|
|
1208
|
+
return {
|
|
1209
|
+
name: "Configuration",
|
|
1210
|
+
status: "fail",
|
|
1211
|
+
message: "Invalid configuration",
|
|
1212
|
+
details: error.message
|
|
1213
|
+
};
|
|
1263
1214
|
}
|
|
1264
1215
|
}
|
|
1265
|
-
function
|
|
1266
|
-
|
|
1267
|
-
const
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1216
|
+
async function checkSDKClient() {
|
|
1217
|
+
try {
|
|
1218
|
+
const client = await getClient();
|
|
1219
|
+
const organization = client.getOrganization();
|
|
1220
|
+
return {
|
|
1221
|
+
name: "SDK Client",
|
|
1222
|
+
status: "pass",
|
|
1223
|
+
message: "CodexClient initialized successfully",
|
|
1224
|
+
details: `Organization: ${organization}`
|
|
1225
|
+
};
|
|
1226
|
+
} catch (error) {
|
|
1227
|
+
return {
|
|
1228
|
+
name: "SDK Client",
|
|
1229
|
+
status: "fail",
|
|
1230
|
+
message: "Failed to initialize CodexClient",
|
|
1231
|
+
details: error.message
|
|
1232
|
+
};
|
|
1271
1233
|
}
|
|
1272
|
-
return false;
|
|
1273
1234
|
}
|
|
1274
|
-
async function
|
|
1275
|
-
const startTime = Date.now();
|
|
1235
|
+
async function checkCache() {
|
|
1276
1236
|
try {
|
|
1277
|
-
const
|
|
1278
|
-
const
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
}
|
|
1287
|
-
const
|
|
1288
|
-
|
|
1289
|
-
"specs/**/*.md",
|
|
1290
|
-
".fractary/standards/**",
|
|
1291
|
-
".fractary/templates/**"
|
|
1292
|
-
];
|
|
1293
|
-
const allFiles = await syncManager.listLocalFiles(repoDir);
|
|
1294
|
-
const targetFiles = allFiles.filter((file) => {
|
|
1295
|
-
for (const pattern of includePatterns) {
|
|
1296
|
-
const regex = new RegExp("^" + pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*") + "$");
|
|
1297
|
-
if (regex.test(file.path)) {
|
|
1298
|
-
return true;
|
|
1299
|
-
}
|
|
1300
|
-
}
|
|
1301
|
-
return false;
|
|
1302
|
-
});
|
|
1303
|
-
const plan = await syncManager.createPlan(
|
|
1304
|
-
config.organization,
|
|
1305
|
-
repo.name,
|
|
1306
|
-
repoDir,
|
|
1307
|
-
targetFiles,
|
|
1308
|
-
syncOptions
|
|
1309
|
-
);
|
|
1310
|
-
if (plan.totalFiles === 0) {
|
|
1237
|
+
const client = await getClient();
|
|
1238
|
+
const stats = await client.getCacheStats();
|
|
1239
|
+
if (stats.entryCount === 0) {
|
|
1240
|
+
return {
|
|
1241
|
+
name: "Cache",
|
|
1242
|
+
status: "warn",
|
|
1243
|
+
message: "Cache is empty",
|
|
1244
|
+
details: "Fetch some documents to populate cache"
|
|
1245
|
+
};
|
|
1246
|
+
}
|
|
1247
|
+
const healthPercent = stats.entryCount > 0 ? stats.freshCount / stats.entryCount * 100 : 100;
|
|
1248
|
+
if (healthPercent < 50) {
|
|
1311
1249
|
return {
|
|
1312
|
-
|
|
1313
|
-
status: "
|
|
1314
|
-
|
|
1315
|
-
|
|
1250
|
+
name: "Cache",
|
|
1251
|
+
status: "warn",
|
|
1252
|
+
message: `${stats.entryCount} entries (${healthPercent.toFixed(0)}% fresh)`,
|
|
1253
|
+
details: `${stats.expiredCount} expired, ${stats.staleCount} stale`
|
|
1316
1254
|
};
|
|
1317
1255
|
}
|
|
1318
|
-
const result = await syncManager.executePlan(plan, syncOptions);
|
|
1319
1256
|
return {
|
|
1320
|
-
|
|
1321
|
-
status:
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
error: result.success ? void 0 : `${result.failed} files failed`
|
|
1257
|
+
name: "Cache",
|
|
1258
|
+
status: "pass",
|
|
1259
|
+
message: `${stats.entryCount} entries (${healthPercent.toFixed(0)}% fresh)`,
|
|
1260
|
+
details: `${formatSize4(stats.totalSize)} total`
|
|
1325
1261
|
};
|
|
1326
1262
|
} catch (error) {
|
|
1327
1263
|
return {
|
|
1328
|
-
|
|
1329
|
-
status: "
|
|
1330
|
-
|
|
1331
|
-
|
|
1264
|
+
name: "Cache",
|
|
1265
|
+
status: "fail",
|
|
1266
|
+
message: "Cache check failed",
|
|
1267
|
+
details: error.message
|
|
1332
1268
|
};
|
|
1333
1269
|
}
|
|
1334
1270
|
}
|
|
1335
|
-
function
|
|
1336
|
-
const
|
|
1337
|
-
|
|
1271
|
+
async function checkStorage() {
|
|
1272
|
+
const configPath = path3__namespace.join(process.cwd(), ".fractary", "codex.yaml");
|
|
1273
|
+
try {
|
|
1274
|
+
const config = await readYamlConfig(configPath);
|
|
1275
|
+
const providers = config.storage || [];
|
|
1276
|
+
if (providers.length === 0) {
|
|
1277
|
+
return {
|
|
1278
|
+
name: "Storage",
|
|
1279
|
+
status: "warn",
|
|
1280
|
+
message: "No storage providers configured",
|
|
1281
|
+
details: "Configure at least one provider in .fractary/codex.yaml"
|
|
1282
|
+
};
|
|
1283
|
+
}
|
|
1284
|
+
const providerTypes = providers.map((p) => p.type).join(", ");
|
|
1285
|
+
const hasGitHub = providers.some((p) => p.type === "github");
|
|
1286
|
+
if (hasGitHub && !process.env.GITHUB_TOKEN) {
|
|
1287
|
+
return {
|
|
1288
|
+
name: "Storage",
|
|
1289
|
+
status: "warn",
|
|
1290
|
+
message: `${providers.length} provider(s): ${providerTypes}`,
|
|
1291
|
+
details: "GITHUB_TOKEN not set (required for GitHub provider)"
|
|
1292
|
+
};
|
|
1293
|
+
}
|
|
1294
|
+
return {
|
|
1295
|
+
name: "Storage",
|
|
1296
|
+
status: "pass",
|
|
1297
|
+
message: `${providers.length} provider(s): ${providerTypes}`,
|
|
1298
|
+
details: "All configured providers available"
|
|
1299
|
+
};
|
|
1300
|
+
} catch (error) {
|
|
1301
|
+
return {
|
|
1302
|
+
name: "Storage",
|
|
1303
|
+
status: "fail",
|
|
1304
|
+
message: "Storage check failed",
|
|
1305
|
+
details: error.message
|
|
1306
|
+
};
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
async function checkTypes() {
|
|
1310
|
+
try {
|
|
1311
|
+
const client = await getClient();
|
|
1312
|
+
const registry = client.getTypeRegistry();
|
|
1313
|
+
const allTypes = registry.list();
|
|
1314
|
+
const builtinCount = allTypes.filter((t) => registry.isBuiltIn(t.name)).length;
|
|
1315
|
+
const customCount = allTypes.length - builtinCount;
|
|
1316
|
+
return {
|
|
1317
|
+
name: "Type Registry",
|
|
1318
|
+
status: "pass",
|
|
1319
|
+
message: `${allTypes.length} types registered`,
|
|
1320
|
+
details: `${builtinCount} built-in, ${customCount} custom`
|
|
1321
|
+
};
|
|
1322
|
+
} catch (error) {
|
|
1323
|
+
return {
|
|
1324
|
+
name: "Type Registry",
|
|
1325
|
+
status: "fail",
|
|
1326
|
+
message: "Type registry check failed",
|
|
1327
|
+
details: error.message
|
|
1328
|
+
};
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
function formatSize4(bytes) {
|
|
1332
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
1333
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
1334
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
1335
|
+
}
|
|
1336
|
+
function healthCommand() {
|
|
1337
|
+
const cmd = new commander.Command("health");
|
|
1338
|
+
cmd.description("Run diagnostics on codex setup").option("--json", "Output as JSON").action(async (options) => {
|
|
1339
|
+
try {
|
|
1340
|
+
const checks = [];
|
|
1341
|
+
checks.push(await checkConfiguration());
|
|
1342
|
+
checks.push(await checkSDKClient());
|
|
1343
|
+
checks.push(await checkCache());
|
|
1344
|
+
checks.push(await checkStorage());
|
|
1345
|
+
checks.push(await checkTypes());
|
|
1346
|
+
const passed = checks.filter((c) => c.status === "pass").length;
|
|
1347
|
+
const warned = checks.filter((c) => c.status === "warn").length;
|
|
1348
|
+
const failed = checks.filter((c) => c.status === "fail").length;
|
|
1349
|
+
if (options.json) {
|
|
1350
|
+
console.log(JSON.stringify({
|
|
1351
|
+
summary: {
|
|
1352
|
+
total: checks.length,
|
|
1353
|
+
passed,
|
|
1354
|
+
warned,
|
|
1355
|
+
failed,
|
|
1356
|
+
healthy: failed === 0
|
|
1357
|
+
},
|
|
1358
|
+
checks
|
|
1359
|
+
}, null, 2));
|
|
1360
|
+
return;
|
|
1361
|
+
}
|
|
1362
|
+
console.log(chalk8__default.default.bold("Codex Health Check\n"));
|
|
1363
|
+
for (const check of checks) {
|
|
1364
|
+
const icon = check.status === "pass" ? chalk8__default.default.green("\u2713") : check.status === "warn" ? chalk8__default.default.yellow("\u26A0") : chalk8__default.default.red("\u2717");
|
|
1365
|
+
const statusColor = check.status === "pass" ? chalk8__default.default.green : check.status === "warn" ? chalk8__default.default.yellow : chalk8__default.default.red;
|
|
1366
|
+
console.log(`${icon} ${chalk8__default.default.bold(check.name)}`);
|
|
1367
|
+
console.log(` ${statusColor(check.message)}`);
|
|
1368
|
+
if (check.details) {
|
|
1369
|
+
console.log(` ${chalk8__default.default.dim(check.details)}`);
|
|
1370
|
+
}
|
|
1371
|
+
console.log("");
|
|
1372
|
+
}
|
|
1373
|
+
console.log(chalk8__default.default.dim("\u2500".repeat(60)));
|
|
1374
|
+
const overallStatus = failed > 0 ? chalk8__default.default.red("UNHEALTHY") : warned > 0 ? chalk8__default.default.yellow("DEGRADED") : chalk8__default.default.green("HEALTHY");
|
|
1375
|
+
console.log(`Status: ${overallStatus}`);
|
|
1376
|
+
console.log(chalk8__default.default.dim(`${passed} passed, ${warned} warnings, ${failed} failed`));
|
|
1377
|
+
if (failed > 0 || warned > 0) {
|
|
1378
|
+
console.log("");
|
|
1379
|
+
console.log(chalk8__default.default.dim("Run checks individually for more details:"));
|
|
1380
|
+
console.log(chalk8__default.default.dim(" fractary codex cache stats"));
|
|
1381
|
+
console.log(chalk8__default.default.dim(" fractary codex types list"));
|
|
1382
|
+
}
|
|
1383
|
+
if (failed > 0) {
|
|
1384
|
+
process.exit(1);
|
|
1385
|
+
}
|
|
1386
|
+
} catch (error) {
|
|
1387
|
+
console.error(chalk8__default.default.red("Error:"), error.message);
|
|
1388
|
+
process.exit(1);
|
|
1389
|
+
}
|
|
1390
|
+
});
|
|
1391
|
+
return cmd;
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
// src/commands/cache/index.ts
|
|
1395
|
+
function cacheCommand() {
|
|
1396
|
+
const cmd = new commander.Command("cache");
|
|
1397
|
+
cmd.description("Manage the codex document cache");
|
|
1398
|
+
cmd.addCommand(cacheListCommand());
|
|
1399
|
+
cmd.addCommand(cacheClearCommand());
|
|
1400
|
+
cmd.addCommand(cacheStatsCommand());
|
|
1401
|
+
cmd.addCommand(healthCommand());
|
|
1402
|
+
return cmd;
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
// src/commands/sync.ts
|
|
1406
|
+
init_cjs_shims();
|
|
1407
|
+
init_migrate_config();
|
|
1408
|
+
function getEnvironmentBranch(config, env) {
|
|
1409
|
+
const envMap = config.sync?.environments || {
|
|
1410
|
+
dev: "develop",
|
|
1411
|
+
test: "test",
|
|
1412
|
+
staging: "staging",
|
|
1413
|
+
prod: "main"
|
|
1414
|
+
};
|
|
1415
|
+
return envMap[env] || env;
|
|
1416
|
+
}
|
|
1417
|
+
function formatBytes(bytes) {
|
|
1418
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
1419
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
1420
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
1421
|
+
}
|
|
1422
|
+
function formatDuration(ms) {
|
|
1423
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
1424
|
+
return `${(ms / 1e3).toFixed(1)}s`;
|
|
1425
|
+
}
|
|
1426
|
+
function syncCommand() {
|
|
1427
|
+
const cmd = new commander.Command("sync");
|
|
1428
|
+
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) => {
|
|
1338
1429
|
try {
|
|
1339
|
-
const configPath =
|
|
1430
|
+
const configPath = path3__namespace.join(process.cwd(), ".fractary", "codex.yaml");
|
|
1340
1431
|
let config;
|
|
1341
1432
|
try {
|
|
1342
1433
|
config = await readYamlConfig(configPath);
|
|
1343
1434
|
} catch (error) {
|
|
1344
|
-
console.error(
|
|
1345
|
-
console.log(
|
|
1435
|
+
console.error(chalk8__default.default.red("Error:"), "Codex not initialized.");
|
|
1436
|
+
console.log(chalk8__default.default.dim('Run "fractary codex init" first.'));
|
|
1437
|
+
process.exit(1);
|
|
1438
|
+
}
|
|
1439
|
+
const { createSyncManager, createLocalStorage, detectCurrentProject } = await import('@fractary/codex');
|
|
1440
|
+
let projectName = name;
|
|
1441
|
+
if (!projectName) {
|
|
1442
|
+
const detected = detectCurrentProject();
|
|
1443
|
+
projectName = detected.project || void 0;
|
|
1444
|
+
}
|
|
1445
|
+
if (!projectName) {
|
|
1446
|
+
console.error(chalk8__default.default.red("Error:"), "Could not determine project name.");
|
|
1447
|
+
console.log(chalk8__default.default.dim("Provide project name as argument or run from a git repository."));
|
|
1346
1448
|
process.exit(1);
|
|
1347
1449
|
}
|
|
1348
1450
|
const validDirections = ["to-codex", "from-codex", "bidirectional"];
|
|
1349
1451
|
if (!validDirections.includes(options.direction)) {
|
|
1350
|
-
console.error(
|
|
1351
|
-
console.log(
|
|
1452
|
+
console.error(chalk8__default.default.red("Error:"), `Invalid direction: ${options.direction}`);
|
|
1453
|
+
console.log(chalk8__default.default.dim("Valid options: to-codex, from-codex, bidirectional"));
|
|
1352
1454
|
process.exit(1);
|
|
1353
1455
|
}
|
|
1354
1456
|
const direction = options.direction;
|
|
1355
|
-
const
|
|
1356
|
-
const
|
|
1457
|
+
const targetBranch = getEnvironmentBranch(config, options.env);
|
|
1458
|
+
const localStorage = createLocalStorage({
|
|
1459
|
+
baseDir: process.cwd()
|
|
1460
|
+
});
|
|
1461
|
+
const syncManager = createSyncManager({
|
|
1462
|
+
localStorage,
|
|
1463
|
+
config: config.sync,
|
|
1464
|
+
manifestPath: path3__namespace.join(process.cwd(), ".fractary", ".codex-sync-manifest.json")
|
|
1465
|
+
});
|
|
1466
|
+
const defaultPatterns = [
|
|
1467
|
+
"docs/**/*.md",
|
|
1468
|
+
"specs/**/*.md",
|
|
1469
|
+
".fractary/standards/**",
|
|
1470
|
+
".fractary/templates/**"
|
|
1471
|
+
];
|
|
1472
|
+
const includePatterns = options.include.length > 0 ? options.include : defaultPatterns;
|
|
1357
1473
|
const excludePatterns = [
|
|
1358
1474
|
...config.sync?.exclude || [],
|
|
1359
1475
|
...options.exclude
|
|
1360
1476
|
];
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1477
|
+
const sourceDir = process.cwd();
|
|
1478
|
+
const allFiles = await syncManager.listLocalFiles(sourceDir);
|
|
1479
|
+
const targetFiles = allFiles.filter((file) => {
|
|
1480
|
+
for (const pattern of excludePatterns) {
|
|
1481
|
+
const regex = new RegExp("^" + pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*") + "$");
|
|
1482
|
+
if (regex.test(file.path)) {
|
|
1483
|
+
return false;
|
|
1484
|
+
}
|
|
1369
1485
|
}
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1486
|
+
for (const pattern of includePatterns) {
|
|
1487
|
+
const regex = new RegExp("^" + pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*") + "$");
|
|
1488
|
+
if (regex.test(file.path)) {
|
|
1489
|
+
return true;
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
return false;
|
|
1493
|
+
});
|
|
1494
|
+
const syncOptions = {
|
|
1495
|
+
direction,
|
|
1496
|
+
dryRun: options.dryRun,
|
|
1497
|
+
force: options.force,
|
|
1498
|
+
include: includePatterns,
|
|
1499
|
+
exclude: excludePatterns
|
|
1500
|
+
};
|
|
1501
|
+
let plan;
|
|
1502
|
+
let routingScan;
|
|
1503
|
+
if (direction === "from-codex") {
|
|
1504
|
+
const codexRepoPath = config.cacheDir || path3__namespace.join(process.cwd(), ".fractary", "codex-cache");
|
|
1377
1505
|
if (options.json) {
|
|
1378
|
-
console.log(JSON.stringify({
|
|
1506
|
+
console.log(JSON.stringify({
|
|
1507
|
+
info: "Routing-aware sync: scanning entire codex repository for files targeting this project",
|
|
1508
|
+
codexPath: codexRepoPath
|
|
1509
|
+
}, null, 2));
|
|
1379
1510
|
} else {
|
|
1380
|
-
console.
|
|
1511
|
+
console.log(chalk8__default.default.blue("\u2139 Using routing-aware sync"));
|
|
1512
|
+
console.log(chalk8__default.default.dim(" Scanning entire codex for files routing to this project...\n"));
|
|
1381
1513
|
}
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1514
|
+
const planWithRouting = await syncManager.createRoutingAwarePlan(
|
|
1515
|
+
config.organization,
|
|
1516
|
+
projectName,
|
|
1517
|
+
codexRepoPath,
|
|
1518
|
+
syncOptions
|
|
1519
|
+
);
|
|
1520
|
+
plan = planWithRouting;
|
|
1521
|
+
routingScan = planWithRouting.routingScan;
|
|
1522
|
+
} else {
|
|
1523
|
+
plan = await syncManager.createPlan(
|
|
1524
|
+
config.organization,
|
|
1525
|
+
projectName,
|
|
1526
|
+
sourceDir,
|
|
1527
|
+
targetFiles,
|
|
1528
|
+
syncOptions
|
|
1529
|
+
);
|
|
1389
1530
|
}
|
|
1390
|
-
if (
|
|
1531
|
+
if (plan.totalFiles === 0) {
|
|
1391
1532
|
if (options.json) {
|
|
1392
1533
|
console.log(JSON.stringify({
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
dryRun: true,
|
|
1398
|
-
repos: {
|
|
1399
|
-
total: repos.length,
|
|
1400
|
-
eligible: eligibleRepos.map((r) => r.name),
|
|
1401
|
-
excluded: excludedRepos.map((r) => r.name)
|
|
1402
|
-
}
|
|
1534
|
+
project: projectName,
|
|
1535
|
+
organization: config.organization,
|
|
1536
|
+
files: [],
|
|
1537
|
+
synced: 0
|
|
1403
1538
|
}, null, 2));
|
|
1404
1539
|
} else {
|
|
1405
|
-
console.log(
|
|
1406
|
-
for (const repo of eligibleRepos) {
|
|
1407
|
-
console.log(chalk6__default.default.green(" \u2713"), repo.name);
|
|
1408
|
-
}
|
|
1409
|
-
if (excludedRepos.length > 0) {
|
|
1410
|
-
console.log("");
|
|
1411
|
-
console.log(chalk6__default.default.dim("Excluded:"));
|
|
1412
|
-
for (const repo of excludedRepos) {
|
|
1413
|
-
console.log(chalk6__default.default.dim(` - ${repo.name}`));
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
console.log(chalk6__default.default.dim(`
|
|
1417
|
-
Total: ${eligibleRepos.length} repos would be synced`));
|
|
1418
|
-
console.log(chalk6__default.default.dim("Run without --dry-run to execute sync."));
|
|
1540
|
+
console.log(chalk8__default.default.yellow("No files to sync."));
|
|
1419
1541
|
}
|
|
1420
1542
|
return;
|
|
1421
1543
|
}
|
|
1422
|
-
if (!options.json) {
|
|
1423
|
-
console.log(chalk6__default.default.blue("Syncing repositories...\n"));
|
|
1424
|
-
}
|
|
1425
|
-
const results = [];
|
|
1426
|
-
const syncOptions = {
|
|
1427
|
-
direction,
|
|
1428
|
-
dryRun: false,
|
|
1429
|
-
force: false
|
|
1430
|
-
};
|
|
1431
|
-
for (let i = 0; i < eligibleRepos.length; i += options.parallel) {
|
|
1432
|
-
const batch = eligibleRepos.slice(i, i + options.parallel);
|
|
1433
|
-
const batchResults = await Promise.all(
|
|
1434
|
-
batch.map((repo) => syncRepository(repo, config, direction, syncOptions))
|
|
1435
|
-
);
|
|
1436
|
-
for (const result of batchResults) {
|
|
1437
|
-
results.push(result);
|
|
1438
|
-
if (!options.json) {
|
|
1439
|
-
if (result.status === "success") {
|
|
1440
|
-
console.log(
|
|
1441
|
-
chalk6__default.default.green(" \u2713"),
|
|
1442
|
-
result.repo,
|
|
1443
|
-
chalk6__default.default.dim(`(${result.filesSynced} files in ${result.duration}ms)`)
|
|
1444
|
-
);
|
|
1445
|
-
} else if (result.status === "skipped") {
|
|
1446
|
-
console.log(
|
|
1447
|
-
chalk6__default.default.dim(" -"),
|
|
1448
|
-
result.repo,
|
|
1449
|
-
chalk6__default.default.dim("(no files to sync)")
|
|
1450
|
-
);
|
|
1451
|
-
} else if (result.status === "error") {
|
|
1452
|
-
console.log(
|
|
1453
|
-
chalk6__default.default.red(" \u2717"),
|
|
1454
|
-
result.repo,
|
|
1455
|
-
chalk6__default.default.red(`(${result.error})`)
|
|
1456
|
-
);
|
|
1457
|
-
}
|
|
1458
|
-
}
|
|
1459
|
-
}
|
|
1460
|
-
}
|
|
1461
|
-
const successful = results.filter((r) => r.status === "success");
|
|
1462
|
-
const skipped = results.filter((r) => r.status === "skipped");
|
|
1463
|
-
const failed = results.filter((r) => r.status === "error");
|
|
1464
|
-
const totalFiles = successful.reduce((sum, r) => sum + (r.filesSynced || 0), 0);
|
|
1465
1544
|
if (options.json) {
|
|
1466
|
-
|
|
1467
|
-
|
|
1545
|
+
const output = {
|
|
1546
|
+
project: projectName,
|
|
1547
|
+
organization: config.organization,
|
|
1468
1548
|
environment: options.env,
|
|
1469
1549
|
branch: targetBranch,
|
|
1470
1550
|
direction,
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1551
|
+
dryRun: options.dryRun || false,
|
|
1552
|
+
plan: {
|
|
1553
|
+
totalFiles: plan.totalFiles,
|
|
1554
|
+
totalBytes: plan.totalBytes,
|
|
1555
|
+
estimatedTime: plan.estimatedTime,
|
|
1556
|
+
conflicts: plan.conflicts.length,
|
|
1557
|
+
skipped: plan.skipped.length
|
|
1558
|
+
},
|
|
1559
|
+
files: plan.files.map((f) => ({
|
|
1560
|
+
path: f.path,
|
|
1561
|
+
operation: f.operation,
|
|
1562
|
+
size: f.size
|
|
1563
|
+
}))
|
|
1564
|
+
};
|
|
1565
|
+
if (options.dryRun) {
|
|
1566
|
+
console.log(JSON.stringify(output, null, 2));
|
|
1567
|
+
return;
|
|
1568
|
+
}
|
|
1569
|
+
const result2 = await syncManager.executePlan(plan, syncOptions);
|
|
1570
|
+
console.log(JSON.stringify({
|
|
1571
|
+
...output,
|
|
1572
|
+
result: {
|
|
1573
|
+
success: result2.success,
|
|
1574
|
+
synced: result2.synced,
|
|
1575
|
+
failed: result2.failed,
|
|
1576
|
+
skipped: result2.skipped,
|
|
1577
|
+
duration: result2.duration,
|
|
1578
|
+
errors: result2.errors
|
|
1478
1579
|
}
|
|
1479
1580
|
}, null, 2));
|
|
1480
|
-
|
|
1581
|
+
return;
|
|
1582
|
+
}
|
|
1583
|
+
console.log(chalk8__default.default.bold("Sync Plan\n"));
|
|
1584
|
+
console.log(` Project: ${chalk8__default.default.cyan(projectName)}`);
|
|
1585
|
+
console.log(` Organization: ${chalk8__default.default.cyan(config.organization)}`);
|
|
1586
|
+
console.log(` Environment: ${chalk8__default.default.cyan(options.env)} (${targetBranch})`);
|
|
1587
|
+
console.log(` Direction: ${chalk8__default.default.cyan(direction)}`);
|
|
1588
|
+
console.log(` Files: ${chalk8__default.default.cyan(plan.totalFiles.toString())}`);
|
|
1589
|
+
console.log(` Total size: ${chalk8__default.default.cyan(formatBytes(plan.totalBytes))}`);
|
|
1590
|
+
if (plan.estimatedTime) {
|
|
1591
|
+
console.log(` Est. time: ${chalk8__default.default.dim(formatDuration(plan.estimatedTime))}`);
|
|
1592
|
+
}
|
|
1593
|
+
if (routingScan) {
|
|
1481
1594
|
console.log("");
|
|
1482
|
-
console.log(
|
|
1483
|
-
|
|
1484
|
-
|
|
1595
|
+
console.log(chalk8__default.default.bold("Routing Statistics\n"));
|
|
1596
|
+
console.log(` Scanned: ${chalk8__default.default.cyan(routingScan.stats.totalScanned.toString())} files`);
|
|
1597
|
+
console.log(` Matched: ${chalk8__default.default.cyan(routingScan.stats.totalMatched.toString())} files`);
|
|
1598
|
+
console.log(` Source projects: ${chalk8__default.default.cyan(routingScan.stats.sourceProjects.length.toString())}`);
|
|
1599
|
+
if (routingScan.stats.sourceProjects.length > 0) {
|
|
1600
|
+
console.log(chalk8__default.default.dim(` ${routingScan.stats.sourceProjects.slice(0, 5).join(", ")}`));
|
|
1601
|
+
if (routingScan.stats.sourceProjects.length > 5) {
|
|
1602
|
+
console.log(chalk8__default.default.dim(` ... and ${routingScan.stats.sourceProjects.length - 5} more`));
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
console.log(` Scan time: ${chalk8__default.default.dim(formatDuration(routingScan.stats.durationMs))}`);
|
|
1606
|
+
}
|
|
1607
|
+
console.log("");
|
|
1608
|
+
if (plan.conflicts.length > 0) {
|
|
1609
|
+
console.log(chalk8__default.default.yellow(`\u26A0 ${plan.conflicts.length} conflicts detected:`));
|
|
1610
|
+
for (const conflict of plan.conflicts.slice(0, 5)) {
|
|
1611
|
+
console.log(chalk8__default.default.yellow(` \u2022 ${conflict.path}`));
|
|
1485
1612
|
}
|
|
1486
|
-
if (
|
|
1487
|
-
console.log(
|
|
1613
|
+
if (plan.conflicts.length > 5) {
|
|
1614
|
+
console.log(chalk8__default.default.dim(` ... and ${plan.conflicts.length - 5} more`));
|
|
1488
1615
|
}
|
|
1616
|
+
console.log("");
|
|
1489
1617
|
}
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
console.log(
|
|
1618
|
+
if (plan.skipped.length > 0) {
|
|
1619
|
+
console.log(chalk8__default.default.dim(`${plan.skipped.length} files skipped (no changes)`));
|
|
1620
|
+
console.log("");
|
|
1621
|
+
}
|
|
1622
|
+
if (options.dryRun) {
|
|
1623
|
+
console.log(chalk8__default.default.blue("Dry run - would sync:\n"));
|
|
1624
|
+
const filesToShow = plan.files.slice(0, 10);
|
|
1625
|
+
for (const file of filesToShow) {
|
|
1626
|
+
const arrow = direction === "to-codex" ? "\u2192" : direction === "from-codex" ? "\u2190" : "\u2194";
|
|
1627
|
+
const opColor = file.operation === "create" ? chalk8__default.default.green : file.operation === "update" ? chalk8__default.default.yellow : chalk8__default.default.dim;
|
|
1628
|
+
console.log(
|
|
1629
|
+
chalk8__default.default.dim(` ${arrow}`),
|
|
1630
|
+
opColor(file.operation.padEnd(7)),
|
|
1631
|
+
file.path,
|
|
1632
|
+
chalk8__default.default.dim(`(${formatBytes(file.size || 0)})`)
|
|
1633
|
+
);
|
|
1634
|
+
}
|
|
1635
|
+
if (plan.files.length > 10) {
|
|
1636
|
+
console.log(chalk8__default.default.dim(` ... and ${plan.files.length - 10} more files`));
|
|
1637
|
+
}
|
|
1638
|
+
console.log(chalk8__default.default.dim(`
|
|
1639
|
+
Total: ${plan.totalFiles} files (${formatBytes(plan.totalBytes)})`));
|
|
1640
|
+
console.log(chalk8__default.default.dim("Run without --dry-run to execute sync."));
|
|
1641
|
+
return;
|
|
1642
|
+
}
|
|
1643
|
+
console.log(chalk8__default.default.blue("Syncing...\n"));
|
|
1644
|
+
const startTime = Date.now();
|
|
1645
|
+
const result = await syncManager.executePlan(plan, syncOptions);
|
|
1646
|
+
const duration = Date.now() - startTime;
|
|
1647
|
+
console.log("");
|
|
1648
|
+
if (result.success) {
|
|
1649
|
+
console.log(chalk8__default.default.green(`\u2713 Sync completed successfully`));
|
|
1650
|
+
console.log(chalk8__default.default.dim(` Synced: ${result.synced} files`));
|
|
1651
|
+
if (result.skipped > 0) {
|
|
1652
|
+
console.log(chalk8__default.default.dim(` Skipped: ${result.skipped} files`));
|
|
1653
|
+
}
|
|
1654
|
+
console.log(chalk8__default.default.dim(` Duration: ${formatDuration(duration)}`));
|
|
1493
1655
|
} else {
|
|
1494
|
-
console.
|
|
1656
|
+
console.log(chalk8__default.default.yellow(`\u26A0 Sync completed with errors`));
|
|
1657
|
+
console.log(chalk8__default.default.green(` Synced: ${result.synced} files`));
|
|
1658
|
+
console.log(chalk8__default.default.red(` Failed: ${result.failed} files`));
|
|
1659
|
+
if (result.skipped > 0) {
|
|
1660
|
+
console.log(chalk8__default.default.dim(` Skipped: ${result.skipped} files`));
|
|
1661
|
+
}
|
|
1662
|
+
if (result.errors.length > 0) {
|
|
1663
|
+
console.log("");
|
|
1664
|
+
console.log(chalk8__default.default.red("Errors:"));
|
|
1665
|
+
for (const error of result.errors.slice(0, 5)) {
|
|
1666
|
+
console.log(chalk8__default.default.red(` \u2022 ${error.path}: ${error.error}`));
|
|
1667
|
+
}
|
|
1668
|
+
if (result.errors.length > 5) {
|
|
1669
|
+
console.log(chalk8__default.default.dim(` ... and ${result.errors.length - 5} more errors`));
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1495
1672
|
}
|
|
1673
|
+
} catch (error) {
|
|
1674
|
+
console.error(chalk8__default.default.red("Error:"), error.message);
|
|
1496
1675
|
process.exit(1);
|
|
1497
1676
|
}
|
|
1498
1677
|
});
|
|
1499
1678
|
return cmd;
|
|
1500
1679
|
}
|
|
1501
1680
|
|
|
1502
|
-
// src/commands/sync/index.ts
|
|
1503
|
-
function syncCommand() {
|
|
1504
|
-
const cmd = new commander.Command("sync");
|
|
1505
|
-
cmd.description("Synchronize with codex repository");
|
|
1506
|
-
cmd.addCommand(syncProjectCommand());
|
|
1507
|
-
cmd.addCommand(syncOrgCommand());
|
|
1508
|
-
return cmd;
|
|
1509
|
-
}
|
|
1510
|
-
|
|
1511
1681
|
// src/commands/types/index.ts
|
|
1512
1682
|
init_cjs_shims();
|
|
1513
1683
|
|
|
@@ -1553,35 +1723,35 @@ function typesListCommand() {
|
|
|
1553
1723
|
return;
|
|
1554
1724
|
}
|
|
1555
1725
|
if (types.length === 0) {
|
|
1556
|
-
console.log(
|
|
1726
|
+
console.log(chalk8__default.default.yellow("No types found."));
|
|
1557
1727
|
return;
|
|
1558
1728
|
}
|
|
1559
|
-
console.log(
|
|
1729
|
+
console.log(chalk8__default.default.bold("Artifact Types\n"));
|
|
1560
1730
|
const builtinTypes = types.filter((t) => registry.isBuiltIn(t.name));
|
|
1561
1731
|
const customTypes = types.filter((t) => !registry.isBuiltIn(t.name));
|
|
1562
1732
|
if (builtinTypes.length > 0 && !options.customOnly) {
|
|
1563
|
-
console.log(
|
|
1564
|
-
console.log(
|
|
1733
|
+
console.log(chalk8__default.default.bold("Built-in Types"));
|
|
1734
|
+
console.log(chalk8__default.default.dim("\u2500".repeat(70)));
|
|
1565
1735
|
for (const type of builtinTypes) {
|
|
1566
1736
|
const patternStr = type.patterns[0] || "";
|
|
1567
|
-
console.log(` ${
|
|
1568
|
-
console.log(` ${
|
|
1737
|
+
console.log(` ${chalk8__default.default.cyan(type.name.padEnd(12))} ${patternStr.padEnd(30)} ${chalk8__default.default.dim(`TTL: ${formatTtl(type.defaultTtl)}`)}`);
|
|
1738
|
+
console.log(` ${chalk8__default.default.dim(" ".repeat(12) + type.description)}`);
|
|
1569
1739
|
}
|
|
1570
1740
|
console.log("");
|
|
1571
1741
|
}
|
|
1572
1742
|
if (customTypes.length > 0 && !options.builtinOnly) {
|
|
1573
|
-
console.log(
|
|
1574
|
-
console.log(
|
|
1743
|
+
console.log(chalk8__default.default.bold("Custom Types"));
|
|
1744
|
+
console.log(chalk8__default.default.dim("\u2500".repeat(70)));
|
|
1575
1745
|
for (const type of customTypes) {
|
|
1576
1746
|
const patternStr = type.patterns[0] || "";
|
|
1577
|
-
console.log(` ${
|
|
1578
|
-
console.log(` ${
|
|
1747
|
+
console.log(` ${chalk8__default.default.green(type.name.padEnd(12))} ${patternStr.padEnd(30)} ${chalk8__default.default.dim(`TTL: ${formatTtl(type.defaultTtl)}`)}`);
|
|
1748
|
+
console.log(` ${chalk8__default.default.dim(" ".repeat(12) + type.description)}`);
|
|
1579
1749
|
}
|
|
1580
1750
|
console.log("");
|
|
1581
1751
|
}
|
|
1582
|
-
console.log(
|
|
1752
|
+
console.log(chalk8__default.default.dim(`Total: ${types.length} types (${builtinTypes.length} built-in, ${customTypes.length} custom)`));
|
|
1583
1753
|
} catch (error) {
|
|
1584
|
-
console.error(
|
|
1754
|
+
console.error(chalk8__default.default.red("Error:"), error.message);
|
|
1585
1755
|
process.exit(1);
|
|
1586
1756
|
}
|
|
1587
1757
|
});
|
|
@@ -1603,643 +1773,236 @@ function typesShowCommand() {
|
|
|
1603
1773
|
const client = await getClient();
|
|
1604
1774
|
const registry = client.getTypeRegistry();
|
|
1605
1775
|
const type = registry.get(name);
|
|
1606
|
-
if (!type) {
|
|
1607
|
-
console.error(
|
|
1608
|
-
console.log(
|
|
1609
|
-
process.exit(1);
|
|
1610
|
-
}
|
|
1611
|
-
const isBuiltin = registry.isBuiltIn(name);
|
|
1612
|
-
if (options.json) {
|
|
1613
|
-
console.log(JSON.stringify({
|
|
1614
|
-
name: type.name,
|
|
1615
|
-
builtin: isBuiltin,
|
|
1616
|
-
description: type.description,
|
|
1617
|
-
patterns: type.patterns,
|
|
1618
|
-
defaultTtl: type.defaultTtl,
|
|
1619
|
-
ttl: formatTtl2(type.defaultTtl),
|
|
1620
|
-
archiveAfterDays: type.archiveAfterDays,
|
|
1621
|
-
archiveStorage: type.archiveStorage,
|
|
1622
|
-
syncPatterns: type.syncPatterns,
|
|
1623
|
-
excludePatterns: type.excludePatterns
|
|
1624
|
-
}, null, 2));
|
|
1625
|
-
return;
|
|
1626
|
-
}
|
|
1627
|
-
const nameColor = isBuiltin ? chalk6__default.default.cyan : chalk6__default.default.green;
|
|
1628
|
-
console.log(chalk6__default.default.bold(`Type: ${nameColor(name)}
|
|
1629
|
-
`));
|
|
1630
|
-
console.log(` ${chalk6__default.default.dim("Source:")} ${isBuiltin ? "Built-in" : "Custom"}`);
|
|
1631
|
-
console.log(` ${chalk6__default.default.dim("Description:")} ${type.description}`);
|
|
1632
|
-
console.log(` ${chalk6__default.default.dim("TTL:")} ${formatTtl2(type.defaultTtl)} (${type.defaultTtl} seconds)`);
|
|
1633
|
-
console.log("");
|
|
1634
|
-
console.log(chalk6__default.default.bold("Patterns"));
|
|
1635
|
-
for (const pattern of type.patterns) {
|
|
1636
|
-
console.log(` ${chalk6__default.default.dim("\u2022")} ${pattern}`);
|
|
1637
|
-
}
|
|
1638
|
-
if (type.archiveAfterDays !== null) {
|
|
1639
|
-
console.log("");
|
|
1640
|
-
console.log(chalk6__default.default.bold("Archive Settings"));
|
|
1641
|
-
console.log(` ${chalk6__default.default.dim("After:")} ${type.archiveAfterDays} days`);
|
|
1642
|
-
console.log(` ${chalk6__default.default.dim("Storage:")} ${type.archiveStorage || "not set"}`);
|
|
1643
|
-
}
|
|
1644
|
-
if (type.syncPatterns && type.syncPatterns.length > 0) {
|
|
1645
|
-
console.log("");
|
|
1646
|
-
console.log(chalk6__default.default.bold("Sync Patterns"));
|
|
1647
|
-
for (const pattern of type.syncPatterns) {
|
|
1648
|
-
console.log(` ${chalk6__default.default.dim("\u2022")} ${pattern}`);
|
|
1649
|
-
}
|
|
1650
|
-
}
|
|
1651
|
-
if (type.excludePatterns && type.excludePatterns.length > 0) {
|
|
1652
|
-
console.log("");
|
|
1653
|
-
console.log(chalk6__default.default.bold("Exclude Patterns"));
|
|
1654
|
-
for (const pattern of type.excludePatterns) {
|
|
1655
|
-
console.log(` ${chalk6__default.default.dim("\u2022")} ${pattern}`);
|
|
1656
|
-
}
|
|
1657
|
-
}
|
|
1658
|
-
} catch (error) {
|
|
1659
|
-
console.error(chalk6__default.default.red("Error:"), error.message);
|
|
1660
|
-
process.exit(1);
|
|
1661
|
-
}
|
|
1662
|
-
});
|
|
1663
|
-
return cmd;
|
|
1664
|
-
}
|
|
1665
|
-
|
|
1666
|
-
// src/commands/types/add.ts
|
|
1667
|
-
init_cjs_shims();
|
|
1668
|
-
init_migrate_config();
|
|
1669
|
-
function isValidTypeName(name) {
|
|
1670
|
-
return /^[a-z][a-z0-9-]*$/.test(name);
|
|
1671
|
-
}
|
|
1672
|
-
function parseTtl(ttl) {
|
|
1673
|
-
const match = ttl.match(/^(\d+)([smhd])$/);
|
|
1674
|
-
if (!match) {
|
|
1675
|
-
throw new Error("Invalid TTL format");
|
|
1676
|
-
}
|
|
1677
|
-
const value = parseInt(match[1], 10);
|
|
1678
|
-
const unit = match[2];
|
|
1679
|
-
switch (unit) {
|
|
1680
|
-
case "s":
|
|
1681
|
-
return value;
|
|
1682
|
-
case "m":
|
|
1683
|
-
return value * 60;
|
|
1684
|
-
case "h":
|
|
1685
|
-
return value * 3600;
|
|
1686
|
-
case "d":
|
|
1687
|
-
return value * 86400;
|
|
1688
|
-
default:
|
|
1689
|
-
throw new Error("Unknown TTL unit");
|
|
1690
|
-
}
|
|
1691
|
-
}
|
|
1692
|
-
function formatTtl3(seconds) {
|
|
1693
|
-
if (seconds < 60) return `${seconds}s`;
|
|
1694
|
-
if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
|
|
1695
|
-
if (seconds < 86400) return `${Math.floor(seconds / 3600)}h`;
|
|
1696
|
-
return `${Math.floor(seconds / 86400)}d`;
|
|
1697
|
-
}
|
|
1698
|
-
function typesAddCommand() {
|
|
1699
|
-
const cmd = new commander.Command("add");
|
|
1700
|
-
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) => {
|
|
1701
|
-
try {
|
|
1702
|
-
if (!isValidTypeName(name)) {
|
|
1703
|
-
console.error(chalk6__default.default.red("Error:"), "Invalid type name.");
|
|
1704
|
-
console.log(chalk6__default.default.dim("Type name must be lowercase, start with a letter, and contain only letters, numbers, and hyphens."));
|
|
1705
|
-
process.exit(1);
|
|
1706
|
-
}
|
|
1707
|
-
const client = await getClient();
|
|
1708
|
-
const registry = client.getTypeRegistry();
|
|
1709
|
-
if (registry.isBuiltIn(name)) {
|
|
1710
|
-
console.error(chalk6__default.default.red("Error:"), `Cannot override built-in type "${name}".`);
|
|
1711
|
-
const builtinNames = registry.list().filter((t) => registry.isBuiltIn(t.name)).map((t) => t.name);
|
|
1712
|
-
console.log(chalk6__default.default.dim("Built-in types: " + builtinNames.join(", ")));
|
|
1713
|
-
process.exit(1);
|
|
1714
|
-
}
|
|
1715
|
-
if (registry.has(name)) {
|
|
1716
|
-
console.error(chalk6__default.default.red("Error:"), `Custom type "${name}" already exists.`);
|
|
1717
|
-
console.log(chalk6__default.default.dim('Use "fractary codex types remove" first to remove it.'));
|
|
1718
|
-
process.exit(1);
|
|
1719
|
-
}
|
|
1720
|
-
let ttlSeconds;
|
|
1721
|
-
try {
|
|
1722
|
-
ttlSeconds = parseTtl(options.ttl);
|
|
1723
|
-
} catch {
|
|
1724
|
-
console.error(chalk6__default.default.red("Error:"), "Invalid TTL format.");
|
|
1725
|
-
console.log(chalk6__default.default.dim("Expected format: <number><unit> where unit is s (seconds), m (minutes), h (hours), or d (days)"));
|
|
1726
|
-
console.log(chalk6__default.default.dim("Examples: 30m, 24h, 7d"));
|
|
1727
|
-
process.exit(1);
|
|
1728
|
-
}
|
|
1729
|
-
const configPath = path2__namespace.join(process.cwd(), ".fractary", "codex.yaml");
|
|
1730
|
-
const config = await readYamlConfig(configPath);
|
|
1731
|
-
if (!config.types) {
|
|
1732
|
-
config.types = { custom: {} };
|
|
1733
|
-
}
|
|
1734
|
-
if (!config.types.custom) {
|
|
1735
|
-
config.types.custom = {};
|
|
1736
|
-
}
|
|
1737
|
-
config.types.custom[name] = {
|
|
1738
|
-
description: options.description || `Custom type: ${name}`,
|
|
1739
|
-
patterns: [options.pattern],
|
|
1740
|
-
defaultTtl: ttlSeconds
|
|
1741
|
-
};
|
|
1742
|
-
await writeYamlConfig(config, configPath);
|
|
1743
|
-
if (options.json) {
|
|
1744
|
-
console.log(JSON.stringify({
|
|
1745
|
-
success: true,
|
|
1746
|
-
type: {
|
|
1747
|
-
name,
|
|
1748
|
-
description: config.types.custom[name].description,
|
|
1749
|
-
patterns: config.types.custom[name].patterns,
|
|
1750
|
-
defaultTtl: ttlSeconds,
|
|
1751
|
-
ttl: formatTtl3(ttlSeconds),
|
|
1752
|
-
builtin: false
|
|
1753
|
-
},
|
|
1754
|
-
message: "Custom type added successfully. Changes will take effect on next CLI invocation."
|
|
1755
|
-
}, null, 2));
|
|
1756
|
-
return;
|
|
1757
|
-
}
|
|
1758
|
-
console.log(chalk6__default.default.green("\u2713"), `Added custom type "${chalk6__default.default.cyan(name)}"`);
|
|
1759
|
-
console.log("");
|
|
1760
|
-
console.log(` ${chalk6__default.default.dim("Pattern:")} ${options.pattern}`);
|
|
1761
|
-
console.log(` ${chalk6__default.default.dim("TTL:")} ${formatTtl3(ttlSeconds)} (${ttlSeconds} seconds)`);
|
|
1762
|
-
if (options.description) {
|
|
1763
|
-
console.log(` ${chalk6__default.default.dim("Description:")} ${options.description}`);
|
|
1764
|
-
}
|
|
1765
|
-
console.log("");
|
|
1766
|
-
console.log(chalk6__default.default.dim("Note: Custom type will be available on next CLI invocation."));
|
|
1767
|
-
} catch (error) {
|
|
1768
|
-
console.error(chalk6__default.default.red("Error:"), error.message);
|
|
1769
|
-
if (error.message.includes("Failed to load configuration")) {
|
|
1770
|
-
console.log(chalk6__default.default.dim('\nRun "fractary codex init" to create a configuration.'));
|
|
1771
|
-
}
|
|
1772
|
-
process.exit(1);
|
|
1773
|
-
}
|
|
1774
|
-
});
|
|
1775
|
-
return cmd;
|
|
1776
|
-
}
|
|
1777
|
-
|
|
1778
|
-
// src/commands/types/remove.ts
|
|
1779
|
-
init_cjs_shims();
|
|
1780
|
-
init_migrate_config();
|
|
1781
|
-
function typesRemoveCommand() {
|
|
1782
|
-
const cmd = new commander.Command("remove");
|
|
1783
|
-
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) => {
|
|
1784
|
-
try {
|
|
1785
|
-
const client = await getClient();
|
|
1786
|
-
const registry = client.getTypeRegistry();
|
|
1787
|
-
if (registry.isBuiltIn(name)) {
|
|
1788
|
-
console.error(chalk6__default.default.red("Error:"), `Cannot remove built-in type "${name}".`);
|
|
1789
|
-
console.log(chalk6__default.default.dim("Built-in types are permanent and cannot be removed."));
|
|
1790
|
-
process.exit(1);
|
|
1791
|
-
}
|
|
1792
|
-
if (!registry.has(name)) {
|
|
1793
|
-
console.error(chalk6__default.default.red("Error:"), `Custom type "${name}" not found.`);
|
|
1794
|
-
console.log(chalk6__default.default.dim('Run "fractary codex types list --custom-only" to see custom types.'));
|
|
1795
|
-
process.exit(1);
|
|
1796
|
-
}
|
|
1797
|
-
const typeInfo = registry.get(name);
|
|
1798
|
-
const configPath = path2__namespace.join(process.cwd(), ".fractary", "codex.yaml");
|
|
1799
|
-
const config = await readYamlConfig(configPath);
|
|
1800
|
-
if (!config.types?.custom?.[name]) {
|
|
1801
|
-
console.error(chalk6__default.default.red("Error:"), `Custom type "${name}" not found in configuration.`);
|
|
1802
|
-
process.exit(1);
|
|
1803
|
-
}
|
|
1804
|
-
delete config.types.custom[name];
|
|
1805
|
-
if (Object.keys(config.types.custom).length === 0) {
|
|
1806
|
-
delete config.types.custom;
|
|
1807
|
-
}
|
|
1808
|
-
if (config.types && Object.keys(config.types).length === 0) {
|
|
1809
|
-
delete config.types;
|
|
1810
|
-
}
|
|
1811
|
-
await writeYamlConfig(config, configPath);
|
|
1812
|
-
if (options.json) {
|
|
1813
|
-
console.log(JSON.stringify({
|
|
1814
|
-
success: true,
|
|
1815
|
-
removed: {
|
|
1816
|
-
name: typeInfo.name,
|
|
1817
|
-
description: typeInfo.description,
|
|
1818
|
-
patterns: typeInfo.patterns,
|
|
1819
|
-
defaultTtl: typeInfo.defaultTtl
|
|
1820
|
-
},
|
|
1821
|
-
message: "Custom type removed successfully. Changes will take effect on next CLI invocation."
|
|
1822
|
-
}, null, 2));
|
|
1823
|
-
return;
|
|
1824
|
-
}
|
|
1825
|
-
console.log(chalk6__default.default.green("\u2713"), `Removed custom type "${chalk6__default.default.cyan(name)}"`);
|
|
1826
|
-
console.log("");
|
|
1827
|
-
console.log(chalk6__default.default.dim("Removed configuration:"));
|
|
1828
|
-
console.log(` ${chalk6__default.default.dim("Pattern:")} ${typeInfo.patterns.join(", ")}`);
|
|
1829
|
-
console.log(` ${chalk6__default.default.dim("Description:")} ${typeInfo.description}`);
|
|
1830
|
-
console.log("");
|
|
1831
|
-
console.log(chalk6__default.default.dim("Note: Custom type will be removed on next CLI invocation."));
|
|
1832
|
-
} catch (error) {
|
|
1833
|
-
console.error(chalk6__default.default.red("Error:"), error.message);
|
|
1834
|
-
if (error.message.includes("Failed to load configuration")) {
|
|
1835
|
-
console.log(chalk6__default.default.dim('\nRun "fractary codex init" to create a configuration.'));
|
|
1836
|
-
}
|
|
1837
|
-
process.exit(1);
|
|
1838
|
-
}
|
|
1839
|
-
});
|
|
1840
|
-
return cmd;
|
|
1841
|
-
}
|
|
1842
|
-
|
|
1843
|
-
// src/commands/types/index.ts
|
|
1844
|
-
function typesCommand() {
|
|
1845
|
-
const cmd = new commander.Command("types");
|
|
1846
|
-
cmd.description("Manage artifact type registry");
|
|
1847
|
-
cmd.addCommand(typesListCommand());
|
|
1848
|
-
cmd.addCommand(typesShowCommand());
|
|
1849
|
-
cmd.addCommand(typesAddCommand());
|
|
1850
|
-
cmd.addCommand(typesRemoveCommand());
|
|
1851
|
-
return cmd;
|
|
1852
|
-
}
|
|
1853
|
-
|
|
1854
|
-
// src/commands/health.ts
|
|
1855
|
-
init_cjs_shims();
|
|
1856
|
-
init_migrate_config();
|
|
1857
|
-
async function fileExists2(filePath) {
|
|
1858
|
-
try {
|
|
1859
|
-
await fs__namespace.access(filePath);
|
|
1860
|
-
return true;
|
|
1861
|
-
} catch {
|
|
1862
|
-
return false;
|
|
1863
|
-
}
|
|
1864
|
-
}
|
|
1865
|
-
async function checkConfiguration() {
|
|
1866
|
-
const configPath = path2__namespace.join(process.cwd(), ".fractary", "codex.yaml");
|
|
1867
|
-
const legacyConfigPath = path2__namespace.join(process.cwd(), ".fractary", "plugins", "codex", "config.json");
|
|
1868
|
-
try {
|
|
1869
|
-
if (!await fileExists2(configPath)) {
|
|
1870
|
-
if (await fileExists2(legacyConfigPath)) {
|
|
1871
|
-
return {
|
|
1872
|
-
name: "Configuration",
|
|
1873
|
-
status: "warn",
|
|
1874
|
-
message: "Legacy JSON configuration detected",
|
|
1875
|
-
details: 'Run "fractary codex migrate" to upgrade to YAML format'
|
|
1876
|
-
};
|
|
1877
|
-
}
|
|
1878
|
-
return {
|
|
1879
|
-
name: "Configuration",
|
|
1880
|
-
status: "fail",
|
|
1881
|
-
message: "No configuration found",
|
|
1882
|
-
details: 'Run "fractary codex init" to create configuration'
|
|
1883
|
-
};
|
|
1884
|
-
}
|
|
1885
|
-
const config = await readYamlConfig(configPath);
|
|
1886
|
-
if (!config.organization) {
|
|
1887
|
-
return {
|
|
1888
|
-
name: "Configuration",
|
|
1889
|
-
status: "warn",
|
|
1890
|
-
message: "No organization configured",
|
|
1891
|
-
details: "Organization slug is required"
|
|
1892
|
-
};
|
|
1893
|
-
}
|
|
1894
|
-
const providerCount = config.storage?.length || 0;
|
|
1895
|
-
if (providerCount === 0) {
|
|
1896
|
-
return {
|
|
1897
|
-
name: "Configuration",
|
|
1898
|
-
status: "warn",
|
|
1899
|
-
message: "No storage providers configured",
|
|
1900
|
-
details: "At least one storage provider is recommended"
|
|
1901
|
-
};
|
|
1902
|
-
}
|
|
1903
|
-
return {
|
|
1904
|
-
name: "Configuration",
|
|
1905
|
-
status: "pass",
|
|
1906
|
-
message: "Valid YAML configuration",
|
|
1907
|
-
details: `Organization: ${config.organization}, ${providerCount} storage provider(s)`
|
|
1908
|
-
};
|
|
1909
|
-
} catch (error) {
|
|
1910
|
-
return {
|
|
1911
|
-
name: "Configuration",
|
|
1912
|
-
status: "fail",
|
|
1913
|
-
message: "Invalid configuration",
|
|
1914
|
-
details: error.message
|
|
1915
|
-
};
|
|
1916
|
-
}
|
|
1917
|
-
}
|
|
1918
|
-
async function checkSDKClient() {
|
|
1919
|
-
try {
|
|
1920
|
-
const client = await getClient();
|
|
1921
|
-
const organization = client.getOrganization();
|
|
1922
|
-
return {
|
|
1923
|
-
name: "SDK Client",
|
|
1924
|
-
status: "pass",
|
|
1925
|
-
message: "CodexClient initialized successfully",
|
|
1926
|
-
details: `Organization: ${organization}`
|
|
1927
|
-
};
|
|
1928
|
-
} catch (error) {
|
|
1929
|
-
return {
|
|
1930
|
-
name: "SDK Client",
|
|
1931
|
-
status: "fail",
|
|
1932
|
-
message: "Failed to initialize CodexClient",
|
|
1933
|
-
details: error.message
|
|
1934
|
-
};
|
|
1935
|
-
}
|
|
1936
|
-
}
|
|
1937
|
-
async function checkCache() {
|
|
1938
|
-
try {
|
|
1939
|
-
const client = await getClient();
|
|
1940
|
-
const stats = await client.getCacheStats();
|
|
1941
|
-
if (stats.entryCount === 0) {
|
|
1942
|
-
return {
|
|
1943
|
-
name: "Cache",
|
|
1944
|
-
status: "warn",
|
|
1945
|
-
message: "Cache is empty",
|
|
1946
|
-
details: "Fetch some documents to populate cache"
|
|
1947
|
-
};
|
|
1948
|
-
}
|
|
1949
|
-
const healthPercent = stats.entryCount > 0 ? stats.freshCount / stats.entryCount * 100 : 100;
|
|
1950
|
-
if (healthPercent < 50) {
|
|
1951
|
-
return {
|
|
1952
|
-
name: "Cache",
|
|
1953
|
-
status: "warn",
|
|
1954
|
-
message: `${stats.entryCount} entries (${healthPercent.toFixed(0)}% fresh)`,
|
|
1955
|
-
details: `${stats.expiredCount} expired, ${stats.staleCount} stale`
|
|
1956
|
-
};
|
|
1957
|
-
}
|
|
1958
|
-
return {
|
|
1959
|
-
name: "Cache",
|
|
1960
|
-
status: "pass",
|
|
1961
|
-
message: `${stats.entryCount} entries (${healthPercent.toFixed(0)}% fresh)`,
|
|
1962
|
-
details: `${formatSize4(stats.totalSize)} total`
|
|
1963
|
-
};
|
|
1964
|
-
} catch (error) {
|
|
1965
|
-
return {
|
|
1966
|
-
name: "Cache",
|
|
1967
|
-
status: "fail",
|
|
1968
|
-
message: "Cache check failed",
|
|
1969
|
-
details: error.message
|
|
1970
|
-
};
|
|
1971
|
-
}
|
|
1972
|
-
}
|
|
1973
|
-
async function checkStorage() {
|
|
1974
|
-
const configPath = path2__namespace.join(process.cwd(), ".fractary", "codex.yaml");
|
|
1975
|
-
try {
|
|
1976
|
-
const config = await readYamlConfig(configPath);
|
|
1977
|
-
const providers = config.storage || [];
|
|
1978
|
-
if (providers.length === 0) {
|
|
1979
|
-
return {
|
|
1980
|
-
name: "Storage",
|
|
1981
|
-
status: "warn",
|
|
1982
|
-
message: "No storage providers configured",
|
|
1983
|
-
details: "Configure at least one provider in .fractary/codex.yaml"
|
|
1984
|
-
};
|
|
1985
|
-
}
|
|
1986
|
-
const providerTypes = providers.map((p) => p.type).join(", ");
|
|
1987
|
-
const hasGitHub = providers.some((p) => p.type === "github");
|
|
1988
|
-
if (hasGitHub && !process.env.GITHUB_TOKEN) {
|
|
1989
|
-
return {
|
|
1990
|
-
name: "Storage",
|
|
1991
|
-
status: "warn",
|
|
1992
|
-
message: `${providers.length} provider(s): ${providerTypes}`,
|
|
1993
|
-
details: "GITHUB_TOKEN not set (required for GitHub provider)"
|
|
1994
|
-
};
|
|
1995
|
-
}
|
|
1996
|
-
return {
|
|
1997
|
-
name: "Storage",
|
|
1998
|
-
status: "pass",
|
|
1999
|
-
message: `${providers.length} provider(s): ${providerTypes}`,
|
|
2000
|
-
details: "All configured providers available"
|
|
2001
|
-
};
|
|
2002
|
-
} catch (error) {
|
|
2003
|
-
return {
|
|
2004
|
-
name: "Storage",
|
|
2005
|
-
status: "fail",
|
|
2006
|
-
message: "Storage check failed",
|
|
2007
|
-
details: error.message
|
|
2008
|
-
};
|
|
2009
|
-
}
|
|
2010
|
-
}
|
|
2011
|
-
async function checkTypes() {
|
|
2012
|
-
try {
|
|
2013
|
-
const client = await getClient();
|
|
2014
|
-
const registry = client.getTypeRegistry();
|
|
2015
|
-
const allTypes = registry.list();
|
|
2016
|
-
const builtinCount = allTypes.filter((t) => registry.isBuiltIn(t.name)).length;
|
|
2017
|
-
const customCount = allTypes.length - builtinCount;
|
|
2018
|
-
return {
|
|
2019
|
-
name: "Type Registry",
|
|
2020
|
-
status: "pass",
|
|
2021
|
-
message: `${allTypes.length} types registered`,
|
|
2022
|
-
details: `${builtinCount} built-in, ${customCount} custom`
|
|
2023
|
-
};
|
|
2024
|
-
} catch (error) {
|
|
2025
|
-
return {
|
|
2026
|
-
name: "Type Registry",
|
|
2027
|
-
status: "fail",
|
|
2028
|
-
message: "Type registry check failed",
|
|
2029
|
-
details: error.message
|
|
2030
|
-
};
|
|
2031
|
-
}
|
|
2032
|
-
}
|
|
2033
|
-
function formatSize4(bytes) {
|
|
2034
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
2035
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
2036
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
2037
|
-
}
|
|
2038
|
-
function healthCommand() {
|
|
2039
|
-
const cmd = new commander.Command("health");
|
|
2040
|
-
cmd.description("Run diagnostics on codex setup").option("--json", "Output as JSON").action(async (options) => {
|
|
2041
|
-
try {
|
|
2042
|
-
const checks = [];
|
|
2043
|
-
checks.push(await checkConfiguration());
|
|
2044
|
-
checks.push(await checkSDKClient());
|
|
2045
|
-
checks.push(await checkCache());
|
|
2046
|
-
checks.push(await checkStorage());
|
|
2047
|
-
checks.push(await checkTypes());
|
|
2048
|
-
const passed = checks.filter((c) => c.status === "pass").length;
|
|
2049
|
-
const warned = checks.filter((c) => c.status === "warn").length;
|
|
2050
|
-
const failed = checks.filter((c) => c.status === "fail").length;
|
|
1776
|
+
if (!type) {
|
|
1777
|
+
console.error(chalk8__default.default.red("Error:"), `Type "${name}" not found.`);
|
|
1778
|
+
console.log(chalk8__default.default.dim('Run "fractary codex types list" to see available types.'));
|
|
1779
|
+
process.exit(1);
|
|
1780
|
+
}
|
|
1781
|
+
const isBuiltin = registry.isBuiltIn(name);
|
|
2051
1782
|
if (options.json) {
|
|
2052
1783
|
console.log(JSON.stringify({
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
1784
|
+
name: type.name,
|
|
1785
|
+
builtin: isBuiltin,
|
|
1786
|
+
description: type.description,
|
|
1787
|
+
patterns: type.patterns,
|
|
1788
|
+
defaultTtl: type.defaultTtl,
|
|
1789
|
+
ttl: formatTtl2(type.defaultTtl),
|
|
1790
|
+
archiveAfterDays: type.archiveAfterDays,
|
|
1791
|
+
archiveStorage: type.archiveStorage,
|
|
1792
|
+
syncPatterns: type.syncPatterns,
|
|
1793
|
+
excludePatterns: type.excludePatterns
|
|
2061
1794
|
}, null, 2));
|
|
2062
1795
|
return;
|
|
2063
1796
|
}
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
1797
|
+
const nameColor = isBuiltin ? chalk8__default.default.cyan : chalk8__default.default.green;
|
|
1798
|
+
console.log(chalk8__default.default.bold(`Type: ${nameColor(name)}
|
|
1799
|
+
`));
|
|
1800
|
+
console.log(` ${chalk8__default.default.dim("Source:")} ${isBuiltin ? "Built-in" : "Custom"}`);
|
|
1801
|
+
console.log(` ${chalk8__default.default.dim("Description:")} ${type.description}`);
|
|
1802
|
+
console.log(` ${chalk8__default.default.dim("TTL:")} ${formatTtl2(type.defaultTtl)} (${type.defaultTtl} seconds)`);
|
|
1803
|
+
console.log("");
|
|
1804
|
+
console.log(chalk8__default.default.bold("Patterns"));
|
|
1805
|
+
for (const pattern of type.patterns) {
|
|
1806
|
+
console.log(` ${chalk8__default.default.dim("\u2022")} ${pattern}`);
|
|
1807
|
+
}
|
|
1808
|
+
if (type.archiveAfterDays !== null) {
|
|
2073
1809
|
console.log("");
|
|
1810
|
+
console.log(chalk8__default.default.bold("Archive Settings"));
|
|
1811
|
+
console.log(` ${chalk8__default.default.dim("After:")} ${type.archiveAfterDays} days`);
|
|
1812
|
+
console.log(` ${chalk8__default.default.dim("Storage:")} ${type.archiveStorage || "not set"}`);
|
|
2074
1813
|
}
|
|
2075
|
-
|
|
2076
|
-
const overallStatus = failed > 0 ? chalk6__default.default.red("UNHEALTHY") : warned > 0 ? chalk6__default.default.yellow("DEGRADED") : chalk6__default.default.green("HEALTHY");
|
|
2077
|
-
console.log(`Status: ${overallStatus}`);
|
|
2078
|
-
console.log(chalk6__default.default.dim(`${passed} passed, ${warned} warnings, ${failed} failed`));
|
|
2079
|
-
if (failed > 0 || warned > 0) {
|
|
1814
|
+
if (type.syncPatterns && type.syncPatterns.length > 0) {
|
|
2080
1815
|
console.log("");
|
|
2081
|
-
console.log(
|
|
2082
|
-
|
|
2083
|
-
|
|
1816
|
+
console.log(chalk8__default.default.bold("Sync Patterns"));
|
|
1817
|
+
for (const pattern of type.syncPatterns) {
|
|
1818
|
+
console.log(` ${chalk8__default.default.dim("\u2022")} ${pattern}`);
|
|
1819
|
+
}
|
|
2084
1820
|
}
|
|
2085
|
-
if (
|
|
2086
|
-
|
|
1821
|
+
if (type.excludePatterns && type.excludePatterns.length > 0) {
|
|
1822
|
+
console.log("");
|
|
1823
|
+
console.log(chalk8__default.default.bold("Exclude Patterns"));
|
|
1824
|
+
for (const pattern of type.excludePatterns) {
|
|
1825
|
+
console.log(` ${chalk8__default.default.dim("\u2022")} ${pattern}`);
|
|
1826
|
+
}
|
|
2087
1827
|
}
|
|
2088
1828
|
} catch (error) {
|
|
2089
|
-
console.error(
|
|
1829
|
+
console.error(chalk8__default.default.red("Error:"), error.message);
|
|
2090
1830
|
process.exit(1);
|
|
2091
1831
|
}
|
|
2092
1832
|
});
|
|
2093
1833
|
return cmd;
|
|
2094
1834
|
}
|
|
2095
1835
|
|
|
2096
|
-
// src/commands/
|
|
1836
|
+
// src/commands/types/add.ts
|
|
2097
1837
|
init_cjs_shims();
|
|
2098
1838
|
init_migrate_config();
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
1839
|
+
function isValidTypeName(name) {
|
|
1840
|
+
return /^[a-z][a-z0-9-]*$/.test(name);
|
|
1841
|
+
}
|
|
1842
|
+
function parseTtl(ttl) {
|
|
1843
|
+
const match = ttl.match(/^(\d+)([smhd])$/);
|
|
1844
|
+
if (!match) {
|
|
1845
|
+
throw new Error("Invalid TTL format");
|
|
1846
|
+
}
|
|
1847
|
+
const value = parseInt(match[1], 10);
|
|
1848
|
+
const unit = match[2];
|
|
1849
|
+
switch (unit) {
|
|
1850
|
+
case "s":
|
|
1851
|
+
return value;
|
|
1852
|
+
case "m":
|
|
1853
|
+
return value * 60;
|
|
1854
|
+
case "h":
|
|
1855
|
+
return value * 3600;
|
|
1856
|
+
case "d":
|
|
1857
|
+
return value * 86400;
|
|
1858
|
+
default:
|
|
1859
|
+
throw new Error("Unknown TTL unit");
|
|
2105
1860
|
}
|
|
2106
1861
|
}
|
|
2107
|
-
|
|
2108
|
-
|
|
1862
|
+
function formatTtl3(seconds) {
|
|
1863
|
+
if (seconds < 60) return `${seconds}s`;
|
|
1864
|
+
if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
|
|
1865
|
+
if (seconds < 86400) return `${Math.floor(seconds / 3600)}h`;
|
|
1866
|
+
return `${Math.floor(seconds / 86400)}d`;
|
|
2109
1867
|
}
|
|
2110
|
-
function
|
|
2111
|
-
const cmd = new commander.Command("
|
|
2112
|
-
cmd.description("
|
|
1868
|
+
function typesAddCommand() {
|
|
1869
|
+
const cmd = new commander.Command("add");
|
|
1870
|
+
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) => {
|
|
2113
1871
|
try {
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
console.log(JSON.stringify({
|
|
2119
|
-
status: "no_config",
|
|
2120
|
-
message: "No legacy configuration file found",
|
|
2121
|
-
path: legacyConfigPath
|
|
2122
|
-
}));
|
|
2123
|
-
} else {
|
|
2124
|
-
console.log(chalk6__default.default.yellow("\u26A0 No legacy configuration file found."));
|
|
2125
|
-
console.log(chalk6__default.default.dim(` Expected: ${legacyConfigPath}`));
|
|
2126
|
-
console.log(chalk6__default.default.dim('\nRun "fractary codex init" to create a new v3.0 YAML configuration.'));
|
|
2127
|
-
}
|
|
2128
|
-
return;
|
|
1872
|
+
if (!isValidTypeName(name)) {
|
|
1873
|
+
console.error(chalk8__default.default.red("Error:"), "Invalid type name.");
|
|
1874
|
+
console.log(chalk8__default.default.dim("Type name must be lowercase, start with a letter, and contain only letters, numbers, and hyphens."));
|
|
1875
|
+
process.exit(1);
|
|
2129
1876
|
}
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
} else {
|
|
2138
|
-
console.log(chalk6__default.default.yellow("\u26A0 YAML configuration already exists."));
|
|
2139
|
-
console.log(chalk6__default.default.dim(` Path: ${newConfigPath}`));
|
|
2140
|
-
console.log(chalk6__default.default.dim('\nUse "fractary codex init --force" to recreate.'));
|
|
2141
|
-
}
|
|
2142
|
-
return;
|
|
1877
|
+
const client = await getClient();
|
|
1878
|
+
const registry = client.getTypeRegistry();
|
|
1879
|
+
if (registry.isBuiltIn(name)) {
|
|
1880
|
+
console.error(chalk8__default.default.red("Error:"), `Cannot override built-in type "${name}".`);
|
|
1881
|
+
const builtinNames = registry.list().filter((t) => registry.isBuiltIn(t.name)).map((t) => t.name);
|
|
1882
|
+
console.log(chalk8__default.default.dim("Built-in types: " + builtinNames.join(", ")));
|
|
1883
|
+
process.exit(1);
|
|
2143
1884
|
}
|
|
2144
|
-
|
|
2145
|
-
|
|
1885
|
+
if (registry.has(name)) {
|
|
1886
|
+
console.error(chalk8__default.default.red("Error:"), `Custom type "${name}" already exists.`);
|
|
1887
|
+
console.log(chalk8__default.default.dim('Use "fractary codex types remove" first to remove it.'));
|
|
1888
|
+
process.exit(1);
|
|
1889
|
+
}
|
|
1890
|
+
let ttlSeconds;
|
|
2146
1891
|
try {
|
|
2147
|
-
|
|
1892
|
+
ttlSeconds = parseTtl(options.ttl);
|
|
2148
1893
|
} catch {
|
|
2149
|
-
console.error(
|
|
1894
|
+
console.error(chalk8__default.default.red("Error:"), "Invalid TTL format.");
|
|
1895
|
+
console.log(chalk8__default.default.dim("Expected format: <number><unit> where unit is s (seconds), m (minutes), h (hours), or d (days)"));
|
|
1896
|
+
console.log(chalk8__default.default.dim("Examples: 30m, 24h, 7d"));
|
|
2150
1897
|
process.exit(1);
|
|
2151
1898
|
}
|
|
2152
|
-
|
|
2153
|
-
|
|
1899
|
+
const configPath = path3__namespace.join(process.cwd(), ".fractary", "codex.yaml");
|
|
1900
|
+
const config = await readYamlConfig(configPath);
|
|
1901
|
+
if (!config.types) {
|
|
1902
|
+
config.types = { custom: {} };
|
|
2154
1903
|
}
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
{
|
|
2158
|
-
createBackup: options.backup !== false,
|
|
2159
|
-
backupSuffix: (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")
|
|
2160
|
-
}
|
|
2161
|
-
);
|
|
2162
|
-
if (!options.json) {
|
|
2163
|
-
console.log(chalk6__default.default.bold("Legacy Configuration:"));
|
|
2164
|
-
console.log(chalk6__default.default.dim(` Path: ${legacyConfigPath}`));
|
|
2165
|
-
console.log(chalk6__default.default.dim(` Organization: ${legacyConfig.organization || legacyConfig.organizationSlug || "unknown"}`));
|
|
2166
|
-
console.log("");
|
|
2167
|
-
console.log(chalk6__default.default.bold("Migration Changes:"));
|
|
2168
|
-
console.log(chalk6__default.default.green(" + Format: JSON \u2192 YAML"));
|
|
2169
|
-
console.log(chalk6__default.default.green(" + Location: .fractary/plugins/codex/ \u2192 .fractary/"));
|
|
2170
|
-
console.log(chalk6__default.default.green(" + File: config.json \u2192 codex.yaml"));
|
|
2171
|
-
console.log(chalk6__default.default.green(" + Storage: Multi-provider configuration"));
|
|
2172
|
-
console.log(chalk6__default.default.green(" + Cache: Modern cache management"));
|
|
2173
|
-
console.log(chalk6__default.default.green(" + Types: Custom type registry"));
|
|
2174
|
-
if (migrationResult.warnings.length > 0) {
|
|
2175
|
-
console.log("");
|
|
2176
|
-
console.log(chalk6__default.default.yellow("Warnings:"));
|
|
2177
|
-
for (const warning of migrationResult.warnings) {
|
|
2178
|
-
console.log(chalk6__default.default.yellow(" \u26A0"), chalk6__default.default.dim(warning));
|
|
2179
|
-
}
|
|
2180
|
-
}
|
|
2181
|
-
console.log("");
|
|
2182
|
-
if (options.dryRun) {
|
|
2183
|
-
console.log(chalk6__default.default.blue("Dry run - no changes made."));
|
|
2184
|
-
console.log(chalk6__default.default.dim("Run without --dry-run to execute migration."));
|
|
2185
|
-
return;
|
|
2186
|
-
}
|
|
1904
|
+
if (!config.types.custom) {
|
|
1905
|
+
config.types.custom = {};
|
|
2187
1906
|
}
|
|
1907
|
+
config.types.custom[name] = {
|
|
1908
|
+
description: options.description || `Custom type: ${name}`,
|
|
1909
|
+
patterns: [options.pattern],
|
|
1910
|
+
defaultTtl: ttlSeconds
|
|
1911
|
+
};
|
|
1912
|
+
await writeYamlConfig(config, configPath);
|
|
2188
1913
|
if (options.json) {
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
organization: migrationResult.yamlConfig.organization
|
|
1914
|
+
console.log(JSON.stringify({
|
|
1915
|
+
success: true,
|
|
1916
|
+
type: {
|
|
1917
|
+
name,
|
|
1918
|
+
description: config.types.custom[name].description,
|
|
1919
|
+
patterns: config.types.custom[name].patterns,
|
|
1920
|
+
defaultTtl: ttlSeconds,
|
|
1921
|
+
ttl: formatTtl3(ttlSeconds),
|
|
1922
|
+
builtin: false
|
|
2199
1923
|
},
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
console.log(JSON.stringify(output, null, 2));
|
|
2204
|
-
if (options.dryRun) {
|
|
2205
|
-
return;
|
|
2206
|
-
}
|
|
1924
|
+
message: "Custom type added successfully. Changes will take effect on next CLI invocation."
|
|
1925
|
+
}, null, 2));
|
|
1926
|
+
return;
|
|
2207
1927
|
}
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
console.log(chalk6__default.default.green("\u2713"), "Cache directory initialized");
|
|
2215
|
-
if (migrationResult.backupPath) {
|
|
2216
|
-
console.log(chalk6__default.default.green("\u2713"), "Legacy config backed up");
|
|
2217
|
-
}
|
|
2218
|
-
console.log("");
|
|
2219
|
-
console.log(chalk6__default.default.bold("New Configuration:"));
|
|
2220
|
-
console.log(chalk6__default.default.dim(` Path: ${newConfigPath}`));
|
|
2221
|
-
console.log(chalk6__default.default.dim(` Organization: ${migrationResult.yamlConfig.organization}`));
|
|
2222
|
-
console.log(chalk6__default.default.dim(` Cache: ${migrationResult.yamlConfig.cacheDir || ".codex-cache"}`));
|
|
2223
|
-
console.log(chalk6__default.default.dim(` Storage Providers: ${migrationResult.yamlConfig.storage?.length || 0}`));
|
|
2224
|
-
console.log("");
|
|
2225
|
-
console.log(chalk6__default.default.bold("Next Steps:"));
|
|
2226
|
-
console.log(chalk6__default.default.dim(" 1. Review the new configuration: .fractary/codex.yaml"));
|
|
2227
|
-
console.log(chalk6__default.default.dim(' 2. Set your GitHub token: export GITHUB_TOKEN="your_token"'));
|
|
2228
|
-
console.log(chalk6__default.default.dim(" 3. Test fetching: fractary codex fetch codex://org/project/path"));
|
|
2229
|
-
if (migrationResult.backupPath) {
|
|
2230
|
-
console.log("");
|
|
2231
|
-
console.log(chalk6__default.default.dim(`Backup saved: ${path2__namespace.basename(migrationResult.backupPath)}`));
|
|
2232
|
-
}
|
|
2233
|
-
}
|
|
1928
|
+
console.log(chalk8__default.default.green("\u2713"), `Added custom type "${chalk8__default.default.cyan(name)}"`);
|
|
1929
|
+
console.log("");
|
|
1930
|
+
console.log(` ${chalk8__default.default.dim("Pattern:")} ${options.pattern}`);
|
|
1931
|
+
console.log(` ${chalk8__default.default.dim("TTL:")} ${formatTtl3(ttlSeconds)} (${ttlSeconds} seconds)`);
|
|
1932
|
+
if (options.description) {
|
|
1933
|
+
console.log(` ${chalk8__default.default.dim("Description:")} ${options.description}`);
|
|
2234
1934
|
}
|
|
1935
|
+
console.log("");
|
|
1936
|
+
console.log(chalk8__default.default.dim("Note: Custom type will be available on next CLI invocation."));
|
|
2235
1937
|
} catch (error) {
|
|
1938
|
+
console.error(chalk8__default.default.red("Error:"), error.message);
|
|
1939
|
+
if (error.message.includes("Failed to load configuration")) {
|
|
1940
|
+
console.log(chalk8__default.default.dim('\nRun "fractary codex init" to create a configuration.'));
|
|
1941
|
+
}
|
|
1942
|
+
process.exit(1);
|
|
1943
|
+
}
|
|
1944
|
+
});
|
|
1945
|
+
return cmd;
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
// src/commands/types/remove.ts
|
|
1949
|
+
init_cjs_shims();
|
|
1950
|
+
init_migrate_config();
|
|
1951
|
+
function typesRemoveCommand() {
|
|
1952
|
+
const cmd = new commander.Command("remove");
|
|
1953
|
+
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) => {
|
|
1954
|
+
try {
|
|
1955
|
+
const client = await getClient();
|
|
1956
|
+
const registry = client.getTypeRegistry();
|
|
1957
|
+
if (registry.isBuiltIn(name)) {
|
|
1958
|
+
console.error(chalk8__default.default.red("Error:"), `Cannot remove built-in type "${name}".`);
|
|
1959
|
+
console.log(chalk8__default.default.dim("Built-in types are permanent and cannot be removed."));
|
|
1960
|
+
process.exit(1);
|
|
1961
|
+
}
|
|
1962
|
+
if (!registry.has(name)) {
|
|
1963
|
+
console.error(chalk8__default.default.red("Error:"), `Custom type "${name}" not found.`);
|
|
1964
|
+
console.log(chalk8__default.default.dim('Run "fractary codex types list --custom-only" to see custom types.'));
|
|
1965
|
+
process.exit(1);
|
|
1966
|
+
}
|
|
1967
|
+
const typeInfo = registry.get(name);
|
|
1968
|
+
const configPath = path3__namespace.join(process.cwd(), ".fractary", "codex.yaml");
|
|
1969
|
+
const config = await readYamlConfig(configPath);
|
|
1970
|
+
if (!config.types?.custom?.[name]) {
|
|
1971
|
+
console.error(chalk8__default.default.red("Error:"), `Custom type "${name}" not found in configuration.`);
|
|
1972
|
+
process.exit(1);
|
|
1973
|
+
}
|
|
1974
|
+
delete config.types.custom[name];
|
|
1975
|
+
if (Object.keys(config.types.custom).length === 0) {
|
|
1976
|
+
delete config.types.custom;
|
|
1977
|
+
}
|
|
1978
|
+
if (config.types && Object.keys(config.types).length === 0) {
|
|
1979
|
+
delete config.types;
|
|
1980
|
+
}
|
|
1981
|
+
await writeYamlConfig(config, configPath);
|
|
2236
1982
|
if (options.json) {
|
|
2237
1983
|
console.log(JSON.stringify({
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
1984
|
+
success: true,
|
|
1985
|
+
removed: {
|
|
1986
|
+
name: typeInfo.name,
|
|
1987
|
+
description: typeInfo.description,
|
|
1988
|
+
patterns: typeInfo.patterns,
|
|
1989
|
+
defaultTtl: typeInfo.defaultTtl
|
|
1990
|
+
},
|
|
1991
|
+
message: "Custom type removed successfully. Changes will take effect on next CLI invocation."
|
|
1992
|
+
}, null, 2));
|
|
1993
|
+
return;
|
|
1994
|
+
}
|
|
1995
|
+
console.log(chalk8__default.default.green("\u2713"), `Removed custom type "${chalk8__default.default.cyan(name)}"`);
|
|
1996
|
+
console.log("");
|
|
1997
|
+
console.log(chalk8__default.default.dim("Removed configuration:"));
|
|
1998
|
+
console.log(` ${chalk8__default.default.dim("Pattern:")} ${typeInfo.patterns.join(", ")}`);
|
|
1999
|
+
console.log(` ${chalk8__default.default.dim("Description:")} ${typeInfo.description}`);
|
|
2000
|
+
console.log("");
|
|
2001
|
+
console.log(chalk8__default.default.dim("Note: Custom type will be removed on next CLI invocation."));
|
|
2002
|
+
} catch (error) {
|
|
2003
|
+
console.error(chalk8__default.default.red("Error:"), error.message);
|
|
2004
|
+
if (error.message.includes("Failed to load configuration")) {
|
|
2005
|
+
console.log(chalk8__default.default.dim('\nRun "fractary codex init" to create a configuration.'));
|
|
2243
2006
|
}
|
|
2244
2007
|
process.exit(1);
|
|
2245
2008
|
}
|
|
@@ -2247,17 +2010,26 @@ function migrateCommand() {
|
|
|
2247
2010
|
return cmd;
|
|
2248
2011
|
}
|
|
2249
2012
|
|
|
2013
|
+
// src/commands/types/index.ts
|
|
2014
|
+
function typesCommand() {
|
|
2015
|
+
const cmd = new commander.Command("types");
|
|
2016
|
+
cmd.description("Manage artifact type registry");
|
|
2017
|
+
cmd.addCommand(typesListCommand());
|
|
2018
|
+
cmd.addCommand(typesShowCommand());
|
|
2019
|
+
cmd.addCommand(typesAddCommand());
|
|
2020
|
+
cmd.addCommand(typesRemoveCommand());
|
|
2021
|
+
return cmd;
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2250
2024
|
// src/cli.ts
|
|
2251
2025
|
function createCLI() {
|
|
2252
2026
|
const program = new commander.Command("fractary-codex");
|
|
2253
|
-
program.description("Centralized knowledge management and distribution for AI agents").version("0.
|
|
2254
|
-
program.addCommand(
|
|
2255
|
-
program.addCommand(
|
|
2027
|
+
program.description("Centralized knowledge management and distribution for AI agents").version("0.3.0");
|
|
2028
|
+
program.addCommand(documentCommand());
|
|
2029
|
+
program.addCommand(configCommand());
|
|
2256
2030
|
program.addCommand(cacheCommand());
|
|
2257
2031
|
program.addCommand(syncCommand());
|
|
2258
2032
|
program.addCommand(typesCommand());
|
|
2259
|
-
program.addCommand(healthCommand());
|
|
2260
|
-
program.addCommand(migrateCommand());
|
|
2261
2033
|
return program;
|
|
2262
2034
|
}
|
|
2263
2035
|
async function main() {
|