Merge worktree-agent: add struct literals, generics, print/log builtins

This commit is contained in:
Will Anderson
2026-04-28 11:51:02 -05:00
40 changed files with 4058 additions and 72 deletions
+16
View File
@@ -0,0 +1,16 @@
{
"name": "Neuron",
"short_name": "Neuron",
"description": "Neuron — AI companion powered by engram-lang",
"start_url": "/",
"display": "standalone",
"background_color": "#0a0a0f",
"theme_color": "#6c7fff",
"orientation": "portrait-primary",
"icons": [
{ "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any maskable" },
{ "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any maskable" }
],
"categories": ["productivity", "utilities"],
"lang": "en-US"
}
+72
View File
@@ -0,0 +1,72 @@
// Engram-lang WASM runtime loader
// Include this in any web app to run .el programs natively in the browser.
//
// Usage:
// import { initRuntime, runElc, evalSource } from '/js/runtime.js';
//
// await initRuntime();
// const result = await runElc('/programs/main.elc');
let wasmModule = null;
/**
* Initialise the engram-lang WASM runtime. Safe to call multiple times —
* subsequent calls return the already-loaded module immediately.
*
* @param {string} wasmUrl - Path to the .wasm file (default: /pkg/el_wasm_bg.wasm)
* @returns {Promise<object>} The loaded runtime API
*/
export async function initRuntime(wasmUrl = '/pkg/el_wasm_bg.wasm') {
if (wasmModule) return wasmModule;
const { default: init, compile_source, load_and_run, eval: elEval, version } =
await import('/pkg/el_wasm.js');
await init(wasmUrl);
wasmModule = { compile_source, load_and_run, eval: elEval, version };
console.log(`engram-lang WASM runtime v${version()} loaded`);
return wasmModule;
}
/**
* Fetch a pre-compiled .elc file from the server and execute it.
*
* The browser caches the .elc file automatically based on Cache-Control
* headers set by the server. New bytecode is available immediately on the
* next fetch — no app-store review required.
*
* @param {string} elcUrl - URL of the .elc bytecode file
* @returns {Promise<any>} The JSON-deserialised result value
*/
export async function runElc(elcUrl) {
const rt = await initRuntime();
const response = await fetch(elcUrl);
if (!response.ok) throw new Error(`Failed to fetch ${elcUrl}: ${response.status}`);
const bytes = new Uint8Array(await response.arrayBuffer());
return JSON.parse(rt.load_and_run(bytes));
}
/**
* Compile engram-lang source and run it immediately. Useful for REPL and
* developer-mode execution where source is available at runtime.
*
* @param {string} source - Engram-lang source code
* @returns {Promise<any>} The JSON-deserialised result value
*/
export async function evalSource(source) {
const rt = await initRuntime();
return JSON.parse(rt.eval(source));
}
/**
* Compile engram-lang source to bytecode bytes without running it.
* The returned Uint8Array can be stored or uploaded as a .elc file.
*
* @param {string} source - Engram-lang source code
* @returns {Promise<Uint8Array>} Compiled bytecode bytes
*/
export async function compileSource(source) {
const rt = await initRuntime();
return rt.compile_source(source);
}
+77
View File
@@ -0,0 +1,77 @@
// Service worker for the Neuron PWA powered by engram-lang.
//
// Caching strategy:
// /pkg/ — WASM runtime files, cache-first (content-addressed, change on version bump)
// *.elc — compiled bytecode, stale-while-revalidate (instant load, background update)
//
// The WASM runtime is fetched once and cached indefinitely.
// Engram programs (.elc) are served from cache immediately, then refreshed in
// the background so the next load gets the newest version — no user action needed.
const CACHE_NAME = 'engram-v1';
const WASM_CACHE = 'engram-wasm-v1';
// Files to pre-cache during service worker installation.
const PRECACHE = [
'/pkg/el_wasm_bg.wasm',
'/pkg/el_wasm.js',
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(WASM_CACHE).then(cache => cache.addAll(PRECACHE))
);
// Take control immediately — don't wait for existing tabs to close.
self.skipWaiting();
});
self.addEventListener('fetch', event => {
const url = new URL(event.request.url);
// WASM runtime files: cache-first.
// These are large and rarely change; the version bump forces a new URL.
if (url.pathname.startsWith('/pkg/')) {
event.respondWith(
caches.match(event.request).then(cached =>
cached || fetch(event.request).then(response => {
caches.open(WASM_CACHE).then(cache =>
cache.put(event.request, response.clone())
);
return response;
})
)
);
return;
}
// Compiled bytecode (.elc): stale-while-revalidate.
// Respond immediately from cache, update in background.
if (url.pathname.endsWith('.elc')) {
event.respondWith(
caches.open(CACHE_NAME).then(async cache => {
const cached = await cache.match(event.request);
const fetchPromise = fetch(event.request).then(response => {
cache.put(event.request, response.clone());
return response;
});
return cached || fetchPromise;
})
);
return;
}
});
self.addEventListener('activate', event => {
// Purge old cache versions to reclaim storage.
event.waitUntil(
caches.keys().then(keys =>
Promise.all(
keys
.filter(k => k !== CACHE_NAME && k !== WASM_CACHE)
.map(k => caches.delete(k))
)
)
);
// Claim all clients immediately.
self.clients.claim();
});