@trops/dash-core 0.1.343 → 0.1.345

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.
@@ -18,7 +18,7 @@ var require$$8$1 = require('https');
18
18
  var require$$0$6 = require('@modelcontextprotocol/sdk/client/index.js');
19
19
  var require$$1$4 = require('@modelcontextprotocol/sdk/client/stdio.js');
20
20
  var require$$0$5 = require('pkce-challenge');
21
- var require$$5$1 = require('child_process');
21
+ var require$$6$1 = require('child_process');
22
22
  var require$$2$2 = require('algoliasearch');
23
23
  var require$$3$3 = require('node:path');
24
24
  var require$$0$7 = require('openai');
@@ -4601,7 +4601,7 @@ function stableHash(obj) {
4601
4601
  return hash.toString(36);
4602
4602
  }
4603
4603
 
4604
- const responseCache$2 = {
4604
+ const responseCache$3 = {
4605
4605
  async get(key, fetcher, options = {}) {
4606
4606
  const { ttl = 30000, forceRefresh = false } = options;
4607
4607
 
@@ -4686,7 +4686,7 @@ const responseCache$2 = {
4686
4686
  },
4687
4687
  };
4688
4688
 
4689
- var responseCache_1 = responseCache$2;
4689
+ var responseCache_1 = responseCache$3;
4690
4690
 
4691
4691
  /**
4692
4692
  * clientCache
@@ -25620,6 +25620,52 @@ const {
25620
25620
  } = streamableHttp$1;
25621
25621
  const path$b = require$$1$2;
25622
25622
  const fs$7 = require$$0$2;
25623
+ const responseCache$2 = responseCache_1;
25624
+
25625
+ /**
25626
+ * Tool name prefixes considered safe to cache (read-only).
25627
+ * Writes/mutations are NOT cached so they always hit the source.
25628
+ */
25629
+ const READ_ONLY_PREFIXES = [
25630
+ "list_",
25631
+ "get_",
25632
+ "read_",
25633
+ "search_",
25634
+ "resolve_",
25635
+ "find_",
25636
+ "fetch_",
25637
+ "describe_",
25638
+ ];
25639
+
25640
+ const WRITE_PREFIXES = [
25641
+ "create_",
25642
+ "write_",
25643
+ "update_",
25644
+ "delete_",
25645
+ "remove_",
25646
+ "append_",
25647
+ "set_",
25648
+ "put_",
25649
+ "post_",
25650
+ "patch_",
25651
+ "send_",
25652
+ "execute_",
25653
+ "run_",
25654
+ ];
25655
+
25656
+ function isReadOnlyTool(toolName) {
25657
+ if (!toolName) return false;
25658
+ const lower = toolName.toLowerCase();
25659
+ // Explicit write prefix wins (in case a tool starts with read_ but actually writes)
25660
+ if (WRITE_PREFIXES.some((p) => lower.startsWith(p))) return false;
25661
+ return READ_ONLY_PREFIXES.some((p) => lower.startsWith(p));
25662
+ }
25663
+
25664
+ /**
25665
+ * Default TTL for cached MCP tool calls (milliseconds).
25666
+ * Short enough to keep data fresh, long enough to dedupe concurrent widget loads.
25667
+ */
25668
+ const DEFAULT_TOOL_CACHE_TTL = 5000;
25623
25669
 
25624
25670
  /**
25625
25671
  * Cached shell PATH result (resolved once, reused for all spawns).
@@ -25657,7 +25703,7 @@ function isNodeEsmError(errorText) {
25657
25703
  function getShellPath$1() {
25658
25704
  if (_shellPath$1 !== null) return _shellPath$1;
25659
25705
 
25660
- const { execSync } = require$$5$1;
25706
+ const { execSync } = require$$6$1;
25661
25707
  const fallbackDirs = ["/usr/local/bin", "/opt/homebrew/bin"];
25662
25708
 
25663
25709
  // Scan nvm versions, tracking both latest and best compatible version
@@ -26241,17 +26287,31 @@ const mcpController$2 = {
26241
26287
  );
26242
26288
  }
26243
26289
 
26244
- console.log(`[mcpController] Calling tool: ${serverName}/${toolName}`);
26290
+ const doCall = async () => {
26291
+ console.log(`[mcpController] Calling tool: ${serverName}/${toolName}`);
26292
+ const result = await server.client.callTool({
26293
+ name: toolName,
26294
+ arguments: args || {},
26295
+ });
26296
+ return {
26297
+ success: true,
26298
+ result,
26299
+ };
26300
+ };
26245
26301
 
26246
- const result = await server.client.callTool({
26247
- name: toolName,
26248
- arguments: args || {},
26249
- });
26302
+ // Cache read-only tool calls with in-flight dedup.
26303
+ // Writes always hit the source (and we invalidate the server's cache).
26304
+ if (isReadOnlyTool(toolName)) {
26305
+ const key = `mcp:${serverName}:${toolName}:${JSON.stringify(args || {})}`;
26306
+ return responseCache$2.get(key, doCall, {
26307
+ ttl: DEFAULT_TOOL_CACHE_TTL,
26308
+ });
26309
+ }
26250
26310
 
26251
- return {
26252
- success: true,
26253
- result,
26254
- };
26311
+ // Write/mutation: invalidate any cached reads for this server
26312
+ // (safest default — broad invalidation when state changes)
26313
+ responseCache$2.invalidatePrefix(`mcp:${serverName}:`);
26314
+ return doCall();
26255
26315
  } catch (error) {
26256
26316
  console.error(
26257
26317
  `[mcpController] Error calling tool ${serverName}/${toolName}:`,
@@ -26473,7 +26533,7 @@ const mcpController$2 = {
26473
26533
  * @returns {{ success } | { error, message }}
26474
26534
  */
26475
26535
  runAuth: async (win, mcpConfig, credentials, authCommand) => {
26476
- const { spawn } = require$$5$1;
26536
+ const { spawn } = require$$6$1;
26477
26537
 
26478
26538
  const env = cleanEnvForChildProcess();
26479
26539
 
@@ -27725,7 +27785,7 @@ var pluginController_1 = pluginController$1;
27725
27785
  * can use the Chat widget without a separate API key.
27726
27786
  */
27727
27787
 
27728
- const { spawn, execSync } = require$$5$1;
27788
+ const { spawn, execSync } = require$$6$1;
27729
27789
  const {
27730
27790
  LLM_STREAM_DELTA: LLM_STREAM_DELTA$2,
27731
27791
  LLM_STREAM_TOOL_CALL: LLM_STREAM_TOOL_CALL$2,