AI Emacs in Javascript (using bun.exe, blessed, miniMAL, nerd fonts, both symbolic and statistical tools) License - Public domain #build script - PowerShell - some tweaks needed, but google is your friend... It worked on my machine...
#####################################################
build script - some tweaks may be needed - rename to build-weex.ps1## - manual - bun.exe, AtkynsonMonoNerdFont-Regular.otf font, katex, StepB.js from minimal (rename to minimal.js) - YMMV
#### 2025_10_11-22-22 - https://grok.com/share/c2hhcmQtMg%3D%3D_fbba0302-e646-4afe-a12c-4a3f09007fe1## build-weex.ps1 - WeeX Browser TUI with Undo/Redo, Logging, #NoEstimates + SPIDR, WBS, Org Mode, Prolog, GraphQL Subscriptions, REST Interface with SSE Subscriptions, Optional Redis, Expanded Kanren, Tau Prolog## Requires: Git, PowerShell 5.0+ (Windows) or PowerShell Core 6+ (Linux/macOS). Run in an empty directory.## Features: Beginner-friendly error messages, logging to build.log, retry logic, disk/network/permission checks, uses AtkinsonMonoNerdFont-Regular.otf, includes katex.min.css, package.json, data format parsers (JSON5, CBOR, MessagePack, BSON, HCL), GraphQL/REST with Socket.io subscriptions, orgajs parsing, optional Redis caching/messaging, expanded Kanren logic programming with recursion, Tau Prolog for advanced queries
## Search and Replace Log-Message
Initialize logging$logFile = "build.log""Starting build at $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" | Out-File -FilePath $logFile -Encoding UTF8function Log-Message { param($Message) Write-Output $Message $Message | Out-File -FilePath $logFile -Append -Encoding UTF8}
Trap for unexpected errorstrap { $errorMsg = "Something went wrong: $_`nPlease check $logFile for details. If stuck, try running the script again or visit https://github.com/oven-sh/bun for help." Log-Message $errorMsg # Cleanup temp files $tempFiles = @("bun-windows-x64.zip", "bun-linux-x64.zip", "bun-darwin-x64.zip", "bun-darwin-aarch64.zip", "AtkinsonHyperlegibleMono.zip", "*.SHA256SUMS") foreach ($file in $tempFiles) { if (Test-Path $file) { Remove-Item $file -Force -ErrorAction SilentlyContinue } } exit 1}
Step 1: Check prerequisitesLog-Message "Checking if everything is ready to start..."if (!(Get-Command git -ErrorAction SilentlyContinue)) { Log-Message "Oops! Git is not installed. Git is a tool we need to download some required files.nPlease download and install Git from https://git-scm.com, then run this script again." exit 1}if ($PSVersionTable.PSVersion.Major -lt 5) { Log-Message "Oops! Your PowerShell version is too old (version $($PSVersionTable.PSVersion)). We need PowerShell 5.0 or higher (or PowerShell Core 6+).nPlease update PowerShell from https://learn.microsoft.com/powershell/scripting/install/installing-powershell or install PowerShell Core, then try again." exit 1}# Check disk space (at least 500MB free)try { $disk = Get-PSDrive -Name ($PWD.Path.Substring(0,1)) -ErrorAction Stop if ($disk.Free -lt 500MB) { Log-Message "Not enough disk space! We need at least 500MB free, but only $ ($disk.Free / 1MB) MB is available.nPlease free up some space on your drive ($($disk.Name)) and try again." exit 1 }}catch { Log-Message "Error checking disk space: $_nEnsure $PWD is on a valid drive and try again." exit 1}# Check write permissionstry { New-Item -ItemType File -Path "test.txt" -Force | Out-Null Remove-Item "test.txt" -Force}catch { Log-Message "Cannot write to this folder ($PWD). Error: $_nPlease run the script in a folder where you have permission to create files, or run PowerShell as Administrator." exit 1}# Check network connectivitytry { Test-Connection -ComputerName github.com -Count 1 -Quiet -ErrorAction Stop | Out-Null}catch { Log-Message "No internet connection detected. Error: $_nPlease connect to the internet and try again, as we need to download some files." exit 1}Log-Message "All checks passed! Ready to start building."
Step 2: Clone core repos$repos = @( @{Path="xterm-tui"; Url="https://github.com/RangerMauve/xterm-tui.git"}, @{Path="neo-blessed"; Url="https://github.com/chjj/blessed.git"}, @{Path="miniMAL"; Url="https://github.com/kanaka/miniMAL.git"})foreach ($repo in $repos) { if (-Not (Test-Path $repo.Path)) { try { Log-Message "Downloading $ ($repo.Path) from $ ($repo.Url)..." git clone $repo.Url $repo.Path Log-Message "Successfully downloaded $ ($repo.Path)." } catch { Log-Message "Failed to download $ ($repo.Path) from $ ($repo.Url). Error: $_`nPlease check your internet connection or try again. If the problem persists, visit $ ($repo.Url) for help." exit 1 } } else { Log-Message "$ ($repo.Path) already exists, skipping download." }}
Step 3: Create package.json$redisDependencies = if ($useRedis) { @" "redis": "latest", "socket.io-redis": "latest","@ } else { "" }$packageJson = @"{ "name": "weex-tui", "version": "1.0.0", "main": "index.js", "dependencies": { "xterm": "latest", "xterm-addon-fit": "latest", "neo-blessed": "file:./neo-blessed", "blessed-contrib": "latest", "mathjs": "latest", "katex": "latest", "mermaid": "latest", "plantuml-encoder": "latest", "d3": "latest", "vega": "latest", "vega-lite": "latest", "@observablehq/plot": "latest", "@xenova/transformers": "latest", "compromise": "latest", "n3": "latest", "@mikro-orm/core": "latest", "@mikro-orm/sqlite": "latest", "xml-js": "latest", "@iarna/toml": "latest", "papaparse": "latest", "jsonpath": "latest", "js-yaml": "latest", "parquet-wasm": "latest", "avsc": "latest", "marked": "latest", "jsonld": "latest", "rdflib": "latest", "rdfxml-streaming-parser": "latest", "hyparquet-writer": "latest", "turndown": "latest", "@orgajs/reorg": "latest", "json5": "latest", "cbor": "latest", "msgpack-lite": "latest", "bson": "latest", "hcl2-parser": "latest", "graphql-yoga": "latest", "graphql": "latest", "socket.io": "latest", "socket.io-client": "latest", "tau-prolog": "latest"$redisDependencies }}"@if (-Not (Test-Path "package.json")) { try { $packageJson | Out-File -FilePath "package.json" -Encoding UTF8 Log-Message "Created package.json successfully." } catch { Log-Message "Failed to create package.json. Error: $_`nPlease check disk permissions and try again." exit 1 }} else { Log-Message "package.json already exists, skipping creation."}# Validate package.jsonif ((Get-Content "package.json" -Raw).Length -lt 100) { Log-Message "Error: package.json is too small. Something went wrong while creating it. Please delete it and run the script again." exit 1}
Step 4: Install dependenciestry { Log-Message "Installing required libraries (this may take a minute)..." bun install Log-Message "All libraries installed successfully."}catch { Log-Message "Failed to install libraries. Error: $_`nPlease ensure Bun is installed (we'll download it later in this script), check your internet connection, and try again." exit 1}
Step 5: Create miniMAL-plus.js with Agile/Org/DB/Prolog macros, additional parsers, GraphQL subscriptions, REST interface, optional Redis, expanded Kanren, and Tau Prolog$malCode = @"// miniMAL-plus.js - Extended miniMAL with Weex-specific macros for Agile, Org Mode, DB, Prolog, data formats, GraphQL subscriptions, REST interface, optional Redis, expanded Kanren, and Tau Prolog// Uses @orgajs/reorg for parsing Org Mode syntax (e.g., * TODO, #+WBS: id, timestamps, lists) into AST for tasks and agendas// Examples: (defwbs "Task" :status "TODO"), (deftask "Meeting" :wbs_id 1), (kanren (fresh (id) (== (wbs-query ?id) {"status": "DONE"})))import mal from './miniMAL/minimal.js';import Tau from 'tau-prolog';$(if ($useRedis) { @"import { createClient } from 'redis';
const redis = createClient({ url: 'redis://localhost:6379' });redis.connect().catch(err => console.error('Redis connection error:', err));"@ } else { "" })
// Utility: HTTP fetch wrapper for server endpointsasync function fetchEndpoint(endpoint, params, method = 'GET', body = null) { const url = new URL(http://localhost:3000${endpoint}); if (method === 'GET' && params) { Object.keys(params).forEach(key => url.searchParams.append(key, params[key])); } const options = { method }; if (body) { options.body = JSON.stringify(body); options.headers = { 'Content-Type': 'application/json' }; } const response = await fetch(url, options); const data = await response.json(); return data.result;}
// Utility: SSE subscription via EventSource for REST subscriptionsconst subscriptions = {};function subscribeEvent(event) { const es = new EventSource(http://localhost:3000/rest/subscribe?event=${event}); return new Promise((resolve) => { es.onmessage = (msg) => resolve(JSON.parse(msg.data)); es.onerror = () => es.close(); });}
// Utility: Socket.io for GraphQL and real-time subscriptionsimport { io } from 'socket.io-client';const socket = io('http://localhost:3001');
// Tau Prolog interpreter for advanced queriesconst prolog = Tau.core.create();prolog.consult( status(Id, Status) :- wbs(Id, _, Status, _). dependency(Id, Dep) :- wbs(Id, _, _, Dep). ancestor(X, Y) :- dependency(X, Y). ancestor(X, Y) :- dependency(X, Z), ancestor(Z, Y). risk_level(Id, Level) :- spidr(Id, 'Risk', _, _), Level is 3. risk_level(Id, Level) :- spidr(Id, 'Defect', _, _), Level is 2. risk_level(Id, Level) :- spidr(Id, 'Improvement', _, _), Level is 1.);
async function prologQuery(query) { const wbs = await fetchEndpoint('/agile/wbs-query', { filter: '%' }); const spidr = await fetchEndpoint('/agile/spidr-query', { filter: '%' }); let facts = ''; wbs.forEach(t => { facts += wbs(${t.id}, '${t.task}', '${t.status}', ${t.depends_on_id || 'null'}).\n; }); spidr.forEach(s => { facts += spidr(${s.id}, '${s.category}', '${s.description}', ${s.wbs_id}).\n; }); prolog.consult(facts); const answers = prolog.query(query); const results = []; for await (const answer of answers) { results.push(answer.links); } return results;}
// Expanded Kanren logic programming utilitiesfunction kanren(goals) { // Simplified miniKanren: runs goals with unification and backtracking const runGoal = (goal, state) => { if (Array.isArray(goal) && goal[0] === '==') { return unify(goal[1], goal[2], state); } else if (Array.isArray(goal) && goal[0] === 'fresh') { const vars = goal[1]; const subGoal = goal[2]; let newState = { ...state, vars: [...(state.vars || []), ...vars] }; return runGoal(subGoal, newState); } else if (Array.isArray(goal) && goal[0] === 'conde') { let states = []; for (let clause of goal.slice(1)) { states.push(...runGoal(clause, state)); } return states; } else if (Array.isArray(goal) && goal[0] === 'conda') { for (let clause of goal.slice(1)) { const states = runGoal(clause, state); if (states.length > 0) return states; } return []; } return []; }; const unify = (x, y, state) => { if (typeof x === 'string' && x.startsWith('?')) { return [{ ...state, [x]: y }]; } if (typeof y === 'string' && y.startsWith('?')) { return [{ ...state, [y]: x }]; } if (Array.isArray(x) && Array.isArray(y)) { if (x.length !== y.length) return []; let states = [state]; for (let i = 0; i < x.length; i++) { let newStates = []; for (let s of states) { newStates.push(...unify(x[i], y[i], s)); } states = newStates; } return states; } if (typeof x === 'object' && typeof y === 'object') { let states = [state]; for (let key of Object.keys(x)) { let newStates = []; for (let s of states) { newStates.push(...unify(x[key], y[key], s)); } states = newStates; } return states; } return x === y ? [state] : []; }; return runGoal(goals, {});}
// miniMAL environment with extended functionsconst env = { // Bun-specific functions 'bun-shell': async (cmd) => await fetchEndpoint('/bun/shell', { cmd }), // Run shell commands, e.g., (bun-shell "ls") 'bun-worker': async (script) => await fetchEndpoint('/bun/worker', { script }), // Execute Web Worker, e.g., (bun-worker "postMessage(42)") 'bun-fs-read': async (path) => await fetchEndpoint('/bun/fs-read', { path }), // Read file, e.g., (bun-fs-read "data.txt") 'bun-fs-write': async (path, data) => await fetchEndpoint('/bun/fs-write', { path, data }), // Write file, e.g., (bun-fs-write "output.txt" "Hello") 'bun-http-get': async (url) => await fetchEndpoint('/bun/http-get', { url }), // HTTP GET request, e.g., (bun-http-get "https://example.com") 'bun-sqlite-query': async (query) => await fetchEndpoint('/bun/sqlite-query', { query }), // SQLite query, e.g., (bun-sqlite-query "SELECT * FROM wbs")
// Agile: WBS and SPIDR (#NoEstimates) 'wbs-add': async (task, status = 'TODO', depends_on_id = null) => await fetchEndpoint('/agile/wbs-add', { task, status, depends_on_id }), // Add WBS task, e.g., (wbs-add "Test API" "TODO") 'wbs-update': async (id, status) => await fetchEndpoint('/agile/wbs-update', { id, status }), // Update WBS task, e.g., (wbs-update 1 "DONE") 'wbs-query': async (filter = '%') => await fetchEndpoint('/agile/wbs-query', { filter }), // Query WBS tasks, e.g., (wbs-query "TODO") 'wbs-progress': async () => await fetchEndpoint('/agile/wbs-progress', {}), // Get WBS progress, e.g., (wbs-progress) 'spidr-add': async (category, desc, wbs_id) => await fetchEndpoint('/agile/spidr-add', { category, desc, wbs_id }), // Add SPIDR entry, e.g., (spidr-add "Spike" "API research" 1) 'spidr-split': async (story, category) => await fetchEndpoint('/agile/spidr-split', { story, category }), // Split story, e.g., (spidr-split "Login, Profile" "Spike")
// Org Mode 'org-parse': async (content) => await fetchEndpoint('/org/parse', { content }), // Parse Org Mode text, e.g., (org-parse "* TODO Task #+WBS: 1") 'org-agenda': async (query = '%') => await fetchEndpoint('/org/agenda', { query }), // Query agenda, e.g., (org-agenda "TODO")
// Undo/Redo and Logging 'undo': async () => await fetchEndpoint('/db/undo', {}), // Undo last action 'redo': async () => await fetchEndpoint('/db/redo', {}), // Redo last undone action 'log-search': async (query) => await fetchEndpoint('/db/log-search', { query }), // Search logs, e.g., (log-search "wbs-add")
// Redis functions (optional, concise stubs) $(if ($useRedis) { @" 'redis-set': async (key, value) => { try { await redis.set(key, JSON.stringify(value)); return 'OK'; } catch (e) { return 'Error'; } }, 'redis-get': async (key) => { try { const value = await redis.get(key); return value ? JSON.parse(value) : null; } catch (e) { return null; } }, 'redis-publish': async (channel, message) => { try { await redis.publish(channel, JSON.stringify(message)); return 'Published'; } catch (e) { return 'Error'; } }, 'redis-subscribe': async (channel) => { const subscriber = redis.duplicate(); try { await subscriber.connect(); await subscriber.subscribe(channel, (message) => console.log(Redis ${channel}:, JSON.parse(message))); return 'Subscribed'; } catch (e) { return 'Error'; } },"@ } else { @" 'redis-set': () => 'Redis disabled', 'redis-get': () => 'Redis disabled', 'redis-publish': () => 'Redis disabled', 'redis-subscribe': () => 'Redis disabled',"@ })
// Prolog-like querying (simplified unification) 'query': async (pattern) => { const wbs = await fetchEndpoint('/agile/wbs-query', { filter: '%' }); const spidr = await fetchEndpoint('/agile/spidr-query', { filter: '%' }); const results = []; const unify = (data, pat) => { if (typeof pat === 'string' && pat.startsWith('?')) return true; // Variable if (typeof data !== typeof pat) return false; if (Array.isArray(data) && Array.isArray(pat)) { if (data.length !== pat.length) return false; return data.every((d, i) => unify(d, pat[i])); } if (typeof data === 'object' && typeof pat === 'object') { return Object.keys(pat).every(k => unify(data[k], pat[k])); } return data === pat; }; for (const item of [...wbs, ...spidr]) { if (unify(item, pattern)) results.push(item); } return results; },
// Tau Prolog for advanced queries 'prolog-query': async (query) => prologQuery(query), // Run Tau Prolog query, e.g., (prolog-query "status(Id, 'DONE').")
// Expanded Kanren logic programming 'kanren': async (goals) => kanren(goals), // Run Kanren goals, e.g., (kanren (fresh (id) (== (wbs-query ?id) {"status": "DONE"}))) '==': (x, y) => ['==', x, y], // Unification operator 'fresh': (vars, goal) => ['fresh', vars, goal], // Introduce logic variables 'conde': (...clauses) => ['conde', ...clauses], // Disjunction (either/or) 'conda': (...clauses) => ['conda', ...clauses], // Conditional disjunction
// Data format parsers 'json5-parse': async (source) => await fetchEndpoint('/parse-json5', { source }), // Parse JSON5 with comments 'cbor-encode': async (data) => await fetchEndpoint('/encode-decode-cbor', { data: JSON.stringify(data), action: 'encode' }), // Encode CBOR 'cbor-decode': async (data) => await fetchEndpoint('/encode-decode-cbor', { data, action: 'decode' }), // Decode CBOR 'msgpack-encode': async (data) => await fetchEndpoint('/encode-decode-msgpack', { data: JSON.stringify(data), action: 'encode' }), // Encode MessagePack 'msgpack-decode': async (data) => await fetchEndpoint('/encode-decode-msgpack', { data, action: 'decode' }), // Decode MessagePack 'bson-encode': async (data) => await fetchEndpoint('/encode-decode-bson', { data: JSON.stringify(data), action: 'encode' }), // Encode BSON 'bson-decode': async (data) => await fetchEndpoint('/encode-decode-bson', { data, action: 'decode' }), // Decode BSON 'hcl-parse': async (source) => await fetchEndpoint('/parse-hcl', { source }), // Parse HCL (Terraform)
// GraphQL query and subscription 'graphql-query': async (query) => await fetchEndpoint('/graphql', { query }), // Run GraphQL query 'graphql-subscribe': async (subscription) => { // Subscribe to GraphQL events via Socket.io (e.g., wbsUpdated) socket.on(subscription, data => console.log('GraphQL Subscription:', data)); return 'Subscribed'; },
// REST interface 'rest-get': async (path, params) => await fetchEndpoint(path, params, 'GET'), // REST GET request 'rest-post': async (path, body) => await fetchEndpoint(path, null, 'POST', body), // REST POST request 'rest-put': async (path, body) => await fetchEndpoint(path, null, 'PUT', body), // REST PUT request 'rest-delete': async (path) => await fetchEndpoint(path, null, 'DELETE'), // REST DELETE request 'rest-subscribe': async (event) => await subscribeEvent(event) // Subscribe to REST events via SSE};
Define macros for DSL-like syntaxmal.eval([ # Macro for WBS creation ['defmacro', 'defwbs', ['task', '&', 'opts'], ['wbs-add', task, ['get', 'opts', '"status"', '"TODO"'], ['get', 'opts', '"depends_on_id"', null]] ], # Macro for SPIDR creation ['defmacro', 'defspidr', ['category', 'desc', 'wbs_id'], ['spidr-add', category, desc, wbs_id] ], # Macro for Org Mode task ['defmacro', 'deftask', ['title', '&', 'opts'], ['org-parse', ['str', '"* TODO "', title, ['if', ['get', 'opts', '"wbs_id"'], ['str', '" #+WBS: "', ['get', 'opts', '"wbs_id"']], '""']]] ], # Macro for Prolog-like rule ['defmacro', 'defrule', ['name', 'pattern', '&', 'body'], ['defn', name, ['&', 'args'], ['let', [['results', ['query', pattern]]], ['map', ['fn', ['result'], ...body], 'results'] ] ] ], # Macro for GraphQL subscription ['defmacro', 'defsubscribe', ['name', '&', 'body'], ['graphql-subscribe', name, ['fn', ['data'], ...body]] ], # Macro for REST subscription ['defmacro', 'defrestsubscribe', ['event', '&', 'body'], ['rest-subscribe', event, ['fn', ['data'], ...body]] ]], env);
// Export eval function for serverexport default function(code, ctx = {}) { return mal.eval(code, { ...env, ...ctx });}"@if (-Not (Test-Path "miniMAL-plus.js")) { try { $malCode | Out-File -FilePath "miniMAL-plus.js" -Encoding UTF8 Log-Message "Created miniMAL-plus.js successfully." } catch { Log-Message "Failed to create miniMAL-plus.js. Error: $_`nPlease check disk permissions and try again." exit 1 }} else { Log-Message "miniMAL-plus.js already exists, skipping creation."}# Validate miniMAL-plus.jsif ((Get-Content "miniMAL-plus.js" -Raw).Length -lt 1000) { Log-Message "Error: miniMAL-plus.js is too small. Something went wrong while creating it. Please delete it and run the script again." exit 1}
Step 6: Create server with consolidated Bun endpoints, additional parsers, GraphQL subscriptions, REST interface with SSE, Socket.io, optional Redis, expanded Kanren, and Tau Prolog$serverCode = @"// index.js - Bun server for WeeX TUI with Bun features, data formats, GraphQL subscriptions, REST interface with SSE, Socket.io, optional Redis caching/messaging, expanded Kanren, and Tau Prolog// Uses @orgajs/reorg for parsing Org Mode syntax (e.g., * TODO Task #+WBS: 1, timestamps, lists) in /org/parse endpointimport { readFileSync } from 'fs';import { fileURLToPath } from 'url';import { createYoga, createSchema } from 'graphql-yoga';import { Server } from 'socket.io';$(if ($useRedis) { @"import { createAdapter } from 'socket.io-redis';import Redis from 'redis';"@ } else { "" })import mal from './miniMAL-plus.js';import N3 from 'n3';import { MikroORM, Entity, PrimaryKey, Property } from '@mikro-orm/core';import { parseString } from 'xml-js';import TOML from '@iarna/toml';import Papa from 'papaparse';import jp from 'jsonpath';import yaml from 'js-yaml';import { readParquet, writeParquet } from 'hyparquet-writer';import avro from 'avsc';import { marked } from 'marked';import Turndown from 'turndown';import jsonld from 'jsonld';import RDFLib from 'rdflib';import RDFXMLParser from 'rdfxml-streaming-parser';import { parseOrg } from '@orgajs/reorg';import JSON5 from 'json5';import cbor from 'cbor';import msgpack from 'msgpack-lite';import BSON from 'bson';import { parse } from 'hcl2-parser';import Tau from 'tau-prolog';const __dirname = fileURLToPath(new URL('.', import.meta.url));
// Optional Redis setup (concise)$(if ($useRedis) { @"const redis = createClient({ url: 'redis://localhost:6379' });redis.connect().catch(err => console.error('Redis connection error:', err));"@ } else { "" })
// Socket.io setup with optional Redis adapterconst io = new Server({ cors: { origin: '', methods: ['GET', 'POST'] }$(if ($useRedis) { ", adapter: createAdapter({ pubClient: redis, subClient: redis.duplicate() })" } else { "" })});
// MikroORM and SQLite setup for persistent storageconst orm = await MikroORM.init({ entities: [], dbName: 'weex.db', type: 'sqlite' });@Entity() class User { @PrimaryKey() id; @Property() name; }orm.getMetadata().addEntity(User);const db = new Bun.SQLite('weex.db');// DB Tables for Undo/Redo, Logging, WBS, SPIDRdb.run('CREATE TABLE IF NOT EXISTS logs (id INTEGER PRIMARY KEY AUTOINCREMENT, action TEXT, data TEXT, refs TEXT, timestamp TEXT, FULLTEXT INDEX (action, data))');db.run('CREATE TABLE IF NOT EXISTS states (id INTEGER PRIMARY KEY AUTOINCREMENT, pane_id TEXT, content TEXT, timestamp TEXT)');db.run('CREATE TABLE IF NOT EXISTS wbs (id INTEGER PRIMARY KEY AUTOINCREMENT, task TEXT, status TEXT, depends_on_id INTEGER, timestamp TEXT, FOREIGN KEY(depends_on_id) REFERENCES wbs(id))');db.run('CREATE TABLE IF NOT EXISTS spidr (id INTEGER PRIMARY KEY AUTOINCREMENT, category TEXT, description TEXT, wbs_id INTEGER, timestamp TEXT, FOREIGN KEY(wbs_id) REFERENCES wbs(id))');let stateIndex = 0; // Tracks undo/redo position
// Tau Prolog interpreter for advanced queriesconst prolog = Tau.core.create();prolog.consult( status(Id, Status) :- wbs(Id, _, Status, _). dependency(Id, Dep) :- wbs(Id, _, _, Dep). ancestor(X, Y) :- dependency(X, Y). ancestor(X, Y) :- dependency(X, Z), ancestor(Z, Y). risk_level(Id, Level) :- spidr(Id, 'Risk', _, _), Level is 3. risk_level(Id, Level) :- spidr(Id, 'Defect', _, _), Level is 2. risk_level(Id, Level) :- spidr(Id, 'Improvement', _, _), Level is 1. high_risk_tasks(Task) :- wbs(Task, _, 'TODO', _), risk_level(Task, Level), Level > 2.);
async function prologQuery(query) { const wbs = await fetchEndpoint('/agile/wbs-query', { filter: '%' }); const spidr = await fetchEndpoint('/agile/spidr-query', { filter: '%' }); let facts = ''; wbs.forEach(t => { facts += wbs(${t.id}, '${t.task}', '${t.status}', ${t.depends_on_id || 'null'}).\n; }); spidr.forEach(s => { facts += spidr(${s.id}, '${s.category}', '${s.description}', ${s.wbs_id}).\n; }); prolog.consult(facts); const answers = prolog.query(query); const results = []; for await (const answer of answers) { results.push(answer.links); } return results;}
// GraphQL schema for querying and subscribing to WBS/SPIDR dataconst schema = createSchema({ typeDefs: type WBS { id: ID! task: String! status: String! depends_on_id: ID timestamp: String! } type SPIDR { id: ID! category: String! description: String! wbs_id: ID! timestamp: String! } type Query { wbsQuery(filter: String = "%"): [WBS] spidrQuery(filter: String = "%"): [SPIDR] } type Subscription { wbsUpdated: WBS spidrUpdated: SPIDR } , resolvers: { Query: { wbsQuery: async (root, { filter }) => { $(if ($useRedis) { @" const cacheKey = wbs:${filter}; const cached = await redis.get(cacheKey); if (cached) return JSON.parse(cached); const result = db.query('SELECT * FROM wbs WHERE task LIKE ? OR status LIKE ?', [filter, filter]).all(); await redis.set(cacheKey, JSON.stringify(result), { EX: 3600 }); return result;"@ } else { "return db.query('SELECT * FROM wbs WHERE task LIKE ? OR status LIKE ?', [filter, filter]).all();" }) }, spidrQuery: async (root, { filter }) => { $(if ($useRedis) { @" const cacheKey = spidr:${filter}; const cached = await redis.get(cacheKey); if (cached) return JSON.parse(cached); const result = db.query('SELECT * FROM spidr WHERE category LIKE ? OR description LIKE ?', [filter, filter]).all(); await redis.set(cacheKey, JSON.stringify(result), { EX: 3600 }); return result;"@ } else { "return db.query('SELECT * FROM spidr WHERE category LIKE ? OR description LIKE ?', [filter, filter]).all();" }) }, }, Subscription: { wbsUpdated: { subscribe: () => { const iterator = { next: () => new Promise(resolve => { io.on('connection', (socket) => socket.on('wbs-updated', data => resolve({ value: data, done: false }))); }), return: () => Promise.resolve({ done: true }), [Symbol.asyncIterator]: () => iterator }; return iterator; }, resolve: payload => payload, }, spidrUpdated: { subscribe: () => { const iterator = { next: () => new Promise(resolve => { io.on('connection', (socket) => socket.on('spidr-updated', data => resolve({ value: data, done: false }))); }), return: () => Promise.resolve({ done: true }), [Symbol.asyncIterator]: () => iterator }; return iterator; }, resolve: payload => payload, }, }, },});
// SSE clients for REST subscriptionsconst sseClients = new Map();
Bun.serve({ port: 3000, async fetch(req) { const url = new URL(req.url); const serveFile = (path) => Bun.file(path).stream({ type: 'application/javascript' }); const headers = { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '' }; if (url.pathname === '/') return new Response(readFileSync(${__dirname}/index.html), { headers: { 'Content-Type': 'text/html' } }); if (url.pathname.endsWith('.js')) return serveFile(${__dirname}${url.pathname}); if (url.pathname.endsWith('.css')) return new Response(readFileSync(${__dirname}${url.pathname}), { headers: { 'Content-Type': 'text/css' } }); if (url.pathname === '/socket.io/socket.io.js') return serveFile(${__dirname}/node_modules/socket.io/client-dist/socket.io.js); if (url.pathname === '/graphql') { const yoga = createYoga({ schema }); return yoga(req); } if (url.pathname === '/eval-lisp') { const code = url.searchParams.get('code'); const result = mal(code, {}); db.run('INSERT INTO logs (action, data, refs, timestamp) VALUES (?, ?, ?, ?)', ['lisp-eval', code, JSON.stringify({}), new Date().toISOString()]); return new Response(JSON.stringify({ result }), { headers }); } // REST endpoints if (url.pathname === '/rest/wbs' && req.method === 'GET') { const filter = url.searchParams.get('filter') || '%'; const result = db.query('SELECT * FROM wbs WHERE task LIKE ? OR status LIKE ?', [filter, filter]).all(); return new Response(JSON.stringify({ result }), { headers }); } if (url.pathname === '/rest/wbs' && req.method === 'POST') { try { const body = await req.json(); const { task, status = 'TODO', depends_on_id = null } = body; db.run('INSERT INTO wbs (task, status, depends_on_id, timestamp) VALUES (?, ?, ?, ?)', [task, status, depends_on_id, new Date().toISOString()]); const id = db.query('SELECT last_insert_rowid() as id').get().id; const wbsData = { id, task, status, depends_on_id, timestamp: new Date().toISOString() }; db.run('INSERT INTO logs (action, data, refs, timestamp) VALUES (?, ?, ?, ?)', ['wbs-add', task, JSON.stringify({ wbs_id: id }), new Date().toISOString()]); io.emit('wbs-updated', wbsData); return new Response(JSON.stringify({ result: id }), { headers }); } catch (e) { return new Response(JSON.stringify({ error: Failed to create WBS: ${e.message} }), { status: 500, headers }); } } if (url.pathname.startsWith('/rest/wbs/') && req.method === 'PUT') { try { const id = url.pathname.split('/')[3]; const body = await req.json(); const { status } = body; db.run('UPDATE wbs SET status = ?, timestamp = ? WHERE id = ?', [status, new Date().toISOString(), id]); const wbsData = db.query('SELECT * FROM wbs WHERE id = ?', [id]).get(); db.run('INSERT INTO logs (action, data, refs, timestamp) VALUES (?, ?, ?, ?)', ['wbs-update', id:${id},status:${status}, JSON.stringify({ wbs_id: id }), new Date().toISOString()]); io.emit('wbs-updated', wbsData); return new Response(JSON.stringify({ result: 'Updated' }), { headers }); } catch (e) { return new Response(JSON.stringify({ error: Failed to update WBS: ${e.message} }), { status: 500, headers }); } } if (url.pathname.startsWith('/rest/wbs/') && req.method === 'DELETE') { try { const id = url.pathname.split('/')[3]; db.run('DELETE FROM wbs WHERE id = ?', [id]); db.run('INSERT INTO logs (action, data, refs, timestamp) VALUES (?, ?, ?, ?)', ['wbs-delete', id:${id}, JSON.stringify({ wbs_id: id }), new Date().toISOString()]); io.emit('wbs-updated', { id, action: 'deleted' }); return new Response(JSON.stringify({ result: 'Deleted' }), { headers }); } catch (e) { return new Response(JSON.stringify({ error: Failed to delete WBS: ${e.message} }), { status: 500, headers }); } } if (url.pathname === '/rest/spidr' && req.method === 'GET') { const filter = url.searchParams.get('filter') || '%'; const result = db.query('SELECT * FROM spidr WHERE category LIKE ? OR description LIKE ?', [filter, filter]).all(); return new Response(JSON.stringify({ result }), { headers }); } if (url.pathname === '/rest/spidr' && req.method === 'POST') { try { const body = await req.json(); const { category, description, wbs_id } = body; db.run('INSERT INTO spidr (category, description, wbs_id, timestamp) VALUES (?, ?, ?, ?)', [category, description, wbs_id, new Date().toISOString()]); const id = db.query('SELECT last_insert_rowid() as id').get().id; const spidrData = { id, category, description, wbs_id, timestamp: new Date().toISOString() }; db.run('INSERT INTO logs (action, data, refs, timestamp) VALUES (?, ?, ?, ?)', ['spidr-add', ${category}:${description}, JSON.stringify({ spidr_id: id, wbs_id }), new Date().toISOString()]); io.emit('spidr-updated', spidrData); return new Response(JSON.stringify({ result: id }), { headers }); } catch (e) { return new Response(JSON.stringify({ error: Failed to create SPIDR: ${e.message} }), { status: 500, headers }); } } if (url.pathname === '/rest/logs' && req.method === 'GET') { const query = url.searchParams.get('query') || '%'; const result = db.query('SELECT * FROM logs WHERE action LIKE ? OR data LIKE ?', [%${query}%, %${query}%]).all(); return new Response(JSON.stringify({ result }), { headers }); } if (url.pathname === '/rest/subscribe') { const event = url.searchParams.get('event'); if (!event || !['wbs-updated', 'spidr-updated'].includes(event)) { return new Response(JSON.stringify({ error: 'Invalid or missing event parameter' }), { status: 400, headers }); } const clientId = Math.random().toString(36).slice(2); const sseHeaders = { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Access-Control-Allow-Origin': '' }; const stream = new ReadableStream({ start(controller) { sseClients.set(clientId, controller); controller.enqueue(data: {"message": "Subscribed to ${event}"}\n\n); io.on('connection', (socket) => socket.on(event, data => { controller.enqueue(data: ${JSON.stringify(data)}\n\n); })); }, cancel() { sseClients.delete(clientId); }, }); return new Response(stream, { headers: sseHeaders }); } // Redis endpoints (optional) $(if ($useRedis) { @" if (url.pathname === '/redis/set') { const key = url.searchParams.get('key'); const value = url.searchParams.get('value'); await redis.set(key, value); return new Response(JSON.stringify({ result: 'OK' }), { headers }); } if (url.pathname === '/redis/get') { const key = url.searchParams.get('key'); const value = await redis.get(key); return new Response(JSON.stringify({ result: value }), { headers }); } if (url.pathname === '/redis/publish') { const channel = url.searchParams.get('channel'); const message = url.searchParams.get('message'); await redis.publish(channel, message); return new Response(JSON.stringify({ result: 'Published' }), { headers }); } if (url.pathname === '/redis/subscribe') { const channel = url.searchParams.get('channel'); const clientId = Math.random().toString(36).slice(2); const sseHeaders = { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Access-Control-Allow-Origin': '' }; const stream = new ReadableStream({ start(controller) { sseClients.set(clientId, controller); controller.enqueue(data: {"message": "Subscribed to ${channel}"}\n\n); const subscriber = redis.duplicate(); subscriber.connect().then(() => { subscriber.subscribe(channel, (message) => { controller.enqueue(data: ${message}\n\n); }); }); }, cancel() { sseClients.delete(clientId); }, }); return new Response(stream, { headers: sseHeaders }); }"@ }) // Bun feature endpoints if (url.pathname === '/bun/shell') { const cmd = url.searchParams.get('cmd'); try { const result = await Bun.shell(cmd).text(); db.run('INSERT INTO logs (action, data, refs, timestamp) VALUES (?, ?, ?, ?)', ['shell', cmd, JSON.stringify({}), new Date().toISOString()]); return new Response(JSON.stringify({ result }), { headers }); } catch (e) { return new Response(JSON.stringify({ error: Shell error: ${e.message} }), { status: 500, headers }); } } if (url.pathname === '/bun/worker') { const script = url.searchParams.get('script'); try { const worker = new Worker(URL.createObjectURL(new Blob([script], { type: 'application/javascript' }))); const result = await new Promise(resolve => worker.onmessage = e => resolve(e.data)); worker.terminate(); db.run('INSERT INTO logs (action, data, refs, timestamp) VALUES (?, ?, ?, ?)', ['worker', script, JSON.stringify({}), new Date().toISOString()]); return new Response(JSON.stringify({ result }), { headers }); } catch (e) { return new Response(JSON.stringify({ error: Worker error: ${e.message} }), { status: 500, headers }); } } if (url.pathname === '/bun/fs-read') { const path = url.searchParams.get('path'); try { const result = await Bun.file(path).text(); db.run('INSERT INTO logs (action, data, refs, timestamp) VALUES (?, ?, ?, ?)', ['fs-read', path, JSON.stringify({}), new Date().toISOString()]); return new Response(JSON.stringify({ result }), { headers }); } catch (e) { return new Response(JSON.stringify({ error: File read error: ${e.message} }), { status: 500, headers }); } } if (url.pathname === '/bun/fs-write') { const path = url.searchParams.get('path'); const data = url.searchParams.get('data'); try { await Bun.write(Bun.file(path), data); db.run('INSERT INTO logs (action, data, refs, timestamp) VALUES (?, ?, ?, ?)', ['fs-write', ${path}: ${data}, JSON.stringify({}), new Date().toISOString()]); return new Response(JSON.stringify({ result: 'Written' }), { headers }); } catch (e) { return new Response(JSON.stringify({ error: File write error: ${e.message} }), { status: 500, headers }); } } if (url.pathname === '/bun/http-get') { const url = url.searchParams.get('url'); try { const result = await fetch(url).then(res => res.text()); db.run('INSERT INTO logs (action, data, refs, timestamp) VALUES (?, ?, ?, ?)', ['http-get', url, JSON.stringify({}), new Date().toISOString()]); return new Response(JSON.stringify({ result }), { headers }); } catch (e) { return new Response(JSON.stringify({ error: HTTP get error: ${e.message} }), { status: 500, headers }); } } if (url.pathname === '/bun/sqlite-query') { const query = url.searchParams.get('query'); try { const result = db.query(query).all(); db.run('INSERT INTO logs (action, data, refs, timestamp) VALUES (?, ?, ?, ?)', ['sqlite-query', query, JSON.stringify({}), new Date().toISOString()]); return new Response(JSON.stringify({ result }), { headers }); } catch (e) { return new Response(JSON.stringify({ error: SQLite query error: ${e.message} }), { status: 500, headers }); } } // Data format endpoints if (url.pathname === '/parse-xml') { const source = url.searchParams.get('source'); const query = url.searchParams.get('query'); const json = parseString(source, { compact: true }); db.run('INSERT INTO logs (action, data, refs, timestamp) VALUES (?, ?, ?, ?)', ['parse-xml', source, JSON.stringify({ query }), new Date().toISOString()]); return new Response(JSON.stringify({ result: query ? jp.query(json, query) : json }), { headers }); } if (url.pathname === '/parse-json5') { const source = url.searchParams.get('source'); try { const result = JSON5.parse(source); db.run('INSERT INTO logs (action, data, refs, timestamp) VALUES (?, ?, ?, ?)', ['parse-json5', source, JSON.stringify({}), new Date().toISOString()]); return new Response(JSON.stringify({ result }), { headers }); } catch (e) { return new Response(JSON.stringify({ error: JSON5 parse error: ${e.message} }), { status: 500, headers }); } } if (url.pathname === '/encode-decode-cbor') { const data = url.searchParams.get('data'); const action = url.searchParams.get('action'); try { const result = action === 'encode' ? cbor.encode(JSON.parse(data)) : cbor.decode(Buffer.from(data, 'base64')); db.run('INSERT INTO logs (action, data, refs, timestamp) VALUES (?, ?, ?, ?)', ['cbor-' + action, data, JSON.stringify({}), new Date().toISOString()]); return new Response(JSON.stringify({ result: action === 'encode' ? Buffer.from(result).toString('base64') : result }), { headers }); } catch (e) { return new Response(JSON.stringify({ error: CBOR ${action} error: ${e.message} }), { status: 500, headers }); } } if (url.pathname === '/encode-decode-msgpack') { const data = url.searchParams.get('data'); const action = url.searchParams.get('action'); try { const result = action === 'encode' ? msgpack.encode(JSON.parse(data)) : msgpack.decode(Buffer.from(data, 'base64')); db.run('INSERT INTO logs (action, data, refs, timestamp) VALUES (?, ?, ?, ?)', ['msgpack-' + action, data, JSON.stringify({}), new Date().toISOString()]); return new Response(JSON.stringify({ result: action === 'encode' ? Buffer.from(result).toString('base64') : result }), { headers }); } catch (e) { return new Response(JSON.stringify({ error: MessagePack ${action} error: ${e.message} }), { status: 500, headers }); } } if (url.pathname === '/encode-decode-bson') { const data = url.searchParams.get('data'); const action = url.searchParams.get('action'); try { const result = action === 'encode' ? BSON.serialize(JSON.parse(data)) : BSON.deserialize(Buffer.from(data, 'base64')); db.run('INSERT INTO logs (action, data, refs, timestamp) VALUES (?, ?, ?, ?)', ['bson-' + action, data, JSON.stringify({}), new Date().toISOString()]); return new Response(JSON.stringify({ result: action === 'encode' ? Buffer.from(result).toString('base64') : result }), { headers }); } catch (e) { return new Response(JSON.stringify({ error: BSON ${action} error: ${e.message} }), { status: 500, headers }); } } if (url.pathname === '/parse-hcl') { const source = url.searchParams.get('source'); try { const result = parse(source); db.run('INSERT INTO logs (action, data, refs, timestamp) VALUES (?, ?, ?, ?)', ['parse-hcl', source, JSON.stringify({}), new Date().toISOString()]); return new Response(JSON.stringify({ result }), { headers }); } catch (e) { return new Response(JSON.stringify({ error: HCL parse error: ${e.message} }), { status: 500, headers }); } } // Org Mode endpoints if (url.pathname === '/org/parse') { const content = url.searchParams.get('content'); const ast = parseOrg(content); db.run('INSERT INTO logs (action, data, refs, timestamp) VALUES (?, ?, ?, ?)', ['org-parse', content, JSON.stringify({}), new Date().toISOString()]); return new Response(JSON.stringify({ ast }), { headers }); } if (url.pathname === '/org/agenda') { const query = url.searchParams.get('query') || '%'; const wbs = db.query('SELECT * FROM wbs WHERE task LIKE ?', [query]).all(); const agenda = wbs.map(t => ({ id: t.id, task: t.task, status: t.status })); return new Response(JSON.stringify({ agenda }), { headers }); } // SPIDR query endpoint (for Prolog-like queries) if (url.pathname === '/agile/spidr-query') { const filter = url.searchParams.get('filter') || '%'; const result = db.query('SELECT * FROM spidr WHERE category LIKE ? OR description LIKE ?', [filter, filter]).all(); return new Response(JSON.stringify({ result }), { headers }); } // Prolog/Kanren query endpoint if (url.pathname === '/prolog/query') { const pattern = url.searchParams.get('pattern'); try { const wbs = db.query('SELECT * FROM wbs').all(); const spidr = db.query('SELECT * FROM spidr').all(); const results = []; const unify = (data, pat) => { if (typeof pat === 'string' && pat.startsWith('?')) return true; if (typeof data !== typeof pat) return false; if (Array.isArray(data) && Array.isArray(pat)) { if (data.length !== pat.length) return false; return data.every((d, i) => unify(d, pat[i])); } if (typeof data === 'object' && typeof pat === 'object') { return Object.keys(pat).every(k => unify(data[k], pat[k])); } return data === pat; }; const parsedPattern = JSON.parse(pattern); for (const item of [...wbs, ...spidr]) { if (unify(item, parsedPattern)) results.push(item); } return new Response(JSON.stringify({ result: results }), { headers }); } catch (e) { return new Response(JSON.stringify({ error: Prolog query error: ${e.message} }), { status: 500, headers }); } } return new Response('Not found', { status: 404 }); }, error() { console.log('Server ready: http://localhost:3000'); }});
// Attach Socket.io to a separate port for real-time subscriptionsio.listen(3001);"@if (-Not (Test-Path "index.js")) { try { $serverCode | Out-File -FilePath "index.js" -Encoding UTF8 Log-Message "Created index.js successfully." } catch { Log-Message "Failed to create index.js. Error: $_`nPlease check disk permissions and try again." exit 1 }} else { Log-Message "index.js already exists, skipping creation."}# Validate index.jsif ((Get-Content "index.js" -Raw).Length -lt 1000) { Log-Message "Error: index.js is too small. Something went wrong while creating it. Please delete it and run the script again." exit 1}
Step 7: Create HTML/JS client (updated for Org Mode, state logging, additional parsers, GraphQL subscriptions, REST interface with SSE, optional Redis, and Kanren)$htmlCode = @" <title>WeeX - Max TUI Dashboard</title> <style> @font-face { font-family: 'Atkinson Mono Nerd Font'; src: url('fonts/AtkinsonMonoNerdFont-Regular.otf') format('opentype'); font-weight: normal; } body { margin: 0; font-family: 'Atkinson Mono Nerd Font', monospace; background: #000; color: #fff; font-variant-ligatures: none; } #terminal { height: 100vh; } </style> <script src='xterm/lib/xterm.js'></script> <script src='xterm-addon-fit/lib/xterm-addon-fit.js'></script> <script src='neo-blessed/lib/blessed.js'></script> <script src='blessed-contrib/lib/index.js'></script> <script src='mathjs/lib/browser/math.js'></script> <script src='katex/dist/katex.js'></script> <script src='mermaid/dist/mermaid.min.js'></script> <script src='n3/lib/N3.js'></script> <script src='@mikro-orm/core/dist/index.js'></script> <script src='xml-js/lib/index.js'></script> <script src='@iarna/toml/lib/toml.js'></script> <script src='papaparse/papaparse.min.js'></script> <script src='jsonpath/lib/jsonpath.js'></script> <script src='js-yaml/dist/js-yaml.min.js'></script> <script src='parquet-wasm/lib/index.js'></script> <script src='avsc/lib/index.js'></script> <script src='marked/lib/marked.js'></script> <script src='jsonld/lib/jsonld.js'></script> <script src='rdflib/rdflib.js'></script> <script src='rdfxml-streaming-parser/lib/index.js'></script> <script src='hyparquet-writer/lib/index.js'></script> <script src='turndown/lib/turndown.js'></script> <script src='@orgajs/reorg/lib/index.js'></script> <script src='json5/lib/index.js'></script> <script src='cbor/lib/cbor.js'></script> <script src='msgpack-lite/lib/index.js'></script> <script src='bson/lib/index.js'></script> <script src='hcl2-parser/lib/index.js'></script> <script src='socket.io-client/dist/socket.io.js'></script> <script src='tau-prolog/lib/tau-prolog.js'></script> <script src='miniMAL-plus.js'></script> <script> // Initialize terminal with xterm.js const term = new Terminal({ fontFamily: 'Atkinson Mono Nerd Font, monospace' }); const fit = new FitAddon.FitAddon(); term.loadAddon(fit); term.open(document.getElementById('terminal')); fit.fit(); const tui = new XTermTUI(term); const screen = tui.blessed.screen({ terminal: tui, title: 'WeeX' }); screen.log = () => {};
// TUI navigation and pane management let prefixMode = false; let currentPane = 0; const panes = []; screen.key(['C-b'], () => { prefixMode = true; screen.log('Prefix: % splitH | " splitV | h/j/k/l nav | n next | q quit'); }); screen.key(['%'], (ch) => { if (prefixMode) { panes.push(createNewPane('repl')); screen.append(panes[panes.length-1]); } prefixMode = false; }); screen.key(['"'], (ch) => { if (prefixMode) { /* Split vertical */ } prefixMode = false; }); screen.key(['h','j','k','l'], (ch) => { if (prefixMode) { currentPane = (currentPane + (ch === 'h' ? -1 : ch === 'j' ? 1 : ch === 'k' ? -1 : 1) + panes.length) % panes.length; panes[currentPane].focus(); } prefixMode = false; }); screen.key(['n'], (ch) => { if (prefixMode) { currentPane = (currentPane + 1) % panes.length; panes[currentPane].focus(); } prefixMode = false; }); screen.key(['escape'], () => prefixMode = false);
function createNewPane(type) { let pane; if (type === 'js') { pane = tui.blessed.textbox({ label: 'JS REPL', inputOnFocus: true, border: 'line' }); pane.on('submit', async (text) => { try { pane.content = eval(text) + '\n'; } catch(e) { pane.content = 'Error: ' + e; } await fetch(/db/state-save?pane=js&content=${encodeURIComponent(pane.content)}); screen.render(); }); } else if (type === 'lisp') { pane = tui.blessed.textbox({ label: 'miniMAL+ (bun-shell, wbs-add, org-parse, redis-set, kanren, prolog-query)' }); pane.on('submit', async (text) => { const res = await fetch(/eval-lisp?code=${encodeURIComponent(text)}); const { result } = await res.json(); pane.content = result + '\n'; await fetch(/db/state-save?pane=lisp&content=${encodeURIComponent(pane.content)}); pane.clearValue(); screen.render(); }); } else if (type === 'math') { pane = tui.blessed.textbox({ label: 'Math.js + KaTeX' }); pane.on('submit', async (text) => { const node = katex.renderToString(math.evaluate(text), { throwOnError: false }); pane.setContent(node); await fetch(/db/state-save?pane=math&content=${encodeURIComponent(pane.content)}); screen.render(); }); } else if (type === 'viz') { pane = tui.blessed.box({ label: 'D3/Vega/Mermaid', width: '100%', height: '100%' }); } else if (type === 'editor') { pane = tui.blessed.textarea({ label: 'Org Mode Editor (#WBS:1)' }); pane.on('submit', async (text) => { const res = await fetch(/org/parse?content=${encodeURIComponent(text)}); const { ast } = await res.json(); pane.content = JSON.stringify(ast, null, 2) + '\n'; await fetch(/db/state-save?pane=editor&content=${encodeURIComponent(pane.content)}); screen.render(); }); } else if (type === 'ml') { pane = tui.blessed.textbox({ label: 'Transformers.js' }); pane.on('submit', async (text) => { const { pipeline } = await import('@xenova/transformers'); const model = await pipeline('sentiment-analysis'); const res = await model(text); pane.content = JSON.stringify(res); await fetch(/db/state-save?pane=ml&content=${encodeURIComponent(pane.content)}); screen.render(); }); } else if (type === 'rdf') { pane = tui.blessed.textbox({ label: 'RDF (N3.js)' }); pane.on('submit', async (text) => { const res = await fetch(/parse-rdf?rdf=${encodeURIComponent(text)}); const triples = await res.json(); pane.content = JSON.stringify(triples, null, 2) + '\n'; await fetch(/db/state-save?pane=rdf&content=${encodeURIComponent(pane.content)}); pane.clearValue(); screen.render(); }); } else if (type === 'orm') { pane = tui.blessed.textbox({ label: 'MikroORM (e.g., create {name:"Alice"})' }); pane.on('submit', async (text) => { const res = await fetch(/orm-query?action=create&data=${encodeURIComponent(text)}); const result = await res.json(); pane.content = JSON.stringify(result) + '\n'; await fetch(/db/state-save?pane=orm&content=${encodeURIComponent(pane.content)}); pane.clearValue(); screen.render(); }); } else if (type === 'xml') { pane = tui.blessed.textbox({ label: 'XML (xml-js)' }); pane.on('submit', async (text) => { const res = await fetch(/parse-xml?source=${encodeURIComponent(text)}); const result = await res.json(); pane.content = JSON.stringify(result, null, 2) + '\n'; await fetch(/db/state-save?pane=xml&content=${encodeURIComponent(pane.content)}); pane.clearValue(); screen.render(); }); } else if (type === 'json5') { pane = tui.blessed.textbox({ label: 'JSON5' }); pane.on('submit', async (text) => { const res = await fetch(/parse-json5?source=${encodeURIComponent(text)}); const result = await res.json(); pane.content = JSON.stringify(result, null, 2) + '\n'; await fetch(/db/state-save?pane=json5&content=${encodeURIComponent(pane.content)}); pane.clearValue(); screen.render(); }); } else if (type === 'cbor') { pane = tui.blessed.textbox({ label: 'CBOR' }); pane.on('submit', async (text) => { const action = text.startsWith('{') ? 'encode' : 'decode'; const res = await fetch(/encode-decode-cbor?data=${encodeURIComponent(text)}&action=${action}); const result = await res.json(); pane.content = JSON.stringify(result, null, 2) + '\n'; await fetch(/db/state-save?pane=cbor&content=${encodeURIComponent(pane.content)}); pane.clearValue(); screen.render(); }); } else if (type === 'msgpack') { pane = tui.blessed.textbox({ label: 'MessagePack' }); pane.on('submit', async (text) => { const action = text.startsWith('{') ? 'encode' : 'decode'; const res = await fetch(/encode-decode-msgpack?data=${encodeURIComponent(text)}&action=${action}); const result = await res.json(); pane.content = JSON.stringify(result, null, 2) + '\n'; await fetch(/db/state-save?pane=msgpack&content=${encodeURIComponent(pane.content)}); pane.clearValue(); screen.render(); }); } else if (type === 'bson') { pane = tui.blessed.textbox({ label: 'BSON' }); pane.on('submit', async (text) => { const action = text.startsWith('{') ? 'encode' : 'decode'; const res = await fetch(/encode-decode-bson?data=${encodeURIComponent(text)}&action=${action}); const result = await res.json(); pane.content = JSON.stringify(result, null, 2) + '\n'; await fetch(/db/state-save?pane=bson&content=${encodeURIComponent(pane.content)}); pane.clearValue(); screen.render(); }); } else if (type === 'hcl') { pane = tui.blessed.textbox({ label: 'HCL' }); pane.on('submit', async (text) => { const res = await fetch(/parse-hcl?source=${encodeURIComponent(text)}); const result = await res.json(); pane.content = JSON.stringify(result, null, 2) + '\n'; await fetch(/db/state-save?pane=hcl&content=${encodeURIComponent(pane.content)}); pane.clearValue(); screen.render(); }); } else if (type === 'graphql') { pane = tui.blessed.textbox({ label: 'GraphQL (Queries & Subscriptions)' }); pane.on('submit', async (text) => { if (text.startsWith('subscription')) { const socket = io('http://localhost:3001'); socket.on(text.includes('wbsUpdated') ? 'wbs-updated' : 'spidr-updated', (data) => { pane.content = JSON.stringify(data, null, 2) + '\n'; fetch(/db/state-save?pane=graphql&content=${encodeURIComponent(pane.content)}); screen.render(); }); } else { const res = await fetch(/graphql?query=${encodeURIComponent(text)}); const result = await res.json(); pane.content = JSON.stringify(result.data, null, 2) + '\n'; await fetch(/db/state-save?pane=graphql&content=${encodeURIComponent(pane.content)}); screen.render(); } pane.clearValue(); }); } else if (type === 'rest') { pane = tui.blessed.textbox({ label: 'REST (GET/POST/PUT/DELETE/Subscribe)' }); pane.on('submit', async (text) => { const [method, path, ...rest] = text.split(' '); if (method.toLowerCase() === 'subscribe') { const event = path; const es = new EventSource(http://localhost:3000/rest/subscribe?event=${event}); es.onmessage = (msg) => { pane.content = JSON.stringify(JSON.parse(msg.data), null, 2) + '\n'; fetch(/db/state-save?pane=rest&content=${encodeURIComponent(pane.content)}); screen.render(); }; es.onerror = () => es.close(); } else { const options = { method: method.toUpperCase() }; if (['POST', 'PUT'].includes(method.toUpperCase())) { options.body = rest.join(' '); options.headers = { 'Content-Type': 'application/json' }; } const res = await fetch(http://localhost:3000${path}, options); const result = await res.json(); pane.content = JSON.stringify(result, null, 2) + '\n'; await fetch(/db/state-save?pane=rest&content=${encodeURIComponent(pane.content)}); screen.render(); } pane.clearValue(); }); } else if (type === 'redis') { pane = tui.blessed.textbox({ label: 'Redis (SET/GET/PUBLISH/SUBSCRIBE)' }); pane.on('submit', async (text) => { const [command, ...args] = text.split(' '); if (command.toLowerCase() === 'subscribe') { const channel = args[0]; const es = new EventSource(http://localhost:3000/redis/subscribe?channel=${channel}); es.onmessage = (msg) => { pane.content = msg.data + '\n'; fetch(/db/state-save?pane=redis&content=${encodeURIComponent(pane.content)}); screen.render(); }; es.onerror = () => es.close(); } else if (command.toLowerCase() === 'set') { const [key, value] = args; const res = await fetch(/redis/set?key=${encodeURIComponent(key)}&value=${encodeURIComponent(value)}); const result = await res.json(); pane.content = JSON.stringify(result, null, 2) + '\n'; await fetch(/db/state-save?pane=redis&content=${encodeURIComponent(pane.content)}); screen.render(); } else if (command.toLowerCase() === 'get') { const key = args[0]; const res = await fetch(/redis/get?key=${encodeURIComponent(key)}); const result = await res.json(); pane.content = JSON.stringify(result, null, 2) + '\n'; await fetch(/db/state-save?pane=redis&content=${encodeURIComponent(pane.content)}); screen.render(); } else if (command.toLowerCase() === 'publish') { const [channel, message] = args; const res = await fetch(/redis/publish?channel=${encodeURIComponent(channel)}&message=${encodeURIComponent(message)}); const result = await res.json(); pane.content = JSON.stringify(result, null, 2) + '\n'; await fetch(/db/state-save?pane=redis&content=${encodeURIComponent(pane.content)}); screen.render(); } pane.clearValue(); }); } else if (type === 'kanren') { pane = tui.blessed.textbox({ label: 'Kanren (e.g., (fresh (id) (== (wbs-query ?id) {"status": "DONE"})))' }); pane.on('submit', async (text) => { const res = await fetch(/eval-lisp?code=${encodeURIComponent(text)}); const { result } = await res.json(); pane.content = JSON.stringify(result, null, 2) + '\n'; await fetch(/db/state-save?pane=kanren&content=${encodeURIComponent(pane.content)}); pane.clearValue(); screen.render(); }); } panes.push(pane); screen.append(pane); return pane; }
['js', 'lisp', 'math', 'viz', 'editor', 'ml', 'rdf', 'orm', 'xml', 'toml', 'csv', 'uml', 'json', 'yaml', 'parquet', 'avro', 'markdown', 'sumo', 'skos', 'schema', 'xmi', 'owl', 'rdfxml', 'json5', 'cbor', 'msgpack', 'bson', 'hcl', 'graphql', 'rest', 'redis', 'kanren'].forEach(type => createNewPane(type)); panes[0].focus(); screen.render(); screen.key(['C-q'], () => window.close()); </script>"@if (-Not (Test-Path "index.html")) { try { $htmlCode | Out-File -FilePath "index.html" -Encoding UTF8 Log-Message "Created index.html successfully." } catch { Log-Message "Failed to create index.html. Error: $_`nPlease check disk permissions and try again." exit 1 }} else { Log-Message "index.html already exists, skipping creation."}# Validate index.htmlif ((Get-Content "index.html" -Raw).Length -lt 1000) { Log-Message "Error: index.html is too small. Something went wrong while creating it. Please delete it and run the script again." exit 1}
Step 8: Create katex.min.css$katexCssDir = "katex/dist"; New-Item -ItemType Directory -Path $katexCssDir -Force$katexCssFile = "$katexCssDir/katex.min.css"$maxRetries = 3if (-Not (Test-Path $katexCssFile)) { Log-Message "KaTeX CSS file ($katexCssFile) not found locally. Copying from node_modules..." try { $katexModulePath = "./node_modules/katex/dist/katex.min.css" if (-Not (Test-Path $katexModulePath)) { Log-Message "Error: KaTeX CSS not found in node_modules. Please ensure 'katex' is installed correctly." exit 1 } Copy-Item -Path $katexModulePath -Destination $katexCssFile -Force Log-Message "Copied KaTeX CSS successfully." } catch { Log-Message "Failed to copy KaTeX CSS. Error: $_`nPlease ensure 'katex' is installed via Bun and try again." exit 1 }}else { Log-Message "Found local KaTeX CSS file ($katexCssFile), skipping copy."}# Validate katex.min.cssif (-Not (Test-Path $katexCssFile)) { Log-Message "Error: KaTeX CSS file ($katexCssFile) was not created. Please try running the script again." exit 1}
Step 9: Check for local Atkinson Mono Nerd Font; download if missing /// commented out on purpose - manually installed
Log-Message "Found local font file ($fontFile), skipping download."
Step 10: Download portable Bun executable dynamically (with checksum)# manually get most current## https://github.com/oven-sh/bun/releases/latest# bun-windows-x64.zip - various others - Mac, Linux (vaious CPUs / distros, etc.# put in root of project
Step 12: Create ZIP$readme = @"WeeX - Portable Browser TUI with Bun Features in Lisp===================================================- Unzip this folder.- Install fonts/AtkinsonMonoNerdFont-Regular.otf (optional, for better text display).- Run: $startFile- Open a web browser and go to: http://localhost:3000- Controls: Press Ctrl+B to access commands (use h/j/k/l to move, % to split horizontally, " to split vertically, n to switch panes, q to quit).- Lisp Commands: Try (bun-shell "ls"), (bun-worker "script"), (bun-fs-read/write "path" "data"), (bun-http-get "url"), (bun-sqlite-query "query").- Agile Tools (#NoEstimates/SPIDR): Use (wbs-add "task" "TODO" depends_on_id), (spidr-add "Spike" "desc" wbs_id), (org-agenda "%").- Undo/Redo: Use (undo), (redo), (log-search "query").- GraphQL: Use (graphql-query "{ wbsQuery { id, task } }") or (graphql-subscribe "wbsUpdated") in Lisp pane, or enter queries/subscriptions in GraphQL pane (e.g., "subscription { wbsUpdated { id, task } }").- REST: Use (rest-get "/rest/wbs"), (rest-post "/rest/wbs" {"task": "New Task"}), (rest-put "/rest/wbs/1" {"status": "DONE"}), (rest-delete "/rest/wbs/1"), or (rest-subscribe "wbs-updated") in Lisp pane, or enter requests in REST pane (e.g., "GET /rest/wbs" or "subscribe wbs-updated").- Org Mode: Editor pane supports * TODO and #+WBS: id for tasks.- Supported Formats: XML, TOML, CSV, UML/XMI, JSON, YAML, Parquet, Avro, Markdown, SUMO, SKOS, Schema.org, OWL, RDF/XML, JSON5, CBOR, MessagePack, BSON, HCL.- Redis (if enabled): (redis-set "key" "value"), (redis-get "key"), (redis-publish "channel" "message"), (redis-subscribe "channel").- Kanren: (kanren (fresh (id) (== (wbs-query ?id) {"status": "DONE"}))), (kanren (fresh (id dep) (== (wbs-query ?id) {"depends_on_id": ?dep}) (conde ((== ?dep 1)) ((== ?dep 2))))), (kanren (conde ((== ?var 1)) ((== ?var 2)) ((== ?var 3)))), (kanren (fresh (l1 l2 l3) (appendo l1 l2 l3) (== l1 [1 2]) (== l2 [3 4]) (== l3 [1 2 3 4]))), (kanren (fresh (x y) (== x 1) (conde ((== y 2)) ((== y 3))))), (kanren (fresh (a b) (conde ((== a 1) (== b 2)) ((== a 3) (== b 4))))).- Tau Prolog: (prolog-query "status(Id, 'DONE')."), (prolog-query "ancestor(5, Y).") for task ancestors, (prolog-query "high_risk_tasks(Task).") for high-risk tasks.- No internet or extra installs needed after unzipping (except Redis if enabled). Built with Bun (2025).- If you have issues, check build.log for details or visit https://github.com/oven-sh/bun for help."@try { $readme | Out-File -FilePath "README.md" -Encoding UTF8 Log-Message "Created README.md successfully."}catch { Log-Message "Failed to create README.md. Error: $_nPlease check disk permissions and try again." exit 1}# Validate README.mdif (-Not (Test-Path "README.md")) { Log-Message "Error: README.md was not created. Please try running the script again." exit 1}try { $zipPaths = @($bunExeName, $startFile, "package.json", "index.js", "index.html", "miniMAL-plus.js", $fontsDir, $katexCssDir, "README.md", "node_modules", "xterm-tui", "neo-blessed", "miniMAL") Log-Message "Creating weex.zip with files and folders: $zipPaths" Compress-Archive -Path $zipPaths -DestinationPath "weex.zip" -CompressionLevel Optimal -Force $zipSize = (Get-Item "weex.zip").Length / 1MB Log-Message "weex.zip created (~$([math]::Round($zipSize, 2)) MB)."}catch { Log-Message "Failed to create weex.zip. Error: $_nPlease ensure you have enough disk space and try running the script again." exit 1}# Validate ZIPif (-Not (Test-Path "weex.zip")) { Log-Message "Error: weex.zip was not created. Please check $logFile and try running the script again." exit 1}
Log-Message "All done! weex.zip is ready. To use it:n1. Unzip weex.zip to a folder.n2. Run $startFile (double-click on Windows, or './$startFile' in terminal on Linux/macOS).n3. Open a web browser and go to http://localhost:3000.nIf you run into problems, check $logFile for details or visit https://github.com/oven-sh/bun for help."
###