@fractary/codex-cli 0.10.15 → 0.10.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
- var fs$1 = require('fs/promises');
5
- var path4 = require('path');
6
- var yaml2 = require('js-yaml');
7
4
  var codex = require('@fractary/codex');
5
+ var path3 = require('path');
8
6
  var os = require('os');
7
+ var fs2 = require('fs/promises');
9
8
  var child_process = require('child_process');
10
9
  var commander = require('commander');
11
- var chalk7 = require('chalk');
10
+ var chalk10 = require('chalk');
12
11
  var crypto = require('crypto');
12
+ require('js-yaml');
13
13
  var fs = require('fs');
14
14
  var url = require('url');
15
15
 
@@ -33,21 +33,14 @@ function _interopNamespace(e) {
33
33
  return Object.freeze(n);
34
34
  }
35
35
 
36
- var fs__namespace = /*#__PURE__*/_interopNamespace(fs$1);
37
- var path4__namespace = /*#__PURE__*/_interopNamespace(path4);
38
- var yaml2__namespace = /*#__PURE__*/_interopNamespace(yaml2);
36
+ var path3__namespace = /*#__PURE__*/_interopNamespace(path3);
39
37
  var os__namespace = /*#__PURE__*/_interopNamespace(os);
40
- var chalk7__default = /*#__PURE__*/_interopDefault(chalk7);
38
+ var fs2__namespace = /*#__PURE__*/_interopNamespace(fs2);
39
+ var chalk10__default = /*#__PURE__*/_interopDefault(chalk10);
41
40
  var crypto__namespace = /*#__PURE__*/_interopNamespace(crypto);
42
41
 
43
42
  var __defProp = Object.defineProperty;
44
43
  var __getOwnPropNames = Object.getOwnPropertyNames;
45
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
46
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
47
- }) : x)(function(x) {
48
- if (typeof require !== "undefined") return require.apply(this, arguments);
49
- throw Error('Dynamic require of "' + x + '" is not supported');
50
- });
51
44
  var __esm = (fn, res) => function __init() {
52
45
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
53
46
  };
@@ -65,477 +58,19 @@ var init_cjs_shims = __esm({
65
58
  }
66
59
  });
67
60
 
