@ouro.bot/cli 0.1.0-alpha.364 → 0.1.0-alpha.366

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 (42) hide show
  1. package/README.md +15 -6
  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 +60 -239
  7. package/dist/heart/daemon/agentic-repair.js +2 -1
  8. package/dist/heart/daemon/cli-defaults.js +15 -68
  9. package/dist/heart/daemon/cli-exec.js +249 -89
  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/interactive-repair.js +37 -2
  15. package/dist/heart/daemon/provider-discovery.js +32 -59
  16. package/dist/heart/hatch/hatch-flow.js +9 -12
  17. package/dist/heart/hatch/specialist-prompt.js +1 -1
  18. package/dist/heart/hatch/specialist-tools.js +21 -1
  19. package/dist/heart/migrate-config.js +15 -42
  20. package/dist/heart/provider-binding-resolver.js +6 -7
  21. package/dist/heart/provider-credentials.js +379 -0
  22. package/dist/heart/provider-failover.js +3 -11
  23. package/dist/heart/provider-ping.js +13 -3
  24. package/dist/heart/provider-state.js +8 -0
  25. package/dist/heart/provider-visibility.js +3 -6
  26. package/dist/heart/providers/anthropic-token.js +15 -47
  27. package/dist/heart/providers/anthropic.js +4 -9
  28. package/dist/heart/providers/azure.js +3 -3
  29. package/dist/heart/providers/github-copilot.js +2 -2
  30. package/dist/heart/providers/minimax-vlm.js +2 -2
  31. package/dist/heart/providers/minimax.js +1 -1
  32. package/dist/heart/providers/openai-codex.js +4 -9
  33. package/dist/repertoire/bitwarden-store.js +63 -17
  34. package/dist/repertoire/bundle-templates.js +2 -2
  35. package/dist/repertoire/credential-access.js +47 -467
  36. package/dist/repertoire/tools-attachments.js +5 -4
  37. package/dist/repertoire/tools-vault.js +10 -80
  38. package/dist/repertoire/vault-unlock.js +359 -0
  39. package/dist/senses/bluebubbles/client.js +39 -4
  40. package/dist/senses/pipeline.js +0 -1
  41. package/package.json +1 -1
  42. package/dist/heart/provider-credential-pool.js +0 -395
@@ -1,44 +1,7 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  Object.defineProperty(exports, "__esModule", { value: true });
36
3
  exports.vaultToolDefinitions = void 0;
37
- const crypto = __importStar(require("node:crypto"));
38
- const fs = __importStar(require("node:fs"));
39
- const path = __importStar(require("node:path"));
40
4
  const identity_1 = require("../heart/identity");
41
- const vault_setup_1 = require("./vault-setup");
42
5
  const runtime_1 = require("../nerves/runtime");
