@hoilab/ada-cli 0.84.17 → 0.84.19

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.
@@ -2423,6 +2423,12 @@ export class InteractiveMode {
2423
2423
  void this.handleMemoryAuditCommand();
2424
2424
  return;
2425
2425
  }
2426
+ if (text === "/vault" || text.startsWith("/vault ")) {
2427
+ const args = text.startsWith("/vault ") ? text.slice(7).trim() : "";
2428
+ this.editor.setText("");
2429
+ void this.handleVaultCommand(args);
2430
+ return;
2431
+ }
2426
2432
  if (text === "/changelog") {
2427
2433
  this.handleChangelogCommand();
2428
2434
  this.editor.setText("");
@@ -5305,6 +5311,142 @@ export class InteractiveMode {
5305
5311
  this.chatContainer.addChild(new Text(lines.join("\n"), 1, 0));
5306
5312
  this.ui.requestRender();
5307
5313
  }
5314
+ async handleVaultCommand(args) {
5315
+ const vault = this.session.resourceLoader.getVaultManager();
5316
+ if (!vault) {
5317
+ this.chatContainer.addChild(new Spacer(1));
5318
+ this.chatContainer.addChild(new Text("Vault unavailable.", 1, 0));
5319
+ this.ui.requestRender();
5320
+ return;
5321
+ }
5322
+ const [action, ...rest] = args.split(/\s+/).filter(Boolean);
5323
+ const name = rest[0] ?? "";
5324
+ const show = (lines) => {
5325
+ this.chatContainer.addChild(new Spacer(1));
5326
+ this.chatContainer.addChild(new Text(lines.join("\n"), 1, 0));
5327
+ this.ui.requestRender();
5328
+ };
5329
+ switch (action ?? "status") {
5330
+ case "unlock": {
5331
+ const passphrase = await this.showExtensionInput("🔓 Vault passphrase (no se guarda en disco)", "••••••••");
5332
+ if (!passphrase) {
5333
+ show(["Unlock cancelled."]);
5334
+ return;
5335
+ }
5336
+ const ok = await vault.unlock(passphrase);
5337
+ show(ok
5338
+ ? ["🔓 Vault unlocked.", ` Path: ${vault.vaultPath}`, ` Secrets: ${vault.list().length}`]
5339
+ : ["❌ Wrong passphrase or corrupted vault."]);
5340
+ return;
5341
+ }
5342
+ case "lock":
5343
+ vault.lock();
5344
+ show(["🔒 Vault locked."]);
5345
+ return;
5346
+ case "add": {
5347
+ if (!vault.isUnlocked) {
5348
+ show(["🔒 Unlock first: /vault unlock"]);
5349
+ return;
5350
+ }
5351
+ if (!name) {
5352
+ show(["Usage: /vault add <name>"]);
5353
+ return;
5354
+ }
5355
+ const value = await this.showExtensionInput(`Value for '${name}'`, "");
5356
+ if (!value) {
5357
+ show(["Cancelled."]);
5358
+ return;
5359
+ }
5360
+ vault.add(name, value);
5361
+ show([`✅ '${name}' saved to the project vault (encrypted).`, " Use @vault:" + name + " in a message to pass it to the agent."]);
5362
+ return;
5363
+ }
5364
+ case "session": {
5365
+ if (!name) {
5366
+ show(["Usage: /vault session add <name> | /vault session remove <name>"]);
5367
+ return;
5368
+ }
5369
+ const sub = rest[0] ?? "";
5370
+ if (sub === "add" && rest[1]) {
5371
+ const value = await this.showExtensionInput(`Session value for '${rest[1]}'`, "");
5372
+ if (!value) {
5373
+ show(["Cancelled."]);
5374
+ return;
5375
+ }
5376
+ vault.sessionAdd(rest[1], value);
5377
+ show([`✅ '${rest[1]}' saved to the SESSION vault (memory only).`]);
5378
+ return;
5379
+ }
5380
+ if (sub === "remove" && rest[1]) {
5381
+ vault.sessionRemove(rest[1]);
5382
+ show([`Session secret '${rest[1]}' removed.`]);
5383
+ return;
5384
+ }
5385
+ show(["Usage: /vault session add <name> | /vault session remove <name>"]);
5386
+ return;
5387
+ }
5388
+ case "remove": {
5389
+ if (!vault.isUnlocked) {
5390
+ show(["🔒 Unlock first: /vault unlock"]);
5391
+ return;
5392
+ }
5393
+ if (!name) {
5394
+ show(["Usage: /vault remove <name>"]);
5395
+ return;
5396
+ }
5397
+ vault.remove(name);
5398
+ show([`🗑️ '${name}' removed from the project vault.`]);
5399
+ return;
5400
+ }
5401
+ case "use": {
5402
+ const available = vault.list();
5403
+ if (available.length === 0) {
5404
+ show(["Vault vacío. Usa /vault unlock y /vault add <name>."]);
5405
+ return;
5406
+ }
5407
+ if (!name) {
5408
+ const names = available
5409
+ .map((e) => ` ${e.name} (${e.source === "session" ? "sesión" : "proyecto"}${e.category ? " · " + e.category : ""})`)
5410
+ .join("\n");
5411
+ show([
5412
+ "Secretos disponibles:",
5413
+ names,
5414
+ "",
5415
+ "Usa /vault use <name> para obtener la referencia, o escribe @vault:<name> directamente en el chat.",
5416
+ ]);
5417
+ return;
5418
+ }
5419
+ const exists = available.some((e) => e.name === name);
5420
+ show(exists
5421
+ ? [`Listo. Escribe esto en el chat: @vault:${name}`, "El agente recibirá el valor; nunca se persiste en la sesión."]
5422
+ : [`No existe el secreto '${name}'. /vault list para verlos.`]);
5423
+ return;
5424
+ }
5425
+ case "list":
5426
+ case "status":
5427
+ default: {
5428
+ const status = vault.status();
5429
+ const entries = vault.list();
5430
+ const lines = [
5431
+ `${theme.bold("🔐 Ada Vault")}`,
5432
+ `${theme.fg("dim", "Unlocked:")} ${status.unlocked ? "yes" : "no"} · ${theme.fg("dim", "File:")} ${status.vaultPath}`,
5433
+ ];
5434
+ if (entries.length === 0) {
5435
+ lines.push(theme.fg("dim", "No secrets yet. Use /vault unlock then /vault add <name>."));
5436
+ }
5437
+ else {
5438
+ lines.push("");
5439
+ for (const entry of entries) {
5440
+ const scope = entry.source === "session" ? theme.fg("dim", "[session]") : theme.fg("dim", "[project]");
5441
+ lines.push(` ${scope} ${entry.name}${entry.note ? ` — ${entry.note}` : ""}`);
5442
+ }
5443
+ }
5444
+ lines.push("", "Use @vault:<name> in a message to pass a secret to the agent (never persisted).");
5445
+ show(lines);
5446
+ return;
5447
+ }
5448
+ }
5449
+ }
5308
5450
  handleChangelogCommand() {
5309
5451
  const changelogPath = getChangelogPath();
5310
5452
  const allEntries = parseChangelog(changelogPath);