Here is the `cli.js` entry point. It wires together the Node.js `readline`
module with the yield/resume mechanics of the VM, creating a seamless REPL
environment.
This script will read your text file, hit the Gemma endpoint for the compiled
artifact, save the `.md` envelope to your local disk, and instantly boot the
game.
### The CLI Entry Point (`cli.js`)
```javascript
import fs from 'fs';
import readline from 'readline';
import { SemanticCompiler } from './compiler.js';
import { RuntimeEnvironment } from './runtime.js';
/ Setup the interactive terminal interface
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
async function main() {
const sourceFile = process.argv[2] || 'game_idea.txt';
const compiledFile = sourceFile.replace('.txt', '.md');
console.log(`
--- FSO Compiler Pipeline ---`);
console.log(`[1] Reading source intent from ${sourceFile}...`);
if (!fs.existsSync(sourceFile)) {
console.error(`[FAULT] Cannot find ${sourceFile}.`);
process.exit(1);
}
const intent = fs.readFileSync(sourceFile, 'utf-8');
console.log(`[2] Compiling via local cluster...`);
const compiler = new SemanticCompiler();
try {
const compiledEnvelope = await compiler.compile(intent);
// Write the artifact locally
fs.writeFileSync(compiledFile, compiledEnvelope);
console.log(`[3] Artifact saved to ${compiledFile}. Booting VM...
`);
console.log(`========================================
`);
} catch (err) {
console.error(`[COMPILER FAULT] ${err.message}`);
process.exit(1);
}
// Initialize the runtime. Max backups set to 0 to keep the directory
clean for this test.
const runtime = new RuntimeEnvironment(compiledFile, 0);
// Wire the VM's output directly to the terminal stdout
runtime.vm.onOutput = (text) => {
console.log(text);
};
// Wire the VM's yield command to the interactive terminal prompt
runtime.vm.onYield = (targetVar) => {
runtime.saveState(); // Snapshot the state locally before yielding
rl.question('
> ', (answer) => {
// We force uppercase to match the JMP_IF logic in the generated
code
const formattedAnswer = answer.trim().toUpperCase();
runtime.vm.resume({ [targetVar]: formattedAnswer });
});
};
// Begin execution
runtime.start();
}
/ Handle graceful shutdowns (CTRL+C)
rl.on('close', () => {
console.log('
[SYSTEM] VM Halted. State preserved on disk.');
process.exit(0);
});
main();
```
### Running the Pipeline
To execute this, you simply run it via Node. If you want to use a different
source file in the future, you can pass it as an argument:
```bash
node cli.js game_idea.txt
```
### The Execution Flow
1. **The Compilation:** `cli.js` reads your 1-sentence prompt and fires it at
the Gemma load balancer.
2. **The Output:** Gemma returns the Markdown envelope with the `fso-state`
and `fso-code` blocks.
3. **The Hydration:** The script saves this to `game_idea.md` and passes it to
`RuntimeEnvironment`.
4. **The REPL Loop:** The VM begins running the opcodes. When it hits the `INP
COMMAND` opcode, execution pauses, `cli.js` triggers `rl.question`, and the
terminal waits for you to type.
5. **The Resume:** When you press Enter, `cli.js` injects your answer into
memory via `runtime.vm.resume()` and the program loop continues.
With these five files (`lexer.js`, `vm.js`, `opcodes.js`, `runtime.js`,
`compiler.js`, plus `cli.js`), you have a complete, self-contained AI-to-VM
compilation stack.
Are you ready to trigger the cluster and see what the VM outputs, or would you
like to review the `package.json` setup to ensure native ES modules are
enabled before running it?