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