cli-sim-1 / index.html
dokii's picture
Add 2 files
2bbb97e verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>T20-MAS CLI Simulation</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'JetBrains Mono', monospace;
}
.terminal-container {
height: 100vh;
background-color: #1e293b;
color: #e2e8f0;
display: flex;
flex-direction: column;
}
.output-area {
flex: 1;
overflow-y: auto;
padding: 1rem;
white-space: pre-wrap;
font-size: 0.95rem;
}
.input-line {
display: flex;
align-items: center;
padding: 0.5rem 1rem;
border-top: 1px solid #334155;
background-color: #1e293b;
}
.prompt {
color: #84cc16;
font-weight: bold;
}
.cursor {
display: inline-block;
width: 8px;
height: 1rem;
background-color: #e2e8f0;
animation: blink 1s step-end infinite;
margin-left: 4px;
}
@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}
.command-history {
color: #64748b;
}
.error-text {
color: #ef4444;
}
.success-text {
color: #84cc16;
}
.dir-text {
color: #38bdf8;
}
.file-text {
color: #e2e8f0;
}
.help-header {
color: #facc15;
font-weight: bold;
}
</style>
</head>
<body class="bg-slate-900 text-slate-200">
<div class="terminal-container">
<!-- Output Area -->
<div id="output" class="output-area"></div>
<!-- Input Area -->
<div class="input-line">
<span class="prompt">t20mas@localhost:~$ </span>
<input
id="cli-input"
type="text"
class="bg-transparent text-slate-200 outline-none flex-1 font-mono"
autofocus
autocomplete="off"
spellcheck="false"
/>
<span id="cursor" class="cursor"></span>
</div>
</div>
<script>
// =============================================
// T20-MAS CLI Simulation - Standalone Web App
// Client-Side Multi-Agent System (Conceptual)
// =============================================
// --- Virtual File System (VFS) Simulation ---
const vfs = {
'/': {
type: 'directory',
children: {
'home': {
type: 'directory',
children: {
'user': {
type: 'directory',
children: {
'projects': {
type: 'directory',
children: {}
},
'config.json': {
type: 'file',
content: JSON.stringify({ theme: 'dark', autoSave: true }, null, 2)
},
'README.txt': {
type: 'file',
content: 'Welcome to T20-MAS CLI\nA conceptual multi-agent task system running in-browser.\nTry "agents list" or "help" for commands.'
}
}
}
}
},
'sys': {
type: 'directory',
children: {
'agents': {
type: 'directory',
children: {
'orchestrator.agent': {
type: 'file',
content: 'Role: Plan Generation\nModel: WebLLM-7B\nStatus: Active'
},
'researcher.agent': {
type: 'file',
content: 'Role: Information Retrieval\nModel: WebLLM-7B\nStatus: Idle'
},
'writer.agent': {
type: 'file',
content: 'Role: Content Generation\nModel: WebLLM-7B\nStatus: Idle'
}
}
},
'tasks.db': {
type: 'file',
content: JSON.stringify([
{ id: 't001', agent: 'orchestrator', status: 'completed', desc: 'Initialize system' }
])
},
'artifacts': {
type: 'directory',
children: {}
}
}
},
'bin': {
type: 'directory',
children: {
't20-cli': {
type: 'file',
content: 'T20-MAS Command Line Interface v0.1.0 (in-browser)'
}
}
}
}
}
};
// --- Client-Side State Management ---
const state = {
currentPath: '/home/user',
commandHistory: [],
historyIndex: -1,
agents: new Map([
['orchestrator', { role: 'Plan Orchestration', status: 'active', tasks: [] }],
['researcher', { role: 'Research & Retrieval', status: 'idle', tasks: [] }],
['writer', { role: 'Content Generation', status: 'idle', tasks: [] }]
]),
session: {
sessionId: 'sess_' + Math.random().toString(36).substr(2, 9),
startTime: new Date(),
goal: '',
status: 'active'
},
artifacts: []
};
// Initialize localStorage persistence
function initStorage() {
if (!localStorage.getItem('t20mas_vfs')) {
localStorage.setItem('t20mas_vfs', JSON.stringify(vfs));
localStorage.setItem('t20mas_state', JSON.stringify(state));
} else {
Object.assign(vfs, JSON.parse(localStorage.getItem('t20mas_vfs')));
Object.assign(state, JSON.parse(localStorage.getItem('t20mas_state')));
}
}
// Save state
function saveState() {
localStorage.setItem('t20mas_vfs', JSON.stringify(vfs));
localStorage.setItem('t20mas_state', JSON.stringify(state));
}
// --- DOM Elements ---
const outputArea = document.getElementById('output');
const cliInput = document.getElementById('cli-input');
const cursor = document.getElementById('cursor');
// --- Utility Functions ---
function log(message, className = '') {
const line = document.createElement('div');
line.className = className;
line.innerText = message;
outputArea.appendChild(line);
outputArea.scrollTop = outputArea.scrollHeight;
}
function getCurrentDir() {
let dir = vfs['/'];
const parts = state.currentPath.split('/').filter(p => p);
for (const part of parts) {
if (dir.children[part] && dir.children[part].type === 'directory') {
dir = dir.children[part];
} else {
return null;
}
}
return dir;
}
function resolvePath(path) {
if (path.startsWith('/')) return path;
return `${state.currentPath}/${path}`.replace(/\/+/g, '/').replace(/\/$/, '') || '/';
}
function navigateTo(path) {
const fullPath = resolvePath(path);
const dir = getDirectoryByPath(fullPath);
if (dir) {
state.currentPath = fullPath;
saveState();
return true;
}
return false;
}
function getDirectoryByPath(path) {
if (path === '/') return vfs['/'];
let dir = vfs['/'];
const parts = path.split('/').filter(p => p);
for (const part of parts) {
if (dir.children[part] && dir.children[part].type === 'directory') {
dir = dir.children[part];
} else {
return null;
}
}
return dir;
}
function getFileByPath(path) {
const parts = path.split('/').filter(p => p);
const filename = parts.pop();
const dirPath = '/' + parts.join('/');
const dir = getDirectoryByPath(dirPath);
if (dir && dir.children[filename] && dir.children[filename].type === 'file') {
return dir.children[filename];
}
return null;
}
function createFile(path, content = '') {
const parts = path.split('/').filter(p => p);
const filename = parts.pop();
const dirPath = '/' + parts.join('/');
const dir = getDirectoryByPath(dirPath);
if (dir) {
dir.children[filename] = {
type: 'file',
content: content
};
saveState();
return true;
}
return false;
}
function deleteFile(path) {
const parts = path.split('/').filter(p => p);
const filename = parts.pop();
const dirPath = '/' + parts.join('/');
const dir = getDirectoryByPath(dirPath);
if (dir && dir.children[filename]) {
delete dir.children[filename];
saveState();
return true;
}
return false;
}
function createDirectory(path) {
const parts = path.split('/').filter(p => p);
const dirname = parts.pop();
const dirPath = '/' + parts.join('/');
const parentDir = getDirectoryByPath(dirPath);
if (parentDir) {
parentDir.children[dirname] = {
type: 'directory',
children: {}
};
saveState();
return true;
}
return false;
}
// --- Command Handlers ---
const commands = {
help: () => {
log('T20-MAS CLI - Available Commands:', 'help-header');
log('');
log('System & Navigation:');
log(' help - Show this help');
log(' clear - Clear the screen');
log(' exit - Exit the system');
log(' history - Show command history');
log(' pwd - Print working directory');
log(' ls [dir] - List directory contents');
log(' cd <dir> - Change directory');
log(' cat <file> - Display file content');
log(' mkdir <dir> - Create a directory');
log(' touch <file> - Create an empty file');
log(' rm <file> - Delete a file');
log(' echo <text> - Print text');
log('');
log('Multi-Agent System (T20-MAS):');
log(' agents list - List all agents');
log(' agents status - Show agent statuses');
log(' task run <goal> - Start a new task (e.g., task run write a poem about AI)');
log(' task list - List current tasks');
log(' artifacts list - List generated artifacts');
log(' session info - Show current session info');
},
clear: () => {
outputArea.innerHTML = '';
},
exit: () => {
log('Shutting down T20-MAS...');
setTimeout(() => {
log('Session terminated. See you next time.');
}, 800);
},
history: () => {
state.commandHistory.forEach((cmd, i) => {
log(`${i + 1} ${cmd}`, 'command-history');
});
},
pwd: () => {
log(state.currentPath);
},
ls: (args) => {
const target = args[0] ? resolvePath(args[0]) : state.currentPath;
const dir = getDirectoryByPath(target);
if (!dir) {
log(`ls: cannot access '${target}': No such directory`, 'error-text');
return;
}
const items = Object.keys(dir.children).sort();
items.forEach(item => {
const isDir = dir.children[item].type === 'directory';
log(isDir ? `${item}/` : item, isDir ? 'dir-text' : 'file-text');
});
},
cd: (args) => {
if (!args[0]) {
log('cd: missing operand');
return;
}
const dir = args[0];
if (dir === '..') {
const parts = state.currentPath.split('/');
parts.pop();
state.currentPath = parts.join('/') || '/';
saveState();
return;
}
const success = navigateTo(dir);
if (!success) {
log(`cd: ${dir}: No such directory`, 'error-text');
}
},
cat: (args) => {
if (!args[0]) {
log('cat: missing file operand');
return;
}
const file = getFileByPath(resolvePath(args[0]));
if (file) {
log(file.content);
} else {
log(`cat: ${args[0]}: No such file`, 'error-text');
}
},
mkdir: (args) => {
if (!args[0]) {
log('mkdir: missing operand');
return;
}
const success = createDirectory(resolvePath(args[0]));
if (!success) {
log(`mkdir: cannot create directory '${args[0]}': No such directory`, 'error-text');
} else {
log(`Directory '${args[0]}' created.`);
}
},
touch: (args) => {
if (!args[0]) {
log('touch: missing operand');
return;
}
const path = resolvePath(args[0]);
const parts = path.split('/');
const filename = parts.pop();
const dirPath = '/' + parts.join('/');
if (!getDirectoryByPath(dirPath)) {
log(`touch: cannot create '${args[0]}': No such directory`, 'error-text');
return;
}
if (!getFileByPath(path)) {
createFile(path, '');
log(`File '${args[0]}' created.`);
}
},
rm: (args) => {
if (!args[0]) {
log('rm: missing operand');
return;
}
const success = deleteFile(resolvePath(args[0]));
if (success) {
log(`File '${args[0]}' deleted.`);
} else {
log(`rm: cannot remove '${args[0]}': No such file`, 'error-text');
}
},
echo: (args) => {
log(args.join(' '));
},
// --- T20-MAS SPECIFIC COMMANDS ---
agents: (args) => {
if (args[0] === 'list') {
log('Agents in T20-MAS:', 'help-header');
state.agents.forEach((profile, id) => {
log(` ${id} [${profile.role}] - ${profile.status}`);
});
} else if (args[0] === 'status') {
log('Agent Status:', 'help-header');
state.agents.forEach((profile, id) => {
log(` ${id}: ${profile.status}`);
});
} else {
log("Agents subcommands: 'list', 'status'");
}
},
task: (args) => {
if (args[0] === 'run' && args.length > 1) {
const goal = args.slice(1).join(' ');
state.session.goal = goal;
log(`🎯 Starting new task: "${goal}"`, 'success-text');
log('🧠 Orchestrator: Generating plan...', 'dir-text');
// Simulate plan generation
setTimeout(() => {
log('✅ Plan created: [Research] → [Write] → [Review]');
log('🔄 Assigning tasks to agents...');
state.agents.get('orchestrator').status = 'busy';
state.agents.get('researcher').status = 'busy';
state.agents.get('writer').status = 'busy';
saveState();
// Simulate research
setTimeout(() => {
log('🔍 Researcher: Gathering data on "' + goal + '"...');
setTimeout(() => {
log('✅ Research completed. Data cached.');
state.agents.get('researcher').status = 'idle';
// Simulate writing
setTimeout(() => {
log('✍️ Writer: Generating content...');
setTimeout(() => {
log('✅ Content generated.');
const artifact = {
id: 'art_' + Date.now(),
name: 'output.txt',
content: `Generated document on: ${goal}\n\nThis is a simulation of a multi-agent system running entirely in your browser. No backend. No server. Just JavaScript.\n\nGenerated by T20-MAS v0.1 at ${new Date().toISOString()}`,
type: 'text/plain'
};
state.artifacts.push(artifact);
const artifactPath = `/sys/artifacts/${artifact.id}.txt`;
createFile(artifactPath, artifact.content);
log(`📎 Artifact saved: ${artifactPath}`);
state.agents.get('writer').status = 'idle';
state.session.status = 'completed';
log('🎉 Task completed successfully!', 'success-text');
saveState();
}, 1500);
}, 1000);
}, 1200);
}, 1000);
}, 800);
} else if (args[0] === 'list') {
log('Active Tasks:');
if (state.session.goal) {
log(` ID: ${state.session.sessionId}`);
log(` Goal: ${state.session.goal}`);
log(` Status: ${state.session.status}`);
} else {
log(' No active tasks.');
}
} else {
log("Task commands: 'run <goal>', 'list'");
}
},
artifacts: (args) => {
if (args[0] === 'list') {
log('Generated Artifacts:', 'help-header');
if (state.artifacts.length === 0) {
log(' No artifacts generated yet.');
} else {
state.artifacts.forEach(art => {
log(` ${art.id}.txt (${art.type})`);
});
}
}
},
'session info': () => {
log('Session Info:', 'help-header');
log(` ID: ${state.session.sessionId}`);
log(` Started: ${state.session.startTime.toLocaleString()}`);
log(` Goal: ${state.session.goal || 'N/A'}`);
log(` Status: ${state.session.status}`);
}
};
// Command History Navigation
cliInput.addEventListener('keydown', (e) => {
if (e.key === 'ArrowUp') {
e.preventDefault();
if (state.historyIndex < state.commandHistory.length - 1) {
state.historyIndex++;
cliInput.value = state.commandHistory[state.commandHistory.length - 1 - state.historyIndex];
}
} else if (e.key === 'ArrowDown') {
e.preventDefault();
if (state.historyIndex > 0) {
state.historyIndex--;
cliInput.value = state.historyHistory.length > 0
? state.commandHistory[state.commandHistory.length - 1 - state.historyIndex]
: '';
} else if (state.historyIndex === 0) {
state.historyIndex = -1;
cliInput.value = '';
}
}
});
// Command Execution
cliInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
const command = cliInput.value.trim();
cliInput.value = '';
state.historyIndex = -1;
// Add to history
if (command) {
state.commandHistory.push(command);
if (state.commandHistory.length > 50) {
state.commandHistory.shift();
}
saveState();
}
// Display command
log(`t20mas@localhost:${state.currentPath}$ ${command}`);
if (!command) return;
const [cmd, ...args] = command.split(' ');
const fullCommand = commands[`${cmd} ${args[0]}`] ? `${cmd} ${args[0]}` : cmd;
const commandArgs = commands[`${cmd} ${args[0]}`] ? args.slice(1) : args;
if (commands[fullCommand]) {
commands[fullCommand](commandArgs);
} else if (cmd) {
log(`Command not found: ${cmd}. Type 'help' for available commands.`, 'error-text');
}
// Exit simulation
if (cmd === 'exit') {
setTimeout(() => {
log('🌐 T20-MAS shutdown complete. Reloading in 2s...');
setTimeout(() => {
window.location.reload();
}, 2000);
}, 500);
}
}
});
// Focus input on load
window.addEventListener('load', () => {
cliInput.focus();
initStorage();
log('');
log('████████╗ ██████╗ ██╗ ██╗██████╗ ██╗████████╗', 'success-text');
log('╚══██╔══╝██╔═══██╗██║ ██║██╔══██╗██║╚══██╔══╝', 'success-text');
log(' ██║ ██║ ██║██║ ██║██████╔╝██║ ██║', 'success-text');
log(' ██║ ██║ ██║██║ ██║██╔══██╗██║ ██║', 'success-text');
log(' ██║ ╚██████╔╝╚██████╔╝██║ ██║██║ ██║', 'success-text');
log(' ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝', 'success-text');
log('');
log('Welcome to T20-MAS CLI v0.1 (In-Browser Multi-Agent System)', 'dir-text');
log('Type "help" to get started. "agents list" to see agents.', 'command-history');
log('');
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-qwensite.hf.space/logo.svg" alt="qwensite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-qwensite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >QwenSite</a> - 🧬 <a href="https://enzostvs-qwensite.hf.space?remix=dokii/cli-sim-1" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>