@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/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
- constructor(agentId, decay = 0.05, debug = false, recallConfig) {
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.log(`MnemoPayLite initialized (in-memory mode, recall: ${this.recallEngine.strategy})`);
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. Move funds to wallet
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 += tx.amount;
240
- // 2. Boost reputation
385
+ this._wallet += fee.netAmount;
386
+ // 3. Boost reputation
241
387
  this._reputation = Math.min(this._reputation + 0.01, 1.0);
242
- // 3. Reinforce recently-accessed memories (feedback loop)
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", { id: tx.id, amount: tx.amount, reinforcedMemories: reinforced });
252
- this.emit("payment:completed", { id: tx.id, amount: tx.amount });
253
- this.log(`Settled $${tx.amount.toFixed(2)} → wallet: $${this._wallet.toFixed(2)}, ` +
254
- `reputation: ${this._reputation.toFixed(2)}, reinforced: ${reinforced} memories`);
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
- this._wallet = Math.max(this._wallet - tx.amount, 0);
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.log("Disconnected (in-memory mode, data discarded)");
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