@hoilab/ada-cli 0.84.18 → 0.84.20

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 (34) hide show
  1. package/dist/core/agent-session.d.ts +10 -2
  2. package/dist/core/agent-session.d.ts.map +1 -1
  3. package/dist/core/agent-session.js +70 -18
  4. package/dist/core/agent-session.js.map +1 -1
  5. package/dist/core/memory-engine/audit.d.ts +1 -1
  6. package/dist/core/memory-engine/audit.d.ts.map +1 -1
  7. package/dist/core/memory-engine/audit.js.map +1 -1
  8. package/dist/core/memory-engine/engine.d.ts +2 -0
  9. package/dist/core/memory-engine/engine.d.ts.map +1 -1
  10. package/dist/core/memory-engine/engine.js +4 -0
  11. package/dist/core/memory-engine/engine.js.map +1 -1
  12. package/dist/core/memory-engine/keychain.d.ts +18 -0
  13. package/dist/core/memory-engine/keychain.d.ts.map +1 -0
  14. package/dist/core/memory-engine/keychain.js +93 -0
  15. package/dist/core/memory-engine/keychain.js.map +1 -0
  16. package/dist/core/memory-engine/security.d.ts.map +1 -1
  17. package/dist/core/memory-engine/security.js +10 -0
  18. package/dist/core/memory-engine/security.js.map +1 -1
  19. package/dist/core/memory-engine/vault.d.ts +22 -5
  20. package/dist/core/memory-engine/vault.d.ts.map +1 -1
  21. package/dist/core/memory-engine/vault.js +64 -8
  22. package/dist/core/memory-engine/vault.js.map +1 -1
  23. package/dist/core/resource-loader.d.ts.map +1 -1
  24. package/dist/core/resource-loader.js +1 -0
  25. package/dist/core/resource-loader.js.map +1 -1
  26. package/dist/index.d.ts +1 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +1 -0
  29. package/dist/index.js.map +1 -1
  30. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  31. package/dist/modes/interactive/interactive-mode.js +24 -0
  32. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  33. package/npm-shrinkwrap.json +2 -2
  34. package/package.json +1 -1
