danube-cli 0.2.0 → 0.2.2
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/danube.mjs +94 -52
- package/package.json +1 -1
package/dist/danube.mjs
CHANGED
|
@@ -159,7 +159,7 @@ var package_default;
|
|
|
159
159
|
var init_package = __esm(() => {
|
|
160
160
|
package_default = {
|
|
161
161
|
name: "danube-cli",
|
|
162
|
-
version: "0.2.
|
|
162
|
+
version: "0.2.2",
|
|
163
163
|
description: "Danube CLI — agent-first tool infrastructure for AI agents",
|
|
164
164
|
type: "module",
|
|
165
165
|
license: "MIT",
|
|
@@ -521,14 +521,64 @@ var init_api = __esm(() => {
|
|
|
521
521
|
init_version();
|
|
522
522
|
});
|
|
523
523
|
|
|
524
|
+
// src/lib/compat.ts
|
|
525
|
+
import { execFile } from "node:child_process";
|
|
526
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
527
|
+
function sleep(ms) {
|
|
528
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
529
|
+
}
|
|
530
|
+
function openUrl(url) {
|
|
531
|
+
try {
|
|
532
|
+
if (process.platform === "darwin") {
|
|
533
|
+
execFile("open", [url]);
|
|
534
|
+
} else if (process.platform === "linux") {
|
|
535
|
+
execFile("xdg-open", [url]);
|
|
536
|
+
} else {
|
|
537
|
+
execFile("cmd", ["/c", "start", url]);
|
|
538
|
+
}
|
|
539
|
+
} catch {}
|
|
540
|
+
}
|
|
541
|
+
function fileExists(filepath) {
|
|
542
|
+
return existsSync(filepath);
|
|
543
|
+
}
|
|
544
|
+
function readFile(filepath) {
|
|
545
|
+
return readFileSync(filepath, "utf-8");
|
|
546
|
+
}
|
|
547
|
+
async function readStdin() {
|
|
548
|
+
const chunks = [];
|
|
549
|
+
for await (const chunk of process.stdin) {
|
|
550
|
+
chunks.push(chunk);
|
|
551
|
+
}
|
|
552
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
553
|
+
}
|
|
554
|
+
var init_compat = () => {};
|
|
555
|
+
|
|
524
556
|
// src/commands/auth.ts
|
|
525
557
|
var exports_auth = {};
|
|
526
558
|
__export(exports_auth, {
|
|
527
559
|
register: () => register
|
|
528
560
|
});
|
|
529
561
|
import chalk2 from "chalk";
|
|
562
|
+
import { createInterface } from "node:readline";
|
|
530
563
|
function register(program) {
|
|
531
|
-
program.command("login").description("Log in to Danube
|
|
564
|
+
program.command("login").description("Log in to Danube (device code flow, or --api-key to save a key directly)").option("--api-key <key>", "Save an existing API key instead of using device code flow").addHelpText("after", `
|
|
565
|
+
Examples:
|
|
566
|
+
$ danube login # Interactive browser flow
|
|
567
|
+
$ danube login --api-key dk_xxx # Save an existing key
|
|
568
|
+
$ DANUBE_API_KEY=dk_xxx danube whoami # Use without saving`).action(handleErrors(async (opts) => {
|
|
569
|
+
if (opts.apiKey) {
|
|
570
|
+
const baseUrl2 = getBaseUrl(ctx.profile);
|
|
571
|
+
const client2 = new ApiClient(baseUrl2, opts.apiKey);
|
|
572
|
+
try {
|
|
573
|
+
await client2.get("/v1/identity/api");
|
|
574
|
+
} catch {
|
|
575
|
+
outputError("invalid_key", "API key is invalid or could not be verified.");
|
|
576
|
+
process.exit(1);
|
|
577
|
+
}
|
|
578
|
+
saveApiKey(opts.apiKey, ctx.profile);
|
|
579
|
+
outputSuccess(`API key saved to profile '${ctx.profile}'`);
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
532
582
|
const baseUrl = getBaseUrl(ctx.profile);
|
|
533
583
|
const client = new ApiClient(baseUrl);
|
|
534
584
|
const data = await client.publicPost("/v1/auth/device/code", {
|
|
@@ -549,28 +599,25 @@ function register(program) {
|
|
|
549
599
|
expires_in: data.expires_in
|
|
550
600
|
});
|
|
551
601
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
if (humanMode) {
|
|
566
|
-
console.log(chalk2.dim(` Open ${data.verification_url} in your browser`));
|
|
567
|
-
}
|
|
602
|
+
const url = `${data.verification_url}?code=${data.user_code}`;
|
|
603
|
+
if (humanMode) {
|
|
604
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
605
|
+
await new Promise((resolve) => {
|
|
606
|
+
rl.question(chalk2.dim(" Press Enter to open browser..."), () => {
|
|
607
|
+
rl.close();
|
|
608
|
+
resolve();
|
|
609
|
+
});
|
|
610
|
+
});
|
|
611
|
+
openUrl(url);
|
|
612
|
+
console.log(chalk2.dim(" Waiting for authorization..."));
|
|
613
|
+
} else {
|
|
614
|
+
openUrl(url);
|
|
568
615
|
}
|
|
569
616
|
const start = Date.now();
|
|
570
617
|
const expiresMs = data.expires_in * 1000;
|
|
571
618
|
const intervalMs = data.interval * 1000;
|
|
572
619
|
while (Date.now() - start < expiresMs) {
|
|
573
|
-
await
|
|
620
|
+
await sleep(intervalMs);
|
|
574
621
|
try {
|
|
575
622
|
const tokenData = await client.publicPost("/v1/auth/device/token", { device_code: data.device_code });
|
|
576
623
|
saveApiKey(tokenData.api_key, ctx.profile);
|
|
@@ -639,10 +686,10 @@ ${chalk2.green("✓")} Authenticated successfully!`);
|
|
|
639
686
|
var init_auth = __esm(() => {
|
|
640
687
|
init_src();
|
|
641
688
|
init_api();
|
|
689
|
+
init_compat();
|
|
642
690
|
init_config();
|
|
643
691
|
init_errors();
|
|
644
692
|
init_output();
|
|
645
|
-
init_api();
|
|
646
693
|
});
|
|
647
694
|
|
|
648
695
|
// src/commands/search.ts
|
|
@@ -682,7 +729,7 @@ async function parseData(data) {
|
|
|
682
729
|
return {};
|
|
683
730
|
data = data.trim();
|
|
684
731
|
if (data === "-") {
|
|
685
|
-
const raw = await
|
|
732
|
+
const raw = await readStdin();
|
|
686
733
|
if (!raw.trim())
|
|
687
734
|
return {};
|
|
688
735
|
try {
|
|
@@ -694,13 +741,12 @@ async function parseData(data) {
|
|
|
694
741
|
}
|
|
695
742
|
if (data.startsWith("@")) {
|
|
696
743
|
const filepath = data.slice(1);
|
|
697
|
-
|
|
698
|
-
if (!await file.exists()) {
|
|
744
|
+
if (!fileExists(filepath)) {
|
|
699
745
|
outputError("file_not_found", `File not found: ${filepath}`);
|
|
700
746
|
process.exit(1);
|
|
701
747
|
}
|
|
702
748
|
try {
|
|
703
|
-
return JSON.parse(
|
|
749
|
+
return JSON.parse(readFile(filepath));
|
|
704
750
|
} catch (e) {
|
|
705
751
|
outputError("invalid_input", `Invalid JSON in ${filepath}: ${e instanceof Error ? e.message : String(e)}`);
|
|
706
752
|
process.exit(1);
|
|
@@ -714,6 +760,7 @@ async function parseData(data) {
|
|
|
714
760
|
}
|
|
715
761
|
}
|
|
716
762
|
var init_data_input = __esm(() => {
|
|
763
|
+
init_compat();
|
|
717
764
|
init_output();
|
|
718
765
|
});
|
|
719
766
|
|
|
@@ -806,9 +853,9 @@ __export(exports_connect, {
|
|
|
806
853
|
register: () => register4
|
|
807
854
|
});
|
|
808
855
|
import chalk3 from "chalk";
|
|
809
|
-
import { createInterface } from "node:readline";
|
|
856
|
+
import { createInterface as createInterface2 } from "node:readline";
|
|
810
857
|
async function promptSecret(prompt) {
|
|
811
|
-
const rl =
|
|
858
|
+
const rl = createInterface2({ input: process.stdin, output: process.stderr });
|
|
812
859
|
return new Promise((resolve) => {
|
|
813
860
|
process.stderr.write(prompt);
|
|
814
861
|
rl.question("", (answer) => {
|
|
@@ -846,7 +893,7 @@ Connecting to ${chalk3.bold(target.name)}...`);
|
|
|
846
893
|
if (humanMode) {
|
|
847
894
|
apiKeyValue = await promptSecret(" Enter API key: ");
|
|
848
895
|
} else {
|
|
849
|
-
apiKeyValue = (await
|
|
896
|
+
apiKeyValue = (await readStdin()).trim();
|
|
850
897
|
if (!apiKeyValue) {
|
|
851
898
|
outputError("invalid_input", "No credential provided on stdin");
|
|
852
899
|
process.exit(1);
|
|
@@ -866,6 +913,7 @@ Connecting to ${chalk3.bold(target.name)}...`);
|
|
|
866
913
|
var init_connect = __esm(() => {
|
|
867
914
|
init_src();
|
|
868
915
|
init_api();
|
|
916
|
+
init_compat();
|
|
869
917
|
init_errors();
|
|
870
918
|
init_output();
|
|
871
919
|
});
|
|
@@ -1075,14 +1123,13 @@ function register6(program) {
|
|
|
1075
1123
|
]);
|
|
1076
1124
|
}));
|
|
1077
1125
|
tools.command("batch <file>").description("Batch execute up to 10 tools from a JSON file").action(handleErrors(async (file) => {
|
|
1078
|
-
|
|
1079
|
-
if (!await f.exists()) {
|
|
1126
|
+
if (!fileExists(file)) {
|
|
1080
1127
|
outputError("file_not_found", `File not found: ${file}`);
|
|
1081
1128
|
process.exit(1);
|
|
1082
1129
|
}
|
|
1083
1130
|
let calls;
|
|
1084
1131
|
try {
|
|
1085
|
-
const parsed = JSON.parse(
|
|
1132
|
+
const parsed = JSON.parse(readFile(file));
|
|
1086
1133
|
if (!Array.isArray(parsed)) {
|
|
1087
1134
|
outputError("invalid_input", "Batch file must contain a JSON array");
|
|
1088
1135
|
process.exit(1);
|
|
@@ -1162,6 +1209,7 @@ function register6(program) {
|
|
|
1162
1209
|
var init_tools = __esm(() => {
|
|
1163
1210
|
init_src();
|
|
1164
1211
|
init_api();
|
|
1212
|
+
init_compat();
|
|
1165
1213
|
init_errors();
|
|
1166
1214
|
init_output();
|
|
1167
1215
|
init_resolve();
|
|
@@ -1250,14 +1298,13 @@ function register8(program) {
|
|
|
1250
1298
|
outputDetail(execution, `Execution ${execution.id}`);
|
|
1251
1299
|
}));
|
|
1252
1300
|
workflows.command("create <file>").description("Create a workflow from a JSON spec file").action(handleErrors(async (file) => {
|
|
1253
|
-
|
|
1254
|
-
if (!await f.exists()) {
|
|
1301
|
+
if (!fileExists(file)) {
|
|
1255
1302
|
outputError("file_not_found", `File not found: ${file}`);
|
|
1256
1303
|
process.exit(1);
|
|
1257
1304
|
}
|
|
1258
1305
|
let spec;
|
|
1259
1306
|
try {
|
|
1260
|
-
spec = JSON.parse(
|
|
1307
|
+
spec = JSON.parse(readFile(file));
|
|
1261
1308
|
} catch (e) {
|
|
1262
1309
|
outputError("invalid_input", `Invalid JSON: ${e instanceof Error ? e.message : String(e)}`);
|
|
1263
1310
|
process.exit(1);
|
|
@@ -1273,14 +1320,13 @@ function register8(program) {
|
|
|
1273
1320
|
outputDetail(workflow, `Created: ${workflow.name}`);
|
|
1274
1321
|
}));
|
|
1275
1322
|
workflows.command("update <workflowId> <file>").description("Update a workflow from a JSON spec file").action(handleErrors(async (workflowId, file) => {
|
|
1276
|
-
|
|
1277
|
-
if (!await f.exists()) {
|
|
1323
|
+
if (!fileExists(file)) {
|
|
1278
1324
|
outputError("file_not_found", `File not found: ${file}`);
|
|
1279
1325
|
process.exit(1);
|
|
1280
1326
|
}
|
|
1281
1327
|
let spec;
|
|
1282
1328
|
try {
|
|
1283
|
-
spec = JSON.parse(
|
|
1329
|
+
spec = JSON.parse(readFile(file));
|
|
1284
1330
|
} catch (e) {
|
|
1285
1331
|
outputError("invalid_input", `Invalid JSON: ${e instanceof Error ? e.message : String(e)}`);
|
|
1286
1332
|
process.exit(1);
|
|
@@ -1298,6 +1344,7 @@ function register8(program) {
|
|
|
1298
1344
|
var init_workflows = __esm(() => {
|
|
1299
1345
|
init_src();
|
|
1300
1346
|
init_api();
|
|
1347
|
+
init_compat();
|
|
1301
1348
|
init_data_input();
|
|
1302
1349
|
init_errors();
|
|
1303
1350
|
init_output();
|
|
@@ -1346,14 +1393,13 @@ ${chalk4.bold(skill.name)}`);
|
|
|
1346
1393
|
}
|
|
1347
1394
|
}));
|
|
1348
1395
|
skills.command("create <file>").description("Create a skill from a JSON spec file").option("--visibility <vis>", "Visibility: private or public", "private").action(handleErrors(async (file, opts) => {
|
|
1349
|
-
|
|
1350
|
-
if (!await f.exists()) {
|
|
1396
|
+
if (!fileExists(file)) {
|
|
1351
1397
|
outputError("file_not_found", `File not found: ${file}`);
|
|
1352
1398
|
process.exit(1);
|
|
1353
1399
|
}
|
|
1354
1400
|
let spec;
|
|
1355
1401
|
try {
|
|
1356
|
-
spec = JSON.parse(
|
|
1402
|
+
spec = JSON.parse(readFile(file));
|
|
1357
1403
|
} catch (e) {
|
|
1358
1404
|
outputError("invalid_input", `Invalid JSON: ${e instanceof Error ? e.message : String(e)}`);
|
|
1359
1405
|
process.exit(1);
|
|
@@ -1372,14 +1418,13 @@ ${chalk4.bold(skill.name)}`);
|
|
|
1372
1418
|
outputDetail(skill, `Created: ${skill.name}`);
|
|
1373
1419
|
}));
|
|
1374
1420
|
skills.command("update <skillId> <file>").description("Update a skill from a JSON spec file").action(handleErrors(async (skillId, file) => {
|
|
1375
|
-
|
|
1376
|
-
if (!await f.exists()) {
|
|
1421
|
+
if (!fileExists(file)) {
|
|
1377
1422
|
outputError("file_not_found", `File not found: ${file}`);
|
|
1378
1423
|
process.exit(1);
|
|
1379
1424
|
}
|
|
1380
1425
|
let spec;
|
|
1381
1426
|
try {
|
|
1382
|
-
spec = JSON.parse(
|
|
1427
|
+
spec = JSON.parse(readFile(file));
|
|
1383
1428
|
} catch (e) {
|
|
1384
1429
|
outputError("invalid_input", `Invalid JSON: ${e instanceof Error ? e.message : String(e)}`);
|
|
1385
1430
|
process.exit(1);
|
|
@@ -1397,6 +1442,7 @@ ${chalk4.bold(skill.name)}`);
|
|
|
1397
1442
|
var init_skills = __esm(() => {
|
|
1398
1443
|
init_src();
|
|
1399
1444
|
init_api();
|
|
1445
|
+
init_compat();
|
|
1400
1446
|
init_errors();
|
|
1401
1447
|
init_output();
|
|
1402
1448
|
});
|
|
@@ -1473,13 +1519,13 @@ var exports_credentials = {};
|
|
|
1473
1519
|
__export(exports_credentials, {
|
|
1474
1520
|
register: () => register11
|
|
1475
1521
|
});
|
|
1476
|
-
import { createInterface as
|
|
1522
|
+
import { createInterface as createInterface3 } from "node:readline";
|
|
1477
1523
|
function register11(program) {
|
|
1478
1524
|
const credentials = program.command("credentials").description("Store service credentials.");
|
|
1479
1525
|
credentials.command("store <serviceId>").description("Store a credential for a service").option("--type <type>", "Credential type: api_key, bearer, oauth", "api_key").action(handleErrors(async (serviceId, opts) => {
|
|
1480
1526
|
let credentialValue;
|
|
1481
1527
|
if (humanMode) {
|
|
1482
|
-
const rl =
|
|
1528
|
+
const rl = createInterface3({ input: process.stdin, output: process.stderr });
|
|
1483
1529
|
credentialValue = await new Promise((resolve) => {
|
|
1484
1530
|
process.stderr.write(" Enter credential value: ");
|
|
1485
1531
|
rl.question("", (answer) => {
|
|
@@ -1488,7 +1534,7 @@ function register11(program) {
|
|
|
1488
1534
|
});
|
|
1489
1535
|
});
|
|
1490
1536
|
} else {
|
|
1491
|
-
credentialValue = (await
|
|
1537
|
+
credentialValue = (await readStdin()).trim();
|
|
1492
1538
|
if (!credentialValue) {
|
|
1493
1539
|
outputError("invalid_input", "No credential provided on stdin");
|
|
1494
1540
|
process.exit(1);
|
|
@@ -1509,6 +1555,7 @@ function register11(program) {
|
|
|
1509
1555
|
var init_credentials = __esm(() => {
|
|
1510
1556
|
init_src();
|
|
1511
1557
|
init_api();
|
|
1558
|
+
init_compat();
|
|
1512
1559
|
init_errors();
|
|
1513
1560
|
init_output();
|
|
1514
1561
|
});
|
|
@@ -1653,13 +1700,7 @@ ${chalk6.green("✓")} Agent registered!`);
|
|
|
1653
1700
|
console.log(`
|
|
1654
1701
|
${chalk6.green("✓")} Checkout created`);
|
|
1655
1702
|
console.log(` ${chalk6.cyan("Open:")} ${result.checkout_url}`);
|
|
1656
|
-
|
|
1657
|
-
if (process.platform === "darwin") {
|
|
1658
|
-
Bun.spawn(["open", result.checkout_url]);
|
|
1659
|
-
} else if (process.platform === "linux") {
|
|
1660
|
-
Bun.spawn(["xdg-open", result.checkout_url]);
|
|
1661
|
-
}
|
|
1662
|
-
} catch {}
|
|
1703
|
+
openUrl(result.checkout_url);
|
|
1663
1704
|
console.log();
|
|
1664
1705
|
} else if (humanMode && result.deposit_address) {
|
|
1665
1706
|
console.log(`
|
|
@@ -1676,6 +1717,7 @@ ${chalk6.green("✓")} Send USDC to:`);
|
|
|
1676
1717
|
var init_agent = __esm(() => {
|
|
1677
1718
|
init_src();
|
|
1678
1719
|
init_api();
|
|
1720
|
+
init_compat();
|
|
1679
1721
|
init_config();
|
|
1680
1722
|
init_errors();
|
|
1681
1723
|
init_output();
|