@ouro.bot/cli 0.1.0-alpha.363 → 0.1.0-alpha.365

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 (44) hide show
  1. package/README.md +16 -7
  2. package/changelog.json +17 -0
  3. package/dist/heart/auth/auth-flow.js +25 -110
  4. package/dist/heart/config.js +69 -55
  5. package/dist/heart/core.js +83 -33
  6. package/dist/heart/daemon/agent-config-check.js +41 -238
  7. package/dist/heart/daemon/agentic-repair.js +1 -1
  8. package/dist/heart/daemon/cli-defaults.js +15 -68
  9. package/dist/heart/daemon/cli-exec.js +334 -102
  10. package/dist/heart/daemon/cli-parse.js +71 -0
  11. package/dist/heart/daemon/daemon-cli.js +1 -2
  12. package/dist/heart/daemon/daemon-entry.js +1 -3
  13. package/dist/heart/daemon/doctor.js +9 -29
  14. package/dist/heart/daemon/provider-discovery.js +32 -59
  15. package/dist/heart/hatch/hatch-flow.js +9 -12
  16. package/dist/heart/hatch/specialist-prompt.js +1 -1
  17. package/dist/heart/hatch/specialist-tools.js +21 -1
  18. package/dist/heart/migrate-config.js +15 -42
  19. package/dist/heart/provider-binding-resolver.js +6 -7
  20. package/dist/heart/provider-credentials.js +379 -0
  21. package/dist/heart/provider-failover.js +3 -11
  22. package/dist/heart/provider-ping.js +13 -3
  23. package/dist/heart/provider-state.js +8 -0
  24. package/dist/heart/provider-visibility.js +3 -6
  25. package/dist/heart/providers/anthropic-token.js +15 -47
  26. package/dist/heart/providers/anthropic.js +4 -9
  27. package/dist/heart/providers/azure.js +3 -3
  28. package/dist/heart/providers/github-copilot.js +2 -2
  29. package/dist/heart/providers/minimax-vlm.js +2 -2
  30. package/dist/heart/providers/minimax.js +1 -1
  31. package/dist/heart/providers/openai-codex.js +4 -9
  32. package/dist/heart/versioning/ouro-path-installer.js +10 -5
  33. package/dist/mind/prompt.js +1 -1
  34. package/dist/repertoire/bitwarden-store.js +63 -17
  35. package/dist/repertoire/bundle-templates.js +2 -2
  36. package/dist/repertoire/credential-access.js +47 -467
  37. package/dist/repertoire/tools-attachments.js +5 -4
  38. package/dist/repertoire/tools-vault.js +10 -80
  39. package/dist/repertoire/vault-unlock.js +359 -0
  40. package/dist/senses/bluebubbles/client.js +39 -4
  41. package/dist/senses/pipeline.js +0 -1
  42. package/package.json +1 -1
  43. package/skills/configure-dev-tools.md +10 -0
  44. package/dist/heart/provider-credential-pool.js +0 -395
@@ -42,7 +42,7 @@ const runtime_1 = require("../../nerves/runtime");
42
42
  const provider_models_1 = require("../provider-models");
43
43
  const machine_identity_1 = require("../machine-identity");
44
44
  const provider_state_1 = require("../provider-state");
45
- const provider_credential_pool_1 = require("../provider-credential-pool");
45
+ const provider_credentials_1 = require("../provider-credentials");
46
46
  function isAgentProvider(value) {
47
47
  return Object.prototype.hasOwnProperty.call(identity_1.PROVIDER_CREDENTIALS, value);
48
48
  }
