dominus-cli 0.2.1 → 0.5.1

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.
package/dist/mcp.js CHANGED
@@ -29,6 +29,7 @@ var CliMsg = {
29
29
  SET_SCRIPT: "cli:set:script",
30
30
  RUN_CODE: "cli:run",
31
31
  GET_PROPERTIES: "cli:get:properties",
32
+ GET_DESCENDANTS_PROPERTIES: "cli:get:descendants:properties",
32
33
  SET_PROPERTIES: "cli:set:properties",
33
34
  INSERT_INSTANCE: "cli:insert",
34
35
  DELETE_INSTANCE: "cli:delete",
@@ -689,6 +690,19 @@ async function startMcpServer() {
689
690
  return { content: [{ type: "text", text: JSON.stringify(res.payload, null, 2) }] };
690
691
  }
691
692
  );
693
+ mcp.tool(
694
+ "get_descendants_properties",
695
+ "Easily get all descendants of a UI instance (or any instance) and all of their properties.",
696
+ {
697
+ path: z.string().describe('Full instance path (e.g., "Workspace.Part", "StarterGui.ScreenGui")'),
698
+ outputFile: z.string().optional().describe("Optional file path to write to prevent limit errors/timeouts")
699
+ },
700
+ async ({ path: path2, outputFile }) => {
701
+ assertConnected();
702
+ const res = await bridge.sendRequest(CliMsg.GET_DESCENDANTS_PROPERTIES, { path: path2, outputFile }, 1e3 * 60 * 5);
703
+ return { content: [{ type: "text", text: JSON.stringify(res.payload, null, 2) }] };
704
+ }
705
+ );
692
706
  mcp.tool(
693
707
  "set_properties",
694
708
  "Set properties on an instance in Roblox Studio",
@@ -788,13 +802,14 @@ async function startMcpServer() {
788
802
  parent: z.string().optional().describe('Parent: "StarterGui", "PlayerGui", or path. Default: StarterGui'),
789
803
  tree: z.record(z.unknown()).describe(
790
804
  'Root UI node: {ClassName, Name, properties..., Children: [{...}, ...]}. UDim2 as [xScale, xOffset, yScale, yOffset], Color3 as "#hex", Font as "GothamBold"'
791
- )
805
+ ),
806
+ animate: z.boolean().optional().describe("If true, task.wait() will be injected between creation of nodes so that the UI writes out dynamically.")
792
807
  },