68
- // src/config/migrate-config.ts
69
- var migrate_config_exports = {};
70
- __export(migrate_config_exports, {
71
- getDefaultYamlConfig: () => getDefaultYamlConfig,
72
- isLegacyConfig: () => isLegacyConfig,
73
- migrateConfig: () => migrateConfig,
74
- readYamlConfig: () => codex.readCodexConfig,
75
- writeYamlConfig: () => writeYamlConfig
76
- });
77
- async function isLegacyConfig(configPath) {
78
- try {
79
- const content = await fs__namespace.readFile(configPath, "utf-8");
80
- const config = JSON.parse(content);
81
- return config.version === "3.0" || config.organizationSlug !== void 0 || config.directories !== void 0 || config.rules !== void 0;
82
- } catch {
83
- return false;
84
- }
85
- }
86
- async function migrateConfig(legacyConfigPath, options) {
87
- const warnings = [];
88
- try {
89
- const content = await fs__namespace.readFile(legacyConfigPath, "utf-8");
90
- const legacy = JSON.parse(content);
91
- let backupPath;
92
- if (options?.createBackup !== false) {
93
- const suffix = options?.backupSuffix || (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
94
- backupPath = `${legacyConfigPath}.backup-${suffix}`;
95
- await fs__namespace.writeFile(backupPath, content, "utf-8");
96
- }
97
- const yamlConfig = {
98
- organization: legacy.organization || legacy.organizationSlug || "default"
99
- };
100
- if (legacy.cache) {
101
- yamlConfig.cacheDir = legacy.cache.directory || ".fractary/codex/cache";
102
- }
103
- if (legacy.storage?.providers) {
104
- yamlConfig.storage = [];
105
- for (const [type, config] of Object.entries(legacy.storage.providers)) {
106
- if (type === "github") {
107
- const githubConfig = config;
108
- yamlConfig.storage.push({
109
- type: "github",
110
- token: githubConfig.token || "${GITHUB_TOKEN}",
111
- apiBaseUrl: githubConfig.baseUrl || "https://api.github.com",
112
- branch: githubConfig.branch || "main",
113
- priority: 50
114
- });
115
- } else if (type === "http") {
116
- const httpConfig = config;
117
- yamlConfig.storage.push({
118
- type: "http",
119
- baseUrl: httpConfig.baseUrl,
120
- headers: httpConfig.headers,
121
- timeout: httpConfig.timeout || 3e4,
122
- priority: 100
123
- });
124
- } else if (type === "local") {
125
- const localConfig = config;
126
- yamlConfig.storage.push({
127
- type: "local",
128
- basePath: localConfig.basePath || "./knowledge",
129
- followSymlinks: localConfig.followSymlinks || false,
130
- priority: 10
131
- });
132
- } else {
133
- warnings.push(`Unknown storage provider type: ${type}`);
134
- }
135
- }
136
- if (yamlConfig.storage.length === 0) {
137
- yamlConfig.storage.push({
138
- type: "github",
139
- token: "${GITHUB_TOKEN}",
140
- apiBaseUrl: "https://api.github.com",
141
- branch: "main",
142
- priority: 50
143
- });
144
- warnings.push("No storage providers found, added default GitHub provider");
145
- }
146
- }
147
- if (legacy.types?.custom && Array.isArray(legacy.types.custom)) {
148
- yamlConfig.types = {
149
- custom: {}
150
- };
151
- for (const customType of legacy.types.custom) {
152
- if (customType.name) {
153
- yamlConfig.types.custom[customType.name] = {
154
- description: customType.description,
155
- patterns: customType.patterns || [],
156
- defaultTtl: customType.defaultTtl,
157
- archiveAfterDays: customType.archiveAfterDays,
158
- archiveStorage: customType.archiveStorage
159
- };
160
- }
161
- }
162
- }
163
- if (legacy.sync) {
164
- yamlConfig.sync = {
165
- bidirectional: true,
166
- conflictResolution: "prompt",
167
- exclude: [
168
- "node_modules/**",
169
- ".git/**",
170
- "**/*.log",
171
- ".env"
172
- ]
173
- };
174
- if (legacy.sync.environments) {
175
- warnings.push("Sync environments are not directly supported in v3.0 - please configure sync rules manually");
176
- }
177
- }
178
- if (legacy.mcp) {
179
- yamlConfig.mcp = {
180
- enabled: legacy.mcp.enabled || false,
181
- port: legacy.mcp.port || 3e3
182
- };
183
- }
184
- return {
185
- success: true,
186
- yamlConfig,
187
- warnings,
188
- backupPath
189
- };
190
- } catch (error) {
191
- throw new Error(
192
- `Migration failed: ${error instanceof Error ? error.message : String(error)}`
193
- );
194
- }
195
- }
196
- async function writeYamlConfig(config, outputPath) {
197
- const dir = path4__namespace.dirname(outputPath);
198
- await fs__namespace.mkdir(dir, { recursive: true });
199
- const yamlContent = yaml2__namespace.dump(config, {
200
- indent: 2,
201
- lineWidth: 80,
202
- noRefs: true,
203
- sortKeys: false
204
- });
205
- await fs__namespace.writeFile(outputPath, yamlContent, "utf-8");
206
- }
207
- function getDefaultYamlConfig(organization) {
208
- return {
209
- organization,
210
- cacheDir: ".fractary/codex/cache",
211
- storage: [
212
- {
213
- type: "local",
214
- basePath: "./knowledge",
215
- followSymlinks: false,
216
- priority: 10
217
- },
218
- {
219
- type: "github",
220
- token: "${GITHUB_TOKEN}",
221
- apiBaseUrl: "https://api.github.com",
222
- branch: "main",
223
- priority: 50
224
- },
225
- {
226
- type: "http",
227
- baseUrl: "https://codex.example.com",
228
- timeout: 3e4,
229
- priority: 100
230
- }
231
- ],
232
- types: {
233
- custom: {}
234
- },
235
- permissions: {
236
- default: "read",
237
- rules: [
238
- {
239
- pattern: "internal/**",
240
- permission: "none"
241
- },
242
- {
243
- pattern: "public/**",
244
- permission: "read"
245
- }
246
- ]
247
- },
248
- sync: {
249
- bidirectional: true,
250
- conflictResolution: "prompt",
251
- exclude: [
252
- "node_modules/**",
253
- ".git/**",
254
- "**/*.log",
255
- ".env"
256
- ]
257
- },
258
- mcp: {
259
- enabled: false,
260
- port: 3e3
261
- }
262
- };
263
- }
264
- var init_migrate_config = __esm({
265
- "src/config/migrate-config.ts"() {
266
- init_cjs_shims();
267
- }
268
- });
269
-
270
- // src/config/config-types.ts
271
- var config_types_exports = {};
272
- __export(config_types_exports, {
273
- parseDuration: () => codex.parseDuration,
274
- parseSize: () => codex.parseSize,
275
- resolveEnvVars: () => codex.expandEnvVars,
276
- resolveEnvVarsInConfig: () => codex.expandEnvVarsInConfig
277
- });
278
- var init_config_types = __esm({
279
- "src/config/config-types.ts"() {
280
- init_cjs_shims();
281
- }
282
- });
283
-
284
61
  // src/client/codex-client.ts
285
62
  var codex_client_exports = {};
286
63
  __export(codex_client_exports, {
287
- CodexClient: () => CodexClient,
64
+ CodexClient: () => codex.CodexClient,
288
65
  CodexError: () => codex.CodexError,
289
66
  ConfigurationError: () => codex.ConfigurationError,
290
67
  PermissionDeniedError: () => codex.PermissionDeniedError,
291
- ValidationError: () => codex.ValidationError
68
+ ValidationError: () => codex.ValidationError,
69
+ createCodexClient: () => codex.createCodexClient
292
70
  });
293
- var CodexClient;
294
71
  var init_codex_client = __esm({
295
72
  "src/client/codex-client.ts"() {
296
73
  init_cjs_shims();
297
- CodexClient = class _CodexClient {
298
- cache;
299
- storage;
300
- types;
301
- organization;
302
- /**
303
- * Private constructor - use CodexClient.create() instead
304
- */
305
- constructor(cache, storage, types, organization) {
306
- this.cache = cache;
307
- this.storage = storage;
308
- this.types = types;
309
- this.organization = organization;
310
- }
311
- /**
312
- * Create a new CodexClient instance
313
- *
314
- * @param options - Optional configuration
315
- * @returns Promise resolving to CodexClient instance
316
- *
317
- * @example
318
- * ```typescript
319
- * const client = await CodexClient.create();
320
- * ```
321
- */
322
- static async create(options) {
323
- const {
324
- CacheManager,
325
- createStorageManager,
326
- createDefaultRegistry,
327
- CodexError: CodexError2,
328
- ConfigurationError: ConfigurationError2
329
- } = await import('@fractary/codex');
330
- const { readYamlConfig } = await Promise.resolve().then(() => (init_migrate_config(), migrate_config_exports));
331
- const { resolveEnvVarsInConfig } = await Promise.resolve().then(() => (init_config_types(), config_types_exports));
332
- try {
333
- const configPath = path4__namespace.join(process.cwd(), ".fractary", "config.yaml");
334
- let config;
335
- try {
336
- config = await readYamlConfig(configPath);
337
- config = resolveEnvVarsInConfig(config);
338
- } catch (error) {
339
- throw new ConfigurationError2(
340
- `Failed to load configuration from ${configPath}. Run "fractary codex init" to create a configuration.`
341
- );
342
- }
343
- const organization = options?.organizationSlug || config.organization;
344
- const cacheDir = options?.cacheDir || config.cacheDir || ".codex-cache";
345
- const storageConfig = {};
346
- if (config.storage && Array.isArray(config.storage)) {
347
- for (const provider of config.storage) {
348
- if (provider.type === "github") {
349
- storageConfig.github = {
350
- token: provider.token || process.env.GITHUB_TOKEN,
351
- apiBaseUrl: provider.apiBaseUrl || "https://api.github.com",
352
- branch: provider.branch || "main"
353
- };
354
- } else if (provider.type === "http") {
355
- storageConfig.http = {
356
- baseUrl: provider.baseUrl,
357
- headers: provider.headers,
358
- timeout: provider.timeout || 3e4
359
- };
360
- } else if (provider.type === "local") {
361
- storageConfig.local = {
362
- basePath: provider.basePath || "./knowledge",
363
- followSymlinks: provider.followSymlinks || false
364
- };
365
- }
366
- }
367
- }
368
- const storage = createStorageManager(storageConfig);
369
- const cache = new CacheManager({
370
- cacheDir,
371
- defaultTtl: 86400,
372
- // 24 hours
373
- maxMemoryEntries: 100,
374
- maxMemorySize: 50 * 1024 * 1024,
375
- // 50MB
376
- enablePersistence: true
377
- });
378
- cache.setStorageManager(storage);
379
- const types = createDefaultRegistry();
380
- if (config.types?.custom) {
381
- for (const [name, customType] of Object.entries(config.types.custom)) {
382
- const ct = customType;
383
- types.register({
384
- name,
385
- description: ct.description || `Custom type: ${name}`,
386
- patterns: ct.patterns || [],
387
- defaultTtl: ct.defaultTtl || 86400,
388
- archiveAfterDays: ct.archiveAfterDays !== void 0 ? ct.archiveAfterDays : null,
389
- archiveStorage: ct.archiveStorage || null
390
- });
391
- }
392
- }
393
- return new _CodexClient(cache, storage, types, organization);
394
- } catch (error) {
395
- if (error instanceof CodexError2) {
396
- throw error;
397
- }
398
- throw new CodexError2(
399
- `Failed to initialize CodexClient: ${error instanceof Error ? error.message : String(error)}`
400
- );
401
- }
402
- }
403
- /**
404
- * Fetch a document by codex:// URI
405
- *
406
- * This method:
407
- * 1. Validates the URI format
408
- * 2. Resolves the URI to a reference
409
- * 3. Uses CacheManager.get() which handles cache-first fetch
410
- *
411
- * @param uri - Codex URI (e.g., codex://org/project/path/to/file.md)
412
- * @param options - Fetch options
413
- * @returns Promise resolving to fetch result
414
- *
415
- * @throws {CodexError} If URI format is invalid or fetch fails
416
- *
417
- * @example
418
- * ```typescript
419
- * const result = await client.fetch('codex://fractary/codex/docs/README.md');
420
- * console.log(result.content.toString());
421
- * ```
422
- */
423
- async fetch(uri, options) {
424
- const { validateUri, resolveReference, CodexError: CodexError2 } = await import('@fractary/codex');
425
- if (!validateUri(uri)) {
426
- throw new CodexError2(`Invalid codex URI: ${uri}`);
427
- }
428
- const resolved = resolveReference(uri);
429
- if (!resolved) {
430
- throw new CodexError2(`Failed to resolve URI: ${uri}`);
431
- }
432
- try {
433
- if (options?.bypassCache) {
434
- const result2 = await this.storage.fetch(resolved);
435
- return {
436
- content: result2.content,
437
- fromCache: false,
438
- metadata: {
439
- fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
440
- contentLength: result2.size
441
- }
442
- };
443
- }
444
- const result = await this.cache.get(resolved, {
445
- ttl: options?.ttl
446
- });
447
- return {
448
- content: result.content,
449
- fromCache: true,
450
- // CacheManager.get handles cache logic
451
- metadata: {
452
- contentLength: result.size
453
- }
454
- };
455
- } catch (error) {
456
- throw new CodexError2(
457
- `Failed to fetch ${uri}: ${error instanceof Error ? error.message : String(error)}`
458
- );
459
- }
460
- }
461
- /**
462
- * Invalidate cache entries
463
- *
464
- * @param pattern - Optional glob pattern to match entries
465
- * If not provided, clears all entries
466
- *
467
- * @example
468
- * ```typescript
469
- * // Clear all cache
470
- * await client.invalidateCache();
471
- *
472
- * // Clear specific URI
473
- * await client.invalidateCache('codex://fractary/codex/docs/README.md');
474
- * ```
475
- */
476
- async invalidateCache(pattern) {
477
- if (pattern) {
478
- await this.cache.invalidate(pattern);
479
- } else {
480
- await this.cache.clear();
481
- }
482
- }
483
- /**
484
- * Get cache statistics
485
- *
486
- * @returns Promise resolving to cache stats
487
- *
488
- * @example
489
- * ```typescript
490
- * const stats = await client.getCacheStats();
491
- * console.log(`Cache entries: ${stats.totalEntries}`);
492
- * console.log(`Total size: ${stats.totalSize}`);
493
- * ```
494
- */
495
- async getCacheStats() {
496
- return this.cache.getStats();
497
- }
498
- /**
499
- * Get the type registry
500
- *
501
- * Provides access to built-in and custom artifact types
502
- *
503
- * @returns TypeRegistry instance
504
- *
505
- * @example
506
- * ```typescript
507
- * const registry = client.getTypeRegistry();
508
- * const types = registry.list();
509
- * ```
510
- */
511
- getTypeRegistry() {
512
- return this.types;
513
- }
514
- /**
515
- * Get the cache manager (for advanced operations)
516
- *
517
- * @returns CacheManager instance
518
- */
519
- getCacheManager() {
520
- return this.cache;
521
- }
522
- /**
523
- * Get the storage manager (for advanced operations)
524
- *
525
- * @returns StorageManager instance
526
- */
527
- getStorageManager() {
528
- return this.storage;
529
- }
530
- /**
531
- * Get the organization slug
532
- *
533
- * @returns Organization slug string
534
- */
535
- getOrganization() {
536
- return this.organization;
537
- }
538
- };
539
74
  }
540
75
  });
541
76
 
@@ -600,7 +135,7 @@ function getTempCodexPath(config) {
600
135
  const codexRepo = config.codex_repo || "codex";
601
136
  const sanitizedOrg = sanitizePathComponent(config.organization);
602
137
  const sanitizedRepo = sanitizePathComponent(codexRepo);
603
- return path4__namespace.join(
138
+ return path3__namespace.join(
604
139
  os__namespace.tmpdir(),
605
140
  "fractary-codex-clone",
606
141
  `${sanitizedOrg}-${sanitizedRepo}-${process.pid}`
@@ -608,8 +143,8 @@ function getTempCodexPath(config) {
608
143
  }
609
144
  async function isValidGitRepo(repoPath) {
610
145
  try {
611
- const gitDir = path4__namespace.join(repoPath, ".git");
612
- const stats = await fs__namespace.stat(gitDir);
146
+ const gitDir = path3__namespace.join(repoPath, ".git");
147
+ const stats = await fs2__namespace.stat(gitDir);
613
148
  return stats.isDirectory();
614
149
  } catch {
615
150
  return false;
@@ -641,8 +176,8 @@ async function execGit(repoPath, args) {
641
176
  }
642
177
  }
643
178
  async function gitClone(url, targetPath, options) {
644
- const parentDir = path4__namespace.dirname(targetPath);
645
- await fs__namespace.mkdir(parentDir, { recursive: true });
179
+ const parentDir = path3__namespace.dirname(targetPath);
180
+ await fs2__namespace.mkdir(parentDir, { recursive: true });
646
181
  const args = ["clone"];
647
182
  if (options?.depth) {
648
183
  if (!Number.isInteger(options.depth) || options.depth <= 0) {
@@ -689,12 +224,12 @@ async function ensureCodexCloned(config, options) {
689
224
  } catch (error) {
690
225
  console.warn(`Failed to update existing clone: ${error.message}`);
691
226
  console.warn(`Removing and cloning fresh...`);
692
- await fs__namespace.rm(tempPath, { recursive: true, force: true });
227
+ await fs2__namespace.rm(tempPath, { recursive: true, force: true });
693
228
  }
694
229
  }
695
230
  const repoUrl = getCodexRepoUrl(config);
696
231
  try {
697
- await fs__namespace.rm(tempPath, { recursive: true, force: true });
232
+ await fs2__namespace.rm(tempPath, { recursive: true, force: true });
698
233
  } catch (error) {
699
234
  console.warn(`Could not remove existing directory ${tempPath}: ${error.message}`);
700
235
  }
@@ -714,85 +249,162 @@ var init_codex_repository = __esm({
714
249
  // src/cli.ts
715
250
  init_cjs_shims();
716
251
 
717
- // src/commands/document/index.ts
718
- init_cjs_shims();
719
-
720
- // src/commands/document/fetch.ts
252
+ // src/commands/config/index.ts
721
253
  init_cjs_shims();
722
254
 
723
- // src/client/get-client.ts
255
+ // src/commands/config/initialize.ts
724
256
  init_cjs_shims();
725
- var clientInstance = null;
726
- async function getClient(options) {
727
- if (!clientInstance) {
728
- const { CodexClient: CodexClient2 } = await Promise.resolve().then(() => (init_codex_client(), codex_client_exports));
729
- clientInstance = await CodexClient2.create(options);
730
- }
731
- return clientInstance;
732
- }
733
-
734
- // src/commands/document/fetch.ts
735
- function hashContent(content) {
736
- return crypto__namespace.createHash("sha256").update(content).digest("hex").slice(0, 16);
737
- }
738
- function fetchCommand() {
739
- const cmd = new commander.Command("fetch");
740
- 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) => {
257
+ function configInitializeCommand() {
258
+ const cmd = new commander.Command("config-initialize");
259
+ cmd.description("Initialize codex section in .fractary/config.yaml (requires base config from @fractary/core)").option("--org <slug>", 'Organization slug (e.g., "fractary")').option("--project <name>", "Project name (default: derived from directory)").option("--codex-repo <name>", 'Codex repository name (e.g., "codex.fractary.com")').option("--sync-preset <name>", "Sync preset (standard, minimal)", "standard").option("--force", "Overwrite existing codex section").option("--no-mcp", "Skip MCP server installation").option("--json", "Output as JSON").action(async (options) => {
741
260
  try {
742
- const { validateUri } = await import('@fractary/codex');
743
- if (!validateUri(uri)) {
744
- console.error(chalk7__default.default.red("Error: Invalid URI format"));
745
- console.log(chalk7__default.default.dim("Expected: codex://org/project/path/to/file.md"));
746
- console.log(chalk7__default.default.dim("Example: codex://fractary/codex/docs/api.md"));
261
+ const configManager = codex.createConfigManager(process.cwd());
262
+ if (!options.json) {
263
+ console.log(chalk10__default.default.blue("Initializing codex configuration...\n"));
264
+ }
265
+ let org = options.org;
266
+ if (!org) {
267
+ org = await configManager.detectOrganization();
268
+ }
269
+ if (!org) {
270
+ try {
271
+ org = codex.resolveOrganization({
272
+ repoName: path3__namespace.basename(process.cwd())
273
+ });
274
+ } catch {
275
+ }
276
+ }
277
+ if (!org) {
278
+ org = path3__namespace.basename(process.cwd()).split("-")[0] || "default";
279
+ if (!options.json) {
280
+ console.log(chalk10__default.default.yellow(`\u26A0 Could not detect organization, using: ${org}`));
281
+ console.log(chalk10__default.default.dim(" Use --org <slug> to specify explicitly\n"));
282
+ }
283
+ } else if (!options.json) {
284
+ console.log(chalk10__default.default.dim(`Organization: ${chalk10__default.default.cyan(org)}
285
+ `));
286
+ }
287
+ const orgValidation = codex.validateNameFormat(org, "organization");
288
+ if (!orgValidation.valid) {
289
+ if (options.json) {
290
+ console.log(JSON.stringify({ error: orgValidation.error }, null, 2));
291
+ } else {
292
+ console.error(chalk10__default.default.red("Error:"), orgValidation.error);
293
+ }
747
294
  process.exit(1);
748
295
  }
749
- const client = await getClient();
750
- if (!options.json && !options.bypassCache) {
751
- console.error(chalk7__default.default.dim(`Fetching ${uri}...`));
296
+ let project = options.project;
297
+ if (!project) {
298
+ project = configManager.detectProject();
299
+ if (!options.json) {
300
+ console.log(chalk10__default.default.dim(`Project: ${chalk10__default.default.cyan(project)}
301
+ `));
302
+ }
752
303
  }
753
- const result = await client.fetch(uri, {
754
- bypassCache: options.bypassCache,
755
- ttl: options.ttl
756
- });
757
- if (options.json) {
758
- const output = {
759
- uri,
760
- content: result.content.toString("utf-8"),
761
- metadata: {
762
- fromCache: result.fromCache,
763
- fetchedAt: result.metadata?.fetchedAt,
764
- expiresAt: result.metadata?.expiresAt,
765
- contentLength: result.metadata?.contentLength || result.content.length,
766
- contentHash: hashContent(result.content)
304
+ let codexRepo = options.codexRepo;
305
+ if (codexRepo) {
306
+ const repoValidation = codex.validateNameFormat(codexRepo, "repository");
307
+ if (!repoValidation.valid) {
308
+ if (options.json) {
309
+ console.log(JSON.stringify({ error: repoValidation.error }, null, 2));
310
+ } else {
311
+ console.error(chalk10__default.default.red("Error:"), repoValidation.error);
767
312
  }
768
- };
769
- console.log(JSON.stringify(output, null, 2));
770
- } else if (options.output) {
771
- await fs__namespace.writeFile(options.output, result.content);
772
- console.log(chalk7__default.default.green("\u2713"), `Written to ${options.output}`);
773
- console.log(chalk7__default.default.dim(` Size: ${result.content.length} bytes`));
774
- if (result.fromCache) {
775
- console.log(chalk7__default.default.dim(" Source: cache"));
776
- } else {
777
- console.log(chalk7__default.default.dim(" Source: storage"));
313
+ process.exit(1);
314
+ }
315
+ if (!options.json) {
316
+ console.log(chalk10__default.default.dim(`Codex repository: ${chalk10__default.default.cyan(codexRepo)}
317
+ `));
778
318
  }
779
319
  } else {
780
- if (result.fromCache && !options.bypassCache) {
781
- console.error(chalk7__default.default.green("\u2713"), chalk7__default.default.dim("from cache\n"));
782
- } else {
783
- console.error(chalk7__default.default.green("\u2713"), chalk7__default.default.dim("fetched\n"));
320
+ const discoveryResult = await configManager.discoverCodexRepo(org);
321
+ if (discoveryResult.repo) {
322
+ codexRepo = discoveryResult.repo;
323
+ if (!options.json) {
324
+ console.log(chalk10__default.default.dim(`Codex repository: ${chalk10__default.default.cyan(codexRepo)} (auto-discovered)
325
+ `));
326
+ }
327
+ } else if (!options.json) {
328
+ if (discoveryResult.message) {
329
+ console.log(chalk10__default.default.dim(` Note: ${discoveryResult.message}
330
+ `));
331
+ }
784
332
  }
785
- console.log(result.content.toString("utf-8"));
786
333
  }
334
+ if (!codexRepo) {
335
+ codexRepo = `codex.${org}.com`;
336
+ if (!options.json) {
337
+ console.log(chalk10__default.default.yellow(`\u26A0 Could not discover codex repository in organization '${org}'`));
338
+ console.log(chalk10__default.default.dim(` Using default: ${chalk10__default.default.cyan(codexRepo)}
339
+ `));
340
+ }
341
+ }
342
+ const result = await configManager.initializeCodexSection({
343
+ organization: org,
344
+ project,
345
+ codexRepo,
346
+ syncPreset: options.syncPreset,
347
+ force: options.force,
348
+ skipMcp: options.mcp === false
349
+ });
350
+ if (options.json) {
351
+ console.log(
352
+ JSON.stringify(
353
+ {
354
+ success: true,
355
+ configPath: result.configPath,
356
+ codexSectionCreated: result.codexSectionCreated,
357
+ organization: org,
358
+ project,
359
+ codexRepo,
360
+ directories: result.directories,
361
+ gitignore: result.gitignore,
362
+ mcp: result.mcp
363
+ },
364
+ null,
365
+ 2
366
+ )
367
+ );
368
+ return;
369
+ }
370
+ console.log("Setting up codex directories...");
371
+ for (const dir of result.directories.created) {
372
+ console.log(chalk10__default.default.green("\u2713"), chalk10__default.default.dim(dir + "/"));
373
+ }
374
+ for (const dir of result.directories.alreadyExisted) {
375
+ console.log(chalk10__default.default.dim(" " + dir + "/ (exists)"));
376
+ }
377
+ if (result.gitignore.created) {
378
+ console.log(chalk10__default.default.green("\u2713"), chalk10__default.default.dim(".fractary/.gitignore (created)"));
379
+ } else if (result.gitignore.updated) {
380
+ console.log(chalk10__default.default.green("\u2713"), chalk10__default.default.dim(".fractary/.gitignore (updated)"));
381
+ } else {
382
+ console.log(chalk10__default.default.green("\u2713"), chalk10__default.default.dim(".fractary/.gitignore (exists)"));
383
+ }
384
+ console.log(chalk10__default.default.green("\u2713"), chalk10__default.default.dim(".fractary/config.yaml (codex section added)"));
385
+ if (result.mcp) {
386
+ if (result.mcp.alreadyInstalled) {
387
+ console.log(chalk10__default.default.green("\u2713"), chalk10__default.default.dim(".mcp.json (already configured)"));
388
+ } else if (result.mcp.migrated) {
389
+ console.log(chalk10__default.default.green("\u2713"), chalk10__default.default.dim(".mcp.json (migrated from old format)"));
390
+ } else if (result.mcp.installed) {
391
+ console.log(chalk10__default.default.green("\u2713"), chalk10__default.default.dim(".mcp.json (created)"));
392
+ }
393
+ }
394
+ console.log(chalk10__default.default.green("\n\u2713 Codex configuration initialized successfully!\n"));
395
+ console.log(chalk10__default.default.bold("Configuration:"));
396
+ console.log(chalk10__default.default.dim(` Organization: ${org}`));
397
+ console.log(chalk10__default.default.dim(` Project: ${project}`));
398
+ console.log(chalk10__default.default.dim(` Codex Repository: ${codexRepo}`));
399
+ console.log(chalk10__default.default.bold("\nNext steps:"));
400
+ console.log(chalk10__default.default.dim(" 1. Restart Claude Code to load the MCP server"));
401
+ console.log(chalk10__default.default.dim(` 2. Verify codex repository access: gh repo view ${org}/${codexRepo}`));
402
+ console.log(chalk10__default.default.dim(" 3. Run first sync: /fractary-codex:sync --from-codex --dry-run"));
787
403
  } catch (error) {
788
- console.error(chalk7__default.default.red("Error:"), error.message);
789
- if (error.message.includes("Failed to load configuration")) {
790
- console.log(chalk7__default.default.dim('\nRun "fractary codex init" to create a configuration.'));
791
- } else if (error.message.includes("GITHUB_TOKEN")) {
792
- console.log(chalk7__default.default.dim('\nSet your GitHub token: export GITHUB_TOKEN="your_token"'));
793
- } else if (error.message.includes("not found") || error.message.includes("404")) {
794
- console.log(chalk7__default.default.dim("\nThe document may not exist or you may not have access."));
795
- console.log(chalk7__default.default.dim("Check the URI and ensure your storage providers are configured correctly."));
404
+ if (options.json) {
405
+ console.log(JSON.stringify({ error: error.message }, null, 2));
406
+ } else {
407
+ console.error(chalk10__default.default.red("Error:"), error.message);
796
408
  }
797
409
  process.exit(1);
798
410
  }
@@ -800,612 +412,345 @@ function fetchCommand() {
800
412
  return cmd;
801
413
  }
802
414
 
803
- // src/commands/document/index.ts
804
- function documentCommand() {
805
- const cmd = new commander.Command("document");
806
- cmd.description("Manage document operations");
807
- cmd.addCommand(fetchCommand());
808
- return cmd;
809
- }
810
-
811
- // src/commands/config/index.ts
812
- init_cjs_shims();
813
-
814
- // src/commands/config/init.ts
815
- init_cjs_shims();
816
-
817
- // src/config/unified-config.ts
415
+ // src/commands/config/update.ts
818
416
  init_cjs_shims();
819
- function sanitizeForS3BucketName(name) {
820
- return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/^-+|-+$/g, "").replace(/-+/g, "-").substring(0, 63);
821
- }
822
- function getDefaultUnifiedConfig(organization, project, codexRepo) {
823
- const sanitizedProject = sanitizeForS3BucketName(project);
824
- return {
825
- file: {
826
- schema_version: codex.CONFIG_SCHEMA_VERSION,
827
- sources: {
828
- specs: {
829
- type: "s3",
830
- bucket: `${sanitizedProject}-files`,
831
- prefix: "specs/",
832
- region: "us-east-1",
833
- local: {
834
- base_path: ".fractary/specs"
835
- },
836
- push: {
837
- compress: false,
838
- keep_local: true
839
- },
840
- auth: {
841
- profile: "default"
842
- }
843
- },
844
- logs: {
845
- type: "s3",
846
- bucket: `${sanitizedProject}-files`,
847
- prefix: "logs/",
848
- region: "us-east-1",
849
- local: {
850
- base_path: ".fractary/logs"
851
- },
852
- push: {
853
- compress: true,
854
- keep_local: true
855
- },
856
- auth: {
857
- profile: "default"
858
- }
417
+ function configUpdateCommand() {
418
+ const cmd = new commander.Command("config-update");
419
+ cmd.description("Update codex configuration fields in .fractary/config.yaml").option("--org <slug>", "Update organization slug").option("--project <name>", "Update project name").option("--codex-repo <name>", "Update codex repository name").option("--sync-preset <name>", "Update sync preset (standard, minimal)").option("--no-mcp", "Skip MCP server update").option("--json", "Output as JSON").action(async (options) => {
420
+ try {
421
+ const configManager = codex.createConfigManager(process.cwd());
422
+ const updateOptions = {
423
+ skipMcp: options.mcp === false
424
+ };
425
+ let hasUpdates = false;
426
+ if (options.org !== void 0) {
427
+ updateOptions.organization = options.org;
428
+ hasUpdates = true;
429
+ }
430
+ if (options.project !== void 0) {
431
+ updateOptions.project = options.project;
432
+ hasUpdates = true;
433
+ }
434
+ if (options.codexRepo !== void 0) {
435
+ updateOptions.codexRepo = options.codexRepo;
436
+ hasUpdates = true;
437
+ }
438
+ if (options.syncPreset !== void 0) {
439
+ updateOptions.syncPreset = options.syncPreset;
440
+ hasUpdates = true;
441
+ }
442
+ if (!hasUpdates) {
443
+ if (options.json) {
444
+ console.log(JSON.stringify({ error: "No fields to update. Provide at least one of: --org, --project, --codex-repo, --sync-preset" }, null, 2));
445
+ } else {
446
+ console.error(chalk10__default.default.red("Error:"), "No fields to update. Provide at least one of: --org, --project, --codex-repo, --sync-preset");
859
447
  }
448
+ process.exit(1);
449
+ }
450
+ if (!options.json) {
451
+ console.log(chalk10__default.default.blue("Updating codex configuration...\n"));
860
452
  }
861
- },
862
- codex: {
863
- schema_version: codex.CONFIG_SCHEMA_VERSION,
864
- organization,
865
- project,
866
- codex_repo: codexRepo,
867
- remotes: {
868
- // The codex repository - uses same token as git operations
869
- [`${organization}/${codexRepo}`]: {
870
- token: "${GITHUB_TOKEN}"
453
+ const result = await configManager.updateCodexSection(updateOptions);
454
+ if (options.json) {
455
+ console.log(
456
+ JSON.stringify(
457
+ {
458
+ success: true,
459
+ configPath: result.configPath,
460
+ fieldsUpdated: result.fieldsUpdated,
461
+ mcp: result.mcp
462
+ },
463
+ null,
464
+ 2
465
+ )
466
+ );
467
+ return;
468
+ }
469
+ if (result.fieldsUpdated.length === 0) {
470
+ console.log(chalk10__default.default.yellow("No fields were updated."));
471
+ return;
472
+ }
473
+ for (const field of result.fieldsUpdated) {
474
+ console.log(chalk10__default.default.green("\u2713"), chalk10__default.default.dim(`Updated: ${field}`));
475
+ }
476
+ if (result.mcp) {
477
+ if (result.mcp.alreadyInstalled) {
478
+ console.log(chalk10__default.default.green("\u2713"), chalk10__default.default.dim(".mcp.json (already configured)"));
479
+ } else if (result.mcp.installed) {
480
+ console.log(chalk10__default.default.green("\u2713"), chalk10__default.default.dim(".mcp.json (updated)"));
871
481
  }
872
482
  }
483
+ console.log(chalk10__default.default.green("\n\u2713 Codex configuration updated successfully!"));
484
+ } catch (error) {
485
+ if (options.json) {
486
+ console.log(JSON.stringify({ error: error.message }, null, 2));
487
+ } else {
488
+ console.error(chalk10__default.default.red("Error:"), error.message);
489
+ }
490
+ process.exit(1);
873
491
  }
874
- };
875
- }
876
- async function readUnifiedConfig(configPath) {
877
- try {
878
- const content = await fs__namespace.readFile(configPath, "utf-8");
879
- const config = yaml2__namespace.load(content);
880
- return config;
881
- } catch (error) {
882
- if (error.code === "ENOENT") {
883
- return null;
884
- }
885
- throw error;
886
- }
887
- }
888
- async function writeUnifiedConfig(config, outputPath) {
889
- const dir = path4__namespace.dirname(outputPath);
890
- await fs__namespace.mkdir(dir, { recursive: true });
891
- const yamlContent = yaml2__namespace.dump(config, {
892
- indent: 2,
893
- lineWidth: 120,
894
- noRefs: true,
895
- sortKeys: false
896
492
  });
897
- await fs__namespace.writeFile(outputPath, yamlContent, "utf-8");
898
- }
899
- function mergeUnifiedConfigs(existing, updates) {
900
- const merged = {};
901
- if (updates.file || existing.file) {
902
- merged.file = {
903
- schema_version: updates.file?.schema_version || existing.file?.schema_version || codex.CONFIG_SCHEMA_VERSION,
904
- sources: {
905
- ...existing.file?.sources || {},
906
- ...updates.file?.sources || {}
907
- }
908
- };
909
- }
910
- if (updates.codex || existing.codex) {
911
- merged.codex = {
912
- schema_version: updates.codex?.schema_version || existing.codex?.schema_version || codex.CONFIG_SCHEMA_VERSION,
913
- organization: updates.codex?.organization || existing.codex?.organization || "default",
914
- project: updates.codex?.project || existing.codex?.project || "default",
915
- codex_repo: updates.codex?.codex_repo || existing.codex?.codex_repo || "",
916
- remotes: {
917
- ...existing.codex?.remotes || {},
918
- ...updates.codex?.remotes || {}
919
- }
920
- };
921
- }
922
- return merged;
923
- }
924
- async function initializeUnifiedConfig(configPath, organization, project, codexRepo, options) {
925
- const existingConfig = await readUnifiedConfig(configPath);
926
- if (existingConfig && !options?.force) {
927
- const defaultConfig = getDefaultUnifiedConfig(organization, project, codexRepo);
928
- const merged = mergeUnifiedConfigs(existingConfig, defaultConfig);
929
- await writeUnifiedConfig(merged, configPath);
930
- return {
931
- created: false,
932
- merged: true,
933
- config: merged
934
- };
935
- }
936
- const config = getDefaultUnifiedConfig(organization, project, codexRepo);
937
- await writeUnifiedConfig(config, configPath);
938
- return {
939
- created: true,
940
- merged: false,
941
- config
942
- };
493
+ return cmd;
943
494
  }
944
495
 
945
- // src/config/gitignore-utils.ts
496
+ // src/commands/config/validate.ts
946
497
  init_cjs_shims();
947
- var DEFAULT_FRACTARY_GITIGNORE = `# .fractary/.gitignore
948
- # This file is managed by multiple plugins - each plugin manages its own section
949
-
950
- # ===== fractary-codex (managed) =====
951
- codex/cache/
952
- # ===== end fractary-codex =====
953
- `;
954
- async function readFractaryGitignore(projectRoot) {
955
- const gitignorePath = path4__namespace.join(projectRoot, ".fractary", ".gitignore");
956
- try {
957
- return await fs__namespace.readFile(gitignorePath, "utf-8");
958
- } catch (error) {
959
- if (error.code === "ENOENT") {
960
- return null;
961
- }
962
- throw error;
963
- }
964
- }
965
- async function writeFractaryGitignore(projectRoot, content) {
966
- const gitignorePath = path4__namespace.join(projectRoot, ".fractary", ".gitignore");
967
- await fs__namespace.mkdir(path4__namespace.join(projectRoot, ".fractary"), { recursive: true });
968
- await fs__namespace.writeFile(gitignorePath, content, "utf-8");
969
- }
970
- function normalizeCachePath(cachePath) {
971
- let normalized = cachePath.replace(/\\/g, "/");
972
- normalized = normalized.replace(/^\.fractary\//, "");
973
- if (!normalized.endsWith("/")) {
974
- normalized += "/";
975
- }
976
- return normalized;
977
- }
978
- function isCachePathIgnored(gitignoreContent, cachePath) {
979
- const normalized = normalizeCachePath(cachePath);
980
- const lines = gitignoreContent.split("\n").map((l) => l.trim());
981
- return lines.some((line) => {
982
- if (line.startsWith("#") || line === "") return false;
983
- let normalizedLine = line.replace(/\\/g, "/");
984
- if (!normalizedLine.endsWith("/")) {
985
- normalizedLine += "/";
498
+ function configValidateCommand() {
499
+ const cmd = new commander.Command("config-validate");
500
+ cmd.description("Validate codex configuration in .fractary/config.yaml (read-only)").option("--json", "Output as JSON").action(async (options) => {
501
+ try {
502
+ const configManager = codex.createConfigManager(process.cwd());
503
+ if (!options.json) {
504
+ console.log(chalk10__default.default.blue("Validating codex configuration...\n"));
505
+ }
506
+ const result = await configManager.validateCodexConfig();
507
+ if (options.json) {
508
+ console.log(JSON.stringify(result, null, 2));
509
+ if (!result.valid) {
510
+ process.exit(1);
511
+ }
512
+ return;
513
+ }
514
+ if (result.errors.length > 0) {
515
+ console.log(chalk10__default.default.red.bold("Errors:"));
516
+ for (const error of result.errors) {
517
+ console.log(chalk10__default.default.red(" \u2717"), `${error.field}: ${error.message}`);
518
+ }
519
+ console.log();
520
+ }
521
+ if (result.warnings.length > 0) {
522
+ console.log(chalk10__default.default.yellow.bold("Warnings:"));
523
+ for (const warning of result.warnings) {
524
+ console.log(chalk10__default.default.yellow(" \u26A0"), `${warning.field}: ${warning.message}`);
525
+ }
526
+ console.log();
527
+ }
528
+ if (result.valid) {
529
+ if (result.warnings.length === 0) {
530
+ console.log(chalk10__default.default.green("\u2713 Codex configuration is valid with no warnings."));
531
+ } else {
532
+ console.log(chalk10__default.default.green("\u2713 Codex configuration is valid"), chalk10__default.default.yellow(`(${result.warnings.length} warning${result.warnings.length > 1 ? "s" : ""})`));
533
+ }
534
+ } else {
535
+ console.log(chalk10__default.default.red(`\u2717 Codex configuration is invalid (${result.errors.length} error${result.errors.length > 1 ? "s" : ""})`));
536
+ process.exit(1);
537
+ }
538
+ } catch (error) {
539
+ if (options.json) {
540
+ console.log(JSON.stringify({ error: error.message }, null, 2));
541
+ } else {
542
+ console.error(chalk10__default.default.red("Error:"), error.message);
543
+ }
544
+ process.exit(1);
986
545
  }
987
- return normalizedLine === normalized;
988
546
  });
989
- }
990
- function addCachePathToGitignore(gitignoreContent, cachePath, comment) {
991
- const normalized = normalizeCachePath(cachePath);
992
- if (isCachePathIgnored(gitignoreContent, cachePath)) {
993
- return gitignoreContent;
994
- }
995
- let addition = "";
996
- {
997
- addition += `
998
- # ${comment}
999
- `;
1000
- }
1001
- addition += normalized + "\n";
1002
- return gitignoreContent.trimEnd() + addition;
1003
- }
1004
- async function ensureCachePathIgnored(projectRoot, cachePath) {
1005
- const gitignorePath = path4__namespace.join(projectRoot, ".fractary", ".gitignore");
1006
- let relativeCachePath = cachePath;
1007
- if (path4__namespace.isAbsolute(cachePath)) {
1008
- relativeCachePath = path4__namespace.relative(path4__namespace.join(projectRoot, ".fractary"), cachePath);
1009
- }
1010
- relativeCachePath = normalizeCachePath(relativeCachePath);
1011
- let content = await readFractaryGitignore(projectRoot);
1012
- const gitignoreExists = content !== null;
1013
- if (!gitignoreExists) {
1014
- content = DEFAULT_FRACTARY_GITIGNORE;
1015
- if (!isCachePathIgnored(content, relativeCachePath)) {
1016
- content = addCachePathToGitignore(content, relativeCachePath, "Custom cache directory");
1017
- }
1018
- await writeFractaryGitignore(projectRoot, content);
1019
- return {
1020
- created: true,
1021
- updated: false,
1022
- alreadyIgnored: false,
1023
- gitignorePath
1024
- };
1025
- }
1026
- if (isCachePathIgnored(content, relativeCachePath)) {
1027
- return {
1028
- created: false,
1029
- updated: false,
1030
- alreadyIgnored: true,
1031
- gitignorePath
1032
- };
1033
- }
1034
- content = addCachePathToGitignore(content, relativeCachePath, "Custom cache directory");
1035
- await writeFractaryGitignore(projectRoot, content);
1036
- return {
1037
- created: false,
1038
- updated: true,
1039
- alreadyIgnored: false,
1040
- gitignorePath
1041
- };
547
+ return cmd;
1042
548
  }
1043
549
 
1044
550
  // src/commands/config/init.ts
1045
- function validateNameFormat(name, type) {
1046
- if (!name || typeof name !== "string") {
1047
- throw new Error(`${type} name is required`);
1048
- }
1049
- if (name.length > 100) {
1050
- throw new Error(`${type} name too long (max 100 characters)`);
1051
- }
1052
- const safePattern = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
1053
- if (!safePattern.test(name)) {
1054
- throw new Error(
1055
- `Invalid ${type} name format: "${name}". Must start with alphanumeric and contain only: a-z, A-Z, 0-9, ., -, _`
1056
- );
1057
- }
1058
- }
1059
- async function getOrgFromGitRemote() {
1060
- try {
1061
- const { execSync } = __require("child_process");
1062
- const remote = execSync("git remote get-url origin 2>/dev/null", { encoding: "utf-8" }).trim();
1063
- const sshMatch = remote.match(/git@github\.com:([^/]+)\//);
1064
- const httpsMatch = remote.match(/github\.com\/([^/]+)\//);
1065
- return sshMatch?.[1] || httpsMatch?.[1] || null;
1066
- } catch {
1067
- return null;
1068
- }
1069
- }
1070
- async function discoverCodexRepo(org) {
1071
- try {
1072
- validateNameFormat(org, "organization");
1073
- } catch (error) {
1074
- return { repo: null, error: "unknown", message: error.message };
1075
- }
1076
- try {
1077
- const { execSync } = __require("child_process");
1078
- try {
1079
- execSync("gh --version", { encoding: "utf-8", stdio: "pipe" });
1080
- } catch {
1081
- return {
1082
- repo: null,
1083
- error: "gh_not_installed",
1084
- message: "GitHub CLI (gh) is not installed. Install from https://cli.github.com/"
1085
- };
1086
- }
1087
- try {
1088
- execSync("gh auth status", { encoding: "utf-8", stdio: "pipe" });
1089
- } catch {
1090
- return {
1091
- repo: null,
1092
- error: "auth_failed",
1093
- message: "GitHub CLI not authenticated. Run: gh auth login"
1094
- };
1095
- }
1096
- const result = execSync(
1097
- `gh repo list ${org} --json name --jq '.[].name | select(startswith("codex."))' 2>&1`,
1098
- { encoding: "utf-8" }
1099
- ).trim();
1100
- if (result.includes("Could not resolve to an Organization") || result.includes("Not Found")) {
1101
- return {
1102
- repo: null,
1103
- error: "org_not_found",
1104
- message: `Organization '${org}' not found on GitHub`
1105
- };
1106
- }
1107
- const repos = result.split("\n").filter(Boolean);
1108
- if (repos.length === 0) {
1109
- return {
1110
- repo: null,
1111
- error: "no_repos_found",
1112
- message: `No codex.* repositories found in organization '${org}'`
1113
- };
1114
- }
1115
- return { repo: repos[0] };
1116
- } catch (error) {
1117
- return {
1118
- repo: null,
1119
- error: "unknown",
1120
- message: error.message || "Unknown error during discovery"
1121
- };
1122
- }
1123
- }
1124
- async function fileExists(filePath) {
1125
- try {
1126
- await fs__namespace.access(filePath);
1127
- return true;
1128
- } catch {
1129
- return false;
551
+ init_cjs_shims();
552
+
553
+ // src/commands/document/index.ts
554
+ init_cjs_shims();
555
+
556
+ // src/commands/document/fetch.ts
557
+ init_cjs_shims();
558
+
559
+ // src/client/get-client.ts
560
+ init_cjs_shims();
561
+ var clientInstance = null;
562
+ async function getClient(options) {
563
+ if (!clientInstance) {
564
+ const { CodexClient: CodexClient2 } = await Promise.resolve().then(() => (init_codex_client(), codex_client_exports));
565
+ clientInstance = await CodexClient2.create(options);
1130
566
  }
567
+ return clientInstance;
1131
568
  }
1132
- async function installMcpServer(projectRoot, configPath = ".fractary/config.yaml", options = {}) {
1133
- const mcpJsonPath = path4__namespace.join(projectRoot, ".mcp.json");
1134
- const { backup = true } = options;
1135
- let existingConfig = { mcpServers: {} };
1136
- let backupPath;
1137
- let migrated = false;
1138
- if (await fileExists(mcpJsonPath)) {
1139
- try {
1140
- const content = await fs__namespace.readFile(mcpJsonPath, "utf-8");
1141
- existingConfig = JSON.parse(content);
1142
- if (backup) {
1143
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").slice(0, 18);
1144
- const suffix = Math.random().toString(36).substring(2, 6);
1145
- backupPath = `${mcpJsonPath}.backup.${timestamp}-${suffix}`;
1146
- await fs__namespace.writeFile(backupPath, content);
1147
- }
1148
- } catch {
1149
- console.log(chalk7__default.default.yellow("\u26A0 Warning: .mcp.json contains invalid JSON, starting fresh"));
1150
- existingConfig = { mcpServers: {} };
1151
- }
1152
- }
1153
- if (!existingConfig.mcpServers) {
1154
- existingConfig.mcpServers = {};
1155
- }
1156
- const existing = existingConfig.mcpServers["fractary-codex"];
1157
- if (existing) {
1158
- const existingCommand = existing.command;
1159
- const existingArgs = existing.args || [];
1160
- if (existingCommand === "npx" && existingArgs.includes("@fractary/codex-mcp")) {
1161
- return {
1162
- installed: false,
1163
- migrated: false,
1164
- alreadyInstalled: true,
1165
- backupPath
1166
- };
1167
- }
1168
- if (existingCommand === "node" || existingArgs.includes("@fractary/codex")) {
1169
- migrated = true;
1170
- }
1171
- }
1172
- existingConfig.mcpServers["fractary-codex"] = {
1173
- command: "npx",
1174
- args: ["-y", "@fractary/codex-mcp", "--config", configPath]
1175
- };
1176
- await fs__namespace.writeFile(
1177
- mcpJsonPath,
1178
- JSON.stringify(existingConfig, null, 2) + "\n"
1179
- );
1180
- return {
1181
- installed: true,
1182
- migrated,
1183
- alreadyInstalled: false,
1184
- backupPath
1185
- };
569
+
570
+ // src/commands/document/fetch.ts
571
+ function hashContent(content) {
572
+ return crypto__namespace.createHash("sha256").update(content).digest("hex").slice(0, 16);
1186
573
  }
1187
- function initCommand() {
1188
- const cmd = new commander.Command("init");
1189
- cmd.description("Initialize unified Fractary configuration (.fractary/config.yaml)").option("--org <slug>", 'Organization slug (e.g., "fractary")').option("--project <name>", "Project name (default: derived from directory)").option("--codex-repo <name>", 'Codex repository name (e.g., "codex.fractary.com")').option("--force", "Overwrite existing configuration").option("--no-mcp", "Skip MCP server installation").action(async (options) => {
574
+ function documentFetchCommand() {
575
+ const cmd = new commander.Command("document-fetch");
576
+ 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) => {
1190
577
  try {
1191
- console.log(chalk7__default.default.blue("Initializing unified Fractary configuration...\n"));
1192
- let org = options.org;
1193
- if (!org) {
1194
- org = await getOrgFromGitRemote();
1195
- }
1196
- if (!org) {
1197
- try {
1198
- const { resolveOrganization } = await import('@fractary/codex');
1199
- org = resolveOrganization({
1200
- repoName: path4__namespace.basename(process.cwd())
1201
- });
1202
- } catch {
1203
- }
1204
- }
1205
- if (!org) {
1206
- org = path4__namespace.basename(process.cwd()).split("-")[0] || "default";
1207
- console.log(chalk7__default.default.yellow(`\u26A0 Could not detect organization, using: ${org}`));
1208
- console.log(chalk7__default.default.dim(" Use --org <slug> to specify explicitly\n"));
1209
- } else {
1210
- console.log(chalk7__default.default.dim(`Organization: ${chalk7__default.default.cyan(org)}
1211
- `));
1212
- }
1213
- try {
1214
- validateNameFormat(org, "organization");
1215
- } catch (error) {
1216
- console.error(chalk7__default.default.red("Error:"), error.message);
578
+ const { validateUri } = await import('@fractary/codex');
579
+ if (!validateUri(uri)) {
580
+ console.error(chalk10__default.default.red("Error: Invalid URI format"));
581
+ console.log(chalk10__default.default.dim("Expected: codex://org/project/path/to/file.md"));
582
+ console.log(chalk10__default.default.dim("Example: codex://fractary/codex/docs/api.md"));
1217
583
  process.exit(1);
1218
584
  }
1219
- let project = options.project;
1220
- if (!project) {
1221
- project = path4__namespace.basename(process.cwd());
1222
- console.log(chalk7__default.default.dim(`Project: ${chalk7__default.default.cyan(project)}
1223
- `));
585
+ const client = await getClient();
586
+ if (!options.json && !options.bypassCache) {
587
+ console.error(chalk10__default.default.dim(`Fetching ${uri}...`));
1224
588
  }
1225
- let codexRepo = options.codexRepo;
1226
- if (codexRepo) {
1227
- try {
1228
- validateNameFormat(codexRepo, "repository");
1229
- } catch (error) {
1230
- console.error(chalk7__default.default.red("Error:"), error.message);
1231
- process.exit(1);
1232
- }
1233
- console.log(chalk7__default.default.dim(`Codex repository: ${chalk7__default.default.cyan(codexRepo)}
1234
- `));
1235
- } else {
1236
- const discoveryResult = await discoverCodexRepo(org);
1237
- if (discoveryResult.repo) {
1238
- codexRepo = discoveryResult.repo;
1239
- console.log(chalk7__default.default.dim(`Codex repository: ${chalk7__default.default.cyan(codexRepo)} (auto-discovered)
1240
- `));
1241
- } else {
1242
- if (discoveryResult.error === "gh_not_installed") {
1243
- console.log(chalk7__default.default.dim(` Note: ${discoveryResult.message}
1244
- `));
1245
- } else if (discoveryResult.error === "auth_failed") {
1246
- console.log(chalk7__default.default.dim(` Note: ${discoveryResult.message}
1247
- `));
1248
- } else if (discoveryResult.error === "org_not_found") {
1249
- console.log(chalk7__default.default.dim(` Note: ${discoveryResult.message}
1250
- `));
589
+ const result = await client.fetch(uri, {
590
+ bypassCache: options.bypassCache,
591
+ ttl: options.ttl
592
+ });
593
+ if (options.json) {
594
+ const output = {
595
+ uri,
596
+ content: result.content.toString("utf-8"),
597
+ metadata: {
598
+ fromCache: result.fromCache,
599
+ fetchedAt: result.metadata?.fetchedAt,
600
+ expiresAt: result.metadata?.expiresAt,
601
+ contentLength: result.metadata?.contentLength || result.content.length,
602
+ contentHash: hashContent(result.content)
1251
603
  }
604
+ };
605
+ console.log(JSON.stringify(output, null, 2));
606
+ } else if (options.output) {
607
+ await fs2__namespace.writeFile(options.output, result.content);
608
+ console.log(chalk10__default.default.green("\u2713"), `Written to ${options.output}`);
609
+ console.log(chalk10__default.default.dim(` Size: ${result.content.length} bytes`));
610
+ if (result.fromCache) {
611
+ console.log(chalk10__default.default.dim(" Source: cache"));
612
+ } else {
613
+ console.log(chalk10__default.default.dim(" Source: storage"));
1252
614
  }
1253
- }
1254
- if (!codexRepo) {
1255
- console.log(chalk7__default.default.yellow(`\u26A0 Could not discover codex repository in organization '${org}'`));
1256
- console.log(chalk7__default.default.dim(" Use --codex-repo <name> to specify explicitly"));
1257
- console.log(chalk7__default.default.dim(" Expected naming convention: codex.{org}.{tld} (e.g., codex.fractary.com)\n"));
1258
- codexRepo = `codex.${org}.com`;
1259
- console.log(chalk7__default.default.dim(` Using default: ${chalk7__default.default.cyan(codexRepo)}
1260
- `));
1261
- }
1262
- const configPath = path4__namespace.join(process.cwd(), ".fractary", "config.yaml");
1263
- const configExists = await fileExists(configPath);
1264
- if (configExists && !options.force) {
1265
- console.log(chalk7__default.default.yellow(`\u26A0 Configuration already exists at .fractary/config.yaml`));
1266
- console.log(chalk7__default.default.dim("Merging with existing configuration...\n"));
1267
- }
1268
- console.log("Creating directory structure...");
1269
- const dirs = [
1270
- ".fractary",
1271
- ".fractary/specs",
1272
- ".fractary/logs",
1273
- ".fractary/codex",
1274
- ".fractary/codex/cache"
1275
- ];
1276
- for (const dir of dirs) {
1277
- await fs__namespace.mkdir(path4__namespace.join(process.cwd(), dir), { recursive: true });
1278
- console.log(chalk7__default.default.green("\u2713"), chalk7__default.default.dim(dir + "/"));
1279
- }
1280
- const gitignoreResult = await ensureCachePathIgnored(process.cwd(), ".fractary/codex/cache");
1281
- if (gitignoreResult.created) {
1282
- console.log(chalk7__default.default.green("\u2713"), chalk7__default.default.dim(".fractary/.gitignore (created)"));
1283
- } else if (gitignoreResult.updated) {
1284
- console.log(chalk7__default.default.green("\u2713"), chalk7__default.default.dim(".fractary/.gitignore (updated)"));
1285
615
  } else {
1286
- console.log(chalk7__default.default.green("\u2713"), chalk7__default.default.dim(".fractary/.gitignore (exists)"));
1287
- }
1288
- console.log("\nInitializing configuration...");
1289
- const result = await initializeUnifiedConfig(
1290
- configPath,
1291
- org,
1292
- project,
1293
- codexRepo,
1294
- { force: options.force }
1295
- );
1296
- if (result.created) {
1297
- console.log(chalk7__default.default.green("\u2713"), chalk7__default.default.dim(".fractary/config.yaml (created)"));
1298
- } else if (result.merged) {
1299
- console.log(chalk7__default.default.green("\u2713"), chalk7__default.default.dim(".fractary/config.yaml (merged with existing)"));
1300
- }
1301
- if (options.mcp !== false) {
1302
- console.log("\nConfiguring MCP server...");
1303
- const mcpResult = await installMcpServer(process.cwd(), ".fractary/config.yaml");
1304
- if (mcpResult.alreadyInstalled) {
1305
- console.log(chalk7__default.default.green("\u2713"), chalk7__default.default.dim(".mcp.json (already configured)"));
1306
- } else if (mcpResult.migrated) {
1307
- console.log(chalk7__default.default.green("\u2713"), chalk7__default.default.dim(".mcp.json (migrated from old format)"));
1308
- if (mcpResult.backupPath) {
1309
- console.log(chalk7__default.default.dim(` Backup: ${path4__namespace.basename(mcpResult.backupPath)}`));
1310
- }
1311
- } else if (mcpResult.installed) {
1312
- console.log(chalk7__default.default.green("\u2713"), chalk7__default.default.dim(".mcp.json (created)"));
616
+ if (result.fromCache && !options.bypassCache) {
617
+ console.error(chalk10__default.default.green("\u2713"), chalk10__default.default.dim("from cache\n"));
618
+ } else {
619
+ console.error(chalk10__default.default.green("\u2713"), chalk10__default.default.dim("fetched\n"));
1313
620
  }
621
+ console.log(result.content.toString("utf-8"));
1314
622
  }
1315
- console.log(chalk7__default.default.green("\n\u2713 Unified configuration initialized successfully!\n"));
1316
- console.log(chalk7__default.default.bold("Configuration:"));
1317
- console.log(chalk7__default.default.dim(` Organization: ${org}`));
1318
- console.log(chalk7__default.default.dim(` Project: ${project}`));
1319
- console.log(chalk7__default.default.dim(` Codex Repository: ${codexRepo}`));
1320
- console.log(chalk7__default.default.dim(` Config: .fractary/config.yaml`));
1321
- console.log(chalk7__default.default.bold("\nFile plugin sources:"));
1322
- console.log(chalk7__default.default.dim(" - specs: .fractary/specs/ \u2192 S3"));
1323
- console.log(chalk7__default.default.dim(" - logs: .fractary/logs/ \u2192 S3"));
1324
- console.log(chalk7__default.default.bold("\nCodex plugin:"));
1325
- console.log(chalk7__default.default.dim(" - Cache: .fractary/codex/cache/"));
1326
- console.log(chalk7__default.default.dim(" - MCP Server: @fractary/codex-mcp (via npx)"));
1327
- console.log(chalk7__default.default.dim(" - Remotes: codex repo configured"));
1328
- console.log(chalk7__default.default.bold("\nGit Authentication:"));
1329
- console.log(chalk7__default.default.dim(" Codex sync uses your existing git credentials."));
1330
- console.log(chalk7__default.default.dim(" Ensure you have access to the codex repository:"));
1331
- console.log(chalk7__default.default.dim(` gh repo view ${org}/${codexRepo}`));
1332
- console.log(chalk7__default.default.dim(" Or set GITHUB_TOKEN environment variable."));
1333
- console.log(chalk7__default.default.bold("\nNext steps:"));
1334
- console.log(chalk7__default.default.dim(" 1. Restart Claude Code to load the MCP server"));
1335
- console.log(chalk7__default.default.dim(" 2. Verify codex repository access: gh repo view " + org + "/" + codexRepo));
1336
- console.log(chalk7__default.default.dim(" 3. Configure AWS credentials for S3 access (if using file plugin)"));
1337
- console.log(chalk7__default.default.dim(" 4. Edit .fractary/config.yaml to add external project remotes"));
1338
- console.log(chalk7__default.default.dim(" 5. Reference docs via codex:// URIs (auto-fetched by MCP)"));
1339
623
  } catch (error) {
1340
- console.error(chalk7__default.default.red("Error:"), error.message);
624
+ console.error(chalk10__default.default.red("Error:"), error.message);
625
+ if (error.message.includes("Failed to load configuration")) {
626
+ console.log(chalk10__default.default.dim('\nRun "fractary-codex configure" to create a configuration.'));
627
+ } else if (error.message.includes("GITHUB_TOKEN")) {
628
+ console.log(chalk10__default.default.dim('\nSet your GitHub token: export GITHUB_TOKEN="your_token"'));
629
+ } else if (error.message.includes("not found") || error.message.includes("404")) {
630
+ console.log(chalk10__default.default.dim("\nThe document may not exist or you may not have access."));
631
+ console.log(chalk10__default.default.dim("Check the URI and ensure your storage providers are configured correctly."));
632
+ }
1341
633
  process.exit(1);
1342
634
  }
1343
635
  });
1344
636
  return cmd;
1345
637
  }
1346
638
 
1347
- // src/commands/config/index.ts
1348
- function configCommand() {
1349
- const cmd = new commander.Command("config");
1350
- cmd.description("Manage configuration");
1351
- cmd.addCommand(initCommand());
1352
- return cmd;
1353
- }
1354
-
1355
639
  // src/commands/cache/index.ts
1356
640
  init_cjs_shims();
1357
641
 
1358
642
  // src/commands/cache/list.ts
1359
643
  init_cjs_shims();
1360
- function formatSize(bytes) {
1361
- if (bytes < 1024) return `${bytes} B`;
1362
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
1363
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
644
+ function formatTtl(seconds) {
645
+ if (seconds < 0) {
646
+ const expired = -seconds;
647
+ if (expired < 60) return chalk10__default.default.red(`expired ${expired}s ago`);
648
+ if (expired < 3600) return chalk10__default.default.red(`expired ${Math.floor(expired / 60)}m ago`);
649
+ return chalk10__default.default.red(`expired ${Math.floor(expired / 3600)}h ago`);
650
+ }
651
+ if (seconds < 60) return chalk10__default.default.green(`${seconds}s`);
652
+ if (seconds < 3600) return chalk10__default.default.green(`${Math.floor(seconds / 60)}m`);
653
+ if (seconds < 86400) return chalk10__default.default.yellow(`${Math.floor(seconds / 3600)}h`);
654
+ return chalk10__default.default.dim(`${Math.floor(seconds / 86400)}d`);
655
+ }
656
+ function formatStatus(status) {
657
+ switch (status) {
658
+ case "fresh":
659
+ return chalk10__default.default.green("fresh");
660
+ case "stale":
661
+ return chalk10__default.default.yellow("stale");
662
+ case "expired":
663
+ return chalk10__default.default.red("expired");
664
+ }
1364
665
  }
1365
666
  function cacheListCommand() {
1366
- const cmd = new commander.Command("list");
1367
- cmd.description("List cache information").option("--json", "Output as JSON").action(async (options) => {
667
+ const cmd = new commander.Command("cache-list");
668
+ cmd.description("List cache entries").option("--json", "Output as JSON").option("--status <status>", "Filter by status (fresh, stale, expired, all)", "all").option("--limit <n>", "Maximum number of entries to show", parseInt).option("--sort <field>", "Sort by field (uri, size, createdAt, expiresAt)", "uri").option("--desc", "Sort in descending order").option("--verbose", "Show detailed entry information").action(async (options) => {
1368
669
  try {
1369
670
  const client = await getClient();
1370
- const stats = await client.getCacheStats();
1371
- if (stats.entryCount === 0) {
671
+ const listOptions = {
672
+ status: options.status,
673
+ limit: options.limit,
674
+ sortBy: options.sort,
675
+ sortDirection: options.desc ? "desc" : "asc"
676
+ };
677
+ const result = await client.listCacheEntries(listOptions);
678
+ if (result.total === 0) {
1372
679
  if (options.json) {
1373
- console.log(JSON.stringify({ entries: 0, message: "Cache is empty" }));
680
+ console.log(JSON.stringify({ entries: [], total: 0, message: "Cache is empty" }));
1374
681
  } else {
1375
- console.log(chalk7__default.default.yellow("Cache is empty."));
1376
- console.log(chalk7__default.default.dim("Fetch some documents to populate the cache."));
682
+ console.log(chalk10__default.default.yellow("Cache is empty."));
683
+ console.log(chalk10__default.default.dim("Fetch some documents to populate the cache."));
1377
684
  }
1378
685
  return;
1379
686
  }
1380
687
  if (options.json) {
1381
- console.log(JSON.stringify({
1382
- entryCount: stats.entryCount,
1383
- totalSize: stats.totalSize,
1384
- freshCount: stats.freshCount,
1385
- staleCount: stats.staleCount,
1386
- expiredCount: stats.expiredCount
1387
- }, null, 2));
688
+ console.log(JSON.stringify(result, null, 2));
1388
689
  return;
1389
690
  }
1390
- console.log(chalk7__default.default.bold("Cache Overview\n"));
1391
- console.log(chalk7__default.default.bold("Entries:"));
1392
- console.log(` Total: ${chalk7__default.default.cyan(stats.entryCount.toString())} entries`);
1393
- console.log(` Fresh: ${chalk7__default.default.green(stats.freshCount.toString())} entries`);
1394
- console.log(` Stale: ${stats.staleCount > 0 ? chalk7__default.default.yellow(stats.staleCount.toString()) : chalk7__default.default.dim("0")} entries`);
1395
- console.log(` Expired: ${stats.expiredCount > 0 ? chalk7__default.default.red(stats.expiredCount.toString()) : chalk7__default.default.dim("0")} entries`);
1396
- console.log("");
1397
- console.log(chalk7__default.default.bold("Storage:"));
1398
- console.log(` Total size: ${chalk7__default.default.cyan(formatSize(stats.totalSize))}`);
1399
- console.log("");
1400
- const healthPercent = stats.entryCount > 0 ? stats.freshCount / stats.entryCount * 100 : 100;
1401
- const healthColor = healthPercent > 80 ? chalk7__default.default.green : healthPercent > 50 ? chalk7__default.default.yellow : chalk7__default.default.red;
1402
- console.log(`Cache health: ${healthColor(`${healthPercent.toFixed(0)}% fresh`)}`);
691
+ console.log(chalk10__default.default.bold(`Cache Entries (${result.entries.length} of ${result.total})
692
+ `));
693
+ if (options.verbose) {
694
+ for (const entry of result.entries) {
695
+ console.log(chalk10__default.default.cyan(entry.uri));
696
+ console.log(` Status: ${formatStatus(entry.status)}`);
697
+ console.log(` Size: ${codex.formatBytes(entry.size)}`);
698
+ console.log(` Content-Type: ${chalk10__default.default.dim(entry.contentType)}`);
699
+ console.log(` TTL: ${formatTtl(entry.remainingTtl)}`);
700
+ console.log(` In Memory: ${entry.inMemory ? chalk10__default.default.green("yes") : chalk10__default.default.dim("no")}`);
701
+ console.log("");
702
+ }
703
+ } else {
704
+ const maxUriLen = Math.min(
705
+ 60,
706
+ Math.max(...result.entries.map((e) => e.uri.length))
707
+ );
708
+ console.log(
709
+ chalk10__default.default.dim(
710
+ `${"URI".padEnd(maxUriLen)} ${"STATUS".padEnd(8)} ${"SIZE".padEnd(10)} TTL`
711
+ )
712
+ );
713
+ console.log(chalk10__default.default.dim("\u2500".repeat(maxUriLen + 35)));
714
+ for (const entry of result.entries) {
715
+ const uri = entry.uri.length > maxUriLen ? "..." + entry.uri.slice(-(maxUriLen - 3)) : entry.uri.padEnd(maxUriLen);
716
+ console.log(
717
+ `${chalk10__default.default.cyan(uri)} ${formatStatus(entry.status).padEnd(17)} ${codex.formatBytes(entry.size).padEnd(10)} ${formatTtl(entry.remainingTtl)}`
718
+ );
719
+ }
720
+ }
721
+ if (result.hasMore) {
722
+ console.log("");
723
+ console.log(
724
+ chalk10__default.default.dim(
725
+ `Showing ${result.entries.length} of ${result.total} entries. Use --limit to see more.`
726
+ )
727
+ );
728
+ }
729
+ const stats = await client.getCacheStats();
1403
730
  console.log("");
1404
- console.log(chalk7__default.default.dim("Note: Individual cache entries are managed by the SDK."));
1405
- console.log(chalk7__default.default.dim('Use "fractary codex cache stats" for detailed statistics.'));
1406
- console.log(chalk7__default.default.dim('Use "fractary codex cache clear" to clear cache entries.'));
731
+ console.log(chalk10__default.default.dim("\u2500".repeat(60)));
732
+ console.log(
733
+ chalk10__default.default.dim(
734
+ `Total: ${stats.entryCount} entries (${codex.formatBytes(stats.totalSize)}) | ${stats.freshCount} fresh, ${stats.staleCount} stale, ${stats.expiredCount} expired`
735
+ )
736
+ );
1407
737
  } catch (error) {
1408
- console.error(chalk7__default.default.red("Error:"), error.message);
738
+ const errorMessage = error.message || "Unknown error";
739
+ if (errorMessage.includes("ENOENT") || errorMessage.includes("not found")) {
740
+ console.error(chalk10__default.default.red("Error:"), "Cache directory not accessible");
741
+ console.error(chalk10__default.default.dim('Run "fractary-codex configure" to initialize the cache.'));
742
+ } else if (errorMessage.includes("EACCES") || errorMessage.includes("permission")) {
743
+ console.error(chalk10__default.default.red("Error:"), "Permission denied accessing cache directory");
744
+ console.error(chalk10__default.default.dim("Check file permissions for .fractary/codex/cache/"));
745
+ } else if (errorMessage.includes("ENOSPC")) {
746
+ console.error(chalk10__default.default.red("Error:"), "No space left on device");
747
+ console.error(chalk10__default.default.dim("Free up disk space and try again."));
748
+ } else if (errorMessage.includes("parse") || errorMessage.includes("JSON")) {
749
+ console.error(chalk10__default.default.red("Error:"), "Failed to parse cache metadata");
750
+ console.error(chalk10__default.default.dim('The cache may be corrupted. Try "fractary-codex cache-clear".'));
751
+ } else {
752
+ console.error(chalk10__default.default.red("Error:"), errorMessage);
753
+ }
1409
754
  process.exit(1);
1410
755
  }
1411
756
  });
@@ -1415,13 +760,13 @@ function cacheListCommand() {
1415
760
  // src/commands/cache/clear.ts
1416
761
  init_cjs_shims();
1417
762
  function cacheClearCommand() {
1418
- const cmd = new commander.Command("clear");
763
+ const cmd = new commander.Command("cache-clear");
1419
764
  cmd.description("Clear cache entries").option("--all", "Clear entire cache").option("--pattern <glob>", 'Clear entries matching URI pattern (e.g., "codex://fractary/*")').option("--dry-run", "Show what would be cleared without actually clearing").action(async (options) => {
1420
765
  try {
1421
766
  const client = await getClient();
1422
767
  const statsBefore = await client.getCacheStats();
1423
768
  if (statsBefore.entryCount === 0) {
1424
- console.log(chalk7__default.default.yellow("Cache is already empty. Nothing to clear."));
769
+ console.log(chalk10__default.default.yellow("Cache is already empty. Nothing to clear."));
1425
770
  return;
1426
771
  }
1427
772
  let pattern;
@@ -1430,65 +775,55 @@ function cacheClearCommand() {
1430
775
  } else if (options.pattern) {
1431
776
  pattern = options.pattern;
1432
777
  } else {
1433
- console.log(chalk7__default.default.yellow("Please specify what to clear:"));
1434
- console.log(chalk7__default.default.dim(" --all Clear entire cache"));
1435
- console.log(chalk7__default.default.dim(' --pattern Clear entries matching pattern (e.g., "codex://fractary/*")'));
778
+ console.log(chalk10__default.default.yellow("Please specify what to clear:"));
779
+ console.log(chalk10__default.default.dim(" --all Clear entire cache"));
780
+ console.log(chalk10__default.default.dim(' --pattern Clear entries matching pattern (e.g., "codex://fractary/*")'));
1436
781
  console.log("");
1437
- console.log(chalk7__default.default.dim("Examples:"));
1438
- console.log(chalk7__default.default.dim(" fractary codex cache clear --all"));
1439
- console.log(chalk7__default.default.dim(' fractary codex cache clear --pattern "codex://fractary/cli/*"'));
782
+ console.log(chalk10__default.default.dim("Examples:"));
783
+ console.log(chalk10__default.default.dim(" fractary-codex cache-clear --all"));
784
+ console.log(chalk10__default.default.dim(' fractary-codex cache-clear --pattern "codex://fractary/cli/*"'));
1440
785
  return;
1441
786
  }
1442
787
  if (options.dryRun) {
1443
- console.log(chalk7__default.default.blue("Dry run - would clear:\n"));
788
+ console.log(chalk10__default.default.blue("Dry run - would clear:\n"));
1444
789
  if (pattern) {
1445
- console.log(chalk7__default.default.dim(` Pattern: ${pattern}`));
1446
- console.log(chalk7__default.default.dim(` This would invalidate matching cache entries`));
790
+ console.log(chalk10__default.default.dim(` Pattern: ${pattern}`));
791
+ console.log(chalk10__default.default.dim(` This would invalidate matching cache entries`));
1447
792
  } else {
1448
- console.log(chalk7__default.default.dim(` All cache entries (${statsBefore.entryCount} entries)`));
793
+ console.log(chalk10__default.default.dim(` All cache entries (${statsBefore.entryCount} entries)`));
1449
794
  }
1450
- console.log(chalk7__default.default.dim(`
1451
- Total size: ${formatSize2(statsBefore.totalSize)}`));
795
+ console.log(chalk10__default.default.dim(`
796
+ Total size: ${codex.formatBytes(statsBefore.totalSize)}`));
1452
797
  return;
1453
798
  }
1454
799
  if (pattern) {
1455
- console.log(chalk7__default.default.blue(`Clearing cache entries matching pattern: ${pattern}
800
+ console.log(chalk10__default.default.blue(`Clearing cache entries matching pattern: ${pattern}
1456
801
  `));
1457
802
  await client.invalidateCache(pattern);
1458
803
  } else {
1459
- console.log(chalk7__default.default.blue(`Clearing entire cache (${statsBefore.entryCount} entries)...
804
+ console.log(chalk10__default.default.blue(`Clearing entire cache (${statsBefore.entryCount} entries)...
1460
805
  `));
1461
806
  await client.invalidateCache();
1462
807
  }
1463
808
  const statsAfter = await client.getCacheStats();
1464
809
  const entriesCleared = statsBefore.entryCount - statsAfter.entryCount;
1465
810
  const sizeFreed = statsBefore.totalSize - statsAfter.totalSize;
1466
- console.log(chalk7__default.default.green(`\u2713 Cleared ${entriesCleared} entries (${formatSize2(sizeFreed)} freed)`));
811
+ console.log(chalk10__default.default.green(`\u2713 Cleared ${entriesCleared} entries (${codex.formatBytes(sizeFreed)} freed)`));
1467
812
  if (statsAfter.entryCount > 0) {
1468
- console.log(chalk7__default.default.dim(` Remaining: ${statsAfter.entryCount} entries (${formatSize2(statsAfter.totalSize)})`));
813
+ console.log(chalk10__default.default.dim(` Remaining: ${statsAfter.entryCount} entries (${codex.formatBytes(statsAfter.totalSize)})`));
1469
814
  }
1470
815
  } catch (error) {
1471
- console.error(chalk7__default.default.red("Error:"), error.message);
816
+ console.error(chalk10__default.default.red("Error:"), error.message);
1472
817
  process.exit(1);
1473
818
  }
1474
819
  });
1475
820
  return cmd;
1476
821
  }
1477
- function formatSize2(bytes) {
1478
- if (bytes < 1024) return `${bytes} B`;
1479
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
1480
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1481
- }
1482
822
 
1483
823
  // src/commands/cache/stats.ts
1484
824
  init_cjs_shims();
1485
- function formatSize3(bytes) {
1486
- if (bytes < 1024) return `${bytes} B`;
1487
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
1488
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1489
- }
1490
825
  function cacheStatsCommand() {
1491
- const cmd = new commander.Command("stats");
826
+ const cmd = new commander.Command("cache-stats");
1492
827
  cmd.description("Display cache statistics").option("--json", "Output as JSON").action(async (options) => {
1493
828
  try {
1494
829
  const client = await getClient();
@@ -1497,25 +832,25 @@ function cacheStatsCommand() {
1497
832
  console.log(JSON.stringify(stats, null, 2));
1498
833
  return;
1499
834
  }
1500
- console.log(chalk7__default.default.bold("Cache Statistics\n"));
1501
- console.log(chalk7__default.default.bold("Overview"));
1502
- console.log(` Total entries: ${chalk7__default.default.cyan(stats.entryCount.toString())}`);
1503
- console.log(` Total size: ${chalk7__default.default.cyan(formatSize3(stats.totalSize))}`);
1504
- console.log(` Fresh entries: ${chalk7__default.default.green(stats.freshCount.toString())}`);
1505
- console.log(` Stale entries: ${stats.staleCount > 0 ? chalk7__default.default.yellow(stats.staleCount.toString()) : chalk7__default.default.dim("0")}`);
1506
- console.log(` Expired entries: ${stats.expiredCount > 0 ? chalk7__default.default.red(stats.expiredCount.toString()) : chalk7__default.default.dim("0")}`);
835
+ console.log(chalk10__default.default.bold("Cache Statistics\n"));
836
+ console.log(chalk10__default.default.bold("Overview"));
837
+ console.log(` Total entries: ${chalk10__default.default.cyan(stats.entryCount.toString())}`);
838
+ console.log(` Total size: ${chalk10__default.default.cyan(codex.formatBytes(stats.totalSize))}`);
839
+ console.log(` Fresh entries: ${chalk10__default.default.green(stats.freshCount.toString())}`);
840
+ console.log(` Stale entries: ${stats.staleCount > 0 ? chalk10__default.default.yellow(stats.staleCount.toString()) : chalk10__default.default.dim("0")}`);
841
+ console.log(` Expired entries: ${stats.expiredCount > 0 ? chalk10__default.default.red(stats.expiredCount.toString()) : chalk10__default.default.dim("0")}`);
1507
842
  console.log("");
1508
843
  const healthPercent = stats.entryCount > 0 ? stats.freshCount / stats.entryCount * 100 : 100;
1509
- const healthColor = healthPercent > 80 ? chalk7__default.default.green : healthPercent > 50 ? chalk7__default.default.yellow : chalk7__default.default.red;
844
+ const healthColor = healthPercent > 80 ? chalk10__default.default.green : healthPercent > 50 ? chalk10__default.default.yellow : chalk10__default.default.red;
1510
845
  console.log(`Cache health: ${healthColor(`${healthPercent.toFixed(0)}% fresh`)}`);
1511
846
  if (stats.expiredCount > 0) {
1512
- console.log(chalk7__default.default.dim('\nRun "fractary codex cache clear --pattern <pattern>" to clean up entries.'));
847
+ console.log(chalk10__default.default.dim('\nRun "fractary-codex cache-clear --pattern <pattern>" to clean up entries.'));
1513
848
  }
1514
849
  if (stats.entryCount === 0) {
1515
- console.log(chalk7__default.default.dim("\nNo cached entries. Fetch some documents to populate the cache."));
850
+ console.log(chalk10__default.default.dim("\nNo cached entries. Fetch some documents to populate the cache."));
1516
851
  }
1517
852
  } catch (error) {
1518
- console.error(chalk7__default.default.red("Error:"), error.message);
853
+ console.error(chalk10__default.default.red("Error:"), error.message);
1519
854
  process.exit(1);
1520
855
  }
1521
856
  });
@@ -1524,260 +859,94 @@ function cacheStatsCommand() {
1524
859
 
1525
860
  // src/commands/cache/health.ts
1526
861
  init_cjs_shims();
1527
- init_migrate_config();
1528
- async function fileExists2(filePath) {
1529
- try {
1530
- await fs__namespace.access(filePath);
1531
- return true;
1532
- } catch {
1533
- return false;
1534
- }
1535
- }
1536
- async function checkConfiguration() {
1537
- const configPath = path4__namespace.join(process.cwd(), ".fractary", "config.yaml");
1538
- const legacyConfigPath = path4__namespace.join(process.cwd(), ".fractary", "plugins", "codex", "config.json");
1539
- try {
1540
- if (!await fileExists2(configPath)) {
1541
- if (await fileExists2(legacyConfigPath)) {
1542
- return {
1543
- name: "Configuration",
1544
- status: "warn",
1545
- message: "Legacy JSON configuration detected",
1546
- details: 'Run "fractary codex migrate" to upgrade to YAML format'
1547
- };
1548
- }
1549
- return {
1550
- name: "Configuration",
1551
- status: "fail",
1552
- message: "No configuration found",
1553
- details: 'Run "fractary codex init" to create configuration'
1554
- };
1555
- }
1556
- const config = await codex.readCodexConfig(configPath);
1557
- if (!config.organization) {
1558
- return {
1559
- name: "Configuration",
1560
- status: "warn",
1561
- message: "No organization configured",
1562
- details: "Organization slug is required"
1563
- };
1564
- }
1565
- const providerCount = config.storage?.length || 0;
1566
- if (providerCount === 0) {
1567
- return {
1568
- name: "Configuration",
1569
- status: "warn",
1570
- message: "No storage providers configured",
1571
- details: "At least one storage provider is recommended"
1572
- };
1573
- }
1574
- return {
1575
- name: "Configuration",
1576
- status: "pass",
1577
- message: "Valid YAML configuration",
1578
- details: `Organization: ${config.organization}, ${providerCount} storage provider(s)`
1579
- };
1580
- } catch (error) {
1581
- return {
1582
- name: "Configuration",
1583
- status: "fail",
1584
- message: "Invalid configuration",
1585
- details: error.message
1586
- };
1587
- }
1588
- }
1589
- async function checkSDKClient() {
1590
- try {
1591
- const client = await getClient();
1592
- const organization = client.getOrganization();
1593
- return {
1594
- name: "SDK Client",
1595
- status: "pass",
1596
- message: "CodexClient initialized successfully",
1597
- details: `Organization: ${organization}`
1598
- };
1599
- } catch (error) {
1600
- return {
1601
- name: "SDK Client",
1602
- status: "fail",
1603
- message: "Failed to initialize CodexClient",
1604
- details: error.message
1605
- };
1606
- }
1607
- }
1608
- async function checkCache() {
1609
- try {
1610
- const client = await getClient();
1611
- const stats = await client.getCacheStats();
1612
- if (stats.entryCount === 0) {
1613
- return {
1614
- name: "Cache",
1615
- status: "warn",
1616
- message: "Cache is empty",
1617
- details: "Fetch some documents to populate cache"
1618
- };
1619
- }
1620
- const healthPercent = stats.entryCount > 0 ? stats.freshCount / stats.entryCount * 100 : 100;
1621
- if (healthPercent < 50) {
1622
- return {
1623
- name: "Cache",
1624
- status: "warn",
1625
- message: `${stats.entryCount} entries (${healthPercent.toFixed(0)}% fresh)`,
1626
- details: `${stats.expiredCount} expired, ${stats.staleCount} stale`
1627
- };
1628
- }
1629
- return {
1630
- name: "Cache",
1631
- status: "pass",
1632
- message: `${stats.entryCount} entries (${healthPercent.toFixed(0)}% fresh)`,
1633
- details: `${formatSize4(stats.totalSize)} total`
1634
- };
1635
- } catch (error) {
1636
- return {
1637
- name: "Cache",
1638
- status: "fail",
1639
- message: "Cache check failed",
1640
- details: error.message
1641
- };
1642
- }
1643
- }
1644
- async function checkStorage() {
1645
- const configPath = path4__namespace.join(process.cwd(), ".fractary", "config.yaml");
1646
- try {
1647
- const config = await codex.readCodexConfig(configPath);
1648
- const providers = config.storage || [];
1649
- if (providers.length === 0) {
1650
- return {
1651
- name: "Storage",
1652
- status: "warn",
1653
- message: "No storage providers configured",
1654
- details: "Configure at least one provider in .fractary/config.yaml"
1655
- };
1656
- }
1657
- const providerTypes = providers.map((p) => p.type).join(", ");
1658
- const hasGitHub = providers.some((p) => p.type === "github");
1659
- if (hasGitHub && !process.env.GITHUB_TOKEN) {
1660
- return {
1661
- name: "Storage",
1662
- status: "warn",
1663
- message: `${providers.length} provider(s): ${providerTypes}`,
1664
- details: "GITHUB_TOKEN not set (required for GitHub provider)"
1665
- };
1666
- }
1667
- return {
1668
- name: "Storage",
1669
- status: "pass",
1670
- message: `${providers.length} provider(s): ${providerTypes}`,
1671
- details: "All configured providers available"
1672
- };
1673
- } catch (error) {
1674
- return {
1675
- name: "Storage",
1676
- status: "fail",
1677
- message: "Storage check failed",
1678
- details: error.message
1679
- };
1680
- }
1681
- }
1682
- async function checkTypes() {
1683
- try {
1684
- const client = await getClient();
1685
- const registry = client.getTypeRegistry();
1686
- const allTypes = registry.list();
1687
- const builtinCount = allTypes.filter((t) => registry.isBuiltIn(t.name)).length;
1688
- const customCount = allTypes.length - builtinCount;
1689
- return {
1690
- name: "Type Registry",
1691
- status: "pass",
1692
- message: `${allTypes.length} types registered`,
1693
- details: `${builtinCount} built-in, ${customCount} custom`
1694
- };
1695
- } catch (error) {
1696
- return {
1697
- name: "Type Registry",
1698
- status: "fail",
1699
- message: "Type registry check failed",
1700
- details: error.message
1701
- };
1702
- }
1703
- }
1704
- function formatSize4(bytes) {
1705
- if (bytes < 1024) return `${bytes} B`;
1706
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
1707
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1708
- }
1709
- function healthCommand() {
1710
- const cmd = new commander.Command("health");
862
+ function cacheHealthCommand() {
863
+ const cmd = new commander.Command("cache-health");
1711
864
  cmd.description("Run diagnostics on codex setup").option("--json", "Output as JSON").action(async (options) => {
1712
865
  try {
866
+ const healthChecker = codex.createHealthChecker({
867
+ projectRoot: process.cwd()
868
+ });
1713
869
  const checks = [];
1714
- checks.push(await checkConfiguration());
1715
- checks.push(await checkSDKClient());
1716
- checks.push(await checkCache());
1717
- checks.push(await checkStorage());
1718
- checks.push(await checkTypes());
1719
- const passed = checks.filter((c) => c.status === "pass").length;
1720
- const warned = checks.filter((c) => c.status === "warn").length;
1721
- const failed = checks.filter((c) => c.status === "fail").length;
870
+ checks.push(await healthChecker.checkConfiguration());
871
+ checks.push(await healthChecker.checkStorage());
872
+ try {
873
+ const client = await getClient();
874
+ const organization = client.getOrganization();
875
+ checks.push({
876
+ name: "SDK Client",
877
+ status: "pass",
878
+ message: "CodexClient initialized successfully",
879
+ details: `Organization: ${organization}`
880
+ });
881
+ const cacheStats = await client.getCacheStats();
882
+ checks.push(healthChecker.checkCacheFromStats(cacheStats));
883
+ const registry = client.getTypeRegistry();
884
+ checks.push(healthChecker.checkTypesFromRegistry(registry));
885
+ } catch (error) {
886
+ checks.push({
887
+ name: "SDK Client",
888
+ status: "fail",
889
+ message: "Failed to initialize CodexClient",
890
+ details: error.message
891
+ });
892
+ checks.push({
893
+ name: "Cache",
894
+ status: "warn",
895
+ message: "Cache check skipped",
896
+ details: "SDK client not available"
897
+ });
898
+ checks.push({
899
+ name: "Type Registry",
900
+ status: "warn",
901
+ message: "Type registry check skipped",
902
+ details: "SDK client not available"
903
+ });
904
+ }
905
+ const result = healthChecker.summarize(checks);
1722
906
  if (options.json) {
1723
- console.log(JSON.stringify({
1724
- summary: {
1725
- total: checks.length,
1726
- passed,
1727
- warned,
1728
- failed,
1729
- healthy: failed === 0
1730
- },
1731
- checks
1732
- }, null, 2));
907
+ console.log(JSON.stringify(result, null, 2));
1733
908
  return;
1734
909
  }
1735
- console.log(chalk7__default.default.bold("Codex Health Check\n"));
1736
- for (const check of checks) {
1737
- const icon = check.status === "pass" ? chalk7__default.default.green("\u2713") : check.status === "warn" ? chalk7__default.default.yellow("\u26A0") : chalk7__default.default.red("\u2717");
1738
- const statusColor = check.status === "pass" ? chalk7__default.default.green : check.status === "warn" ? chalk7__default.default.yellow : chalk7__default.default.red;
1739
- console.log(`${icon} ${chalk7__default.default.bold(check.name)}`);
910
+ console.log(chalk10__default.default.bold("Codex Health Check\n"));
911
+ for (const check of result.checks) {
912
+ const icon = check.status === "pass" ? chalk10__default.default.green("\u2713") : check.status === "warn" ? chalk10__default.default.yellow("\u26A0") : chalk10__default.default.red("\u2717");
913
+ const statusColor = check.status === "pass" ? chalk10__default.default.green : check.status === "warn" ? chalk10__default.default.yellow : chalk10__default.default.red;
914
+ console.log(`${icon} ${chalk10__default.default.bold(check.name)}`);
1740
915
  console.log(` ${statusColor(check.message)}`);
1741
916
  if (check.details) {
1742
- console.log(` ${chalk7__default.default.dim(check.details)}`);
917
+ console.log(` ${chalk10__default.default.dim(check.details)}`);
1743
918
  }
1744
919
  console.log("");
1745
920
  }
1746
- console.log(chalk7__default.default.dim("\u2500".repeat(60)));
1747
- const overallStatus = failed > 0 ? chalk7__default.default.red("UNHEALTHY") : warned > 0 ? chalk7__default.default.yellow("DEGRADED") : chalk7__default.default.green("HEALTHY");
921
+ console.log(chalk10__default.default.dim("\u2500".repeat(60)));
922
+ const overallStatus = result.summary.status === "unhealthy" ? chalk10__default.default.red("UNHEALTHY") : result.summary.status === "degraded" ? chalk10__default.default.yellow("DEGRADED") : chalk10__default.default.green("HEALTHY");
1748
923
  console.log(`Status: ${overallStatus}`);
1749
- console.log(chalk7__default.default.dim(`${passed} passed, ${warned} warnings, ${failed} failed`));
1750
- if (failed > 0 || warned > 0) {
924
+ console.log(
925
+ chalk10__default.default.dim(`${result.summary.passed} passed, ${result.summary.warned} warnings, ${result.summary.failed} failed`)
926
+ );
927
+ if (result.summary.failed > 0 || result.summary.warned > 0) {
1751
928
  console.log("");
1752
- console.log(chalk7__default.default.dim("Run checks individually for more details:"));
1753
- console.log(chalk7__default.default.dim(" fractary codex cache stats"));
1754
- console.log(chalk7__default.default.dim(" fractary codex types list"));
929
+ console.log(chalk10__default.default.dim("Run checks individually for more details:"));
930
+ console.log(chalk10__default.default.dim(" fractary-codex cache-stats"));
1755
931
  }
1756
- if (failed > 0) {
932
+ if (result.summary.failed > 0) {
1757
933
  process.exit(1);
1758
934
  }
1759
935
  } catch (error) {
1760
- console.error(chalk7__default.default.red("Error:"), error.message);
936
+ console.error(chalk10__default.default.red("Error:"), error.message);
1761
937
  process.exit(1);
1762
938
  }
1763
939
  });
1764
940
  return cmd;
1765
941
  }
1766
942
 
1767
- // src/commands/cache/index.ts
1768
- function cacheCommand() {
1769
- const cmd = new commander.Command("cache");
1770
- cmd.description("Manage the codex document cache");
1771
- cmd.addCommand(cacheListCommand());
1772
- cmd.addCommand(cacheClearCommand());
1773
- cmd.addCommand(cacheStatsCommand());
1774
- cmd.addCommand(healthCommand());
1775
- return cmd;
1776
- }
1777
-
1778
943
  // src/commands/sync.ts
1779
944
  init_cjs_shims();
1780
- init_migrate_config();
945
+
946
+ // src/config/migrate-config.ts
947
+ init_cjs_shims();
948
+
949
+ // src/commands/sync.ts
1781
950
  function getEnvironmentBranch(config, env) {
1782
951
  const envMap = config.sync?.environments || {
1783
952
  dev: "develop",
@@ -1787,26 +956,17 @@ function getEnvironmentBranch(config, env) {
1787
956
  };
1788
957
  return envMap[env] || env;
1789
958
  }
1790
- function formatBytes(bytes) {
1791
- if (bytes < 1024) return `${bytes} B`;
1792
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
1793
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1794
- }
1795
- function formatDuration(ms) {
1796
- if (ms < 1e3) return `${ms}ms`;
1797
- return `${(ms / 1e3).toFixed(1)}s`;
1798
- }
1799
959
  function syncCommand() {
1800
960
  const cmd = new commander.Command("sync");
1801
961
  cmd.description("Sync single project with codex repository").argument("[name]", "Project name (auto-detected if not provided)").option("--env <env>", "Target environment (dev/test/staging/prod)", "prod").option("--dry-run", "Show what would sync without executing").option("--direction <dir>", "Sync direction (to-codex/from-codex/bidirectional)", "bidirectional").option("--include <pattern>", "Include files matching pattern (can be used multiple times)", (val, prev) => prev.concat([val]), []).option("--exclude <pattern>", "Exclude files matching pattern (can be used multiple times)", (val, prev) => prev.concat([val]), []).option("--force", "Force sync without checking timestamps").option("--json", "Output as JSON").option("--work-id <id>", "GitHub issue number or URL to scope sync to").action(async (name, options) => {
1802
962
  try {
1803
- const configPath = path4__namespace.join(process.cwd(), ".fractary", "config.yaml");
963
+ const configPath = path3__namespace.join(process.cwd(), ".fractary", "config.yaml");
1804
964
  let config;
1805
965
  try {
1806
966
  config = await codex.readCodexConfig(configPath);
1807
967
  } catch (error) {
1808
- console.error(chalk7__default.default.red("Error:"), "Codex not initialized.");
1809
- console.log(chalk7__default.default.dim('Run "fractary codex init" first.'));
968
+ console.error(chalk10__default.default.red("Error:"), "Codex not initialized.");
969
+ console.log(chalk10__default.default.dim('Run "fractary-codex configure" first.'));
1810
970
  process.exit(1);
1811
971
  }
1812
972
  const { createSyncManager, createLocalStorage, detectCurrentProject } = await import('@fractary/codex');
@@ -1819,14 +979,14 @@ function syncCommand() {
1819
979
  projectName = detected.project || void 0;
1820
980
  }
1821
981
  if (!projectName) {
1822
- console.error(chalk7__default.default.red("Error:"), "Could not determine project name.");
1823
- console.log(chalk7__default.default.dim("Provide project name as argument, set codex.project in config, or run from a git repository."));
982
+ console.error(chalk10__default.default.red("Error:"), "Could not determine project name.");
983
+ console.log(chalk10__default.default.dim("Provide project name as argument, set codex.project in config, or run from a git repository."));
1824
984
  process.exit(1);
1825
985
  }
1826
986
  const validDirections = ["to-codex", "from-codex", "bidirectional"];
1827
987
  if (!validDirections.includes(options.direction)) {
1828
- console.error(chalk7__default.default.red("Error:"), `Invalid direction: ${options.direction}`);
1829
- console.log(chalk7__default.default.dim("Valid options: to-codex, from-codex, bidirectional"));
988
+ console.error(chalk10__default.default.red("Error:"), `Invalid direction: ${options.direction}`);
989
+ console.log(chalk10__default.default.dim("Valid options: to-codex, from-codex, bidirectional"));
1830
990
  process.exit(1);
1831
991
  }
1832
992
  const direction = options.direction;
@@ -1837,7 +997,7 @@ function syncCommand() {
1837
997
  const syncManager = createSyncManager({
1838
998
  localStorage,
1839
999
  config: config.sync,
1840
- manifestPath: path4__namespace.join(process.cwd(), ".fractary", ".codex-sync-manifest.json")
1000
+ manifestPath: path3__namespace.join(process.cwd(), ".fractary", ".codex-sync-manifest.json")
1841
1001
  });
1842
1002
  const defaultToCodexPatterns = [
1843
1003
  "docs/**/*.md",
@@ -1867,13 +1027,13 @@ function syncCommand() {
1867
1027
  });
1868
1028
  matches.forEach((match) => matchedFilePaths.add(match));
1869
1029
  } catch (error) {
1870
- console.error(chalk7__default.default.yellow(`Warning: Invalid pattern "${pattern}": ${error.message}`));
1030
+ console.error(chalk10__default.default.yellow(`Warning: Invalid pattern "${pattern}": ${error.message}`));
1871
1031
  }
1872
1032
  }
1873
1033
  const targetFiles = await Promise.all(
1874
1034
  Array.from(matchedFilePaths).map(async (filePath) => {
1875
- const fullPath = path4__namespace.join(sourceDir, filePath);
1876
- const stats = await import('fs/promises').then((fs8) => fs8.stat(fullPath));
1035
+ const fullPath = path3__namespace.join(sourceDir, filePath);
1036
+ const stats = await import('fs/promises').then((fs3) => fs3.stat(fullPath));
1877
1037
  return {
1878
1038
  path: filePath,
1879
1039
  size: stats.size,
@@ -1897,14 +1057,14 @@ function syncCommand() {
1897
1057
  try {
1898
1058
  const { ensureCodexCloned: ensureCodexCloned2 } = await Promise.resolve().then(() => (init_codex_repository(), codex_repository_exports));
1899
1059
  if (!options.json) {
1900
- console.log(chalk7__default.default.blue("\u2139 Cloning/updating codex repository..."));
1060
+ console.log(chalk10__default.default.blue("\u2139 Cloning/updating codex repository..."));
1901
1061
  }
1902
1062
  codexRepoPath = await ensureCodexCloned2(config, {
1903
1063
  branch: targetBranch
1904
1064
  });
1905
1065
  if (!options.json) {
1906
- console.log(chalk7__default.default.dim(` Codex cloned to: ${codexRepoPath}`));
1907
- console.log(chalk7__default.default.dim(" Scanning for files routing to this project...\n"));
1066
+ console.log(chalk10__default.default.dim(` Codex cloned to: ${codexRepoPath}`));
1067
+ console.log(chalk10__default.default.dim(" Scanning for files routing to this project...\n"));
1908
1068
  } else {
1909
1069
  console.log(JSON.stringify({
1910
1070
  info: "Routing-aware sync: cloned codex repository and scanning for files targeting this project",
@@ -1912,29 +1072,29 @@ function syncCommand() {
1912
1072
  }, null, 2));
1913
1073
  }
1914
1074
  } catch (error) {
1915
- console.error(chalk7__default.default.red("Error:"), "Failed to clone codex repository");
1916
- console.error(chalk7__default.default.dim(` ${error.message}`));
1917
- console.log(chalk7__default.default.yellow("\nTroubleshooting:"));
1075
+ console.error(chalk10__default.default.red("Error:"), "Failed to clone codex repository");
1076
+ console.error(chalk10__default.default.dim(` ${error.message}`));
1077
+ console.log(chalk10__default.default.yellow("\nTroubleshooting:"));
1918
1078
  if (error.message.includes("Git command not found")) {
1919
- console.log(chalk7__default.default.dim(" Git is not installed or not in PATH."));
1920
- console.log(chalk7__default.default.dim(" Install git: https://git-scm.com/downloads"));
1079
+ console.log(chalk10__default.default.dim(" Git is not installed or not in PATH."));
1080
+ console.log(chalk10__default.default.dim(" Install git: https://git-scm.com/downloads"));
1921
1081
  } else if (error.message.includes("authentication failed") || error.message.includes("Authentication failed")) {
1922
- console.log(chalk7__default.default.dim(" GitHub authentication is required for private repositories."));
1923
- console.log(chalk7__default.default.dim(" 1. Check auth status: gh auth status"));
1924
- console.log(chalk7__default.default.dim(" 2. Login if needed: gh auth login"));
1925
- console.log(chalk7__default.default.dim(" 3. Or set GITHUB_TOKEN environment variable"));
1082
+ console.log(chalk10__default.default.dim(" GitHub authentication is required for private repositories."));
1083
+ console.log(chalk10__default.default.dim(" 1. Check auth status: gh auth status"));
1084
+ console.log(chalk10__default.default.dim(" 2. Login if needed: gh auth login"));
1085
+ console.log(chalk10__default.default.dim(" 3. Or set GITHUB_TOKEN environment variable"));
1926
1086
  } else if (error.message.includes("Permission denied")) {
1927
- console.log(chalk7__default.default.dim(" Permission denied accessing repository files."));
1928
- console.log(chalk7__default.default.dim(" 1. Check file/directory permissions"));
1929
- console.log(chalk7__default.default.dim(" 2. Ensure you have access to the repository"));
1087
+ console.log(chalk10__default.default.dim(" Permission denied accessing repository files."));
1088
+ console.log(chalk10__default.default.dim(" 1. Check file/directory permissions"));
1089
+ console.log(chalk10__default.default.dim(" 2. Ensure you have access to the repository"));
1930
1090
  } else if (error.message.includes("not found") || error.message.includes("does not exist")) {
1931
- console.log(chalk7__default.default.dim(` Repository not found: ${config.organization}/${config.codex_repo || "codex"}`));
1932
- console.log(chalk7__default.default.dim(" 1. Verify the repository exists on GitHub"));
1933
- console.log(chalk7__default.default.dim(" 2. Check organization and repository names in config"));
1091
+ console.log(chalk10__default.default.dim(` Repository not found: ${config.organization}/${config.codex_repo || "codex"}`));
1092
+ console.log(chalk10__default.default.dim(" 1. Verify the repository exists on GitHub"));
1093
+ console.log(chalk10__default.default.dim(" 2. Check organization and repository names in config"));
1934
1094
  } else {
1935
- console.log(chalk7__default.default.dim(" 1. Ensure git is installed: git --version"));
1936
- console.log(chalk7__default.default.dim(" 2. Check GitHub auth: gh auth status"));
1937
- console.log(chalk7__default.default.dim(` 3. Verify repo exists: ${config.organization}/${config.codex_repo || "codex"}`));
1095
+ console.log(chalk10__default.default.dim(" 1. Ensure git is installed: git --version"));
1096
+ console.log(chalk10__default.default.dim(" 2. Check GitHub auth: gh auth status"));
1097
+ console.log(chalk10__default.default.dim(` 3. Verify repo exists: ${config.organization}/${config.codex_repo || "codex"}`));
1938
1098
  }
1939
1099
  process.exit(1);
1940
1100
  }
@@ -1953,17 +1113,17 @@ function syncCommand() {
1953
1113
  try {
1954
1114
  const { ensureCodexCloned: ensureCodexCloned2 } = await Promise.resolve().then(() => (init_codex_repository(), codex_repository_exports));
1955
1115
  if (!options.json) {
1956
- console.log(chalk7__default.default.blue("\u2139 Cloning/updating codex repository..."));
1116
+ console.log(chalk10__default.default.blue("\u2139 Cloning/updating codex repository..."));
1957
1117
  }
1958
1118
  codexRepoPath = await ensureCodexCloned2(config, {
1959
1119
  branch: targetBranch
1960
1120
  });
1961
1121
  if (!options.json) {
1962
- console.log(chalk7__default.default.dim(` Codex cloned to: ${codexRepoPath}`));
1122
+ console.log(chalk10__default.default.dim(` Codex cloned to: ${codexRepoPath}`));
1963
1123
  }
1964
1124
  } catch (error) {
1965
- console.error(chalk7__default.default.red("Error:"), "Failed to clone codex repository");
1966
- console.error(chalk7__default.default.dim(` ${error.message}`));
1125
+ console.error(chalk10__default.default.red("Error:"), "Failed to clone codex repository");
1126
+ console.error(chalk10__default.default.dim(` ${error.message}`));
1967
1127
  process.exit(1);
1968
1128
  }
1969
1129
  plan = await syncManager.createPlan(
@@ -1975,7 +1135,7 @@ function syncCommand() {
1975
1135
  syncOptions
1976
1136
  );
1977
1137
  plan.source = sourceDir;
1978
- plan.target = path4__namespace.join(codexRepoPath, "projects", projectName);
1138
+ plan.target = path3__namespace.join(codexRepoPath, "projects", projectName);
1979
1139
  }
1980
1140
  if (plan.totalFiles === 0) {
1981
1141
  if (options.json) {
@@ -1989,7 +1149,7 @@ function syncCommand() {
1989
1149
  message: "No files to sync"
1990
1150
  }, null, 2));
1991
1151
  } else {
1992
- console.log(chalk7__default.default.yellow("No files to sync."));
1152
+ console.log(chalk10__default.default.yellow("No files to sync."));
1993
1153
  }
1994
1154
  return;
1995
1155
  }
@@ -2045,81 +1205,81 @@ function syncCommand() {
2045
1205
  }, null, 2));
2046
1206
  return;
2047
1207
  }
2048
- console.log(chalk7__default.default.bold("Sync Plan\n"));
2049
- console.log(` Project: ${chalk7__default.default.cyan(projectName)}`);
2050
- console.log(` Organization: ${chalk7__default.default.cyan(config.organization)}`);
2051
- console.log(` Environment: ${chalk7__default.default.cyan(options.env)} (${targetBranch})`);
2052
- console.log(` Direction: ${chalk7__default.default.cyan(direction)}`);
2053
- console.log(` Files: ${chalk7__default.default.cyan(plan.totalFiles.toString())}`);
2054
- console.log(` Total size: ${chalk7__default.default.cyan(formatBytes(plan.totalBytes))}`);
1208
+ console.log(chalk10__default.default.bold("Sync Plan\n"));
1209
+ console.log(` Project: ${chalk10__default.default.cyan(projectName)}`);
1210
+ console.log(` Organization: ${chalk10__default.default.cyan(config.organization)}`);
1211
+ console.log(` Environment: ${chalk10__default.default.cyan(options.env)} (${targetBranch})`);
1212
+ console.log(` Direction: ${chalk10__default.default.cyan(direction)}`);
1213
+ console.log(` Files: ${chalk10__default.default.cyan(plan.totalFiles.toString())}`);
1214
+ console.log(` Total size: ${chalk10__default.default.cyan(codex.formatBytes(plan.totalBytes))}`);
2055
1215
  if (plan.estimatedTime) {
2056
- console.log(` Est. time: ${chalk7__default.default.dim(formatDuration(plan.estimatedTime))}`);
1216
+ console.log(` Est. time: ${chalk10__default.default.dim(codex.formatDuration(plan.estimatedTime))}`);
2057
1217
  }
2058
1218
  if (routingScan) {
2059
1219
  console.log("");
2060
- console.log(chalk7__default.default.bold("Routing Statistics\n"));
2061
- console.log(` Scanned: ${chalk7__default.default.cyan(routingScan.stats.totalScanned.toString())} files`);
2062
- console.log(` Matched: ${chalk7__default.default.cyan(routingScan.stats.totalMatched.toString())} files`);
2063
- console.log(` Source projects: ${chalk7__default.default.cyan(routingScan.stats.sourceProjects.length.toString())}`);
1220
+ console.log(chalk10__default.default.bold("Routing Statistics\n"));
1221
+ console.log(` Scanned: ${chalk10__default.default.cyan(routingScan.stats.totalScanned.toString())} files`);
1222
+ console.log(` Matched: ${chalk10__default.default.cyan(routingScan.stats.totalMatched.toString())} files`);
1223
+ console.log(` Source projects: ${chalk10__default.default.cyan(routingScan.stats.sourceProjects.length.toString())}`);
2064
1224
  if (routingScan.stats.sourceProjects.length > 0) {
2065
- console.log(chalk7__default.default.dim(` ${routingScan.stats.sourceProjects.slice(0, 5).join(", ")}`));
1225
+ console.log(chalk10__default.default.dim(` ${routingScan.stats.sourceProjects.slice(0, 5).join(", ")}`));
2066
1226
  if (routingScan.stats.sourceProjects.length > 5) {
2067
- console.log(chalk7__default.default.dim(` ... and ${routingScan.stats.sourceProjects.length - 5} more`));
1227
+ console.log(chalk10__default.default.dim(` ... and ${routingScan.stats.sourceProjects.length - 5} more`));
2068
1228
  }
2069
1229
  }
2070
- console.log(` Scan time: ${chalk7__default.default.dim(formatDuration(routingScan.stats.durationMs))}`);
1230
+ console.log(` Scan time: ${chalk10__default.default.dim(codex.formatDuration(routingScan.stats.durationMs))}`);
2071
1231
  }
2072
1232
  console.log("");
2073
1233
  if (plan.conflicts.length > 0) {
2074
- console.log(chalk7__default.default.yellow(`\u26A0 ${plan.conflicts.length} conflicts detected:`));
1234
+ console.log(chalk10__default.default.yellow(`\u26A0 ${plan.conflicts.length} conflicts detected:`));
2075
1235
  for (const conflict of plan.conflicts.slice(0, 5)) {
2076
- console.log(chalk7__default.default.yellow(` \u2022 ${conflict.path}`));
1236
+ console.log(chalk10__default.default.yellow(` \u2022 ${conflict.path}`));
2077
1237
  }
2078
1238
  if (plan.conflicts.length > 5) {
2079
- console.log(chalk7__default.default.dim(` ... and ${plan.conflicts.length - 5} more`));
1239
+ console.log(chalk10__default.default.dim(` ... and ${plan.conflicts.length - 5} more`));
2080
1240
  }
2081
1241
  console.log("");
2082
1242
  }
2083
1243
  if (plan.skipped.length > 0) {
2084
- console.log(chalk7__default.default.dim(`${plan.skipped.length} files skipped (no changes)`));
1244
+ console.log(chalk10__default.default.dim(`${plan.skipped.length} files skipped (no changes)`));
2085
1245
  console.log("");
2086
1246
  }
2087
1247
  if (options.dryRun) {
2088
- console.log(chalk7__default.default.blue("Dry run - would sync:\n"));
1248
+ console.log(chalk10__default.default.blue("Dry run - would sync:\n"));
2089
1249
  const filesToShow = plan.files.slice(0, 10);
2090
1250
  for (const file of filesToShow) {
2091
1251
  const arrow = direction === "to-codex" ? "\u2192" : direction === "from-codex" ? "\u2190" : "\u2194";
2092
- const opColor = file.operation === "create" ? chalk7__default.default.green : file.operation === "update" ? chalk7__default.default.yellow : chalk7__default.default.dim;
1252
+ const opColor = file.operation === "create" ? chalk10__default.default.green : file.operation === "update" ? chalk10__default.default.yellow : chalk10__default.default.dim;
2093
1253
  console.log(
2094
- chalk7__default.default.dim(` ${arrow}`),
1254
+ chalk10__default.default.dim(` ${arrow}`),
2095
1255
  opColor(file.operation.padEnd(7)),
2096
1256
  file.path,
2097
- chalk7__default.default.dim(`(${formatBytes(file.size || 0)})`)
1257
+ chalk10__default.default.dim(`(${codex.formatBytes(file.size || 0)})`)
2098
1258
  );
2099
1259
  }
2100
1260
  if (plan.files.length > 10) {
2101
- console.log(chalk7__default.default.dim(` ... and ${plan.files.length - 10} more files`));
1261
+ console.log(chalk10__default.default.dim(` ... and ${plan.files.length - 10} more files`));
2102
1262
  }
2103
- console.log(chalk7__default.default.dim(`
2104
- Total: ${plan.totalFiles} files (${formatBytes(plan.totalBytes)})`));
2105
- console.log(chalk7__default.default.dim("Run without --dry-run to execute sync."));
1263
+ console.log(chalk10__default.default.dim(`
1264
+ Total: ${plan.totalFiles} files (${codex.formatBytes(plan.totalBytes)})`));
1265
+ console.log(chalk10__default.default.dim("Run without --dry-run to execute sync."));
2106
1266
  return;
2107
1267
  }
2108
- console.log(chalk7__default.default.blue("Syncing...\n"));
1268
+ console.log(chalk10__default.default.blue("Syncing...\n"));
2109
1269
  const startTime = Date.now();
2110
1270
  const result = await syncManager.executePlan(plan, syncOptions);
2111
1271
  const duration = Date.now() - startTime;
2112
1272
  if (direction === "to-codex" && codexRepoPath && result.synced > 0) {
2113
1273
  try {
2114
1274
  if (!options.json) {
2115
- console.log(chalk7__default.default.blue("Committing and pushing to codex..."));
1275
+ console.log(chalk10__default.default.blue("Committing and pushing to codex..."));
2116
1276
  }
2117
1277
  const { RepoManager } = await import('@fractary/core/repo');
2118
1278
  const repoManager = new RepoManager({ platform: "github" }, codexRepoPath);
2119
1279
  repoManager.stageAll();
2120
1280
  if (repoManager.isClean()) {
2121
1281
  if (!options.json) {
2122
- console.log(chalk7__default.default.dim(" No changes to push - codex is already up to date"));
1282
+ console.log(chalk10__default.default.dim(" No changes to push - codex is already up to date"));
2123
1283
  }
2124
1284
  } else {
2125
1285
  repoManager.commit({
@@ -2127,401 +1287,62 @@ Total: ${plan.totalFiles} files (${formatBytes(plan.totalBytes)})`));
2127
1287
  });
2128
1288
  repoManager.push({});
2129
1289
  if (!options.json) {
2130
- console.log(chalk7__default.default.dim(" Changes pushed to codex repository"));
1290
+ console.log(chalk10__default.default.dim(" Changes pushed to codex repository"));
2131
1291
  }
2132
1292
  }
2133
1293
  } catch (error) {
2134
- console.error(chalk7__default.default.red("Error pushing to codex:"), error.message);
1294
+ console.error(chalk10__default.default.red("Error pushing to codex:"), error.message);
2135
1295
  }
2136
1296
  }
2137
1297
  console.log("");
2138
1298
  if (result.success) {
2139
- console.log(chalk7__default.default.green(`\u2713 Sync completed successfully`));
2140
- console.log(chalk7__default.default.dim(` Synced: ${result.synced} files`));
1299
+ console.log(chalk10__default.default.green(`\u2713 Sync completed successfully`));
1300
+ console.log(chalk10__default.default.dim(` Synced: ${result.synced} files`));
2141
1301
  if (result.skipped > 0) {
2142
- console.log(chalk7__default.default.dim(` Skipped: ${result.skipped} files`));
1302
+ console.log(chalk10__default.default.dim(` Skipped: ${result.skipped} files`));
2143
1303
  }
2144
- console.log(chalk7__default.default.dim(` Duration: ${formatDuration(duration)}`));
1304
+ console.log(chalk10__default.default.dim(` Duration: ${codex.formatDuration(duration)}`));
2145
1305
  } else {
2146
- console.log(chalk7__default.default.yellow(`\u26A0 Sync completed with errors`));
2147
- console.log(chalk7__default.default.green(` Synced: ${result.synced} files`));
2148
- console.log(chalk7__default.default.red(` Failed: ${result.failed} files`));
1306
+ console.log(chalk10__default.default.yellow(`\u26A0 Sync completed with errors`));
1307
+ console.log(chalk10__default.default.green(` Synced: ${result.synced} files`));
1308
+ console.log(chalk10__default.default.red(` Failed: ${result.failed} files`));
2149
1309
  if (result.skipped > 0) {
2150
- console.log(chalk7__default.default.dim(` Skipped: ${result.skipped} files`));
1310
+ console.log(chalk10__default.default.dim(` Skipped: ${result.skipped} files`));
2151
1311
  }
2152
1312
  if (result.errors.length > 0) {
2153
1313
  console.log("");
2154
- console.log(chalk7__default.default.red("Errors:"));
1314
+ console.log(chalk10__default.default.red("Errors:"));
2155
1315
  for (const error of result.errors.slice(0, 5)) {
2156
- console.log(chalk7__default.default.red(` \u2022 ${error.path}: ${error.error}`));
1316
+ console.log(chalk10__default.default.red(` \u2022 ${error.path}: ${error.error}`));
2157
1317
  }
2158
1318
  if (result.errors.length > 5) {
2159
- console.log(chalk7__default.default.dim(` ... and ${result.errors.length - 5} more errors`));
1319
+ console.log(chalk10__default.default.dim(` ... and ${result.errors.length - 5} more errors`));
2160
1320
  }
2161
1321
  }
2162
1322
  }
2163
1323
  } catch (error) {
2164
- console.error(chalk7__default.default.red("Error:"), error.message);
2165
- process.exit(1);
2166
- }
2167
- });
2168
- return cmd;
2169
- }
2170
-
2171
- // src/commands/types/index.ts
2172
- init_cjs_shims();
2173
-
2174
- // src/commands/types/list.ts
2175
- init_cjs_shims();
2176
- function formatTtl(seconds) {
2177
- if (seconds < 60) return `${seconds}s`;
2178
- if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
2179
- if (seconds < 86400) return `${Math.floor(seconds / 3600)}h`;
2180
- return `${Math.floor(seconds / 86400)}d`;
2181
- }
2182
- function typesListCommand() {
2183
- const cmd = new commander.Command("list");
2184
- cmd.description("List all artifact types").option("--json", "Output as JSON").option("--custom-only", "Show only custom types").option("--builtin-only", "Show only built-in types").action(async (options) => {
2185
- try {
2186
- const client = await getClient();
2187
- const registry = client.getTypeRegistry();
2188
- const allTypes = registry.list();
2189
- let types = allTypes;
2190
- if (options.customOnly) {
2191
- types = allTypes.filter((t) => !registry.isBuiltIn(t.name));
2192
- } else if (options.builtinOnly) {
2193
- types = allTypes.filter((t) => registry.isBuiltIn(t.name));
2194
- }
2195
- if (options.json) {
2196
- const builtinCount = types.filter((t) => registry.isBuiltIn(t.name)).length;
2197
- const customCount = types.length - builtinCount;
2198
- console.log(JSON.stringify({
2199
- count: types.length,
2200
- builtinCount,
2201
- customCount,
2202
- types: types.map((t) => ({
2203
- name: t.name,
2204
- description: t.description,
2205
- patterns: t.patterns,
2206
- defaultTtl: t.defaultTtl,
2207
- ttl: formatTtl(t.defaultTtl),
2208
- builtin: registry.isBuiltIn(t.name),
2209
- archiveAfterDays: t.archiveAfterDays,
2210
- archiveStorage: t.archiveStorage
2211
- }))
2212
- }, null, 2));
2213
- return;
2214
- }
2215
- if (types.length === 0) {
2216
- console.log(chalk7__default.default.yellow("No types found."));
2217
- return;
2218
- }
2219
- console.log(chalk7__default.default.bold("Artifact Types\n"));
2220
- const builtinTypes = types.filter((t) => registry.isBuiltIn(t.name));
2221
- const customTypes = types.filter((t) => !registry.isBuiltIn(t.name));
2222
- if (builtinTypes.length > 0 && !options.customOnly) {
2223
- console.log(chalk7__default.default.bold("Built-in Types"));
2224
- console.log(chalk7__default.default.dim("\u2500".repeat(70)));
2225
- for (const type of builtinTypes) {
2226
- const patternStr = type.patterns[0] || "";
2227
- console.log(` ${chalk7__default.default.cyan(type.name.padEnd(12))} ${patternStr.padEnd(30)} ${chalk7__default.default.dim(`TTL: ${formatTtl(type.defaultTtl)}`)}`);
2228
- console.log(` ${chalk7__default.default.dim(" ".repeat(12) + type.description)}`);
2229
- }
2230
- console.log("");
2231
- }
2232
- if (customTypes.length > 0 && !options.builtinOnly) {
2233
- console.log(chalk7__default.default.bold("Custom Types"));
2234
- console.log(chalk7__default.default.dim("\u2500".repeat(70)));
2235
- for (const type of customTypes) {
2236
- const patternStr = type.patterns[0] || "";
2237
- console.log(` ${chalk7__default.default.green(type.name.padEnd(12))} ${patternStr.padEnd(30)} ${chalk7__default.default.dim(`TTL: ${formatTtl(type.defaultTtl)}`)}`);
2238
- console.log(` ${chalk7__default.default.dim(" ".repeat(12) + type.description)}`);
2239
- }
2240
- console.log("");
2241
- }
2242
- console.log(chalk7__default.default.dim(`Total: ${types.length} types (${builtinTypes.length} built-in, ${customTypes.length} custom)`));
2243
- } catch (error) {
2244
- console.error(chalk7__default.default.red("Error:"), error.message);
2245
- process.exit(1);
2246
- }
2247
- });
2248
- return cmd;
2249
- }
2250
-
2251
- // src/commands/types/show.ts
2252
- init_cjs_shims();
2253
- function formatTtl2(seconds) {
2254
- if (seconds < 60) return `${seconds}s`;
2255
- if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
2256
- if (seconds < 86400) return `${Math.floor(seconds / 3600)}h`;
2257
- return `${Math.floor(seconds / 86400)}d`;
2258
- }
2259
- function typesShowCommand() {
2260
- const cmd = new commander.Command("show");
2261
- cmd.description("Show details for a specific type").argument("<name>", "Type name").option("--json", "Output as JSON").action(async (name, options) => {
2262
- try {
2263
- const client = await getClient();
2264
- const registry = client.getTypeRegistry();
2265
- const type = registry.get(name);
2266
- if (!type) {
2267
- console.error(chalk7__default.default.red("Error:"), `Type "${name}" not found.`);
2268
- console.log(chalk7__default.default.dim('Run "fractary codex types list" to see available types.'));
2269
- process.exit(1);
2270
- }
2271
- const isBuiltin = registry.isBuiltIn(name);
2272
- if (options.json) {
2273
- console.log(JSON.stringify({
2274
- name: type.name,
2275
- builtin: isBuiltin,
2276
- description: type.description,
2277
- patterns: type.patterns,
2278
- defaultTtl: type.defaultTtl,
2279
- ttl: formatTtl2(type.defaultTtl),
2280
- archiveAfterDays: type.archiveAfterDays,
2281
- archiveStorage: type.archiveStorage,
2282
- syncPatterns: type.syncPatterns,
2283
- excludePatterns: type.excludePatterns
2284
- }, null, 2));
2285
- return;
2286
- }
2287
- const nameColor = isBuiltin ? chalk7__default.default.cyan : chalk7__default.default.green;
2288
- console.log(chalk7__default.default.bold(`Type: ${nameColor(name)}
2289
- `));
2290
- console.log(` ${chalk7__default.default.dim("Source:")} ${isBuiltin ? "Built-in" : "Custom"}`);
2291
- console.log(` ${chalk7__default.default.dim("Description:")} ${type.description}`);
2292
- console.log(` ${chalk7__default.default.dim("TTL:")} ${formatTtl2(type.defaultTtl)} (${type.defaultTtl} seconds)`);
2293
- console.log("");
2294
- console.log(chalk7__default.default.bold("Patterns"));
2295
- for (const pattern of type.patterns) {
2296
- console.log(` ${chalk7__default.default.dim("\u2022")} ${pattern}`);
2297
- }
2298
- if (type.archiveAfterDays !== null) {
2299
- console.log("");
2300
- console.log(chalk7__default.default.bold("Archive Settings"));
2301
- console.log(` ${chalk7__default.default.dim("After:")} ${type.archiveAfterDays} days`);
2302
- console.log(` ${chalk7__default.default.dim("Storage:")} ${type.archiveStorage || "not set"}`);
2303
- }
2304
- if (type.syncPatterns && type.syncPatterns.length > 0) {
2305
- console.log("");
2306
- console.log(chalk7__default.default.bold("Sync Patterns"));
2307
- for (const pattern of type.syncPatterns) {
2308
- console.log(` ${chalk7__default.default.dim("\u2022")} ${pattern}`);
2309
- }
2310
- }
2311
- if (type.excludePatterns && type.excludePatterns.length > 0) {
2312
- console.log("");
2313
- console.log(chalk7__default.default.bold("Exclude Patterns"));
2314
- for (const pattern of type.excludePatterns) {
2315
- console.log(` ${chalk7__default.default.dim("\u2022")} ${pattern}`);
2316
- }
2317
- }
2318
- } catch (error) {
2319
- console.error(chalk7__default.default.red("Error:"), error.message);
2320
- process.exit(1);
2321
- }
2322
- });
2323
- return cmd;
2324
- }
2325
-
2326
- // src/commands/types/add.ts
2327
- init_cjs_shims();
2328
- init_migrate_config();
2329
- function isValidTypeName(name) {
2330
- return /^[a-z][a-z0-9-]*$/.test(name);
2331
- }
2332
- function parseTtl(ttl) {
2333
- const match = ttl.match(/^(\d+)([smhd])$/);
2334
- if (!match) {
2335
- throw new Error("Invalid TTL format");
2336
- }
2337
- const value = parseInt(match[1], 10);
2338
- const unit = match[2];
2339
- switch (unit) {
2340
- case "s":
2341
- return value;
2342
- case "m":
2343
- return value * 60;
2344
- case "h":
2345
- return value * 3600;
2346
- case "d":
2347
- return value * 86400;
2348
- default:
2349
- throw new Error("Unknown TTL unit");
2350
- }
2351
- }
2352
- function formatTtl3(seconds) {
2353
- if (seconds < 60) return `${seconds}s`;
2354
- if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
2355
- if (seconds < 86400) return `${Math.floor(seconds / 3600)}h`;
2356
- return `${Math.floor(seconds / 86400)}d`;
2357
- }
2358
- function typesAddCommand() {
2359
- const cmd = new commander.Command("add");
2360
- 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) => {
2361
- try {
2362
- if (!isValidTypeName(name)) {
2363
- console.error(chalk7__default.default.red("Error:"), "Invalid type name.");
2364
- console.log(chalk7__default.default.dim("Type name must be lowercase, start with a letter, and contain only letters, numbers, and hyphens."));
2365
- process.exit(1);
2366
- }
2367
- const client = await getClient();
2368
- const registry = client.getTypeRegistry();
2369
- if (registry.isBuiltIn(name)) {
2370
- console.error(chalk7__default.default.red("Error:"), `Cannot override built-in type "${name}".`);
2371
- const builtinNames = registry.list().filter((t) => registry.isBuiltIn(t.name)).map((t) => t.name);
2372
- console.log(chalk7__default.default.dim("Built-in types: " + builtinNames.join(", ")));
2373
- process.exit(1);
2374
- }
2375
- if (registry.has(name)) {
2376
- console.error(chalk7__default.default.red("Error:"), `Custom type "${name}" already exists.`);
2377
- console.log(chalk7__default.default.dim('Use "fractary codex types remove" first to remove it.'));
2378
- process.exit(1);
2379
- }
2380
- let ttlSeconds;
2381
- try {
2382
- ttlSeconds = parseTtl(options.ttl);
2383
- } catch {
2384
- console.error(chalk7__default.default.red("Error:"), "Invalid TTL format.");
2385
- console.log(chalk7__default.default.dim("Expected format: <number><unit> where unit is s (seconds), m (minutes), h (hours), or d (days)"));
2386
- console.log(chalk7__default.default.dim("Examples: 30m, 24h, 7d"));
2387
- process.exit(1);
2388
- }
2389
- const configPath = path4__namespace.join(process.cwd(), ".fractary", "config.yaml");
2390
- const config = await codex.readCodexConfig(configPath);
2391
- if (!config.types) {
2392
- config.types = { custom: {} };
2393
- }
2394
- if (!config.types.custom) {
2395
- config.types.custom = {};
2396
- }
2397
- config.types.custom[name] = {
2398
- description: options.description || `Custom type: ${name}`,
2399
- patterns: [options.pattern],
2400
- defaultTtl: ttlSeconds
2401
- };
2402
- await writeYamlConfig(config, configPath);
2403
- if (options.json) {
2404
- console.log(JSON.stringify({
2405
- success: true,
2406
- type: {
2407
- name,
2408
- description: config.types.custom[name].description,
2409
- patterns: config.types.custom[name].patterns,
2410
- defaultTtl: ttlSeconds,
2411
- ttl: formatTtl3(ttlSeconds),
2412
- builtin: false
2413
- },
2414
- message: "Custom type added successfully. Changes will take effect on next CLI invocation."
2415
- }, null, 2));
2416
- return;
2417
- }
2418
- console.log(chalk7__default.default.green("\u2713"), `Added custom type "${chalk7__default.default.cyan(name)}"`);
2419
- console.log("");
2420
- console.log(` ${chalk7__default.default.dim("Pattern:")} ${options.pattern}`);
2421
- console.log(` ${chalk7__default.default.dim("TTL:")} ${formatTtl3(ttlSeconds)} (${ttlSeconds} seconds)`);
2422
- if (options.description) {
2423
- console.log(` ${chalk7__default.default.dim("Description:")} ${options.description}`);
2424
- }
2425
- console.log("");
2426
- console.log(chalk7__default.default.dim("Note: Custom type will be available on next CLI invocation."));
2427
- } catch (error) {
2428
- console.error(chalk7__default.default.red("Error:"), error.message);
2429
- if (error.message.includes("Failed to load configuration")) {
2430
- console.log(chalk7__default.default.dim('\nRun "fractary codex init" to create a configuration.'));
2431
- }
2432
- process.exit(1);
2433
- }
2434
- });
2435
- return cmd;
2436
- }
2437
-
2438
- // src/commands/types/remove.ts
2439
- init_cjs_shims();
2440
- init_migrate_config();
2441
- function typesRemoveCommand() {
2442
- const cmd = new commander.Command("remove");
2443
- 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) => {
2444
- try {
2445
- const client = await getClient();
2446
- const registry = client.getTypeRegistry();
2447
- if (registry.isBuiltIn(name)) {
2448
- console.error(chalk7__default.default.red("Error:"), `Cannot remove built-in type "${name}".`);
2449
- console.log(chalk7__default.default.dim("Built-in types are permanent and cannot be removed."));
2450
- process.exit(1);
2451
- }
2452
- if (!registry.has(name)) {
2453
- console.error(chalk7__default.default.red("Error:"), `Custom type "${name}" not found.`);
2454
- console.log(chalk7__default.default.dim('Run "fractary codex types list --custom-only" to see custom types.'));
2455
- process.exit(1);
2456
- }
2457
- const typeInfo = registry.get(name);
2458
- const configPath = path4__namespace.join(process.cwd(), ".fractary", "config.yaml");
2459
- const config = await codex.readCodexConfig(configPath);
2460
- if (!config.types?.custom?.[name]) {
2461
- console.error(chalk7__default.default.red("Error:"), `Custom type "${name}" not found in configuration.`);
2462
- process.exit(1);
2463
- }
2464
- delete config.types.custom[name];
2465
- if (Object.keys(config.types.custom).length === 0) {
2466
- delete config.types.custom;
2467
- }
2468
- if (config.types && Object.keys(config.types).length === 0) {
2469
- delete config.types;
2470
- }
2471
- await writeYamlConfig(config, configPath);
2472
- if (options.json) {
2473
- console.log(JSON.stringify({
2474
- success: true,
2475
- removed: {
2476
- name: typeInfo.name,
2477
- description: typeInfo.description,
2478
- patterns: typeInfo.patterns,
2479
- defaultTtl: typeInfo.defaultTtl
2480
- },
2481
- message: "Custom type removed successfully. Changes will take effect on next CLI invocation."
2482
- }, null, 2));
2483
- return;
2484
- }
2485
- console.log(chalk7__default.default.green("\u2713"), `Removed custom type "${chalk7__default.default.cyan(name)}"`);
2486
- console.log("");
2487
- console.log(chalk7__default.default.dim("Removed configuration:"));
2488
- console.log(` ${chalk7__default.default.dim("Pattern:")} ${typeInfo.patterns.join(", ")}`);
2489
- console.log(` ${chalk7__default.default.dim("Description:")} ${typeInfo.description}`);
2490
- console.log("");
2491
- console.log(chalk7__default.default.dim("Note: Custom type will be removed on next CLI invocation."));
2492
- } catch (error) {
2493
- console.error(chalk7__default.default.red("Error:"), error.message);
2494
- if (error.message.includes("Failed to load configuration")) {
2495
- console.log(chalk7__default.default.dim('\nRun "fractary codex init" to create a configuration.'));
2496
- }
1324
+ console.error(chalk10__default.default.red("Error:"), error.message);
2497
1325
  process.exit(1);
2498
1326
  }
2499
1327
  });
2500
1328
  return cmd;
2501
1329
  }
2502
-
2503
- // src/commands/types/index.ts
2504
- function typesCommand() {
2505
- const cmd = new commander.Command("types");
2506
- cmd.description("Manage artifact type registry");
2507
- cmd.addCommand(typesListCommand());
2508
- cmd.addCommand(typesShowCommand());
2509
- cmd.addCommand(typesAddCommand());
2510
- cmd.addCommand(typesRemoveCommand());
2511
- return cmd;
2512
- }
2513
1330
  var __filename2 = url.fileURLToPath(importMetaUrl);
2514
- var __dirname$1 = path4.dirname(__filename2);
2515
- var packageJson = JSON.parse(fs.readFileSync(path4.join(__dirname$1, "../package.json"), "utf-8"));
1331
+ var __dirname$1 = path3.dirname(__filename2);
1332
+ var packageJson = JSON.parse(fs.readFileSync(path3.join(__dirname$1, "../package.json"), "utf-8"));
2516
1333
  var VERSION = packageJson.version;
2517
1334
  function createCLI() {
2518
1335
  const program = new commander.Command("fractary-codex");
2519
1336
  program.description("Centralized knowledge management and distribution for AI agents").version(VERSION);
2520
- program.addCommand(documentCommand());
2521
- program.addCommand(configCommand());
2522
- program.addCommand(cacheCommand());
1337
+ program.addCommand(configInitializeCommand());
1338
+ program.addCommand(configUpdateCommand());
1339
+ program.addCommand(configValidateCommand());
1340
+ program.addCommand(documentFetchCommand());
1341
+ program.addCommand(cacheListCommand());
1342
+ program.addCommand(cacheClearCommand());
1343
+ program.addCommand(cacheStatsCommand());
1344
+ program.addCommand(cacheHealthCommand());
2523
1345
  program.addCommand(syncCommand());
2524
- program.addCommand(typesCommand());
2525
1346
  return program;
2526
1347
  }
2527
1348
  async function main() {