@fractary/codex-cli 0.10.16 → 0.10.20
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 +555 -1365
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +548 -1357
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.cjs
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var fs4 = require('fs/promises');
|
|
5
|
-
var path2 = require('path');
|
|
6
|
-
var yaml = 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
|
|
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
|
|
37
|
-
var path2__namespace = /*#__PURE__*/_interopNamespace(path2);
|
|
38
|
-
var yaml__namespace = /*#__PURE__*/_interopNamespace(yaml);
|
|
36
|
+
var path3__namespace = /*#__PURE__*/_interopNamespace(path3);
|
|
39
37
|
var os__namespace = /*#__PURE__*/_interopNamespace(os);
|
|
40
|
-
var
|
|
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 fs4__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 fs4__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 fs4__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 = path2__namespace.dirname(outputPath);
|
|
198
|
-
await fs4__namespace.mkdir(dir, { recursive: true });
|
|
199
|
-
const yamlContent = yaml__namespace.dump(config, {
|
|
200
|
-
indent: 2,
|
|
201
|
-
lineWidth: 80,
|
|
202
|
-
noRefs: true,
|
|
203
|
-
sortKeys: false
|
|
204
|
-
});
|
|
205
|
-
await fs4__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 = path2__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 configure" 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
|
|
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 =
|
|
612
|
-
const stats = await
|
|
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 =
|
|
645
|
-
await
|
|
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
|
|
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
|
|
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
|
}
|
|
@@ -717,539 +252,304 @@ init_cjs_shims();
|
|
|
717
252
|
// src/commands/config/index.ts
|
|
718
253
|
init_cjs_shims();
|
|
719
254
|
|
|
720
|
-
// src/commands/config/
|
|
721
|
-
init_cjs_shims();
|
|
722
|
-
|
|
723
|
-
// src/config/unified-config.ts
|
|
255
|
+
// src/commands/config/initialize.ts
|
|
724
256
|
init_cjs_shims();
|
|
725
|
-
function
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
function getDefaultUnifiedConfig(organization, project, codexRepo) {
|
|
729
|
-
const sanitizedProject = sanitizeForS3BucketName(project);
|
|
730
|
-
return {
|
|
731
|
-
file: {
|
|
732
|
-
schema_version: codex.CONFIG_SCHEMA_VERSION,
|
|
733
|
-
sources: {
|
|
734
|
-
specs: {
|
|
735
|
-
type: "s3",
|
|
736
|
-
bucket: `${sanitizedProject}-files`,
|
|
737
|
-
prefix: "specs/",
|
|
738
|
-
region: "us-east-1",
|
|
739
|
-
local: {
|
|
740
|
-
base_path: ".fractary/specs"
|
|
741
|
-
},
|
|
742
|
-
push: {
|
|
743
|
-
compress: false,
|
|
744
|
-
keep_local: true
|
|
745
|
-
},
|
|
746
|
-
auth: {
|
|
747
|
-
profile: "default"
|
|
748
|
-
}
|
|
749
|
-
},
|
|
750
|
-
logs: {
|
|
751
|
-
type: "s3",
|
|
752
|
-
bucket: `${sanitizedProject}-files`,
|
|
753
|
-
prefix: "logs/",
|
|
754
|
-
region: "us-east-1",
|
|
755
|
-
local: {
|
|
756
|
-
base_path: ".fractary/logs"
|
|
757
|
-
},
|
|
758
|
-
push: {
|
|
759
|
-
compress: true,
|
|
760
|
-
keep_local: true
|
|
761
|
-
},
|
|
762
|
-
auth: {
|
|
763
|
-
profile: "default"
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
},
|
|
768
|
-
codex: {
|
|
769
|
-
schema_version: codex.CONFIG_SCHEMA_VERSION,
|
|
770
|
-
organization,
|
|
771
|
-
project,
|
|
772
|
-
codex_repo: codexRepo,
|
|
773
|
-
remotes: {
|
|
774
|
-
// The codex repository - uses same token as git operations
|
|
775
|
-
[`${organization}/${codexRepo}`]: {
|
|
776
|
-
token: "${GITHUB_TOKEN}"
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
};
|
|
781
|
-
}
|
|
782
|
-
async function readUnifiedConfig(configPath) {
|
|
783
|
-
try {
|
|
784
|
-
const content = await fs4__namespace.readFile(configPath, "utf-8");
|
|
785
|
-
const config = yaml__namespace.load(content);
|
|
786
|
-
return config;
|
|
787
|
-
} catch (error) {
|
|
788
|
-
if (error.code === "ENOENT") {
|
|
789
|
-
return null;
|
|
790
|
-
}
|
|
791
|
-
throw error;
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
async function writeUnifiedConfig(config, outputPath) {
|
|
795
|
-
const dir = path2__namespace.dirname(outputPath);
|
|
796
|
-
await fs4__namespace.mkdir(dir, { recursive: true });
|
|
797
|
-
const yamlContent = yaml__namespace.dump(config, {
|
|
798
|
-
indent: 2,
|
|
799
|
-
lineWidth: 120,
|
|
800
|
-
noRefs: true,
|
|
801
|
-
sortKeys: false
|
|
802
|
-
});
|
|
803
|
-
await fs4__namespace.writeFile(outputPath, yamlContent, "utf-8");
|
|
804
|
-
}
|
|
805
|
-
function mergeUnifiedConfigs(existing, updates) {
|
|
806
|
-
const merged = {};
|
|
807
|
-
if (updates.file || existing.file) {
|
|
808
|
-
merged.file = {
|
|
809
|
-
schema_version: updates.file?.schema_version || existing.file?.schema_version || codex.CONFIG_SCHEMA_VERSION,
|
|
810
|
-
sources: {
|
|
811
|
-
...existing.file?.sources || {},
|
|
812
|
-
...updates.file?.sources || {}
|
|
813
|
-
}
|
|
814
|
-
};
|
|
815
|
-
}
|
|
816
|
-
if (updates.codex || existing.codex) {
|
|
817
|
-
merged.codex = {
|
|
818
|
-
schema_version: updates.codex?.schema_version || existing.codex?.schema_version || codex.CONFIG_SCHEMA_VERSION,
|
|
819
|
-
organization: updates.codex?.organization || existing.codex?.organization || "default",
|
|
820
|
-
project: updates.codex?.project || existing.codex?.project || "default",
|
|
821
|
-
codex_repo: updates.codex?.codex_repo || existing.codex?.codex_repo || "",
|
|
822
|
-
remotes: {
|
|
823
|
-
...existing.codex?.remotes || {},
|
|
824
|
-
...updates.codex?.remotes || {}
|
|
825
|
-
}
|
|
826
|
-
};
|
|
827
|
-
}
|
|
828
|
-
return merged;
|
|
829
|
-
}
|
|
830
|
-
async function initializeUnifiedConfig(configPath, organization, project, codexRepo, options) {
|
|
831
|
-
const existingConfig = await readUnifiedConfig(configPath);
|
|
832
|
-
if (existingConfig && !options?.force) {
|
|
833
|
-
const defaultConfig = getDefaultUnifiedConfig(organization, project, codexRepo);
|
|
834
|
-
const merged = mergeUnifiedConfigs(existingConfig, defaultConfig);
|
|
835
|
-
await writeUnifiedConfig(merged, configPath);
|
|
836
|
-
return {
|
|
837
|
-
created: false,
|
|
838
|
-
merged: true,
|
|
839
|
-
config: merged
|
|
840
|
-
};
|
|
841
|
-
}
|
|
842
|
-
const config = getDefaultUnifiedConfig(organization, project, codexRepo);
|
|
843
|
-
await writeUnifiedConfig(config, configPath);
|
|
844
|
-
return {
|
|
845
|
-
created: true,
|
|
846
|
-
merged: false,
|
|
847
|
-
config
|
|
848
|
-
};
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
// src/config/gitignore-utils.ts
|
|
852
|
-
init_cjs_shims();
|
|
853
|
-
var DEFAULT_FRACTARY_GITIGNORE = `# .fractary/.gitignore
|
|
854
|
-
# This file is managed by multiple plugins - each plugin manages its own section
|
|
855
|
-
|
|
856
|
-
# ===== fractary-codex (managed) =====
|
|
857
|
-
codex/cache/
|
|
858
|
-
# ===== end fractary-codex =====
|
|
859
|
-
`;
|
|
860
|
-
async function readFractaryGitignore(projectRoot) {
|
|
861
|
-
const gitignorePath = path2__namespace.join(projectRoot, ".fractary", ".gitignore");
|
|
862
|
-
try {
|
|
863
|
-
return await fs4__namespace.readFile(gitignorePath, "utf-8");
|
|
864
|
-
} catch (error) {
|
|
865
|
-
if (error.code === "ENOENT") {
|
|
866
|
-
return null;
|
|
867
|
-
}
|
|
868
|
-
throw error;
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
async function writeFractaryGitignore(projectRoot, content) {
|
|
872
|
-
const gitignorePath = path2__namespace.join(projectRoot, ".fractary", ".gitignore");
|
|
873
|
-
await fs4__namespace.mkdir(path2__namespace.join(projectRoot, ".fractary"), { recursive: true });
|
|
874
|
-
await fs4__namespace.writeFile(gitignorePath, content, "utf-8");
|
|
875
|
-
}
|
|
876
|
-
function normalizeCachePath(cachePath) {
|
|
877
|
-
let normalized = cachePath.replace(/\\/g, "/");
|
|
878
|
-
normalized = normalized.replace(/^\.fractary\//, "");
|
|
879
|
-
if (!normalized.endsWith("/")) {
|
|
880
|
-
normalized += "/";
|
|
881
|
-
}
|
|
882
|
-
return normalized;
|
|
883
|
-
}
|
|
884
|
-
function isCachePathIgnored(gitignoreContent, cachePath) {
|
|
885
|
-
const normalized = normalizeCachePath(cachePath);
|
|
886
|
-
const lines = gitignoreContent.split("\n").map((l) => l.trim());
|
|
887
|
-
return lines.some((line) => {
|
|
888
|
-
if (line.startsWith("#") || line === "") return false;
|
|
889
|
-
let normalizedLine = line.replace(/\\/g, "/");
|
|
890
|
-
if (!normalizedLine.endsWith("/")) {
|
|
891
|
-
normalizedLine += "/";
|
|
892
|
-
}
|
|
893
|
-
return normalizedLine === normalized;
|
|
894
|
-
});
|
|
895
|
-
}
|
|
896
|
-
function addCachePathToGitignore(gitignoreContent, cachePath, comment) {
|
|
897
|
-
const normalized = normalizeCachePath(cachePath);
|
|
898
|
-
if (isCachePathIgnored(gitignoreContent, cachePath)) {
|
|
899
|
-
return gitignoreContent;
|
|
900
|
-
}
|
|
901
|
-
let addition = "";
|
|
902
|
-
{
|
|
903
|
-
addition += `
|
|
904
|
-
# ${comment}
|
|
905
|
-
`;
|
|
906
|
-
}
|
|
907
|
-
addition += normalized + "\n";
|
|
908
|
-
return gitignoreContent.trimEnd() + addition;
|
|
909
|
-
}
|
|
910
|
-
async function ensureCachePathIgnored(projectRoot, cachePath) {
|
|
911
|
-
const gitignorePath = path2__namespace.join(projectRoot, ".fractary", ".gitignore");
|
|
912
|
-
let relativeCachePath = cachePath;
|
|
913
|
-
if (path2__namespace.isAbsolute(cachePath)) {
|
|
914
|
-
relativeCachePath = path2__namespace.relative(path2__namespace.join(projectRoot, ".fractary"), cachePath);
|
|
915
|
-
}
|
|
916
|
-
relativeCachePath = normalizeCachePath(relativeCachePath);
|
|
917
|
-
let content = await readFractaryGitignore(projectRoot);
|
|
918
|
-
const gitignoreExists = content !== null;
|
|
919
|
-
if (!gitignoreExists) {
|
|
920
|
-
content = DEFAULT_FRACTARY_GITIGNORE;
|
|
921
|
-
if (!isCachePathIgnored(content, relativeCachePath)) {
|
|
922
|
-
content = addCachePathToGitignore(content, relativeCachePath, "Custom cache directory");
|
|
923
|
-
}
|
|
924
|
-
await writeFractaryGitignore(projectRoot, content);
|
|
925
|
-
return {
|
|
926
|
-
created: true,
|
|
927
|
-
updated: false,
|
|
928
|
-
alreadyIgnored: false,
|
|
929
|
-
gitignorePath
|
|
930
|
-
};
|
|
931
|
-
}
|
|
932
|
-
if (isCachePathIgnored(content, relativeCachePath)) {
|
|
933
|
-
return {
|
|
934
|
-
created: false,
|
|
935
|
-
updated: false,
|
|
936
|
-
alreadyIgnored: true,
|
|
937
|
-
gitignorePath
|
|
938
|
-
};
|
|
939
|
-
}
|
|
940
|
-
content = addCachePathToGitignore(content, relativeCachePath, "Custom cache directory");
|
|
941
|
-
await writeFractaryGitignore(projectRoot, content);
|
|
942
|
-
return {
|
|
943
|
-
created: false,
|
|
944
|
-
updated: true,
|
|
945
|
-
alreadyIgnored: false,
|
|
946
|
-
gitignorePath
|
|
947
|
-
};
|
|
948
|
-
}
|
|
949
|
-
|
|
950
|
-
// src/commands/config/init.ts
|
|
951
|
-
function validateNameFormat(name, type) {
|
|
952
|
-
if (!name || typeof name !== "string") {
|
|
953
|
-
throw new Error(`${type} name is required`);
|
|
954
|
-
}
|
|
955
|
-
if (name.length > 100) {
|
|
956
|
-
throw new Error(`${type} name too long (max 100 characters)`);
|
|
957
|
-
}
|
|
958
|
-
const safePattern = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
|
|
959
|
-
if (!safePattern.test(name)) {
|
|
960
|
-
throw new Error(
|
|
961
|
-
`Invalid ${type} name format: "${name}". Must start with alphanumeric and contain only: a-z, A-Z, 0-9, ., -, _`
|
|
962
|
-
);
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
async function getOrgFromGitRemote() {
|
|
966
|
-
try {
|
|
967
|
-
const { execSync } = __require("child_process");
|
|
968
|
-
const remote = execSync("git remote get-url origin 2>/dev/null", { encoding: "utf-8" }).trim();
|
|
969
|
-
const sshMatch = remote.match(/git@github\.com:([^/]+)\//);
|
|
970
|
-
const httpsMatch = remote.match(/github\.com\/([^/]+)\//);
|
|
971
|
-
return sshMatch?.[1] || httpsMatch?.[1] || null;
|
|
972
|
-
} catch {
|
|
973
|
-
return null;
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
async function discoverCodexRepo(org) {
|
|
977
|
-
try {
|
|
978
|
-
validateNameFormat(org, "organization");
|
|
979
|
-
} catch (error) {
|
|
980
|
-
return { repo: null, error: "unknown", message: error.message };
|
|
981
|
-
}
|
|
982
|
-
try {
|
|
983
|
-
const { execSync } = __require("child_process");
|
|
984
|
-
try {
|
|
985
|
-
execSync("gh --version", { encoding: "utf-8", stdio: "pipe" });
|
|
986
|
-
} catch {
|
|
987
|
-
return {
|
|
988
|
-
repo: null,
|
|
989
|
-
error: "gh_not_installed",
|
|
990
|
-
message: "GitHub CLI (gh) is not installed. Install from https://cli.github.com/"
|
|
991
|
-
};
|
|
992
|
-
}
|
|
993
|
-
try {
|
|
994
|
-
execSync("gh auth status", { encoding: "utf-8", stdio: "pipe" });
|
|
995
|
-
} catch {
|
|
996
|
-
return {
|
|
997
|
-
repo: null,
|
|
998
|
-
error: "auth_failed",
|
|
999
|
-
message: "GitHub CLI not authenticated. Run: gh auth login"
|
|
1000
|
-
};
|
|
1001
|
-
}
|
|
1002
|
-
const result = execSync(
|
|
1003
|
-
`gh repo list ${org} --json name --jq '.[].name | select(startswith("codex."))' 2>&1`,
|
|
1004
|
-
{ encoding: "utf-8" }
|
|
1005
|
-
).trim();
|
|
1006
|
-
if (result.includes("Could not resolve to an Organization") || result.includes("Not Found")) {
|
|
1007
|
-
return {
|
|
1008
|
-
repo: null,
|
|
1009
|
-
error: "org_not_found",
|
|
1010
|
-
message: `Organization '${org}' not found on GitHub`
|
|
1011
|
-
};
|
|
1012
|
-
}
|
|
1013
|
-
const repos = result.split("\n").filter(Boolean);
|
|
1014
|
-
if (repos.length === 0) {
|
|
1015
|
-
return {
|
|
1016
|
-
repo: null,
|
|
1017
|
-
error: "no_repos_found",
|
|
1018
|
-
message: `No codex.* repositories found in organization '${org}'`
|
|
1019
|
-
};
|
|
1020
|
-
}
|
|
1021
|
-
return { repo: repos[0] };
|
|
1022
|
-
} catch (error) {
|
|
1023
|
-
return {
|
|
1024
|
-
repo: null,
|
|
1025
|
-
error: "unknown",
|
|
1026
|
-
message: error.message || "Unknown error during discovery"
|
|
1027
|
-
};
|
|
1028
|
-
}
|
|
1029
|
-
}
|
|
1030
|
-
async function fileExists(filePath) {
|
|
1031
|
-
try {
|
|
1032
|
-
await fs4__namespace.access(filePath);
|
|
1033
|
-
return true;
|
|
1034
|
-
} catch {
|
|
1035
|
-
return false;
|
|
1036
|
-
}
|
|
1037
|
-
}
|
|
1038
|
-
async function installMcpServer(projectRoot, configPath = ".fractary/config.yaml", options = {}) {
|
|
1039
|
-
const mcpJsonPath = path2__namespace.join(projectRoot, ".mcp.json");
|
|
1040
|
-
const { backup = true } = options;
|
|
1041
|
-
let existingConfig = { mcpServers: {} };
|
|
1042
|
-
let backupPath;
|
|
1043
|
-
let migrated = false;
|
|
1044
|
-
if (await fileExists(mcpJsonPath)) {
|
|
257
|
+
function configInitializeCommand() {
|
|
258
|
+
const cmd = new commander.Command("config-init");
|
|
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) => {
|
|
1045
260
|
try {
|
|
1046
|
-
const
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
const suffix = Math.random().toString(36).substring(2, 6);
|
|
1051
|
-
backupPath = `${mcpJsonPath}.backup.${timestamp}-${suffix}`;
|
|
1052
|
-
await fs4__namespace.writeFile(backupPath, content);
|
|
1053
|
-
}
|
|
1054
|
-
} catch {
|
|
1055
|
-
console.log(chalk7__default.default.yellow("\u26A0 Warning: .mcp.json contains invalid JSON, starting fresh"));
|
|
1056
|
-
existingConfig = { mcpServers: {} };
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
if (!existingConfig.mcpServers) {
|
|
1060
|
-
existingConfig.mcpServers = {};
|
|
1061
|
-
}
|
|
1062
|
-
const existing = existingConfig.mcpServers["fractary-codex"];
|
|
1063
|
-
if (existing) {
|
|
1064
|
-
const existingCommand = existing.command;
|
|
1065
|
-
const existingArgs = existing.args || [];
|
|
1066
|
-
if (existingCommand === "npx" && existingArgs.includes("@fractary/codex-mcp")) {
|
|
1067
|
-
return {
|
|
1068
|
-
installed: false,
|
|
1069
|
-
migrated: false,
|
|
1070
|
-
alreadyInstalled: true,
|
|
1071
|
-
backupPath
|
|
1072
|
-
};
|
|
1073
|
-
}
|
|
1074
|
-
if (existingCommand === "node" || existingArgs.includes("@fractary/codex")) {
|
|
1075
|
-
migrated = true;
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1078
|
-
existingConfig.mcpServers["fractary-codex"] = {
|
|
1079
|
-
command: "npx",
|
|
1080
|
-
args: ["-y", "@fractary/codex-mcp", "--config", configPath]
|
|
1081
|
-
};
|
|
1082
|
-
await fs4__namespace.writeFile(
|
|
1083
|
-
mcpJsonPath,
|
|
1084
|
-
JSON.stringify(existingConfig, null, 2) + "\n"
|
|
1085
|
-
);
|
|
1086
|
-
return {
|
|
1087
|
-
installed: true,
|
|
1088
|
-
migrated,
|
|
1089
|
-
alreadyInstalled: false,
|
|
1090
|
-
backupPath
|
|
1091
|
-
};
|
|
1092
|
-
}
|
|
1093
|
-
function configureCommand() {
|
|
1094
|
-
const cmd = new commander.Command("configure");
|
|
1095
|
-
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) => {
|
|
1096
|
-
try {
|
|
1097
|
-
console.log(chalk7__default.default.blue("Initializing unified Fractary configuration...\n"));
|
|
261
|
+
const configManager = codex.createConfigManager(process.cwd());
|
|
262
|
+
if (!options.json) {
|
|
263
|
+
console.log(chalk10__default.default.blue("Initializing codex configuration...\n"));
|
|
264
|
+
}
|
|
1098
265
|
let org = options.org;
|
|
1099
266
|
if (!org) {
|
|
1100
|
-
org = await
|
|
267
|
+
org = await configManager.detectOrganization();
|
|
1101
268
|
}
|
|
1102
269
|
if (!org) {
|
|
1103
270
|
try {
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
repoName: path2__namespace.basename(process.cwd())
|
|
271
|
+
org = codex.resolveOrganization({
|
|
272
|
+
repoName: path3__namespace.basename(process.cwd())
|
|
1107
273
|
});
|
|
1108
274
|
} catch {
|
|
1109
275
|
}
|
|
1110
276
|
}
|
|
1111
277
|
if (!org) {
|
|
1112
|
-
org =
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
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)}
|
|
1117
285
|
`));
|
|
1118
286
|
}
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
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
|
+
}
|
|
1123
294
|
process.exit(1);
|
|
1124
295
|
}
|
|
1125
296
|
let project = options.project;
|
|
1126
297
|
if (!project) {
|
|
1127
|
-
project =
|
|
1128
|
-
|
|
298
|
+
project = configManager.detectProject();
|
|
299
|
+
if (!options.json) {
|
|
300
|
+
console.log(chalk10__default.default.dim(`Project: ${chalk10__default.default.cyan(project)}
|
|
1129
301
|
`));
|
|
302
|
+
}
|
|
1130
303
|
}
|
|
1131
304
|
let codexRepo = options.codexRepo;
|
|
1132
305
|
if (codexRepo) {
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
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);
|
|
312
|
+
}
|
|
1137
313
|
process.exit(1);
|
|
1138
314
|
}
|
|
1139
|
-
|
|
315
|
+
if (!options.json) {
|
|
316
|
+
console.log(chalk10__default.default.dim(`Codex repository: ${chalk10__default.default.cyan(codexRepo)}
|
|
1140
317
|
`));
|
|
318
|
+
}
|
|
1141
319
|
} else {
|
|
1142
|
-
const discoveryResult = await discoverCodexRepo(org);
|
|
320
|
+
const discoveryResult = await configManager.discoverCodexRepo(org);
|
|
1143
321
|
if (discoveryResult.repo) {
|
|
1144
322
|
codexRepo = discoveryResult.repo;
|
|
1145
|
-
|
|
1146
|
-
`))
|
|
1147
|
-
} else {
|
|
1148
|
-
if (discoveryResult.error === "gh_not_installed") {
|
|
1149
|
-
console.log(chalk7__default.default.dim(` Note: ${discoveryResult.message}
|
|
1150
|
-
`));
|
|
1151
|
-
} else if (discoveryResult.error === "auth_failed") {
|
|
1152
|
-
console.log(chalk7__default.default.dim(` Note: ${discoveryResult.message}
|
|
323
|
+
if (!options.json) {
|
|
324
|
+
console.log(chalk10__default.default.dim(`Codex repository: ${chalk10__default.default.cyan(codexRepo)} (auto-discovered)
|
|
1153
325
|
`));
|
|
1154
|
-
}
|
|
1155
|
-
|
|
326
|
+
}
|
|
327
|
+
} else if (!options.json) {
|
|
328
|
+
if (discoveryResult.message) {
|
|
329
|
+
console.log(chalk10__default.default.dim(` Note: ${discoveryResult.message}
|
|
1156
330
|
`));
|
|
1157
331
|
}
|
|
1158
332
|
}
|
|
1159
333
|
}
|
|
1160
334
|
if (!codexRepo) {
|
|
1161
|
-
console.log(chalk7__default.default.yellow(`\u26A0 Could not discover codex repository in organization '${org}'`));
|
|
1162
|
-
console.log(chalk7__default.default.dim(" Use --codex-repo <name> to specify explicitly"));
|
|
1163
|
-
console.log(chalk7__default.default.dim(" Expected naming convention: codex.{org}.{tld} (e.g., codex.fractary.com)\n"));
|
|
1164
335
|
codexRepo = `codex.${org}.com`;
|
|
1165
|
-
|
|
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)}
|
|
1166
339
|
`));
|
|
340
|
+
}
|
|
1167
341
|
}
|
|
1168
|
-
const
|
|
1169
|
-
|
|
1170
|
-
if (configExists && !options.force) {
|
|
1171
|
-
console.log(chalk7__default.default.yellow(`\u26A0 Configuration already exists at .fractary/config.yaml`));
|
|
1172
|
-
console.log(chalk7__default.default.dim("Merging with existing configuration...\n"));
|
|
1173
|
-
}
|
|
1174
|
-
console.log("Creating directory structure...");
|
|
1175
|
-
const dirs = [
|
|
1176
|
-
".fractary",
|
|
1177
|
-
".fractary/specs",
|
|
1178
|
-
".fractary/logs",
|
|
1179
|
-
".fractary/codex",
|
|
1180
|
-
".fractary/codex/cache"
|
|
1181
|
-
];
|
|
1182
|
-
for (const dir of dirs) {
|
|
1183
|
-
await fs4__namespace.mkdir(path2__namespace.join(process.cwd(), dir), { recursive: true });
|
|
1184
|
-
console.log(chalk7__default.default.green("\u2713"), chalk7__default.default.dim(dir + "/"));
|
|
1185
|
-
}
|
|
1186
|
-
const gitignoreResult = await ensureCachePathIgnored(process.cwd(), ".fractary/codex/cache");
|
|
1187
|
-
if (gitignoreResult.created) {
|
|
1188
|
-
console.log(chalk7__default.default.green("\u2713"), chalk7__default.default.dim(".fractary/.gitignore (created)"));
|
|
1189
|
-
} else if (gitignoreResult.updated) {
|
|
1190
|
-
console.log(chalk7__default.default.green("\u2713"), chalk7__default.default.dim(".fractary/.gitignore (updated)"));
|
|
1191
|
-
} else {
|
|
1192
|
-
console.log(chalk7__default.default.green("\u2713"), chalk7__default.default.dim(".fractary/.gitignore (exists)"));
|
|
1193
|
-
}
|
|
1194
|
-
console.log("\nInitializing configuration...");
|
|
1195
|
-
const result = await initializeUnifiedConfig(
|
|
1196
|
-
configPath,
|
|
1197
|
-
org,
|
|
342
|
+
const result = await configManager.initializeCodexSection({
|
|
343
|
+
organization: org,
|
|
1198
344
|
project,
|
|
1199
345
|
codexRepo,
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
console.log(
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
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)"));
|
|
1219
392
|
}
|
|
1220
393
|
}
|
|
1221
|
-
console.log(
|
|
1222
|
-
console.log(
|
|
1223
|
-
console.log(
|
|
1224
|
-
console.log(
|
|
1225
|
-
console.log(
|
|
1226
|
-
console.log(
|
|
1227
|
-
console.log(
|
|
1228
|
-
console.log(
|
|
1229
|
-
console.log(
|
|
1230
|
-
console.log(chalk7__default.default.bold("\nCodex plugin:"));
|
|
1231
|
-
console.log(chalk7__default.default.dim(" - Cache: .fractary/codex/cache/"));
|
|
1232
|
-
console.log(chalk7__default.default.dim(" - MCP Server: @fractary/codex-mcp (via npx)"));
|
|
1233
|
-
console.log(chalk7__default.default.dim(" - Remotes: codex repo configured"));
|
|
1234
|
-
console.log(chalk7__default.default.bold("\nGit Authentication:"));
|
|
1235
|
-
console.log(chalk7__default.default.dim(" Codex sync uses your existing git credentials."));
|
|
1236
|
-
console.log(chalk7__default.default.dim(" Ensure you have access to the codex repository:"));
|
|
1237
|
-
console.log(chalk7__default.default.dim(` gh repo view ${org}/${codexRepo}`));
|
|
1238
|
-
console.log(chalk7__default.default.dim(" Or set GITHUB_TOKEN environment variable."));
|
|
1239
|
-
console.log(chalk7__default.default.bold("\nNext steps:"));
|
|
1240
|
-
console.log(chalk7__default.default.dim(" 1. Restart Claude Code to load the MCP server"));
|
|
1241
|
-
console.log(chalk7__default.default.dim(" 2. Verify codex repository access: gh repo view " + org + "/" + codexRepo));
|
|
1242
|
-
console.log(chalk7__default.default.dim(" 3. Configure AWS credentials for S3 access (if using file plugin)"));
|
|
1243
|
-
console.log(chalk7__default.default.dim(" 4. Edit .fractary/config.yaml to add external project remotes"));
|
|
1244
|
-
console.log(chalk7__default.default.dim(" 5. Reference docs via codex:// URIs (auto-fetched by MCP)"));
|
|
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"));
|
|
1245
403
|
} catch (error) {
|
|
1246
|
-
|
|
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);
|
|
408
|
+
}
|
|
1247
409
|
process.exit(1);
|
|
1248
410
|
}
|
|
1249
411
|
});
|
|
1250
412
|
return cmd;
|
|
1251
413
|
}
|
|
1252
414
|
|
|
415
|
+
// src/commands/config/update.ts
|
|
416
|
+
init_cjs_shims();
|
|
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");
|
|
447
|
+
}
|
|
448
|
+
process.exit(1);
|
|
449
|
+
}
|
|
450
|
+
if (!options.json) {
|
|
451
|
+
console.log(chalk10__default.default.blue("Updating codex configuration...\n"));
|
|
452
|
+
}
|
|
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)"));
|
|
481
|
+
}
|
|
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);
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
return cmd;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// src/commands/config/validate.ts
|
|
497
|
+
init_cjs_shims();
|
|
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);
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
return cmd;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// src/commands/config/init.ts
|
|
551
|
+
init_cjs_shims();
|
|
552
|
+
|
|
1253
553
|
// src/commands/document/index.ts
|
|
1254
554
|
init_cjs_shims();
|
|
1255
555
|
|
|
@@ -1277,14 +577,14 @@ function documentFetchCommand() {
|
|
|
1277
577
|
try {
|
|
1278
578
|
const { validateUri } = await import('@fractary/codex');
|
|
1279
579
|
if (!validateUri(uri)) {
|
|
1280
|
-
console.error(
|
|
1281
|
-
console.log(
|
|
1282
|
-
console.log(
|
|
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"));
|
|
1283
583
|
process.exit(1);
|
|
1284
584
|
}
|
|
1285
585
|
const client = await getClient();
|
|
1286
586
|
if (!options.json && !options.bypassCache) {
|
|
1287
|
-
console.error(
|
|
587
|
+
console.error(chalk10__default.default.dim(`Fetching ${uri}...`));
|
|
1288
588
|
}
|
|
1289
589
|
const result = await client.fetch(uri, {
|
|
1290
590
|
bypassCache: options.bypassCache,
|
|
@@ -1304,31 +604,31 @@ function documentFetchCommand() {
|
|
|
1304
604
|
};
|
|
1305
605
|
console.log(JSON.stringify(output, null, 2));
|
|
1306
606
|
} else if (options.output) {
|
|
1307
|
-
await
|
|
1308
|
-
console.log(
|
|
1309
|
-
console.log(
|
|
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`));
|
|
1310
610
|
if (result.fromCache) {
|
|
1311
|
-
console.log(
|
|
611
|
+
console.log(chalk10__default.default.dim(" Source: cache"));
|
|
1312
612
|
} else {
|
|
1313
|
-
console.log(
|
|
613
|
+
console.log(chalk10__default.default.dim(" Source: storage"));
|
|
1314
614
|
}
|
|
1315
615
|
} else {
|
|
1316
616
|
if (result.fromCache && !options.bypassCache) {
|
|
1317
|
-
console.error(
|
|
617
|
+
console.error(chalk10__default.default.green("\u2713"), chalk10__default.default.dim("from cache\n"));
|
|
1318
618
|
} else {
|
|
1319
|
-
console.error(
|
|
619
|
+
console.error(chalk10__default.default.green("\u2713"), chalk10__default.default.dim("fetched\n"));
|
|
1320
620
|
}
|
|
1321
621
|
console.log(result.content.toString("utf-8"));
|
|
1322
622
|
}
|
|
1323
623
|
} catch (error) {
|
|
1324
|
-
console.error(
|
|
624
|
+
console.error(chalk10__default.default.red("Error:"), error.message);
|
|
1325
625
|
if (error.message.includes("Failed to load configuration")) {
|
|
1326
|
-
console.log(
|
|
626
|
+
console.log(chalk10__default.default.dim('\nRun "fractary-codex configure" to create a configuration.'));
|
|
1327
627
|
} else if (error.message.includes("GITHUB_TOKEN")) {
|
|
1328
|
-
console.log(
|
|
628
|
+
console.log(chalk10__default.default.dim('\nSet your GitHub token: export GITHUB_TOKEN="your_token"'));
|
|
1329
629
|
} else if (error.message.includes("not found") || error.message.includes("404")) {
|
|
1330
|
-
console.log(
|
|
1331
|
-
console.log(
|
|
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."));
|
|
1332
632
|
}
|
|
1333
633
|
process.exit(1);
|
|
1334
634
|
}
|
|
@@ -1341,55 +641,116 @@ init_cjs_shims();
|
|
|
1341
641
|
|
|
1342
642
|
// src/commands/cache/list.ts
|
|
1343
643
|
init_cjs_shims();
|
|
1344
|
-
function
|
|
1345
|
-
if (
|
|
1346
|
-
|
|
1347
|
-
|
|
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
|
+
}
|
|
1348
665
|
}
|
|
1349
666
|
function cacheListCommand() {
|
|
1350
667
|
const cmd = new commander.Command("cache-list");
|
|
1351
|
-
cmd.description("List cache
|
|
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) => {
|
|
1352
669
|
try {
|
|
1353
670
|
const client = await getClient();
|
|
1354
|
-
const
|
|
1355
|
-
|
|
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) {
|
|
1356
679
|
if (options.json) {
|
|
1357
|
-
console.log(JSON.stringify({ entries: 0, message: "Cache is empty" }));
|
|
680
|
+
console.log(JSON.stringify({ entries: [], total: 0, message: "Cache is empty" }));
|
|
1358
681
|
} else {
|
|
1359
|
-
console.log(
|
|
1360
|
-
console.log(
|
|
682
|
+
console.log(chalk10__default.default.yellow("Cache is empty."));
|
|
683
|
+
console.log(chalk10__default.default.dim("Fetch some documents to populate the cache."));
|
|
1361
684
|
}
|
|
1362
685
|
return;
|
|
1363
686
|
}
|
|
1364
687
|
if (options.json) {
|
|
1365
|
-
console.log(JSON.stringify(
|
|
1366
|
-
entryCount: stats.entryCount,
|
|
1367
|
-
totalSize: stats.totalSize,
|
|
1368
|
-
freshCount: stats.freshCount,
|
|
1369
|
-
staleCount: stats.staleCount,
|
|
1370
|
-
expiredCount: stats.expiredCount
|
|
1371
|
-
}, null, 2));
|
|
688
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1372
689
|
return;
|
|
1373
690
|
}
|
|
1374
|
-
console.log(
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
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();
|
|
1387
730
|
console.log("");
|
|
1388
|
-
console.log(
|
|
1389
|
-
console.log(
|
|
1390
|
-
|
|
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
|
+
);
|
|
1391
737
|
} catch (error) {
|
|
1392
|
-
|
|
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
|
+
}
|
|
1393
754
|
process.exit(1);
|
|
1394
755
|
}
|
|
1395
756
|
});
|
|
@@ -1405,7 +766,7 @@ function cacheClearCommand() {
|
|
|
1405
766
|
const client = await getClient();
|
|
1406
767
|
const statsBefore = await client.getCacheStats();
|
|
1407
768
|
if (statsBefore.entryCount === 0) {
|
|
1408
|
-
console.log(
|
|
769
|
+
console.log(chalk10__default.default.yellow("Cache is already empty. Nothing to clear."));
|
|
1409
770
|
return;
|
|
1410
771
|
}
|
|
1411
772
|
let pattern;
|
|
@@ -1414,63 +775,53 @@ function cacheClearCommand() {
|
|
|
1414
775
|
} else if (options.pattern) {
|
|
1415
776
|
pattern = options.pattern;
|
|
1416
777
|
} else {
|
|
1417
|
-
console.log(
|
|
1418
|
-
console.log(
|
|
1419
|
-
console.log(
|
|
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/*")'));
|
|
1420
781
|
console.log("");
|
|
1421
|
-
console.log(
|
|
1422
|
-
console.log(
|
|
1423
|
-
console.log(
|
|
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/*"'));
|
|
1424
785
|
return;
|
|
1425
786
|
}
|
|
1426
787
|
if (options.dryRun) {
|
|
1427
|
-
console.log(
|
|
788
|
+
console.log(chalk10__default.default.blue("Dry run - would clear:\n"));
|
|
1428
789
|
if (pattern) {
|
|
1429
|
-
console.log(
|
|
1430
|
-
console.log(
|
|
790
|
+
console.log(chalk10__default.default.dim(` Pattern: ${pattern}`));
|
|
791
|
+
console.log(chalk10__default.default.dim(` This would invalidate matching cache entries`));
|
|
1431
792
|
} else {
|
|
1432
|
-
console.log(
|
|
793
|
+
console.log(chalk10__default.default.dim(` All cache entries (${statsBefore.entryCount} entries)`));
|
|
1433
794
|
}
|
|
1434
|
-
console.log(
|
|
1435
|
-
Total size: ${
|
|
795
|
+
console.log(chalk10__default.default.dim(`
|
|
796
|
+
Total size: ${codex.formatBytes(statsBefore.totalSize)}`));
|
|
1436
797
|
return;
|
|
1437
798
|
}
|
|
1438
799
|
if (pattern) {
|
|
1439
|
-
console.log(
|
|
800
|
+
console.log(chalk10__default.default.blue(`Clearing cache entries matching pattern: ${pattern}
|
|
1440
801
|
`));
|
|
1441
802
|
await client.invalidateCache(pattern);
|
|
1442
803
|
} else {
|
|
1443
|
-
console.log(
|
|
804
|
+
console.log(chalk10__default.default.blue(`Clearing entire cache (${statsBefore.entryCount} entries)...
|
|
1444
805
|
`));
|
|
1445
806
|
await client.invalidateCache();
|
|
1446
807
|
}
|
|
1447
808
|
const statsAfter = await client.getCacheStats();
|
|
1448
809
|
const entriesCleared = statsBefore.entryCount - statsAfter.entryCount;
|
|
1449
810
|
const sizeFreed = statsBefore.totalSize - statsAfter.totalSize;
|
|
1450
|
-
console.log(
|
|
811
|
+
console.log(chalk10__default.default.green(`\u2713 Cleared ${entriesCleared} entries (${codex.formatBytes(sizeFreed)} freed)`));
|
|
1451
812
|
if (statsAfter.entryCount > 0) {
|
|
1452
|
-
console.log(
|
|
813
|
+
console.log(chalk10__default.default.dim(` Remaining: ${statsAfter.entryCount} entries (${codex.formatBytes(statsAfter.totalSize)})`));
|
|
1453
814
|
}
|
|
1454
815
|
} catch (error) {
|
|
1455
|
-
console.error(
|
|
816
|
+
console.error(chalk10__default.default.red("Error:"), error.message);
|
|
1456
817
|
process.exit(1);
|
|
1457
818
|
}
|
|
1458
819
|
});
|
|
1459
820
|
return cmd;
|
|
1460
821
|
}
|
|
1461
|
-
function formatSize2(bytes) {
|
|
1462
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
1463
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
1464
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
1465
|
-
}
|
|
1466
822
|
|
|
1467
823
|
// src/commands/cache/stats.ts
|
|
1468
824
|
init_cjs_shims();
|
|
1469
|
-
function formatSize3(bytes) {
|
|
1470
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
1471
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
1472
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
1473
|
-
}
|
|
1474
825
|
function cacheStatsCommand() {
|
|
1475
826
|
const cmd = new commander.Command("cache-stats");
|
|
1476
827
|
cmd.description("Display cache statistics").option("--json", "Output as JSON").action(async (options) => {
|
|
@@ -1481,25 +832,25 @@ function cacheStatsCommand() {
|
|
|
1481
832
|
console.log(JSON.stringify(stats, null, 2));
|
|
1482
833
|
return;
|
|
1483
834
|
}
|
|
1484
|
-
console.log(
|
|
1485
|
-
console.log(
|
|
1486
|
-
console.log(` Total entries: ${
|
|
1487
|
-
console.log(` Total size: ${
|
|
1488
|
-
console.log(` Fresh entries: ${
|
|
1489
|
-
console.log(` Stale entries: ${stats.staleCount > 0 ?
|
|
1490
|
-
console.log(` Expired entries: ${stats.expiredCount > 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")}`);
|
|
1491
842
|
console.log("");
|
|
1492
843
|
const healthPercent = stats.entryCount > 0 ? stats.freshCount / stats.entryCount * 100 : 100;
|
|
1493
|
-
const healthColor = healthPercent > 80 ?
|
|
844
|
+
const healthColor = healthPercent > 80 ? chalk10__default.default.green : healthPercent > 50 ? chalk10__default.default.yellow : chalk10__default.default.red;
|
|
1494
845
|
console.log(`Cache health: ${healthColor(`${healthPercent.toFixed(0)}% fresh`)}`);
|
|
1495
846
|
if (stats.expiredCount > 0) {
|
|
1496
|
-
console.log(
|
|
847
|
+
console.log(chalk10__default.default.dim('\nRun "fractary-codex cache-clear --pattern <pattern>" to clean up entries.'));
|
|
1497
848
|
}
|
|
1498
849
|
if (stats.entryCount === 0) {
|
|
1499
|
-
console.log(
|
|
850
|
+
console.log(chalk10__default.default.dim("\nNo cached entries. Fetch some documents to populate the cache."));
|
|
1500
851
|
}
|
|
1501
852
|
} catch (error) {
|
|
1502
|
-
console.error(
|
|
853
|
+
console.error(chalk10__default.default.red("Error:"), error.message);
|
|
1503
854
|
process.exit(1);
|
|
1504
855
|
}
|
|
1505
856
|
});
|
|
@@ -1508,239 +859,81 @@ function cacheStatsCommand() {
|
|
|
1508
859
|
|
|
1509
860
|
// src/commands/cache/health.ts
|
|
1510
861
|
init_cjs_shims();
|
|
1511
|
-
init_migrate_config();
|
|
1512
|
-
async function fileExists2(filePath) {
|
|
1513
|
-
try {
|
|
1514
|
-
await fs4__namespace.access(filePath);
|
|
1515
|
-
return true;
|
|
1516
|
-
} catch {
|
|
1517
|
-
return false;
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
|
-
async function checkConfiguration() {
|
|
1521
|
-
const configPath = path2__namespace.join(process.cwd(), ".fractary", "config.yaml");
|
|
1522
|
-
const legacyConfigPath = path2__namespace.join(process.cwd(), ".fractary", "plugins", "codex", "config.json");
|
|
1523
|
-
try {
|
|
1524
|
-
if (!await fileExists2(configPath)) {
|
|
1525
|
-
if (await fileExists2(legacyConfigPath)) {
|
|
1526
|
-
return {
|
|
1527
|
-
name: "Configuration",
|
|
1528
|
-
status: "warn",
|
|
1529
|
-
message: "Legacy JSON configuration detected",
|
|
1530
|
-
details: "Migration from legacy JSON format may be required"
|
|
1531
|
-
};
|
|
1532
|
-
}
|
|
1533
|
-
return {
|
|
1534
|
-
name: "Configuration",
|
|
1535
|
-
status: "fail",
|
|
1536
|
-
message: "No configuration found",
|
|
1537
|
-
details: 'Run "fractary-codex configure" to create configuration'
|
|
1538
|
-
};
|
|
1539
|
-
}
|
|
1540
|
-
const config = await codex.readCodexConfig(configPath);
|
|
1541
|
-
if (!config.organization) {
|
|
1542
|
-
return {
|
|
1543
|
-
name: "Configuration",
|
|
1544
|
-
status: "warn",
|
|
1545
|
-
message: "No organization configured",
|
|
1546
|
-
details: "Organization slug is required"
|
|
1547
|
-
};
|
|
1548
|
-
}
|
|
1549
|
-
const providerCount = config.storage?.length || 0;
|
|
1550
|
-
if (providerCount === 0) {
|
|
1551
|
-
return {
|
|
1552
|
-
name: "Configuration",
|
|
1553
|
-
status: "warn",
|
|
1554
|
-
message: "No storage providers configured",
|
|
1555
|
-
details: "At least one storage provider is recommended"
|
|
1556
|
-
};
|
|
1557
|
-
}
|
|
1558
|
-
return {
|
|
1559
|
-
name: "Configuration",
|
|
1560
|
-
status: "pass",
|
|
1561
|
-
message: "Valid YAML configuration",
|
|
1562
|
-
details: `Organization: ${config.organization}, ${providerCount} storage provider(s)`
|
|
1563
|
-
};
|
|
1564
|
-
} catch (error) {
|
|
1565
|
-
return {
|
|
1566
|
-
name: "Configuration",
|
|
1567
|
-
status: "fail",
|
|
1568
|
-
message: "Invalid configuration",
|
|
1569
|
-
details: error.message
|
|
1570
|
-
};
|
|
1571
|
-
}
|
|
1572
|
-
}
|
|
1573
|
-
async function checkSDKClient() {
|
|
1574
|
-
try {
|
|
1575
|
-
const client = await getClient();
|
|
1576
|
-
const organization = client.getOrganization();
|
|
1577
|
-
return {
|
|
1578
|
-
name: "SDK Client",
|
|
1579
|
-
status: "pass",
|
|
1580
|
-
message: "CodexClient initialized successfully",
|
|
1581
|
-
details: `Organization: ${organization}`
|
|
1582
|
-
};
|
|
1583
|
-
} catch (error) {
|
|
1584
|
-
return {
|
|
1585
|
-
name: "SDK Client",
|
|
1586
|
-
status: "fail",
|
|
1587
|
-
message: "Failed to initialize CodexClient",
|
|
1588
|
-
details: error.message
|
|
1589
|
-
};
|
|
1590
|
-
}
|
|
1591
|
-
}
|
|
1592
|
-
async function checkCache() {
|
|
1593
|
-
try {
|
|
1594
|
-
const client = await getClient();
|
|
1595
|
-
const stats = await client.getCacheStats();
|
|
1596
|
-
if (stats.entryCount === 0) {
|
|
1597
|
-
return {
|
|
1598
|
-
name: "Cache",
|
|
1599
|
-
status: "warn",
|
|
1600
|
-
message: "Cache is empty",
|
|
1601
|
-
details: "Fetch some documents to populate cache"
|
|
1602
|
-
};
|
|
1603
|
-
}
|
|
1604
|
-
const healthPercent = stats.entryCount > 0 ? stats.freshCount / stats.entryCount * 100 : 100;
|
|
1605
|
-
if (healthPercent < 50) {
|
|
1606
|
-
return {
|
|
1607
|
-
name: "Cache",
|
|
1608
|
-
status: "warn",
|
|
1609
|
-
message: `${stats.entryCount} entries (${healthPercent.toFixed(0)}% fresh)`,
|
|
1610
|
-
details: `${stats.expiredCount} expired, ${stats.staleCount} stale`
|
|
1611
|
-
};
|
|
1612
|
-
}
|
|
1613
|
-
return {
|
|
1614
|
-
name: "Cache",
|
|
1615
|
-
status: "pass",
|
|
1616
|
-
message: `${stats.entryCount} entries (${healthPercent.toFixed(0)}% fresh)`,
|
|
1617
|
-
details: `${formatSize4(stats.totalSize)} total`
|
|
1618
|
-
};
|
|
1619
|
-
} catch (error) {
|
|
1620
|
-
return {
|
|
1621
|
-
name: "Cache",
|
|
1622
|
-
status: "fail",
|
|
1623
|
-
message: "Cache check failed",
|
|
1624
|
-
details: error.message
|
|
1625
|
-
};
|
|
1626
|
-
}
|
|
1627
|
-
}
|
|
1628
|
-
async function checkStorage() {
|
|
1629
|
-
const configPath = path2__namespace.join(process.cwd(), ".fractary", "config.yaml");
|
|
1630
|
-
try {
|
|
1631
|
-
const config = await codex.readCodexConfig(configPath);
|
|
1632
|
-
const providers = config.storage || [];
|
|
1633
|
-
if (providers.length === 0) {
|
|
1634
|
-
return {
|
|
1635
|
-
name: "Storage",
|
|
1636
|
-
status: "warn",
|
|
1637
|
-
message: "No storage providers configured",
|
|
1638
|
-
details: "Configure at least one provider in .fractary/config.yaml"
|
|
1639
|
-
};
|
|
1640
|
-
}
|
|
1641
|
-
const providerTypes = providers.map((p) => p.type).join(", ");
|
|
1642
|
-
const hasGitHub = providers.some((p) => p.type === "github");
|
|
1643
|
-
if (hasGitHub && !process.env.GITHUB_TOKEN) {
|
|
1644
|
-
return {
|
|
1645
|
-
name: "Storage",
|
|
1646
|
-
status: "warn",
|
|
1647
|
-
message: `${providers.length} provider(s): ${providerTypes}`,
|
|
1648
|
-
details: "GITHUB_TOKEN not set (required for GitHub provider)"
|
|
1649
|
-
};
|
|
1650
|
-
}
|
|
1651
|
-
return {
|
|
1652
|
-
name: "Storage",
|
|
1653
|
-
status: "pass",
|
|
1654
|
-
message: `${providers.length} provider(s): ${providerTypes}`,
|
|
1655
|
-
details: "All configured providers available"
|
|
1656
|
-
};
|
|
1657
|
-
} catch (error) {
|
|
1658
|
-
return {
|
|
1659
|
-
name: "Storage",
|
|
1660
|
-
status: "fail",
|
|
1661
|
-
message: "Storage check failed",
|
|
1662
|
-
details: error.message
|
|
1663
|
-
};
|
|
1664
|
-
}
|
|
1665
|
-
}
|
|
1666
|
-
async function checkTypes() {
|
|
1667
|
-
try {
|
|
1668
|
-
const client = await getClient();
|
|
1669
|
-
const registry = client.getTypeRegistry();
|
|
1670
|
-
const allTypes = registry.list();
|
|
1671
|
-
const builtinCount = allTypes.filter((t) => registry.isBuiltIn(t.name)).length;
|
|
1672
|
-
const customCount = allTypes.length - builtinCount;
|
|
1673
|
-
return {
|
|
1674
|
-
name: "Type Registry",
|
|
1675
|
-
status: "pass",
|
|
1676
|
-
message: `${allTypes.length} types registered`,
|
|
1677
|
-
details: `${builtinCount} built-in, ${customCount} custom`
|
|
1678
|
-
};
|
|
1679
|
-
} catch (error) {
|
|
1680
|
-
return {
|
|
1681
|
-
name: "Type Registry",
|
|
1682
|
-
status: "fail",
|
|
1683
|
-
message: "Type registry check failed",
|
|
1684
|
-
details: error.message
|
|
1685
|
-
};
|
|
1686
|
-
}
|
|
1687
|
-
}
|
|
1688
|
-
function formatSize4(bytes) {
|
|
1689
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
1690
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
1691
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
1692
|
-
}
|
|
1693
862
|
function cacheHealthCommand() {
|
|
1694
863
|
const cmd = new commander.Command("cache-health");
|
|
1695
864
|
cmd.description("Run diagnostics on codex setup").option("--json", "Output as JSON").action(async (options) => {
|
|
1696
865
|
try {
|
|
866
|
+
const healthChecker = codex.createHealthChecker({
|
|
867
|
+
projectRoot: process.cwd()
|
|
868
|
+
});
|
|
1697
869
|
const checks = [];
|
|
1698
|
-
checks.push(await checkConfiguration());
|
|
1699
|
-
checks.push(await
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
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);
|
|
1706
906
|
if (options.json) {
|
|
1707
|
-
console.log(JSON.stringify(
|
|
1708
|
-
summary: {
|
|
1709
|
-
total: checks.length,
|
|
1710
|
-
passed,
|
|
1711
|
-
warned,
|
|
1712
|
-
failed,
|
|
1713
|
-
healthy: failed === 0
|
|
1714
|
-
},
|
|
1715
|
-
checks
|
|
1716
|
-
}, null, 2));
|
|
907
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1717
908
|
return;
|
|
1718
909
|
}
|
|
1719
|
-
console.log(
|
|
1720
|
-
for (const check of checks) {
|
|
1721
|
-
const icon = check.status === "pass" ?
|
|
1722
|
-
const statusColor = check.status === "pass" ?
|
|
1723
|
-
console.log(`${icon} ${
|
|
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)}`);
|
|
1724
915
|
console.log(` ${statusColor(check.message)}`);
|
|
1725
916
|
if (check.details) {
|
|
1726
|
-
console.log(` ${
|
|
917
|
+
console.log(` ${chalk10__default.default.dim(check.details)}`);
|
|
1727
918
|
}
|
|
1728
919
|
console.log("");
|
|
1729
920
|
}
|
|
1730
|
-
console.log(
|
|
1731
|
-
const overallStatus =
|
|
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");
|
|
1732
923
|
console.log(`Status: ${overallStatus}`);
|
|
1733
|
-
console.log(
|
|
1734
|
-
|
|
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) {
|
|
1735
928
|
console.log("");
|
|
1736
|
-
console.log(
|
|
1737
|
-
console.log(
|
|
929
|
+
console.log(chalk10__default.default.dim("Run checks individually for more details:"));
|
|
930
|
+
console.log(chalk10__default.default.dim(" fractary-codex cache-stats"));
|
|
1738
931
|
}
|
|
1739
|
-
if (failed > 0) {
|
|
932
|
+
if (result.summary.failed > 0) {
|
|
1740
933
|
process.exit(1);
|
|
1741
934
|
}
|
|
1742
935
|
} catch (error) {
|
|
1743
|
-
console.error(
|
|
936
|
+
console.error(chalk10__default.default.red("Error:"), error.message);
|
|
1744
937
|
process.exit(1);
|
|
1745
938
|
}
|
|
1746
939
|
});
|
|
@@ -1749,7 +942,11 @@ function cacheHealthCommand() {
|
|
|
1749
942
|
|
|
1750
943
|
// src/commands/sync.ts
|
|
1751
944
|
init_cjs_shims();
|
|
1752
|
-
|
|
945
|
+
|
|
946
|
+
// src/config/migrate-config.ts
|
|
947
|
+
init_cjs_shims();
|
|
948
|
+
|
|
949
|
+
// src/commands/sync.ts
|
|
1753
950
|
function getEnvironmentBranch(config, env) {
|
|
1754
951
|
const envMap = config.sync?.environments || {
|
|
1755
952
|
dev: "develop",
|
|
@@ -1759,26 +956,17 @@ function getEnvironmentBranch(config, env) {
|
|
|
1759
956
|
};
|
|
1760
957
|
return envMap[env] || env;
|
|
1761
958
|
}
|
|
1762
|
-
function formatBytes(bytes) {
|
|
1763
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
1764
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
1765
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
1766
|
-
}
|
|
1767
|
-
function formatDuration(ms) {
|
|
1768
|
-
if (ms < 1e3) return `${ms}ms`;
|
|
1769
|
-
return `${(ms / 1e3).toFixed(1)}s`;
|
|
1770
|
-
}
|
|
1771
959
|
function syncCommand() {
|
|
1772
960
|
const cmd = new commander.Command("sync");
|
|
1773
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) => {
|
|
1774
962
|
try {
|
|
1775
|
-
const configPath =
|
|
963
|
+
const configPath = path3__namespace.join(process.cwd(), ".fractary", "config.yaml");
|
|
1776
964
|
let config;
|
|
1777
965
|
try {
|
|
1778
966
|
config = await codex.readCodexConfig(configPath);
|
|
1779
967
|
} catch (error) {
|
|
1780
|
-
console.error(
|
|
1781
|
-
console.log(
|
|
968
|
+
console.error(chalk10__default.default.red("Error:"), "Codex not initialized.");
|
|
969
|
+
console.log(chalk10__default.default.dim('Run "fractary-codex configure" first.'));
|
|
1782
970
|
process.exit(1);
|
|
1783
971
|
}
|
|
1784
972
|
const { createSyncManager, createLocalStorage, detectCurrentProject } = await import('@fractary/codex');
|
|
@@ -1791,14 +979,14 @@ function syncCommand() {
|
|
|
1791
979
|
projectName = detected.project || void 0;
|
|
1792
980
|
}
|
|
1793
981
|
if (!projectName) {
|
|
1794
|
-
console.error(
|
|
1795
|
-
console.log(
|
|
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."));
|
|
1796
984
|
process.exit(1);
|
|
1797
985
|
}
|
|
1798
986
|
const validDirections = ["to-codex", "from-codex", "bidirectional"];
|
|
1799
987
|
if (!validDirections.includes(options.direction)) {
|
|
1800
|
-
console.error(
|
|
1801
|
-
console.log(
|
|
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"));
|
|
1802
990
|
process.exit(1);
|
|
1803
991
|
}
|
|
1804
992
|
const direction = options.direction;
|
|
@@ -1809,7 +997,7 @@ function syncCommand() {
|
|
|
1809
997
|
const syncManager = createSyncManager({
|
|
1810
998
|
localStorage,
|
|
1811
999
|
config: config.sync,
|
|
1812
|
-
manifestPath:
|
|
1000
|
+
manifestPath: path3__namespace.join(process.cwd(), ".fractary", ".codex-sync-manifest.json")
|
|
1813
1001
|
});
|
|
1814
1002
|
const defaultToCodexPatterns = [
|
|
1815
1003
|
"docs/**/*.md",
|
|
@@ -1839,13 +1027,13 @@ function syncCommand() {
|
|
|
1839
1027
|
});
|
|
1840
1028
|
matches.forEach((match) => matchedFilePaths.add(match));
|
|
1841
1029
|
} catch (error) {
|
|
1842
|
-
console.error(
|
|
1030
|
+
console.error(chalk10__default.default.yellow(`Warning: Invalid pattern "${pattern}": ${error.message}`));
|
|
1843
1031
|
}
|
|
1844
1032
|
}
|
|
1845
1033
|
const targetFiles = await Promise.all(
|
|
1846
1034
|
Array.from(matchedFilePaths).map(async (filePath) => {
|
|
1847
|
-
const fullPath =
|
|
1848
|
-
const stats = await import('fs/promises').then((
|
|
1035
|
+
const fullPath = path3__namespace.join(sourceDir, filePath);
|
|
1036
|
+
const stats = await import('fs/promises').then((fs3) => fs3.stat(fullPath));
|
|
1849
1037
|
return {
|
|
1850
1038
|
path: filePath,
|
|
1851
1039
|
size: stats.size,
|
|
@@ -1869,14 +1057,14 @@ function syncCommand() {
|
|
|
1869
1057
|
try {
|
|
1870
1058
|
const { ensureCodexCloned: ensureCodexCloned2 } = await Promise.resolve().then(() => (init_codex_repository(), codex_repository_exports));
|
|
1871
1059
|
if (!options.json) {
|
|
1872
|
-
console.log(
|
|
1060
|
+
console.log(chalk10__default.default.blue("\u2139 Cloning/updating codex repository..."));
|
|
1873
1061
|
}
|
|
1874
1062
|
codexRepoPath = await ensureCodexCloned2(config, {
|
|
1875
1063
|
branch: targetBranch
|
|
1876
1064
|
});
|
|
1877
1065
|
if (!options.json) {
|
|
1878
|
-
console.log(
|
|
1879
|
-
console.log(
|
|
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"));
|
|
1880
1068
|
} else {
|
|
1881
1069
|
console.log(JSON.stringify({
|
|
1882
1070
|
info: "Routing-aware sync: cloned codex repository and scanning for files targeting this project",
|
|
@@ -1884,29 +1072,29 @@ function syncCommand() {
|
|
|
1884
1072
|
}, null, 2));
|
|
1885
1073
|
}
|
|
1886
1074
|
} catch (error) {
|
|
1887
|
-
console.error(
|
|
1888
|
-
console.error(
|
|
1889
|
-
console.log(
|
|
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:"));
|
|
1890
1078
|
if (error.message.includes("Git command not found")) {
|
|
1891
|
-
console.log(
|
|
1892
|
-
console.log(
|
|
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"));
|
|
1893
1081
|
} else if (error.message.includes("authentication failed") || error.message.includes("Authentication failed")) {
|
|
1894
|
-
console.log(
|
|
1895
|
-
console.log(
|
|
1896
|
-
console.log(
|
|
1897
|
-
console.log(
|
|
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"));
|
|
1898
1086
|
} else if (error.message.includes("Permission denied")) {
|
|
1899
|
-
console.log(
|
|
1900
|
-
console.log(
|
|
1901
|
-
console.log(
|
|
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"));
|
|
1902
1090
|
} else if (error.message.includes("not found") || error.message.includes("does not exist")) {
|
|
1903
|
-
console.log(
|
|
1904
|
-
console.log(
|
|
1905
|
-
console.log(
|
|
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"));
|
|
1906
1094
|
} else {
|
|
1907
|
-
console.log(
|
|
1908
|
-
console.log(
|
|
1909
|
-
console.log(
|
|
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"}`));
|
|
1910
1098
|
}
|
|
1911
1099
|
process.exit(1);
|
|
1912
1100
|
}
|
|
@@ -1925,17 +1113,17 @@ function syncCommand() {
|
|
|
1925
1113
|
try {
|
|
1926
1114
|
const { ensureCodexCloned: ensureCodexCloned2 } = await Promise.resolve().then(() => (init_codex_repository(), codex_repository_exports));
|
|
1927
1115
|
if (!options.json) {
|
|
1928
|
-
console.log(
|
|
1116
|
+
console.log(chalk10__default.default.blue("\u2139 Cloning/updating codex repository..."));
|
|
1929
1117
|
}
|
|
1930
1118
|
codexRepoPath = await ensureCodexCloned2(config, {
|
|
1931
1119
|
branch: targetBranch
|
|
1932
1120
|
});
|
|
1933
1121
|
if (!options.json) {
|
|
1934
|
-
console.log(
|
|
1122
|
+
console.log(chalk10__default.default.dim(` Codex cloned to: ${codexRepoPath}`));
|
|
1935
1123
|
}
|
|
1936
1124
|
} catch (error) {
|
|
1937
|
-
console.error(
|
|
1938
|
-
console.error(
|
|
1125
|
+
console.error(chalk10__default.default.red("Error:"), "Failed to clone codex repository");
|
|
1126
|
+
console.error(chalk10__default.default.dim(` ${error.message}`));
|
|
1939
1127
|
process.exit(1);
|
|
1940
1128
|
}
|
|
1941
1129
|
plan = await syncManager.createPlan(
|
|
@@ -1947,7 +1135,7 @@ function syncCommand() {
|
|
|
1947
1135
|
syncOptions
|
|
1948
1136
|
);
|
|
1949
1137
|
plan.source = sourceDir;
|
|
1950
|
-
plan.target =
|
|
1138
|
+
plan.target = path3__namespace.join(codexRepoPath, "projects", projectName);
|
|
1951
1139
|
}
|
|
1952
1140
|
if (plan.totalFiles === 0) {
|
|
1953
1141
|
if (options.json) {
|
|
@@ -1961,7 +1149,7 @@ function syncCommand() {
|
|
|
1961
1149
|
message: "No files to sync"
|
|
1962
1150
|
}, null, 2));
|
|
1963
1151
|
} else {
|
|
1964
|
-
console.log(
|
|
1152
|
+
console.log(chalk10__default.default.yellow("No files to sync."));
|
|
1965
1153
|
}
|
|
1966
1154
|
return;
|
|
1967
1155
|
}
|
|
@@ -2017,81 +1205,81 @@ function syncCommand() {
|
|
|
2017
1205
|
}, null, 2));
|
|
2018
1206
|
return;
|
|
2019
1207
|
}
|
|
2020
|
-
console.log(
|
|
2021
|
-
console.log(` Project: ${
|
|
2022
|
-
console.log(` Organization: ${
|
|
2023
|
-
console.log(` Environment: ${
|
|
2024
|
-
console.log(` Direction: ${
|
|
2025
|
-
console.log(` Files: ${
|
|
2026
|
-
console.log(` Total size: ${
|
|
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))}`);
|
|
2027
1215
|
if (plan.estimatedTime) {
|
|
2028
|
-
console.log(` Est. time: ${
|
|
1216
|
+
console.log(` Est. time: ${chalk10__default.default.dim(codex.formatDuration(plan.estimatedTime))}`);
|
|
2029
1217
|
}
|
|
2030
1218
|
if (routingScan) {
|
|
2031
1219
|
console.log("");
|
|
2032
|
-
console.log(
|
|
2033
|
-
console.log(` Scanned: ${
|
|
2034
|
-
console.log(` Matched: ${
|
|
2035
|
-
console.log(` Source projects: ${
|
|
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())}`);
|
|
2036
1224
|
if (routingScan.stats.sourceProjects.length > 0) {
|
|
2037
|
-
console.log(
|
|
1225
|
+
console.log(chalk10__default.default.dim(` ${routingScan.stats.sourceProjects.slice(0, 5).join(", ")}`));
|
|
2038
1226
|
if (routingScan.stats.sourceProjects.length > 5) {
|
|
2039
|
-
console.log(
|
|
1227
|
+
console.log(chalk10__default.default.dim(` ... and ${routingScan.stats.sourceProjects.length - 5} more`));
|
|
2040
1228
|
}
|
|
2041
1229
|
}
|
|
2042
|
-
console.log(` Scan time: ${
|
|
1230
|
+
console.log(` Scan time: ${chalk10__default.default.dim(codex.formatDuration(routingScan.stats.durationMs))}`);
|
|
2043
1231
|
}
|
|
2044
1232
|
console.log("");
|
|
2045
1233
|
if (plan.conflicts.length > 0) {
|
|
2046
|
-
console.log(
|
|
1234
|
+
console.log(chalk10__default.default.yellow(`\u26A0 ${plan.conflicts.length} conflicts detected:`));
|
|
2047
1235
|
for (const conflict of plan.conflicts.slice(0, 5)) {
|
|
2048
|
-
console.log(
|
|
1236
|
+
console.log(chalk10__default.default.yellow(` \u2022 ${conflict.path}`));
|
|
2049
1237
|
}
|
|
2050
1238
|
if (plan.conflicts.length > 5) {
|
|
2051
|
-
console.log(
|
|
1239
|
+
console.log(chalk10__default.default.dim(` ... and ${plan.conflicts.length - 5} more`));
|
|
2052
1240
|
}
|
|
2053
1241
|
console.log("");
|
|
2054
1242
|
}
|
|
2055
1243
|
if (plan.skipped.length > 0) {
|
|
2056
|
-
console.log(
|
|
1244
|
+
console.log(chalk10__default.default.dim(`${plan.skipped.length} files skipped (no changes)`));
|
|
2057
1245
|
console.log("");
|
|
2058
1246
|
}
|
|
2059
1247
|
if (options.dryRun) {
|
|
2060
|
-
console.log(
|
|
1248
|
+
console.log(chalk10__default.default.blue("Dry run - would sync:\n"));
|
|
2061
1249
|
const filesToShow = plan.files.slice(0, 10);
|
|
2062
1250
|
for (const file of filesToShow) {
|
|
2063
1251
|
const arrow = direction === "to-codex" ? "\u2192" : direction === "from-codex" ? "\u2190" : "\u2194";
|
|
2064
|
-
const opColor = file.operation === "create" ?
|
|
1252
|
+
const opColor = file.operation === "create" ? chalk10__default.default.green : file.operation === "update" ? chalk10__default.default.yellow : chalk10__default.default.dim;
|
|
2065
1253
|
console.log(
|
|
2066
|
-
|
|
1254
|
+
chalk10__default.default.dim(` ${arrow}`),
|
|
2067
1255
|
opColor(file.operation.padEnd(7)),
|
|
2068
1256
|
file.path,
|
|
2069
|
-
|
|
1257
|
+
chalk10__default.default.dim(`(${codex.formatBytes(file.size || 0)})`)
|
|
2070
1258
|
);
|
|
2071
1259
|
}
|
|
2072
1260
|
if (plan.files.length > 10) {
|
|
2073
|
-
console.log(
|
|
1261
|
+
console.log(chalk10__default.default.dim(` ... and ${plan.files.length - 10} more files`));
|
|
2074
1262
|
}
|
|
2075
|
-
console.log(
|
|
2076
|
-
Total: ${plan.totalFiles} files (${formatBytes(plan.totalBytes)})`));
|
|
2077
|
-
console.log(
|
|
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."));
|
|
2078
1266
|
return;
|
|
2079
1267
|
}
|
|
2080
|
-
console.log(
|
|
1268
|
+
console.log(chalk10__default.default.blue("Syncing...\n"));
|
|
2081
1269
|
const startTime = Date.now();
|
|
2082
1270
|
const result = await syncManager.executePlan(plan, syncOptions);
|
|
2083
1271
|
const duration = Date.now() - startTime;
|
|
2084
1272
|
if (direction === "to-codex" && codexRepoPath && result.synced > 0) {
|
|
2085
1273
|
try {
|
|
2086
1274
|
if (!options.json) {
|
|
2087
|
-
console.log(
|
|
1275
|
+
console.log(chalk10__default.default.blue("Committing and pushing to codex..."));
|
|
2088
1276
|
}
|
|
2089
1277
|
const { RepoManager } = await import('@fractary/core/repo');
|
|
2090
1278
|
const repoManager = new RepoManager({ platform: "github" }, codexRepoPath);
|
|
2091
1279
|
repoManager.stageAll();
|
|
2092
1280
|
if (repoManager.isClean()) {
|
|
2093
1281
|
if (!options.json) {
|
|
2094
|
-
console.log(
|
|
1282
|
+
console.log(chalk10__default.default.dim(" No changes to push - codex is already up to date"));
|
|
2095
1283
|
}
|
|
2096
1284
|
} else {
|
|
2097
1285
|
repoManager.commit({
|
|
@@ -2099,54 +1287,56 @@ Total: ${plan.totalFiles} files (${formatBytes(plan.totalBytes)})`));
|
|
|
2099
1287
|
});
|
|
2100
1288
|
repoManager.push({});
|
|
2101
1289
|
if (!options.json) {
|
|
2102
|
-
console.log(
|
|
1290
|
+
console.log(chalk10__default.default.dim(" Changes pushed to codex repository"));
|
|
2103
1291
|
}
|
|
2104
1292
|
}
|
|
2105
1293
|
} catch (error) {
|
|
2106
|
-
console.error(
|
|
1294
|
+
console.error(chalk10__default.default.red("Error pushing to codex:"), error.message);
|
|
2107
1295
|
}
|
|
2108
1296
|
}
|
|
2109
1297
|
console.log("");
|
|
2110
1298
|
if (result.success) {
|
|
2111
|
-
console.log(
|
|
2112
|
-
console.log(
|
|
1299
|
+
console.log(chalk10__default.default.green(`\u2713 Sync completed successfully`));
|
|
1300
|
+
console.log(chalk10__default.default.dim(` Synced: ${result.synced} files`));
|
|
2113
1301
|
if (result.skipped > 0) {
|
|
2114
|
-
console.log(
|
|
1302
|
+
console.log(chalk10__default.default.dim(` Skipped: ${result.skipped} files`));
|
|
2115
1303
|
}
|
|
2116
|
-
console.log(
|
|
1304
|
+
console.log(chalk10__default.default.dim(` Duration: ${codex.formatDuration(duration)}`));
|
|
2117
1305
|
} else {
|
|
2118
|
-
console.log(
|
|
2119
|
-
console.log(
|
|
2120
|
-
console.log(
|
|
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`));
|
|
2121
1309
|
if (result.skipped > 0) {
|
|
2122
|
-
console.log(
|
|
1310
|
+
console.log(chalk10__default.default.dim(` Skipped: ${result.skipped} files`));
|
|
2123
1311
|
}
|
|
2124
1312
|
if (result.errors.length > 0) {
|
|
2125
1313
|
console.log("");
|
|
2126
|
-
console.log(
|
|
1314
|
+
console.log(chalk10__default.default.red("Errors:"));
|
|
2127
1315
|
for (const error of result.errors.slice(0, 5)) {
|
|
2128
|
-
console.log(
|
|
1316
|
+
console.log(chalk10__default.default.red(` \u2022 ${error.path}: ${error.error}`));
|
|
2129
1317
|
}
|
|
2130
1318
|
if (result.errors.length > 5) {
|
|
2131
|
-
console.log(
|
|
1319
|
+
console.log(chalk10__default.default.dim(` ... and ${result.errors.length - 5} more errors`));
|
|
2132
1320
|
}
|
|
2133
1321
|
}
|
|
2134
1322
|
}
|
|
2135
1323
|
} catch (error) {
|
|
2136
|
-
console.error(
|
|
1324
|
+
console.error(chalk10__default.default.red("Error:"), error.message);
|
|
2137
1325
|
process.exit(1);
|
|
2138
1326
|
}
|
|
2139
1327
|
});
|
|
2140
1328
|
return cmd;
|
|
2141
1329
|
}
|
|
2142
1330
|
var __filename2 = url.fileURLToPath(importMetaUrl);
|
|
2143
|
-
var __dirname$1 =
|
|
2144
|
-
var packageJson = JSON.parse(fs.readFileSync(
|
|
1331
|
+
var __dirname$1 = path3.dirname(__filename2);
|
|
1332
|
+
var packageJson = JSON.parse(fs.readFileSync(path3.join(__dirname$1, "../package.json"), "utf-8"));
|
|
2145
1333
|
var VERSION = packageJson.version;
|
|
2146
1334
|
function createCLI() {
|
|
2147
1335
|
const program = new commander.Command("fractary-codex");
|
|
2148
1336
|
program.description("Centralized knowledge management and distribution for AI agents").version(VERSION);
|
|
2149
|
-
program.addCommand(
|
|
1337
|
+
program.addCommand(configInitializeCommand());
|
|
1338
|
+
program.addCommand(configUpdateCommand());
|
|
1339
|
+
program.addCommand(configValidateCommand());
|
|
2150
1340
|
program.addCommand(documentFetchCommand());
|
|
2151
1341
|
program.addCommand(cacheListCommand());
|
|
2152
1342
|
program.addCommand(cacheClearCommand());
|