43
6
  exports.vaultToolDefinitions = [
44
7
  {
@@ -61,49 +24,16 @@ exports.vaultToolDefinitions = [
61
24
  message: "vault_setup invoked",
62
25
  meta: { tool: "vault_setup", agentName },
63
26
  });
64
- try {
65
- const config = (0, identity_1.loadAgentConfig)();
66
- const { email, serverUrl } = (0, identity_1.resolveVaultConfig)(agentName, config.vault);
67
- // Generate a strong random master password (32 bytes -> base64)
68
- const masterPassword = crypto.randomBytes(32).toString("base64");
69
- // Store master password in secrets.json BEFORE creating the account
70
- // so it's not lost if the process crashes after registration
71
- const secretsPath = (0, identity_1.getAgentSecretsPath)(agentName);
72
- const secretsDir = path.dirname(secretsPath);
73
- if (!fs.existsSync(secretsDir)) {
74
- fs.mkdirSync(secretsDir, { recursive: true, mode: 0o700 });
75
- }
76
- let secrets = {};
77
- if (fs.existsSync(secretsPath)) {
78
- try {
79
- secrets = JSON.parse(fs.readFileSync(secretsPath, "utf-8"));
80
- }
81
- catch {
82
- // If secrets.json is corrupt, start fresh but don't lose the file
83
- secrets = {};
84
- }
85
- }
86
- secrets.vault = {
87
- ...(typeof secrets.vault === "object" && secrets.vault !== null ? secrets.vault : {}),
88
- masterPassword,
89
- email,
90
- serverUrl,
91
- };
92
- fs.writeFileSync(secretsPath, JSON.stringify(secrets, null, 2) + "\n", {
93
- mode: 0o600,
94
- });
95
- // Create the vault account
96
- const result = await (0, vault_setup_1.createVaultAccount)(agentName, serverUrl, email, masterPassword);
97
- if (!result.success) {
98
- return `Vault setup failed: ${result.error}`;
99
- }
100
- return `Vault created at ${serverUrl} for ${email}. Master password stored in secrets.json.`;
101
- }
102
- catch (err) {
103
- /* v8 ignore next -- defensive: error handling @preserve */
104
- const reason = err instanceof Error ? err.message : String(err);
105
- return `Vault setup error: ${reason}`;
106
- }
27
+ return [
28
+ "Vault setup is human-required.",
29
+ "",
30
+ "Why I cannot do it here:",
31
+ " Creating or unlocking a vault requires secret entry that must stay out of agent context.",
32
+ "",
33
+ "Do this in a terminal:",
34
+ ` ouro vault create --agent ${agentName}`,
35
+ ` ouro vault unlock --agent ${agentName}`,
36
+ ].join("\n");
107
37
  },
108
38
  summaryKeys: [],
109
39
  },
