dominus-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/transport/protocol.ts","../src/transport/ws-server.ts","../src/config/config.ts","../src/memory/store.ts","../src/mcp/server.ts","../src/mcp/index.ts"],"names":["fs","result","path"],"mappings":"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","file":"mcp.js","sourcesContent":["import { nanoid } from 'nanoid';\r\n\r\nexport interface WsMessage<T = unknown> {\r\n id: string;\r\n type: string;\r\n payload: T;\r\n ts: number;\r\n}\r\n\r\nexport const StudioMsg = {\r\n CONNECTED: 'studio:connected',\r\n DISCONNECTED: 'studio:disconnected',\r\n EXPLORER: 'studio:explorer',\r\n OUTPUT: 'studio:output',\r\n ERROR: 'studio:error',\r\n SELECTION: 'studio:selection',\r\n SCRIPT_CONTENT: 'studio:script:content',\r\n SCRIPT_CHANGED: 'studio:script:changed',\r\n RESPONSE: 'studio:response',\r\n REFLECTION: 'studio:reflection',\r\n TEST_RESULTS: 'studio:test:results',\r\n} as const;\r\n\r\nexport const CliMsg = {\r\n GET_EXPLORER: 'cli:get:explorer',\r\n GET_SCRIPT: 'cli:get:script',\r\n SET_SCRIPT: 'cli:set:script',\r\n RUN_CODE: 'cli:run',\r\n GET_PROPERTIES: 'cli:get:properties',\r\n SET_PROPERTIES: 'cli:set:properties',\r\n INSERT_INSTANCE: 'cli:insert',\r\n DELETE_INSTANCE: 'cli:delete',\r\n GET_SELECTION: 'cli:get:selection',\r\n SELECT: 'cli:select',\r\n SEARCH_SCRIPTS: 'cli:search:scripts',\r\n GET_OUTPUT: 'cli:get:output',\r\n RUN_TESTS: 'cli:run:tests',\r\n EXECUTE_RUN_TEST: 'cli:test:run',\r\n EXECUTE_PLAY_TEST: 'cli:test:play',\r\n END_TEST: 'cli:test:end',\r\n BUILD_UI: 'cli:build:ui',\r\n GET_REFLECTION: 'cli:get:reflection',\r\n UPLOAD_ASSET: 'cli:upload:asset',\r\n} as const;\r\n\r\nexport type StudioMsgType = (typeof StudioMsg)[keyof typeof StudioMsg];\r\nexport type CliMsgType = (typeof CliMsg)[keyof typeof CliMsg];\r\n\r\nexport interface ExplorerNode {\r\n name: string;\r\n className: string;\r\n path: string;\r\n children?: ExplorerNode[];\r\n}\r\n\r\nexport interface StudioConnectedPayload {\r\n studioVersion: string;\r\n placeId?: number;\r\n placeName?: string;\r\n engineVersion?: string;\r\n}\r\n\r\nexport interface ScriptContentPayload {\r\n path: string;\r\n className: 'Script' | 'LocalScript' | 'ModuleScript';\r\n source: string;\r\n lineCount: number;\r\n}\r\n\r\nexport interface ScriptChangedPayload {\r\n path: string;\r\n source: string;\r\n}\r\n\r\nexport interface OutputPayload {\r\n message: string;\r\n level: 'info' | 'warn' | 'error';\r\n timestamp: number;\r\n source?: string;\r\n}\r\n\r\nexport interface SelectionPayload {\r\n paths: string[];\r\n classNames: string[];\r\n}\r\n\r\nexport interface PropertyEntry {\r\n name: string;\r\n value: string;\r\n type: string;\r\n category?: string;\r\n}\r\n\r\nexport interface TestResultPayload {\r\n name: string;\r\n passed: boolean;\r\n duration: number;\r\n error?: string;\r\n}\r\n\r\nexport interface StudioTestPayload {\r\n args?: unknown;\r\n}\r\n\r\nexport interface StudioTestResultPayload {\r\n success: boolean;\r\n result?: unknown;\r\n error?: string;\r\n duration?: number;\r\n}\r\n\r\nexport interface ReflectionPayload {\r\n className: string;\r\n properties: { name: string; type: string; category: string }[];\r\n methods: { name: string; parameters: string[] }[];\r\n events: { name: string; parameters: string[] }[];\r\n}\r\n\r\nexport interface RunCodePayload {\r\n code: string;\r\n}\r\n\r\nexport interface RunCodeResponsePayload {\r\n output: string;\r\n error?: string;\r\n duration: number;\r\n}\r\n\r\nexport interface SearchScriptsPayload {\r\n query: string;\r\n maxResults?: number;\r\n}\r\n\r\nexport interface SearchResultPayload {\r\n results: {\r\n path: string;\r\n className: string;\r\n matches: { line: number; text: string }[];\r\n }[];\r\n}\r\n\r\nexport interface InsertInstancePayload {\r\n className: string;\r\n parentPath: string;\r\n name: string;\r\n properties?: Record<string, unknown>;\r\n}\r\n\r\nexport interface SetPropertiesPayload {\r\n path: string;\r\n properties: Record<string, unknown>;\r\n}\r\n\r\nexport function createMessage<T>(type: string, payload: T): WsMessage<T> {\r\n return { id: nanoid(), type, payload, ts: Date.now() };\r\n}\r\n\r\nexport function createRequest<T>(type: string, payload: T): WsMessage<T> {\r\n return createMessage(type, payload);\r\n}\r\n\r\nexport function parseMessage(raw: string): WsMessage {\r\n try {\r\n return JSON.parse(raw) as WsMessage;\r\n } catch {\r\n throw new Error(`Failed to parse WebSocket message: ${raw.slice(0, 100)}`);\r\n }\r\n}\r\n\r\nexport function serializeMessage(msg: WsMessage): string {\r\n return JSON.stringify(msg);\r\n}\r\n","import { WebSocketServer, WebSocket } from 'ws';\nimport { EventEmitter } from 'node:events';\nimport {\n parseMessage,\n serializeMessage,\n createMessage,\n StudioMsg,\n type WsMessage,\n type StudioConnectedPayload,\n} from './protocol.js';\n\nexport interface StudioConnection {\n ws: WebSocket;\n studioVersion?: string;\n placeId?: number;\n placeName?: string;\n connectedAt: number;\n}\n\nexport interface StudioBridge extends EventEmitter {\n sendRequest<T = unknown>(type: string, payload: unknown, timeoutMs?: number): Promise<WsMessage<T>>;\n sendNotification(type: string, payload: unknown): void;\n isConnected(): boolean;\n getConnectionInfo(): StudioConnection | null;\n getPort(): number;\n stop(): Promise<void>;\n}\n\nexport class DominusServer extends EventEmitter implements StudioBridge {\n private wss: WebSocketServer | null = null;\n private studioClient: StudioConnection | null = null;\n private controllers = new Set<WebSocket>();\n private pendingRequests = new Map<\n string,\n { resolve: (msg: WsMessage) => void; reject: (err: Error) => void; timer: ReturnType<typeof setTimeout> }\n >();\n private relayRequests = new Map<string, WebSocket>();\n private port: number;\n\n constructor(port = 18088) {\n super();\n this.port = port;\n }\n\n start(maxRetries = 0): Promise<void> {\n return new Promise((resolve, reject) => {\n const tryPort = (port: number, attempt: number) => {\n const wss = new WebSocketServer({ port });\n\n wss.on('listening', () => {\n this.wss = wss;\n this.port = port;\n this.wss.on('connection', (ws) => this.handleConnection(ws));\n this.emit('server:started', { port });\n resolve();\n });\n\n wss.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE' && attempt < maxRetries) {\n wss.close();\n tryPort(port + 1, attempt + 1);\n } else {\n this.emit('server:error', err);\n reject(err);\n }\n });\n };\n\n tryPort(this.port, 0);\n });\n }\n\n private handleConnection(ws: WebSocket): void {\n let identified = false;\n\n ws.on('message', (raw) => {\n try {\n const msg = parseMessage(raw.toString());\n\n if (!identified) {\n if (msg.type === StudioMsg.CONNECTED) {\n identified = true;\n this.setStudioClient(ws, msg);\n return;\n }\n if (msg.type === 'controller:connect') {\n identified = true;\n this.addController(ws);\n ws.send(serializeMessage(createMessage('controller:welcome', {\n studioConnected: this.isConnected(),\n port: this.port,\n })));\n return;\n }\n }\n\n if (this.controllers.has(ws)) {\n this.handleControllerMessage(ws, msg);\n } else {\n this.handleStudioMessage(msg);\n }\n } catch (err) {\n this.emit('server:error', err);\n }\n });\n\n ws.on('close', () => {\n if (this.controllers.has(ws)) {\n this.controllers.delete(ws);\n for (const [id, controllerWs] of this.relayRequests) {\n if (controllerWs === ws) this.relayRequests.delete(id);\n }\n } else if (this.studioClient?.ws === ws) {\n this.studioClient = null;\n this.emit('studio:disconnected');\n this.broadcastToControllers('studio:disconnected', {});\n for (const [id, pending] of this.pendingRequests) {\n clearTimeout(pending.timer);\n pending.reject(new Error('Studio disconnected'));\n this.pendingRequests.delete(id);\n }\n }\n });\n\n ws.on('error', (err) => {\n this.emit('server:error', err);\n });\n }\n\n private setStudioClient(ws: WebSocket, msg: WsMessage): void {\n if (this.studioClient) {\n this.studioClient.ws.close();\n }\n\n const payload = msg.payload as StudioConnectedPayload;\n this.studioClient = {\n ws,\n connectedAt: Date.now(),\n studioVersion: payload.studioVersion,\n placeId: payload.placeId,\n placeName: payload.placeName,\n };\n\n this.emit('studio:connected', payload);\n this.broadcastToControllers('studio:connected', payload);\n }\n\n private addController(ws: WebSocket): void {\n this.controllers.add(ws);\n this.emit('controller:connected');\n }\n\n private broadcastToControllers(type: string, payload: unknown): void {\n const msg = serializeMessage(createMessage(type, payload));\n for (const ws of this.controllers) {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(msg);\n }\n }\n }\n\n private handleControllerMessage(controllerWs: WebSocket, msg: WsMessage): void {\n if (!this.studioClient || this.studioClient.ws.readyState !== WebSocket.OPEN) {\n controllerWs.send(serializeMessage({\n id: msg.id,\n type: StudioMsg.RESPONSE,\n payload: { error: 'Studio not connected' },\n ts: Date.now(),\n }));\n return;\n }\n\n this.relayRequests.set(msg.id, controllerWs);\n this.studioClient.ws.send(serializeMessage(msg));\n }\n\n private handleStudioMessage(msg: WsMessage): void {\n if (msg.type === StudioMsg.CONNECTED) {\n const payload = msg.payload as StudioConnectedPayload;\n if (this.studioClient) {\n this.studioClient.studioVersion = payload.studioVersion;\n this.studioClient.placeId = payload.placeId;\n this.studioClient.placeName = payload.placeName;\n }\n this.emit('studio:connected', payload);\n this.broadcastToControllers('studio:connected', payload);\n return;\n }\n\n if (msg.type === StudioMsg.RESPONSE) {\n // Check if this is a relayed request from a controller\n const controllerWs = this.relayRequests.get(msg.id);\n if (controllerWs && controllerWs.readyState === WebSocket.OPEN) {\n controllerWs.send(serializeMessage(msg));\n this.relayRequests.delete(msg.id);\n return;\n }\n\n // Otherwise handle locally (MCP or direct)\n const pending = this.pendingRequests.get(msg.id);\n if (pending) {\n clearTimeout(pending.timer);\n pending.resolve(msg);\n this.pendingRequests.delete(msg.id);\n }\n return;\n }\n\n // Forward events to controllers and local listeners\n this.emit(msg.type, msg.payload);\n this.emit('message', msg);\n this.broadcastToControllers(msg.type, msg.payload);\n }\n\n sendRequest<T = unknown>(type: string, payload: unknown, timeoutMs = 10000): Promise<WsMessage<T>> {\n return new Promise((resolve, reject) => {\n if (!this.studioClient || this.studioClient.ws.readyState !== WebSocket.OPEN) {\n reject(new Error('No Studio connection'));\n return;\n }\n\n const msg = createMessage(type, payload);\n\n const timer = setTimeout(() => {\n this.pendingRequests.delete(msg.id);\n reject(new Error(`Request timed out: ${type}`));\n }, timeoutMs);\n\n this.pendingRequests.set(msg.id, {\n resolve: resolve as (msg: WsMessage) => void,\n reject,\n timer,\n });\n\n this.studioClient.ws.send(serializeMessage(msg));\n });\n }\n\n sendNotification(type: string, payload: unknown): void {\n if (!this.studioClient || this.studioClient.ws.readyState !== WebSocket.OPEN) {\n return;\n }\n const msg = createMessage(type, payload);\n this.studioClient.ws.send(serializeMessage(msg));\n }\n\n isConnected(): boolean {\n return this.studioClient !== null && this.studioClient.ws.readyState === WebSocket.OPEN;\n }\n\n getConnectionInfo(): StudioConnection | null {\n return this.studioClient;\n }\n\n getPort(): number {\n return this.port;\n }\n\n stop(): Promise<void> {\n return new Promise((resolve) => {\n if (this.studioClient) {\n this.studioClient.ws.close();\n this.studioClient = null;\n }\n for (const ws of this.controllers) {\n ws.close();\n }\n this.controllers.clear();\n for (const [, pending] of this.pendingRequests) {\n clearTimeout(pending.timer);\n pending.reject(new Error('Server shutting down'));\n }\n this.pendingRequests.clear();\n this.relayRequests.clear();\n\n if (this.wss) {\n this.wss.close(() => resolve());\n } else {\n resolve();\n }\n });\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport type { ConfigAccess } from '../tools/types.js';\n\nconst DOMINUS_DIR = path.join(os.homedir(), '.dominus');\nconst CONFIG_PATH = path.join(DOMINUS_DIR, 'config.json');\nconst DB_PATH = path.join(DOMINUS_DIR, 'dominus.db');\nconst RULES_PATH = path.join(DOMINUS_DIR, 'rules.json');\n\nexport type AIProviderType =\n | 'openai'\n | 'anthropic'\n | 'gemini'\n | 'xai'\n | 'openrouter'\n | 'custom';\n\nexport interface ProviderConfig {\n name: string;\n baseUrl: string;\n envVar: string;\n defaultModel: string;\n}\n\nexport const PROVIDERS: Record<AIProviderType, ProviderConfig> = {\n openai: {\n name: 'OpenAI',\n baseUrl: 'https://api.openai.com/v1',\n envVar: 'OPENAI_API_KEY',\n defaultModel: 'gpt-5.3-codex',\n },\n anthropic: {\n name: 'Anthropic',\n baseUrl: 'https://api.anthropic.com/v1/',\n envVar: 'ANTHROPIC_API_KEY',\n defaultModel: 'claude-sonnet-4-6',\n },\n gemini: {\n name: 'Google Gemini',\n baseUrl: 'https://generativelanguage.googleapis.com/v1beta/openai',\n envVar: 'GEMINI_API_KEY',\n defaultModel: 'gemini-3.1-pro',\n },\n xai: {\n name: 'xAI (Grok)',\n baseUrl: 'https://api.x.ai/v1',\n envVar: 'XAI_API_KEY',\n defaultModel: 'grok-4.2',\n },\n openrouter: {\n name: 'OpenRouter',\n baseUrl: 'https://openrouter.ai/api/v1',\n envVar: 'OPENROUTER_API_KEY',\n defaultModel: 'anthropic/claude-sonnet-4-6',\n },\n custom: {\n name: 'Custom',\n baseUrl: '',\n envVar: '',\n defaultModel: '',\n },\n};\n\nexport interface DominusConfig {\n provider: AIProviderType;\n apiKey?: string;\n apiBaseUrl: string;\n model: string;\n port: number;\n maxToolIterations: number;\n maxVerifyRetries: number;\n tokenBudget: number;\n autoIndex: boolean;\n autoLearn: boolean;\n userName: string;\n openCloudApiKey?: string;\n}\n\nconst DEFAULTS: DominusConfig = {\n provider: 'openai',\n apiBaseUrl: '',\n model: '',\n port: 18088,\n maxToolIterations: 25,\n maxVerifyRetries: 3,\n tokenBudget: 128000,\n autoIndex: true,\n autoLearn: true,\n userName: 'Developer',\n};\n\n/**\n * Auto-detect provider from environment variables.\n * Returns the first provider whose env var is set, or null.\n */\nexport function detectProviderFromEnv(): { provider: AIProviderType; apiKey: string } | null {\n const priority: AIProviderType[] = ['openai', 'anthropic', 'gemini', 'xai', 'openrouter'];\n for (const p of priority) {\n const key = process.env[PROVIDERS[p].envVar];\n if (key) return { provider: p, apiKey: key };\n }\n return null;\n}\n\n/**\n * Resolve the effective base URL and model for a provider config.\n */\nexport function resolveProviderSettings(config: DominusConfig): {\n baseUrl: string;\n model: string;\n} {\n const providerInfo = PROVIDERS[config.provider];\n return {\n baseUrl: config.apiBaseUrl || providerInfo?.baseUrl || PROVIDERS.openrouter.baseUrl,\n model: config.model || providerInfo?.defaultModel || 'gpt-4o',\n };\n}\n\nexport interface DominusRules {\n do: string[];\n dont: string[];\n conventions: string[];\n context: string;\n}\n\nconst DEFAULT_RULES: DominusRules = {\n do: [],\n dont: [],\n conventions: [],\n context: '',\n};\n\nfunction ensureDir(): void {\n if (!fs.existsSync(DOMINUS_DIR)) {\n fs.mkdirSync(DOMINUS_DIR, { recursive: true });\n }\n}\n\nfunction readJson<T>(filePath: string, defaults: T): T {\n try {\n if (fs.existsSync(filePath)) {\n const raw = fs.readFileSync(filePath, 'utf-8');\n return { ...defaults, ...JSON.parse(raw) };\n }\n } catch {\n // Corrupted file; reset to defaults\n }\n return { ...defaults };\n}\n\nfunction writeJson(filePath: string, data: unknown): void {\n ensureDir();\n fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');\n}\n\nexport function loadConfig(): DominusConfig {\n ensureDir();\n return readJson(CONFIG_PATH, DEFAULTS);\n}\n\nexport function saveConfig(config: DominusConfig): void {\n writeJson(CONFIG_PATH, config);\n}\n\nexport function getConfigValue<K extends keyof DominusConfig>(key: K): DominusConfig[K] {\n const config = loadConfig();\n return config[key];\n}\n\nexport function setConfigValue<K extends keyof DominusConfig>(\n key: K,\n value: DominusConfig[K],\n): void {\n const config = loadConfig();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (config as any)[key] = value;\n saveConfig(config);\n}\n\nexport function loadRules(): DominusRules {\n ensureDir();\n return readJson(RULES_PATH, DEFAULT_RULES);\n}\n\nexport function saveRules(rules: DominusRules): void {\n writeJson(RULES_PATH, rules);\n}\n\nexport function getDominusDir(): string {\n ensureDir();\n return DOMINUS_DIR;\n}\n\nexport function getDbPath(): string {\n ensureDir();\n return DB_PATH;\n}\n\nexport function createConfigAccess(): ConfigAccess {\n return {\n get<T>(key: string): T | undefined {\n const config = loadConfig() as unknown as Record<string, unknown>;\n return config[key] as T | undefined;\n },\n set(key: string, value: unknown): void {\n const config = loadConfig() as unknown as Record<string, unknown>;\n config[key] = value;\n saveConfig(config as unknown as DominusConfig);\n },\n getAll(): Record<string, unknown> {\n return loadConfig() as unknown as Record<string, unknown>;\n },\n };\n}\n","import fs from 'node:fs';\r\nimport initSqlJs from 'sql.js';\r\nimport type { Database, QueryExecResult } from 'sql.js';\r\nimport { getDbPath } from '../config/config.js';\r\nimport type { Fact, FactCategory, SessionSummary, ChatMessage, ScriptEntry } from './types.js';\r\n\r\nlet db: Database | null = null;\r\nlet dbPath: string;\r\n\r\nconst SCHEMA = `\r\nCREATE TABLE IF NOT EXISTS facts (\r\n id INTEGER PRIMARY KEY AUTOINCREMENT,\r\n project_id TEXT NOT NULL,\r\n content TEXT NOT NULL,\r\n category TEXT NOT NULL,\r\n source TEXT,\r\n relevance REAL DEFAULT 1.0,\r\n created_at INTEGER NOT NULL,\r\n accessed_at INTEGER NOT NULL\r\n);\r\n\r\nCREATE TABLE IF NOT EXISTS summaries (\r\n id INTEGER PRIMARY KEY AUTOINCREMENT,\r\n project_id TEXT NOT NULL,\r\n session_id TEXT NOT NULL,\r\n summary TEXT NOT NULL,\r\n created_at INTEGER NOT NULL\r\n);\r\n\r\nCREATE TABLE IF NOT EXISTS messages (\r\n id INTEGER PRIMARY KEY AUTOINCREMENT,\r\n session_id TEXT NOT NULL,\r\n role TEXT NOT NULL,\r\n content TEXT NOT NULL,\r\n tool_name TEXT,\r\n created_at INTEGER NOT NULL\r\n);\r\n\r\nCREATE TABLE IF NOT EXISTS script_index (\r\n id INTEGER PRIMARY KEY AUTOINCREMENT,\r\n project_id TEXT NOT NULL,\r\n path TEXT NOT NULL,\r\n class_name TEXT NOT NULL,\r\n summary TEXT,\r\n line_count INTEGER,\r\n last_hash TEXT,\r\n updated_at INTEGER NOT NULL\r\n);\r\n\r\nCREATE INDEX IF NOT EXISTS idx_facts_project ON facts(project_id);\r\nCREATE INDEX IF NOT EXISTS idx_facts_category ON facts(project_id, category);\r\nCREATE INDEX IF NOT EXISTS idx_scripts_project ON script_index(project_id);\r\nCREATE INDEX IF NOT EXISTS idx_messages_session ON messages(session_id);\r\nCREATE INDEX IF NOT EXISTS idx_summaries_project ON summaries(project_id);\r\n`;\r\n\r\nfunction persist(): void {\r\n if (!db) return;\r\n const data = db.export();\r\n fs.writeFileSync(dbPath, Buffer.from(data));\r\n}\r\n\r\nexport async function initMemoryStore(): Promise<void> {\r\n if (db) return;\r\n dbPath = getDbPath();\r\n const SQL = await initSqlJs();\r\n\r\n if (fs.existsSync(dbPath)) {\r\n const buffer = fs.readFileSync(dbPath);\r\n db = new SQL.Database(buffer);\r\n } else {\r\n db = new SQL.Database();\r\n }\r\n\r\n db.run(SCHEMA);\r\n persist();\r\n}\r\n\r\nexport function getDb(): Database {\r\n if (!db) throw new Error('Memory store not initialized. Call initMemoryStore() first.');\r\n return db;\r\n}\r\n\r\nexport function closeMemoryStore(): void {\r\n if (db) {\r\n persist();\r\n db.close();\r\n db = null;\r\n }\r\n}\r\n\r\n// --- Facts ---\r\n\r\nexport function storeFact(fact: Omit<Fact, 'id'>): number {\r\n const d = getDb();\r\n d.run(\r\n `INSERT INTO facts (project_id, content, category, source, relevance, created_at, accessed_at)\r\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\r\n [\r\n fact.projectId,\r\n fact.content,\r\n fact.category,\r\n fact.source ?? null,\r\n fact.relevance,\r\n fact.createdAt,\r\n fact.accessedAt,\r\n ],\r\n );\r\n persist();\r\n const stmt = d.prepare('SELECT last_insert_rowid()');\r\n stmt.step();\r\n const row = stmt.get();\r\n stmt.free();\r\n return (row?.[0] as number) ?? 0;\r\n}\r\n\r\nexport function recallFacts(projectId: string, query: string, limit = 10): Fact[] {\r\n const d = getDb();\r\n const keywords = query\r\n .toLowerCase()\r\n .split(/\\s+/)\r\n .filter((w) => w.length > 2);\r\n\r\n if (keywords.length === 0) {\r\n const result = d.exec(\r\n `SELECT * FROM facts WHERE project_id = ? ORDER BY relevance DESC, accessed_at DESC LIMIT ?`,\r\n [projectId, limit],\r\n );\r\n return rowsToFacts(result);\r\n }\r\n\r\n const likeClauses = keywords.map(() => `LOWER(content) LIKE ?`).join(' OR ');\r\n const likeParams = keywords.map((k) => `%${k}%`);\r\n\r\n const result = d.exec(\r\n `SELECT * FROM facts WHERE project_id = ? AND (${likeClauses})\r\n ORDER BY relevance DESC, accessed_at DESC LIMIT ?`,\r\n [projectId, ...likeParams, limit],\r\n );\r\n\r\n const facts = rowsToFacts(result);\r\n\r\n // Update accessed_at for recalled facts\r\n for (const fact of facts) {\r\n if (fact.id) {\r\n d.run(`UPDATE facts SET accessed_at = ? WHERE id = ?`, [Date.now(), fact.id]);\r\n }\r\n }\r\n if (facts.length > 0) persist();\r\n\r\n return facts;\r\n}\r\n\r\nexport function getAllFacts(projectId: string): Fact[] {\r\n const d = getDb();\r\n const result = d.exec(\r\n `SELECT * FROM facts WHERE project_id = ? ORDER BY relevance DESC`,\r\n [projectId],\r\n );\r\n return rowsToFacts(result);\r\n}\r\n\r\nfunction rowsToFacts(result: QueryExecResult[]): Fact[] {\r\n if (!result[0]) return [];\r\n return result[0].values.map((row) => ({\r\n id: row[0] as number,\r\n projectId: row[1] as string,\r\n content: row[2] as string,\r\n category: row[3] as FactCategory,\r\n source: row[4] as string | undefined,\r\n relevance: row[5] as number,\r\n createdAt: row[6] as number,\r\n accessedAt: row[7] as number,\r\n }));\r\n}\r\n\r\n// --- Messages ---\r\n\r\nexport function storeMessage(msg: Omit<ChatMessage, 'id'>): void {\r\n const d = getDb();\r\n d.run(\r\n `INSERT INTO messages (session_id, role, content, tool_name, created_at)\r\n VALUES (?, ?, ?, ?, ?)`,\r\n [msg.sessionId, msg.role, msg.content, msg.toolName ?? null, msg.createdAt],\r\n );\r\n persist();\r\n}\r\n\r\nexport function getSessionMessages(sessionId: string, limit = 100): ChatMessage[] {\r\n const d = getDb();\r\n const result = d.exec(\r\n `SELECT * FROM messages WHERE session_id = ? ORDER BY created_at ASC LIMIT ?`,\r\n [sessionId, limit],\r\n );\r\n if (!result[0]) return [];\r\n return result[0].values.map((row) => ({\r\n id: row[0] as number,\r\n sessionId: row[1] as string,\r\n role: row[2] as ChatMessage['role'],\r\n content: row[3] as string,\r\n toolName: (row[4] as string) || undefined,\r\n createdAt: row[5] as number,\r\n }));\r\n}\r\n\r\n// --- Summaries ---\r\n\r\nexport function storeSummary(summary: Omit<SessionSummary, 'id'>): void {\r\n const d = getDb();\r\n d.run(\r\n `INSERT INTO summaries (project_id, session_id, summary, created_at)\r\n VALUES (?, ?, ?, ?)`,\r\n [summary.projectId, summary.sessionId, summary.summary, summary.createdAt],\r\n );\r\n persist();\r\n}\r\n\r\nexport function getProjectSummaries(projectId: string, limit = 20): SessionSummary[] {\r\n const d = getDb();\r\n const result = d.exec(\r\n `SELECT * FROM summaries WHERE project_id = ? ORDER BY created_at DESC LIMIT ?`,\r\n [projectId, limit],\r\n );\r\n if (!result[0]) return [];\r\n return result[0].values.map((row) => ({\r\n id: row[0] as number,\r\n projectId: row[1] as string,\r\n sessionId: row[2] as string,\r\n summary: row[3] as string,\r\n createdAt: row[4] as number,\r\n }));\r\n}\r\n\r\n// --- Script Index ---\r\n\r\nexport function upsertScript(entry: Omit<ScriptEntry, 'id'>): void {\r\n const d = getDb();\r\n const existing = d.exec(\r\n `SELECT id FROM script_index WHERE project_id = ? AND path = ?`,\r\n [entry.projectId, entry.path],\r\n );\r\n\r\n if (existing[0]?.values.length) {\r\n d.run(\r\n `UPDATE script_index SET class_name = ?, summary = ?, line_count = ?, last_hash = ?, updated_at = ?\r\n WHERE project_id = ? AND path = ?`,\r\n [\r\n entry.className,\r\n entry.summary ?? null,\r\n entry.lineCount ?? null,\r\n entry.lastHash ?? null,\r\n entry.updatedAt,\r\n entry.projectId,\r\n entry.path,\r\n ],\r\n );\r\n } else {\r\n d.run(\r\n `INSERT INTO script_index (project_id, path, class_name, summary, line_count, last_hash, updated_at)\r\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\r\n [\r\n entry.projectId,\r\n entry.path,\r\n entry.className,\r\n entry.summary ?? null,\r\n entry.lineCount ?? null,\r\n entry.lastHash ?? null,\r\n entry.updatedAt,\r\n ],\r\n );\r\n }\r\n persist();\r\n}\r\n\r\nexport function getScriptIndex(\r\n projectId: string,\r\n): { path: string; summary?: string; className: string }[] {\r\n const d = getDb();\r\n const result = d.exec(\r\n `SELECT path, summary, class_name FROM script_index WHERE project_id = ? ORDER BY path`,\r\n [projectId],\r\n );\r\n if (!result[0]) return [];\r\n return result[0].values.map((row) => ({\r\n path: row[0] as string,\r\n summary: (row[1] as string) || undefined,\r\n className: row[2] as string,\r\n }));\r\n}\r\n\r\nexport function getScriptEntry(projectId: string, scriptPath: string): ScriptEntry | null {\r\n const d = getDb();\r\n const result = d.exec(\r\n `SELECT * FROM script_index WHERE project_id = ? AND path = ?`,\r\n [projectId, scriptPath],\r\n );\r\n if (!result[0]?.values.length) return null;\r\n const row = result[0].values[0];\r\n return {\r\n id: row[0] as number,\r\n projectId: row[1] as string,\r\n path: row[2] as string,\r\n className: row[3] as string,\r\n summary: (row[4] as string) || undefined,\r\n lineCount: (row[5] as number) || undefined,\r\n lastHash: (row[6] as string) || undefined,\r\n updatedAt: row[7] as number,\r\n };\r\n}\r\n\r\n// --- Decay ---\r\n\r\nexport function decayRelevance(projectId: string, factor = 0.95): void {\r\n const d = getDb();\r\n d.run(`UPDATE facts SET relevance = relevance * ? WHERE project_id = ?`, [factor, projectId]);\r\n persist();\r\n}\r\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\r\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\r\nimport { z } from 'zod';\r\nimport { DominusServer } from '../transport/ws-server.js';\r\nimport { CliMsg, type ExplorerNode, type ScriptContentPayload, type RunCodeResponsePayload, type SearchResultPayload, type OutputPayload, type SelectionPayload, type PropertyEntry, type TestResultPayload, type StudioTestResultPayload } from '../transport/protocol.js';\r\nimport { initMemoryStore, recallFacts, storeFact, getScriptIndex } from '../memory/store.js';\r\nimport { loadConfig } from '../config/config.js';\r\n\r\nlet wsServer: DominusServer;\r\n\r\nexport async function startMcpServer(): Promise<void> {\r\n const config = loadConfig();\r\n await initMemoryStore();\r\n\r\n wsServer = new DominusServer(config.port);\r\n await wsServer.start();\r\n\r\n const mcp = new McpServer({\r\n name: 'dominus',\r\n version: '0.1.0',\r\n });\r\n\r\n // --- Studio Tools ---\r\n\r\n mcp.tool(\r\n 'read_script',\r\n 'Read the source code of a script in Roblox Studio',\r\n { path: z.string().describe('Full instance path, e.g. \"ServerScriptService.GameManager\"') },\r\n async ({ path }) => {\r\n assertConnected();\r\n const res = await wsServer.sendRequest<ScriptContentPayload>(CliMsg.GET_SCRIPT, { path });\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload, null, 2) }] };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'edit_script',\r\n 'Replace the entire source code of a script in Roblox Studio',\r\n {\r\n path: z.string().describe('Full instance path'),\r\n source: z.string().describe('New complete source code'),\r\n },\r\n async ({ path, source }) => {\r\n assertConnected();\r\n const res = await wsServer.sendRequest(CliMsg.SET_SCRIPT, { path, source });\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload) }] };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'run_code',\r\n 'Execute Luau code in Roblox Studio and return output',\r\n { code: z.string().describe('Luau code to execute') },\r\n async ({ code }) => {\r\n assertConnected();\r\n const res = await wsServer.sendRequest<RunCodeResponsePayload>(CliMsg.RUN_CODE, { code });\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload, null, 2) }] };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'get_explorer',\r\n 'Get the DataModel explorer tree from Roblox Studio',\r\n {\r\n rootPath: z.string().optional().describe('Root path to start from. Omit for entire tree.'),\r\n maxDepth: z.number().optional().default(3).describe('Maximum tree depth'),\r\n },\r\n async ({ rootPath, maxDepth }) => {\r\n assertConnected();\r\n const res = await wsServer.sendRequest<{ tree: ExplorerNode[] }>(CliMsg.GET_EXPLORER, {\r\n rootPath: rootPath ?? null,\r\n maxDepth,\r\n });\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload, null, 2) }] };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'get_properties',\r\n 'Get all properties of an instance in Roblox Studio',\r\n { path: z.string().describe('Full instance path') },\r\n async ({ path }) => {\r\n assertConnected();\r\n const res = await wsServer.sendRequest<{ properties: PropertyEntry[] }>(CliMsg.GET_PROPERTIES, { path });\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload, null, 2) }] };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'set_properties',\r\n 'Set properties on an instance in Roblox Studio',\r\n {\r\n path: z.string().describe('Full instance path'),\r\n properties: z.record(z.unknown()).describe('Key-value pairs of properties to set'),\r\n },\r\n async ({ path, properties }) => {\r\n assertConnected();\r\n const res = await wsServer.sendRequest(CliMsg.SET_PROPERTIES, { path, properties });\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload) }] };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'insert_instance',\r\n 'Create a new instance in the Roblox Studio DataModel',\r\n {\r\n className: z.string().describe('Class name (e.g. \"Part\", \"Script\")'),\r\n parentPath: z.string().describe('Parent instance path'),\r\n name: z.string().describe('Name for the new instance'),\r\n properties: z.record(z.unknown()).optional().describe('Optional properties to set'),\r\n },\r\n async ({ className, parentPath, name, properties }) => {\r\n assertConnected();\r\n const res = await wsServer.sendRequest(CliMsg.INSERT_INSTANCE, {\r\n className, parentPath, name, properties: properties ?? {},\r\n });\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload) }] };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'delete_instance',\r\n 'Delete an instance from the Roblox Studio DataModel',\r\n { path: z.string().describe('Full instance path to delete') },\r\n async ({ path }) => {\r\n assertConnected();\r\n const res = await wsServer.sendRequest(CliMsg.DELETE_INSTANCE, { path });\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload) }] };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'get_selection',\r\n 'Get the currently selected instances in Roblox Studio',\r\n {},\r\n async () => {\r\n assertConnected();\r\n const res = await wsServer.sendRequest<SelectionPayload>(CliMsg.GET_SELECTION, {});\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload, null, 2) }] };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'search_scripts',\r\n 'Search all scripts in Roblox Studio for a text pattern',\r\n {\r\n query: z.string().describe('Text to search for'),\r\n maxResults: z.number().optional().default(20).describe('Max results'),\r\n },\r\n async ({ query, maxResults }) => {\r\n assertConnected();\r\n const res = await wsServer.sendRequest<SearchResultPayload>(CliMsg.SEARCH_SCRIPTS, { query, maxResults });\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload, null, 2) }] };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'get_output',\r\n 'Get recent output log from Roblox Studio',\r\n {\r\n limit: z.number().optional().default(50).describe('Max entries'),\r\n level: z.enum(['info', 'warn', 'error']).optional().describe('Filter by level'),\r\n },\r\n async ({ limit, level }) => {\r\n assertConnected();\r\n const res = await wsServer.sendRequest<{ entries: OutputPayload[] }>(CliMsg.GET_OUTPUT, {\r\n limit, level: level ?? null,\r\n });\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload, null, 2) }] };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'get_class_info',\r\n 'Look up the schema of any Roblox class using ReflectionService. Returns all properties (with types), methods (with parameters), and events. ' +\r\n 'ALWAYS use this before creating or modifying GUI elements to know correct property names and types.',\r\n { className: z.string().describe('Roblox class name, e.g. \"Frame\", \"TextLabel\", \"Part\", \"MeshPart\"') },\r\n async ({ className }) => {\r\n assertConnected();\r\n const res = await wsServer.sendRequest<unknown>(CliMsg.GET_REFLECTION, { className });\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload, null, 2) }] };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'create_ui',\r\n 'Create an entire UI tree in one call. Pass a declarative JSON tree — ClassName, Name, properties, Children. ' +\r\n 'All types auto-coerced in Luau (UDim2, Color3, Font, enums). 10x faster than run_code. ' +\r\n 'UDim2: [xScale, xOffset, yScale, yOffset]. Color3: \"#hex\" or \"rgb(r,g,b)\". Font: \"GothamBold\". Enums: string names.',\r\n {\r\n parent: z.string().optional().describe('Parent: \"StarterGui\", \"PlayerGui\", or path. Default: StarterGui'),\r\n tree: z.record(z.unknown()).describe(\r\n 'Root UI node: {ClassName, Name, properties..., Children: [{...}, ...]}. ' +\r\n 'UDim2 as [xScale, xOffset, yScale, yOffset], Color3 as \"#hex\", Font as \"GothamBold\"',\r\n ),\r\n },\r\n async ({ parent, tree }) => {\r\n assertConnected();\r\n const res = await wsServer.sendRequest<{ success: boolean; path?: string; instanceCount?: number; error?: string }>(\r\n CliMsg.BUILD_UI, { parent: parent ?? 'StarterGui', tree },\r\n );\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload, null, 2) }] };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'run_tests',\r\n 'Run tests by requiring ModuleScripts matching test naming conventions (*.test, *.spec, *Test, *Spec). Lightweight — does not enter Run/Play mode.',\r\n { testName: z.string().optional().describe('Specific test name, or omit to run all') },\r\n async ({ testName }) => {\r\n assertConnected();\r\n const res = await wsServer.sendRequest<{ results: TestResultPayload[] }>(CliMsg.RUN_TESTS, {\r\n testName: testName ?? null,\r\n });\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload, null, 2) }] };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'execute_run_test',\r\n 'Start a Run mode test session using StudioTestService:ExecuteRunModeAsync(). ' +\r\n 'This actually enters Run mode in Studio. Pass args that server scripts can retrieve via GetTestArgs(). ' +\r\n 'Yields until EndTest() is called or the session stops. Returns the value from EndTest(). ' +\r\n 'Use for headless automated tests — no player, just server scripts.',\r\n { args: z.unknown().optional().describe('Arguments passed to the test session. Server scripts get this via StudioTestService:GetTestArgs()') },\r\n async ({ args }) => {\r\n assertConnected();\r\n const res = await wsServer.sendRequest<StudioTestResultPayload>(CliMsg.EXECUTE_RUN_TEST, { args: args ?? null }, 120_000);\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload, null, 2) }] };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'execute_play_test',\r\n 'Start a solo Play mode test session using StudioTestService:ExecutePlayModeAsync(). ' +\r\n 'This enters Play mode with a player character. Pass args that server scripts can retrieve via GetTestArgs(). ' +\r\n 'Yields until EndTest() is called or the session stops. Returns the value from EndTest(). ' +\r\n 'Use for tests needing a player character and full client-server simulation.',\r\n { args: z.unknown().optional().describe('Arguments passed to the test session. Server scripts get this via StudioTestService:GetTestArgs()') },\r\n async ({ args }) => {\r\n assertConnected();\r\n const res = await wsServer.sendRequest<StudioTestResultPayload>(CliMsg.EXECUTE_PLAY_TEST, { args: args ?? null }, 120_000);\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload, null, 2) }] };\r\n },\r\n );\r\n\r\n // --- Builder Tools ---\r\n\r\n mcp.tool(\r\n 'create_part',\r\n 'Create a Part with position, size, color, material — all in one call. Faster than insert_instance + set_properties.',\r\n {\r\n name: z.string().describe('Name for the part'),\r\n parent: z.string().optional().describe('Parent path (default: Workspace)'),\r\n shape: z.enum(['Block', 'Ball', 'Cylinder', 'Wedge', 'CornerWedge']).optional().describe('Part shape'),\r\n position: z.object({ x: z.number(), y: z.number(), z: z.number() }).optional().describe('World position'),\r\n size: z.object({ x: z.number(), y: z.number(), z: z.number() }).optional().describe('Size in studs'),\r\n color: z.string().optional().describe('Hex \"#00FF00\", BrickColor name, or \"rgb(0,255,0)\"'),\r\n material: z.string().optional().describe('Plastic, Wood, Grass, Neon, Metal, etc.'),\r\n transparency: z.number().optional().describe('0=opaque, 1=invisible'),\r\n anchored: z.boolean().optional().describe('Anchored (default: true)'),\r\n canCollide: z.boolean().optional().describe('Has collision'),\r\n },\r\n async (params) => {\r\n assertConnected();\r\n const properties: Record<string, unknown> = {};\r\n if (params.position) properties.Position = { X: params.position.x, Y: params.position.y, Z: params.position.z };\r\n if (params.size) properties.Size = { X: params.size.x, Y: params.size.y, Z: params.size.z };\r\n if (params.color) {\r\n const c = params.color;\r\n if (c.startsWith('#')) properties.Color = c;\r\n else if (c.startsWith('rgb')) {\r\n const m = c.match(/(\\d+)/g);\r\n if (m && m.length >= 3) properties.Color = { red: parseInt(m[0]), green: parseInt(m[1]), blue: parseInt(m[2]) };\r\n } else properties.BrickColor = c;\r\n }\r\n if (params.material) properties.Material = params.material;\r\n if (params.transparency !== undefined) properties.Transparency = params.transparency;\r\n if (params.anchored !== undefined) properties.Anchored = params.anchored;\r\n else properties.Anchored = true;\r\n if (params.canCollide !== undefined) properties.CanCollide = params.canCollide;\r\n if (params.shape && params.shape !== 'Block') properties.Shape = params.shape;\r\n\r\n const className = params.shape === 'Wedge' ? 'WedgePart' : params.shape === 'CornerWedge' ? 'CornerWedgePart' : 'Part';\r\n\r\n const res = await wsServer.sendRequest<{ success: boolean; path?: string; error?: string }>(CliMsg.INSERT_INSTANCE, {\r\n className,\r\n parentPath: params.parent ?? 'Workspace',\r\n name: params.name,\r\n properties,\r\n });\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload, null, 2) }] };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'clone_instance',\r\n 'Clone an existing instance, optionally rename it, move it, or offset its position',\r\n {\r\n path: z.string().describe('Path of instance to clone'),\r\n newName: z.string().optional().describe('Name for the clone'),\r\n newParent: z.string().optional().describe('Parent path for the clone'),\r\n offset: z.object({ x: z.number(), y: z.number(), z: z.number() }).optional().describe('Position offset from original'),\r\n },\r\n async (params) => {\r\n assertConnected();\r\n const parts = params.path.split('.');\r\n let resolve = 'game';\r\n for (const p of parts) resolve += `[\"${p}\"]`;\r\n\r\n const lines = [`local orig = ${resolve}`, `local clone = orig:Clone()`];\r\n if (params.newName) lines.push(`clone.Name = \"${params.newName}\"`);\r\n if (params.newParent) {\r\n const pp = params.newParent.split('.');\r\n let pr = 'game';\r\n for (const p of pp) pr += `[\"${p}\"]`;\r\n lines.push(`clone.Parent = ${pr}`);\r\n } else {\r\n lines.push(`clone.Parent = orig.Parent`);\r\n }\r\n if (params.offset) {\r\n lines.push(`if clone:IsA(\"BasePart\") then`);\r\n lines.push(` clone.Position = clone.Position + Vector3.new(${params.offset.x}, ${params.offset.y}, ${params.offset.z})`);\r\n lines.push(`end`);\r\n }\r\n lines.push(`print(\"Cloned: \" .. clone:GetFullName())`);\r\n\r\n const res = await wsServer.sendRequest<RunCodeResponsePayload>(CliMsg.RUN_CODE, { code: lines.join('\\n') });\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload, null, 2) }] };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'group_instances',\r\n 'Group multiple instances into a Model or Folder',\r\n {\r\n paths: z.array(z.string()).describe('Array of instance paths to group'),\r\n groupName: z.string().describe('Name for the group'),\r\n groupClass: z.enum(['Model', 'Folder']).optional().describe('Container class (default: Model)'),\r\n parent: z.string().optional().describe('Parent path (default: Workspace)'),\r\n },\r\n async (params) => {\r\n assertConnected();\r\n const gc = params.groupClass ?? 'Model';\r\n const parent = params.parent ?? 'Workspace';\r\n const parentParts = parent.split('.');\r\n let parentResolve = 'game';\r\n for (const p of parentParts) parentResolve += `[\"${p}\"]`;\r\n\r\n const resolves = params.paths.map((path) => {\r\n const parts = path.split('.');\r\n let r = 'game';\r\n for (const part of parts) r += `[\"${part}\"]`;\r\n return r;\r\n });\r\n\r\n const code = [\r\n `local group = Instance.new(\"${gc}\")`,\r\n `group.Name = \"${params.groupName}\"`,\r\n `group.Parent = ${parentResolve}`,\r\n ...resolves.map((r) => `${r}.Parent = group`),\r\n `print(\"Grouped ${params.paths.length} instances into: \" .. group:GetFullName())`,\r\n ].join('\\n');\r\n\r\n const res = await wsServer.sendRequest<RunCodeResponsePayload>(CliMsg.RUN_CODE, { code });\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload, null, 2) }] };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'build_multiple',\r\n 'Create many parts/instances in one batch. Send an array of specs — all created in a single round-trip. Ideal for building trees, houses, vehicles.',\r\n {\r\n parts: z.array(z.object({\r\n name: z.string(),\r\n className: z.string().optional(),\r\n parent: z.string().optional(),\r\n position: z.object({ x: z.number(), y: z.number(), z: z.number() }).optional(),\r\n size: z.object({ x: z.number(), y: z.number(), z: z.number() }).optional(),\r\n color: z.string().optional().describe('Hex \"#RRGGBB\" or BrickColor name'),\r\n material: z.string().optional(),\r\n transparency: z.number().optional(),\r\n anchored: z.boolean().optional(),\r\n shape: z.enum(['Block', 'Ball', 'Cylinder', 'Wedge']).optional(),\r\n })).describe('Array of part specifications'),\r\n groupName: z.string().optional().describe('Group all parts into a Model with this name'),\r\n groupParent: z.string().optional().describe('Parent for the group (default: Workspace)'),\r\n },\r\n async (params) => {\r\n assertConnected();\r\n const parts = params.parts;\r\n const groupName = params.groupName;\r\n const groupParent = params.groupParent ?? 'Workspace';\r\n\r\n function resolveP(path: string): string {\r\n const segs = path.split('.');\r\n let r = 'game';\r\n for (const s of segs) r += `[\"${s}\"]`;\r\n return r;\r\n }\r\n\r\n const lines: string[] = [];\r\n if (groupName) {\r\n lines.push(`local _group = Instance.new(\"Model\")`);\r\n lines.push(`_group.Name = \"${groupName}\"`);\r\n lines.push(`_group.Parent = ${resolveP(groupParent)}`);\r\n }\r\n for (let i = 0; i < parts.length; i++) {\r\n const p = parts[i];\r\n const v = `_p${i}`;\r\n const cn = p.className ?? (p.shape === 'Wedge' ? 'WedgePart' : 'Part');\r\n lines.push(`local ${v} = Instance.new(\"${cn}\")`);\r\n lines.push(`${v}.Name = \"${p.name}\"`);\r\n if (p.position) lines.push(`${v}.Position = Vector3.new(${p.position.x}, ${p.position.y}, ${p.position.z})`);\r\n if (p.size) lines.push(`${v}.Size = Vector3.new(${p.size.x}, ${p.size.y}, ${p.size.z})`);\r\n if (p.color) {\r\n if (p.color.startsWith('#')) lines.push(`${v}.Color = Color3.fromHex(\"${p.color}\")`);\r\n else lines.push(`${v}.BrickColor = BrickColor.new(\"${p.color}\")`);\r\n }\r\n if (p.material) lines.push(`${v}.Material = Enum.Material.${p.material}`);\r\n if (p.transparency !== undefined) lines.push(`${v}.Transparency = ${p.transparency}`);\r\n lines.push(`${v}.Anchored = ${p.anchored ?? true}`);\r\n if (p.shape && p.shape !== 'Block' && cn === 'Part') lines.push(`${v}.Shape = Enum.PartType.${p.shape}`);\r\n lines.push(`${v}.Parent = ${groupName ? '_group' : resolveP(p.parent ?? 'Workspace')}`);\r\n }\r\n lines.push(`print(\"Built ${parts.length} parts${groupName ? ` in ${groupName}` : ''}\")`);\r\n\r\n const res = await wsServer.sendRequest<RunCodeResponsePayload>(CliMsg.RUN_CODE, { code: lines.join('\\n') });\r\n return { content: [{ type: 'text' as const, text: JSON.stringify(res.payload, null, 2) }] };\r\n },\r\n );\r\n\r\n // --- Memory Tools ---\r\n\r\n mcp.tool(\r\n 'recall_memory',\r\n 'Search persistent memory for facts about the current Roblox project',\r\n { query: z.string().describe('What to search for') },\r\n async ({ query }) => {\r\n const facts = recallFacts('current', query, 15);\r\n const scripts = getScriptIndex('current');\r\n return {\r\n content: [{\r\n type: 'text' as const,\r\n text: JSON.stringify({ facts: facts.map(f => f.content), scriptIndex: scripts }, null, 2),\r\n }],\r\n };\r\n },\r\n );\r\n\r\n mcp.tool(\r\n 'remember',\r\n 'Store a fact about the project in persistent memory for future sessions',\r\n {\r\n fact: z.string().describe('The fact to remember'),\r\n category: z.enum(['architecture', 'pattern', 'preference', 'bug', 'api', 'general']).describe('Category'),\r\n },\r\n async ({ fact, category }) => {\r\n const now = Date.now();\r\n storeFact({ projectId: 'current', content: fact, category, source: 'mcp', relevance: 1.0, createdAt: now, accessedAt: now });\r\n return { content: [{ type: 'text' as const, text: `Remembered: ${fact}` }] };\r\n },\r\n );\r\n\r\n // --- Resources ---\r\n\r\n mcp.resource(\r\n 'studio://status',\r\n 'studio://status',\r\n async () => {\r\n const info = wsServer.getConnectionInfo();\r\n return {\r\n contents: [{\r\n uri: 'studio://status',\r\n text: JSON.stringify({\r\n connected: wsServer.isConnected(),\r\n placeName: info?.placeName,\r\n placeId: info?.placeId,\r\n studioVersion: info?.studioVersion,\r\n port: wsServer.getPort(),\r\n }, null, 2),\r\n mimeType: 'application/json',\r\n }],\r\n };\r\n },\r\n );\r\n\r\n // Start the MCP server on stdio\r\n const transport = new StdioServerTransport();\r\n await mcp.connect(transport);\r\n}\r\n\r\nfunction assertConnected(): void {\r\n if (!wsServer.isConnected()) {\r\n throw new Error(\r\n 'Roblox Studio is not connected. Open Studio and click the Dominus plugin Connect button.',\r\n );\r\n }\r\n}\r\n","import { startMcpServer } from './server.js';\r\n\r\nstartMcpServer().catch((err) => {\r\n console.error('Failed to start Dominus MCP server:', err);\r\n process.exit(1);\r\n});\r\n"]}
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "dominus-cli",
3
+ "version": "0.1.0",
4
+ "description": "AI-powered autonomous agent for Roblox Studio development. Real-time WebSocket bridge, persistent memory, and intelligent tool use.",
5
+ "type": "module",
6
+ "bin": {
7
+ "dominus": "./dist/index.js",
8
+ "dominus-mcp": "./dist/mcp.js"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "scripts": {
12
+ "dev": "tsx src/index.tsx",
13
+ "build": "tsup",
14
+ "build:plugin": "rojo build plugin/default.project.json -o plugin/Dominus.rbxm",
15
+ "start": "node dist/index.js",
16
+ "test": "vitest run",
17
+ "test:watch": "vitest",
18
+ "test:coverage": "vitest run --coverage",
19
+ "lint": "prettier --check .",
20
+ "format": "prettier --write .",
21
+ "typecheck": "tsc --noEmit",
22
+ "prepublishOnly": "pnpm build",
23
+ "install-plugin": "tsx src/install-plugin.ts"
24
+ },
25
+ "dependencies": {
26
+ "@modelcontextprotocol/sdk": "^1.27.0",
27
+ "chalk": "^5.4.1",
28
+ "commander": "^13.1.0",
29
+ "figures": "^6.1.0",
30
+ "ink": "^5.1.0",
31
+ "ink-spinner": "^5.0.0",
32
+ "ink-text-input": "^6.0.0",
33
+ "nanoid": "^5.1.0",
34
+ "openai": "^4.77.0",
35
+ "react": "^18.3.1",
36
+ "sql.js": "^1.14.0",
37
+ "ws": "^8.18.0",
38
+ "zod": "^3.24.0"
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^22.0.0",
42
+ "@types/react": "^18.3.0",
43
+ "@types/ws": "^8.5.0",
44
+ "@vitest/coverage-v8": "^2.1.0",
45
+ "prettier": "^3.4.0",
46
+ "tsup": "^8.3.0",
47
+ "tsx": "^4.19.0",
48
+ "typescript": "^5.7.0",
49
+ "vitest": "^2.1.0"
50
+ },
51
+ "engines": {
52
+ "node": ">=20.0.0"
53
+ },
54
+ "files": [
55
+ "dist",
56
+ "plugin"
57
+ ],
58
+ "keywords": [
59
+ "roblox",
60
+ "roblox-studio",
61
+ "cli",
62
+ "tui",
63
+ "ai",
64
+ "agent",
65
+ "luau",
66
+ "dominus",
67
+ "websocket",
68
+ "openrouter",
69
+ "mcp",
70
+ "model-context-protocol"
71
+ ],
72
+ "author": "Eli",
73
+ "license": "MIT",
74
+ "repository": {
75
+ "type": "git",
76
+ "url": "https://github.com/eli/dominus"
77
+ }
78
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "Dominus",
3
+ "tree": {
4
+ "$path": "src"
5
+ }
6
+ }
@@ -0,0 +1,116 @@
1
+ --[[
2
+ Code executor: safely run Luau code in the Studio plugin context
3
+ ]]
4
+
5
+ local Executor = {}
6
+
7
+ function Executor.run(code)
8
+ local output = {}
9
+ local startTime = os.clock()
10
+
11
+ -- Capture prints by temporarily overriding
12
+ local oldPrint = print
13
+ local oldWarn = warn
14
+ local capturedOutput = {}
15
+
16
+ local env = setmetatable({
17
+ print = function(...)
18
+ local args = table.pack(...)
19
+ local parts = {}
20
+ for i = 1, args.n do
21
+ table.insert(parts, tostring(args[i]))
22
+ end
23
+ local line = table.concat(parts, "\t")
24
+ table.insert(capturedOutput, line)
25
+ oldPrint(...)
26
+ end,
27
+ warn = function(...)
28
+ local args = table.pack(...)
29
+ local parts = {}
30
+ for i = 1, args.n do
31
+ table.insert(parts, tostring(args[i]))
32
+ end
33
+ local line = "WARN: " .. table.concat(parts, "\t")
34
+ table.insert(capturedOutput, line)
35
+ oldWarn(...)
36
+ end,
37
+ game = game,
38
+ workspace = workspace,
39
+ script = script,
40
+ require = require,
41
+ task = task,
42
+ wait = task.wait,
43
+ delay = task.delay,
44
+ spawn = task.spawn,
45
+ typeof = typeof,
46
+ Instance = Instance,
47
+ Enum = Enum,
48
+ Vector3 = Vector3,
49
+ CFrame = CFrame,
50
+ Color3 = Color3,
51
+ BrickColor = BrickColor,
52
+ UDim2 = UDim2,
53
+ UDim = UDim,
54
+ Ray = Ray,
55
+ Region3 = Region3,
56
+ NumberRange = NumberRange,
57
+ NumberSequence = NumberSequence,
58
+ ColorSequence = ColorSequence,
59
+ Rect = Rect,
60
+ TweenInfo = TweenInfo,
61
+ math = math,
62
+ string = string,
63
+ table = table,
64
+ coroutine = coroutine,
65
+ os = os,
66
+ tostring = tostring,
67
+ tonumber = tonumber,
68
+ type = type,
69
+ pairs = pairs,
70
+ ipairs = ipairs,
71
+ next = next,
72
+ select = select,
73
+ unpack = unpack or table.unpack,
74
+ pcall = pcall,
75
+ xpcall = xpcall,
76
+ error = error,
77
+ assert = assert,
78
+ rawget = rawget,
79
+ rawset = rawset,
80
+ setmetatable = setmetatable,
81
+ getmetatable = getmetatable,
82
+ }, {
83
+ __index = function(_, key)
84
+ return game:GetService(key)
85
+ end,
86
+ })
87
+
88
+ local fn, compileErr = loadstring(code)
89
+ if not fn then
90
+ return {
91
+ output = table.concat(capturedOutput, "\n"),
92
+ error = "Compile error: " .. tostring(compileErr),
93
+ duration = os.clock() - startTime,
94
+ }
95
+ end
96
+
97
+ setfenv(fn, env)
98
+ local ok, runtimeErr = pcall(fn)
99
+
100
+ local duration = os.clock() - startTime
101
+
102
+ if not ok then
103
+ return {
104
+ output = table.concat(capturedOutput, "\n"),
105
+ error = "Runtime error: " .. tostring(runtimeErr),
106
+ duration = duration,
107
+ }
108
+ end
109
+
110
+ return {
111
+ output = table.concat(capturedOutput, "\n"),
112
+ duration = duration,
113
+ }
114
+ end
115
+
116
+ return Executor
@@ -0,0 +1,251 @@
1
+ --[[
2
+ Explorer module: serialize DataModel tree, read/write scripts, search, manage instances
3
+ ]]
4
+
5
+ local ScriptEditorService = game:GetService("ScriptEditorService")
6
+
7
+ local Explorer = {}
8
+
9
+ local SCRIPT_CLASSES = {
10
+ Script = true,
11
+ LocalScript = true,
12
+ ModuleScript = true,
13
+ }
14
+
15
+ function Explorer.getPath(instance)
16
+ local parts = {}
17
+ local current = instance
18
+ while current and current ~= game do
19
+ table.insert(parts, 1, current.Name)
20
+ current = current.Parent
21
+ end
22
+ return table.concat(parts, ".")
23
+ end
24
+
25
+ function Explorer.resolveInstance(path)
26
+ local parts = string.split(path, ".")
27
+ local current = game
28
+ for _, part in parts do
29
+ local child = current:FindFirstChild(part)
30
+ if not child then
31
+ return nil
32
+ end
33
+ current = child
34
+ end
35
+ return current
36
+ end
37
+
38
+ function Explorer.getTree(rootPath, maxDepth)
39
+ maxDepth = maxDepth or 3
40
+
41
+ local root
42
+ if rootPath and rootPath ~= "" then
43
+ root = Explorer.resolveInstance(rootPath)
44
+ if not root then
45
+ return {}
46
+ end
47
+ else
48
+ root = game
49
+ end
50
+
51
+ local function serialize(instance, depth)
52
+ if depth > maxDepth then
53
+ return nil
54
+ end
55
+
56
+ local node = {
57
+ name = instance.Name,
58
+ className = instance.ClassName,
59
+ path = Explorer.getPath(instance),
60
+ }
61
+
62
+ local children = {}
63
+ for _, child in instance:GetChildren() do
64
+ local childNode = serialize(child, depth + 1)
65
+ if childNode then
66
+ table.insert(children, childNode)
67
+ end
68
+ end
69
+
70
+ if #children > 0 then
71
+ node.children = children
72
+ end
73
+
74
+ return node
75
+ end
76
+
77
+ if root == game then
78
+ local topLevel = {}
79
+ for _, service in game:GetChildren() do
80
+ local ok, node = pcall(serialize, service, 1)
81
+ if ok and node then
82
+ table.insert(topLevel, node)
83
+ end
84
+ end
85
+ return topLevel
86
+ else
87
+ local node = serialize(root, 0)
88
+ return node and { node } or {}
89
+ end
90
+ end
91
+
92
+ function Explorer.getScriptSource(path)
93
+ local instance = Explorer.resolveInstance(path)
94
+ if not instance then
95
+ return { success = false, error = "Instance not found: " .. path }
96
+ end
97
+
98
+ if not SCRIPT_CLASSES[instance.ClassName] then
99
+ return { success = false, error = "Not a script: " .. path }
100
+ end
101
+
102
+ local ok, source = pcall(function()
103
+ return ScriptEditorService:GetEditorSource(instance)
104
+ end)
105
+
106
+ if not ok then
107
+ -- Fallback to .Source property
108
+ ok, source = pcall(function()
109
+ return instance.Source
110
+ end)
111
+ end
112
+
113
+ if not ok then
114
+ return { success = false, error = "Could not read source: " .. tostring(source) }
115
+ end
116
+
117
+ local lines = select(2, source:gsub("\n", "\n")) + 1
118
+
119
+ return {
120
+ path = path,
121
+ className = instance.ClassName,
122
+ source = source,
123
+ lineCount = lines,
124
+ }
125
+ end
126
+
127
+ function Explorer.setScriptSource(path, newSource)
128
+ local instance = Explorer.resolveInstance(path)
129
+ if not instance then
130
+ return { success = false, error = "Instance not found: " .. path }
131
+ end
132
+
133
+ if not SCRIPT_CLASSES[instance.ClassName] then
134
+ return { success = false, error = "Not a script: " .. path }
135
+ end
136
+
137
+ local ok, err = pcall(function()
138
+ ScriptEditorService:UpdateSourceAsync(instance, function()
139
+ return newSource
140
+ end)
141
+ end)
142
+
143
+ if not ok then
144
+ return { success = false, error = "Failed to update source: " .. tostring(err) }
145
+ end
146
+
147
+ return { success = true }
148
+ end
149
+
150
+ function Explorer.insertInstance(className, parentPath, name, properties)
151
+ local parent = Explorer.resolveInstance(parentPath)
152
+ if not parent then
153
+ return { success = false, error = "Parent not found: " .. parentPath }
154
+ end
155
+
156
+ local ok, instance = pcall(function()
157
+ local obj = Instance.new(className)
158
+ obj.Name = name
159
+
160
+ if properties then
161
+ for key, value in properties do
162
+ pcall(function()
163
+ obj[key] = value
164
+ end)
165
+ end
166
+ end
167
+
168
+ obj.Parent = parent
169
+ return obj
170
+ end)
171
+
172
+ if not ok then
173
+ return { success = false, error = "Failed to create instance: " .. tostring(instance) }
174
+ end
175
+
176
+ return { success = true, path = Explorer.getPath(instance) }
177
+ end
178
+
179
+ function Explorer.deleteInstance(path)
180
+ local instance = Explorer.resolveInstance(path)
181
+ if not instance then
182
+ return { success = false, error = "Instance not found: " .. path }
183
+ end
184
+
185
+ local ok, err = pcall(function()
186
+ instance:Destroy()
187
+ end)
188
+
189
+ if not ok then
190
+ return { success = false, error = "Failed to delete: " .. tostring(err) }
191
+ end
192
+
193
+ return { success = true }
194
+ end
195
+
196
+ function Explorer.searchScripts(query, maxResults)
197
+ maxResults = maxResults or 20
198
+ local results = {}
199
+ local queryLower = string.lower(query)
200
+
201
+ local function searchIn(instance)
202
+ if #results >= maxResults then
203
+ return
204
+ end
205
+
206
+ if SCRIPT_CLASSES[instance.ClassName] then
207
+ local ok, source = pcall(function()
208
+ return ScriptEditorService:GetEditorSource(instance)
209
+ end)
210
+
211
+ if not ok then
212
+ ok, source = pcall(function() return instance.Source end)
213
+ end
214
+
215
+ if ok and source then
216
+ local matches = {}
217
+ local lineNum = 0
218
+ for line in source:gmatch("[^\n]+") do
219
+ lineNum = lineNum + 1
220
+ if string.find(string.lower(line), queryLower, 1, true) then
221
+ table.insert(matches, { line = lineNum, text = line })
222
+ if #matches >= 5 then
223
+ break
224
+ end
225
+ end
226
+ end
227
+
228
+ if #matches > 0 then
229
+ table.insert(results, {
230
+ path = Explorer.getPath(instance),
231
+ className = instance.ClassName,
232
+ matches = matches,
233
+ })
234
+ end
235
+ end
236
+ end
237
+
238
+ for _, child in instance:GetChildren() do
239
+ if #results >= maxResults then
240
+ return
241
+ end
242
+ pcall(searchIn, child)
243
+ end
244
+ end
245
+
246
+ pcall(searchIn, game)
247
+
248
+ return { results = results }
249
+ end
250
+
251
+ return Explorer