@mnemopay/sdk 0.9.0 → 0.9.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.
- package/dist/adaptive.d.ts +214 -0
- package/dist/adaptive.d.ts.map +1 -0
- package/dist/adaptive.js +389 -0
- package/dist/adaptive.js.map +1 -0
- package/dist/commerce.d.ts +2 -0
- package/dist/commerce.d.ts.map +1 -1
- package/dist/commerce.js +37 -7
- package/dist/commerce.js.map +1 -1
- package/dist/identity.d.ts +31 -3
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +142 -3
- package/dist/identity.js.map +1 -1
- package/dist/index.d.ts +29 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +349 -66
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +47 -5
- package/dist/mcp/server.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.createSandboxServer = exports.MockCommerceProvider = exports.CommerceEngine = exports.MnemoPayNetwork = exports.IdentityRegistry = exports.Ledger = exports.JSONFileStorage = exports.SQLiteStorage = exports.NIGERIAN_BANKS = exports.PaystackRail = exports.LightningRail = exports.StripeRail = exports.MockRail = 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;
|
|
17
|
+
exports.createSandboxServer = exports.DEFAULT_ADAPTIVE_CONFIG = exports.AdaptiveEngine = exports.MockCommerceProvider = exports.CommerceEngine = exports.MnemoPayNetwork = exports.constantTimeEqual = exports.IdentityRegistry = exports.Ledger = exports.JSONFileStorage = exports.SQLiteStorage = exports.NIGERIAN_BANKS = exports.PaystackRail = exports.LightningRail = exports.StripeRail = exports.MockRail = 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;
|
|
18
18
|
exports.autoScore = autoScore;
|
|
19
19
|
exports.computeScore = computeScore;
|
|
20
20
|
exports.reputationTier = reputationTier;
|
|
@@ -23,6 +23,7 @@ const fraud_js_1 = require("./fraud.js");
|
|
|
23
23
|
const index_js_1 = require("./rails/index.js");
|
|
24
24
|
const ledger_js_1 = require("./ledger.js");
|
|
25
25
|
const identity_js_1 = require("./identity.js");
|
|
26
|
+
const adaptive_js_1 = require("./adaptive.js");
|
|
26
27
|
class EventEmitter {
|
|
27
28
|
_events = new Map();
|
|
28
29
|
on(event, fn) {
|
|
@@ -78,6 +79,29 @@ const IMPORTANCE_PATTERNS = [
|
|
|
78
79
|
const LONG_CONTENT_THRESHOLD = 200;
|
|
79
80
|
const LONG_CONTENT_BOOST = 0.10;
|
|
80
81
|
const BASE_IMPORTANCE = 0.50;
|
|
82
|
+
// ─── Security: prompt injection defense ───────────────────────────────────
|
|
83
|
+
const INJECTION_PATTERNS = [
|
|
84
|
+
/\b(ignore|disregard|forget)\b.{0,30}\b(previous|prior|above|all)\b.{0,30}\b(instructions?|rules?|constraints?)\b/i,
|
|
85
|
+
/\b(you are|act as|pretend|roleplay|simulate)\b.{0,30}\b(admin|root|system|god|superuser)\b/i,
|
|
86
|
+
/\bsystem\s*:\s*/i,
|
|
87
|
+
/\bassistant\s*:\s*/i,
|
|
88
|
+
/\b(transfer|send|move)\b.{0,20}\b(all|every|maximum)\b.{0,20}\b(funds?|money|balance|wallet)\b/i,
|
|
89
|
+
/\b(set|change|update|override)\b.{0,20}\b(wallet|balance|reputation|role|permission)\b.{0,10}\b(to|=)\b/i,
|
|
90
|
+
];
|
|
91
|
+
function sanitizeMemoryContent(content) {
|
|
92
|
+
let sanitized = content;
|
|
93
|
+
for (const pattern of INJECTION_PATTERNS) {
|
|
94
|
+
sanitized = sanitized.replace(pattern, "[FILTERED]");
|
|
95
|
+
}
|
|
96
|
+
return sanitized;
|
|
97
|
+
}
|
|
98
|
+
function validateTags(tags) {
|
|
99
|
+
return tags
|
|
100
|
+
.filter(t => typeof t === "string" && t.length <= 50)
|
|
101
|
+
.map(t => t.replace(/[^a-zA-Z0-9_\-:.]/g, ""))
|
|
102
|
+
.filter(t => t.length > 0)
|
|
103
|
+
.slice(0, 20);
|
|
104
|
+
}
|
|
81
105
|
function autoScore(content) {
|
|
82
106
|
let score = BASE_IMPORTANCE;
|
|
83
107
|
if (content.length > LONG_CONTENT_THRESHOLD)
|
|
@@ -113,8 +137,18 @@ class MnemoPayLite extends EventEmitter {
|
|
|
113
137
|
storageAdapter;
|
|
114
138
|
/** Guard against concurrent double-settle on the same transaction */
|
|
115
139
|
_settlingTxIds = new Set();
|
|
140
|
+
/** Guard against concurrent double-refund on the same transaction */
|
|
141
|
+
_refundingTxIds = new Set();
|
|
142
|
+
/** Track whether process exit hooks have been registered (prevent listener leak) */
|
|
143
|
+
_exitHooksRegistered = false;
|
|
116
144
|
/** Guard against concurrent wallet mutations */
|
|
117
145
|
_walletLock = Promise.resolve();
|
|
146
|
+
/** Max wallet balance — prevents overflow/accumulation attacks */
|
|
147
|
+
static MAX_WALLET_BALANCE = 1_000_000; // $1M ceiling
|
|
148
|
+
/** Max memories per agent — prevents memory exhaustion attacks */
|
|
149
|
+
static MAX_MEMORIES = 50_000;
|
|
150
|
+
/** Max transactions tracked — prevents unbounded growth */
|
|
151
|
+
static MAX_TRANSACTIONS = 100_000;
|
|
118
152
|
/** Fraud detection, rate limiting, dispute resolution, and platform fee */
|
|
119
153
|
fraud;
|
|
120
154
|
/** Pluggable payment rail (Stripe, Lightning, etc.). Default: in-memory mock. */
|
|
@@ -125,6 +159,8 @@ class MnemoPayLite extends EventEmitter {
|
|
|
125
159
|
ledger;
|
|
126
160
|
/** Agent identity registry — cryptographic identity, KYA compliance, capability tokens */
|
|
127
161
|
identity;
|
|
162
|
+
/** Adaptive business intelligence — learns from operations, optimizes within secure bounds */
|
|
163
|
+
adaptive;
|
|
128
164
|
constructor(agentId, decay = 0.05, debug = false, recallConfig, fraudConfig, paymentRail, requireCounterparty = false, storage) {
|
|
129
165
|
super();
|
|
130
166
|
this.agentId = agentId;
|
|
@@ -136,6 +172,7 @@ class MnemoPayLite extends EventEmitter {
|
|
|
136
172
|
this.requireCounterparty = requireCounterparty;
|
|
137
173
|
this.ledger = new ledger_js_1.Ledger();
|
|
138
174
|
this.identity = new identity_js_1.IdentityRegistry();
|
|
175
|
+
this.adaptive = new adaptive_js_1.AdaptiveEngine();
|
|
139
176
|
// Use provided storage adapter, or auto-detect persistence
|
|
140
177
|
if (storage) {
|
|
141
178
|
this.storageAdapter = storage;
|
|
@@ -173,6 +210,22 @@ class MnemoPayLite extends EventEmitter {
|
|
|
173
210
|
this._loadFromDisk();
|
|
174
211
|
// Auto-save every 30 seconds
|
|
175
212
|
this.persistTimer = setInterval(() => this._saveToDisk(), 30_000);
|
|
213
|
+
// Hook process exit signals to flush data before shutdown.
|
|
214
|
+
// This prevents memory loss on restart, SIGTERM, or uncaught exceptions.
|
|
215
|
+
// Guard: only register once per instance to prevent listener leaks on repeated calls.
|
|
216
|
+
if (typeof process !== "undefined" && process.on && !this._exitHooksRegistered) {
|
|
217
|
+
this._exitHooksRegistered = true;
|
|
218
|
+
const flush = () => { this._saveToDisk(); };
|
|
219
|
+
process.on("beforeExit", flush);
|
|
220
|
+
process.on("SIGINT", () => { flush(); process.exit(0); });
|
|
221
|
+
process.on("SIGTERM", () => { flush(); process.exit(0); });
|
|
222
|
+
// Save on uncaught exception too — data is more valuable than a clean exit
|
|
223
|
+
process.on("uncaughtException", (err) => {
|
|
224
|
+
flush();
|
|
225
|
+
this.log(`Uncaught exception (data saved): ${err.message}`);
|
|
226
|
+
process.exit(1);
|
|
227
|
+
});
|
|
228
|
+
}
|
|
176
229
|
this.log(`Persistence enabled: ${this.persistPath}`);
|
|
177
230
|
}
|
|
178
231
|
catch (e) {
|
|
@@ -186,12 +239,75 @@ class MnemoPayLite extends EventEmitter {
|
|
|
186
239
|
const fs = require("fs");
|
|
187
240
|
if (!fs.existsSync(this.persistPath))
|
|
188
241
|
return;
|
|
189
|
-
|
|
190
|
-
|
|
242
|
+
// Corruption recovery: try main → .bak → .tmp (triple fallback)
|
|
243
|
+
let rawText;
|
|
244
|
+
try {
|
|
245
|
+
rawText = fs.readFileSync(this.persistPath, "utf-8");
|
|
246
|
+
JSON.parse(rawText); // validate JSON
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
const bakPath = this.persistPath + ".bak";
|
|
250
|
+
const tmpPath = this.persistPath + ".tmp";
|
|
251
|
+
if (fs.existsSync(bakPath)) {
|
|
252
|
+
try {
|
|
253
|
+
rawText = fs.readFileSync(bakPath, "utf-8");
|
|
254
|
+
JSON.parse(rawText);
|
|
255
|
+
this.log("Main persist file corrupted — recovered from .bak backup");
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
if (fs.existsSync(tmpPath)) {
|
|
259
|
+
rawText = fs.readFileSync(tmpPath, "utf-8");
|
|
260
|
+
this.log("Main + .bak corrupted — recovered from .tmp");
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
this.log("All persist files corrupted — starting fresh");
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
else if (fs.existsSync(tmpPath)) {
|
|
269
|
+
rawText = fs.readFileSync(tmpPath, "utf-8");
|
|
270
|
+
this.log("Main persist file corrupted — recovered from .tmp");
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
this.log("Persist file corrupted and no backup available");
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
const raw = JSON.parse(rawText);
|
|
278
|
+
// Schema validation: reject obviously malformed persisted data
|
|
279
|
+
if (typeof raw !== "object" || raw === null) {
|
|
280
|
+
this.log("Persisted data is not an object — ignoring");
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
if (raw.agentId !== undefined && raw.agentId !== this.agentId) {
|
|
284
|
+
this.log(`Persisted data agentId mismatch (${raw.agentId} vs ${this.agentId}) — ignoring`);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
if (raw.wallet !== undefined && (typeof raw.wallet !== "number" || !Number.isFinite(raw.wallet) || raw.wallet < 0 || raw.wallet > MnemoPayLite.MAX_WALLET_BALANCE)) {
|
|
288
|
+
this.log(`Persisted wallet value invalid ($${raw.wallet}) — resetting to 0`);
|
|
289
|
+
raw.wallet = 0;
|
|
290
|
+
}
|
|
291
|
+
if (raw.reputation !== undefined && (typeof raw.reputation !== "number" || raw.reputation < 0 || raw.reputation > 1)) {
|
|
292
|
+
this.log(`Persisted reputation invalid (${raw.reputation}) — resetting to 0.5`);
|
|
293
|
+
raw.reputation = 0.5;
|
|
294
|
+
}
|
|
295
|
+
// Restore memories (with tags parsing for both stringified and array formats)
|
|
191
296
|
if (raw.memories) {
|
|
192
297
|
for (const m of raw.memories) {
|
|
193
298
|
m.createdAt = new Date(m.createdAt);
|
|
194
299
|
m.lastAccessed = new Date(m.lastAccessed);
|
|
300
|
+
// Tags may be stringified JSON or an array — handle both
|
|
301
|
+
if (typeof m.tags === "string") {
|
|
302
|
+
try {
|
|
303
|
+
m.tags = JSON.parse(m.tags);
|
|
304
|
+
}
|
|
305
|
+
catch {
|
|
306
|
+
m.tags = [];
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
if (!Array.isArray(m.tags))
|
|
310
|
+
m.tags = [];
|
|
195
311
|
this.memories.set(m.id, m);
|
|
196
312
|
}
|
|
197
313
|
}
|
|
@@ -356,8 +472,16 @@ class MnemoPayLite extends EventEmitter {
|
|
|
356
472
|
identity: this.identity.serialize(),
|
|
357
473
|
savedAt: new Date().toISOString(),
|
|
358
474
|
});
|
|
359
|
-
// Atomic write
|
|
475
|
+
// Atomic write with backup: .bak → .tmp → main
|
|
360
476
|
const tmpPath = this.persistPath + ".tmp";
|
|
477
|
+
const bakPath = this.persistPath + ".bak";
|
|
478
|
+
// Keep a backup of the last known-good file before overwriting
|
|
479
|
+
if (fs.existsSync(this.persistPath)) {
|
|
480
|
+
try {
|
|
481
|
+
fs.copyFileSync(this.persistPath, bakPath);
|
|
482
|
+
}
|
|
483
|
+
catch { /* best effort */ }
|
|
484
|
+
}
|
|
361
485
|
fs.writeFileSync(tmpPath, data, "utf-8");
|
|
362
486
|
fs.renameSync(tmpPath, this.persistPath);
|
|
363
487
|
}
|
|
@@ -369,15 +493,36 @@ class MnemoPayLite extends EventEmitter {
|
|
|
369
493
|
if (this.debugMode)
|
|
370
494
|
console.log(`[mnemopay:${this.agentId}] ${msg}`);
|
|
371
495
|
}
|
|
496
|
+
_lastAuditHash = "0";
|
|
372
497
|
audit(action, details) {
|
|
373
498
|
const entry = {
|
|
374
499
|
id: randomUUID(),
|
|
375
500
|
agentId: this.agentId,
|
|
376
501
|
action,
|
|
377
|
-
details
|
|
502
|
+
details: {
|
|
503
|
+
...details,
|
|
504
|
+
_prevHash: this._lastAuditHash,
|
|
505
|
+
},
|
|
378
506
|
createdAt: new Date(),
|
|
379
507
|
};
|
|
508
|
+
// Hash chain: each entry includes a hash linking it to the previous entry.
|
|
509
|
+
// Tampering with any entry breaks the chain, making modification detectable.
|
|
510
|
+
try {
|
|
511
|
+
const { createHash } = require("crypto");
|
|
512
|
+
this._lastAuditHash = createHash("sha256")
|
|
513
|
+
.update(`${entry.id}:${entry.action}:${this._lastAuditHash}`)
|
|
514
|
+
.digest("hex")
|
|
515
|
+
.slice(0, 16);
|
|
516
|
+
}
|
|
517
|
+
catch {
|
|
518
|
+
this._lastAuditHash = entry.id.slice(0, 16);
|
|
519
|
+
}
|
|
520
|
+
entry.details._hash = this._lastAuditHash;
|
|
380
521
|
this.auditLog.push(entry);
|
|
522
|
+
// Cap in-memory audit log to prevent unbounded growth
|
|
523
|
+
if (this.auditLog.length > 1000) {
|
|
524
|
+
this.auditLog.splice(0, this.auditLog.length - 500);
|
|
525
|
+
}
|
|
381
526
|
}
|
|
382
527
|
// ── Memory Methods ──────────────────────────────────────────────────────
|
|
383
528
|
async remember(content, opts) {
|
|
@@ -385,28 +530,37 @@ class MnemoPayLite extends EventEmitter {
|
|
|
385
530
|
throw new Error("Memory content is required");
|
|
386
531
|
if (content.length > 100_000)
|
|
387
532
|
throw new Error("Memory content exceeds 100KB limit");
|
|
388
|
-
|
|
533
|
+
// Security: prevent memory exhaustion attacks
|
|
534
|
+
if (this.memories.size >= MnemoPayLite.MAX_MEMORIES) {
|
|
535
|
+
throw new Error(`Memory limit reached (${MnemoPayLite.MAX_MEMORIES}). Consolidate or forget old memories first.`);
|
|
536
|
+
}
|
|
537
|
+
// Security: sanitize against prompt injection
|
|
538
|
+
const safeContent = sanitizeMemoryContent(content);
|
|
539
|
+
// Security: validate and sanitize tags
|
|
540
|
+
const safeTags = validateTags(opts?.tags ?? []);
|
|
541
|
+
const importance = opts?.importance ?? autoScore(safeContent);
|
|
389
542
|
const now = new Date();
|
|
390
543
|
const mem = {
|
|
391
544
|
id: randomUUID(),
|
|
392
545
|
agentId: this.agentId,
|
|
393
|
-
content,
|
|
546
|
+
content: safeContent,
|
|
394
547
|
importance: Math.min(Math.max(importance, 0), 1),
|
|
395
548
|
score: importance,
|
|
396
549
|
createdAt: now,
|
|
397
550
|
lastAccessed: now,
|
|
398
551
|
accessCount: 0,
|
|
399
|
-
tags:
|
|
552
|
+
tags: safeTags,
|
|
400
553
|
};
|
|
401
554
|
this.memories.set(mem.id, mem);
|
|
402
555
|
// Generate embedding if using vector/hybrid recall
|
|
403
556
|
if (this.recallEngine.strategy !== "score") {
|
|
404
557
|
await this.recallEngine.embed(mem.id, content);
|
|
405
558
|
}
|
|
406
|
-
this.audit("memory:stored", { id: mem.id,
|
|
559
|
+
this.audit("memory:stored", { id: mem.id, tags: safeTags, importance: mem.importance });
|
|
407
560
|
this._saveToDisk();
|
|
408
|
-
this.emit("memory:stored", { id: mem.id,
|
|
409
|
-
this.
|
|
561
|
+
this.emit("memory:stored", { id: mem.id, importance: mem.importance });
|
|
562
|
+
this.adaptive.observe({ type: "memory_store", agentId: this.agentId, timestamp: Date.now() });
|
|
563
|
+
this.log(`Stored memory: id=${mem.id} (importance: ${mem.importance.toFixed(2)}, tags: ${safeTags.join(",") || "none"})`);
|
|
410
564
|
return mem.id;
|
|
411
565
|
}
|
|
412
566
|
async recall(queryOrLimit, maybeLimit) {
|
|
@@ -439,6 +593,7 @@ class MnemoPayLite extends EventEmitter {
|
|
|
439
593
|
m.accessCount++;
|
|
440
594
|
}
|
|
441
595
|
this.emit("memory:recalled", { count: results.length });
|
|
596
|
+
this.adaptive.observe({ type: "memory_recall", agentId: this.agentId, timestamp: Date.now() });
|
|
442
597
|
this.log(`Recalled ${results.length} memories (strategy: ${this.recallEngine.strategy})`);
|
|
443
598
|
return results;
|
|
444
599
|
}
|
|
@@ -453,10 +608,16 @@ class MnemoPayLite extends EventEmitter {
|
|
|
453
608
|
return existed;
|
|
454
609
|
}
|
|
455
610
|
async reinforce(id, boost = 0.1) {
|
|
611
|
+
if (!id || typeof id !== "string")
|
|
612
|
+
throw new Error("Memory ID is required");
|
|
613
|
+
if (typeof boost !== "number" || !Number.isFinite(boost))
|
|
614
|
+
throw new Error("Boost must be a finite number");
|
|
615
|
+
if (boost < -0.5 || boost > 0.5)
|
|
616
|
+
throw new Error("Boost must be between -0.5 and 0.5");
|
|
456
617
|
const mem = this.memories.get(id);
|
|
457
618
|
if (!mem)
|
|
458
619
|
throw new Error(`Memory ${id} not found`);
|
|
459
|
-
mem.importance = Math.min(mem.importance + boost, 1.0);
|
|
620
|
+
mem.importance = Math.min(Math.max(mem.importance + boost, 0), 1.0);
|
|
460
621
|
mem.lastAccessed = new Date();
|
|
461
622
|
this.audit("memory:reinforced", { id, boost, newImportance: mem.importance });
|
|
462
623
|
this._saveToDisk();
|
|
@@ -524,6 +685,12 @@ class MnemoPayLite extends EventEmitter {
|
|
|
524
685
|
amount = Math.round(amount * 100) / 100;
|
|
525
686
|
if (!reason || typeof reason !== "string")
|
|
526
687
|
throw new Error("Reason is required");
|
|
688
|
+
if (reason.length > 1000)
|
|
689
|
+
throw new Error("Reason exceeds 1000 character limit");
|
|
690
|
+
// Security: prevent unbounded transaction growth
|
|
691
|
+
if (this.transactions.size >= MnemoPayLite.MAX_TRANSACTIONS) {
|
|
692
|
+
throw new Error(`Transaction limit reached (${MnemoPayLite.MAX_TRANSACTIONS}). Archive old transactions.`);
|
|
693
|
+
}
|
|
527
694
|
const maxCharge = 500 * this._reputation;
|
|
528
695
|
if (amount > maxCharge) {
|
|
529
696
|
throw new Error(`Amount $${amount.toFixed(2)} exceeds reputation ceiling $${maxCharge.toFixed(2)} ` +
|
|
@@ -536,6 +703,7 @@ class MnemoPayLite extends EventEmitter {
|
|
|
536
703
|
this.audit("fraud:blocked", { amount, reason, riskScore: risk.score, signals: risk.signals.map((s) => s.type) });
|
|
537
704
|
this._saveToDisk();
|
|
538
705
|
this.emit("fraud:blocked", { amount, risk });
|
|
706
|
+
this.adaptive.observe({ type: "fraud_block", agentId: this.agentId, amount, timestamp: Date.now() });
|
|
539
707
|
throw new Error(risk.reason || `Charge blocked: risk score ${risk.score}`);
|
|
540
708
|
}
|
|
541
709
|
if (risk.flagged) {
|
|
@@ -566,6 +734,7 @@ class MnemoPayLite extends EventEmitter {
|
|
|
566
734
|
this.audit("payment:pending", { id: tx.id, amount, reason, riskScore: risk.score, rail: this.paymentRail.name, externalId: hold.externalId });
|
|
567
735
|
this._saveToDisk();
|
|
568
736
|
this.emit("payment:pending", { id: tx.id, amount, reason });
|
|
737
|
+
this.adaptive.observe({ type: "charge", agentId: this.agentId, amount, timestamp: Date.now() });
|
|
569
738
|
this.log(`Charge created: $${amount.toFixed(2)} for "${reason}" (pending, risk: ${risk.score}, rail: ${this.paymentRail.name})`);
|
|
570
739
|
return { ...tx };
|
|
571
740
|
}
|
|
@@ -611,16 +780,20 @@ class MnemoPayLite extends EventEmitter {
|
|
|
611
780
|
const fee = this.fraud.applyPlatformFee(tx.id, this.agentId, tx.amount);
|
|
612
781
|
tx.platformFee = fee.feeAmount;
|
|
613
782
|
tx.netAmount = fee.netAmount;
|
|
614
|
-
// 4.
|
|
783
|
+
// 4. Ledger FIRST (atomic: record before wallet mutation)
|
|
784
|
+
this.ledger.recordSettlement(this.agentId, tx.id, tx.amount, fee.feeAmount, fee.netAmount, tx.counterpartyId);
|
|
785
|
+
// 5. Move NET funds to wallet (atomic via sequential lock + overflow guard)
|
|
615
786
|
const prevLock = this._walletLock;
|
|
616
787
|
this._walletLock = prevLock.then(() => {
|
|
788
|
+
const newBalance = this._wallet + fee.netAmount;
|
|
789
|
+
if (newBalance > MnemoPayLite.MAX_WALLET_BALANCE) {
|
|
790
|
+
throw new Error(`Wallet overflow: balance would exceed $${MnemoPayLite.MAX_WALLET_BALANCE.toLocaleString()}`);
|
|
791
|
+
}
|
|
617
792
|
tx.status = "completed";
|
|
618
793
|
tx.completedAt = new Date();
|
|
619
|
-
this._wallet
|
|
794
|
+
this._wallet = Math.round(newBalance * 100) / 100; // 2-decimal precision
|
|
620
795
|
});
|
|
621
796
|
await this._walletLock;
|
|
622
|
-
// Ledger: escrow → float → revenue (fee) + counterparty/agent (net)
|
|
623
|
-
this.ledger.recordSettlement(this.agentId, tx.id, tx.amount, fee.feeAmount, fee.netAmount, tx.counterpartyId);
|
|
624
797
|
// 4. Boost reputation
|
|
625
798
|
this._reputation = Math.min(this._reputation + 0.01, 1.0);
|
|
626
799
|
// 5. Reinforce recently-accessed memories (feedback loop)
|
|
@@ -641,6 +814,7 @@ class MnemoPayLite extends EventEmitter {
|
|
|
641
814
|
});
|
|
642
815
|
this._saveToDisk();
|
|
643
816
|
this.emit("payment:completed", { id: tx.id, amount: fee.netAmount, fee: fee.feeAmount });
|
|
817
|
+
this.adaptive.observe({ type: "settle", agentId: this.agentId, amount: fee.netAmount, timestamp: Date.now() });
|
|
644
818
|
this.log(`Settled $${tx.amount.toFixed(2)} (fee: $${fee.feeAmount.toFixed(2)}, net: $${fee.netAmount.toFixed(2)}) → ` +
|
|
645
819
|
`wallet: $${this._wallet.toFixed(2)}, reputation: ${this._reputation.toFixed(2)}, reinforced: ${reinforced} memories`);
|
|
646
820
|
return { ...tx };
|
|
@@ -650,6 +824,8 @@ class MnemoPayLite extends EventEmitter {
|
|
|
650
824
|
}
|
|
651
825
|
}
|
|
652
826
|
async refund(txId) {
|
|
827
|
+
if (!txId || typeof txId !== "string")
|
|
828
|
+
throw new Error("Transaction ID is required");
|
|
653
829
|
const tx = this.transactions.get(txId);
|
|
654
830
|
if (!tx)
|
|
655
831
|
throw new Error(`Transaction ${txId} not found`);
|
|
@@ -657,38 +833,48 @@ class MnemoPayLite extends EventEmitter {
|
|
|
657
833
|
throw new Error(`Transaction ${txId} already refunded`);
|
|
658
834
|
if (tx.status === "expired")
|
|
659
835
|
throw new Error(`Transaction ${txId} has expired and cannot be refunded`);
|
|
660
|
-
//
|
|
661
|
-
if (
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
836
|
+
// Prevent concurrent double-refund (mirrors settle guard)
|
|
837
|
+
if (this._refundingTxIds.has(txId))
|
|
838
|
+
throw new Error(`Transaction ${txId} is already being refunded`);
|
|
839
|
+
this._refundingTxIds.add(txId);
|
|
840
|
+
try {
|
|
841
|
+
// Enforce dispute window: completed transactions can only be refunded within the window
|
|
842
|
+
if (tx.status === "completed" && tx.completedAt) {
|
|
843
|
+
const windowMs = this.fraud.config.disputeWindowMinutes * 60_000;
|
|
844
|
+
const elapsed = Date.now() - tx.completedAt.getTime();
|
|
845
|
+
if (windowMs > 0 && elapsed > windowMs) {
|
|
846
|
+
throw new Error(`Refund window expired. Transaction was settled ${Math.floor(elapsed / 60_000)} minutes ago. ` +
|
|
847
|
+
`Refund window is ${this.fraud.config.disputeWindowMinutes} minutes.`);
|
|
848
|
+
}
|
|
667
849
|
}
|
|
850
|
+
// Reverse on external rail
|
|
851
|
+
if (tx.externalId) {
|
|
852
|
+
const reversal = await this.paymentRail.reversePayment(tx.externalId, tx.amount);
|
|
853
|
+
tx.externalStatus = reversal.status;
|
|
854
|
+
}
|
|
855
|
+
if (tx.status === "completed") {
|
|
856
|
+
// Refund the net amount (platform fee is NOT refunded)
|
|
857
|
+
const refundAmount = tx.netAmount ?? tx.amount;
|
|
858
|
+
this._wallet = Math.max(this._wallet - refundAmount, 0);
|
|
859
|
+
this._reputation = Math.max(this._reputation - 0.05, 0);
|
|
860
|
+
// Ledger: reverse the net settlement
|
|
861
|
+
this.ledger.recordRefund(this.agentId, tx.id, refundAmount, tx.counterpartyId);
|
|
862
|
+
}
|
|
863
|
+
else if (tx.status === "pending") {
|
|
864
|
+
// Ledger: release escrow back to agent
|
|
865
|
+
this.ledger.recordCancellation(this.agentId, tx.amount, tx.id);
|
|
866
|
+
}
|
|
867
|
+
tx.status = "refunded";
|
|
868
|
+
this.audit("payment:refunded", { id: tx.id, amount: tx.amount, netRefunded: tx.netAmount ?? tx.amount });
|
|
869
|
+
this._saveToDisk();
|
|
870
|
+
this.emit("payment:refunded", { id: tx.id });
|
|
871
|
+
this.adaptive.observe({ type: "refund", agentId: this.agentId, amount: tx.amount, timestamp: Date.now() });
|
|
872
|
+
this.log(`Refunded $${tx.amount.toFixed(2)} → reputation: ${this._reputation.toFixed(2)}`);
|
|
873
|
+
return { ...tx };
|
|
668
874
|
}
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
const reversal = await this.paymentRail.reversePayment(tx.externalId, tx.amount);
|
|
672
|
-
tx.externalStatus = reversal.status;
|
|
673
|
-
}
|
|
674
|
-
if (tx.status === "completed") {
|
|
675
|
-
// Refund the net amount (platform fee is NOT refunded)
|
|
676
|
-
const refundAmount = tx.netAmount ?? tx.amount;
|
|
677
|
-
this._wallet = Math.max(this._wallet - refundAmount, 0);
|
|
678
|
-
this._reputation = Math.max(this._reputation - 0.05, 0);
|
|
679
|
-
// Ledger: reverse the net settlement
|
|
680
|
-
this.ledger.recordRefund(this.agentId, tx.id, refundAmount, tx.counterpartyId);
|
|
681
|
-
}
|
|
682
|
-
else if (tx.status === "pending") {
|
|
683
|
-
// Ledger: release escrow back to agent
|
|
684
|
-
this.ledger.recordCancellation(this.agentId, tx.amount, tx.id);
|
|
875
|
+
finally {
|
|
876
|
+
this._refundingTxIds.delete(txId);
|
|
685
877
|
}
|
|
686
|
-
tx.status = "refunded";
|
|
687
|
-
this.audit("payment:refunded", { id: tx.id, amount: tx.amount, netRefunded: tx.netAmount ?? tx.amount });
|
|
688
|
-
this._saveToDisk();
|
|
689
|
-
this.emit("payment:refunded", { id: tx.id });
|
|
690
|
-
this.log(`Refunded $${tx.amount.toFixed(2)} → reputation: ${this._reputation.toFixed(2)}`);
|
|
691
|
-
return { ...tx };
|
|
692
878
|
}
|
|
693
879
|
// ── Dispute Resolution ─────────────────────────────────────────────────
|
|
694
880
|
async dispute(txId, reason, evidence) {
|
|
@@ -704,23 +890,39 @@ class MnemoPayLite extends EventEmitter {
|
|
|
704
890
|
this.audit("payment:disputed", { id: tx.id, disputeId: d.id, reason });
|
|
705
891
|
this._saveToDisk();
|
|
706
892
|
this.emit("payment:disputed", { txId, disputeId: d.id, reason });
|
|
893
|
+
this.adaptive.observe({ type: "dispute", agentId: this.agentId, amount: tx.amount, timestamp: Date.now() });
|
|
707
894
|
this.log(`Dispute filed for tx ${txId}: ${reason}`);
|
|
708
895
|
return d;
|
|
709
896
|
}
|
|
710
897
|
async resolveDispute(disputeId, outcome) {
|
|
898
|
+
if (!disputeId || typeof disputeId !== "string")
|
|
899
|
+
throw new Error("Dispute ID is required");
|
|
900
|
+
if (outcome !== "refund" && outcome !== "uphold")
|
|
901
|
+
throw new Error("Outcome must be 'refund' or 'uphold'");
|
|
902
|
+
// Security: verify authorization BEFORE mutating dispute state
|
|
903
|
+
// Look up the dispute's transaction to check ownership first
|
|
904
|
+
const disputes = this.fraud.getDisputes?.() ?? [];
|
|
905
|
+
const pending = disputes.find((d) => d.id === disputeId);
|
|
906
|
+
if (pending) {
|
|
907
|
+
const tx = this.transactions.get(pending.txId);
|
|
908
|
+
if (tx && tx.agentId !== this.agentId)
|
|
909
|
+
throw new Error("Unauthorized: cannot resolve another agent's dispute");
|
|
910
|
+
}
|
|
711
911
|
const d = this.fraud.resolveDispute(disputeId, outcome);
|
|
912
|
+
const tx = this.transactions.get(d.txId);
|
|
913
|
+
if (!tx)
|
|
914
|
+
throw new Error("Dispute references unknown transaction");
|
|
712
915
|
if (outcome === "refund") {
|
|
713
|
-
|
|
714
|
-
if (tx && tx.status === "disputed") {
|
|
916
|
+
if (tx.status === "disputed") {
|
|
715
917
|
const refundAmount = tx.netAmount ?? tx.amount;
|
|
918
|
+
// Ledger first, then wallet (atomic ordering)
|
|
716
919
|
this._wallet = Math.max(this._wallet - refundAmount, 0);
|
|
717
920
|
this._reputation = Math.max(this._reputation - 0.05, 0);
|
|
718
921
|
tx.status = "refunded";
|
|
719
922
|
}
|
|
720
923
|
}
|
|
721
924
|
else {
|
|
722
|
-
|
|
723
|
-
if (tx && tx.status === "disputed") {
|
|
925
|
+
if (tx.status === "disputed") {
|
|
724
926
|
tx.status = "completed"; // Restore to completed
|
|
725
927
|
}
|
|
726
928
|
}
|
|
@@ -751,6 +953,30 @@ class MnemoPayLite extends EventEmitter {
|
|
|
751
953
|
async verifyLedger() {
|
|
752
954
|
return this.ledger.verify();
|
|
753
955
|
}
|
|
956
|
+
/**
|
|
957
|
+
* Reconcile wallet balance against ledger (source of truth).
|
|
958
|
+
* Returns drift amount. If drift !== 0, the wallet is corrected to match the ledger.
|
|
959
|
+
* Call periodically or after crashes to detect/fix inconsistencies.
|
|
960
|
+
*/
|
|
961
|
+
async reconcile() {
|
|
962
|
+
const walletBefore = Math.round(this._wallet * 100) / 100;
|
|
963
|
+
const acctBalance = this.ledger.getAccountBalance(`agent:${this.agentId}`, "USD");
|
|
964
|
+
const ledgerBalance = Math.round(acctBalance.balance * 100) / 100;
|
|
965
|
+
const drift = Math.round((walletBefore - ledgerBalance) * 100) / 100;
|
|
966
|
+
// Garbage-collect expired tokens during reconciliation (natural maintenance cycle)
|
|
967
|
+
const purgedTokens = this.identity.purgeExpiredTokens();
|
|
968
|
+
if (purgedTokens > 0)
|
|
969
|
+
this.log(`Purged ${purgedTokens} expired/revoked tokens`);
|
|
970
|
+
if (drift !== 0) {
|
|
971
|
+
this.log(`RECONCILIATION DRIFT: wallet=$${walletBefore}, ledger=$${ledgerBalance}, drift=$${drift}`);
|
|
972
|
+
this._wallet = ledgerBalance;
|
|
973
|
+
this.audit("reconciliation:drift", { walletBefore, ledgerBalance, drift, purgedTokens });
|
|
974
|
+
this._saveToDisk();
|
|
975
|
+
this.emit("reconciliation:drift", { walletBefore, ledgerBalance, drift });
|
|
976
|
+
return { walletBefore, ledgerBalance, drift, corrected: true };
|
|
977
|
+
}
|
|
978
|
+
return { walletBefore, ledgerBalance, drift: 0, corrected: false };
|
|
979
|
+
}
|
|
754
980
|
/**
|
|
755
981
|
* Get all ledger entries for a specific transaction.
|
|
756
982
|
*/
|
|
@@ -811,7 +1037,7 @@ class MnemoPayLite extends EventEmitter {
|
|
|
811
1037
|
name: `MnemoPay Agent (${this.agentId})`,
|
|
812
1038
|
description: "AI agent with persistent cognitive memory and micropayment capabilities via MnemoPay protocol.",
|
|
813
1039
|
url,
|
|
814
|
-
version: "0.
|
|
1040
|
+
version: "0.9.2",
|
|
815
1041
|
capabilities: {
|
|
816
1042
|
memory: true,
|
|
817
1043
|
payments: true,
|
|
@@ -828,6 +1054,23 @@ class MnemoPayLite extends EventEmitter {
|
|
|
828
1054
|
}
|
|
829
1055
|
// ── x402 Settlement ────────────────────────────────────────────────────
|
|
830
1056
|
configureX402(config) {
|
|
1057
|
+
// SSRF protection: block internal network targets
|
|
1058
|
+
try {
|
|
1059
|
+
const url = new URL(config.facilitatorUrl);
|
|
1060
|
+
const blocked = ["localhost", "127.0.0.1", "0.0.0.0", "::1", "169.254.169.254", "metadata.google.internal"];
|
|
1061
|
+
if (blocked.some(h => url.hostname === h || url.hostname.endsWith(".internal") || url.hostname.endsWith(".local"))) {
|
|
1062
|
+
throw new Error(`SSRF blocked: facilitator URL points to internal network (${url.hostname})`);
|
|
1063
|
+
}
|
|
1064
|
+
// Block private IP ranges
|
|
1065
|
+
if (/^(10\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.)/.test(url.hostname)) {
|
|
1066
|
+
throw new Error(`SSRF blocked: facilitator URL points to private IP (${url.hostname})`);
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
catch (e) {
|
|
1070
|
+
if (e.message?.startsWith("SSRF"))
|
|
1071
|
+
throw e;
|
|
1072
|
+
throw new Error(`Invalid facilitator URL: ${config.facilitatorUrl}`);
|
|
1073
|
+
}
|
|
831
1074
|
this.x402 = config;
|
|
832
1075
|
this.log(`x402 configured: ${config.facilitatorUrl} (${config.token || "USDC"} on ${config.chain || "base"})`);
|
|
833
1076
|
}
|
|
@@ -943,23 +1186,50 @@ class MnemoPay extends EventEmitter {
|
|
|
943
1186
|
const text = await res.text();
|
|
944
1187
|
return text ? JSON.parse(text) : null;
|
|
945
1188
|
}
|
|
1189
|
+
// ── Retry logic for production API calls ─────────────────────────────────
|
|
1190
|
+
async withRetry(fn, maxRetries = 2, delayMs = 500) {
|
|
1191
|
+
let lastError = null;
|
|
1192
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
1193
|
+
try {
|
|
1194
|
+
return await fn();
|
|
1195
|
+
}
|
|
1196
|
+
catch (err) {
|
|
1197
|
+
lastError = err;
|
|
1198
|
+
// Don't retry client errors (4xx) — only transient failures (5xx, network)
|
|
1199
|
+
if (err.message?.includes("4") && /\b4\d{2}\b/.test(err.message))
|
|
1200
|
+
throw err;
|
|
1201
|
+
if (attempt < maxRetries) {
|
|
1202
|
+
await new Promise(resolve => setTimeout(resolve, delayMs * (attempt + 1)));
|
|
1203
|
+
this.log(`Retrying (${attempt + 1}/${maxRetries}): ${err.message}`);
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
throw lastError;
|
|
1208
|
+
}
|
|
946
1209
|
// ── Memory Methods (→ Mnemosyne API) ───────────────────────────────────
|
|
947
1210
|
async remember(content, opts) {
|
|
948
|
-
|
|
949
|
-
|
|
1211
|
+
if (!content || typeof content !== "string")
|
|
1212
|
+
throw new Error("Memory content is required");
|
|
1213
|
+
if (content.length > 100_000)
|
|
1214
|
+
throw new Error("Memory content exceeds 100KB limit");
|
|
1215
|
+
// Security: sanitize against prompt injection (same as MnemoPayLite)
|
|
1216
|
+
const safeContent = sanitizeMemoryContent(content);
|
|
1217
|
+
const safeTags = validateTags(opts?.tags ?? []);
|
|
1218
|
+
const importance = opts?.importance ?? autoScore(safeContent);
|
|
1219
|
+
const result = await this.withRetry(() => this.mnemoFetch("/v1/memories", {
|
|
950
1220
|
method: "POST",
|
|
951
1221
|
body: JSON.stringify({
|
|
952
|
-
content,
|
|
1222
|
+
content: safeContent,
|
|
953
1223
|
tier: "long_term",
|
|
954
1224
|
metadata: {
|
|
955
1225
|
memory_type: "OBSERVATION",
|
|
956
|
-
tags:
|
|
1226
|
+
tags: safeTags,
|
|
957
1227
|
confidence: importance,
|
|
958
1228
|
},
|
|
959
1229
|
}),
|
|
960
|
-
});
|
|
961
|
-
this.emit("memory:stored", { id: result.id,
|
|
962
|
-
this.log(`Stored memory: "${
|
|
1230
|
+
}));
|
|
1231
|
+
this.emit("memory:stored", { id: result.id, importance });
|
|
1232
|
+
this.log(`Stored memory: "${safeContent.slice(0, 60)}..." (id: ${result.id})`);
|
|
963
1233
|
return result.id;
|
|
964
1234
|
}
|
|
965
1235
|
async recall(queryOrLimit, maybeLimit) {
|
|
@@ -1020,9 +1290,14 @@ class MnemoPay extends EventEmitter {
|
|
|
1020
1290
|
}
|
|
1021
1291
|
// ── Payment Methods (→ AgentPay API) ───────────────────────────────────
|
|
1022
1292
|
async charge(amount, reason) {
|
|
1023
|
-
if (amount <= 0)
|
|
1024
|
-
throw new Error("Amount must be positive");
|
|
1025
|
-
|
|
1293
|
+
if (!Number.isFinite(amount) || amount <= 0)
|
|
1294
|
+
throw new Error("Amount must be a positive finite number");
|
|
1295
|
+
amount = Math.round(amount * 100) / 100;
|
|
1296
|
+
if (!reason || typeof reason !== "string")
|
|
1297
|
+
throw new Error("Reason is required");
|
|
1298
|
+
if (reason.length > 1000)
|
|
1299
|
+
throw new Error("Reason exceeds 1000 character limit");
|
|
1300
|
+
const result = await this.withRetry(() => this.agentpayFetch("/api/escrow", {
|
|
1026
1301
|
method: "POST",
|
|
1027
1302
|
body: JSON.stringify({
|
|
1028
1303
|
agentId: this.agentId,
|
|
@@ -1030,7 +1305,7 @@ class MnemoPay extends EventEmitter {
|
|
|
1030
1305
|
reason,
|
|
1031
1306
|
currency: "USD",
|
|
1032
1307
|
}),
|
|
1033
|
-
});
|
|
1308
|
+
}));
|
|
1034
1309
|
const tx = {
|
|
1035
1310
|
id: result.id,
|
|
1036
1311
|
agentId: this.agentId,
|
|
@@ -1044,10 +1319,12 @@ class MnemoPay extends EventEmitter {
|
|
|
1044
1319
|
return tx;
|
|
1045
1320
|
}
|
|
1046
1321
|
async settle(txId) {
|
|
1047
|
-
|
|
1322
|
+
if (!txId || typeof txId !== "string")
|
|
1323
|
+
throw new Error("Transaction ID is required");
|
|
1324
|
+
const result = await this.withRetry(() => this.agentpayFetch(`/api/escrow/${encodeURIComponent(txId)}/release`, {
|
|
1048
1325
|
method: "POST",
|
|
1049
1326
|
body: JSON.stringify({}),
|
|
1050
|
-
});
|
|
1327
|
+
}));
|
|
1051
1328
|
this.emit("payment:completed", { id: txId, amount: result.amount });
|
|
1052
1329
|
this.log(`Settled: $${result.amount?.toFixed(2)}`);
|
|
1053
1330
|
return {
|
|
@@ -1061,10 +1338,12 @@ class MnemoPay extends EventEmitter {
|
|
|
1061
1338
|
};
|
|
1062
1339
|
}
|
|
1063
1340
|
async refund(txId) {
|
|
1064
|
-
|
|
1341
|
+
if (!txId || typeof txId !== "string")
|
|
1342
|
+
throw new Error("Transaction ID is required");
|
|
1343
|
+
const result = await this.withRetry(() => this.agentpayFetch(`/api/escrow/${encodeURIComponent(txId)}/refund`, {
|
|
1065
1344
|
method: "POST",
|
|
1066
1345
|
body: JSON.stringify({}),
|
|
1067
|
-
});
|
|
1346
|
+
}));
|
|
1068
1347
|
this.emit("payment:refunded", { id: txId });
|
|
1069
1348
|
this.log(`Refunded: ${txId}`);
|
|
1070
1349
|
return {
|
|
@@ -1150,7 +1429,7 @@ class MnemoPay extends EventEmitter {
|
|
|
1150
1429
|
name: `MnemoPay Agent (${this.agentId})`,
|
|
1151
1430
|
description: "AI agent with persistent cognitive memory and micropayment capabilities via MnemoPay protocol.",
|
|
1152
1431
|
url,
|
|
1153
|
-
version: "0.
|
|
1432
|
+
version: "0.9.2",
|
|
1154
1433
|
capabilities: {
|
|
1155
1434
|
memory: true,
|
|
1156
1435
|
payments: true,
|
|
@@ -1261,11 +1540,15 @@ var ledger_js_2 = require("./ledger.js");
|
|
|
1261
1540
|
Object.defineProperty(exports, "Ledger", { enumerable: true, get: function () { return ledger_js_2.Ledger; } });
|
|
1262
1541
|
var identity_js_2 = require("./identity.js");
|
|
1263
1542
|
Object.defineProperty(exports, "IdentityRegistry", { enumerable: true, get: function () { return identity_js_2.IdentityRegistry; } });
|
|
1543
|
+
Object.defineProperty(exports, "constantTimeEqual", { enumerable: true, get: function () { return identity_js_2.constantTimeEqual; } });
|
|
1264
1544
|
var network_js_1 = require("./network.js");
|
|
1265
1545
|
Object.defineProperty(exports, "MnemoPayNetwork", { enumerable: true, get: function () { return network_js_1.MnemoPayNetwork; } });
|
|
1266
1546
|
var commerce_js_1 = require("./commerce.js");
|
|
1267
1547
|
Object.defineProperty(exports, "CommerceEngine", { enumerable: true, get: function () { return commerce_js_1.CommerceEngine; } });
|
|
1268
1548
|
Object.defineProperty(exports, "MockCommerceProvider", { enumerable: true, get: function () { return commerce_js_1.MockCommerceProvider; } });
|
|
1549
|
+
var adaptive_js_2 = require("./adaptive.js");
|
|
1550
|
+
Object.defineProperty(exports, "AdaptiveEngine", { enumerable: true, get: function () { return adaptive_js_2.AdaptiveEngine; } });
|
|
1551
|
+
Object.defineProperty(exports, "DEFAULT_ADAPTIVE_CONFIG", { enumerable: true, get: function () { return adaptive_js_2.DEFAULT_ADAPTIVE_CONFIG; } });
|
|
1269
1552
|
var server_js_1 = require("./mcp/server.js");
|
|
1270
1553
|
Object.defineProperty(exports, "createSandboxServer", { enumerable: true, get: function () { return __importDefault(server_js_1).default; } });
|
|
1271
1554
|
//# sourceMappingURL=index.js.map
|