@celiums/modules-starter 0.1.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/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ Creative Commons Attribution-NonCommercial 4.0 International
2
+
3
+ Copyright (c) 2026 Celiums Solutions LLC
4
+
5
+ You are free to:
6
+ Share — copy and redistribute the material in any medium or format
7
+ Adapt — remix, transform, and build upon the material
8
+
9
+ Under the following terms:
10
+ Attribution — You must give appropriate credit, provide a link to
11
+ the license, and indicate if changes were made.
12
+
13
+ NonCommercial — You may not use the material for commercial purposes.
14
+ You may not sell, sublicense, or redistribute these modules as a
15
+ standalone knowledge product or dataset.
16
+
17
+ The licensor cannot revoke these freedoms as long as you follow the
18
+ license terms.
19
+
20
+ Full license text: https://creativecommons.org/licenses/by-nc/4.0/legalcode
21
+
22
+ ---
23
+
24
+ These modules are curated expert knowledge units created by Celiums
25
+ Solutions LLC. They are provided free of charge for use with the
26
+ Celiums OpenCore platform. Using them to build your own projects,
27
+ learn, and improve your AI workflows is encouraged. Repackaging
28
+ and selling them is not permitted.
Binary file
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@celiums/modules-starter",
3
+ "version": "0.1.0",
4
+ "description": "5,100 curated expert knowledge modules for the Celiums OpenCore. Covers 18 developer categories: software engineering, frontend, backend, DevOps, databases, security, AI/ML, and more.",
5
+ "keywords": [
6
+ "celiums", "knowledge", "modules", "ai", "mcp",
7
+ "developer-tools", "curated", "expert-knowledge"
8
+ ],
9
+ "homepage": "https://celiums.ai",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/terrizoaguimor/celiums-memory.git",
13
+ "directory": "packages/modules-starter"
14
+ },
15
+ "license": "CC-BY-NC-4.0",
16
+ "author": {
17
+ "name": "Celiums Solutions LLC",
18
+ "email": "hello@celiums.ai",
19
+ "url": "https://celiums.ai"
20
+ },
21
+ "type": "module",
22
+ "main": "./src/index.ts",
23
+ "exports": {
24
+ ".": {
25
+ "import": "./src/index.ts"
26
+ }
27
+ },
28
+ "files": [
29
+ "src",
30
+ "data",
31
+ "LICENSE",
32
+ "README.md"
33
+ ],
34
+ "dependencies": {
35
+ "pg": "^8.13.0"
36
+ },
37
+ "optionalDependencies": {
38
+ "better-sqlite3": "^11.5.0"
39
+ }
40
+ }
package/src/index.ts ADDED
@@ -0,0 +1,215 @@
1
+ /**
2
+ * @celiums/modules-starter — 5,100 curated expert knowledge modules
3
+ *
4
+ * This package ships the free OpenCore module library. These are
5
+ * the modules that every Celiums user gets out of the box — covering
6
+ * 18 developer categories from software engineering to AI/ML.
7
+ *
8
+ * Usage:
9
+ * import { hydrate } from '@celiums/modules-starter';
10
+ * await hydrate({ pg: pool }); // PostgreSQL
11
+ * await hydrate({ sqlite: db }); // better-sqlite3
12
+ * const modules = await loadAll(); // in-memory array
13
+ *
14
+ * License: CC-BY-NC-4.0 (use freely, cannot resell)
15
+ *
16
+ * @package @celiums/modules-starter
17
+ */
18
+
19
+ import { createReadStream } from 'node:fs';
20
+ import { createGunzip } from 'node:zlib';
21
+ import { createInterface } from 'node:readline';
22
+ import { fileURLToPath } from 'node:url';
23
+ import { dirname, join } from 'node:path';
24
+
25
+ const __filename = fileURLToPath(import.meta.url);
26
+ const __dirname = dirname(__filename);
27
+ const SEED_PATH = join(__dirname, '..', 'data', 'seed.jsonl.gz');
28
+
29
+ export interface StarterModule {
30
+ name: string;
31
+ displayName: string;
32
+ description: string;
33
+ category: string;
34
+ keywords: string[];
35
+ lineCount: number;
36
+ evalScore: number | null;
37
+ version: string;
38
+ content: string;
39
+ }
40
+
41
+ /**
42
+ * Stream modules from the seed file one at a time.
43
+ * Memory-efficient — never loads all 5K into RAM at once.
44
+ */
45
+ export async function* streamModules(): AsyncGenerator<StarterModule> {
46
+ const gunzip = createGunzip();
47
+ const input = createReadStream(SEED_PATH).pipe(gunzip);
48
+ const rl = createInterface({ input, crlfDelay: Infinity });
49
+
50
+ for await (const line of rl) {
51
+ if (!line.trim()) continue;
52
+ yield JSON.parse(line) as StarterModule;
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Load all modules into memory. ~5,100 modules, ~80 MB uncompressed.
58
+ * Use streamModules() if you want to process one at a time.
59
+ */
60
+ export async function loadAll(): Promise<StarterModule[]> {
61
+ const modules: StarterModule[] = [];
62
+ for await (const m of streamModules()) {
63
+ modules.push(m);
64
+ }
65
+ return modules;
66
+ }
67
+
68
+ /**
69
+ * Get the total module count without loading content.
70
+ */
71
+ export async function count(): Promise<number> {
72
+ let n = 0;
73
+ const gunzip = createGunzip();
74
+ const input = createReadStream(SEED_PATH).pipe(gunzip);
75
+ const rl = createInterface({ input, crlfDelay: Infinity });
76
+ for await (const line of rl) {
77
+ if (line.trim()) n++;
78
+ }
79
+ return n;
80
+ }
81
+
82
+ /**
83
+ * Hydrate a database with the starter modules.
84
+ * Supports PostgreSQL (pg.Pool) and better-sqlite3.
85
+ *
86
+ * Creates the `modules` table if it doesn't exist and inserts
87
+ * all 5,100 modules. Idempotent — uses ON CONFLICT DO NOTHING.
88
+ */
89
+ export async function hydrate(target: {
90
+ pg?: any; // pg.Pool instance
91
+ sqlite?: any; // better-sqlite3 Database instance
92
+ }): Promise<{ inserted: number; skipped: number; totalMs: number }> {
93
+ const t0 = Date.now();
94
+
95
+ if (target.pg) {
96
+ return hydratePg(target.pg, t0);
97
+ }
98
+ if (target.sqlite) {
99
+ return hydrateSqlite(target.sqlite, t0);
100
+ }
101
+ throw new Error('hydrate() requires { pg: Pool } or { sqlite: Database }');
102
+ }
103
+
104
+ // ── PostgreSQL hydration ──────────────────────────────────
105
+
106
+ const PG_CREATE_TABLE = `
107
+ CREATE TABLE IF NOT EXISTS modules (
108
+ name TEXT PRIMARY KEY,
109
+ display_name TEXT NOT NULL,
110
+ description TEXT NOT NULL DEFAULT '',
111
+ category TEXT NOT NULL DEFAULT 'general',
112
+ keywords TEXT[] NOT NULL DEFAULT '{}',
113
+ line_count INTEGER NOT NULL DEFAULT 0,
114
+ eval_score NUMERIC(4,1),
115
+ version TEXT NOT NULL DEFAULT '2.0',
116
+ content TEXT NOT NULL DEFAULT '',
117
+ search_tsv TSVECTOR GENERATED ALWAYS AS (
118
+ setweight(to_tsvector('english', coalesce(name, '')), 'A') ||
119
+ setweight(to_tsvector('english', coalesce(display_name, '')), 'A') ||
120
+ setweight(to_tsvector('english', coalesce(description, '')), 'B') ||
121
+ setweight(to_tsvector('english', coalesce(array_to_string(keywords, ' '), '')), 'C')
122
+ ) STORED,
123
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
124
+ );
125
+
126
+ CREATE INDEX IF NOT EXISTS idx_modules_category ON modules(category);
127
+ CREATE INDEX IF NOT EXISTS idx_modules_search_tsv ON modules USING GIN(search_tsv);
128
+ CREATE INDEX IF NOT EXISTS idx_modules_eval ON modules(eval_score DESC NULLS LAST);
129
+ `;
130
+
131
+ async function hydratePg(pool: any, t0: number) {
132
+ const client = await pool.connect();
133
+ let inserted = 0;
134
+ let skipped = 0;
135
+ try {
136
+ await client.query(PG_CREATE_TABLE);
137
+ await client.query('BEGIN');
138
+ for await (const m of streamModules()) {
139
+ const r = await client.query(
140
+ `INSERT INTO modules (name, display_name, description, category, keywords, line_count, eval_score, version, content)
141
+ VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)
142
+ ON CONFLICT (name) DO NOTHING`,
143
+ [m.name, m.displayName, m.description, m.category, m.keywords, m.lineCount, m.evalScore, m.version, m.content],
144
+ );
145
+ if (r.rowCount && r.rowCount > 0) inserted++;
146
+ else skipped++;
147
+ }
148
+ await client.query('COMMIT');
149
+ } catch (e) {
150
+ await client.query('ROLLBACK');
151
+ throw e;
152
+ } finally {
153
+ client.release();
154
+ }
155
+ return { inserted, skipped, totalMs: Date.now() - t0 };
156
+ }
157
+
158
+ // ── SQLite hydration (FTS5) ──────────────────────────────
159
+
160
+ const SQLITE_CREATE_TABLE = `
161
+ CREATE TABLE IF NOT EXISTS modules (
162
+ name TEXT PRIMARY KEY,
163
+ display_name TEXT NOT NULL,
164
+ description TEXT NOT NULL DEFAULT '',
165
+ category TEXT NOT NULL DEFAULT 'general',
166
+ keywords TEXT NOT NULL DEFAULT '',
167
+ line_count INTEGER NOT NULL DEFAULT 0,
168
+ eval_score REAL,
169
+ version TEXT NOT NULL DEFAULT '2.0',
170
+ content TEXT NOT NULL DEFAULT ''
171
+ );
172
+
173
+ CREATE VIRTUAL TABLE IF NOT EXISTS modules_fts USING fts5(
174
+ name, display_name, description, keywords, content,
175
+ content=modules, content_rowid=rowid
176
+ );
177
+
178
+ CREATE TRIGGER IF NOT EXISTS modules_ai AFTER INSERT ON modules BEGIN
179
+ INSERT INTO modules_fts(rowid, name, display_name, description, keywords, content)
180
+ VALUES (new.rowid, new.name, new.display_name, new.description, new.keywords, new.content);
181
+ END;
182
+ `;
183
+
184
+ async function hydrateSqlite(db: any, t0: number) {
185
+ db.exec(SQLITE_CREATE_TABLE);
186
+ const insert = db.prepare(
187
+ `INSERT OR IGNORE INTO modules (name, display_name, description, category, keywords, line_count, eval_score, version, content)
188
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
189
+ );
190
+ let inserted = 0;
191
+ let skipped = 0;
192
+ const tx = db.transaction(() => {
193
+ // Can't use async generator inside synchronous transaction, so we collect first
194
+ // This is fine — 5K modules fit in memory
195
+ });
196
+
197
+ // Collect all modules (sync requirement of better-sqlite3 transactions)
198
+ const all: StarterModule[] = [];
199
+ for await (const m of streamModules()) {
200
+ all.push(m);
201
+ }
202
+
203
+ db.exec('BEGIN');
204
+ for (const m of all) {
205
+ const info = insert.run(
206
+ m.name, m.displayName, m.description, m.category,
207
+ m.keywords.join(', '), m.lineCount, m.evalScore, m.version, m.content,
208
+ );
209
+ if (info.changes > 0) inserted++;
210
+ else skipped++;
211
+ }
212
+ db.exec('COMMIT');
213
+
214
+ return { inserted, skipped, totalMs: Date.now() - t0 };
215
+ }