@@ -0,0 +1,359 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.resolveVaultUnlockStore = resolveVaultUnlockStore;
37
+ exports.readVaultUnlockSecret = readVaultUnlockSecret;
38
+ exports.storeVaultUnlockSecret = storeVaultUnlockSecret;
39
+ exports.getVaultUnlockStatus = getVaultUnlockStatus;
40
+ const node_child_process_1 = require("node:child_process");
41
+ const crypto = __importStar(require("node:crypto"));
42
+ const fs = __importStar(require("node:fs"));
43
+ const os = __importStar(require("node:os"));
44
+ const path = __importStar(require("node:path"));
45
+ const runtime_1 = require("../nerves/runtime");
46
+ const VAULT_UNLOCK_SERVICE = "ouro.vault";
47
+ const PLAINTEXT_UNLOCK_DIR = path.join(".ouro-cli", "vault-unlock");
48
+ const WINDOWS_DPAPI_UNLOCK_DIR = path.join(".ouro-cli", "vault-unlock-dpapi");
49
+ const SUPPORTED_STORES = ["auto", "macos-keychain", "windows-dpapi", "linux-secret-service", "plaintext-file"];
50
+ function platform(deps) {
51
+ return deps.platform ?? process.platform;
52
+ }
53
+ function spawnSync(deps) {
54
+ return deps.spawnSync ?? node_child_process_1.spawnSync;
55
+ }
56
+ function homeDir(deps) {
57
+ return deps.homeDir ?? os.homedir();
58
+ }
59
+ function vaultKey(config) {
60
+ return `${config.serverUrl}:${config.email}`;
61
+ }
62
+ function vaultLabel(config) {
63
+ return `${config.email} at ${config.serverUrl}`;
64
+ }
65
+ function plaintextUnlockPath(config, deps) {
66
+ const digest = crypto.createHash("sha256").update(vaultKey(config)).digest("hex").slice(0, 24);
67
+ return path.join(homeDir(deps), PLAINTEXT_UNLOCK_DIR, `${digest}.secret`);
68
+ }
69
+ function windowsDpapiUnlockPath(config, deps) {
70
+ const digest = crypto.createHash("sha256").update(vaultKey(config)).digest("hex").slice(0, 24);
71
+ const localAppData = process.env.LOCALAPPDATA;
72
+ const baseDir = localAppData && platform(deps) === "win32"
73
+ ? path.join(localAppData, "Ouro")
74
+ : path.join(homeDir(deps), WINDOWS_DPAPI_UNLOCK_DIR);
75
+ return path.join(baseDir, "vault-unlock", `${digest}.dpapi`);
76
+ }
77
+ function commandExists(command, deps) {
78
+ const result = spawnSync(deps)(command, ["--version"], { encoding: "utf8" });
79
+ const code = result.error?.code;
80
+ return code !== "ENOENT";
81
+ }
82
+ function missingSecureStoreMessage(config) {
83
+ const agentPart = config.agentName ? ` for ${config.agentName}` : "";
84
+ return [
85
+ `No supported secure local secret store was found on this machine${agentPart}.`,
86
+ "",
87
+ `Ouro knows the credential vault is ${vaultLabel(config)}, but it cannot cache the vault unlock secret here yet.`,
88
+ "",
89
+ "On macOS, Ouro uses Keychain automatically.",
90
+ "On Windows, Ouro uses a CurrentUser DPAPI-encrypted local file automatically.",
91
+ "On Linux/WSL, install and configure Secret Service/libsecret, or choose the explicit plaintext fallback on a trusted machine.",
92
+ "",
93
+ config.agentName
94
+ ? `Run \`ouro vault unlock --agent ${config.agentName} --store plaintext-file\` to store the vault unlock secret in a chmod 0600 local file.`
95
+ : "Run `ouro vault unlock --store plaintext-file` to store the vault unlock secret in a chmod 0600 local file.",
96
+ ].join("\n");
97
+ }
98
+ function lockedMessage(config, store) {
99
+ const agentPart = config.agentName ? ` for ${config.agentName}` : "";
100
+ const command = config.agentName
101
+ ? `ouro vault unlock --agent ${config.agentName}${store.kind === "plaintext-file" ? " --store plaintext-file" : ""}`
102
+ : `ouro vault unlock${store.kind === "plaintext-file" ? " --store plaintext-file" : ""}`;
103
+ return [
104
+ `Ouro credential vault is locked on this machine${agentPart}.`,
105
+ "",
106
+ `Vault: ${vaultLabel(config)}`,
107
+ `Local unlock store: ${store.kind} (${store.location})`,
108
+ "",
109
+ `Run \`${command}\` and enter the vault unlock secret from the operator password manager.`,
110
+ ].join("\n");
111
+ }
112
+ function validateStoreKind(store) {
113
+ const requested = store ?? "auto";
114
+ if (!SUPPORTED_STORES.includes(requested)) {
115
+ throw new Error(`unknown vault unlock store '${requested}'. Use auto|macos-keychain|windows-dpapi|linux-secret-service|plaintext-file.`);
116
+ }
117
+ return requested;
118
+ }
119
+ function resolveVaultUnlockStore(config, deps = {}) {
120
+ const requested = validateStoreKind(deps.store);
121
+ const currentPlatform = platform(deps);
122
+ if (requested === "macos-keychain") {
123
+ if (currentPlatform !== "darwin") {
124
+ throw new Error(`macos-keychain unlock store is only available on macOS; this machine is ${currentPlatform}.`);
125
+ }
126
+ return { kind: "macos-keychain", secure: true, location: "macOS Keychain" };
127
+ }
128
+ if (requested === "linux-secret-service") {
129
+ if (currentPlatform !== "linux") {
130
+ throw new Error(`linux-secret-service unlock store is only available on Linux/WSL; this machine is ${currentPlatform}.`);
131
+ }
132
+ if (!commandExists("secret-tool", deps)) {
133
+ throw new Error("linux-secret-service unlock store requires the `secret-tool` command from libsecret.");
134
+ }
135
+ return { kind: "linux-secret-service", secure: true, location: "Secret Service via secret-tool" };
136
+ }
137
+ if (requested === "windows-dpapi") {
138
+ if (currentPlatform !== "win32") {
139
+ throw new Error(`windows-dpapi unlock store is only available on Windows; this machine is ${currentPlatform}.`);
140
+ }
141
+ return { kind: "windows-dpapi", secure: true, location: windowsDpapiUnlockPath(config, deps) };
142
+ }
143
+ if (requested === "plaintext-file") {
144
+ return { kind: "plaintext-file", secure: false, location: plaintextUnlockPath(config, deps) };
145
+ }
146
+ if (currentPlatform === "darwin") {
147
+ return { kind: "macos-keychain", secure: true, location: "macOS Keychain" };
148
+ }
149
+ if (currentPlatform === "win32") {
150
+ return { kind: "windows-dpapi", secure: true, location: windowsDpapiUnlockPath(config, deps) };
151
+ }
152
+ if (currentPlatform === "linux" && commandExists("secret-tool", deps)) {
153
+ return { kind: "linux-secret-service", secure: true, location: "Secret Service via secret-tool" };
154
+ }
155
+ throw new Error(missingSecureStoreMessage(config));
156
+ }
157
+ function readFromMacosKeychain(config, deps) {
158
+ const result = spawnSync(deps)("security", [
159
+ "find-generic-password",
160
+ "-s",
161
+ VAULT_UNLOCK_SERVICE,
162
+ "-a",
163
+ vaultKey(config),
164
+ "-w",
165
+ ], { encoding: "utf8" });
166
+ const secret = typeof result.stdout === "string" ? result.stdout.trim() : "";
167
+ return result.status === 0 && secret ? secret : null;
168
+ }
169
+ function writeToMacosKeychain(config, secret, deps) {
170
+ const result = spawnSync(deps)("security", [
171
+ "add-generic-password",
172
+ "-U",
173
+ "-s",
174
+ VAULT_UNLOCK_SERVICE,
175
+ "-a",
176
+ vaultKey(config),
177
+ "-w",
178
+ secret,
179
+ ], { encoding: "utf8" });
180
+ if (result.status !== 0) {
181
+ const stderr = typeof result.stderr === "string" ? result.stderr.trim() : "";
182
+ throw new Error(`failed to store vault unlock secret in macOS Keychain${stderr ? `: ${stderr}` : ""}`);
183
+ }
184
+ }
185
+ function readFromLinuxSecretService(config, deps) {
186
+ const result = spawnSync(deps)("secret-tool", [
187
+ "lookup",
188
+ "service",
189
+ VAULT_UNLOCK_SERVICE,
190
+ "account",
191
+ vaultKey(config),
192
+ ], { encoding: "utf8" });
193
+ const secret = typeof result.stdout === "string" ? result.stdout.trim() : "";
194
+ return result.status === 0 && secret ? secret : null;
195
+ }
196
+ function writeToLinuxSecretService(config, secret, deps) {
197
+ const result = spawnSync(deps)("secret-tool", [
198
+ "store",
199
+ "--label",
200
+ `Ouro credential vault ${vaultLabel(config)}`,
201
+ "service",
202
+ VAULT_UNLOCK_SERVICE,
203
+ "account",
204
+ vaultKey(config),
205
+ ], { encoding: "utf8", input: secret });
206
+ if (result.status !== 0) {
207
+ const stderr = typeof result.stderr === "string" ? result.stderr.trim() : "";
208
+ throw new Error(`failed to store vault unlock secret in Linux Secret Service${stderr ? `: ${stderr}` : ""}`);
209
+ }
210
+ }
211
+ function runWindowsDpapi(mode, payload, deps) {
212
+ const script = `
213
+ $ErrorActionPreference = "Stop"
214
+ $inputJson = [Console]::In.ReadToEnd()
215
+ $payload = $inputJson | ConvertFrom-Json
216
+ Add-Type -AssemblyName System.Security
217
+ if ($payload.mode -eq "protect") {
218
+ $bytes = [Text.Encoding]::UTF8.GetBytes([string]$payload.secret)
219
+ $protected = [Security.Cryptography.ProtectedData]::Protect($bytes, $null, [Security.Cryptography.DataProtectionScope]::CurrentUser)
220
+ [Console]::Out.Write([Convert]::ToBase64String($protected))
221
+ } elseif ($payload.mode -eq "unprotect") {
222
+ $protected = [Convert]::FromBase64String([string]$payload.ciphertext)
223
+ $bytes = [Security.Cryptography.ProtectedData]::Unprotect($protected, $null, [Security.Cryptography.DataProtectionScope]::CurrentUser)
224
+ [Console]::Out.Write([Text.Encoding]::UTF8.GetString($bytes))
225
+ } else {
226
+ throw "unknown DPAPI mode"
227
+ }
228
+ `;
229
+ const result = spawnSync(deps)("powershell.exe", [
230
+ "-NoProfile",
231
+ "-NonInteractive",
232
+ "-ExecutionPolicy",
233
+ "Bypass",
234
+ "-Command",
235
+ script,
236
+ ], {
237
+ encoding: "utf8",
238
+ input: JSON.stringify({ mode, ...payload }),
239
+ });
240
+ if (result.status !== 0) {
241
+ const stderr = typeof result.stderr === "string" ? result.stderr.trim() : "";
242
+ const error = result.error instanceof Error ? result.error.message : stderr;
243
+ throw new Error(`Windows DPAPI ${mode} failed${error ? `: ${error}` : ""}`);
244
+ }
245
+ return typeof result.stdout === "string" ? result.stdout : "";
246
+ }
247
+ function readFromWindowsDpapi(config, deps) {
248
+ const filePath = windowsDpapiUnlockPath(config, deps);
249
+ if (!fs.existsSync(filePath))
250
+ return null;
251
+ const ciphertext = fs.readFileSync(filePath, "utf8").trim();
252
+ if (!ciphertext)
253
+ return null;
254
+ const secret = runWindowsDpapi("unprotect", { ciphertext }, deps).trim();
255
+ return secret || null;
256
+ }
257
+ function writeToWindowsDpapi(config, secret, deps) {
258
+ const filePath = windowsDpapiUnlockPath(config, deps);
259
+ const ciphertext = runWindowsDpapi("protect", { secret }, deps).trim();
260
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
261
+ fs.writeFileSync(filePath, `${ciphertext}\n`, "utf8");
262
+ }
263
+ function readFromPlaintextFile(config, deps) {
264
+ const filePath = plaintextUnlockPath(config, deps);
265
+ if (!fs.existsSync(filePath))
266
+ return null;
267
+ if (platform(deps) !== "win32") {
268
+ const mode = fs.statSync(filePath).mode & 0o777;
269
+ if ((mode & 0o077) !== 0) {
270
+ throw new Error(`refusing to read plaintext vault unlock file at ${filePath} because permissions are too broad; run chmod 600 ${filePath}`);
271
+ }
272
+ }
273
+ const secret = fs.readFileSync(filePath, "utf8").trim();
274
+ return secret || null;
275
+ }
276
+ function writeToPlaintextFile(config, secret, deps) {
277
+ const filePath = plaintextUnlockPath(config, deps);
278
+ fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });
279
+ fs.writeFileSync(filePath, secret, { encoding: "utf8", mode: 0o600 });
280
+ if (platform(deps) !== "win32") {
281
+ fs.chmodSync(path.dirname(filePath), 0o700);
282
+ fs.chmodSync(filePath, 0o600);
283
+ }
284
+ }
285
+ function readFromStore(config, store, deps) {
286
+ if (store.kind === "macos-keychain")
287
+ return readFromMacosKeychain(config, deps);
288
+ if (store.kind === "windows-dpapi")
289
+ return readFromWindowsDpapi(config, deps);
290
+ if (store.kind === "linux-secret-service")
291
+ return readFromLinuxSecretService(config, deps);
292
+ return readFromPlaintextFile(config, deps);
293
+ }
294
+ function writeToStore(config, store, secret, deps) {
295
+ if (store.kind === "macos-keychain") {
296
+ writeToMacosKeychain(config, secret, deps);
297
+ return;
298
+ }
299
+ if (store.kind === "linux-secret-service") {
300
+ writeToLinuxSecretService(config, secret, deps);
301
+ return;
302
+ }
303
+ if (store.kind === "windows-dpapi") {
304
+ writeToWindowsDpapi(config, secret, deps);
305
+ return;
306
+ }
307
+ writeToPlaintextFile(config, secret, deps);
308
+ }
309
+ function readVaultUnlockSecret(config, deps = {}) {
310
+ const store = resolveVaultUnlockStore(config, deps);
311
+ const secret = readFromStore(config, store, deps);
312
+ if (!secret) {
313
+ throw new Error(lockedMessage(config, store));
314
+ }
315
+ (0, runtime_1.emitNervesEvent)({
316
+ component: "repertoire",
317
+ event: "repertoire.vault_unlock_loaded",
318
+ message: "loaded vault unlock material from local store",
319
+ meta: { store: store.kind, secure: store.secure, hasAgentName: !!config.agentName },
320
+ });
321
+ return { secret, store };
322
+ }
323
+ function storeVaultUnlockSecret(config, secret, deps = {}) {
324
+ const trimmed = secret.trim();
325
+ if (!trimmed) {
326
+ throw new Error("vault unlock secret is required");
327
+ }
328
+ const store = resolveVaultUnlockStore(config, deps);
329
+ writeToStore(config, store, trimmed, deps);
330
+ (0, runtime_1.emitNervesEvent)({
331
+ component: "repertoire",
332
+ event: "repertoire.vault_unlock_stored",
333
+ message: "stored vault unlock material in local store",
334
+ meta: { store: store.kind, secure: store.secure, hasAgentName: !!config.agentName },
335
+ });
336
+ return store;
337
+ }
338
+ function getVaultUnlockStatus(config, deps = {}) {
339
+ try {
340
+ const store = resolveVaultUnlockStore(config, deps);
341
+ const stored = !!readFromStore(config, store, deps);
342
+ return {
343
+ configured: true,
344
+ stored,
345
+ store,
346
+ fix: stored
347
+ ? "Vault unlock secret is available on this machine."
348
+ : lockedMessage(config, store),
349
+ };
350
+ }
351
+ catch (error) {
352
+ return {
353
+ configured: false,
354
+ stored: false,
355
+ error: error instanceof Error ? error.message : String(error),
356
+ fix: error instanceof Error ? error.message : String(error),
357
+ };
358
+ }
359
+ }
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.createBlueBubblesClient = createBlueBubblesClient;
4
37
  const node_crypto_1 = require("node:crypto");
