@mnemopay/sdk 0.2.0 → 0.4.0
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.
- package/README.md +2 -2
- package/dist/fraud-ml.d.ts +174 -0
- package/dist/fraud-ml.d.ts.map +1 -0
- package/dist/fraud-ml.js +544 -0
- package/dist/fraud-ml.js.map +1 -0
- package/dist/fraud.d.ts +212 -0
- package/dist/fraud.d.ts.map +1 -0
- package/dist/fraud.js +633 -0
- package/dist/fraud.js.map +1 -0
- package/dist/index.d.ts +84 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +381 -18
- package/dist/index.js.map +1 -1
- package/dist/langgraph/tools.d.ts +2 -2
- package/dist/langgraph/tools.d.ts.map +1 -1
- package/dist/langgraph/tools.js +13 -1
- package/dist/langgraph/tools.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +117 -4
- package/dist/mcp/server.js.map +1 -1
- package/package.json +6 -4
package/dist/index.js
CHANGED
|
@@ -11,10 +11,12 @@
|
|
|
11
11
|
* MnemoPay.create({...}) → Postgres + Redis (production)
|
|
12
12
|
*/
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.l2Normalize = exports.localEmbed = exports.cosineSimilarity = exports.RecallEngine = exports.MnemoPay = exports.MnemoPayLite = void 0;
|
|
14
|
+
exports.BehaviorProfile = exports.TransactionGraph = exports.IsolationForest = exports.DEFAULT_RATE_LIMIT = exports.DEFAULT_FRAUD_CONFIG = exports.RateLimiter = exports.FraudGuard = exports.l2Normalize = exports.localEmbed = exports.cosineSimilarity = exports.RecallEngine = exports.MnemoPay = exports.MnemoPayLite = void 0;
|
|
15
15
|
exports.autoScore = autoScore;
|
|
16
16
|
exports.computeScore = computeScore;
|
|
17
|
+
exports.reputationTier = reputationTier;
|
|
17
18
|
const engine_js_1 = require("./recall/engine.js");
|
|
19
|
+
const fraud_js_1 = require("./fraud.js");
|
|
18
20
|
class EventEmitter {
|
|
19
21
|
_events = new Map();
|
|
20
22
|
on(event, fn) {
|
|
@@ -50,6 +52,17 @@ class EventEmitter {
|
|
|
50
52
|
function randomUUID() {
|
|
51
53
|
return crypto.randomUUID();
|
|
52
54
|
}
|
|
55
|
+
function reputationTier(score) {
|
|
56
|
+
if (score >= 0.9)
|
|
57
|
+
return "exemplary";
|
|
58
|
+
if (score >= 0.7)
|
|
59
|
+
return "trusted";
|
|
60
|
+
if (score >= 0.4)
|
|
61
|
+
return "established";
|
|
62
|
+
if (score >= 0.2)
|
|
63
|
+
return "newcomer";
|
|
64
|
+
return "untrusted";
|
|
65
|
+
}
|
|
53
66
|
// ─── Auto-scoring keywords ─────────────────────────────────────────────────
|
|
54
67
|
const IMPORTANCE_PATTERNS = [
|
|
55
68
|
{ pattern: /\b(error|fail|crash|critical|broken|bug)\b/i, boost: 0.20 },
|
|
@@ -87,15 +100,123 @@ class MnemoPayLite extends EventEmitter {
|
|
|
87
100
|
_wallet = 0;
|
|
88
101
|
_reputation = 0.5;
|
|
89
102
|
recallEngine;
|
|
90
|
-
|
|
103
|
+
_createdAt = new Date();
|
|
104
|
+
x402;
|
|
105
|
+
persistPath;
|
|
106
|
+
persistTimer;
|
|
107
|
+
/** Fraud detection, rate limiting, dispute resolution, and platform fee */
|
|
108
|
+
fraud;
|
|
109
|
+
constructor(agentId, decay = 0.05, debug = false, recallConfig, fraudConfig) {
|
|
91
110
|
super();
|
|
92
111
|
this.agentId = agentId;
|
|
93
112
|
this.decay = decay;
|
|
94
113
|
this.debugMode = debug;
|
|
95
114
|
this.recallEngine = new engine_js_1.RecallEngine(recallConfig);
|
|
96
|
-
this.
|
|
115
|
+
this.fraud = new fraud_js_1.FraudGuard(fraudConfig);
|
|
116
|
+
// Auto-detect persistence: MNEMOPAY_PERSIST_DIR env var or explicit enablePersistence()
|
|
117
|
+
const persistDir = typeof process !== "undefined" ? process.env?.MNEMOPAY_PERSIST_DIR : undefined;
|
|
118
|
+
if (persistDir) {
|
|
119
|
+
this.enablePersistence(persistDir);
|
|
120
|
+
}
|
|
121
|
+
this.log(`MnemoPayLite initialized (${this.persistPath ? "persistent" : "in-memory"} mode, recall: ${this.recallEngine.strategy})`);
|
|
97
122
|
setTimeout(() => this.emit("ready"), 0);
|
|
98
123
|
}
|
|
124
|
+
// ── Persistence ────────────────────────────────────────────────────────
|
|
125
|
+
enablePersistence(dir) {
|
|
126
|
+
try {
|
|
127
|
+
const fs = require("fs");
|
|
128
|
+
const path = require("path");
|
|
129
|
+
if (!fs.existsSync(dir))
|
|
130
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
131
|
+
this.persistPath = path.join(dir, `${this.agentId}.json`);
|
|
132
|
+
this._loadFromDisk();
|
|
133
|
+
// Auto-save every 30 seconds
|
|
134
|
+
this.persistTimer = setInterval(() => this._saveToDisk(), 30_000);
|
|
135
|
+
this.log(`Persistence enabled: ${this.persistPath}`);
|
|
136
|
+
}
|
|
137
|
+
catch (e) {
|
|
138
|
+
this.log(`Persistence unavailable (browser?): ${e}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
_loadFromDisk() {
|
|
142
|
+
if (!this.persistPath)
|
|
143
|
+
return;
|
|
144
|
+
try {
|
|
145
|
+
const fs = require("fs");
|
|
146
|
+
if (!fs.existsSync(this.persistPath))
|
|
147
|
+
return;
|
|
148
|
+
const raw = JSON.parse(fs.readFileSync(this.persistPath, "utf-8"));
|
|
149
|
+
// Restore memories
|
|
150
|
+
if (raw.memories) {
|
|
151
|
+
for (const m of raw.memories) {
|
|
152
|
+
m.createdAt = new Date(m.createdAt);
|
|
153
|
+
m.lastAccessed = new Date(m.lastAccessed);
|
|
154
|
+
this.memories.set(m.id, m);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Restore transactions
|
|
158
|
+
if (raw.transactions) {
|
|
159
|
+
for (const t of raw.transactions) {
|
|
160
|
+
t.createdAt = new Date(t.createdAt);
|
|
161
|
+
if (t.completedAt)
|
|
162
|
+
t.completedAt = new Date(t.completedAt);
|
|
163
|
+
this.transactions.set(t.id, t);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// Restore state
|
|
167
|
+
if (raw.wallet !== undefined)
|
|
168
|
+
this._wallet = raw.wallet;
|
|
169
|
+
if (raw.reputation !== undefined)
|
|
170
|
+
this._reputation = raw.reputation;
|
|
171
|
+
if (raw.createdAt)
|
|
172
|
+
this._createdAt = new Date(raw.createdAt);
|
|
173
|
+
if (raw.auditLog) {
|
|
174
|
+
this.auditLog = raw.auditLog.map((e) => ({ ...e, createdAt: new Date(e.createdAt) }));
|
|
175
|
+
}
|
|
176
|
+
// Restore fraud guard state
|
|
177
|
+
if (raw.fraudGuard) {
|
|
178
|
+
try {
|
|
179
|
+
const restored = fraud_js_1.FraudGuard.deserialize(raw.fraudGuard, this.fraud.config);
|
|
180
|
+
// Copy restored state into existing guard (preserve config from constructor)
|
|
181
|
+
Object.assign(this.fraud, {
|
|
182
|
+
// Only copy internal state, not config
|
|
183
|
+
});
|
|
184
|
+
// Re-create fraud guard with restored data
|
|
185
|
+
const restoredGuard = fraud_js_1.FraudGuard.deserialize(raw.fraudGuard, this.fraud.config);
|
|
186
|
+
this.fraud = restoredGuard;
|
|
187
|
+
}
|
|
188
|
+
catch (e) {
|
|
189
|
+
this.log(`Failed to restore fraud guard state: ${e}`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
this.log(`Loaded ${this.memories.size} memories, ${this.transactions.size} transactions from disk`);
|
|
193
|
+
}
|
|
194
|
+
catch (e) {
|
|
195
|
+
this.log(`Failed to load persisted data: ${e}`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
_saveToDisk() {
|
|
199
|
+
if (!this.persistPath)
|
|
200
|
+
return;
|
|
201
|
+
try {
|
|
202
|
+
const fs = require("fs");
|
|
203
|
+
const data = JSON.stringify({
|
|
204
|
+
agentId: this.agentId,
|
|
205
|
+
wallet: this._wallet,
|
|
206
|
+
reputation: this._reputation,
|
|
207
|
+
createdAt: this._createdAt.toISOString(),
|
|
208
|
+
memories: Array.from(this.memories.values()),
|
|
209
|
+
transactions: Array.from(this.transactions.values()),
|
|
210
|
+
auditLog: this.auditLog.slice(-500), // Keep last 500 entries
|
|
211
|
+
fraudGuard: this.fraud.serialize(),
|
|
212
|
+
savedAt: new Date().toISOString(),
|
|
213
|
+
});
|
|
214
|
+
fs.writeFileSync(this.persistPath, data, "utf-8");
|
|
215
|
+
}
|
|
216
|
+
catch (e) {
|
|
217
|
+
this.log(`Failed to persist data: ${e}`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
99
220
|
log(msg) {
|
|
100
221
|
if (this.debugMode)
|
|
101
222
|
console.log(`[mnemopay:${this.agentId}] ${msg}`);
|
|
@@ -131,6 +252,7 @@ class MnemoPayLite extends EventEmitter {
|
|
|
131
252
|
await this.recallEngine.embed(mem.id, content);
|
|
132
253
|
}
|
|
133
254
|
this.audit("memory:stored", { id: mem.id, content: content.slice(0, 100), importance: mem.importance });
|
|
255
|
+
this._saveToDisk();
|
|
134
256
|
this.emit("memory:stored", { id: mem.id, content, importance: mem.importance });
|
|
135
257
|
this.log(`Stored memory: "${content.slice(0, 60)}..." (importance: ${mem.importance.toFixed(2)})`);
|
|
136
258
|
return mem.id;
|
|
@@ -173,6 +295,7 @@ class MnemoPayLite extends EventEmitter {
|
|
|
173
295
|
if (existed) {
|
|
174
296
|
this.recallEngine.remove(id);
|
|
175
297
|
this.audit("memory:deleted", { id });
|
|
298
|
+
this._saveToDisk();
|
|
176
299
|
this.log(`Forgot memory: ${id}`);
|
|
177
300
|
}
|
|
178
301
|
return existed;
|
|
@@ -184,6 +307,7 @@ class MnemoPayLite extends EventEmitter {
|
|
|
184
307
|
mem.importance = Math.min(mem.importance + boost, 1.0);
|
|
185
308
|
mem.lastAccessed = new Date();
|
|
186
309
|
this.audit("memory:reinforced", { id, boost, newImportance: mem.importance });
|
|
310
|
+
this._saveToDisk();
|
|
187
311
|
this.log(`Reinforced memory ${id} by +${boost} → ${mem.importance.toFixed(2)}`);
|
|
188
312
|
}
|
|
189
313
|
async consolidate() {
|
|
@@ -201,11 +325,12 @@ class MnemoPayLite extends EventEmitter {
|
|
|
201
325
|
// Clean up embedding cache for pruned memories
|
|
202
326
|
this.recallEngine.removeBatch(prunedIds);
|
|
203
327
|
this.audit("memory:consolidated", { pruned });
|
|
328
|
+
this._saveToDisk();
|
|
204
329
|
this.log(`Consolidated: pruned ${pruned} stale memories`);
|
|
205
330
|
return pruned;
|
|
206
331
|
}
|
|
207
332
|
// ── Payment Methods ─────────────────────────────────────────────────────
|
|
208
|
-
async charge(amount, reason) {
|
|
333
|
+
async charge(amount, reason, ctx) {
|
|
209
334
|
if (amount <= 0)
|
|
210
335
|
throw new Error("Amount must be positive");
|
|
211
336
|
const maxCharge = 500 * this._reputation;
|
|
@@ -213,6 +338,21 @@ class MnemoPayLite extends EventEmitter {
|
|
|
213
338
|
throw new Error(`Amount $${amount.toFixed(2)} exceeds reputation ceiling $${maxCharge.toFixed(2)} ` +
|
|
214
339
|
`(reputation: ${this._reputation.toFixed(2)}, max: $${maxCharge.toFixed(2)})`);
|
|
215
340
|
}
|
|
341
|
+
// ── Fraud check ──────────────────────────────────────────────────────
|
|
342
|
+
const pendingCount = Array.from(this.transactions.values()).filter((t) => t.status === "pending").length;
|
|
343
|
+
const risk = this.fraud.assessCharge(this.agentId, amount, this._reputation, this._createdAt, pendingCount, ctx);
|
|
344
|
+
if (!risk.allowed) {
|
|
345
|
+
this.audit("fraud:blocked", { amount, reason, riskScore: risk.score, signals: risk.signals.map((s) => s.type) });
|
|
346
|
+
this._saveToDisk();
|
|
347
|
+
this.emit("fraud:blocked", { amount, risk });
|
|
348
|
+
throw new Error(risk.reason || `Charge blocked: risk score ${risk.score}`);
|
|
349
|
+
}
|
|
350
|
+
if (risk.flagged) {
|
|
351
|
+
this.audit("fraud:flagged", { amount, reason, riskScore: risk.score, signals: risk.signals.map((s) => s.type) });
|
|
352
|
+
this.emit("fraud:flagged", { amount, risk });
|
|
353
|
+
}
|
|
354
|
+
// Record charge for velocity tracking
|
|
355
|
+
this.fraud.recordCharge(this.agentId, amount, ctx);
|
|
216
356
|
const tx = {
|
|
217
357
|
id: randomUUID(),
|
|
218
358
|
agentId: this.agentId,
|
|
@@ -220,11 +360,13 @@ class MnemoPayLite extends EventEmitter {
|
|
|
220
360
|
reason,
|
|
221
361
|
status: "pending",
|
|
222
362
|
createdAt: new Date(),
|
|
363
|
+
riskScore: risk.score,
|
|
223
364
|
};
|
|
224
365
|
this.transactions.set(tx.id, tx);
|
|
225
|
-
this.audit("payment:pending", { id: tx.id, amount, reason });
|
|
366
|
+
this.audit("payment:pending", { id: tx.id, amount, reason, riskScore: risk.score });
|
|
367
|
+
this._saveToDisk();
|
|
226
368
|
this.emit("payment:pending", { id: tx.id, amount, reason });
|
|
227
|
-
this.log(`Charge created: $${amount.toFixed(2)} for "${reason}" (pending)`);
|
|
369
|
+
this.log(`Charge created: $${amount.toFixed(2)} for "${reason}" (pending, risk: ${risk.score})`);
|
|
228
370
|
return { ...tx };
|
|
229
371
|
}
|
|
230
372
|
async settle(txId) {
|
|
@@ -233,13 +375,17 @@ class MnemoPayLite extends EventEmitter {
|
|
|
233
375
|
throw new Error(`Transaction ${txId} not found`);
|
|
234
376
|
if (tx.status !== "pending")
|
|
235
377
|
throw new Error(`Transaction ${txId} is ${tx.status}, not pending`);
|
|
236
|
-
// 1.
|
|
378
|
+
// 1. Apply platform fee
|
|
379
|
+
const fee = this.fraud.applyPlatformFee(tx.id, this.agentId, tx.amount);
|
|
380
|
+
tx.platformFee = fee.feeAmount;
|
|
381
|
+
tx.netAmount = fee.netAmount;
|
|
382
|
+
// 2. Move NET funds to wallet (after fee)
|
|
237
383
|
tx.status = "completed";
|
|
238
384
|
tx.completedAt = new Date();
|
|
239
|
-
this._wallet +=
|
|
240
|
-
//
|
|
385
|
+
this._wallet += fee.netAmount;
|
|
386
|
+
// 3. Boost reputation
|
|
241
387
|
this._reputation = Math.min(this._reputation + 0.01, 1.0);
|
|
242
|
-
//
|
|
388
|
+
// 4. Reinforce recently-accessed memories (feedback loop)
|
|
243
389
|
const oneHourAgo = Date.now() - 3_600_000;
|
|
244
390
|
let reinforced = 0;
|
|
245
391
|
for (const mem of this.memories.values()) {
|
|
@@ -248,10 +394,14 @@ class MnemoPayLite extends EventEmitter {
|
|
|
248
394
|
reinforced++;
|
|
249
395
|
}
|
|
250
396
|
}
|
|
251
|
-
this.audit("payment:completed", {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
397
|
+
this.audit("payment:completed", {
|
|
398
|
+
id: tx.id, grossAmount: tx.amount, platformFee: fee.feeAmount,
|
|
399
|
+
netAmount: fee.netAmount, feeRate: fee.feeRate, reinforcedMemories: reinforced,
|
|
400
|
+
});
|
|
401
|
+
this._saveToDisk();
|
|
402
|
+
this.emit("payment:completed", { id: tx.id, amount: fee.netAmount, fee: fee.feeAmount });
|
|
403
|
+
this.log(`Settled $${tx.amount.toFixed(2)} (fee: $${fee.feeAmount.toFixed(2)}, net: $${fee.netAmount.toFixed(2)}) → ` +
|
|
404
|
+
`wallet: $${this._wallet.toFixed(2)}, reputation: ${this._reputation.toFixed(2)}, reinforced: ${reinforced} memories`);
|
|
255
405
|
return { ...tx };
|
|
256
406
|
}
|
|
257
407
|
async refund(txId) {
|
|
@@ -261,15 +411,58 @@ class MnemoPayLite extends EventEmitter {
|
|
|
261
411
|
if (tx.status === "refunded")
|
|
262
412
|
throw new Error(`Transaction ${txId} already refunded`);
|
|
263
413
|
if (tx.status === "completed") {
|
|
264
|
-
|
|
414
|
+
// Refund the net amount (platform fee is NOT refunded)
|
|
415
|
+
const refundAmount = tx.netAmount ?? tx.amount;
|
|
416
|
+
this._wallet = Math.max(this._wallet - refundAmount, 0);
|
|
265
417
|
this._reputation = Math.max(this._reputation - 0.05, 0);
|
|
266
418
|
}
|
|
267
419
|
tx.status = "refunded";
|
|
268
|
-
this.audit("payment:refunded", { id: tx.id, amount: tx.amount });
|
|
420
|
+
this.audit("payment:refunded", { id: tx.id, amount: tx.amount, netRefunded: tx.netAmount ?? tx.amount });
|
|
421
|
+
this._saveToDisk();
|
|
269
422
|
this.emit("payment:refunded", { id: tx.id });
|
|
270
423
|
this.log(`Refunded $${tx.amount.toFixed(2)} → reputation: ${this._reputation.toFixed(2)}`);
|
|
271
424
|
return { ...tx };
|
|
272
425
|
}
|
|
426
|
+
// ── Dispute Resolution ─────────────────────────────────────────────────
|
|
427
|
+
async dispute(txId, reason, evidence) {
|
|
428
|
+
const tx = this.transactions.get(txId);
|
|
429
|
+
if (!tx)
|
|
430
|
+
throw new Error(`Transaction ${txId} not found`);
|
|
431
|
+
if (tx.status !== "completed")
|
|
432
|
+
throw new Error(`Can only dispute completed transactions (current: ${tx.status})`);
|
|
433
|
+
if (!tx.completedAt)
|
|
434
|
+
throw new Error(`Transaction ${txId} has no completion date`);
|
|
435
|
+
const d = this.fraud.fileDispute(txId, this.agentId, reason, tx.completedAt, evidence);
|
|
436
|
+
tx.status = "disputed";
|
|
437
|
+
this.audit("payment:disputed", { id: tx.id, disputeId: d.id, reason });
|
|
438
|
+
this._saveToDisk();
|
|
439
|
+
this.emit("payment:disputed", { txId, disputeId: d.id, reason });
|
|
440
|
+
this.log(`Dispute filed for tx ${txId}: ${reason}`);
|
|
441
|
+
return d;
|
|
442
|
+
}
|
|
443
|
+
async resolveDispute(disputeId, outcome) {
|
|
444
|
+
const d = this.fraud.resolveDispute(disputeId, outcome);
|
|
445
|
+
if (outcome === "refund") {
|
|
446
|
+
const tx = this.transactions.get(d.txId);
|
|
447
|
+
if (tx && tx.status === "disputed") {
|
|
448
|
+
const refundAmount = tx.netAmount ?? tx.amount;
|
|
449
|
+
this._wallet = Math.max(this._wallet - refundAmount, 0);
|
|
450
|
+
this._reputation = Math.max(this._reputation - 0.05, 0);
|
|
451
|
+
tx.status = "refunded";
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
else {
|
|
455
|
+
const tx = this.transactions.get(d.txId);
|
|
456
|
+
if (tx && tx.status === "disputed") {
|
|
457
|
+
tx.status = "completed"; // Restore to completed
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
this.audit("dispute:resolved", { disputeId, outcome, txId: d.txId });
|
|
461
|
+
this._saveToDisk();
|
|
462
|
+
this.emit("dispute:resolved", { disputeId, outcome });
|
|
463
|
+
this.log(`Dispute ${disputeId} resolved: ${outcome}`);
|
|
464
|
+
return d;
|
|
465
|
+
}
|
|
273
466
|
async balance() {
|
|
274
467
|
return { wallet: this._wallet, reputation: this._reputation };
|
|
275
468
|
}
|
|
@@ -292,8 +485,93 @@ class MnemoPayLite extends EventEmitter {
|
|
|
292
485
|
all.reverse();
|
|
293
486
|
return all.slice(0, limit).map((tx) => ({ ...tx }));
|
|
294
487
|
}
|
|
488
|
+
// ── Reputation ──────────────────────────────────────────────────────────
|
|
489
|
+
async reputation() {
|
|
490
|
+
const txs = Array.from(this.transactions.values());
|
|
491
|
+
const settled = txs.filter((t) => t.status === "completed");
|
|
492
|
+
const refunded = txs.filter((t) => t.status === "refunded");
|
|
493
|
+
const totalCompleted = settled.length + refunded.length;
|
|
494
|
+
const settlementRate = totalCompleted > 0 ? settled.length / totalCompleted : 0;
|
|
495
|
+
const totalValueSettled = settled.reduce((sum, t) => sum + t.amount, 0);
|
|
496
|
+
const mems = Array.from(this.memories.values());
|
|
497
|
+
const avgImportance = mems.length > 0
|
|
498
|
+
? mems.reduce((sum, m) => sum + m.importance, 0) / mems.length
|
|
499
|
+
: 0;
|
|
500
|
+
const ageHours = (Date.now() - this._createdAt.getTime()) / 3_600_000;
|
|
501
|
+
const report = {
|
|
502
|
+
agentId: this.agentId,
|
|
503
|
+
score: this._reputation,
|
|
504
|
+
tier: reputationTier(this._reputation),
|
|
505
|
+
settledCount: settled.length,
|
|
506
|
+
refundCount: refunded.length,
|
|
507
|
+
settlementRate,
|
|
508
|
+
totalValueSettled,
|
|
509
|
+
memoriesCount: this.memories.size,
|
|
510
|
+
avgMemoryImportance: Math.round(avgImportance * 100) / 100,
|
|
511
|
+
ageHours: Math.round(ageHours * 10) / 10,
|
|
512
|
+
generatedAt: new Date(),
|
|
513
|
+
};
|
|
514
|
+
this.log(`Reputation: ${report.tier} (${report.score.toFixed(2)}), ${report.settledCount} settled, rate: ${(report.settlementRate * 100).toFixed(0)}%`);
|
|
515
|
+
return report;
|
|
516
|
+
}
|
|
517
|
+
// ── A2A Agent Card ─────────────────────────────────────────────────────
|
|
518
|
+
agentCard(url, contact) {
|
|
519
|
+
return {
|
|
520
|
+
name: `MnemoPay Agent (${this.agentId})`,
|
|
521
|
+
description: "AI agent with persistent cognitive memory and micropayment capabilities via MnemoPay protocol.",
|
|
522
|
+
url,
|
|
523
|
+
version: "0.2.0",
|
|
524
|
+
capabilities: {
|
|
525
|
+
memory: true,
|
|
526
|
+
payments: true,
|
|
527
|
+
reputation: true,
|
|
528
|
+
},
|
|
529
|
+
protocols: ["mcp", "a2a"],
|
|
530
|
+
tools: [
|
|
531
|
+
"remember", "recall", "forget", "reinforce", "consolidate",
|
|
532
|
+
"charge", "settle", "refund", "balance", "profile",
|
|
533
|
+
"reputation", "logs", "history",
|
|
534
|
+
],
|
|
535
|
+
contact,
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
// ── x402 Settlement ────────────────────────────────────────────────────
|
|
539
|
+
configureX402(config) {
|
|
540
|
+
this.x402 = config;
|
|
541
|
+
this.log(`x402 configured: ${config.facilitatorUrl} (${config.token || "USDC"} on ${config.chain || "base"})`);
|
|
542
|
+
}
|
|
543
|
+
async settleViaX402(txId) {
|
|
544
|
+
if (!this.x402)
|
|
545
|
+
throw new Error("x402 not configured. Call configureX402() first.");
|
|
546
|
+
const tx = this.transactions.get(txId);
|
|
547
|
+
if (!tx)
|
|
548
|
+
throw new Error(`Transaction ${txId} not found`);
|
|
549
|
+
if (tx.status !== "pending")
|
|
550
|
+
throw new Error(`Transaction ${txId} is ${tx.status}, not pending`);
|
|
551
|
+
// Submit payment to x402 facilitator
|
|
552
|
+
const res = await fetch(`${this.x402.facilitatorUrl}/payments`, {
|
|
553
|
+
method: "POST",
|
|
554
|
+
headers: { "Content-Type": "application/json" },
|
|
555
|
+
body: JSON.stringify({
|
|
556
|
+
amount: tx.amount,
|
|
557
|
+
token: this.x402.token || "USDC",
|
|
558
|
+
chain: this.x402.chain || "base",
|
|
559
|
+
from: this.x402.walletAddress,
|
|
560
|
+
memo: `mnemopay:${tx.id}:${tx.reason}`,
|
|
561
|
+
}),
|
|
562
|
+
});
|
|
563
|
+
if (!res.ok) {
|
|
564
|
+
const body = await res.text().catch(() => "");
|
|
565
|
+
throw new Error(`x402 settlement failed (${res.status}): ${body}`);
|
|
566
|
+
}
|
|
567
|
+
// On success, settle locally
|
|
568
|
+
return this.settle(txId);
|
|
569
|
+
}
|
|
295
570
|
async disconnect() {
|
|
296
|
-
this.
|
|
571
|
+
this._saveToDisk();
|
|
572
|
+
if (this.persistTimer)
|
|
573
|
+
clearInterval(this.persistTimer);
|
|
574
|
+
this.log("Disconnected" + (this.persistPath ? " (data saved to disk)" : " (in-memory mode, data discarded)"));
|
|
297
575
|
}
|
|
298
576
|
}
|
|
299
577
|
exports.MnemoPayLite = MnemoPayLite;
|
|
@@ -537,6 +815,82 @@ class MnemoPay extends EventEmitter {
|
|
|
537
815
|
completedAt: t.completedAt ? new Date(t.completedAt) : undefined,
|
|
538
816
|
}));
|
|
539
817
|
}
|
|
818
|
+
// ── Reputation ──────────────────────────────────────────────────────────
|
|
819
|
+
async reputation() {
|
|
820
|
+
const [prof, txs] = await Promise.all([
|
|
821
|
+
this.profile(),
|
|
822
|
+
this.history(1000),
|
|
823
|
+
]);
|
|
824
|
+
const settled = txs.filter((t) => t.status === "completed");
|
|
825
|
+
const refunded = txs.filter((t) => t.status === "refunded");
|
|
826
|
+
const totalCompleted = settled.length + refunded.length;
|
|
827
|
+
const settlementRate = totalCompleted > 0 ? settled.length / totalCompleted : 0;
|
|
828
|
+
const totalValueSettled = settled.reduce((sum, t) => sum + t.amount, 0);
|
|
829
|
+
return {
|
|
830
|
+
agentId: this.agentId,
|
|
831
|
+
score: prof.reputation,
|
|
832
|
+
tier: reputationTier(prof.reputation),
|
|
833
|
+
settledCount: settled.length,
|
|
834
|
+
refundCount: refunded.length,
|
|
835
|
+
settlementRate,
|
|
836
|
+
totalValueSettled,
|
|
837
|
+
memoriesCount: prof.memoriesCount,
|
|
838
|
+
avgMemoryImportance: 0, // not available via API
|
|
839
|
+
ageHours: 0, // not tracked server-side yet
|
|
840
|
+
generatedAt: new Date(),
|
|
841
|
+
};
|
|
842
|
+
}
|
|
843
|
+
// ── A2A Agent Card ─────────────────────────────────────────────────────
|
|
844
|
+
agentCard(url, contact) {
|
|
845
|
+
return {
|
|
846
|
+
name: `MnemoPay Agent (${this.agentId})`,
|
|
847
|
+
description: "AI agent with persistent cognitive memory and micropayment capabilities via MnemoPay protocol.",
|
|
848
|
+
url,
|
|
849
|
+
version: "0.2.0",
|
|
850
|
+
capabilities: {
|
|
851
|
+
memory: true,
|
|
852
|
+
payments: true,
|
|
853
|
+
reputation: true,
|
|
854
|
+
},
|
|
855
|
+
protocols: ["mcp", "a2a"],
|
|
856
|
+
tools: [
|
|
857
|
+
"remember", "recall", "forget", "reinforce", "consolidate",
|
|
858
|
+
"charge", "settle", "refund", "balance", "profile",
|
|
859
|
+
"reputation", "logs", "history",
|
|
860
|
+
],
|
|
861
|
+
contact,
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
// ── x402 Settlement ────────────────────────────────────────────────────
|
|
865
|
+
x402;
|
|
866
|
+
configureX402(config) {
|
|
867
|
+
this.x402 = config;
|
|
868
|
+
this.log(`x402 configured: ${config.facilitatorUrl} (${config.token || "USDC"} on ${config.chain || "base"})`);
|
|
869
|
+
}
|
|
870
|
+
async settleViaX402(txId) {
|
|
871
|
+
if (!this.x402)
|
|
872
|
+
throw new Error("x402 not configured. Call configureX402() first.");
|
|
873
|
+
// Get transaction details from AgentPay
|
|
874
|
+
const txData = await this.agentpayFetch(`/api/escrow/${txId}`);
|
|
875
|
+
// Submit to x402 facilitator
|
|
876
|
+
const res = await fetch(`${this.x402.facilitatorUrl}/payments`, {
|
|
877
|
+
method: "POST",
|
|
878
|
+
headers: { "Content-Type": "application/json" },
|
|
879
|
+
body: JSON.stringify({
|
|
880
|
+
amount: txData.amount,
|
|
881
|
+
token: this.x402.token || "USDC",
|
|
882
|
+
chain: this.x402.chain || "base",
|
|
883
|
+
from: this.x402.walletAddress,
|
|
884
|
+
memo: `mnemopay:${txId}:${txData.reason || ""}`,
|
|
885
|
+
}),
|
|
886
|
+
});
|
|
887
|
+
if (!res.ok) {
|
|
888
|
+
const body = await res.text().catch(() => "");
|
|
889
|
+
throw new Error(`x402 settlement failed (${res.status}): ${body}`);
|
|
890
|
+
}
|
|
891
|
+
// On success, settle in AgentPay
|
|
892
|
+
return this.settle(txId);
|
|
893
|
+
}
|
|
540
894
|
async disconnect() {
|
|
541
895
|
this.log("Disconnected");
|
|
542
896
|
}
|
|
@@ -555,7 +909,7 @@ class MnemoPay extends EventEmitter {
|
|
|
555
909
|
vectorWeight: opts.vectorWeight,
|
|
556
910
|
}
|
|
557
911
|
: undefined;
|
|
558
|
-
return new MnemoPayLite(agentId, opts?.decay ?? 0.05, opts?.debug ?? false, recallConfig);
|
|
912
|
+
return new MnemoPayLite(agentId, opts?.decay ?? 0.05, opts?.debug ?? false, recallConfig, opts?.fraud);
|
|
559
913
|
}
|
|
560
914
|
/**
|
|
561
915
|
* Production mode. Connects to Mnemosyne + AgentPay backends.
|
|
@@ -573,4 +927,13 @@ Object.defineProperty(exports, "RecallEngine", { enumerable: true, get: function
|
|
|
573
927
|
Object.defineProperty(exports, "cosineSimilarity", { enumerable: true, get: function () { return engine_js_2.cosineSimilarity; } });
|
|
574
928
|
Object.defineProperty(exports, "localEmbed", { enumerable: true, get: function () { return engine_js_2.localEmbed; } });
|
|
575
929
|
Object.defineProperty(exports, "l2Normalize", { enumerable: true, get: function () { return engine_js_2.l2Normalize; } });
|
|
930
|
+
var fraud_js_2 = require("./fraud.js");
|
|
931
|
+
Object.defineProperty(exports, "FraudGuard", { enumerable: true, get: function () { return fraud_js_2.FraudGuard; } });
|
|
932
|
+
Object.defineProperty(exports, "RateLimiter", { enumerable: true, get: function () { return fraud_js_2.RateLimiter; } });
|
|
933
|
+
Object.defineProperty(exports, "DEFAULT_FRAUD_CONFIG", { enumerable: true, get: function () { return fraud_js_2.DEFAULT_FRAUD_CONFIG; } });
|
|
934
|
+
Object.defineProperty(exports, "DEFAULT_RATE_LIMIT", { enumerable: true, get: function () { return fraud_js_2.DEFAULT_RATE_LIMIT; } });
|
|
935
|
+
var fraud_ml_js_1 = require("./fraud-ml.js");
|
|
936
|
+
Object.defineProperty(exports, "IsolationForest", { enumerable: true, get: function () { return fraud_ml_js_1.IsolationForest; } });
|
|
937
|
+
Object.defineProperty(exports, "TransactionGraph", { enumerable: true, get: function () { return fraud_ml_js_1.TransactionGraph; } });
|
|
938
|
+
Object.defineProperty(exports, "BehaviorProfile", { enumerable: true, get: function () { return fraud_ml_js_1.BehaviorProfile; } });
|
|
576
939
|
//# sourceMappingURL=index.js.map
|