mindcache 3.4.1 → 3.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.
@@ -425,15 +425,9 @@ var init_CloudAdapter = __esm({
425
425
  var DEFAULT_KEY_ATTRIBUTES = {
426
426
  type: "text",
427
427
  contentTags: [],
428
- systemTags: ["SystemPrompt", "LLMWrite"],
429
- // visible in system prompt and writable by LLM by default
430
- zIndex: 0,
431
- // Legacy - derived from systemTags
432
- readonly: false,
433
- visible: true,
434
- hardcoded: false,
435
- template: false,
436
- tags: []
428
+ systemTags: [],
429
+ // Keys are private by default - explicitly add SystemPrompt/LLMRead/LLMWrite to enable LLM access
430
+ zIndex: 0
437
431
  };
438
432
 
439
433
  // src/core/MindCache.ts
@@ -451,35 +445,14 @@ var MindCache = class {
451
445
  // (Less critical with Yjs but kept for API compat)
452
446
  normalizeSystemTags(tags) {
453
447
  const normalized = [];
454
- let hasSystemPrompt = false;
455
- let hasLLMRead = false;
456
- let hasLLMWrite = false;
457
- let hasReadonly = false;
448
+ const seen = /* @__PURE__ */ new Set();
458
449
  for (const tag of tags) {
459
- if (tag === "SystemPrompt" || tag === "prompt") {
460
- hasSystemPrompt = true;
461
- } else if (tag === "LLMRead") {
462
- hasLLMRead = true;
463
- } else if (tag === "LLMWrite") {
464
- hasLLMWrite = true;
465
- } else if (tag === "readonly") {
466
- hasReadonly = true;
467
- } else if (tag === "protected") {
468
- normalized.push(tag);
469
- } else if (tag === "ApplyTemplate" || tag === "template") {
470
- normalized.push("ApplyTemplate");
471
- }
472
- }
473
- if (hasSystemPrompt) {
474
- normalized.push("SystemPrompt");
475
- }
476
- if (hasLLMRead) {
477
- normalized.push("LLMRead");
478
- }
479
- if (hasReadonly) {
480
- normalized.push("readonly");
481
- } else if (hasLLMWrite) {
482
- normalized.push("LLMWrite");
450
+ if (["SystemPrompt", "LLMRead", "LLMWrite", "protected", "ApplyTemplate"].includes(tag)) {
451
+ if (!seen.has(tag)) {
452
+ seen.add(tag);
453
+ normalized.push(tag);
454
+ }
455
+ }
483
456
  }
484
457
  return normalized;
485
458
  }
@@ -906,16 +879,10 @@ var MindCache = class {
906
879
  const attrs = entry.attributes || {};
907
880
  const normalizedAttrs = {
908
881
  type: attrs.type || "text",
882
+ contentType: attrs.contentType,
909
883
  contentTags: attrs.contentTags || [],
910
- systemTags: attrs.systemTags || this.normalizeSystemTags(attrs.visible !== false ? ["prompt"] : []),
911
- zIndex: attrs.zIndex ?? 0,
912
- // Legacy fields
913
- readonly: attrs.readonly ?? false,
914
- visible: attrs.visible ?? true,
915
- hardcoded: attrs.hardcoded ?? false,
916
- template: attrs.template ?? false,
917
- tags: attrs.tags || [],
918
- contentType: attrs.contentType
884
+ systemTags: this.normalizeSystemTags(attrs.systemTags || []),
885
+ zIndex: attrs.zIndex ?? 0
919
886
  };
920
887
  entryMap.set("attributes", normalizedAttrs);
921
888
  }
@@ -1020,7 +987,7 @@ var MindCache = class {
1020
987
  if (_processingStack && _processingStack.has(key)) {
1021
988
  return `{{${key}}}`;
1022
989
  }
1023
- if (attributes?.systemTags?.includes("ApplyTemplate") || attributes?.systemTags?.includes("template") || attributes?.template) {
990
+ if (attributes?.systemTags?.includes("ApplyTemplate")) {
1024
991
  if (typeof value === "string") {
1025
992
  const stack = _processingStack || /* @__PURE__ */ new Set();
1026
993
  stack.add(key);
@@ -1034,13 +1001,8 @@ var MindCache = class {
1034
1001
  return {
1035
1002
  type: "text",
1036
1003
  contentTags: [],
1037
- systemTags: ["prompt", "readonly", "protected"],
1038
- zIndex: 999999,
1039
- readonly: true,
1040
- visible: true,
1041
- hardcoded: true,
1042
- template: false,
1043
- tags: []
1004
+ systemTags: ["SystemPrompt", "protected"],
1005
+ zIndex: 999999
1044
1006
  };
1045
1007
  }
1046
1008
  const entryMap = this.rootMap.get(key);
@@ -1107,22 +1069,13 @@ var MindCache = class {
1107
1069
  this.getUndoManager(key);
1108
1070
  this.doc.transact(() => {
1109
1071
  const oldAttributes = isNewEntry ? {
1110
- ...DEFAULT_KEY_ATTRIBUTES,
1111
- contentTags: [],
1112
- systemTags: ["SystemPrompt", "LLMWrite"],
1113
- tags: [],
1114
- zIndex: 0
1072
+ ...DEFAULT_KEY_ATTRIBUTES
1115
1073
  } : entryMap.get("attributes");
1116
1074
  const finalAttributes = attributes ? { ...oldAttributes, ...attributes } : oldAttributes;
1117
1075
  let normalizedAttributes = { ...finalAttributes };
1118
1076
  if (finalAttributes.systemTags) {
1119
1077
  normalizedAttributes.systemTags = this.normalizeSystemTags(finalAttributes.systemTags);
1120
1078
  }
1121
- if (finalAttributes.template) {
1122
- if (!normalizedAttributes.systemTags.includes("template")) {
1123
- normalizedAttributes.systemTags.push("template");
1124
- }
1125
- }
1126
1079
  let valueToSet = value;
1127
1080
  if (normalizedAttributes.type === "document" && !(valueToSet instanceof Y.Text)) {
1128
1081
  valueToSet = new Y.Text(typeof value === "string" ? value : String(value ?? ""));
@@ -1133,6 +1086,38 @@ var MindCache = class {
1133
1086
  entryMap.set("attributes", normalizedAttributes);
1134
1087
  });
1135
1088
  }
1089
+ /**
1090
+ * LLM-safe method to write a value to a key.
1091
+ * This method:
1092
+ * - Only updates the value, never modifies attributes/systemTags
1093
+ * - Checks LLMWrite permission before writing
1094
+ * - Returns false if key doesn't exist or lacks LLMWrite permission
1095
+ *
1096
+ * Used by create_vercel_ai_tools() to prevent LLMs from escalating privileges.
1097
+ */
1098
+ llm_set_key(key, value) {
1099
+ if (key === "$date" || key === "$time" || key === "$version") {
1100
+ return false;
1101
+ }
1102
+ const entryMap = this.rootMap.get(key);
1103
+ if (!entryMap) {
1104
+ return false;
1105
+ }
1106
+ const attributes = entryMap.get("attributes");
1107
+ if (!attributes?.systemTags?.includes("LLMWrite")) {
1108
+ return false;
1109
+ }
1110
+ if (attributes.type === "document") {
1111
+ if (typeof value === "string") {
1112
+ this._replaceDocumentText(key, value);
1113
+ }
1114
+ return true;
1115
+ }
1116
+ this.doc.transact(() => {
1117
+ entryMap.set("value", value);
1118
+ });
1119
+ return true;
1120
+ }
1136
1121
  delete_key(key) {
1137
1122
  if (key === "$date" || key === "$time") {
1138
1123
  return;
@@ -1577,15 +1562,13 @@ var MindCache = class {
1577
1562
  }
1578
1563
  const attributes = entryMap.get("attributes");
1579
1564
  const value = entryMap.get("value");
1580
- if (attributes?.hardcoded) {
1565
+ if (attributes?.systemTags?.includes("protected")) {
1581
1566
  return;
1582
1567
  }
1583
1568
  lines.push(`### ${key}`);
1584
1569
  const entryType = attributes?.type || "text";
1585
1570
  lines.push(`- **Type**: \`${entryType}\``);
1586
- lines.push(`- **Readonly**: \`${attributes?.readonly ?? false}\``);
1587
- lines.push(`- **Visible**: \`${attributes?.visible ?? true}\``);
1588
- lines.push(`- **Template**: \`${attributes?.template ?? false}\``);
1571
+ lines.push(`- **System Tags**: \`${attributes?.systemTags?.join(", ") || "none"}\``);
1589
1572
  lines.push(`- **Z-Index**: \`${attributes?.zIndex ?? 0}\``);
1590
1573
  if (attributes?.contentTags && attributes.contentTags.length > 0) {
1591
1574
  lines.push(`- **Tags**: \`${attributes.contentTags.join("`, `")}\``);
@@ -1671,16 +1654,11 @@ var MindCache = class {
1671
1654
  }
1672
1655
  continue;
1673
1656
  }
1674
- if (line.startsWith("- **Readonly**:")) {
1675
- currentAttributes.readonly = line.includes("`true`");
1676
- continue;
1677
- }
1678
- if (line.startsWith("- **Visible**:")) {
1679
- currentAttributes.visible = line.includes("`true`");
1680
- continue;
1681
- }
1682
- if (line.startsWith("- **Template**:")) {
1683
- currentAttributes.template = line.includes("`true`");
1657
+ if (line.startsWith("- **System Tags**:")) {
1658
+ const tagsStr = line.match(/`([^`]+)`/)?.[1] || "";
1659
+ if (tagsStr !== "none") {
1660
+ currentAttributes.systemTags = tagsStr.split(", ").filter((t) => t);
1661
+ }
1684
1662
  continue;
1685
1663
  }
1686
1664
  if (line.startsWith("- **Z-Index**:")) {
@@ -1691,7 +1669,6 @@ var MindCache = class {
1691
1669
  if (line.startsWith("- **Tags**:")) {
1692
1670
  const tags = line.match(/`([^`]+)`/g)?.map((t) => t.slice(1, -1)) || [];
1693
1671
  currentAttributes.contentTags = tags;
1694
- currentAttributes.tags = tags;
1695
1672
  continue;
1696
1673
  }
1697
1674
  if (line.startsWith("- **Content Type**:")) {
@@ -1947,8 +1924,12 @@ var MindCache = class {
1947
1924
  /**
1948
1925
  * Generate Vercel AI SDK compatible tools for writable keys.
1949
1926
  * For document type keys, generates additional tools: append_, insert_, edit_
1927
+ *
1928
+ * Security: All tools use llm_set_key internally which:
1929
+ * - Only modifies VALUES, never attributes/systemTags
1930
+ * - Prevents LLMs from escalating privileges
1950
1931
  */
1951
- get_aisdk_tools() {
1932
+ create_vercel_ai_tools() {
1952
1933
  const tools = {};
1953
1934
  for (const [key, val] of this.rootMap) {
1954
1935
  if (key.startsWith("$")) {
@@ -1956,7 +1937,7 @@ var MindCache = class {
1956
1937
  }
1957
1938
  const entryMap = val;
1958
1939
  const attributes = entryMap.get("attributes");
1959
- const isWritable = !attributes?.readonly && (attributes?.systemTags?.includes("LLMWrite") || !attributes?.systemTags);
1940
+ const isWritable = attributes?.systemTags?.includes("LLMWrite");
1960
1941
  if (!isWritable) {
1961
1942
  continue;
1962
1943
  }
@@ -1972,15 +1953,18 @@ var MindCache = class {
1972
1953
  required: ["value"]
1973
1954
  },
1974
1955
  execute: async ({ value }) => {
1975
- if (isDocument) {
1976
- this._replaceDocumentText(key, value);
1977
- } else {
1978
- this.set_value(key, value);
1956
+ const success = this.llm_set_key(key, value);
1957
+ if (success) {
1958
+ return {
1959
+ result: `Successfully wrote "${value}" to ${key}`,
1960
+ key,
1961
+ value
1962
+ };
1979
1963
  }
1980
1964
  return {
1981
- result: `Successfully wrote "${value}" to ${key}`,
1965
+ result: `Failed to write to ${key} - permission denied or key not found`,
1982
1966
  key,
1983
- value
1967
+ error: true
1984
1968
  };
1985
1969
  }
1986
1970
  };
@@ -1995,6 +1979,9 @@ var MindCache = class {
1995
1979
  required: ["text"]
1996
1980
  },
1997
1981
  execute: async ({ text }) => {
1982
+ if (!attributes?.systemTags?.includes("LLMWrite")) {
1983
+ return { result: `Permission denied for ${key}`, key, error: true };
1984
+ }
1998
1985
  const yText = this.get_document(key);
1999
1986
  if (yText) {
2000
1987
  yText.insert(yText.length, text);
@@ -2018,6 +2005,9 @@ var MindCache = class {
2018
2005
  required: ["index", "text"]
2019
2006
  },
2020
2007
  execute: async ({ index, text }) => {
2008
+ if (!attributes?.systemTags?.includes("LLMWrite")) {
2009
+ return { result: `Permission denied for ${key}`, key, error: true };
2010
+ }
2021
2011
  this.insert_text(key, index, text);
2022
2012
  return {
2023
2013
  result: `Successfully inserted text at position ${index} in ${key}`,
@@ -2038,6 +2028,9 @@ var MindCache = class {
2038
2028
  required: ["find", "replace"]
2039
2029
  },
2040
2030
  execute: async ({ find, replace }) => {
2031
+ if (!attributes?.systemTags?.includes("LLMWrite")) {
2032
+ return { result: `Permission denied for ${key}`, key, error: true };
2033
+ }
2041
2034
  const yText = this.get_document(key);
2042
2035
  if (yText) {
2043
2036
  const text = yText.toString();
@@ -2062,6 +2055,12 @@ var MindCache = class {
2062
2055
  }
2063
2056
  return tools;
2064
2057
  }
2058
+ /**
2059
+ * @deprecated Use create_vercel_ai_tools() instead
2060
+ */
2061
+ get_aisdk_tools() {
2062
+ return this.create_vercel_ai_tools();
2063
+ }
2065
2064
  /**
2066
2065
  * Generate a system prompt containing all visible STM keys and their values.
2067
2066
  * Indicates which tools can be used to modify writable keys.
@@ -2074,13 +2073,13 @@ var MindCache = class {
2074
2073
  }
2075
2074
  const entryMap = val;
2076
2075
  const attributes = entryMap.get("attributes");
2077
- const isVisible = attributes?.visible !== false && (attributes?.systemTags?.includes("prompt") || attributes?.systemTags?.includes("SystemPrompt") || !attributes?.systemTags);
2076
+ const isVisible = attributes?.systemTags?.includes("SystemPrompt") || attributes?.systemTags?.includes("LLMRead");
2078
2077
  if (!isVisible) {
2079
2078
  continue;
2080
2079
  }
2081
2080
  const value = this.get_value(key);
2082
2081
  const displayValue = typeof value === "object" ? JSON.stringify(value) : value;
2083
- const isWritable = !attributes?.readonly && (attributes?.systemTags?.includes("LLMWrite") || !attributes?.systemTags);
2082
+ const isWritable = attributes?.systemTags?.includes("LLMWrite");
2084
2083
  const isDocument = attributes?.type === "document";
2085
2084
  const sanitizedKey = this.sanitizeKeyForTool(key);
2086
2085
  if (isWritable) {
@@ -2121,7 +2120,7 @@ var MindCache = class {
2121
2120
  return null;
2122
2121
  }
2123
2122
  const attributes = entryMap.get("attributes");
2124
- const isWritable = !attributes?.readonly && (attributes?.systemTags?.includes("LLMWrite") || !attributes?.systemTags);
2123
+ const isWritable = attributes?.systemTags?.includes("LLMWrite");
2125
2124
  if (!isWritable) {
2126
2125
  return null;
2127
2126
  }