@finchagentic/mcp 4.6.1 → 4.6.2

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 (58) hide show
  1. package/package.json +5 -6
  2. package/dist/_http-cache.js +0 -96
  3. package/dist/_text-search.js +0 -39
  4. package/dist/agent-loop.js +0 -301
  5. package/dist/annotations.js +0 -122
  6. package/dist/cli.js +0 -1391
  7. package/dist/clink-input.js +0 -15
  8. package/dist/config.js +0 -132
  9. package/dist/convex.js +0 -175
  10. package/dist/dex-pair.js +0 -54
  11. package/dist/enrichment-router.js +0 -315
  12. package/dist/index.js +0 -258
  13. package/dist/llm.js +0 -298
  14. package/dist/local-memory-file.js +0 -150
  15. package/dist/local-memory.js +0 -135
  16. package/dist/local-vault.js +0 -456
  17. package/dist/output-schemas.js +0 -605
  18. package/dist/project.js +0 -36
  19. package/dist/prompts.js +0 -111
  20. package/dist/public-url.js +0 -107
  21. package/dist/resources.js +0 -111
  22. package/dist/server.js +0 -322
  23. package/dist/signal-gate.js +0 -57
  24. package/dist/token-decimals.js +0 -26
  25. package/dist/token-gate.js +0 -88
  26. package/dist/tool-filter.js +0 -53
  27. package/dist/tools/_solidity-scan.js +0 -313
  28. package/dist/tools/agents.js +0 -441
  29. package/dist/tools/automation.js +0 -354
  30. package/dist/tools/base-mcp.js +0 -466
  31. package/dist/tools/base.js +0 -283
  32. package/dist/tools/chronicle.js +0 -268
  33. package/dist/tools/coder.js +0 -94
  34. package/dist/tools/deep-research.js +0 -1421
  35. package/dist/tools/defi.js +0 -292
  36. package/dist/tools/equity.js +0 -372
  37. package/dist/tools/events.js +0 -182
  38. package/dist/tools/github.js +0 -564
  39. package/dist/tools/insider.js +0 -264
  40. package/dist/tools/insight.js +0 -630
  41. package/dist/tools/market.js +0 -555
  42. package/dist/tools/memory.js +0 -1059
  43. package/dist/tools/miroshark.js +0 -350
  44. package/dist/tools/monitor.js +0 -319
  45. package/dist/tools/os.js +0 -236
  46. package/dist/tools/packets.js +0 -296
  47. package/dist/tools/research-chain.js +0 -226
  48. package/dist/tools/research-compare.js +0 -280
  49. package/dist/tools/research.js +0 -188
  50. package/dist/tools/rh-bridge.js +0 -148
  51. package/dist/tools/rh-mcp.js +0 -1448
  52. package/dist/tools/rh-orders.js +0 -556
  53. package/dist/tools/scanner.js +0 -564
  54. package/dist/tools/stake.js +0 -369
  55. package/dist/tools/vault.js +0 -1020
  56. package/dist/tools/wallet.js +0 -200
  57. package/dist/types.js +0 -2
  58. package/dist/wallet.js +0 -372