@@ -533,13 +566,15 @@ function createBlueBubblesClient(config = (0, config_1.getBlueBubblesConfig)(),
533
566
  throw new Error("VLM fallback requires a minimax credential for this agent — " +
534
567
  "configure one or switch to a vision-capable chat model");
535
568
  }
536
- const { apiKey } = (0, config_1.getMinimaxConfig)();
569
+ const { readProviderCredentialRecord } = await Promise.resolve().then(() => __importStar(require("../../heart/provider-credentials")));
570
+ const credential = await readProviderCredentialRecord((0, identity_1.getAgentName)(), "minimax");
571
+ const apiKey = credential.ok ? credential.record.credentials.apiKey : undefined;
537
572
  if (!apiKey) {
538
- throw new Error("VLM fallback: minimax API key not found in secrets.json — " +
539
- "re-run credential setup or ask the user to add a minimax key");
573
+ throw new Error("VLM fallback: minimax API key not found in the agent vault — " +
574
+ "run `ouro auth --agent <agent> --provider minimax`");
540
575
  }
541
576
  return (0, minimax_vlm_1.minimaxVlmDescribe)({
542
- apiKey,
577
+ apiKey: String(apiKey),
543
578
  prompt: params.prompt,
544
579
  imageDataUrl: params.imageDataUrl,
545
580
  baseURL: minimax_1.MINIMAX_PROVIDER_BASE_URL,
@@ -205,7 +205,6 @@ async function handleInboundTurn(input) {
205
205
  model: failoverAction.model,
206
206
  credentialRevision: failoverAction.credentialRevision,
207
207
  source: failoverAction.source,
208
- contributedByAgent: failoverAction.contributedByAgent,
209
208
  },
210
209
  });
211
210
  // Replace "switch to <provider>" with a context message for the agent.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.364",
3
+ "version": "0.1.0-alpha.366",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",