mindcache 3.4.1 → 3.4.3

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.
@@ -205,6 +205,7 @@ var init_CloudAdapter = __esm({
205
205
  RECONNECT_DELAY = 1e3;
206
206
  MAX_RECONNECT_DELAY = 3e4;
207
207
  exports.CloudAdapter = class {
208
+ // Track if initial sync is complete
208
209
  constructor(config) {
209
210
  this.config = config;
210
211
  if (!config.baseUrl) {
@@ -224,6 +225,7 @@ var init_CloudAdapter = __esm({
224
225
  token = null;
225
226
  handleOnline = null;
226
227
  handleOffline = null;
228
+ _synced = false;
227
229
  /** Browser network status - instantly updated via navigator.onLine */
228
230
  get isOnline() {
229
231
  return this._isOnline;
@@ -406,10 +408,14 @@ var init_CloudAdapter = __esm({
406
408
  const encoder = encoding__namespace.createEncoder();
407
409
  const decoder = decoding__namespace.createDecoder(new Uint8Array(event.data));
408
410
  if (this.mindcache) {
409
- syncProtocol__namespace.readSyncMessage(decoder, encoder, this.mindcache.doc, this);
411
+ const messageType = syncProtocol__namespace.readSyncMessage(decoder, encoder, this.mindcache.doc, this);
410
412
  if (encoding__namespace.length(encoder) > 0) {
411
413
  this.sendBinary(encoding__namespace.toUint8Array(encoder));
412
414
  }
415
+ if (!this._synced && (messageType === 1 || messageType === 2)) {
416
+ this._synced = true;
417
+ this.emit("synced");
418
+ }
413
419
  }
414
420
  }
415
421
  } catch (error) {
@@ -453,15 +459,9 @@ var init_CloudAdapter = __esm({
453
459
  var DEFAULT_KEY_ATTRIBUTES = {
454
460
  type: "text",
455
461
  contentTags: [],
456
- systemTags: ["SystemPrompt", "LLMWrite"],
457
- // visible in system prompt and writable by LLM by default
458
- zIndex: 0,
459
- // Legacy - derived from systemTags
460
- readonly: false,
461
- visible: true,
462
- hardcoded: false,
463
- template: false,
464
- tags: []
462
+ systemTags: [],
463
+ // Keys are private by default - explicitly add SystemPrompt/LLMRead/LLMWrite to enable LLM access
464
+ zIndex: 0
465
465
  };
466
466
 
467
467
  // src/core/MindCache.ts
@@ -479,35 +479,14 @@ var MindCache = class {
479
479
  // (Less critical with Yjs but kept for API compat)
480
480
  normalizeSystemTags(tags) {
481
481
  const normalized = [];
482
- let hasSystemPrompt = false;
483
- let hasLLMRead = false;
484
- let hasLLMWrite = false;
485
- let hasReadonly = false;
482
+ const seen = /* @__PURE__ */ new Set();
486
483
  for (const tag of tags) {
487
- if (tag === "SystemPrompt" || tag === "prompt") {
488
- hasSystemPrompt = true;
489
- } else if (tag === "LLMRead") {
490
- hasLLMRead = true;
491
- } else if (tag === "LLMWrite") {
492
- hasLLMWrite = true;
493
- } else if (tag === "readonly") {
494
- hasReadonly = true;
495
- } else if (tag === "protected") {
496
- normalized.push(tag);
497
- } else if (tag === "ApplyTemplate" || tag === "template") {
498
- normalized.push("ApplyTemplate");
499
- }
500
- }
501
- if (hasSystemPrompt) {
502
- normalized.push("SystemPrompt");
503
- }
504
- if (hasLLMRead) {
505
- normalized.push("LLMRead");
506
- }
507
- if (hasReadonly) {
508
- normalized.push("readonly");
509
- } else if (hasLLMWrite) {
510
- normalized.push("LLMWrite");
484
+ if (["SystemPrompt", "LLMRead", "LLMWrite", "protected", "ApplyTemplate"].includes(tag)) {
485
+ if (!seen.has(tag)) {
486
+ seen.add(tag);
487
+ normalized.push(tag);
488
+ }
489
+ }
511
490
  }
512
491
  return normalized;
513
492
  }
@@ -531,7 +510,7 @@ var MindCache = class {
531
510
  _historyOptions = { maxEntries: 100, snapshotInterval: 10 };
532
511
  _historyEnabled = false;
533
512
  constructor(options) {
534
- this.doc = new Y__namespace.Doc();
513
+ this.doc = options?.doc || new Y__namespace.Doc();
535
514
  this.rootMap = this.doc.getMap("mindcache");
536
515
  this.rootMap.observeDeep((events) => {
537
516
  const keysAffected = /* @__PURE__ */ new Set();
@@ -934,16 +913,10 @@ var MindCache = class {
934
913
  const attrs = entry.attributes || {};
935
914
  const normalizedAttrs = {
936
915
  type: attrs.type || "text",
916
+ contentType: attrs.contentType,
937
917
  contentTags: attrs.contentTags || [],
938
- systemTags: attrs.systemTags || this.normalizeSystemTags(attrs.visible !== false ? ["prompt"] : []),
939
- zIndex: attrs.zIndex ?? 0,
940
- // Legacy fields
941
- readonly: attrs.readonly ?? false,
942
- visible: attrs.visible ?? true,
943
- hardcoded: attrs.hardcoded ?? false,
944
- template: attrs.template ?? false,
945
- tags: attrs.tags || [],
946
- contentType: attrs.contentType
918
+ systemTags: this.normalizeSystemTags(attrs.systemTags || []),
919
+ zIndex: attrs.zIndex ?? 0
947
920
  };
948
921
  entryMap.set("attributes", normalizedAttrs);
949
922
  }
@@ -1048,7 +1021,7 @@ var MindCache = class {
1048
1021
  if (_processingStack && _processingStack.has(key)) {
1049
1022
  return `{{${key}}}`;
1050
1023
  }
1051
- if (attributes?.systemTags?.includes("ApplyTemplate") || attributes?.systemTags?.includes("template") || attributes?.template) {
1024
+ if (attributes?.systemTags?.includes("ApplyTemplate")) {
1052
1025
  if (typeof value === "string") {
1053
1026
  const stack = _processingStack || /* @__PURE__ */ new Set();
1054
1027
  stack.add(key);
@@ -1062,13 +1035,8 @@ var MindCache = class {
1062
1035
  return {
1063
1036
  type: "text",
1064
1037
  contentTags: [],
1065
- systemTags: ["prompt", "readonly", "protected"],
1066
- zIndex: 999999,
1067
- readonly: true,
1068
- visible: true,
1069
- hardcoded: true,
1070
- template: false,
1071
- tags: []
1038
+ systemTags: ["SystemPrompt", "protected"],
1039
+ zIndex: 999999
1072
1040
  };
1073
1041
  }
1074
1042
  const entryMap = this.rootMap.get(key);
@@ -1135,22 +1103,13 @@ var MindCache = class {
1135
1103
  this.getUndoManager(key);
1136
1104
  this.doc.transact(() => {
1137
1105
  const oldAttributes = isNewEntry ? {
1138
- ...DEFAULT_KEY_ATTRIBUTES,
1139
- contentTags: [],
1140
- systemTags: ["SystemPrompt", "LLMWrite"],
1141
- tags: [],
1142
- zIndex: 0
1106
+ ...DEFAULT_KEY_ATTRIBUTES
1143
1107
  } : entryMap.get("attributes");
1144
1108
  const finalAttributes = attributes ? { ...oldAttributes, ...attributes } : oldAttributes;
1145
1109
  let normalizedAttributes = { ...finalAttributes };
1146
1110
  if (finalAttributes.systemTags) {
1147
1111
  normalizedAttributes.systemTags = this.normalizeSystemTags(finalAttributes.systemTags);
1148
1112
  }
1149
- if (finalAttributes.template) {
1150
- if (!normalizedAttributes.systemTags.includes("template")) {
1151
- normalizedAttributes.systemTags.push("template");
1152
- }
1153
- }
1154
1113
  let valueToSet = value;
1155
1114
  if (normalizedAttributes.type === "document" && !(valueToSet instanceof Y__namespace.Text)) {
1156
1115
  valueToSet = new Y__namespace.Text(typeof value === "string" ? value : String(value ?? ""));
@@ -1161,6 +1120,38 @@ var MindCache = class {
1161
1120
  entryMap.set("attributes", normalizedAttributes);
1162
1121
  });
1163
1122
  }
1123
+ /**
1124
+ * LLM-safe method to write a value to a key.
1125
+ * This method:
1126
+ * - Only updates the value, never modifies attributes/systemTags
1127
+ * - Checks LLMWrite permission before writing
1128
+ * - Returns false if key doesn't exist or lacks LLMWrite permission
1129
+ *
1130
+ * Used by create_vercel_ai_tools() to prevent LLMs from escalating privileges.
1131
+ */
1132
+ llm_set_key(key, value) {
1133
+ if (key === "$date" || key === "$time" || key === "$version") {
1134
+ return false;
1135
+ }
1136
+ const entryMap = this.rootMap.get(key);
1137
+ if (!entryMap) {
1138
+ return false;
1139
+ }
1140
+ const attributes = entryMap.get("attributes");
1141
+ if (!attributes?.systemTags?.includes("LLMWrite")) {
1142
+ return false;
1143
+ }
1144
+ if (attributes.type === "document") {
1145
+ if (typeof value === "string") {
1146
+ this._replaceDocumentText(key, value);
1147
+ }
1148
+ return true;
1149
+ }
1150
+ this.doc.transact(() => {
1151
+ entryMap.set("value", value);
1152
+ });
1153
+ return true;
1154
+ }
1164
1155
  delete_key(key) {
1165
1156
  if (key === "$date" || key === "$time") {
1166
1157
  return;
@@ -1605,15 +1596,13 @@ var MindCache = class {
1605
1596
  }
1606
1597
  const attributes = entryMap.get("attributes");
1607
1598
  const value = entryMap.get("value");
1608
- if (attributes?.hardcoded) {
1599
+ if (attributes?.systemTags?.includes("protected")) {
1609
1600
  return;
1610
1601
  }
1611
1602
  lines.push(`### ${key}`);
1612
1603
  const entryType = attributes?.type || "text";
1613
1604
  lines.push(`- **Type**: \`${entryType}\``);
1614
- lines.push(`- **Readonly**: \`${attributes?.readonly ?? false}\``);
1615
- lines.push(`- **Visible**: \`${attributes?.visible ?? true}\``);
1616
- lines.push(`- **Template**: \`${attributes?.template ?? false}\``);
1605
+ lines.push(`- **System Tags**: \`${attributes?.systemTags?.join(", ") || "none"}\``);
1617
1606
  lines.push(`- **Z-Index**: \`${attributes?.zIndex ?? 0}\``);
1618
1607
  if (attributes?.contentTags && attributes.contentTags.length > 0) {
1619
1608
  lines.push(`- **Tags**: \`${attributes.contentTags.join("`, `")}\``);
@@ -1643,7 +1632,10 @@ var MindCache = class {
1643
1632
  }
1644
1633
  lines.push("```");
1645
1634
  } else {
1646
- lines.push(`- **Value**: ${value}`);
1635
+ lines.push("- **Value**:");
1636
+ lines.push("```");
1637
+ lines.push(String(value));
1638
+ lines.push("```");
1647
1639
  }
1648
1640
  lines.push("");
1649
1641
  });
@@ -1678,7 +1670,7 @@ var MindCache = class {
1678
1670
  for (const line of lines) {
1679
1671
  if (line.startsWith("### ") && !line.startsWith("### Appendix")) {
1680
1672
  if (currentKey && currentValue !== null) {
1681
- this.set_value(currentKey, currentValue, currentAttributes);
1673
+ this.set_value(currentKey, currentValue.trim(), currentAttributes);
1682
1674
  }
1683
1675
  currentKey = line.substring(4).trim();
1684
1676
  currentAttributes = {};
@@ -1699,16 +1691,11 @@ var MindCache = class {
1699
1691
  }
1700
1692
  continue;
1701
1693
  }
1702
- if (line.startsWith("- **Readonly**:")) {
1703
- currentAttributes.readonly = line.includes("`true`");
1704
- continue;
1705
- }
1706
- if (line.startsWith("- **Visible**:")) {
1707
- currentAttributes.visible = line.includes("`true`");
1708
- continue;
1709
- }
1710
- if (line.startsWith("- **Template**:")) {
1711
- currentAttributes.template = line.includes("`true`");
1694
+ if (line.startsWith("- **System Tags**:")) {
1695
+ const tagsStr = line.match(/`([^`]+)`/)?.[1] || "";
1696
+ if (tagsStr !== "none") {
1697
+ currentAttributes.systemTags = tagsStr.split(", ").filter((t) => t);
1698
+ }
1712
1699
  continue;
1713
1700
  }
1714
1701
  if (line.startsWith("- **Z-Index**:")) {
@@ -1719,7 +1706,6 @@ var MindCache = class {
1719
1706
  if (line.startsWith("- **Tags**:")) {
1720
1707
  const tags = line.match(/`([^`]+)`/g)?.map((t) => t.slice(1, -1)) || [];
1721
1708
  currentAttributes.contentTags = tags;
1722
- currentAttributes.tags = tags;
1723
1709
  continue;
1724
1710
  }
1725
1711
  if (line.startsWith("- **Content Type**:")) {
@@ -1727,10 +1713,24 @@ var MindCache = class {
1727
1713
  continue;
1728
1714
  }
1729
1715
  if (line.startsWith("- **Value**:") && !line.includes("[See Appendix")) {
1730
- currentValue = line.substring(12).trim();
1716
+ const afterValue = line.substring(12).trim();
1717
+ if (afterValue === "") {
1718
+ currentValue = "";
1719
+ } else if (afterValue === "```" || afterValue === "```json") {
1720
+ inCodeBlock = true;
1721
+ codeBlockContent = [];
1722
+ currentValue = "";
1723
+ } else if (afterValue.startsWith("```")) {
1724
+ inCodeBlock = true;
1725
+ codeBlockContent = [afterValue.substring(3)];
1726
+ currentValue = "";
1727
+ } else {
1728
+ currentValue = afterValue;
1729
+ }
1731
1730
  continue;
1732
1731
  }
1733
- if (line === "```json" || line === "```") {
1732
+ const trimmedLine = line.trim();
1733
+ if (trimmedLine === "```json" || trimmedLine === "```") {
1734
1734
  if (inCodeBlock) {
1735
1735
  inCodeBlock = false;
1736
1736
  if (currentKey && codeBlockContent.length > 0) {
@@ -1739,15 +1739,27 @@ var MindCache = class {
1739
1739
  codeBlockContent = [];
1740
1740
  } else {
1741
1741
  inCodeBlock = true;
1742
+ codeBlockContent = [];
1742
1743
  }
1743
1744
  continue;
1744
1745
  }
1745
1746
  if (inCodeBlock) {
1746
1747
  codeBlockContent.push(line);
1748
+ } else if (currentKey && currentValue !== null) {
1749
+ currentValue += "\n" + line;
1747
1750
  }
1748
1751
  }
1749
1752
  if (currentKey && currentValue !== null) {
1750
- this.set_value(currentKey, currentValue, currentAttributes);
1753
+ this.set_value(currentKey, currentValue.trim(), currentAttributes);
1754
+ }
1755
+ const hasParsedKeys = lines.some((line) => line.startsWith("### ") && !line.startsWith("### Appendix"));
1756
+ if (!hasParsedKeys && markdown.trim().length > 0) {
1757
+ this.set_value("imported_content", markdown.trim(), {
1758
+ type: "text",
1759
+ systemTags: ["SystemPrompt", "LLMWrite"],
1760
+ // Default assumptions
1761
+ zIndex: 0
1762
+ });
1751
1763
  }
1752
1764
  }
1753
1765
  /**
@@ -1975,8 +1987,12 @@ var MindCache = class {
1975
1987
  /**
1976
1988
  * Generate Vercel AI SDK compatible tools for writable keys.
1977
1989
  * For document type keys, generates additional tools: append_, insert_, edit_
1990
+ *
1991
+ * Security: All tools use llm_set_key internally which:
1992
+ * - Only modifies VALUES, never attributes/systemTags
1993
+ * - Prevents LLMs from escalating privileges
1978
1994
  */
1979
- get_aisdk_tools() {
1995
+ create_vercel_ai_tools() {
1980
1996
  const tools = {};
1981
1997
  for (const [key, val] of this.rootMap) {
1982
1998
  if (key.startsWith("$")) {
@@ -1984,7 +2000,7 @@ var MindCache = class {
1984
2000
  }
1985
2001
  const entryMap = val;
1986
2002
  const attributes = entryMap.get("attributes");
1987
- const isWritable = !attributes?.readonly && (attributes?.systemTags?.includes("LLMWrite") || !attributes?.systemTags);
2003
+ const isWritable = attributes?.systemTags?.includes("LLMWrite");
1988
2004
  if (!isWritable) {
1989
2005
  continue;
1990
2006
  }
@@ -2000,15 +2016,18 @@ var MindCache = class {
2000
2016
  required: ["value"]
2001
2017
  },
2002
2018
  execute: async ({ value }) => {
2003
- if (isDocument) {
2004
- this._replaceDocumentText(key, value);
2005
- } else {
2006
- this.set_value(key, value);
2019
+ const success = this.llm_set_key(key, value);
2020
+ if (success) {
2021
+ return {
2022
+ result: `Successfully wrote "${value}" to ${key}`,
2023
+ key,
2024
+ value
2025
+ };
2007
2026
  }
2008
2027
  return {
2009
- result: `Successfully wrote "${value}" to ${key}`,
2028
+ result: `Failed to write to ${key} - permission denied or key not found`,
2010
2029
  key,
2011
- value
2030
+ error: true
2012
2031
  };
2013
2032
  }
2014
2033
  };
@@ -2023,6 +2042,9 @@ var MindCache = class {
2023
2042
  required: ["text"]
2024
2043
  },
2025
2044
  execute: async ({ text }) => {
2045
+ if (!attributes?.systemTags?.includes("LLMWrite")) {
2046
+ return { result: `Permission denied for ${key}`, key, error: true };
2047
+ }
2026
2048
  const yText = this.get_document(key);
2027
2049
  if (yText) {
2028
2050
  yText.insert(yText.length, text);
@@ -2046,6 +2068,9 @@ var MindCache = class {
2046
2068
  required: ["index", "text"]
2047
2069
  },
2048
2070
  execute: async ({ index, text }) => {
2071
+ if (!attributes?.systemTags?.includes("LLMWrite")) {
2072
+ return { result: `Permission denied for ${key}`, key, error: true };
2073
+ }
2049
2074
  this.insert_text(key, index, text);
2050
2075
  return {
2051
2076
  result: `Successfully inserted text at position ${index} in ${key}`,
@@ -2066,6 +2091,9 @@ var MindCache = class {
2066
2091
  required: ["find", "replace"]
2067
2092
  },
2068
2093
  execute: async ({ find, replace }) => {
2094
+ if (!attributes?.systemTags?.includes("LLMWrite")) {
2095
+ return { result: `Permission denied for ${key}`, key, error: true };
2096
+ }
2069
2097
  const yText = this.get_document(key);
2070
2098
  if (yText) {
2071
2099
  const text = yText.toString();
@@ -2090,6 +2118,12 @@ var MindCache = class {
2090
2118
  }
2091
2119
  return tools;
2092
2120
  }
2121
+ /**
2122
+ * @deprecated Use create_vercel_ai_tools() instead
2123
+ */
2124
+ get_aisdk_tools() {
2125
+ return this.create_vercel_ai_tools();
2126
+ }
2093
2127
  /**
2094
2128
  * Generate a system prompt containing all visible STM keys and their values.
2095
2129
  * Indicates which tools can be used to modify writable keys.
@@ -2102,13 +2136,13 @@ var MindCache = class {
2102
2136
  }
2103
2137
  const entryMap = val;
2104
2138
  const attributes = entryMap.get("attributes");
2105
- const isVisible = attributes?.visible !== false && (attributes?.systemTags?.includes("prompt") || attributes?.systemTags?.includes("SystemPrompt") || !attributes?.systemTags);
2139
+ const isVisible = attributes?.systemTags?.includes("SystemPrompt") || attributes?.systemTags?.includes("LLMRead");
2106
2140
  if (!isVisible) {
2107
2141
  continue;
2108
2142
  }
2109
2143
  const value = this.get_value(key);
2110
2144
  const displayValue = typeof value === "object" ? JSON.stringify(value) : value;
2111
- const isWritable = !attributes?.readonly && (attributes?.systemTags?.includes("LLMWrite") || !attributes?.systemTags);
2145
+ const isWritable = attributes?.systemTags?.includes("LLMWrite");
2112
2146
  const isDocument = attributes?.type === "document";
2113
2147
  const sanitizedKey = this.sanitizeKeyForTool(key);
2114
2148
  if (isWritable) {
@@ -2149,7 +2183,7 @@ var MindCache = class {
2149
2183
  return null;
2150
2184
  }
2151
2185
  const attributes = entryMap.get("attributes");
2152
- const isWritable = !attributes?.readonly && (attributes?.systemTags?.includes("LLMWrite") || !attributes?.systemTags);
2186
+ const isWritable = attributes?.systemTags?.includes("LLMWrite");
2153
2187
  if (!isWritable) {
2154
2188
  return null;
2155
2189
  }