793
- async ({ parent, tree }) => {
808
+ async ({ parent, tree, animate }) => {
794
809
  assertConnected();
795
810
  const res = await bridge.sendRequest(
796
811
  CliMsg.BUILD_UI,
797
- { parent: parent ?? "StarterGui", tree }
812
+ { parent: parent ?? "StarterGui", tree, animate }
798
813
  );
799
814
  return { content: [{ type: "text", text: JSON.stringify(res.payload, null, 2) }] };
800
815
  }
package/dist/mcp.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/transport/protocol.ts","../src/transport/ws-server.ts","../src/transport/ws-client.ts","../src/config/config.ts","../src/memory/store.ts","../src/mcp/server.ts","../src/mcp/index.ts"],"names":["EventEmitter","WebSocket","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 { WebSocket } from 'ws';\r\nimport { EventEmitter } from 'node:events';\r\nimport {\r\n parseMessage,\r\n serializeMessage,\r\n createMessage,\r\n StudioMsg,\r\n type WsMessage,\r\n type StudioConnectedPayload,\r\n} from './protocol.js';\r\nimport type { StudioBridge, StudioConnection } from './ws-server.js';\r\n\r\n/**\r\n * Connects as a relay client to an existing DominusServer.\r\n * Has the same interface as DominusServer so the TUI/Agent\r\n * can use either transparently.\r\n */\r\nexport class DominusClient extends EventEmitter implements StudioBridge {\r\n private ws: WebSocket | null = null;\r\n private port: number;\r\n private studioConnected = false;\r\n private connectionInfo: Omit<StudioConnection, 'ws'> | null = null;\r\n private pendingRequests = new Map<\r\n string,\r\n { resolve: (msg: WsMessage) => void; reject: (err: Error) => void; timer: ReturnType<typeof setTimeout> }\r\n >();\r\n\r\n constructor(port = 18088) {\r\n super();\r\n this.port = port;\r\n }\r\n\r\n connect(): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n const url = `ws://localhost:${this.port}`;\r\n const ws = new WebSocket(url);\r\n\r\n ws.on('open', () => {\r\n this.ws = ws;\r\n ws.send(serializeMessage(createMessage('controller:connect', {})));\r\n this.emit('server:started', { port: this.port, relay: true });\r\n resolve();\r\n });\r\n\r\n ws.on('message', (raw) => {\r\n try {\r\n const msg = parseMessage(raw.toString());\r\n this.handleMessage(msg);\r\n } catch (err) {\r\n this.emit('server:error', err);\r\n }\r\n });\r\n\r\n ws.on('close', () => {\r\n this.ws = null;\r\n this.studioConnected = false;\r\n this.emit('studio:disconnected');\r\n for (const [id, pending] of this.pendingRequests) {\r\n clearTimeout(pending.timer);\r\n pending.reject(new Error('Relay connection lost'));\r\n this.pendingRequests.delete(id);\r\n }\r\n });\r\n\r\n ws.on('error', (err) => {\r\n if (!this.ws) reject(err);\r\n this.emit('server:error', err);\r\n });\r\n });\r\n }\r\n\r\n private handleMessage(msg: WsMessage): void {\r\n if (msg.type === 'controller:welcome') {\r\n const p = msg.payload as { studioConnected: boolean };\r\n this.studioConnected = p.studioConnected;\r\n if (this.studioConnected) {\r\n this.emit('studio:connected', {});\r\n }\r\n return;\r\n }\r\n\r\n if (msg.type === 'studio:connected') {\r\n this.studioConnected = true;\r\n const payload = msg.payload as StudioConnectedPayload;\r\n this.connectionInfo = {\r\n connectedAt: Date.now(),\r\n studioVersion: payload.studioVersion,\r\n placeId: payload.placeId,\r\n placeName: payload.placeName,\r\n };\r\n this.emit('studio:connected', payload);\r\n return;\r\n }\r\n\r\n if (msg.type === 'studio:disconnected') {\r\n this.studioConnected = false;\r\n this.connectionInfo = null;\r\n this.emit('studio:disconnected');\r\n return;\r\n }\r\n\r\n if (msg.type === StudioMsg.RESPONSE) {\r\n const pending = this.pendingRequests.get(msg.id);\r\n if (pending) {\r\n clearTimeout(pending.timer);\r\n pending.resolve(msg);\r\n this.pendingRequests.delete(msg.id);\r\n }\r\n return;\r\n }\r\n\r\n this.emit(msg.type, msg.payload);\r\n this.emit('message', msg);\r\n }\r\n\r\n sendRequest<T = unknown>(type: string, payload: unknown, timeoutMs = 10000): Promise<WsMessage<T>> {\r\n return new Promise((resolve, reject) => {\r\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\r\n reject(new Error('Not connected to Dominus server'));\r\n return;\r\n }\r\n if (!this.studioConnected) {\r\n reject(new Error('Studio not connected'));\r\n return;\r\n }\r\n\r\n const msg = createMessage(type, payload);\r\n\r\n const timer = setTimeout(() => {\r\n this.pendingRequests.delete(msg.id);\r\n reject(new Error(`Request timed out: ${type}`));\r\n }, timeoutMs);\r\n\r\n this.pendingRequests.set(msg.id, {\r\n resolve: resolve as (msg: WsMessage) => void,\r\n reject,\r\n timer,\r\n });\r\n\r\n this.ws.send(serializeMessage(msg));\r\n });\r\n }\r\n\r\n sendNotification(type: string, payload: unknown): void {\r\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;\r\n const msg = createMessage(type, payload);\r\n this.ws.send(serializeMessage(msg));\r\n }\r\n\r\n isConnected(): boolean {\r\n return this.studioConnected;\r\n }\r\n\r\n getConnectionInfo(): StudioConnection | null {\r\n if (!this.connectionInfo) return null;\r\n return { ...this.connectionInfo, ws: this.ws! } as StudioConnection;\r\n }\r\n\r\n getPort(): number {\r\n return this.port;\r\n }\r\n\r\n stop(): Promise<void> {\r\n return new Promise((resolve) => {\r\n for (const [, pending] of this.pendingRequests) {\r\n clearTimeout(pending.timer);\r\n pending.reject(new Error('Client shutting down'));\r\n }\r\n this.pendingRequests.clear();\r\n if (this.ws) {\r\n this.ws.close();\r\n this.ws = null;\r\n }\r\n resolve();\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * Check if a Dominus server is already running on the given port.\r\n */\r\nexport async function isPortInUse(port: number): Promise<boolean> {\r\n return new Promise((resolve) => {\r\n const ws = new WebSocket(`ws://localhost:${port}`);\r\n const timer = setTimeout(() => {\r\n ws.close();\r\n resolve(false);\r\n }, 1000);\r\n\r\n ws.on('open', () => {\r\n clearTimeout(timer);\r\n ws.close();\r\n resolve(true);\r\n });\r\n\r\n ws.on('error', () => {\r\n clearTimeout(timer);\r\n resolve(false);\r\n });\r\n });\r\n}\r\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, type StudioBridge } from '../transport/ws-server.js';\r\nimport { DominusClient, isPortInUse } from '../transport/ws-client.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 bridge: StudioBridge;\r\n\r\nexport async function startMcpServer(): Promise<void> {\r\n const config = loadConfig();\r\n await initMemoryStore();\r\n\r\n const portTaken = await isPortInUse(config.port);\r\n if (portTaken) {\r\n const client = new DominusClient(config.port);\r\n await client.connect();\r\n bridge = client;\r\n } else {\r\n const server = new DominusServer(config.port);\r\n await server.start();\r\n bridge = server;\r\n }\r\n\r\n const mcp = new McpServer({\r\n name: 'dominus',\r\n version: '0.2.1',\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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 = bridge.getConnectionInfo();\r\n return {\r\n contents: [{\r\n uri: 'studio://status',\r\n text: JSON.stringify({\r\n connected: bridge.isConnected(),\r\n placeName: info?.placeName,\r\n placeId: info?.placeId,\r\n studioVersion: info?.studioVersion,\r\n port: bridge.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 (!bridge.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"]}
1
+ {"version":3,"sources":["../src/transport/protocol.ts","../src/transport/ws-server.ts","../src/transport/ws-client.ts","../src/config/config.ts","../src/memory/store.ts","../src/mcp/server.ts","../src/mcp/index.ts"],"names":["EventEmitter","WebSocket","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 GET_DESCENDANTS_PROPERTIES: 'cli:get:descendants: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 SERIALIZE_UI: 'cli:serialize:ui',\r\n MOVE_INSTANCE: 'cli:move:instance',\r\n UNDO: 'cli:undo',\r\n REDO: 'cli:redo',\r\n BULK_SET_PROPERTIES: 'cli:bulk:set:properties',\r\n FIND_REPLACE_SCRIPTS: 'cli:find:replace:scripts',\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 { WebSocket } from 'ws';\r\nimport { EventEmitter } from 'node:events';\r\nimport {\r\n parseMessage,\r\n serializeMessage,\r\n createMessage,\r\n StudioMsg,\r\n type WsMessage,\r\n type StudioConnectedPayload,\r\n} from './protocol.js';\r\nimport type { StudioBridge, StudioConnection } from './ws-server.js';\r\n\r\n/**\r\n * Connects as a relay client to an existing DominusServer.\r\n * Has the same interface as DominusServer so the TUI/Agent\r\n * can use either transparently.\r\n */\r\nexport class DominusClient extends EventEmitter implements StudioBridge {\r\n private ws: WebSocket | null = null;\r\n private port: number;\r\n private studioConnected = false;\r\n private connectionInfo: Omit<StudioConnection, 'ws'> | null = null;\r\n private pendingRequests = new Map<\r\n string,\r\n { resolve: (msg: WsMessage) => void; reject: (err: Error) => void; timer: ReturnType<typeof setTimeout> }\r\n >();\r\n\r\n constructor(port = 18088) {\r\n super();\r\n this.port = port;\r\n }\r\n\r\n connect(): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n const url = `ws://localhost:${this.port}`;\r\n const ws = new WebSocket(url);\r\n\r\n ws.on('open', () => {\r\n this.ws = ws;\r\n ws.send(serializeMessage(createMessage('controller:connect', {})));\r\n this.emit('server:started', { port: this.port, relay: true });\r\n resolve();\r\n });\r\n\r\n ws.on('message', (raw) => {\r\n try {\r\n const msg = parseMessage(raw.toString());\r\n this.handleMessage(msg);\r\n } catch (err) {\r\n this.emit('server:error', err);\r\n }\r\n });\r\n\r\n ws.on('close', () => {\r\n this.ws = null;\r\n this.studioConnected = false;\r\n this.emit('studio:disconnected');\r\n for (const [id, pending] of this.pendingRequests) {\r\n clearTimeout(pending.timer);\r\n pending.reject(new Error('Relay connection lost'));\r\n this.pendingRequests.delete(id);\r\n }\r\n });\r\n\r\n ws.on('error', (err) => {\r\n if (!this.ws) reject(err);\r\n this.emit('server:error', err);\r\n });\r\n });\r\n }\r\n\r\n private handleMessage(msg: WsMessage): void {\r\n if (msg.type === 'controller:welcome') {\r\n const p = msg.payload as { studioConnected: boolean };\r\n this.studioConnected = p.studioConnected;\r\n if (this.studioConnected) {\r\n this.emit('studio:connected', {});\r\n }\r\n return;\r\n }\r\n\r\n if (msg.type === 'studio:connected') {\r\n this.studioConnected = true;\r\n const payload = msg.payload as StudioConnectedPayload;\r\n this.connectionInfo = {\r\n connectedAt: Date.now(),\r\n studioVersion: payload.studioVersion,\r\n placeId: payload.placeId,\r\n placeName: payload.placeName,\r\n };\r\n this.emit('studio:connected', payload);\r\n return;\r\n }\r\n\r\n if (msg.type === 'studio:disconnected') {\r\n this.studioConnected = false;\r\n this.connectionInfo = null;\r\n this.emit('studio:disconnected');\r\n return;\r\n }\r\n\r\n if (msg.type === StudioMsg.RESPONSE) {\r\n const pending = this.pendingRequests.get(msg.id);\r\n if (pending) {\r\n clearTimeout(pending.timer);\r\n pending.resolve(msg);\r\n this.pendingRequests.delete(msg.id);\r\n }\r\n return;\r\n }\r\n\r\n this.emit(msg.type, msg.payload);\r\n this.emit('message', msg);\r\n }\r\n\r\n sendRequest<T = unknown>(type: string, payload: unknown, timeoutMs = 10000): Promise<WsMessage<T>> {\r\n return new Promise((resolve, reject) => {\r\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\r\n reject(new Error('Not connected to Dominus server'));\r\n return;\r\n }\r\n if (!this.studioConnected) {\r\n reject(new Error('Studio not connected'));\r\n return;\r\n }\r\n\r\n const msg = createMessage(type, payload);\r\n\r\n const timer = setTimeout(() => {\r\n this.pendingRequests.delete(msg.id);\r\n reject(new Error(`Request timed out: ${type}`));\r\n }, timeoutMs);\r\n\r\n this.pendingRequests.set(msg.id, {\r\n resolve: resolve as (msg: WsMessage) => void,\r\n reject,\r\n timer,\r\n });\r\n\r\n this.ws.send(serializeMessage(msg));\r\n });\r\n }\r\n\r\n sendNotification(type: string, payload: unknown): void {\r\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;\r\n const msg = createMessage(type, payload);\r\n this.ws.send(serializeMessage(msg));\r\n }\r\n\r\n isConnected(): boolean {\r\n return this.studioConnected;\r\n }\r\n\r\n getConnectionInfo(): StudioConnection | null {\r\n if (!this.connectionInfo) return null;\r\n return { ...this.connectionInfo, ws: this.ws! } as StudioConnection;\r\n }\r\n\r\n getPort(): number {\r\n return this.port;\r\n }\r\n\r\n stop(): Promise<void> {\r\n return new Promise((resolve) => {\r\n for (const [, pending] of this.pendingRequests) {\r\n clearTimeout(pending.timer);\r\n pending.reject(new Error('Client shutting down'));\r\n }\r\n this.pendingRequests.clear();\r\n if (this.ws) {\r\n this.ws.close();\r\n this.ws = null;\r\n }\r\n resolve();\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * Check if a Dominus server is already running on the given port.\r\n */\r\nexport async function isPortInUse(port: number): Promise<boolean> {\r\n return new Promise((resolve) => {\r\n const ws = new WebSocket(`ws://localhost:${port}`);\r\n const timer = setTimeout(() => {\r\n ws.close();\r\n resolve(false);\r\n }, 1000);\r\n\r\n ws.on('open', () => {\r\n clearTimeout(timer);\r\n ws.close();\r\n resolve(true);\r\n });\r\n\r\n ws.on('error', () => {\r\n clearTimeout(timer);\r\n resolve(false);\r\n });\r\n });\r\n}\r\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, type StudioBridge } from '../transport/ws-server.js';\r\nimport { DominusClient, isPortInUse } from '../transport/ws-client.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 bridge: StudioBridge;\r\n\r\nexport async function startMcpServer(): Promise<void> {\r\n const config = loadConfig();\r\n await initMemoryStore();\r\n\r\n const portTaken = await isPortInUse(config.port);\r\n if (portTaken) {\r\n const client = new DominusClient(config.port);\r\n await client.connect();\r\n bridge = client;\r\n } else {\r\n const server = new DominusServer(config.port);\r\n await server.start();\r\n bridge = server;\r\n }\r\n\r\n const mcp = new McpServer({\r\n name: 'dominus',\r\n version: '0.2.1',\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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 'get_descendants_properties',\r\n 'Easily get all descendants of a UI instance (or any instance) and all of their properties.',\r\n { \r\n path: z.string().describe('Full instance path (e.g., \"Workspace.Part\", \"StarterGui.ScreenGui\")'),\r\n outputFile: z.string().optional().describe('Optional file path to write to prevent limit errors/timeouts'),\r\n },\r\n async ({ path, outputFile }) => {\r\n assertConnected();\r\n const res = await bridge.sendRequest<unknown>(CliMsg.GET_DESCENDANTS_PROPERTIES, { path, outputFile }, 1000 * 60 * 5);\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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 animate: z.boolean().optional().describe('If true, task.wait() will be injected between creation of nodes so that the UI writes out dynamically.'),\r\n },\r\n async ({ parent, tree, animate }) => {\r\n assertConnected();\r\n const res = await bridge.sendRequest<{ success: boolean; path?: string; instanceCount?: number; error?: string }>(\r\n CliMsg.BUILD_UI, { parent: parent ?? 'StarterGui', tree, animate },\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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 bridge.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 = bridge.getConnectionInfo();\r\n return {\r\n contents: [{\r\n uri: 'studio://status',\r\n text: JSON.stringify({\r\n connected: bridge.isConnected(),\r\n placeName: info?.placeName,\r\n placeId: info?.placeId,\r\n studioVersion: info?.studioVersion,\r\n port: bridge.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 (!bridge.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dominus-cli",
3
- "version": "0.2.1",
3
+ "version": "0.5.1",
4
4
  "description": "AI-powered autonomous agent for Roblox Studio development. Real-time WebSocket bridge, persistent memory, and intelligent tool use.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -8,20 +8,6 @@
8
8
  "dominus-mcp": "./dist/mcp.js"
9
9
  },
10
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
11
  "dependencies": {
26
12
  "@modelcontextprotocol/sdk": "^1.27.0",
27
13
  "chalk": "^5.4.1",
@@ -42,6 +28,7 @@
42
28
  "@types/react": "^18.3.0",
43
29
  "@types/ws": "^8.5.0",
44
30
  "@vitest/coverage-v8": "^2.1.0",
31
+ "nodemon": "^3.1.14",
45
32
  "prettier": "^3.4.0",
46
33
  "tsup": "^8.3.0",
47
34
  "tsx": "^4.19.0",
@@ -74,5 +61,19 @@
74
61
  "repository": {
75
62
  "type": "git",
76
63
  "url": "https://github.com/eli/dominus"
64
+ },
65
+ "scripts": {
66
+ "dev": "tsx src/index.tsx",
67
+ "dev:mcp": "nodemon --watch src -e ts,tsx --exec \"pnpm run build && node dist/mcp.js\"",
68
+ "build": "tsup",
69
+ "build:plugin": "rojo build plugin/default.project.json -o plugin/Dominus.rbxm",
70
+ "start": "node dist/index.js",
71
+ "test": "vitest run",
72
+ "test:watch": "vitest",
73
+ "test:coverage": "vitest run --coverage",
74
+ "lint": "prettier --check .",
75
+ "format": "prettier --write .",
76
+ "typecheck": "tsc --noEmit",
77
+ "install-plugin": "tsx src/install-plugin.ts"
77
78
  }
78
- }
79
+ }
Binary file
@@ -45,6 +45,7 @@ function Executor.run(code)
45
45
  typeof = typeof,
46
46
  Instance = Instance,
47
47
  Enum = Enum,
48
+ Vector2 = Vector2,
48
49
  Vector3 = Vector3,
49
50
  CFrame = CFrame,
50
51
  Color3 = Color3,