@agent-diaries/core 0.1.1 → 0.1.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/README.md CHANGED
@@ -17,7 +17,7 @@
17
17
 
18
18
  - **🚫 Deduplication & Loop Prevention:** Automatically filter out tasks your agent has already seen.
19
19
  - **🔒 Fully Lock-Safe:** Uses atomic spin-locks and advisory locks to completely eliminate race conditions, even with 50+ concurrent agents processing the exact same task simultaneously.
20
- - **☁️ Cloud-Native Adapters:** Comes with official adapters for **Redis** and **PostgreSQL** for Vercel/AWS Lambda deployments, plus a local file adapter for development.
20
+ - **☁️ Cloud-Native Adapters:** Comes with official adapters for **Redis** and **MongoDB** for Vercel/AWS Lambda deployments, plus a local file adapter for development.
21
21
  - **⚡ Ultra-Lightweight:** Negligible bundle size, zero heavy dependencies.
22
22
 
23
23
  ## 📦 Installation
@@ -32,7 +32,7 @@ If you plan to use a specific cloud adapter, install its peer dependency:
32
32
 
33
33
  ```bash
34
34
  npm install ioredis # For Redis Storage
35
- npm install pg # For PostgreSQL Storage
35
+ npm install mongodb # For MongoDB Storage
36
36
  ```
37
37
 
38
38
  ## 🚀 Quick Start
@@ -104,6 +104,55 @@ const diary = new AgentDiary({
104
104
  });
105
105
  ```
106
106
 
107
+ ## 📊 200-Agent Real-World Cloud Benchmarks
108
+
109
+ Agent Diaries Core is mathematically proven to handle massive concurrent agent swarms without race conditions or database corruption.
110
+
111
+ To prove its viability for enterprise serverless deployments, we rigorously stress-tested the library against a **Live Cloud Upstash Redis Database**, blasting it with **200 serverless agents** executing distributed lock requests across the internet at the exact same millisecond.
112
+
113
+ ### The Real-Life Architecture
114
+ ```typescript
115
+ const NUM_AGENTS = 200;
116
+ let agents = Array.from({ length: NUM_AGENTS }, () => getDiary());
117
+ const viralTask = `Analyze breaking news: OpenAI releases GPT-5 - ${Date.now()}`;
118
+
119
+ // Fire 200 distributed agents at the exact same millisecond
120
+ let results = await Promise.all(
121
+ agents.map(agent => agent.claimTask(viralTask).catch(() => false))
122
+ );
123
+
124
+ let successful = results.filter(r => r === true).length;
125
+ console.log(` Actual Locks: ${successful}`); // Always exactly 1.
126
+ ```
127
+
128
+ ### The Results (Zero Race Conditions)
129
+ > *Tested via WAN connection to an Upstash Serverless Redis instance*
130
+
131
+ ```text
132
+ =================================
133
+ 🌪️ INITIALIZING 200-AGENT SWARM: Upstash Redis (Cloud)
134
+ =================================
135
+ [Test 1] The Herd Effect: 200 Agents competing for exactly ONE viral task...
136
+ Expected Locks: 1
137
+ Actual Locks: 1
138
+ Resolution Time: 13254ms
139
+ 🟢 PASSED (199 race conditions prevented)
140
+
141
+ [Test 2] Real World Distribution: 200 Agents processing 10 common data tasks...
142
+ Expected Locks: 10
143
+ Actual Locks: 10
144
+ Resolution Time: 12828ms
145
+ 🟢 PASSED (190 duplicate LLM calls prevented)
146
+
147
+ [Test 3] Extreme Write Contention: 200 Agents blasting state updates at the exact same time...
148
+ Expected Written: 200
149
+ Actual Written: 200
150
+ Write Duration: 16267ms
151
+ 🟢 PASSED (Zero data corruption)
152
+ ```
153
+
154
+ **💡 Engineering Insight:** While SQL databases perform well on local network environments, relational connection poolers (like pgBouncer or Supavisor) completely buckle under the massive concurrent TCP bursts generated by serverless AI swarms. **Redis or MongoDB (via atomic upserts)** are strictly required for reliable lock management in high-concurrency serverless edge environments.
155
+
107
156
  ## 📚 API Reference
108
157
 
109
158
  - **`diary.claimTask(title: string): Promise<boolean>`**
@@ -0,0 +1,12 @@
1
+ import { StorageAdapter } from '../storage';
2
+ import { Collection } from 'mongodb';
3
+ export declare class MongoStorage<T> implements StorageAdapter<T> {
4
+ private collection;
5
+ constructor(config: {
6
+ collection: Collection;
7
+ });
8
+ private hashString;
9
+ get(key: string): Promise<T | null>;
10
+ set(key: string, data: T): Promise<void>;
11
+ withLock<R>(key: string, fn: () => Promise<R>): Promise<R>;
12
+ }
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MongoStorage = void 0;
7
+ const crypto_1 = __importDefault(require("crypto"));
8
+ class MongoStorage {
9
+ collection;
10
+ constructor(config) {
11
+ this.collection = config.collection;
12
+ }
13
+ hashString(str) {
14
+ return crypto_1.default.createHash('sha256').update(str).digest('hex');
15
+ }
16
+ async get(key) {
17
+ const hash = this.hashString(key);
18
+ const doc = await this.collection.findOne({ _id: hash });
19
+ if (!doc || !doc.data)
20
+ return null;
21
+ return JSON.parse(doc.data);
22
+ }
23
+ async set(key, data) {
24
+ const hash = this.hashString(key);
25
+ await this.collection.updateOne({ _id: hash }, { $set: { data: JSON.stringify(data) } }, { upsert: true });
26
+ }
27
+ async withLock(key, fn) {
28
+ const hash = this.hashString(key);
29
+ const lockId = `lock:${hash}`;
30
+ const acquireLock = async () => {
31
+ try {
32
+ await this.collection.insertOne({ _id: lockId, lockedAt: new Date() });
33
+ return true;
34
+ }
35
+ catch (error) {
36
+ if (error.code === 11000)
37
+ return false;
38
+ throw error;
39
+ }
40
+ };
41
+ while (!(await acquireLock())) {
42
+ await new Promise(resolve => setTimeout(resolve, 50));
43
+ }
44
+ try {
45
+ return await fn();
46
+ }
47
+ finally {
48
+ await this.collection.deleteOne({ _id: lockId });
49
+ }
50
+ }
51
+ }
52
+ exports.MongoStorage = MongoStorage;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-diaries/core",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "The lightweight, framework-agnostic memory layer for edge AI agents.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -31,8 +31,8 @@
31
31
  "homepage": "https://github.com/swapwarick/agent-diaries-core#readme",
32
32
  "license": "MIT",
33
33
  "devDependencies": {
34
+ "@types/dotenv": "^6.1.1",
34
35
  "@types/node": "^20.0.0",
35
- "@types/pg": "^8.20.0",
36
36
  "@types/proper-lockfile": "^4.1.4",
37
37
  "@vitest/coverage-v8": "^4.1.5",
38
38
  "ts-node": "^10.9.2",
@@ -40,8 +40,9 @@
40
40
  "vitest": "^4.1.5"
41
41
  },
42
42
  "dependencies": {
43
+ "dotenv": "^17.4.2",
43
44
  "ioredis": "^5.10.1",
44
- "pg": "^8.20.0",
45
+ "mongodb": "^7.2.0",
45
46
  "proper-lockfile": "^4.1.2"
46
47
  }
47
- }
48
+ }