Skip to content

st33pr1d3r-collab/JellyfishShell-TIDE

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 

Repository files navigation

JellyfishShell-TIDE

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 $maxRetries with ${maxRetries}

Configuration: Set to $true to enable Redis (requires Redis runtime installed)$useRedis = $false

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 11: Create start script# manually create start.bat - # bun.exe index.js

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." ###

About

AI Emacs in Javascript (using bun.exe, blessed, miniMAL, nerd fonts, both symbolic and statistical tools)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors