@dirxai/cli 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +271 -106
- package/package.json +5 -11
- package/LICENSE +0 -21
- package/README.md +0 -89
package/dist/index.js
CHANGED
|
@@ -207,12 +207,100 @@ var init_init = __esm({
|
|
|
207
207
|
}
|
|
208
208
|
});
|
|
209
209
|
|
|
210
|
+
// src/commands/register.ts
|
|
211
|
+
var register_exports = {};
|
|
212
|
+
__export(register_exports, {
|
|
213
|
+
runRegister: () => runRegister
|
|
214
|
+
});
|
|
215
|
+
async function runRegister(options) {
|
|
216
|
+
const projectDir = options.dir ?? process.cwd();
|
|
217
|
+
const gatewayUrl = options.gatewayUrl ?? process.env.DIRX_GATEWAY_URL ?? "https://api.dirx.ai";
|
|
218
|
+
const domain = options.domain ?? process.env.DIRX_DOMAIN;
|
|
219
|
+
if (!domain) {
|
|
220
|
+
throw new Error(
|
|
221
|
+
"Domain is required. Use --domain or DIRX_DOMAIN env var."
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
const token = await resolveToken({
|
|
225
|
+
token: options.token,
|
|
226
|
+
domain,
|
|
227
|
+
gatewayUrl
|
|
228
|
+
});
|
|
229
|
+
const dirMdPath = join(projectDir, "DIR.md");
|
|
230
|
+
let dirMd;
|
|
231
|
+
try {
|
|
232
|
+
dirMd = await readFile(dirMdPath, "utf-8");
|
|
233
|
+
} catch {
|
|
234
|
+
throw new Error(
|
|
235
|
+
`DIR.md not found at ${dirMdPath}. Run 'dirx init' first.`
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
if (!dirMd.trim()) {
|
|
239
|
+
throw new Error(`DIR.md is empty at ${dirMdPath}`);
|
|
240
|
+
}
|
|
241
|
+
const baseUrl = gatewayUrl.replace(/\/$/, "");
|
|
242
|
+
const url = `${baseUrl}/registry/services?domain=${encodeURIComponent(domain)}`;
|
|
243
|
+
const res = await fetch(url, {
|
|
244
|
+
method: "POST",
|
|
245
|
+
headers: {
|
|
246
|
+
Authorization: `Bearer ${token}`,
|
|
247
|
+
"Content-Type": "text/markdown"
|
|
248
|
+
},
|
|
249
|
+
body: dirMd
|
|
250
|
+
});
|
|
251
|
+
if (!res.ok) {
|
|
252
|
+
const body = await res.text();
|
|
253
|
+
throw new Error(`Registration failed (${res.status}): ${body}`);
|
|
254
|
+
}
|
|
255
|
+
const result = await res.json();
|
|
256
|
+
console.log(`Registered ${result.name} as ${result.domain}`);
|
|
257
|
+
}
|
|
258
|
+
async function resolveToken(options) {
|
|
259
|
+
if (options.token) return options.token;
|
|
260
|
+
if (process.env.DIRX_PUBLISH_TOKEN) return process.env.DIRX_PUBLISH_TOKEN;
|
|
261
|
+
if (options.domain) {
|
|
262
|
+
const stored = await getToken(options.domain);
|
|
263
|
+
if (stored) return stored;
|
|
264
|
+
const gw = options.gatewayUrl ?? process.env.DIRX_GATEWAY_URL;
|
|
265
|
+
if (gw) {
|
|
266
|
+
const renewed = await renewToken(gw, options.domain);
|
|
267
|
+
if (renewed) return renewed;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
throw new Error(
|
|
271
|
+
"No auth token found. Use `dirx claim <domain>` to obtain a publish token, or provide --token."
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
async function renewToken(gatewayUrl, domain) {
|
|
275
|
+
const baseUrl = gatewayUrl.replace(/\/$/, "");
|
|
276
|
+
try {
|
|
277
|
+
const res = await fetch(`${baseUrl}/domains/verify`, {
|
|
278
|
+
method: "POST",
|
|
279
|
+
headers: { "Content-Type": "application/json" },
|
|
280
|
+
body: JSON.stringify({ domain })
|
|
281
|
+
});
|
|
282
|
+
if (!res.ok) return null;
|
|
283
|
+
const data = await res.json();
|
|
284
|
+
if (!data.publishToken) return null;
|
|
285
|
+
await saveToken(domain, data.publishToken);
|
|
286
|
+
console.log(`Token renewed for ${domain}`);
|
|
287
|
+
return data.publishToken;
|
|
288
|
+
} catch {
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
var init_register = __esm({
|
|
293
|
+
"src/commands/register.ts"() {
|
|
294
|
+
init_credentials();
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
|
|
210
298
|
// src/commands/generate.ts
|
|
211
299
|
var generate_exports = {};
|
|
212
300
|
__export(generate_exports, {
|
|
213
301
|
runGenerate: () => runGenerate
|
|
214
302
|
});
|
|
215
|
-
async function runGenerate(dir) {
|
|
303
|
+
async function runGenerate(dir, opts) {
|
|
216
304
|
const target = dir === "." ? process.cwd() : dir;
|
|
217
305
|
const dirJsonPath = join(target, "dir.json");
|
|
218
306
|
if (!existsSync(dirJsonPath)) {
|
|
@@ -242,6 +330,17 @@ No route definitions detected.`);
|
|
|
242
330
|
}
|
|
243
331
|
console.log(`
|
|
244
332
|
Edit DIR.md and dir.json to describe your API.`);
|
|
333
|
+
if (opts?.register) {
|
|
334
|
+
console.log(`
|
|
335
|
+
Registering with gateway...`);
|
|
336
|
+
const { runRegister: runRegister2 } = await Promise.resolve().then(() => (init_register(), register_exports));
|
|
337
|
+
await runRegister2({
|
|
338
|
+
gatewayUrl: opts.gatewayUrl,
|
|
339
|
+
token: opts.token,
|
|
340
|
+
domain: opts.domain,
|
|
341
|
+
dir: target
|
|
342
|
+
});
|
|
343
|
+
}
|
|
245
344
|
}
|
|
246
345
|
function detectFrameworkFromPackage(target) {
|
|
247
346
|
const pkgPath = join(target, "package.json");
|
|
@@ -427,94 +526,6 @@ var init_claim = __esm({
|
|
|
427
526
|
}
|
|
428
527
|
});
|
|
429
528
|
|
|
430
|
-
// src/commands/register.ts
|
|
431
|
-
var register_exports = {};
|
|
432
|
-
__export(register_exports, {
|
|
433
|
-
runRegister: () => runRegister
|
|
434
|
-
});
|
|
435
|
-
async function runRegister(options) {
|
|
436
|
-
const projectDir = options.dir ?? process.cwd();
|
|
437
|
-
const gatewayUrl = options.gatewayUrl ?? process.env.DIRX_GATEWAY_URL ?? "https://api.dirx.ai";
|
|
438
|
-
const domain = options.domain ?? process.env.DIRX_DOMAIN;
|
|
439
|
-
if (!domain) {
|
|
440
|
-
throw new Error(
|
|
441
|
-
"Domain is required. Use --domain or DIRX_DOMAIN env var."
|
|
442
|
-
);
|
|
443
|
-
}
|
|
444
|
-
const token = await resolveToken({
|
|
445
|
-
token: options.token,
|
|
446
|
-
domain,
|
|
447
|
-
gatewayUrl
|
|
448
|
-
});
|
|
449
|
-
const dirMdPath = join(projectDir, "DIR.md");
|
|
450
|
-
let dirMd;
|
|
451
|
-
try {
|
|
452
|
-
dirMd = await readFile(dirMdPath, "utf-8");
|
|
453
|
-
} catch {
|
|
454
|
-
throw new Error(
|
|
455
|
-
`DIR.md not found at ${dirMdPath}. Run 'dirx init' first.`
|
|
456
|
-
);
|
|
457
|
-
}
|
|
458
|
-
if (!dirMd.trim()) {
|
|
459
|
-
throw new Error(`DIR.md is empty at ${dirMdPath}`);
|
|
460
|
-
}
|
|
461
|
-
const baseUrl = gatewayUrl.replace(/\/$/, "");
|
|
462
|
-
const url = `${baseUrl}/registry/services?domain=${encodeURIComponent(domain)}`;
|
|
463
|
-
const res = await fetch(url, {
|
|
464
|
-
method: "POST",
|
|
465
|
-
headers: {
|
|
466
|
-
Authorization: `Bearer ${token}`,
|
|
467
|
-
"Content-Type": "text/markdown"
|
|
468
|
-
},
|
|
469
|
-
body: dirMd
|
|
470
|
-
});
|
|
471
|
-
if (!res.ok) {
|
|
472
|
-
const body = await res.text();
|
|
473
|
-
throw new Error(`Registration failed (${res.status}): ${body}`);
|
|
474
|
-
}
|
|
475
|
-
const result = await res.json();
|
|
476
|
-
console.log(`Registered ${result.name} as ${result.domain}`);
|
|
477
|
-
}
|
|
478
|
-
async function resolveToken(options) {
|
|
479
|
-
if (options.token) return options.token;
|
|
480
|
-
if (process.env.DIRX_PUBLISH_TOKEN) return process.env.DIRX_PUBLISH_TOKEN;
|
|
481
|
-
if (options.domain) {
|
|
482
|
-
const stored = await getToken(options.domain);
|
|
483
|
-
if (stored) return stored;
|
|
484
|
-
const gw = options.gatewayUrl ?? process.env.DIRX_GATEWAY_URL;
|
|
485
|
-
if (gw) {
|
|
486
|
-
const renewed = await renewToken(gw, options.domain);
|
|
487
|
-
if (renewed) return renewed;
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
throw new Error(
|
|
491
|
-
"No auth token found. Use `dirx claim <domain>` to obtain a publish token, or provide --token."
|
|
492
|
-
);
|
|
493
|
-
}
|
|
494
|
-
async function renewToken(gatewayUrl, domain) {
|
|
495
|
-
const baseUrl = gatewayUrl.replace(/\/$/, "");
|
|
496
|
-
try {
|
|
497
|
-
const res = await fetch(`${baseUrl}/domains/verify`, {
|
|
498
|
-
method: "POST",
|
|
499
|
-
headers: { "Content-Type": "application/json" },
|
|
500
|
-
body: JSON.stringify({ domain })
|
|
501
|
-
});
|
|
502
|
-
if (!res.ok) return null;
|
|
503
|
-
const data = await res.json();
|
|
504
|
-
if (!data.publishToken) return null;
|
|
505
|
-
await saveToken(domain, data.publishToken);
|
|
506
|
-
console.log(`Token renewed for ${domain}`);
|
|
507
|
-
return data.publishToken;
|
|
508
|
-
} catch {
|
|
509
|
-
return null;
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
var init_register = __esm({
|
|
513
|
-
"src/commands/register.ts"() {
|
|
514
|
-
init_credentials();
|
|
515
|
-
}
|
|
516
|
-
});
|
|
517
|
-
|
|
518
529
|
// src/commands/status.ts
|
|
519
530
|
var status_exports = {};
|
|
520
531
|
__export(status_exports, {
|
|
@@ -664,13 +675,140 @@ var init_provider_map = __esm({
|
|
|
664
675
|
}
|
|
665
676
|
});
|
|
666
677
|
|
|
678
|
+
// src/format.ts
|
|
679
|
+
function isSearchResults(data) {
|
|
680
|
+
if (!Array.isArray(data) || data.length === 0) return false;
|
|
681
|
+
const first = data[0];
|
|
682
|
+
return typeof first === "object" && first !== null && "domain" in first && ("title" in first || "name" in first);
|
|
683
|
+
}
|
|
684
|
+
function isEndpointResults(data) {
|
|
685
|
+
if (!Array.isArray(data) || data.length === 0) return false;
|
|
686
|
+
const first = data[0];
|
|
687
|
+
return typeof first === "object" && first !== null && "method" in first && "path" in first;
|
|
688
|
+
}
|
|
689
|
+
function extractPayload(result) {
|
|
690
|
+
if (typeof result !== "object" || result === null) return result;
|
|
691
|
+
const obj = result;
|
|
692
|
+
if ("ok" in obj && "data" in obj) {
|
|
693
|
+
const data = obj.data;
|
|
694
|
+
if (typeof data === "object" && data !== null && "results" in data) {
|
|
695
|
+
return data.results;
|
|
696
|
+
}
|
|
697
|
+
return data;
|
|
698
|
+
}
|
|
699
|
+
if ("results" in obj && "query" in obj) return obj.results;
|
|
700
|
+
return result;
|
|
701
|
+
}
|
|
702
|
+
function formatLs(result) {
|
|
703
|
+
const payload = extractPayload(result);
|
|
704
|
+
if (Array.isArray(payload)) {
|
|
705
|
+
if (payload.length === 0) return "(empty)";
|
|
706
|
+
return payload.map((item) => typeof item === "string" ? item : JSON.stringify(item)).join("\n");
|
|
707
|
+
}
|
|
708
|
+
if (typeof payload === "object" && payload !== null && "items" in payload) {
|
|
709
|
+
const items = payload.items;
|
|
710
|
+
if (!Array.isArray(items) || items.length === 0) return "(empty)";
|
|
711
|
+
const rich = items.some(
|
|
712
|
+
(item) => typeof item === "object" && item !== null && "path" in item
|
|
713
|
+
);
|
|
714
|
+
if (!rich) {
|
|
715
|
+
return items.map((item) => typeof item === "string" ? item : JSON.stringify(item)).join("\n");
|
|
716
|
+
}
|
|
717
|
+
const entries = items;
|
|
718
|
+
const maxPath = Math.min(
|
|
719
|
+
40,
|
|
720
|
+
Math.max(8, ...entries.map((e) => (e.path ?? "").length))
|
|
721
|
+
);
|
|
722
|
+
return entries.map((entry) => {
|
|
723
|
+
const path = entry.path ?? "<unknown>";
|
|
724
|
+
const title = entry.title ?? "";
|
|
725
|
+
if (title) {
|
|
726
|
+
return `${path.padEnd(maxPath)} ${title}`;
|
|
727
|
+
}
|
|
728
|
+
return path;
|
|
729
|
+
}).join("\n");
|
|
730
|
+
}
|
|
731
|
+
return JSON.stringify(payload);
|
|
732
|
+
}
|
|
733
|
+
function formatGrep(result) {
|
|
734
|
+
const payload = extractPayload(result);
|
|
735
|
+
if (isSearchResults(payload)) {
|
|
736
|
+
if (payload.length === 0) return "(no matches)";
|
|
737
|
+
let domainCount = 0;
|
|
738
|
+
let endpointCount = 0;
|
|
739
|
+
const blocks = payload.map((s) => {
|
|
740
|
+
domainCount++;
|
|
741
|
+
const name = s.title || s.name || "";
|
|
742
|
+
const header = name ? `${s.domain} ${name}` : s.domain;
|
|
743
|
+
const lines = [header];
|
|
744
|
+
if (s.description) {
|
|
745
|
+
const desc = s.description.length > 80 ? s.description.slice(0, 77) + "..." : s.description;
|
|
746
|
+
lines.push(` ${desc}`);
|
|
747
|
+
}
|
|
748
|
+
const endpoints = s.matched_endpoints;
|
|
749
|
+
if (endpoints && endpoints.length > 0) {
|
|
750
|
+
lines[0] += ` \xB7 ${endpoints.length} matched`;
|
|
751
|
+
for (const ep of endpoints) {
|
|
752
|
+
endpointCount++;
|
|
753
|
+
const method = (ep.method ?? "").padEnd(6);
|
|
754
|
+
const desc = ep.description ? ` -- ${ep.description}` : "";
|
|
755
|
+
lines.push(` ${method} ${ep.path}${desc}`);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
return lines.join("\n");
|
|
759
|
+
});
|
|
760
|
+
const output2 = blocks.join("\n\n");
|
|
761
|
+
if (domainCount > 0 || endpointCount > 0) {
|
|
762
|
+
const parts = [];
|
|
763
|
+
if (domainCount > 0) parts.push(`${domainCount} service${domainCount === 1 ? "" : "s"}`);
|
|
764
|
+
if (endpointCount > 0) parts.push(`${endpointCount} endpoint${endpointCount === 1 ? "" : "s"}`);
|
|
765
|
+
return `${output2}
|
|
766
|
+
|
|
767
|
+
-- ${parts.join(", ")} matched`;
|
|
768
|
+
}
|
|
769
|
+
return output2;
|
|
770
|
+
}
|
|
771
|
+
if (isEndpointResults(payload)) {
|
|
772
|
+
if (payload.length === 0) return "(no matches)";
|
|
773
|
+
return payload.map((ep) => {
|
|
774
|
+
const method = (ep.method ?? "").padEnd(6);
|
|
775
|
+
const desc = ep.description ? ` -- ${ep.description}` : "";
|
|
776
|
+
return `${method} ${ep.path}${desc}`;
|
|
777
|
+
}).join("\n");
|
|
778
|
+
}
|
|
779
|
+
return JSON.stringify(payload);
|
|
780
|
+
}
|
|
781
|
+
function formatCat(result) {
|
|
782
|
+
const payload = extractPayload(result);
|
|
783
|
+
if (typeof payload === "string") return payload;
|
|
784
|
+
return JSON.stringify(payload);
|
|
785
|
+
}
|
|
786
|
+
function formatMutate(result, verb, path) {
|
|
787
|
+
const payload = extractPayload(result);
|
|
788
|
+
if (payload === null || payload === void 0) {
|
|
789
|
+
return `${verb}: ${path}`;
|
|
790
|
+
}
|
|
791
|
+
if (typeof payload === "object" && Object.keys(payload).length === 0) {
|
|
792
|
+
return `${verb}: ${path}`;
|
|
793
|
+
}
|
|
794
|
+
return `${verb}: ${path}
|
|
795
|
+
${JSON.stringify(payload)}`;
|
|
796
|
+
}
|
|
797
|
+
function formatJson(result) {
|
|
798
|
+
return JSON.stringify(result);
|
|
799
|
+
}
|
|
800
|
+
var init_format = __esm({
|
|
801
|
+
"src/format.ts"() {
|
|
802
|
+
}
|
|
803
|
+
});
|
|
804
|
+
|
|
667
805
|
// src/commands/fs.ts
|
|
668
806
|
var fs_exports = {};
|
|
669
807
|
__export(fs_exports, {
|
|
670
808
|
registerFsCommands: () => registerFsCommands
|
|
671
809
|
});
|
|
672
|
-
function output(result) {
|
|
673
|
-
console.log(
|
|
810
|
+
function output(result, jsonMode) {
|
|
811
|
+
console.log(jsonMode ? formatJson(result) : formatCat(result));
|
|
674
812
|
}
|
|
675
813
|
function extractDomain(path) {
|
|
676
814
|
const cleaned = path.replace(/^\/+/, "");
|
|
@@ -708,33 +846,40 @@ function handleError(err, cmdPath) {
|
|
|
708
846
|
process.exit(1);
|
|
709
847
|
}
|
|
710
848
|
}
|
|
711
|
-
console.error(
|
|
849
|
+
console.error(message);
|
|
712
850
|
process.exit(1);
|
|
713
851
|
}
|
|
714
852
|
function registerFsCommands(program2) {
|
|
715
|
-
program2.command("ls").description("List directory contents in the DirX path space").argument("
|
|
853
|
+
program2.command("ls").description("List directory contents in the DirX path space").argument("[path]", "Directory path (e.g. /net/)", "/").action(async (path) => {
|
|
716
854
|
try {
|
|
855
|
+
let normalizedPath = path.trim();
|
|
856
|
+
if (normalizedPath.length > 1 && normalizedPath.endsWith("/")) {
|
|
857
|
+
normalizedPath = normalizedPath.replace(/\/+$/, "");
|
|
858
|
+
}
|
|
859
|
+
const jsonMode = program2.opts().json === true;
|
|
717
860
|
const client = await createClient();
|
|
718
|
-
const result = await client.execute(`ls ${
|
|
719
|
-
|
|
861
|
+
const result = await client.execute(`ls ${normalizedPath}`);
|
|
862
|
+
console.log(jsonMode ? formatJson(result) : formatLs(result));
|
|
720
863
|
} catch (err) {
|
|
721
864
|
handleError(err, path);
|
|
722
865
|
}
|
|
723
866
|
});
|
|
724
867
|
program2.command("cat").description("Read file contents from a DirX path").argument("<path>", "File path").action(async (path) => {
|
|
725
868
|
try {
|
|
869
|
+
const jsonMode = program2.opts().json === true;
|
|
726
870
|
const client = await createClient();
|
|
727
871
|
const result = await client.execute(`cat ${path}`);
|
|
728
|
-
output(result);
|
|
872
|
+
output(result, jsonMode);
|
|
729
873
|
} catch (err) {
|
|
730
874
|
handleError(err, path);
|
|
731
875
|
}
|
|
732
876
|
});
|
|
733
877
|
program2.command("read").description("Read file contents (alias for cat)").argument("<path>", "File path").action(async (path) => {
|
|
734
878
|
try {
|
|
879
|
+
const jsonMode = program2.opts().json === true;
|
|
735
880
|
const client = await createClient();
|
|
736
881
|
const result = await client.execute(`cat ${path}`);
|
|
737
|
-
output(result);
|
|
882
|
+
output(result, jsonMode);
|
|
738
883
|
} catch (err) {
|
|
739
884
|
handleError(err, path);
|
|
740
885
|
}
|
|
@@ -747,9 +892,10 @@ function registerFsCommands(program2) {
|
|
|
747
892
|
const { readFileSync: readFileSync4 } = await import('fs');
|
|
748
893
|
payload = readFileSync4(opts.file, "utf-8");
|
|
749
894
|
}
|
|
895
|
+
const jsonMode = program2.opts().json === true;
|
|
750
896
|
const client = await createClient();
|
|
751
897
|
const result = await client.execute(`write ${path} ${payload}`);
|
|
752
|
-
|
|
898
|
+
console.log(jsonMode ? formatJson(result) : formatMutate(result, "Created", path));
|
|
753
899
|
} catch (err) {
|
|
754
900
|
handleError(err, path);
|
|
755
901
|
}
|
|
@@ -763,28 +909,41 @@ function registerFsCommands(program2) {
|
|
|
763
909
|
const { readFileSync: readFileSync4 } = await import('fs');
|
|
764
910
|
payload = readFileSync4(opts.file, "utf-8");
|
|
765
911
|
}
|
|
912
|
+
const jsonMode = program2.opts().json === true;
|
|
766
913
|
const client = await createClient();
|
|
767
914
|
const result = await client.execute(`edit ${path} ${payload}`);
|
|
768
|
-
|
|
915
|
+
console.log(jsonMode ? formatJson(result) : formatMutate(result, "Updated", path));
|
|
769
916
|
} catch (err) {
|
|
770
917
|
handleError(err, path);
|
|
771
918
|
}
|
|
772
919
|
}
|
|
773
920
|
);
|
|
921
|
+
program2.command("rm").description("Remove a resource at a DirX path").argument("<path>", "Resource path").action(async (path) => {
|
|
922
|
+
try {
|
|
923
|
+
const jsonMode = program2.opts().json === true;
|
|
924
|
+
const client = await createClient();
|
|
925
|
+
const result = await client.execute(`rm ${path}`);
|
|
926
|
+
console.log(jsonMode ? formatJson(result) : formatMutate(result, "Removed", path));
|
|
927
|
+
} catch (err) {
|
|
928
|
+
handleError(err, path);
|
|
929
|
+
}
|
|
930
|
+
});
|
|
774
931
|
program2.command("bash").description("Execute a multi-step pipeline on the gateway").argument("<pipeline>", "Pipeline expression").action(async (pipeline) => {
|
|
775
932
|
try {
|
|
933
|
+
const jsonMode = program2.opts().json === true;
|
|
776
934
|
const client = await createClient();
|
|
777
935
|
const result = await client.execute(`bash ${pipeline}`);
|
|
778
|
-
output(result);
|
|
936
|
+
output(result, jsonMode);
|
|
779
937
|
} catch (err) {
|
|
780
938
|
handleError(err);
|
|
781
939
|
}
|
|
782
940
|
});
|
|
783
|
-
program2.command("grep").description("Search across services in the DirX path space").argument("<pattern>", "Search pattern").argument("
|
|
941
|
+
program2.command("grep").description("Search across services in the DirX path space").argument("<pattern>", "Search pattern").argument("[path]", "Search scope path", "/").action(async (pattern, path) => {
|
|
784
942
|
try {
|
|
943
|
+
const jsonMode = program2.opts().json === true;
|
|
785
944
|
const client = await createClient();
|
|
786
945
|
const result = await client.execute(`grep ${pattern} ${path}`);
|
|
787
|
-
|
|
946
|
+
console.log(jsonMode ? formatJson(result) : formatGrep(result));
|
|
788
947
|
} catch (err) {
|
|
789
948
|
handleError(err, path);
|
|
790
949
|
}
|
|
@@ -794,6 +953,7 @@ var init_fs = __esm({
|
|
|
794
953
|
"src/commands/fs.ts"() {
|
|
795
954
|
init_client();
|
|
796
955
|
init_provider_map();
|
|
956
|
+
init_format();
|
|
797
957
|
}
|
|
798
958
|
});
|
|
799
959
|
|
|
@@ -860,7 +1020,7 @@ function registerKeysCommand(program2) {
|
|
|
860
1020
|
try {
|
|
861
1021
|
const client = await createClient();
|
|
862
1022
|
const result = await client.listByok();
|
|
863
|
-
console.log(JSON.stringify(result
|
|
1023
|
+
console.log(JSON.stringify(result));
|
|
864
1024
|
} catch (err) {
|
|
865
1025
|
const msg = err instanceof Error ? err.message : String(err);
|
|
866
1026
|
console.error(`Error: ${msg}`);
|
|
@@ -916,7 +1076,7 @@ try {
|
|
|
916
1076
|
} catch {
|
|
917
1077
|
}
|
|
918
1078
|
var program = new Command();
|
|
919
|
-
program.name("dirx").description("DirX \u2014 Unified Gateway & CLI for Agents").version(version);
|
|
1079
|
+
program.name("dirx").description("DirX \u2014 Unified Gateway & CLI for Agents").version(version).option("--json", "Output raw JSON instead of human-readable text");
|
|
920
1080
|
program.command("auth").description("Authenticate with the DirX gateway").option("--gateway-url <url>", "Gateway URL (default: https://api.dirx.ai)").action(async (opts) => {
|
|
921
1081
|
const { runAuth: runAuth2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
922
1082
|
await runAuth2({ gatewayUrl: opts.gatewayUrl });
|
|
@@ -925,9 +1085,14 @@ program.command("init").description("Initialize DirX in the current project").ar
|
|
|
925
1085
|
const { runInit: runInit2 } = await Promise.resolve().then(() => (init_init(), init_exports));
|
|
926
1086
|
await runInit2(dir);
|
|
927
1087
|
});
|
|
928
|
-
program.command("generate").description("Scan project and
|
|
1088
|
+
program.command("generate").description("Scan project and generate DIR.md, optionally register").argument("[dir]", "Project directory", ".").option("--register", "Register the service with the gateway after generating").option("--gateway-url <url>", "Gateway URL for registration").option("--token <token>", "Auth token for registration").option("--domain <domain>", "Domain name for the service").action(async (dir, opts) => {
|
|
929
1089
|
const { runGenerate: runGenerate2 } = await Promise.resolve().then(() => (init_generate(), generate_exports));
|
|
930
|
-
await runGenerate2(dir
|
|
1090
|
+
await runGenerate2(dir, {
|
|
1091
|
+
register: opts.register,
|
|
1092
|
+
gatewayUrl: opts.gatewayUrl,
|
|
1093
|
+
token: opts.token,
|
|
1094
|
+
domain: opts.domain
|
|
1095
|
+
});
|
|
931
1096
|
});
|
|
932
1097
|
program.command("claim").description("Claim domain ownership via DNS verification").argument("<domain>", "Domain to claim").option("--verify", "Verify DNS record and obtain publish token").option("--gateway-url <url>", "Gateway URL").action(
|
|
933
1098
|
async (domain, opts) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dirxai/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "DirX — Unified Gateway & CLI for Agents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -9,22 +9,16 @@
|
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
11
|
"build": "tsup",
|
|
12
|
-
"dev": "tsup --watch"
|
|
13
|
-
"lint": "tsc --noEmit",
|
|
14
|
-
"test": "vitest run"
|
|
12
|
+
"dev": "tsup --watch"
|
|
15
13
|
},
|
|
16
14
|
"dependencies": {
|
|
15
|
+
"@dirxai/core": "^0.3.0",
|
|
17
16
|
"commander": "^13.0.0"
|
|
18
17
|
},
|
|
19
|
-
"devDependencies": {
|
|
20
|
-
"@types/node": "^22.0.0",
|
|
21
|
-
"tsup": "^8.0.0",
|
|
22
|
-
"typescript": "^5.7.0",
|
|
23
|
-
"vitest": "^4.0.0"
|
|
24
|
-
},
|
|
25
18
|
"repository": {
|
|
26
19
|
"type": "git",
|
|
27
|
-
"url": "https://github.com/dirxai/dirx.git"
|
|
20
|
+
"url": "https://github.com/dirxai/dirx.git",
|
|
21
|
+
"directory": "packages/cli"
|
|
28
22
|
},
|
|
29
23
|
"homepage": "https://dirx.ai",
|
|
30
24
|
"keywords": [
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 DirX AI
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/README.md
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
# DirX — Unified Gateway & CLI for Agents
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/@dirxai/cli)
|
|
4
|
-
[](https://opensource.org/licenses/MIT)
|
|
5
|
-
|
|
6
|
-
DirX gives AI agents a unified, file-system-like interface to discover and interact with internet APIs — with built-in governance, access control, and auditing.
|
|
7
|
-
|
|
8
|
-
## Install
|
|
9
|
-
|
|
10
|
-
```bash
|
|
11
|
-
npm install -g @dirxai/cli
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
## Quick Start
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
# Authenticate with the gateway
|
|
18
|
-
dirx auth
|
|
19
|
-
|
|
20
|
-
# Browse the API directory
|
|
21
|
-
dirx ls /
|
|
22
|
-
dirx ls /net/
|
|
23
|
-
|
|
24
|
-
# Read service descriptions
|
|
25
|
-
dirx cat /net/api.github.com/DIR.md
|
|
26
|
-
|
|
27
|
-
# Search across services
|
|
28
|
-
dirx grep "weather" /net/
|
|
29
|
-
|
|
30
|
-
# Write data
|
|
31
|
-
dirx write /net/api.example.com/data -d '{"key": "value"}'
|
|
32
|
-
|
|
33
|
-
# Manage API keys (BYOK)
|
|
34
|
-
dirx keys set api.github.com --token ghp_xxxx --sync
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Commands
|
|
38
|
-
|
|
39
|
-
### Agent Commands
|
|
40
|
-
|
|
41
|
-
| Command | Description |
|
|
42
|
-
|---------|-------------|
|
|
43
|
-
| `dirx ls <path>` | List directory contents |
|
|
44
|
-
| `dirx cat <path>` | Read file contents |
|
|
45
|
-
| `dirx write <path>` | Write data |
|
|
46
|
-
| `dirx edit <path>` | Partial update |
|
|
47
|
-
| `dirx grep <pattern> <path>` | Search across services |
|
|
48
|
-
| `dirx bash <pipeline>` | Execute multi-step pipeline |
|
|
49
|
-
|
|
50
|
-
### Developer Tools
|
|
51
|
-
|
|
52
|
-
| Command | Description |
|
|
53
|
-
|---------|-------------|
|
|
54
|
-
| `dirx init [dir]` | Initialize DirX in a project |
|
|
55
|
-
| `dirx generate [dir]` | Scan and detect route definitions |
|
|
56
|
-
| `dirx claim <domain>` | Claim domain via DNS verification |
|
|
57
|
-
| `dirx register` | Register DIR.md with the gateway |
|
|
58
|
-
|
|
59
|
-
### Configuration
|
|
60
|
-
|
|
61
|
-
| Command | Description |
|
|
62
|
-
|---------|-------------|
|
|
63
|
-
| `dirx auth` | Authenticate with the gateway |
|
|
64
|
-
| `dirx keys set <domain>` | Set an API key |
|
|
65
|
-
| `dirx keys list` | List stored keys |
|
|
66
|
-
| `dirx keys remove <domain>` | Remove a key |
|
|
67
|
-
| `dirx status` | Show CLI config and auth status |
|
|
68
|
-
|
|
69
|
-
## Environment Variables
|
|
70
|
-
|
|
71
|
-
| Variable | Description | Default |
|
|
72
|
-
|----------|-------------|---------|
|
|
73
|
-
| `DIRX_GATEWAY_URL` | Gateway URL | `https://api.dirx.ai` |
|
|
74
|
-
| `DIRX_TOKEN` | Agent token | — |
|
|
75
|
-
| `DIRX_HOME` | Config directory | `~/.dirx` |
|
|
76
|
-
|
|
77
|
-
## Development
|
|
78
|
-
|
|
79
|
-
```bash
|
|
80
|
-
git clone https://github.com/dirxai/dirx.git
|
|
81
|
-
cd dirx
|
|
82
|
-
npm install
|
|
83
|
-
npm run build
|
|
84
|
-
npm run lint
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
## License
|
|
88
|
-
|
|
89
|
-
MIT
|