@ouro.bot/cli 0.1.0-alpha.8 → 0.1.0-alpha.9

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.
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.ensureDaemonRunning = ensureDaemonRunning;
37
37
  exports.parseOuroCommand = parseOuroCommand;
38
+ exports.discoverExistingCredentials = discoverExistingCredentials;
38
39
  exports.createDefaultOuroCliDeps = createDefaultOuroCliDeps;
39
40
  exports.runOuroCli = runOuroCli;
40
41
  const child_process_1 = require("child_process");
@@ -458,7 +459,61 @@ async function defaultLinkFriendIdentity(command) {
458
459
  });
459
460
  return `linked ${command.provider}:${command.externalId} to ${command.friendId}`;
460
461
  }
461
- /* v8 ignore next 49 -- integration: interactive terminal specialist session @preserve */
462
+ function discoverExistingCredentials(secretsRoot) {
463
+ const found = [];
464
+ let entries;
465
+ try {
466
+ entries = fs.readdirSync(secretsRoot, { withFileTypes: true });
467
+ }
468
+ catch {
469
+ return found;
470
+ }
471
+ for (const entry of entries) {
472
+ if (!entry.isDirectory())
473
+ continue;
474
+ const secretsPath = path.join(secretsRoot, entry.name, "secrets.json");
475
+ let raw;
476
+ try {
477
+ raw = fs.readFileSync(secretsPath, "utf-8");
478
+ }
479
+ catch {
480
+ continue;
481
+ }
482
+ let parsed;
483
+ try {
484
+ parsed = JSON.parse(raw);
485
+ }
486
+ catch {
487
+ continue;
488
+ }
489
+ if (!parsed.providers)
490
+ continue;
491
+ for (const [provName, provConfig] of Object.entries(parsed.providers)) {
492
+ if (provName === "anthropic" && provConfig.setupToken) {
493
+ found.push({ agentName: entry.name, provider: "anthropic", credentials: { setupToken: provConfig.setupToken } });
494
+ }
495
+ else if (provName === "openai-codex" && provConfig.oauthAccessToken) {
496
+ found.push({ agentName: entry.name, provider: "openai-codex", credentials: { oauthAccessToken: provConfig.oauthAccessToken } });
497
+ }
498
+ else if (provName === "minimax" && provConfig.apiKey) {
499
+ found.push({ agentName: entry.name, provider: "minimax", credentials: { apiKey: provConfig.apiKey } });
500
+ }
501
+ else if (provName === "azure" && provConfig.apiKey && provConfig.endpoint && provConfig.deployment) {
502
+ found.push({ agentName: entry.name, provider: "azure", credentials: { apiKey: provConfig.apiKey, endpoint: provConfig.endpoint, deployment: provConfig.deployment } });
503
+ }
504
+ }
505
+ }
506
+ // Deduplicate by provider+credential value (keep first seen)
507
+ const seen = new Set();
508
+ return found.filter((cred) => {
509
+ const key = `${cred.provider}:${JSON.stringify(cred.credentials)}`;
510
+ if (seen.has(key))
511
+ return false;
512
+ seen.add(key);
513
+ return true;
514
+ });
515
+ }
516
+ /* v8 ignore next 79 -- integration: interactive terminal specialist session @preserve */
462
517
  async function defaultRunAdoptionSpecialist() {
463
518
  const readline = await Promise.resolve().then(() => __importStar(require("readline/promises")));
464
519
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
@@ -467,31 +522,72 @@ async function defaultRunAdoptionSpecialist() {
467
522
  return answer.trim();
468
523
  };
469
524
  try {
470
- process.stdout.write("\nwelcome to ouro. let's get you set up.\n");
471
- process.stdout.write("i need an API key to power our conversation.\n\n");
472
- const providerRaw = await prompt("provider (anthropic/azure/minimax/openai-codex): ");
473
- if (!isAgentProvider(providerRaw)) {
474
- process.stdout.write("unknown provider. run `ouro hatch` to try again.\n");
475
- return null;
476
- }
477
- const credentials = {};
478
- if (providerRaw === "anthropic")
479
- credentials.setupToken = await prompt("API key: ");
480
- if (providerRaw === "openai-codex")
481
- credentials.oauthAccessToken = await prompt("OAuth token: ");
482
- if (providerRaw === "minimax")
483
- credentials.apiKey = await prompt("API key: ");
484
- if (providerRaw === "azure") {
485
- credentials.apiKey = await prompt("API key: ");
486
- credentials.endpoint = await prompt("endpoint: ");
487
- credentials.deployment = await prompt("deployment: ");
525
+ const secretsRoot = path.join(os.homedir(), ".agentsecrets");
526
+ const discovered = discoverExistingCredentials(secretsRoot);
527
+ let providerRaw;
528
+ let credentials = {};
529
+ if (discovered.length > 0) {
530
+ process.stdout.write("\nwelcome to ouro. let's get you set up.\n");
531
+ process.stdout.write("i found existing API credentials:\n\n");
532
+ const unique = [...new Map(discovered.map((d) => [`${d.provider}`, d])).values()];
533
+ for (let i = 0; i < unique.length; i++) {
534
+ process.stdout.write(` ${i + 1}. ${unique[i].provider} (from ${unique[i].agentName})\n`);
535
+ }
536
+ process.stdout.write("\n");
537
+ const choice = await prompt("use one of these? enter number, or 'new' for a different key: ");
538
+ const idx = parseInt(choice, 10) - 1;
539
+ if (idx >= 0 && idx < unique.length) {
540
+ providerRaw = unique[idx].provider;
541
+ credentials = unique[idx].credentials;
542
+ }
543
+ else {
544
+ const pRaw = await prompt("provider (anthropic/azure/minimax/openai-codex): ");
545
+ if (!isAgentProvider(pRaw)) {
546
+ process.stdout.write("unknown provider. run `ouro hatch` to try again.\n");
547
+ rl.close();
548
+ return null;
549
+ }
550
+ providerRaw = pRaw;
551
+ if (providerRaw === "anthropic")
552
+ credentials.setupToken = await prompt("API key: ");
553
+ if (providerRaw === "openai-codex")
554
+ credentials.oauthAccessToken = await prompt("OAuth token: ");
555
+ if (providerRaw === "minimax")
556
+ credentials.apiKey = await prompt("API key: ");
557
+ if (providerRaw === "azure") {
558
+ credentials.apiKey = await prompt("API key: ");
559
+ credentials.endpoint = await prompt("endpoint: ");
560
+ credentials.deployment = await prompt("deployment: ");
561
+ }
562
+ }
563
+ }
564
+ else {
565
+ process.stdout.write("\nwelcome to ouro. let's get you set up.\n");
566
+ process.stdout.write("i need an API key to power our conversation.\n\n");
567
+ const pRaw = await prompt("provider (anthropic/azure/minimax/openai-codex): ");
568
+ if (!isAgentProvider(pRaw)) {
569
+ process.stdout.write("unknown provider. run `ouro hatch` to try again.\n");
570
+ rl.close();
571
+ return null;
572
+ }
573
+ providerRaw = pRaw;
574
+ if (providerRaw === "anthropic")
575
+ credentials.setupToken = await prompt("API key: ");
576
+ if (providerRaw === "openai-codex")
577
+ credentials.oauthAccessToken = await prompt("OAuth token: ");
578
+ if (providerRaw === "minimax")
579
+ credentials.apiKey = await prompt("API key: ");
580
+ if (providerRaw === "azure") {
581
+ credentials.apiKey = await prompt("API key: ");
582
+ credentials.endpoint = await prompt("endpoint: ");
583
+ credentials.deployment = await prompt("deployment: ");
584
+ }
488
585
  }
489
586
  rl.close();
490
587
  process.stdout.write("\n");
491
588
  // Locate the bundled AdoptionSpecialist.ouro shipped with the npm package
492
589
  const bundleSourceDir = path.resolve(__dirname, "..", "..", "..", "AdoptionSpecialist.ouro");
493
590
  const bundlesRoot = (0, identity_1.getAgentBundlesRoot)();
494
- const secretsRoot = path.join(os.homedir(), ".agentsecrets");
495
591
  return await (0, specialist_orchestrator_1.runAdoptionSpecialist)({
496
592
  bundleSourceDir,
497
593
  bundlesRoot,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.8",
3
+ "version": "0.1.0-alpha.9",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "ouro": "dist/heart/daemon/ouro-entry.js",