| |
| |
| |
| |
|
|
|
|
| import { execSync } from 'child_process';
|
| import { promises as fs } from 'fs';
|
| import path from 'path';
|
|
|
|
|
|
|
|
|
|
|
| export enum CompilationMode {
|
| GBNF = 'gbnf',
|
| SKELETON = 'skeleton',
|
| DUALPASS = 'dual-pass',
|
| }
|
|
|
| export interface XMLCompilationRequest {
|
| mode: CompilationMode;
|
| naturalLanguage: string;
|
| llamaUrl?: string;
|
| ollamaUrl?: string;
|
| model?: string;
|
| temperature?: number;
|
| }
|
|
|
| export interface XMLCompilationResponse {
|
| mode: CompilationMode;
|
| input: string;
|
| xmlOutput: string;
|
| validationStatus: 'VALID' | 'INVALID' | 'PARTIAL';
|
| metadata: {
|
| timestamp: number;
|
| executionTimeMs: number;
|
| tokenCount?: number;
|
| };
|
| }
|
|
|
|
|
|
|
|
|
|
|
| function validateXML(xmlText: string): {
|
| valid: boolean;
|
| errors: string[];
|
| } {
|
| try {
|
|
|
| const parser = new DOMParser();
|
| const doc = parser.parseFromString(xmlText, 'text/xml');
|
|
|
| if (doc.documentElement.tagName === 'parsererror') {
|
| return {
|
| valid: false,
|
| errors: [doc.documentElement.textContent || 'XML parse error'],
|
| };
|
| }
|
|
|
|
|
| const requiredTags = ['system_prompt', 'identity', 'logic_gates', 'execution_flow'];
|
| const missingTags = requiredTags.filter((tag) => !doc.querySelector(tag));
|
|
|
| if (missingTags.length > 0) {
|
| return {
|
| valid: false,
|
| errors: [`Missing required tags: ${missingTags.join(', ')}`],
|
| };
|
| }
|
|
|
| return { valid: true, errors: [] };
|
| } catch (e: any) {
|
| return {
|
| valid: false,
|
| errors: [e.message],
|
| };
|
| }
|
| }
|
|
|
|
|
|
|
|
|
|
|
| export async function compileNaturalLanguageToXML(
|
| req: XMLCompilationRequest
|
| ): Promise<XMLCompilationResponse> {
|
| const startTime = Date.now();
|
|
|
| try {
|
| let xmlOutput: string;
|
|
|
| switch (req.mode) {
|
| case CompilationMode.GBNF:
|
| xmlOutput = await compileWithGBNF(req);
|
| break;
|
| case CompilationMode.SKELETON:
|
| xmlOutput = await compileWithSkeleton(req);
|
| break;
|
| case CompilationMode.DUALPASS:
|
| xmlOutput = await compileWithDualPass(req);
|
| break;
|
| default:
|
| throw new Error(`Unknown mode: ${req.mode}`);
|
| }
|
|
|
| const validation = validateXML(xmlOutput);
|
|
|
| return {
|
| mode: req.mode,
|
| input: req.naturalLanguage,
|
| xmlOutput,
|
| validationStatus: validation.valid ? 'VALID' : 'INVALID',
|
| metadata: {
|
| timestamp: Date.now(),
|
| executionTimeMs: Date.now() - startTime,
|
| },
|
| };
|
| } catch (error: any) {
|
| throw new Error(`XML compilation failed (${req.mode}): ${error.message}`);
|
| }
|
| }
|
|
|
|
|
|
|
|
|
|
|
| async function compileWithGBNF(req: XMLCompilationRequest): Promise<string> {
|
|
|
| const llamaUrl = req.llamaUrl || process.env.LLAMA_URL || 'http://localhost:8080';
|
|
|
| try {
|
|
|
| const grammarPath = path.join(
|
| __dirname,
|
| '../artifacts/bridges/xml-compiler-grammars/sovereign_prompt.gbnf'
|
| );
|
| const grammarText = await fs.readFile(grammarPath, 'utf-8');
|
|
|
|
|
| const payload = {
|
| prompt: `Convert this natural language instruction into a sovereign XML system prompt:\n\n${req.naturalLanguage}`,
|
| grammar: grammarText,
|
| temperature: req.temperature || 0.3,
|
| n_predict: 2048,
|
| };
|
|
|
| const response = await fetch(`${llamaUrl}/completion`, {
|
| method: 'POST',
|
| headers: { 'Content-Type': 'application/json' },
|
| body: JSON.stringify(payload),
|
| });
|
|
|
| if (!response.ok) {
|
| throw new Error(`llama.cpp responded with ${response.status}`);
|
| }
|
|
|
| const data = await response.json();
|
| return data.content || '';
|
| } catch (e: any) {
|
| throw new Error(`GBNF compilation failed: ${e.message}`);
|
| }
|
| }
|
|
|
|
|
|
|
|
|
|
|
| async function compileWithSkeleton(req: XMLCompilationRequest): Promise<string> {
|
| const ollamaUrl = req.ollamaUrl || process.env.OLLAMA_URL || 'http://localhost:11434';
|
| const model = req.model || process.env.XML_MODEL || 'nemotron';
|
|
|
| try {
|
|
|
| const skeletonPath = path.join(
|
| __dirname,
|
| '../artifacts/bridges/xml-compiler-skeletons/sovereign_prompt.xml'
|
| );
|
| const skeleton = await fs.readFile(skeletonPath, 'utf-8');
|
|
|
|
|
| const placeholders = skeleton.match(/\{\{(\w+)\}\}/g) || [];
|
| const placeholderKeys = placeholders.map((p) => p.replace(/\{|\}/g, ''));
|
|
|
|
|
| const systemPrompt = `You are a Skeleton Filler Agent.
|
| You will receive an XML skeleton with {{PLACEHOLDER}} tokens.
|
| Return ONLY a JSON object mapping each placeholder key to its value.
|
| No XML. No explanation. Pure JSON.`;
|
|
|
| const userPrompt = `Skeleton placeholders to fill: ${placeholderKeys.join(', ')}
|
|
|
| Natural language instruction:
|
| ${req.naturalLanguage}`;
|
|
|
| const payload = {
|
| model,
|
| system: systemPrompt,
|
| prompt: userPrompt,
|
| stream: false,
|
| options: {
|
| temperature: req.temperature || 0.3,
|
| top_p: 0.9,
|
| },
|
| };
|
|
|
| const response = await fetch(`${ollamaUrl}/api/generate`, {
|
| method: 'POST',
|
| headers: { 'Content-Type': 'application/json' },
|
| body: JSON.stringify(payload),
|
| });
|
|
|
| if (!response.ok) {
|
| throw new Error(`Ollama responded with ${response.status}`);
|
| }
|
|
|
| const data = await response.json();
|
| const llmResponse = data.response || '{}';
|
|
|
|
|
| let fillMapping: Record<string, string> = {};
|
| try {
|
| fillMapping = JSON.parse(llmResponse);
|
| } catch {
|
|
|
| const jsonMatch = llmResponse.match(/\{[\s\S]*\}/);
|
| if (jsonMatch) {
|
| fillMapping = JSON.parse(jsonMatch[0]);
|
| }
|
| }
|
|
|
|
|
| let filledXML = skeleton;
|
| for (const [key, value] of Object.entries(fillMapping)) {
|
| filledXML = filledXML.replace(new RegExp(`\\{\\{${key}\\}\\}`, 'g'), String(value));
|
| }
|
|
|
|
|
| filledXML = filledXML.replace(/\{\{(\w+)\}\}/g, '');
|
|
|
| return filledXML;
|
| } catch (e: any) {
|
| throw new Error(`Skeleton compilation failed: ${e.message}`);
|
| }
|
| }
|
|
|
|
|
|
|
|
|
|
|
| async function compileWithDualPass(req: XMLCompilationRequest): Promise<string> {
|
| const ollamaUrl = req.ollamaUrl || process.env.OLLAMA_URL || 'http://localhost:11434';
|
| const model = req.model || process.env.XML_MODEL || 'nemotron';
|
|
|
| try {
|
| const systemPrompt = `You are a Compiler Agent. Convert natural language into sovereign XML prompts.
|
|
|
| Follow this exact output sequence:
|
| 1. <thought_process>: outline the identity, logic gates, and execution flow needed.
|
| 2. <xml_output>: convert your thought process into the finalized XML.
|
| Do not output any text after </xml_output>.
|
|
|
| The XML must match this structure:
|
| <system_prompt>
|
| <identity>...</identity>
|
| <logic_gates><gate><name/><condition/><action/></gate></logic_gates>
|
| <execution_flow><step><order/><instruction/></step></execution_flow>
|
| </system_prompt>`;
|
|
|
| const payload = {
|
| model,
|
| system: systemPrompt,
|
| prompt: req.naturalLanguage,
|
| stream: false,
|
| options: {
|
| temperature: req.temperature || 0.3,
|
| top_p: 0.9,
|
| },
|
| };
|
|
|
| const response = await fetch(`${ollamaUrl}/api/generate`, {
|
| method: 'POST',
|
| headers: { 'Content-Type': 'application/json' },
|
| body: JSON.stringify(payload),
|
| });
|
|
|
| if (!response.ok) {
|
| throw new Error(`Ollama responded with ${response.status}`);
|
| }
|
|
|
| const data = await response.json();
|
| const fullResponse = data.response || '';
|
|
|
|
|
| const xmlMatch = fullResponse.match(/<xml_output>([\s\S]*?)<\/xml_output>/);
|
| const xmlOutput = xmlMatch ? xmlMatch[1].trim() : fullResponse;
|
|
|
| return xmlOutput;
|
| } catch (e: any) {
|
| throw new Error(`Dual-pass compilation failed: ${e.message}`);
|
| }
|
| }
|
|
|
|
|
|
|
|
|
|
|
| export interface ModelControlRequest {
|
| xmlPrompt: string;
|
| model: string;
|
| userQuery: string;
|
| temperature?: number;
|
| maxTokens?: number;
|
| }
|
|
|
| export interface ModelControlResponse {
|
| model: string;
|
| response: string;
|
| promptUsed: string;
|
| executionTimeMs: number;
|
| }
|
|
|
| export async function controlModelViaXML(
|
| req: ModelControlRequest
|
| ): Promise<ModelControlResponse> {
|
| const startTime = Date.now();
|
| const ollamaUrl = process.env.OLLAMA_URL || 'http://localhost:11434';
|
|
|
| try {
|
|
|
| const validation = validateXML(req.xmlPrompt);
|
| if (!validation.valid) {
|
| throw new Error(`Invalid XML prompt: ${validation.errors.join('; ')}`);
|
| }
|
|
|
|
|
| const systemPrompt = extractSystemPromptFromXML(req.xmlPrompt);
|
|
|
|
|
| const payload = {
|
| model: req.model,
|
| system: systemPrompt,
|
| prompt: req.userQuery,
|
| stream: false,
|
| options: {
|
| temperature: req.temperature || 0.7,
|
| top_p: 0.9,
|
| num_predict: req.maxTokens || 512,
|
| },
|
| };
|
|
|
| const response = await fetch(`${ollamaUrl}/api/generate`, {
|
| method: 'POST',
|
| headers: { 'Content-Type': 'application/json' },
|
| body: JSON.stringify(payload),
|
| });
|
|
|
| if (!response.ok) {
|
| throw new Error(`Ollama responded with ${response.status}`);
|
| }
|
|
|
| const data = await response.json();
|
|
|
| return {
|
| model: req.model,
|
| response: data.response || '',
|
| promptUsed: systemPrompt,
|
| executionTimeMs: Date.now() - startTime,
|
| };
|
| } catch (e: any) {
|
| throw new Error(`Model control failed: ${e.message}`);
|
| }
|
| }
|
|
|
|
|
|
|
|
|
|
|
| function extractSystemPromptFromXML(xmlText: string): string {
|
| try {
|
| const parser = new DOMParser();
|
| const doc = parser.parseFromString(xmlText, 'text/xml');
|
|
|
| const identity = doc.querySelector('identity')?.textContent || '';
|
| const gates = Array.from(doc.querySelectorAll('logic_gates gate'))
|
| .map((gate) => `${gate.querySelector('name')?.textContent}: ${gate.querySelector('condition')?.textContent}`)
|
| .join('\n');
|
|
|
| const flow = Array.from(doc.querySelectorAll('execution_flow step'))
|
| .map((step) => `${step.querySelector('order')?.textContent}. ${step.querySelector('instruction')?.textContent}`)
|
| .join('\n');
|
|
|
| return `${identity}\n\nLogic Gates:\n${gates}\n\nExecution Flow:\n${flow}`;
|
| } catch {
|
|
|
| return xmlText;
|
| }
|
| }
|
|
|
| export default {
|
| compileNaturalLanguageToXML,
|
| controlModelViaXML,
|
| CompilationMode,
|
| };
|
|
|