entroly-wasm 0.10.0 → 0.12.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/package.json CHANGED
@@ -1,51 +1,12 @@
1
- {
2
- "name": "entroly-wasm",
3
- "version": "0.10.0",
4
- "description": "Information-theoretic context optimization for AI coding agents. Zero-friction, pure WebAssembly — no Python dependency.",
5
- "main": "index.js",
6
- "types": "pkg/entroly_wasm.d.ts",
7
- "bin": {
8
- "entroly-wasm": "./js/cli.js"
9
- },
10
- "files": [
11
- "index.js",
12
- "pkg/entroly_wasm_bg.wasm",
13
- "pkg/entroly_wasm.js",
14
- "pkg/entroly_wasm.d.ts",
15
- "js/cli.js",
16
- "js/server.js",
17
- "js/config.js",
18
- "js/auto_index.js",
19
- "js/checkpoint.js",
20
- "js/autotune.js",
21
- "js/vault.js",
22
- "js/cogops.js",
23
- "js/workspace.js",
24
- "js/repo_map.js",
25
- "js/skills.js",
26
- "js/multimodal.js",
27
- "js/value_tracker.js",
28
- "js/agentskills_export.js",
29
- "js/gateways.js",
30
- "js/vault_observer.js",
31
- "js/distill.js",
32
- "js/federation.js",
33
- "js/evolution_daemon.js"
34
- ],
35
- "scripts": {
36
- "serve": "node js/server.js",
37
- "optimize": "node js/cli.js optimize",
38
- "health": "node js/cli.js health",
39
- "demo": "node js/cli.js demo",
40
- "autotune": "node js/cli.js autotune",
41
- "test": "node test_wasm_e2e.js"
42
- },
43
- "keywords": [
44
- "entroly", "context-optimization", "mcp", "mcp-server", "ai", "agents",
45
- "wasm", "webassembly", "information-theory", "knapsack", "entropy", "autotune"
46
- ],
47
- "repository": { "type": "git", "url": "https://github.com/juyterman1000/entroly" },
48
- "author": "entroly",
49
- "license": "Apache-2.0",
50
- "engines": { "node": ">=16.0.0" }
51
- }
1
+ {
2
+ "name": "entroly-wasm",
3
+ "description": "WebAssembly build of Entroly — information-theoretic context optimization for JavaScript/TypeScript",
4
+ "version": "0.12.0",
5
+ "files": [
6
+ "entroly_wasm_bg.wasm",
7
+ "entroly_wasm.js",
8
+ "entroly_wasm.d.ts"
9
+ ],
10
+ "main": "entroly_wasm.js",
11
+ "types": "entroly_wasm.d.ts"
12
+ }
package/index.js DELETED
@@ -1,67 +0,0 @@
1
- // Entroly — Information-theoretic context optimization for JavaScript/TypeScript.
2
- //
3
- // Usage:
4
- // const { EntrolyEngine, autoIndex, EntrolyConfig } = require('entroly-wasm');
5
- //
6
- // const engine = new EntrolyEngine();
7
- // autoIndex(engine); // auto-discover and ingest codebase
8
- // engine.optimize(8000, "fix the auth bug");
9
- //
10
- // Or as MCP server:
11
- // npx entroly-wasm serve
12
-
13
- const { WasmEntrolyEngine } = require('./pkg/entroly_wasm');
14
- const { EntrolyConfig } = require('./js/config');
15
- const { autoIndex, startIncrementalWatcher, estimateTokens } = require('./js/auto_index');
16
- const { CheckpointManager, persistIndex, loadIndex } = require('./js/checkpoint');
17
- const { EntrolyMCPServer } = require('./js/server');
18
- const { runAutotune, startAutotuneDaemon, TaskProfileOptimizer, FeedbackJournal } = require('./js/autotune');
19
- const { ValueTracker, EVOLUTION_TAX_RATE, estimateCost } = require('./js/value_tracker');
20
- const { exportPromoted: exportAgentSkills } = require('./js/agentskills_export');
21
- const { TelegramGateway, DiscordGateway, SlackGateway } = require('./js/gateways');
22
- const { VaultObserver } = require('./js/vault_observer');
23
-
24
- module.exports = {
25
- // Core engine (wasm)
26
- EntrolyEngine: WasmEntrolyEngine,
27
- WasmEntrolyEngine,
28
-
29
- // Configuration
30
- EntrolyConfig,
31
-
32
- // Codebase scanning
33
- autoIndex,
34
- startIncrementalWatcher,
35
- estimateTokens,
36
-
37
- // State persistence
38
- CheckpointManager,
39
- persistIndex,
40
- loadIndex,
41
-
42
- // MCP Server
43
- EntrolyMCPServer,
44
-
45
- // Autotune + Task-Conditioned Profiles
46
- runAutotune,
47
- startAutotuneDaemon,
48
- TaskProfileOptimizer,
49
- FeedbackJournal,
50
-
51
- // Self-funded evolution budget (C_spent ≤ τ·S(t))
52
- ValueTracker,
53
- EVOLUTION_TAX_RATE,
54
- estimateCost,
55
-
56
- // agentskills.io portable export
57
- exportAgentSkills,
58
-
59
- // Chat gateways (live self-evolution event stream)
60
- TelegramGateway,
61
- DiscordGateway,
62
- SlackGateway,
63
-
64
- // Observe the shared vault — works with skills promoted by the
65
- // Python daemon OR any node-side orchestrator. No daemon required.
66
- VaultObserver,
67
- };
@@ -1,129 +0,0 @@
1
- /**
2
- * agentskills.io export — JS port.
3
- * Exports promoted vault skills to the portable agentskills.io v0.1 spec
4
- * so any compatible runtime can consume them.
5
- *
6
- * CLI: node js/agentskills_export.js [out_dir]
7
- */
8
-
9
- 'use strict';
10
-
11
- const fs = require('fs');
12
- const path = require('path');
13
-
14
- const SPEC_VERSION = '0.1';
15
-
16
- function parseFrontmatter(text) {
17
- if (!text.startsWith('---')) return { meta: {}, body: text };
18
- const end = text.indexOf('\n---', 3);
19
- if (end < 0) return { meta: {}, body: text };
20
- const header = text.slice(3, end).trim();
21
- const body = text.slice(end + 4).replace(/^\n+/, '');
22
- const meta = {};
23
- for (const line of header.split('\n')) {
24
- const i = line.indexOf(':');
25
- if (i > 0) meta[line.slice(0, i).trim()] = line.slice(i + 1).trim();
26
- }
27
- return { meta, body };
28
- }
29
-
30
- function loadSkill(dir) {
31
- const skillMd = path.join(dir, 'SKILL.md');
32
- const toolPy = path.join(dir, 'tool.py');
33
- if (!fs.existsSync(skillMd) || !fs.existsSync(toolPy)) return null;
34
-
35
- const { meta, body } = parseFrontmatter(fs.readFileSync(skillMd, 'utf8'));
36
- if ((meta.status || '') !== 'promoted') return null;
37
-
38
- let metrics = {};
39
- const mp = path.join(dir, 'metrics.json');
40
- if (fs.existsSync(mp)) {
41
- try { metrics = JSON.parse(fs.readFileSync(mp, 'utf8')); } catch (_) {}
42
- }
43
- return {
44
- meta,
45
- procedure: body,
46
- toolCode: fs.readFileSync(toolPy, 'utf8'),
47
- metrics,
48
- };
49
- }
50
-
51
- function exportPromoted({
52
- vaultPath = '.entroly/vault',
53
- outDir = './dist/agentskills',
54
- } = {}) {
55
- const skillsDir = path.join(vaultPath, 'evolution', 'skills');
56
- if (!fs.existsSync(skillsDir)) {
57
- return { status: 'no_vault', skillsDir };
58
- }
59
- fs.mkdirSync(outDir, { recursive: true });
60
-
61
- const exported = [];
62
- const skipped = [];
63
-
64
- for (const name of fs.readdirSync(skillsDir).sort()) {
65
- const dir = path.join(skillsDir, name);
66
- if (!fs.statSync(dir).isDirectory()) continue;
67
-
68
- const loaded = loadSkill(dir);
69
- if (!loaded) { skipped.push(name); continue; }
70
-
71
- const target = path.join(outDir, name);
72
- fs.rmSync(target, { recursive: true, force: true });
73
- fs.mkdirSync(target, { recursive: true });
74
-
75
- const skillJson = {
76
- spec_version: SPEC_VERSION,
77
- id: loaded.meta.skill_id || name,
78
- name: loaded.meta.name || name,
79
- entity: loaded.meta.entity || '',
80
- description: `Skill for handling ${loaded.meta.entity || name} queries`,
81
- status: loaded.meta.status || 'promoted',
82
- created_at: loaded.meta.created_at || '',
83
- metrics: {
84
- fitness_score: loaded.metrics.fitness_score || 0,
85
- runs: loaded.metrics.runs || 0,
86
- successes: loaded.metrics.successes || 0,
87
- failures: loaded.metrics.failures || 0,
88
- },
89
- entrypoint: {
90
- runtime: 'python',
91
- module: 'tool',
92
- match: 'matches',
93
- execute: 'execute',
94
- },
95
- origin: {
96
- runtime: 'entroly',
97
- synthesis: 'structural',
98
- token_cost: 0.0,
99
- },
100
- };
101
-
102
- fs.writeFileSync(path.join(target, 'skill.json'), JSON.stringify(skillJson, null, 2));
103
- fs.writeFileSync(path.join(target, 'procedure.md'), loaded.procedure);
104
- fs.writeFileSync(path.join(target, 'tool.py'), loaded.toolCode);
105
- fs.writeFileSync(path.join(target, 'tests.json'), '[]');
106
-
107
- exported.push(skillJson.id);
108
- }
109
-
110
- fs.writeFileSync(
111
- path.join(outDir, 'manifest.json'),
112
- JSON.stringify({
113
- spec_version: SPEC_VERSION,
114
- exported_at: new Date().toISOString(),
115
- source: 'entroly',
116
- skills: exported,
117
- }, null, 2),
118
- );
119
-
120
- return { status: 'ok', outDir, exported, skipped };
121
- }
122
-
123
- module.exports = { exportPromoted, SPEC_VERSION };
124
-
125
- if (require.main === module) {
126
- const out = process.argv[2] || './dist/agentskills';
127
- const result = exportPromoted({ outDir: out });
128
- console.log(JSON.stringify(result, null, 2));
129
- }
package/js/auto_index.js DELETED
@@ -1,262 +0,0 @@
1
- // Entroly Auto-Index — JS port of auto_index.py
2
- // Git-aware codebase discovery and ingestion.
3
-
4
- const fs = require('fs');
5
- const path = require('path');
6
- const { execSync } = require('child_process');
7
-
8
- const SUPPORTED_EXTENSIONS = new Set([
9
- // Systems
10
- '.rs', '.c', '.cpp', '.h', '.hpp', '.cc', '.hxx', '.zig',
11
- // Web / JS / TS
12
- '.js', '.ts', '.jsx', '.tsx', '.mjs', '.mts', '.cjs', '.cts', '.vue', '.svelte',
13
- // Python
14
- '.py', '.pyi',
15
- // JVM
16
- '.java', '.kt', '.scala',
17
- // .NET
18
- '.cs', '.csx', '.fs',
19
- // Go
20
- '.go',
21
- // Swift
22
- '.swift',
23
- // Ruby
24
- '.rb',
25
- // PHP
26
- '.php',
27
- // Dart
28
- '.dart',
29
- // Elixir
30
- '.ex', '.exs',
31
- // Lua
32
- '.lua',
33
- // R
34
- '.r',
35
- // Shell / Config
36
- '.sh', '.bash', '.zsh', '.toml', '.yaml', '.yml', '.json',
37
- // Terraform
38
- '.tf', '.hcl',
39
- // Docs
40
- '.md', '.rst',
41
- // SQL
42
- '.sql',
43
- // Docker
44
- '.dockerfile',
45
- ]);
46
-
47
- const SKIP_PATTERNS = new Set([
48
- 'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'Cargo.lock',
49
- 'poetry.lock', 'Pipfile.lock', 'composer.lock', 'Gemfile.lock',
50
- '.DS_Store', 'thumbs.db',
51
- ]);
52
-
53
- const BINARY_EXTENSIONS = new Set([
54
- '.png', '.jpg', '.jpeg', '.gif', '.bmp', '.ico', '.svg', '.webp', '.tiff',
55
- '.mp3', '.mp4', '.avi', '.mov', '.wav', '.flac', '.ogg', '.webm',
56
- '.zip', '.tar', '.gz', '.bz2', '.7z', '.rar', '.xz',
57
- '.wasm', '.so', '.dll', '.dylib', '.a', '.o', '.obj', '.exe', '.bin',
58
- '.pyc', '.pyo', '.class', '.jar',
59
- '.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx',
60
- '.ttf', '.otf', '.woff', '.woff2', '.eot',
61
- '.db', '.sqlite', '.sqlite3',
62
- '.dat', '.pak', '.map',
63
- ]);
64
-
65
- const MAX_FILE_BYTES = 50 * 1024;
66
- const ABSOLUTE_MAX_BYTES = 500 * 1024;
67
- const MAX_FILES = parseInt(process.env.ENTROLY_MAX_FILES || '5000', 10);
68
-
69
- let ignorePatterns = [];
70
-
71
- function gitLsFiles(projectDir) {
72
- try {
73
- const result = execSync('git ls-files --cached --others --exclude-standard', {
74
- cwd: projectDir, encoding: 'utf-8', timeout: 10000, stdio: ['pipe', 'pipe', 'pipe'],
75
- });
76
- return result.split('\n').map(f => f.trim()).filter(Boolean);
77
- } catch {
78
- return [];
79
- }
80
- }
81
-
82
- function walkFallback(projectDir) {
83
- const files = [];
84
- const skipDirs = new Set(['node_modules', '__pycache__', 'target', 'dist', 'build', '.git', 'venv', '.venv', 'env']);
85
-
86
- function walk(dir) {
87
- if (files.length >= MAX_FILES) return;
88
- let entries;
89
- try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }
90
- for (const entry of entries) {
91
- if (files.length >= MAX_FILES) return;
92
- if (entry.name.startsWith('.') || skipDirs.has(entry.name)) {
93
- if (entry.isDirectory()) continue;
94
- }
95
- const full = path.join(dir, entry.name);
96
- if (entry.isDirectory()) { walk(full); }
97
- else { files.push(path.relative(projectDir, full)); }
98
- }
99
- }
100
- walk(projectDir);
101
- return files;
102
- }
103
-
104
- function loadEntrolyIgnore(projectDir) {
105
- const ignorePath = path.join(projectDir, '.entrolyignore');
106
- try {
107
- const content = fs.readFileSync(ignorePath, 'utf-8');
108
- return content.split('\n').map(l => l.trim()).filter(l => l && !l.startsWith('#'));
109
- } catch { return []; }
110
- }
111
-
112
- function matchesIgnore(relPath) {
113
- const { minimatch } = (() => {
114
- try { return require('minimatch'); } catch { return { minimatch: null }; }
115
- })();
116
- for (const pattern of ignorePatterns) {
117
- if (minimatch) {
118
- if (minimatch(relPath, pattern)) return true;
119
- if (minimatch(path.basename(relPath), pattern)) return true;
120
- } else {
121
- // Simple glob fallback
122
- if (relPath.includes(pattern.replace('*', '')) || path.basename(relPath).includes(pattern.replace('*', ''))) return true;
123
- }
124
- }
125
- return false;
126
- }
127
-
128
- function shouldIndex(relPath) {
129
- const basename = path.basename(relPath);
130
- if (SKIP_PATTERNS.has(basename)) return false;
131
- const ext = path.extname(basename).toLowerCase();
132
- if (BINARY_EXTENSIONS.has(ext)) return false;
133
- if (ignorePatterns.length && matchesIgnore(relPath)) return false;
134
- if (basename.startsWith('Dockerfile')) return true;
135
- return SUPPORTED_EXTENSIONS.has(ext);
136
- }
137
-
138
- function estimateTokens(content) {
139
- return Math.max(1, Math.floor(content.length / 4));
140
- }
141
-
142
- /**
143
- * Auto-index a project's codebase into the Entroly wasm engine.
144
- * @param {WasmEntrolyEngine} engine
145
- * @param {string} [projectDir]
146
- * @param {boolean} [force=false]
147
- * @returns {object} Summary with indexed file count, tokens, and duration.
148
- */
149
- function autoIndex(engine, projectDir, force = false) {
150
- projectDir = projectDir || process.cwd();
151
- projectDir = path.resolve(projectDir);
152
-
153
- ignorePatterns = loadEntrolyIgnore(projectDir);
154
-
155
- if (!force && engine.fragment_count() > 0) {
156
- return {
157
- status: 'skipped', reason: 'persistent_index_loaded',
158
- existing_fragments: engine.fragment_count(),
159
- };
160
- }
161
-
162
- const t0 = Date.now();
163
-
164
- let files = gitLsFiles(projectDir);
165
- let discovery = 'git';
166
- if (!files.length) { files = walkFallback(projectDir); discovery = 'walk'; }
167
-
168
- const allIndexable = files.filter(shouldIndex);
169
- const indexable = allIndexable.slice(0, MAX_FILES);
170
-
171
- let indexed = 0, totalTokens = 0, skippedSize = 0, skippedRead = 0;
172
-
173
- for (const relPath of indexable) {
174
- const absPath = path.join(projectDir, relPath);
175
- let stat;
176
- try { stat = fs.statSync(absPath); } catch { continue; }
177
-
178
- if (stat.size > ABSOLUTE_MAX_BYTES) { skippedSize++; continue; }
179
- if (stat.size > MAX_FILE_BYTES || stat.size === 0) { skippedSize++; continue; }
180
-
181
- // Binary detection
182
- try {
183
- const fd = fs.openSync(absPath, 'r');
184
- const buf = Buffer.alloc(Math.min(8192, stat.size));
185
- fs.readSync(fd, buf, 0, buf.length, 0);
186
- fs.closeSync(fd);
187
- if (buf.includes(0)) { skippedRead++; continue; }
188
- } catch { skippedRead++; continue; }
189
-
190
- let content;
191
- try { content = fs.readFileSync(absPath, 'utf-8'); } catch { skippedRead++; continue; }
192
- if (!content.trim()) continue;
193
-
194
- const tokens = estimateTokens(content);
195
- engine.ingest(content, `file:${relPath}`, tokens, false);
196
- indexed++;
197
- totalTokens += tokens;
198
- }
199
-
200
- const elapsed = ((Date.now() - t0) / 1000).toFixed(2);
201
-
202
- // Trigger dep graph build
203
- if (indexed > 0) {
204
- try { engine.optimize(1, ''); } catch {}
205
- }
206
-
207
- return {
208
- status: 'indexed', files_indexed: indexed, total_tokens: totalTokens,
209
- duration_s: parseFloat(elapsed), discovery_method: discovery,
210
- skipped_too_large: skippedSize, skipped_unreadable: skippedRead,
211
- project_dir: projectDir,
212
- };
213
- }
214
-
215
- /**
216
- * Start incremental file watcher (background interval).
217
- * @param {WasmEntrolyEngine} engine
218
- * @param {string} [projectDir]
219
- * @param {number} [intervalMs=120000]
220
- * @returns {NodeJS.Timeout}
221
- */
222
- function startIncrementalWatcher(engine, projectDir, intervalMs = 120000) {
223
- projectDir = projectDir || process.cwd();
224
- projectDir = path.resolve(projectDir);
225
- const indexedMtimes = {};
226
-
227
- // Initial snapshot
228
- const files = gitLsFiles(projectDir);
229
- for (const rel of files) {
230
- try { indexedMtimes[rel] = fs.statSync(path.join(projectDir, rel)).mtimeMs; } catch {}
231
- }
232
-
233
- return setInterval(() => {
234
- try {
235
- const files = gitLsFiles(projectDir);
236
- let count = 0;
237
- for (const rel of files) {
238
- if (!shouldIndex(rel)) continue;
239
- const abs = path.join(projectDir, rel);
240
- let mtime;
241
- try { mtime = fs.statSync(abs).mtimeMs; } catch { continue; }
242
- if (indexedMtimes[rel] === undefined || mtime > indexedMtimes[rel]) {
243
- indexedMtimes[rel] = mtime;
244
- try {
245
- const stat = fs.statSync(abs);
246
- if (stat.size > MAX_FILE_BYTES || stat.size === 0) continue;
247
- const content = fs.readFileSync(abs, 'utf-8');
248
- if (!content.trim()) continue;
249
- engine.ingest(content, `file:${rel}`, estimateTokens(content), false);
250
- count++;
251
- } catch { continue; }
252
- }
253
- if (count >= 100) break;
254
- }
255
- if (count > 0) console.error(`[entroly] Incremental re-index: ${count} new/modified files`);
256
- } catch (e) {
257
- console.error(`[entroly] Incremental re-index error: ${e.message}`);
258
- }
259
- }, intervalMs);
260
- }
261
-
262
- module.exports = { autoIndex, startIncrementalWatcher, estimateTokens };