@@ -1,456 +0,0 @@
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.getLocalVaultConfig = getLocalVaultConfig;
37
- exports.localVaultSave = localVaultSave;
38
- exports.localVaultRead = localVaultRead;
39
- exports.localVaultList = localVaultList;
40
- exports.localVaultSearch = localVaultSearch;
41
- exports.localVaultHistory = localVaultHistory;
42
- exports.localVaultDiff = localVaultDiff;
43
- exports.localVaultExport = localVaultExport;
44
- exports.localVaultPin = localVaultPin;
45
- exports.localVaultDelete = localVaultDelete;
46
- exports.localVaultTag = localVaultTag;
47
- exports.localVaultLink = localVaultLink;
48
- exports.localVaultRelated = localVaultRelated;
49
- exports.localVaultStoreCredential = localVaultStoreCredential;
50
- exports.localVaultGetCredential = localVaultGetCredential;
51
- const fs = __importStar(require("fs"));
52
- const os = __importStar(require("os"));
53
- const path = __importStar(require("path"));
54
- const crypto = __importStar(require("crypto"));
55
- const config_js_1 = require("./config.js");
56
- const _text_search_js_1 = require("./_text-search.js");
57
- // Fully-local, user-owned Noel-Vault backend. Mirrors the two-tier pattern of
58
- // local-memory.ts: when the user opts in (`vaultBackend: "local"`), the vault
59
- // tools store versioned artifacts on the user's own disk under
60
- // ~/.finch/vault/ - no Finch account, no Convex, no network, no cost to
61
- // the platform. Zero runtime dependencies (plain JSON + one content file per
62
- // version), same spirit as codebase-memory-mcp's local-first SQLite store.
63
- //
64
- // Every exported function returns objects shaped like the Convex /vault/*
65
- // responses so tools/vault.ts can swap the data source with a one-line branch
66
- // and reuse all of its existing rendering. Not-found cases THROW an Error whose
67
- // message contains "not found", matching how callConvex surfaces a 404 (the
68
- // vault handlers already catch and format that).
69
- const VAULT_DIR = path.join(os.homedir(), ".finch", "vault");
70
- // Local vault is enabled purely by config - it needs no server, just the
71
- // filesystem. Returns null (→ "use Convex") when the user hasn't opted in.
72
- function getLocalVaultConfig() {
73
- try {
74
- if ((0, config_js_1.readConfig)().vaultBackend !== "local")
75
- return null;
76
- return { dir: VAULT_DIR };
77
- }
78
- catch {
79
- return null;
80
- }
81
- }
82
- function now() { return Date.now(); }
83
- function ensureDir(cfg) {
84
- fs.mkdirSync(path.join(cfg.dir, "data"), { recursive: true });
85
- }
86
- function indexPath(cfg) { return path.join(cfg.dir, "index.json"); }
87
- function readIndex(cfg) {
88
- try {
89
- const raw = fs.readFileSync(indexPath(cfg), "utf8");
90
- const parsed = JSON.parse(raw);
91
- return { entries: parsed.entries ?? {}, links: parsed.links ?? [] };
92
- }
93
- catch {
94
- return { entries: {}, links: [] };
95
- }
96
- }
97
- // Atomic write: temp file + rename, so a crash mid-write can't corrupt the
98
- // manifest every entry depends on.
99
- function writeIndex(cfg, idx) {
100
- ensureDir(cfg);
101
- const tmp = indexPath(cfg) + `.tmp-${process.pid}`;
102
- fs.writeFileSync(tmp, JSON.stringify(idx, null, 2), "utf8");
103
- fs.renameSync(tmp, indexPath(cfg));
104
- }
105
- function keyDir(key) {
106
- return crypto.createHash("sha1").update(key).digest("hex").slice(0, 16);
107
- }
108
- function contentPath(cfg, dir, version) {
109
- return path.join(cfg.dir, "data", dir, `v${version}`);
110
- }
111
- function readContent(cfg, dir, version) {
112
- try {
113
- return fs.readFileSync(contentPath(cfg, dir, version), "utf8");
114
- }
115
- catch {
116
- return "";
117
- }
118
- }
119
- function writeContent(cfg, dir, version, content) {
120
- const d = path.join(cfg.dir, "data", dir);
121
- fs.mkdirSync(d, { recursive: true });
122
- fs.writeFileSync(contentPath(cfg, dir, version), content, "utf8");
123
- }
124
- function slugify(s) {
125
- return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60) || "entry";
126
- }
127
- function notFound(key) {
128
- return new Error(`Vault entry not found: ${key}`);
129
- }
130
- function localVaultSave(cfg, input) {
131
- const idx = readIndex(cfg);
132
- let key = input.key ?? `${input.type}/${slugify(input.title)}`;
133
- // An auto-generated key can collide with an unrelated entry when two
134
- // different titles slugify to the same thing. Only version-in-place when the
135
- // key was explicit or the existing entry is the same title; otherwise
136
- // disambiguate, so a different note never silently gets folded into this one.
137
- if (!input.key && idx.entries[key] && idx.entries[key].title !== input.title) {
138
- let n = 2;
139
- while (idx.entries[`${key}-${n}`])
140
- n++;
141
- key = `${key}-${n}`;
142
- }
143
- // Parity with the hosted vault: [[wikilinks]] become graph edges, #tags are
144
- // pulled into the entry's tag set.
145
- const inlineTags = Array.from(new Set((input.content.match(/(?:^|\s)#([a-z0-9][a-z0-9_-]*)/gi) ?? []).map((t) => t.trim().replace(/^#/, "").toLowerCase())));
146
- const wikilinks = Array.from(new Set((input.content.match(/\[\[([^\]]+)\]\]/g) ?? []).map((w) => w.slice(2, -2).trim())));
147
- const tags = Array.from(new Set([...(input.tags ?? []), ...inlineTags]));
148
- const existing = idx.entries[key];
149
- const ts = now();
150
- if (existing) {
151
- const currentContent = readContent(cfg, existing.dir, existing.currentVersion);
152
- if (currentContent === input.content) {
153
- // No change - don't bump the version (matches hosted "Unchanged").
154
- return { key, version: existing.currentVersion, changed: false, linksCreated: 0, linksMissing: [], inlineTagsExtracted: inlineTags.length };
155
- }
156
- const version = existing.currentVersion + 1;
157
- writeContent(cfg, existing.dir, version, input.content);
158
- existing.currentVersion = version;
159
- existing.title = input.title;
160
- existing.type = input.type;
161
- existing.contentType = input.contentType ?? existing.contentType;
162
- existing.agentId = input.agentId ?? existing.agentId;
163
- existing.tags = Array.from(new Set([...existing.tags, ...tags]));
164
- existing.updatedAt = ts;
165
- existing.metadata = input.metadata ?? existing.metadata;
166
- existing.versions.push({ version, commitMsg: input.commitMsg, agentId: input.agentId, size: Buffer.byteLength(input.content), createdAt: ts });
167
- const linkResult = applyWikilinks(idx, key, wikilinks);
168
- writeIndex(cfg, idx);
169
- return { key, version, changed: true, ...linkResult, inlineTagsExtracted: inlineTags.length };
170
- }
171
- const dir = keyDir(key);
172
- writeContent(cfg, dir, 1, input.content);
173
- idx.entries[key] = {
174
- key, dir, type: input.type, title: input.title, contentType: input.contentType,
175
- agentId: input.agentId, tags, pinned: false, currentVersion: 1,
176
- createdAt: ts, updatedAt: ts, metadata: input.metadata,
177
- versions: [{ version: 1, commitMsg: input.commitMsg, agentId: input.agentId, size: Buffer.byteLength(input.content), createdAt: ts }],
178
- };
179
- const linkResult = applyWikilinks(idx, key, wikilinks);
180
- writeIndex(cfg, idx);
181
- return { key, version: 1, changed: true, ...linkResult, inlineTagsExtracted: inlineTags.length };
182
- }
183
- function applyWikilinks(idx, fromKey, targets) {
184
- let linksCreated = 0;
185
- const linksMissing = [];
186
- for (const toKey of targets) {
187
- if (!idx.entries[toKey]) {
188
- linksMissing.push(toKey);
189
- continue;
190
- }
191
- const dup = idx.links.find((l) => l.fromKey === fromKey && l.toKey === toKey && l.relation === "references");
192
- if (!dup) {
193
- idx.links.push({ fromKey, toKey, relation: "references" });
194
- linksCreated++;
195
- }
196
- }
197
- return { linksCreated, linksMissing };
198
- }
199
- // ── read ──────────────────────────────────────────────────────────────────────
200
- function localVaultRead(cfg, key) {
201
- const idx = readIndex(cfg);
202
- const e = idx.entries[key];
203
- if (!e)
204
- throw notFound(key);
205
- const linkedKeys = idx.links.filter((l) => l.fromKey === key).map((l) => `${l.toKey} (${l.relation})`);
206
- const backlinks = idx.links
207
- .filter((l) => l.toKey === key)
208
- .map((l) => ({ key: l.fromKey, title: idx.entries[l.fromKey]?.title }));
209
- return {
210
- key: e.key, title: e.title, type: e.type, version: e.currentVersion,
211
- size: e.versions[e.versions.length - 1]?.size, tags: e.tags, isPinned: e.pinned,
212
- agentId: e.agentId, updatedAt: e.updatedAt, content: readContent(cfg, e.dir, e.currentVersion),
213
- linkedKeys, backlinks,
214
- };
215
- }
216
- // ── list ──────────────────────────────────────────────────────────────────────
217
- function localVaultList(cfg, opts) {
218
- const idx = readIndex(cfg);
219
- let rows = Object.values(idx.entries).filter((e) => e.type !== "credential");
220
- if (opts.type)
221
- rows = rows.filter((e) => e.type === opts.type);
222
- if (opts.agentId)
223
- rows = rows.filter((e) => e.agentId === opts.agentId);
224
- if (opts.pinned !== undefined)
225
- rows = rows.filter((e) => e.pinned === opts.pinned);
226
- rows.sort((a, b) => (Number(b.pinned) - Number(a.pinned)) || (b.updatedAt - a.updatedAt));
227
- const entries = rows.slice(0, opts.limit ?? 50).map((e) => ({
228
- key: e.key, title: e.title, type: e.type, version: e.currentVersion,
229
- size: e.versions[e.versions.length - 1]?.size, updatedAt: e.updatedAt, isPinned: e.pinned,
230
- }));
231
- return { entries };
232
- }
233
- // ── search (full-text, local) ─────────────────────────────────────────────────
234
- function localVaultSearch(cfg, query, opts) {
235
- const idx = readIndex(cfg);
236
- const terms = (0, _text_search_js_1.meaningfulTerms)(query);
237
- const scored = [];
238
- if (terms.length === 0)
239
- return { results: [] };
240
- for (const e of Object.values(idx.entries)) {
241
- if (e.type === "credential")
242
- continue;
243
- if (opts.type && e.type !== opts.type)
244
- continue;
245
- const content = readContent(cfg, e.dir, e.currentVersion);
246
- const hay = `${e.title}\n${e.tags.join(" ")}\n${content}`.toLowerCase();
247
- let score = 0;
248
- for (const t of terms) {
249
- if (e.title.toLowerCase().includes(t))
250
- score += 3;
251
- if (e.tags.some((tag) => tag.toLowerCase().includes(t)))
252
- score += 2;
253
- score += Math.min((0, _text_search_js_1.wordOccurrences)(hay, t), 5);
254
- }
255
- if (score > 0) {
256
- const firstHit = terms.map((t) => content.toLowerCase().indexOf(t)).filter((i) => i >= 0).sort((a, b) => a - b)[0] ?? 0;
257
- scored.push({ e, score, preview: content.slice(Math.max(0, firstHit - 20), firstHit + 180).replace(/\n/g, " ") });
258
- }
259
- }
260
- scored.sort((a, b) => b.score - a.score);
261
- const results = scored.slice(0, opts.limit ?? 20).map(({ e, preview }) => ({
262
- key: e.key, title: e.title, type: e.type, version: e.currentVersion, preview,
263
- }));
264
- return { results };
265
- }
266
- // ── history ───────────────────────────────────────────────────────────────────
267
- function localVaultHistory(cfg, key) {
268
- const idx = readIndex(cfg);
269
- const e = idx.entries[key];
270
- if (!e)
271
- throw notFound(key);
272
- return {
273
- key: e.key, title: e.title, currentVersion: e.currentVersion,
274
- history: [...e.versions].sort((a, b) => b.version - a.version),
275
- };
276
- }
277
- // ── diff ──────────────────────────────────────────────────────────────────────
278
- function lineDiff(a, b) {
279
- const al = a.split("\n"), bl = b.split("\n");
280
- const m = al.length, n = bl.length;
281
- // LCS length table (bottom-up) - fine for the artifact sizes a vault holds.
282
- const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
283
- for (let i = m - 1; i >= 0; i--)
284
- for (let j = n - 1; j >= 0; j--)
285
- dp[i][j] = al[i] === bl[j] ? dp[i + 1][j + 1] + 1 : Math.max(dp[i + 1][j], dp[i][j + 1]);
286
- const out = [];
287
- let i = 0, j = 0;
288
- while (i < m && j < n) {
289
- if (al[i] === bl[j]) {
290
- out.push(` ${al[i]}`);
291
- i++;
292
- j++;
293
- }
294
- else if (dp[i + 1][j] >= dp[i][j + 1]) {
295
- out.push(`- ${al[i]}`);
296
- i++;
297
- }
298
- else {
299
- out.push(`+ ${bl[j]}`);
300
- j++;
301
- }
302
- }
303
- while (i < m)
304
- out.push(`- ${al[i++]}`);
305
- while (j < n)
306
- out.push(`+ ${bl[j++]}`);
307
- return out.join("\n");
308
- }
309
- function localVaultDiff(cfg, key, fromVersion, toVersion) {
310
- const idx = readIndex(cfg);
311
- const e = idx.entries[key];
312
- if (!e)
313
- throw notFound(key);
314
- const has = (v) => e.versions.some((x) => x.version === v);
315
- if (!has(fromVersion) || !has(toVersion)) {
316
- throw new Error(`version range v${fromVersion}->v${toVersion} invalid for ${key}`);
317
- }
318
- const from = readContent(cfg, e.dir, fromVersion);
319
- const to = readContent(cfg, e.dir, toVersion);
320
- // The LCS diff is O(m*n) in memory - guard against a pathologically large
321
- // multi-line entry blowing up the process instead of returning a diff.
322
- const la = from.split("\n").length, lb = to.split("\n").length;
323
- if (la * lb > 4000000) {
324
- return { key, diff: `(v${fromVersion}: ${la} lines · v${toVersion}: ${lb} lines — too large for a line-by-line diff)` };
325
- }
326
- return { key, diff: lineDiff(from, to) };
327
- }
328
- // ── export ────────────────────────────────────────────────────────────────────
329
- function localVaultExport(cfg, type) {
330
- const idx = readIndex(cfg);
331
- let rows = Object.values(idx.entries).filter((e) => e.type !== "credential");
332
- if (type)
333
- rows = rows.filter((e) => e.type === type);
334
- const entries = rows.map((e) => ({
335
- key: e.key, title: e.title, type: e.type, version: e.currentVersion,
336
- content: readContent(cfg, e.dir, e.currentVersion),
337
- }));
338
- return { exportedAt: now(), totalEntries: entries.length, entries };
339
- }
340
- // ── pin / delete / tag ────────────────────────────────────────────────────────
341
- function localVaultPin(cfg, key, pinned) {
342
- const idx = readIndex(cfg);
343
- const e = idx.entries[key];
344
- if (!e)
345
- throw notFound(key);
346
- e.pinned = pinned;
347
- writeIndex(cfg, idx);
348
- return { pinned };
349
- }
350
- function localVaultDelete(cfg, key) {
351
- const idx = readIndex(cfg);
352
- const e = idx.entries[key];
353
- if (!e)
354
- throw notFound(key);
355
- const versionsRemoved = e.versions.length;
356
- try {
357
- fs.rmSync(path.join(cfg.dir, "data", e.dir), { recursive: true, force: true });
358
- }
359
- catch { /* best effort */ }
360
- delete idx.entries[key];
361
- idx.links = idx.links.filter((l) => l.fromKey !== key && l.toKey !== key);
362
- writeIndex(cfg, idx);
363
- return { versionsRemoved };
364
- }
365
- function localVaultTag(cfg, key, tags, replace) {
366
- const idx = readIndex(cfg);
367
- const e = idx.entries[key];
368
- if (!e)
369
- throw notFound(key);
370
- e.tags = replace ? Array.from(new Set(tags)) : Array.from(new Set([...e.tags, ...tags]));
371
- e.updatedAt = now();
372
- writeIndex(cfg, idx);
373
- return { tags: e.tags };
374
- }
375
- // ── link / related ────────────────────────────────────────────────────────────
376
- function localVaultLink(cfg, fromKey, toKey, relation) {
377
- const idx = readIndex(cfg);
378
- if (!idx.entries[fromKey])
379
- throw notFound(fromKey);
380
- if (!idx.entries[toKey])
381
- throw notFound(toKey);
382
- const existing = idx.links.find((l) => l.fromKey === fromKey && l.toKey === toKey);
383
- if (existing) {
384
- existing.relation = relation;
385
- writeIndex(cfg, idx);
386
- return { updated: true };
387
- }
388
- idx.links.push({ fromKey, toKey, relation });
389
- writeIndex(cfg, idx);
390
- return { updated: false };
391
- }
392
- function localVaultRelated(cfg, key, relation) {
393
- const idx = readIndex(cfg);
394
- if (!idx.entries[key])
395
- throw notFound(key);
396
- const related = [];
397
- for (const l of idx.links) {
398
- if (relation && l.relation !== relation)
399
- continue;
400
- if (l.fromKey === key) {
401
- const t = idx.entries[l.toKey];
402
- if (t)
403
- related.push({ key: l.toKey, title: t.title, type: t.type, relation: l.relation, direction: "→" });
404
- }
405
- else if (l.toKey === key) {
406
- const f = idx.entries[l.fromKey];
407
- if (f)
408
- related.push({ key: l.fromKey, title: f.title, type: f.type, relation: l.relation, direction: "←" });
409
- }
410
- }
411
- return { key, related };
412
- }
413
- // ── credentials (AES-256-GCM, key at ~/.finch/vault/.credkey, 0600) ─────────
414
- function credKeyPath(cfg) { return path.join(cfg.dir, ".credkey"); }
415
- function credStorePath(cfg) { return path.join(cfg.dir, "credentials.json"); }
416
- function getCredKey(cfg) {
417
- ensureDir(cfg);
418
- const p = credKeyPath(cfg);
419
- try {
420
- return Buffer.from(fs.readFileSync(p, "utf8").trim(), "hex");
421
- }
422
- catch {
423
- const key = crypto.randomBytes(32);
424
- fs.writeFileSync(p, key.toString("hex"), { mode: 0o600 });
425
- return key;
426
- }
427
- }
428
- function readCredStore(cfg) {
429
- try {
430
- return JSON.parse(fs.readFileSync(credStorePath(cfg), "utf8"));
431
- }
432
- catch {
433
- return {};
434
- }
435
- }
436
- function localVaultStoreCredential(cfg, name, value, description) {
437
- const key = getCredKey(cfg);
438
- const iv = crypto.randomBytes(12);
439
- const cipher = crypto.createCipheriv("aes-256-gcm", key, iv);
440
- const enc = Buffer.concat([cipher.update(value, "utf8"), cipher.final()]);
441
- const store = readCredStore(cfg);
442
- store[name] = { iv: iv.toString("hex"), tag: cipher.getAuthTag().toString("hex"), data: enc.toString("hex"), description, storedAt: new Date(now()).toUTCString() };
443
- fs.writeFileSync(credStorePath(cfg), JSON.stringify(store, null, 2), { mode: 0o600 });
444
- return { name, key: `credential/${name}` };
445
- }
446
- function localVaultGetCredential(cfg, name) {
447
- const store = readCredStore(cfg);
448
- const rec = store[name];
449
- if (!rec)
450
- throw notFound(`credential ${name}`);
451
- const key = getCredKey(cfg);
452
- const decipher = crypto.createDecipheriv("aes-256-gcm", key, Buffer.from(rec.iv, "hex"));
453
- decipher.setAuthTag(Buffer.from(rec.tag, "hex"));
454
- const dec = Buffer.concat([decipher.update(Buffer.from(rec.data, "hex")), decipher.final()]).toString("utf8");
455
- return { name, value: dec, description: rec.description, storedAt: rec.storedAt };
456
- }