mirror of
https://github.com/brazilofmux/tinymux
synced 2026-08-13 00:23:11 -04:00
New JS modules: timers.js — setInterval-based repeating timers hooks.js — CONNECT/DISCONNECT/ACTIVITY event hooks spawns.js — pattern-based output routing to spawn views variables.js — $var.name namespace (world, event, regexp, datetime, temp) mcp.js — MCP 2.1 protocol with simpleedit support Trigger system upgraded: hilite, substitution (find/replace), line classification, TTS, enabled flag, capture group substitution ($0, $1, $2) New slash commands (23 total): /repeat, /killtimer, /timers — timer management /hook, /unhook, /hooks — event hooks /spawn add|remove|list|focus — output routing /log — toggle logging (downloads as file) /speak — text-to-speech via Web Speech API /set, /unset, /vars — variable management Integration: MCP parser per connection, intercepts #$# lines MCP editor dialog (textarea) for remote editing Hooks fire on connect/disconnect with auto-login Timers auto-cancel on disconnect Spawn matching routes to per-tab line buffers Log downloads as timestamped .log file via Blob URL TTS via SpeechSynthesis API Reconnect path wired with all new features Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
60 lines
1.9 KiB
JavaScript
60 lines
1.9 KiB
JavaScript
// spawns.js -- Spawn (output routing) system for the web client.
|
|
'use strict';
|
|
|
|
class SpawnDB {
|
|
constructor() {
|
|
this.spawns = []; // [{name, path, patterns, exceptions, prefix, maxLines, weight}]
|
|
}
|
|
|
|
add(def) {
|
|
const s = {
|
|
name: def.name || '',
|
|
path: def.path || def.name.toLowerCase(),
|
|
patterns: def.patterns || [],
|
|
exceptions: def.exceptions || [],
|
|
prefix: def.prefix || '',
|
|
maxLines: def.maxLines || 20000,
|
|
weight: def.weight || 0,
|
|
};
|
|
s._compiled = s.patterns.map(p => { try { return new RegExp(p, 'i'); } catch(e) { return null; } }).filter(Boolean);
|
|
s._exceptions = s.exceptions.map(p => { try { return new RegExp(p, 'i'); } catch(e) { return null; } }).filter(Boolean);
|
|
|
|
const idx = this.spawns.findIndex(x => x.path === s.path);
|
|
if (idx >= 0) this.spawns[idx] = s;
|
|
else this.spawns.push(s);
|
|
this.spawns.sort((a, b) => a.weight - b.weight);
|
|
}
|
|
|
|
remove(path) {
|
|
this.spawns = this.spawns.filter(s => s.path !== path);
|
|
}
|
|
|
|
list() { return this.spawns; }
|
|
|
|
// Returns array of spawn paths that match this line
|
|
match(line) {
|
|
const matched = [];
|
|
for (const s of this.spawns) {
|
|
if (!s._compiled.length) continue;
|
|
const hits = s._compiled.some(r => r.test(line));
|
|
if (!hits) continue;
|
|
const excepted = s._exceptions.some(r => r.test(line));
|
|
if (excepted) continue;
|
|
matched.push(s.path);
|
|
}
|
|
return matched;
|
|
}
|
|
|
|
loadFrom(defs) {
|
|
this.spawns = [];
|
|
for (const d of defs) this.add(d);
|
|
}
|
|
|
|
toJSON() {
|
|
return this.spawns.map(s => ({
|
|
name: s.name, path: s.path, patterns: s.patterns,
|
|
exceptions: s.exceptions, prefix: s.prefix,
|
|
maxLines: s.maxLines, weight: s.weight,
|
|
}));
|
|
}
|
|
}
|