@@ -52,20 +52,6 @@ function agentRootFor(agentName, bundlesRoot) {
52
52
  function configPathFor(agentName, bundlesRoot) {
53
53
  return path.join(agentRootFor(agentName, bundlesRoot), "agent.json");
54
54
  }
55
- function formatFacingList(facings) {
56
- if (facings.length === 1)
57
- return facings[0];
58
- return `${facings.slice(0, -1).join(", ")} and ${facings[facings.length - 1]}`;
59
- }
60
- function selectedProviderMap(selectedProviders) {
61
- const byProvider = new Map();
62
- for (const selected of selectedProviders) {
63
- const facings = byProvider.get(selected.provider) ?? [];
64
- facings.push(selected.facing);
65
- byProvider.set(selected.provider, facings);
66
- }
67
- return byProvider;
68
- }
69
55
  function resolveFacingProvider(parsed, facing, agentName, agentJsonPath) {
70
56
  const raw = parsed[facing];
71
57
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
@@ -101,114 +87,6 @@ function resolveFacingProvider(parsed, facing, agentName, agentJsonPath) {
101
87
  }
102
88
  return { ok: true, selected: { facing, provider } };
103
89
  }
104
- function resolveSelectedProviders(parsed, agentName, agentJsonPath) {
105
- const hasHumanFacing = parsed.humanFacing !== undefined;
106
- const hasAgentFacing = parsed.agentFacing !== undefined;
107
- if (!hasHumanFacing && !hasAgentFacing && typeof parsed.provider === "string") {
108
- if (!isAgentProvider(parsed.provider)) {
109
- return {
110
- ok: false,
111
- result: {
112
- ok: false,
113
- error: `Unknown provider '${parsed.provider}' in agent.json for '${agentName}'`,
114
- fix: `Set provider to one of: ${Object.keys(identity_1.PROVIDER_CREDENTIALS).join(", ")}`,
115
- },
116
- };
117
- }
118
- return { ok: true, selectedProviders: [{ facing: "provider", provider: parsed.provider }] };
119
- }
120
- const human = resolveFacingProvider(parsed, "humanFacing", agentName, agentJsonPath);
121
- if (!human.ok)
122
- return human;
123
- const agent = resolveFacingProvider(parsed, "agentFacing", agentName, agentJsonPath);
124
- if (!agent.ok)
125
- return agent;
126
- return { ok: true, selectedProviders: [human.selected, agent.selected] };
127
- }
128
- function readConfigCheckContext(agentName, bundlesRoot, secretsRoot) {
129
- const agentJsonPath = path.join(bundlesRoot, `${agentName}.ouro`, "agent.json");
130
- let raw;
131
- try {
132
- raw = fs.readFileSync(agentJsonPath, "utf-8");
133
- }
134
- catch {
135
- return {
136
- ok: false,
137
- result: {
138
- ok: false,
139
- error: `agent.json not found at ${agentJsonPath}`,
140
- fix: `Run 'ouro hatch ${agentName}' to create the agent bundle, or verify that ${bundlesRoot}/${agentName}.ouro/ exists.`,
141
- },
142
- };
143
- }
144
- let parsed;
145
- try {
146
- parsed = JSON.parse(raw);
147
- }
148
- catch {
149
- return {
150
- ok: false,
151
- result: {
152
- ok: false,
153
- error: `agent.json at ${agentJsonPath} contains invalid JSON`,
154
- fix: `Open ${agentJsonPath} and fix the JSON syntax.`,
155
- },
156
- };
157
- }
158
- // Disabled agents are valid — they just won't run
159
- if (parsed.enabled === false) {
160
- return {
161
- ok: true,
162
- context: {
163
- agentJsonPath,
164
- secretsJsonPath: path.join(secretsRoot, agentName, "secrets.json"),
165
- providers: {},
166
- selectedProviders: [],
167
- },
168
- };
169
- }
170
- const selected = resolveSelectedProviders(parsed, agentName, agentJsonPath);
171
- if (!selected.ok)
172
- return selected;
173
- const secretsJsonPath = path.join(secretsRoot, agentName, "secrets.json");
174
- let secrets;
175
- try {
176
- const secretsRaw = fs.readFileSync(secretsJsonPath, "utf-8");
177
- secrets = JSON.parse(secretsRaw);
178
- }
179
- catch {
180
- const firstProvider = selected.selectedProviders[0].provider;
181
- return {
182
- ok: false,
183
- result: {
184
- ok: false,
185
- error: `secrets.json not found or unreadable at ${secretsJsonPath}`,
186
- fix: `Run 'ouro auth --agent ${agentName} --provider ${firstProvider}' to configure credentials, or create ${secretsJsonPath} with providers.${firstProvider} credentials.`,
187
- },
188
- };
189
- }
190
- const providers = secrets.providers;
191
- if (!providers || typeof providers !== "object" || Array.isArray(providers)) {
192
- const firstProvider = selected.selectedProviders[0].provider;
193
- return {
194
- ok: false,
195
- result: {
196
- ok: false,
197
- error: `secrets.json for '${agentName}' is missing providers object`,
198
- fix: `Run 'ouro auth --agent ${agentName} --provider ${firstProvider}' to configure credentials.`,
199
- },
200
- };
201
- }
202
- return {
203
- ok: true,
204
- context: {
205
- agentJsonPath,
206
- secretsJsonPath,
207
- providers,
208
- selectedProviders: selected.selectedProviders,
209
- },
210
- };
211
- }
212
90
  function readAgentConfigForProviderState(agentName, bundlesRoot) {
213
91
  const agentJsonPath = configPathFor(agentName, bundlesRoot);
214
92
  let raw;
@@ -270,7 +148,7 @@ function bootstrapMissingProviderState(input) {
270
148
  if (!inner.ok)
271
149
  return { ok: false, error: inner.result.error, fix: inner.result.fix };
272
150
  const now = new Date();
273
- const homeDir = (0, provider_credential_pool_1.providerCredentialHomeDirFromSecretsRoot)(input.secretsRoot);
151
+ const homeDir = (0, provider_credentials_1.providerCredentialMachineHomeDir)(input.homeDir);
274
152
  const machine = (0, machine_identity_1.loadOrCreateMachineIdentity)({ homeDir, now: () => now });
275
153
  const state = (0, provider_state_1.bootstrapProviderStateFromAgentConfig)({
276
154
  machineId: machine.machineId,
@@ -290,7 +168,7 @@ function bootstrapMissingProviderState(input) {
290
168
  });
291
169
  return { ok: true, agentRoot, state };
292
170
  }
293
- function readOrBootstrapProviderStateForCheck(agentName, bundlesRoot, secretsRoot) {
171
+ function readOrBootstrapProviderStateForCheck(agentName, bundlesRoot, deps = {}) {
294
172
  const configResult = readAgentConfigForProviderState(agentName, bundlesRoot);
295
173
  if (!configResult.ok)
296
174
  return { ok: false, result: configResult.result };
@@ -314,61 +192,14 @@ function readOrBootstrapProviderStateForCheck(agentName, bundlesRoot, secretsRoo
314
192
  const bootstrap = bootstrapMissingProviderState({
315
193
  agentName,
316
194
  bundlesRoot,
317
- secretsRoot,
318
195
  parsed: configResult.parsed,
319
196
  agentJsonPath: configResult.agentJsonPath,
197
+ homeDir: deps.homeDir,
320
198
  });
321
199
  if (!bootstrap.ok)
322
200
  return { ok: false, result: bootstrap };
323
201
  return { ok: true, disabled: false, agentRoot: bootstrap.agentRoot, state: bootstrap.state };
324
202
  }
325
- function validateSelectedProviderSecrets(agentName, context) {
326
- for (const [provider, facings] of selectedProviderMap(context.selectedProviders)) {
327
- const desc = identity_1.PROVIDER_CREDENTIALS[provider];
328
- const providerSecrets = context.providers[provider];
329
- const selectedBy = formatFacingList(facings);
330
- if (!providerSecrets) {
331
- return {
332
- ok: false,
333
- error: `secrets.json for '${agentName}' is missing providers.${provider} section selected by ${selectedBy}`,
334
- fix: `Run 'ouro auth --agent ${agentName} --provider ${provider}' to configure ${provider} credentials.`,
335
- };
336
- }
337
- // Azure special case: managed identity only needs endpoint + deployment.
338
- if (provider === "azure") {
339
- const hasEndpoint = typeof providerSecrets.endpoint === "string" && providerSecrets.endpoint.length > 0;
340
- const hasDeployment = typeof providerSecrets.deployment === "string" && providerSecrets.deployment.length > 0;
341
- const hasManagedId = typeof providerSecrets.managedIdentityClientId === "string" && providerSecrets.managedIdentityClientId.length > 0;
342
- if (hasEndpoint && hasDeployment && hasManagedId) {
343
- continue;
344
- }
345
- }
346
- const missing = desc.required.filter((field) => {
347
- const val = providerSecrets[field];
348
- return typeof val !== "string" || val.length === 0;
349
- });
350
- if (missing.length > 0) {
351
- return {
352
- ok: false,
353
- error: `secrets.json for '${agentName}' is missing required ${provider} credentials selected by ${selectedBy}: ${missing.join(", ")}`,
354
- fix: `Run 'ouro auth --agent ${agentName} --provider ${provider}' to set up ${provider} credentials, or add the missing fields to providers.${provider} in ${context.secretsJsonPath}.`,
355
- };
356
- }
357
- }
358
- return { ok: true };
359
- }
360
- function emitConfigValid(agentName, context, liveProviderCheck) {
361
- (0, runtime_1.emitNervesEvent)({
362
- component: "daemon",
363
- event: "daemon.agent_config_valid",
364
- message: "agent config validation passed",
365
- meta: {
366
- agent: agentName,
367
- providers: [...selectedProviderMap(context.selectedProviders).keys()],
368
- liveProviderCheck,
369
- },
370
- });
371
- }
372
203
  function providerCredentialConfig(record) {
373
204
  return {
374
205
  ...record.credentials,
@@ -395,63 +226,18 @@ function writeLaneReadiness(input) {
395
226
  };
396
227
  (0, provider_state_1.writeProviderState)(input.agentRoot, input.state);
397
228
  }
398
- function legacyProviderCredentialCandidates(agentName, secretsRoot) {
399
- const secretsPath = path.join(secretsRoot, agentName, "secrets.json");
400
- let parsed;
401
- try {
402
- parsed = JSON.parse(fs.readFileSync(secretsPath, "utf-8"));
403
- }
404
- catch {
405
- return [];
406
- }
407
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
408
- return [];
409
- const providers = parsed.providers;
410
- if (!providers || typeof providers !== "object" || Array.isArray(providers))
411
- return [];
412
- const candidates = [];
413
- for (const [providerKey, rawConfig] of Object.entries(providers)) {
414
- if (!isAgentProvider(providerKey) || !rawConfig || typeof rawConfig !== "object" || Array.isArray(rawConfig)) {
415
- continue;
416
- }
417
- const split = (0, provider_credential_pool_1.splitProviderCredentialFields)(providerKey, rawConfig);
418
- if (Object.keys(split.credentials).length === 0 && Object.keys(split.config).length === 0)
419
- continue;
420
- candidates.push({ provider: providerKey, credentials: split.credentials, config: split.config });
421
- }
422
- return candidates;
423
- }
424
- function readPoolWithLegacyMigration(agentName, homeDir, secretsRoot) {
425
- const initial = (0, provider_credential_pool_1.readProviderCredentialPool)(homeDir);
426
- if (initial.ok || initial.reason === "invalid")
427
- return initial;
428
- const candidates = legacyProviderCredentialCandidates(agentName, secretsRoot);
429
- for (const candidate of candidates) {
430
- (0, provider_credential_pool_1.upsertProviderCredential)({
431
- homeDir,
432
- provider: candidate.provider,
433
- credentials: candidate.credentials,
434
- config: candidate.config,
435
- provenance: {
436
- source: "legacy-agent-secrets",
437
- contributedByAgent: agentName,
438
- },
439
- });
440
- }
441
- return candidates.length > 0 ? (0, provider_credential_pool_1.readProviderCredentialPool)(homeDir) : initial;
442
- }
443
- function missingCredentialResult(agentName, lane, provider, model, poolPath) {
229
+ function missingCredentialResult(agentName, lane, provider, model, credentialPath) {
444
230
  return {
445
231
  ok: false,
446
- error: `${lane} provider ${provider} model ${model} has no credentials in the machine provider pool at ${poolPath}`,
232
+ error: `${lane} provider ${provider} model ${model} has no credentials in ${agentName}'s vault at ${credentialPath}`,
447
233
  fix: `Run 'ouro auth --agent ${agentName} --provider ${provider}' to authenticate this machine, or run 'ouro use --agent ${agentName} --lane ${lane} --provider <provider> --model <model>' to choose a working provider/model.`,
448
234
  };
449
235
  }
450
236
  function invalidPoolResult(agentName, lane, provider, model, pool) {
451
237
  return {
452
238
  ok: false,
453
- error: `${lane} provider ${provider} model ${model} cannot read machine provider credentials at ${pool.poolPath}: ${pool.error}`,
454
- fix: `Fix ${pool.poolPath}, then run 'ouro auth --agent ${agentName} --provider ${provider}' or 'ouro use --agent ${agentName} --lane ${lane} --provider <provider> --model <model> --force'.`,
239
+ error: `${lane} provider ${provider} model ${model} cannot read provider credentials from ${agentName}'s vault at ${pool.poolPath}: ${pool.error}`,
240
+ fix: `Run 'ouro vault unlock --agent ${agentName}', then run 'ouro auth --agent ${agentName} --provider ${provider}' if the credential is missing or stale.`,
455
241
  };
456
242
  }
457
243
  function failedPingResult(agentName, lane, provider, model, result) {
@@ -465,30 +251,47 @@ function credentialRecordForLane(pool, provider) {
465
251
  return pool.providers[provider];
466
252
  }
467
253
  /**
468
- * Pre-spawn validation: ensures agent.json exists and required secrets are present.
469
- * Returns `{ ok: true }` when the agent is ready to run, or a descriptive error
470
- * with an actionable fix message when something is missing.
254
+ * Structural validation only. Live provider credential validation belongs to
255
+ * checkAgentConfigWithProviderHealth(), which reads the agent vault and pings.
471
256
  */
472
- function checkAgentConfig(agentName, bundlesRoot, secretsRoot) {
473
- const contextResult = readConfigCheckContext(agentName, bundlesRoot, secretsRoot);
474
- if (!contextResult.ok)
475
- return contextResult.result;
476
- const context = contextResult.context;
477
- const structural = validateSelectedProviderSecrets(agentName, context);
478
- if (!structural.ok)
479
- return structural;
480
- emitConfigValid(agentName, context, false);
257
+ function checkAgentConfig(agentName, bundlesRoot) {
258
+ const configResult = readAgentConfigForProviderState(agentName, bundlesRoot);
259
+ if (!configResult.ok)
260
+ return configResult.result;
261
+ if (configResult.disabled)
262
+ return { ok: true };
263
+ const outward = readFacingForBootstrap(configResult.parsed, "humanFacing", agentName, configResult.agentJsonPath);
264
+ if (!outward.ok)
265
+ return outward.result;
266
+ const inner = readFacingForBootstrap(configResult.parsed, "agentFacing", agentName, configResult.agentJsonPath);
267
+ if (!inner.ok)
268
+ return inner.result;
269
+ (0, runtime_1.emitNervesEvent)({
270
+ component: "daemon",
271
+ event: "daemon.agent_config_valid",
272
+ message: "agent config validation passed",
273
+ meta: {
274
+ agent: agentName,
275
+ providers: [...new Set([outward.provider, inner.provider])],
276
+ liveProviderCheck: false,
277
+ },
278
+ });
481
279
  return { ok: true };
482
280
  }
483
- async function checkAgentConfigWithProviderHealth(agentName, bundlesRoot, secretsRoot, deps = {}) {
484
- const stateResult = readOrBootstrapProviderStateForCheck(agentName, bundlesRoot, secretsRoot);
281
+ async function checkAgentConfigWithProviderHealth(agentName, bundlesRoot, secretsRootOrDeps = {}, maybeDeps = {}) {
282
+ const deps = typeof secretsRootOrDeps === "string"
283
+ ? {
284
+ ...maybeDeps,
285
+ homeDir: maybeDeps.homeDir ?? (path.basename(secretsRootOrDeps) === ".agentsecrets" ? path.dirname(secretsRootOrDeps) : undefined),
286
+ }
287
+ : secretsRootOrDeps;
288
+ const stateResult = readOrBootstrapProviderStateForCheck(agentName, bundlesRoot, deps);
485
289
  if (!stateResult.ok)
486
290
  return stateResult.result;
487
291
  if (stateResult.disabled)
488
292
  return { ok: true };
489
293
  const ping = deps.pingProvider ?? (await Promise.resolve().then(() => __importStar(require("../provider-ping")))).pingProvider;
490
- const homeDir = (0, provider_credential_pool_1.providerCredentialHomeDirFromSecretsRoot)(secretsRoot);
491
- const poolResult = readPoolWithLegacyMigration(agentName, homeDir, secretsRoot);
294
+ const poolResult = await (0, provider_credentials_1.refreshProviderCredentialPool)(agentName);
492
295
  const pingGroups = new Map();
493
296
  const lanes = ["outward", "inner"];
494
297
  for (const lane of lanes) {
@@ -111,7 +111,7 @@ async function runAgenticRepair(degraded, deps) {
111
111
  // Try to discover a working provider for agentic diagnosis
112
112
  let discoveredProvider = null;
113
113
  try {
114
- discoveredProvider = await deps.discoverWorkingProvider();
114
+ discoveredProvider = await deps.discoverWorkingProvider(degraded[0].agent);
115
115
  }
116
116
  catch (error) {
117
117
  const msg = error instanceof Error ? error.message : String(error);
@@ -42,7 +42,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
42
42
  exports.defaultStartDaemonProcess = defaultStartDaemonProcess;
43
43
  exports.readFirstBundleMetaVersion = readFirstBundleMetaVersion;
44
44
  exports.defaultListDiscoveredAgents = defaultListDiscoveredAgents;
45
- exports.discoverExistingCredentials = discoverExistingCredentials;
46
45
  exports.defaultRunSerpentGuide = defaultRunSerpentGuide;
47
46
  exports.createDefaultOuroCliDeps = createDefaultOuroCliDeps;
48
47
  const child_process_1 = require("child_process");
@@ -73,6 +72,7 @@ const auth_flow_1 = require("../auth/auth-flow");
73
72
  const provider_models_1 = require("../provider-models");
74
73
  const cli_parse_1 = require("./cli-parse");
75
74
  const provider_discovery_1 = require("./provider-discovery");
75
+ const provider_credentials_1 = require("../provider-credentials");
76
76
  // ── Default implementations ──
77
77
  function defaultStartDaemonProcess(socketPath) {
78
78
  const entry = path.join((0, identity_1.getRepoRoot)(), "dist", "heart", "daemon", "daemon-entry.js");
@@ -228,65 +228,10 @@ function defaultListDiscoveredAgents() {
228
228
  readFileSync: fs.readFileSync,
229
229
  });
230
230
  }
231
- // ── Credential discovery ──
232
- function discoverExistingCredentials(secretsRoot) {
233
- const found = [];
234
- let entries;
235
- try {
236
- entries = fs.readdirSync(secretsRoot, { withFileTypes: true });
237
- }
238
- catch {
239
- return found;
240
- }
241
- for (const entry of entries) {
242
- if (!entry.isDirectory())
243
- continue;
244
- const secretsPath = path.join(secretsRoot, entry.name, "secrets.json");
245
- let raw;
246
- try {
247
- raw = fs.readFileSync(secretsPath, "utf-8");
248
- }
249
- catch {
250
- continue;
251
- }
252
- let parsed;
253
- try {
254
- parsed = JSON.parse(raw);
255
- }
256
- catch {
257
- continue;
258
- }
259
- if (!parsed.providers)
260
- continue;
261
- for (const [provName, provConfig] of Object.entries(parsed.providers)) {
262
- const desc = identity_1.PROVIDER_CREDENTIALS[provName];
263
- /* v8 ignore next -- guard: unknown provider names in stored secrets @preserve */
264
- if (!desc)
265
- continue;
266
- const hasRequired = desc.required.every((key) => !!provConfig[key]);
267
- if (hasRequired) {
268
- const credentials = {};
269
- for (const key of Object.keys(provConfig))
270
- credentials[key] = provConfig[key];
271
- found.push({ agentName: entry.name, provider: provName, credentials, providerConfig: { ...provConfig } });
272
- }
273
- }
274
- }
275
- // Deduplicate by provider+credential value (keep first seen)
276
- const seen = new Set();
277
- return found.filter((cred) => {
278
- const key = `${cred.provider}:${JSON.stringify(cred.credentials)}`;
279
- if (seen.has(key))
280
- return false;
281
- seen.add(key);
282
- return true;
283
- });
284
- }
285
231
  // ── Serpent guide (interactive hatch) ──
286
232
  /* v8 ignore start -- integration: interactive terminal specialist session @preserve */
287
233
  async function defaultRunSerpentGuide() {
288
234
  const { runCliSession } = await Promise.resolve().then(() => __importStar(require("../../senses/cli")));
289
- const { patchRuntimeConfig } = await Promise.resolve().then(() => __importStar(require("../config")));
290
235
  const { setAgentName, setAgentConfigOverride } = await Promise.resolve().then(() => __importStar(require("../identity")));
291
236
  const readlinePromises = await Promise.resolve().then(() => __importStar(require("readline/promises")));
292
237
  const crypto = await Promise.resolve().then(() => __importStar(require("crypto")));
@@ -301,8 +246,7 @@ async function defaultRunSerpentGuide() {
301
246
  let providerConfig = {};
302
247
  const tempDir = path.join(os.tmpdir(), `ouro-hatch-${crypto.randomUUID()}`);
303
248
  try {
304
- const secretsRoot = path.join(os.homedir(), ".agentsecrets");
305
- const discovered = discoverExistingCredentials(secretsRoot);
249
+ const discovered = [];
306
250
  const existingBundleCount = (0, specialist_orchestrator_1.listExistingBundles)((0, identity_1.getAgentBundlesRoot)()).length;
307
251
  const hatchVerb = existingBundleCount > 0 ? "let's hatch a new agent." : "let's hatch your first agent.";
308
252
  // Default models per provider (used when entering new credentials)
@@ -367,11 +311,20 @@ async function defaultRunSerpentGuide() {
367
311
  }
368
312
  coldRl.close();
369
313
  process.stdout.write("\n");
314
+ const selectedCredentialPayload = { ...providerConfig, ...credentials };
315
+ const split = (0, provider_credentials_1.splitProviderCredentialFields)(providerRaw, selectedCredentialPayload);
316
+ (0, provider_credentials_1.cacheProviderCredentialRecords)("SerpentGuide", [
317
+ (0, provider_credentials_1.createProviderCredentialRecord)({
318
+ provider: providerRaw,
319
+ credentials: split.credentials,
320
+ config: split.config,
321
+ provenance: { source: "manual" },
322
+ }),
323
+ ]);
370
324
  // Phase 2: configure runtime for serpent guide
371
325
  const bundleSourceDir = path.resolve(__dirname, "..", "..", "..", "SerpentGuide.ouro");
372
326
  const bundlesRoot = (0, identity_1.getAgentBundlesRoot)();
373
- const secretsRoot2 = path.join(os.homedir(), ".agentsecrets");
374
- // Suppress non-critical log noise during hatch (no secrets.json, etc.)
327
+ // Suppress non-critical log noise during hatch.
375
328
  const { setRuntimeLogger } = await Promise.resolve().then(() => __importStar(require("../../nerves/runtime")));
376
329
  const { createLogger } = await Promise.resolve().then(() => __importStar(require("../../nerves")));
377
330
  setRuntimeLogger(createLogger({ level: "error" }));
@@ -394,14 +347,9 @@ async function defaultRunSerpentGuide() {
394
347
  agentFacing: { provider: providerRaw, model: resolvedModel },
395
348
  phrases,
396
349
  });
397
- patchRuntimeConfig({
398
- providers: {
399
- [providerRaw]: { ...providerConfig, ...credentials },
400
- },
401
- });
402
350
  // Ping-verify credentials before entering the serpent guide session
403
351
  const { pingProvider } = await Promise.resolve().then(() => __importStar(require("../provider-ping")));
404
- const pingResult = await pingProvider(providerRaw, { ...providerConfig, ...credentials });
352
+ const pingResult = await pingProvider(providerRaw, selectedCredentialPayload);
405
353
  if (!pingResult.ok) {
406
354
  process.stdout.write(`credentials didn't work (${pingResult.message}). run 'ouro hatch' to try again.\n`);
407
355
  return null;
@@ -416,10 +364,9 @@ async function defaultRunSerpentGuide() {
416
364
  const specialistTools = (0, specialist_tools_1.getSpecialistTools)();
417
365
  const specialistExecTool = (0, specialist_tools_1.createSpecialistExecTool)({
418
366
  tempDir,
419
- credentials,
367
+ credentials: selectedCredentialPayload,
420
368
  provider: providerRaw,
421
369
  bundlesRoot,
422
- secretsRoot: secretsRoot2,
423
370
  animationWriter: (text) => process.stdout.write(text),
424
371
  });
425
372
  // Run the serpent guide session via runCliSession