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.
Files changed (2) hide show
  1. package/dist/danube.mjs +94 -52
  2. 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.0",
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 via device code (opens browser)").action(handleErrors(async () => {
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
- try {
553
- const url = `${data.verification_url}?code=${data.user_code}`;
554
- if (process.platform === "darwin") {
555
- Bun.spawn(["open", url]);
556
- } else if (process.platform === "linux") {
557
- Bun.spawn(["xdg-open", url]);
558
- } else {
559
- Bun.spawn(["start", url]);
560
- }
561
- if (humanMode) {
562
- console.log(chalk2.dim(" Browser opened. Waiting for authorization..."));
563
- }
564
- } catch {
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 Bun.sleep(intervalMs);
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 Bun.stdin.text();
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
- const file = Bun.file(filepath);
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(await file.text());
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 = createInterface({ input: process.stdin, output: process.stderr });
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 Bun.stdin.text()).trim();
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
- const f = Bun.file(file);
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(await f.text());
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
- const f = Bun.file(file);
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(await f.text());
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
- const f = Bun.file(file);
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(await f.text());
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
- const f = Bun.file(file);
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(await f.text());
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
- const f = Bun.file(file);
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(await f.text());
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 createInterface2 } from "node:readline";
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 = createInterface2({ input: process.stdin, output: process.stderr });
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 Bun.stdin.text()).trim();
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
- try {
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();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "danube-cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Danube CLI — agent-first tool infrastructure for AI agents",
5
5
  "type": "module",
6
6
  "license": "MIT",