@adiholick/nvstudio-mcp 2.4.0 → 2.4.2

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.
@@ -153,7 +153,12 @@ function syncRuntimeAndPlugins() {
153
153
  if (fs_1.default.existsSync(publicSrc)) {
154
154
  fs_1.default.cpSync(publicSrc, publicDest, { recursive: true, force: true });
155
155
  }
156
- console.log(`[Build] ✅ Berhasil menyinkronkan runtime ${nvRuntimeDir} (dist, public, studio-plugin, src)`);
156
+ const dataSrc = path_1.default.join(rootDir, 'data');
157
+ const dataDest = path_1.default.join(nvRuntimeDir, 'data');
158
+ if (fs_1.default.existsSync(dataSrc)) {
159
+ fs_1.default.cpSync(dataSrc, dataDest, { recursive: true, force: true });
160
+ }
161
+ console.log(`[Build] ✅ Berhasil menyinkronkan runtime ${nvRuntimeDir} (dist, public, studio-plugin, src, data)`);
157
162
  }
158
163
  catch (err) {
159
164
  console.warn(`[Build] Gagal menyinkronkan ke ~/.nvstudio-mcp: ${err.message}`);
@@ -11,6 +11,7 @@ const path_1 = __importDefault(require("path"));
11
11
  const uuid_1 = require("uuid");
12
12
  const DATA_DIR = path_1.default.join(process.cwd(), 'data');
13
13
  const DB_FILE = path_1.default.join(DATA_DIR, 'vfx-database.json');
14
+ const BUNDLED_DB_FILE = path_1.default.join(__dirname, '..', 'data', 'vfx-database.json');
14
15
  // ── Default Seed Presets ───────────────────────────────────────────────────────
15
16
  const DEFAULT_PRESETS = [
16
17
  {
@@ -408,9 +409,13 @@ class VfxDatabase {
408
409
  }
409
410
  }
410
411
  loadDatabase() {
411
- if (fs_1.default.existsSync(DB_FILE)) {
412
+ let targetFile = DB_FILE;
413
+ if (!fs_1.default.existsSync(targetFile) && fs_1.default.existsSync(BUNDLED_DB_FILE)) {
414
+ targetFile = BUNDLED_DB_FILE;
415
+ }
416
+ if (fs_1.default.existsSync(targetFile)) {
412
417
  try {
413
- const raw = fs_1.default.readFileSync(DB_FILE, 'utf-8');
418
+ const raw = fs_1.default.readFileSync(targetFile, 'utf-8');
414
419
  const list = JSON.parse(raw);
415
420
  for (const item of list) {
416
421
  item.category = normalizeVfxCategory(item.category);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adiholick/nvstudio-mcp",
3
- "version": "2.4.0",
3
+ "version": "2.4.2",
4
4
  "description": "Local Bridge Server MCP for Roblox Studio with Animation, VFX, and Rigging Engines",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -10,7 +10,8 @@
10
10
  "dist",
11
11
  "public",
12
12
  "studio-plugin",
13
- "agent-plugin"
13
+ "agent-plugin",
14
+ "data"
14
15
  ],
15
16
  "scripts": {
16
17
  "build": "tsc && npm run build:plugin",
package/public/index.html CHANGED
@@ -1156,7 +1156,7 @@
1156
1156
  </nav>
1157
1157
 
1158
1158
  <div class="sidebar-footer">
1159
- <span class="badge-v2" id="pkg-version">v2.4.0</span>
1159
+ <span class="badge-v2" id="pkg-version">v2.4.2</span>
1160
1160
  <span style="font-size:10px; opacity:0.6;">Model Context Protocol</span>
1161
1161
  </div>
1162
1162
  </aside>
@@ -1484,7 +1484,7 @@
1484
1484
  <div class="page" id="page-about">
1485
1485
  <div class="about-section">
1486
1486
  <div class="about-hero">
1487
- <h2>nvstudio-mcp <span class="v2-chip" id="about-version-chip">v2.4.0</span></h2>
1487
+ <h2>nvstudio-mcp <span class="v2-chip" id="about-version-chip">v2.4.2</span></h2>
1488
1488
  <p>Jembatan pintar berbasis <strong>Model Context Protocol (MCP)</strong> yang menghubungkan AI Agent (Antigravity IDE, Cursor, Claude Desktop, Windsurf) secara langsung ke dalam <strong>Roblox Studio</strong>.</p>
1489
1489
  <div class="about-links">
1490
1490
  <a class="about-link" href="https://github.com/Adiholick/nvstudio-mcp" target="_blank">
@@ -1499,7 +1499,7 @@
1499
1499
  </div>
1500
1500
 
1501
1501
  <div class="about-card">
1502
- <h3>🚀 Fitur Baru v2.4.0</h3>
1502
+ <h3>🚀 Fitur Baru v2.4.2</h3>
1503
1503
  <ul>
1504
1504
  <li><strong>🦴 NV-Rig Engine:</strong> Rigging headless presisi $O(1)$ untuk R6, R15, dan Custom Rig. Menyediakan inspeksi sendi (<code>inspect_rig</code>), pemindahan poros C0/C1 simultan anti-dislokasi (<code>edit_rig_joint</code>), auto-rigging instan (<code>auto_rig</code>), dan assembly welding senjata/prop (<code>weld_assembly</code>).</li>
1505
1505
  <li><strong>🎬 NV-Animation Engine:</strong> Pembuatan animasi karakter halus alami (Walk, Slash, Punch, Idle, IK) langsung menjadi <code>KeyframeSequence</code> resmi dengan interpolasi Bezier (Cubic/Quad) dan penegakan batas anatomis aman tanpa glitch.</li>
@@ -1,5 +1,5 @@
1
1
  -- ══════════════════════════════════════════════════════════════════════
2
- -- NVStudio MCP Plugin v2.4.0
2
+ -- NVStudio MCP Plugin v2.4.2
3
3
  -- Arsitektur: Dual-Mode WebSocket Duplex (Port 3055/ws) + Fallback Long-Polling
4
4
  -- Plugin auto-connect saat dimuat via WebSocket native, dengan fallback otomatis
5
5
  -- ke HTTP stream jika WebSocket tidak tersedia di environment Roblox Studio ini.
@@ -162,7 +162,7 @@ local function addSystemLog(msg, msgType)
162
162
  local fullMsg = prefix .. msg
163
163
  table.insert(ctx.recentLogs, fullMsg)
164
164
  if #ctx.recentLogs > MAX_LOGS then table.remove(ctx.recentLogs, 1) end
165
- if ui then ui:addLog(fullMsg, color) end
165
+ if ui then pcall(function() ui:addLog(fullMsg, color) end) end
166
166
  end
167
167
  LogService.MessageOut:Connect(addSystemLog)
168
168
 
@@ -237,8 +237,14 @@ local function processTask(taskData)
237
237
  result.id = taskData.id
238
238
 
239
239
  if ui then
240
- local color = result.status == "success" and Color3.fromRGB(100, 255, 100) or Color3.fromRGB(255, 100, 100)
241
- ui:addLog("[AI Result] " .. tostring(result.result or result.error), color)
240
+ pcall(function()
241
+ local color = result.status == "success" and Color3.fromRGB(100, 255, 100) or Color3.fromRGB(255, 100, 100)
242
+ local summary = tostring(result.result or result.error or "")
243
+ if #summary > 500 then
244
+ summary = string.sub(summary, 1, 500) .. " ... [Output besar]"
245
+ end
246
+ ui:addLog("[AI Result] " .. summary, color)
247
+ end)
242
248
  end
243
249
 
244
250
  return result
@@ -976,7 +976,7 @@ end
976
976
  <BinaryString name="Tags"></BinaryString>
977
977
  <token name="RunContext">0</token>
978
978
  <ProtectedString name="Source"><![CDATA[-- ══════════════════════════════════════════════════════════════════════
979
- -- NVStudio MCP Plugin v2.4.0
979
+ -- NVStudio MCP Plugin v2.4.2
980
980
  -- Arsitektur: Dual-Mode WebSocket Duplex (Port 3055/ws) + Fallback Long-Polling
981
981
  -- Plugin auto-connect saat dimuat via WebSocket native, dengan fallback otomatis
982
982
  -- ke HTTP stream jika WebSocket tidak tersedia di environment Roblox Studio ini.
@@ -1139,7 +1139,7 @@ local function addSystemLog(msg, msgType)
1139
1139
  local fullMsg = prefix .. msg
1140
1140
  table.insert(ctx.recentLogs, fullMsg)
1141
1141
  if #ctx.recentLogs > MAX_LOGS then table.remove(ctx.recentLogs, 1) end
1142
- if ui then ui:addLog(fullMsg, color) end
1142
+ if ui then pcall(function() ui:addLog(fullMsg, color) end) end
1143
1143
  end
1144
1144
  LogService.MessageOut:Connect(addSystemLog)
1145
1145
 
@@ -1214,8 +1214,14 @@ local function processTask(taskData)
1214
1214
  result.id = taskData.id
1215
1215
 
1216
1216
  if ui then
1217
- local color = result.status == "success" and Color3.fromRGB(100, 255, 100) or Color3.fromRGB(255, 100, 100)
1218
- ui:addLog("[AI Result] " .. tostring(result.result or result.error), color)
1217
+ pcall(function()
1218
+ local color = result.status == "success" and Color3.fromRGB(100, 255, 100) or Color3.fromRGB(255, 100, 100)
1219
+ local summary = tostring(result.result or result.error or "")
1220
+ if #summary > 500 then
1221
+ summary = string.sub(summary, 1, 500) .. " ... [Output besar]"
1222
+ end
1223
+ ui:addLog("[AI Result] " .. summary, color)
1224
+ end)
1219
1225
  end
1220
1226
 
1221
1227
  return result
@@ -5584,7 +5590,7 @@ function UIManager.init(pluginInstance, studioId)
5584
5590
 
5585
5591
  -- Version
5586
5592
  local versionLabel = Instance.new("TextLabel")
5587
- versionLabel.Text = "v2.4.0"
5593
+ versionLabel.Text = "v2.4.2"
5588
5594
  versionLabel.Font = Enum.Font.Gotham
5589
5595
  versionLabel.TextSize = 11
5590
5596
  versionLabel.TextColor3 = Color3.fromRGB(120, 120, 130)
@@ -5847,8 +5853,14 @@ end
5847
5853
  -- Menambahkan baris log baru ke terminal GUI
5848
5854
  -- ═══════════════════════════════════════════
5849
5855
  function UIManager:addLog(text, color)
5856
+ local rawText = tostring(text or "")
5857
+ local MAX_LOG_LENGTH = 1000
5858
+ if #rawText > MAX_LOG_LENGTH then
5859
+ rawText = string.sub(rawText, 1, MAX_LOG_LENGTH) .. " ... [Terpotong " .. tostring(#rawText - MAX_LOG_LENGTH) .. " karakter]"
5860
+ end
5861
+
5850
5862
  local timestamp = os.date("%H:%M:%S")
5851
- local displayText = "[" .. timestamp .. "] " .. text
5863
+ local displayText = "[" .. timestamp .. "] " .. rawText
5852
5864
 
5853
5865
  local logLabel = Instance.new("TextLabel")
5854
5866
  logLabel.Text = displayText
@@ -95,7 +95,7 @@ function UIManager.init(pluginInstance, studioId)
95
95
 
96
96
  -- Version
97
97
  local versionLabel = Instance.new("TextLabel")
98
- versionLabel.Text = "v2.4.0"
98
+ versionLabel.Text = "v2.4.2"
99
99
  versionLabel.Font = Enum.Font.Gotham
100
100
  versionLabel.TextSize = 11
101
101
  versionLabel.TextColor3 = Color3.fromRGB(120, 120, 130)
@@ -358,8 +358,14 @@ end
358
358
  -- Menambahkan baris log baru ke terminal GUI
359
359
  -- ═══════════════════════════════════════════
360
360
  function UIManager:addLog(text, color)
361
+ local rawText = tostring(text or "")
362
+ local MAX_LOG_LENGTH = 1000
363
+ if #rawText > MAX_LOG_LENGTH then
364
+ rawText = string.sub(rawText, 1, MAX_LOG_LENGTH) .. " ... [Terpotong " .. tostring(#rawText - MAX_LOG_LENGTH) .. " karakter]"
365
+ end
366
+
361
367
  local timestamp = os.date("%H:%M:%S")
362
- local displayText = "[" .. timestamp .. "] " .. text
368
+ local displayText = "[" .. timestamp .. "] " .. rawText
363
369
 
364
370
  local logLabel = Instance.new("TextLabel")
365
371
  logLabel.Text = displayText