@trops/dash-core 0.1.47 → 0.1.48

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.
@@ -22,6 +22,7 @@ var require$$2$4 = require('algoliasearch');
22
22
  var require$$3$2 = require('node:path');
23
23
  var require$$0$3 = require('openai');
24
24
  require('live-plugin-manager');
25
+ var require$$0$4 = require('@anthropic-ai/sdk');
25
26
  var require$$2$6 = require('os');
26
27
  var require$$3$3 = require('adm-zip');
27
28
  var require$$4$1 = require('url');
@@ -513,6 +514,36 @@ var openaiEvents$1 = {
513
514
  OPENAI_DESCRIBE_IMAGE_ERROR,
514
515
  };
515
516
 
517
+ /**
518
+ * Event Constants File - LLM Events
519
+ *
520
+ * This file contains event constants for LLM (Large Language Model)
521
+ * chat IPC communication — streaming, tool-use, and lifecycle.
522
+ */
523
+
524
+ // --- Renderer → Main (invoke) ---
525
+ const LLM_SEND_MESSAGE$1 = "llm-send-message";
526
+ const LLM_ABORT_REQUEST$1 = "llm-abort-request";
527
+ const LLM_LIST_CONNECTED_TOOLS$1 = "llm-list-connected-tools";
528
+
529
+ // --- Main → Renderer (send) ---
530
+ const LLM_STREAM_DELTA$2 = "llm-stream-delta";
531
+ const LLM_STREAM_TOOL_CALL$2 = "llm-stream-tool-call";
532
+ const LLM_STREAM_TOOL_RESULT$2 = "llm-stream-tool-result";
533
+ const LLM_STREAM_COMPLETE$2 = "llm-stream-complete";
534
+ const LLM_STREAM_ERROR$2 = "llm-stream-error";
535
+
536
+ var llmEvents$1 = {
537
+ LLM_SEND_MESSAGE: LLM_SEND_MESSAGE$1,
538
+ LLM_ABORT_REQUEST: LLM_ABORT_REQUEST$1,
539
+ LLM_LIST_CONNECTED_TOOLS: LLM_LIST_CONNECTED_TOOLS$1,
540
+ LLM_STREAM_DELTA: LLM_STREAM_DELTA$2,
541
+ LLM_STREAM_TOOL_CALL: LLM_STREAM_TOOL_CALL$2,
542
+ LLM_STREAM_TOOL_RESULT: LLM_STREAM_TOOL_RESULT$2,
543
+ LLM_STREAM_COMPLETE: LLM_STREAM_COMPLETE$2,
544
+ LLM_STREAM_ERROR: LLM_STREAM_ERROR$2,
545
+ };
546
+
516
547
  /**
517
548
  * Event Constants File - Client Cache Events
518
549
  *
@@ -550,6 +581,7 @@ const registryEvents = registryEvents$1;
550
581
  const algoliaEvents = algoliaEvents$1;
551
582
  const menuItemEvents = menuItemEvents$1;
552
583
  const openaiEvents = openaiEvents$1;
584
+ const llmEvents = llmEvents$1;
553
585
  const clientCacheEvents = clientCacheEvents$1;
554
586
 
555
587
  const publicEvents = {
@@ -571,6 +603,7 @@ var events$8 = {
571
603
  ...algoliaEvents,
572
604
  ...menuItemEvents,
573
605
  ...openaiEvents,
606
+ ...llmEvents,
574
607
  ...clientCacheEvents,
575
608
  };
576
609
 
@@ -4839,7 +4872,7 @@ function interpolate(template, credentials) {
4839
4872
  });
4840
4873
  }
4841
4874
 
4842
- const mcpController$1 = {
4875
+ const mcpController$2 = {
4843
4876
  /**
4844
4877
  * startServer
4845
4878
  * Start an MCP server with the given config and credentials
@@ -4877,7 +4910,7 @@ const mcpController$1 = {
4877
4910
  try {
4878
4911
  // Stop if in stale/error state
4879
4912
  if (activeServers.has(serverName)) {
4880
- await mcpController$1.stopServer(win, serverName);
4913
+ await mcpController$2.stopServer(win, serverName);
4881
4914
  }
4882
4915
 
4883
4916
  console.log(
@@ -5313,6 +5346,28 @@ const mcpController$1 = {
5313
5346
  }
5314
5347
  },
5315
5348
 
5349
+ /**
5350
+ * listConnectedServers
5351
+ * Returns all connected servers with their cached tool lists.
5352
+ * Used by llmController to discover available MCP tools.
5353
+ *
5354
+ * @returns {Array<{ serverName, tools, resources, status }>}
5355
+ */
5356
+ listConnectedServers: () => {
5357
+ const servers = [];
5358
+ for (const [serverName, server] of activeServers) {
5359
+ if (server.status === STATUS.CONNECTED) {
5360
+ servers.push({
5361
+ serverName,
5362
+ tools: server.tools || [],
5363
+ resources: server.resources || [],
5364
+ status: server.status,
5365
+ });
5366
+ }
5367
+ }
5368
+ return servers;
5369
+ },
5370
+
5316
5371
  /**
5317
5372
  * stopAllServers
5318
5373
  * Stop all running MCP servers (called on app quit)
@@ -5328,14 +5383,14 @@ const mcpController$1 = {
5328
5383
  );
5329
5384
  const promises = [];
5330
5385
  for (const [serverName] of activeServers) {
5331
- promises.push(mcpController$1.stopServer(null, serverName));
5386
+ promises.push(mcpController$2.stopServer(null, serverName));
5332
5387
  }
5333
5388
  await Promise.allSettled(promises);
5334
5389
  console.log("[mcpController] All servers stopped");
5335
5390
  },
5336
5391
  };
5337
5392
 
5338
- var mcpController_1 = mcpController$1;
5393
+ var mcpController_1 = mcpController$2;
5339
5394
 
5340
5395
  /**
5341
5396
  * registryController.js
@@ -6262,6 +6317,316 @@ const pluginController$1 = {
6262
6317
 
6263
6318
  var pluginController_1 = pluginController$1;
6264
6319
 
6320
+ /**
6321
+ * llmController.js
6322
+ *
6323
+ * Manages LLM chat interactions in the main process.
6324
+ * Streams responses from Anthropic's Messages API, handles tool-use loops
6325
+ * by calling MCP tools via mcpController, and supports request cancellation.
6326
+ *
6327
+ * Conversation state lives in the renderer — this controller is stateless
6328
+ * per-request, receiving the full messages array each time.
6329
+ */
6330
+
6331
+ const Anthropic = require$$0$4;
6332
+ const mcpController$1 = mcpController_1;
6333
+ const {
6334
+ LLM_STREAM_DELTA: LLM_STREAM_DELTA$1,
6335
+ LLM_STREAM_TOOL_CALL: LLM_STREAM_TOOL_CALL$1,
6336
+ LLM_STREAM_TOOL_RESULT: LLM_STREAM_TOOL_RESULT$1,
6337
+ LLM_STREAM_COMPLETE: LLM_STREAM_COMPLETE$1,
6338
+ LLM_STREAM_ERROR: LLM_STREAM_ERROR$1,
6339
+ } = llmEvents$1;
6340
+
6341
+ /**
6342
+ * In-flight requests for cancellation support.
6343
+ * Map<requestId, AbortController>
6344
+ */
6345
+ const activeRequests = new Map();
6346
+
6347
+ /**
6348
+ * Default maximum tool-use rounds to prevent infinite loops.
6349
+ */
6350
+ const DEFAULT_MAX_TOOL_ROUNDS = 10;
6351
+
6352
+ /**
6353
+ * Convert MCP tool format to Anthropic tool format.
6354
+ * MCP: { name, description, inputSchema }
6355
+ * Anthropic: { name, description, input_schema }
6356
+ */
6357
+ function mcpToolToAnthropic(tool) {
6358
+ return {
6359
+ name: tool.name,
6360
+ description: tool.description || "",
6361
+ input_schema: tool.inputSchema || { type: "object", properties: {} },
6362
+ };
6363
+ }
6364
+
6365
+ /**
6366
+ * Extract text content from an MCP tool result.
6367
+ * MCP results can be { content: [{ type: "text", text: "..." }] } or plain strings.
6368
+ */
6369
+ function extractToolResultText(mcpResult) {
6370
+ if (!mcpResult) return "No result returned.";
6371
+ if (mcpResult.error) return `Error: ${mcpResult.message}`;
6372
+
6373
+ const result = mcpResult.result;
6374
+ if (!result) return "No result returned.";
6375
+
6376
+ // MCP standard: { content: [{ type, text }] }
6377
+ if (result.content && Array.isArray(result.content)) {
6378
+ return result.content
6379
+ .filter((c) => c.type === "text")
6380
+ .map((c) => c.text)
6381
+ .join("\n");
6382
+ }
6383
+
6384
+ // Plain string
6385
+ if (typeof result === "string") return result;
6386
+
6387
+ // Fallback: JSON stringify
6388
+ return JSON.stringify(result);
6389
+ }
6390
+
6391
+ const llmController$1 = {
6392
+ /**
6393
+ * sendMessage
6394
+ * Stream a response from the Anthropic Messages API with tool-use support.
6395
+ *
6396
+ * @param {BrowserWindow} win - the window to send stream events to
6397
+ * @param {string} requestId - unique ID for this request (for filtering + cancellation)
6398
+ * @param {object} params - { apiKey, model, messages, tools, toolServerMap, systemPrompt, maxToolRounds }
6399
+ */
6400
+ sendMessage: async (win, requestId, params) => {
6401
+ const {
6402
+ apiKey,
6403
+ model = "claude-sonnet-4-20250514",
6404
+ messages,
6405
+ tools = [],
6406
+ toolServerMap = {},
6407
+ systemPrompt,
6408
+ maxToolRounds = DEFAULT_MAX_TOOL_ROUNDS,
6409
+ } = params;
6410
+
6411
+ // Set up abort controller
6412
+ const abortController = new AbortController();
6413
+ activeRequests.set(requestId, abortController);
6414
+
6415
+ try {
6416
+ if (!apiKey) {
6417
+ throw new Error(
6418
+ "API key is required. Add an Anthropic provider in your dashboard settings.",
6419
+ );
6420
+ }
6421
+
6422
+ const client = new Anthropic({ apiKey });
6423
+
6424
+ // Convert MCP tools to Anthropic format
6425
+ const anthropicTools = tools.map(mcpToolToAnthropic);
6426
+
6427
+ // Build the conversation — mutable copy for tool-use loop
6428
+ let currentMessages = [...messages];
6429
+ let toolRound = 0;
6430
+
6431
+ while (toolRound <= maxToolRounds) {
6432
+ // Check for abort before each API call
6433
+ if (abortController.signal.aborted) {
6434
+ return;
6435
+ }
6436
+
6437
+ // Build request params
6438
+ const requestParams = {
6439
+ model,
6440
+ max_tokens: 8192,
6441
+ messages: currentMessages,
6442
+ stream: true,
6443
+ };
6444
+ if (systemPrompt) {
6445
+ requestParams.system = systemPrompt;
6446
+ }
6447
+ if (anthropicTools.length > 0) {
6448
+ requestParams.tools = anthropicTools;
6449
+ }
6450
+
6451
+ // Stream the response
6452
+ const stream = client.messages.stream(requestParams, {
6453
+ signal: abortController.signal,
6454
+ });
6455
+
6456
+ let responseContentBlocks = [];
6457
+ let stopReason = null;
6458
+
6459
+ // Collect text deltas and content blocks
6460
+ stream.on("text", (text) => {
6461
+ if (win && !win.isDestroyed()) {
6462
+ win.webContents.send(LLM_STREAM_DELTA$1, { requestId, text });
6463
+ }
6464
+ });
6465
+
6466
+ // Wait for the full message
6467
+ const finalMessage = await stream.finalMessage();
6468
+ responseContentBlocks = finalMessage.content;
6469
+ stopReason = finalMessage.stop_reason;
6470
+
6471
+ // Check for tool use
6472
+ const toolUseBlocks = responseContentBlocks.filter(
6473
+ (block) => block.type === "tool_use",
6474
+ );
6475
+
6476
+ if (stopReason === "end_turn" || toolUseBlocks.length === 0) {
6477
+ // Done — send complete event
6478
+ if (win && !win.isDestroyed()) {
6479
+ win.webContents.send(LLM_STREAM_COMPLETE$1, {
6480
+ requestId,
6481
+ content: responseContentBlocks,
6482
+ stopReason,
6483
+ usage: finalMessage.usage,
6484
+ });
6485
+ }
6486
+ return;
6487
+ }
6488
+
6489
+ // Tool use round
6490
+ toolRound++;
6491
+
6492
+ // Append assistant message with tool_use blocks
6493
+ currentMessages.push({
6494
+ role: "assistant",
6495
+ content: responseContentBlocks,
6496
+ });
6497
+
6498
+ // Execute each tool call
6499
+ const toolResults = [];
6500
+ for (const toolBlock of toolUseBlocks) {
6501
+ if (abortController.signal.aborted) return;
6502
+
6503
+ const serverName = toolServerMap[toolBlock.name];
6504
+
6505
+ // Notify renderer of tool call
6506
+ if (win && !win.isDestroyed()) {
6507
+ win.webContents.send(LLM_STREAM_TOOL_CALL$1, {
6508
+ requestId,
6509
+ toolUseId: toolBlock.id,
6510
+ toolName: toolBlock.name,
6511
+ serverName,
6512
+ input: toolBlock.input,
6513
+ });
6514
+ }
6515
+
6516
+ let resultText;
6517
+ let isError = false;
6518
+
6519
+ if (!serverName) {
6520
+ resultText = `Error: No MCP server found for tool "${toolBlock.name}". The server may have disconnected.`;
6521
+ isError = true;
6522
+ } else {
6523
+ try {
6524
+ const mcpResult = await mcpController$1.callTool(
6525
+ win,
6526
+ serverName,
6527
+ toolBlock.name,
6528
+ toolBlock.input,
6529
+ );
6530
+ if (mcpResult.error) {
6531
+ resultText = `Error: ${mcpResult.message}`;
6532
+ isError = true;
6533
+ } else {
6534
+ resultText = extractToolResultText(mcpResult);
6535
+ }
6536
+ } catch (err) {
6537
+ resultText = `Error calling tool: ${err.message}`;
6538
+ isError = true;
6539
+ }
6540
+ }
6541
+
6542
+ // Notify renderer of tool result
6543
+ if (win && !win.isDestroyed()) {
6544
+ win.webContents.send(LLM_STREAM_TOOL_RESULT$1, {
6545
+ requestId,
6546
+ toolUseId: toolBlock.id,
6547
+ toolName: toolBlock.name,
6548
+ result: resultText,
6549
+ isError,
6550
+ });
6551
+ }
6552
+
6553
+ toolResults.push({
6554
+ type: "tool_result",
6555
+ tool_use_id: toolBlock.id,
6556
+ content: resultText,
6557
+ is_error: isError,
6558
+ });
6559
+ }
6560
+
6561
+ // Append tool results as user message
6562
+ currentMessages.push({
6563
+ role: "user",
6564
+ content: toolResults,
6565
+ });
6566
+
6567
+ // Loop continues — next API call with tool results
6568
+ }
6569
+
6570
+ // Exceeded max tool rounds
6571
+ if (win && !win.isDestroyed()) {
6572
+ win.webContents.send(LLM_STREAM_ERROR$1, {
6573
+ requestId,
6574
+ error: `Exceeded maximum tool-use rounds (${maxToolRounds}). The assistant may be stuck in a loop.`,
6575
+ code: "MAX_TOOL_ROUNDS",
6576
+ });
6577
+ }
6578
+ } catch (error) {
6579
+ if (abortController.signal.aborted) {
6580
+ // Request was cancelled — not an error
6581
+ return;
6582
+ }
6583
+
6584
+ console.error(`[llmController] Error in sendMessage:`, error);
6585
+
6586
+ const errorPayload = {
6587
+ requestId,
6588
+ error: error.message || "Unknown error",
6589
+ code: error.status || error.code || "UNKNOWN",
6590
+ };
6591
+
6592
+ // Handle rate limiting
6593
+ if (error.status === 429) {
6594
+ errorPayload.code = "RATE_LIMITED";
6595
+ const retryAfter = error.headers?.["retry-after"];
6596
+ if (retryAfter) {
6597
+ errorPayload.retryAfter = parseInt(retryAfter, 10);
6598
+ }
6599
+ }
6600
+
6601
+ if (win && !win.isDestroyed()) {
6602
+ win.webContents.send(LLM_STREAM_ERROR$1, errorPayload);
6603
+ }
6604
+ } finally {
6605
+ activeRequests.delete(requestId);
6606
+ }
6607
+ },
6608
+
6609
+ /**
6610
+ * abortRequest
6611
+ * Cancel an in-flight LLM request.
6612
+ *
6613
+ * @param {BrowserWindow} win - the window (unused but kept for API consistency)
6614
+ * @param {string} requestId - the request to cancel
6615
+ * @returns {{ success: boolean }}
6616
+ */
6617
+ abortRequest: (win, requestId) => {
6618
+ const controller = activeRequests.get(requestId);
6619
+ if (controller) {
6620
+ controller.abort();
6621
+ activeRequests.delete(requestId);
6622
+ return { success: true };
6623
+ }
6624
+ return { success: false, message: "Request not found" };
6625
+ },
6626
+ };
6627
+
6628
+ var llmController_1 = llmController$1;
6629
+
6265
6630
  /**
6266
6631
  * clientFactories.js
6267
6632
  *
@@ -6392,7 +6757,7 @@ var controller = {
6392
6757
  searchIndex,
6393
6758
  };
6394
6759
 
6395
- const { ipcRenderer: ipcRenderer$g } = require$$0;
6760
+ const { ipcRenderer: ipcRenderer$h } = require$$0;
6396
6761
  const {
6397
6762
  SECURE_STORE_ENCRYPTION_CHECK,
6398
6763
  SECURE_STORE_SET_DATA,
@@ -6404,10 +6769,10 @@ const {
6404
6769
  */