@@ -380,6 +380,25 @@ export class AgentSession {
380
380
  // =========================================================================
381
381
  // Automatic project memory (claude-mem style)
382
382
  // =========================================================================
383
+ /**
384
+ * Replace vault-expanded secrets with the redacted form for UI events and
385
+ * persistence (the LLM still receives the expanded values via agent state).
386
+ */
387
+ _applyVaultRedaction(event) {
388
+ if (event.message.role !== "user")
389
+ return;
390
+ const id = event.message.id;
391
+ if (!id)
392
+ return;
393
+ const redactedText = this._vaultRedactions.get(id);
394
+ if (redactedText === undefined)
395
+ return;
396
+ this._vaultRedactions.delete(id);
397
+ event.message = {
398
+ ...event.message,
399
+ content: [{ type: "text", text: redactedText }],
400
+ };
401
+ }
383
402
  /** Live-index a message for the Memory Engine session search (layer 3c). */
384
403
  _indexMessageForMemory(message) {
385
404
  const memoryEngine = this._resourceLoader.getMemoryEngine();
@@ -469,8 +488,11 @@ Task: given the CURRENT MEMORY and the LATEST CONVERSATION TURN, produce the COM
469
488
  // Track last assistant message for auto-compaction check
470
489
  _lastAssistantMessage = undefined;
471
490
  _lastAutoMemorizeAt = 0;
472
- /** Redacted user-message content pending persistence (vault expansion). */
473
- _pendingUserRedactions = [];
491
+ /** Vault expansion redactions by user-message id (frontend + persistence). */
492
+ _vaultRedactions = new Map();
493
+ _userMessageSeq = 0;
494
+ /** Pending expansion for the user message built right after (prompt flow). */
495
+ _pendingVaultExpansion = null;
474
496
  /** Internal handler for agent events - shared by subscribe and reconnect */
475
497
  _handleAgentEvent = async (event) => {
476
498
  // When a user message starts, check if it's from either queue and remove it BEFORE emitting
@@ -530,15 +552,9 @@ Task: given the CURRENT MEMORY and the LATEST CONVERSATION TURN, produce the COM
530
552
  else if (event.message.role === "user" ||
531
553
  event.message.role === "assistant" ||
532
554
  event.message.role === "toolResult") {
533
- // Regular LLM message - persist as SessionMessageEntry.
534
- // Vault expansion: persist the REDACTED form so secrets expanded
535
- // from the vault never land in the session file.
536
- let toPersist = event.message;
537
- if (event.message.role === "user" && this._pendingUserRedactions.length > 0) {
538
- const redactedText = this._pendingUserRedactions.shift();
539
- toPersist = { ...event.message, content: [{ type: "text", text: redactedText }] };
540
- }
541
- this.sessionManager.appendMessage(toPersist);
555
+ // Regular LLM message - persist as SessionMessageEntry. Vault
556
+ // expansions are already redacted by _applyVaultRedaction above.
557
+ this.sessionManager.appendMessage(event.message);
542
558
  }
543
559
  // Other message types (bashExecution, compactionSummary, branchSummary) are persisted elsewhere
544
560
  // Track assistant message for auto-compaction (checked on agent_end)
@@ -627,6 +643,7 @@ Task: given the CURRENT MEMORY and the LATEST CONVERSATION TURN, produce the COM
627
643
  this._turnIndex++;
628
644
  }
629
645
  else if (event.type === "message_start") {
646
+ this._applyVaultRedaction(event);
630
647
  const extensionEvent = {
631
648
  type: "message_start",
632
649
  message: event.message,
@@ -642,6 +659,7 @@ Task: given the CURRENT MEMORY and the LATEST CONVERSATION TURN, produce the COM
642
659
  await this._extensionRunner.emit(extensionEvent);
643
660
  }
644
661
  else if (event.type === "message_end") {
662
+ this._applyVaultRedaction(event);
645
663
  const extensionEvent = {
646
664
  type: "message_end",
647
665
  message: event.message,
@@ -1027,8 +1045,20 @@ Task: given the CURRENT MEMORY and the LATEST CONVERSATION TURN, produce the COM
1027
1045
  if (vaultManager) {
1028
1046
  const expansion = expandVaultRefs(expandedText, vaultManager);
1029
1047
  if (expansion.expanded.length > 0) {
1030
- this._pendingUserRedactions.push(expandedText);
1048
+ this._pendingVaultExpansion = {
1049
+ id: `usr-vault-${++this._userMessageSeq}`,
1050
+ redactedText: expandedText,
1051
+ };
1031
1052
  expandedText = expansion.text;
1053
+ // Audit the vault usage (names only — never the values).
1054
+ memoryEngine?.recordAudit({
1055
+ action: "vault-use",
1056
+ source: "user",
1057
+ target: "vault",
1058
+ scope: vaultManager.status().vaultPath,
1059
+ ok: true,
1060
+ reason: expansion.expanded.join(", "),
1061
+ });
1032
1062
  }
1033
1063
  }
1034
1064
  // If streaming, queue via steer() or followUp() based on option
@@ -1075,11 +1105,18 @@ Task: given the CURRENT MEMORY and the LATEST CONVERSATION TURN, produce the COM
1075
1105
  if (currentImages) {
1076
1106
  userContent.push(...currentImages);
1077
1107
  }
1078
- messages.push({
1108
+ const vaultExpansion = this._pendingVaultExpansion;
1109
+ this._pendingVaultExpansion = null;
1110
+ const userMessage = {
1111
+ ...(vaultExpansion ? { id: vaultExpansion.id } : {}),
1079
1112
  role: "user",
1080
1113
  content: userContent,
1081
1114
  timestamp: Date.now(),
1082
- });
1115
+ };
1116
+ if (vaultExpansion) {
1117
+ this._vaultRedactions.set(vaultExpansion.id, vaultExpansion.redactedText);
1118
+ }
1119
+ messages.push(userMessage);
1083
1120
  // Inject any pending "nextTurn" messages as context alongside the user message
1084
1121
  for (const msg of this._pendingNextTurnMessages) {
1085
1122
  messages.push(msg);
@@ -1224,11 +1261,18 @@ Task: given the CURRENT MEMORY and the LATEST CONVERSATION TURN, produce the COM
1224
1261
  if (images) {
1225
1262
  content.push(...images);
1226
1263
  }
1227
- this.agent.steer({
1264
+ const vaultExpansion = this._pendingVaultExpansion;
1265
+ this._pendingVaultExpansion = null;
1266
+ const message = {
1267
+ ...(vaultExpansion ? { id: vaultExpansion.id } : {}),
1228
1268
  role: "user",
1229
1269
  content,
1230
1270
  timestamp: Date.now(),
1231
- });
1271
+ };
1272
+ if (vaultExpansion) {
1273
+ this._vaultRedactions.set(vaultExpansion.id, vaultExpansion.redactedText);
1274
+ }
1275
+ this.agent.steer(message);
1232
1276
  }
1233
1277
  /**
1234
1278
  * Internal: Queue a follow-up message (already expanded, no extension command check).
@@ -1240,11 +1284,19 @@ Task: given the CURRENT MEMORY and the LATEST CONVERSATION TURN, produce the COM
1240
1284
  if (images) {
1241
1285
  content.push(...images);
1242
1286
  }
1243
- this.agent.followUp({
1287
+ const vaultExpansion = this._pendingVaultExpansion;
1288
+ this._pendingVaultExpansion = null;
1289
+ const message = {
1290
+ ...(vaultExpansion ? { id: vaultExpansion.id } : {}),
1244
1291
  role: "user",
1245
1292
  content,
1246
1293
  timestamp: Date.now(),
1247
- });
1294
+ };
1295
+ if (vaultExpansion) {
1296
+ this._vaultRedactions.set(vaultExpansion.id, vaultExpansion.redactedText);
1297
+ }
1298
+ this.agent.followUp(message);
1299
+ return;
1248
1300
  }
1249
1301
  /**
1250
1302
  * Throw an error if the text is an extension command.