@ouro.bot/cli 0.1.0-alpha.371 → 0.1.0-alpha.373

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/changelog.json CHANGED
@@ -1,6 +1,22 @@
1
1
  {
2
2
  "_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
3
3
  "versions": [
4
+ {
5
+ "version": "0.1.0-alpha.373",
6
+ "changes": [
7
+ "SerpentGuide bootstrap now discovers provider credentials from unlockable installed agent vaults, so a new hatch can reuse sources such as `minimax from slugger's vault` without creating persistent SerpentGuide credentials.",
8
+ "SerpentGuide credential options now preserve provenance for installed-agent vault sources and env sources while keeping secret values out of terminal labels.",
9
+ "`@ouro.bot/cli` and the `ouro.bot` wrapper are version-synced for the SerpentGuide installed-agent credential discovery release."
10
+ ]
11
+ },
12
+ {
13
+ "version": "0.1.0-alpha.372",
14
+ "changes": [
15
+ "Locked-vault errors now explain that provider credentials are still stored in the agent vault and that this computer is missing usable local unlock material.",
16
+ "The locked-vault guidance now names common machine-local causes, including a new computer, local profile or hostname migration, and removed local unlock entries.",
17
+ "`@ouro.bot/cli` and the `ouro.bot` wrapper are version-synced for the locked-vault bootstrap copy release."
18
+ ]
19
+ },
4
20
  {
5
21
  "version": "0.1.0-alpha.371",
6
22
  "changes": [
@@ -247,10 +247,18 @@ async function defaultRunSerpentGuide() {
247
247
  const tempDir = path.join(os.tmpdir(), `ouro-hatch-${crypto.randomUUID()}`);
248
248
  try {
249
249
  const discovered = [];
250
- const existingBundleCount = (0, specialist_orchestrator_1.listExistingBundles)((0, identity_1.getAgentBundlesRoot)()).length;
250
+ const existingBundles = (0, specialist_orchestrator_1.listExistingBundles)((0, identity_1.getAgentBundlesRoot)());
251
+ const existingBundleCount = existingBundles.length;
251
252
  const hatchVerb = existingBundleCount > 0 ? "let's hatch a new agent." : "let's hatch your first agent.";
252
253
  // Default models per provider (used when entering new credentials)
253
254
  const defaultModels = provider_models_1.DEFAULT_PROVIDER_MODELS;
255
+ const installedAgentCreds = await (0, provider_discovery_1.discoverInstalledAgentCredentials)(existingBundles);
256
+ for (const cred of installedAgentCreds) {
257
+ discovered.push({
258
+ ...cred,
259
+ providerConfig: { model: defaultModels[cred.provider], ...cred.providerConfig },
260
+ });
261
+ }
254
262
  // Scan environment variables for API keys using the shared helper
255
263
  const envCreds = (0, provider_discovery_1.scanEnvVarCredentials)(process.env);
256
264
  const envDiscovered = [];
@@ -268,21 +276,21 @@ async function defaultRunSerpentGuide() {
268
276
  if (discovered.length > 0) {
269
277
  process.stdout.write(`\n\ud83d\udc0d welcome to ouroboros! ${hatchVerb}\n`);
270
278
  process.stdout.write("i found existing API credentials:\n\n");
271
- const unique = [...new Map(discovered.map((d) => [`${d.provider}`, d])).values()];
272
- for (let i = 0; i < unique.length; i++) {
273
- const model = unique[i].providerConfig.model || unique[i].providerConfig.deployment || "";
279
+ const credentialOptions = discovered;
280
+ for (let i = 0; i < credentialOptions.length; i++) {
281
+ const model = credentialOptions[i].providerConfig.model || credentialOptions[i].providerConfig.deployment || "";
274
282
  const modelLabel = model ? `, ${model}` : "";
275
- const envMatch = envDiscovered.find((e) => e.provider === unique[i].provider && unique[i].agentName === "env");
276
- const sourceLabel = envMatch ? `from env: $${envMatch.envVar}` : `from ${unique[i].agentName}`;
277
- process.stdout.write(` ${i + 1}. ${unique[i].provider}${modelLabel} (${sourceLabel})\n`);
283
+ const envMatch = envDiscovered.find((e) => e.provider === credentialOptions[i].provider && credentialOptions[i].agentName === "env");
284
+ const sourceLabel = (0, provider_discovery_1.describeDiscoveredCredentialSource)(credentialOptions[i], envMatch?.envVar);
285
+ process.stdout.write(` ${i + 1}. ${credentialOptions[i].provider}${modelLabel} (${sourceLabel})\n`);
278
286
  }
279
287
  process.stdout.write("\n");
280
288
  const choice = await coldPrompt("use one of these? enter number, or 'new' for a different key: ");
281
289
  const idx = parseInt(choice, 10) - 1;
282
- if (idx >= 0 && idx < unique.length) {
283
- providerRaw = unique[idx].provider;
284
- credentials = unique[idx].credentials;
285
- providerConfig = unique[idx].providerConfig;
290
+ if (idx >= 0 && idx < credentialOptions.length) {
291
+ providerRaw = credentialOptions[idx].provider;
292
+ credentials = credentialOptions[idx].credentials;
293
+ providerConfig = credentialOptions[idx].providerConfig;
286
294
  }
287
295
  else {
288
296
  const pRaw = await coldPrompt("provider (anthropic/azure/minimax/openai-codex/github-copilot): ");
@@ -354,7 +362,6 @@ async function defaultRunSerpentGuide() {
354
362
  process.stdout.write(`credentials didn't work (${pingResult.message}). run 'ouro hatch' to try again.\n`);
355
363
  return null;
356
364
  }
357
- const existingBundles = (0, specialist_orchestrator_1.listExistingBundles)(bundlesRoot);
358
365
  const systemPrompt = (0, specialist_prompt_1.buildSpecialistSystemPrompt)(soulText, identity.content, existingBundles, {
359
366
  tempDir,
360
367
  provider: providerRaw,
@@ -8,6 +8,8 @@
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.scanEnvVarCredentials = scanEnvVarCredentials;
11
+ exports.discoverInstalledAgentCredentials = discoverInstalledAgentCredentials;
12
+ exports.describeDiscoveredCredentialSource = describeDiscoveredCredentialSource;
11
13
  exports.discoverWorkingProvider = discoverWorkingProvider;
12
14
  const identity_1 = require("../identity");
13
15
  const provider_credentials_1 = require("../provider-credentials");
@@ -45,14 +47,36 @@ function stringifyProviderFields(fields) {
45
47
  }
46
48
  return result;
47
49
  }
48
- function discoveredFromVaultRecord(record) {
50
+ function discoveredFromVaultRecord(record, agentName = "vault") {
49
51
  return {
50
52
  provider: record.provider,
51
- agentName: "vault",
53
+ agentName,
52
54
  credentials: stringifyProviderFields(record.credentials),
53
55
  providerConfig: stringifyProviderFields(record.config),
54
56
  };
55
57
  }
58
+ async function discoverInstalledAgentCredentials(agentNames) {
59
+ const discovered = [];
60
+ for (const agentName of agentNames) {
61
+ if (agentName === "SerpentGuide")
62
+ continue;
63
+ const poolResult = await (0, provider_credentials_1.refreshProviderCredentialPool)(agentName, { preserveCachedOnFailure: true });
64
+ if (!poolResult.ok)
65
+ continue;
66
+ for (const record of Object.values(poolResult.pool.providers)) {
67
+ if (!record)
68
+ continue;
69
+ discovered.push(discoveredFromVaultRecord(record, agentName));
70
+ }
71
+ }
72
+ return discovered;
73
+ }
74
+ function describeDiscoveredCredentialSource(credential, envVar) {
75
+ if (credential.agentName === "env") {
76
+ return envVar ? `from env: $${envVar}` : "from env";
77
+ }
78
+ return `from ${credential.agentName}'s vault`;
79
+ }
56
80
  async function discoverWorkingProvider(deps) {
57
81
  const poolResult = await (0, provider_credentials_1.refreshProviderCredentialPool)(deps.agentName);
58
82
  if (!poolResult.ok) {
@@ -106,6 +106,10 @@ function lockedMessage(config, store) {
106
106
  `Vault: ${vaultLabel(config)}`,
107
107
  `Local unlock store: ${store.kind} (${store.location})`,
108
108
  "",
109
+ "Provider credentials are still stored in the agent vault.",
110
+ "This computer does not currently have usable local unlock material for that vault.",
111
+ "This can happen on a new computer, after a local profile or hostname migration, or if the local unlock entry was removed.",
112
+ "",
109
113
  `Run \`${command}\` and enter the vault unlock secret from the operator password manager.`,
110
114
  ].join("\n");
111
115
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.371",
3
+ "version": "0.1.0-alpha.373",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",