6405
6770
  const secureStoreApi$2 = {
6406
6771
  isEncryptionAvailable: () =>
6407
- ipcRenderer$g.invoke(SECURE_STORE_ENCRYPTION_CHECK, {}),
6772
+ ipcRenderer$h.invoke(SECURE_STORE_ENCRYPTION_CHECK, {}),
6408
6773
  saveData: (key, value) =>
6409
- ipcRenderer$g.invoke(SECURE_STORE_SET_DATA, { key, value }),
6410
- getData: (key) => ipcRenderer$g.invoke(SECURE_STORE_GET_DATA, { key }),
6774
+ ipcRenderer$h.invoke(SECURE_STORE_SET_DATA, { key, value }),
6775
+ getData: (key) => ipcRenderer$h.invoke(SECURE_STORE_GET_DATA, { key }),
6411
6776
  };
6412
6777
 
6413
6778
  var secureStoreApi_1 = secureStoreApi$2;
@@ -6418,7 +6783,7 @@ var secureStoreApi_1 = secureStoreApi$2;
6418
6783
  * Handle the workspace configuration file
6419
6784
  */
6420
6785
 
6421
- const { ipcRenderer: ipcRenderer$f } = require$$0;
6786
+ const { ipcRenderer: ipcRenderer$g } = require$$0;
6422
6787
  const {
6423
6788
  WORKSPACE_LIST,
6424
6789
  WORKSPACE_SAVE,
@@ -6435,7 +6800,7 @@ const workspaceApi$2 = {
6435
6800
  */
6436
6801
  listWorkspacesForApplication: (appId) => {
6437
6802
  console.log("listWorkspacesForApplication called with appId:", appId);
6438
- return ipcRenderer$f.invoke(WORKSPACE_LIST, { appId });
6803
+ return ipcRenderer$g.invoke(WORKSPACE_LIST, { appId });
6439
6804
  },
6440
6805
 
6441
6806
  /**
@@ -6446,7 +6811,7 @@ const workspaceApi$2 = {
6446
6811
  * @returns
6447
6812
  */
6448
6813
  saveWorkspaceForApplication: (appId, data) =>
6449
- ipcRenderer$f.invoke(WORKSPACE_SAVE, { appId, data }),
6814
+ ipcRenderer$g.invoke(WORKSPACE_SAVE, { appId, data }),
6450
6815
 
6451
6816
  /**
6452
6817
  * deleteWorkspaceForApplication
@@ -6456,7 +6821,7 @@ const workspaceApi$2 = {
6456
6821
  * @returns
6457
6822
  */
6458
6823
  deleteWorkspaceForApplication: (appId, workspaceId) =>
6459
- ipcRenderer$f.invoke(WORKSPACE_DELETE, { appId, workspaceId }),
6824
+ ipcRenderer$g.invoke(WORKSPACE_DELETE, { appId, workspaceId }),
6460
6825
  };
6461
6826
 
6462
6827
  var workspaceApi_1 = workspaceApi$2;
@@ -6468,15 +6833,15 @@ var workspaceApi_1 = workspaceApi$2;
6468
6833
  */
6469
6834
 
6470
6835
  // ipcRenderer that must be used to invoke the events
6471
- const { ipcRenderer: ipcRenderer$e } = require$$0;
6836
+ const { ipcRenderer: ipcRenderer$f } = require$$0;
6472
6837
 
6473
6838
  const { LAYOUT_LIST, LAYOUT_SAVE } = events$8;
6474
6839
 
6475
6840
  const layoutApi$2 = {
6476
6841
  listLayoutsForApplication: (appId) =>
6477
- ipcRenderer$e.invoke(LAYOUT_LIST, { appId }),
6842
+ ipcRenderer$f.invoke(LAYOUT_LIST, { appId }),
6478
6843
  saveLayoutForApplication: (appId, data) =>
6479
- ipcRenderer$e.invoke(LAYOUT_SAVE, { appId, data }),
6844
+ ipcRenderer$f.invoke(LAYOUT_SAVE, { appId, data }),
6480
6845
  };
6481
6846
 
6482
6847
  var layoutApi_1 = layoutApi$2;
@@ -6488,7 +6853,7 @@ var layoutApi_1 = layoutApi$2;
6488
6853
  */
6489
6854
 
6490
6855
  // ipcRenderer that must be used to invoke the events
6491
- const { ipcRenderer: ipcRenderer$d } = require$$0;
6856
+ const { ipcRenderer: ipcRenderer$e } = require$$0;
6492
6857
 
6493
6858
  const {
6494
6859
  DATA_JSON_TO_CSV_FILE,
@@ -6507,7 +6872,7 @@ const {
6507
6872
  const dataApi$2 = {
6508
6873
  // convert a json array of objects to a csv string and save to file
6509
6874
  convertJsonToCsvFile: (appId, jsonObject, filename) =>
6510
- ipcRenderer$d.invoke(DATA_JSON_TO_CSV_FILE, {
6875
+ ipcRenderer$e.invoke(DATA_JSON_TO_CSV_FILE, {
6511
6876
  appId,
6512
6877
  jsonObject,
6513
6878
  filename,
@@ -6515,10 +6880,10 @@ const dataApi$2 = {
6515
6880
 
6516
6881
  // convert a json array of objects to a csv string and return a string
6517
6882
  convertJsonToCsvString: (appId, jsonObject) =>
6518
- ipcRenderer$d.invoke(DATA_JSON_TO_CSV_STRING, { appId, jsonObject }),
6883
+ ipcRenderer$e.invoke(DATA_JSON_TO_CSV_STRING, { appId, jsonObject }),
6519
6884
 
6520
6885
  parseXMLStream: (filepath, outpath, start) =>
6521
- ipcRenderer$d.invoke(PARSE_XML_STREAM, {
6886
+ ipcRenderer$e.invoke(PARSE_XML_STREAM, {
6522
6887
  filepath,
6523
6888
  outpath,
6524
6889
  start,
@@ -6532,7 +6897,7 @@ const dataApi$2 = {
6532
6897
  headers = null,
6533
6898
  limit = null,
6534
6899
  ) => {
6535
- ipcRenderer$d.invoke(PARSE_CSV_STREAM, {
6900
+ ipcRenderer$e.invoke(PARSE_CSV_STREAM, {
6536
6901
  filepath,
6537
6902
  outpath,
6538
6903
  delimiter,
@@ -6543,15 +6908,15 @@ const dataApi$2 = {
6543
6908
  },
6544
6909
 
6545
6910
  readLinesFromFile: (filepath, lineCount) => {
6546
- ipcRenderer$d.invoke(READ_LINES, { filepath, lineCount });
6911
+ ipcRenderer$e.invoke(READ_LINES, { filepath, lineCount });
6547
6912
  },
6548
6913
 
6549
6914
  readJSONFromFile: (filepath, objectCount = null) => {
6550
- ipcRenderer$d.invoke(READ_JSON, { filepath, objectCount });
6915
+ ipcRenderer$e.invoke(READ_JSON, { filepath, objectCount });
6551
6916
  },
6552
6917
 
6553
6918
  readDataFromURL: (url, toFilepath) => {
6554
- ipcRenderer$d.invoke(READ_DATA_URL, { url, toFilepath });
6919
+ ipcRenderer$e.invoke(READ_DATA_URL, { url, toFilepath });
6555
6920
  },
6556
6921
 
6557
6922
  /*
@@ -6560,7 +6925,7 @@ const dataApi$2 = {
6560
6925
  * @param {object} returnEmpty the return empty object
6561
6926
  */
6562
6927
  saveData: (data, filename, append, returnEmpty, uuid) =>
6563
- ipcRenderer$d.invoke(DATA_SAVE_TO_FILE, {
6928
+ ipcRenderer$e.invoke(DATA_SAVE_TO_FILE, {
6564
6929
  data,
6565
6930
  filename,
6566
6931
  append,
@@ -6572,14 +6937,14 @@ const dataApi$2 = {
6572
6937
  * @param {string} filename the filename to read (not path)
6573
6938
  */
6574
6939
  readData: (filename, returnEmpty = []) =>
6575
- ipcRenderer$d.invoke(DATA_READ_FROM_FILE, { filename, returnEmpty }),
6940
+ ipcRenderer$e.invoke(DATA_READ_FROM_FILE, { filename, returnEmpty }),
6576
6941
 
6577
6942
  /**
6578
6943
  * transformFile
6579
6944
  * @returns
6580
6945
  */
6581
6946
  transformFile: (filepath, outFilepath, mappingFunctionBody, args) => {
6582
- ipcRenderer$d.invoke(TRANSFORM_FILE, {
6947
+ ipcRenderer$e.invoke(TRANSFORM_FILE, {
6583
6948
  filepath,
6584
6949
  outFilepath,
6585
6950
  mappingFunctionBody,
@@ -6588,7 +6953,7 @@ const dataApi$2 = {
6588
6953
  },
6589
6954
 
6590
6955
  extractColorsFromImageURL: (url) => {
6591
- ipcRenderer$d.invoke(EXTRACT_COLORS_FROM_IMAGE, {
6956
+ ipcRenderer$e.invoke(EXTRACT_COLORS_FROM_IMAGE, {
6592
6957
  url,
6593
6958
  });
6594
6959
  },
@@ -6603,7 +6968,7 @@ var dataApi_1 = dataApi$2;
6603
6968
  */
6604
6969
 
6605
6970
  // ipcRenderer that must be used to invoke the events
6606
- const { ipcRenderer: ipcRenderer$c } = require$$0;
6971
+ const { ipcRenderer: ipcRenderer$d } = require$$0;
6607
6972
 
6608
6973
  const {
6609
6974
  SETTINGS_GET,
@@ -6614,14 +6979,14 @@ const {
6614
6979
  } = events$8;
6615
6980
 
6616
6981
  const settingsApi$2 = {
6617
- getSettingsForApplication: () => ipcRenderer$c.invoke(SETTINGS_GET, {}),
6982
+ getSettingsForApplication: () => ipcRenderer$d.invoke(SETTINGS_GET, {}),
6618
6983
  saveSettingsForApplication: (data) =>
6619
- ipcRenderer$c.invoke(SETTINGS_SAVE, { data }),
6620
- getDataDirectory: () => ipcRenderer$c.invoke(SETTINGS_GET_DATA_DIR, {}),
6984
+ ipcRenderer$d.invoke(SETTINGS_SAVE, { data }),
6985
+ getDataDirectory: () => ipcRenderer$d.invoke(SETTINGS_GET_DATA_DIR, {}),
6621
6986
  setDataDirectory: (dataDirectory) =>
6622
- ipcRenderer$c.invoke(SETTINGS_SET_DATA_DIR, { dataDirectory }),
6987
+ ipcRenderer$d.invoke(SETTINGS_SET_DATA_DIR, { dataDirectory }),
6623
6988
  migrateDataDirectory: (oldDirectory, newDirectory) =>
6624
- ipcRenderer$c.invoke(SETTINGS_MIGRATE_DATA_DIR, {
6989
+ ipcRenderer$d.invoke(SETTINGS_MIGRATE_DATA_DIR, {
6625
6990
  oldDirectory,
6626
6991
  newDirectory,
6627
6992
  }),
@@ -6636,7 +7001,7 @@ var settingsApi_1 = settingsApi$2;
6636
7001
  */
6637
7002
 
6638
7003
  // ipcRenderer that must be used to invoke the events
6639
- const { ipcRenderer: ipcRenderer$b } = require$$0;
7004
+ const { ipcRenderer: ipcRenderer$c } = require$$0;
6640
7005
 
6641
7006
  const { CHOOSE_FILE } = events$8;
6642
7007
 
@@ -6648,7 +7013,7 @@ const dialogApi$2 = {
6648
7013
  */
6649
7014
  chooseFile: (allowFile = true, extensions = ["*"]) => {
6650
7015
  console.log("dialog api choose file");
6651
- return ipcRenderer$b.invoke(CHOOSE_FILE, { allowFile, extensions });
7016
+ return ipcRenderer$c.invoke(CHOOSE_FILE, { allowFile, extensions });
6652
7017
  },
6653
7018
  };
6654
7019
 
@@ -6667,7 +7032,7 @@ var dialogApi_1 = dialogApi$2;
6667
7032
  * mainApi.widgets.uninstall('Weather')
6668
7033
  */
6669
7034
 
6670
- const { ipcRenderer: ipcRenderer$a } = require$$0;
7035
+ const { ipcRenderer: ipcRenderer$b } = require$$0;
6671
7036
 
6672
7037
  const widgetApi$2 = {
6673
7038
  /**
@@ -6676,7 +7041,7 @@ const widgetApi$2 = {
6676
7041
  */
6677
7042
  list: async () => {
6678
7043
  try {
6679
- return await ipcRenderer$a.invoke("widget:list");
7044
+ return await ipcRenderer$b.invoke("widget:list");
6680
7045
  } catch (error) {
6681
7046
  console.error("[WidgetApi] Error listing widgets:", error);
6682
7047
  throw error;
@@ -6690,7 +7055,7 @@ const widgetApi$2 = {
6690
7055
  */
6691
7056
  get: async (widgetName) => {
6692
7057
  try {
6693
- return await ipcRenderer$a.invoke("widget:get", widgetName);
7058
+ return await ipcRenderer$b.invoke("widget:get", widgetName);
6694
7059
  } catch (error) {
6695
7060
  console.error(`[WidgetApi] Error getting widget ${widgetName}:`, error);
6696
7061
  throw error;
@@ -6721,7 +7086,7 @@ const widgetApi$2 = {
6721
7086
  console.log(
6722
7087
  `[WidgetApi] Installing widget: ${widgetName} from ${downloadUrl}`,
6723
7088
  );
6724
- const config = await ipcRenderer$a.invoke(
7089
+ const config = await ipcRenderer$b.invoke(
6725
7090
  "widget:install",
6726
7091
  widgetName,
6727
7092
  downloadUrl,
@@ -6761,7 +7126,7 @@ const widgetApi$2 = {
6761
7126
  console.log(
6762
7127
  `[WidgetApi] Installing local widget: ${widgetName} from ${localPath}`,
6763
7128
  );
6764
- const config = await ipcRenderer$a.invoke(
7129
+ const config = await ipcRenderer$b.invoke(
6765
7130
  "widget:install-local",
6766
7131
  widgetName,
6767
7132
  localPath,
@@ -6792,7 +7157,7 @@ const widgetApi$2 = {
6792
7157
  loadFolder: async (folderPath) => {
6793
7158
  try {
6794
7159
  console.log(`[WidgetApi] Loading widgets from folder: ${folderPath}`);
6795
- const results = await ipcRenderer$a.invoke(
7160
+ const results = await ipcRenderer$b.invoke(
6796
7161
  "widget:load-folder",
6797
7162
  folderPath,
6798
7163
  );
@@ -6816,7 +7181,7 @@ const widgetApi$2 = {
6816
7181
  uninstall: async (widgetName) => {
6817
7182
  try {
6818
7183
  console.log(`[WidgetApi] Uninstalling widget: ${widgetName}`);
6819
- const success = await ipcRenderer$a.invoke("widget:uninstall", widgetName);
7184
+ const success = await ipcRenderer$b.invoke("widget:uninstall", widgetName);
6820
7185
  if (success) {
6821
7186
  console.log(`[WidgetApi] ✓ Widget ${widgetName} uninstalled`);
6822
7187
  } else {
@@ -6839,7 +7204,7 @@ const widgetApi$2 = {
6839
7204
  */
6840
7205
  getCachePath: async () => {
6841
7206
  try {
6842
- return await ipcRenderer$a.invoke("widget:cache-path");
7207
+ return await ipcRenderer$b.invoke("widget:cache-path");
6843
7208
  } catch (error) {
6844
7209
  console.error("[WidgetApi] Error getting cache path:", error);
6845
7210
  throw error;
@@ -6853,7 +7218,7 @@ const widgetApi$2 = {
6853
7218
  */
6854
7219
  getStoragePath: async () => {
6855
7220
  try {
6856
- return await ipcRenderer$a.invoke("widget:storage-path");
7221
+ return await ipcRenderer$b.invoke("widget:storage-path");
6857
7222
  } catch (error) {
6858
7223
  console.error("[WidgetApi] Error getting storage path:", error);
6859
7224
  throw error;
@@ -6870,7 +7235,7 @@ const widgetApi$2 = {
6870
7235
  setStoragePath: async (customPath) => {
6871
7236
  try {
6872
7237
  console.log(`[WidgetApi] Setting storage path to: ${customPath}`);
6873
- const result = await ipcRenderer$a.invoke(
7238
+ const result = await ipcRenderer$b.invoke(
6874
7239
  "widget:set-storage-path",
6875
7240
  customPath,
6876
7241
  );
@@ -6892,7 +7257,7 @@ const widgetApi$2 = {
6892
7257
  */
6893
7258
  getComponentConfigs: async () => {
6894
7259
  try {
6895
- return await ipcRenderer$a.invoke("widget:get-component-configs");
7260
+ return await ipcRenderer$b.invoke("widget:get-component-configs");
6896
7261
  } catch (error) {
6897
7262
  console.error("[WidgetApi] Error getting component configs:", error);
6898
7263
  return [];
@@ -6907,7 +7272,7 @@ const widgetApi$2 = {
6907
7272
  */
6908
7273
  readBundle: async (widgetName) => {
6909
7274
  try {
6910
- return await ipcRenderer$a.invoke("widget:read-bundle", widgetName);
7275
+ return await ipcRenderer$b.invoke("widget:read-bundle", widgetName);
6911
7276
  } catch (error) {
6912
7277
  console.error(
6913
7278
  `[WidgetApi] Error reading bundle for ${widgetName}:`,
@@ -6924,7 +7289,7 @@ const widgetApi$2 = {
6924
7289
  */
6925
7290
  readAllBundles: async () => {
6926
7291
  try {
6927
- return await ipcRenderer$a.invoke("widget:read-all-bundles");
7292
+ return await ipcRenderer$b.invoke("widget:read-all-bundles");
6928
7293
  } catch (error) {
6929
7294
  console.error("[WidgetApi] Error reading all bundles:", error);
6930
7295
  return [];
@@ -6944,7 +7309,7 @@ const widgetApi$2 = {
6944
7309
  * });
6945
7310
  */
6946
7311
  onInstalled: (callback) => {
6947
- ipcRenderer$a.on("widget:installed", (event, data) => {
7312
+ ipcRenderer$b.on("widget:installed", (event, data) => {
6948
7313
  callback(data);
6949
7314
  });
6950
7315
  },
@@ -6962,7 +7327,7 @@ const widgetApi$2 = {
6962
7327
  * });
6963
7328
  */
6964
7329
  onLoaded: (callback) => {
6965
- ipcRenderer$a.on("widgets:loaded", (event, data) => {
7330
+ ipcRenderer$b.on("widgets:loaded", (event, data) => {
6966
7331
  callback(data);
6967
7332
  });
6968
7333
  },
@@ -6973,7 +7338,7 @@ const widgetApi$2 = {
6973
7338
  * @param {Function} callback - The callback to remove
6974
7339
  */
6975
7340
  removeInstalledListener: (callback) => {
6976
- ipcRenderer$a.removeListener("widget:installed", callback);
7341
+ ipcRenderer$b.removeListener("widget:installed", callback);
6977
7342
  },
6978
7343
 
6979
7344
  /**
@@ -6982,7 +7347,7 @@ const widgetApi$2 = {
6982
7347
  * @param {Function} callback - The callback to remove
6983
7348
  */
6984
7349
  removeLoadedListener: (callback) => {
6985
- ipcRenderer$a.removeListener("widgets:loaded", callback);
7350
+ ipcRenderer$b.removeListener("widgets:loaded", callback);
6986
7351
  },
6987
7352
  };
6988
7353
 
@@ -6995,7 +7360,7 @@ var widgetApi_1 = widgetApi$2;
6995
7360
  * Communicates with main process via IPC to handle encryption and file storage
6996
7361
  */
6997
7362
 
6998
- const { ipcRenderer: ipcRenderer$9 } = require$$0;
7363
+ const { ipcRenderer: ipcRenderer$a } = require$$0;
6999
7364
  const {
7000
7365
  PROVIDER_SAVE,
7001
7366
  PROVIDER_LIST,
@@ -7025,7 +7390,7 @@ const providerApi$2 = {
7025
7390
  providerClass = "credential",
7026
7391
  mcpConfig = null,
7027
7392
  ) =>
7028
- ipcRenderer$9.invoke(PROVIDER_SAVE, {
7393
+ ipcRenderer$a.invoke(PROVIDER_SAVE, {
7029
7394
  appId,
7030
7395
  providerName,
7031
7396
  providerType,
@@ -7042,7 +7407,7 @@ const providerApi$2 = {
7042
7407
  * @param {String} appId - the appId specified in the dash initialization
7043
7408
  * @returns {Promise<Array>} Array of provider objects with name, type, credentials
7044
7409
  */
7045
- listProviders: (appId) => ipcRenderer$9.invoke(PROVIDER_LIST, { appId }),
7410
+ listProviders: (appId) => ipcRenderer$a.invoke(PROVIDER_LIST, { appId }),
7046
7411
 
7047
7412
  /**
7048
7413
  * getProvider
@@ -7054,7 +7419,7 @@ const providerApi$2 = {
7054
7419
  * @returns {Promise<Object>} Provider object with name, type, credentials
7055
7420
  */
7056
7421
  getProvider: (appId, providerName) =>
7057
- ipcRenderer$9.invoke(PROVIDER_GET, { appId, providerName }),
7422
+ ipcRenderer$a.invoke(PROVIDER_GET, { appId, providerName }),
7058
7423
 
7059
7424
  /**
7060
7425
  * deleteProvider
@@ -7066,7 +7431,7 @@ const providerApi$2 = {
7066
7431
  * @returns {Promise}
7067
7432
  */
7068
7433
  deleteProvider: (appId, providerName) =>
7069
- ipcRenderer$9.invoke(PROVIDER_DELETE, { appId, providerName }),
7434
+ ipcRenderer$a.invoke(PROVIDER_DELETE, { appId, providerName }),
7070
7435
 
7071
7436
  /**
7072
7437
  * listProvidersForApplication
@@ -7076,14 +7441,14 @@ const providerApi$2 = {
7076
7441
  * @param {String} appId - the appId specified in the dash initialization
7077
7442
  */
7078
7443
  listProvidersForApplication: (appId) => {
7079
- ipcRenderer$9
7444
+ ipcRenderer$a
7080
7445
  .invoke(PROVIDER_LIST, { appId })
7081
7446
  .then((result) => {
7082
7447
  // Emit the event for ElectronDashboardApi to listen to
7083
- ipcRenderer$9.send("PROVIDER_LIST_COMPLETE", result);
7448
+ ipcRenderer$a.send("PROVIDER_LIST_COMPLETE", result);
7084
7449
  })
7085
7450
  .catch((error) => {
7086
- ipcRenderer$9.send("PROVIDER_LIST_ERROR", {
7451
+ ipcRenderer$a.send("PROVIDER_LIST_ERROR", {
7087
7452
  error: error.message,
7088
7453
  });
7089
7454
  });
@@ -7100,7 +7465,7 @@ const providerApi$2 = {
7100
7465
  providerType,
7101
7466
  credentials,
7102
7467
  ) => {
7103
- ipcRenderer$9
7468
+ ipcRenderer$a
7104
7469
  .invoke(PROVIDER_SAVE, {
7105
7470
  appId,
7106
7471
  providerName,
@@ -7108,10 +7473,10 @@ const providerApi$2 = {
7108
7473
  credentials,
7109
7474
  })
7110
7475
  .then((result) => {
7111
- ipcRenderer$9.send("PROVIDER_SAVE_COMPLETE", result);
7476
+ ipcRenderer$a.send("PROVIDER_SAVE_COMPLETE", result);
7112
7477
  })
7113
7478
  .catch((error) => {
7114
- ipcRenderer$9.send("PROVIDER_SAVE_ERROR", {
7479
+ ipcRenderer$a.send("PROVIDER_SAVE_ERROR", {
7115
7480
  error: error.message,
7116
7481
  });
7117
7482
  });
@@ -7123,13 +7488,13 @@ const providerApi$2 = {
7123
7488
  * Event-listener-based version for use with ElectronDashboardApi
7124
7489
  */
7125
7490
  getProviderForApplication: (appId, providerName) => {
7126
- ipcRenderer$9
7491
+ ipcRenderer$a
7127
7492
  .invoke(PROVIDER_GET, { appId, providerName })
7128
7493
  .then((result) => {
7129
- ipcRenderer$9.send("PROVIDER_GET_COMPLETE", result);
7494
+ ipcRenderer$a.send("PROVIDER_GET_COMPLETE", result);
7130
7495
  })
7131
7496
  .catch((error) => {
7132
- ipcRenderer$9.send("PROVIDER_GET_ERROR", {
7497
+ ipcRenderer$a.send("PROVIDER_GET_ERROR", {
7133
7498
  error: error.message,
7134
7499
  });
7135
7500
  });
@@ -7141,13 +7506,13 @@ const providerApi$2 = {
7141
7506
  * Event-listener-based version for use with ElectronDashboardApi
7142
7507
  */
7143
7508
  deleteProviderForApplication: (appId, providerName) => {
7144
- ipcRenderer$9
7509
+ ipcRenderer$a
7145
7510
  .invoke(PROVIDER_DELETE, { appId, providerName })
7146
7511
  .then((result) => {
7147
- ipcRenderer$9.send("PROVIDER_DELETE_COMPLETE", result);
7512
+ ipcRenderer$a.send("PROVIDER_DELETE_COMPLETE", result);
7148
7513
  })
7149
7514
  .catch((error) => {
7150
- ipcRenderer$9.send("PROVIDER_DELETE_ERROR", {
7515
+ ipcRenderer$a.send("PROVIDER_DELETE_ERROR", {
7151
7516
  error: error.message,
7152
7517
  });
7153
7518
  });
@@ -7163,7 +7528,7 @@ var providerApi_1 = providerApi$2;
7163
7528
  * Communicates with main process via IPC to manage MCP server lifecycle.
7164
7529
  */
7165
7530
 
7166
- const { ipcRenderer: ipcRenderer$8 } = require$$0;
7531
+ const { ipcRenderer: ipcRenderer$9 } = require$$0;
7167
7532
  const {
7168
7533
  MCP_START_SERVER,
7169
7534
  MCP_STOP_SERVER,
@@ -7186,7 +7551,7 @@ const mcpApi$2 = {
7186
7551
  * @returns {Promise<{ success, serverName, tools, status } | { error, message }>}
7187
7552
  */
7188
7553
  startServer: (serverName, mcpConfig, credentials) =>
7189
- ipcRenderer$8.invoke(MCP_START_SERVER, {
7554
+ ipcRenderer$9.invoke(MCP_START_SERVER, {
7190
7555
  serverName,
7191
7556
  mcpConfig,
7192
7557
  credentials,
@@ -7200,7 +7565,7 @@ const mcpApi$2 = {
7200
7565
  * @returns {Promise<{ success, serverName } | { error, message }>}
7201
7566
  */
7202
7567
  stopServer: (serverName) =>
7203
- ipcRenderer$8.invoke(MCP_STOP_SERVER, { serverName }),
7568
+ ipcRenderer$9.invoke(MCP_STOP_SERVER, { serverName }),
7204
7569
 
7205
7570
  /**
7206
7571
  * listTools
@@ -7209,7 +7574,7 @@ const mcpApi$2 = {
7209
7574
  * @param {string} serverName the server name
7210
7575
  * @returns {Promise<{ tools } | { error, message }>}
7211
7576
  */
7212
- listTools: (serverName) => ipcRenderer$8.invoke(MCP_LIST_TOOLS, { serverName }),
7577
+ listTools: (serverName) => ipcRenderer$9.invoke(MCP_LIST_TOOLS, { serverName }),
7213
7578
 
7214
7579
  /**
7215
7580
  * callTool
@@ -7222,7 +7587,7 @@ const mcpApi$2 = {
7222
7587
  * @returns {Promise<{ result } | { error, message }>}
7223
7588
  */
7224
7589
  callTool: (serverName, toolName, args, allowedTools = null) =>
7225
- ipcRenderer$8.invoke(MCP_CALL_TOOL, {
7590
+ ipcRenderer$9.invoke(MCP_CALL_TOOL, {
7226
7591
  serverName,
7227
7592
  toolName,
7228
7593
  args,
@@ -7237,7 +7602,7 @@ const mcpApi$2 = {
7237
7602
  * @returns {Promise<{ resources } | { error, message }>}
7238
7603
  */
7239
7604
  listResources: (serverName) =>
7240
- ipcRenderer$8.invoke(MCP_LIST_RESOURCES, { serverName }),
7605
+ ipcRenderer$9.invoke(MCP_LIST_RESOURCES, { serverName }),
7241
7606
 
7242
7607
  /**
7243
7608
  * readResource
@@ -7248,7 +7613,7 @@ const mcpApi$2 = {
7248
7613
  * @returns {Promise<{ resource } | { error, message }>}
7249
7614
  */
7250
7615
  readResource: (serverName, uri) =>
7251
- ipcRenderer$8.invoke(MCP_READ_RESOURCE, { serverName, uri }),
7616
+ ipcRenderer$9.invoke(MCP_READ_RESOURCE, { serverName, uri }),
7252
7617
 
7253
7618
  /**
7254
7619
  * getServerStatus
@@ -7258,7 +7623,7 @@ const mcpApi$2 = {
7258
7623
  * @returns {Promise<{ status, tools, error }>}
7259
7624
  */
7260
7625
  getServerStatus: (serverName) =>
7261
- ipcRenderer$8.invoke(MCP_SERVER_STATUS, { serverName }),
7626
+ ipcRenderer$9.invoke(MCP_SERVER_STATUS, { serverName }),
7262
7627
 
7263
7628
  /**
7264
7629
  * getCatalog
@@ -7266,7 +7631,7 @@ const mcpApi$2 = {
7266
7631
  *
7267
7632
  * @returns {Promise<{ catalog } | { error, message }>}
7268
7633
  */
7269
- getCatalog: () => ipcRenderer$8.invoke(MCP_GET_CATALOG),
7634
+ getCatalog: () => ipcRenderer$9.invoke(MCP_GET_CATALOG),
7270
7635
  };
7271
7636
 
7272
7637
  var mcpApi_1 = mcpApi$2;
@@ -7284,7 +7649,7 @@ var mcpApi_1 = mcpApi$2;
7284
7649
  * mainApi.registry.checkUpdates([{ name: "weather-widgets", version: "1.0.0" }])
7285
7650
  */
7286
7651
 
7287
- const { ipcRenderer: ipcRenderer$7 } = require$$0;
7652
+ const { ipcRenderer: ipcRenderer$8 } = require$$0;
7288
7653
 
7289
7654
  const registryApi$2 = {
7290
7655
  /**
@@ -7294,7 +7659,7 @@ const registryApi$2 = {
7294
7659
  */
7295
7660
  fetchIndex: async (forceRefresh = false) => {
7296
7661
  try {
7297
- return await ipcRenderer$7.invoke("registry:fetch-index", forceRefresh);
7662
+ return await ipcRenderer$8.invoke("registry:fetch-index", forceRefresh);
7298
7663
  } catch (error) {
7299
7664
  console.error("[RegistryApi] Error fetching index:", error);
7300
7665
  throw error;
@@ -7309,7 +7674,7 @@ const registryApi$2 = {
7309
7674
  */
7310
7675
  search: async (query = "", filters = {}) => {
7311
7676
  try {
7312
- return await ipcRenderer$7.invoke("registry:search", query, filters);
7677
+ return await ipcRenderer$8.invoke("registry:search", query, filters);
7313
7678
  } catch (error) {
7314
7679
  console.error("[RegistryApi] Error searching registry:", error);
7315
7680
  throw error;
@@ -7323,7 +7688,7 @@ const registryApi$2 = {
7323
7688
  */
7324
7689
  getPackage: async (packageName) => {
7325
7690
  try {
7326
- return await ipcRenderer$7.invoke("registry:get-package", packageName);
7691
+ return await ipcRenderer$8.invoke("registry:get-package", packageName);
7327
7692
  } catch (error) {
7328
7693
  console.error(
7329
7694
  `[RegistryApi] Error getting package ${packageName}:`,
@@ -7340,7 +7705,7 @@ const registryApi$2 = {
7340
7705
  */
7341
7706
  checkUpdates: async (installedWidgets = []) => {
7342
7707
  try {
7343
- return await ipcRenderer$7.invoke(
7708
+ return await ipcRenderer$8.invoke(
7344
7709
  "registry:check-updates",
7345
7710
  installedWidgets,
7346
7711
  );
@@ -7359,17 +7724,17 @@ var registryApi_1 = registryApi$2;
7359
7724
  * Handle the theme configuration file
7360
7725
  */
7361
7726
 
7362
- const { ipcRenderer: ipcRenderer$6 } = require$$0;
7727
+ const { ipcRenderer: ipcRenderer$7 } = require$$0;
7363
7728
 
7364
7729
  const { THEME_LIST, THEME_SAVE, THEME_DELETE } = events$8;
7365
7730
 
7366
7731
  const themeApi$2 = {
7367
7732
  listThemesForApplication: (appId) =>
7368
- ipcRenderer$6.invoke(THEME_LIST, { appId }),
7733
+ ipcRenderer$7.invoke(THEME_LIST, { appId }),
7369
7734
  saveThemeForApplication: (appId, themeName, themeObject) =>
7370
- ipcRenderer$6.invoke(THEME_SAVE, { appId, themeName, themeObject }),
7735
+ ipcRenderer$7.invoke(THEME_SAVE, { appId, themeName, themeObject }),
7371
7736
  deleteThemeForApplication: (appId, themeKey) =>
7372
- ipcRenderer$6.invoke(THEME_DELETE, { appId, themeKey }),
7737
+ ipcRenderer$7.invoke(THEME_DELETE, { appId, themeKey }),
7373
7738
  };
7374
7739
 
7375
7740
  var themeApi_1 = themeApi$2;
@@ -7381,7 +7746,7 @@ var themeApi_1 = themeApi$2;
7381
7746
  */
7382
7747
 
7383
7748
  // ipcRenderer that must be used to invoke the events
7384
- const { ipcRenderer: ipcRenderer$5 } = require$$0;
7749
+ const { ipcRenderer: ipcRenderer$6 } = require$$0;
7385
7750
 
7386
7751
  const {
7387
7752
  ALGOLIA_LIST_INDICES,
@@ -7395,10 +7760,10 @@ const {
7395
7760
 
7396
7761
  const algoliaApi$2 = {
7397
7762
  listIndices: (application) =>
7398
- ipcRenderer$5.invoke(ALGOLIA_LIST_INDICES, application),
7763
+ ipcRenderer$6.invoke(ALGOLIA_LIST_INDICES, application),
7399
7764
 
7400
7765
  browseObjects: (appId, apiKey, indexName) => {
7401
- ipcRenderer$5.invoke(ALGOLIA_BROWSE_OBJECTS, {
7766
+ ipcRenderer$6.invoke(ALGOLIA_BROWSE_OBJECTS, {
7402
7767
  appId,
7403
7768
  apiKey,
7404
7769
  indexName,
@@ -7406,10 +7771,10 @@ const algoliaApi$2 = {
7406
7771
  });
7407
7772
  },
7408
7773
 
7409
- saveSynonyms: () => ipcRenderer$5.invoke(ALGOLIA_SAVE_SYNONYMS, {}),
7774
+ saveSynonyms: () => ipcRenderer$6.invoke(ALGOLIA_SAVE_SYNONYMS, {}),
7410
7775
 
7411
7776
  getAnalyticsForQuery: (application, indexName, query) =>
7412
- ipcRenderer$5.invoke(ALGOLIA_ANALYTICS_FOR_QUERY, {
7777
+ ipcRenderer$6.invoke(ALGOLIA_ANALYTICS_FOR_QUERY, {
7413
7778
  application,
7414
7779
  indexName,
7415
7780
  query,
@@ -7422,7 +7787,7 @@ const algoliaApi$2 = {
7422
7787
  dir,
7423
7788
  createIfNotExists = false,
7424
7789
  ) =>
7425
- ipcRenderer$5.invoke(ALGOLIA_PARTIAL_UPDATE_OBJECTS, {
7790
+ ipcRenderer$6.invoke(ALGOLIA_PARTIAL_UPDATE_OBJECTS, {
7426
7791
  appId,
7427
7792
  apiKey,
7428
7793
  indexName,
@@ -7431,7 +7796,7 @@ const algoliaApi$2 = {
7431
7796
  }),
7432
7797
 
7433
7798
  createBatchesFromFile: (filepath, batchFilepath, batchSize) => {
7434
- ipcRenderer$5.invoke(ALGOLIA_CREATE_BATCH, {
7799
+ ipcRenderer$6.invoke(ALGOLIA_CREATE_BATCH, {
7435
7800
  filepath,
7436
7801
  batchFilepath,
7437
7802
  batchSize,
@@ -7439,7 +7804,7 @@ const algoliaApi$2 = {
7439
7804
  },
7440
7805
 
7441
7806
  browseObjectsToFile: (appId, apiKey, indexName, toFilename, query = "") => {
7442
- ipcRenderer$5.invoke(ALGOLIA_BROWSE_OBJECTS, {
7807
+ ipcRenderer$6.invoke(ALGOLIA_BROWSE_OBJECTS, {
7443
7808
  appId,
7444
7809
  apiKey,
7445
7810
  indexName,
@@ -7449,7 +7814,7 @@ const algoliaApi$2 = {
7449
7814
  },
7450
7815
 
7451
7816
  search: (appId, apiKey, indexName, query = "", options = {}) =>
7452
- ipcRenderer$5.invoke(ALGOLIA_SEARCH, {
7817
+ ipcRenderer$6.invoke(ALGOLIA_SEARCH, {
7453
7818
  appId,
7454
7819
  apiKey,
7455
7820
  indexName,
@@ -7464,14 +7829,14 @@ var algoliaApi_1 = algoliaApi$2;
7464
7829
  * openAI
7465
7830
  */
7466
7831
 
7467
- const { ipcRenderer: ipcRenderer$4 } = require$$0;
7832
+ const { ipcRenderer: ipcRenderer$5 } = require$$0;
7468
7833
 
7469
7834
  const { OPENAI_DESCRIBE_IMAGE } = openaiEvents$1;
7470
7835
 
7471
7836
  const openaiApi$2 = {
7472
7837
  // convert a json array of objects to a csv string and save to file
7473
7838
  describeImage: (imageUrl, apiKey, prompt = "What's in this image?") =>
7474
- ipcRenderer$4.invoke(OPENAI_DESCRIBE_IMAGE, { imageUrl, apiKey, prompt }),
7839
+ ipcRenderer$5.invoke(OPENAI_DESCRIBE_IMAGE, { imageUrl, apiKey, prompt }),
7475
7840
  };
7476
7841
 
7477
7842
  var openaiApi_1 = openaiApi$2;
@@ -7482,14 +7847,14 @@ var openaiApi_1 = openaiApi$2;
7482
7847
  */
7483
7848
 
7484
7849
  // ipcRenderer that must be used to invoke the events
7485
- const { ipcRenderer: ipcRenderer$3 } = require$$0;
7850
+ const { ipcRenderer: ipcRenderer$4 } = require$$0;
7486
7851
 
7487
7852
  const { MENU_ITEMS_SAVE, MENU_ITEMS_LIST } = events$8;
7488
7853
 
7489
7854
  const menuItemsApi$2 = {
7490
7855
  saveMenuItem: (appId, menuItem) =>
7491
- ipcRenderer$3.invoke(MENU_ITEMS_SAVE, { appId, menuItem }),
7492
- listMenuItems: (appId) => ipcRenderer$3.invoke(MENU_ITEMS_LIST, { appId }),
7856
+ ipcRenderer$4.invoke(MENU_ITEMS_SAVE, { appId, menuItem }),
7857
+ listMenuItems: (appId) => ipcRenderer$4.invoke(MENU_ITEMS_LIST, { appId }),
7493
7858
  };
7494
7859
 
7495
7860
  var menuItemsApi_1 = menuItemsApi$2;
@@ -7501,16 +7866,123 @@ var menuItemsApi_1 = menuItemsApi$2;
7501
7866
  */
7502
7867
 
7503
7868
  // ipcRenderer that must be used to invoke the events
7504
- const { ipcRenderer: ipcRenderer$2 } = require$$0;
7869
+ const { ipcRenderer: ipcRenderer$3 } = require$$0;
7505
7870
 
7506
7871
  const pluginApi$2 = {
7507
7872
  install: (packageName, filepath) =>
7508
- ipcRenderer$2.invoke("plugin-install", { packageName, filepath }),
7509
- uninstall: (filepath) => ipcRenderer$2.invoke("plugin-uninstall", filepath),
7873
+ ipcRenderer$3.invoke("plugin-install", { packageName, filepath }),
7874
+ uninstall: (filepath) => ipcRenderer$3.invoke("plugin-uninstall", filepath),
7510
7875
  };
7511
7876
 
7512
7877
  var pluginApi_1 = pluginApi$2;
7513
7878
 
7879
+ /**
7880
+ * llmApi.js
7881
+ *
7882
+ * Preload bridge for LLM chat operations.
7883
+ * Communicates with main process via IPC for streaming chat,
7884
+ * tool-use events, and request cancellation.
7885
+ */
7886
+
7887
+ const { ipcRenderer: ipcRenderer$2 } = require$$0;
7888
+ const {
7889
+ LLM_SEND_MESSAGE,
7890
+ LLM_ABORT_REQUEST,
7891
+ LLM_LIST_CONNECTED_TOOLS,
7892
+ LLM_STREAM_DELTA,
7893
+ LLM_STREAM_TOOL_CALL,
7894
+ LLM_STREAM_TOOL_RESULT,
7895
+ LLM_STREAM_COMPLETE,
7896
+ LLM_STREAM_ERROR,
7897
+ } = llmEvents$1;
7898
+
7899
+ const llmApi$2 = {
7900
+ /**
7901
+ * sendMessage
7902
+ * Start a streaming LLM request with optional tool-use.
7903
+ *
7904
+ * @param {string} requestId - unique ID for filtering stream events
7905
+ * @param {object} params - { apiKey, model, messages, tools, toolServerMap, systemPrompt, maxToolRounds }
7906
+ * @returns {Promise<void>}
7907
+ */
7908
+ sendMessage: (requestId, params) =>
7909
+ ipcRenderer$2.invoke(LLM_SEND_MESSAGE, { requestId, ...params }),
7910
+
7911
+ /**
7912
+ * abortRequest
7913
+ * Cancel an in-flight LLM request.
7914
+ *
7915
+ * @param {string} requestId - the request to cancel
7916
+ * @returns {Promise<{ success: boolean }>}
7917
+ */
7918
+ abortRequest: (requestId) =>
7919
+ ipcRenderer$2.invoke(LLM_ABORT_REQUEST, { requestId }),
7920
+
7921
+ /**
7922
+ * listConnectedTools
7923
+ * Get all tools from all connected MCP servers.
7924
+ *
7925
+ * @returns {Promise<Array<{ serverName, tools, resources, status }>>}
7926
+ */
7927
+ listConnectedTools: () => ipcRenderer$2.invoke(LLM_LIST_CONNECTED_TOOLS),
7928
+
7929
+ // --- Stream event listeners ---
7930
+
7931
+ /**
7932
+ * onStreamDelta
7933
+ * Listen for text chunks as they stream in.
7934
+ */
7935
+ onStreamDelta: (callback) => {
7936
+ ipcRenderer$2.on(LLM_STREAM_DELTA, (_event, data) => callback(data));
7937
+ },
7938
+
7939
+ /**
7940
+ * onStreamToolCall
7941
+ * Listen for tool call notifications.
7942
+ */
7943
+ onStreamToolCall: (callback) => {
7944
+ ipcRenderer$2.on(LLM_STREAM_TOOL_CALL, (_event, data) => callback(data));
7945
+ },
7946
+
7947
+ /**
7948
+ * onStreamToolResult
7949
+ * Listen for tool result notifications.
7950
+ */
7951
+ onStreamToolResult: (callback) => {
7952
+ ipcRenderer$2.on(LLM_STREAM_TOOL_RESULT, (_event, data) => callback(data));
7953
+ },
7954
+
7955
+ /**
7956
+ * onStreamComplete
7957
+ * Listen for stream completion (final response).
7958
+ */
7959
+ onStreamComplete: (callback) => {
7960
+ ipcRenderer$2.on(LLM_STREAM_COMPLETE, (_event, data) => callback(data));
7961
+ },
7962
+
7963
+ /**
7964
+ * onStreamError
7965
+ * Listen for stream errors.
7966
+ */
7967
+ onStreamError: (callback) => {
7968
+ ipcRenderer$2.on(LLM_STREAM_ERROR, (_event, data) => callback(data));
7969
+ },
7970
+
7971
+ /**
7972
+ * removeAllStreamListeners
7973
+ * Clean up all LLM stream listeners.
7974
+ */
7975
+ removeAllStreamListeners: () => {
7976
+ ipcRenderer$2.removeAllListeners(LLM_STREAM_DELTA);
7977
+ ipcRenderer$2.removeAllListeners(LLM_STREAM_TOOL_CALL);
7978
+ ipcRenderer$2.removeAllListeners(LLM_STREAM_TOOL_RESULT);
7979
+ ipcRenderer$2.removeAllListeners(LLM_STREAM_COMPLETE);
7980
+ ipcRenderer$2.removeAllListeners(LLM_STREAM_ERROR);
7981
+ },
7982
+ };
7983
+
7984
+ var llmApi_1 = llmApi$2;
7985
+
7514
7986
  /**
7515
7987
  * clientCacheApi.js
7516
7988
  *
@@ -8964,6 +9436,7 @@ const algoliaApi$1 = algoliaApi_1;
8964
9436
  const openaiApi$1 = openaiApi_1;
8965
9437
  const menuItemsApi$1 = menuItemsApi_1;
8966
9438
  const pluginApi$1 = pluginApi_1;
9439
+ const llmApi$1 = llmApi_1;
8967
9440
  const clientCacheApi$1 = clientCacheApi_1;
8968
9441
 
8969
9442
  // Events constants
@@ -9027,6 +9500,9 @@ function createMainApi$1(extensions = {}) {
9027
9500
 
9028
9501
  pathPlugins: "",
9029
9502
 
9503
+ // LLM
9504
+ llm: llmApi$1,
9505
+
9030
9506
  // APIs previously in template
9031
9507
  algolia: algoliaApi$1,
9032
9508
  openai: openaiApi$1,
@@ -9076,6 +9552,7 @@ const algoliaController = algoliaController_1;
9076
9552
  const openaiController = openaiController_1;
9077
9553
  const menuItemsController = menuItemsController_1;
9078
9554
  const pluginController = pluginController_1;
9555
+ const llmController = llmController_1;
9079
9556
 
9080
9557
  // --- Utils ---
9081
9558
  const clientCache = requireClientCache();
@@ -9101,6 +9578,7 @@ const algoliaApi = algoliaApi_1;
9101
9578
  const openaiApi = openaiApi_1;
9102
9579
  const menuItemsApi = menuItemsApi_1;
9103
9580
  const pluginApi = pluginApi_1;
9581
+ const llmApi = llmApi_1;
9104
9582
  const clientCacheApi = clientCacheApi_1;
9105
9583
 
9106
9584
  // --- Events ---
@@ -9130,6 +9608,7 @@ var electron = {
9130
9608
  openaiController,
9131
9609
  menuItemsController,
9132
9610
  pluginController,
9611
+ llmController,
9133
9612
 
9134
9613
  // Controller functions (flat) — spread for convenient destructuring
9135
9614
  ...controllers,
@@ -9150,6 +9629,7 @@ var electron = {
9150
9629
  openaiApi,
9151
9630
  menuItemsApi,
9152
9631
  pluginApi,
9632
+ llmApi,
9153
9633
  clientCacheApi,
9154
9634
 
9155
9635
  // Events