@elizaos/plugin-localdb 2.0.0-beta.1 → 2.0.3-beta.3

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Shaw Walters and elizaOS Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # @elizaos/plugin-localdb
2
+
3
+ Persistent local database adapter for elizaOS. Stores agent state to a JSON file on Node.js or to `localStorage` in the browser. No external database required.
4
+
5
+ ## What it does
6
+
7
+ elizaOS agents need a `DatabaseAdapter` to store memories, entities, rooms, relationships, tasks, and other runtime state. This plugin provides that adapter with local persistence:
8
+
9
+ - **Node.js:** all collections are written to a single `localdb.json` file. Data survives process restarts.
10
+ - **Browser:** all collections are written to `localStorage` under the key `elizaos:localdb:<agentId>`.
11
+
12
+ Vector search uses an in-memory HNSW index (cosine similarity). The index is rebuilt from embeddings written during the current session; it does not persist across restarts.
13
+
14
+ ## Capabilities added to an Eliza agent
15
+
16
+ - Full `IDatabaseAdapter` implementation: entities, memories (with vector search), rooms, worlds, components, relationships, participants, tasks, logs, cache, pairing requests.
17
+ - JSON-patch operations on component data (`set`, `remove`, `push`, `increment`).
18
+ - Levenshtein-based embedding cache lookup for deduplication.
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ npm install @elizaos/plugin-localdb
24
+ ```
25
+
26
+ Add the plugin to your agent character:
27
+
28
+ ```ts
29
+ import localdbPlugin from "@elizaos/plugin-localdb";
30
+
31
+ const character = {
32
+ plugins: [localdbPlugin],
33
+ // ...
34
+ };
35
+ ```
36
+
37
+ The plugin registers itself only if no other database adapter has already been loaded. Load order matters — place it after any preferred adapter so it acts as a fallback, or first if it is the intended adapter.
38
+
39
+ ## Configuration
40
+
41
+ | Environment variable | Default | Description |
42
+ |----------------------|---------|-------------|
43
+ | `LOCALDB_DATA_DIR` | `.eliza-localdb/` (process cwd) | Directory where `localdb.json` is written. Also readable as an agent setting under the same key. |
44
+
45
+ The browser entry ignores all env vars and uses `localStorage` automatically.
46
+
47
+ ## Limitations
48
+
49
+ - **Not for high write throughput.** The file backend flushes the entire JSON document after every write.
50
+ - **Vector index is not persisted.** Semantic memory search is unavailable for data written in previous sessions until new embeddings are stored.
51
+ - **No transaction atomicity.** Concurrent writes in a single process are not isolated.
52
+ - **Designed for development and lightweight deployments.** For production agents with large memory stores, prefer a SQL-backed adapter.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elizaos/plugin-localdb",
3
- "version": "2.0.0-beta.1",
3
+ "version": "2.0.3-beta.3",
4
4
  "type": "module",
5
5
  "description": "File-backed (Node) and localStorage (browser) persistence via plugin-inmemorydb; ships compiled ESM in dist/.",
6
6
  "main": "./dist/index.js",
@@ -23,33 +23,41 @@
23
23
  },
24
24
  "import": "./dist/index.js",
25
25
  "default": "./dist/index.js"
26
+ },
27
+ "./*.css": "./dist/*.css",
28
+ "./*": {
29
+ "types": "./dist/*.d.ts",
30
+ "import": "./dist/*.js",
31
+ "default": "./dist/*.js"
26
32
  }
27
33
  },
28
34
  "sideEffects": false,
29
35
  "files": [
36
+ "registry-entry.json",
30
37
  "dist"
31
38
  ],
32
39
  "scripts": {
33
40
  "build": "tsup --config tsup.config.ts",
34
41
  "dev": "tsup --config tsup.config.ts --watch",
35
42
  "clean": "rm -rf dist .turbo",
36
- "typecheck": "tsc --noEmit -p tsconfig.json",
37
- "lint": "echo \"Lint skipped\"",
38
- "lint:check": "bun run lint",
39
- "test": "echo \"No tests\""
43
+ "typecheck": "tsgo --noEmit -p tsconfig.json",
44
+ "lint": "bunx @biomejs/biome check --write --unsafe .",
45
+ "lint:check": "bunx @biomejs/biome check .",
46
+ "test": "vitest run"
40
47
  },
41
48
  "dependencies": {
42
- "@elizaos/core": "2.0.0-beta.1",
43
- "@elizaos/plugin-inmemorydb": "2.0.0-beta.1"
49
+ "@elizaos/core": "2.0.3-beta.3",
50
+ "@elizaos/plugin-inmemorydb": "2.0.3-beta.3"
44
51
  },
45
52
  "devDependencies": {
46
53
  "@types/node": "25.6.2",
47
54
  "tsup": "8.5.1",
48
- "typescript": "^6.0.3"
55
+ "typescript": "^6.0.3",
56
+ "vitest": "^4.0.18"
49
57
  },
50
58
  "peerDependencies": {
51
- "@elizaos/core": "2.0.0-beta.1",
52
- "@elizaos/plugin-inmemorydb": "2.0.0-beta.1"
59
+ "@elizaos/core": "2.0.3-beta.3",
60
+ "@elizaos/plugin-inmemorydb": "2.0.3-beta.3"
53
61
  },
54
62
  "publishConfig": {
55
63
  "access": "public"
@@ -58,5 +66,6 @@
58
66
  "type": "git",
59
67
  "url": "git+https://github.com/elizaos/eliza.git",
60
68
  "directory": "plugins/plugin-localdb"
61
- }
69
+ },
70
+ "gitHead": "f54b0f4eaed317d59fa7dbcdce20f4cdb0734420"
62
71
  }
@@ -0,0 +1,25 @@
1
+ {
2
+ "id": "localdb",
3
+ "name": "Localdb",
4
+ "description": "Simple JSON-based local database storage for elizaOS - no SQL, no migrations",
5
+ "npmName": "@elizaos/plugin-localdb",
6
+ "version": "2.0.0-beta.0",
7
+ "source": "bundled",
8
+ "tags": ["database", "storage", "localdb"],
9
+ "config": {},
10
+ "render": {
11
+ "visible": false,
12
+ "pinTo": [],
13
+ "style": "card",
14
+ "group": "feature-other",
15
+ "groupOrder": 12,
16
+ "actions": ["enable", "configure"]
17
+ },
18
+ "resources": {
19
+ "homepage": "https://github.com/elizaos-plugins/plugin-localdb#readme",
20
+ "repository": "https://github.com/elizaos-plugins/plugin-localdb"
21
+ },
22
+ "dependsOn": [],
23
+ "kind": "plugin",
24
+ "subtype": "database"
25
+ }
@@ -1,7 +0,0 @@
1
- import { UUID, Plugin } from '@elizaos/core';
2
- import { InMemoryDatabaseAdapter } from '@elizaos/plugin-inmemorydb';
3
-
4
- declare function createDatabaseAdapter(agentId: UUID): InMemoryDatabaseAdapter;
5
- declare const plugin: Plugin;
6
-
7
- export { createDatabaseAdapter, plugin as default, plugin };
@@ -1,113 +0,0 @@
1
- // index.browser.ts
2
- import {
3
- InMemoryDatabaseAdapter
4
- } from "@elizaos/plugin-inmemorydb";
5
- var BrowserLocalStorage = class {
6
- constructor(key) {
7
- this.key = key;
8
- }
9
- key;
10
- collections = /* @__PURE__ */ new Map();
11
- ready = false;
12
- async init() {
13
- const raw = globalThis.localStorage?.getItem(this.key);
14
- if (raw) {
15
- const parsed = JSON.parse(raw);
16
- for (const [collection, entries] of Object.entries(parsed)) {
17
- this.collections.set(collection, new Map(Object.entries(entries)));
18
- }
19
- }
20
- this.ready = true;
21
- }
22
- async close() {
23
- await this.flush();
24
- this.ready = false;
25
- }
26
- async isReady() {
27
- return this.ready;
28
- }
29
- getCollection(collection) {
30
- let current = this.collections.get(collection);
31
- if (!current) {
32
- current = /* @__PURE__ */ new Map();
33
- this.collections.set(collection, current);
34
- }
35
- return current;
36
- }
37
- async flush() {
38
- const out = {};
39
- for (const [collection, entries] of this.collections) {
40
- out[collection] = Object.fromEntries(entries);
41
- }
42
- globalThis.localStorage?.setItem(this.key, JSON.stringify(out));
43
- }
44
- async get(collection, id) {
45
- const item = this.getCollection(collection).get(id);
46
- return item === void 0 ? null : item;
47
- }
48
- async getAll(collection) {
49
- return Array.from(this.getCollection(collection).values());
50
- }
51
- async getWhere(collection, predicate) {
52
- return (await this.getAll(collection)).filter(predicate);
53
- }
54
- async set(collection, id, data) {
55
- this.getCollection(collection).set(id, data);
56
- await this.flush();
57
- }
58
- async delete(collection, id) {
59
- const deleted = this.getCollection(collection).delete(id);
60
- if (deleted) await this.flush();
61
- return deleted;
62
- }
63
- async deleteMany(collection, ids) {
64
- const current = this.getCollection(collection);
65
- for (const id of ids) current.delete(id);
66
- await this.flush();
67
- }
68
- async deleteWhere(collection, predicate) {
69
- const current = this.getCollection(collection);
70
- for (const [id, item] of current) {
71
- if (predicate(item)) current.delete(id);
72
- }
73
- await this.flush();
74
- }
75
- async count(collection, predicate) {
76
- const current = this.getCollection(collection);
77
- if (!predicate) return current.size;
78
- let total = 0;
79
- for (const item of current.values()) {
80
- if (predicate(item)) total++;
81
- }
82
- return total;
83
- }
84
- async clear() {
85
- this.collections.clear();
86
- await this.flush();
87
- }
88
- };
89
- function createDatabaseAdapter(agentId) {
90
- return new InMemoryDatabaseAdapter(
91
- new BrowserLocalStorage(`elizaos:localdb:${agentId}`),
92
- agentId
93
- );
94
- }
95
- var plugin = {
96
- name: "@elizaos/plugin-localdb",
97
- description: "Browser localStorage database storage for elizaOS examples.",
98
- async init(_config, runtime) {
99
- const r = runtime;
100
- const hasAdapter = r.adapter !== void 0 || r.databaseAdapter !== void 0 || (r.hasDatabaseAdapter?.() ?? false);
101
- if (hasAdapter) return;
102
- const adapter = createDatabaseAdapter(runtime.agentId);
103
- await adapter.initialize();
104
- r.registerDatabaseAdapter?.(adapter);
105
- }
106
- };
107
- var index_browser_default = plugin;
108
- export {
109
- createDatabaseAdapter,
110
- index_browser_default as default,
111
- plugin
112
- };
113
- //# sourceMappingURL=index.browser.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../index.browser.ts"],"sourcesContent":["import type {\n IAgentRuntime,\n IDatabaseAdapter,\n Plugin,\n UUID,\n} from \"@elizaos/core\";\nimport {\n InMemoryDatabaseAdapter,\n type IStorage,\n} from \"@elizaos/plugin-inmemorydb\";\n\ntype RuntimeWithDatabase = IAgentRuntime & {\n registerDatabaseAdapter?: (adapter: IDatabaseAdapter) => void;\n adapter?: IDatabaseAdapter;\n databaseAdapter?: IDatabaseAdapter;\n hasDatabaseAdapter?: () => boolean;\n};\n\nclass BrowserLocalStorage implements IStorage {\n private collections = new Map<string, Map<string, unknown>>();\n private ready = false;\n\n constructor(private readonly key: string) {}\n\n async init(): Promise<void> {\n const raw = globalThis.localStorage?.getItem(this.key);\n if (raw) {\n const parsed = JSON.parse(raw) as Record<string, Record<string, unknown>>;\n for (const [collection, entries] of Object.entries(parsed)) {\n this.collections.set(collection, new Map(Object.entries(entries)));\n }\n }\n this.ready = true;\n }\n\n async close(): Promise<void> {\n await this.flush();\n this.ready = false;\n }\n\n async isReady(): Promise<boolean> {\n return this.ready;\n }\n\n private getCollection(collection: string): Map<string, unknown> {\n let current = this.collections.get(collection);\n if (!current) {\n current = new Map();\n this.collections.set(collection, current);\n }\n return current;\n }\n\n private async flush(): Promise<void> {\n const out: Record<string, Record<string, unknown>> = {};\n for (const [collection, entries] of this.collections) {\n out[collection] = Object.fromEntries(entries);\n }\n globalThis.localStorage?.setItem(this.key, JSON.stringify(out));\n }\n\n async get<T>(collection: string, id: string): Promise<T | null> {\n const item = this.getCollection(collection).get(id);\n return item === undefined ? null : (item as T);\n }\n\n async getAll<T>(collection: string): Promise<T[]> {\n return Array.from(this.getCollection(collection).values()) as T[];\n }\n\n async getWhere<T>(\n collection: string,\n predicate: (item: T) => boolean,\n ): Promise<T[]> {\n return (await this.getAll<T>(collection)).filter(predicate);\n }\n\n async set<T>(collection: string, id: string, data: T): Promise<void> {\n this.getCollection(collection).set(id, data);\n await this.flush();\n }\n\n async delete(collection: string, id: string): Promise<boolean> {\n const deleted = this.getCollection(collection).delete(id);\n if (deleted) await this.flush();\n return deleted;\n }\n\n async deleteMany(collection: string, ids: string[]): Promise<void> {\n const current = this.getCollection(collection);\n for (const id of ids) current.delete(id);\n await this.flush();\n }\n\n async deleteWhere<T = Record<string, unknown>>(\n collection: string,\n predicate: (item: T) => boolean,\n ): Promise<void> {\n const current = this.getCollection(collection);\n for (const [id, item] of current) {\n if (predicate(item as T)) current.delete(id);\n }\n await this.flush();\n }\n\n async count<T = Record<string, unknown>>(\n collection: string,\n predicate?: (item: T) => boolean,\n ): Promise<number> {\n const current = this.getCollection(collection);\n if (!predicate) return current.size;\n let total = 0;\n for (const item of current.values()) {\n if (predicate(item as T)) total++;\n }\n return total;\n }\n\n async clear(): Promise<void> {\n this.collections.clear();\n await this.flush();\n }\n}\n\nexport function createDatabaseAdapter(agentId: UUID): InMemoryDatabaseAdapter {\n return new InMemoryDatabaseAdapter(\n new BrowserLocalStorage(`elizaos:localdb:${agentId}`),\n agentId,\n );\n}\n\nexport const plugin: Plugin = {\n name: \"@elizaos/plugin-localdb\",\n description: \"Browser localStorage database storage for elizaOS examples.\",\n\n async init(\n _config: Record<string, string>,\n runtime: IAgentRuntime,\n ): Promise<void> {\n const r = runtime as RuntimeWithDatabase;\n const hasAdapter =\n r.adapter !== undefined ||\n r.databaseAdapter !== undefined ||\n (r.hasDatabaseAdapter?.() ?? false);\n\n if (hasAdapter) return;\n\n const adapter = createDatabaseAdapter(runtime.agentId);\n await adapter.initialize();\n r.registerDatabaseAdapter?.(adapter);\n },\n};\n\nexport default plugin;\n"],"mappings":"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","names":[]}
package/dist/index.d.ts DELETED
@@ -1,7 +0,0 @@
1
- import { UUID, Plugin } from '@elizaos/core';
2
- import { InMemoryDatabaseAdapter } from '@elizaos/plugin-inmemorydb';
3
-
4
- declare function createDatabaseAdapter(agentId: UUID, dataDir: string): InMemoryDatabaseAdapter;
5
- declare const plugin: Plugin;
6
-
7
- export { createDatabaseAdapter, plugin as default, plugin };
package/dist/index.js DELETED
@@ -1,128 +0,0 @@
1
- // index.ts
2
- import { mkdir, readFile, writeFile } from "fs/promises";
3
- import { dirname, join } from "path";
4
- import { logger } from "@elizaos/core";
5
- import {
6
- InMemoryDatabaseAdapter
7
- } from "@elizaos/plugin-inmemorydb";
8
- var FileStorage = class {
9
- collections = /* @__PURE__ */ new Map();
10
- ready = false;
11
- filePath;
12
- constructor(dataDir) {
13
- this.filePath = join(dataDir, "localdb.json");
14
- }
15
- async init() {
16
- await mkdir(dirname(this.filePath), { recursive: true });
17
- try {
18
- const raw = await readFile(this.filePath, "utf8");
19
- const parsed = JSON.parse(raw);
20
- for (const [collection, entries] of Object.entries(parsed)) {
21
- this.collections.set(collection, new Map(Object.entries(entries)));
22
- }
23
- } catch (error) {
24
- if (error.code !== "ENOENT") throw error;
25
- }
26
- this.ready = true;
27
- }
28
- async close() {
29
- await this.flush();
30
- this.ready = false;
31
- }
32
- async isReady() {
33
- return this.ready;
34
- }
35
- getCollection(collection) {
36
- let current = this.collections.get(collection);
37
- if (!current) {
38
- current = /* @__PURE__ */ new Map();
39
- this.collections.set(collection, current);
40
- }
41
- return current;
42
- }
43
- async flush() {
44
- const out = {};
45
- for (const [collection, entries] of this.collections) {
46
- out[collection] = Object.fromEntries(entries);
47
- }
48
- await writeFile(this.filePath, JSON.stringify(out, null, 2), "utf8");
49
- }
50
- async get(collection, id) {
51
- const item = this.getCollection(collection).get(id);
52
- return item === void 0 ? null : item;
53
- }
54
- async getAll(collection) {
55
- return Array.from(this.getCollection(collection).values());
56
- }
57
- async getWhere(collection, predicate) {
58
- return (await this.getAll(collection)).filter(predicate);
59
- }
60
- async set(collection, id, data) {
61
- this.getCollection(collection).set(id, data);
62
- await this.flush();
63
- }
64
- async delete(collection, id) {
65
- const deleted = this.getCollection(collection).delete(id);
66
- if (deleted) await this.flush();
67
- return deleted;
68
- }
69
- async deleteMany(collection, ids) {
70
- const current = this.getCollection(collection);
71
- for (const id of ids) current.delete(id);
72
- await this.flush();
73
- }
74
- async deleteWhere(collection, predicate) {
75
- const current = this.getCollection(collection);
76
- for (const [id, item] of current) {
77
- if (predicate(item)) current.delete(id);
78
- }
79
- await this.flush();
80
- }
81
- async count(collection, predicate) {
82
- const current = this.getCollection(collection);
83
- if (!predicate) return current.size;
84
- let total = 0;
85
- for (const item of current.values()) {
86
- if (predicate(item)) total++;
87
- }
88
- return total;
89
- }
90
- async clear() {
91
- this.collections.clear();
92
- await this.flush();
93
- }
94
- };
95
- function getDataDir(runtime) {
96
- const configured = runtime.getSetting?.("LOCALDB_DATA_DIR");
97
- if (typeof configured === "string" && configured.length > 0) {
98
- return configured;
99
- }
100
- const envDir = process.env.LOCALDB_DATA_DIR;
101
- if (typeof envDir === "string" && envDir.length > 0) {
102
- return envDir;
103
- }
104
- return join(process.cwd(), ".eliza-localdb");
105
- }
106
- function createDatabaseAdapter(agentId, dataDir) {
107
- return new InMemoryDatabaseAdapter(new FileStorage(dataDir), agentId);
108
- }
109
- var plugin = {
110
- name: "@elizaos/plugin-localdb",
111
- description: "Local JSON-file database storage for elizaOS examples.",
112
- async init(_config, runtime) {
113
- const r = runtime;
114
- const hasAdapter = r.adapter !== void 0 || r.databaseAdapter !== void 0 || (r.hasDatabaseAdapter?.() ?? false);
115
- if (hasAdapter) return;
116
- const adapter = createDatabaseAdapter(runtime.agentId, getDataDir(r));
117
- await adapter.initialize();
118
- r.registerDatabaseAdapter?.(adapter);
119
- logger.info({ src: "plugin:localdb" }, "Local database adapter registered");
120
- }
121
- };
122
- var index_default = plugin;
123
- export {
124
- createDatabaseAdapter,
125
- index_default as default,
126
- plugin
127
- };
128
- //# sourceMappingURL=index.js.map
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../index.ts"],"sourcesContent":["import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport type {\n IAgentRuntime,\n IDatabaseAdapter,\n Plugin,\n UUID,\n} from \"@elizaos/core\";\nimport { logger } from \"@elizaos/core\";\nimport {\n InMemoryDatabaseAdapter,\n type IStorage,\n} from \"@elizaos/plugin-inmemorydb\";\n\ntype RuntimeWithDatabase = IAgentRuntime & {\n registerDatabaseAdapter?: (adapter: IDatabaseAdapter) => void;\n adapter?: IDatabaseAdapter;\n databaseAdapter?: IDatabaseAdapter;\n hasDatabaseAdapter?: () => boolean;\n getSetting?: (key: string) => string | undefined;\n};\n\nclass FileStorage implements IStorage {\n private collections = new Map<string, Map<string, unknown>>();\n private ready = false;\n private readonly filePath: string;\n\n constructor(dataDir: string) {\n this.filePath = join(dataDir, \"localdb.json\");\n }\n\n async init(): Promise<void> {\n await mkdir(dirname(this.filePath), { recursive: true });\n try {\n const raw = await readFile(this.filePath, \"utf8\");\n const parsed = JSON.parse(raw) as Record<string, Record<string, unknown>>;\n for (const [collection, entries] of Object.entries(parsed)) {\n this.collections.set(collection, new Map(Object.entries(entries)));\n }\n } catch (error) {\n if ((error as { code?: string }).code !== \"ENOENT\") throw error;\n }\n this.ready = true;\n }\n\n async close(): Promise<void> {\n await this.flush();\n this.ready = false;\n }\n\n async isReady(): Promise<boolean> {\n return this.ready;\n }\n\n private getCollection(collection: string): Map<string, unknown> {\n let current = this.collections.get(collection);\n if (!current) {\n current = new Map();\n this.collections.set(collection, current);\n }\n return current;\n }\n\n private async flush(): Promise<void> {\n const out: Record<string, Record<string, unknown>> = {};\n for (const [collection, entries] of this.collections) {\n out[collection] = Object.fromEntries(entries);\n }\n await writeFile(this.filePath, JSON.stringify(out, null, 2), \"utf8\");\n }\n\n async get<T>(collection: string, id: string): Promise<T | null> {\n const item = this.getCollection(collection).get(id);\n return item === undefined ? null : (item as T);\n }\n\n async getAll<T>(collection: string): Promise<T[]> {\n return Array.from(this.getCollection(collection).values()) as T[];\n }\n\n async getWhere<T>(\n collection: string,\n predicate: (item: T) => boolean,\n ): Promise<T[]> {\n return (await this.getAll<T>(collection)).filter(predicate);\n }\n\n async set<T>(collection: string, id: string, data: T): Promise<void> {\n this.getCollection(collection).set(id, data);\n await this.flush();\n }\n\n async delete(collection: string, id: string): Promise<boolean> {\n const deleted = this.getCollection(collection).delete(id);\n if (deleted) await this.flush();\n return deleted;\n }\n\n async deleteMany(collection: string, ids: string[]): Promise<void> {\n const current = this.getCollection(collection);\n for (const id of ids) current.delete(id);\n await this.flush();\n }\n\n async deleteWhere<T = Record<string, unknown>>(\n collection: string,\n predicate: (item: T) => boolean,\n ): Promise<void> {\n const current = this.getCollection(collection);\n for (const [id, item] of current) {\n if (predicate(item as T)) current.delete(id);\n }\n await this.flush();\n }\n\n async count<T = Record<string, unknown>>(\n collection: string,\n predicate?: (item: T) => boolean,\n ): Promise<number> {\n const current = this.getCollection(collection);\n if (!predicate) return current.size;\n let total = 0;\n for (const item of current.values()) {\n if (predicate(item as T)) total++;\n }\n return total;\n }\n\n async clear(): Promise<void> {\n this.collections.clear();\n await this.flush();\n }\n}\n\nfunction getDataDir(runtime: RuntimeWithDatabase): string {\n const configured = runtime.getSetting?.(\"LOCALDB_DATA_DIR\");\n if (typeof configured === \"string\" && configured.length > 0) {\n return configured;\n }\n\n const envDir = process.env.LOCALDB_DATA_DIR;\n if (typeof envDir === \"string\" && envDir.length > 0) {\n return envDir;\n }\n\n return join(process.cwd(), \".eliza-localdb\");\n}\n\nexport function createDatabaseAdapter(\n agentId: UUID,\n dataDir: string,\n): InMemoryDatabaseAdapter {\n return new InMemoryDatabaseAdapter(new FileStorage(dataDir), agentId);\n}\n\nexport const plugin: Plugin = {\n name: \"@elizaos/plugin-localdb\",\n description: \"Local JSON-file database storage for elizaOS examples.\",\n\n async init(\n _config: Record<string, string>,\n runtime: IAgentRuntime,\n ): Promise<void> {\n const r = runtime as RuntimeWithDatabase;\n const hasAdapter =\n r.adapter !== undefined ||\n r.databaseAdapter !== undefined ||\n (r.hasDatabaseAdapter?.() ?? false);\n\n if (hasAdapter) return;\n\n const adapter = createDatabaseAdapter(runtime.agentId, getDataDir(r));\n await adapter.initialize();\n r.registerDatabaseAdapter?.(adapter);\n logger.info({ src: \"plugin:localdb\" }, \"Local database adapter registered\");\n },\n};\n\nexport default plugin;\n"],"mappings":"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","names":[]}